/************************************************************************************** * 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; MQTTSNPacket::MQTTSNPacket() { _buf = 0; _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 >= 3) { len = desirialize(buf, len); } else { len = 0; } return len; } int MQTTSNPacket::getType(void) { if ( _bufLen == 0 ) { return 0; } int value = 0; int p = MQTTSNPacket_decode(_buf, _bufLen, &value); return _buf[p]; } 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 len = MQTTSNSerialize_advertise(buf, 5, (unsigned char) gatewayid, (unsigned short) duration); return desirialize(buf, len); } int MQTTSNPacket::setGWINFO(uint8_t gatewayId) { unsigned char buf[3]; int len = MQTTSNSerialize_gwinfo(buf, 3, (unsigned char) gatewayId, 0, 0); return desirialize(buf, len); } int MQTTSNPacket::setConnect(void) { unsigned char buf[40]; MQTTSNPacket_connectData data; data.clientID.cstring = (char*)"client01"; int len = MQTTSNSerialize_connect(buf, 40, &data); return desirialize(buf, len); } int MQTTSNPacket::setCONNACK(uint8_t returnCode) { unsigned char buf[3]; int len = MQTTSNSerialize_connack(buf, 3, (int) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setWILLTOPICREQ(void) { unsigned char buf[2]; int len = MQTTSNSerialize_willtopicreq(buf, 2); return desirialize(buf, len); } int MQTTSNPacket::setWILLMSGREQ(void) { unsigned char buf[2]; int len = MQTTSNSerialize_willmsgreq(buf, 2); return desirialize(buf, len); } int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* topicName) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int len = MQTTSNSerialize_register(buf, MQTTSNGW_MAX_PACKET_SIZE, (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 len = MQTTSNSerialize_regack(buf, 7, (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 len = MQTTSNSerialize_publish(buf, MQTTSNGW_MAX_PACKET_SIZE, (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 len = MQTTSNSerialize_puback(buf, 7, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setPUBREC(uint16_t msgId) { unsigned char buf[4]; int len = MQTTSNSerialize_pubrec(buf, 4, (unsigned short) msgId); return desirialize(buf, len); } int MQTTSNPacket::setPUBREL(uint16_t msgId) { unsigned char buf[4]; int len = MQTTSNSerialize_pubrel(buf, 4, (unsigned short) msgId); return desirialize(buf, len); } int MQTTSNPacket::setPUBCOMP(uint16_t msgId) { unsigned char buf[4]; int len = MQTTSNSerialize_pubcomp(buf, 4, (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 len = MQTTSNSerialize_suback(buf, 8, 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 len = MQTTSNSerialize_unsuback(buf, 4, (unsigned short) msgId); return desirialize(buf, len); } int MQTTSNPacket::setPINGRESP(void) { unsigned char buf[32]; int len = MQTTSNSerialize_pingresp(buf, 32); return desirialize(buf, len); } int MQTTSNPacket::setDISCONNECT(uint16_t duration) { unsigned char buf[4]; int len = MQTTSNSerialize_disconnect(buf, 4, (int) duration); return desirialize(buf, len); } int MQTTSNPacket::setWILLTOPICRESP(uint8_t returnCode) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int len = MQTTSNSerialize_willtopicresp(buf, MQTTSNGW_MAX_PACKET_SIZE, (int) returnCode); return desirialize(buf, len); } int MQTTSNPacket::setWILLMSGRESP(uint8_t returnCode) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int len = MQTTSNSerialize_willmsgresp(buf, MQTTSNGW_MAX_PACKET_SIZE, (int) returnCode); 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) { return MQTTSNDeserialize_disconnect((int*) duration, _buf, _bufLen); } 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 value = 0; int i = MQTTSNPacket_decode(_buf, _bufLen, &value); int size = _bufLen > SIZEOF_LOG_PACKET ? SIZEOF_LOG_PACKET : _bufLen; for (; 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: 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: case MQTTSN_UNSUBACK: sprintf(pbuf, " %02X%02X", _buf[5], _buf[6]); break; default: sprintf(pbuf, " "); break; } return pbuf; }