Merge pull request #128 from eclipse/develop

You can select Aggregate or Transparent gateway in the config file setting.
This commit is contained in:
Tomoaki Yamaguchi
2018-08-14 08:22:27 +09:00
committed by GitHub
72 changed files with 5464 additions and 2185 deletions

View File

@@ -14,7 +14,7 @@
</extensions> </extensions>
</storageModule> </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> <storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1685199227" name="Debug" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=" parent="cdt.managedbuild.config.gnu.exe.debug"> <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1685199227" name="Debug" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.exe.debug">
<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1685199227." name="/" resourcePath=""> <folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1685199227." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.102264757" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug"> <toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.102264757" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.2137160061" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/> <targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.2137160061" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
@@ -66,7 +66,7 @@
</toolChain> </toolChain>
</folderInfo> </folderInfo>
<sourceEntries> <sourceEntries>
<entry excluding="MQTTSNGateway/src/linux/xbee|MQTTSNGateway/src/linux/udp6|MQTTSNGateway/src/tests|MQTTSNGateway/GatewayTester|MQTTSNGateway/GatewayTester/samples/mainTest.cpp|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|MQTTSNGateway/src/tests/mainTestProcessFramework.cpp|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNPacket/test|MQTTSNPacket/samples" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> <entry excluding="MQTTSNGateway/src/MQTTSNGWProxy.cpp|MQTTSNGateway/src/linux/udp6|MQTTSNGateway/GatewayTester/samples/mainTest.cpp|MQTTSNPacket/test|MQTTSNPacket/samples|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNGateway/src/linux/xbee|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|MQTTSNGateway/src/tests|MQTTSNGateway/src/tests/mainTestProcessFramework.cpp|MQTTSNGateway/GatewayTester|ClientPubQoS-1|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries> </sourceEntries>
</configuration> </configuration>
</storageModule> </storageModule>
@@ -136,8 +136,8 @@
</toolChain> </toolChain>
</folderInfo> </folderInfo>
<sourceEntries> <sourceEntries>
<entry excluding="MQTTSNGateway/GatewayTester|MQTTSNGateway/GatewayTester/samples/mainTest.cpp|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp|MQTTSNPacket/src|MQTTSNGateway/src|MQTTSNGateway/src/linux|MQTTSNGateway/src/linux/udp|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNGateway/src/linux/xbee|MQTTSNPacket/test|MQTTSNPacket/samples" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> <entry excluding="MQTTSNGateway/src/linux/udp|MQTTSNPacket/test|MQTTSNPacket/samples|MQTTSNGateway/src/linux|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp|MQTTSNGateway/GatewayTester/samples/mainTest.cpp|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|MQTTSNGateway/src/linux/xbee|MQTTSNGateway/src|MQTTSNPacket/src|MQTTSNGateway/GatewayTester|ClientPubQoS-1" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="tests|tests/mainTestProcessFramework.cpp|mainLogmonitor.cpp|linux|linux/udp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway/src"/> <entry excluding="MQTTSNGWProxy.cpp|mainLogmonitor.cpp|tests|tests/mainTestProcessFramework.cpp|linux|linux/udp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway/src"/>
<entry excluding="xbee|udp6" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway/src/linux"/> <entry excluding="xbee|udp6" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway/src/linux"/>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket/src"/> <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket/src"/>
</sourceEntries> </sourceEntries>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.config.gnu.exe.debug.1685199227" name="Debug">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-181211225584734458" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
<configuration id="cdt.managedbuild.config.gnu.exe.release.561557339" name="Release">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-181211225584734458" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>

View File

@@ -1,7 +1,6 @@
language: cpp language: cpp
compiler: compiler:
- g++ - g++
- clang
install: install:
- if ["$CXX" = "g++" ]; then export CXX="g++-4.8"; fi - if ["$CXX" = "g++" ]; then export CXX="g++-4.8"; fi
@@ -14,7 +13,6 @@ addons:
- g++-4.8 - g++-4.8
- cmake - cmake
- cmake-data - cmake-data
- clang
script: script:
- ./travis-build.sh - ./travis-build.sh

View File

@@ -7,9 +7,13 @@ PUBAPPL := mainPub
PRGSUB := MQTT-SNSub PRGSUB := MQTT-SNSub
SUBAPPL := mainSub SUBAPPL := mainSub
PRGQOS := MQTT-SNPubQoS-1
QOSAPPL := mainPubQoS-1
SRCDIR := samples SRCDIR := samples
SRCPUB := ClientPub SRCPUB := ClientPub
SRCSUB := ClientSub SRCSUB := ClientSub
SRCQOS := ClientPubQoS-1
SUBDIR := src SUBDIR := src
CPPSRCS := \ CPPSRCS := \
@@ -46,10 +50,11 @@ DEPS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.d)
PROGPUB := $(OUTDIR)/$(PRGPUB) PROGPUB := $(OUTDIR)/$(PRGPUB)
PROGSUB := $(OUTDIR)/$(PRGSUB) PROGSUB := $(OUTDIR)/$(PRGSUB)
PROGQOS := $(OUTDIR)/$(PRGQOS)
.PHONY: install clean .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 $(PROGSUB): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/$(SUBAPPL).o
$(CXX) $(LDFLAGS) -o $(PROGSUB) $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/$(SUBAPPL).o $(OBJS) $(LIBS) $(LDADD) $(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 $(OUTDIR)/$(SUBDIR)/%.o:$(SUBDIR)/%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi @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 $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/%.o:$(SRCDIR)/$(SRCSUB)%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< $(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: clean:
rm -rf $(OUTDIR) rm -rf $(OUTDIR)
@@ -88,4 +100,5 @@ install:
cp -pf $(PROG) ../../../ cp -pf $(PROG) ../../../
cp -pf $(PROGPUB) ../../../ cp -pf $(PROGPUB) ../../../
cp -pf $(PROGSUB) ../../../ cp -pf $(PROGSUB) ../../../
cp -pf $(PROGQOS) ../../../

View File

@@ -52,10 +52,10 @@ extern LScreen* theScreen;
* UDP Configuration (theNetcon) * UDP Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
UDPCONF = { UDPCONF = {
"GatewayTestPubClient", // ClientId "ClientPUB", // ClientId
{225,1,1,1}, // Multicast group IP {225,1,1,1}, // Multicast group IP
1883, // Multicast group Port 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) void setup(void)
{ {
SetForwarderMode(false);
} }

View File

@@ -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 = {
"QoS-1_Client01", // 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 ********************/

View File

@@ -52,10 +52,10 @@ extern LScreen* theScreen;
* UDP Configuration (theNetcon) * UDP Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
UDPCONF = { UDPCONF = {
"ty4twGatewaySubClient", // ClientId "ClientSUB", // ClientId
{225,1,1,1}, // Multicast group IP {225,1,1,1}, // Multicast group IP
1883, // Multicast group Port 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) void setup(void)
{ {
SetForwarderMode(false);
} }

View File

@@ -55,7 +55,7 @@ UDPCONF = {
"GatewayTestClient", // ClientId "GatewayTestClient", // ClientId
{225,1,1,1}, // Multicast group IP {225,1,1,1}, // Multicast group IP
1883, // Multicast group Port 1883, // Multicast group Port
20001, // Local PortNo 20020, // Local PortNo
}; };
/*------------------------------------------------------ /*------------------------------------------------------
@@ -220,7 +220,7 @@ TASK_LIST = {// e.g. TASK( task, executing duration in second),
*------------------------------------------------------*/ *------------------------------------------------------*/
void setup(void) void setup(void)
{ {
//SetForwarderMode(); SetForwarderMode(false);
} }

View File

@@ -30,21 +30,16 @@ extern uint16_t getUint16(const uint8_t* pos);
extern LMqttsnClient* theClient; extern LMqttsnClient* theClient;
extern LScreen* theScreen; extern LScreen* theScreen;
/*===================================== /*=====================================
Class GwProxy Class GwProxy
======================================*/ ======================================*/
static const char* packet_names[] = static const char* packet_names[] = { "ADVERTISE", "SEARCHGW", "GWINFO", "RESERVED", "CONNECT", "CONNACK",
{ "WILLTOPICREQ", "WILLTOPIC", "WILLMSGREQ", "WILLMSG", "REGISTER", "REGACK", "PUBLISH", "PUBACK", "PUBCOMP",
"ADVERTISE", "SEARCHGW", "GWINFO", "RESERVED", "CONNECT", "CONNACK", "PUBREC", "PUBREL", "RESERVED", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP",
"WILLTOPICREQ", "WILLTOPIC", "WILLMSGREQ", "WILLMSG", "REGISTER", "REGACK", "DISCONNECT", "RESERVED", "WILLTOPICUPD", "WILLTOPICRESP", "WILLMSGUPD", "WILLMSGRESP" };
"PUBLISH", "PUBACK", "PUBCOMP", "PUBREC", "PUBREL", "RESERVED",
"SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP",
"DISCONNECT", "RESERVED", "WILLTOPICUPD", "WILLTOPICRESP", "WILLMSGUPD",
"WILLMSGRESP"
};
LGwProxy::LGwProxy(){ LGwProxy::LGwProxy()
{
_nextMsgId = 0; _nextMsgId = 0;
_status = GW_LOST; _status = GW_LOST;
_gwId = 0; _gwId = 0;
@@ -61,13 +56,16 @@ LGwProxy::LGwProxy(){
_tWake = 0; _tWake = 0;
_initialized = 0; _initialized = 0;
_isForwarderMode = false; _isForwarderMode = false;
_isQoSMinus1Mode = false;
} }
LGwProxy::~LGwProxy(){ LGwProxy::~LGwProxy()
{
_topicTbl.clearTopic(); _topicTbl.clearTopic();
} }
void LGwProxy::initialize(LUdpConfig netconf, LMqttsnConfig mqconf){ void LGwProxy::initialize(LUdpConfig netconf, LMqttsnConfig mqconf)
{
_network.initialize(netconf); _network.initialize(netconf);
_clientId = netconf.clientId; _clientId = netconf.clientId;
_willTopic = mqconf.willTopic; _willTopic = mqconf.willTopic;
@@ -79,78 +77,105 @@ void LGwProxy::initialize(LUdpConfig netconf, LMqttsnConfig mqconf){
_initialized = 1; _initialized = 1;
} }
void LGwProxy::connect(){ void LGwProxy::connect()
{
char* pos; char* pos;
while (_status != GW_CONNECTED){ while (_status != GW_CONNECTED)
{
pos = _msg; pos = _msg;
if (_status == GW_SEND_WILLMSG){ if (_status == GW_LOST)
*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){
*pos++ = 3; *pos++ = 3;
*pos++ = MQTTSN_TYPE_SEARCHGW; *pos++ = MQTTSN_TYPE_SEARCHGW;
*pos = 0; // SERCHGW *pos = 0; // SERCHGW
_status = GW_SEARCHING; _status = GW_SEARCHING;
writeGwMsg(); 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(); getConnectResponce();
} }
return; return;
} }
int LGwProxy::getConnectResponce(void){ int LGwProxy::getConnectResponce(void)
{
int len = readMsg(); int len = readMsg();
if (len == 0){ if (len == 0)
if (_sendUTC + MQTTSN_TIME_RETRY < time(NULL)){ {
if (_sendUTC + MQTTSN_TIME_RETRY < time(NULL))
{
if (_msg[1] == MQTTSN_TYPE_CONNECT) if (_msg[1] == MQTTSN_TYPE_CONNECT)
{ {
_connectRetry--; _connectRetry--;
} }
if (--_retryCount > 0){ if (--_retryCount > 0)
writeMsg((const uint8_t*)_msg); // Not writeGwMsg() : not to reset the counter. {
writeMsg((const uint8_t*) _msg); // Not writeGwMsg() : not to reset the counter.
_sendUTC = time(NULL); _sendUTC = time(NULL);
}else{ }
else
{
_sendUTC = 0; _sendUTC = 0;
if ( _status > GW_SEARCHING && _connectRetry > 0){ if (_status > GW_SEARCHING && _connectRetry > 0)
{
_status = GW_CONNECTING; _status = GW_CONNECTING;
}else{ }
else
{
_status = GW_LOST; _status = GW_LOST;
_gwId = 0; _gwId = 0;
} }
@@ -158,66 +183,87 @@ int LGwProxy::getConnectResponce(void){
} }
} }
return 0; return 0;
}else if (_mqttsnMsg[0] == MQTTSN_TYPE_GWINFO && _status == GW_SEARCHING){ }
else if (_mqttsnMsg[0] == MQTTSN_TYPE_GWINFO && _status == GW_SEARCHING)
{
_network.setGwAddress(); _network.setGwAddress();
_gwId = _mqttsnMsg[1]; _gwId = _mqttsnMsg[1];
_status = GW_CONNECTING; _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; _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; _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; _status = GW_CONNECTED;
_connectRetry = MQTTSN_RETRY_COUNT; _connectRetry = MQTTSN_RETRY_COUNT;
setPingReqTimer(); setPingReqTimer();
if ( _tSleep ){ if (_tSleep)
{
_tSleep = 0; _tSleep = 0;
}else{ }
else
{
DISPLAY("\033[0m\033[0;32m\n\n Connected to the Broker\033[0m\033[0;37m\n\n"); 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(); _topicTbl.clearTopic();
_initialized = 0; _initialized = 0;
theClient->onConnect(); // SUBSCRIBEs are conducted theClient->onConnect(); // SUBSCRIBEs are conducted
} }
} }
}else{ }
else
{
_status = GW_CONNECTING; _status = GW_CONNECTING;
} }
} }
return 1; return 1;
} }
void LGwProxy::reconnect(void){ void LGwProxy::reconnect(void)
{
D_MQTTLOG("...Gateway reconnect\r\n"); D_MQTTLOG("...Gateway reconnect\r\n");
_status = GW_DISCONNECTED; _status = GW_DISCONNECTED;
connect(); connect();
} }
void LGwProxy::disconnect(uint16_t secs){ void LGwProxy::disconnect(uint16_t secs)
{
_tSleep = secs; _tSleep = secs;
_tWake = 0; _tWake = 0;
_msg[1] = MQTTSN_TYPE_DISCONNECT; _msg[1] = MQTTSN_TYPE_DISCONNECT;
if (secs){ if (secs)
{
_msg[0] = 4; _msg[0] = 4;
setUint16((uint8_t*) _msg + 2, secs); setUint16((uint8_t*) _msg + 2, secs);
_status = GW_SLEEPING; _status = GW_SLEEPING;
}else{ }
else
{
_msg[0] = 2; _msg[0] = 2;
_keepAliveTimer.stop(); _keepAliveTimer.stop();
_status = GW_DISCONNECTING; _status = GW_DISCONNECTING;
} }
_retryCount = MQTTSN_RETRY_COUNT; _retryCount = MQTTSN_RETRY_COUNT;
writeMsg((const uint8_t*)_msg); writeMsg((const uint8_t*) _msg);
_sendUTC = time(NULL); _sendUTC = time(NULL);
while ( _status != GW_DISCONNECTED && _status != GW_SLEPT){ while (_status != GW_DISCONNECTED && _status != GW_SLEPT)
if (getDisconnectResponce() < 0){ {
if (getDisconnectResponce() < 0)
{
_status = GW_LOST; _status = GW_LOST;
DISPLAY("\033[0m\033[0;31m\n\n!!!!!! DISCONNECT Error !!!!!\033[0m\033[0;37m \n\n"); DISPLAY("\033[0m\033[0;31m\n\n!!!!!! DISCONNECT Error !!!!!\033[0m\033[0;37m \n\n");
return; return;
@@ -225,48 +271,63 @@ void LGwProxy::disconnect(uint16_t secs){
} }
} }
int LGwProxy::getDisconnectResponce(void){ int LGwProxy::getDisconnectResponce(void)
{
int len = readMsg(); int len = readMsg();
if (len == 0){ if (len == 0)
if (_sendUTC + MQTTSN_TIME_RETRY < time(NULL)){ {
if (--_retryCount >= 0){ if (_sendUTC + MQTTSN_TIME_RETRY < time(NULL))
writeMsg((const uint8_t*)_msg); {
if (--_retryCount >= 0)
{
writeMsg((const uint8_t*) _msg);
_sendUTC = time(NULL); _sendUTC = time(NULL);
}else{ }
else
{
_status = GW_LOST; _status = GW_LOST;
_gwId = 0; _gwId = 0;
return -1; return -1;
} }
} }
return 0; 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; _status = GW_SLEPT;
uint32_t remain = _keepAliveTimer.getRemain(); uint32_t remain = _keepAliveTimer.getRemain();
theClient->setSleepMode(remain); theClient->setSleepMode(remain);
/* Wake up and starts from this point. */ /* Wake up and starts from this point. */
}else{ }
else
{
_status = GW_DISCONNECTED; _status = GW_DISCONNECTED;
} }
} }
return 0; return 0;
} }
int LGwProxy::getMessage(void){ int LGwProxy::getMessage(void)
{
int len = readMsg(); int len = readMsg();
if (len < 0){ if (len < 0)
{
return len; //error return len; //error
} }
#ifdef DEBUG_MQTTSN #ifdef DEBUG_MQTTSN
if (len){ if (len)
{
D_MQTTLOG(" recved msgType %x\n", _mqttsnMsg[0]); D_MQTTLOG(" recved msgType %x\n", _mqttsnMsg[0]);
} }
#endif #endif
if (len == 0){ if (len == 0)
{
// Check PINGREQ required // Check PINGREQ required
checkPingReq(); checkPingReq();
@@ -282,87 +343,115 @@ int LGwProxy::getMessage(void){
// Check Timeout of SUBSCRIBEs, // Check Timeout of SUBSCRIBEs,
theClient->getSubscribeManager()->checkTimeout(); theClient->getSubscribeManager()->checkTimeout();
}else if (_mqttsnMsg[0] == MQTTSN_TYPE_PUBLISH){ }
else if (_mqttsnMsg[0] == MQTTSN_TYPE_PUBLISH)
{
theClient->getPublishManager()->published(_mqttsnMsg, len); 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 ){ else if (_mqttsnMsg[0] == MQTTSN_TYPE_PUBACK || _mqttsnMsg[0] == MQTTSN_TYPE_PUBCOMP
theClient->getPublishManager()->responce(_mqttsnMsg, (uint16_t)len); || _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); theClient->getSubscribeManager()->responce(_mqttsnMsg);
}else if (_mqttsnMsg[0] == MQTTSN_TYPE_REGISTER){ }
else if (_mqttsnMsg[0] == MQTTSN_TYPE_REGISTER)
{
_regMgr.responceRegister(_mqttsnMsg, len); _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)); _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; _pingStatus = 0;
setPingReqTimer(); setPingReqTimer();
if ( _tSleep > 0 ){ if (_tSleep > 0)
{
_tWake += _tkeepAlive; _tWake += _tkeepAlive;
if ( _tWake < _tSleep ){ if (_tWake < _tSleep)
{
theClient->setSleepMode(_tkeepAlive * 1000UL); 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"); DISPLAY("\033[0m\033[0;32m\n\n Get back to ACTIVE.\033[0m\033[0;37m\n\n");
_tWake = 0; _tWake = 0;
connect(); connect();
} }
} }
} }
}else if (_mqttsnMsg[0] == MQTTSN_TYPE_DISCONNECT){ }
else if (_mqttsnMsg[0] == MQTTSN_TYPE_DISCONNECT)
{
_status = GW_LOST; _status = GW_LOST;
_gwAliveTimer.stop(); _gwAliveTimer.stop();
_keepAliveTimer.stop(); _keepAliveTimer.stop();
}else if (_mqttsnMsg[0] == MQTTSN_TYPE_ADVERTISE){ }
if (getUint16((const uint8_t*)(_mqttsnMsg + 2)) < 61){ else if (_mqttsnMsg[0] == MQTTSN_TYPE_ADVERTISE)
_tAdv = getUint16((const uint8_t*)(_mqttsnMsg + 2)) * 1500; {
}else{ if (getUint16((const uint8_t*) (_mqttsnMsg + 2)) < 61)
_tAdv = getUint16((const uint8_t*)(_mqttsnMsg + 2)) * 1100; {
_tAdv = getUint16((const uint8_t*) (_mqttsnMsg + 2)) * 1500;
}
else
{
_tAdv = getUint16((const uint8_t*) (_mqttsnMsg + 2)) * 1100;
} }
_gwAliveTimer.start(_tAdv); _gwAliveTimer.start(_tAdv);
} }
return 0; return 0;
} }
uint16_t LGwProxy::registerTopic(char* topicName, uint16_t topicId)
{
uint16_t LGwProxy::registerTopic(char* topicName, uint16_t topicId){
uint16_t id = topicId; uint16_t id = topicId;
if (id == 0){ if (id == 0)
{
id = _topicTbl.getTopicId(topicName); id = _topicTbl.getTopicId(topicName);
_regMgr.registerTopic(topicName); _regMgr.registerTopic(topicName);
} }
return id; return id;
} }
int LGwProxy::writeMsg(const uint8_t* msg)
int LGwProxy::writeMsg(const uint8_t* msg){ {
uint16_t len; uint16_t len;
uint8_t pos; uint8_t pos;
uint8_t rc = 0; uint8_t rc = 0;
if (msg[0] == 0x01){ if (msg[0] == 0x01)
{
len = getUint16(msg + 1); len = getUint16(msg + 1);
pos = 2; pos = 2;
}else{ }
else
{
len = msg[0]; len = msg[0];
pos = 1; pos = 1;
} }
if (msg[0] == 3 && msg[1] == MQTTSN_TYPE_SEARCHGW){ if (msg[0] == 3 && msg[1] == MQTTSN_TYPE_SEARCHGW)
rc = _network.broadcast(msg,len);
}else
{ {
if ( _isForwarderMode ) rc = _network.broadcast(msg, len);
}
else
{
if (_isForwarderMode)
{ {
// create a forwarder encapsulation message WirelessNodeId is a 4bytes fake data // 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[0] = 7;
buf[1] = MQTTSN_TYPE_ENCAPSULATED; buf[1] = MQTTSN_TYPE_ENCAPSULATED;
buf[2] = 1; buf[2] = 1;
@@ -371,16 +460,19 @@ int LGwProxy::writeMsg(const uint8_t* msg){
buf[5] = 'I'; buf[5] = 'I';
buf[6] = 'd'; buf[6] = 'd';
memcpy(buf + 7, msg, len); memcpy(buf + 7, msg, len);
if ( buf) if (buf)
rc = _network.unicast(buf, len + 7); rc = _network.unicast(buf, len + 7);
free(buf); free(buf);
DISPLAY(" Encapsulated\n "); DISPLAY(" Encapsulated\n ");
}else{ }
rc = _network.unicast(msg,len); else
{
rc = _network.unicast(msg, len);
} }
if (rc > 0){ if (rc > 0)
if ( msg[pos] >= MQTTSN_TYPE_ADVERTISE && msg[pos] <= MQTTSN_TYPE_WILLMSGRESP ) {
if (msg[pos] >= MQTTSN_TYPE_ADVERTISE && msg[pos] <= MQTTSN_TYPE_WILLMSGRESP)
{ {
DISPLAY(" send %s\n", packet_names[msg[pos]]); DISPLAY(" send %s\n", packet_names[msg[pos]]);
} }
@@ -389,105 +481,139 @@ int LGwProxy::writeMsg(const uint8_t* msg){
return rc; return rc;
} }
void LGwProxy::writeGwMsg(void){ void LGwProxy::writeGwMsg(void)
{
_retryCount = MQTTSN_RETRY_COUNT; _retryCount = MQTTSN_RETRY_COUNT;
writeMsg((const uint8_t*)_msg); writeMsg((const uint8_t*) _msg);
_sendUTC = time(NULL); _sendUTC = time(NULL);
} }
int LGwProxy::readMsg(void){ int LGwProxy::readMsg(void)
{
int len = 0; int len = 0;
uint8_t* msg = _network.getMessage(&len); uint8_t* msg = _network.getMessage(&len);
_mqttsnMsg = msg; _mqttsnMsg = msg;
if (len == 0){ if (len == 0)
{
return 0; return 0;
} }
if (_mqttsnMsg[0] == 0x01){ if (_mqttsnMsg[0] == 0x01)
int msgLen = (int) getUint16((const uint8_t*)_mqttsnMsg + 1); {
if (len != msgLen){ int msgLen = (int) getUint16((const uint8_t*) _mqttsnMsg + 1);
if (len != msgLen)
{
_mqttsnMsg += 3; _mqttsnMsg += 3;
len = msgLen - 3; len = msgLen - 3;
} }
}else{ }
else
{
_mqttsnMsg += 1; _mqttsnMsg += 1;
len -= 1; len -= 1;
} }
if ( *_mqttsnMsg == MQTTSN_TYPE_ENCAPSULATED ) if (*_mqttsnMsg == MQTTSN_TYPE_ENCAPSULATED)
{ {
int lenEncap = len + 1; int lenEncap = len + 1;
if (msg[lenEncap] == 0x01){ if (msg[lenEncap] == 0x01)
int msgLen = (int) getUint16((const uint8_t*)(msg + lenEncap + 1)); {
int msgLen = (int) getUint16((const uint8_t*) (msg + lenEncap + 1));
msg += (lenEncap + 3); msg += (lenEncap + 3);
len = msgLen - 3; len = msgLen - 3;
}else{ }
else
{
msg += (lenEncap + 1); msg += (lenEncap + 1);
len = *(msg - 1); len = *(msg - 1);
} }
_mqttsnMsg = msg; _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]); DISPLAY(" recv %s\n", packet_names[*_mqttsnMsg]);
} }
return len; 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; _willTopic = willTopic;
_retainWill = _qosWill = 0; _retainWill = _qosWill = 0;
if (qos == 1){ if (qos == 1)
{
_qosWill = MQTTSN_FLAG_QOS_1; _qosWill = MQTTSN_FLAG_QOS_1;
}else if (qos == 2){ }
else if (qos == 2)
{
_qosWill = MQTTSN_FLAG_QOS_2; _qosWill = MQTTSN_FLAG_QOS_2;
} }
if (retain){ if (retain)
{
_retainWill = MQTTSN_FLAG_RETAIN; _retainWill = MQTTSN_FLAG_RETAIN;
} }
} }
void LGwProxy::setWillMsg(const char* willMsg){ void LGwProxy::setWillMsg(const char* willMsg)
{
_willMsg = willMsg; _willMsg = willMsg;
} }
void LGwProxy::setCleanSession(bool flg)
void LGwProxy::setCleanSession(bool flg){ {
if (flg){ if (flg)
{
_cleanSession = MQTTSN_FLAG_CLEAN; _cleanSession = MQTTSN_FLAG_CLEAN;
}else{ }
else
{
_cleanSession = 0; _cleanSession = 0;
} }
} }
uint16_t LGwProxy::getNextMsgId(void){ uint16_t LGwProxy::getNextMsgId(void)
{
_nextMsgId++; _nextMsgId++;
if (_nextMsgId == 0){ if (_nextMsgId == 0)
{
_nextMsgId = 1; _nextMsgId = 1;
} }
return _nextMsgId; return _nextMsgId;
} }
void LGwProxy::checkPingReq(void){ void LGwProxy::checkPingReq(void)
{
if ( _isQoSMinus1Mode )
{
return;
}
uint8_t msg[2]; uint8_t msg[2];
msg[0] = 0x02; msg[0] = 0x02;
msg[1] = MQTTSN_TYPE_PINGREQ; 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; _pingStatus = GW_WAIT_PINGRESP;
_pingRetryCount = MQTTSN_RETRY_COUNT; _pingRetryCount = MQTTSN_RETRY_COUNT;
writeMsg((const uint8_t*)msg); writeMsg((const uint8_t*) msg);
_pingSendUTC = time(NULL); _pingSendUTC = time(NULL);
}else if (_pingStatus == GW_WAIT_PINGRESP){ }
if (_pingSendUTC + MQTTSN_TIME_RETRY < time(NULL)){ else if (_pingStatus == GW_WAIT_PINGRESP)
if (--_pingRetryCount > 0){ {
writeMsg((const uint8_t*)msg); if (_pingSendUTC + MQTTSN_TIME_RETRY < time(NULL))
{
if (--_pingRetryCount > 0)
{
writeMsg((const uint8_t*) msg);
_pingSendUTC = time(NULL); _pingSendUTC = time(NULL);
}else{ }
else
{
_status = GW_LOST; _status = GW_LOST;
_gwId = 0; _gwId = 0;
_pingStatus = 0; _pingStatus = 0;
@@ -498,8 +624,10 @@ void LGwProxy::checkPingReq(void){
} }
} }
void LGwProxy::checkAdvertise(void){ void LGwProxy::checkAdvertise(void)
if ( _gwAliveTimer.isTimeUp()){ {
if (_gwAliveTimer.isTimeUp())
{
_status = GW_LOST; _status = GW_LOST;
_gwId = 0; _gwId = 0;
_pingStatus = 0; _pingStatus = 0;
@@ -509,27 +637,37 @@ void LGwProxy::checkAdvertise(void){
} }
} }
LTopicTable* LGwProxy::getTopicTable(void){ LTopicTable* LGwProxy::getTopicTable(void)
{
return &_topicTbl; return &_topicTbl;
} }
LRegisterManager* LGwProxy::getRegisterManager(void){ LRegisterManager* LGwProxy::getRegisterManager(void)
{
return &_regMgr; return &_regMgr;
} }
bool LGwProxy::isPingReqRequired(void){ bool LGwProxy::isPingReqRequired(void)
{
return _keepAliveTimer.isTimeUp(_tkeepAlive * 1000UL); return _keepAliveTimer.isTimeUp(_tkeepAlive * 1000UL);
} }
void LGwProxy::setPingReqTimer(void){ void LGwProxy::setPingReqTimer(void)
{
_keepAliveTimer.start(_tkeepAlive * 1000UL); _keepAliveTimer.start(_tkeepAlive * 1000UL);
} }
const char* LGwProxy::getClientId(void) { const char* LGwProxy::getClientId(void)
{
return _clientId; return _clientId;
} }
void LGwProxy::setForwarderMode(void) void LGwProxy::setForwarderMode(bool valid)
{ {
_isForwarderMode = true; _isForwarderMode = valid;
}
void LGwProxy::setQoSMinus1Mode(bool valid)
{
_isQoSMinus1Mode = valid;
} }

View File

@@ -65,7 +65,8 @@ public:
void setCleanSession(bool); void setCleanSession(bool);
void setKeepAliveDuration(uint16_t duration); void setKeepAliveDuration(uint16_t duration);
void setAdvertiseDuration(uint16_t duration); void setAdvertiseDuration(uint16_t duration);
void setForwarderMode(void); void setForwarderMode(bool valid);
void setQoSMinus1Mode(bool valid);
void reconnect(void); void reconnect(void);
int writeMsg(const uint8_t* msg); int writeMsg(const uint8_t* msg);
void setPingReqTimer(void); void setPingReqTimer(void);
@@ -109,6 +110,7 @@ private:
uint16_t _tSleep; uint16_t _tSleep;
uint16_t _tWake; uint16_t _tWake;
bool _isForwarderMode; bool _isForwarderMode;
bool _isQoSMinus1Mode;
char _msg[MQTTSN_MAX_MSG_LENGTH + 1]; char _msg[MQTTSN_MAX_MSG_LENGTH + 1];
}; };

View File

@@ -27,7 +27,6 @@
======================================*/ ======================================*/
//#define DEBUG_NW //#define DEBUG_NW
//#define DEBUG_MQTTSN //#define DEBUG_MQTTSN
//#define DEBUG_OTA
/**************************************** /****************************************
MQTT-SN Parameters MQTT-SN Parameters
@@ -105,7 +104,9 @@ typedef enum
#define END_OF_SUBSCRIBE_LIST {MQTTSN_TOPIC_TYPE_NORMAL,0,0,0, 0} #define END_OF_SUBSCRIBE_LIST {MQTTSN_TOPIC_TYPE_NORMAL,0,0,0, 0}
#define UDPCONF LUdpConfig theNetcon #define UDPCONF LUdpConfig theNetcon
#define MQTTSNCONF LMqttsnConfig theMqcon #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 #ifdef CLIENT_MODE
#define DISPLAY(...) #define DISPLAY(...)
#define PROMPT(...) #define PROMPT(...)
@@ -142,6 +143,7 @@ typedef enum
#define QoS0 0 #define QoS0 0
#define QoS1 1 #define QoS1 1
#define QoS2 2 #define QoS2 2
#define Q0Sm1 3
#define MQTTSN_TYPE_ADVERTISE 0x00 #define MQTTSN_TYPE_ADVERTISE 0x00
#define MQTTSN_TYPE_SEARCHGW 0x01 #define MQTTSN_TYPE_SEARCHGW 0x01
#define MQTTSN_TYPE_GWINFO 0x02 #define MQTTSN_TYPE_GWINFO 0x02
@@ -177,7 +179,7 @@ typedef enum
#define MQTTSN_FLAG_QOS_0 0x0 #define MQTTSN_FLAG_QOS_0 0x0
#define MQTTSN_FLAG_QOS_1 0x20 #define MQTTSN_FLAG_QOS_1 0x20
#define MQTTSN_FLAG_QOS_2 0x40 #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_RETAIN 0x10
#define MQTTSN_FLAG_WILL 0x08 #define MQTTSN_FLAG_WILL 0x08
#define MQTTSN_FLAG_CLEAN 0x04 #define MQTTSN_FLAG_CLEAN 0x04

View File

@@ -40,351 +40,351 @@ const char* NULLCHAR = "";
LPublishManager::LPublishManager() LPublishManager::LPublishManager()
{ {
_first = 0; _first = 0;
_last = 0; _last = 0;
_elmCnt = 0; _elmCnt = 0;
_publishedFlg = SAVE_TASK_INDEX; _publishedFlg = SAVE_TASK_INDEX;
} }
LPublishManager::~LPublishManager() LPublishManager::~LPublishManager()
{ {
PubElement* elm = _first; PubElement* elm = _first;
PubElement* sav = 0; PubElement* sav = 0;
while (elm) while (elm)
{ {
sav = elm->next; sav = elm->next;
if (elm != 0) if (elm != 0)
{ {
delElement(elm); delElement(elm);
} }
elm = sav; elm = sav;
} }
} }
void LPublishManager::publish(const char* topicName, Payload* payload, uint8_t qos, bool retain) 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) void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain)
{ {
uint16_t msgId = 0; uint16_t msgId = 0;
uint8_t topicType = MQTTSN_TOPIC_TYPE_SHORT; uint8_t topicType = MQTTSN_TOPIC_TYPE_SHORT;
if ( strlen(topicName) > 2 ) if ( strlen(topicName) > 2 )
{ {
topicType = MQTTSN_TOPIC_TYPE_NORMAL; topicType = MQTTSN_TOPIC_TYPE_NORMAL;
} }
if ( qos > 0 ) if ( qos > 0 && qos < 3 )
{ {
msgId = theClient->getGwProxy()->getNextMsgId(); 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) if (elm->status == TOPICID_IS_READY)
{ {
sendPublish(elm); sendPublish(elm);
} }
else else
{ {
theClient->getGwProxy()->registerTopic((char*) topicName, 0); theClient->getGwProxy()->registerTopic((char*) topicName, 0);
} }
} }
void LPublishManager::publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain) 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) void LPublishManager::publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain)
{ {
uint16_t msgId = 0; uint16_t msgId = 0;
if ( qos > 0 ) if ( qos > 0 && qos < 3 )
{ {
msgId = theClient->getGwProxy()->getNextMsgId(); msgId = theClient->getGwProxy()->getNextMsgId();
} }
PubElement* elm = add(NULLCHAR, topicId, payload, len, qos, retain, msgId, MQTTSN_TOPIC_TYPE_PREDEFINED); PubElement* elm = add(NULLCHAR, topicId, payload, len, qos, retain, msgId, MQTTSN_TOPIC_TYPE_PREDEFINED);
sendPublish(elm); sendPublish(elm);
} }
void LPublishManager::sendPublish(PubElement* elm) void LPublishManager::sendPublish(PubElement* elm)
{ {
if (elm == 0) if (elm == 0)
{ {
return; return;
} }
theClient->getGwProxy()->connect(); theClient->getGwProxy()->connect();
uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1]; uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1];
uint8_t org = 0; uint8_t org = 0;
if (elm->payloadlen > 128) if (elm->payloadlen > 128)
{ {
msg[0] = 0x01; msg[0] = 0x01;
setUint16(msg + 1, elm->payloadlen + 9); setUint16(msg + 1, elm->payloadlen + 9);
org = 2; org = 2;
} }
else else
{ {
msg[0] = (uint8_t) elm->payloadlen + 7; msg[0] = (uint8_t) elm->payloadlen + 7;
} }
msg[org + 1] = MQTTSN_TYPE_PUBLISH; msg[org + 1] = MQTTSN_TYPE_PUBLISH;
msg[org + 2] = elm->flag; msg[org + 2] = elm->flag;
if ((elm->retryCount < MQTTSN_RETRY_COUNT)) if ((elm->retryCount < MQTTSN_RETRY_COUNT))
{ {
msg[org + 2] = msg[org + 2] | MQTTSN_FLAG_DUP; msg[org + 2] = msg[org + 2] | MQTTSN_FLAG_DUP;
} }
if ((elm->flag & 0x03) == MQTTSN_TOPIC_TYPE_SHORT ) if ((elm->flag & 0x03) == MQTTSN_TOPIC_TYPE_SHORT )
{ {
memcpy(msg + org + 3, elm->topicName, 2); memcpy(msg + org + 3, elm->topicName, 2);
} }
else else
{ {
setUint16(msg + org + 3, elm->topicId); setUint16(msg + org + 3, elm->topicId);
} }
setUint16(msg + org + 5, elm->msgId); setUint16(msg + org + 5, elm->msgId);
memcpy(msg + org + 7, elm->payload, elm->payloadlen); memcpy(msg + org + 7, elm->payload, elm->payloadlen);
theClient->getGwProxy()->writeMsg(msg); theClient->getGwProxy()->writeMsg(msg);
theClient->getGwProxy()->setPingReqTimer(); theClient->getGwProxy()->setPingReqTimer();
if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_0) 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); DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Published. \033[0m\033[0;37m\n\n", elm->topicName);
remove(elm); // PUBLISH Done remove(elm); // PUBLISH Done
return; return;
} }
else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_1) else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_1)
{ {
elm->status = WAIT_PUBACK; elm->status = WAIT_PUBACK;
} }
else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_2) else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_2)
{ {
elm->status = WAIT_PUBREC; elm->status = WAIT_PUBREC;
} }
elm->sendUTC = time(NULL); elm->sendUTC = time(NULL);
elm->retryCount--; elm->retryCount--;
} }
void LPublishManager::sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType) void LPublishManager::sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType)
{ {
PubElement* elm = _first; PubElement* elm = _first;
while (elm) while (elm)
{ {
if (strcmp(elm->topicName, topicName) == 0 && elm->status == TOPICID_IS_SUSPEND) if (strcmp(elm->topicName, topicName) == 0 && elm->status == TOPICID_IS_SUSPEND)
{ {
elm->topicId = topicId; elm->topicId = topicId;
elm->flag |= topicType; elm->flag |= topicType;
elm->status = TOPICID_IS_READY; elm->status = TOPICID_IS_READY;
sendPublish(elm); sendPublish(elm);
elm = 0; elm = 0;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
} }
void LPublishManager::sendPubAck(uint16_t topicId, uint16_t msgId, uint8_t rc) void LPublishManager::sendPubAck(uint16_t topicId, uint16_t msgId, uint8_t rc)
{ {
uint8_t msg[7]; uint8_t msg[7];
msg[0] = 7; msg[0] = 7;
msg[1] = MQTTSN_TYPE_PUBACK; msg[1] = MQTTSN_TYPE_PUBACK;
setUint16(msg + 2, topicId); setUint16(msg + 2, topicId);
setUint16(msg + 4, msgId); setUint16(msg + 4, msgId);
msg[6] = rc; msg[6] = rc;
theClient->getGwProxy()->writeMsg(msg); theClient->getGwProxy()->writeMsg(msg);
} }
void LPublishManager::sendPubRel(PubElement* elm) void LPublishManager::sendPubRel(PubElement* elm)
{ {
uint8_t msg[4]; uint8_t msg[4];
msg[0] = 4; msg[0] = 4;
msg[1] = MQTTSN_TYPE_PUBREL; msg[1] = MQTTSN_TYPE_PUBREL;
setUint16(msg + 2, elm->msgId); setUint16(msg + 2, elm->msgId);
theClient->getGwProxy()->writeMsg(msg); theClient->getGwProxy()->writeMsg(msg);
} }
bool LPublishManager::isDone(void) bool LPublishManager::isDone(void)
{ {
return (_first == 0); return (_first == 0);
} }
bool LPublishManager::isMaxFlight(void) 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) void LPublishManager::responce(const uint8_t* msg, uint16_t msglen)
{ {
if (msg[0] == MQTTSN_TYPE_PUBACK) if (msg[0] == MQTTSN_TYPE_PUBACK)
{ {
uint16_t msgId = getUint16(msg + 3); uint16_t msgId = getUint16(msg + 3);
PubElement* elm = getElement(msgId); PubElement* elm = getElement(msgId);
if (elm == 0) if (elm == 0)
{ {
return; return;
} }
if (msg[5] == MQTTSN_RC_ACCEPTED) if (msg[5] == MQTTSN_RC_ACCEPTED)
{ {
if (elm->status == WAIT_PUBACK) 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); 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 remove(elm); // PUBLISH Done
} }
} }
else if (msg[5] == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID) else if (msg[5] == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID)
{ {
elm->status = TOPICID_IS_SUSPEND; elm->status = TOPICID_IS_SUSPEND;
elm->topicId = 0; elm->topicId = 0;
elm->retryCount = MQTTSN_RETRY_COUNT; elm->retryCount = MQTTSN_RETRY_COUNT;
elm->sendUTC = 0; elm->sendUTC = 0;
theClient->getGwProxy()->registerTopic((char*) elm->topicName, 0); theClient->getGwProxy()->registerTopic((char*) elm->topicName, 0);
} }
} }
else if (msg[0] == MQTTSN_TYPE_PUBREC) else if (msg[0] == MQTTSN_TYPE_PUBREC)
{ {
PubElement* elm = getElement(getUint16(msg + 1)); PubElement* elm = getElement(getUint16(msg + 1));
if (elm == 0) if (elm == 0)
{ {
return; return;
} }
if (elm->status == WAIT_PUBREC || elm->status == WAIT_PUBCOMP) if (elm->status == WAIT_PUBREC || elm->status == WAIT_PUBCOMP)
{ {
sendPubRel(elm); sendPubRel(elm);
elm->status = WAIT_PUBCOMP; elm->status = WAIT_PUBCOMP;
elm->sendUTC = time(NULL); elm->sendUTC = time(NULL);
} }
} }
else if (msg[0] == MQTTSN_TYPE_PUBCOMP) else if (msg[0] == MQTTSN_TYPE_PUBCOMP)
{ {
PubElement* elm = getElement(getUint16(msg + 1)); PubElement* elm = getElement(getUint16(msg + 1));
if (elm == 0) if (elm == 0)
{ {
return; return;
} }
if (elm->status == WAIT_PUBCOMP) 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); 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 remove(elm); // PUBLISH Done
} }
} }
} }
void LPublishManager::published(uint8_t* msg, uint16_t msglen) 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) if (msg[1] & MQTTSN_FLAG_QOS_1)
{ {
sendPubAck(topicId, getUint16(msg + 4), MQTTSN_RC_ACCEPTED); sendPubAck(topicId, getUint16(msg + 4), MQTTSN_RC_ACCEPTED);
} }
_publishedFlg = NEG_TASK_INDEX; _publishedFlg = NEG_TASK_INDEX;
theClient->getTopicTable()->execCallback(topicId, msg + 6, msglen - 6, (MQTTSN_topicTypes)(msg[1] & MQTTSN_TOPIC_TYPE)); theClient->getTopicTable()->execCallback(topicId, msg + 6, msglen - 6, (MQTTSN_topicTypes)(msg[1] & MQTTSN_TOPIC_TYPE));
_publishedFlg = SAVE_TASK_INDEX; _publishedFlg = SAVE_TASK_INDEX;
} }
void LPublishManager::checkTimeout(void) void LPublishManager::checkTimeout(void)
{ {
PubElement* elm = _first; PubElement* elm = _first;
while (elm) while (elm)
{ {
if (elm->sendUTC > 0 && elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL)) if (elm->sendUTC > 0 && elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL))
{ {
if (elm->retryCount >= 0) if (elm->retryCount >= 0)
{ {
sendPublish(elm); sendPublish(elm);
D_MQTTLOG("...Timeout retry\r\n"); D_MQTTLOG("...Timeout retry\r\n");
} }
else else
{ {
theClient->getGwProxy()->reconnect(); theClient->getGwProxy()->reconnect();
elm->retryCount = MQTTSN_RETRY_COUNT; elm->retryCount = MQTTSN_RETRY_COUNT;
break; break;
} }
} }
elm = elm->next; elm = elm->next;
} }
} }
PubElement* LPublishManager::getElement(uint16_t msgId) PubElement* LPublishManager::getElement(uint16_t msgId)
{ {
PubElement* elm = _first; PubElement* elm = _first;
while (elm) while (elm)
{ {
if (elm->msgId == msgId) if (elm->msgId == msgId)
{ {
break; break;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
return elm; return elm;
} }
PubElement* LPublishManager::getElement(const char* topicName) PubElement* LPublishManager::getElement(const char* topicName)
{ {
PubElement* elm = _first; PubElement* elm = _first;
while (elm) while (elm)
{ {
if (strcmp(elm->topicName, topicName) == 0) if (strcmp(elm->topicName, topicName) == 0)
{ {
break; break;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
return elm; return elm;
} }
void LPublishManager::remove(PubElement* elm) void LPublishManager::remove(PubElement* elm)
{ {
if (elm) if (elm)
{ {
if (elm->prev == 0) if (elm->prev == 0)
{ {
_first = elm->next; _first = elm->next;
if (elm->next == 0) if (elm->next == 0)
{ {
_last = 0; _last = 0;
} }
else else
{ {
elm->next->prev = 0; elm->next->prev = 0;
_last = elm->next; _last = elm->next;
} }
} }
else else
{ {
if ( elm->next == 0 ) if ( elm->next == 0 )
{ {
_last = elm->prev; _last = elm->prev;
} }
elm->prev->next = elm->next; elm->prev->next = elm->next;
} }
delElement(elm); delElement(elm);
} }
} }
void LPublishManager::delElement(PubElement* elm) void LPublishManager::delElement(PubElement* elm)
{ {
if (elm->taskIndex >= 0) if (elm->taskIndex >= 0)
{ {
theClient->getTaskManager()->done(elm->taskIndex); theClient->getTaskManager()->done(elm->taskIndex);
} }
_elmCnt--; _elmCnt--;
if ( elm->payload ) if ( elm->payload )
{ {
free(elm->payload); free(elm->payload);
} }
free(elm); free(elm);
} }
/* /*
@@ -393,84 +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, 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) if (elm == 0)
{ {
return elm; return elm;
} }
if (_last == 0) if (_last == 0)
{ {
_first = elm; _first = elm;
_last = elm; _last = elm;
} }
else else
{ {
elm->prev = _last; elm->prev = _last;
_last->next = elm; _last->next = elm;
_last = elm; _last = elm;
} }
elm->topicName = topicName; elm->topicName = topicName;
elm->flag |= topicType; elm->flag |= topicType;
if (qos == 0) if (qos == 0)
{ {
elm->flag |= MQTTSN_FLAG_QOS_0; elm->flag |= MQTTSN_FLAG_QOS_0;
} }
else if (qos == 1) else if (qos == 1)
{ {
elm->flag |= MQTTSN_FLAG_QOS_1; elm->flag |= MQTTSN_FLAG_QOS_1;
} }
else if (qos == 2) else if (qos == 2)
{ {
elm->flag |= MQTTSN_FLAG_QOS_2; elm->flag |= MQTTSN_FLAG_QOS_2;
} }
if (retain) else if (qos == 3)
{ {
elm->flag |= MQTTSN_FLAG_RETAIN; elm->flag |= MQTTSN_FLAG_QOS_M1;
} }
if (retain)
{
elm->flag |= MQTTSN_FLAG_RETAIN;
}
if (topicId) if (topicId)
{ {
elm->status = TOPICID_IS_READY; elm->status = TOPICID_IS_READY;
elm->topicId = topicId; elm->topicId = topicId;
} }
else else
{ {
uint16_t id = theClient->getTopicId(topicName); uint16_t id = theClient->getTopicId(topicName);
if ( id ) if ( id )
{ {
elm->status = TOPICID_IS_READY; elm->status = TOPICID_IS_READY;
elm->topicId = id; elm->topicId = id;
} }
} }
elm->payloadlen = len; elm->payloadlen = len;
elm->msgId = msgId; elm->msgId = msgId;
elm->retryCount = MQTTSN_RETRY_COUNT; elm->retryCount = MQTTSN_RETRY_COUNT;
elm->sendUTC = 0; elm->sendUTC = 0;
if (_publishedFlg == NEG_TASK_INDEX) if (_publishedFlg == NEG_TASK_INDEX)
{ {
elm->taskIndex = -1; elm->taskIndex = -1;
} }
else else
{ {
elm->taskIndex = theClient->getTaskManager()->getIndex(); elm->taskIndex = theClient->getTaskManager()->getIndex();
theClient->getTaskManager()->suspend(elm->taskIndex); theClient->getTaskManager()->suspend(elm->taskIndex);
} }
elm->payload = (uint8_t*) malloc(len); elm->payload = (uint8_t*) malloc(len);
if (elm->payload == 0) if (elm->payload == 0)
{ {
delElement(elm); delElement(elm);
return 0; return 0;
} }
memcpy(elm->payload, payload, len); memcpy(elm->payload, payload, len);
++_elmCnt; ++_elmCnt;
return elm; return elm;
} }

View File

@@ -10,7 +10,6 @@ TESTAPPL := mainTestProcess
CONFIG := gateway.conf CONFIG := gateway.conf
CLIENTS := clients.conf CLIENTS := clients.conf
PREDEFTOPIC := predefinedTopic.conf PREDEFTOPIC := predefinedTopic.conf
FORWARDERS := forwarders.conf
SRCDIR := src SRCDIR := src
SUBDIR := ../MQTTSNPacket/src SUBDIR := ../MQTTSNPacket/src
@@ -39,6 +38,15 @@ $(SRCDIR)/MQTTSNGWPublishHandler.cpp \
$(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \ $(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \
$(SRCDIR)/MQTTSNGWEncapsulatedPacket.cpp \ $(SRCDIR)/MQTTSNGWEncapsulatedPacket.cpp \
$(SRCDIR)/MQTTSNGWForwarder.cpp \ $(SRCDIR)/MQTTSNGWForwarder.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)/$(SENSORNET)/SensorNetwork.cpp \
$(SRCDIR)/$(OS)/Timer.cpp \ $(SRCDIR)/$(OS)/Timer.cpp \
$(SRCDIR)/$(OS)/Network.cpp \ $(SRCDIR)/$(OS)/Network.cpp \
@@ -140,7 +148,6 @@ install:
cp -pf $(CONFIG) ../../ cp -pf $(CONFIG) ../../
cp -pf $(CLIENTS) ../../ cp -pf $(CLIENTS) ../../
cp -pf $(PREDEFTOPIC) ../../ cp -pf $(PREDEFTOPIC) ../../
cp -pf $(FORWARDERS) ../../
exectest: exectest:

View File

@@ -2,7 +2,7 @@
### **step1. Build the gateway** ### **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 $ cd paho.mqtt-sn.embedded-c/MQTTSNGateway
$ make $ make
$ make install $ make install
@@ -22,57 +22,69 @@ $ ./MQTT-SNGateway [-f Config file name]
### **How to Change the configuration of the gateway** ### **How to Change the configuration of the gateway**
**../gateway.conf** Contents are follows: **../gateway.conf** Contents are follows:
```` <pre><dev>
# config file of MQTT-SN Gateway # config file of MQTT-SN Gateway
#
BrokerName=iot.eclipse.org BrokerName=iot.eclipse.org
BrokerPortNo=1883 BrokerPortNo=1883
BrokerSecurePortNo=8883 BrokerSecurePortNo=8883
#
# When AggregateGateway=YES or ClientAuthentication=YES,
# All clients must be specified by the ClientList File
#
ClientAuthentication=NO ClientAuthentication=NO
ClientsList=/path/to/your_clients.conf AggregateGateway=NO
QoS-1=NO
Forwarder=NO
#ClientsList=/path/to/your_clients.conf
PredefinedTopic=NO PredefinedTopic=NO
PredefinedTopicList=/path/to/your_predefinedTopic.conf #PredefinedTopicList=/path/to/your_predefinedTopic.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
Forwarder=NO
ForwardersList=/home/tomoaki/tmp/forwarders.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 # UDP
GatewayPortNo=10000 GatewayPortNo=10000
MulticastIP=225.1.1.1 MulticastIP=225.1.1.1
MulticastPortNo=1883 MulticastPortNo=1883
# XBee # XBee
Baudrate=38400 Baudrate=38400
SerialDevice=/dev/ttyUSB0 SerialDevice=/dev/ttyUSB0
ApiMode=2 ApiMode=2
````
# LOG
ShearedMemory=NO;
</dev></pre>
**BrokerName** to specify a domain name of the Broker, and **BrokerPortNo** is a port No of the Broker. **BrokerSecurePortNo** is for TLS connection. **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(). **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. Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW message.
**GatewayId** is used by GWINFO message. **GatewayId** is used by GWINFO message.
**KeepAlive** is a duration of ADVERTISE message in seconds. **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 **AggregateGateway** or **ClientAuthentication** is **YES**, All clients which connect to the gateway must be declared by a **ClientsList** file.
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. 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 **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 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 **YES**, Forwarder Encapsulation Message is available. Connectable Forwarders must be declared by a **ClientsList** file.
### ** How to monitor the gateway from remote. ** ### ** How to monitor the gateway from remote. **
Uncomment line32 in MQTTSNGWDefined.h. Uncomment line32 in MQTTSNGWDefined.h.

View File

@@ -11,8 +11,37 @@
# http://www.eclipse.org/org/documents/edl-v10.php. # 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 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.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. # SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function.
# #
Client02,172.16.1.7:12002 GatewayTester, 172.16.1.11:20020
Client03,172.16.1.8:13003 ClientPUB,172.16.1.11:2010
Client01,172.16.1.6:12001 Client01,172.16.1.11:12001
Client02,172.16.1.11:12002
Client03,172.16.1.11:13003
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

View File

@@ -1,16 +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.
#***********************************************************************
#
# SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function.
#
Forwarder01,172.16.1.7:12002

View File

@@ -10,21 +10,28 @@
# and the Eclipse Distribution License is available at # and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php. # http://www.eclipse.org/org/documents/edl-v10.php.
#*************************************************************************** #***************************************************************************
#
# config file of MQTT-SN Gateway # config file of MQTT-SN Gateway
#
BrokerName=iot.eclipse.org BrokerName=iot.eclipse.org
BrokerPortNo=1883 BrokerPortNo=1883
BrokerSecurePortNo=8883 BrokerSecurePortNo=8883
#
# When AggregateGateway=YES or ClientAuthentication=YES,
# All clients must be specified by the ClientList File
#
ClientAuthentication=NO ClientAuthentication=NO
ClientsList=/path/to/your_clients.conf AggregateGateway=NO
QoS-1=NO
Forwarder=NO
#ClientsList=/path/to/your_clients.conf
PredefinedTopic=NO PredefinedTopic=NO
PredefinedTopicList=/path/to/your_predefinedTopic.conf #PredefinedTopicList=/path/to/your_predefinedTopic.conf
Forwarder=NO
ForwardersList=/path/to/your_forwarers.conf
#RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/ #RootCApath=/etc/ssl/certs/
@@ -37,6 +44,7 @@ KeepAlive=900
#LoginID=your_ID #LoginID=your_ID
#Password=your_Password #Password=your_Password
# UDP # UDP
GatewayPortNo=10000 GatewayPortNo=10000
MulticastIP=225.1.1.1 MulticastIP=225.1.1.1

View File

@@ -11,9 +11,36 @@
# http://www.eclipse.org/org/documents/edl-v10.php. # 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 Clients
# #
GatewayTestClient,ty4tw/predefinedTopic1, 1 GatewayTestClient,ty4tw/predefinedTopic1, 1
GatewayTestClient,ty4tw/predefinedTopic2, 2 GatewayTestClient,ty4tw/predefinedTopic2, 2
GatewayTestClient,ty4tw/predefinedTopic3, 3 GatewayTestClient,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

View File

@@ -21,6 +21,9 @@
using namespace MQTTSNGW; using namespace MQTTSNGW;
int readInt(char** ptr);
void writeInt(unsigned char** pptr, int msgId);
#define MAX_NO_OF_REMAINING_LENGTH_BYTES 3 #define MAX_NO_OF_REMAINING_LENGTH_BYTES 3
/** /**
* List of the predefined MQTT v3 packet names. * List of the predefined MQTT v3 packet names.
@@ -511,12 +514,12 @@ char* MQTTGWPacket::getMsgId(char* pbuf)
sprintf(pbuf, " %04X", pub.msgId); sprintf(pbuf, " %04X", pub.msgId);
} }
break; break;
case SUBSCRIBE:
case UNSUBSCRIBE:
case PUBACK: case PUBACK:
case PUBREC: case PUBREC:
case PUBREL: case PUBREL:
case PUBCOMP: case PUBCOMP:
case SUBSCRIBE:
case UNSUBSCRIBE:
case SUBACK: case SUBACK:
case UNSUBACK: case UNSUBACK:
sprintf(pbuf, " %02X%02X", _data[0], _data[1]); sprintf(pbuf, " %02X%02X", _data[0], _data[1]);
@@ -525,9 +528,77 @@ char* MQTTGWPacket::getMsgId(char* pbuf)
sprintf(pbuf, " "); sprintf(pbuf, " ");
break; break;
} }
if ( strcmp(pbuf, " 0000") == 0 )
{
sprintf(pbuf, " ");
}
return 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;
switch ( type )
{
case PUBLISH:
Publish pub;
pub.topiclen = 0;
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) char* MQTTGWPacket::print(char* pbuf)
{ {
uint8_t packetData[MQTTSNGW_MAX_PACKET_SIZE]; uint8_t packetData[MQTTSNGW_MAX_PACKET_SIZE];
@@ -561,3 +632,14 @@ MQTTGWPacket& MQTTGWPacket::operator =(MQTTGWPacket& packet)
return *this; 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;
}

View File

@@ -116,6 +116,12 @@ typedef struct
unsigned char version; /**< MQTT version number */ unsigned char version; /**< MQTT version number */
} Connect; } 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. * Data for a willMessage.
*/ */
@@ -177,6 +183,15 @@ typedef struct
int msgId; /**< MQTT message id */ int msgId; /**< MQTT message id */
} Ack; } Ack;
/**
* UTF8String.
*/
typedef struct
{
unsigned char len;
char* data;
} UTF8String;
/** /**
* Class MQTT Packet * Class MQTT Packet
*/ */
@@ -203,7 +218,11 @@ public:
int setHeader(unsigned char msgType); int setHeader(unsigned char msgType);
int setSUBSCRIBE(const char* topic, unsigned char qos, unsigned short msgId); int setSUBSCRIBE(const char* topic, unsigned char qos, unsigned short msgId);
int setUNSUBSCRIBE(const char* topics, unsigned short msgid); int setUNSUBSCRIBE(const char* topics, unsigned short msgid);
UTF8String getTopic(void);
char* getMsgId(char* buf); char* getMsgId(char* buf);
int getMsgId(void);
void setMsgId(int msgId);
char* print(char* buf); char* print(char* buf);
MQTTGWPacket& operator =(MQTTGWPacket& packet); MQTTGWPacket& operator =(MQTTGWPacket& packet);

View File

@@ -106,7 +106,7 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
/* This message might be subscribed with wild card. */ /* This message might be subscribed with wild card. */
topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; topicId.type = MQTTSN_TOPIC_TYPE_NORMAL;
Topic* topic = client->getTopics()->match(&topicId); Topic* topic = client->getTopics()->match(&topicId);
if (topic == 0) if (topic == nullptr)
{ {
WRITELOG(" Invalid Topic. PUBLISH message is canceled.\n"); WRITELOG(" Invalid Topic. PUBLISH message is canceled.\n");
if (pub.header.bits.qos == 1) if (pub.header.bits.qos == 1)
@@ -131,8 +131,7 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
/* create REGISTER */ /* create REGISTER */
MQTTSNPacket* regPacket = new MQTTSNPacket(); MQTTSNPacket* regPacket = new MQTTSNPacket();
MQTTSNString topicName; MQTTSNString topicName = MQTTSNString_initializer;
topicName.cstring = 0;
topicName.lenstring.len = topicId.data.long_.len; topicName.lenstring.len = topicId.data.long_.len;
topicName.lenstring.data = topicId.data.long_.name; topicName.lenstring.data = topicId.data.long_.name;
@@ -182,7 +181,7 @@ void MQTTGWPublishHandler::handlePuback(Client* client, MQTTGWPacket* packet)
{ {
Ack ack; Ack ack;
packet->getAck(&ack); packet->getAck(&ack);
TopicIdMapelement* topicId = client->getWaitedPubTopicId((uint16_t)ack.msgId); TopicIdMapElement* topicId = client->getWaitedPubTopicId((uint16_t)ack.msgId);
if (topicId) if (topicId)
{ {
MQTTSNPacket* mqttsnPacket = new MQTTSNPacket(); MQTTSNPacket* mqttsnPacket = new MQTTSNPacket();
@@ -235,3 +234,90 @@ 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);
}
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 )
{
ClientTopicElement* p = list->getFirstElement();
while ( p )
{
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, msg);
_gateway->getPacketEventQue()->post(ev);
}
else
{
break;
}
p = list->getNextElement(p);
}
delete list;
}
}

View File

@@ -32,6 +32,11 @@ public:
void handlePuback(Client* client, MQTTGWPacket* packet); void handlePuback(Client* client, MQTTGWPacket* packet);
void handleAck(Client* client, MQTTGWPacket* packet, int type); 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: private:
void replyACK(Client* client, Publish* pub, int type); void replyACK(Client* client, Publish* pub, int type);

View File

@@ -38,7 +38,7 @@ void MQTTGWSubscribeHandler::handleSuback(Client* client, MQTTGWPacket* packet)
int qos = 0; int qos = 0;
packet->getSUBACK(&msgId, &rc); packet->getSUBACK(&msgId, &rc);
TopicIdMapelement* topicId = client->getWaitedSubTopicId(msgId); TopicIdMapElement* topicId = client->getWaitedSubTopicId(msgId);
if (topicId) if (topicId)
{ {
@@ -72,3 +72,28 @@ void MQTTGWSubscribeHandler::handleUnsuback(Client* client, MQTTGWPacket* packet
_gateway->getClientSendQue()->post(evt); _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);
}
}

View File

@@ -31,6 +31,8 @@ public:
~MQTTGWSubscribeHandler(); ~MQTTGWSubscribeHandler();
void handleSuback(Client* clnode, MQTTGWPacket* packet); void handleSuback(Client* clnode, MQTTGWPacket* packet);
void handleUnsuback(Client* clnode, MQTTGWPacket* packet); void handleUnsuback(Client* clnode, MQTTGWPacket* packet);
void handleAggregateSuback(Client* client, MQTTGWPacket* packet);
void handleAggregateUnsuback(Client* client, MQTTGWPacket* packet);
private: private:
Gateway* _gateway; Gateway* _gateway;

View File

@@ -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 <string.h>
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);
}
}

View File

@@ -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_ */

View File

@@ -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 <string.h>
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<char*>(name.c_str());
string nameSecure = string(adpterName) + "-S";
idSecure.cstring = const_cast<char*>(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);
}
}

View File

@@ -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 <stdint.h>
#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_ */

View File

@@ -0,0 +1,188 @@
/**************************************************************************************
* 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 <string.h>
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(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();
}
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);
}

View File

@@ -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 Forwarder;
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(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_ */

View File

@@ -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;
}

View File

@@ -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 <stdint.h>
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_ */

View File

@@ -0,0 +1,145 @@
/**************************************************************************************
* 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 <stdio.h>
#include <string.h>
#include <string>
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(AGGREGATER_TYPE);
string name = _gateway->getGWParams()->gatewayName;
setup(name.c_str(), 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;
}

View File

@@ -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_ */

View File

@@ -16,6 +16,7 @@
#include "MQTTSNGWBrokerRecvTask.h" #include "MQTTSNGWBrokerRecvTask.h"
#include "MQTTSNGWClient.h" #include "MQTTSNGWClient.h"
#include "MQTTSNGWClientList.h"
#include <unistd.h> #include <unistd.h>
using namespace std; using namespace std;
@@ -30,7 +31,7 @@ BrokerRecvTask::BrokerRecvTask(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
_gateway->attach((Thread*)this); _gateway->attach((Thread*)this);
_light = 0; _light = nullptr;
} }
BrokerRecvTask::~BrokerRecvTask() BrokerRecvTask::~BrokerRecvTask()
@@ -52,9 +53,9 @@ void BrokerRecvTask::initialize(int argc, char** argv)
void BrokerRecvTask::run(void) void BrokerRecvTask::run(void)
{ {
struct timeval timeout; struct timeval timeout;
MQTTGWPacket* packet = 0; MQTTGWPacket* packet = nullptr;
int rc; int rc;
Event* ev = 0; Event* ev = nullptr;
fd_set rset; fd_set rset;
fd_set wset; fd_set wset;
@@ -74,9 +75,9 @@ void BrokerRecvTask::run(void)
int sockfd = 0; int sockfd = 0;
/* Prepare sockets list to read */ /* 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()) if (client->getNetwork()->isValid())
{ {
@@ -101,7 +102,7 @@ void BrokerRecvTask::run(void)
int activity = select(maxSock + 1, &rset, 0, 0, &timeout); int activity = select(maxSock + 1, &rset, 0, 0, &timeout);
if (activity > 0) if (activity > 0)
{ {
client = _gateway->getClientList()->getClient(); client = _gateway->getClientList()->getClient(0);
while (client > 0) while (client > 0)
{ {

View File

@@ -14,6 +14,7 @@
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#include <MQTTSNGWAdapterManager.h>
#include "MQTTSNGWBrokerSendTask.h" #include "MQTTSNGWBrokerSendTask.h"
#include "MQTTSNGWDefines.h" #include "MQTTSNGWDefines.h"
#include "MQTTSNGateway.h" #include "MQTTSNGateway.h"
@@ -34,8 +35,8 @@ BrokerSendTask::BrokerSendTask(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
_gateway->attach((Thread*)this); _gateway->attach((Thread*)this);
_gwparams = 0; _gwparams = nullptr;
_light = 0; _light = nullptr;
} }
BrokerSendTask::~BrokerSendTask() BrokerSendTask::~BrokerSendTask()
@@ -57,9 +58,10 @@ void BrokerSendTask::initialize(int argc, char** argv)
*/ */
void BrokerSendTask::run() void BrokerSendTask::run()
{ {
Event* ev = 0; Event* ev = nullptr;
MQTTGWPacket* packet = 0; MQTTGWPacket* packet = nullptr;
Client* client = 0; Client* client = nullptr;
AdapterManager* adpMgr = _gateway->getAdapterManager();
int rc = 0; int rc = 0;
while (true) while (true)
@@ -78,6 +80,9 @@ void BrokerSendTask::run()
client = ev->getClient(); client = ev->getClient();
packet = ev->getMQTTGWPacket(); packet = ev->getMQTTGWPacket();
/* Check Client is managed by Adapters */
client = adpMgr->getClient(*client);
if ( packet->getType() == CONNECT && client->getNetwork()->isValid() ) if ( packet->getType() == CONNECT && client->getNetwork()->isValid() )
{ {
client->getNetwork()->close(); client->getNetwork()->close();
@@ -89,12 +94,12 @@ void BrokerSendTask::run()
if (client->isSecureNetwork()) if (client->isSecureNetwork())
{ {
rc = client->getNetwork()->connect(_gwparams->brokerName, _gwparams->portSecure, _gwparams->rootCApath, rc = client->getNetwork()->connect((const char*)_gwparams->brokerName, (const char*)_gwparams->portSecure, (const char*)_gwparams->rootCApath,
_gwparams->rootCAfile, _gwparams->certKey, _gwparams->privateKey); (const char*)_gwparams->rootCAfile, (const char*)_gwparams->certKey, (const char*)_gwparams->privateKey);
} }
else else
{ {
rc = client->getNetwork()->connect(_gwparams->brokerName, _gwparams->port); rc = client->getNetwork()->connect((const char*)_gwparams->brokerName, (const char*)_gwparams->port);
} }
if ( !rc ) if ( !rc )

View File

@@ -22,12 +22,15 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class Adapter;
/*===================================== /*=====================================
Class BrokerSendTask Class BrokerSendTask
=====================================*/ =====================================*/
class BrokerSendTask : public Thread class BrokerSendTask : public Thread
{ {
MAGIC_WORD_FOR_THREAD; MAGIC_WORD_FOR_THREAD;
friend AdapterManager;
public: public:
BrokerSendTask(Gateway* gateway); BrokerSendTask(Gateway* gateway);
~BrokerSendTask(); ~BrokerSendTask();

File diff suppressed because it is too large Load Diff

View File

@@ -28,6 +28,9 @@
#include "MQTTSNPacket.h" #include "MQTTSNPacket.h"
#include "MQTTSNGWEncapsulatedPacket.h" #include "MQTTSNGWEncapsulatedPacket.h"
#include "MQTTSNGWForwarder.h" #include "MQTTSNGWForwarder.h"
#include "MQTTSNGWTopic.h"
#include "MQTTSNGWClientList.h"
#include "MQTTSNGWAdapter.h"
namespace MQTTSNGW 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 Class WaitREGACKPacket
@@ -229,15 +151,21 @@ private:
waitREGACKPacket* _end; waitREGACKPacket* _end;
}; };
/*===================================== /*=====================================
Class Client Class Client
=====================================*/ =====================================*/
typedef enum typedef enum
{ {
Cstat_Disconnected = 0, Cstat_TryConnecting, Cstat_Connecting, Cstat_Active, Cstat_Asleep, Cstat_Awake, Cstat_Lost Cstat_Disconnected = 0, Cstat_TryConnecting, Cstat_Connecting, Cstat_Active, Cstat_Asleep, Cstat_Awake, Cstat_Lost
} ClientStatus; } ClientStatus;
typedef enum
{
Ctype_Regular = 0, Ctype_Forwarded, Ctype_QoS_1, Ctype_Aggregated, Ctype_Proxy, Ctype_Aggregater
}ClientType;
class Forwarder; class Forwarder;
class Client class Client
@@ -249,10 +177,13 @@ public:
~Client(); ~Client();
Connect* getConnectData(void); Connect* getConnectData(void);
TopicIdMapelement* getWaitedPubTopicId(uint16_t msgId); TopicIdMapElement* getWaitedPubTopicId(uint16_t msgId);
TopicIdMapelement* getWaitedSubTopicId(uint16_t msgId); TopicIdMapElement* getWaitedSubTopicId(uint16_t msgId);
MQTTGWPacket* getClientSleepPacket(void); MQTTGWPacket* getClientSleepPacket(void);
void deleteFirstClientSleepPacket(void); void deleteFirstClientSleepPacket(void);
MQTTSNPacket* getProxyPacket(void);
void deleteFirstProxyPacket(void);
WaitREGACKPacketList* getWaitREGACKPacketList(void); WaitREGACKPacketList* getWaitREGACKPacketList(void);
void eraseWaitedPubTopicId(uint16_t msgId); void eraseWaitedPubTopicId(uint16_t msgId);
@@ -261,6 +192,7 @@ public:
void clearWaitedSubTopicId(void); void clearWaitedSubTopicId(void);
int setClientSleepPacket(MQTTGWPacket*); int setClientSleepPacket(MQTTGWPacket*);
int setProxyPacket(MQTTSNPacket* packet);
void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
@@ -271,6 +203,8 @@ public:
void connackSended(int rc); void connackSended(int rc);
void disconnected(void); void disconnected(void);
bool isConnectSendable(void); bool isConnectSendable(void);
void tryConnect(void);
ClientStatus getClientStatus(void);
uint16_t getNextPacketId(void); uint16_t getNextPacketId(void);
uint8_t getNextSnMsgId(void); uint8_t getNextSnMsgId(void);
@@ -286,6 +220,16 @@ public:
Forwarder* getForwarder(void); Forwarder* getForwarder(void);
void setForwarder(Forwarder* forwader); void setForwarder(Forwarder* forwader);
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 setClientId(MQTTSNString id);
void setWillTopic(MQTTSNString willTopic); void setWillTopic(MQTTSNString willTopic);
void setWillMsg(MQTTSNString willmsg); void setWillMsg(MQTTSNString willmsg);
@@ -298,6 +242,7 @@ public:
bool erasable(void); bool erasable(void);
bool isDisconnect(void); bool isDisconnect(void);
bool isConnecting(void);
bool isActive(void); bool isActive(void);
bool isSleep(void); bool isSleep(void);
bool isAwake(void); bool isAwake(void);
@@ -310,11 +255,11 @@ public:
bool isHoldPringReqest(void); bool isHoldPringReqest(void);
Client* getNextClient(void); Client* getNextClient(void);
Client* getOTAClient(void);
void setOTAClient(Client* cl);
private: private:
PacketQue<MQTTGWPacket> _clientSleepPacketQue; PacketQue<MQTTGWPacket> _clientSleepPacketQue;
PacketQue<MQTTSNPacket> _proxyPacketQue;
WaitREGACKPacketList _waitREGACKList; WaitREGACKPacketList _waitREGACKList;
Topics* _topics; Topics* _topics;
@@ -345,40 +290,13 @@ private:
SensorNetAddress _sensorNetAddr; SensorNetAddress _sensorNetAddr;
Forwarder* _forwarder; Forwarder* _forwarder;
ClientType _clientType;
bool _sessionStatus; bool _sessionStatus;
bool _hasPredefTopic; bool _hasPredefTopic;
Client* _nextClient; Client* _nextClient;
Client* _prevClient; Client* _prevClient;
Client* _otaClient;
};
/*=====================================
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;
}; };

View File

@@ -0,0 +1,473 @@
/**************************************************************************************
* 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 "MQTTSNGateway.h"
#include <string.h>
#include <string>
using namespace MQTTSNGW;
extern Gateway* theGateway;
/*=====================================
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(bool aggregate)
{
if (theGateway->getGWParams()->clientAuthentication )
{
int type = TRANSPEARENT_TYPE;
if ( aggregate )
{
type = AGGREGATER_TYPE;
}
setClientList(type);
_authorize = true;
}
}
void ClientList::setClientList(int type)
{
char param[MQTTSNGW_PARAM_MAX];
string fileName;
GatewayParams* params = theGateway->getGWParams();
if (theGateway->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.");
}
if ( params->clientListName == nullptr )
{
params->clientListName = strdup(fileName.c_str());
}
}
void ClientList::setPredefinedTopics(bool aggrecate)
{
char param[MQTTSNGW_PARAM_MAX];
string fileName;
GatewayParams* params = theGateway->getGWParams();
if (theGateway->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 forwarder;
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);
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 if ( forwarder && type == FORWARDER_TYPE)
{
theGateway->getAdapterManager()->getForwarderList()->addForwarder(&netAddr, &clientId);
}
else if (type == TRANSPEARENT_TYPE )
{
createClient(&netAddr, &clientId, stable, secure, 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;
}

View File

@@ -0,0 +1,72 @@
/**************************************************************************************
* 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
#define FORWARDER_TYPE 3
class Client;
/*=====================================
Class ClientList
=====================================*/
class ClientList
{
public:
ClientList();
~ClientList();
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);
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);
Gateway* _gateway {nullptr};
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_ */

View File

@@ -15,12 +15,13 @@
**************************************************************************************/ **************************************************************************************/
#include "MQTTSNGWClientRecvTask.h" #include "MQTTSNGWClientRecvTask.h"
#include "MQTTSNGateway.h"
#include "MQTTSNPacket.h" #include "MQTTSNPacket.h"
#include "MQTTSNGWForwarder.h" #include "MQTTSNGWQoSm1Proxy.h"
#include "MQTTSNGWEncapsulatedPacket.h" #include "MQTTSNGWEncapsulatedPacket.h"
#include <cstring> #include <cstring>
//#include "MQTTSNGWForwarder.h"
using namespace MQTTSNGW; using namespace MQTTSNGW;
char* currentDateTime(void); char* currentDateTime(void);
/*===================================== /*=====================================
@@ -56,14 +57,19 @@ void ClientRecvTask::initialize(int argc, char** argv)
*/ */
void ClientRecvTask::run() void ClientRecvTask::run()
{ {
Event* ev = 0; Event* ev = nullptr;
Client* client = 0; AdapterManager* adpMgr = _gateway->getAdapterManager();
char buf[128]; QoSm1Proxy* qosm1Proxy = adpMgr->getQoSm1Proxy();
bool isAggrActive = adpMgr->isAggregaterActive();
ClientList* clientList = _gateway->getClientList();
EventQue* packetEventQue = _gateway->getPacketEventQue();
char buf[128];
while (true) while (true)
{ {
Forwarder* fwd = 0; Client* client = nullptr;
Forwarder* fwd = nullptr;
WirelessNodeId nodeId; WirelessNodeId nodeId;
MQTTSNPacket* packet = new MQTTSNPacket(); MQTTSNPacket* packet = new MQTTSNPacket();
@@ -91,53 +97,65 @@ void ClientRecvTask::run()
if ( packet->getType() == MQTTSN_SEARCHGW ) if ( packet->getType() == MQTTSN_SEARCHGW )
{ {
/* write log and post Event */ /* write log and post Event */
log(0, packet); log(0, packet, 0);
ev = new Event(); ev = new Event();
ev->setBrodcastEvent(packet); ev->setBrodcastEvent(packet);
_gateway->getPacketEventQue()->post(ev); packetEventQue->post(ev);
continue; continue;
} }
SensorNetAddress* senderAddr = _gateway->getSensorNetwork()->getSenderAddress();
if ( packet->getType() == MQTTSN_ENCAPSULATED ) if ( packet->getType() == MQTTSN_ENCAPSULATED )
{ {
fwd = _gateway->getForwarderList()->getForwarder(_sensorNetwork->getSenderAddress()); fwd = _gateway->getAdapterManager()->getForwarderList()->getForwarder(senderAddr);
if ( fwd == 0 ) if ( fwd != nullptr )
{ {
log(0, packet); MQTTSNString fwdName = MQTTSNString_initializer;
WRITELOG("%s Forwarder %s is not authorized.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); fwdName.cstring = const_cast<char *>( fwd->getName() );
delete packet; log(0, packet, &fwdName);
continue;
}
else
{
MQTTSNString fwdName;
fwdName.lenstring.data = const_cast<char *>( fwd->getName() );
fwdName.lenstring.len = strlen(fwdName.lenstring.data);
log(0, packet, &fwdName);
MQTTSNGWEncapsulatedPacket encap; /* get the packet from the encapsulation message */
encap.desirialize(packet->getPacketData(), packet->getPacketLength()); MQTTSNGWEncapsulatedPacket encap;
nodeId.setId( encap.getWirelessNodeId() ); encap.desirialize(packet->getPacketData(), packet->getPacketLength());
client = fwd->getClient(&nodeId); nodeId.setId( encap.getWirelessNodeId() );
delete packet; client = fwd->getClient(&nodeId);
packet = encap.getMQTTSNPacket(); packet = encap.getMQTTSNPacket();
} }
} }
else else
{ {
/* get client from the ClientList of Gateway by sensorNetAddress. */ /* Check the client belonging to QoS-1Proxy ? */
client = _gateway->getClientList()->getClient(_sensorNetwork->getSenderAddress());
if ( qosm1Proxy->isActive() )
{
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;
}
}
}
} }
client = _gateway->getClientList()->getClient(senderAddr);
if ( client ) if ( client )
{ {
/* write log and post Event */ /* write log and post Event */
log(client, packet); log(client, packet, 0);
ev = new Event(); ev = new Event();
ev->setClientRecvEvent(client,packet); ev->setClientRecvEvent(client,packet);
_gateway->getPacketEventQue()->post(ev); packetEventQue->post(ev);
} }
else else
{ {
@@ -149,19 +167,19 @@ void ClientRecvTask::run()
if ( !packet->getCONNECT(&data) ) if ( !packet->getCONNECT(&data) )
{ {
log(0, packet, &data.clientID); 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; delete packet;
continue; continue;
} }
client = _gateway->getClientList()->getClient(&data.clientID); client = clientList->getClient(&data.clientID);
if ( fwd ) if ( fwd )
{ {
if ( client == 0 ) if ( client == nullptr )
{ {
/* create a new client */ /* 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. */ /* Add to af forwarded client list of forwarder. */
fwd->addClient(client, &nodeId); fwd->addClient(client, &nodeId);
@@ -171,12 +189,12 @@ void ClientRecvTask::run()
if ( client ) if ( client )
{ {
/* Client exists. Set SensorNet Address of it. */ /* Client exists. Set SensorNet Address of it. */
client->setClientAddress(_sensorNetwork->getSenderAddress()); client->setClientAddress(senderAddr);
} }
else else
{ {
/* create a new client */ /* create a new client */
client = _gateway->getClientList()->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, false, false); client = clientList->createClient(senderAddr, &data.clientID, isAggrActive);
} }
} }
@@ -184,7 +202,7 @@ void ClientRecvTask::run()
if (!client) 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; delete packet;
continue; continue;
} }
@@ -192,23 +210,20 @@ void ClientRecvTask::run()
/* post Client RecvEvent */ /* post Client RecvEvent */
ev = new Event(); ev = new Event();
ev->setClientRecvEvent(client, packet); ev->setClientRecvEvent(client, packet);
_gateway->getPacketEventQue()->post(ev); packetEventQue->post(ev);
} }
else 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); if ( packet->getType() == MQTTSN_ENCAPSULATED )
delete packet; {
WRITELOG("%s Forwarder(%s) is not declared by ClientList file. message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER);
/* Send DISCONNECT */ }
if ( fwd == 0 ) else
{ {
packet = new MQTTSNPacket(); WRITELOG("%s Client(%s) is not connecting. message has been discarded.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER);
packet->setDISCONNECT(0); }
ev = new Event(); delete packet;
ev->setClientSendEvent(_sensorNetwork->getSenderAddress(), packet);
_gateway->getClientSendQue()->post(ev);
}
} }
} }
} }
@@ -216,16 +231,22 @@ void ClientRecvTask::run()
void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id) void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id)
{ {
char pbuf[SIZE_OF_LOG_PACKET * 3];
const char* clientId; const char* clientId;
char cstr[MAX_CLIENTID_LENGTH + 1]; char cstr[MAX_CLIENTID_LENGTH + 1];
char msgId[6];
if ( id ) if ( id )
{ {
memset((void*)cstr, 0, id->lenstring.len + 1); if ( id->cstring )
strncpy(cstr, id->lenstring.data, id->lenstring.len) ; {
clientId = cstr; 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 ) else if ( client )
{ {
@@ -236,40 +257,48 @@ void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id)
clientId = UNKNOWNCL; clientId = UNKNOWNCL;
} }
switch (packet->getType()) log(clientId, packet);
{ }
case MQTTSN_SEARCHGW:
WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, CLIENT, packet->print(pbuf)); void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet)
break; {
case MQTTSN_CONNECT: char pbuf[SIZE_OF_LOG_PACKET * 3];
case MQTTSN_PINGREQ: char msgId[6];
WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));
break; switch (packet->getType())
case MQTTSN_DISCONNECT: {
case MQTTSN_WILLTOPICUPD: case MQTTSN_SEARCHGW:
case MQTTSN_WILLMSGUPD: WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, CLIENT, packet->print(pbuf));
case MQTTSN_WILLTOPIC: break;
case MQTTSN_WILLMSG: case MQTTSN_CONNECT:
WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); case MQTTSN_PINGREQ:
break; WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));
case MQTTSN_PUBLISH: break;
case MQTTSN_REGISTER: case MQTTSN_DISCONNECT:
case MQTTSN_SUBSCRIBE: case MQTTSN_WILLTOPICUPD:
case MQTTSN_UNSUBSCRIBE: case MQTTSN_WILLMSGUPD:
WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); case MQTTSN_WILLTOPIC:
break; case MQTTSN_WILLMSG:
case MQTTSN_REGACK: WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));
case MQTTSN_PUBACK: break;
case MQTTSN_PUBREC: case MQTTSN_PUBLISH:
case MQTTSN_PUBREL: case MQTTSN_REGISTER:
case MQTTSN_PUBCOMP: case MQTTSN_SUBSCRIBE:
WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); case MQTTSN_UNSUBSCRIBE:
break; WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf));
case MQTTSN_ENCAPSULATED: break;
WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); case MQTTSN_REGACK:
break; case MQTTSN_PUBACK:
default: case MQTTSN_PUBREC:
WRITELOG(FORMAT_W_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); case MQTTSN_PUBREL:
break; 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;
}
} }

View File

@@ -21,6 +21,7 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class AdapterManager;
/*===================================== /*=====================================
Class ClientRecvTask Class ClientRecvTask
@@ -28,14 +29,16 @@ namespace MQTTSNGW
class ClientRecvTask:public Thread class ClientRecvTask:public Thread
{ {
MAGIC_WORD_FOR_THREAD; MAGIC_WORD_FOR_THREAD;
friend AdapterManager;
public: public:
ClientRecvTask(Gateway*); ClientRecvTask(Gateway*);
~ClientRecvTask(); ~ClientRecvTask(void);
virtual void initialize(int argc, char** argv); virtual void initialize(int argc, char** argv);
void run(); void run(void);
private: private:
void log(Client*, MQTTSNPacket*, MQTTSNString* id = 0); void log(Client*, MQTTSNPacket*, MQTTSNString* id);
void log(const char* clientId, MQTTSNPacket* packet);
Gateway* _gateway; Gateway* _gateway;
SensorNetwork* _sensorNetwork; SensorNetwork* _sensorNetwork;

View File

@@ -15,9 +15,9 @@
**************************************************************************************/ **************************************************************************************/
#include "MQTTSNGWClientSendTask.h" #include "MQTTSNGWClientSendTask.h"
#include "MQTTSNGWPacket.h" #include "MQTTSNGWPacket.h"
#include "MQTTSNGWPacket.h"
#include "MQTTSNGateway.h" #include "MQTTSNGateway.h"
#include "MQTTSNGWEncapsulatedPacket.h" #include "MQTTSNGWEncapsulatedPacket.h"
#include "MQTTSNGWQoSm1Proxy.h"
using namespace MQTTSNGW; using namespace MQTTSNGW;
using namespace std; using namespace std;
@@ -39,8 +39,9 @@ ClientSendTask::~ClientSendTask()
void ClientSendTask::run() void ClientSendTask::run()
{ {
Client* client = 0; Client* client = nullptr;
MQTTSNPacket* packet = 0; MQTTSNPacket* packet = nullptr;
AdapterManager* adpMgr = _gateway->getAdapterManager();
int rc = 0; int rc = 0;
while (true) while (true)
@@ -57,22 +58,7 @@ void ClientSendTask::run()
{ {
client = ev->getClient(); client = ev->getClient();
packet = ev->getMQTTSNPacket(); packet = ev->getMQTTSNPacket();
Forwarder* fwd = client->getForwarder(); rc = adpMgr->unicastToClient(client, packet, this);
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);
rc = packet->unicast(_sensorNetwork, client->getSensorNetAddress());
}
} }
else if (ev->getEventType() == EtBroadcast) else if (ev->getEventType() == EtBroadcast)
{ {
@@ -135,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));
}

View File

@@ -21,6 +21,7 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class AdapterManager;
/*===================================== /*=====================================
Class ClientSendTask Class ClientSendTask
@@ -28,14 +29,14 @@ namespace MQTTSNGW
class ClientSendTask: public Thread class ClientSendTask: public Thread
{ {
MAGIC_WORD_FOR_THREAD; MAGIC_WORD_FOR_THREAD;
friend AdapterManager;
public: public:
ClientSendTask(Gateway* gateway); ClientSendTask(Gateway* gateway);
~ClientSendTask(); ~ClientSendTask(void);
void run(); void run(void);
private: private:
void log(Client*, MQTTSNPacket*); void log(Client* client, MQTTSNPacket* packet);
void log(Forwarder*, MQTTSNGWEncapsulatedPacket*);
Gateway* _gateway; Gateway* _gateway;
SensorNetwork* _sensorNetwork; SensorNetwork* _sensorNetwork;

View File

@@ -90,7 +90,10 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet
//* clear ConnectData of Client */ //* clear ConnectData of Client */
Connect* connectData = client->getConnectData(); Connect* connectData = client->getConnectData();
memset(connectData, 0, sizeof(Connect)); memset(connectData, 0, sizeof(Connect));
client->disconnected(); if ( !client->isAdapter() )
{
client->disconnected();
}
Topics* topics = client->getTopics(); Topics* topics = client->getTopics();
@@ -101,7 +104,7 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet
connectData->keepAliveTimer = data.duration; connectData->keepAliveTimer = data.duration;
connectData->flags.bits.will = data.willFlag; 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.password = 1;
connectData->flags.bits.username = 1; connectData->flags.bits.username = 1;
@@ -153,7 +156,7 @@ void MQTTSNConnectionHandler::handleWilltopic(Client* client, MQTTSNPacket* pack
{ {
int willQos; int willQos;
uint8_t willRetain; uint8_t willRetain;
MQTTSNString willTopic; MQTTSNString willTopic = MQTTSNString_initializer;
if ( packet->getWILLTOPIC(&willQos, &willRetain, &willTopic) == 0 ) if ( packet->getWILLTOPIC(&willQos, &willRetain, &willTopic) == 0 )
{ {
@@ -187,7 +190,7 @@ void MQTTSNConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet
return; return;
} }
MQTTSNString willmsg; MQTTSNString willmsg = MQTTSNString_initializer;
Connect* connectData = client->getConnectData(); Connect* connectData = client->getConnectData();
if( client->isConnectSendable() ) if( client->isConnectSendable() )
@@ -288,9 +291,9 @@ void MQTTSNConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet
void MQTTSNConnectionHandler::sendStoredPublish(Client* client) 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. // ToDo: This version can't re-send PUBLISH when PUBACK is not returned.
client->deleteFirstClientSleepPacket(); // pop the que to delete element. client->deleteFirstClientSleepPacket(); // pop the que to delete element.

View File

@@ -40,11 +40,15 @@ namespace MQTTSNGW
#define MAX_CLIENTS (100) // Number of Clients can be handled. #define MAX_CLIENTS (100) // Number of Clients can be handled.
#define MAX_CLIENTID_LENGTH (64) // Max length of clientID #define MAX_CLIENTID_LENGTH (64) // Max length of clientID
#define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages #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_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 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) #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 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 * Data Type
==================================*/ ==================================*/

View File

@@ -52,7 +52,7 @@ void WirelessNodeId::setId(uint8_t* id, uint8_t len)
} }
else else
{ {
_nodeId = 0; _nodeId = nullptr;
_len = 0; _len = 0;
} }
} }
@@ -123,7 +123,7 @@ int MQTTSNGWEncapsulatedPacket::desirialize(unsigned char* buf, unsigned short l
if ( _mqttsn ) if ( _mqttsn )
{ {
delete _mqttsn; delete _mqttsn;
_mqttsn = 0; _mqttsn = nullptr;
} }
_ctrl = buf[2]; _ctrl = buf[2];

View File

@@ -13,19 +13,21 @@
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#include <string.h>
#include "MQTTSNGWForwarder.h" #include "MQTTSNGWForwarder.h"
#include "SensorNetwork.h"
#include <string.h>
using namespace MQTTSNGW; using namespace MQTTSNGW;
using namespace std; using namespace std;
/* /*=====================================
* Class ForwarderList Class ForwarderList
*/ =====================================*/
ForwarderList::ForwarderList() ForwarderList::ForwarderList()
{ {
_head = 0; _head = nullptr;
} }
ForwarderList::~ForwarderList() ForwarderList::~ForwarderList()
@@ -42,6 +44,22 @@ ForwarderList::~ForwarderList()
} }
} }
void ForwarderList::initialize(Gateway* gw)
{
char param[MQTTSNGW_PARAM_MAX];
string fileName;
if (gw->getParam("Forwarder", param) == 0 )
{
if (!strcasecmp(param, "YES") )
{
gw->getClientList()->setClientList(FORWARDER_TYPE);
}
}
}
Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr) Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr)
{ {
Forwarder* p = _head; Forwarder* p = _head;
@@ -56,61 +74,10 @@ Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr)
return p; return p;
} }
bool ForwarderList::setFowerder(const char* fileName) Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId)
{
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* fdr = new Forwarder(addr, forwarderId); Forwarder* fdr = new Forwarder(addr, forwarderId);
if ( _head == 0 ) if ( _head == nullptr )
{ {
_head = fdr; _head = fdr;
} }
@@ -119,7 +86,7 @@ Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, string* forwarde
Forwarder* p = _head; Forwarder* p = _head;
while ( p ) while ( p )
{ {
if ( p->_next == 0 ) if ( p->_next == nullptr )
{ {
p->_next = fdr; p->_next = fdr;
break; break;
@@ -135,30 +102,30 @@ Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, string* forwarde
Forwarder::Forwarder() Forwarder::Forwarder()
{ {
_headClient = 0; _headClient = nullptr;
_next = 0; _next = nullptr;
} }
/* /*=====================================
* Class Forwarder Class ForwarderList
*/ =====================================*/
Forwarder::Forwarder(SensorNetAddress* addr, string* forwarderId) Forwarder::Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId)
{ {
_forwarderName = *forwarderId; _forwarderName = string(forwarderId->cstring);
_sensorNetAddr = *addr; _sensorNetAddr = *addr;
_headClient = 0; _headClient = nullptr;
_next = 0; _next = nullptr;
} }
Forwarder::~Forwarder(void) Forwarder::~Forwarder(void)
{ {
if ( _headClient ) if ( _headClient )
{ {
ForwardedClient* p = _headClient; ForwarderElement* p = _headClient;
while ( p ) while ( p )
{ {
ForwardedClient* next = p->_next; ForwarderElement* next = p->_next;
delete p; delete p;
p = next; p = next;
} }
@@ -172,12 +139,12 @@ const char* Forwarder::getId(void)
void Forwarder::addClient(Client* client, WirelessNodeId* id) void Forwarder::addClient(Client* client, WirelessNodeId* id)
{ {
ForwardedClient* p = _headClient; ForwarderElement* p = _headClient;
ForwardedClient* prev = 0; ForwarderElement* prev = nullptr;
client->setForwarder(this); client->setForwarder(this);
if ( p != 0 ) if ( p != nullptr )
{ {
while ( p ) while ( p )
{ {
@@ -191,7 +158,7 @@ void Forwarder::addClient(Client* client, WirelessNodeId* id)
} }
} }
ForwardedClient* fclient = new ForwardedClient(); ForwarderElement* fclient = new ForwarderElement();
fclient->setClient(client); fclient->setClient(client);
fclient->setWirelessNodeId(id); fclient->setWirelessNodeId(id);
@@ -208,9 +175,9 @@ void Forwarder::addClient(Client* client, WirelessNodeId* id)
Client* Forwarder::getClient(WirelessNodeId* id) Client* Forwarder::getClient(WirelessNodeId* id)
{ {
Client* cl = 0; Client* cl = nullptr;
_mutex.lock(); _mutex.lock();
ForwardedClient* p = _headClient; ForwarderElement* p = _headClient;
while ( p ) while ( p )
{ {
if ( *(p->_wirelessNodeId) == *id ) if ( *(p->_wirelessNodeId) == *id )
@@ -234,9 +201,9 @@ const char* Forwarder::getName(void)
WirelessNodeId* Forwarder::getWirelessNodeId(Client* client) WirelessNodeId* Forwarder::getWirelessNodeId(Client* client)
{ {
WirelessNodeId* nodeId = 0; WirelessNodeId* nodeId = nullptr;
_mutex.lock(); _mutex.lock();
ForwardedClient* p = _headClient; ForwarderElement* p = _headClient;
while ( p ) while ( p )
{ {
if ( p->_client == client ) if ( p->_client == client )
@@ -255,9 +222,9 @@ WirelessNodeId* Forwarder::getWirelessNodeId(Client* client)
void Forwarder::eraseClient(Client* client) void Forwarder::eraseClient(Client* client)
{ {
ForwardedClient* prev = 0; ForwarderElement* prev = nullptr;
_mutex.lock(); _mutex.lock();
ForwardedClient* p = _headClient; ForwarderElement* p = _headClient;
while ( p ) while ( p )
{ {
@@ -291,14 +258,14 @@ SensorNetAddress* Forwarder::getSensorNetAddr(void)
* Class ForwardedClient * Class ForwardedClient
*/ */
ForwardedClient::ForwardedClient() ForwarderElement::ForwarderElement()
: _client{0} : _client{0}
, _wirelessNodeId{0} , _wirelessNodeId{0}
, _next{0} , _next{0}
{ {
} }
ForwardedClient::~ForwardedClient() ForwarderElement::~ForwarderElement()
{ {
if (_wirelessNodeId) if (_wirelessNodeId)
{ {
@@ -306,14 +273,14 @@ ForwardedClient::~ForwardedClient()
} }
} }
void ForwardedClient::setClient(Client* client) void ForwarderElement::setClient(Client* client)
{ {
_client = client; _client = client;
} }
void ForwardedClient::setWirelessNodeId(WirelessNodeId* id) void ForwarderElement::setWirelessNodeId(WirelessNodeId* id)
{ {
if ( _wirelessNodeId == 0 ) if ( _wirelessNodeId == nullptr )
{ {
_wirelessNodeId = new WirelessNodeId(); _wirelessNodeId = new WirelessNodeId();
} }

View File

@@ -18,39 +18,47 @@
#define MQTTSNGATEWAY_SRC_MQTTSNGWFORWARDER_H_ #define MQTTSNGATEWAY_SRC_MQTTSNGWFORWARDER_H_
#include "MQTTSNGWClient.h" #include "MQTTSNGWClient.h"
#include "MQTTSNGateway.h"
#include "MQTTSNGWEncapsulatedPacket.h" #include "MQTTSNGWEncapsulatedPacket.h"
#include "SensorNetwork.h" #include "SensorNetwork.h"
namespace MQTTSNGW namespace MQTTSNGW
{ {
class Gateway;
class Client; class Client;
class WirelessNodeId; class WirelessNodeId;
class ForwardedClient /*=====================================
Class ForwarderElement
=====================================*/
class ForwarderElement
{ {
friend class Forwarder; friend class Forwarder;
public: public:
ForwardedClient(); ForwarderElement();
~ForwardedClient(); ~ForwarderElement();
void setClient(Client* client); void setClient(Client* client);
void setWirelessNodeId(WirelessNodeId* id); void setWirelessNodeId(WirelessNodeId* id);
private: private:
Client* _client; Client* _client;
WirelessNodeId* _wirelessNodeId; WirelessNodeId* _wirelessNodeId;
ForwardedClient* _next; ForwarderElement* _next;
}; };
/*=====================================
Class Forwarder
=====================================*/
class Forwarder class Forwarder
{ {
friend class ForwarderList; friend class ForwarderList;
public: public:
Forwarder(); Forwarder(void);
Forwarder(SensorNetAddress* addr, string* forwarderId); Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId);
~Forwarder(); ~Forwarder();
void initialize(void);
const char* getId(void); const char* getId(void);
void addClient(Client* client, WirelessNodeId* id); void addClient(Client* client, WirelessNodeId* id);
Client* getClient(WirelessNodeId* id); Client* getClient(WirelessNodeId* id);
@@ -62,20 +70,23 @@ public:
private: private:
string _forwarderName; string _forwarderName;
SensorNetAddress _sensorNetAddr; SensorNetAddress _sensorNetAddr;
ForwardedClient* _headClient; ForwarderElement* _headClient{nullptr};
Forwarder* _next; Forwarder* _next {nullptr};
Mutex _mutex; Mutex _mutex;
}; };
/*=====================================
Class ForwarderList
=====================================*/
class ForwarderList class ForwarderList
{ {
public: public:
ForwarderList(); ForwarderList();
~ForwarderList(); ~ForwarderList();
void initialize(Gateway* gw);
Forwarder* getForwarder(SensorNetAddress* addr); Forwarder* getForwarder(SensorNetAddress* addr);
bool setFowerder(const char* fileName); Forwarder* addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId);
Forwarder* addForwarder(SensorNetAddress* addr, string* forwarderId);
private: private:
Forwarder* _head; Forwarder* _head;

View File

@@ -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)
{
}

View File

@@ -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 <stdint.h>
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_ */

View File

@@ -24,12 +24,30 @@
using namespace std; using namespace std;
using namespace MQTTSNGW; 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; _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() MQTTSNPacket::~MQTTSNPacket()
{ {
if (_buf) if (_buf)
@@ -101,6 +119,17 @@ int MQTTSNPacket::getType(void)
return _buf[p]; 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) unsigned char* MQTTSNPacket::getPacketData(void)
{ {
return _buf; return _buf;
@@ -119,7 +148,8 @@ const char* MQTTSNPacket::getName()
int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration) int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration)
{ {
unsigned char buf[5]; 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); (unsigned short) duration);
return desirialize(buf, len); return desirialize(buf, len);
} }
@@ -127,44 +157,55 @@ int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration)
int MQTTSNPacket::setGWINFO(uint8_t gatewayId) int MQTTSNPacket::setGWINFO(uint8_t gatewayId)
{ {
unsigned char buf[3]; 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); return desirialize(buf, len);
} }
int MQTTSNPacket::setConnect(void) int MQTTSNPacket::setConnect(void)
{ {
unsigned char buf[40]; unsigned char buf[40];
int buflen = sizeof(buf);
MQTTSNPacket_connectData data; MQTTSNPacket_connectData data;
data.clientID.cstring = (char*)"client01"; data.clientID.cstring = (char*)"client01";
int len = MQTTSNSerialize_connect(buf, 40, &data); int len = MQTTSNSerialize_connect(buf, buflen, &data);
return desirialize(buf, len); return desirialize(buf, len);
} }
bool MQTTSNPacket::isAccepted(void)
{
return ( getType() == MQTTSN_CONNACK) && (_buf[2] == MQTTSN_RC_ACCEPTED);
}
int MQTTSNPacket::setCONNACK(uint8_t returnCode) int MQTTSNPacket::setCONNACK(uint8_t returnCode)
{ {
unsigned char buf[3]; 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); return desirialize(buf, len);
} }
int MQTTSNPacket::setWILLTOPICREQ(void) int MQTTSNPacket::setWILLTOPICREQ(void)
{ {
unsigned char buf[2]; unsigned char buf[2];
int len = MQTTSNSerialize_willtopicreq(buf, 2); int buflen = sizeof(buf);
int len = MQTTSNSerialize_willtopicreq(buf, buflen);
return desirialize(buf, len); return desirialize(buf, len);
} }
int MQTTSNPacket::setWILLMSGREQ(void) int MQTTSNPacket::setWILLMSGREQ(void)
{ {
unsigned char buf[2]; unsigned char buf[2];
int len = MQTTSNSerialize_willmsgreq(buf, 2); int buflen = sizeof(buf);
int len = MQTTSNSerialize_willmsgreq(buf, buflen);
return desirialize(buf, len); return desirialize(buf, len);
} }
int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* topicName) int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* topicName)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; 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); topicName);
return desirialize(buf, len); return desirialize(buf, len);
} }
@@ -172,7 +213,8 @@ int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* to
int MQTTSNPacket::setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode) int MQTTSNPacket::setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode)
{ {
unsigned char buf[7]; 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); (unsigned char) returnCode);
return desirialize(buf, len); return desirialize(buf, len);
} }
@@ -181,7 +223,8 @@ int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t ms
uint8_t* payload, uint16_t payloadlen) uint8_t* payload, uint16_t payloadlen)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; 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); (unsigned short) msgId, topic, (unsigned char*) payload, (int) payloadlen);
return desirialize(buf, len); return desirialize(buf, len);
} }
@@ -189,7 +232,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) int MQTTSNPacket::setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode)
{ {
unsigned char buf[7]; 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); (unsigned char) returnCode);
return desirialize(buf, len); return desirialize(buf, len);
} }
@@ -197,28 +241,32 @@ int MQTTSNPacket::setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode
int MQTTSNPacket::setPUBREC(uint16_t msgId) int MQTTSNPacket::setPUBREC(uint16_t msgId)
{ {
unsigned char buf[4]; 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); return desirialize(buf, len);
} }
int MQTTSNPacket::setPUBREL(uint16_t msgId) int MQTTSNPacket::setPUBREL(uint16_t msgId)
{ {
unsigned char buf[4]; 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); return desirialize(buf, len);
} }
int MQTTSNPacket::setPUBCOMP(uint16_t msgId) int MQTTSNPacket::setPUBCOMP(uint16_t msgId)
{ {
unsigned char buf[4]; 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); return desirialize(buf, len);
} }
int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode) int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode)
{ {
unsigned char buf[8]; 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); (unsigned short) msgId, (unsigned char) returnCode);
return desirialize(buf, len); return desirialize(buf, len);
} }
@@ -226,38 +274,59 @@ int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t r
int MQTTSNPacket::setUNSUBACK(uint16_t msgId) int MQTTSNPacket::setUNSUBACK(uint16_t msgId)
{ {
unsigned char buf[4]; 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); return desirialize(buf, len);
} }
int MQTTSNPacket::setPINGRESP(void) int MQTTSNPacket::setPINGRESP(void)
{ {
unsigned char buf[32]; unsigned char buf[32];
int len = MQTTSNSerialize_pingresp(buf, 32); int buflen = sizeof(buf);
int len = MQTTSNSerialize_pingresp(buf, buflen);
return desirialize(buf, len); return desirialize(buf, len);
} }
int MQTTSNPacket::setDISCONNECT(uint16_t duration) int MQTTSNPacket::setDISCONNECT(uint16_t duration)
{ {
unsigned char buf[4]; 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); return desirialize(buf, len);
} }
int MQTTSNPacket::setWILLTOPICRESP(uint8_t returnCode) int MQTTSNPacket::setWILLTOPICRESP(uint8_t returnCode)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; 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); return desirialize(buf, len);
} }
int MQTTSNPacket::setWILLMSGRESP(uint8_t returnCode) int MQTTSNPacket::setWILLMSGRESP(uint8_t returnCode)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; 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); 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) int MQTTSNPacket::getSERCHGW(uint8_t* radius)
{ {
return MQTTSNDeserialize_searchgw((unsigned char*) radius, (unsigned char*) _buf, _bufLen); return MQTTSNDeserialize_searchgw((unsigned char*) radius, (unsigned char*) _buf, _bufLen);
@@ -409,5 +478,110 @@ char* MQTTSNPacket::getMsgId(char* pbuf)
sprintf(pbuf, " "); sprintf(pbuf, " ");
break; break;
} }
if ( strcmp(pbuf, " 0000") == 0 )
{
sprintf(pbuf, " ");
}
return 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 );
}

View File

@@ -26,8 +26,9 @@ namespace MQTTSNGW
class MQTTSNPacket class MQTTSNPacket
{ {
public: public:
MQTTSNPacket(); MQTTSNPacket(void);
~MQTTSNPacket(); MQTTSNPacket(MQTTSNPacket &packet);
~MQTTSNPacket(void);
int unicast(SensorNetwork* network, SensorNetAddress* sendTo); int unicast(SensorNetwork* network, SensorNetAddress* sendTo);
int broadcast(SensorNetwork* network); int broadcast(SensorNetwork* network);
int recv(SensorNetwork* network); int recv(SensorNetwork* network);
@@ -59,6 +60,9 @@ public:
int setWILLTOPICRESP(uint8_t returnCode); int setWILLTOPICRESP(uint8_t returnCode);
int setWILLMSGRESP(uint8_t returnCode); int setWILLMSGRESP(uint8_t returnCode);
int setCONNECT(MQTTSNPacket_connectData* options);
int setPINGREQ(MQTTSNString* clientId);
int getSERCHGW(uint8_t* radius); int getSERCHGW(uint8_t* radius);
int getCONNECT(MQTTSNPacket_connectData* option); int getCONNECT(MQTTSNPacket_connectData* option);
int getCONNACK(uint8_t* returnCode); int getCONNACK(uint8_t* returnCode);
@@ -76,7 +80,13 @@ public:
int getDISCONNECT(uint16_t* duration); int getDISCONNECT(uint16_t* duration);
int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic); int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic);
int getWILLMSGUPD(MQTTSNString* willMsg); int getWILLMSGUPD(MQTTSNString* willMsg);
bool isAccepted(void);
bool isDuplicate(void);
bool isQoSMinusPUBLISH(void);
char* getMsgId(char* buf); char* getMsgId(char* buf);
int getMsgId(void);
void setMsgId(uint16_t msgId);
char* print(char* buf); char* print(char* buf);
private: private:

View File

@@ -21,12 +21,16 @@
#include "MQTTGWPacket.h" #include "MQTTGWPacket.h"
#include "MQTTSNGWClient.h" #include "MQTTSNGWClient.h"
#include "MQTTSNGWProcess.h" #include "MQTTSNGWProcess.h"
#include "MQTTSNGWAdapterManager.h"
#include "MQTTGWConnectionHandler.h" #include "MQTTGWConnectionHandler.h"
#include "MQTTGWPublishHandler.h" #include "MQTTGWPublishHandler.h"
#include "MQTTGWSubscribeHandler.h" #include "MQTTGWSubscribeHandler.h"
#include "MQTTSNGWConnectionHandler.h" #include "MQTTSNGWConnectionHandler.h"
#include "MQTTSNGWPublishHandler.h" #include "MQTTSNGWPublishHandler.h"
#include "MQTTSNGWSubscribeHandler.h" #include "MQTTSNGWSubscribeHandler.h"
#include "Timer.h"
#include "MQTTSNAggregateConnectionHandler.h"
#include <string.h> #include <string.h>
using namespace std; using namespace std;
@@ -48,6 +52,8 @@ PacketHandleTask::PacketHandleTask(Gateway* gateway)
_mqttsnConnection = new MQTTSNConnectionHandler(_gateway); _mqttsnConnection = new MQTTSNConnectionHandler(_gateway);
_mqttsnPublish = new MQTTSNPublishHandler(_gateway); _mqttsnPublish = new MQTTSNPublishHandler(_gateway);
_mqttsnSubscribe = new MQTTSNSubscribeHandler(_gateway); _mqttsnSubscribe = new MQTTSNSubscribeHandler(_gateway);
_mqttsnAggrConnection = new MQTTSNAggregateConnectionHandler(_gateway);
} }
/** /**
@@ -79,15 +85,22 @@ PacketHandleTask::~PacketHandleTask()
{ {
delete _mqttsnSubscribe; delete _mqttsnSubscribe;
} }
if ( _mqttsnAggrConnection )
{
delete _mqttsnAggrConnection;
}
} }
void PacketHandleTask::run() void PacketHandleTask::run()
{ {
Event* ev = 0; Event* ev = nullptr;
EventQue* eventQue = _gateway->getPacketEventQue(); EventQue* eventQue = _gateway->getPacketEventQue();
Client* client = 0; AdapterManager* adpMgr = _gateway->getAdapterManager();
MQTTSNPacket* snPacket = 0;
MQTTGWPacket* brPacket = 0; Client* client = nullptr;
MQTTSNPacket* snPacket = nullptr;
MQTTGWPacket* brPacket = nullptr;
char msgId[6]; char msgId[6];
memset(msgId, 0, 6); memset(msgId, 0, 6);
@@ -113,6 +126,9 @@ void PacketHandleTask::run()
_mqttsnConnection->sendADVERTISE(); _mqttsnConnection->sendADVERTISE();
_advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL);
} }
/*------ Check Adapters Connect or PINGREQ ------*/
adpMgr->checkConnection();
} }
/*------ Handle SEARCHGW Message ---------*/ /*------ Handle SEARCHGW Message ---------*/
@@ -130,101 +146,221 @@ void PacketHandleTask::run()
DEBUGLOG(" PacketHandleTask gets %s %s from the client.\n", snPacket->getName(), snPacket->getMsgId(msgId)); DEBUGLOG(" PacketHandleTask gets %s %s from the client.\n", snPacket->getName(), snPacket->getMsgId(msgId));
switch (snPacket->getType()) if ( adpMgr->isAggregatedClient(client) )
{ {
case MQTTSN_CONNECT: aggregatePacketHandler(client, snPacket);
_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;
} }
else
{
transparentPacketHandler(client, snPacket);
}
/* Reset the Timer for PINGREQ. */ /* Reset the Timer for PINGREQ. */
client->updateStatus(snPacket); client->updateStatus(snPacket);
} }
/*------ Handle Messages form Broker ---------*/ /*------ Handle Messages form Broker ---------*/
else if (ev->getEventType() == EtBrokerRecv) else if ( ev->getEventType() == EtBrokerRecv )
{ {
client = ev->getClient(); client = ev->getClient();
brPacket = ev->getMQTTGWPacket(); brPacket = ev->getMQTTGWPacket();
DEBUGLOG(" PacketHandleTask gets %s %s from the broker.\n", brPacket->getName(), brPacket->getMsgId(msgId)); DEBUGLOG(" PacketHandleTask gets %s %s from the broker.\n", brPacket->getName(), brPacket->getMsgId(msgId));
switch (brPacket->getType())
if ( client->isAggregater() )
{ {
case CONNACK: aggregatePacketHandler(client, brPacket);
_mqttConnection->handleConnack(client, brPacket); }
break; else
case PINGRESP: {
_mqttConnection->handlePingresp(client, brPacket); transparentPacketHandler(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;
} }
} }
delete ev; 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;
}
}

View File

@@ -17,46 +17,60 @@
#ifndef MQTTSNGWPACKETHANDLETASK_H_ #ifndef MQTTSNGWPACKETHANDLETASK_H_
#define MQTTSNGWPACKETHANDLETASK_H_ #define MQTTSNGWPACKETHANDLETASK_H_
#include <Timer.h> #include "Timer.h"
#include "MQTTSNGWDefines.h" #include "MQTTSNGWProcess.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"
namespace MQTTSNGW 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 #define ERRNO_APL_01 11 // Task Initialize Error
class Thread;
class Timer;
/*===================================== /*=====================================
Class PacketHandleTask Class PacketHandleTask
=====================================*/ =====================================*/
class PacketHandleTask : public Thread class PacketHandleTask : public Thread
{ {
MAGIC_WORD_FOR_THREAD; MAGIC_WORD_FOR_THREAD;
friend class MQTTGWAggregatePublishHandler;
friend class MQTTGWAggregateSubscribeHandler;
friend class MQTTSNAggregateConnectionHandler;
friend class MQTTSNAggregatePublishHandler;
friend class MQTTSNAggregateSubscribeHandler;
public: public:
PacketHandleTask(Gateway* gateway); PacketHandleTask(Gateway* gateway);
~PacketHandleTask(); ~PacketHandleTask();
void run(); void run();
private: 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 _advertiseTimer;
Timer _sendUnixTimer; Timer _sendUnixTimer;
MQTTGWConnectionHandler* _mqttConnection; MQTTGWConnectionHandler* _mqttConnection {nullptr};
MQTTGWPublishHandler* _mqttPublish; MQTTGWPublishHandler* _mqttPublish {nullptr};
MQTTGWSubscribeHandler* _mqttSubscribe; MQTTGWSubscribeHandler* _mqttSubscribe {nullptr};
MQTTSNConnectionHandler* _mqttsnConnection; MQTTSNConnectionHandler* _mqttsnConnection {nullptr};
MQTTSNPublishHandler* _mqttsnPublish; MQTTSNPublishHandler* _mqttsnPublish {nullptr};
MQTTSNSubscribeHandler* _mqttsnSubscribe; MQTTSNSubscribeHandler* _mqttsnSubscribe {nullptr};
MQTTSNAggregateConnectionHandler* _mqttsnAggrConnection {nullptr};
}; };

View File

@@ -34,8 +34,8 @@ char* currentDateTime(void);
/*===================================== /*=====================================
Global Variables & Functions Global Variables & Functions
======================================*/ ======================================*/
Process* MQTTSNGW::theProcess = 0; Process* MQTTSNGW::theProcess = nullptr;
MultiTaskProcess* MQTTSNGW::theMultiTaskProcess = 0; MultiTaskProcess* MQTTSNGW::theMultiTaskProcess = nullptr;
/* /*
* Save the type of signal * Save the type of signal
@@ -359,8 +359,8 @@ Exception::Exception(const int exNo, const string& message)
{ {
_message = message; _message = message;
_exNo = exNo; _exNo = exNo;
_fileName = 0; _fileName = nullptr;
_functionName = 0; _functionName = nullptr;
_line = 0; _line = 0;
} }

View File

@@ -132,8 +132,8 @@ public:
QueElement(T* t) QueElement(T* t)
{ {
_element = t; _element = t;
_next = 0; _next = nullptr;
_prev = 0; _prev = nullptr;
} }
~QueElement() ~QueElement()
@@ -155,8 +155,8 @@ class Que
public: public:
Que() Que()
{ {
_head = 0; _head = nullptr;
_tail = 0; _tail = nullptr;
_cnt = 0; _cnt = 0;
_maxSize = 0; _maxSize = 0;
} }
@@ -180,12 +180,12 @@ public:
QueElement<T>* head = _head; QueElement<T>* head = _head;
if ( _head == _tail ) if ( _head == _tail )
{ {
_head = _tail = 0; _head = _tail = nullptr;
} }
else else
{ {
_head = head->_next; _head = head->_next;
head->_prev = 0; head->_prev = nullptr;
} }
delete head; delete head;
_cnt--; _cnt--;
@@ -861,13 +861,13 @@ class ListElm
public: public:
ListElm() ListElm()
{ {
_elm = 0; _elm = nullptr;
_prev = _next = 0; _prev = _next = nullptr;
} }
ListElm(T* elm) ListElm(T* elm)
{ {
_elm = elm; _elm = elm;
_prev = _next = 0; _prev = _next = nullptr;
} }
T* getContent(void) T* getContent(void)
{ {
@@ -888,7 +888,7 @@ class List{
public: public:
List() List()
{ {
_head = _tail = 0; _head = _tail = nullptr;
_size = 0; _size = 0;
} }
~List() ~List()
@@ -899,11 +899,11 @@ public:
int add(T* t) int add(T* t)
{ {
ListElm<T>* elm = new ListElm<T>(t); ListElm<T>* elm = new ListElm<T>(t);
if ( elm == 0 ) if ( elm == nullptr )
{ {
return 0; return 0;
} }
if ( _head == 0 ) if ( _head == nullptr )
{ {
_head = elm; _head = elm;
_tail = elm; _tail = elm;
@@ -929,7 +929,7 @@ public:
else if ( _tail == elm ) else if ( _tail == elm )
{ {
_tail = elm->_prev; _tail = elm->_prev;
elm->_prev->_next = 0; elm->_prev->_next = nullptr;
_size--; _size--;
delete elm; delete elm;
} }
@@ -950,8 +950,8 @@ public:
delete p; delete p;
p = q; p = q;
} }
_head = 0; _head = nullptr;
_tail = 0; _tail = nullptr;
_size = 0; _size = 0;
} }

View File

@@ -20,6 +20,7 @@
#include "MQTTGWPacket.h" #include "MQTTGWPacket.h"
#include "MQTTSNGateway.h" #include "MQTTSNGateway.h"
#include "MQTTSNGWClient.h" #include "MQTTSNGWClient.h"
#include "MQTTSNGWQoSm1Proxy.h"
#include <string.h> #include <string.h>
using namespace std; using namespace std;
using namespace MQTTSNGW; 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; uint8_t dup;
int qos; int qos;
@@ -43,30 +44,30 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
uint8_t* payload; uint8_t* payload;
MQTTSN_topicid topicid; MQTTSN_topicid topicid;
int payloadlen; int payloadlen;
Publish pub; Publish pub = {0, 0, 0, 0, 0, 0};
char shortTopic[2]; char shortTopic[2];
if ( !client->isActive() ) if ( !_gateway->getAdapterManager()->getQoSm1Proxy()->isActive() )
{ {
/* Reply DISCONNECT to the client */ if ( client->isQoSm1() )
Event* ev = new Event(); {
MQTTSNPacket* disconnect = new MQTTSNPacket(); _gateway->getAdapterManager()->getQoSm1Proxy()->savePacket(client, packet);
disconnect->setDISCONNECT(0);
ev->setClientSendEvent(client, disconnect); return nullptr;
_gateway->getClientSendQue()->post(ev); }
return;
} }
if ( packet->getPUBLISH(&dup, &qos, &retained, &msgId, &topicid, &payload, &payloadlen) ==0 ) if ( packet->getPUBLISH(&dup, &qos, &retained, &msgId, &topicid, &payload, &payloadlen) ==0 )
{ {
return; return nullptr;
} }
pub.msgId = msgId; pub.msgId = msgId;
pub.header.bits.dup = dup; pub.header.bits.dup = dup;
pub.header.bits.qos = qos; pub.header.bits.qos = ( qos == 3 ? 0 : qos );
pub.header.bits.retain = retained; pub.header.bits.retain = retained;
Topic* topic = 0; Topic* topic = nullptr;
if( topicid.type == MQTTSN_TOPIC_TYPE_SHORT ) if( topicid.type == MQTTSN_TOPIC_TYPE_SHORT )
{ {
@@ -79,7 +80,13 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
{ {
topic = client->getTopics()->getTopicById(&topicid); topic = client->getTopics()->getTopicById(&topicid);
if( !topic && msgId && qos > 0 ) if( !topic && qos == 3 )
{
WRITELOG("%s Invali TopicId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return nullptr;
}
if( !topic && msgId && qos > 0 && qos < 3 )
{ {
/* Reply PubAck with INVALID_TOPIC_ID to the client */ /* Reply PubAck with INVALID_TOPIC_ID to the client */
MQTTSNPacket* pubAck = new MQTTSNPacket(); MQTTSNPacket* pubAck = new MQTTSNPacket();
@@ -87,7 +94,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setClientSendEvent(client, pubAck); ev1->setClientSendEvent(client, pubAck);
_gateway->getClientSendQue()->post(ev1); _gateway->getClientSendQue()->post(ev1);
return; return nullptr;
} }
if ( topic ) if ( topic )
{ {
@@ -96,7 +103,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
} }
} }
/* Save a msgId & a TopicId pare for PUBACK */ /* 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); client->setWaitedPubTopicId(msgId, topicid.data.id, topicid.type);
} }
@@ -106,9 +113,18 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
MQTTGWPacket* publish = new MQTTGWPacket(); MQTTGWPacket* publish = new MQTTGWPacket();
publish->setPUBLISH(&pub); publish->setPUBLISH(&pub);
Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, publish); if ( _gateway->getAdapterManager()->isAggregaterActive() && client->isAggregated() )
_gateway->getBrokerSendQue()->post(ev1); {
return publish;
}
else
{
Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, publish);
_gateway->getBrokerSendQue()->post(ev1);
return nullptr;
}
} }
void MQTTSNPublishHandler::handlePuback(Client* client, MQTTSNPacket* packet) void MQTTSNPublishHandler::handlePuback(Client* client, MQTTSNPacket* packet)
@@ -126,11 +142,14 @@ void MQTTSNPublishHandler::handlePuback(Client* client, MQTTSNPacket* packet)
if ( rc == MQTTSN_RC_ACCEPTED) if ( rc == MQTTSN_RC_ACCEPTED)
{ {
MQTTGWPacket* pubAck = new MQTTGWPacket(); if ( !_gateway->getAdapterManager()->getAggregater()->isActive() )
pubAck->setAck(PUBACK, msgId); {
Event* ev1 = new Event(); MQTTGWPacket* pubAck = new MQTTGWPacket();
ev1->setBrokerSendEvent(client, pubAck); pubAck->setAck(PUBACK, msgId);
_gateway->getBrokerSendQue()->post(ev1); Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, pubAck);
_gateway->getBrokerSendQue()->post(ev1);
}
} }
else if ( rc == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID) else if ( rc == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID)
{ {
@@ -161,7 +180,7 @@ void MQTTSNPublishHandler::handleRegister(Client* client, MQTTSNPacket* packet)
{ {
uint16_t id; uint16_t id;
uint16_t msgId; uint16_t msgId;
MQTTSNString topicName; MQTTSNString topicName = MQTTSNString_initializer;;
MQTTSN_topicid topicid; MQTTSN_topicid topicid;
if ( client->isActive() || client->isAwake()) if ( client->isActive() || client->isAwake())
@@ -199,7 +218,7 @@ void MQTTSNPublishHandler::handleRegAck( Client* client, MQTTSNPacket* packet)
MQTTSNPacket* regAck = client->getWaitREGACKPacketList()->getPacket(msgId); MQTTSNPacket* regAck = client->getWaitREGACKPacketList()->getPacket(msgId);
if ( regAck != 0 ) if ( regAck != nullptr )
{ {
client->getWaitREGACKPacketList()->erase(msgId); client->getWaitREGACKPacketList()->erase(msgId);
Event* ev = new Event(); Event* ev = new Event();
@@ -219,3 +238,48 @@ 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);
}
}

View File

@@ -27,11 +27,15 @@ class MQTTSNPublishHandler
public: public:
MQTTSNPublishHandler(Gateway* gateway); MQTTSNPublishHandler(Gateway* gateway);
~MQTTSNPublishHandler(); ~MQTTSNPublishHandler();
void handlePublish(Client* client, MQTTSNPacket* packet); MQTTGWPacket* handlePublish(Client* client, MQTTSNPacket* packet);
void handlePuback(Client* client, MQTTSNPacket* packet); void handlePuback(Client* client, MQTTSNPacket* packet);
void handleAck(Client* client, MQTTSNPacket* packet, uint8_t packetType); void handleAck(Client* client, MQTTSNPacket* packet, uint8_t packetType);
void handleRegister(Client* client, MQTTSNPacket* packet); void handleRegister(Client* client, MQTTSNPacket* packet);
void handleRegAck( 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: private:
Gateway* _gateway; Gateway* _gateway;
}; };

View File

@@ -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
**************************************************************************************/
#include "MQTTSNGWQoSm1Proxy.h"
#include "MQTTSNGateway.h"
#include "SensorNetwork.h"
#include "MQTTSNGWClientList.h"
#include <string>
#include <string.h>
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(QOSM1PROXY_TYPE);
/* initialize Adapter */
string name = string(_gateway->getGWParams()->gatewayName) + "QoS-1";
setup(name.c_str(), Atype_QoSm1Proxy);
_isActive = true;
}
}
}
bool QoSm1Proxy::isActive(void)
{
return _isActive;
}

View File

@@ -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_ */

View File

@@ -34,13 +34,13 @@ MQTTSNSubscribeHandler::~MQTTSNSubscribeHandler()
} }
void MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packet) MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packet)
{ {
uint8_t dup; uint8_t dup;
int qos; int qos;
uint16_t msgId; uint16_t msgId;
MQTTSN_topicid topicFilter; MQTTSN_topicid topicFilter;
Topic* topic = 0; Topic* topic = nullptr;
uint16_t topicId = 0; uint16_t topicId = 0;
MQTTGWPacket* subscribe; MQTTGWPacket* subscribe;
Event* ev1; Event* ev1;
@@ -48,12 +48,12 @@ void MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packe
if ( packet->getSUBSCRIBE(&dup, &qos, &msgId, &topicFilter) == 0 ) if ( packet->getSUBSCRIBE(&dup, &qos, &msgId, &topicFilter) == 0 )
{ {
return; return nullptr;
} }
if ( msgId == 0 ) if ( msgId == 0 )
{ {
return; return nullptr;
} }
if ( topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED ) 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) else if (topicFilter.type == MQTTSN_TOPIC_TYPE_NORMAL)
{ {
topic = client->getTopics()->getTopicByName(&topicFilter); topic = client->getTopics()->getTopicByName(&topicFilter);
if ( topic == 0 ) if ( topic == nullptr )
{ {
topic = client->getTopics()->add(&topicFilter); 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); WRITELOG("%s Client(%s) can't add the Topic.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return; return nullptr;
} }
} }
topicId = topic->getTopicId(); topicId = topic->getTopicId();
@@ -100,10 +100,17 @@ void MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packe
client->setWaitedSubTopicId(msgId, topicId, topicFilter.type); client->setWaitedSubTopicId(msgId, topicId, topicFilter.type);
ev1 = new Event(); if ( !client->isAggregated() )
ev1->setBrokerSendEvent(client, subscribe); {
_gateway->getBrokerSendQue()->post(ev1); ev1 = new Event();
return; ev1->setBrokerSendEvent(client, subscribe);
_gateway->getBrokerSendQue()->post(ev1);
return nullptr;
}
else
{
return subscribe;
}
RespExit: RespExit:
@@ -112,22 +119,23 @@ RespExit:
evsuback = new Event(); evsuback = new Event();
evsuback->setClientSendEvent(client, sSuback); evsuback->setClientSendEvent(client, sSuback);
_gateway->getClientSendQue()->post(evsuback); _gateway->getClientSendQue()->post(evsuback);
return nullptr;
} }
void MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* packet) MQTTGWPacket* MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* packet)
{ {
uint16_t msgId; uint16_t msgId;
MQTTSN_topicid topicFilter; MQTTSN_topicid topicFilter;
MQTTGWPacket* unsubscribe = 0;; MQTTGWPacket* unsubscribe = nullptr;
if ( packet->getUNSUBSCRIBE(&msgId, &topicFilter) == 0 ) if ( packet->getUNSUBSCRIBE(&msgId, &topicFilter) == 0 )
{ {
return; return nullptr;
} }
if ( msgId == 0 ) if ( msgId == 0 )
{ {
return; return nullptr;
} }
Topic* topic = client->getTopics()->getTopicById(&topicFilter); Topic* topic = client->getTopics()->getTopicById(&topicFilter);
@@ -143,14 +151,14 @@ void MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* pac
} }
else else
{ {
if ( topic == 0 ) if ( topic == nullptr )
{ {
MQTTSNPacket* sUnsuback = new MQTTSNPacket(); MQTTSNPacket* sUnsuback = new MQTTSNPacket();
sUnsuback->setUNSUBACK(msgId); sUnsuback->setUNSUBACK(msgId);
Event* evsuback = new Event(); Event* evsuback = new Event();
evsuback->setClientSendEvent(client, sUnsuback); evsuback->setClientSendEvent(client, sUnsuback);
_gateway->getClientSendQue()->post(evsuback); _gateway->getClientSendQue()->post(evsuback);
return; return nullptr;
} }
else else
{ {
@@ -159,8 +167,81 @@ void MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* pac
} }
} }
Event* ev1 = new Event(); if ( !client->isAggregated() )
ev1->setBrokerSendEvent(client, unsubscribe); {
_gateway->getBrokerSendQue()->post(ev1); 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);
}
}

View File

@@ -31,8 +31,10 @@ class MQTTSNSubscribeHandler
public: public:
MQTTSNSubscribeHandler(Gateway* gateway); MQTTSNSubscribeHandler(Gateway* gateway);
~MQTTSNSubscribeHandler(); ~MQTTSNSubscribeHandler();
void handleSubscribe(Client* client, MQTTSNPacket* packet); MQTTGWPacket* handleSubscribe(Client* client, MQTTSNPacket* packet);
void handleUnsubscribe(Client* client, MQTTSNPacket* packet); MQTTGWPacket* handleUnsubscribe(Client* client, MQTTSNPacket* packet);
void handleAggregateSubscribe(Client* client, MQTTSNPacket* packet);
void handleAggregateUnsubscribe(Client* client, MQTTSNPacket* packet);
private: private:
Gateway* _gateway; Gateway* _gateway;

View File

@@ -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 <string.h>
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<char*>(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;
}

View File

@@ -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_ */

View File

@@ -17,6 +17,6 @@
#ifndef MQTTSNGWVERSION_H_IN_ #ifndef MQTTSNGWVERSION_H_IN_
#define MQTTSNGWVERSION_H_IN_ #define MQTTSNGWVERSION_H_IN_
#define PAHO_GATEWAY_VERSION "1.2.0" #define PAHO_GATEWAY_VERSION "1.3.0"
#endif /* MQTTSNGWVERSION_H_IN_ */ #endif /* MQTTSNGWVERSION_H_IN_ */

View File

@@ -18,6 +18,8 @@
#include "SensorNetwork.h" #include "SensorNetwork.h"
#include "MQTTSNGWProcess.h" #include "MQTTSNGWProcess.h"
#include "MQTTSNGWVersion.h" #include "MQTTSNGWVersion.h"
#include "MQTTSNGWQoSm1Proxy.h"
#include "MQTTSNGWClient.h"
#include <string.h> #include <string.h>
using namespace MQTTSNGW; using namespace MQTTSNGW;
@@ -26,29 +28,15 @@ char* currentDateTime(void);
/*===================================== /*=====================================
Class Gateway Class Gateway
=====================================*/ =====================================*/
Gateway::Gateway() MQTTSNGW::Gateway* theGateway = nullptr;
Gateway::Gateway(void)
{ {
theMultiTaskProcess = this; theMultiTaskProcess = this;
theProcess = this; theProcess = this;
_params.loginId = 0; _packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS);
_params.password = 0; _clientList = new ClientList();
_params.keepAlive = 0; _adapterManager = new AdapterManager(this);
_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;
_packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS);
} }
Gateway::~Gateway() Gateway::~Gateway()
@@ -101,23 +89,40 @@ Gateway::~Gateway()
{ {
free(_params.configName); free(_params.configName);
} }
if ( _params.predefinedTopicFileName )
if ( _params.qosMinusClientListName )
{ {
free(_params.predefinedTopicFileName); free(_params.qosMinusClientListName);
} }
if ( _params.forwarderListName )
if ( _adapterManager )
{ {
free(_params.forwarderListName); 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) void Gateway::initialize(int argc, char** argv)
{ {
char param[MQTTSNGW_PARAM_MAX]; char param[MQTTSNGW_PARAM_MAX];
string fileName; string fileName;
theGateway = this;
MultiTaskProcess::initialize(argc, argv); MultiTaskProcess::initialize(argc, argv);
resetRingBuffer(); resetRingBuffer();
_params.configDir = *getConfigDirName();
fileName = _params.configDir + *getConfigFileName();
_params.configName = strdup(fileName.c_str());
if (getParam("BrokerName", param) == 0) if (getParam("BrokerName", param) == 0)
{ {
_params.brokerName = strdup(param); _params.brokerName = strdup(param);
@@ -163,6 +168,11 @@ void Gateway::initialize(int argc, char** argv)
_params.gatewayName = strdup(param); _params.gatewayName = strdup(param);
} }
if (_params.gatewayName == 0 )
{
throw Exception( "Gateway::initialize: Gateway Name is missing.");
}
_params.mqttVersion = DEFAULT_MQTT_VERSION; _params.mqttVersion = DEFAULT_MQTT_VERSION;
if (getParam("MQTTVersion", param) == 0) if (getParam("MQTTVersion", param) == 0)
{ {
@@ -176,7 +186,6 @@ void Gateway::initialize(int argc, char** argv)
} }
_params.keepAlive = DEFAULT_KEEP_ALIVE_TIME; _params.keepAlive = DEFAULT_KEEP_ALIVE_TIME;
if (getParam("KeepAlive", param) == 0) if (getParam("KeepAlive", param) == 0)
{ {
_params.keepAlive = atoi(param); _params.keepAlive = atoi(param);
@@ -201,79 +210,23 @@ void Gateway::initialize(int argc, char** argv)
{ {
if (!strcasecmp(param, "YES")) if (!strcasecmp(param, "YES"))
{ {
if (getParam("ClientsList", param) == 0) _params.clientAuthentication = true;
{
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());
} }
} }
/* ClientList and Adapters Initialize */
_adapterManager->initialize();
bool aggregate = _adapterManager->isAggregaterActive();
_clientList->initialize(aggregate);
if (getParam("PredefinedTopic", param) == 0 ) /* Setup predefined topics */
{ _clientList->setPredefinedTopics(aggregate);
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());
}
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;
}
}
fileName = *getConfigDirName() + *getConfigFileName();
_params.configName = strdup(fileName.c_str());
} }
void Gateway::run(void) void Gateway::run(void)
{ {
/* write prompts */
_lightIndicator.redLight(true); _lightIndicator.redLight(true);
WRITELOG("\n%s", PAHO_COPYRIGHT4); WRITELOG("\n%s", PAHO_COPYRIGHT4);
WRITELOG("\n%s\n", PAHO_COPYRIGHT0); WRITELOG("\n%s\n", PAHO_COPYRIGHT0);
@@ -284,26 +237,26 @@ void Gateway::run(void)
WRITELOG("%s\n", PAHO_COPYRIGHT4); WRITELOG("%s\n", PAHO_COPYRIGHT4);
WRITELOG("\n%s %s has been started.\n\n", currentDateTime(), _params.gatewayName); WRITELOG("\n%s %s has been started.\n\n", currentDateTime(), _params.gatewayName);
WRITELOG(" ConfigFile: %s\n", _params.configName); 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 ) if ( _params.predefinedTopicFileName )
{ {
WRITELOG(" PreDefFile: %s\n", _params.predefinedTopicFileName); WRITELOG(" PreDefFile: %s\n", _params.predefinedTopicFileName);
} }
if ( _params.forwarderListName )
{
WRITELOG(" Forwarders: %s\n", _params.forwarderListName);
}
WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription()); WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription());
WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure);
WRITELOG(" RootCApath: %s\n", _params.rootCApath); WRITELOG(" RootCApath: %s\n", _params.rootCApath);
WRITELOG(" RootCAfile: %s\n", _params.rootCAfile); WRITELOG(" RootCAfile: %s\n", _params.rootCAfile);
WRITELOG(" CertKey: %s\n", _params.certKey); WRITELOG(" CertKey: %s\n", _params.certKey);
WRITELOG(" PrivateKey: %s\n", _params.privateKey); WRITELOG(" PrivateKey: %s\n\n\n", _params.privateKey);
/* Run Tasks until CTRL+C entred */
MultiTaskProcess::run(); MultiTaskProcess::run();
/* stop Tasks */ /* stop Tasks */
@@ -341,12 +294,7 @@ EventQue* Gateway::getBrokerSendQue()
ClientList* Gateway::getClientList() ClientList* Gateway::getClientList()
{ {
return &_clientList; return _clientList;
}
ForwarderList* Gateway::getForwarderList(void)
{
return &_forwarderList;
} }
SensorNetwork* Gateway::getSensorNetwork() SensorNetwork* Gateway::getSensorNetwork()
@@ -364,6 +312,18 @@ GatewayParams* Gateway::getGWParams(void)
return &_params; return &_params;
} }
AdapterManager* Gateway::getAdapterManager(void)
{
return _adapterManager;
}
bool Gateway::hasSecureConnection(void)
{
return ( _params.certKey
&& _params.privateKey
&& _params.rootCApath
&& _params.rootCAfile );
}
/*===================================== /*=====================================
Class EventQue Class EventQue
=====================================*/ =====================================*/
@@ -390,9 +350,9 @@ void EventQue::setMaxSize(uint16_t maxSize)
Event* EventQue::wait(void) Event* EventQue::wait(void)
{ {
Event* ev = 0; Event* ev = nullptr;
while(ev == 0) while(ev == nullptr)
{ {
if ( _que.size() == 0 ) if ( _que.size() == 0 )
{ {
@@ -460,11 +420,7 @@ int EventQue::size()
=====================================*/ =====================================*/
Event::Event() Event::Event()
{ {
_eventType = Et_NA;
_client = 0;
_sensorNetAddr = 0;
_mqttSNPacket = 0;
_mqttGWPacket = 0;
} }
Event::~Event() Event::~Event()
@@ -560,3 +516,5 @@ MQTTGWPacket* Event::getMQTTGWPacket(void)
{ {
return _mqttGWPacket; return _mqttGWPacket;
} }

View File

@@ -16,10 +16,10 @@
#ifndef MQTTSNGATEWAY_H_ #ifndef MQTTSNGATEWAY_H_
#define MQTTSNGATEWAY_H_ #define MQTTSNGATEWAY_H_
#include "MQTTSNGWClient.h" #include <MQTTSNGWAdapterManager.h>
#include "MQTTSNGWForwarder.h"
#include "MQTTSNGWProcess.h" #include "MQTTSNGWProcess.h"
#include "MQTTSNPacket.h" #include "MQTTSNPacket.h"
#include "MQTTSNGWClient.h"
namespace MQTTSNGW namespace MQTTSNGW
{ {
@@ -74,6 +74,8 @@ namespace MQTTSNGW
/*===================================== /*=====================================
Class Event Class Event
====================================*/ ====================================*/
class Client;
enum EventType{ enum EventType{
Et_NA = 0, Et_NA = 0,
EtStop, EtStop,
@@ -106,13 +108,14 @@ public:
MQTTGWPacket* getMQTTGWPacket(void); MQTTGWPacket* getMQTTGWPacket(void);
private: private:
EventType _eventType; EventType _eventType {Et_NA};
Client* _client; Client* _client {nullptr};
SensorNetAddress* _sensorNetAddr; SensorNetAddress* _sensorNetAddr {nullptr};
MQTTSNPacket* _mqttSNPacket; MQTTSNPacket* _mqttSNPacket {nullptr};
MQTTGWPacket* _mqttGWPacket; MQTTGWPacket* _mqttGWPacket {nullptr};
}; };
/*===================================== /*=====================================
Class EventQue Class EventQue
====================================*/ ====================================*/
@@ -133,37 +136,47 @@ private:
Semaphore _sem; Semaphore _sem;
}; };
/*
* GatewayParams
*/ /*=====================================
typedef struct Class GatewayParams
====================================*/
class GatewayParams
{ {
char* configName; public:
char* clientListName; string configDir;
char* loginId; char* configName {nullptr};
char* password; char* clientListName {nullptr};
uint16_t keepAlive; char* loginId {nullptr};
uint8_t gatewayId; char* password {nullptr};
uint8_t mqttVersion; uint16_t keepAlive {0};
uint16_t maxInflightMsgs; uint8_t gatewayId {0};
char* gatewayName; uint8_t mqttVersion {0};
char* brokerName; uint16_t maxInflightMsgs {0};
char* port; char* gatewayName {nullptr};
char* portSecure; char* brokerName {nullptr};
char* rootCApath; char* port {nullptr};
char* rootCAfile; char* portSecure {nullptr};
char* certKey; char* rootCApath {nullptr};
char* privateKey; char* rootCAfile {nullptr};
char* predefinedTopicFileName; char* certKey {nullptr};
char* forwarderListName; char* privateKey {nullptr};
}GatewayParams; char* predefinedTopicFileName {nullptr};
char* qosMinusClientListName {nullptr};
bool clientAuthentication {false};
};
/*===================================== /*=====================================
Class Gateway Class Gateway
=====================================*/ =====================================*/
class AdapterManager;
class ClientList;
class Gateway: public MultiTaskProcess{ class Gateway: public MultiTaskProcess{
public: public:
Gateway(); Gateway(void);
~Gateway(); ~Gateway();
virtual void initialize(int argc, char** argv); virtual void initialize(int argc, char** argv);
void run(void); void run(void);
@@ -172,20 +185,22 @@ public:
EventQue* getClientSendQue(void); EventQue* getClientSendQue(void);
EventQue* getBrokerSendQue(void); EventQue* getBrokerSendQue(void);
ClientList* getClientList(void); ClientList* getClientList(void);
ForwarderList* getForwarderList(void);
SensorNetwork* getSensorNetwork(void); SensorNetwork* getSensorNetwork(void);
LightIndicator* getLightIndicator(void); LightIndicator* getLightIndicator(void);
GatewayParams* getGWParams(void); GatewayParams* getGWParams(void);
AdapterManager* getAdapterManager(void);
int getParam(const char* parameter, char* value);
bool hasSecureConnection(void);
private: private:
ClientList _clientList; GatewayParams _params;
ForwarderList _forwarderList; ClientList* _clientList {nullptr};
EventQue _packetEventQue; EventQue _packetEventQue;
EventQue _brokerSendQue; EventQue _brokerSendQue;
EventQue _clientSendQue; EventQue _clientSendQue;
LightIndicator _lightIndicator; LightIndicator _lightIndicator;
GatewayParams _params;
SensorNetwork _sensorNetwork; SensorNetwork _sensorNetwork;
AdapterManager* _adapterManager {nullptr};
}; };
} }

View File

@@ -30,6 +30,20 @@
using namespace std; using namespace std;
using namespace MQTTSNGW; 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 Class Mutex
=====================================*/ =====================================*/

View File

@@ -23,19 +23,18 @@
using namespace MQTTSNGW; using namespace MQTTSNGW;
/* /*
* Gateway Process * Gateway Application
*/ */
Gateway* gw = new Gateway(); Gateway gateway;
PacketHandleTask task1(gw); PacketHandleTask task1(&gateway);
ClientRecvTask task2(gw); ClientRecvTask task2(&gateway);
ClientSendTask task3(gw); ClientSendTask task3(&gateway);
BrokerRecvTask task4(gw); BrokerRecvTask task4(&gateway);
BrokerSendTask task5(gw); BrokerSendTask task5(&gateway);
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
gw->initialize(argc, argv); gateway.initialize(argc, argv);
gw->run(); gateway.run();
delete gw;
return 0; return 0;
} }

View File

@@ -34,7 +34,7 @@ TestTopicIdMap::~TestTopicIdMap()
bool TestTopicIdMap::testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicTypes type) 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 ) if ( elm )
{ {
//printf("msgid=%d id=%d type=%d\n", msgid, elm->getTopicId(), elm->getTopicType()); //printf("msgid=%d id=%d type=%d\n", msgid, elm->getTopicId(), elm->getTopicType());