From 4932d2d0ee4e7142580c1c0ba9d06634b6059189 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Sun, 29 Jul 2018 16:11:38 +0900 Subject: [PATCH 01/10] QoS-1 PUBLISH is available #34 BugFix of #69 Signed-off-by: tomoaki --- .cproject | 8 +- MQTTSNGateway/GatewayTester/Makefile | 17 +- .../samples/ClientPubQoS-1/mainPubQoS-1.cpp | 161 ++++++ .../GatewayTester/samples/mainTest.cpp | 2 +- MQTTSNGateway/GatewayTester/src/LGwProxy.cpp | 477 +++++++++++------- MQTTSNGateway/GatewayTester/src/LGwProxy.h | 4 +- .../GatewayTester/src/LMqttsnClientApp.h | 8 +- .../GatewayTester/src/LPublishManager.cpp | 6 +- MQTTSNGateway/Makefile | 3 + MQTTSNGateway/README.md | 4 + MQTTSNGateway/forwarders.conf | 11 +- MQTTSNGateway/gateway.conf | 3 + MQTTSNGateway/predefinedTopic.conf | 21 +- MQTTSNGateway/qos-1clients.conf | 27 + MQTTSNGateway/src/MQTTGWPublishHandler.cpp | 3 +- MQTTSNGateway/src/MQTTSNGWClient.cpp | 91 +++- MQTTSNGateway/src/MQTTSNGWClient.h | 15 +- MQTTSNGateway/src/MQTTSNGWClientProxy.cpp | 252 +++++++++ MQTTSNGateway/src/MQTTSNGWClientProxy.h | 77 +++ MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp | 140 +++-- MQTTSNGateway/src/MQTTSNGWClientRecvTask.h | 4 +- MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp | 5 + .../src/MQTTSNGWConnectionHandler.cpp | 9 +- MQTTSNGateway/src/MQTTSNGWDefines.h | 1 + MQTTSNGateway/src/MQTTSNGWForwarder.cpp | 29 +- MQTTSNGateway/src/MQTTSNGWForwarder.h | 10 +- MQTTSNGateway/src/MQTTSNGWPacket.cpp | 84 ++- MQTTSNGateway/src/MQTTSNGWPacket.h | 5 + .../src/MQTTSNGWPacketHandleTask.cpp | 3 + MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp | 38 +- MQTTSNGateway/src/MQTTSNGateway.cpp | 94 +++- MQTTSNGateway/src/MQTTSNGateway.h | 10 +- 32 files changed, 1274 insertions(+), 348 deletions(-) create mode 100644 MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp create mode 100644 MQTTSNGateway/qos-1clients.conf create mode 100644 MQTTSNGateway/src/MQTTSNGWClientProxy.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWClientProxy.h diff --git a/.cproject b/.cproject index c3137e8..fae7107 100644 --- a/.cproject +++ b/.cproject @@ -14,7 +14,7 @@ - + @@ -66,7 +66,7 @@ - + @@ -136,8 +136,8 @@ - - + + diff --git a/MQTTSNGateway/GatewayTester/Makefile b/MQTTSNGateway/GatewayTester/Makefile index 7ce0f29..0ed4a27 100644 --- a/MQTTSNGateway/GatewayTester/Makefile +++ b/MQTTSNGateway/GatewayTester/Makefile @@ -7,9 +7,13 @@ PUBAPPL := mainPub PRGSUB := MQTT-SNSub SUBAPPL := mainSub +PRGQOS := MQTT-SNPubQoS-1 +QOSAPPL := mainPubQoS-1 + SRCDIR := samples SRCPUB := ClientPub SRCSUB := ClientSub +SRCQOS := ClientPubQoS-1 SUBDIR := src CPPSRCS := \ @@ -46,10 +50,11 @@ DEPS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.d) PROGPUB := $(OUTDIR)/$(PRGPUB) PROGSUB := $(OUTDIR)/$(PRGSUB) +PROGQOS := $(OUTDIR)/$(PRGQOS) .PHONY: install clean -all: $(PROG) $(PROGPUB) $(PROGSUB) +all: $(PROG) $(PROGPUB) $(PROGSUB) $(PROGQOS) @@ -64,6 +69,9 @@ $(PROGPUB): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCPUB)/$(PUBAPPL).o $(PROGSUB): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/$(SUBAPPL).o $(CXX) $(LDFLAGS) -o $(PROGSUB) $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/$(SUBAPPL).o $(OBJS) $(LIBS) $(LDADD) +$(PROGQOS): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCQOS)/$(QOSAPPL).o + $(CXX) $(LDFLAGS) -o $(PROGQOS) $(OUTDIR)/$(SRCDIR)/$(SRCQOS)/$(QOSAPPL).o $(OBJS) $(LIBS) $(LDADD) + $(OUTDIR)/$(SUBDIR)/%.o:$(SUBDIR)/%.cpp @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi @@ -80,6 +88,10 @@ $(OUTDIR)/$(SRCDIR)/$(SRCPUB)/%.o:$(SRCDIR)/$(SRCPUB)%.cpp $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/%.o:$(SRCDIR)/$(SRCSUB)%.cpp @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< + +$(OUTDIR)/$(SRCDIR)/$(SRCQOS)/%.o:$(SRCDIR)/$(SRCQOS)%.cpp + @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< clean: rm -rf $(OUTDIR) @@ -88,4 +100,5 @@ install: cp -pf $(PROG) ../../../ cp -pf $(PROGPUB) ../../../ cp -pf $(PROGSUB) ../../../ - + cp -pf $(PROGQOS) ../../../ + \ No newline at end of file diff --git a/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp b/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp new file mode 100644 index 0000000..8b72f53 --- /dev/null +++ b/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** + * 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. + * + *--------------------------------------------------------------------------- + * + * MQTT-SN GATEWAY TEST CLIENT + * + * Supported functions. + * + * void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false ); + * + * void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false ); + * + * void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos ); + * + * void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos ); + * + * void UNSUBSCRIBE ( const char* topicName ); + * + * void UNSUBSCRIBE ( uint16_t topicId ); + * + * void DISCONNECT ( uint16_t sleepInSecs ); + * + * void CONNECT ( void ); + * + * void DISPLAY( format, .....); <== instead of printf() + * + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation + ***************************************************************************/ + +#include "LMqttsnClientApp.h" +#include "LMqttsnClient.h" +#include "LScreen.h" + +using namespace std; +using namespace linuxAsyncClient; +extern LMqttsnClient* theClient; +extern LScreen* theScreen; + +/*------------------------------------------------------ + * UDP Configuration (theNetcon) + *------------------------------------------------------*/ +UDPCONF = { + "GatewayTestPubClient", // ClientId + {225,1,1,1}, // Multicast group IP + 1883, // Multicast group Port + 20001, // Local PortNo +}; + +/*------------------------------------------------------ + * Client Configuration (theMqcon) + *------------------------------------------------------*/ +MQTTSNCONF = { + 300, //KeepAlive [seconds] + true, //Clean session + 300, //Sleep duration [seconds] + "", //WillTopic + "", //WillMessage + 0, //WillQos + false //WillRetain +}; + +/*------------------------------------------------------ + * Define Topics + *------------------------------------------------------*/ + + +/*------------------------------------------------------ + * Callback routines for Subscribed Topics + *------------------------------------------------------*/ + +/*------------------------------------------------------ + * A Link list of Callback routines and Topics + *------------------------------------------------------*/ +SUBSCRIBE_LIST = {// e.g. SUB(TopicType, topicName, TopicId, callback, QoSx), + + END_OF_SUBSCRIBE_LIST + }; + +/*------------------------------------------------------ + * Test functions + *------------------------------------------------------*/ + +void publishTopic1(void) +{ + char payload[300]; + sprintf(payload, "publish \"ty4tw/Topic1\" \n"); + uint8_t qos = 3; + PUBLISH(1,(uint8_t*)payload, strlen(payload), qos); +} + +void publishTopic2(void) +{ + char payload[300]; + sprintf(payload, "publish \"ty4tw/topic2\" \n"); + uint8_t qos = 3; + PUBLISH(2,(uint8_t*)payload, strlen(payload), qos); +} + +void publishTopic57(void) +{ + char payload[300]; + sprintf(payload, "publish \"ty4tw/topic57\" \n"); + uint8_t qos = 3; + PUBLISH(5,(uint8_t*)payload, strlen(payload), qos); +} + + +void disconnect(void) +{ + DISCONNECT(0); +} + + +/*------------------------------------------------------ + * A List of Test functions is valid in case of + * line 23 of LMqttsnClientApp.h is commented out. + * //#define CLIENT_MODE + *------------------------------------------------------*/ + +TEST_LIST = {// e.g. TEST( Label, Test), + TEST("Step1:Publish topic1", publishTopic1), + TEST("Step2:Publish topic57", publishTopic57), + TEST("Step3:Publish topic2", publishTopic2), + END_OF_TEST_LIST + }; + + +/*------------------------------------------------------ + * List of tasks is invalid in case of line23 of + * LMqttsnClientApp.h is commented out. + * #define CLIENT_MODE + *------------------------------------------------------*/ +TASK_LIST = {// e.g. TASK( task, executing duration in second), + TASK(publishTopic1, 4), // publishTopic1() is executed every 4 seconds + TASK(publishTopic2, 7), // publishTopic2() is executed every 7 seconds + END_OF_TASK_LIST + }; + + +/*------------------------------------------------------ + * Initialize function + *------------------------------------------------------*/ +void setup(void) +{ + SetQoSMinus1Mode(true); +} + + +/***************** END OF PROGRAM ********************/ diff --git a/MQTTSNGateway/GatewayTester/samples/mainTest.cpp b/MQTTSNGateway/GatewayTester/samples/mainTest.cpp index 34db1c5..6075ced 100644 --- a/MQTTSNGateway/GatewayTester/samples/mainTest.cpp +++ b/MQTTSNGateway/GatewayTester/samples/mainTest.cpp @@ -220,7 +220,7 @@ TASK_LIST = {// e.g. TASK( task, executing duration in second), *------------------------------------------------------*/ void setup(void) { - //SetForwarderMode(); + SetForwarderMode(false); } diff --git a/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp b/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp index 78cc726..b0e86cd 100644 --- a/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp +++ b/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp @@ -30,21 +30,16 @@ extern uint16_t getUint16(const uint8_t* pos); extern LMqttsnClient* theClient; extern LScreen* theScreen; - /*===================================== - Class GwProxy + Class GwProxy ======================================*/ -static const char* packet_names[] = -{ - "ADVERTISE", "SEARCHGW", "GWINFO", "RESERVED", "CONNECT", "CONNACK", - "WILLTOPICREQ", "WILLTOPIC", "WILLMSGREQ", "WILLMSG", "REGISTER", "REGACK", - "PUBLISH", "PUBACK", "PUBCOMP", "PUBREC", "PUBREL", "RESERVED", - "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", - "DISCONNECT", "RESERVED", "WILLTOPICUPD", "WILLTOPICRESP", "WILLMSGUPD", - "WILLMSGRESP" -}; +static const char* packet_names[] = { "ADVERTISE", "SEARCHGW", "GWINFO", "RESERVED", "CONNECT", "CONNACK", + "WILLTOPICREQ", "WILLTOPIC", "WILLMSGREQ", "WILLMSG", "REGISTER", "REGACK", "PUBLISH", "PUBACK", "PUBCOMP", + "PUBREC", "PUBREL", "RESERVED", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", + "DISCONNECT", "RESERVED", "WILLTOPICUPD", "WILLTOPICRESP", "WILLMSGUPD", "WILLMSGRESP" }; -LGwProxy::LGwProxy(){ +LGwProxy::LGwProxy() +{ _nextMsgId = 0; _status = GW_LOST; _gwId = 0; @@ -61,13 +56,16 @@ LGwProxy::LGwProxy(){ _tWake = 0; _initialized = 0; _isForwarderMode = false; + _isQoSMinus1Mode = false; } -LGwProxy::~LGwProxy(){ +LGwProxy::~LGwProxy() +{ _topicTbl.clearTopic(); } -void LGwProxy::initialize(LUdpConfig netconf, LMqttsnConfig mqconf){ +void LGwProxy::initialize(LUdpConfig netconf, LMqttsnConfig mqconf) +{ _network.initialize(netconf); _clientId = netconf.clientId; _willTopic = mqconf.willTopic; @@ -79,78 +77,105 @@ void LGwProxy::initialize(LUdpConfig netconf, LMqttsnConfig mqconf){ _initialized = 1; } -void LGwProxy::connect(){ +void LGwProxy::connect() +{ char* pos; - while (_status != GW_CONNECTED){ + while (_status != GW_CONNECTED) + { pos = _msg; - if (_status == GW_SEND_WILLMSG){ - *pos++ = 2 + (uint8_t)strlen(_willMsg); - *pos++ = MQTTSN_TYPE_WILLMSG; - strcpy(pos,_willMsg); // WILLMSG - _status = GW_WAIT_CONNACK; - writeGwMsg(); - }else if (_status == GW_SEND_WILLTOPIC){ - *pos++ = 3 + (uint8_t)strlen(_willTopic); - *pos++ = MQTTSN_TYPE_WILLTOPIC; - *pos++ = _qosWill | _retainWill; - strcpy(pos,_willTopic); // WILLTOPIC - _status = GW_WAIT_WILLMSGREQ; - writeGwMsg(); - }else if (_status == GW_CONNECTING || _status == GW_DISCONNECTED || _status == GW_SLEPT ){ - uint8_t clientIdLen = uint8_t(strlen(_clientId) > 23 ? 23 : strlen(_clientId)); - *pos++ = 6 + clientIdLen; - *pos++ = MQTTSN_TYPE_CONNECT; - pos++; - if (_cleanSession){ - _msg[2] = MQTTSN_FLAG_CLEAN; - } - *pos++ = MQTTSN_PROTOCOL_ID; - setUint16((uint8_t*)pos, _tkeepAlive); - pos += 2; - strncpy(pos, _clientId, clientIdLen); - _msg[ 6 + clientIdLen] = 0; - _status = GW_WAIT_CONNACK; - if ( _willMsg && _willTopic && _status != GW_SLEPT ){ - if (strlen(_willMsg) && strlen(_willTopic)){ - _msg[2] = _msg[2] | MQTTSN_FLAG_WILL; // CONNECT - _status = GW_WAIT_WILLTOPICREQ; - } - } - writeGwMsg(); - _connectRetry = MQTTSN_RETRY_COUNT; - }else if (_status == GW_LOST){ + if (_status == GW_LOST) + { *pos++ = 3; *pos++ = MQTTSN_TYPE_SEARCHGW; *pos = 0; // SERCHGW _status = GW_SEARCHING; writeGwMsg(); - + } + else if (_status == GW_SEND_WILLMSG) + { + *pos++ = 2 + (uint8_t) strlen(_willMsg); + *pos++ = MQTTSN_TYPE_WILLMSG; + strcpy(pos, _willMsg); // WILLMSG + _status = GW_WAIT_CONNACK; + writeGwMsg(); + } + else if (_status == GW_SEND_WILLTOPIC) + { + *pos++ = 3 + (uint8_t) strlen(_willTopic); + *pos++ = MQTTSN_TYPE_WILLTOPIC; + *pos++ = _qosWill | _retainWill; + strcpy(pos, _willTopic); // WILLTOPIC + _status = GW_WAIT_WILLMSGREQ; + writeGwMsg(); + } + else if (_status == GW_CONNECTING || _status == GW_DISCONNECTED || _status == GW_SLEPT) + { + uint8_t clientIdLen = uint8_t(strlen(_clientId) > 23 ? 23 : strlen(_clientId)); + if (_isQoSMinus1Mode) + { + _status = GW_CONNECTED; + } + else + { + *pos++ = 6 + clientIdLen; + *pos++ = MQTTSN_TYPE_CONNECT; + pos++; + if (_cleanSession) + { + _msg[2] = MQTTSN_FLAG_CLEAN; + } + *pos++ = MQTTSN_PROTOCOL_ID; + setUint16((uint8_t*) pos, _tkeepAlive); + pos += 2; + strncpy(pos, _clientId, clientIdLen); + _msg[6 + clientIdLen] = 0; + _status = GW_WAIT_CONNACK; + if (_willMsg && _willTopic && _status != GW_SLEPT) + { + if (strlen(_willMsg) && strlen(_willTopic)) + { + _msg[2] = _msg[2] | MQTTSN_FLAG_WILL; // CONNECT + _status = GW_WAIT_WILLTOPICREQ; + } + } + writeGwMsg(); + _connectRetry = MQTTSN_RETRY_COUNT; + } } getConnectResponce(); } return; } -int LGwProxy::getConnectResponce(void){ +int LGwProxy::getConnectResponce(void) +{ int len = readMsg(); - if (len == 0){ - if (_sendUTC + MQTTSN_TIME_RETRY < time(NULL)){ + if (len == 0) + { + if (_sendUTC + MQTTSN_TIME_RETRY < time(NULL)) + { if (_msg[1] == MQTTSN_TYPE_CONNECT) { _connectRetry--; } - if (--_retryCount > 0){ - writeMsg((const uint8_t*)_msg); // Not writeGwMsg() : not to reset the counter. + if (--_retryCount > 0) + { + writeMsg((const uint8_t*) _msg); // Not writeGwMsg() : not to reset the counter. _sendUTC = time(NULL); - }else{ + } + else + { _sendUTC = 0; - if ( _status > GW_SEARCHING && _connectRetry > 0){ + if (_status > GW_SEARCHING && _connectRetry > 0) + { _status = GW_CONNECTING; - }else{ + } + else + { _status = GW_LOST; _gwId = 0; } @@ -158,66 +183,87 @@ int LGwProxy::getConnectResponce(void){ } } return 0; - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_GWINFO && _status == GW_SEARCHING){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_GWINFO && _status == GW_SEARCHING) + { _network.setGwAddress(); _gwId = _mqttsnMsg[1]; _status = GW_CONNECTING; - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLTOPICREQ && _status == GW_WAIT_WILLTOPICREQ){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLTOPICREQ && _status == GW_WAIT_WILLTOPICREQ) + { _status = GW_SEND_WILLTOPIC; - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLMSGREQ && _status == GW_WAIT_WILLMSGREQ){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLMSGREQ && _status == GW_WAIT_WILLMSGREQ) + { _status = GW_SEND_WILLMSG; - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_CONNACK && _status == GW_WAIT_CONNACK){ - if (_mqttsnMsg[1] == MQTTSN_RC_ACCEPTED){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_CONNACK && _status == GW_WAIT_CONNACK) + { + if (_mqttsnMsg[1] == MQTTSN_RC_ACCEPTED) + { _status = GW_CONNECTED; _connectRetry = MQTTSN_RETRY_COUNT; setPingReqTimer(); - if ( _tSleep ){ + if (_tSleep) + { _tSleep = 0; - }else{ + } + else + { DISPLAY("\033[0m\033[0;32m\n\n Connected to the Broker\033[0m\033[0;37m\n\n"); - if ( _cleanSession || _initialized == 1 ) + if (_cleanSession || _initialized == 1) { _topicTbl.clearTopic(); _initialized = 0; theClient->onConnect(); // SUBSCRIBEs are conducted } } - }else{ + } + else + { _status = GW_CONNECTING; } } return 1; } -void LGwProxy::reconnect(void){ +void LGwProxy::reconnect(void) +{ D_MQTTLOG("...Gateway reconnect\r\n"); _status = GW_DISCONNECTED; connect(); } -void LGwProxy::disconnect(uint16_t secs){ +void LGwProxy::disconnect(uint16_t secs) +{ _tSleep = secs; _tWake = 0; _msg[1] = MQTTSN_TYPE_DISCONNECT; - if (secs){ + if (secs) + { _msg[0] = 4; setUint16((uint8_t*) _msg + 2, secs); _status = GW_SLEEPING; - }else{ + } + else + { _msg[0] = 2; _keepAliveTimer.stop(); _status = GW_DISCONNECTING; } _retryCount = MQTTSN_RETRY_COUNT; - writeMsg((const uint8_t*)_msg); + writeMsg((const uint8_t*) _msg); _sendUTC = time(NULL); - while ( _status != GW_DISCONNECTED && _status != GW_SLEPT){ - if (getDisconnectResponce() < 0){ + while (_status != GW_DISCONNECTED && _status != GW_SLEPT) + { + if (getDisconnectResponce() < 0) + { _status = GW_LOST; DISPLAY("\033[0m\033[0;31m\n\n!!!!!! DISCONNECT Error !!!!!\033[0m\033[0;37m \n\n"); return; @@ -225,48 +271,63 @@ void LGwProxy::disconnect(uint16_t secs){ } } -int LGwProxy::getDisconnectResponce(void){ +int LGwProxy::getDisconnectResponce(void) +{ int len = readMsg(); - if (len == 0){ - if (_sendUTC + MQTTSN_TIME_RETRY < time(NULL)){ - if (--_retryCount >= 0){ - writeMsg((const uint8_t*)_msg); + if (len == 0) + { + if (_sendUTC + MQTTSN_TIME_RETRY < time(NULL)) + { + if (--_retryCount >= 0) + { + writeMsg((const uint8_t*) _msg); _sendUTC = time(NULL); - }else{ + } + else + { _status = GW_LOST; _gwId = 0; return -1; } } return 0; - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_DISCONNECT){ - if (_status == GW_SLEEPING ){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_DISCONNECT) + { + if (_status == GW_SLEEPING) + { _status = GW_SLEPT; uint32_t remain = _keepAliveTimer.getRemain(); theClient->setSleepMode(remain); /* Wake up and starts from this point. */ - }else{ + } + else + { _status = GW_DISCONNECTED; } } return 0; } -int LGwProxy::getMessage(void){ +int LGwProxy::getMessage(void) +{ int len = readMsg(); - if (len < 0){ + if (len < 0) + { return len; //error } #ifdef DEBUG_MQTTSN - if (len){ + if (len) + { D_MQTTLOG(" recved msgType %x\n", _mqttsnMsg[0]); } #endif - if (len == 0){ + if (len == 0) + { // Check PINGREQ required checkPingReq(); @@ -282,87 +343,115 @@ int LGwProxy::getMessage(void){ // Check Timeout of SUBSCRIBEs, theClient->getSubscribeManager()->checkTimeout(); - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_PUBLISH){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_PUBLISH) + { theClient->getPublishManager()->published(_mqttsnMsg, len); - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_PUBACK || _mqttsnMsg[0] == MQTTSN_TYPE_PUBCOMP || - _mqttsnMsg[0] == MQTTSN_TYPE_PUBREC || _mqttsnMsg[0] == MQTTSN_TYPE_PUBREL ){ - theClient->getPublishManager()->responce(_mqttsnMsg, (uint16_t)len); + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_PUBACK || _mqttsnMsg[0] == MQTTSN_TYPE_PUBCOMP + || _mqttsnMsg[0] == MQTTSN_TYPE_PUBREC || _mqttsnMsg[0] == MQTTSN_TYPE_PUBREL) + { + theClient->getPublishManager()->responce(_mqttsnMsg, (uint16_t) len); - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_SUBACK || _mqttsnMsg[0] == MQTTSN_TYPE_UNSUBACK){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_SUBACK || _mqttsnMsg[0] == MQTTSN_TYPE_UNSUBACK) + { theClient->getSubscribeManager()->responce(_mqttsnMsg); - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_REGISTER){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_REGISTER) + { _regMgr.responceRegister(_mqttsnMsg, len); - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_REGACK){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_REGACK) + { _regMgr.responceRegAck(getUint16(_mqttsnMsg + 3), getUint16(_mqttsnMsg + 1)); - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_PINGRESP){ - if (_pingStatus == GW_WAIT_PINGRESP){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_PINGRESP) + { + if (_pingStatus == GW_WAIT_PINGRESP) + { _pingStatus = 0; setPingReqTimer(); - if ( _tSleep > 0 ){ + if (_tSleep > 0) + { _tWake += _tkeepAlive; - if ( _tWake < _tSleep ){ + if (_tWake < _tSleep) + { theClient->setSleepMode(_tkeepAlive * 1000UL); - }else{ + } + else + { DISPLAY("\033[0m\033[0;32m\n\n Get back to ACTIVE.\033[0m\033[0;37m\n\n"); _tWake = 0; connect(); } } } - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_DISCONNECT){ + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_DISCONNECT) + { _status = GW_LOST; _gwAliveTimer.stop(); _keepAliveTimer.stop(); - }else if (_mqttsnMsg[0] == MQTTSN_TYPE_ADVERTISE){ - if (getUint16((const uint8_t*)(_mqttsnMsg + 2)) < 61){ - _tAdv = getUint16((const uint8_t*)(_mqttsnMsg + 2)) * 1500; - }else{ - _tAdv = getUint16((const uint8_t*)(_mqttsnMsg + 2)) * 1100; + } + else if (_mqttsnMsg[0] == MQTTSN_TYPE_ADVERTISE) + { + if (getUint16((const uint8_t*) (_mqttsnMsg + 2)) < 61) + { + _tAdv = getUint16((const uint8_t*) (_mqttsnMsg + 2)) * 1500; + } + else + { + _tAdv = getUint16((const uint8_t*) (_mqttsnMsg + 2)) * 1100; } _gwAliveTimer.start(_tAdv); } return 0; } - - - -uint16_t LGwProxy::registerTopic(char* topicName, uint16_t topicId){ +uint16_t LGwProxy::registerTopic(char* topicName, uint16_t topicId) +{ uint16_t id = topicId; - if (id == 0){ + if (id == 0) + { id = _topicTbl.getTopicId(topicName); _regMgr.registerTopic(topicName); } return id; } - -int LGwProxy::writeMsg(const uint8_t* msg){ +int LGwProxy::writeMsg(const uint8_t* msg) +{ uint16_t len; uint8_t pos; - uint8_t rc = 0; + uint8_t rc = 0; - if (msg[0] == 0x01){ + if (msg[0] == 0x01) + { len = getUint16(msg + 1); pos = 2; - }else{ + } + else + { len = msg[0]; pos = 1; } - if (msg[0] == 3 && msg[1] == MQTTSN_TYPE_SEARCHGW){ - rc = _network.broadcast(msg,len); - }else + if (msg[0] == 3 && msg[1] == MQTTSN_TYPE_SEARCHGW) { - if ( _isForwarderMode ) + rc = _network.broadcast(msg, len); + } + else + { + if (_isForwarderMode) { // create a forwarder encapsulation message WirelessNodeId is a 4bytes fake data - uint8_t* buf = (uint8_t*)malloc(len + 7); + uint8_t* buf = (uint8_t*) malloc(len + 7); buf[0] = 7; buf[1] = MQTTSN_TYPE_ENCAPSULATED; buf[2] = 1; @@ -371,16 +460,19 @@ int LGwProxy::writeMsg(const uint8_t* msg){ buf[5] = 'I'; buf[6] = 'd'; memcpy(buf + 7, msg, len); - if ( buf) - rc = _network.unicast(buf, len + 7); + if (buf) + rc = _network.unicast(buf, len + 7); free(buf); DISPLAY(" Encapsulated\n "); - }else{ - rc = _network.unicast(msg,len); + } + else + { + rc = _network.unicast(msg, len); } - if (rc > 0){ - if ( msg[pos] >= MQTTSN_TYPE_ADVERTISE && msg[pos] <= MQTTSN_TYPE_WILLMSGRESP ) + if (rc > 0) + { + if (msg[pos] >= MQTTSN_TYPE_ADVERTISE && msg[pos] <= MQTTSN_TYPE_WILLMSGRESP) { DISPLAY(" send %s\n", packet_names[msg[pos]]); } @@ -389,105 +481,134 @@ int LGwProxy::writeMsg(const uint8_t* msg){ return rc; } -void LGwProxy::writeGwMsg(void){ +void LGwProxy::writeGwMsg(void) +{ _retryCount = MQTTSN_RETRY_COUNT; - writeMsg((const uint8_t*)_msg); + writeMsg((const uint8_t*) _msg); _sendUTC = time(NULL); } -int LGwProxy::readMsg(void){ +int LGwProxy::readMsg(void) +{ int len = 0; uint8_t* msg = _network.getMessage(&len); _mqttsnMsg = msg; - if (len == 0){ + if (len == 0) + { return 0; } - if (_mqttsnMsg[0] == 0x01){ - int msgLen = (int) getUint16((const uint8_t*)_mqttsnMsg + 1); - if (len != msgLen){ + if (_mqttsnMsg[0] == 0x01) + { + int msgLen = (int) getUint16((const uint8_t*) _mqttsnMsg + 1); + if (len != msgLen) + { _mqttsnMsg += 3; len = msgLen - 3; } - }else{ + } + else + { _mqttsnMsg += 1; len -= 1; } - if ( *_mqttsnMsg == MQTTSN_TYPE_ENCAPSULATED ) + if (*_mqttsnMsg == MQTTSN_TYPE_ENCAPSULATED) { int lenEncap = len + 1; - if (msg[lenEncap] == 0x01){ - int msgLen = (int) getUint16((const uint8_t*)(msg + lenEncap + 1)); + if (msg[lenEncap] == 0x01) + { + int msgLen = (int) getUint16((const uint8_t*) (msg + lenEncap + 1)); msg += (lenEncap + 3); len = msgLen - 3; - }else{ + } + else + { msg += (lenEncap + 1); len = *(msg - 1); } _mqttsnMsg = msg; - DISPLAY(" recv encapslated message\n" ); + DISPLAY(" recv encapslated message\n"); } - if ( *_mqttsnMsg >= MQTTSN_TYPE_ADVERTISE && *_mqttsnMsg <= MQTTSN_TYPE_WILLMSGRESP ) + if (*_mqttsnMsg >= MQTTSN_TYPE_ADVERTISE && *_mqttsnMsg <= MQTTSN_TYPE_WILLMSGRESP) { DISPLAY(" recv %s\n", packet_names[*_mqttsnMsg]); } return len; } -void LGwProxy::setWillTopic(const char* willTopic, uint8_t qos, bool retain){ +void LGwProxy::setWillTopic(const char* willTopic, uint8_t qos, bool retain) +{ _willTopic = willTopic; _retainWill = _qosWill = 0; - if (qos == 1){ + if (qos == 1) + { _qosWill = MQTTSN_FLAG_QOS_1; - }else if (qos == 2){ + } + else if (qos == 2) + { _qosWill = MQTTSN_FLAG_QOS_2; } - if (retain){ + if (retain) + { _retainWill = MQTTSN_FLAG_RETAIN; } } -void LGwProxy::setWillMsg(const char* willMsg){ +void LGwProxy::setWillMsg(const char* willMsg) +{ _willMsg = willMsg; } - -void LGwProxy::setCleanSession(bool flg){ - if (flg){ +void LGwProxy::setCleanSession(bool flg) +{ + if (flg) + { _cleanSession = MQTTSN_FLAG_CLEAN; - }else{ + } + else + { _cleanSession = 0; } } -uint16_t LGwProxy::getNextMsgId(void){ +uint16_t LGwProxy::getNextMsgId(void) +{ _nextMsgId++; - if (_nextMsgId == 0){ + if (_nextMsgId == 0) + { _nextMsgId = 1; } return _nextMsgId; } -void LGwProxy::checkPingReq(void){ +void LGwProxy::checkPingReq(void) +{ uint8_t msg[2]; msg[0] = 0x02; msg[1] = MQTTSN_TYPE_PINGREQ; - - if ( (_status == GW_CONNECTED || _status == GW_SLEPT) && isPingReqRequired() && _pingStatus != GW_WAIT_PINGRESP){ + + if ((_status == GW_CONNECTED || _status == GW_SLEPT) && isPingReqRequired() && _pingStatus != GW_WAIT_PINGRESP) + { _pingStatus = GW_WAIT_PINGRESP; _pingRetryCount = MQTTSN_RETRY_COUNT; - writeMsg((const uint8_t*)msg); + writeMsg((const uint8_t*) msg); _pingSendUTC = time(NULL); - }else if (_pingStatus == GW_WAIT_PINGRESP){ - if (_pingSendUTC + MQTTSN_TIME_RETRY < time(NULL)){ - if (--_pingRetryCount > 0){ - writeMsg((const uint8_t*)msg); + } + else if (_pingStatus == GW_WAIT_PINGRESP) + { + if (_pingSendUTC + MQTTSN_TIME_RETRY < time(NULL)) + { + if (--_pingRetryCount > 0) + { + writeMsg((const uint8_t*) msg); _pingSendUTC = time(NULL); - }else{ + } + else + { _status = GW_LOST; _gwId = 0; _pingStatus = 0; @@ -498,8 +619,10 @@ void LGwProxy::checkPingReq(void){ } } -void LGwProxy::checkAdvertise(void){ - if ( _gwAliveTimer.isTimeUp()){ +void LGwProxy::checkAdvertise(void) +{ + if (_gwAliveTimer.isTimeUp()) + { _status = GW_LOST; _gwId = 0; _pingStatus = 0; @@ -509,27 +632,37 @@ void LGwProxy::checkAdvertise(void){ } } -LTopicTable* LGwProxy::getTopicTable(void){ +LTopicTable* LGwProxy::getTopicTable(void) +{ return &_topicTbl; } -LRegisterManager* LGwProxy::getRegisterManager(void){ +LRegisterManager* LGwProxy::getRegisterManager(void) +{ return &_regMgr; } -bool LGwProxy::isPingReqRequired(void){ +bool LGwProxy::isPingReqRequired(void) +{ return _keepAliveTimer.isTimeUp(_tkeepAlive * 1000UL); } -void LGwProxy::setPingReqTimer(void){ +void LGwProxy::setPingReqTimer(void) +{ _keepAliveTimer.start(_tkeepAlive * 1000UL); } -const char* LGwProxy::getClientId(void) { +const char* LGwProxy::getClientId(void) +{ return _clientId; } -void LGwProxy::setForwarderMode(void) +void LGwProxy::setForwarderMode(bool valid) { - _isForwarderMode = true; + _isForwarderMode = valid; +} + +void LGwProxy::setQoSMinus1Mode(bool valid) +{ + _isQoSMinus1Mode = valid; } diff --git a/MQTTSNGateway/GatewayTester/src/LGwProxy.h b/MQTTSNGateway/GatewayTester/src/LGwProxy.h index a34be1f..814affc 100644 --- a/MQTTSNGateway/GatewayTester/src/LGwProxy.h +++ b/MQTTSNGateway/GatewayTester/src/LGwProxy.h @@ -65,7 +65,8 @@ public: void setCleanSession(bool); void setKeepAliveDuration(uint16_t duration); void setAdvertiseDuration(uint16_t duration); - void setForwarderMode(void); + void setForwarderMode(bool valid); + void setQoSMinus1Mode(bool valid); void reconnect(void); int writeMsg(const uint8_t* msg); void setPingReqTimer(void); @@ -109,6 +110,7 @@ private: uint16_t _tSleep; uint16_t _tWake; bool _isForwarderMode; + bool _isQoSMinus1Mode; char _msg[MQTTSN_MAX_MSG_LENGTH + 1]; }; diff --git a/MQTTSNGateway/GatewayTester/src/LMqttsnClientApp.h b/MQTTSNGateway/GatewayTester/src/LMqttsnClientApp.h index 9891921..b848e4c 100644 --- a/MQTTSNGateway/GatewayTester/src/LMqttsnClientApp.h +++ b/MQTTSNGateway/GatewayTester/src/LMqttsnClientApp.h @@ -27,7 +27,6 @@ ======================================*/ //#define DEBUG_NW //#define DEBUG_MQTTSN -//#define DEBUG_OTA /**************************************** MQTT-SN Parameters @@ -105,7 +104,9 @@ typedef enum #define END_OF_SUBSCRIBE_LIST {MQTTSN_TOPIC_TYPE_NORMAL,0,0,0, 0} #define UDPCONF LUdpConfig theNetcon #define MQTTSNCONF LMqttsnConfig theMqcon -#define SetForwarderMode theClient->getGwProxy()->setForwarderMode +#define SetForwarderMode(...) theClient->getGwProxy()->setForwarderMode(__VA_ARGS__) +#define SetQoSMinus1Mode(...) theClient->getGwProxy()->setQoSMinus1Mode(__VA_ARGS__) + #ifdef CLIENT_MODE #define DISPLAY(...) #define PROMPT(...) @@ -142,6 +143,7 @@ typedef enum #define QoS0 0 #define QoS1 1 #define QoS2 2 +#define Q0Sm1 3 #define MQTTSN_TYPE_ADVERTISE 0x00 #define MQTTSN_TYPE_SEARCHGW 0x01 #define MQTTSN_TYPE_GWINFO 0x02 @@ -177,7 +179,7 @@ typedef enum #define MQTTSN_FLAG_QOS_0 0x0 #define MQTTSN_FLAG_QOS_1 0x20 #define MQTTSN_FLAG_QOS_2 0x40 -#define MQTTSN_FLAG_QOS_N1 0xc0 +#define MQTTSN_FLAG_QOS_M1 0x60 #define MQTTSN_FLAG_RETAIN 0x10 #define MQTTSN_FLAG_WILL 0x08 #define MQTTSN_FLAG_CLEAN 0x04 diff --git a/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp b/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp index 4e20c8d..ccdfe62 100644 --- a/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp +++ b/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp @@ -75,7 +75,7 @@ void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t topicType = MQTTSN_TOPIC_TYPE_NORMAL; } - if ( qos > 0 ) + if ( qos > 0 && qos < 3 ) { msgId = theClient->getGwProxy()->getNextMsgId(); } @@ -428,6 +428,10 @@ PubElement* LPublishManager::add(const char* topicName, uint16_t topicId, uint8_ { elm->flag |= MQTTSN_FLAG_QOS_2; } + else if (qos == 3) + { + elm->flag |= MQTTSN_FLAG_QOS_M1; + } if (retain) { elm->flag |= MQTTSN_FLAG_RETAIN; diff --git a/MQTTSNGateway/Makefile b/MQTTSNGateway/Makefile index cfc9283..f9a2c6f 100644 --- a/MQTTSNGateway/Makefile +++ b/MQTTSNGateway/Makefile @@ -11,6 +11,7 @@ CONFIG := gateway.conf CLIENTS := clients.conf PREDEFTOPIC := predefinedTopic.conf FORWARDERS := forwarders.conf +QOSM1CLIENT := qos-1clients.conf SRCDIR := src SUBDIR := ../MQTTSNPacket/src @@ -39,6 +40,7 @@ $(SRCDIR)/MQTTSNGWPublishHandler.cpp \ $(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \ $(SRCDIR)/MQTTSNGWEncapsulatedPacket.cpp \ $(SRCDIR)/MQTTSNGWForwarder.cpp \ +$(SRCDIR)/MQTTSNGWClientProxy.cpp \ $(SRCDIR)/$(OS)/$(SENSORNET)/SensorNetwork.cpp \ $(SRCDIR)/$(OS)/Timer.cpp \ $(SRCDIR)/$(OS)/Network.cpp \ @@ -141,6 +143,7 @@ install: cp -pf $(CLIENTS) ../../ cp -pf $(PREDEFTOPIC) ../../ cp -pf $(FORWARDERS) ../../ + cp -pf $(QOSM1CLIENT) ../../ exectest: diff --git a/MQTTSNGateway/README.md b/MQTTSNGateway/README.md index 28e149c..2144ec5 100644 --- a/MQTTSNGateway/README.md +++ b/MQTTSNGateway/README.md @@ -38,6 +38,9 @@ PredefinedTopicList=/path/to/your_predefinedTopic.conf Forwarder=NO ForwardersList=/home/tomoaki/tmp/forwarders.conf + +QoS-1=NO +QoS-1ClientsList=/path/to/your_qos-1clients.conf #RootCAfile=/path/to/your_Root_CA.crt #RootCApath=/path/to/your_certs_directory/ @@ -69,6 +72,7 @@ Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW messag when **ClientAuthentication** is YES, see MQTTSNGWClient.cpp line53, clients file specified by ClientsList is required. This file defines connect allowed clients by ClientId and SensorNetwork Address. e.g. IP address and Port No. When **PredefinedTopic** is YES, Pre-definedTopicID file specified by PredefinedTopicList is effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format. When **Forwarder** is YES, Forwarder Encapsulation Message is available. Connectable Forwarders are specifed by ForwardersList file. In this file, ForwarderIds and those sensorNet addresses are declared in CSV format. +When **QoS-1** is YES, QoS-1 PUBLISH Message is available. Clients which allow to send it, are specifed by QoS-1ClientsList file. In this file, ClientsId and those sensorNet addresses are declared in CSV format. diff --git a/MQTTSNGateway/forwarders.conf b/MQTTSNGateway/forwarders.conf index 3275924..cfb11dd 100644 --- a/MQTTSNGateway/forwarders.conf +++ b/MQTTSNGateway/forwarders.conf @@ -11,6 +11,15 @@ # http://www.eclipse.org/org/documents/edl-v10.php. #*********************************************************************** # -# SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function. +# This file declares valid MQTTSNForwarders. +# Forwarders are defined by ForwarderId same as ClientId and those SensorNetAddress +# in a CSV format as follow: +# +# ForwarderId, SensorNetAddress # +# where SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function. +# + Forwarder01,172.16.1.7:12002 + + diff --git a/MQTTSNGateway/gateway.conf b/MQTTSNGateway/gateway.conf index 10e02a4..a888771 100644 --- a/MQTTSNGateway/gateway.conf +++ b/MQTTSNGateway/gateway.conf @@ -26,6 +26,9 @@ PredefinedTopicList=/path/to/your_predefinedTopic.conf Forwarder=NO ForwardersList=/path/to/your_forwarers.conf +QoS-1=NO +QoS-1ClientsList=/path/to/your_qos-1clients.conf + #RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCApath=/etc/ssl/certs/ #CertsFile=/path/to/certKey.pem diff --git a/MQTTSNGateway/predefinedTopic.conf b/MQTTSNGateway/predefinedTopic.conf index 9b50801..2ad779a 100644 --- a/MQTTSNGateway/predefinedTopic.conf +++ b/MQTTSNGateway/predefinedTopic.conf @@ -11,7 +11,26 @@ # http://www.eclipse.org/org/documents/edl-v10.php. #*********************************************************************** # -# ClientID, TopicName, TopicID +# pre-defined-topics are defined by this file. +# A format of this file is in CSV as follows: +# +# ClientID, TopicName, TopicID +# +# This file is consist from two sections. +# One for QoS-1 PUBLISH Clients, the other for another clients. + +# +# pre-defined-topics for QoS-1 clients. +# ClientIDs should be "ClientProxy" +# + +ClientProxy, ty4tw/proxy/predefTopic1, 1 +ClientProxy, ty4tw/proxy/predefTopic2, 2 +ClientProxy, ty4tw/proxy/predefTopic3, 3 + + +# +# pre-defined-topics for another clients # GatewayTestClient,ty4tw/predefinedTopic1, 1 diff --git a/MQTTSNGateway/qos-1clients.conf b/MQTTSNGateway/qos-1clients.conf new file mode 100644 index 0000000..e21832a --- /dev/null +++ b/MQTTSNGateway/qos-1clients.conf @@ -0,0 +1,27 @@ +#*********************************************************************** +# Copyright (c) 2018, 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. +#*********************************************************************** +# +# Clients which send QoS-1 PUBLISH are defined by this file. +# +# Clients are defined by the ClientId and those SensorNetAddress +# in a CSV format as follow: +# +# ClientId, SensorNetAddress +# +# where SensorNetwork address format is defined by +# SensorNetAddress::setAddress(string* data) function. +# +# + +QoS-1_Client,172.16.1.7:12002 + diff --git a/MQTTSNGateway/src/MQTTGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTGWPublishHandler.cpp index b29fea0..5a2b5a6 100644 --- a/MQTTSNGateway/src/MQTTGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTGWPublishHandler.cpp @@ -131,8 +131,7 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet) /* create REGISTER */ MQTTSNPacket* regPacket = new MQTTSNPacket(); - MQTTSNString topicName; - topicName.cstring = 0; + MQTTSNString topicName = MQTTSNString_initializer; topicName.lenstring.len = topicId.data.long_.len; topicName.lenstring.data = topicId.data.long_.name; diff --git a/MQTTSNGateway/src/MQTTSNGWClient.cpp b/MQTTSNGateway/src/MQTTSNGWClient.cpp index 0a81ef8..124ad58 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClient.cpp @@ -19,12 +19,13 @@ #include "MQTTSNGWClient.h" #include "MQTTSNGateway.h" #include "SensorNetwork.h" -#include "MQTTSNGWForwarder.h" #include "Network.h" #include #include #include +#include "MQTTSNGWForwarder.h" + using namespace MQTTSNGW; char* currentDateTime(void); /*===================================== @@ -80,11 +81,7 @@ bool ClientList::authorize(const char* fileName) bool secure; bool stable; SensorNetAddress netAddr; - MQTTSNString clientId; - - clientId.cstring = 0; - clientId.lenstring.data = 0; - clientId.lenstring.len = 0; + MQTTSNString clientId = MQTTSNString_initializer; if ((fp = fopen(fileName, "r")) != 0) { @@ -131,13 +128,9 @@ bool ClientList::setPredefinedTopics(const char* fileName) FILE* fp; char buf[MAX_CLIENTID_LENGTH + 256]; size_t pos0, pos1; - MQTTSNString clientId; + MQTTSNString clientId = MQTTSNString_initializer;; bool rc = false; - clientId.cstring = 0; - clientId.lenstring.data = 0; - clientId.lenstring.len = 0; - if ((fp = fopen(fileName, "r")) != 0) { while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0) @@ -300,9 +293,8 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, } else { - MQTTSNString dummyId; + MQTTSNString dummyId MQTTSNString_initializer;; dummyId.cstring = strdup(""); - dummyId.lenstring.len = 0; client->setClientId(dummyId); free(dummyId.cstring); } @@ -367,6 +359,7 @@ Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicN // create Topic & Add it client->getTopics()->add((const char*)topicName.c_str(), topicId); + client->_hasPredefTopic = true; return client; } @@ -413,9 +406,11 @@ Client::Client(bool secure) _prevClient = 0; _nextClient = 0; _clientSleepPacketQue.setMaxSize(MAX_SAVED_PUBLISH); + _proxyPacketQue.setMaxSize(MAX_SAVED_PUBLISH); _hasPredefTopic = false; _holdPingRequest = false; _forwarder = 0; + _isProxy = false; } Client::~Client() @@ -485,6 +480,30 @@ int Client::setClientSleepPacket(MQTTGWPacket* packet) return rc; } +MQTTSNPacket* Client::getProxyPacket(void) +{ + return _proxyPacketQue.getPacket(); +} + +void Client::deleteFirstProxyPacket() +{ + _proxyPacketQue.pop(); +} + +int Client::setProxyPacket(MQTTSNPacket* packet) +{ + int rc = _proxyPacketQue.post(packet); + if ( rc ) + { + WRITELOG("%s %s is Disconnected. the packet was saved.\n", currentDateTime(), _clientId); + } + else + { + WRITELOG("%s %s is Disconnected and discard the packet.\n", currentDateTime(), _clientId); + } + return rc; +} + Connect* Client::getConnectData(void) { return &_connectData; @@ -572,7 +591,10 @@ void Client::updateStatus(MQTTSNPacket* packet) case MQTTSN_PUBCOMP: case MQTTSN_PUBREL: case MQTTSN_PUBREC: - _keepAliveTimer.start(_keepAliveMsec * 1.5); + if ( !_isProxy ) + { + _keepAliveTimer.start(_keepAliveMsec * 1.5); + } break; case MQTTSN_DISCONNECT: uint16_t duration; @@ -641,9 +663,14 @@ void Client::disconnected(void) _waitWillMsgFlg = false; } +void Client::tryConnect(void) +{ + _status = Cstat_TryConnecting; +} + bool Client::isConnectSendable(void) { - if (_status == Cstat_Lost || _status == Cstat_TryConnecting) + if ( _status == Cstat_Lost || _status == Cstat_TryConnecting ) { return false; } @@ -703,6 +730,11 @@ void Client::setTopics(Topics* topics) _topics = topics; } +ClientStatus Client::getClientStatus(void) +{ + return _status; +} + void Client::setWaitWillMsgFlg(bool flg) { _waitWillMsgFlg = flg; @@ -733,6 +765,11 @@ bool Client::isAwake(void) return (_status == Cstat_Awake); } +bool Client::isConnecting(void) +{ + return (_status == Cstat_Connecting); +} + bool Client::isSecureNetwork(void) { return _secureNetwork; @@ -760,10 +797,18 @@ void Client::setClientId(MQTTSNString id) free(_clientId); } - /* save clientId into (char*)_clientId NULL terminated */ - _clientId = (char*)calloc(MQTTSNstrlen(id) + 1, 1); - unsigned char* ptr = (unsigned char*)_clientId; - writeMQTTSNString((unsigned char**)&ptr, id); + if ( id.cstring ) + { + _clientId = (char*)calloc(strlen(id.cstring) + 1, 1); + memcpy(_clientId, id.cstring, strlen(id.cstring)); + } + else + { + /* save clientId into (char*)_clientId NULL terminated */ + _clientId = (char*)calloc(MQTTSNstrlen(id) + 1, 1); + unsigned char* ptr = (unsigned char*)_clientId; + writeMQTTSNString((unsigned char**)&ptr, id); + } } void Client::setWillTopic(MQTTSNString willTopic) @@ -812,14 +857,14 @@ const char* Client::getStatus(void) return theClientStatus[_status]; } -Client* Client::getOTAClient(void) +bool Client::isProxy(void) { - return _otaClient; + return _isProxy; } -void Client::setOTAClient(Client* cl) +void Client::setPorxy(bool isProxy) { - _otaClient =cl; + _isProxy = isProxy;; } void Client::holdPingRequest(void) diff --git a/MQTTSNGateway/src/MQTTSNGWClient.h b/MQTTSNGateway/src/MQTTSNGWClient.h index 8900656..ff67365 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.h +++ b/MQTTSNGateway/src/MQTTSNGWClient.h @@ -253,6 +253,9 @@ public: TopicIdMapelement* getWaitedSubTopicId(uint16_t msgId); MQTTGWPacket* getClientSleepPacket(void); void deleteFirstClientSleepPacket(void); + + MQTTSNPacket* getProxyPacket(void); + void deleteFirstProxyPacket(void); WaitREGACKPacketList* getWaitREGACKPacketList(void); void eraseWaitedPubTopicId(uint16_t msgId); @@ -261,6 +264,7 @@ public: void clearWaitedSubTopicId(void); int setClientSleepPacket(MQTTGWPacket*); + int setProxyPacket(MQTTSNPacket* packet); void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); @@ -271,6 +275,8 @@ public: void connackSended(int rc); void disconnected(void); bool isConnectSendable(void); + void tryConnect(void); + ClientStatus getClientStatus(void); uint16_t getNextPacketId(void); uint8_t getNextSnMsgId(void); @@ -286,6 +292,9 @@ public: Forwarder* getForwarder(void); void setForwarder(Forwarder* forwader); + void setPorxy(bool isProxy); + bool isProxy(void); + void setClientId(MQTTSNString id); void setWillTopic(MQTTSNString willTopic); void setWillMsg(MQTTSNString willmsg); @@ -298,6 +307,7 @@ public: bool erasable(void); bool isDisconnect(void); + bool isConnecting(void); bool isActive(void); bool isSleep(void); bool isAwake(void); @@ -310,11 +320,11 @@ public: bool isHoldPringReqest(void); Client* getNextClient(void); - Client* getOTAClient(void); - void setOTAClient(Client* cl); private: PacketQue _clientSleepPacketQue; + PacketQue _proxyPacketQue; + WaitREGACKPacketList _waitREGACKList; Topics* _topics; @@ -345,6 +355,7 @@ private: SensorNetAddress _sensorNetAddr; Forwarder* _forwarder; + bool _isProxy; bool _sessionStatus; diff --git a/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp b/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp new file mode 100644 index 0000000..d7ac795 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp @@ -0,0 +1,252 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 "MQTTSNGWDefines.h" +#include "MQTTSNGWClientProxy.h" +#include "MQTTSNGateway.h" +#include "SensorNetwork.h" +#include +#include +#include + +using namespace MQTTSNGW; + +#define RESPONSE_DURATION 900 // Secs + +/* + * Class ClientProxyElement + */ + +ClientProxyElement::ClientProxyElement(void) + : _clientId{0} + , _next{0} +{ + +} + +ClientProxyElement::ClientProxyElement(SensorNetAddress* addr, string* clientId) + : _next{0} +{ + _clientId = *clientId; + _sensorNetAddr = *addr; +} + +ClientProxyElement::~ClientProxyElement(void) +{ + +} + +/* + * Class ClientProxy + */ + +ClientProxy:: ClientProxy(void) + : _head{0} +{ + _gateway = 0; + _client = 0; +} + +ClientProxy:: ClientProxy(Gateway* gw) + : _head{0} +{ + _gateway = gw; + _client = 0; +} + + +ClientProxy::~ClientProxy(void) +{ + if ( _head ) + { + ClientProxyElement* p = _head; + while ( p ) + { + ClientProxyElement* next = p->_next; + delete p; + p = next; + } + } +} + +void ClientProxy::setGateway(Gateway* gw) +{ + _gateway = gw; +} + +ClientProxyElement* ClientProxy::add(SensorNetAddress* addr, string* clientId) +{ + ClientProxyElement* elm = new ClientProxyElement(addr, clientId); + if ( _head == 0 ) + { + _head = elm; + } + else + { + ClientProxyElement* p = _head; + while ( p ) + { + if ( p->_next == 0 ) + { + p->_next = elm; + break; + } + else + { + p = p->_next; + } + } + } + return elm; +} + +const char* ClientProxy::getClientId(SensorNetAddress* addr) +{ + ClientProxyElement* p = _head; + while ( p ) + { + if ( p->_sensorNetAddr.isMatch(addr) ) + { + return p->_clientId.c_str(); + break; + } + p = p->_next; + } + return 0; +} + +void ClientProxy::setClient(Client* client) +{ + _client = client; +} + +Client* ClientProxy::getClient(void) +{ + return _client; +} + +bool ClientProxy::setClientProxy(const char* fileName) +{ + FILE* fp; + char buf[MAX_CLIENTID_LENGTH + 256]; + size_t pos; + + SensorNetAddress netAddr; + + if ((fp = fopen(fileName, "r")) != 0) + { + while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0) + { + if (*buf == '#') + { + continue; + } + string data = string(buf); + while ((pos = data.find_first_of("  \t\n")) != string::npos) + { + data.erase(pos, 1); + } + if (data.empty()) + { + continue; + } + + pos = data.find_first_of(","); + string id = data.substr(0, pos); + string addr = data.substr(pos + 1); + + if (netAddr.setAddress(&addr) == 0) + { + add(&netAddr, &id); + } + else + { + WRITELOG("Invalid address %s\n", data.c_str()); + return false; + } + } + fclose(fp); + } + else + { + WRITELOG("Can not open the QoS_1Client List. %s\n", fileName); + return false; + } + return true; +} + + +void ClientProxy::checkConnection(void) +{ + if ( _client->isDisconnect() || ( _client->isConnecting() && _responseTimer.isTimeup()) ) + { + _client->connectSended(); + _responseTimer.start(RESPONSE_DURATION * 1000UL); + MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; + options.clientID.cstring = _client->getClientId(); + options.duration = RESPONSE_DURATION; + + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNECT(&options); + Event* ev = new Event(); + ev->setClientRecvEvent(_client, packet); + _gateway->getPacketEventQue()->post(ev); + + } + else if ( _client->isActive() && _keepAliveTimer.isTimeup() ) + { + MQTTSNPacket* packet = new MQTTSNPacket(); + MQTTSNString clientId = MQTTSNString_initializer; + packet->setPINGREQ(&clientId); + Event* ev = new Event(); + ev->setClientRecvEvent(_client, packet); + _gateway->getPacketEventQue()->post(ev); + resetPingTimer(); + } +} + +void ClientProxy::resetPingTimer(void) +{ + _keepAliveTimer.start(RESPONSE_DURATION * 1000UL); +} + +void ClientProxy::send(MQTTSNPacket* packet) +{ + if ( packet->getType() == MQTTSN_CONNACK || packet->getType() == MQTTSN_PINGRESP ) + { + resetPingTimer(); + sendStoredPublish(); + } + else if ( packet->getType() == MQTTSN_PINGRESP ) + { + resetPingTimer(); + } +} + +void ClientProxy::sendStoredPublish(void) +{ + MQTTSNPacket* msg = 0; + + while ( ( msg = _client->getProxyPacket() ) != 0 ) + { + _client->deleteFirstProxyPacket(); // pop the que to delete element. + + Event* ev = new Event(); + ev->setClientRecvEvent(_client, msg); + _gateway->getPacketEventQue()->post(ev); + } +} diff --git a/MQTTSNGateway/src/MQTTSNGWClientProxy.h b/MQTTSNGateway/src/MQTTSNGWClientProxy.h new file mode 100644 index 0000000..43e0acc --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWClientProxy.h @@ -0,0 +1,77 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTPROXY_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTPROXY_H_ + +#include "MQTTSNGateway.h" +#include "MQTTGWPacket.h" +#include "MQTTSNGWClient.h" +#include "SensorNetwork.h" +#include "MQTTSNGWProcess.h" + + + +namespace MQTTSNGW +{ +class Gateway; + +class ClientProxyElement +{ + friend class ClientProxy; +public: + ClientProxyElement(void); + ClientProxyElement(SensorNetAddress* addr, string* clientId); + ~ClientProxyElement(void); +private: + SensorNetAddress _sensorNetAddr; + string _clientId; + ClientProxyElement* _next; +}; + +class ClientProxy +{ +public: + ClientProxy(void); + ClientProxy(Gateway* gw); + ~ClientProxy(void); + bool setClientProxy(const char* fileName); + ClientProxyElement* add(SensorNetAddress* addr, string* clientId); + const char* getClientId(SensorNetAddress* addr); + void setClient(Client*); + Client* getClient(void); + void setGateway(Gateway* gw); + void setKeepAlive(uint16_t secs); + + void checkConnection(void); + void resetPingTimer(void); + void send(MQTTSNPacket* packet); + +private: + void sendStoredPublish(void); + + Gateway* _gateway; + Client* _client; + ClientProxyElement* _head; + Timer _keepAliveTimer; + Timer _responseTimer; +}; + +} + + + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTPROXY_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp index 9b74341..c17eaf9 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp @@ -17,10 +17,11 @@ #include "MQTTSNGWClientRecvTask.h" #include "MQTTSNGateway.h" #include "MQTTSNPacket.h" -#include "MQTTSNGWForwarder.h" #include "MQTTSNGWEncapsulatedPacket.h" #include +#include "MQTTSNGWForwarder.h" + using namespace MQTTSNGW; char* currentDateTime(void); /*===================================== @@ -91,31 +92,32 @@ void ClientRecvTask::run() if ( packet->getType() == MQTTSN_SEARCHGW ) { /* write log and post Event */ - log(0, packet); + log(0, packet, 0); ev = new Event(); ev->setBrodcastEvent(packet); _gateway->getPacketEventQue()->post(ev); continue; } + if ( packet->getType() == MQTTSN_ENCAPSULATED ) { fwd = _gateway->getForwarderList()->getForwarder(_sensorNetwork->getSenderAddress()); if ( fwd == 0 ) { - log(0, packet); - WRITELOG("%s Forwarder %s is not authorized.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); + log(0, packet, 0); + WRITELOG("%s Forwarder %s is not authenticated.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); delete packet; continue; } else { - MQTTSNString fwdName; - fwdName.lenstring.data = const_cast( fwd->getName() ); - fwdName.lenstring.len = strlen(fwdName.lenstring.data); + MQTTSNString fwdName = MQTTSNString_initializer; + fwdName.cstring = const_cast( fwd->getName() ); log(0, packet, &fwdName); + /* get the packet from the encapsulation message */ MQTTSNGWEncapsulatedPacket encap; encap.desirialize(packet->getPacketData(), packet->getPacketLength()); nodeId.setId( encap.getWirelessNodeId() ); @@ -126,15 +128,35 @@ void ClientRecvTask::run() } else { - /* get client from the ClientList of Gateway by sensorNetAddress. */ - client = _gateway->getClientList()->getClient(_sensorNetwork->getSenderAddress()); + const char* clientName = _gateway->getClientProxy()->getClientId(_sensorNetwork->getSenderAddress()); + + if ( clientName ) // This client is for QoS-1 PUBLISH. + { + if ( packet->isQoSMinusPUBLISH() ) + { + client = _gateway->getClientProxy()->getClient(); // point to the ClientProxy + } + else + { + client = _gateway->getClientProxy()->getClient(); + log(clientName, packet); + WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); + delete packet; + continue; + } + } + else + { + /* get client from the ClientList of Gateway by sensorNetAddress. */ + client = _gateway->getClientList()->getClient(_sensorNetwork->getSenderAddress()); + } } if ( client ) { /* write log and post Event */ - log(client, packet); + log(client, packet, 0); ev = new Event(); ev->setClientRecvEvent(client,packet); _gateway->getPacketEventQue()->post(ev); @@ -196,7 +218,7 @@ void ClientRecvTask::run() } else { - log(client, packet); + log(client, packet, 0); WRITELOG("%s Client(%s) is not connecting. message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); delete packet; @@ -216,16 +238,22 @@ void ClientRecvTask::run() void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id) { - char pbuf[SIZE_OF_LOG_PACKET * 3]; const char* clientId; char cstr[MAX_CLIENTID_LENGTH + 1]; - char msgId[6]; if ( id ) { - memset((void*)cstr, 0, id->lenstring.len + 1); - strncpy(cstr, id->lenstring.data, id->lenstring.len) ; - clientId = cstr; + if ( id->cstring ) + { + strncpy(cstr, id->cstring, strlen(id->cstring) ); + clientId = cstr; + } + else + { + memset((void*)cstr, 0, id->lenstring.len + 1); + strncpy(cstr, id->lenstring.data, id->lenstring.len ); + clientId = cstr; + } } else if ( client ) { @@ -236,40 +264,48 @@ void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id) clientId = UNKNOWNCL; } - switch (packet->getType()) - { - case MQTTSN_SEARCHGW: - WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, CLIENT, packet->print(pbuf)); - break; - case MQTTSN_CONNECT: - case MQTTSN_PINGREQ: - WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); - break; - case MQTTSN_DISCONNECT: - case MQTTSN_WILLTOPICUPD: - case MQTTSN_WILLMSGUPD: - case MQTTSN_WILLTOPIC: - case MQTTSN_WILLMSG: - WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); - break; - case MQTTSN_PUBLISH: - case MQTTSN_REGISTER: - case MQTTSN_SUBSCRIBE: - case MQTTSN_UNSUBSCRIBE: - WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); - break; - case MQTTSN_REGACK: - case MQTTSN_PUBACK: - case MQTTSN_PUBREC: - case MQTTSN_PUBREL: - case MQTTSN_PUBCOMP: - WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); - break; - case MQTTSN_ENCAPSULATED: - WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); - break; - default: - WRITELOG(FORMAT_W_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); - break; - } + log(clientId, packet); +} + +void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet) +{ + char pbuf[SIZE_OF_LOG_PACKET * 3]; + char msgId[6]; + + switch (packet->getType()) + { + case MQTTSN_SEARCHGW: + WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, CLIENT, packet->print(pbuf)); + break; + case MQTTSN_CONNECT: + case MQTTSN_PINGREQ: + WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); + break; + case MQTTSN_DISCONNECT: + case MQTTSN_WILLTOPICUPD: + case MQTTSN_WILLMSGUPD: + case MQTTSN_WILLTOPIC: + case MQTTSN_WILLMSG: + WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); + break; + case MQTTSN_PUBLISH: + case MQTTSN_REGISTER: + case MQTTSN_SUBSCRIBE: + case MQTTSN_UNSUBSCRIBE: + WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); + break; + case MQTTSN_REGACK: + case MQTTSN_PUBACK: + case MQTTSN_PUBREC: + case MQTTSN_PUBREL: + case MQTTSN_PUBCOMP: + WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); + break; + case MQTTSN_ENCAPSULATED: + WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); + break; + default: + WRITELOG(FORMAT_W_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); + break; + } } diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h index 295c0ee..b681a24 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h @@ -35,8 +35,8 @@ public: void run(); private: - void log(Client*, MQTTSNPacket*, MQTTSNString* id = 0); - + void log(Client*, MQTTSNPacket*, MQTTSNString* id); + void log(const char* clientId, MQTTSNPacket* packet); Gateway* _gateway; SensorNetwork* _sensorNetwork; }; diff --git a/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp index 87de924..76fe572 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp @@ -71,6 +71,11 @@ void ClientSendTask::run() else { log(client, packet); + if ( client->isProxy() ) + { + _gateway->getClientProxy()->send(packet); + continue; + } rc = packet->unicast(_sensorNetwork, client->getSensorNetAddress()); } } diff --git a/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp b/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp index 06b8d43..43aea61 100644 --- a/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp @@ -90,7 +90,10 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet //* clear ConnectData of Client */ Connect* connectData = client->getConnectData(); memset(connectData, 0, sizeof(Connect)); - client->disconnected(); + if ( !client->isProxy() ) + { + client->disconnected(); + } Topics* topics = client->getTopics(); @@ -153,7 +156,7 @@ void MQTTSNConnectionHandler::handleWilltopic(Client* client, MQTTSNPacket* pack { int willQos; uint8_t willRetain; - MQTTSNString willTopic; + MQTTSNString willTopic = MQTTSNString_initializer; if ( packet->getWILLTOPIC(&willQos, &willRetain, &willTopic) == 0 ) { @@ -187,7 +190,7 @@ void MQTTSNConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet return; } - MQTTSNString willmsg; + MQTTSNString willmsg = MQTTSNString_initializer; Connect* connectData = client->getConnectData(); if( client->isConnectSendable() ) diff --git a/MQTTSNGateway/src/MQTTSNGWDefines.h b/MQTTSNGateway/src/MQTTSNGWDefines.h index 8f7f837..7da2109 100644 --- a/MQTTSNGateway/src/MQTTSNGWDefines.h +++ b/MQTTSNGateway/src/MQTTSNGWDefines.h @@ -27,6 +27,7 @@ namespace MQTTSNGW #define CLIENT_LIST "clients.conf" #define PREDEFINEDTOPIC_FILE "predefinedTopic.conf" #define FORWARDER_LIST "forwarders.conf" +#define QOS_1CLIENT_LIST "qos-1clients.conf" /*========================================================== * Gateway default parameters diff --git a/MQTTSNGateway/src/MQTTSNGWForwarder.cpp b/MQTTSNGateway/src/MQTTSNGWForwarder.cpp index 0bad175..ad1e94b 100644 --- a/MQTTSNGateway/src/MQTTSNGWForwarder.cpp +++ b/MQTTSNGateway/src/MQTTSNGWForwarder.cpp @@ -13,9 +13,10 @@ * Contributors: * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ -#include #include "MQTTSNGWForwarder.h" +#include + using namespace MQTTSNGW; using namespace std; @@ -155,10 +156,10 @@ Forwarder::~Forwarder(void) { if ( _headClient ) { - ForwardedClient* p = _headClient; + ForwarderElement* p = _headClient; while ( p ) { - ForwardedClient* next = p->_next; + ForwarderElement* next = p->_next; delete p; p = next; } @@ -172,8 +173,8 @@ const char* Forwarder::getId(void) void Forwarder::addClient(Client* client, WirelessNodeId* id) { - ForwardedClient* p = _headClient; - ForwardedClient* prev = 0; + ForwarderElement* p = _headClient; + ForwarderElement* prev = 0; client->setForwarder(this); @@ -191,7 +192,7 @@ void Forwarder::addClient(Client* client, WirelessNodeId* id) } } - ForwardedClient* fclient = new ForwardedClient(); + ForwarderElement* fclient = new ForwarderElement(); fclient->setClient(client); fclient->setWirelessNodeId(id); @@ -210,7 +211,7 @@ Client* Forwarder::getClient(WirelessNodeId* id) { Client* cl = 0; _mutex.lock(); - ForwardedClient* p = _headClient; + ForwarderElement* p = _headClient; while ( p ) { if ( *(p->_wirelessNodeId) == *id ) @@ -236,7 +237,7 @@ WirelessNodeId* Forwarder::getWirelessNodeId(Client* client) { WirelessNodeId* nodeId = 0; _mutex.lock(); - ForwardedClient* p = _headClient; + ForwarderElement* p = _headClient; while ( p ) { if ( p->_client == client ) @@ -255,9 +256,9 @@ WirelessNodeId* Forwarder::getWirelessNodeId(Client* client) void Forwarder::eraseClient(Client* client) { - ForwardedClient* prev = 0; + ForwarderElement* prev = 0; _mutex.lock(); - ForwardedClient* p = _headClient; + ForwarderElement* p = _headClient; while ( p ) { @@ -291,14 +292,14 @@ SensorNetAddress* Forwarder::getSensorNetAddr(void) * Class ForwardedClient */ -ForwardedClient::ForwardedClient() +ForwarderElement::ForwarderElement() : _client{0} , _wirelessNodeId{0} , _next{0} { } -ForwardedClient::~ForwardedClient() +ForwarderElement::~ForwarderElement() { if (_wirelessNodeId) { @@ -306,12 +307,12 @@ ForwardedClient::~ForwardedClient() } } -void ForwardedClient::setClient(Client* client) +void ForwarderElement::setClient(Client* client) { _client = client; } -void ForwardedClient::setWirelessNodeId(WirelessNodeId* id) +void ForwarderElement::setWirelessNodeId(WirelessNodeId* id) { if ( _wirelessNodeId == 0 ) { diff --git a/MQTTSNGateway/src/MQTTSNGWForwarder.h b/MQTTSNGateway/src/MQTTSNGWForwarder.h index db6d099..2c58e66 100644 --- a/MQTTSNGateway/src/MQTTSNGWForwarder.h +++ b/MQTTSNGateway/src/MQTTSNGWForwarder.h @@ -28,18 +28,18 @@ namespace MQTTSNGW class Client; class WirelessNodeId; -class ForwardedClient +class ForwarderElement { friend class Forwarder; public: - ForwardedClient(); - ~ForwardedClient(); + ForwarderElement(); + ~ForwarderElement(); void setClient(Client* client); void setWirelessNodeId(WirelessNodeId* id); private: Client* _client; WirelessNodeId* _wirelessNodeId; - ForwardedClient* _next; + ForwarderElement* _next; }; @@ -62,7 +62,7 @@ public: private: string _forwarderName; SensorNetAddress _sensorNetAddr; - ForwardedClient* _headClient; + ForwarderElement* _headClient; Forwarder* _next; Mutex _mutex; }; diff --git a/MQTTSNGateway/src/MQTTSNGWPacket.cpp b/MQTTSNGateway/src/MQTTSNGWPacket.cpp index 74c00fb..222597f 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacket.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPacket.cpp @@ -101,6 +101,17 @@ int MQTTSNPacket::getType(void) 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; @@ -119,7 +130,8 @@ const char* MQTTSNPacket::getName() int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration) { unsigned char buf[5]; - int len = MQTTSNSerialize_advertise(buf, 5, (unsigned char) gatewayid, + int buflen = sizeof(buf); + int len = MQTTSNSerialize_advertise(buf, buflen, (unsigned char) gatewayid, (unsigned short) duration); return desirialize(buf, len); } @@ -127,44 +139,50 @@ int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration) int MQTTSNPacket::setGWINFO(uint8_t gatewayId) { unsigned char buf[3]; - int len = MQTTSNSerialize_gwinfo(buf, 3, (unsigned char) gatewayId, 0, 0); + 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, 40, &data); + int len = MQTTSNSerialize_connect(buf, buflen, &data); return desirialize(buf, len); } int MQTTSNPacket::setCONNACK(uint8_t returnCode) { unsigned char buf[3]; - int len = MQTTSNSerialize_connack(buf, 3, (int) returnCode); + 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 len = MQTTSNSerialize_willtopicreq(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 len = MQTTSNSerialize_willmsgreq(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 len = MQTTSNSerialize_register(buf, MQTTSNGW_MAX_PACKET_SIZE, (unsigned short) topicId, (unsigned short) msgId, + int buflen = sizeof(buf); + int len = MQTTSNSerialize_register(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, topicName); return desirialize(buf, len); } @@ -172,7 +190,8 @@ int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* to 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, + int buflen = sizeof(buf); + int len = MQTTSNSerialize_regack(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); return desirialize(buf, len); } @@ -181,7 +200,8 @@ int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t ms 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, + 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); } @@ -189,7 +209,8 @@ int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t ms 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, + int buflen = sizeof(buf); + int len = MQTTSNSerialize_puback(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); return desirialize(buf, len); } @@ -197,28 +218,32 @@ int MQTTSNPacket::setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode int MQTTSNPacket::setPUBREC(uint16_t msgId) { unsigned char buf[4]; - int len = MQTTSNSerialize_pubrec(buf, 4, (unsigned short) msgId); + 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 len = MQTTSNSerialize_pubrel(buf, 4, (unsigned short) msgId); + 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 len = MQTTSNSerialize_pubcomp(buf, 4, (unsigned short) msgId); + 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 len = MQTTSNSerialize_suback(buf, 8, qos, (unsigned short) topicId, + int buflen = sizeof(buf); + int len = MQTTSNSerialize_suback(buf, buflen, qos, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); return desirialize(buf, len); } @@ -226,38 +251,59 @@ int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t r int MQTTSNPacket::setUNSUBACK(uint16_t msgId) { unsigned char buf[4]; - int len = MQTTSNSerialize_unsuback(buf, 4, (unsigned short) msgId); + 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 len = MQTTSNSerialize_pingresp(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 len = MQTTSNSerialize_disconnect(buf, 4, (int) duration); + 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 len = MQTTSNSerialize_willtopicresp(buf, MQTTSNGW_MAX_PACKET_SIZE, (int) returnCode); + 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 len = MQTTSNSerialize_willmsgresp(buf, MQTTSNGW_MAX_PACKET_SIZE, (int) returnCode); + 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); diff --git a/MQTTSNGateway/src/MQTTSNGWPacket.h b/MQTTSNGateway/src/MQTTSNGWPacket.h index 5cd7578..22e3bd7 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacket.h +++ b/MQTTSNGateway/src/MQTTSNGWPacket.h @@ -59,6 +59,9 @@ public: int setWILLTOPICRESP(uint8_t returnCode); int setWILLMSGRESP(uint8_t returnCode); + int setCONNECT(MQTTSNPacket_connectData* options); + int setPINGREQ(MQTTSNString* clientId); + int getSERCHGW(uint8_t* radius); int getCONNECT(MQTTSNPacket_connectData* option); int getCONNACK(uint8_t* returnCode); @@ -76,6 +79,8 @@ public: int getDISCONNECT(uint16_t* duration); int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic); int getWILLMSGUPD(MQTTSNString* willMsg); + + bool isQoSMinusPUBLISH(void); char* getMsgId(char* buf); char* print(char* buf); diff --git a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp index 02dd9ab..e1c5e09 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp @@ -113,6 +113,9 @@ void PacketHandleTask::run() _mqttsnConnection->sendADVERTISE(); _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); } + + /*------ Check ClientProxy to Connect or send PINGREQ ------*/ + _gateway->getClientProxy()->checkConnection(); } /*------ Handle SEARCHGW Message ---------*/ diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp index 4f0adc4..dac2040 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp @@ -43,18 +43,26 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) uint8_t* payload; MQTTSN_topicid topicid; int payloadlen; - Publish pub; + Publish pub = {0, 0, 0, 0, 0, 0}; + char shortTopic[2]; if ( !client->isActive() ) { - /* Reply DISCONNECT to the client */ - Event* ev = new Event(); - MQTTSNPacket* disconnect = new MQTTSNPacket(); - disconnect->setDISCONNECT(0); - ev->setClientSendEvent(client, disconnect); - _gateway->getClientSendQue()->post(ev); - return; + if ( client->isProxy() ) + { + client->setProxyPacket(packet); + } + else + { + /* Reply DISCONNECT to the client */ + Event* ev = new Event(); + MQTTSNPacket* disconnect = new MQTTSNPacket(); + disconnect->setDISCONNECT(0); + ev->setClientSendEvent(client, disconnect); + _gateway->getClientSendQue()->post(ev); + } + return; } if ( packet->getPUBLISH(&dup, &qos, &retained, &msgId, &topicid, &payload, &payloadlen) ==0 ) @@ -63,7 +71,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) } pub.msgId = msgId; pub.header.bits.dup = dup; - pub.header.bits.qos = qos; + pub.header.bits.qos = ( qos == 3 ? 0 : qos ); pub.header.bits.retain = retained; Topic* topic = 0; @@ -79,7 +87,13 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) { topic = client->getTopics()->getTopicById(&topicid); - if( !topic && msgId && qos > 0 ) + if( !topic && qos == 3 ) + { + WRITELOG("%s Invali TopicId.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + return; + } + + if( !topic && msgId && qos > 0 && qos < 3 ) { /* Reply PubAck with INVALID_TOPIC_ID to the client */ MQTTSNPacket* pubAck = new MQTTSNPacket(); @@ -96,7 +110,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) } } /* Save a msgId & a TopicId pare for PUBACK */ - if( msgId && qos > 0 ) + if( msgId && qos > 0 && qos < 3) { client->setWaitedPubTopicId(msgId, topicid.data.id, topicid.type); } @@ -161,7 +175,7 @@ void MQTTSNPublishHandler::handleRegister(Client* client, MQTTSNPacket* packet) { uint16_t id; uint16_t msgId; - MQTTSNString topicName; + MQTTSNString topicName = MQTTSNString_initializer;; MQTTSN_topicid topicid; if ( client->isActive() || client->isAwake()) diff --git a/MQTTSNGateway/src/MQTTSNGateway.cpp b/MQTTSNGateway/src/MQTTSNGateway.cpp index c6029ce..ac47ff7 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.cpp +++ b/MQTTSNGateway/src/MQTTSNGateway.cpp @@ -30,6 +30,7 @@ Gateway::Gateway() { theMultiTaskProcess = this; theProcess = this; + _clientProxy = new ClientProxy(this); _params.loginId = 0; _params.password = 0; _params.keepAlive = 0; @@ -48,6 +49,7 @@ Gateway::Gateway() _params.configName = 0; _params.predefinedTopicFileName = 0; _params.forwarderListName = 0; + _params.qosMinusClientListName = 0; _packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS); } @@ -109,12 +111,21 @@ Gateway::~Gateway() { free(_params.forwarderListName); } + if ( _params.qosMinusClientListName ) + { + free(_params.qosMinusClientListName); + } + if ( _clientProxy ) + { + delete _clientProxy; + } } void Gateway::initialize(int argc, char** argv) { char param[MQTTSNGW_PARAM_MAX]; string fileName; + bool secure = false; MultiTaskProcess::initialize(argc, argv); resetRingBuffer(); @@ -201,6 +212,7 @@ void Gateway::initialize(int argc, char** argv) { if (!strcasecmp(param, "YES")) { + secure = true; if (getParam("ClientsList", param) == 0) { fileName = string(param); @@ -218,7 +230,33 @@ void Gateway::initialize(int argc, char** argv) } } + /* Set ClientProxy's Client */ + MQTTSNString id = MQTTSNString_initializer; + id.cstring = const_cast(CLIENTPROXY); + Client* client = _clientList.createClient(0, &id, true, secure); + _clientProxy->setClient(client); + client->setPorxy(true); + _clientProxy->setGateway(this); + if (getParam("QoS-1", param) == 0 ) + { + if (!strcasecmp(param, "YES") ) + { + if (getParam("QoS-1ClientsList", param) == 0) + { + fileName = string(param); + } + else + { + fileName = *getConfigDirName() + string(QOS_1CLIENT_LIST); + } + if ( !_clientProxy->setClientProxy(fileName.c_str()) ) + { + throw Exception("Gateway::initialize: No QoS-1ClientsList file defined by the configuration.."); + } + _params.qosMinusClientListName = strdup(fileName.c_str()); + } + } if (getParam("PredefinedTopic", param) == 0 ) { @@ -238,38 +276,31 @@ void Gateway::initialize(int argc, char** argv) } _params.predefinedTopicFileName = strdup(fileName.c_str()); } - else - { - _params.predefinedTopicFileName = 0; - } } if (getParam("Forwarder", param) == 0 ) - { - if (!strcasecmp(param, "YES") ) - { - if (getParam("ForwardersList", param) == 0) - { - fileName = string(param); - } - else - { - fileName = *getConfigDirName() + string(FORWARDER_LIST); - } - if ( !_forwarderList.setFowerder(fileName.c_str()) ) - { - throw Exception("Gateway::initialize: No ForwardersList file defined by the configuration.."); - } - _params.forwarderListName = strdup(fileName.c_str()); - } - else - { - _params.forwarderListName = 0; - } - } + { + if (!strcasecmp(param, "YES") ) + { + if (getParam("ForwardersList", param) == 0) + { + fileName = string(param); + } + else + { + fileName = *getConfigDirName() + string(FORWARDER_LIST); + } + if ( !_forwarderList.setFowerder(fileName.c_str()) ) + { + throw Exception("Gateway::initialize: No ForwardersList file defined by the configuration.."); + } + _params.forwarderListName = strdup(fileName.c_str()); + } + } fileName = *getConfigDirName() + *getConfigFileName(); _params.configName = strdup(fileName.c_str()); + } void Gateway::run(void) @@ -295,6 +326,10 @@ void Gateway::run(void) if ( _params.forwarderListName ) { WRITELOG(" Forwarders: %s\n", _params.forwarderListName); + } + if ( _params.qosMinusClientListName ) + { + WRITELOG(" QoS-1: %s\n", _params.qosMinusClientListName); } WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription()); WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); @@ -302,7 +337,7 @@ void Gateway::run(void) WRITELOG(" RootCApath: %s\n", _params.rootCApath); WRITELOG(" RootCAfile: %s\n", _params.rootCAfile); WRITELOG(" CertKey: %s\n", _params.certKey); - WRITELOG(" PrivateKey: %s\n", _params.privateKey); + WRITELOG(" PrivateKey: %s\n\n\n", _params.privateKey); MultiTaskProcess::run(); @@ -364,6 +399,11 @@ GatewayParams* Gateway::getGWParams(void) return &_params; } +ClientProxy* Gateway::getClientProxy(void) +{ + return _clientProxy; +} + /*===================================== Class EventQue =====================================*/ diff --git a/MQTTSNGateway/src/MQTTSNGateway.h b/MQTTSNGateway/src/MQTTSNGateway.h index d219d6f..dbe6ae4 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.h +++ b/MQTTSNGateway/src/MQTTSNGateway.h @@ -17,10 +17,12 @@ #define MQTTSNGATEWAY_H_ #include "MQTTSNGWClient.h" -#include "MQTTSNGWForwarder.h" #include "MQTTSNGWProcess.h" #include "MQTTSNPacket.h" +#include "MQTTSNGWForwarder.h" +#include "MQTTSNGWClientProxy.h" + namespace MQTTSNGW { /*================================= @@ -43,6 +45,7 @@ namespace MQTTSNGW #define CLIENT "Client" #define CLIENTS "Clients" #define UNKNOWNCL "Unknown Client !" +#define CLIENTPROXY "ClientProxy" #define LEFTARROW "<---" #define RIGHTARROW "--->" @@ -156,11 +159,14 @@ typedef struct char* privateKey; char* predefinedTopicFileName; char* forwarderListName; + char* qosMinusClientListName; }GatewayParams; /*===================================== Class Gateway =====================================*/ +class ClientProxy; + class Gateway: public MultiTaskProcess{ public: Gateway(); @@ -176,9 +182,11 @@ public: SensorNetwork* getSensorNetwork(void); LightIndicator* getLightIndicator(void); GatewayParams* getGWParams(void); + ClientProxy* getClientProxy(void); private: ClientList _clientList; + ClientProxy* _clientProxy; ForwarderList _forwarderList; EventQue _packetEventQue; EventQue _brokerSendQue; From 79f6aef8e4ec4effa635d1a5cd6ccbf394b82c04 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Tue, 31 Jul 2018 06:20:57 +0900 Subject: [PATCH 02/10] BugFix: PINGREQ timeout of ClientProxy reset PINGREQ timer of ClientProxy when QoS-1 PUBLISH is sent. Signed-off-by: tomoaki --- MQTTSNGateway/GatewayTester/src/LGwProxy.cpp | 5 + .../GatewayTester/src/LPublishManager.cpp | 654 +++++++++--------- MQTTSNGateway/src/MQTTSNGWClientProxy.cpp | 7 +- MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp | 8 +- MQTTSNGateway/src/MQTTSNGWVersion.h | 2 +- MQTTSNGateway/src/MQTTSNGateway.cpp | 2 +- 6 files changed, 345 insertions(+), 333 deletions(-) diff --git a/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp b/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp index b0e86cd..cdacac1 100644 --- a/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp +++ b/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp @@ -586,6 +586,11 @@ uint16_t LGwProxy::getNextMsgId(void) void LGwProxy::checkPingReq(void) { + if ( _isQoSMinus1Mode ) + { + return; + } + uint8_t msg[2]; msg[0] = 0x02; msg[1] = MQTTSN_TYPE_PINGREQ; diff --git a/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp b/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp index ccdfe62..918cddb 100644 --- a/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp +++ b/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp @@ -40,351 +40,351 @@ const char* NULLCHAR = ""; LPublishManager::LPublishManager() { - _first = 0; - _last = 0; - _elmCnt = 0; - _publishedFlg = SAVE_TASK_INDEX; + _first = 0; + _last = 0; + _elmCnt = 0; + _publishedFlg = SAVE_TASK_INDEX; } LPublishManager::~LPublishManager() { - PubElement* elm = _first; - PubElement* sav = 0; - while (elm) - { - sav = elm->next; - if (elm != 0) - { - delElement(elm); - } - elm = sav; - } + PubElement* elm = _first; + PubElement* sav = 0; + while (elm) + { + sav = elm->next; + if (elm != 0) + { + delElement(elm); + } + elm = sav; + } } void LPublishManager::publish(const char* topicName, Payload* payload, uint8_t qos, bool retain) { - publish(topicName, payload->getRowData(), payload->getLen(), qos, retain); + publish(topicName, payload->getRowData(), payload->getLen(), qos, retain); } void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain) { - uint16_t msgId = 0; - uint8_t topicType = MQTTSN_TOPIC_TYPE_SHORT; + uint16_t msgId = 0; + uint8_t topicType = MQTTSN_TOPIC_TYPE_SHORT; if ( strlen(topicName) > 2 ) { topicType = MQTTSN_TOPIC_TYPE_NORMAL; } - if ( qos > 0 && qos < 3 ) - { - msgId = theClient->getGwProxy()->getNextMsgId(); - } + if ( qos > 0 && qos < 3 ) + { + msgId = theClient->getGwProxy()->getNextMsgId(); + } - PubElement* elm = add(topicName, 0, payload, len, qos, retain, msgId, topicType); + PubElement* elm = add(topicName, 0, payload, len, qos, retain, msgId, topicType); - if (elm->status == TOPICID_IS_READY) - { - sendPublish(elm); - } - else - { - theClient->getGwProxy()->registerTopic((char*) topicName, 0); - } + if (elm->status == TOPICID_IS_READY) + { + sendPublish(elm); + } + else + { + theClient->getGwProxy()->registerTopic((char*) topicName, 0); + } } void LPublishManager::publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain) { - publish(topicId, payload->getRowData(), payload->getLen(), qos, retain); + publish(topicId, payload->getRowData(), payload->getLen(), qos, retain); } void LPublishManager::publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain) { - uint16_t msgId = 0; - if ( qos > 0 ) - { - msgId = theClient->getGwProxy()->getNextMsgId(); - } - PubElement* elm = add(NULLCHAR, topicId, payload, len, qos, retain, msgId, MQTTSN_TOPIC_TYPE_PREDEFINED); - sendPublish(elm); + uint16_t msgId = 0; + if ( qos > 0 && qos < 3 ) + { + msgId = theClient->getGwProxy()->getNextMsgId(); + } + PubElement* elm = add(NULLCHAR, topicId, payload, len, qos, retain, msgId, MQTTSN_TOPIC_TYPE_PREDEFINED); + sendPublish(elm); } void LPublishManager::sendPublish(PubElement* elm) { - if (elm == 0) - { - return; - } + if (elm == 0) + { + return; + } - theClient->getGwProxy()->connect(); + theClient->getGwProxy()->connect(); - uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1]; - uint8_t org = 0; - if (elm->payloadlen > 128) - { - msg[0] = 0x01; - setUint16(msg + 1, elm->payloadlen + 9); - org = 2; - } - else - { - msg[0] = (uint8_t) elm->payloadlen + 7; - } - msg[org + 1] = MQTTSN_TYPE_PUBLISH; - msg[org + 2] = elm->flag; - if ((elm->retryCount < MQTTSN_RETRY_COUNT)) - { - msg[org + 2] = msg[org + 2] | MQTTSN_FLAG_DUP; - } - if ((elm->flag & 0x03) == MQTTSN_TOPIC_TYPE_SHORT ) - { - memcpy(msg + org + 3, elm->topicName, 2); - } - else - { - setUint16(msg + org + 3, elm->topicId); - } - setUint16(msg + org + 5, elm->msgId); - memcpy(msg + org + 7, elm->payload, elm->payloadlen); + uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1]; + uint8_t org = 0; + if (elm->payloadlen > 128) + { + msg[0] = 0x01; + setUint16(msg + 1, elm->payloadlen + 9); + org = 2; + } + else + { + msg[0] = (uint8_t) elm->payloadlen + 7; + } + msg[org + 1] = MQTTSN_TYPE_PUBLISH; + msg[org + 2] = elm->flag; + if ((elm->retryCount < MQTTSN_RETRY_COUNT)) + { + msg[org + 2] = msg[org + 2] | MQTTSN_FLAG_DUP; + } + if ((elm->flag & 0x03) == MQTTSN_TOPIC_TYPE_SHORT ) + { + memcpy(msg + org + 3, elm->topicName, 2); + } + else + { + setUint16(msg + org + 3, elm->topicId); + } + setUint16(msg + org + 5, elm->msgId); + memcpy(msg + org + 7, elm->payload, elm->payloadlen); - theClient->getGwProxy()->writeMsg(msg); - theClient->getGwProxy()->setPingReqTimer(); - if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_0) - { - DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Published. \033[0m\033[0;37m\n\n", elm->topicName); - remove(elm); // PUBLISH Done - return; - } - else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_1) - { - elm->status = WAIT_PUBACK; - } - else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_2) - { - elm->status = WAIT_PUBREC; - } + theClient->getGwProxy()->writeMsg(msg); + theClient->getGwProxy()->setPingReqTimer(); + if ( ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_0 ) || ( (elm->flag & 0x60) == MQTTSN_FLAG_QOS_M1) ) + { + DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Published. \033[0m\033[0;37m\n\n", elm->topicName); + remove(elm); // PUBLISH Done + return; + } + else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_1) + { + elm->status = WAIT_PUBACK; + } + else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_2) + { + elm->status = WAIT_PUBREC; + } - elm->sendUTC = time(NULL); - elm->retryCount--; + elm->sendUTC = time(NULL); + elm->retryCount--; } void LPublishManager::sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType) { - PubElement* elm = _first; - while (elm) - { - if (strcmp(elm->topicName, topicName) == 0 && elm->status == TOPICID_IS_SUSPEND) - { - elm->topicId = topicId; - elm->flag |= topicType; - elm->status = TOPICID_IS_READY; - sendPublish(elm); - elm = 0; - } - else - { - elm = elm->next; - } - } + PubElement* elm = _first; + while (elm) + { + if (strcmp(elm->topicName, topicName) == 0 && elm->status == TOPICID_IS_SUSPEND) + { + elm->topicId = topicId; + elm->flag |= topicType; + elm->status = TOPICID_IS_READY; + sendPublish(elm); + elm = 0; + } + else + { + elm = elm->next; + } + } } void LPublishManager::sendPubAck(uint16_t topicId, uint16_t msgId, uint8_t rc) { - uint8_t msg[7]; - msg[0] = 7; - msg[1] = MQTTSN_TYPE_PUBACK; - setUint16(msg + 2, topicId); - setUint16(msg + 4, msgId); - msg[6] = rc; - theClient->getGwProxy()->writeMsg(msg); + uint8_t msg[7]; + msg[0] = 7; + msg[1] = MQTTSN_TYPE_PUBACK; + setUint16(msg + 2, topicId); + setUint16(msg + 4, msgId); + msg[6] = rc; + theClient->getGwProxy()->writeMsg(msg); } void LPublishManager::sendPubRel(PubElement* elm) { - uint8_t msg[4]; - msg[0] = 4; - msg[1] = MQTTSN_TYPE_PUBREL; - setUint16(msg + 2, elm->msgId); - theClient->getGwProxy()->writeMsg(msg); + uint8_t msg[4]; + msg[0] = 4; + msg[1] = MQTTSN_TYPE_PUBREL; + setUint16(msg + 2, elm->msgId); + theClient->getGwProxy()->writeMsg(msg); } bool LPublishManager::isDone(void) { - return (_first == 0); + return (_first == 0); } bool LPublishManager::isMaxFlight(void) { - return (_elmCnt > MAX_INFLIGHT_MSG / 2); + return (_elmCnt > MAX_INFLIGHT_MSG / 2); } void LPublishManager::responce(const uint8_t* msg, uint16_t msglen) { - if (msg[0] == MQTTSN_TYPE_PUBACK) - { - uint16_t msgId = getUint16(msg + 3); - PubElement* elm = getElement(msgId); - if (elm == 0) - { - return; - } - if (msg[5] == MQTTSN_RC_ACCEPTED) - { - if (elm->status == WAIT_PUBACK) - { - DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Published. \033[0m\033[0;37m\n\n", elm->topicName, elm->topicId); - remove(elm); // PUBLISH Done - } - } - else if (msg[5] == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID) - { - elm->status = TOPICID_IS_SUSPEND; - elm->topicId = 0; - elm->retryCount = MQTTSN_RETRY_COUNT; - elm->sendUTC = 0; - theClient->getGwProxy()->registerTopic((char*) elm->topicName, 0); - } - } - else if (msg[0] == MQTTSN_TYPE_PUBREC) - { - PubElement* elm = getElement(getUint16(msg + 1)); - if (elm == 0) - { - return; - } - if (elm->status == WAIT_PUBREC || elm->status == WAIT_PUBCOMP) - { - sendPubRel(elm); - elm->status = WAIT_PUBCOMP; - elm->sendUTC = time(NULL); - } - } - else if (msg[0] == MQTTSN_TYPE_PUBCOMP) - { - PubElement* elm = getElement(getUint16(msg + 1)); - if (elm == 0) - { - return; - } - if (elm->status == WAIT_PUBCOMP) - { - DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Published. \033[0m\033[0;37m\n\n", elm->topicName, elm->topicId); - remove(elm); // PUBLISH Done - } - } + if (msg[0] == MQTTSN_TYPE_PUBACK) + { + uint16_t msgId = getUint16(msg + 3); + PubElement* elm = getElement(msgId); + if (elm == 0) + { + return; + } + if (msg[5] == MQTTSN_RC_ACCEPTED) + { + if (elm->status == WAIT_PUBACK) + { + DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Published. \033[0m\033[0;37m\n\n", elm->topicName, elm->topicId); + remove(elm); // PUBLISH Done + } + } + else if (msg[5] == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID) + { + elm->status = TOPICID_IS_SUSPEND; + elm->topicId = 0; + elm->retryCount = MQTTSN_RETRY_COUNT; + elm->sendUTC = 0; + theClient->getGwProxy()->registerTopic((char*) elm->topicName, 0); + } + } + else if (msg[0] == MQTTSN_TYPE_PUBREC) + { + PubElement* elm = getElement(getUint16(msg + 1)); + if (elm == 0) + { + return; + } + if (elm->status == WAIT_PUBREC || elm->status == WAIT_PUBCOMP) + { + sendPubRel(elm); + elm->status = WAIT_PUBCOMP; + elm->sendUTC = time(NULL); + } + } + else if (msg[0] == MQTTSN_TYPE_PUBCOMP) + { + PubElement* elm = getElement(getUint16(msg + 1)); + if (elm == 0) + { + return; + } + if (elm->status == WAIT_PUBCOMP) + { + DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Published. \033[0m\033[0;37m\n\n", elm->topicName, elm->topicId); + remove(elm); // PUBLISH Done + } + } } void LPublishManager::published(uint8_t* msg, uint16_t msglen) { - uint16_t topicId = getUint16(msg + 2); + uint16_t topicId = getUint16(msg + 2); - if (msg[1] & MQTTSN_FLAG_QOS_1) - { - sendPubAck(topicId, getUint16(msg + 4), MQTTSN_RC_ACCEPTED); - } + if (msg[1] & MQTTSN_FLAG_QOS_1) + { + sendPubAck(topicId, getUint16(msg + 4), MQTTSN_RC_ACCEPTED); + } - _publishedFlg = NEG_TASK_INDEX; - theClient->getTopicTable()->execCallback(topicId, msg + 6, msglen - 6, (MQTTSN_topicTypes)(msg[1] & MQTTSN_TOPIC_TYPE)); - _publishedFlg = SAVE_TASK_INDEX; + _publishedFlg = NEG_TASK_INDEX; + theClient->getTopicTable()->execCallback(topicId, msg + 6, msglen - 6, (MQTTSN_topicTypes)(msg[1] & MQTTSN_TOPIC_TYPE)); + _publishedFlg = SAVE_TASK_INDEX; } void LPublishManager::checkTimeout(void) { - PubElement* elm = _first; - while (elm) - { - if (elm->sendUTC > 0 && elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL)) - { - if (elm->retryCount >= 0) - { - sendPublish(elm); - D_MQTTLOG("...Timeout retry\r\n"); - } - else - { - theClient->getGwProxy()->reconnect(); - elm->retryCount = MQTTSN_RETRY_COUNT; - break; - } - } - elm = elm->next; - } + PubElement* elm = _first; + while (elm) + { + if (elm->sendUTC > 0 && elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL)) + { + if (elm->retryCount >= 0) + { + sendPublish(elm); + D_MQTTLOG("...Timeout retry\r\n"); + } + else + { + theClient->getGwProxy()->reconnect(); + elm->retryCount = MQTTSN_RETRY_COUNT; + break; + } + } + elm = elm->next; + } } PubElement* LPublishManager::getElement(uint16_t msgId) { - PubElement* elm = _first; - while (elm) - { - if (elm->msgId == msgId) - { - break; - } - else - { - elm = elm->next; - } - } - return elm; + PubElement* elm = _first; + while (elm) + { + if (elm->msgId == msgId) + { + break; + } + else + { + elm = elm->next; + } + } + return elm; } PubElement* LPublishManager::getElement(const char* topicName) { - PubElement* elm = _first; - while (elm) - { - if (strcmp(elm->topicName, topicName) == 0) - { - break; - } - else - { - elm = elm->next; - } - } - return elm; + PubElement* elm = _first; + while (elm) + { + if (strcmp(elm->topicName, topicName) == 0) + { + break; + } + else + { + elm = elm->next; + } + } + return elm; } void LPublishManager::remove(PubElement* elm) { - if (elm) - { - if (elm->prev == 0) - { - _first = elm->next; - if (elm->next == 0) - { - _last = 0; - } - else - { - elm->next->prev = 0; - _last = elm->next; - } - } - else - { - if ( elm->next == 0 ) - { - _last = elm->prev; - } - elm->prev->next = elm->next; - } - delElement(elm); - } + if (elm) + { + if (elm->prev == 0) + { + _first = elm->next; + if (elm->next == 0) + { + _last = 0; + } + else + { + elm->next->prev = 0; + _last = elm->next; + } + } + else + { + if ( elm->next == 0 ) + { + _last = elm->prev; + } + elm->prev->next = elm->next; + } + delElement(elm); + } } void LPublishManager::delElement(PubElement* elm) { - if (elm->taskIndex >= 0) - { - theClient->getTaskManager()->done(elm->taskIndex); - } - _elmCnt--; - if ( elm->payload ) - { - free(elm->payload); - } - free(elm); + if (elm->taskIndex >= 0) + { + theClient->getTaskManager()->done(elm->taskIndex); + } + _elmCnt--; + if ( elm->payload ) + { + free(elm->payload); + } + free(elm); } /* @@ -393,88 +393,88 @@ void LPublishManager::delElement(PubElement* elm) }*/ PubElement* LPublishManager::add(const char* topicName, uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, - uint8_t retain, uint16_t msgId, uint8_t topicType) + uint8_t retain, uint16_t msgId, uint8_t topicType) { - PubElement* elm = (PubElement*) calloc(1, sizeof(PubElement)); + PubElement* elm = (PubElement*) calloc(1, sizeof(PubElement)); - if (elm == 0) - { - return elm; - } - if (_last == 0) - { - _first = elm; - _last = elm; - } - else - { - elm->prev = _last; - _last->next = elm; - _last = elm; - } + if (elm == 0) + { + return elm; + } + if (_last == 0) + { + _first = elm; + _last = elm; + } + else + { + elm->prev = _last; + _last->next = elm; + _last = elm; + } - elm->topicName = topicName; - elm->flag |= topicType; + elm->topicName = topicName; + elm->flag |= topicType; - if (qos == 0) - { - elm->flag |= MQTTSN_FLAG_QOS_0; - } - else if (qos == 1) - { - elm->flag |= MQTTSN_FLAG_QOS_1; - } - else if (qos == 2) - { - elm->flag |= MQTTSN_FLAG_QOS_2; - } - else if (qos == 3) + if (qos == 0) + { + elm->flag |= MQTTSN_FLAG_QOS_0; + } + else if (qos == 1) + { + elm->flag |= MQTTSN_FLAG_QOS_1; + } + else if (qos == 2) + { + elm->flag |= MQTTSN_FLAG_QOS_2; + } + else if (qos == 3) { elm->flag |= MQTTSN_FLAG_QOS_M1; } - if (retain) - { - elm->flag |= MQTTSN_FLAG_RETAIN; - } + if (retain) + { + elm->flag |= MQTTSN_FLAG_RETAIN; + } - if (topicId) - { - elm->status = TOPICID_IS_READY; - elm->topicId = topicId; - } - else - { - uint16_t id = theClient->getTopicId(topicName); + if (topicId) + { + elm->status = TOPICID_IS_READY; + elm->topicId = topicId; + } + else + { + uint16_t id = theClient->getTopicId(topicName); if ( id ) { elm->status = TOPICID_IS_READY; elm->topicId = id; } - } + } - elm->payloadlen = len; - elm->msgId = msgId; - elm->retryCount = MQTTSN_RETRY_COUNT; - elm->sendUTC = 0; + elm->payloadlen = len; + elm->msgId = msgId; + elm->retryCount = MQTTSN_RETRY_COUNT; + elm->sendUTC = 0; - if (_publishedFlg == NEG_TASK_INDEX) - { - elm->taskIndex = -1; - } - else - { - elm->taskIndex = theClient->getTaskManager()->getIndex(); - theClient->getTaskManager()->suspend(elm->taskIndex); - } + if (_publishedFlg == NEG_TASK_INDEX) + { + elm->taskIndex = -1; + } + else + { + elm->taskIndex = theClient->getTaskManager()->getIndex(); + theClient->getTaskManager()->suspend(elm->taskIndex); + } - elm->payload = (uint8_t*) malloc(len); - if (elm->payload == 0) - { - delElement(elm); - return 0; - } - memcpy(elm->payload, payload, len); + elm->payload = (uint8_t*) malloc(len); + if (elm->payload == 0) + { + delElement(elm); + return 0; + } + memcpy(elm->payload, payload, len); - ++_elmCnt; - return elm; + ++_elmCnt; + return elm; } diff --git a/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp b/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp index d7ac795..aaf350e 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp @@ -25,7 +25,8 @@ using namespace MQTTSNGW; -#define RESPONSE_DURATION 900 // Secs +#define KEEPALIVE_DURATION 900 // Secs +#define RESPONSE_DURATION 10 // Secs /* * Class ClientProxyElement @@ -198,7 +199,7 @@ void ClientProxy::checkConnection(void) _responseTimer.start(RESPONSE_DURATION * 1000UL); MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; options.clientID.cstring = _client->getClientId(); - options.duration = RESPONSE_DURATION; + options.duration = KEEPALIVE_DURATION; MQTTSNPacket* packet = new MQTTSNPacket(); packet->setCONNECT(&options); @@ -221,7 +222,7 @@ void ClientProxy::checkConnection(void) void ClientProxy::resetPingTimer(void) { - _keepAliveTimer.start(RESPONSE_DURATION * 1000UL); + _keepAliveTimer.start(KEEPALIVE_DURATION * 1000UL); } void ClientProxy::send(MQTTSNPacket* packet) diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp index dac2040..dd763cf 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp @@ -89,7 +89,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) if( !topic && qos == 3 ) { - WRITELOG("%s Invali TopicId.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + WRITELOG("%s Invali TopicId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); return; } @@ -123,6 +123,12 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) Event* ev1 = new Event(); ev1->setBrokerSendEvent(client, publish); _gateway->getBrokerSendQue()->post(ev1); + + /* reset PINGREQ of ClientProxy */ + if ( qos == 3 ) + { + _gateway->getClientProxy()->resetPingTimer(); + } } void MQTTSNPublishHandler::handlePuback(Client* client, MQTTSNPacket* packet) diff --git a/MQTTSNGateway/src/MQTTSNGWVersion.h b/MQTTSNGateway/src/MQTTSNGWVersion.h index 04c55ce..2e458a2 100644 --- a/MQTTSNGateway/src/MQTTSNGWVersion.h +++ b/MQTTSNGateway/src/MQTTSNGWVersion.h @@ -17,6 +17,6 @@ #ifndef MQTTSNGWVERSION_H_IN_ #define MQTTSNGWVERSION_H_IN_ -#define PAHO_GATEWAY_VERSION "1.2.0" +#define PAHO_GATEWAY_VERSION "1.2.1" #endif /* MQTTSNGWVERSION_H_IN_ */ diff --git a/MQTTSNGateway/src/MQTTSNGateway.cpp b/MQTTSNGateway/src/MQTTSNGateway.cpp index ac47ff7..d9b0b8e 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.cpp +++ b/MQTTSNGateway/src/MQTTSNGateway.cpp @@ -329,7 +329,7 @@ void Gateway::run(void) } if ( _params.qosMinusClientListName ) { - WRITELOG(" QoS-1: %s\n", _params.qosMinusClientListName); + WRITELOG(" QoS-1File: %s\n", _params.qosMinusClientListName); } WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription()); WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); From e942ee451d19ffc18db189f1edf9bd07bb45293a Mon Sep 17 00:00:00 2001 From: tomoaki Date: Tue, 31 Jul 2018 06:57:13 +0900 Subject: [PATCH 03/10] BugFix of #126 and the content of the conf file matched with the sample program Signed-off-by: tomoaki --- .../GatewayTester/samples/ClientPub/mainPub.cpp | 6 +++--- .../samples/ClientPubQoS-1/mainPubQoS-1.cpp | 2 +- .../GatewayTester/samples/ClientSub/mainSub.cpp | 6 +++--- MQTTSNGateway/GatewayTester/samples/mainTest.cpp | 2 +- MQTTSNGateway/predefinedTopic.conf | 11 ++++++++++- MQTTSNGateway/qos-1clients.conf | 7 +++++-- MQTTSNGateway/src/MQTTSNGWClient.cpp | 3 +-- MQTTSNGateway/src/MQTTSNGWClient.h | 1 - MQTTSNGateway/src/MQTTSNGWClientProxy.cpp | 6 +++++- 9 files changed, 29 insertions(+), 15 deletions(-) diff --git a/MQTTSNGateway/GatewayTester/samples/ClientPub/mainPub.cpp b/MQTTSNGateway/GatewayTester/samples/ClientPub/mainPub.cpp index 816dba7..c9a571c 100644 --- a/MQTTSNGateway/GatewayTester/samples/ClientPub/mainPub.cpp +++ b/MQTTSNGateway/GatewayTester/samples/ClientPub/mainPub.cpp @@ -52,10 +52,10 @@ extern LScreen* theScreen; * UDP Configuration (theNetcon) *------------------------------------------------------*/ UDPCONF = { - "GatewayTestPubClient", // ClientId + "ClientPUB", // ClientId {225,1,1,1}, // Multicast group IP 1883, // Multicast group Port - 20001, // Local PortNo + 20010, // Local PortNo }; /*------------------------------------------------------ @@ -159,7 +159,7 @@ TASK_LIST = {// e.g. TASK( task, executing duration in second), *------------------------------------------------------*/ void setup(void) { - + SetForwarderMode(false); } diff --git a/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp b/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp index 8b72f53..34151ed 100644 --- a/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp +++ b/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp @@ -52,7 +52,7 @@ extern LScreen* theScreen; * UDP Configuration (theNetcon) *------------------------------------------------------*/ UDPCONF = { - "GatewayTestPubClient", // ClientId + "QoS-1_Client01", // ClientId {225,1,1,1}, // Multicast group IP 1883, // Multicast group Port 20001, // Local PortNo diff --git a/MQTTSNGateway/GatewayTester/samples/ClientSub/mainSub.cpp b/MQTTSNGateway/GatewayTester/samples/ClientSub/mainSub.cpp index 585c8ec..9bf8c1b 100644 --- a/MQTTSNGateway/GatewayTester/samples/ClientSub/mainSub.cpp +++ b/MQTTSNGateway/GatewayTester/samples/ClientSub/mainSub.cpp @@ -52,10 +52,10 @@ extern LScreen* theScreen; * UDP Configuration (theNetcon) *------------------------------------------------------*/ UDPCONF = { - "ty4twGatewaySubClient", // ClientId + "ClientSUB", // ClientId {225,1,1,1}, // Multicast group IP 1883, // Multicast group Port - 20002, // Local PortNo + 20011, // Local PortNo }; /*------------------------------------------------------ @@ -199,7 +199,7 @@ TASK_LIST = {// e.g. TASK( task, executing duration in second), *------------------------------------------------------*/ void setup(void) { - + SetForwarderMode(false); } diff --git a/MQTTSNGateway/GatewayTester/samples/mainTest.cpp b/MQTTSNGateway/GatewayTester/samples/mainTest.cpp index 6075ced..06aa565 100644 --- a/MQTTSNGateway/GatewayTester/samples/mainTest.cpp +++ b/MQTTSNGateway/GatewayTester/samples/mainTest.cpp @@ -55,7 +55,7 @@ UDPCONF = { "GatewayTestClient", // ClientId {225,1,1,1}, // Multicast group IP 1883, // Multicast group Port - 20001, // Local PortNo + 20020, // Local PortNo }; /*------------------------------------------------------ diff --git a/MQTTSNGateway/predefinedTopic.conf b/MQTTSNGateway/predefinedTopic.conf index 2ad779a..eec33f4 100644 --- a/MQTTSNGateway/predefinedTopic.conf +++ b/MQTTSNGateway/predefinedTopic.conf @@ -35,4 +35,13 @@ ClientProxy, ty4tw/proxy/predefTopic3, 3 GatewayTestClient,ty4tw/predefinedTopic1, 1 GatewayTestClient,ty4tw/predefinedTopic2, 2 -GatewayTestClient,ty4tw/predefinedTopic3, 3 \ No newline at end of file +GatewayTestClient,ty4tw/predefinedTopic3, 3 + +ClientPUB,ty4tw/predefinedTopic1, 1 +ClientPUB,ty4tw/predefinedTopic2, 2 +ClientPUB,ty4tw/predefinedTopic3, 3 + +ClientSUB,ty4tw/predefinedTopic1, 1 +ClientSUB,ty4tw/predefinedTopic2, 2 +ClientSUB,ty4tw/predefinedTopic3, 3 + diff --git a/MQTTSNGateway/qos-1clients.conf b/MQTTSNGateway/qos-1clients.conf index e21832a..58ed914 100644 --- a/MQTTSNGateway/qos-1clients.conf +++ b/MQTTSNGateway/qos-1clients.conf @@ -23,5 +23,8 @@ # # -QoS-1_Client,172.16.1.7:12002 - +QoS-1_Client01,172.16.1.11:20001 +QoS-1_Clien02t,172.16.1.11:20002 +QoS-1_Client03,172.16.1.11:20003 +QoS-1_Client04,172.16.1.11:20004 +QoS-1_Client05,172.16.1.11:20005 diff --git a/MQTTSNGateway/src/MQTTSNGWClient.cpp b/MQTTSNGateway/src/MQTTSNGWClient.cpp index 124ad58..deda727 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClient.cpp @@ -402,7 +402,6 @@ Client::Client(bool secure) _connAck = 0; _waitWillMsgFlg = false; _sessionStatus = false; - _otaClient = 0; _prevClient = 0; _nextClient = 0; _clientSleepPacketQue.setMaxSize(MAX_SAVED_PUBLISH); @@ -570,7 +569,7 @@ void Client::setSessionStatus(bool status) bool Client::erasable(void) { - return _sessionStatus || !_hasPredefTopic; + return _sessionStatus && !_hasPredefTopic && _forwarder == 0; } void Client::updateStatus(MQTTSNPacket* packet) diff --git a/MQTTSNGateway/src/MQTTSNGWClient.h b/MQTTSNGateway/src/MQTTSNGWClient.h index ff67365..c4757e7 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.h +++ b/MQTTSNGateway/src/MQTTSNGWClient.h @@ -363,7 +363,6 @@ private: Client* _nextClient; Client* _prevClient; - Client* _otaClient; }; /*===================================== diff --git a/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp b/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp index aaf350e..cf430f0 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp @@ -227,7 +227,7 @@ void ClientProxy::resetPingTimer(void) void ClientProxy::send(MQTTSNPacket* packet) { - if ( packet->getType() == MQTTSN_CONNACK || packet->getType() == MQTTSN_PINGRESP ) + if ( packet->getType() == MQTTSN_CONNACK ) { resetPingTimer(); sendStoredPublish(); @@ -236,6 +236,10 @@ void ClientProxy::send(MQTTSNPacket* packet) { resetPingTimer(); } + else if ( packet->getType() == MQTTSN_DISCONNECT ) + { + // blank + } } void ClientProxy::sendStoredPublish(void) From df080f28510e948ec09735393a6f23834cedf065 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Tue, 31 Jul 2018 15:49:25 +0900 Subject: [PATCH 04/10] Set whether to run ClientProxy at startup. If it does not start, do not create an instance of ClientProxy. Change the name of ClientProxy to QoSm1Proxy Signed-off-by: tomoaki --- MQTTSNGateway/Makefile | 2 +- MQTTSNGateway/README.md | 2 +- MQTTSNGateway/gateway.conf | 9 ++-- MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp | 43 ++++++++--------- MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp | 2 +- .../src/MQTTSNGWPacketHandleTask.cpp | 8 +++- MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp | 2 +- ...ClientProxy.cpp => MQTTSNGWQoS-1Proxy.cpp} | 45 ++++++++--------- ...SNGWClientProxy.h => MQTTSNGWQoS-1Proxy.h} | 30 ++++++------ MQTTSNGateway/src/MQTTSNGateway.cpp | 48 +++++++++++++------ MQTTSNGateway/src/MQTTSNGateway.h | 9 ++-- 11 files changed, 112 insertions(+), 88 deletions(-) rename MQTTSNGateway/src/{MQTTSNGWClientProxy.cpp => MQTTSNGWQoS-1Proxy.cpp} (82%) rename MQTTSNGateway/src/{MQTTSNGWClientProxy.h => MQTTSNGWQoS-1Proxy.h} (72%) diff --git a/MQTTSNGateway/Makefile b/MQTTSNGateway/Makefile index f9a2c6f..0eca7fd 100644 --- a/MQTTSNGateway/Makefile +++ b/MQTTSNGateway/Makefile @@ -40,7 +40,7 @@ $(SRCDIR)/MQTTSNGWPublishHandler.cpp \ $(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \ $(SRCDIR)/MQTTSNGWEncapsulatedPacket.cpp \ $(SRCDIR)/MQTTSNGWForwarder.cpp \ -$(SRCDIR)/MQTTSNGWClientProxy.cpp \ +$(SRCDIR)/MQTTSNGWQoS-1Proxy.cpp \ $(SRCDIR)/$(OS)/$(SENSORNET)/SensorNetwork.cpp \ $(SRCDIR)/$(OS)/Timer.cpp \ $(SRCDIR)/$(OS)/Network.cpp \ diff --git a/MQTTSNGateway/README.md b/MQTTSNGateway/README.md index 2144ec5..9444a3a 100644 --- a/MQTTSNGateway/README.md +++ b/MQTTSNGateway/README.md @@ -72,7 +72,7 @@ Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW messag when **ClientAuthentication** is YES, see MQTTSNGWClient.cpp line53, clients file specified by ClientsList is required. This file defines connect allowed clients by ClientId and SensorNetwork Address. e.g. IP address and Port No. When **PredefinedTopic** is YES, Pre-definedTopicID file specified by PredefinedTopicList is effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format. When **Forwarder** is YES, Forwarder Encapsulation Message is available. Connectable Forwarders are specifed by ForwardersList file. In this file, ForwarderIds and those sensorNet addresses are declared in CSV format. -When **QoS-1** is YES, QoS-1 PUBLISH Message is available. Clients which allow to send it, are specifed by QoS-1ClientsList file. In this file, ClientsId and those sensorNet addresses are declared in CSV format. +When **QoS-1** is YES, QoS-1 PUBLISH Message is available. Clients which allow to send it, are specifed by QoS-1ClientsList file. In this file, ClientsId and those sensorNet addresses are declared in CSV format. QoS-1ProxyName is a ClientId of the proxy. diff --git a/MQTTSNGateway/gateway.conf b/MQTTSNGateway/gateway.conf index a888771..d3f5fe6 100644 --- a/MQTTSNGateway/gateway.conf +++ b/MQTTSNGateway/gateway.conf @@ -18,16 +18,17 @@ BrokerPortNo=1883 BrokerSecurePortNo=8883 ClientAuthentication=NO -ClientsList=/path/to/your_clients.conf +#ClientsList=/path/to/your_clients.conf PredefinedTopic=NO -PredefinedTopicList=/path/to/your_predefinedTopic.conf +#PredefinedTopicList=/path/to/your_predefinedTopic.conf Forwarder=NO -ForwardersList=/path/to/your_forwarers.conf +#ForwardersList=/path/to/your_forwarers.conf QoS-1=NO -QoS-1ClientsList=/path/to/your_qos-1clients.conf +OoS-1ProxyName=Proxy007 +#QoS-1ClientsList=/path/to/your_qos-1clients.conf #RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCApath=/etc/ssl/certs/ diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp index c17eaf9..a996051 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp @@ -128,21 +128,28 @@ void ClientRecvTask::run() } else { - const char* clientName = _gateway->getClientProxy()->getClientId(_sensorNetwork->getSenderAddress()); + /* when QoSm1Proxy is available, select QoS-1 PUBLISH message */ + QoSm1Proxy* pxy = _gateway->getQoSm1Proxy(); + if ( pxy ) + { + /* get ClientId not Client which can send QoS-1 PUBLISH */ + const char* clientName = pxy->getClientId(_sensorNetwork->getSenderAddress()); - if ( clientName ) // This client is for QoS-1 PUBLISH. - { - if ( packet->isQoSMinusPUBLISH() ) + if ( clientName ) { - client = _gateway->getClientProxy()->getClient(); // point to the ClientProxy - } - else - { - client = _gateway->getClientProxy()->getClient(); - log(clientName, packet); - WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); - delete packet; - continue; + if ( packet->isQoSMinusPUBLISH() ) + { + /* QoS1Proxy takes responsibility of the client */ + client = _gateway->getQoSm1Proxy()->getClient(); + } + else + { + client = _gateway->getQoSm1Proxy()->getClient(); + log(clientName, packet); + WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); + delete packet; + continue; + } } } else @@ -221,16 +228,6 @@ void ClientRecvTask::run() log(client, packet, 0); WRITELOG("%s Client(%s) is not connecting. message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); delete packet; - - /* Send DISCONNECT */ - if ( fwd == 0 ) - { - packet = new MQTTSNPacket(); - packet->setDISCONNECT(0); - ev = new Event(); - ev->setClientSendEvent(_sensorNetwork->getSenderAddress(), packet); - _gateway->getClientSendQue()->post(ev); - } } } } diff --git a/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp index 76fe572..54107a5 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp @@ -73,7 +73,7 @@ void ClientSendTask::run() log(client, packet); if ( client->isProxy() ) { - _gateway->getClientProxy()->send(packet); + _gateway->getQoSm1Proxy()->send(packet); continue; } rc = packet->unicast(_sensorNetwork, client->getSensorNetAddress()); diff --git a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp index e1c5e09..53ad17a 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp @@ -114,8 +114,12 @@ void PacketHandleTask::run() _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); } - /*------ Check ClientProxy to Connect or send PINGREQ ------*/ - _gateway->getClientProxy()->checkConnection(); + /*------ Check QoS-1 Proxy Connect or PINGREQ ------*/ + QoSm1Proxy* pxy = _gateway->getQoSm1Proxy(); + if ( pxy ) + { + pxy->checkConnection(); + } } /*------ Handle SEARCHGW Message ---------*/ diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp index dd763cf..aedb5df 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp @@ -127,7 +127,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) /* reset PINGREQ of ClientProxy */ if ( qos == 3 ) { - _gateway->getClientProxy()->resetPingTimer(); + _gateway->getQoSm1Proxy()->resetPingTimer(); } } diff --git a/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp similarity index 82% rename from MQTTSNGateway/src/MQTTSNGWClientProxy.cpp rename to MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp index cf430f0..5858655 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientProxy.cpp +++ b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp @@ -15,8 +15,9 @@ **************************************************************************************/ +#include "MQTTSNGWQoS-1Proxy.h" + #include "MQTTSNGWDefines.h" -#include "MQTTSNGWClientProxy.h" #include "MQTTSNGateway.h" #include "SensorNetwork.h" #include @@ -32,21 +33,21 @@ using namespace MQTTSNGW; * Class ClientProxyElement */ -ClientProxyElement::ClientProxyElement(void) +QoSm1ProxyElement::QoSm1ProxyElement(void) : _clientId{0} , _next{0} { } -ClientProxyElement::ClientProxyElement(SensorNetAddress* addr, string* clientId) +QoSm1ProxyElement::QoSm1ProxyElement(SensorNetAddress* addr, string* clientId) : _next{0} { _clientId = *clientId; _sensorNetAddr = *addr; } -ClientProxyElement::~ClientProxyElement(void) +QoSm1ProxyElement::~QoSm1ProxyElement(void) { } @@ -55,14 +56,14 @@ ClientProxyElement::~ClientProxyElement(void) * Class ClientProxy */ -ClientProxy:: ClientProxy(void) +QoSm1Proxy:: QoSm1Proxy(void) : _head{0} { _gateway = 0; _client = 0; } -ClientProxy:: ClientProxy(Gateway* gw) +QoSm1Proxy:: QoSm1Proxy(Gateway* gw) : _head{0} { _gateway = gw; @@ -70,35 +71,35 @@ ClientProxy:: ClientProxy(Gateway* gw) } -ClientProxy::~ClientProxy(void) +QoSm1Proxy::~QoSm1Proxy(void) { if ( _head ) { - ClientProxyElement* p = _head; + QoSm1ProxyElement* p = _head; while ( p ) { - ClientProxyElement* next = p->_next; + QoSm1ProxyElement* next = p->_next; delete p; p = next; } } } -void ClientProxy::setGateway(Gateway* gw) +void QoSm1Proxy::setGateway(Gateway* gw) { _gateway = gw; } -ClientProxyElement* ClientProxy::add(SensorNetAddress* addr, string* clientId) +QoSm1ProxyElement* QoSm1Proxy::add(SensorNetAddress* addr, string* clientId) { - ClientProxyElement* elm = new ClientProxyElement(addr, clientId); + QoSm1ProxyElement* elm = new QoSm1ProxyElement(addr, clientId); if ( _head == 0 ) { _head = elm; } else { - ClientProxyElement* p = _head; + QoSm1ProxyElement* p = _head; while ( p ) { if ( p->_next == 0 ) @@ -115,9 +116,9 @@ ClientProxyElement* ClientProxy::add(SensorNetAddress* addr, string* clientId) return elm; } -const char* ClientProxy::getClientId(SensorNetAddress* addr) +const char* QoSm1Proxy::getClientId(SensorNetAddress* addr) { - ClientProxyElement* p = _head; + QoSm1ProxyElement* p = _head; while ( p ) { if ( p->_sensorNetAddr.isMatch(addr) ) @@ -130,17 +131,17 @@ const char* ClientProxy::getClientId(SensorNetAddress* addr) return 0; } -void ClientProxy::setClient(Client* client) +void QoSm1Proxy::setClient(Client* client) { _client = client; } -Client* ClientProxy::getClient(void) +Client* QoSm1Proxy::getClient(void) { return _client; } -bool ClientProxy::setClientProxy(const char* fileName) +bool QoSm1Proxy::setClientProxy(const char* fileName) { FILE* fp; char buf[MAX_CLIENTID_LENGTH + 256]; @@ -191,7 +192,7 @@ bool ClientProxy::setClientProxy(const char* fileName) } -void ClientProxy::checkConnection(void) +void QoSm1Proxy::checkConnection(void) { if ( _client->isDisconnect() || ( _client->isConnecting() && _responseTimer.isTimeup()) ) { @@ -220,12 +221,12 @@ void ClientProxy::checkConnection(void) } } -void ClientProxy::resetPingTimer(void) +void QoSm1Proxy::resetPingTimer(void) { _keepAliveTimer.start(KEEPALIVE_DURATION * 1000UL); } -void ClientProxy::send(MQTTSNPacket* packet) +void QoSm1Proxy::send(MQTTSNPacket* packet) { if ( packet->getType() == MQTTSN_CONNACK ) { @@ -242,7 +243,7 @@ void ClientProxy::send(MQTTSNPacket* packet) } } -void ClientProxy::sendStoredPublish(void) +void QoSm1Proxy::sendStoredPublish(void) { MQTTSNPacket* msg = 0; diff --git a/MQTTSNGateway/src/MQTTSNGWClientProxy.h b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h similarity index 72% rename from MQTTSNGateway/src/MQTTSNGWClientProxy.h rename to MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h index 43e0acc..c5db5e4 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientProxy.h +++ b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h @@ -14,8 +14,8 @@ * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ -#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTPROXY_H_ -#define MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTPROXY_H_ +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_ #include "MQTTSNGateway.h" #include "MQTTGWPacket.h" @@ -29,27 +29,27 @@ namespace MQTTSNGW { class Gateway; -class ClientProxyElement +class QoSm1ProxyElement { - friend class ClientProxy; + friend class QoSm1Proxy; public: - ClientProxyElement(void); - ClientProxyElement(SensorNetAddress* addr, string* clientId); - ~ClientProxyElement(void); + QoSm1ProxyElement(void); + QoSm1ProxyElement(SensorNetAddress* addr, string* clientId); + ~QoSm1ProxyElement(void); private: SensorNetAddress _sensorNetAddr; string _clientId; - ClientProxyElement* _next; + QoSm1ProxyElement* _next; }; -class ClientProxy +class QoSm1Proxy { public: - ClientProxy(void); - ClientProxy(Gateway* gw); - ~ClientProxy(void); + QoSm1Proxy(void); + QoSm1Proxy(Gateway* gw); + ~QoSm1Proxy(void); bool setClientProxy(const char* fileName); - ClientProxyElement* add(SensorNetAddress* addr, string* clientId); + QoSm1ProxyElement* add(SensorNetAddress* addr, string* clientId); const char* getClientId(SensorNetAddress* addr); void setClient(Client*); Client* getClient(void); @@ -65,7 +65,7 @@ private: Gateway* _gateway; Client* _client; - ClientProxyElement* _head; + QoSm1ProxyElement* _head; Timer _keepAliveTimer; Timer _responseTimer; }; @@ -74,4 +74,4 @@ private: -#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTPROXY_H_ */ +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGateway.cpp b/MQTTSNGateway/src/MQTTSNGateway.cpp index d9b0b8e..069ac5a 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.cpp +++ b/MQTTSNGateway/src/MQTTSNGateway.cpp @@ -30,7 +30,7 @@ Gateway::Gateway() { theMultiTaskProcess = this; theProcess = this; - _clientProxy = new ClientProxy(this); + _qosm1Proxy = 0; _params.loginId = 0; _params.password = 0; _params.keepAlive = 0; @@ -50,6 +50,7 @@ Gateway::Gateway() _params.predefinedTopicFileName = 0; _params.forwarderListName = 0; _params.qosMinusClientListName = 0; + _params.qosm1proxyName = 0; _packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS); } @@ -115,9 +116,14 @@ Gateway::~Gateway() { free(_params.qosMinusClientListName); } - if ( _clientProxy ) + if ( _params.qosm1proxyName ) { - delete _clientProxy; + free(_params.qosm1proxyName); + } + + if ( _qosm1Proxy ) + { + delete _qosm1Proxy; } } @@ -230,18 +236,32 @@ void Gateway::initialize(int argc, char** argv) } } - /* Set ClientProxy's Client */ - MQTTSNString id = MQTTSNString_initializer; - id.cstring = const_cast(CLIENTPROXY); - Client* client = _clientList.createClient(0, &id, true, secure); - _clientProxy->setClient(client); - client->setPorxy(true); - _clientProxy->setGateway(this); + /* Set QoSm1Proxy's Client */ - if (getParam("QoS-1", param) == 0 ) + if (getParam("QoS-1", param) == 0 ) { if (!strcasecmp(param, "YES") ) { + /* Set QoSm1Proxy's Client */ + + _qosm1Proxy = new QoSm1Proxy(this); + MQTTSNString id = MQTTSNString_initializer; + + if (getParam("QoS-1ProxyName", param) == 0 ) + { + string name = string(param); + id.cstring = const_cast(name.c_str()); + } + else + { + id.cstring = const_cast(CLIENTPROXY); + } + Client* client = _clientList.createClient(0, &id, true, secure); + _qosm1Proxy->setClient(client); + client->setPorxy(true); + _qosm1Proxy->setGateway(this); + + if (getParam("QoS-1ClientsList", param) == 0) { fileName = string(param); @@ -250,7 +270,7 @@ void Gateway::initialize(int argc, char** argv) { fileName = *getConfigDirName() + string(QOS_1CLIENT_LIST); } - if ( !_clientProxy->setClientProxy(fileName.c_str()) ) + if ( !_qosm1Proxy->setClientProxy(fileName.c_str()) ) { throw Exception("Gateway::initialize: No QoS-1ClientsList file defined by the configuration.."); } @@ -399,9 +419,9 @@ GatewayParams* Gateway::getGWParams(void) return &_params; } -ClientProxy* Gateway::getClientProxy(void) +QoSm1Proxy* Gateway::getQoSm1Proxy(void) { - return _clientProxy; + return _qosm1Proxy; } /*===================================== diff --git a/MQTTSNGateway/src/MQTTSNGateway.h b/MQTTSNGateway/src/MQTTSNGateway.h index dbe6ae4..b547e0a 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.h +++ b/MQTTSNGateway/src/MQTTSNGateway.h @@ -21,7 +21,7 @@ #include "MQTTSNPacket.h" #include "MQTTSNGWForwarder.h" -#include "MQTTSNGWClientProxy.h" +#include "MQTTSNGWQoS-1Proxy.h" namespace MQTTSNGW { @@ -159,13 +159,14 @@ typedef struct char* privateKey; char* predefinedTopicFileName; char* forwarderListName; + char* qosm1proxyName; char* qosMinusClientListName; }GatewayParams; /*===================================== Class Gateway =====================================*/ -class ClientProxy; +class QoSm1Proxy; class Gateway: public MultiTaskProcess{ public: @@ -182,11 +183,11 @@ public: SensorNetwork* getSensorNetwork(void); LightIndicator* getLightIndicator(void); GatewayParams* getGWParams(void); - ClientProxy* getClientProxy(void); + QoSm1Proxy* getQoSm1Proxy(void); private: ClientList _clientList; - ClientProxy* _clientProxy; + QoSm1Proxy* _qosm1Proxy; ForwarderList _forwarderList; EventQue _packetEventQue; EventQue _brokerSendQue; From 862e5015127c19bf0d28af4747f2b82b6ca438a8 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Tue, 31 Jul 2018 17:41:28 +0900 Subject: [PATCH 05/10] BugFix add retry PINGREQ and re CONNECT #126 Signed-off-by: tomoaki --- MQTTSNGateway/README.md | 9 +++--- MQTTSNGateway/gateway.conf | 1 + MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp | 5 ++- MQTTSNGateway/src/MQTTSNGWDefines.h | 3 ++ MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp | 33 +++++++++++++++----- MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h | 2 ++ 6 files changed, 40 insertions(+), 13 deletions(-) diff --git a/MQTTSNGateway/README.md b/MQTTSNGateway/README.md index 9444a3a..3bae83e 100644 --- a/MQTTSNGateway/README.md +++ b/MQTTSNGateway/README.md @@ -31,16 +31,17 @@ BrokerPortNo=1883 BrokerSecurePortNo=8883 ClientAuthentication=NO -ClientsList=/path/to/your_clients.conf +#ClientsList=/path/to/your_clients.conf PredefinedTopic=NO -PredefinedTopicList=/path/to/your_predefinedTopic.conf +#PredefinedTopicList=/path/to/your_predefinedTopic.conf Forwarder=NO -ForwardersList=/home/tomoaki/tmp/forwarders.conf +#ForwardersList=/home/tomoaki/tmp/forwarders.conf QoS-1=NO -QoS-1ClientsList=/path/to/your_qos-1clients.conf +QoS-1ProxyName=Proxy007 +#QoS-1ClientsList=/path/to/your_qos-1clients.conf #RootCAfile=/path/to/your_Root_CA.crt #RootCApath=/path/to/your_certs_directory/ diff --git a/MQTTSNGateway/gateway.conf b/MQTTSNGateway/gateway.conf index d3f5fe6..277f7ae 100644 --- a/MQTTSNGateway/gateway.conf +++ b/MQTTSNGateway/gateway.conf @@ -41,6 +41,7 @@ KeepAlive=900 #LoginID=your_ID #Password=your_Password + # UDP GatewayPortNo=10000 MulticastIP=225.1.1.1 diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp index a996051..d5397b4 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp @@ -128,6 +128,8 @@ void ClientRecvTask::run() } else { + client = 0; + /* when QoSm1Proxy is available, select QoS-1 PUBLISH message */ QoSm1Proxy* pxy = _gateway->getQoSm1Proxy(); if ( pxy ) @@ -152,7 +154,8 @@ void ClientRecvTask::run() } } } - else + + if ( client == 0 ) { /* get client from the ClientList of Gateway by sensorNetAddress. */ client = _gateway->getClientList()->getClient(_sensorNetwork->getSenderAddress()); diff --git a/MQTTSNGateway/src/MQTTSNGWDefines.h b/MQTTSNGateway/src/MQTTSNGWDefines.h index 7da2109..c15ae45 100644 --- a/MQTTSNGateway/src/MQTTSNGWDefines.h +++ b/MQTTSNGateway/src/MQTTSNGWDefines.h @@ -46,6 +46,9 @@ namespace MQTTSNGW #define MQTTSNGW_MAX_PACKET_SIZE (1024) // Max Packet size (5+2+TopicLen+PayloadLen + Foward Encapsulation) #define SIZE_OF_LOG_PACKET (500) // Length of the packet log in bytes +#define QOSM1_PROXY_KEEPALIVE_DURATION 900 // Secs +#define QOSM1_PROXY_RESPONSE_DURATION 10 // Secs +#define QOSM1_PROXY_MAX_RETRY_CNT 3 /*================================= * Data Type ==================================*/ diff --git a/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp index 5858655..67e98ce 100644 --- a/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp +++ b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp @@ -24,10 +24,11 @@ #include #include -using namespace MQTTSNGW; +#define QOSM1_PROXY_KEEPALIVE_DURATION 900 // Secs +#define QOSM1_PROXY_RESPONSE_DURATION 10 // Secs +#define QOSM1_PROXY_MAX_RETRY_CNT 3 -#define KEEPALIVE_DURATION 900 // Secs -#define RESPONSE_DURATION 10 // Secs +using namespace MQTTSNGW; /* * Class ClientProxyElement @@ -58,6 +59,8 @@ QoSm1ProxyElement::~QoSm1ProxyElement(void) QoSm1Proxy:: QoSm1Proxy(void) : _head{0} + , _isWaitingResp{false} + , _retryCnt{0} { _gateway = 0; _client = 0; @@ -65,6 +68,8 @@ QoSm1Proxy:: QoSm1Proxy(void) QoSm1Proxy:: QoSm1Proxy(Gateway* gw) : _head{0} +, _isWaitingResp{false} +, _retryCnt{0} { _gateway = gw; _client = 0; @@ -197,19 +202,18 @@ void QoSm1Proxy::checkConnection(void) if ( _client->isDisconnect() || ( _client->isConnecting() && _responseTimer.isTimeup()) ) { _client->connectSended(); - _responseTimer.start(RESPONSE_DURATION * 1000UL); + _responseTimer.start(QOSM1_PROXY_RESPONSE_DURATION * 1000UL); MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; options.clientID.cstring = _client->getClientId(); - options.duration = KEEPALIVE_DURATION; + options.duration = QOSM1_PROXY_KEEPALIVE_DURATION; MQTTSNPacket* packet = new MQTTSNPacket(); packet->setCONNECT(&options); Event* ev = new Event(); ev->setClientRecvEvent(_client, packet); _gateway->getPacketEventQue()->post(ev); - } - else if ( _client->isActive() && _keepAliveTimer.isTimeup() ) + else if ( (_client->isActive() && _keepAliveTimer.isTimeup() ) || (_isWaitingResp && _responseTimer.isTimeup() ) ) { MQTTSNPacket* packet = new MQTTSNPacket(); MQTTSNString clientId = MQTTSNString_initializer; @@ -217,13 +221,20 @@ void QoSm1Proxy::checkConnection(void) Event* ev = new Event(); ev->setClientRecvEvent(_client, packet); _gateway->getPacketEventQue()->post(ev); + _responseTimer.start(QOSM1_PROXY_RESPONSE_DURATION * 1000UL); + _isWaitingResp = true; + + if ( ++_retryCnt > QOSM1_PROXY_MAX_RETRY_CNT ) + { + _client->disconnected(); + } resetPingTimer(); } } void QoSm1Proxy::resetPingTimer(void) { - _keepAliveTimer.start(KEEPALIVE_DURATION * 1000UL); + _keepAliveTimer.start(QOSM1_PROXY_KEEPALIVE_DURATION * 1000UL); } void QoSm1Proxy::send(MQTTSNPacket* packet) @@ -231,10 +242,16 @@ void QoSm1Proxy::send(MQTTSNPacket* packet) if ( packet->getType() == MQTTSN_CONNACK ) { resetPingTimer(); + _responseTimer.stop(); + _retryCnt = 0; sendStoredPublish(); } else if ( packet->getType() == MQTTSN_PINGRESP ) { + _responseTimer.stop(); + _isWaitingResp = false; + _retryCnt = 0; + resetPingTimer(); } else if ( packet->getType() == MQTTSN_DISCONNECT ) diff --git a/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h index c5db5e4..9960668 100644 --- a/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h +++ b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h @@ -68,6 +68,8 @@ private: QoSm1ProxyElement* _head; Timer _keepAliveTimer; Timer _responseTimer; + bool _isWaitingResp; + int _retryCnt; }; } From f7fc5c49f5b7522394e945c27b7e7478a0cf25e7 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Sat, 4 Aug 2018 17:46:42 +0900 Subject: [PATCH 06/10] Update: Add Aggregate Gateway functions. #127 Signed-off-by: tomoaki --- .cproject | 4 +- .settings/language.settings.xml | 25 + .travis.yml | 2 - MQTTSNGateway/Makefile | 12 +- MQTTSNGateway/README.md | 73 +- MQTTSNGateway/clients.conf | 27 +- MQTTSNGateway/gateway.conf | 17 +- MQTTSNGateway/predefinedTopic.conf | 33 +- MQTTSNGateway/qos-1clients.conf | 30 - MQTTSNGateway/src/MQTTGWPacket.cpp | 86 +- MQTTSNGateway/src/MQTTGWPacket.h | 19 + MQTTSNGateway/src/MQTTGWPublishHandler.cpp | 90 +- MQTTSNGateway/src/MQTTGWPublishHandler.h | 5 + MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp | 27 +- MQTTSNGateway/src/MQTTGWSubscribeHandler.h | 2 + .../src/MQTTSNAggregateConnectionHandler.cpp | 202 ++++ .../src/MQTTSNAggregateConnectionHandler.h | 48 + MQTTSNGateway/src/MQTTSNGWAdapter.cpp | 321 ++++++ MQTTSNGateway/src/MQTTSNGWAdapter.h | 99 ++ MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp | 253 +++++ MQTTSNGateway/src/MQTTSNGWAdapterManager.h | 70 ++ .../src/MQTTSNGWAggregateTopicTable.cpp | 161 +++ .../src/MQTTSNGWAggregateTopicTable.h | 98 ++ MQTTSNGateway/src/MQTTSNGWAggregater.cpp | 143 +++ MQTTSNGateway/src/MQTTSNGWAggregater.h | 76 ++ MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp | 13 +- MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp | 21 +- MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h | 3 + MQTTSNGateway/src/MQTTSNGWClient.cpp | 944 ++---------------- MQTTSNGateway/src/MQTTSNGWClient.h | 136 +-- MQTTSNGateway/src/MQTTSNGWClientList.cpp | 460 +++++++++ MQTTSNGateway/src/MQTTSNGWClientList.h | 70 ++ MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp | 94 +- MQTTSNGateway/src/MQTTSNGWClientRecvTask.h | 7 +- MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp | 35 +- MQTTSNGateway/src/MQTTSNGWClientSendTask.h | 9 +- .../src/MQTTSNGWConnectionHandler.cpp | 8 +- MQTTSNGateway/src/MQTTSNGWDefines.h | 2 +- .../src/MQTTSNGWEncapsulatedPacket.cpp | 4 +- MQTTSNGateway/src/MQTTSNGWForwarder.cpp | 67 +- MQTTSNGateway/src/MQTTSNGWForwarder.h | 22 +- MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp | 218 ++++ MQTTSNGateway/src/MQTTSNGWMessageIdTable.h | 78 ++ MQTTSNGateway/src/MQTTSNGWPacket.cpp | 132 ++- MQTTSNGateway/src/MQTTSNGWPacket.h | 9 +- .../src/MQTTSNGWPacketHandleTask.cpp | 309 ++++-- MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h | 58 +- MQTTSNGateway/src/MQTTSNGWProcess.cpp | 8 +- MQTTSNGateway/src/MQTTSNGWProcess.h | 30 +- MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp | 105 +- MQTTSNGateway/src/MQTTSNGWPublishHandler.h | 6 +- MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp | 275 ----- MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h | 79 -- MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp | 75 ++ MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h | 53 + .../src/MQTTSNGWSubscribeHandler.cpp | 121 ++- MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h | 6 +- MQTTSNGateway/src/MQTTSNGWTopic.cpp | 519 ++++++++++ MQTTSNGateway/src/MQTTSNGWTopic.h | 115 +++ MQTTSNGateway/src/MQTTSNGWVersion.h | 2 +- MQTTSNGateway/src/MQTTSNGateway.cpp | 206 ++-- MQTTSNGateway/src/MQTTSNGateway.h | 93 +- MQTTSNGateway/src/linux/Threading.cpp | 14 + MQTTSNGateway/src/mainGateway.cpp | 19 +- MQTTSNGateway/src/tests/TestTopicIdMap.cpp | 2 +- 65 files changed, 4368 insertions(+), 1982 deletions(-) create mode 100644 .settings/language.settings.xml delete mode 100644 MQTTSNGateway/qos-1clients.conf create mode 100644 MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.cpp create mode 100644 MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.h create mode 100644 MQTTSNGateway/src/MQTTSNGWAdapter.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWAdapter.h create mode 100644 MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWAdapterManager.h create mode 100644 MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.h create mode 100644 MQTTSNGateway/src/MQTTSNGWAggregater.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWAggregater.h create mode 100644 MQTTSNGateway/src/MQTTSNGWClientList.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWClientList.h create mode 100644 MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWMessageIdTable.h delete mode 100644 MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp delete mode 100644 MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h create mode 100644 MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h create mode 100644 MQTTSNGateway/src/MQTTSNGWTopic.cpp create mode 100644 MQTTSNGateway/src/MQTTSNGWTopic.h diff --git a/.cproject b/.cproject index fae7107..f52491d 100644 --- a/.cproject +++ b/.cproject @@ -66,7 +66,7 @@ - + @@ -137,7 +137,7 @@ - + diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml new file mode 100644 index 0000000..f557f24 --- /dev/null +++ b/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.travis.yml b/.travis.yml index 04f67cf..ed564b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: cpp compiler: - g++ - - clang install: - if ["$CXX" = "g++" ]; then export CXX="g++-4.8"; fi @@ -14,7 +13,6 @@ addons: - g++-4.8 - cmake - cmake-data - - clang script: - ./travis-build.sh diff --git a/MQTTSNGateway/Makefile b/MQTTSNGateway/Makefile index 0eca7fd..fb4562b 100644 --- a/MQTTSNGateway/Makefile +++ b/MQTTSNGateway/Makefile @@ -11,7 +11,6 @@ CONFIG := gateway.conf CLIENTS := clients.conf PREDEFTOPIC := predefinedTopic.conf FORWARDERS := forwarders.conf -QOSM1CLIENT := qos-1clients.conf SRCDIR := src SUBDIR := ../MQTTSNPacket/src @@ -40,7 +39,15 @@ $(SRCDIR)/MQTTSNGWPublishHandler.cpp \ $(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \ $(SRCDIR)/MQTTSNGWEncapsulatedPacket.cpp \ $(SRCDIR)/MQTTSNGWForwarder.cpp \ -$(SRCDIR)/MQTTSNGWQoS-1Proxy.cpp \ +$(SRCDIR)/MQTTSNGWQoSm1Proxy.cpp \ +$(SRCDIR)/MQTTSNGWAdapter.cpp \ +$(SRCDIR)/MQTTSNGWAggregater.cpp \ +$(SRCDIR)/MQTTSNGWClientList.cpp \ +$(SRCDIR)/MQTTSNGWTopic.cpp \ +$(SRCDIR)/MQTTSNGWAdapterManager.cpp \ +$(SRCDIR)/MQTTSNAggregateConnectionHandler.cpp \ +$(SRCDIR)/MQTTSNGWMessageIdTable.cpp \ +$(SRCDIR)/MQTTSNGWAggregateTopicTable.cpp \ $(SRCDIR)/$(OS)/$(SENSORNET)/SensorNetwork.cpp \ $(SRCDIR)/$(OS)/Timer.cpp \ $(SRCDIR)/$(OS)/Network.cpp \ @@ -143,7 +150,6 @@ install: cp -pf $(CLIENTS) ../../ cp -pf $(PREDEFTOPIC) ../../ cp -pf $(FORWARDERS) ../../ - cp -pf $(QOSM1CLIENT) ../../ exectest: diff --git a/MQTTSNGateway/README.md b/MQTTSNGateway/README.md index 3bae83e..5d1627a 100644 --- a/MQTTSNGateway/README.md +++ b/MQTTSNGateway/README.md @@ -2,7 +2,7 @@ ### **step1. Build the gateway** ```` -$ git clone https://github.com/eclipse/paho.mqtt-sn.embedded-c +$ git clone -b experiment https://github.com/eclipse/paho.mqtt-sn.embedded-c $ cd paho.mqtt-sn.embedded-c/MQTTSNGateway $ make $ make install @@ -22,58 +22,69 @@ $ ./MQTT-SNGateway [-f Config file name] ### **How to Change the configuration of the gateway** **../gateway.conf** Contents are follows: -```` +
    
 
 # config file of MQTT-SN Gateway
+#
 
 BrokerName=iot.eclipse.org
 BrokerPortNo=1883
-BrokerSecurePortNo=8883    
+BrokerSecurePortNo=8883
 
+#
+# When AggregateGateway=YES or ClientAuthentication=YES,
+# All clients must be specified by the ClientList File  
+#
+
+AggregateGateway=NO
 ClientAuthentication=NO
-#ClientsList=/path/to/your_clients.conf    
 
-PredefinedTopic=NO
+#ClientsList=/path/to/your_clients.conf
+
+QoS-1=NO
+OoS-1ProxyName=Proxy007
+
 #PredefinedTopicList=/path/to/your_predefinedTopic.conf
 
 Forwarder=NO
-#ForwardersList=/home/tomoaki/tmp/forwarders.conf
+#ForwardersList=/path/to/your_forwarers.conf
+
+#RootCAfile=/etc/ssl/certs/ca-certificates.crt
+#RootCApath=/etc/ssl/certs/
+#CertsFile=/path/to/certKey.pem
+#PrivateKey=/path/to/privateKey.pem
+
+GatewayID=1
+GatewayName=PahoGateway-01
+KeepAlive=900
+#LoginID=your_ID
+#Password=your_Password
 
-QoS-1=NO
-QoS-1ProxyName=Proxy007
-#QoS-1ClientsList=/path/to/your_qos-1clients.conf
-    
-#RootCAfile=/path/to/your_Root_CA.crt    
-#RootCApath=/path/to/your_certs_directory/   
-#CertKey=/path/to/your_cert.pem
-#PrivateKey=/path/to/your_private-key.pem
-    
-GatewayID=1    
-GatewayName=PahoGateway-01    
-KeepAlive=900    
-#LoginID=your_ID    
-#Password=your_Password    
 
 # UDP
-GatewayPortNo=10000    
-MulticastIP=225.1.1.1    
-MulticastPortNo=1883    
+GatewayPortNo=10000
+MulticastIP=225.1.1.1
+MulticastPortNo=1883
 
 # XBee
-Baudrate=38400    
-SerialDevice=/dev/ttyUSB0    
-ApiMode=2    
-````    
+Baudrate=38400
+SerialDevice=/dev/ttyUSB0
+ApiMode=2
+
+# LOG
+ShearedMemory=NO;
+
+
**BrokerName** to specify a domain name of the Broker, and **BrokerPortNo** is a port No of the Broker. **BrokerSecurePortNo** is for TLS connection. **MulticastIP** and **MulticastPortNo** is a multicast address for GWSEARCH messages. Gateway is waiting GWSEARCH and when receiving it send GWINFO message via MulticastIP address. Clients can get the gateway address (Gateway IP address and **GatewayPortNo**) from GWINFO message by means of std::recvfrom(). Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW message. **GatewayId** is used by GWINFO message. **KeepAlive** is a duration of ADVERTISE message in seconds. -when **ClientAuthentication** is YES, see MQTTSNGWClient.cpp line53, clients file specified by ClientsList is required. This file defines connect allowed clients by ClientId and SensorNetwork Address. e.g. IP address and Port No. -When **PredefinedTopic** is YES, Pre-definedTopicID file specified by PredefinedTopicList is effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format. -When **Forwarder** is YES, Forwarder Encapsulation Message is available. Connectable Forwarders are specifed by ForwardersList file. In this file, ForwarderIds and those sensorNet addresses are declared in CSV format. -When **QoS-1** is YES, QoS-1 PUBLISH Message is available. Clients which allow to send it, are specifed by QoS-1ClientsList file. In this file, ClientsId and those sensorNet addresses are declared in CSV format. QoS-1ProxyName is a ClientId of the proxy. +when **AggregateGateway** or **ClientAuthentication** is **YES**, All clients which connect to the gateway must be declared by a **ClientsList** file. +Format of the file is ClientId and SensorNetwork Address. e.g. IP address and Port No etc, in CSV. more detail see clients.conf +When **PredefinedTopic** is **YES**, **Pre-definedTopicId**s specified by **PredefinedTopicList** are effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format. +When **Forwarder** is **YE**S, Forwarder Encapsulation Message is available. Connectable Forwarders are specifed by **ForwardersList** file. In this file, ForwarderIds and those sensorNet addresses are declared in CSV format. diff --git a/MQTTSNGateway/clients.conf b/MQTTSNGateway/clients.conf index 16d128a..28d2bab 100644 --- a/MQTTSNGateway/clients.conf +++ b/MQTTSNGateway/clients.conf @@ -11,8 +11,29 @@ # http://www.eclipse.org/org/documents/edl-v10.php. #*********************************************************************** # +# File format is: +# Lines bigning with # are comment line. +# ClientId, SensorNetAddress, "unstableLine", "secureConnection" +# in case of UDP, SensorNetAddress format is portNo@IPAddress. +# if the SensorNetwork is not stable, write unstableLine. +# if Broker's Connection is SSL, write secureConnection. +# if the client send PUBLISH QoS-1, QoS-1 is required. +# +# Ex: +# #Client List +# ClientId1,11200@192.168.10.10 +# ClientID2,35000@192.168.50.200,unstableLine +# ClientID3,40000@192.168.200.50,secureConnection +# ClientID4,41000@192.168.200.51,unstableLine,secureConnection +# ClientID5,41000@192.168.200.51,unstableLine,secureConnection,QoS-1 +# # SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function. # -Client02,172.16.1.7:12002 -Client03,172.16.1.8:13003 -Client01,172.16.1.6:12001 + +Client02,172.16.1.11:12002 +Client03,172.16.1.11:13003 +Client01,172.16.1.11:12001 + +QoS-1_Client01,172.16.1.11:20001,QoS-1 +QoS-1_Client02,172.16.1.11:20002,QoS-1 +QoS-1_Client03,172.16.1.11:20003,QoS-1 diff --git a/MQTTSNGateway/gateway.conf b/MQTTSNGateway/gateway.conf index 277f7ae..e2a1d25 100644 --- a/MQTTSNGateway/gateway.conf +++ b/MQTTSNGateway/gateway.conf @@ -10,26 +10,33 @@ # and the Eclipse Distribution License is available at # http://www.eclipse.org/org/documents/edl-v10.php. #*************************************************************************** - +# # config file of MQTT-SN Gateway +# BrokerName=iot.eclipse.org BrokerPortNo=1883 BrokerSecurePortNo=8883 +# +# When AggregateGateway=YES or ClientAuthentication=YES, +# All clients must be specified by the ClientList File +# + +AggregateGateway=NO ClientAuthentication=NO + #ClientsList=/path/to/your_clients.conf +QoS-1=NO +OoS-1ProxyName=Proxy007 + PredefinedTopic=NO #PredefinedTopicList=/path/to/your_predefinedTopic.conf Forwarder=NO #ForwardersList=/path/to/your_forwarers.conf -QoS-1=NO -OoS-1ProxyName=Proxy007 -#QoS-1ClientsList=/path/to/your_qos-1clients.conf - #RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCApath=/etc/ssl/certs/ #CertsFile=/path/to/certKey.pem diff --git a/MQTTSNGateway/predefinedTopic.conf b/MQTTSNGateway/predefinedTopic.conf index eec33f4..95d23ea 100644 --- a/MQTTSNGateway/predefinedTopic.conf +++ b/MQTTSNGateway/predefinedTopic.conf @@ -20,28 +20,27 @@ # One for QoS-1 PUBLISH Clients, the other for another clients. # -# pre-defined-topics for QoS-1 clients. -# ClientIDs should be "ClientProxy" -# - -ClientProxy, ty4tw/proxy/predefTopic1, 1 -ClientProxy, ty4tw/proxy/predefTopic2, 2 -ClientProxy, ty4tw/proxy/predefTopic3, 3 - - -# -# pre-defined-topics for another clients +# pre-defined-topics for Clients # GatewayTestClient,ty4tw/predefinedTopic1, 1 GatewayTestClient,ty4tw/predefinedTopic2, 2 GatewayTestClient,ty4tw/predefinedTopic3, 3 -ClientPUB,ty4tw/predefinedTopic1, 1 -ClientPUB,ty4tw/predefinedTopic2, 2 -ClientPUB,ty4tw/predefinedTopic3, 3 +# +# pre-defined-topics for QoS-1 clients. +# + +QoS-1_Client01,ty4tw/proxy/predefTopic1, 1 +QoS-1_Client01,ty4tw/proxy/predefTopic2, 2 +QoS-1_Client01,ty4tw/proxy/predefTopic3, 3 + +QoS-1_Client02,ty4tw/proxy/predefTopic1, 1 +QoS-1_Client02,ty4tw/proxy/predefTopic3, 2 +QoS-1_Client02,ty4tw/proxy/predefTopic3, 3 + +QoS-1_Client03,ty4tw/proxy/predefTopic1, 1 +QoS-1_Client03,ty4tw/proxy/predefTopic2, 2 +QoS-1_Client03,ty4tw/proxy/predefTopic3, 3 -ClientSUB,ty4tw/predefinedTopic1, 1 -ClientSUB,ty4tw/predefinedTopic2, 2 -ClientSUB,ty4tw/predefinedTopic3, 3 diff --git a/MQTTSNGateway/qos-1clients.conf b/MQTTSNGateway/qos-1clients.conf deleted file mode 100644 index 58ed914..0000000 --- a/MQTTSNGateway/qos-1clients.conf +++ /dev/null @@ -1,30 +0,0 @@ -#*********************************************************************** -# Copyright (c) 2018, 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. -#*********************************************************************** -# -# Clients which send QoS-1 PUBLISH are defined by this file. -# -# Clients are defined by the ClientId and those SensorNetAddress -# in a CSV format as follow: -# -# ClientId, SensorNetAddress -# -# where SensorNetwork address format is defined by -# SensorNetAddress::setAddress(string* data) function. -# -# - -QoS-1_Client01,172.16.1.11:20001 -QoS-1_Clien02t,172.16.1.11:20002 -QoS-1_Client03,172.16.1.11:20003 -QoS-1_Client04,172.16.1.11:20004 -QoS-1_Client05,172.16.1.11:20005 diff --git a/MQTTSNGateway/src/MQTTGWPacket.cpp b/MQTTSNGateway/src/MQTTGWPacket.cpp index 55532fc..67ff660 100644 --- a/MQTTSNGateway/src/MQTTGWPacket.cpp +++ b/MQTTSNGateway/src/MQTTGWPacket.cpp @@ -21,6 +21,9 @@ using namespace MQTTSNGW; +int readInt(char** ptr); +void writeInt(unsigned char** pptr, int msgId); + #define MAX_NO_OF_REMAINING_LENGTH_BYTES 3 /** * List of the predefined MQTT v3 packet names. @@ -511,12 +514,12 @@ char* MQTTGWPacket::getMsgId(char* pbuf) sprintf(pbuf, " %04X", pub.msgId); } break; + case SUBSCRIBE: + case UNSUBSCRIBE: case PUBACK: case PUBREC: case PUBREL: case PUBCOMP: - case SUBSCRIBE: - case UNSUBSCRIBE: case SUBACK: case UNSUBACK: sprintf(pbuf, " %02X%02X", _data[0], _data[1]); @@ -525,9 +528,77 @@ char* MQTTGWPacket::getMsgId(char* pbuf) sprintf(pbuf, " "); break; } + if ( strcmp(pbuf, " 0000") == 0 ) + { + sprintf(pbuf, " "); + } return pbuf; } +int MQTTGWPacket::getMsgId(void) +{ + int type = getType(); + int msgId = 0; + + switch ( type ) + { + case PUBLISH: + Publish pub; + pub.msgId = 0; + getPUBLISH(&pub); + msgId = pub.msgId; + break; + case PUBACK: + case PUBREC: + case PUBREL: + case PUBCOMP: + case SUBSCRIBE: + case UNSUBSCRIBE: + case SUBACK: + case UNSUBACK: + msgId = 256 * (unsigned char)_data[0] + (unsigned char)_data[1]; + break; + default: + break; + } + return msgId; +} + +void MQTTGWPacket::setMsgId(int msgId) +{ + int type = getType(); + unsigned char* ptr = 0; + int len = 0; + + switch ( type ) + { + case PUBLISH: + Publish pub; + pub.msgId = 0; + getPUBLISH(&pub); + pub.msgId = msgId; + ptr = _data + pub.topiclen; + writeInt(&ptr, pub.msgId); + *ptr++ = (unsigned char)(msgId / 256); + *ptr = (unsigned char)(msgId % 256); + break; + case SUBSCRIBE: + case UNSUBSCRIBE: + case PUBACK: + case PUBREC: + case PUBREL: + case PUBCOMP: + case SUBACK: + case UNSUBACK: + ptr = _data; + *ptr++ = (unsigned char)(msgId / 256); + *ptr = (unsigned char)(msgId % 256); + break; + default: + break; + } +} + char* MQTTGWPacket::print(char* pbuf) { uint8_t packetData[MQTTSNGW_MAX_PACKET_SIZE]; @@ -561,3 +632,14 @@ MQTTGWPacket& MQTTGWPacket::operator =(MQTTGWPacket& packet) return *this; } +UTF8String MQTTGWPacket::getTopic(void) +{ + UTF8String str = {0, nullptr}; + if ( _header.bits.type == SUBSCRIBE || _header.bits.type == UNSUBSCRIBE ) + { + char* ptr = (char*)(_data + 2); + str.len = readInt(&ptr); + str.data = (char*)(_data + 4); + } + return str; +} diff --git a/MQTTSNGateway/src/MQTTGWPacket.h b/MQTTSNGateway/src/MQTTGWPacket.h index 458dd4d..bc35d97 100644 --- a/MQTTSNGateway/src/MQTTGWPacket.h +++ b/MQTTSNGateway/src/MQTTGWPacket.h @@ -116,6 +116,12 @@ typedef struct unsigned char version; /**< MQTT version number */ } Connect; +#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 } +#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \ + MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} } + + + /** * Data for a willMessage. */ @@ -177,6 +183,15 @@ typedef struct int msgId; /**< MQTT message id */ } Ack; +/** + * UTF8String. + */ +typedef struct +{ + unsigned char len; + char* data; +} UTF8String; + /** * Class MQTT Packet */ @@ -203,7 +218,11 @@ public: int setHeader(unsigned char msgType); int setSUBSCRIBE(const char* topic, unsigned char qos, unsigned short msgId); int setUNSUBSCRIBE(const char* topics, unsigned short msgid); + + UTF8String getTopic(void); char* getMsgId(char* buf); + int getMsgId(void); + void setMsgId(int msgId); char* print(char* buf); MQTTGWPacket& operator =(MQTTGWPacket& packet); diff --git a/MQTTSNGateway/src/MQTTGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTGWPublishHandler.cpp index 5a2b5a6..b264a36 100644 --- a/MQTTSNGateway/src/MQTTGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTGWPublishHandler.cpp @@ -106,7 +106,7 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet) /* This message might be subscribed with wild card. */ topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; Topic* topic = client->getTopics()->match(&topicId); - if (topic == 0) + if (topic == nullptr) { WRITELOG(" Invalid Topic. PUBLISH message is canceled.\n"); if (pub.header.bits.qos == 1) @@ -181,7 +181,7 @@ void MQTTGWPublishHandler::handlePuback(Client* client, MQTTGWPacket* packet) { Ack ack; packet->getAck(&ack); - TopicIdMapelement* topicId = client->getWaitedPubTopicId((uint16_t)ack.msgId); + TopicIdMapElement* topicId = client->getWaitedPubTopicId((uint16_t)ack.msgId); if (topicId) { MQTTSNPacket* mqttsnPacket = new MQTTSNPacket(); @@ -234,3 +234,89 @@ void MQTTGWPublishHandler::handleAck(Client* client, MQTTGWPacket* packet, int t } } + + +void MQTTGWPublishHandler::handleAggregatePuback(Client* client, MQTTGWPacket* packet) +{ + uint16_t msgId = packet->getMsgId(); + uint16_t clientMsgId = 0; + Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId); + if ( newClient != nullptr ) + { + packet->setMsgId((int)clientMsgId); + handlePuback(newClient, packet); + } +} + +void MQTTGWPublishHandler::handleAggregateAck(Client* client, MQTTGWPacket* packet, int type) +{ + uint16_t msgId = packet->getMsgId(); + uint16_t clientMsgId = 0; + Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId); + if ( newClient != nullptr ) + { + packet->setMsgId((int)clientMsgId); + handleAck(newClient, packet,type); + } +} + +void MQTTGWPublishHandler::handleAggregatePubrel(Client* client, MQTTGWPacket* packet) +{ + Publish pub; + packet->getPUBLISH(&pub); + replyACK(client, &pub, PUBCOMP); +} + +void MQTTGWPublishHandler::handleAggregatePublish(Client* client, MQTTGWPacket* packet) +{ + Publish pub; + packet->getPUBLISH(&pub); + + WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), + RIGHTARROW, client->getClientId(), "is sleeping. a message was saved."); + + if (pub.header.bits.qos == 1) + { + replyACK(client, &pub, PUBACK); + } + else if ( pub.header.bits.qos == 2) + { + replyACK(client, &pub, PUBREC); + } + + MQTTGWPacket* msg = new MQTTGWPacket(); + *msg = *packet; + if ( msg->getType() == 0 ) + { + WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER); + delete msg; + return; + } + + string* topicName = new string(pub.topic); + Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); + AggregateTopicElement* list = _gateway->getAdapterManager()->createClientList(&topic); + if ( list != nullptr ) + { + ClientTopicElement* p = list->getFirstElement(); + + while ( p ) + { + Client* devClient = p->getClient(); + if ( devClient != nullptr ) + { + Event* ev = new Event(); + ev->setBrokerRecvEvent(devClient, packet); + _gateway->getPacketEventQue()->post(ev); + } + else + { + break; + } + + p = list->getNextElement(p); + } + delete list; + } +} + diff --git a/MQTTSNGateway/src/MQTTGWPublishHandler.h b/MQTTSNGateway/src/MQTTGWPublishHandler.h index 72ac8b1..fee60e8 100644 --- a/MQTTSNGateway/src/MQTTGWPublishHandler.h +++ b/MQTTSNGateway/src/MQTTGWPublishHandler.h @@ -32,6 +32,11 @@ public: void handlePuback(Client* client, MQTTGWPacket* packet); void handleAck(Client* client, MQTTGWPacket* packet, int type); + void handleAggregatePublish(Client* client, MQTTGWPacket* packet); + void handleAggregatePuback(Client* client, MQTTGWPacket* packet); + void handleAggregateAck(Client* client, MQTTGWPacket* packet, int type); + void handleAggregatePubrel(Client* client, MQTTGWPacket* packet); + private: void replyACK(Client* client, Publish* pub, int type); diff --git a/MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp b/MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp index a8264ac..2df4815 100644 --- a/MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp +++ b/MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp @@ -38,7 +38,7 @@ void MQTTGWSubscribeHandler::handleSuback(Client* client, MQTTGWPacket* packet) int qos = 0; packet->getSUBACK(&msgId, &rc); - TopicIdMapelement* topicId = client->getWaitedSubTopicId(msgId); + TopicIdMapElement* topicId = client->getWaitedSubTopicId(msgId); if (topicId) { @@ -72,3 +72,28 @@ void MQTTGWSubscribeHandler::handleUnsuback(Client* client, MQTTGWPacket* packet _gateway->getClientSendQue()->post(evt); } +void MQTTGWSubscribeHandler::handleAggregateSuback(Client* client, MQTTGWPacket* packet) +{ + uint16_t msgId = packet->getMsgId(); + uint16_t clientMsgId = 0; + Client* newClient = _gateway->getAdapterManager()->getAggregater()->convertClient(msgId, &clientMsgId); + if ( newClient != nullptr ) + { + packet->setMsgId((int)clientMsgId); + handleSuback(newClient, packet); + } +} + +void MQTTGWSubscribeHandler::handleAggregateUnsuback(Client* client, MQTTGWPacket* packet) +{ + uint16_t msgId = packet->getMsgId(); + uint16_t clientMsgId = 0; + Client* newClient = _gateway->getAdapterManager()->getAggregater()->convertClient(msgId, &clientMsgId); + if ( newClient != nullptr ) + { + packet->setMsgId((int)clientMsgId); + handleUnsuback(newClient, packet); + } +} + + diff --git a/MQTTSNGateway/src/MQTTGWSubscribeHandler.h b/MQTTSNGateway/src/MQTTGWSubscribeHandler.h index 1775826..d52b70f 100644 --- a/MQTTSNGateway/src/MQTTGWSubscribeHandler.h +++ b/MQTTSNGateway/src/MQTTGWSubscribeHandler.h @@ -31,6 +31,8 @@ public: ~MQTTGWSubscribeHandler(); void handleSuback(Client* clnode, MQTTGWPacket* packet); void handleUnsuback(Client* clnode, MQTTGWPacket* packet); + void handleAggregateSuback(Client* client, MQTTGWPacket* packet); + void handleAggregateUnsuback(Client* client, MQTTGWPacket* packet); private: Gateway* _gateway; diff --git a/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.cpp b/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.cpp new file mode 100644 index 0000000..dded6df --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.cpp @@ -0,0 +1,202 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 "MQTTSNAggregateConnectionHandler.h" +#include "MQTTSNGateway.h" +#include "MQTTSNGWPacket.h" +#include "MQTTGWPacket.h" +#include + +using namespace std; +using namespace MQTTSNGW; + +/*===================================== + Class MQTTSNAggregateConnectionHandler + =====================================*/ +MQTTSNAggregateConnectionHandler::MQTTSNAggregateConnectionHandler(Gateway* gateway) +{ + _gateway = gateway; +} + +MQTTSNAggregateConnectionHandler::~MQTTSNAggregateConnectionHandler() +{ + +} + + +/* + * CONNECT + */ +void MQTTSNAggregateConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet) +{ + MQTTSNPacket_connectData data; + if ( packet->getCONNECT(&data) == 0 ) + { + return; + } + + /* return CONNACK when the client is sleeping */ + if ( client->isSleep() || client->isAwake() ) + { + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNACK(MQTTSN_RC_ACCEPTED); + Event* ev = new Event(); + ev->setClientSendEvent(client, packet); + _gateway->getClientSendQue()->post(ev); + sendStoredPublish(client); + return; + } + + //* clear ConnectData of Client */ + Connect* connectData = client->getConnectData(); + memset(connectData, 0, sizeof(Connect)); + + client->disconnected(); + + Topics* topics = client->getTopics(); + + /* CONNECT was not sent yet. prepare Connect data */ + + + client->setSessionStatus(false); + if (data.cleansession) + { + /* reset the table of msgNo and TopicId pare */ + client->clearWaitedPubTopicId(); + client->clearWaitedSubTopicId(); + + /* renew the TopicList */ + if (topics) + { + _gateway->getAdapterManager()->removeAggregateTopicList(topics, client); + topics->eraseNormal(); + } + client->setSessionStatus(true); + } + + if (data.willFlag) + { + /* create & send WILLTOPICREQ message to the client */ + MQTTSNPacket* reqTopic = new MQTTSNPacket(); + reqTopic->setWILLTOPICREQ(); + Event* evwr = new Event(); + evwr->setClientSendEvent(client, reqTopic); + + /* Send WILLTOPICREQ to the client */ + _gateway->getClientSendQue()->post(evwr); + } + else + { + /* create CONNACK & send it to the client */ + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNACK(MQTTSN_RC_ACCEPTED); + Event* ev = new Event(); + ev->setClientSendEvent(client, packet); + _gateway->getClientSendQue()->post(ev); + client->connackSended(MQTTSN_RC_ACCEPTED); + sendStoredPublish(client); + return; + } +} + + +/* + * WILLMSG + */ +void MQTTSNAggregateConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet) +{ + if ( !client->isWaitWillMsg() ) + { + DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n"); + return; + } + + MQTTSNString willmsg = MQTTSNString_initializer; + //Connect* connectData = client->getConnectData(); + + if( client->isConnectSendable() ) + { + /* save WillMsg in the client */ + if ( packet->getWILLMSG(&willmsg) == 0 ) + { + return; + } + client->setWillMsg(willmsg); + + /* Send CONNACK to the client */ + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNACK(MQTTSN_RC_ACCEPTED); + Event* ev = new Event(); + ev->setClientSendEvent(client, packet); + _gateway->getClientSendQue()->post(ev); + + sendStoredPublish(client); + return; + } +} + +/* + * DISCONNECT + */ +void MQTTSNAggregateConnectionHandler::handleDisconnect(Client* client, MQTTSNPacket* packet) +{ + MQTTSNPacket* snMsg = new MQTTSNPacket(); + snMsg->setDISCONNECT(0); + Event* evt = new Event(); + evt->setClientSendEvent(client, snMsg); + _gateway->getClientSendQue()->post(evt); +} + +/* + * PINGREQ + */ +void MQTTSNAggregateConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet) +{ + if ( ( client->isSleep() || client->isAwake() ) && client->getClientSleepPacket() ) + { + sendStoredPublish(client); + client->holdPingRequest(); + } + else + { + /* create and send PINGRESP to the PacketHandler */ + client->resetPingRequest(); + + MQTTGWPacket* pingresp = new MQTTGWPacket(); + + pingresp->setHeader(PINGRESP); + + Event* evt = new Event(); + evt->setBrokerRecvEvent(client, pingresp); + _gateway->getPacketEventQue()->post(evt); + } +} + +void MQTTSNAggregateConnectionHandler::sendStoredPublish(Client* client) +{ + MQTTGWPacket* msg = nullptr; + + while ( ( msg = client->getClientSleepPacket() ) != nullptr ) + { + // ToDo: This version can't re-send PUBLISH when PUBACK is not returned. + client->deleteFirstClientSleepPacket(); // pop the que to delete element. + + Event* ev = new Event(); + ev->setBrokerRecvEvent(client, msg); + _gateway->getPacketEventQue()->post(ev); + } +} + diff --git a/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.h b/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.h new file mode 100644 index 0000000..46bf4f0 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.h @@ -0,0 +1,48 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNAGGREGATECONNECTIONHANDLER_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNAGGREGATECONNECTIONHANDLER_H_ + +#include "MQTTSNGWDefines.h" + +namespace MQTTSNGW +{ +class Gateway; +class Client; +class MQTTSNPacket; + +class MQTTSNAggregateConnectionHandler +{ +public: + MQTTSNAggregateConnectionHandler(Gateway* gateway); + ~MQTTSNAggregateConnectionHandler(void); + + void handleConnect(Client* client, MQTTSNPacket* packet); + void handleWillmsg(Client* client, MQTTSNPacket* packet); + void handleDisconnect(Client* client, MQTTSNPacket* packet); + void handlePingreq(Client* client, MQTTSNPacket* packet); + +private: + void sendStoredPublish(Client* client); + + char _pbuf[MQTTSNGW_MAX_PACKET_SIZE * 3]; + Gateway* _gateway; +}; + +} + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNAGGREGATECONNECTIONHANDLER_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWAdapter.cpp b/MQTTSNGateway/src/MQTTSNGWAdapter.cpp new file mode 100644 index 0000000..73cbc29 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWAdapter.cpp @@ -0,0 +1,321 @@ +/************************************************************************************** + * 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 "Timer.h" +#include "MQTTSNGWDefines.h" +#include "MQTTSNGateway.h" +#include "MQTTSNGWAdapter.h" +#include "SensorNetwork.h" +#include "MQTTSNGWProcess.h" +#include "MQTTSNGWClient.h" + +#include +using namespace MQTTSNGW; + + +/*===================================== + Class Adapter + =====================================*/ +Adapter:: Adapter(Gateway* gw) +{ + _gateway = gw; + _proxy = new Proxy(gw); + _proxySecure = new Proxy(gw); +} + +Adapter::~Adapter(void) +{ + if ( _proxy ) + { + delete _proxy; + } + + if ( _proxySecure ) + { + delete _proxySecure; + } +} + + +void Adapter::setup(const char* adpterName, AdapterType adapterType) +{ + _isSecure = false; + if ( _gateway->hasSecureConnection() ) + { + _isSecure = true; + } + + MQTTSNString id = MQTTSNString_initializer; + MQTTSNString idSecure = MQTTSNString_initializer; + + string name = string(adpterName); + id.cstring = const_cast(name.c_str()); + string nameSecure = string(adpterName) + "-S"; + idSecure.cstring = const_cast(nameSecure.c_str()); + + Client* client = _gateway->getClientList()->createClient(0, &id, true, false, TRANSPEARENT_TYPE); + setClient(client, false); + client->setAdapterType(adapterType); + + client = _gateway->getClientList()->createClient(0, &idSecure, true, true, TRANSPEARENT_TYPE); + setClient(client, true); + client->setAdapterType(adapterType); +} + + +Client* Adapter::getClient(SensorNetAddress* addr) +{ + Client* client = _gateway->getClientList()->getClient(addr); + if ( !client ) + { + return nullptr; + } + else if ( client->isQoSm1() ) + { + return client; + } + else + { + return nullptr; + } +} + +const char* Adapter::getClientId(SensorNetAddress* addr) +{ + Client* client = getClient(addr); + if ( !client ) + { + return nullptr; + } + else if ( client->isQoSm1() ) + { + return client->getClientId(); + } + else + { + return nullptr; + } +} + +bool Adapter::isSecure(SensorNetAddress* addr) +{ + Client* client = getClient(addr); + if ( !client ) + { + return false; + } + else if ( client->isSecureNetwork() ) + { + return true; + } + else + { + return false; + } +} + +void Adapter::setClient(Client* client, bool secure) +{ + if ( secure ) + { + _clientSecure = client; + } + else + { + _client = client; + } +} + +Client* Adapter::getClient(void) +{ + return _client; +} + +Client* Adapter::getSecureClient(void) +{ + return _clientSecure; +} + +void Adapter::checkConnection(void) +{ + _proxy->checkConnection(_client); + + if ( _isSecure ) + { + _proxySecure->checkConnection(_clientSecure); + } +} + +void Adapter::send(MQTTSNPacket* packet, Client* client) +{ + Proxy* proxy = _proxy; + if ( client->isSecureNetwork() && !_isSecure ) + { + if ( _isSecure ) + { + proxy = _proxySecure; + } + else + { + WRITELOG("%s %s No Secure connections %s 's packet is discarded.%s\n", ERRMSG_HEADER, client->getClientId() , ERRMSG_FOOTER); + return; + } + } + + proxy->recv(packet, client); + +} + +void Adapter::resetPingTimer(bool secure) +{ + if ( secure ) + { + _proxySecure->resetPingTimer(); + } + else + { + _proxy->resetPingTimer(); + } +} + +bool Adapter::isActive(void) +{ + return _isActive; +} + +void Adapter::savePacket(Client* client, MQTTSNPacket* packet) +{ + if ( client->isSecureNetwork()) + { + _proxySecure->savePacket(client, packet); + } + else + { + _proxy->savePacket(client, packet); + } +} + + +Client* Adapter::getAdapterClient(Client* client) +{ + if ( client->isSecureNetwork() ) + { + return _client; + } + else + { + return _client; + } +} + +/*===================================== + Class Proxy + =====================================*/ +Proxy::Proxy(Gateway* gw) +{ + _gateway = gw; + _suspendedPacketEventQue = new EventQue(); +} +Proxy::~Proxy(void) +{ + if ( _suspendedPacketEventQue ) + { + delete _suspendedPacketEventQue; + } +} + +void Proxy::checkConnection(Client* client) +{ + if ( client->isDisconnect() || ( client->isConnecting() && _responseTimer.isTimeup()) ) + { + client->connectSended(); + _responseTimer.start(QOSM1_PROXY_RESPONSE_DURATION * 1000UL); + MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; + options.clientID.cstring = client->getClientId(); + options.duration = QOSM1_PROXY_KEEPALIVE_DURATION; + + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNECT(&options); + Event* ev = new Event(); + ev->setClientRecvEvent(client, packet); + _gateway->getPacketEventQue()->post(ev); + } + else if ( (client->isActive() && _keepAliveTimer.isTimeup() ) || (_isWaitingResp && _responseTimer.isTimeup() ) ) + { + MQTTSNPacket* packet = new MQTTSNPacket(); + MQTTSNString clientId = MQTTSNString_initializer; + packet->setPINGREQ(&clientId); + Event* ev = new Event(); + ev->setClientRecvEvent(client, packet); + _gateway->getPacketEventQue()->post(ev); + _responseTimer.start(QOSM1_PROXY_RESPONSE_DURATION * 1000UL); + _isWaitingResp = true; + + if ( ++_retryCnt > QOSM1_PROXY_MAX_RETRY_CNT ) + { + client->disconnected(); + } + resetPingTimer(); + } +} + + +void Proxy::resetPingTimer(void) +{ + _keepAliveTimer.start(QOSM1_PROXY_KEEPALIVE_DURATION * 1000UL); +} + +void Proxy::recv(MQTTSNPacket* packet, Client* client) +{ + if ( packet->getType() == MQTTSN_CONNACK ) + { + if ( packet->isAccepted() ) + { + _responseTimer.stop(); + _retryCnt = 0; + resetPingTimer(); + sendSuspendedPacket(); + } + } + else if ( packet->getType() == MQTTSN_PINGRESP ) + { + _isWaitingResp = false; + _responseTimer.stop(); + _retryCnt = 0; + resetPingTimer(); + } + else if ( packet->getType() == MQTTSN_DISCONNECT ) + { + // blank + } +} + +void Proxy::savePacket(Client* client, MQTTSNPacket* packet) +{ + MQTTSNPacket* pk = new MQTTSNPacket(*packet); + Event* ev = new Event(); + ev->setClientRecvEvent(client, pk); + _suspendedPacketEventQue->post(ev); +} + +void Proxy::sendSuspendedPacket(void) +{ + while ( _suspendedPacketEventQue->size() ) + { + Event* ev = _suspendedPacketEventQue->wait(); + _gateway->getPacketEventQue()->post(ev); + } +} + diff --git a/MQTTSNGateway/src/MQTTSNGWAdapter.h b/MQTTSNGateway/src/MQTTSNGWAdapter.h new file mode 100644 index 0000000..8ea4b45 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWAdapter.h @@ -0,0 +1,99 @@ +/************************************************************************************** + * 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 + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWADAPTER_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWADAPTER_H_ + +#include +#include "Timer.h" +namespace MQTTSNGW +{ +class Gateway; +class Client; +class Proxy; +class SensorNetAddress; +class MQTTSNPacket; +class MQTTSNGWPacket; +class EventQue; +class Timer; + +/* When you add a new type, Client::setAdapterType() and Client::isAdapter() functions must be modified. */ +typedef enum{ + Atype_QoSm1Proxy, Atype_Aggregater +}AdapterType; + +/*===================================== + Class Adapter + =====================================*/ +class Adapter +{ +public: + Adapter(Gateway* gw); + ~Adapter(void); + + void setup(const char* adpterName, AdapterType adapterType); + const char* getClientId(SensorNetAddress* addr); + void setClient(Client* client, bool secure); + Client* getClient(SensorNetAddress* addr); + Client* getClient(void); + Client* getSecureClient(void); + Client* getAdapterClient(Client* client); + void resetPingTimer(bool secure); + void checkConnection(void); + void send(MQTTSNPacket* packet, Client* client); + bool isActive(void); + bool isSecure(SensorNetAddress* addr); + void savePacket(Client* client, MQTTSNPacket* packet); + +private: + Gateway* _gateway {nullptr}; + Proxy* _proxy {nullptr}; + Proxy* _proxySecure {nullptr}; + Client* _client {nullptr}; + Client* _clientSecure {nullptr}; + bool _isActive {false}; + bool _isSecure{false}; +}; + + +/*===================================== + Class Proxy + =====================================*/ +class Proxy +{ +public: + Proxy(Gateway* gw); + ~Proxy(void); + + void setKeepAlive(uint16_t secs); + void checkConnection(Client* client); + void resetPingTimer(void); + void recv(MQTTSNPacket* packet, Client* client); + void savePacket(Client* client, MQTTSNPacket* packet); + +private: + void sendSuspendedPacket(void); + Gateway* _gateway; + EventQue* _suspendedPacketEventQue {nullptr}; + Timer _keepAliveTimer; + Timer _responseTimer; + bool _isWaitingResp {false}; + int _retryCnt {0}; +}; + +} + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWADAPTER_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp b/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp new file mode 100644 index 0000000..6cbef35 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp @@ -0,0 +1,253 @@ +/************************************************************************************** + * 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 "MQTTSNGWDefines.h" +#include "MQTTSNGateway.h" +#include "SensorNetwork.h" +#include "MQTTSNGWProcess.h" +#include "MQTTSNGWVersion.h" +#include "MQTTSNGWClientRecvTask.h" +#include "MQTTSNGWClientSendTask.h" +#include "MQTTSNGWClient.h" +#include "MQTTSNGWAggregater.h" +#include "MQTTSNGWQoSm1Proxy.h" +#include +using namespace MQTTSNGW; + +char* currentDateTime(void); + +/*===================================== + Class AdapterManager + =====================================*/ +AdapterManager::AdapterManager(Gateway* gw) +{ + _gateway = gw; + _forwarders = new ForwarderList(); + _qosm1Proxy = new QoSm1Proxy(gw); + _aggregater = new Aggregater(gw); +} + + +void AdapterManager::initialize(void) +{ + _aggregater->initialize(); + _forwarders->initialize(_gateway); + _qosm1Proxy->initialize(); +} + + +AdapterManager::~AdapterManager(void) +{ + if ( _forwarders ) + { + delete _forwarders; + } + if ( _qosm1Proxy ) + { + delete _qosm1Proxy; + } + if ( _aggregater ) + { + delete _aggregater; + } +} + +ForwarderList* AdapterManager::getForwarderList(void) +{ + return _forwarders; +} + +QoSm1Proxy* AdapterManager::getQoSm1Proxy(void) +{ + return _qosm1Proxy; +} + +Aggregater* AdapterManager::getAggregater(void) +{ + return _aggregater; +} + +bool AdapterManager::isAggregatedClient(Client* client) +{ + if ( !_aggregater->isActive() || client->isQoSm1() || client->isAggregater() || client->isQoSm1Proxy()) + { + return false; + } + else + { + return true; + } +} + + +Client* AdapterManager::getClient(MQTTSNPacket* packet, ClientRecvTask* task) +{ + char buf[128]; + WirelessNodeId nodeId; + SensorNetAddress* senderAddr = _gateway->getSensorNetwork()->getSenderAddress(); + + Client* client = nullptr; + + if ( packet->getType() == MQTTSN_ENCAPSULATED ) + { + Forwarder* fwd = getForwarderList()->getForwarder(senderAddr); + + if ( fwd == nullptr ) + { + task->log(0, packet, 0); + WRITELOG("%s Forwarder %s is not authenticated.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER); + delete packet; + return client; + } + else + { + MQTTSNString fwdName = MQTTSNString_initializer; + fwdName.cstring = const_cast( fwd->getName() ); + task->log(0, packet, &fwdName); + + /* get the packet from the encapsulation message */ + MQTTSNGWEncapsulatedPacket encap; + encap.desirialize(packet->getPacketData(), packet->getPacketLength()); + nodeId.setId( encap.getWirelessNodeId() ); + client = fwd->getClient(&nodeId); + delete packet; + packet = encap.getMQTTSNPacket(); + } + } + else + { + /* Check the client belonging to QoS-1Proxy ? */ + + if ( _qosm1Proxy->isActive() ) + { + /* get ClientId not Client which can send QoS-1 PUBLISH */ + const char* clientName = _qosm1Proxy->getClientId(senderAddr); + + if ( clientName ) + { + if ( !packet->isQoSMinusPUBLISH() ) + { + client = _qosm1Proxy->getClient(); + task->log(clientName, packet); + WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, senderAddr->sprint(buf), ERRMSG_FOOTER); + delete packet; + return client; + } + } + } + } + + if ( client == nullptr ) + { + /* get client from the ClientList of Gateway by sensorNetAddress. */ + client = _gateway->getClientList()->getClient(senderAddr); + } + return client; +} + +Client* AdapterManager::getClient(Client& client) +{ + bool secure = client.isSecureNetwork(); + Client* newClient = &client; + if ( client.isQoSm1() ) + { + newClient = _qosm1Proxy->getAdapterClient(&client); + _qosm1Proxy->resetPingTimer(secure); + } + else if ( client.isAggregated() ) + + { + newClient = _aggregater->getAdapterClient(&client); + _aggregater->resetPingTimer(secure); + } + + return newClient; +} + +int AdapterManager::unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task) +{ + char pbuf[SIZE_OF_LOG_PACKET * 3]; + Forwarder* fwd = client->getForwarder(); + int rc = 0; + + if ( fwd ) + { + MQTTSNGWEncapsulatedPacket encap(packet); + WirelessNodeId* wnId = fwd->getWirelessNodeId(client); + encap.setWirelessNodeId(wnId); + WRITELOG(FORMAT_Y_W_G, currentDateTime(), encap.getName(), RIGHTARROW, fwd->getId(), encap.print(pbuf)); + task->log(client, packet); + rc = encap.unicast(_gateway->getSensorNetwork(),fwd->getSensorNetAddr()); + } + else + { + task->log(client, packet); + if ( client->isQoSm1Proxy() ) + { + _qosm1Proxy->send(packet, client); + } + else if ( client->isAggregater() ) + { + _aggregater->send(packet, client); + } + else + { + rc = packet->unicast(_gateway->getSensorNetwork(), client->getSensorNetAddress()); + } + } + return rc; +} + +void AdapterManager::checkConnection(void) +{ + if ( _aggregater->isActive()) + { + _aggregater->checkConnection(); + } + else if ( _qosm1Proxy->isActive()) + { + _qosm1Proxy->checkConnection(); + } +} + +Client* AdapterManager::convertClient(uint16_t msgId, uint16_t* clientMsgId) +{ + return _aggregater->convertClient(msgId, clientMsgId); +} + +bool AdapterManager::isAggregaterActive(void) +{ + return _aggregater->isActive(); +} + +AggregateTopicElement* AdapterManager::createClientList(Topic* topic) +{ + return _aggregater->createClientList(topic); +} + +int AdapterManager::addAggregateTopic(Topic* topic, Client* client) +{ + return _aggregater->addAggregateTopic(topic, client); +} + +void AdapterManager::removeAggregateTopic(Topic* topic, Client* client) +{ + _aggregater->removeAggregateTopic(topic, client); +} + +void AdapterManager::removeAggregateTopicList(Topics* topics, Client* client) +{ + _aggregater->removeAggregateTopicList(topics, client); +} diff --git a/MQTTSNGateway/src/MQTTSNGWAdapterManager.h b/MQTTSNGateway/src/MQTTSNGWAdapterManager.h new file mode 100644 index 0000000..749f1a9 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWAdapterManager.h @@ -0,0 +1,70 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_ + +#include "MQTTSNGWAggregater.h" +#include "MQTTSNGWQoSm1Proxy.h" +namespace MQTTSNGW +{ +class Gateway; +class Client; +class QoSm1Proxy; +class Aggregater; +class ForwarderList; +class MQTTSNPacket; +class MQTTSNGWPacket; +class ClientRecvTask; +class ClientSendTask; + +/*===================================== + Class AdapterManager + =====================================*/ +class AdapterManager +{ +public: + AdapterManager(Gateway* gw); + ~AdapterManager(void); + void initialize(void); + ForwarderList* getForwarderList(void); + QoSm1Proxy* getQoSm1Proxy(void); + Aggregater* getAggregater(void); + void checkConnection(void); + + bool isAggregatedClient(Client* client); + Client* getClient(MQTTSNPacket* packet, ClientRecvTask* task); + Client* getClient(Client& client); + Client* convertClient(uint16_t msgId, uint16_t* clientMsgId); + int unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task); + bool isAggregaterActive(void); + AggregateTopicElement* createClientList(Topic* topic); + int addAggregateTopic(Topic* topic, Client* client); + void removeAggregateTopic(Topic* topic, Client* client); + void removeAggregateTopicList(Topics* topics, Client* client); + +private: + Gateway* _gateway {nullptr}; + ForwarderList* _forwarders {nullptr}; + QoSm1Proxy* _qosm1Proxy {nullptr}; + Aggregater* _aggregater {nullptr}; +}; + + + + +} +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp b/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp new file mode 100644 index 0000000..b53aea1 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp @@ -0,0 +1,161 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 "MQTTSNGWAggregateTopicTable.h" +#include "MQTTSNGWClient.h" + +/*===================================== + Class ClientTopicElement + =====================================*/ +ClientTopicElement::ClientTopicElement(Client* client) +{ + _client = client; +} + +ClientTopicElement::~ClientTopicElement() +{ + +} + +Client* ClientTopicElement::getClient(void) +{ + return _client; +} + +/*===================================== + Class AggregateTopicElement + =====================================*/ +AggregateTopicElement::AggregateTopicElement(void) +{ + +} + +AggregateTopicElement::AggregateTopicElement(Topic* topic, Client* client) +{ + ClientTopicElement* elm = new ClientTopicElement(client); + if ( elm != nullptr ) + { + _head = elm; + _tail = elm; + } +} + +AggregateTopicElement::~AggregateTopicElement(void) +{ + _mutex.lock(); + if ( _head != nullptr ) + { + ClientTopicElement* p = _tail; + while ( p ) + { + ClientTopicElement* pPrev = p; + delete p; + p = pPrev->_prev; + } + _head = _tail = nullptr; + } + _mutex.unlock(); +} + +ClientTopicElement* AggregateTopicElement::add(Client* client) +{ + ClientTopicElement* elm = new ClientTopicElement(client); + if ( elm == nullptr ) + { + return nullptr; + } + _mutex.lock(); + if ( _head == nullptr ) + { + _head = elm; + _tail = elm; + } + else + { + ClientTopicElement* p = find(client); + if ( p == nullptr ) + { + p = _tail; + _tail = elm; + elm->_prev = p; + p->_next = elm; + } + else + { + delete elm; + elm = nullptr; + } + } + _mutex.unlock(); + return elm; +} + +ClientTopicElement* AggregateTopicElement::find(Client* client) +{ + ClientTopicElement* p = _head; + while ( p ) + { + if ( p->_client == client) + { + break; + } + p = p->_next; + } + return p; +} + +ClientTopicElement* AggregateTopicElement::getFirstElement(void) +{ + return _head; +} + +ClientTopicElement* AggregateTopicElement::getNextElement(ClientTopicElement* elm) +{ + return elm->_next; +} + + +/*===================================== + Class AggregateTopicTable + ======================================*/ + +AggregateTopicTable::AggregateTopicTable() +{ + +} + +AggregateTopicTable::~AggregateTopicTable() +{ + +} + +AggregateTopicElement* AggregateTopicTable::add(Topic* topic, Client* client) +{ + //ToDo: AggregateGW + return 0; +} + +void AggregateTopicTable::remove(Topic* topic, Client* client) +{ + //ToDo: AggregateGW +} + +AggregateTopicElement* AggregateTopicTable::getClientList(Topic* client) +{ + // ToDo: AggregateGW + return 0; +} + + diff --git a/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.h b/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.h new file mode 100644 index 0000000..624743f --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.h @@ -0,0 +1,98 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATETOPICTABLE_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATETOPICTABLE_H_ + +#include "MQTTSNGWDefines.h" +#include "MQTTSNGWProcess.h" +#include +namespace MQTTSNGW +{ + +class Client; +class Topic; +class AggregateTopicElement; +class ClientTopicElement; +class Mutex; + +/*===================================== + Class AggregateTopicTable + ======================================*/ +class AggregateTopicTable +{ +public: + AggregateTopicTable(); + ~AggregateTopicTable(); + + AggregateTopicElement* add(Topic* topic, Client* client); + AggregateTopicElement* getClientList(Topic* client); + void remove(Topic* topic, Client* client); + void clear(void); +private: + AggregateTopicElement* _head {nullptr}; + AggregateTopicElement* _tail {nullptr}; + int _cnt {0}; + int _maxSize {MAX_MESSAGEID_TABLE_SIZE}; +}; + +/*===================================== + Class AggregateTopicElement + =====================================*/ +class AggregateTopicElement +{ + friend class AggregateTopicTable; +public: + AggregateTopicElement(void); + AggregateTopicElement(Topic* topic, Client* client); + ~AggregateTopicElement(void); + + ClientTopicElement* add(Client* client); + ClientTopicElement* getFirstElement(void); + ClientTopicElement* getNextElement(ClientTopicElement* elm); + void erase(ClientTopicElement* elm); + ClientTopicElement* find(Client* client); + +private: + Mutex _mutex; + Topic* _topic {nullptr}; + ClientTopicElement* _head {nullptr}; + ClientTopicElement* _tail {nullptr}; +}; + +/*===================================== + Class ClientTopicElement + =====================================*/ +class ClientTopicElement +{ + friend class AggregateTopicTable; + friend class AggregateTopicElement; +public: + ClientTopicElement(Client* client); + ~ClientTopicElement(void); + Client* getClient(void); + +private: + Client* _client {nullptr}; + ClientTopicElement* _next {nullptr}; + ClientTopicElement* _prev {nullptr}; +}; + +} + + + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATETOPICTABLE_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWAggregater.cpp b/MQTTSNGateway/src/MQTTSNGWAggregater.cpp new file mode 100644 index 0000000..a091625 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWAggregater.cpp @@ -0,0 +1,143 @@ +/************************************************************************************** + * 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 "MQTTSNGWAggregater.h" +#include "MQTTSNGateway.h" +#include "MQTTSNGWClient.h" +#include "MQTTSNGWAdapter.h" +#include "MQTTSNGWAdapterManager.h" +#include "MQTTSNGWMessageIdTable.h" +#include "MQTTSNGWTopic.h" +#include +#include +#include + +using namespace MQTTSNGW; + +Aggregater::Aggregater(Gateway* gw) : Adapter(gw) +{ + _gateway = gw; +} + +Aggregater::~Aggregater(void) +{ + +} + +void Aggregater::initialize(void) +{ + char param[MQTTSNGW_PARAM_MAX]; + + if (_gateway->getParam("AggregateGateway", param) == 0 ) + { + if (!strcasecmp(param, "YES") ) + { + /* Create Aggregated Clients */ + _gateway->getClientList()->setClientList(_gateway, AGGREGATER_TYPE); + setup((const char*)(_gateway->getGWParams()->gatewayName), Atype_Aggregater); + _isActive = true; + } + } + + //testMessageIdTable(); + +} + +bool Aggregater::isActive(void) +{ + return _isActive; +} + +uint16_t Aggregater::msgId(void) +{ + return Adapter::getSecureClient()->getNextPacketId(); +} + +Client* Aggregater::convertClient(uint16_t msgId, uint16_t* clientMsgId) +{ + return _msgIdTable.getClientMsgId(msgId, clientMsgId); +} + + +uint16_t Aggregater::addMessageIdTable(Client* client, uint16_t msgId) +{ + /* set Non secure client`s nextMsgId. otherwise Id is duplicated.*/ + + MessageIdElement* elm = _msgIdTable.add(this, client, msgId); + if ( elm == nullptr ) + { + return 0; + } + else + { + return elm->_msgId; + } +} + +uint16_t Aggregater::getMsgId(Client* client, uint16_t clientMsgId) +{ + return _msgIdTable.getMsgId(client, clientMsgId); +} + +void Aggregater::removeAggregateTopic(Topic* topic, Client* client) +{ + // ToDo: AggregateGW this method called when the client disconnect and erase it`s Topics. this method call */ +} + +void Aggregater::removeAggregateTopicList(Topics* topics, Client* client) +{ + // ToDo: AggregateGW this method called when the client disconnect and erase it`s Topics. this method call */ +} + +int Aggregater::addAggregateTopic(Topic* topic, Client* client) +{ + // ToDo: AggregateGW */ + return 0; +} + +AggregateTopicElement* Aggregater::createClientList(Topic* topic) +{ + // ToDo: AggregateGW */ + return 0; +} + +bool Aggregater::testMessageIdTable(void) +{ + Client* client = new Client(); + uint16_t msgId = 0; + + printf("msgId=%d\n", addMessageIdTable(client,1)); + printf("msgId=%d\n", addMessageIdTable(client,2)); + printf("msgId=%d\n", addMessageIdTable(client,3)); + printf("msgId=%d\n", addMessageIdTable(client,1)); + printf("msgId=%d\n", addMessageIdTable(client,2)); + printf("msgId=%d\n", addMessageIdTable(client,3)); + printf("msgId=%d\n", addMessageIdTable(client,4)); + printf("msgId=%d\n", addMessageIdTable(client,4)); + printf("msgId=%d\n", addMessageIdTable(client,4)); + + convertClient(1,&msgId); + printf("msgId=%d\n",msgId); + convertClient(2,&msgId); + printf("msgId=%d\n",msgId); + convertClient(5,&msgId); + printf("msgId=%d\n",msgId); + convertClient(4,&msgId); + printf("msgId=%d\n",msgId); + convertClient(3,&msgId); + printf("msgId=%d\n",msgId); + return true; +} + diff --git a/MQTTSNGateway/src/MQTTSNGWAggregater.h b/MQTTSNGateway/src/MQTTSNGWAggregater.h new file mode 100644 index 0000000..9baaa15 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWAggregater.h @@ -0,0 +1,76 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATER_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATER_H_ + +#include "MQTTSNGWAdapter.h" +#include "MQTTSNGWMessageIdTable.h" +#include "MQTTSNGWAggregateTopicTable.h" +namespace MQTTSNGW +{ +class Gateway; +class Adapter; +class Client; +class SensorNetAddress; +class MessageIdTable; +class AggregateTopicTable; +class Topics; + +/*===================================== + Class Aggregater + =====================================*/ +class Aggregater : public Adapter +{ + friend class MessageIdTable; +public: + Aggregater(Gateway* gw); + ~Aggregater(void); + + void initialize(void); + + const char* getClientId(SensorNetAddress* addr); + Client* getClient(SensorNetAddress* addr); + Client* convertClient(uint16_t msgId, uint16_t* clientMsgId); + uint16_t addMessageIdTable(Client* client, uint16_t msgId); + uint16_t getMsgId(Client* client, uint16_t clientMsgId); + + + AggregateTopicElement* createClientList(Topic* topic); + int addAggregateTopic(Topic* topic, Client* client); + void removeAggregateTopic(Topic* topic, Client* client); + void removeAggregateTopicList(Topics* topics, Client* client); + bool isActive(void); + + bool testMessageIdTable(void); + +private: + uint16_t msgId(void); + Gateway* _gateway {nullptr}; + MessageIdTable _msgIdTable; + AggregateTopicTable _topicTable; + + bool _isActive {false}; + bool _isSecure {false}; +}; + + + +} + + + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATER_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp index 36c122c..01f6fb1 100644 --- a/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp @@ -16,6 +16,7 @@ #include "MQTTSNGWBrokerRecvTask.h" #include "MQTTSNGWClient.h" +#include "MQTTSNGWClientList.h" #include using namespace std; @@ -30,7 +31,7 @@ BrokerRecvTask::BrokerRecvTask(Gateway* gateway) { _gateway = gateway; _gateway->attach((Thread*)this); - _light = 0; + _light = nullptr; } BrokerRecvTask::~BrokerRecvTask() @@ -52,9 +53,9 @@ void BrokerRecvTask::initialize(int argc, char** argv) void BrokerRecvTask::run(void) { struct timeval timeout; - MQTTGWPacket* packet = 0; + MQTTGWPacket* packet = nullptr; int rc; - Event* ev = 0; + Event* ev = nullptr; fd_set rset; fd_set wset; @@ -74,9 +75,9 @@ void BrokerRecvTask::run(void) int sockfd = 0; /* Prepare sockets list to read */ - Client* client = _gateway->getClientList()->getClient(); + Client* client = _gateway->getClientList()->getClient(0); - while (client > 0) + while ( client ) { if (client->getNetwork()->isValid()) { @@ -101,7 +102,7 @@ void BrokerRecvTask::run(void) int activity = select(maxSock + 1, &rset, 0, 0, &timeout); if (activity > 0) { - client = _gateway->getClientList()->getClient(); + client = _gateway->getClientList()->getClient(0); while (client > 0) { diff --git a/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp b/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp index cc7798e..b886c9a 100644 --- a/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp @@ -14,6 +14,7 @@ * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ +#include #include "MQTTSNGWBrokerSendTask.h" #include "MQTTSNGWDefines.h" #include "MQTTSNGateway.h" @@ -34,8 +35,8 @@ BrokerSendTask::BrokerSendTask(Gateway* gateway) { _gateway = gateway; _gateway->attach((Thread*)this); - _gwparams = 0; - _light = 0; + _gwparams = nullptr; + _light = nullptr; } BrokerSendTask::~BrokerSendTask() @@ -57,9 +58,10 @@ void BrokerSendTask::initialize(int argc, char** argv) */ void BrokerSendTask::run() { - Event* ev = 0; - MQTTGWPacket* packet = 0; - Client* client = 0; + Event* ev = nullptr; + MQTTGWPacket* packet = nullptr; + Client* client = nullptr; + AdapterManager* adpMgr = _gateway->getAdapterManager(); int rc = 0; while (true) @@ -78,6 +80,9 @@ void BrokerSendTask::run() client = ev->getClient(); packet = ev->getMQTTGWPacket(); + /* Check Client is managed by Adapters */ + client = adpMgr->getClient(*client); + if ( packet->getType() == CONNECT && client->getNetwork()->isValid() ) { client->getNetwork()->close(); @@ -89,12 +94,12 @@ void BrokerSendTask::run() if (client->isSecureNetwork()) { - rc = client->getNetwork()->connect(_gwparams->brokerName, _gwparams->portSecure, _gwparams->rootCApath, - _gwparams->rootCAfile, _gwparams->certKey, _gwparams->privateKey); + rc = client->getNetwork()->connect((const char*)_gwparams->brokerName, (const char*)_gwparams->portSecure, (const char*)_gwparams->rootCApath, + (const char*)_gwparams->rootCAfile, (const char*)_gwparams->certKey, (const char*)_gwparams->privateKey); } else { - rc = client->getNetwork()->connect(_gwparams->brokerName, _gwparams->port); + rc = client->getNetwork()->connect((const char*)_gwparams->brokerName, (const char*)_gwparams->port); } if ( !rc ) diff --git a/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h b/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h index f287536..8244112 100644 --- a/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h +++ b/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h @@ -22,12 +22,15 @@ namespace MQTTSNGW { +class Adapter; + /*===================================== Class BrokerSendTask =====================================*/ class BrokerSendTask : public Thread { MAGIC_WORD_FOR_THREAD; + friend AdapterManager; public: BrokerSendTask(Gateway* gateway); ~BrokerSendTask(); diff --git a/MQTTSNGateway/src/MQTTSNGWClient.cpp b/MQTTSNGateway/src/MQTTSNGWClient.cpp index deda727..f524d0b 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClient.cpp @@ -16,10 +16,9 @@ **************************************************************************************/ #include "MQTTSNGWDefines.h" -#include "MQTTSNGWClient.h" +#include "MQTTSNGWClientList.h" #include "MQTTSNGateway.h" #include "SensorNetwork.h" -#include "Network.h" #include #include #include @@ -28,350 +27,7 @@ using namespace MQTTSNGW; char* currentDateTime(void); -/*===================================== - Class ClientList - =====================================*/ -ClientList::ClientList() -{ - _clientCnt = 0; - _authorize = false; - _firstClient = 0; - _endClient = 0; -} -ClientList::~ClientList() -{ - _mutex.lock(); - Client* cl = _firstClient; - Client* ncl; - - while (cl != 0) - { - ncl = cl->_nextClient; - delete cl; - cl = ncl; - }; - _mutex.unlock(); -} - -/** - * Create ClientList from a client list file. - * @param File name of the client list - * @return true: Reject client connection that is not registered in the client list - * - * File format is: - * Lines bigning with # are comment line. - * ClientId, SensorNetAddress, "unstableLine", "secureConnection" - * in case of UDP, SensorNetAddress format is portNo@IPAddress. - * if the SensorNetwork is not stable, write unstableLine. - * if BrokerConnection is SSL, write secureConnection. - * - * Ex: - * #Client List - * ClientId1,11200@192.168.10.10 - * ClientID2,35000@192.168.50.200,unstableLine - * ClientID3,40000@192.168.200.50,secureConnection - * ClientID4,41000@192.168.200.51,unstableLine,secureConnection - */ -bool ClientList::authorize(const char* fileName) -{ - FILE* fp; - char buf[MAX_CLIENTID_LENGTH + 256]; - size_t pos; - bool secure; - bool stable; - SensorNetAddress netAddr; - MQTTSNString clientId = MQTTSNString_initializer; - - if ((fp = fopen(fileName, "r")) != 0) - { - while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0) - { - if (*buf == '#') - { - continue; - } - string data = string(buf); - while ((pos = data.find_first_of("  \t\n")) != string::npos) - { - data.erase(pos, 1); - } - if (data.empty()) - { - continue; - } - pos = data.find_first_of(","); - string id = data.substr(0, pos); - clientId.cstring = strdup(id.c_str()); - string addr = data.substr(pos + 1); - - if (netAddr.setAddress(&addr) == 0) - { - secure = (data.find("secureConnection") != string::npos); - stable = !(data.find("unstableLine") != string::npos); - createClient(&netAddr, &clientId, stable, secure); - } - else - { - WRITELOG("Invalid address %s\n", data.c_str()); - } - free(clientId.cstring); - } - fclose(fp); - _authorize = true; - } - return _authorize; -} - -bool ClientList::setPredefinedTopics(const char* fileName) -{ - FILE* fp; - char buf[MAX_CLIENTID_LENGTH + 256]; - size_t pos0, pos1; - MQTTSNString clientId = MQTTSNString_initializer;; - bool rc = false; - - if ((fp = fopen(fileName, "r")) != 0) - { - while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0) - { - if (*buf == '#') - { - continue; - } - string data = string(buf); - while ((pos0 = data.find_first_of("  \t\n")) != string::npos) - { - data.erase(pos0, 1); - } - if (data.empty()) - { - continue; - } - - pos0 = data.find_first_of(","); - pos1 = data.find(",", pos0 + 1) ; - string id = data.substr(0, pos0); - clientId.cstring = strdup(id.c_str()); - string topicName = data.substr(pos0 + 1, pos1 - pos0 -1); - uint16_t topicID = stoul(data.substr(pos1 + 1)); - createPredefinedTopic( &clientId, topicName, topicID); - free(clientId.cstring); - } - fclose(fp); - rc = true; - } - else - { - WRITELOG("Can not open the Predefined Topic List. %s\n", fileName); - return false; - } - return rc; -} - -void ClientList::erase(Client*& client) -{ - if ( !_authorize && client->erasable()) - { - _mutex.lock(); - Client* prev = client->_prevClient; - Client* next = client->_nextClient; - - if (prev) - { - prev->_nextClient = next; - } - else - { - _firstClient = next; - - } - if (next) - { - next->_prevClient = prev; - } - else - { - _endClient = prev; - } - _clientCnt--; - Forwarder* fwd = client->getForwarder(); - if ( fwd ) - { - fwd->eraseClient(client); - } - delete client; - client = 0; - _mutex.unlock(); - } -} - -Client* ClientList::getClient(SensorNetAddress* addr) -{ - if ( addr ) - { - _mutex.lock(); - Client* client = _firstClient; - - while (client != 0) - { - if (client->getSensorNetAddress()->isMatch(addr) ) - { - _mutex.unlock(); - return client; - } - client = client->_nextClient; - } - _mutex.unlock(); - } - return 0; -} - -Client* ClientList::getClient(void) -{ - return _firstClient; -} - - -Client* ClientList::getClient(MQTTSNString* clientId) -{ - _mutex.lock(); - Client* client = _firstClient; - const char* clID =clientId->cstring; - - if (clID == 0 ) - { - clID = clientId->lenstring.data; - } - - while (client != 0) - { - if (strncmp((const char*)client->getClientId(), clID, MQTTSNstrlen(*clientId)) == 0 ) - { - _mutex.unlock(); - return client; - } - client = client->_nextClient; - } - _mutex.unlock(); - return 0; -} - -Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure) -{ - Client* client = 0; - - /* clients must be authorized */ - if ( _authorize ) - { - /* search cliene with sensorNetAddress from the list */ - return getClient(addr); - } - - /* anonimous clients */ - if ( _clientCnt > MAX_CLIENTS ) - { - return 0; // full of clients - } - - client = getClient(addr); - if ( client ) - { - return client; - } - - /* creat a new client */ - client = new Client(secure); - if ( addr ) - { - client->setClientAddress(addr); - } - client->setSensorNetType(unstableLine); - if ( MQTTSNstrlen(*clientId) ) - { - client->setClientId(*clientId); - } - else - { - MQTTSNString dummyId MQTTSNString_initializer;; - dummyId.cstring = strdup(""); - client->setClientId(dummyId); - free(dummyId.cstring); - } - - _mutex.lock(); - - /* add the list */ - if ( _firstClient == 0 ) - { - _firstClient = client; - _endClient = client; - } - else - { - _endClient->_nextClient = client; - client->_prevClient = _endClient; - _endClient = client; - } - _clientCnt++; - _mutex.unlock(); - return client; -} - -Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t topicId) -{ - Client* client = getClient(clientId); - - if ( _authorize && client == 0) - { - return 0; - } - - /* anonimous clients */ - if ( _clientCnt > MAX_CLIENTS ) - { - return 0; // full of clients - } - - if ( client == 0 ) - { - /* creat a new client */ - client = new Client(); - client->setClientId(*clientId); - - _mutex.lock(); - - /* add the list */ - if ( _firstClient == 0 ) - { - _firstClient = client; - _endClient = client; - } - else - { - _endClient->_nextClient = client; - client->_prevClient = _endClient; - _endClient = client; - } - _clientCnt++; - _mutex.unlock(); - } - - // create Topic & Add it - client->getTopics()->add((const char*)topicName.c_str(), topicId); - client->_hasPredefTopic = true; - return client; -} - -uint16_t ClientList::getClientCount() -{ - return _clientCnt; -} - -bool ClientList::isAuthorized() -{ - return _authorize; -} /*===================================== Class Client @@ -385,31 +41,24 @@ Client::Client(bool secure) _status = Cstat_Disconnected; _keepAliveMsec = 0; _topics = new Topics(); - _clientId = 0; - _willTopic = 0; - _willMsg = 0; - _connectData.Protocol = 0; - _connectData.clientID = 0; - _connectData.flags.all = 0; - _connectData.header.byte = 0; - _connectData.keepAliveTimer = 0; - _connectData.version = 0; - _connectData.willMsg = 0; - _connectData.willTopic = 0; + _clientId = nullptr; + _willTopic = nullptr; + _willMsg = nullptr; + _connectData = {0, 0, 0, 0, 0, 0, 0}; _network = new Network(secure); _secureNetwork = secure; _sensorNetype = true; - _connAck = 0; + _connAck = nullptr; _waitWillMsgFlg = false; _sessionStatus = false; - _prevClient = 0; - _nextClient = 0; + _prevClient = nullptr; + _nextClient = nullptr; _clientSleepPacketQue.setMaxSize(MAX_SAVED_PUBLISH); _proxyPacketQue.setMaxSize(MAX_SAVED_PUBLISH); _hasPredefTopic = false; _holdPingRequest = false; - _forwarder = 0; - _isProxy = false; + _forwarder = nullptr; + _clientType = Ctype_Regular; } Client::~Client() @@ -445,12 +94,12 @@ Client::~Client() } } -TopicIdMapelement* Client::getWaitedPubTopicId(uint16_t msgId) +TopicIdMapElement* Client::getWaitedPubTopicId(uint16_t msgId) { return _waitedPubTopicIdMap.getElement(msgId); } -TopicIdMapelement* Client::getWaitedSubTopicId(uint16_t msgId) +TopicIdMapElement* Client::getWaitedSubTopicId(uint16_t msgId) { return _waitedSubTopicIdMap.getElement(msgId); } @@ -555,6 +204,7 @@ void Client::setKeepAlive(MQTTSNPacket* packet) void Client::setForwarder(Forwarder* forwarder) { _forwarder = forwarder; + _clientType = Ctype_Forwarded; } Forwarder* Client::getForwarder(void) @@ -569,7 +219,7 @@ void Client::setSessionStatus(bool status) bool Client::erasable(void) { - return _sessionStatus && !_hasPredefTopic && _forwarder == 0; + return _sessionStatus && !_hasPredefTopic && _forwarder == nullptr; } void Client::updateStatus(MQTTSNPacket* packet) @@ -590,7 +240,7 @@ void Client::updateStatus(MQTTSNPacket* packet) case MQTTSN_PUBCOMP: case MQTTSN_PUBREL: case MQTTSN_PUBREC: - if ( !_isProxy ) + if ( _clientType != Ctype_Proxy ) { _keepAliveTimer.start(_keepAliveMsec * 1.5); } @@ -856,14 +506,60 @@ const char* Client::getStatus(void) return theClientStatus[_status]; } -bool Client::isProxy(void) +bool Client::isQoSm1Proxy(void) { - return _isProxy; + return _clientType == Ctype_Proxy; } -void Client::setPorxy(bool isProxy) +bool Client::isForwarded(void) { - _isProxy = isProxy;; + return _clientType == Ctype_Forwarded; +} + +bool Client::isAggregated(void) +{ + return _clientType == Ctype_Aggregated; +} + +bool Client::isAggregater(void) +{ + return _clientType == Ctype_Aggregater; +} + +void Client::setAdapterType(AdapterType type) +{ + switch ( type ) + { + case Atype_QoSm1Proxy: + _clientType = Ctype_Proxy; + break; + case Atype_Aggregater: + _clientType = Ctype_Aggregater; + break; + default: + throw Exception("Client::setAdapterType(): Invalid Type."); + break; + } +} + +bool Client::isAdapter(void) +{ + return _clientType == Ctype_Proxy || _clientType == Ctype_Aggregater; +} + +bool Client::isQoSm1(void) +{ + return _clientType == Ctype_QoS_1; +} + +void Client::setQoSm1(void) +{ + _clientType = Ctype_QoS_1; +} + +void Client::setAggregated(void) +{ + _clientType = Ctype_Aggregated; } void Client::holdPingRequest(void) @@ -881,499 +577,7 @@ bool Client::isHoldPringReqest(void) return _holdPingRequest; } -/*===================================== - Class Topic - ======================================*/ -Topic::Topic() -{ - _type = MQTTSN_TOPIC_TYPE_NORMAL; - _topicName = 0; - _topicId = 0; - _next = 0; -} -Topic::Topic(string* topic, MQTTSN_topicTypes type) -{ - _type = type; - _topicName = topic; - _topicId = 0; - _next = 0; -} - -Topic::~Topic() -{ - if ( _topicName ) - { - delete _topicName; - } -} - -string* Topic::getTopicName(void) -{ - return _topicName; -} - -uint16_t Topic::getTopicId(void) -{ - return _topicId; -} - -MQTTSN_topicTypes Topic::getType(void) -{ - return _type; -} - -bool Topic::isMatch(string* topicName) -{ - string::size_type tlen = _topicName->size(); - - string::size_type tpos = 0; - string::size_type tloc = 0; - string::size_type pos = 0; - string::size_type loc = 0; - string wildcard = "#"; - string wildcards = "+"; - - while(true) - { - loc = topicName->find('/', pos); - tloc = _topicName->find('/', tpos); - - if ( loc != string::npos && tloc != string::npos ) - { - string subtopic = topicName->substr(pos, loc - pos); - string subtopict = _topicName->substr(tpos, tloc - tpos); - if (subtopict == wildcard) - { - return true; - } - else if (subtopict == wildcards) - { - if ( (tpos = tloc + 1 ) > tlen ) - { - pos = loc + 1; - loc = topicName->find('/', pos); - if ( loc == string::npos ) - { - return true; - } - else - { - return false; - } - } - pos = loc + 1; - } - else if ( subtopic != subtopict ) - { - return false; - } - else - { - if ( (tpos = tloc + 1) > tlen ) - { - return false; - } - - pos = loc + 1; - } - } - else if ( loc == string::npos && tloc == string::npos ) - { - string subtopic = topicName->substr(pos); - string subtopict = _topicName->substr(tpos); - if ( subtopict == wildcard || subtopict == wildcards) - { - return true; - } - else if ( subtopic == subtopict ) - { - return true; - } - else - { - return false; - } - } - else if ( loc == string::npos && tloc != string::npos ) - { - string subtopic = topicName->substr(pos); - string subtopict = _topicName->substr(tpos, tloc - tpos); - if ( subtopic != subtopict) - { - return false; - } - - tpos = tloc + 1; - - return _topicName->substr(tpos) == wildcard; - } - else if ( loc != string::npos && tloc == string::npos ) - { - return _topicName->substr(tpos) == wildcard; - } - } -} - -void Topic::print(void) -{ - WRITELOG("TopicName=%s ID=%d Type=%d\n", _topicName->c_str(), _topicId, _type); -} - -/*===================================== - Class Topics - ======================================*/ -Topics::Topics() -{ - _first = 0; - _nextTopicId = 0; - _cnt = 0; -} - -Topics::~Topics() -{ - Topic* p = _first; - while (p) - { - Topic* q = p->_next; - delete p; - p = q; - } -} - -Topic* Topics::getTopicByName(const MQTTSN_topicid* topicid) -{ - Topic* p = _first; - char* ch = topicid->data.long_.name; - - string sname = string(ch, ch + topicid->data.long_.len); - while (p) - { - if ( p->_topicName->compare(sname) == 0 ) - { - return p; - } - p = p->_next; - } - return 0; -} - -Topic* Topics::getTopicById(const MQTTSN_topicid* topicid) -{ - Topic* p = _first; - - while (p) - { - if ( p->_type == topicid->type && p->_topicId == topicid->data.id ) - { - return p; - } - p = p->_next; - } - return 0; -} - -// For MQTTSN_TOPIC_TYPE_NORMAL */ -Topic* Topics::add(const MQTTSN_topicid* topicid) -{ - if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL ) - { - return 0; - } - - Topic* topic = getTopicByName(topicid); - - if ( topic ) - { - return topic; - } - string name(topicid->data.long_.name, topicid->data.long_.len); - return add(name.c_str(), 0); -} - -Topic* Topics::add(const char* topicName, uint16_t id) -{ - MQTTSN_topicid topicId; - - if ( _cnt >= MAX_TOPIC_PAR_CLIENT ) - { - return 0; - } - - topicId.data.long_.name = (char*)const_cast(topicName); - topicId.data.long_.len = strlen(topicName); - - - Topic* topic = getTopicByName(&topicId); - - if ( topic ) - { - return topic; - } - - topic = new Topic(); - - if (topic == 0) - { - return 0; - } - - string* name = new string(topicName); - topic->_topicName = name; - - if ( id == 0 ) - { - topic->_type = MQTTSN_TOPIC_TYPE_NORMAL; - topic->_topicId = getNextTopicId(); - } - else - { - topic->_type = MQTTSN_TOPIC_TYPE_PREDEFINED; - topic->_topicId = id; - } - - _cnt++; - - if ( _first == 0) - { - _first = topic; - } - else - { - Topic* tp = _first; - while (tp) - { - if (tp->_next == 0) - { - tp->_next = topic; - break; - } - else - { - tp = tp->_next; - } - } - } - return topic; -} - -uint16_t Topics::getNextTopicId() -{ - return ++_nextTopicId == 0xffff ? _nextTopicId += 2 : _nextTopicId; -} - -Topic* Topics::match(const MQTTSN_topicid* topicid) -{ - if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL) - { - return 0; - } - string topicName(topicid->data.long_.name, topicid->data.long_.len); - - Topic* topic = _first; - while (topic) - { - if (topic->isMatch(&topicName)) - { - return topic; - } - topic = topic->_next; - } - return 0; -} - - -void Topics::eraseNormal(void) -{ - Topic* topic = _first; - Topic* next = 0; - Topic* prev = 0; - - while (topic) - { - if ( topic->_type == MQTTSN_TOPIC_TYPE_NORMAL ) - { - next = topic->_next; - if ( _first == topic ) - { - _first = next; - } - if ( prev ) - { - prev->_next = next; - } - delete topic; - _cnt--; - topic = next; - } - else - { - prev = topic; - topic = topic->_next; - } - } -} - -void Topics::print(void) -{ - Topic* topic = _first; - if (topic == 0 ) - { - WRITELOG("No Topic.\n"); - } - else - { - while (topic) - { - topic->print(); - topic = topic->_next; - } - } -} - -uint8_t Topics::getCount(void) -{ - return _cnt; -} - -/*===================================== - Class TopicIdMap - =====================================*/ -TopicIdMapelement::TopicIdMapelement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) -{ - _msgId = msgId; - _topicId = topicId; - _type = type; - _next = 0; - _prev = 0; -} - -TopicIdMapelement::~TopicIdMapelement() -{ - -} - -MQTTSN_topicTypes TopicIdMapelement::getTopicType(void) -{ - return _type; -} - -uint16_t TopicIdMapelement::getTopicId(void) -{ - return _topicId; -} - -TopicIdMap::TopicIdMap() -{ - _maxInflight = MAX_INFLIGHTMESSAGES; - _msgIds = 0; - _first = 0; - _end = 0; - _cnt = 0; -} - -TopicIdMap::~TopicIdMap() -{ - TopicIdMapelement* p = _first; - while ( p ) - { - TopicIdMapelement* q = p->_next; - delete p; - p = q; - } -} - -TopicIdMapelement* TopicIdMap::getElement(uint16_t msgId) -{ - TopicIdMapelement* p = _first; - while ( p ) - { - if ( p->_msgId == msgId ) - { - return p; - } - p = p->_next; - } - return 0; -} - -TopicIdMapelement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) -{ - if ( _cnt > _maxInflight * 2 || ( topicId == 0 && type != MQTTSN_TOPIC_TYPE_SHORT ) ) - { - return 0; - } - if ( getElement(msgId) > 0 ) - { - erase(msgId); - } - - TopicIdMapelement* elm = new TopicIdMapelement(msgId, topicId, type); - if ( elm == 0 ) - { - return 0; - } - if ( _first == 0 ) - { - _first = elm; - _end = elm; - } - else - { - elm->_prev = _end; - _end->_next = elm; - _end = elm; - } - _cnt++; - return elm; -} - -void TopicIdMap::erase(uint16_t msgId) -{ - TopicIdMapelement* p = _first; - while ( p ) - { - if ( p->_msgId == msgId ) - { - if ( p->_prev == 0 ) - { - _first = p->_next; - } - else - { - p->_prev->_next = p->_next; - } - - if ( p->_next == 0 ) - { - _end = p->_prev; - } - else - { - p->_next->_prev = p->_prev; - } - delete p; - break; - - } - p = p->_next; - } - _cnt--; -} - -void TopicIdMap::clear(void) -{ - TopicIdMapelement* p = _first; - while ( p ) - { - TopicIdMapelement* q = p->_next; - delete p; - p = q; - } - _first = 0; - _end = 0; - _cnt = 0; -} /*===================================== Class WaitREGACKPacket @@ -1382,8 +586,8 @@ waitREGACKPacket::waitREGACKPacket(MQTTSNPacket* packet, uint16_t REGACKMsgId) { _packet = packet; _msgId = REGACKMsgId; - _next = 0; - _prev = 0; + _next = nullptr; + _prev = nullptr; } waitREGACKPacket::~waitREGACKPacket() @@ -1397,8 +601,8 @@ waitREGACKPacket::~waitREGACKPacket() WaitREGACKPacketList::WaitREGACKPacketList() { - _first = 0; - _end = 0; + _first = nullptr; + _end = nullptr; _cnt = 0; } @@ -1416,12 +620,12 @@ WaitREGACKPacketList::~WaitREGACKPacketList() int WaitREGACKPacketList::setPacket(MQTTSNPacket* packet, uint16_t REGACKMsgId) { waitREGACKPacket* elm = new waitREGACKPacket(packet, REGACKMsgId); - if (elm == 0) + if (elm == nullptr) { return 0; } - if (_first == 0) + if (_first == nullptr) { _first = elm; _end = elm; @@ -1447,7 +651,7 @@ MQTTSNPacket* WaitREGACKPacketList::getPacket(uint16_t REGACKMsgId) } p = p->_next; } - return 0; + return nullptr; } void WaitREGACKPacketList::erase(uint16_t REGACKMsgId) @@ -1457,7 +661,7 @@ void WaitREGACKPacketList::erase(uint16_t REGACKMsgId) { if (p->_msgId == REGACKMsgId) { - if (p->_prev == 0) + if (p->_prev == nullptr) { _first = p->_next; @@ -1466,7 +670,7 @@ void WaitREGACKPacketList::erase(uint16_t REGACKMsgId) { p->_prev->_next = p->_next; } - if (p->_next == 0) + if (p->_next == nullptr) { _end = p->_prev; } diff --git a/MQTTSNGateway/src/MQTTSNGWClient.h b/MQTTSNGateway/src/MQTTSNGWClient.h index c4757e7..5529ed0 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.h +++ b/MQTTSNGateway/src/MQTTSNGWClient.h @@ -28,6 +28,9 @@ #include "MQTTSNPacket.h" #include "MQTTSNGWEncapsulatedPacket.h" #include "MQTTSNGWForwarder.h" +#include "MQTTSNGWTopic.h" +#include "MQTTSNGWClientList.h" +#include "MQTTSNGWAdapter.h" namespace MQTTSNGW { @@ -111,87 +114,6 @@ private: }; -/*===================================== - Class Topic - ======================================*/ -class Topic -{ - friend class Topics; -public: - Topic(); - Topic(string* topic, MQTTSN_topicTypes type); - ~Topic(); - string* getTopicName(void); - uint16_t getTopicId(void); - MQTTSN_topicTypes getType(void); - bool isMatch(string* topicName); - void print(void); -private: - MQTTSN_topicTypes _type; - uint16_t _topicId; - string* _topicName; - Topic* _next; -}; - -/*===================================== - Class Topics - ======================================*/ -class Topics -{ -public: - Topics(); - ~Topics(); - Topic* add(const MQTTSN_topicid* topicid); - Topic* add(const char* topicName, uint16_t id = 0); - Topic* getTopicByName(const MQTTSN_topicid* topic); - Topic* getTopicById(const MQTTSN_topicid* topicid); - Topic* match(const MQTTSN_topicid* topicid); - void eraseNormal(void); - uint16_t getNextTopicId(); - void print(void); - uint8_t getCount(void); -private: - uint16_t _nextTopicId; - Topic* _first; - uint8_t _cnt; -}; - -/*===================================== - Class TopicIdMap - =====================================*/ -class TopicIdMapelement -{ - friend class TopicIdMap; -public: - TopicIdMapelement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); - ~TopicIdMapelement(); - MQTTSN_topicTypes getTopicType(void); - uint16_t getTopicId(void); - -private: - uint16_t _msgId; - uint16_t _topicId; - MQTTSN_topicTypes _type; - TopicIdMapelement* _next; - TopicIdMapelement* _prev; -}; - -class TopicIdMap -{ -public: - TopicIdMap(); - ~TopicIdMap(); - TopicIdMapelement* getElement(uint16_t msgId); - TopicIdMapelement* add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); - void erase(uint16_t msgId); - void clear(void); -private: - uint16_t* _msgIds; - TopicIdMapelement* _first; - TopicIdMapelement* _end; - int _cnt; - int _maxInflight; -}; /*===================================== Class WaitREGACKPacket @@ -229,15 +151,21 @@ private: waitREGACKPacket* _end; }; + + /*===================================== Class Client =====================================*/ - typedef enum { Cstat_Disconnected = 0, Cstat_TryConnecting, Cstat_Connecting, Cstat_Active, Cstat_Asleep, Cstat_Awake, Cstat_Lost } ClientStatus; +typedef enum +{ + Ctype_Regular = 0, Ctype_Forwarded, Ctype_QoS_1, Ctype_Aggregated, Ctype_Proxy, Ctype_Aggregater +}ClientType; + class Forwarder; class Client @@ -249,8 +177,8 @@ public: ~Client(); Connect* getConnectData(void); - TopicIdMapelement* getWaitedPubTopicId(uint16_t msgId); - TopicIdMapelement* getWaitedSubTopicId(uint16_t msgId); + TopicIdMapElement* getWaitedPubTopicId(uint16_t msgId); + TopicIdMapElement* getWaitedSubTopicId(uint16_t msgId); MQTTGWPacket* getClientSleepPacket(void); void deleteFirstClientSleepPacket(void); @@ -292,8 +220,15 @@ public: Forwarder* getForwarder(void); void setForwarder(Forwarder* forwader); - void setPorxy(bool isProxy); - bool isProxy(void); + void setAdapterType(AdapterType type); + void setQoSm1(void); + void setAggregated(void); + bool isQoSm1Proxy(void); + bool isForwarded(void); + bool isAggregated(void); + bool isAggregater(void); + bool isQoSm1(void); + bool isAdapter(void); void setClientId(MQTTSNString id); void setWillTopic(MQTTSNString willTopic); @@ -355,8 +290,7 @@ private: SensorNetAddress _sensorNetAddr; Forwarder* _forwarder; - bool _isProxy; - + ClientType _clientType; bool _sessionStatus; bool _hasPredefTopic; @@ -365,32 +299,6 @@ private: Client* _prevClient; }; -/*===================================== - Class ClientList - =====================================*/ -class ClientList -{ -public: - ClientList(); - ~ClientList(); - bool authorize(const char* fileName); - bool setPredefinedTopics(const char* fileName); - void erase(Client*&); - Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure); - Client* getClient(SensorNetAddress* addr); - Client* getClient(MQTTSNString* clientId); - uint16_t getClientCount(void); - Client* getClient(void); - bool isAuthorized(); -private: - Client* createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t toipcId); - Client* _firstClient; - Client* _endClient; - Mutex _mutex; - uint16_t _clientCnt; - bool _authorize; -}; - } diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.cpp b/MQTTSNGateway/src/MQTTSNGWClientList.cpp new file mode 100644 index 0000000..23bdcdd --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWClientList.cpp @@ -0,0 +1,460 @@ +/************************************************************************************** + * 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 + * Tieto Poland Sp. z o.o. - Gateway improvements + **************************************************************************************/ +#include "MQTTSNGWClientList.h" +#include +#include + +/*===================================== + Class ClientList + =====================================*/ +ClientList::ClientList() +{ + _clientCnt = 0; + _authorize = false; + _firstClient = nullptr; + _endClient = nullptr; +} + +ClientList::~ClientList() +{ + _mutex.lock(); + Client* cl = _firstClient; + Client* ncl; + + while (cl != nullptr) + { + ncl = cl->_nextClient; + delete cl; + cl = ncl; + }; + _mutex.unlock(); +} + +void ClientList::initialize(Gateway* gw, bool aggregate) +{ + if (gw->getGWParams()->clientAuthentication ) + { + int type = TRANSPEARENT_TYPE; + if ( aggregate ) + { + type = AGGREGATER_TYPE; + } + setClientList(gw, type); + _authorize = true; + } +} + +void ClientList::setClientList(Gateway* gw, int type) +{ + char param[MQTTSNGW_PARAM_MAX]; + string fileName; + GatewayParams* params = gw->getGWParams(); + if (gw->getParam("ClientsList", param) == 0) + { + fileName = string(param); + } + else + { + fileName = params->configDir + string(CLIENT_LIST); + } + + if (!createList(fileName.c_str(), type)) + { + throw Exception("ClientList::initialize(): No client list defined by the configuration."); + } + params->clientListName = strdup(fileName.c_str()); +} + +void ClientList::setPredefinedTopics(Gateway* gw, bool aggrecate) +{ + char param[MQTTSNGW_PARAM_MAX]; + + string fileName; + GatewayParams* params = gw->getGWParams(); + + if (gw->getParam("PredefinedTopicList", param) == 0) + { + fileName = string(param); + } + else + { + fileName = params->configDir + string(PREDEFINEDTOPIC_FILE); + } + + if ( readPredefinedList(fileName.c_str(), aggrecate) ) + { + params->predefinedTopicFileName = strdup(fileName.c_str()); + } +} + +/** + * Create ClientList from a client list file. + * @param File name of the client list + * @return true: Reject client connection that is not registered in the client list + * + * File format is: + * Lines bigning with # are comment line. + * ClientId, SensorNetAddress, "unstableLine", "secureConnection" + * in case of UDP, SensorNetAddress format is portNo@IPAddress. + * if the SensorNetwork is not stable, write unstableLine. + * if BrokerConnection is SSL, write secureConnection. + * if the client send PUBLISH QoS-1, QoS-1 is required. + * + * Ex: + * #Client List + * ClientId1,11200@192.168.10.10 + * ClientID2,35000@192.168.50.200,unstableLine + * ClientID3,40000@192.168.200.50,secureConnection + * ClientID4,41000@192.168.200.51,unstableLine,secureConnection + * ClientID5,41000@192.168.200.51,unstableLine,secureConnection,QoS-1 + */ + +bool ClientList::createList(const char* fileName, int type) +{ + FILE* fp; + char buf[MAX_CLIENTID_LENGTH + 256]; + size_t pos; + bool secure; + bool stable; + bool qos_1; + bool rc = true; + SensorNetAddress netAddr; + MQTTSNString clientId = MQTTSNString_initializer; + + if ((fp = fopen(fileName, "r")) != 0) + { + while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0) + { + if (*buf == '#') + { + continue; + } + string data = string(buf); + while ((pos = data.find_first_of("  \t\n")) != string::npos) + { + data.erase(pos, 1); + } + if (data.empty()) + { + continue; + } + pos = data.find_first_of(","); + string id = data.substr(0, pos); + clientId.cstring = strdup(id.c_str()); + string addr = data.substr(pos + 1); + + if (netAddr.setAddress(&addr) == 0) + { + qos_1 = (data.find("QoS-1") != string::npos); + secure = (data.find("secureConnection") != string::npos); + stable = !(data.find("unstableLine") != string::npos); + if ( (qos_1 && type == QOSM1PROXY_TYPE) || (!qos_1 && type == AGGREGATER_TYPE) ) + { + createClient(&netAddr, &clientId, stable, secure, type); + } + else + { + createClient(&netAddr, &clientId, stable, secure, TRANSPEARENT_TYPE); + } + } + else + { + WRITELOG("Invalid address %s\n", data.c_str()); + rc = false; + } + free(clientId.cstring); + } + fclose(fp); + } + return rc; +} + +bool ClientList::readPredefinedList(const char* fileName, bool aggregate) +{ + FILE* fp; + char buf[MAX_CLIENTID_LENGTH + 256]; + size_t pos0, pos1; + MQTTSNString clientId = MQTTSNString_initializer;; + bool rc = false; + + if ((fp = fopen(fileName, "r")) != 0) + { + while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0) + { + if (*buf == '#') + { + continue; + } + string data = string(buf); + while ((pos0 = data.find_first_of("  \t\n")) != string::npos) + { + data.erase(pos0, 1); + } + if (data.empty()) + { + continue; + } + + pos0 = data.find_first_of(","); + pos1 = data.find(",", pos0 + 1) ; + string id = data.substr(0, pos0); + clientId.cstring = strdup(id.c_str()); + string topicName = data.substr(pos0 + 1, pos1 - pos0 -1); + uint16_t topicID = stoul(data.substr(pos1 + 1)); + createPredefinedTopic( &clientId, topicName, topicID, aggregate); + free(clientId.cstring); + } + fclose(fp); + rc = true; + } + else + { + WRITELOG("ClientList can not open the Predefined Topic List. %s\n", fileName); + return false; + } + return rc; +} + +void ClientList::erase(Client*& client) +{ + if ( !_authorize && client->erasable()) + { + _mutex.lock(); + Client* prev = client->_prevClient; + Client* next = client->_nextClient; + + if (prev) + { + prev->_nextClient = next; + } + else + { + _firstClient = next; + + } + if (next) + { + next->_prevClient = prev; + } + else + { + _endClient = prev; + } + _clientCnt--; + Forwarder* fwd = client->getForwarder(); + if ( fwd ) + { + fwd->eraseClient(client); + } + delete client; + client = nullptr; + _mutex.unlock(); + } +} + +Client* ClientList::getClient(SensorNetAddress* addr) +{ + if ( addr ) + { + _mutex.lock(); + Client* client = _firstClient; + + while (client != nullptr) + { + if (client->getSensorNetAddress()->isMatch(addr) ) + { + _mutex.unlock(); + return client; + } + client = client->_nextClient; + } + _mutex.unlock(); + } + return 0; +} + +Client* ClientList::getClient(int index) +{ + Client* client = _firstClient; + int p = 0; + while ( client != nullptr ) + { + if ( p == index ) + { + return client; + } + else + { + client = client->_nextClient; + p++; + } + } + return nullptr; +} + + +Client* ClientList::getClient(MQTTSNString* clientId) +{ + _mutex.lock(); + Client* client = _firstClient; + const char* clID =clientId->cstring; + + if (clID == nullptr ) + { + clID = clientId->lenstring.data; + } + + while (client != nullptr) + { + if (strncmp((const char*)client->getClientId(), clID, MQTTSNstrlen(*clientId)) == 0 ) + { + _mutex.unlock(); + return client; + } + client = client->_nextClient; + } + _mutex.unlock(); + return 0; +} + +Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, int type) +{ + return createClient(addr, clientId, false, false, type); +} + +Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type) +{ + Client* client = nullptr; + + /* anonimous clients */ + if ( _clientCnt > MAX_CLIENTS ) + { + return 0; // full of clients + } + + client = getClient(addr); + if ( client ) + { + return client; + } + + /* creat a new client */ + client = new Client(secure); + if ( addr ) + { + client->setClientAddress(addr); + } + client->setSensorNetType(unstableLine); + if ( MQTTSNstrlen(*clientId) ) + { + client->setClientId(*clientId); + } + else + { + MQTTSNString dummyId MQTTSNString_initializer;; + dummyId.cstring = strdup(""); + client->setClientId(dummyId); + free(dummyId.cstring); + } + + if ( type == AGGREGATER_TYPE ) + { + client->setAggregated(); + } + else if ( type == QOSM1PROXY_TYPE ) + { + client->setQoSm1(); + } + + _mutex.lock(); + + /* add the list */ + if ( _firstClient == nullptr ) + { + _firstClient = client; + _endClient = client; + } + else + { + _endClient->_nextClient = client; + client->_prevClient = _endClient; + _endClient = client; + } + _clientCnt++; + _mutex.unlock(); + return client; +} + +Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t topicId, bool aggregate) +{ + Client* client = getClient(clientId); + + if ( _authorize && client == nullptr) + { + return 0; + } + + /* anonimous clients */ + if ( _clientCnt > MAX_CLIENTS ) + { + return nullptr; // full of clients + } + + if ( client == nullptr ) + { + /* creat a new client */ + client = new Client(); + client->setClientId(*clientId); + if ( aggregate ) + { + client->setAggregated(); + } + _mutex.lock(); + + /* add the list */ + if ( _firstClient == nullptr ) + { + _firstClient = client; + _endClient = client; + } + else + { + _endClient->_nextClient = client; + client->_prevClient = _endClient; + _endClient = client; + } + _clientCnt++; + _mutex.unlock(); + } + + // create Topic & Add it + client->getTopics()->add((const char*)topicName.c_str(), topicId); + client->_hasPredefTopic = true; + return client; +} + +uint16_t ClientList::getClientCount() +{ + return _clientCnt; +} + +bool ClientList::isAuthorized() +{ + return _authorize; +} + + diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.h b/MQTTSNGateway/src/MQTTSNGWClientList.h new file mode 100644 index 0000000..4e0f81e --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWClientList.h @@ -0,0 +1,70 @@ +/************************************************************************************** + * 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 + * Tieto Poland Sp. z o.o. - Gateway improvements + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_ + +#include "MQTTSNGWClient.h" +#include "MQTTSNGateway.h" + +namespace MQTTSNGW +{ +#define TRANSPEARENT_TYPE 0 +#define QOSM1PROXY_TYPE 1 +#define AGGREGATER_TYPE 2 + +class Client; + +/*===================================== + Class ClientList + =====================================*/ +class ClientList +{ +public: + ClientList(); + ~ClientList(); + + void initialize(Gateway* gw, bool aggregate); + void setClientList(Gateway* gw, int type); + void setPredefinedTopics(Gateway* gw, bool aggregate); + void erase(Client*&); + Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId,int type); + Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type); + bool createList(const char* fileName, int type); + Client* getClient(SensorNetAddress* addr); + Client* getClient(MQTTSNString* clientId); + Client* getClient(int index); + uint16_t getClientCount(void); + Client* getClient(void); + bool isAuthorized(); + +private: + bool readPredefinedList(const char* fileName, bool _aggregate); + Client* createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t toipcId, bool _aggregate); + Client* _firstClient; + Client* _endClient; + Mutex _mutex; + uint16_t _clientCnt; + bool _authorize {false}; +}; + + +} + + + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp index d5397b4..b1e805a 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp @@ -15,12 +15,12 @@ **************************************************************************************/ #include "MQTTSNGWClientRecvTask.h" -#include "MQTTSNGateway.h" #include "MQTTSNPacket.h" +#include "MQTTSNGWQoSm1Proxy.h" #include "MQTTSNGWEncapsulatedPacket.h" #include -#include "MQTTSNGWForwarder.h" +//#include "MQTTSNGWForwarder.h" using namespace MQTTSNGW; char* currentDateTime(void); @@ -57,14 +57,18 @@ void ClientRecvTask::initialize(int argc, char** argv) */ void ClientRecvTask::run() { - Event* ev = 0; - Client* client = 0; - char buf[128]; + Event* ev = nullptr; + Client* client = nullptr; + AdapterManager* adpMgr = _gateway->getAdapterManager(); + bool isAggrActive = adpMgr->isAggregaterActive(); + ClientList* clientList = _gateway->getClientList(); + EventQue* packetEventQue = _gateway->getPacketEventQue(); + char buf[128]; while (true) { - Forwarder* fwd = 0; + Forwarder* fwd = nullptr; WirelessNodeId nodeId; MQTTSNPacket* packet = new MQTTSNPacket(); @@ -95,73 +99,11 @@ void ClientRecvTask::run() log(0, packet, 0); ev = new Event(); ev->setBrodcastEvent(packet); - _gateway->getPacketEventQue()->post(ev); + packetEventQue->post(ev); continue; } - - if ( packet->getType() == MQTTSN_ENCAPSULATED ) - { - fwd = _gateway->getForwarderList()->getForwarder(_sensorNetwork->getSenderAddress()); - - if ( fwd == 0 ) - { - log(0, packet, 0); - WRITELOG("%s Forwarder %s is not authenticated.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); - delete packet; - continue; - } - else - { - MQTTSNString fwdName = MQTTSNString_initializer; - fwdName.cstring = const_cast( fwd->getName() ); - log(0, packet, &fwdName); - - /* get the packet from the encapsulation message */ - MQTTSNGWEncapsulatedPacket encap; - encap.desirialize(packet->getPacketData(), packet->getPacketLength()); - nodeId.setId( encap.getWirelessNodeId() ); - client = fwd->getClient(&nodeId); - delete packet; - packet = encap.getMQTTSNPacket(); - } - } - else - { - client = 0; - - /* when QoSm1Proxy is available, select QoS-1 PUBLISH message */ - QoSm1Proxy* pxy = _gateway->getQoSm1Proxy(); - if ( pxy ) - { - /* get ClientId not Client which can send QoS-1 PUBLISH */ - const char* clientName = pxy->getClientId(_sensorNetwork->getSenderAddress()); - - if ( clientName ) - { - if ( packet->isQoSMinusPUBLISH() ) - { - /* QoS1Proxy takes responsibility of the client */ - client = _gateway->getQoSm1Proxy()->getClient(); - } - else - { - client = _gateway->getQoSm1Proxy()->getClient(); - log(clientName, packet); - WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); - delete packet; - continue; - } - } - } - - if ( client == 0 ) - { - /* get client from the ClientList of Gateway by sensorNetAddress. */ - client = _gateway->getClientList()->getClient(_sensorNetwork->getSenderAddress()); - } - } - + client = adpMgr->getClient(packet, this); if ( client ) { @@ -169,7 +111,7 @@ void ClientRecvTask::run() log(client, packet, 0); ev = new Event(); ev->setClientRecvEvent(client,packet); - _gateway->getPacketEventQue()->post(ev); + packetEventQue->post(ev); } else { @@ -186,14 +128,14 @@ void ClientRecvTask::run() continue; } - client = _gateway->getClientList()->getClient(&data.clientID); + client = clientList->getClient(&data.clientID); if ( fwd ) { - if ( client == 0 ) + if ( client == nullptr ) { /* create a new client */ - client = _gateway->getClientList()->createClient(0, &data.clientID, false, false); + client = clientList->createClient(0, &data.clientID, isAggrActive); } /* Add to af forwarded client list of forwarder. */ fwd->addClient(client, &nodeId); @@ -208,7 +150,7 @@ void ClientRecvTask::run() else { /* create a new client */ - client = _gateway->getClientList()->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, false, false); + client = clientList->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, isAggrActive); } } @@ -224,7 +166,7 @@ void ClientRecvTask::run() /* post Client RecvEvent */ ev = new Event(); ev->setClientRecvEvent(client, packet); - _gateway->getPacketEventQue()->post(ev); + packetEventQue->post(ev); } else { diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h index b681a24..30a63e9 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h @@ -21,6 +21,7 @@ namespace MQTTSNGW { +class AdapterManager; /*===================================== Class ClientRecvTask @@ -28,15 +29,17 @@ namespace MQTTSNGW class ClientRecvTask:public Thread { MAGIC_WORD_FOR_THREAD; + friend AdapterManager; public: ClientRecvTask(Gateway*); - ~ClientRecvTask(); + ~ClientRecvTask(void); virtual void initialize(int argc, char** argv); - void run(); + void run(void); private: void log(Client*, MQTTSNPacket*, MQTTSNString* id); void log(const char* clientId, MQTTSNPacket* packet); + Gateway* _gateway; SensorNetwork* _sensorNetwork; }; diff --git a/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp index 54107a5..788d024 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp @@ -15,9 +15,9 @@ **************************************************************************************/ #include "MQTTSNGWClientSendTask.h" #include "MQTTSNGWPacket.h" -#include "MQTTSNGWPacket.h" #include "MQTTSNGateway.h" #include "MQTTSNGWEncapsulatedPacket.h" +#include "MQTTSNGWQoSm1Proxy.h" using namespace MQTTSNGW; using namespace std; @@ -39,8 +39,9 @@ ClientSendTask::~ClientSendTask() void ClientSendTask::run() { - Client* client = 0; - MQTTSNPacket* packet = 0; + Client* client = nullptr; + MQTTSNPacket* packet = nullptr; + AdapterManager* adpMgr = _gateway->getAdapterManager(); int rc = 0; while (true) @@ -57,27 +58,7 @@ void ClientSendTask::run() { client = ev->getClient(); packet = ev->getMQTTSNPacket(); - Forwarder* fwd = client->getForwarder(); - - if ( fwd ) - { - MQTTSNGWEncapsulatedPacket encap(packet); - WirelessNodeId* wnId = fwd->getWirelessNodeId(client); - encap.setWirelessNodeId(wnId); - log(fwd, &encap); - log(client, packet); - rc = encap.unicast(_sensorNetwork,fwd->getSensorNetAddr()); - } - else - { - log(client, packet); - if ( client->isProxy() ) - { - _gateway->getQoSm1Proxy()->send(packet); - continue; - } - rc = packet->unicast(_sensorNetwork, client->getSensorNetAddress()); - } + rc = adpMgr->unicastToClient(client, packet, this); } else if (ev->getEventType() == EtBroadcast) { @@ -140,9 +121,3 @@ void ClientSendTask::log(Client* client, MQTTSNPacket* packet) } } -void ClientSendTask::log(Forwarder* forwarder, MQTTSNGWEncapsulatedPacket* packet) -{ - char pbuf[SIZE_OF_LOG_PACKET * 3]; - const char* forwarderId = forwarder->getId(); - WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, forwarderId, packet->print(pbuf)); -} diff --git a/MQTTSNGateway/src/MQTTSNGWClientSendTask.h b/MQTTSNGateway/src/MQTTSNGWClientSendTask.h index b6cff2f..3eaf84f 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientSendTask.h +++ b/MQTTSNGateway/src/MQTTSNGWClientSendTask.h @@ -21,6 +21,7 @@ namespace MQTTSNGW { +class AdapterManager; /*===================================== Class ClientSendTask @@ -28,14 +29,14 @@ namespace MQTTSNGW class ClientSendTask: public Thread { MAGIC_WORD_FOR_THREAD; + friend AdapterManager; public: ClientSendTask(Gateway* gateway); - ~ClientSendTask(); - void run(); + ~ClientSendTask(void); + void run(void); private: - void log(Client*, MQTTSNPacket*); - void log(Forwarder*, MQTTSNGWEncapsulatedPacket*); + void log(Client* client, MQTTSNPacket* packet); Gateway* _gateway; SensorNetwork* _sensorNetwork; diff --git a/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp b/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp index 43aea61..33b3ef8 100644 --- a/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp @@ -90,7 +90,7 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet //* clear ConnectData of Client */ Connect* connectData = client->getConnectData(); memset(connectData, 0, sizeof(Connect)); - if ( !client->isProxy() ) + if ( !client->isAdapter() ) { client->disconnected(); } @@ -104,7 +104,7 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet connectData->keepAliveTimer = data.duration; connectData->flags.bits.will = data.willFlag; - if ((const char*) _gateway->getGWParams()->loginId != 0 && (const char*) _gateway->getGWParams()->password != 0) + if ((const char*) _gateway->getGWParams()->loginId != nullptr && (const char*) _gateway->getGWParams()->password != 0) { connectData->flags.bits.password = 1; connectData->flags.bits.username = 1; @@ -291,9 +291,9 @@ void MQTTSNConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet void MQTTSNConnectionHandler::sendStoredPublish(Client* client) { - MQTTGWPacket* msg = 0; + MQTTGWPacket* msg = nullptr; - while ( ( msg = client->getClientSleepPacket() ) != 0 ) + while ( ( msg = client->getClientSleepPacket() ) != nullptr ) { // ToDo: This version can't re-send PUBLISH when PUBACK is not returned. client->deleteFirstClientSleepPacket(); // pop the que to delete element. diff --git a/MQTTSNGateway/src/MQTTSNGWDefines.h b/MQTTSNGateway/src/MQTTSNGWDefines.h index c15ae45..0cc22b6 100644 --- a/MQTTSNGateway/src/MQTTSNGWDefines.h +++ b/MQTTSNGateway/src/MQTTSNGWDefines.h @@ -27,7 +27,6 @@ namespace MQTTSNGW #define CLIENT_LIST "clients.conf" #define PREDEFINEDTOPIC_FILE "predefinedTopic.conf" #define FORWARDER_LIST "forwarders.conf" -#define QOS_1CLIENT_LIST "qos-1clients.conf" /*========================================================== * Gateway default parameters @@ -41,6 +40,7 @@ namespace MQTTSNGW #define MAX_CLIENTS (100) // Number of Clients can be handled. #define MAX_CLIENTID_LENGTH (64) // Max length of clientID #define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages +#define MAX_MESSAGEID_TABLE_SIZE (500) // Number of MessageIdTable size #define MAX_SAVED_PUBLISH (20) // Max number of PUBLISH message for Asleep state #define MAX_TOPIC_PAR_CLIENT (50) // Max Topic count for a client. it should be less than 256 #define MQTTSNGW_MAX_PACKET_SIZE (1024) // Max Packet size (5+2+TopicLen+PayloadLen + Foward Encapsulation) diff --git a/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.cpp b/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.cpp index 1c06d13..750867f 100644 --- a/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.cpp +++ b/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.cpp @@ -52,7 +52,7 @@ void WirelessNodeId::setId(uint8_t* id, uint8_t len) } else { - _nodeId = 0; + _nodeId = nullptr; _len = 0; } } @@ -123,7 +123,7 @@ int MQTTSNGWEncapsulatedPacket::desirialize(unsigned char* buf, unsigned short l if ( _mqttsn ) { delete _mqttsn; - _mqttsn = 0; + _mqttsn = nullptr; } _ctrl = buf[2]; diff --git a/MQTTSNGateway/src/MQTTSNGWForwarder.cpp b/MQTTSNGateway/src/MQTTSNGWForwarder.cpp index ad1e94b..20a05e9 100644 --- a/MQTTSNGateway/src/MQTTSNGWForwarder.cpp +++ b/MQTTSNGateway/src/MQTTSNGWForwarder.cpp @@ -20,13 +20,13 @@ using namespace MQTTSNGW; using namespace std; -/* - * Class ForwarderList - */ +/*===================================== + Class ForwarderList + =====================================*/ ForwarderList::ForwarderList() { - _head = 0; + _head = nullptr; } ForwarderList::~ForwarderList() @@ -43,6 +43,35 @@ ForwarderList::~ForwarderList() } } + +void ForwarderList::initialize(Gateway* gw) +{ + char param[MQTTSNGW_PARAM_MAX]; + string fileName; + GatewayParams* params = gw->getGWParams(); + + if (gw->getParam("Forwarder", param) == 0 ) + { + if (!strcasecmp(param, "YES") ) + { + if (gw->getParam("ForwardersList", param) == 0) + { + fileName = string(param); + } + else + { + fileName = params->configDir + string(FORWARDER_LIST); + } + if ( !setFowerder(fileName.c_str()) ) + { + throw Exception("ForwarderList::initialize: No ForwardersList file defined by the configuration.."); + } + params->forwarderListName = strdup(fileName.c_str()); + } + } +} + + Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr) { Forwarder* p = _head; @@ -111,7 +140,7 @@ bool ForwarderList::setFowerder(const char* fileName) Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, string* forwarderId) { Forwarder* fdr = new Forwarder(addr, forwarderId); - if ( _head == 0 ) + if ( _head == nullptr ) { _head = fdr; } @@ -120,7 +149,7 @@ Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, string* forwarde Forwarder* p = _head; while ( p ) { - if ( p->_next == 0 ) + if ( p->_next == nullptr ) { p->_next = fdr; break; @@ -136,20 +165,20 @@ Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, string* forwarde Forwarder::Forwarder() { - _headClient = 0; - _next = 0; + _headClient = nullptr; + _next = nullptr; } -/* - * Class Forwarder - */ +/*===================================== + Class ForwarderList + =====================================*/ Forwarder::Forwarder(SensorNetAddress* addr, string* forwarderId) { _forwarderName = *forwarderId; _sensorNetAddr = *addr; - _headClient = 0; - _next = 0; + _headClient = nullptr; + _next = nullptr; } Forwarder::~Forwarder(void) @@ -174,11 +203,11 @@ const char* Forwarder::getId(void) void Forwarder::addClient(Client* client, WirelessNodeId* id) { ForwarderElement* p = _headClient; - ForwarderElement* prev = 0; + ForwarderElement* prev = nullptr; client->setForwarder(this); - if ( p != 0 ) + if ( p != nullptr ) { while ( p ) { @@ -209,7 +238,7 @@ void Forwarder::addClient(Client* client, WirelessNodeId* id) Client* Forwarder::getClient(WirelessNodeId* id) { - Client* cl = 0; + Client* cl = nullptr; _mutex.lock(); ForwarderElement* p = _headClient; while ( p ) @@ -235,7 +264,7 @@ const char* Forwarder::getName(void) WirelessNodeId* Forwarder::getWirelessNodeId(Client* client) { - WirelessNodeId* nodeId = 0; + WirelessNodeId* nodeId = nullptr; _mutex.lock(); ForwarderElement* p = _headClient; while ( p ) @@ -256,7 +285,7 @@ WirelessNodeId* Forwarder::getWirelessNodeId(Client* client) void Forwarder::eraseClient(Client* client) { - ForwarderElement* prev = 0; + ForwarderElement* prev = nullptr; _mutex.lock(); ForwarderElement* p = _headClient; @@ -314,7 +343,7 @@ void ForwarderElement::setClient(Client* client) void ForwarderElement::setWirelessNodeId(WirelessNodeId* id) { - if ( _wirelessNodeId == 0 ) + if ( _wirelessNodeId == nullptr ) { _wirelessNodeId = new WirelessNodeId(); } diff --git a/MQTTSNGateway/src/MQTTSNGWForwarder.h b/MQTTSNGateway/src/MQTTSNGWForwarder.h index 2c58e66..354067f 100644 --- a/MQTTSNGateway/src/MQTTSNGWForwarder.h +++ b/MQTTSNGateway/src/MQTTSNGWForwarder.h @@ -18,22 +18,27 @@ #define MQTTSNGATEWAY_SRC_MQTTSNGWFORWARDER_H_ #include "MQTTSNGWClient.h" +#include "MQTTSNGateway.h" #include "MQTTSNGWEncapsulatedPacket.h" #include "SensorNetwork.h" namespace MQTTSNGW { - +class Gateway; class Client; class WirelessNodeId; +/*===================================== + Class ForwarderElement + =====================================*/ class ForwarderElement { friend class Forwarder; public: ForwarderElement(); ~ForwarderElement(); + void setClient(Client* client); void setWirelessNodeId(WirelessNodeId* id); private: @@ -42,15 +47,18 @@ private: ForwarderElement* _next; }; - +/*===================================== + Class Forwarder + =====================================*/ class Forwarder { friend class ForwarderList; public: - Forwarder(); + Forwarder(void); Forwarder(SensorNetAddress* addr, string* forwarderId); ~Forwarder(); + void initialize(void); const char* getId(void); void addClient(Client* client, WirelessNodeId* id); Client* getClient(WirelessNodeId* id); @@ -62,17 +70,21 @@ public: private: string _forwarderName; SensorNetAddress _sensorNetAddr; - ForwarderElement* _headClient; - Forwarder* _next; + ForwarderElement* _headClient{nullptr}; + Forwarder* _next {nullptr}; Mutex _mutex; }; +/*===================================== + Class ForwarderList + =====================================*/ class ForwarderList { public: ForwarderList(); ~ForwarderList(); + void initialize(Gateway* gw); Forwarder* getForwarder(SensorNetAddress* addr); bool setFowerder(const char* fileName); Forwarder* addForwarder(SensorNetAddress* addr, string* forwarderId); diff --git a/MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp b/MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp new file mode 100644 index 0000000..b87e06c --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp @@ -0,0 +1,218 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 "MQTTSNGWMessageIdTable.h" +#include "MQTTSNGWClient.h" + +using namespace MQTTSNGW; + +/*=============================== + * Class MessageIdTable + ===============================*/ +MessageIdTable::MessageIdTable() +{ + +} + +MessageIdTable::~MessageIdTable() +{ + _mutex.lock(); + if ( _head != nullptr ) + { + MessageIdElement* p = _tail; + while ( p ) + { + MessageIdElement* pPrev = p; + delete p; + _cnt--; + p = pPrev->_prev; + } + _head = _tail = nullptr; + } + _mutex.unlock(); +} + +MessageIdElement* MessageIdTable::add(Aggregater* aggregater, Client* client, uint16_t clientMsgId) +{ + if ( _cnt > _maxSize ) + { + return nullptr; + } + + MessageIdElement* elm = new MessageIdElement(0, client, clientMsgId); + if ( elm == nullptr ) + { + return nullptr; + } + _mutex.lock(); + if ( _head == nullptr ) + { + elm->_msgId = aggregater->msgId(); + _head = elm; + _tail = elm; + _cnt++; + } + else + { + MessageIdElement* p = find(client, clientMsgId); + if ( p == nullptr ) + { + elm->_msgId = aggregater->msgId(); + p = _tail; + _tail = elm; + elm->_prev = p; + p->_next = elm; + _cnt++; + } + else + { + delete elm; + elm = nullptr; + } + } + _mutex.unlock(); + return elm; +} + +MessageIdElement* MessageIdTable::find(uint16_t msgId) +{ + MessageIdElement* p = _head; + while ( p ) + { + if ( p->_msgId == msgId) + { + break; + } + p = p->_next; + } + return p; +} + +MessageIdElement* MessageIdTable::find(Client* client, uint16_t clientMsgId) +{ + MessageIdElement* p = _head; + while ( p ) + { + if ( p->_clientMsgId == clientMsgId && p->_client == client) + { + break; + } + p = p->_next; + } + return p; +} + + +Client* MessageIdTable::getClientMsgId(uint16_t msgId, uint16_t* clientMsgId) +{ + Client* clt = nullptr; + *clientMsgId = 0; + _mutex.lock(); + MessageIdElement* p = find(msgId); + if ( p != nullptr ) + { + clt = p->_client; + *clientMsgId = p->_clientMsgId; + clear(p); + } + _mutex.unlock(); + return clt; +} + +void MessageIdTable::erase(uint16_t msgId) +{ + _mutex.lock(); + MessageIdElement* p = find(msgId); + clear(p); + _mutex.unlock(); +} + +void MessageIdTable::clear(MessageIdElement* elm) +{ + if ( elm == nullptr ) + { + return; + } + + if ( elm->_prev == nullptr ) + { + _head = elm->_next; + if ( _head == nullptr) + { + _tail = nullptr; + } + else + { + _head->_prev = nullptr; + } + delete elm; + _cnt--; + return; + } + else + { + elm->_prev->_next = elm->_next; + if ( elm->_next == nullptr ) + { + _tail = elm->_prev; + } + else + { + elm->_next->_prev = elm->_prev; + } + delete elm; + _cnt--; + return; + } +} + + +uint16_t MessageIdTable::getMsgId(Client* client, uint16_t clientMsgId) +{ + uint16_t msgId = 0; + MessageIdElement* p = find(client, clientMsgId); + if ( p != nullptr ) + { + msgId = p->_msgId; + } + return msgId; +} + +/*=============================== + * Class MessageIdElement + ===============================*/ +MessageIdElement::MessageIdElement(void) + : _msgId{0} + , _clientMsgId {0} + , _client {nullptr} + , _next {nullptr} + , _prev {nullptr} +{ + +} + +MessageIdElement::MessageIdElement(uint16_t msgId, Client* client, uint16_t clientMsgId) + : MessageIdElement() +{ + _msgId = msgId; + _client = client; + _clientMsgId = clientMsgId; +} + +MessageIdElement::~MessageIdElement(void) +{ + +} diff --git a/MQTTSNGateway/src/MQTTSNGWMessageIdTable.h b/MQTTSNGateway/src/MQTTSNGWMessageIdTable.h new file mode 100644 index 0000000..59f7be6 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWMessageIdTable.h @@ -0,0 +1,78 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWMESSAGEIDTABLE_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWMESSAGEIDTABLE_H_ + +#include "MQTTSNGWDefines.h" +#include "MQTTSNGWProcess.h" + +#include +namespace MQTTSNGW +{ + +class Client; +class MessageIdElement; +class Meutex; +class Aggregater; +/*===================================== + Class MessageIdTable + ======================================*/ +class MessageIdTable +{ +public: + MessageIdTable(); + ~MessageIdTable(); + + MessageIdElement* add(Aggregater* aggregater, Client* client, uint16_t clientMsgId); + Client* getClientMsgId(uint16_t msgId, uint16_t* clientMsgId); + uint16_t getMsgId(Client* client, uint16_t clientMsgId); + void erase(uint16_t msgId); + void clear(MessageIdElement* elm); +private: + MessageIdElement* find(uint16_t msgId); + MessageIdElement* find(Client* client, uint16_t clientMsgId); + MessageIdElement* _head {nullptr}; + MessageIdElement* _tail {nullptr}; + int _cnt {0}; + int _maxSize {MAX_MESSAGEID_TABLE_SIZE}; + Mutex _mutex; +}; + +/*===================================== + Class MessageIdElement + =====================================*/ +class MessageIdElement +{ + friend class MessageIdTable; + friend class Aggregater; +public: + MessageIdElement(void); + MessageIdElement(uint16_t msgId, Client* client, uint16_t clientMsgId); + ~MessageIdElement(void); + +private: + uint16_t _msgId; + uint16_t _clientMsgId; + Client* _client; + MessageIdElement* _next; + MessageIdElement* _prev; +}; + + +} + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWMESSAGEIDTABLE_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWPacket.cpp b/MQTTSNGateway/src/MQTTSNGWPacket.cpp index 222597f..998eaf1 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacket.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPacket.cpp @@ -24,12 +24,30 @@ using namespace std; using namespace MQTTSNGW; +int readInt(char** pptr); +void writeInt(unsigned char** pptr, int msgId); -MQTTSNPacket::MQTTSNPacket() +MQTTSNPacket::MQTTSNPacket(void) { - _buf = 0; + _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) @@ -154,6 +172,11 @@ int MQTTSNPacket::setConnect(void) 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]; @@ -455,5 +478,110 @@ char* MQTTSNPacket::getMsgId(char* pbuf) 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 ); +} diff --git a/MQTTSNGateway/src/MQTTSNGWPacket.h b/MQTTSNGateway/src/MQTTSNGWPacket.h index 22e3bd7..7a624a3 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacket.h +++ b/MQTTSNGateway/src/MQTTSNGWPacket.h @@ -26,8 +26,9 @@ namespace MQTTSNGW class MQTTSNPacket { public: - MQTTSNPacket(); - ~MQTTSNPacket(); + MQTTSNPacket(void); + MQTTSNPacket(MQTTSNPacket &packet); + ~MQTTSNPacket(void); int unicast(SensorNetwork* network, SensorNetAddress* sendTo); int broadcast(SensorNetwork* network); int recv(SensorNetwork* network); @@ -80,8 +81,12 @@ public: int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic); int getWILLMSGUPD(MQTTSNString* willMsg); + bool isAccepted(void); + bool isDuplicate(void); bool isQoSMinusPUBLISH(void); char* getMsgId(char* buf); + int getMsgId(void); + void setMsgId(uint16_t msgId); char* print(char* buf); private: diff --git a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp index 53ad17a..47f1eae 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp @@ -21,12 +21,16 @@ #include "MQTTGWPacket.h" #include "MQTTSNGWClient.h" #include "MQTTSNGWProcess.h" +#include "MQTTSNGWAdapterManager.h" #include "MQTTGWConnectionHandler.h" #include "MQTTGWPublishHandler.h" #include "MQTTGWSubscribeHandler.h" #include "MQTTSNGWConnectionHandler.h" #include "MQTTSNGWPublishHandler.h" #include "MQTTSNGWSubscribeHandler.h" +#include "Timer.h" +#include "MQTTSNAggregateConnectionHandler.h" + #include using namespace std; @@ -48,6 +52,8 @@ PacketHandleTask::PacketHandleTask(Gateway* gateway) _mqttsnConnection = new MQTTSNConnectionHandler(_gateway); _mqttsnPublish = new MQTTSNPublishHandler(_gateway); _mqttsnSubscribe = new MQTTSNSubscribeHandler(_gateway); + + _mqttsnAggrConnection = new MQTTSNAggregateConnectionHandler(_gateway); } /** @@ -79,15 +85,22 @@ PacketHandleTask::~PacketHandleTask() { delete _mqttsnSubscribe; } + + if ( _mqttsnAggrConnection ) + { + delete _mqttsnAggrConnection; + } } void PacketHandleTask::run() { - Event* ev = 0; + Event* ev = nullptr; EventQue* eventQue = _gateway->getPacketEventQue(); - Client* client = 0; - MQTTSNPacket* snPacket = 0; - MQTTGWPacket* brPacket = 0; + AdapterManager* adpMgr = _gateway->getAdapterManager(); + + Client* client = nullptr; + MQTTSNPacket* snPacket = nullptr; + MQTTGWPacket* brPacket = nullptr; char msgId[6]; memset(msgId, 0, 6); @@ -114,12 +127,8 @@ void PacketHandleTask::run() _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); } - /*------ Check QoS-1 Proxy Connect or PINGREQ ------*/ - QoSm1Proxy* pxy = _gateway->getQoSm1Proxy(); - if ( pxy ) - { - pxy->checkConnection(); - } + /*------ Check Adapters Connect or PINGREQ ------*/ + adpMgr->checkConnection(); } /*------ Handle SEARCHGW Message ---------*/ @@ -137,101 +146,221 @@ void PacketHandleTask::run() DEBUGLOG(" PacketHandleTask gets %s %s from the client.\n", snPacket->getName(), snPacket->getMsgId(msgId)); - switch (snPacket->getType()) + if ( adpMgr->isAggregatedClient(client) ) { - case MQTTSN_CONNECT: - _mqttsnConnection->handleConnect(client, snPacket); - break; - case MQTTSN_WILLTOPIC: - _mqttsnConnection->handleWilltopic(client, snPacket); - break; - case MQTTSN_WILLMSG: - _mqttsnConnection->handleWillmsg(client, snPacket); - break; - case MQTTSN_DISCONNECT: - _mqttsnConnection->handleDisconnect(client, snPacket); - break; - case MQTTSN_WILLMSGUPD: - _mqttsnConnection->handleWillmsgupd(client, snPacket); - break; - case MQTTSN_PINGREQ: - _mqttsnConnection->handlePingreq(client, snPacket); - break; - case MQTTSN_PUBLISH: - _mqttsnPublish->handlePublish(client, snPacket); - break; - case MQTTSN_PUBACK: - _mqttsnPublish->handlePuback(client, snPacket); - break; - case MQTTSN_PUBREC: - _mqttsnPublish->handleAck(client, snPacket, PUBREC); - break; - case MQTTSN_PUBREL: - _mqttsnPublish->handleAck(client, snPacket, PUBREL); - break; - case MQTTSN_PUBCOMP: - _mqttsnPublish->handleAck(client, snPacket, PUBCOMP); - break; - case MQTTSN_REGISTER: - _mqttsnPublish->handleRegister(client, snPacket); - break; - case MQTTSN_REGACK: - _mqttsnPublish->handleRegAck(client, snPacket); - break; - case MQTTSN_SUBSCRIBE: - _mqttsnSubscribe->handleSubscribe(client, snPacket); - break; - case MQTTSN_UNSUBSCRIBE: - _mqttsnSubscribe->handleUnsubscribe(client, snPacket); - break; - default: - break; + aggregatePacketHandler(client, snPacket); } + else + { + transparentPacketHandler(client, snPacket); + } + /* Reset the Timer for PINGREQ. */ client->updateStatus(snPacket); } - /*------ Handle Messages form Broker ---------*/ - else if (ev->getEventType() == EtBrokerRecv) + else if ( ev->getEventType() == EtBrokerRecv ) { client = ev->getClient(); brPacket = ev->getMQTTGWPacket(); DEBUGLOG(" PacketHandleTask gets %s %s from the broker.\n", brPacket->getName(), brPacket->getMsgId(msgId)); - switch (brPacket->getType()) + + + if ( client->isAggregater() ) { - case CONNACK: - _mqttConnection->handleConnack(client, brPacket); - break; - case PINGRESP: - _mqttConnection->handlePingresp(client, brPacket); - break; - case PUBLISH: - _mqttPublish->handlePublish(client, brPacket); - break; - case PUBACK: - _mqttPublish->handlePuback(client, brPacket); - break; - case PUBREC: - _mqttPublish->handleAck(client, brPacket, PUBREC); - break; - case PUBREL: - _mqttPublish->handleAck(client, brPacket, PUBREL); - break; - case PUBCOMP: - _mqttPublish->handleAck(client, brPacket, PUBCOMP); - break; - case SUBACK: - _mqttSubscribe->handleSuback(client, brPacket); - break; - case UNSUBACK: - _mqttSubscribe->handleUnsuback(client, brPacket); - break; - default: - break; + aggregatePacketHandler(client, brPacket); + } + else + { + transparentPacketHandler(client, brPacket); } } delete ev; } } + + +void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTSNPacket* packet) +{ + switch (packet->getType()) + { + case MQTTSN_CONNECT: + _mqttsnAggrConnection->handleConnect(client, packet); + break; + case MQTTSN_WILLTOPIC: + _mqttsnConnection->handleWilltopic(client, packet); + break; + case MQTTSN_WILLMSG: + _mqttsnAggrConnection->handleWillmsg(client, packet); + break; + case MQTTSN_DISCONNECT: + _mqttsnAggrConnection->handleDisconnect(client, packet); + break; + case MQTTSN_WILLMSGUPD: + _mqttsnConnection->handleWillmsgupd(client, packet); + break; + case MQTTSN_PINGREQ: + _mqttsnAggrConnection->handlePingreq(client, packet); + break; + case MQTTSN_PUBLISH: + _mqttsnPublish->handleAggregatePublish(client, packet); + break; + case MQTTSN_PUBACK: + _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBACK); + break; + case MQTTSN_PUBREC: + _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBREC); + break; + case MQTTSN_PUBREL: + _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBREL); + break; + case MQTTSN_PUBCOMP: + _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBCOMP); + break; + case MQTTSN_REGISTER: + _mqttsnPublish->handleRegister(client, packet); + break; + case MQTTSN_REGACK: + _mqttsnPublish->handleRegAck(client, packet); + break; + case MQTTSN_SUBSCRIBE: + _mqttsnSubscribe->handleAggregateSubscribe(client, packet); + break; + case MQTTSN_UNSUBSCRIBE: + _mqttsnSubscribe->handleAggregateUnsubscribe(client, packet); + break; + default: + break; + } +} + + +void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTGWPacket* packet) +{ + switch (packet->getType()) + { + case CONNACK: + _mqttConnection->handleConnack(client, packet); + break; + case PINGRESP: + _mqttConnection->handlePingresp(client, packet); + break; + case PUBLISH: + _mqttPublish->handleAggregatePublish(client, packet); + break; + case PUBACK: + _mqttPublish->handleAggregatePuback(client, packet); + break; + case PUBREC: + _mqttPublish->handleAggregateAck(client, packet, PUBREC); + break; + case PUBREL: + _mqttPublish->handleAggregatePubrel(client, packet); + break; + case PUBCOMP: + _mqttPublish->handleAggregateAck(client, packet, PUBCOMP); + break; + case SUBACK: + _mqttSubscribe->handleAggregateSuback(client, packet); + break; + case UNSUBACK: + _mqttSubscribe->handleAggregateUnsuback(client, packet); + break; + default: + break; + } +} + +void PacketHandleTask::transparentPacketHandler(Client*client, MQTTSNPacket* packet) +{ + switch (packet->getType()) + { + case MQTTSN_CONNECT: + _mqttsnConnection->handleConnect(client, packet); + break; + case MQTTSN_WILLTOPIC: + _mqttsnConnection->handleWilltopic(client, packet); + break; + case MQTTSN_WILLMSG: + _mqttsnConnection->handleWillmsg(client, packet); + break; + case MQTTSN_DISCONNECT: + _mqttsnConnection->handleDisconnect(client, packet); + break; + case MQTTSN_WILLMSGUPD: + _mqttsnConnection->handleWillmsgupd(client, packet); + break; + case MQTTSN_PINGREQ: + _mqttsnConnection->handlePingreq(client, packet); + break; + case MQTTSN_PUBLISH: + _mqttsnPublish->handlePublish(client, packet); + break; + case MQTTSN_PUBACK: + _mqttsnPublish->handlePuback(client, packet); + break; + case MQTTSN_PUBREC: + _mqttsnPublish->handleAck(client, packet, PUBREC); + break; + case MQTTSN_PUBREL: + _mqttsnPublish->handleAck(client, packet, PUBREL); + break; + case MQTTSN_PUBCOMP: + _mqttsnPublish->handleAck(client, packet, PUBCOMP); + break; + case MQTTSN_REGISTER: + _mqttsnPublish->handleRegister(client, packet); + break; + case MQTTSN_REGACK: + _mqttsnPublish->handleRegAck(client, packet); + break; + case MQTTSN_SUBSCRIBE: + _mqttsnSubscribe->handleSubscribe(client, packet); + break; + case MQTTSN_UNSUBSCRIBE: + _mqttsnSubscribe->handleUnsubscribe(client, packet); + break; + default: + break; + } +} + + +void PacketHandleTask::transparentPacketHandler(Client*client, MQTTGWPacket* packet) +{ + switch (packet->getType()) + { + case CONNACK: + _mqttConnection->handleConnack(client, packet); + break; + case PINGRESP: + _mqttConnection->handlePingresp(client, packet); + break; + case PUBLISH: + _mqttPublish->handlePublish(client, packet); + break; + case PUBACK: + _mqttPublish->handlePuback(client, packet); + break; + case PUBREC: + _mqttPublish->handleAck(client, packet, PUBREC); + break; + case PUBREL: + _mqttPublish->handleAck(client, packet, PUBREL); + break; + case PUBCOMP: + _mqttPublish->handleAck(client, packet, PUBCOMP); + break; + case SUBACK: + _mqttSubscribe->handleSuback(client, packet); + break; + case UNSUBACK: + _mqttSubscribe->handleUnsuback(client, packet); + break; + default: + break; + } +} + diff --git a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h index 7114605..a77eb65 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h +++ b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h @@ -17,46 +17,60 @@ #ifndef MQTTSNGWPACKETHANDLETASK_H_ #define MQTTSNGWPACKETHANDLETASK_H_ -#include -#include "MQTTSNGWDefines.h" -#include "MQTTSNGateway.h" -#include "MQTTSNGWClient.h" -#include "MQTTSNGWPacket.h" -#include "MQTTGWPacket.h" -#include "MQTTGWConnectionHandler.h" -#include "MQTTGWPublishHandler.h" -#include "MQTTGWSubscribeHandler.h" -#include "MQTTSNGWConnectionHandler.h" -#include "MQTTSNGWPublishHandler.h" -#include "MQTTSNGWSubscribeHandler.h" -#include "SensorNetwork.h" - - +#include "Timer.h" +#include "MQTTSNGWProcess.h" namespace MQTTSNGW { +class Gateway; +class Client; +class MQTTSNPacket; +class MQTTGWPacket; +class Timer; +class MQTTGWConnectionHandler; +class MQTTGWPublishHandler; +class MQTTGWSubscribeHandler; +class MQTTSNConnectionHandler; +class MQTTSNPublishHandler; +class MQTTSNSubscribeHandler; + +class MQTTSNAggregateConnectionHandler; #define ERRNO_APL_01 11 // Task Initialize Error +class Thread; +class Timer; /*===================================== Class PacketHandleTask =====================================*/ class PacketHandleTask : public Thread { MAGIC_WORD_FOR_THREAD; + friend class MQTTGWAggregatePublishHandler; + friend class MQTTGWAggregateSubscribeHandler; + friend class MQTTSNAggregateConnectionHandler; + friend class MQTTSNAggregatePublishHandler; + friend class MQTTSNAggregateSubscribeHandler; public: PacketHandleTask(Gateway* gateway); ~PacketHandleTask(); void run(); private: - Gateway* _gateway; + void aggregatePacketHandler(Client*client, MQTTSNPacket* packet); + void aggregatePacketHandler(Client*client, MQTTGWPacket* packet); + void transparentPacketHandler(Client*client, MQTTSNPacket* packet); + void transparentPacketHandler(Client*client, MQTTGWPacket* packet); + + Gateway* _gateway {nullptr}; Timer _advertiseTimer; Timer _sendUnixTimer; - MQTTGWConnectionHandler* _mqttConnection; - MQTTGWPublishHandler* _mqttPublish; - MQTTGWSubscribeHandler* _mqttSubscribe; - MQTTSNConnectionHandler* _mqttsnConnection; - MQTTSNPublishHandler* _mqttsnPublish; - MQTTSNSubscribeHandler* _mqttsnSubscribe; + MQTTGWConnectionHandler* _mqttConnection {nullptr}; + MQTTGWPublishHandler* _mqttPublish {nullptr}; + MQTTGWSubscribeHandler* _mqttSubscribe {nullptr}; + MQTTSNConnectionHandler* _mqttsnConnection {nullptr}; + MQTTSNPublishHandler* _mqttsnPublish {nullptr}; + MQTTSNSubscribeHandler* _mqttsnSubscribe {nullptr}; + + MQTTSNAggregateConnectionHandler* _mqttsnAggrConnection {nullptr}; }; diff --git a/MQTTSNGateway/src/MQTTSNGWProcess.cpp b/MQTTSNGateway/src/MQTTSNGWProcess.cpp index 549b439..88ba292 100644 --- a/MQTTSNGateway/src/MQTTSNGWProcess.cpp +++ b/MQTTSNGateway/src/MQTTSNGWProcess.cpp @@ -34,8 +34,8 @@ char* currentDateTime(void); /*===================================== Global Variables & Functions ======================================*/ -Process* MQTTSNGW::theProcess = 0; -MultiTaskProcess* MQTTSNGW::theMultiTaskProcess = 0; +Process* MQTTSNGW::theProcess = nullptr; +MultiTaskProcess* MQTTSNGW::theMultiTaskProcess = nullptr; /* * Save the type of signal @@ -359,8 +359,8 @@ Exception::Exception(const int exNo, const string& message) { _message = message; _exNo = exNo; - _fileName = 0; - _functionName = 0; + _fileName = nullptr; + _functionName = nullptr; _line = 0; } diff --git a/MQTTSNGateway/src/MQTTSNGWProcess.h b/MQTTSNGateway/src/MQTTSNGWProcess.h index 1ff48da..1fb02a9 100644 --- a/MQTTSNGateway/src/MQTTSNGWProcess.h +++ b/MQTTSNGateway/src/MQTTSNGWProcess.h @@ -132,8 +132,8 @@ public: QueElement(T* t) { _element = t; - _next = 0; - _prev = 0; + _next = nullptr; + _prev = nullptr; } ~QueElement() @@ -155,8 +155,8 @@ class Que public: Que() { - _head = 0; - _tail = 0; + _head = nullptr; + _tail = nullptr; _cnt = 0; _maxSize = 0; } @@ -180,12 +180,12 @@ public: QueElement* head = _head; if ( _head == _tail ) { - _head = _tail = 0; + _head = _tail = nullptr; } else { _head = head->_next; - head->_prev = 0; + head->_prev = nullptr; } delete head; _cnt--; @@ -861,13 +861,13 @@ class ListElm public: ListElm() { - _elm = 0; - _prev = _next = 0; + _elm = nullptr; + _prev = _next = nullptr; } ListElm(T* elm) { _elm = elm; - _prev = _next = 0; + _prev = _next = nullptr; } T* getContent(void) { @@ -888,7 +888,7 @@ class List{ public: List() { - _head = _tail = 0; + _head = _tail = nullptr; _size = 0; } ~List() @@ -899,11 +899,11 @@ public: int add(T* t) { ListElm* elm = new ListElm(t); - if ( elm == 0 ) + if ( elm == nullptr ) { return 0; } - if ( _head == 0 ) + if ( _head == nullptr ) { _head = elm; _tail = elm; @@ -929,7 +929,7 @@ public: else if ( _tail == elm ) { _tail = elm->_prev; - elm->_prev->_next = 0; + elm->_prev->_next = nullptr; _size--; delete elm; } @@ -950,8 +950,8 @@ public: delete p; p = q; } - _head = 0; - _tail = 0; + _head = nullptr; + _tail = nullptr; _size = 0; } diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp index aedb5df..26b1816 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp @@ -20,6 +20,7 @@ #include "MQTTGWPacket.h" #include "MQTTSNGateway.h" #include "MQTTSNGWClient.h" +#include "MQTTSNGWQoSm1Proxy.h" #include using namespace std; using namespace MQTTSNGW; @@ -34,7 +35,7 @@ MQTTSNPublishHandler::~MQTTSNPublishHandler() } -void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) +MQTTGWPacket* MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) { uint8_t dup; int qos; @@ -47,34 +48,26 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) char shortTopic[2]; - if ( !client->isActive() ) + if ( !_gateway->getAdapterManager()->getQoSm1Proxy()->isActive() ) { - if ( client->isProxy() ) + if ( client->isQoSm1() ) { - client->setProxyPacket(packet); + _gateway->getAdapterManager()->getQoSm1Proxy()->savePacket(client, packet); + + return nullptr; } - else - { - /* Reply DISCONNECT to the client */ - Event* ev = new Event(); - MQTTSNPacket* disconnect = new MQTTSNPacket(); - disconnect->setDISCONNECT(0); - ev->setClientSendEvent(client, disconnect); - _gateway->getClientSendQue()->post(ev); - } - return; } if ( packet->getPUBLISH(&dup, &qos, &retained, &msgId, &topicid, &payload, &payloadlen) ==0 ) { - return; + return nullptr; } pub.msgId = msgId; pub.header.bits.dup = dup; pub.header.bits.qos = ( qos == 3 ? 0 : qos ); pub.header.bits.retain = retained; - Topic* topic = 0; + Topic* topic = nullptr; if( topicid.type == MQTTSN_TOPIC_TYPE_SHORT ) { @@ -90,7 +83,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) if( !topic && qos == 3 ) { WRITELOG("%s Invali TopicId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - return; + return nullptr; } if( !topic && msgId && qos > 0 && qos < 3 ) @@ -101,7 +94,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) Event* ev1 = new Event(); ev1->setClientSendEvent(client, pubAck); _gateway->getClientSendQue()->post(ev1); - return; + return nullptr; } if ( topic ) { @@ -120,14 +113,17 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) MQTTGWPacket* publish = new MQTTGWPacket(); publish->setPUBLISH(&pub); - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, publish); - _gateway->getBrokerSendQue()->post(ev1); - /* reset PINGREQ of ClientProxy */ - if ( qos == 3 ) + if ( !_gateway->getAdapterManager()->isAggregaterActive() ) { - _gateway->getQoSm1Proxy()->resetPingTimer(); + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, publish); + _gateway->getBrokerSendQue()->post(ev1); + return nullptr; + } + else + { + return publish; } } @@ -146,11 +142,14 @@ void MQTTSNPublishHandler::handlePuback(Client* client, MQTTSNPacket* packet) if ( rc == MQTTSN_RC_ACCEPTED) { - MQTTGWPacket* pubAck = new MQTTGWPacket(); - pubAck->setAck(PUBACK, msgId); - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, pubAck); - _gateway->getBrokerSendQue()->post(ev1); + if ( !_gateway->getAdapterManager()->getAggregater()->isActive() ) + { + MQTTGWPacket* pubAck = new MQTTGWPacket(); + pubAck->setAck(PUBACK, msgId); + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, pubAck); + _gateway->getBrokerSendQue()->post(ev1); + } } else if ( rc == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID) { @@ -219,7 +218,7 @@ void MQTTSNPublishHandler::handleRegAck( Client* client, MQTTSNPacket* packet) MQTTSNPacket* regAck = client->getWaitREGACKPacketList()->getPacket(msgId); - if ( regAck != 0 ) + if ( regAck != nullptr ) { client->getWaitREGACKPacketList()->erase(msgId); Event* ev = new Event(); @@ -239,3 +238,49 @@ void MQTTSNPublishHandler::handleRegAck( Client* client, MQTTSNPacket* packet) } } + + + + +void MQTTSNPublishHandler::handleAggregatePublish(Client* client, MQTTSNPacket* packet) +{ + int msgId = 0; + MQTTGWPacket* publish = handlePublish(client, packet); + if ( publish != nullptr ) + { + if ( publish->getMsgId() > 0 ) + { + if ( packet->isDuplicate() ) + { + msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); + } + else + { + msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); + } + publish->setMsgId(msgId); + } + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, publish); + _gateway->getBrokerSendQue()->post(ev1); + } +} + +void MQTTSNPublishHandler::handleAggregateAck(Client* client, MQTTSNPacket* packet, int type) +{ + if ( type == MQTTSN_PUBREC ) + { + uint16_t msgId; + + if ( packet->getACK(&msgId) == 0 ) + { + return; + } + MQTTSNPacket* ackPacket = new MQTTSNPacket(); + ackPacket->setPUBREL(msgId); + Event* ev = new Event(); + ev->setClientSendEvent(client, ackPacket); + _gateway->getClientSendQue()->post(ev); + } + return; +} diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.h b/MQTTSNGateway/src/MQTTSNGWPublishHandler.h index f7fc2d8..85efeb8 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.h +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.h @@ -27,11 +27,15 @@ class MQTTSNPublishHandler public: MQTTSNPublishHandler(Gateway* gateway); ~MQTTSNPublishHandler(); - void handlePublish(Client* client, MQTTSNPacket* packet); + MQTTGWPacket* handlePublish(Client* client, MQTTSNPacket* packet); void handlePuback(Client* client, MQTTSNPacket* packet); void handleAck(Client* client, MQTTSNPacket* packet, uint8_t packetType); void handleRegister(Client* client, MQTTSNPacket* packet); void handleRegAck( Client* client, MQTTSNPacket* packet); + + void handleAggregatePublish(Client* client, MQTTSNPacket* packet); + void handleAggregateAck(Client* client, MQTTSNPacket* packet, int type); + private: Gateway* _gateway; }; diff --git a/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp deleted file mode 100644 index 67e98ce..0000000 --- a/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/************************************************************************************** - * Copyright (c) 2018, 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 "MQTTSNGWQoS-1Proxy.h" - -#include "MQTTSNGWDefines.h" -#include "MQTTSNGateway.h" -#include "SensorNetwork.h" -#include -#include -#include - -#define QOSM1_PROXY_KEEPALIVE_DURATION 900 // Secs -#define QOSM1_PROXY_RESPONSE_DURATION 10 // Secs -#define QOSM1_PROXY_MAX_RETRY_CNT 3 - -using namespace MQTTSNGW; - -/* - * Class ClientProxyElement - */ - -QoSm1ProxyElement::QoSm1ProxyElement(void) - : _clientId{0} - , _next{0} -{ - -} - -QoSm1ProxyElement::QoSm1ProxyElement(SensorNetAddress* addr, string* clientId) - : _next{0} -{ - _clientId = *clientId; - _sensorNetAddr = *addr; -} - -QoSm1ProxyElement::~QoSm1ProxyElement(void) -{ - -} - -/* - * Class ClientProxy - */ - -QoSm1Proxy:: QoSm1Proxy(void) - : _head{0} - , _isWaitingResp{false} - , _retryCnt{0} -{ - _gateway = 0; - _client = 0; -} - -QoSm1Proxy:: QoSm1Proxy(Gateway* gw) - : _head{0} -, _isWaitingResp{false} -, _retryCnt{0} -{ - _gateway = gw; - _client = 0; -} - - -QoSm1Proxy::~QoSm1Proxy(void) -{ - if ( _head ) - { - QoSm1ProxyElement* p = _head; - while ( p ) - { - QoSm1ProxyElement* next = p->_next; - delete p; - p = next; - } - } -} - -void QoSm1Proxy::setGateway(Gateway* gw) -{ - _gateway = gw; -} - -QoSm1ProxyElement* QoSm1Proxy::add(SensorNetAddress* addr, string* clientId) -{ - QoSm1ProxyElement* elm = new QoSm1ProxyElement(addr, clientId); - if ( _head == 0 ) - { - _head = elm; - } - else - { - QoSm1ProxyElement* p = _head; - while ( p ) - { - if ( p->_next == 0 ) - { - p->_next = elm; - break; - } - else - { - p = p->_next; - } - } - } - return elm; -} - -const char* QoSm1Proxy::getClientId(SensorNetAddress* addr) -{ - QoSm1ProxyElement* p = _head; - while ( p ) - { - if ( p->_sensorNetAddr.isMatch(addr) ) - { - return p->_clientId.c_str(); - break; - } - p = p->_next; - } - return 0; -} - -void QoSm1Proxy::setClient(Client* client) -{ - _client = client; -} - -Client* QoSm1Proxy::getClient(void) -{ - return _client; -} - -bool QoSm1Proxy::setClientProxy(const char* fileName) -{ - FILE* fp; - char buf[MAX_CLIENTID_LENGTH + 256]; - size_t pos; - - SensorNetAddress netAddr; - - if ((fp = fopen(fileName, "r")) != 0) - { - while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0) - { - if (*buf == '#') - { - continue; - } - string data = string(buf); - while ((pos = data.find_first_of("  \t\n")) != string::npos) - { - data.erase(pos, 1); - } - if (data.empty()) - { - continue; - } - - pos = data.find_first_of(","); - string id = data.substr(0, pos); - string addr = data.substr(pos + 1); - - if (netAddr.setAddress(&addr) == 0) - { - add(&netAddr, &id); - } - else - { - WRITELOG("Invalid address %s\n", data.c_str()); - return false; - } - } - fclose(fp); - } - else - { - WRITELOG("Can not open the QoS_1Client List. %s\n", fileName); - return false; - } - return true; -} - - -void QoSm1Proxy::checkConnection(void) -{ - if ( _client->isDisconnect() || ( _client->isConnecting() && _responseTimer.isTimeup()) ) - { - _client->connectSended(); - _responseTimer.start(QOSM1_PROXY_RESPONSE_DURATION * 1000UL); - MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; - options.clientID.cstring = _client->getClientId(); - options.duration = QOSM1_PROXY_KEEPALIVE_DURATION; - - MQTTSNPacket* packet = new MQTTSNPacket(); - packet->setCONNECT(&options); - Event* ev = new Event(); - ev->setClientRecvEvent(_client, packet); - _gateway->getPacketEventQue()->post(ev); - } - else if ( (_client->isActive() && _keepAliveTimer.isTimeup() ) || (_isWaitingResp && _responseTimer.isTimeup() ) ) - { - MQTTSNPacket* packet = new MQTTSNPacket(); - MQTTSNString clientId = MQTTSNString_initializer; - packet->setPINGREQ(&clientId); - Event* ev = new Event(); - ev->setClientRecvEvent(_client, packet); - _gateway->getPacketEventQue()->post(ev); - _responseTimer.start(QOSM1_PROXY_RESPONSE_DURATION * 1000UL); - _isWaitingResp = true; - - if ( ++_retryCnt > QOSM1_PROXY_MAX_RETRY_CNT ) - { - _client->disconnected(); - } - resetPingTimer(); - } -} - -void QoSm1Proxy::resetPingTimer(void) -{ - _keepAliveTimer.start(QOSM1_PROXY_KEEPALIVE_DURATION * 1000UL); -} - -void QoSm1Proxy::send(MQTTSNPacket* packet) -{ - if ( packet->getType() == MQTTSN_CONNACK ) - { - resetPingTimer(); - _responseTimer.stop(); - _retryCnt = 0; - sendStoredPublish(); - } - else if ( packet->getType() == MQTTSN_PINGRESP ) - { - _responseTimer.stop(); - _isWaitingResp = false; - _retryCnt = 0; - - resetPingTimer(); - } - else if ( packet->getType() == MQTTSN_DISCONNECT ) - { - // blank - } -} - -void QoSm1Proxy::sendStoredPublish(void) -{ - MQTTSNPacket* msg = 0; - - while ( ( msg = _client->getProxyPacket() ) != 0 ) - { - _client->deleteFirstProxyPacket(); // pop the que to delete element. - - Event* ev = new Event(); - ev->setClientRecvEvent(_client, msg); - _gateway->getPacketEventQue()->post(ev); - } -} diff --git a/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h b/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h deleted file mode 100644 index 9960668..0000000 --- a/MQTTSNGateway/src/MQTTSNGWQoS-1Proxy.h +++ /dev/null @@ -1,79 +0,0 @@ -/************************************************************************************** - * Copyright (c) 2018, 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 - **************************************************************************************/ - -#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_ -#define MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_ - -#include "MQTTSNGateway.h" -#include "MQTTGWPacket.h" -#include "MQTTSNGWClient.h" -#include "SensorNetwork.h" -#include "MQTTSNGWProcess.h" - - - -namespace MQTTSNGW -{ -class Gateway; - -class QoSm1ProxyElement -{ - friend class QoSm1Proxy; -public: - QoSm1ProxyElement(void); - QoSm1ProxyElement(SensorNetAddress* addr, string* clientId); - ~QoSm1ProxyElement(void); -private: - SensorNetAddress _sensorNetAddr; - string _clientId; - QoSm1ProxyElement* _next; -}; - -class QoSm1Proxy -{ -public: - QoSm1Proxy(void); - QoSm1Proxy(Gateway* gw); - ~QoSm1Proxy(void); - bool setClientProxy(const char* fileName); - QoSm1ProxyElement* add(SensorNetAddress* addr, string* clientId); - const char* getClientId(SensorNetAddress* addr); - void setClient(Client*); - Client* getClient(void); - void setGateway(Gateway* gw); - void setKeepAlive(uint16_t secs); - - void checkConnection(void); - void resetPingTimer(void); - void send(MQTTSNPacket* packet); - -private: - void sendStoredPublish(void); - - Gateway* _gateway; - Client* _client; - QoSm1ProxyElement* _head; - Timer _keepAliveTimer; - Timer _responseTimer; - bool _isWaitingResp; - int _retryCnt; -}; - -} - - - -#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp new file mode 100644 index 0000000..2021e17 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp @@ -0,0 +1,75 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 "MQTTSNGWQoSm1Proxy.h" +#include "MQTTSNGateway.h" +#include "SensorNetwork.h" +#include "MQTTSNGWClientList.h" +#include +#include + + +using namespace MQTTSNGW; + +/*===================================== + Class QoSm1Proxy + =====================================*/ +QoSm1Proxy:: QoSm1Proxy(Gateway* gw) : Adapter(gw) +{ + _gateway = gw; +} + +QoSm1Proxy::~QoSm1Proxy(void) +{ + +} + + +void QoSm1Proxy::initialize(void) +{ + char param[MQTTSNGW_PARAM_MAX]; + + if ( _gateway->hasSecureConnection() ) + { + _isSecure = true; + } + + if (_gateway->getParam("QoS-1", param) == 0 ) + { + if (strcasecmp(param, "YES") == 0 ) + { + /* Create QoS-1 Clients */ + _gateway->getClientList()->setClientList(_gateway, QOSM1PROXY_TYPE); + + /* set ClientId of this Proxy */ + const char* name = CLIENTPROXY; + if (_gateway->getParam("QoS-1ProxyName", param) == 0 ) + { + name = param; + } + /* initialize Adapter */ + setup(name, Atype_QoSm1Proxy); + _isActive = true; + } + } +} + + +bool QoSm1Proxy::isActive(void) +{ + return _isActive; +} + diff --git a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h new file mode 100644 index 0000000..d3dfcf5 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h @@ -0,0 +1,53 @@ +/************************************************************************************** + * Copyright (c) 2018, 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 + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWQOSM1PROXY_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWQOSM1PROXY_H_ + +#include "MQTTSNGWAdapter.h" +namespace MQTTSNGW +{ +class Gateway; +class Adapter; +class Client; +class SensorNetAddress; +class MQTTSNPacket; + +/*===================================== + Class QoSm1Proxy + =====================================*/ +class QoSm1Proxy : public Adapter +{ +public: + QoSm1Proxy(Gateway* gw); + ~QoSm1Proxy(void); + + void initialize(void); + bool isActive(void); + +private: + Gateway* _gateway; + + bool _isActive {false}; + bool _isSecure {false}; +}; + + +} + + + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWQOSM1PROXY_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.cpp b/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.cpp index fd192a5..6bca10f 100644 --- a/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.cpp @@ -34,13 +34,13 @@ MQTTSNSubscribeHandler::~MQTTSNSubscribeHandler() } -void MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packet) +MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packet) { uint8_t dup; int qos; uint16_t msgId; MQTTSN_topicid topicFilter; - Topic* topic = 0; + Topic* topic = nullptr; uint16_t topicId = 0; MQTTGWPacket* subscribe; Event* ev1; @@ -48,12 +48,12 @@ void MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packe if ( packet->getSUBSCRIBE(&dup, &qos, &msgId, &topicFilter) == 0 ) { - return; + return nullptr; } if ( msgId == 0 ) { - return; + return nullptr; } if ( topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED ) @@ -73,13 +73,13 @@ void MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packe else if (topicFilter.type == MQTTSN_TOPIC_TYPE_NORMAL) { topic = client->getTopics()->getTopicByName(&topicFilter); - if ( topic == 0 ) + if ( topic == nullptr ) { topic = client->getTopics()->add(&topicFilter); - if ( topic == 0 ) + if ( topic == nullptr ) { WRITELOG("%s Client(%s) can't add the Topic.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - return; + return nullptr; } } topicId = topic->getTopicId(); @@ -100,10 +100,17 @@ void MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packe client->setWaitedSubTopicId(msgId, topicId, topicFilter.type); - ev1 = new Event(); - ev1->setBrokerSendEvent(client, subscribe); - _gateway->getBrokerSendQue()->post(ev1); - return; + if ( !client->isAggregated() ) + { + ev1 = new Event(); + ev1->setBrokerSendEvent(client, subscribe); + _gateway->getBrokerSendQue()->post(ev1); + return nullptr; + } + else + { + return subscribe; + } RespExit: @@ -112,22 +119,23 @@ RespExit: evsuback = new Event(); evsuback->setClientSendEvent(client, sSuback); _gateway->getClientSendQue()->post(evsuback); + return nullptr; } -void MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* packet) +MQTTGWPacket* MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* packet) { uint16_t msgId; MQTTSN_topicid topicFilter; - MQTTGWPacket* unsubscribe = 0;; + MQTTGWPacket* unsubscribe = nullptr; if ( packet->getUNSUBSCRIBE(&msgId, &topicFilter) == 0 ) { - return; + return nullptr; } if ( msgId == 0 ) { - return; + return nullptr; } Topic* topic = client->getTopics()->getTopicById(&topicFilter); @@ -143,14 +151,14 @@ void MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* pac } else { - if ( topic == 0 ) + if ( topic == nullptr ) { MQTTSNPacket* sUnsuback = new MQTTSNPacket(); sUnsuback->setUNSUBACK(msgId); Event* evsuback = new Event(); evsuback->setClientSendEvent(client, sUnsuback); _gateway->getClientSendQue()->post(evsuback); - return; + return nullptr; } else { @@ -159,8 +167,81 @@ void MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* pac } } - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, unsubscribe); - _gateway->getBrokerSendQue()->post(ev1); + if ( !client->isAggregated() ) + { + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, unsubscribe); + _gateway->getBrokerSendQue()->post(ev1); + return nullptr; + } + else + { + return unsubscribe; + } } +void MQTTSNSubscribeHandler::handleAggregateSubscribe(Client* client, MQTTSNPacket* packet) +{ + MQTTGWPacket* subscribe = handleSubscribe(client, packet); + + if ( subscribe != nullptr ) + { + UTF8String str = subscribe->getTopic(); + string* topicName = new string(str.data, str.len); + Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); + _gateway->getAdapterManager()->addAggregateTopic(&topic, client); + + int msgId = 0; + if ( packet->isDuplicate() ) + { + msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); + } + else + { + msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); + } + + if ( msgId == 0 ) + { + WRITELOG("%s MQTTSNSubscribeHandler can't create MessageIdTableElement %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + return; + } +WRITELOG("msgId=%d\n",msgId); + subscribe->setMsgId(msgId); + Event* ev = new Event(); + ev->setBrokerSendEvent(client, subscribe); + _gateway->getBrokerSendQue()->post(ev); + } +} + +void MQTTSNSubscribeHandler::handleAggregateUnsubscribe(Client* client, MQTTSNPacket* packet) +{ + MQTTGWPacket* unsubscribe = handleUnsubscribe(client, packet); + if ( unsubscribe != nullptr ) + { + UTF8String str = unsubscribe->getTopic(); + string* topicName = new string(str.data, str.len); + Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); + _gateway->getAdapterManager()->removeAggregateTopic(&topic, client); + + int msgId = 0; + if ( packet->isDuplicate() ) + { + msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); + } + else + { + msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); + } + + if ( msgId == 0 ) + { + WRITELOG("%s MQTTSNUnsubscribeHandler can't create MessageIdTableElement %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + return; + } + unsubscribe->setMsgId(msgId); + Event* ev = new Event(); + ev->setBrokerSendEvent(client, unsubscribe); + _gateway->getBrokerSendQue()->post(ev); + } +} diff --git a/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h b/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h index 21410d5..5b2202a 100644 --- a/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h +++ b/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h @@ -31,8 +31,10 @@ class MQTTSNSubscribeHandler public: MQTTSNSubscribeHandler(Gateway* gateway); ~MQTTSNSubscribeHandler(); - void handleSubscribe(Client* client, MQTTSNPacket* packet); - void handleUnsubscribe(Client* client, MQTTSNPacket* packet); + MQTTGWPacket* handleSubscribe(Client* client, MQTTSNPacket* packet); + MQTTGWPacket* handleUnsubscribe(Client* client, MQTTSNPacket* packet); + void handleAggregateSubscribe(Client* client, MQTTSNPacket* packet); + void handleAggregateUnsubscribe(Client* client, MQTTSNPacket* packet); private: Gateway* _gateway; diff --git a/MQTTSNGateway/src/MQTTSNGWTopic.cpp b/MQTTSNGateway/src/MQTTSNGWTopic.cpp new file mode 100644 index 0000000..7777a2c --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWTopic.cpp @@ -0,0 +1,519 @@ +/************************************************************************************** + * 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 + * Tieto Poland Sp. z o.o. - Gateway improvements + **************************************************************************************/ +#include "MQTTSNGWTopic.h" +#include "MQTTSNGWDefines.h" +#include "MQTTSNGateway.h" +#include + +using namespace MQTTSNGW; + +/*===================================== + Class Topic + ======================================*/ +Topic::Topic() +{ + _type = MQTTSN_TOPIC_TYPE_NORMAL; + _topicName = nullptr; + _topicId = 0; + _next = nullptr; +} + +Topic::Topic(string* topic, MQTTSN_topicTypes type) +{ + _type = type; + _topicName = topic; + _topicId = 0; + _next = nullptr; +} + +Topic::~Topic() +{ + if ( _topicName ) + { + delete _topicName; + } +} + +string* Topic::getTopicName(void) +{ + return _topicName; +} + +uint16_t Topic::getTopicId(void) +{ + return _topicId; +} + +MQTTSN_topicTypes Topic::getType(void) +{ + return _type; +} + +bool Topic::isMatch(string* topicName) +{ + string::size_type tlen = _topicName->size(); + + string::size_type tpos = 0; + string::size_type tloc = 0; + string::size_type pos = 0; + string::size_type loc = 0; + string wildcard = "#"; + string wildcards = "+"; + + while(true) + { + loc = topicName->find('/', pos); + tloc = _topicName->find('/', tpos); + + if ( loc != string::npos && tloc != string::npos ) + { + string subtopic = topicName->substr(pos, loc - pos); + string subtopict = _topicName->substr(tpos, tloc - tpos); + if (subtopict == wildcard) + { + return true; + } + else if (subtopict == wildcards) + { + if ( (tpos = tloc + 1 ) > tlen ) + { + pos = loc + 1; + loc = topicName->find('/', pos); + if ( loc == string::npos ) + { + return true; + } + else + { + return false; + } + } + pos = loc + 1; + } + else if ( subtopic != subtopict ) + { + return false; + } + else + { + if ( (tpos = tloc + 1) > tlen ) + { + return false; + } + + pos = loc + 1; + } + } + else if ( loc == string::npos && tloc == string::npos ) + { + string subtopic = topicName->substr(pos); + string subtopict = _topicName->substr(tpos); + if ( subtopict == wildcard || subtopict == wildcards) + { + return true; + } + else if ( subtopic == subtopict ) + { + return true; + } + else + { + return false; + } + } + else if ( loc == string::npos && tloc != string::npos ) + { + string subtopic = topicName->substr(pos); + string subtopict = _topicName->substr(tpos, tloc - tpos); + if ( subtopic != subtopict) + { + return false; + } + + tpos = tloc + 1; + + return _topicName->substr(tpos) == wildcard; + } + else if ( loc != string::npos && tloc == string::npos ) + { + return _topicName->substr(tpos) == wildcard; + } + } +} + +void Topic::print(void) +{ + WRITELOG("TopicName=%s ID=%d Type=%d\n", _topicName->c_str(), _topicId, _type); +} + +/*===================================== + Class Topics + ======================================*/ +Topics::Topics() +{ + _first = nullptr; + _nextTopicId = 0; + _cnt = 0; +} + +Topics::~Topics() +{ + Topic* p = _first; + while (p) + { + Topic* q = p->_next; + delete p; + p = q; + } +} + +Topic* Topics::getTopicByName(const MQTTSN_topicid* topicid) +{ + Topic* p = _first; + char* ch = topicid->data.long_.name; + + string sname = string(ch, ch + topicid->data.long_.len); + while (p) + { + if ( p->_topicName->compare(sname) == 0 ) + { + return p; + } + p = p->_next; + } + return 0; +} + +Topic* Topics::getTopicById(const MQTTSN_topicid* topicid) +{ + Topic* p = _first; + + while (p) + { + if ( p->_type == topicid->type && p->_topicId == topicid->data.id ) + { + return p; + } + p = p->_next; + } + return 0; +} + +// For MQTTSN_TOPIC_TYPE_NORMAL */ +Topic* Topics::add(const MQTTSN_topicid* topicid) +{ + if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL ) + { + return 0; + } + + Topic* topic = getTopicByName(topicid); + + if ( topic ) + { + return topic; + } + string name(topicid->data.long_.name, topicid->data.long_.len); + return add(name.c_str(), 0); +} + +Topic* Topics::add(const char* topicName, uint16_t id) +{ + MQTTSN_topicid topicId; + + if ( _cnt >= MAX_TOPIC_PAR_CLIENT ) + { + return 0; + } + + topicId.data.long_.name = (char*)const_cast(topicName); + topicId.data.long_.len = strlen(topicName); + + + Topic* topic = getTopicByName(&topicId); + + if ( topic ) + { + return topic; + } + + topic = new Topic(); + + if (topic == nullptr) + { + return nullptr; + } + + string* name = new string(topicName); + topic->_topicName = name; + + if ( id == 0 ) + { + topic->_type = MQTTSN_TOPIC_TYPE_NORMAL; + topic->_topicId = getNextTopicId(); + } + else + { + topic->_type = MQTTSN_TOPIC_TYPE_PREDEFINED; + topic->_topicId = id; + } + + _cnt++; + + if ( _first == nullptr) + { + _first = topic; + } + else + { + Topic* tp = _first; + while (tp) + { + if (tp->_next == nullptr) + { + tp->_next = topic; + break; + } + else + { + tp = tp->_next; + } + } + } + return topic; +} + +uint16_t Topics::getNextTopicId() +{ + return ++_nextTopicId == 0xffff ? _nextTopicId += 2 : _nextTopicId; +} + +Topic* Topics::match(const MQTTSN_topicid* topicid) +{ + if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL) + { + return 0; + } + string topicName(topicid->data.long_.name, topicid->data.long_.len); + + Topic* topic = _first; + while (topic) + { + if (topic->isMatch(&topicName)) + { + return topic; + } + topic = topic->_next; + } + return 0; +} + + +void Topics::eraseNormal(void) +{ + Topic* topic = _first; + Topic* next = nullptr; + Topic* prev = nullptr; + + while (topic) + { + if ( topic->_type == MQTTSN_TOPIC_TYPE_NORMAL ) + { + next = topic->_next; + if ( _first == topic ) + { + _first = next; + } + if ( prev ) + { + prev->_next = next; + } + delete topic; + _cnt--; + topic = next; + } + else + { + prev = topic; + topic = topic->_next; + } + } +} + +void Topics::print(void) +{ + Topic* topic = _first; + if (topic == nullptr ) + { + WRITELOG("No Topic.\n"); + } + else + { + while (topic) + { + topic->print(); + topic = topic->_next; + } + } +} + +uint8_t Topics::getCount(void) +{ + return _cnt; +} + +/*===================================== + Class TopicIdMap + =====================================*/ +TopicIdMapElement::TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) +{ + _msgId = msgId; + _topicId = topicId; + _type = type; + _next = nullptr; + _prev = nullptr; +} + +TopicIdMapElement::~TopicIdMapElement() +{ + +} + +MQTTSN_topicTypes TopicIdMapElement::getTopicType(void) +{ + return _type; +} + +uint16_t TopicIdMapElement::getTopicId(void) +{ + return _topicId; +} + +TopicIdMap::TopicIdMap() +{ + _maxInflight = MAX_INFLIGHTMESSAGES; + _msgIds = 0; + _first = nullptr; + _end = nullptr; + _cnt = 0; +} + +TopicIdMap::~TopicIdMap() +{ + TopicIdMapElement* p = _first; + while ( p ) + { + TopicIdMapElement* q = p->_next; + delete p; + p = q; + } +} + +TopicIdMapElement* TopicIdMap::getElement(uint16_t msgId) +{ + TopicIdMapElement* p = _first; + while ( p ) + { + if ( p->_msgId == msgId ) + { + return p; + } + p = p->_next; + } + return 0; +} + +TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) +{ + if ( _cnt > _maxInflight * 2 || ( topicId == 0 && type != MQTTSN_TOPIC_TYPE_SHORT ) ) + { + return 0; + } + if ( getElement(msgId) > 0 ) + { + erase(msgId); + } + + TopicIdMapElement* elm = new TopicIdMapElement(msgId, topicId, type); + if ( elm == 0 ) + { + return 0; + } + if ( _first == nullptr ) + { + _first = elm; + _end = elm; + } + else + { + elm->_prev = _end; + _end->_next = elm; + _end = elm; + } + _cnt++; + return elm; +} + +void TopicIdMap::erase(uint16_t msgId) +{ + TopicIdMapElement* p = _first; + while ( p ) + { + if ( p->_msgId == msgId ) + { + if ( p->_prev == nullptr ) + { + _first = p->_next; + } + else + { + p->_prev->_next = p->_next; + } + + if ( p->_next == nullptr ) + { + _end = p->_prev; + } + else + { + p->_next->_prev = p->_prev; + } + delete p; + break; + + } + p = p->_next; + } + _cnt--; +} + +void TopicIdMap::clear(void) +{ + TopicIdMapElement* p = _first; + while ( p ) + { + TopicIdMapElement* q = p->_next; + delete p; + p = q; + } + _first = nullptr; + _end = nullptr; + _cnt = 0; +} + + + diff --git a/MQTTSNGateway/src/MQTTSNGWTopic.h b/MQTTSNGateway/src/MQTTSNGWTopic.h new file mode 100644 index 0000000..5c3cc77 --- /dev/null +++ b/MQTTSNGateway/src/MQTTSNGWTopic.h @@ -0,0 +1,115 @@ +/************************************************************************************** + * 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 + * Tieto Poland Sp. z o.o. - Gateway improvements + **************************************************************************************/ + +#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWTOPIC_H_ +#define MQTTSNGATEWAY_SRC_MQTTSNGWTOPIC_H_ + +#include "MQTTSNGWPacket.h" +#include "MQTTSNPacket.h" + +namespace MQTTSNGW +{ + + +/*===================================== + Class Topic + ======================================*/ +class Topic +{ + friend class Topics; +public: + Topic(); + Topic(string* topic, MQTTSN_topicTypes type); + ~Topic(); + string* getTopicName(void); + uint16_t getTopicId(void); + MQTTSN_topicTypes getType(void); + bool isMatch(string* topicName); + void print(void); +private: + MQTTSN_topicTypes _type; + uint16_t _topicId; + string* _topicName; + Topic* _next; +}; + +/*===================================== + Class Topics + ======================================*/ +class Topics +{ +public: + Topics(); + ~Topics(); + Topic* add(const MQTTSN_topicid* topicid); + Topic* add(const char* topicName, uint16_t id = 0); + Topic* getTopicByName(const MQTTSN_topicid* topic); + Topic* getTopicById(const MQTTSN_topicid* topicid); + Topic* match(const MQTTSN_topicid* topicid); + void eraseNormal(void); + uint16_t getNextTopicId(); + void print(void); + uint8_t getCount(void); +private: + uint16_t _nextTopicId; + Topic* _first; + uint8_t _cnt; +}; + +/*===================================== + Class TopicIdMapElement + =====================================*/ +class TopicIdMapElement +{ + friend class TopicIdMap; +public: + TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); + ~TopicIdMapElement(); + MQTTSN_topicTypes getTopicType(void); + uint16_t getTopicId(void); + +private: + uint16_t _msgId; + uint16_t _topicId; + MQTTSN_topicTypes _type; + TopicIdMapElement* _next; + TopicIdMapElement* _prev; +}; + +class TopicIdMap +{ +public: + TopicIdMap(); + ~TopicIdMap(); + TopicIdMapElement* getElement(uint16_t msgId); + TopicIdMapElement* add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); + void erase(uint16_t msgId); + void clear(void); +private: + uint16_t* _msgIds; + TopicIdMapElement* _first; + TopicIdMapElement* _end; + int _cnt; + int _maxInflight; +}; + + +} + + + +#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWTOPIC_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWVersion.h b/MQTTSNGateway/src/MQTTSNGWVersion.h index 2e458a2..1fd764c 100644 --- a/MQTTSNGateway/src/MQTTSNGWVersion.h +++ b/MQTTSNGateway/src/MQTTSNGWVersion.h @@ -17,6 +17,6 @@ #ifndef MQTTSNGWVERSION_H_IN_ #define MQTTSNGWVERSION_H_IN_ -#define PAHO_GATEWAY_VERSION "1.2.1" +#define PAHO_GATEWAY_VERSION "1.3.0" #endif /* MQTTSNGWVERSION_H_IN_ */ diff --git a/MQTTSNGateway/src/MQTTSNGateway.cpp b/MQTTSNGateway/src/MQTTSNGateway.cpp index 069ac5a..2192850 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.cpp +++ b/MQTTSNGateway/src/MQTTSNGateway.cpp @@ -18,6 +18,8 @@ #include "SensorNetwork.h" #include "MQTTSNGWProcess.h" #include "MQTTSNGWVersion.h" +#include "MQTTSNGWQoSm1Proxy.h" +#include "MQTTSNGWClient.h" #include using namespace MQTTSNGW; @@ -26,32 +28,13 @@ char* currentDateTime(void); /*===================================== Class Gateway =====================================*/ -Gateway::Gateway() +Gateway::Gateway(void) { - theMultiTaskProcess = this; - theProcess = this; - _qosm1Proxy = 0; - _params.loginId = 0; - _params.password = 0; - _params.keepAlive = 0; - _params.gatewayId = 0; - _params.mqttVersion = 0; - _params.maxInflightMsgs = 0; - _params.gatewayName = 0; - _params.brokerName = 0; - _params.port = 0; - _params.portSecure = 0; - _params.rootCApath = 0; - _params.rootCAfile = 0; - _params.certKey = 0; - _params.privateKey = 0; - _params.clientListName = 0; - _params.configName = 0; - _params.predefinedTopicFileName = 0; - _params.forwarderListName = 0; - _params.qosMinusClientListName = 0; - _params.qosm1proxyName = 0; - _packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS); + theMultiTaskProcess = this; + theProcess = this; + _packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS); + _clientList = new ClientList(); + _adapterManager = new AdapterManager(this); } Gateway::~Gateway() @@ -116,25 +99,34 @@ Gateway::~Gateway() { free(_params.qosMinusClientListName); } - if ( _params.qosm1proxyName ) - { - free(_params.qosm1proxyName); - } - if ( _qosm1Proxy ) + if ( _adapterManager ) { - delete _qosm1Proxy; + delete _adapterManager; } + if ( _clientList ) + { + delete _clientList; + } +} + +int Gateway::getParam(const char* parameter, char* value) +{ + return MultiTaskProcess::getParam(parameter, value); } void Gateway::initialize(int argc, char** argv) { char param[MQTTSNGW_PARAM_MAX]; string fileName; - bool secure = false; + MultiTaskProcess::initialize(argc, argv); resetRingBuffer(); + _params.configDir = *getConfigDirName(); + fileName = _params.configDir + *getConfigFileName(); + _params.configName = strdup(fileName.c_str()); + if (getParam("BrokerName", param) == 0) { _params.brokerName = strdup(param); @@ -180,6 +172,11 @@ void Gateway::initialize(int argc, char** argv) _params.gatewayName = strdup(param); } + if (_params.gatewayName == 0 ) + { + throw Exception( "Gateway::initialize: Gateway Name is missing."); + } + _params.mqttVersion = DEFAULT_MQTT_VERSION; if (getParam("MQTTVersion", param) == 0) { @@ -193,7 +190,6 @@ void Gateway::initialize(int argc, char** argv) } _params.keepAlive = DEFAULT_KEEP_ALIVE_TIME; - if (getParam("KeepAlive", param) == 0) { _params.keepAlive = atoi(param); @@ -218,113 +214,23 @@ void Gateway::initialize(int argc, char** argv) { if (!strcasecmp(param, "YES")) { - secure = true; - if (getParam("ClientsList", param) == 0) - { - fileName = string(param); - } - else - { - fileName = *getConfigDirName() + string(CLIENT_LIST); - } - - if (!_clientList.authorize(fileName.c_str())) - { - throw Exception("Gateway::initialize: No client list defined by the configuration."); - } - _params.clientListName = strdup(fileName.c_str()); + _params.clientAuthentication = true; } } - /* Set QoSm1Proxy's Client */ + /* ClientList and Adapters Initialize */ + _adapterManager->initialize(); - if (getParam("QoS-1", param) == 0 ) - { - if (!strcasecmp(param, "YES") ) - { - /* Set QoSm1Proxy's Client */ - - _qosm1Proxy = new QoSm1Proxy(this); - MQTTSNString id = MQTTSNString_initializer; - - if (getParam("QoS-1ProxyName", param) == 0 ) - { - string name = string(param); - id.cstring = const_cast(name.c_str()); - } - else - { - id.cstring = const_cast(CLIENTPROXY); - } - Client* client = _clientList.createClient(0, &id, true, secure); - _qosm1Proxy->setClient(client); - client->setPorxy(true); - _qosm1Proxy->setGateway(this); - - - if (getParam("QoS-1ClientsList", param) == 0) - { - fileName = string(param); - } - else - { - fileName = *getConfigDirName() + string(QOS_1CLIENT_LIST); - } - if ( !_qosm1Proxy->setClientProxy(fileName.c_str()) ) - { - throw Exception("Gateway::initialize: No QoS-1ClientsList file defined by the configuration.."); - } - _params.qosMinusClientListName = strdup(fileName.c_str()); - } - } - - if (getParam("PredefinedTopic", param) == 0 ) - { - if (!strcasecmp(param, "YES") ) - { - if (getParam("PredefinedTopicList", param) == 0) - { - fileName = string(param); - } - else - { - fileName = *getConfigDirName() + string(PREDEFINEDTOPIC_FILE); - } - if (!_clientList.setPredefinedTopics(fileName.c_str())) - { - throw Exception("Gateway::initialize: No PredefinedTopic file defined by the configuration.."); - } - _params.predefinedTopicFileName = strdup(fileName.c_str()); - } - } - - if (getParam("Forwarder", param) == 0 ) - { - if (!strcasecmp(param, "YES") ) - { - if (getParam("ForwardersList", param) == 0) - { - fileName = string(param); - } - else - { - fileName = *getConfigDirName() + string(FORWARDER_LIST); - } - if ( !_forwarderList.setFowerder(fileName.c_str()) ) - { - throw Exception("Gateway::initialize: No ForwardersList file defined by the configuration.."); - } - _params.forwarderListName = strdup(fileName.c_str()); - } - } - - fileName = *getConfigDirName() + *getConfigFileName(); - _params.configName = strdup(fileName.c_str()); + bool aggregate = _adapterManager->isAggregaterActive(); + _clientList->initialize(this, aggregate); + /* Setup predefined topics */ + _clientList->setPredefinedTopics(this, aggregate); } void Gateway::run(void) { + /* write prompts */ _lightIndicator.redLight(true); WRITELOG("\n%s", PAHO_COPYRIGHT4); WRITELOG("\n%s\n", PAHO_COPYRIGHT0); @@ -335,30 +241,36 @@ void Gateway::run(void) WRITELOG("%s\n", PAHO_COPYRIGHT4); WRITELOG("\n%s %s has been started.\n\n", currentDateTime(), _params.gatewayName); WRITELOG(" ConfigFile: %s\n", _params.configName); + if ( getClientList()->isAuthorized() ) { WRITELOG(" ClientList: %s\n", _params.clientListName); } + if ( _params.predefinedTopicFileName ) { WRITELOG(" PreDefFile: %s\n", _params.predefinedTopicFileName); } + if ( _params.forwarderListName ) { WRITELOG(" Forwarders: %s\n", _params.forwarderListName); } + if ( _params.qosMinusClientListName ) { WRITELOG(" QoS-1File: %s\n", _params.qosMinusClientListName); } + WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription()); WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); - WRITELOG(" RootCApath: %s\n", _params.rootCApath); WRITELOG(" RootCAfile: %s\n", _params.rootCAfile); WRITELOG(" CertKey: %s\n", _params.certKey); WRITELOG(" PrivateKey: %s\n\n\n", _params.privateKey); + + /* Run Tasks until CTRL+C entred */ MultiTaskProcess::run(); /* stop Tasks */ @@ -396,12 +308,7 @@ EventQue* Gateway::getBrokerSendQue() ClientList* Gateway::getClientList() { - return &_clientList; -} - -ForwarderList* Gateway::getForwarderList(void) -{ - return &_forwarderList; + return _clientList; } SensorNetwork* Gateway::getSensorNetwork() @@ -419,11 +326,18 @@ GatewayParams* Gateway::getGWParams(void) return &_params; } -QoSm1Proxy* Gateway::getQoSm1Proxy(void) +AdapterManager* Gateway::getAdapterManager(void) { - return _qosm1Proxy; + return _adapterManager; } +bool Gateway::hasSecureConnection(void) +{ + return ( _params.certKey + && _params.privateKey + && _params.rootCApath + && _params.rootCAfile ); +} /*===================================== Class EventQue =====================================*/ @@ -450,9 +364,9 @@ void EventQue::setMaxSize(uint16_t maxSize) Event* EventQue::wait(void) { - Event* ev = 0; + Event* ev = nullptr; - while(ev == 0) + while(ev == nullptr) { if ( _que.size() == 0 ) { @@ -520,11 +434,7 @@ int EventQue::size() =====================================*/ Event::Event() { - _eventType = Et_NA; - _client = 0; - _sensorNetAddr = 0; - _mqttSNPacket = 0; - _mqttGWPacket = 0; + } Event::~Event() @@ -620,3 +530,5 @@ MQTTGWPacket* Event::getMQTTGWPacket(void) { return _mqttGWPacket; } + + diff --git a/MQTTSNGateway/src/MQTTSNGateway.h b/MQTTSNGateway/src/MQTTSNGateway.h index b547e0a..2507de5 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.h +++ b/MQTTSNGateway/src/MQTTSNGateway.h @@ -16,12 +16,10 @@ #ifndef MQTTSNGATEWAY_H_ #define MQTTSNGATEWAY_H_ -#include "MQTTSNGWClient.h" +#include #include "MQTTSNGWProcess.h" #include "MQTTSNPacket.h" - -#include "MQTTSNGWForwarder.h" -#include "MQTTSNGWQoS-1Proxy.h" +#include "MQTTSNGWClient.h" namespace MQTTSNGW { @@ -46,6 +44,7 @@ namespace MQTTSNGW #define CLIENTS "Clients" #define UNKNOWNCL "Unknown Client !" #define CLIENTPROXY "ClientProxy" +#define CLIENTPROXY_SECURE "ClientProxyS" #define LEFTARROW "<---" #define RIGHTARROW "--->" @@ -77,6 +76,8 @@ namespace MQTTSNGW /*===================================== Class Event ====================================*/ +class Client; + enum EventType{ Et_NA = 0, EtStop, @@ -109,13 +110,14 @@ public: MQTTGWPacket* getMQTTGWPacket(void); private: - EventType _eventType; - Client* _client; - SensorNetAddress* _sensorNetAddr; - MQTTSNPacket* _mqttSNPacket; - MQTTGWPacket* _mqttGWPacket; + EventType _eventType {Et_NA}; + Client* _client {nullptr}; + SensorNetAddress* _sensorNetAddr {nullptr}; + MQTTSNPacket* _mqttSNPacket {nullptr}; + MQTTGWPacket* _mqttGWPacket {nullptr}; }; + /*===================================== Class EventQue ====================================*/ @@ -136,41 +138,48 @@ private: Semaphore _sem; }; -/* - * GatewayParams - */ -typedef struct + + +/*===================================== + Class GatewayParams + ====================================*/ +class GatewayParams { - char* configName; - char* clientListName; - char* loginId; - char* password; - uint16_t keepAlive; - uint8_t gatewayId; - uint8_t mqttVersion; - uint16_t maxInflightMsgs; - char* gatewayName; - char* brokerName; - char* port; - char* portSecure; - char* rootCApath; - char* rootCAfile; - char* certKey; - char* privateKey; - char* predefinedTopicFileName; - char* forwarderListName; - char* qosm1proxyName; - char* qosMinusClientListName; -}GatewayParams; +public: + string configDir; + char* configName {nullptr}; + char* clientListName {nullptr}; + char* loginId {nullptr}; + char* password {nullptr}; + uint16_t keepAlive {0}; + uint8_t gatewayId {0}; + uint8_t mqttVersion {0}; + uint16_t maxInflightMsgs {0}; + char* gatewayName {nullptr}; + char* brokerName {nullptr}; + char* port {nullptr}; + char* portSecure {nullptr}; + char* rootCApath {nullptr}; + char* rootCAfile {nullptr}; + char* certKey {nullptr}; + char* privateKey {nullptr}; + char* predefinedTopicFileName {nullptr}; + char* forwarderListName {nullptr}; + char* qosMinusClientListName {nullptr}; + bool clientAuthentication {false}; +}; + + /*===================================== Class Gateway =====================================*/ -class QoSm1Proxy; +class AdapterManager; +class ClientList; class Gateway: public MultiTaskProcess{ public: - Gateway(); + Gateway(void); ~Gateway(); virtual void initialize(int argc, char** argv); void run(void); @@ -179,22 +188,22 @@ public: EventQue* getClientSendQue(void); EventQue* getBrokerSendQue(void); ClientList* getClientList(void); - ForwarderList* getForwarderList(void); SensorNetwork* getSensorNetwork(void); LightIndicator* getLightIndicator(void); GatewayParams* getGWParams(void); - QoSm1Proxy* getQoSm1Proxy(void); + AdapterManager* getAdapterManager(void); + int getParam(const char* parameter, char* value); + bool hasSecureConnection(void); private: - ClientList _clientList; - QoSm1Proxy* _qosm1Proxy; - ForwarderList _forwarderList; + GatewayParams _params; + ClientList* _clientList {nullptr}; EventQue _packetEventQue; EventQue _brokerSendQue; EventQue _clientSendQue; LightIndicator _lightIndicator; - GatewayParams _params; SensorNetwork _sensorNetwork; + AdapterManager* _adapterManager {nullptr}; }; } diff --git a/MQTTSNGateway/src/linux/Threading.cpp b/MQTTSNGateway/src/linux/Threading.cpp index c214a44..b0b3ac4 100644 --- a/MQTTSNGateway/src/linux/Threading.cpp +++ b/MQTTSNGateway/src/linux/Threading.cpp @@ -30,6 +30,20 @@ using namespace std; using namespace MQTTSNGW; +#if defined(OSX) +int sem_timedwait(sem_type sem, const struct timespec *timeout) +{ + int rc = -1; + int64_t tout = timeout->tv_sec * 1000L + tv_nsec * 1000000L + rc = (int)dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, tout)); + if (rc != 0) + { + rc = ETIMEDOUT; + } + return rc; +} +#endif + /*===================================== Class Mutex =====================================*/ diff --git a/MQTTSNGateway/src/mainGateway.cpp b/MQTTSNGateway/src/mainGateway.cpp index 227f9c8..6fcbbc4 100644 --- a/MQTTSNGateway/src/mainGateway.cpp +++ b/MQTTSNGateway/src/mainGateway.cpp @@ -23,19 +23,18 @@ using namespace MQTTSNGW; /* - * Gateway Process + * Gateway Application */ -Gateway* gw = new Gateway(); -PacketHandleTask task1(gw); -ClientRecvTask task2(gw); -ClientSendTask task3(gw); -BrokerRecvTask task4(gw); -BrokerSendTask task5(gw); +Gateway gateway; +PacketHandleTask task1(&gateway); +ClientRecvTask task2(&gateway); +ClientSendTask task3(&gateway); +BrokerRecvTask task4(&gateway); +BrokerSendTask task5(&gateway); int main(int argc, char** argv) { - gw->initialize(argc, argv); - gw->run(); - delete gw; + gateway.initialize(argc, argv); + gateway.run(); return 0; } diff --git a/MQTTSNGateway/src/tests/TestTopicIdMap.cpp b/MQTTSNGateway/src/tests/TestTopicIdMap.cpp index dea9b47..ce3ecb3 100644 --- a/MQTTSNGateway/src/tests/TestTopicIdMap.cpp +++ b/MQTTSNGateway/src/tests/TestTopicIdMap.cpp @@ -34,7 +34,7 @@ TestTopicIdMap::~TestTopicIdMap() bool TestTopicIdMap::testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicTypes type) { - TopicIdMapelement* elm = _map->getElement((uint16_t)msgid ); + TopicIdMapElement* elm = _map->getElement((uint16_t)msgid ); if ( elm ) { //printf("msgid=%d id=%d type=%d\n", msgid, elm->getTopicId(), elm->getTopicType()); From e308c3da83edb7d8cc13f43ff4fbf593df74caeb Mon Sep 17 00:00:00 2001 From: tomoaki Date: Sun, 12 Aug 2018 14:59:51 +0900 Subject: [PATCH 07/10] Correction to eliminate compiler warning message Signed-off-by: tomoaki --- MQTTSNGateway/src/MQTTGWPacket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MQTTSNGateway/src/MQTTGWPacket.cpp b/MQTTSNGateway/src/MQTTGWPacket.cpp index 67ff660..45cb9d8 100644 --- a/MQTTSNGateway/src/MQTTGWPacket.cpp +++ b/MQTTSNGateway/src/MQTTGWPacket.cpp @@ -568,12 +568,12 @@ void MQTTGWPacket::setMsgId(int msgId) { int type = getType(); unsigned char* ptr = 0; - int len = 0; switch ( type ) { case PUBLISH: Publish pub; + pub.topiclen = 0; pub.msgId = 0; getPUBLISH(&pub); pub.msgId = msgId; From f216abd97e4d426137631aa00cf386f0a827c72a Mon Sep 17 00:00:00 2001 From: tomoaki Date: Mon, 13 Aug 2018 06:05:18 +0900 Subject: [PATCH 08/10] BugFix: resource leak Signed-off-by: tomoaki --- MQTTSNGateway/src/MQTTGWPublishHandler.cpp | 21 ++++++++++---------- MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp | 1 - 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/MQTTSNGateway/src/MQTTGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTGWPublishHandler.cpp index b264a36..ce5625d 100644 --- a/MQTTSNGateway/src/MQTTGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTGWPublishHandler.cpp @@ -284,16 +284,9 @@ void MQTTGWPublishHandler::handleAggregatePublish(Client* client, MQTTGWPacket* replyACK(client, &pub, PUBREC); } - MQTTGWPacket* msg = new MQTTGWPacket(); - *msg = *packet; - if ( msg->getType() == 0 ) - { - WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER); - delete msg; - return; - } - string* topicName = new string(pub.topic); + + string* topicName = new string(pub.topic, pub.topiclen); Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); AggregateTopicElement* list = _gateway->getAdapterManager()->createClientList(&topic); if ( list != nullptr ) @@ -305,8 +298,16 @@ void MQTTGWPublishHandler::handleAggregatePublish(Client* client, MQTTGWPacket* Client* devClient = p->getClient(); if ( devClient != nullptr ) { + MQTTGWPacket* msg = new MQTTGWPacket(); + *msg = *packet; + if ( msg->getType() == 0 ) + { + WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER); + delete msg; + break; + } Event* ev = new Event(); - ev->setBrokerRecvEvent(devClient, packet); + ev->setBrokerRecvEvent(devClient, msg); _gateway->getPacketEventQue()->post(ev); } else diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp index 26b1816..1126d52 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp @@ -282,5 +282,4 @@ void MQTTSNPublishHandler::handleAggregateAck(Client* client, MQTTSNPacket* pack ev->setClientSendEvent(client, ackPacket); _gateway->getClientSendQue()->post(ev); } - return; } From 97cffe457365cfd166539d5de5d20b34cfe625d3 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Mon, 13 Aug 2018 21:28:51 +0900 Subject: [PATCH 09/10] Forwerders are declared by the ClientList file. Signed-off-by: tomoaki --- MQTTSNGateway/Makefile | 2 - MQTTSNGateway/README.md | 12 +-- MQTTSNGateway/clients.conf | 22 ++++-- MQTTSNGateway/forwarders.conf | 25 ------- MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp | 66 ----------------- MQTTSNGateway/src/MQTTSNGWAdapterManager.h | 2 +- MQTTSNGateway/src/MQTTSNGWAggregater.cpp | 2 +- MQTTSNGateway/src/MQTTSNGWClientList.cpp | 31 +++++--- MQTTSNGateway/src/MQTTSNGWClientList.h | 8 +- MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp | 77 ++++++++++++++++++-- MQTTSNGateway/src/MQTTSNGWForwarder.cpp | 73 ++----------------- MQTTSNGateway/src/MQTTSNGWForwarder.h | 5 +- MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp | 2 +- MQTTSNGateway/src/MQTTSNGateway.cpp | 30 ++------ MQTTSNGateway/src/MQTTSNGateway.h | 1 - 15 files changed, 131 insertions(+), 227 deletions(-) delete mode 100644 MQTTSNGateway/forwarders.conf diff --git a/MQTTSNGateway/Makefile b/MQTTSNGateway/Makefile index fb4562b..4015b85 100644 --- a/MQTTSNGateway/Makefile +++ b/MQTTSNGateway/Makefile @@ -10,7 +10,6 @@ TESTAPPL := mainTestProcess CONFIG := gateway.conf CLIENTS := clients.conf PREDEFTOPIC := predefinedTopic.conf -FORWARDERS := forwarders.conf SRCDIR := src SUBDIR := ../MQTTSNPacket/src @@ -149,7 +148,6 @@ install: cp -pf $(CONFIG) ../../ cp -pf $(CLIENTS) ../../ cp -pf $(PREDEFTOPIC) ../../ - cp -pf $(FORWARDERS) ../../ exectest: diff --git a/MQTTSNGateway/README.md b/MQTTSNGateway/README.md index 5d1627a..8504eda 100644 --- a/MQTTSNGateway/README.md +++ b/MQTTSNGateway/README.md @@ -36,18 +36,16 @@ BrokerSecurePortNo=8883 # All clients must be specified by the ClientList File # -AggregateGateway=NO -ClientAuthentication=NO - #ClientsList=/path/to/your_clients.conf +ClientAuthentication=NO +AggregateGateway=NO +Forwarder=NO QoS-1=NO OoS-1ProxyName=Proxy007 #PredefinedTopicList=/path/to/your_predefinedTopic.conf -Forwarder=NO -#ForwardersList=/path/to/your_forwarers.conf #RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCApath=/etc/ssl/certs/ @@ -84,11 +82,9 @@ Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW messag when **AggregateGateway** or **ClientAuthentication** is **YES**, All clients which connect to the gateway must be declared by a **ClientsList** file. Format of the file is ClientId and SensorNetwork Address. e.g. IP address and Port No etc, in CSV. more detail see clients.conf When **PredefinedTopic** is **YES**, **Pre-definedTopicId**s specified by **PredefinedTopicList** are effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format. -When **Forwarder** is **YE**S, Forwarder Encapsulation Message is available. Connectable Forwarders are specifed by **ForwardersList** file. In this file, ForwarderIds and those sensorNet addresses are declared in CSV format. +When **Forwarder** is **YE**S, Forwarder Encapsulation Message is available. Connectable Forwarders must be declared by a **ClientsList** file. - - ### ** How to monitor the gateway from remote. ** Uncomment line32 in MQTTSNGWDefined.h. diff --git a/MQTTSNGateway/clients.conf b/MQTTSNGateway/clients.conf index 28d2bab..ddb2310 100644 --- a/MQTTSNGateway/clients.conf +++ b/MQTTSNGateway/clients.conf @@ -15,25 +15,33 @@ # Lines bigning with # are comment line. # ClientId, SensorNetAddress, "unstableLine", "secureConnection" # in case of UDP, SensorNetAddress format is portNo@IPAddress. -# if the SensorNetwork is not stable, write unstableLine. -# if Broker's Connection is SSL, write secureConnection. -# if the client send PUBLISH QoS-1, QoS-1 is required. +# if the SensorNetwork is not stable, write "unstableLine". +# if Broker's Connection is SSL, write "secureConnection". +# if the client is a forwarder, "forwarder" is required. +# if the client send PUBLISH QoS-1, "QoS-1" is required. # # Ex: # #Client List # ClientId1,11200@192.168.10.10 # ClientID2,35000@192.168.50.200,unstableLine # ClientID3,40000@192.168.200.50,secureConnection -# ClientID4,41000@192.168.200.51,unstableLine,secureConnection -# ClientID5,41000@192.168.200.51,unstableLine,secureConnection,QoS-1 +# ClientID4,41000@192.168.200.52,unstableLine,secureConnection +# ClientID5,41000@192.168.200.53,unstableLine,secureConnection,QoS-1 +# ClientID6,41000@192.168.200.54,unstableLine,secureConnection,forwarder # # SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function. # - +GatewayTester, 172.16.1.11:20020 +ClientPUB,172.16.1.11:2010 +Client01,172.16.1.11:12001 Client02,172.16.1.11:12002 Client03,172.16.1.11:13003 -Client01,172.16.1.11:12001 QoS-1_Client01,172.16.1.11:20001,QoS-1 QoS-1_Client02,172.16.1.11:20002,QoS-1 QoS-1_Client03,172.16.1.11:20003,QoS-1 + +Forwarder01,172.16.1.11:22002,forwarder +Forwarder02,172.16.1.11:22003,forwarder +Forwarder03,172.16.1.11:22004,forwarder + diff --git a/MQTTSNGateway/forwarders.conf b/MQTTSNGateway/forwarders.conf deleted file mode 100644 index cfb11dd..0000000 --- a/MQTTSNGateway/forwarders.conf +++ /dev/null @@ -1,25 +0,0 @@ -#*********************************************************************** -# Copyright (c) 2018, 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. -#*********************************************************************** -# -# This file declares valid MQTTSNForwarders. -# Forwarders are defined by ForwarderId same as ClientId and those SensorNetAddress -# in a CSV format as follow: -# -# ForwarderId, SensorNetAddress -# -# where SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function. -# - -Forwarder01,172.16.1.7:12002 - - diff --git a/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp b/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp index 6cbef35..45be65a 100644 --- a/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp +++ b/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp @@ -91,72 +91,6 @@ bool AdapterManager::isAggregatedClient(Client* client) } } - -Client* AdapterManager::getClient(MQTTSNPacket* packet, ClientRecvTask* task) -{ - char buf[128]; - WirelessNodeId nodeId; - SensorNetAddress* senderAddr = _gateway->getSensorNetwork()->getSenderAddress(); - - Client* client = nullptr; - - if ( packet->getType() == MQTTSN_ENCAPSULATED ) - { - Forwarder* fwd = getForwarderList()->getForwarder(senderAddr); - - if ( fwd == nullptr ) - { - task->log(0, packet, 0); - WRITELOG("%s Forwarder %s is not authenticated.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER); - delete packet; - return client; - } - else - { - MQTTSNString fwdName = MQTTSNString_initializer; - fwdName.cstring = const_cast( fwd->getName() ); - task->log(0, packet, &fwdName); - - /* get the packet from the encapsulation message */ - MQTTSNGWEncapsulatedPacket encap; - encap.desirialize(packet->getPacketData(), packet->getPacketLength()); - nodeId.setId( encap.getWirelessNodeId() ); - client = fwd->getClient(&nodeId); - delete packet; - packet = encap.getMQTTSNPacket(); - } - } - else - { - /* Check the client belonging to QoS-1Proxy ? */ - - if ( _qosm1Proxy->isActive() ) - { - /* get ClientId not Client which can send QoS-1 PUBLISH */ - const char* clientName = _qosm1Proxy->getClientId(senderAddr); - - if ( clientName ) - { - if ( !packet->isQoSMinusPUBLISH() ) - { - client = _qosm1Proxy->getClient(); - task->log(clientName, packet); - WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, senderAddr->sprint(buf), ERRMSG_FOOTER); - delete packet; - return client; - } - } - } - } - - if ( client == nullptr ) - { - /* get client from the ClientList of Gateway by sensorNetAddress. */ - client = _gateway->getClientList()->getClient(senderAddr); - } - return client; -} - Client* AdapterManager::getClient(Client& client) { bool secure = client.isSecureNetwork(); diff --git a/MQTTSNGateway/src/MQTTSNGWAdapterManager.h b/MQTTSNGateway/src/MQTTSNGWAdapterManager.h index 749f1a9..510d02f 100644 --- a/MQTTSNGateway/src/MQTTSNGWAdapterManager.h +++ b/MQTTSNGateway/src/MQTTSNGWAdapterManager.h @@ -26,6 +26,7 @@ class Client; class QoSm1Proxy; class Aggregater; class ForwarderList; +class Forwarder; class MQTTSNPacket; class MQTTSNGWPacket; class ClientRecvTask; @@ -46,7 +47,6 @@ public: void checkConnection(void); bool isAggregatedClient(Client* client); - Client* getClient(MQTTSNPacket* packet, ClientRecvTask* task); Client* getClient(Client& client); Client* convertClient(uint16_t msgId, uint16_t* clientMsgId); int unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task); diff --git a/MQTTSNGateway/src/MQTTSNGWAggregater.cpp b/MQTTSNGateway/src/MQTTSNGWAggregater.cpp index a091625..e6765ca 100644 --- a/MQTTSNGateway/src/MQTTSNGWAggregater.cpp +++ b/MQTTSNGateway/src/MQTTSNGWAggregater.cpp @@ -45,7 +45,7 @@ void Aggregater::initialize(void) if (!strcasecmp(param, "YES") ) { /* Create Aggregated Clients */ - _gateway->getClientList()->setClientList(_gateway, AGGREGATER_TYPE); + _gateway->getClientList()->setClientList(AGGREGATER_TYPE); setup((const char*)(_gateway->getGWParams()->gatewayName), Atype_Aggregater); _isActive = true; } diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.cpp b/MQTTSNGateway/src/MQTTSNGWClientList.cpp index 23bdcdd..c0ecf85 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientList.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientList.cpp @@ -15,9 +15,12 @@ * Tieto Poland Sp. z o.o. - Gateway improvements **************************************************************************************/ #include "MQTTSNGWClientList.h" +#include "MQTTSNGateway.h" #include #include +using namespace MQTTSNGW; +extern Gateway* theGateway; /*===================================== Class ClientList =====================================*/ @@ -44,26 +47,26 @@ ClientList::~ClientList() _mutex.unlock(); } -void ClientList::initialize(Gateway* gw, bool aggregate) +void ClientList::initialize(bool aggregate) { - if (gw->getGWParams()->clientAuthentication ) + if (theGateway->getGWParams()->clientAuthentication ) { int type = TRANSPEARENT_TYPE; if ( aggregate ) { type = AGGREGATER_TYPE; } - setClientList(gw, type); + setClientList(type); _authorize = true; } } -void ClientList::setClientList(Gateway* gw, int type) +void ClientList::setClientList(int type) { char param[MQTTSNGW_PARAM_MAX]; string fileName; - GatewayParams* params = gw->getGWParams(); - if (gw->getParam("ClientsList", param) == 0) + GatewayParams* params = theGateway->getGWParams(); + if (theGateway->getParam("ClientsList", param) == 0) { fileName = string(param); } @@ -79,14 +82,14 @@ void ClientList::setClientList(Gateway* gw, int type) params->clientListName = strdup(fileName.c_str()); } -void ClientList::setPredefinedTopics(Gateway* gw, bool aggrecate) +void ClientList::setPredefinedTopics(bool aggrecate) { char param[MQTTSNGW_PARAM_MAX]; string fileName; - GatewayParams* params = gw->getGWParams(); + GatewayParams* params = theGateway->getGWParams(); - if (gw->getParam("PredefinedTopicList", param) == 0) + if (theGateway->getParam("PredefinedTopicList", param) == 0) { fileName = string(param); } @@ -131,6 +134,7 @@ bool ClientList::createList(const char* fileName, int type) bool secure; bool stable; bool qos_1; + bool forwarder; bool rc = true; SensorNetAddress netAddr; MQTTSNString clientId = MQTTSNString_initializer; @@ -160,15 +164,20 @@ bool ClientList::createList(const char* fileName, int type) if (netAddr.setAddress(&addr) == 0) { qos_1 = (data.find("QoS-1") != string::npos); + forwarder = (data.find("forwarder") != string::npos); secure = (data.find("secureConnection") != string::npos); stable = !(data.find("unstableLine") != string::npos); if ( (qos_1 && type == QOSM1PROXY_TYPE) || (!qos_1 && type == AGGREGATER_TYPE) ) { createClient(&netAddr, &clientId, stable, secure, type); } - else + else if ( forwarder && type == FORWARDER_TYPE) { - createClient(&netAddr, &clientId, stable, secure, TRANSPEARENT_TYPE); + theGateway->getAdapterManager()->getForwarderList()->addForwarder(&netAddr, &clientId); + } + else if (type == TRANSPEARENT_TYPE ) + { + createClient(&netAddr, &clientId, stable, secure, type); } } else diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.h b/MQTTSNGateway/src/MQTTSNGWClientList.h index 4e0f81e..135f365 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientList.h +++ b/MQTTSNGateway/src/MQTTSNGWClientList.h @@ -26,6 +26,7 @@ namespace MQTTSNGW #define TRANSPEARENT_TYPE 0 #define QOSM1PROXY_TYPE 1 #define AGGREGATER_TYPE 2 +#define FORWARDER_TYPE 3 class Client; @@ -38,9 +39,9 @@ public: ClientList(); ~ClientList(); - void initialize(Gateway* gw, bool aggregate); - void setClientList(Gateway* gw, int type); - void setPredefinedTopics(Gateway* gw, bool aggregate); + void initialize(bool aggregate); + void setClientList(int type); + void setPredefinedTopics(bool aggregate); void erase(Client*&); Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId,int type); Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type); @@ -54,6 +55,7 @@ public: private: bool readPredefinedList(const char* fileName, bool _aggregate); + Gateway* _gateway {nullptr}; Client* createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t toipcId, bool _aggregate); Client* _firstClient; Client* _endClient; diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp index b1e805a..7e70a52 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp @@ -60,6 +60,7 @@ void ClientRecvTask::run() Event* ev = nullptr; Client* client = nullptr; AdapterManager* adpMgr = _gateway->getAdapterManager(); + QoSm1Proxy* qosm1Proxy = adpMgr->getQoSm1Proxy(); bool isAggrActive = adpMgr->isAggregaterActive(); ClientList* clientList = _gateway->getClientList(); EventQue* packetEventQue = _gateway->getPacketEventQue(); @@ -103,7 +104,60 @@ void ClientRecvTask::run() continue; } - client = adpMgr->getClient(packet, this); + + Client* client = nullptr; + SensorNetAddress* senderAddr = _gateway->getSensorNetwork()->getSenderAddress(); + + if ( packet->getType() == MQTTSN_ENCAPSULATED ) + { + fwd = _gateway->getAdapterManager()->getForwarderList()->getForwarder(senderAddr); + + if ( fwd != nullptr ) + { + MQTTSNString fwdName = MQTTSNString_initializer; + fwdName.cstring = const_cast( fwd->getName() ); + log(0, packet, &fwdName); + + /* get the packet from the encapsulation message */ + MQTTSNGWEncapsulatedPacket encap; + encap.desirialize(packet->getPacketData(), packet->getPacketLength()); + nodeId.setId( encap.getWirelessNodeId() ); + client = fwd->getClient(&nodeId); + packet = encap.getMQTTSNPacket(); + + if ( client == nullptr ) + { + /* get client of Forwarder or QoSm1Proxy */ + client = _gateway->getClientList()->getClient(senderAddr); + } + } + } + else + { + /* Check the client belonging to QoS-1Proxy ? */ + + if ( qosm1Proxy->isActive() ) + { + /* get ClientId not Client which can send QoS-1 PUBLISH */ + const char* clientName = qosm1Proxy->getClientId(senderAddr); + + if ( clientName ) + { + if ( !packet->isQoSMinusPUBLISH() ) + { + client = qosm1Proxy->getClient(); + log(clientName, packet); + WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, senderAddr->sprint(buf), ERRMSG_FOOTER); + delete packet; + continue; + } + } + else + { + client = _gateway->getClientList()->getClient(senderAddr); + } + } + } if ( client ) { @@ -123,7 +177,7 @@ void ClientRecvTask::run() if ( !packet->getCONNECT(&data) ) { log(0, packet, &data.clientID); - WRITELOG("%s CONNECT message form %s is incorrect.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); + WRITELOG("%s CONNECT message form %s is incorrect.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER); delete packet; continue; } @@ -145,12 +199,12 @@ void ClientRecvTask::run() if ( client ) { /* Client exists. Set SensorNet Address of it. */ - client->setClientAddress(_sensorNetwork->getSenderAddress()); + client->setClientAddress(senderAddr); } else { /* create a new client */ - client = clientList->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, isAggrActive); + client = clientList->createClient(senderAddr, &data.clientID, isAggrActive); } } @@ -158,7 +212,7 @@ void ClientRecvTask::run() if (!client) { - WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); + WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER); delete packet; continue; } @@ -168,11 +222,18 @@ void ClientRecvTask::run() ev->setClientRecvEvent(client, packet); packetEventQue->post(ev); } - else + else { log(client, packet, 0); - WRITELOG("%s Client(%s) is not connecting. message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); - delete packet; + if ( packet->getType() == MQTTSN_ENCAPSULATED ) + { + WRITELOG("%s Forwarder(%s) is not declared by ClientList file. message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); + } + else + { + WRITELOG("%s Client(%s) is not connecting. message has been discarded.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER); + } + delete packet; } } } diff --git a/MQTTSNGateway/src/MQTTSNGWForwarder.cpp b/MQTTSNGateway/src/MQTTSNGWForwarder.cpp index 20a05e9..5fa2a49 100644 --- a/MQTTSNGateway/src/MQTTSNGWForwarder.cpp +++ b/MQTTSNGateway/src/MQTTSNGWForwarder.cpp @@ -14,6 +14,7 @@ * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ #include "MQTTSNGWForwarder.h" +#include "SensorNetwork.h" #include @@ -48,25 +49,12 @@ void ForwarderList::initialize(Gateway* gw) { char param[MQTTSNGW_PARAM_MAX]; string fileName; - GatewayParams* params = gw->getGWParams(); if (gw->getParam("Forwarder", param) == 0 ) { if (!strcasecmp(param, "YES") ) { - if (gw->getParam("ForwardersList", param) == 0) - { - fileName = string(param); - } - else - { - fileName = params->configDir + string(FORWARDER_LIST); - } - if ( !setFowerder(fileName.c_str()) ) - { - throw Exception("ForwarderList::initialize: No ForwardersList file defined by the configuration.."); - } - params->forwarderListName = strdup(fileName.c_str()); + gw->getClientList()->setClientList(FORWARDER_TYPE); } } } @@ -86,58 +74,7 @@ Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr) return p; } -bool ForwarderList::setFowerder(const char* fileName) -{ - FILE* fp; - char buf[MAX_CLIENTID_LENGTH + 256]; - size_t pos; - - SensorNetAddress netAddr; - - if ((fp = fopen(fileName, "r")) != 0) - { - while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0) - { - if (*buf == '#') - { - continue; - } - string data = string(buf); - while ((pos = data.find_first_of("  \t\n")) != string::npos) - { - data.erase(pos, 1); - } - if (data.empty()) - { - continue; - } - - pos = data.find_first_of(","); - string id = data.substr(0, pos); - string addr = data.substr(pos + 1); - - if (netAddr.setAddress(&addr) == 0) - { - addForwarder(&netAddr, &id); - } - else - { - WRITELOG("Invalid address %s\n", data.c_str()); - return false; - } - } - fclose(fp); - } - else - { - WRITELOG("Can not open the forwarders List. %s\n", fileName); - return false; - } - return true; -} - - -Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, string* forwarderId) +Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId) { Forwarder* fdr = new Forwarder(addr, forwarderId); if ( _head == nullptr ) @@ -173,9 +110,9 @@ Forwarder::Forwarder() Class ForwarderList =====================================*/ -Forwarder::Forwarder(SensorNetAddress* addr, string* forwarderId) +Forwarder::Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId) { - _forwarderName = *forwarderId; + _forwarderName = string(forwarderId->cstring); _sensorNetAddr = *addr; _headClient = nullptr; _next = nullptr; diff --git a/MQTTSNGateway/src/MQTTSNGWForwarder.h b/MQTTSNGateway/src/MQTTSNGWForwarder.h index 354067f..a7279d2 100644 --- a/MQTTSNGateway/src/MQTTSNGWForwarder.h +++ b/MQTTSNGateway/src/MQTTSNGWForwarder.h @@ -55,7 +55,7 @@ class Forwarder friend class ForwarderList; public: Forwarder(void); - Forwarder(SensorNetAddress* addr, string* forwarderId); + Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId); ~Forwarder(); void initialize(void); @@ -86,8 +86,7 @@ public: void initialize(Gateway* gw); Forwarder* getForwarder(SensorNetAddress* addr); - bool setFowerder(const char* fileName); - Forwarder* addForwarder(SensorNetAddress* addr, string* forwarderId); + Forwarder* addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId); private: Forwarder* _head; diff --git a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp index 2021e17..591043e 100644 --- a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp +++ b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp @@ -52,7 +52,7 @@ void QoSm1Proxy::initialize(void) if (strcasecmp(param, "YES") == 0 ) { /* Create QoS-1 Clients */ - _gateway->getClientList()->setClientList(_gateway, QOSM1PROXY_TYPE); + _gateway->getClientList()->setClientList(QOSM1PROXY_TYPE); /* set ClientId of this Proxy */ const char* name = CLIENTPROXY; diff --git a/MQTTSNGateway/src/MQTTSNGateway.cpp b/MQTTSNGateway/src/MQTTSNGateway.cpp index 2192850..25ab87f 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.cpp +++ b/MQTTSNGateway/src/MQTTSNGateway.cpp @@ -28,6 +28,8 @@ char* currentDateTime(void); /*===================================== Class Gateway =====================================*/ +MQTTSNGW::Gateway* theGateway = nullptr; + Gateway::Gateway(void) { theMultiTaskProcess = this; @@ -87,14 +89,7 @@ Gateway::~Gateway() { free(_params.configName); } - if ( _params.predefinedTopicFileName ) - { - free(_params.predefinedTopicFileName); - } - if ( _params.forwarderListName ) - { - free(_params.forwarderListName); - } + if ( _params.qosMinusClientListName ) { free(_params.qosMinusClientListName); @@ -119,6 +114,7 @@ void Gateway::initialize(int argc, char** argv) { char param[MQTTSNGW_PARAM_MAX]; string fileName; + theGateway = this; MultiTaskProcess::initialize(argc, argv); resetRingBuffer(); @@ -222,10 +218,10 @@ void Gateway::initialize(int argc, char** argv) _adapterManager->initialize(); bool aggregate = _adapterManager->isAggregaterActive(); - _clientList->initialize(this, aggregate); + _clientList->initialize(aggregate); /* Setup predefined topics */ - _clientList->setPredefinedTopics(this, aggregate); + _clientList->setPredefinedTopics(aggregate); } void Gateway::run(void) @@ -242,9 +238,9 @@ void Gateway::run(void) WRITELOG("\n%s %s has been started.\n\n", currentDateTime(), _params.gatewayName); WRITELOG(" ConfigFile: %s\n", _params.configName); - if ( getClientList()->isAuthorized() ) + if ( _params.clientListName ) { - WRITELOG(" ClientList: %s\n", _params.clientListName); + WRITELOG(" ClientList: %s\n", _params.clientListName); } if ( _params.predefinedTopicFileName ) @@ -252,16 +248,6 @@ void Gateway::run(void) WRITELOG(" PreDefFile: %s\n", _params.predefinedTopicFileName); } - if ( _params.forwarderListName ) - { - WRITELOG(" Forwarders: %s\n", _params.forwarderListName); - } - - if ( _params.qosMinusClientListName ) - { - WRITELOG(" QoS-1File: %s\n", _params.qosMinusClientListName); - } - WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription()); WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); WRITELOG(" RootCApath: %s\n", _params.rootCApath); diff --git a/MQTTSNGateway/src/MQTTSNGateway.h b/MQTTSNGateway/src/MQTTSNGateway.h index 2507de5..3344cfa 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.h +++ b/MQTTSNGateway/src/MQTTSNGateway.h @@ -164,7 +164,6 @@ public: char* certKey {nullptr}; char* privateKey {nullptr}; char* predefinedTopicFileName {nullptr}; - char* forwarderListName {nullptr}; char* qosMinusClientListName {nullptr}; bool clientAuthentication {false}; }; From 9de1dc37058ec7e6f0948e450f58c57317de0691 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Tue, 14 Aug 2018 08:11:11 +0900 Subject: [PATCH 10/10] Generate the QoSm1Proxy Name from the Gateway Id. Bugfix of AggregatePublish Memory leak of ClientList Signed-off-by: tomoaki --- MQTTSNGateway/README.md | 16 ++++++++-------- MQTTSNGateway/gateway.conf | 10 +++------- MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp | 3 ++- MQTTSNGateway/src/MQTTSNGWAggregater.cpp | 4 +++- MQTTSNGateway/src/MQTTSNGWClientList.cpp | 6 +++++- MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp | 18 ++++-------------- MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp | 10 +++++----- MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp | 9 ++------- MQTTSNGateway/src/MQTTSNGateway.h | 2 -- 9 files changed, 32 insertions(+), 46 deletions(-) diff --git a/MQTTSNGateway/README.md b/MQTTSNGateway/README.md index 8504eda..e04ffa6 100644 --- a/MQTTSNGateway/README.md +++ b/MQTTSNGateway/README.md @@ -36,17 +36,16 @@ BrokerSecurePortNo=8883 # All clients must be specified by the ClientList File # -#ClientsList=/path/to/your_clients.conf - ClientAuthentication=NO AggregateGateway=NO -Forwarder=NO QoS-1=NO -OoS-1ProxyName=Proxy007 +Forwarder=NO +#ClientsList=/path/to/your_clients.conf + +PredefinedTopic=NO #PredefinedTopicList=/path/to/your_predefinedTopic.conf - #RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCApath=/etc/ssl/certs/ #CertsFile=/path/to/certKey.pem @@ -79,10 +78,11 @@ ShearedMemory=NO; Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW message. **GatewayId** is used by GWINFO message. **KeepAlive** is a duration of ADVERTISE message in seconds. -when **AggregateGateway** or **ClientAuthentication** is **YES**, All clients which connect to the gateway must be declared by a **ClientsList** file. -Format of the file is ClientId and SensorNetwork Address. e.g. IP address and Port No etc, in CSV. more detail see clients.conf +when **AggregateGateway** or **ClientAuthentication** is **YES**, All clients which connect to the gateway must be declared by a **ClientsList** file. +Format of the file is ClientId and SensorNetwork Address. e.g. IP address and Port No etc, in CSV. more detail see clients.conf. +When **QoS-1** is **YES**, QoS-1 PUBLISH is available. All clients which send QoS-1 PUBLISH must be specified by Client.conf file. When **PredefinedTopic** is **YES**, **Pre-definedTopicId**s specified by **PredefinedTopicList** are effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format. -When **Forwarder** is **YE**S, Forwarder Encapsulation Message is available. Connectable Forwarders must be declared by a **ClientsList** file. +When **Forwarder** is **YES**, Forwarder Encapsulation Message is available. Connectable Forwarders must be declared by a **ClientsList** file. ### ** How to monitor the gateway from remote. ** diff --git a/MQTTSNGateway/gateway.conf b/MQTTSNGateway/gateway.conf index e2a1d25..52481de 100644 --- a/MQTTSNGateway/gateway.conf +++ b/MQTTSNGateway/gateway.conf @@ -23,20 +23,16 @@ BrokerSecurePortNo=8883 # All clients must be specified by the ClientList File # -AggregateGateway=NO ClientAuthentication=NO +AggregateGateway=NO +QoS-1=NO +Forwarder=NO #ClientsList=/path/to/your_clients.conf -QoS-1=NO -OoS-1ProxyName=Proxy007 - PredefinedTopic=NO #PredefinedTopicList=/path/to/your_predefinedTopic.conf -Forwarder=NO -#ForwardersList=/path/to/your_forwarers.conf - #RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCApath=/etc/ssl/certs/ #CertsFile=/path/to/certKey.pem diff --git a/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp b/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp index 45be65a..935d58d 100644 --- a/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp +++ b/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp @@ -150,7 +150,8 @@ void AdapterManager::checkConnection(void) { _aggregater->checkConnection(); } - else if ( _qosm1Proxy->isActive()) + + if ( _qosm1Proxy->isActive()) { _qosm1Proxy->checkConnection(); } diff --git a/MQTTSNGateway/src/MQTTSNGWAggregater.cpp b/MQTTSNGateway/src/MQTTSNGWAggregater.cpp index e6765ca..1eceedd 100644 --- a/MQTTSNGateway/src/MQTTSNGWAggregater.cpp +++ b/MQTTSNGateway/src/MQTTSNGWAggregater.cpp @@ -46,7 +46,9 @@ void Aggregater::initialize(void) { /* Create Aggregated Clients */ _gateway->getClientList()->setClientList(AGGREGATER_TYPE); - setup((const char*)(_gateway->getGWParams()->gatewayName), Atype_Aggregater); + + string name = _gateway->getGWParams()->gatewayName; + setup(name.c_str(), Atype_Aggregater); _isActive = true; } } diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.cpp b/MQTTSNGateway/src/MQTTSNGWClientList.cpp index c0ecf85..488944b 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientList.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientList.cpp @@ -79,7 +79,11 @@ void ClientList::setClientList(int type) { throw Exception("ClientList::initialize(): No client list defined by the configuration."); } - params->clientListName = strdup(fileName.c_str()); + + if ( params->clientListName == nullptr ) + { + params->clientListName = strdup(fileName.c_str()); + } } void ClientList::setPredefinedTopics(bool aggrecate) diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp index 7e70a52..b927532 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp @@ -58,7 +58,6 @@ void ClientRecvTask::initialize(int argc, char** argv) void ClientRecvTask::run() { Event* ev = nullptr; - Client* client = nullptr; AdapterManager* adpMgr = _gateway->getAdapterManager(); QoSm1Proxy* qosm1Proxy = adpMgr->getQoSm1Proxy(); bool isAggrActive = adpMgr->isAggregaterActive(); @@ -69,6 +68,7 @@ void ClientRecvTask::run() while (true) { + Client* client = nullptr; Forwarder* fwd = nullptr; WirelessNodeId nodeId; @@ -105,7 +105,6 @@ void ClientRecvTask::run() } - Client* client = nullptr; SensorNetAddress* senderAddr = _gateway->getSensorNetwork()->getSenderAddress(); if ( packet->getType() == MQTTSN_ENCAPSULATED ) @@ -124,12 +123,6 @@ void ClientRecvTask::run() nodeId.setId( encap.getWirelessNodeId() ); client = fwd->getClient(&nodeId); packet = encap.getMQTTSNPacket(); - - if ( client == nullptr ) - { - /* get client of Forwarder or QoSm1Proxy */ - client = _gateway->getClientList()->getClient(senderAddr); - } } } else @@ -138,8 +131,7 @@ void ClientRecvTask::run() if ( qosm1Proxy->isActive() ) { - /* get ClientId not Client which can send QoS-1 PUBLISH */ - const char* clientName = qosm1Proxy->getClientId(senderAddr); + const char* clientName = qosm1Proxy->getClientId(senderAddr); if ( clientName ) { @@ -152,13 +144,11 @@ void ClientRecvTask::run() continue; } } - else - { - client = _gateway->getClientList()->getClient(senderAddr); - } } } + client = _gateway->getClientList()->getClient(senderAddr); + if ( client ) { /* write log and post Event */ diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp index 1126d52..53bbb43 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp @@ -114,17 +114,17 @@ MQTTGWPacket* MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* MQTTGWPacket* publish = new MQTTGWPacket(); publish->setPUBLISH(&pub); - if ( !_gateway->getAdapterManager()->isAggregaterActive() ) + if ( _gateway->getAdapterManager()->isAggregaterActive() && client->isAggregated() ) + { + return publish; + } + else { Event* ev1 = new Event(); ev1->setBrokerSendEvent(client, publish); _gateway->getBrokerSendQue()->post(ev1); return nullptr; } - else - { - return publish; - } } void MQTTSNPublishHandler::handlePuback(Client* client, MQTTSNPacket* packet) diff --git a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp index 591043e..50ff56c 100644 --- a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp +++ b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp @@ -54,14 +54,9 @@ void QoSm1Proxy::initialize(void) /* Create QoS-1 Clients */ _gateway->getClientList()->setClientList(QOSM1PROXY_TYPE); - /* set ClientId of this Proxy */ - const char* name = CLIENTPROXY; - if (_gateway->getParam("QoS-1ProxyName", param) == 0 ) - { - name = param; - } /* initialize Adapter */ - setup(name, Atype_QoSm1Proxy); + string name = string(_gateway->getGWParams()->gatewayName) + "QoS-1"; + setup(name.c_str(), Atype_QoSm1Proxy); _isActive = true; } } diff --git a/MQTTSNGateway/src/MQTTSNGateway.h b/MQTTSNGateway/src/MQTTSNGateway.h index 3344cfa..b4c0f5c 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.h +++ b/MQTTSNGateway/src/MQTTSNGateway.h @@ -43,8 +43,6 @@ namespace MQTTSNGW #define CLIENT "Client" #define CLIENTS "Clients" #define UNKNOWNCL "Unknown Client !" -#define CLIENTPROXY "ClientProxy" -#define CLIENTPROXY_SECURE "ClientProxyS" #define LEFTARROW "<---" #define RIGHTARROW "--->"