/************************************************************************************** * Copyright (c) 2016, Tomoaki Yamaguchi * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ #include "MQTTSNGateway.h" #include "MQTTSNGWPacket.h" #include "MQTTSNPacket.h" #include "SensorNetwork.h" #include #include #include using namespace std; using namespace MQTTSNGW; int readInt(char** pptr); void writeInt(unsigned char** pptr, int msgId); MQTTSNPacket::MQTTSNPacket(void) { _buf = nullptr; _bufLen = 0; } MQTTSNPacket::MQTTSNPacket(MQTTSNPacket& packet) { _buf = (unsigned char*) malloc(packet._bufLen); if (_buf) { _bufLen = packet._bufLen; memcpy(_buf, packet._buf, _bufLen); } else { _buf = nullptr; _bufLen = 0; } } MQTTSNPacket::~MQTTSNPacket() { if (_buf) { free(_buf); } } int MQTTSNPacket::unicast(SensorNetwork* network, SensorNetAddress* sendTo) { return network->unicast(_buf, _bufLen, sendTo); } int MQTTSNPacket::broadcast(SensorNetwork* network) { return network->broadcast(_buf, _bufLen); } int MQTTSNPacket::serialize(uint8_t* buf) { buf = _buf; return _bufLen; } int MQTTSNPacket::desirialize(unsigned char* buf, unsigned short len) { if (_buf) { free(_buf); } _buf = (unsigned char*) calloc(len, sizeof(unsigned char)); if (_buf) { memcpy(_buf, buf, len); _bufLen = len; } else { _bufLen = 0; } return _bufLen; } int MQTTSNPacket::recv(SensorNetwork* network) { uint8_t buf[MQTTSNGW_MAX_PACKET_SIZE]; int len = network->read((uint8_t*) buf, MQTTSNGW_MAX_PACKET_SIZE); if (len > 1) { len = desirialize(buf, len); } return len; } int MQTTSNPacket::getType(void) { if (_bufLen == 0) { return 0; } int value = 0; int p = MQTTSNPacket_decode(_buf, _bufLen, &value); return _buf[p]; } bool MQTTSNPacket::isQoSMinusPUBLISH(void) { if (_bufLen == 0) { return false;; } int value = 0; int p = MQTTSNPacket_decode(_buf, _bufLen, &value); return ((_buf[p] == MQTTSN_PUBLISH) && ((_buf[p + 1] & 0x60) == 0x60)); } unsigned char* MQTTSNPacket::getPacketData(void) { return _buf; } int MQTTSNPacket::getPacketLength(void) { return _bufLen; } const char* MQTTSNPacket::getName() { return MQTTSNPacket_name(getType()); } int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration) { unsigned char buf[5]; int buflen = sizeof(buf); int len = MQTTSNSerialize_advertise(buf, buflen, (unsigned char) gatewayid, (unsigned short) duration); return desirialize(buf, len); } int MQTTSNPacket::setGWINFO(uint8_t gatewayId) { unsigned char buf[3]; int buflen = sizeof(buf); int len = MQTTSNSerialize_gwinfo(buf, buflen, (unsigned char) gatewayId, 0, 0); return desirialize(buf, len); } int MQTTSNPacket::setConnect(void) { unsigned char buf[40]; int buflen = sizeof(buf); MQTTSNPacket_connectData data; data.clientID.cstring = (char*) "client01"; int len = MQTTSNSerialize_connect(buf, buflen, &data); return desirialize(buf, len); } bool MQTTSNPacket::isAccepted(void) { return (getType() == MQTTSN_CONNACK) && (_buf[2] == MQTTSN_RC_ACCEPTED); } int MQTTSNPacket::setCONNACK(uint8_t returnCode) { unsigned char buf[3]; int buflen = sizeof(buf); int len = MQTTSNSerialize_connack(buf, buflen, (int) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setWILLTOPICREQ(void) { unsigned char buf[2]; int buflen = sizeof(buf); int len = MQTTSNSerialize_willtopicreq(buf, buflen); return desirialize(buf, len); } int MQTTSNPacket::setWILLMSGREQ(void) { unsigned char buf[2]; int buflen = sizeof(buf); int len = MQTTSNSerialize_willmsgreq(buf, buflen); return desirialize(buf, len); } int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* topicName) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int buflen = sizeof(buf); int len = MQTTSNSerialize_register(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, topicName); return desirialize(buf, len); } int MQTTSNPacket::setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode) { unsigned char buf[7]; int buflen = sizeof(buf); int len = MQTTSNSerialize_regack(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, MQTTSN_topicid topic, uint8_t* payload, uint16_t payloadlen) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int buflen = sizeof(buf); int len = MQTTSNSerialize_publish(buf, buflen, (unsigned char) dup, qos, (unsigned char) retained, (unsigned short) msgId, topic, (unsigned char*) payload, (int) payloadlen); return desirialize(buf, len); } int MQTTSNPacket::setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode) { unsigned char buf[7]; int buflen = sizeof(buf); int len = MQTTSNSerialize_puback(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setPUBREC(uint16_t msgId) { unsigned char buf[4]; int buflen = sizeof(buf); int len = MQTTSNSerialize_pubrec(buf, buflen, (unsigned short) msgId); return desirialize(buf, len); } int MQTTSNPacket::setPUBREL(uint16_t msgId) { unsigned char buf[4]; int buflen = sizeof(buf); int len = MQTTSNSerialize_pubrel(buf, buflen, (unsigned short) msgId); return desirialize(buf, len); } int MQTTSNPacket::setPUBCOMP(uint16_t msgId) { unsigned char buf[4]; int buflen = sizeof(buf); int len = MQTTSNSerialize_pubcomp(buf, buflen, (unsigned short) msgId); return desirialize(buf, len); } int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode) { unsigned char buf[8]; int buflen = sizeof(buf); int len = MQTTSNSerialize_suback(buf, buflen, qos, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setUNSUBACK(uint16_t msgId) { unsigned char buf[4]; int buflen = sizeof(buf); int len = MQTTSNSerialize_unsuback(buf, buflen, (unsigned short) msgId); return desirialize(buf, len); } int MQTTSNPacket::setPINGRESP(void) { unsigned char buf[32]; int buflen = sizeof(buf); int len = MQTTSNSerialize_pingresp(buf, buflen); return desirialize(buf, len); } int MQTTSNPacket::setDISCONNECT(uint16_t duration) { unsigned char buf[4]; int buflen = sizeof(buf); int len = MQTTSNSerialize_disconnect(buf, buflen, (int) duration); return desirialize(buf, len); } int MQTTSNPacket::setWILLTOPICRESP(uint8_t returnCode) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int buflen = sizeof(buf); int len = MQTTSNSerialize_willtopicresp(buf, buflen, (int) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setWILLMSGRESP(uint8_t returnCode) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int buflen = sizeof(buf); int len = MQTTSNSerialize_willmsgresp(buf, buflen, (int) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setCONNECT(MQTTSNPacket_connectData* options) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int buflen = sizeof(buf); int len = MQTTSNSerialize_connect(buf, buflen, options); return desirialize(buf, len); } int MQTTSNPacket::setPINGREQ(MQTTSNString* clientId) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int buflen = sizeof(buf); int len = MQTTSNSerialize_pingreq(buf, buflen, *clientId); return desirialize(buf, len); } int MQTTSNPacket::getSERCHGW(uint8_t* radius) { return MQTTSNDeserialize_searchgw((unsigned char*) radius, (unsigned char*) _buf, _bufLen); } int MQTTSNPacket::getCONNECT(MQTTSNPacket_connectData* data) { return MQTTSNDeserialize_connect(data, _buf, _bufLen); } int MQTTSNPacket::getCONNACK(uint8_t* returnCode) { return MQTTSNSerialize_connack(_buf, _bufLen, (int) *returnCode); } int MQTTSNPacket::getWILLTOPIC(int* willQoS, uint8_t* willRetain, MQTTSNString* willTopic) { return MQTTSNDeserialize_willtopic((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen); } int MQTTSNPacket::getWILLMSG(MQTTSNString* willmsg) { return MQTTSNDeserialize_willmsg(willmsg, _buf, _bufLen); } int MQTTSNPacket::getREGISTER(uint16_t* topicId, uint16_t* msgId, MQTTSNString* topicName) { return MQTTSNDeserialize_register((unsigned short*) topicId, (unsigned short*) msgId, topicName, _buf, _bufLen); } int MQTTSNPacket::getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode) { return MQTTSNDeserialize_regack((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf, _bufLen); } int MQTTSNPacket::getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId, MQTTSN_topicid* topic, uint8_t** payload, int* payloadlen) { return MQTTSNDeserialize_publish((unsigned char*) dup, qos, (unsigned char*) retained, (unsigned short*) msgId, topic, (unsigned char**) payload, (int*) payloadlen, _buf, _bufLen); } int MQTTSNPacket::getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode) { return MQTTSNDeserialize_puback((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf, _bufLen); } int MQTTSNPacket::getACK(uint16_t* msgId) { unsigned char type; return MQTTSNDeserialize_ack(&type, (unsigned short*) msgId, _buf, _bufLen); } int MQTTSNPacket::getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId, MQTTSN_topicid* topicFilter) { return MQTTSNDeserialize_subscribe((unsigned char*) dup, qos, (unsigned short*) msgId, topicFilter, _buf, _bufLen); } int MQTTSNPacket::getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter) { return MQTTSNDeserialize_unsubscribe((unsigned short*) msgId, topicFilter, _buf, _bufLen); } int MQTTSNPacket::getPINGREQ(void) { if (getType() == MQTTSN_PINGRESP && _bufLen > 2) { return _bufLen - 2; } return 0; } int MQTTSNPacket::getDISCONNECT(uint16_t* duration) { int dur = 0; int rc = MQTTSNDeserialize_disconnect(&dur, _buf, _bufLen); *duration = (uint16_t) dur; return rc; } int MQTTSNPacket::getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic) { return MQTTSNDeserialize_willtopicupd((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen); } int MQTTSNPacket::getWILLMSGUPD(MQTTSNString* willMsg) { return MQTTSNDeserialize_willmsgupd(willMsg, _buf, _bufLen); } char* MQTTSNPacket::print(char* pbuf) { char* ptr = pbuf; char** pptr = &pbuf; int size = _bufLen > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : _bufLen; for (int i = 0; i < size; i++) { sprintf(*pptr, " %02X", *(_buf + i)); *pptr += 3; } **pptr = 0; return ptr; } char* MQTTSNPacket::getMsgId(char* pbuf) { int value = 0; int p = 0; switch (getType()) { case MQTTSN_PUBLISH: p = MQTTSNPacket_decode(_buf, _bufLen, &value); if (_buf[p + 1] & 0x80) { sprintf(pbuf, "+%02X%02X", _buf[p + 4], _buf[p + 5]); } else { sprintf(pbuf, " %02X%02X", _buf[p + 4], _buf[p + 5]); } break; case MQTTSN_PUBACK: case MQTTSN_REGISTER: case MQTTSN_REGACK: sprintf(pbuf, " %02X%02X", _buf[4], _buf[5]); break; case MQTTSN_PUBREC: case MQTTSN_PUBREL: case MQTTSN_PUBCOMP: case MQTTSN_UNSUBACK: sprintf(pbuf, " %02X%02X", _buf[2], _buf[3]); break; case MQTTSN_SUBSCRIBE: case MQTTSN_UNSUBSCRIBE: p = MQTTSNPacket_decode(_buf, _bufLen, &value); sprintf(pbuf, " %02X%02X", _buf[p + 2], _buf[p + 3]); break; case MQTTSN_SUBACK: sprintf(pbuf, " %02X%02X", _buf[5], _buf[6]); break; default: sprintf(pbuf, " "); break; } if (strcmp(pbuf, " 0000") == 0) { sprintf(pbuf, " "); } return pbuf; } int MQTTSNPacket::getMsgId(void) { int value = 0; int p = 0; int msgId = 0; char* ptr = 0; switch (getType()) { case MQTTSN_PUBLISH: p = MQTTSNPacket_decode(_buf, _bufLen, &value); ptr = (char*) _buf + p + 4; msgId = readInt((char**) &ptr); break; case MQTTSN_PUBACK: case MQTTSN_REGISTER: case MQTTSN_REGACK: ptr = (char*) _buf + 4; msgId = readInt((char**) &ptr); break; case MQTTSN_PUBREC: case MQTTSN_PUBREL: case MQTTSN_PUBCOMP: case MQTTSN_UNSUBACK: ptr = (char*) _buf + 2; msgId = readInt((char**) &ptr); break; case MQTTSN_SUBSCRIBE: case MQTTSN_UNSUBSCRIBE: p = MQTTSNPacket_decode(_buf, _bufLen, &value); ptr = (char*) _buf + p + 2; msgId = readInt((char**) &ptr); break; case MQTTSN_SUBACK: ptr = (char*) _buf + 5; msgId = readInt((char**) &ptr); break; default: break; } return msgId; } void MQTTSNPacket::setMsgId(uint16_t msgId) { int value = 0; int p = 0; //unsigned char* ptr = 0; switch (getType()) { case MQTTSN_PUBLISH: p = MQTTSNPacket_decode(_buf, _bufLen, &value); _buf[p + 4] = (unsigned char) (msgId / 256); _buf[p + 5] = (unsigned char) (msgId % 256); //ptr = _buf + p + 4; //writeInt(&ptr, msgId); break; case MQTTSN_PUBACK: case MQTTSN_REGISTER: case MQTTSN_REGACK: _buf[4] = (unsigned char) (msgId / 256); _buf[5] = (unsigned char) (msgId % 256); //ptr = _buf + 4; //writeInt(&ptr, msgId); break; case MQTTSN_PUBREC: case MQTTSN_PUBREL: case MQTTSN_PUBCOMP: case MQTTSN_UNSUBACK: _buf[2] = (unsigned char) (msgId / 256); _buf[3] = (unsigned char) (msgId % 256); //ptr = _buf + 2; //writeInt(&ptr, msgId); break; case MQTTSN_SUBSCRIBE: case MQTTSN_UNSUBSCRIBE: p = MQTTSNPacket_decode(_buf, _bufLen, &value); _buf[p + 2] = (unsigned char) (msgId / 256); _buf[p + 3] = (unsigned char) (msgId % 256); //ptr = _buf + p + 2; //writeInt(&ptr, msgId); break; case MQTTSN_SUBACK: _buf[5] = (unsigned char) (msgId / 256); _buf[6] = (unsigned char) (msgId % 256); //ptr = _buf + 5; //writeInt(&ptr, msgId); break; default: break; } } bool MQTTSNPacket::isDuplicate(void) { int value = 0; int p = MQTTSNPacket_decode(_buf, _bufLen, &value); return (_buf[p + 1] & 0x80); }