Update: Add Aggregate Gateway functions. #127

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
This commit is contained in:
tomoaki
2018-08-04 17:46:42 +09:00
parent 862e501512
commit f7fc5c49f5
65 changed files with 4368 additions and 1982 deletions

View File

@@ -66,7 +66,7 @@
</toolChain> </toolChain>
</folderInfo> </folderInfo>
<sourceEntries> <sourceEntries>
<entry excluding="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=""/> <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>
@@ -137,7 +137,7 @@
</folderInfo> </folderInfo>
<sourceEntries> <sourceEntries>
<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="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="mainLogmonitor.cpp|tests|tests/mainTestProcessFramework.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

@@ -11,7 +11,6 @@ CONFIG := gateway.conf
CLIENTS := clients.conf CLIENTS := clients.conf
PREDEFTOPIC := predefinedTopic.conf PREDEFTOPIC := predefinedTopic.conf
FORWARDERS := forwarders.conf FORWARDERS := forwarders.conf
QOSM1CLIENT := qos-1clients.conf
SRCDIR := src SRCDIR := src
SUBDIR := ../MQTTSNPacket/src SUBDIR := ../MQTTSNPacket/src
@@ -40,7 +39,15 @@ $(SRCDIR)/MQTTSNGWPublishHandler.cpp \
$(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \ $(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \
$(SRCDIR)/MQTTSNGWEncapsulatedPacket.cpp \ $(SRCDIR)/MQTTSNGWEncapsulatedPacket.cpp \
$(SRCDIR)/MQTTSNGWForwarder.cpp \ $(SRCDIR)/MQTTSNGWForwarder.cpp \
$(SRCDIR)/MQTTSNGWQoS-1Proxy.cpp \ $(SRCDIR)/MQTTSNGWQoSm1Proxy.cpp \
$(SRCDIR)/MQTTSNGWAdapter.cpp \
$(SRCDIR)/MQTTSNGWAggregater.cpp \
$(SRCDIR)/MQTTSNGWClientList.cpp \
$(SRCDIR)/MQTTSNGWTopic.cpp \
$(SRCDIR)/MQTTSNGWAdapterManager.cpp \
$(SRCDIR)/MQTTSNAggregateConnectionHandler.cpp \
$(SRCDIR)/MQTTSNGWMessageIdTable.cpp \
$(SRCDIR)/MQTTSNGWAggregateTopicTable.cpp \
$(SRCDIR)/$(OS)/$(SENSORNET)/SensorNetwork.cpp \ $(SRCDIR)/$(OS)/$(SENSORNET)/SensorNetwork.cpp \
$(SRCDIR)/$(OS)/Timer.cpp \ $(SRCDIR)/$(OS)/Timer.cpp \
$(SRCDIR)/$(OS)/Network.cpp \ $(SRCDIR)/$(OS)/Network.cpp \
@@ -143,7 +150,6 @@ install:
cp -pf $(CLIENTS) ../../ cp -pf $(CLIENTS) ../../
cp -pf $(PREDEFTOPIC) ../../ cp -pf $(PREDEFTOPIC) ../../
cp -pf $(FORWARDERS) ../../ cp -pf $(FORWARDERS) ../../
cp -pf $(QOSM1CLIENT) ../../
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,58 +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
#
AggregateGateway=NO
ClientAuthentication=NO ClientAuthentication=NO
#ClientsList=/path/to/your_clients.conf
PredefinedTopic=NO #ClientsList=/path/to/your_clients.conf
QoS-1=NO
OoS-1ProxyName=Proxy007
#PredefinedTopicList=/path/to/your_predefinedTopic.conf #PredefinedTopicList=/path/to/your_predefinedTopic.conf
Forwarder=NO Forwarder=NO
#ForwardersList=/home/tomoaki/tmp/forwarders.conf #ForwardersList=/path/to/your_forwarers.conf
#RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/
#CertsFile=/path/to/certKey.pem
#PrivateKey=/path/to/privateKey.pem
GatewayID=1
GatewayName=PahoGateway-01
KeepAlive=900
#LoginID=your_ID
#Password=your_Password
QoS-1=NO
QoS-1ProxyName=Proxy007
#QoS-1ClientsList=/path/to/your_qos-1clients.conf
#RootCAfile=/path/to/your_Root_CA.crt
#RootCApath=/path/to/your_certs_directory/
#CertKey=/path/to/your_cert.pem
#PrivateKey=/path/to/your_private-key.pem
GatewayID=1
GatewayName=PahoGateway-01
KeepAlive=900
#LoginID=your_ID
#Password=your_Password
# UDP # 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 **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 **QoS-1** is YES, QoS-1 PUBLISH Message is available. Clients which allow to send it, are specifed by QoS-1ClientsList file. In this file, ClientsId and those sensorNet addresses are declared in CSV format. QoS-1ProxyName is a ClientId of the proxy. When **Forwarder** is **YE**S, Forwarder Encapsulation Message is available. Connectable Forwarders are specifed by **ForwardersList** file. In this file, ForwarderIds and those sensorNet addresses are declared in CSV format.

View File

@@ -11,8 +11,29 @@
# 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 send PUBLISH QoS-1, QoS-1 is required.
#
# Ex:
# #Client List
# ClientId1,11200@192.168.10.10
# ClientID2,35000@192.168.50.200,unstableLine
# ClientID3,40000@192.168.200.50,secureConnection
# ClientID4,41000@192.168.200.51,unstableLine,secureConnection
# ClientID5,41000@192.168.200.51,unstableLine,secureConnection,QoS-1
#
# SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function. # SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function.
# #
Client02,172.16.1.7:12002
Client03,172.16.1.8:13003 Client02,172.16.1.11:12002
Client01,172.16.1.6:12001 Client03,172.16.1.11:13003
Client01,172.16.1.11:12001
QoS-1_Client01,172.16.1.11:20001,QoS-1
QoS-1_Client02,172.16.1.11:20002,QoS-1
QoS-1_Client03,172.16.1.11:20003,QoS-1

View File

@@ -10,26 +10,33 @@
# 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
#
AggregateGateway=NO
ClientAuthentication=NO ClientAuthentication=NO
#ClientsList=/path/to/your_clients.conf #ClientsList=/path/to/your_clients.conf
QoS-1=NO
OoS-1ProxyName=Proxy007
PredefinedTopic=NO PredefinedTopic=NO
#PredefinedTopicList=/path/to/your_predefinedTopic.conf #PredefinedTopicList=/path/to/your_predefinedTopic.conf
Forwarder=NO Forwarder=NO
#ForwardersList=/path/to/your_forwarers.conf #ForwardersList=/path/to/your_forwarers.conf
QoS-1=NO
OoS-1ProxyName=Proxy007
#QoS-1ClientsList=/path/to/your_qos-1clients.conf
#RootCAfile=/etc/ssl/certs/ca-certificates.crt #RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/ #RootCApath=/etc/ssl/certs/
#CertsFile=/path/to/certKey.pem #CertsFile=/path/to/certKey.pem

View File

@@ -20,28 +20,27 @@
# One for QoS-1 PUBLISH Clients, the other for another clients. # One for QoS-1 PUBLISH Clients, the other for another clients.
# #
# pre-defined-topics for QoS-1 clients. # pre-defined-topics for Clients
# ClientIDs should be "ClientProxy"
#
ClientProxy, ty4tw/proxy/predefTopic1, 1
ClientProxy, ty4tw/proxy/predefTopic2, 2
ClientProxy, ty4tw/proxy/predefTopic3, 3
#
# pre-defined-topics for another clients
# #
GatewayTestClient,ty4tw/predefinedTopic1, 1 GatewayTestClient,ty4tw/predefinedTopic1, 1
GatewayTestClient,ty4tw/predefinedTopic2, 2 GatewayTestClient,ty4tw/predefinedTopic2, 2
GatewayTestClient,ty4tw/predefinedTopic3, 3 GatewayTestClient,ty4tw/predefinedTopic3, 3
ClientPUB,ty4tw/predefinedTopic1, 1 #
ClientPUB,ty4tw/predefinedTopic2, 2 # pre-defined-topics for QoS-1 clients.
ClientPUB,ty4tw/predefinedTopic3, 3 #
QoS-1_Client01,ty4tw/proxy/predefTopic1, 1
QoS-1_Client01,ty4tw/proxy/predefTopic2, 2
QoS-1_Client01,ty4tw/proxy/predefTopic3, 3
QoS-1_Client02,ty4tw/proxy/predefTopic1, 1
QoS-1_Client02,ty4tw/proxy/predefTopic3, 2
QoS-1_Client02,ty4tw/proxy/predefTopic3, 3
QoS-1_Client03,ty4tw/proxy/predefTopic1, 1
QoS-1_Client03,ty4tw/proxy/predefTopic2, 2
QoS-1_Client03,ty4tw/proxy/predefTopic3, 3
ClientSUB,ty4tw/predefinedTopic1, 1
ClientSUB,ty4tw/predefinedTopic2, 2
ClientSUB,ty4tw/predefinedTopic3, 3

View File

@@ -1,30 +0,0 @@
#***********************************************************************
# Copyright (c) 2018, Tomoaki Yamaguchi
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v1.0 which accompany this distribution.
#
# The Eclipse Public License is available at
# http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#***********************************************************************
#
# Clients which send QoS-1 PUBLISH are defined by this file.
#
# Clients are defined by the ClientId and those SensorNetAddress
# in a CSV format as follow:
#
# ClientId, SensorNetAddress
#
# where SensorNetwork address format is defined by
# SensorNetAddress::setAddress(string* data) function.
#
#
QoS-1_Client01,172.16.1.11:20001
QoS-1_Clien02t,172.16.1.11:20002
QoS-1_Client03,172.16.1.11:20003
QoS-1_Client04,172.16.1.11:20004
QoS-1_Client05,172.16.1.11:20005

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;
int len = 0;
switch ( type )
{
case PUBLISH:
Publish pub;
pub.msgId = 0;
getPUBLISH(&pub);
pub.msgId = msgId;
ptr = _data + pub.topiclen;
writeInt(&ptr, pub.msgId);
*ptr++ = (unsigned char)(msgId / 256);
*ptr = (unsigned char)(msgId % 256);
break;
case SUBSCRIBE:
case UNSUBSCRIBE:
case PUBACK:
case PUBREC:
case PUBREL:
case PUBCOMP:
case SUBACK:
case UNSUBACK:
ptr = _data;
*ptr++ = (unsigned char)(msgId / 256);
*ptr = (unsigned char)(msgId % 256);
break;
default:
break;
}
}
char* MQTTGWPacket::print(char* pbuf) 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)
@@ -181,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();
@@ -234,3 +234,89 @@ void MQTTGWPublishHandler::handleAck(Client* client, MQTTGWPacket* packet, int t
} }
} }
void MQTTGWPublishHandler::handleAggregatePuback(Client* client, MQTTGWPacket* packet)
{
uint16_t msgId = packet->getMsgId();
uint16_t clientMsgId = 0;
Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId);
if ( newClient != nullptr )
{
packet->setMsgId((int)clientMsgId);
handlePuback(newClient, packet);
}
}
void MQTTGWPublishHandler::handleAggregateAck(Client* client, MQTTGWPacket* packet, int type)
{
uint16_t msgId = packet->getMsgId();
uint16_t clientMsgId = 0;
Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId);
if ( newClient != nullptr )
{
packet->setMsgId((int)clientMsgId);
handleAck(newClient, packet,type);
}
}
void MQTTGWPublishHandler::handleAggregatePubrel(Client* client, MQTTGWPacket* packet)
{
Publish pub;
packet->getPUBLISH(&pub);
replyACK(client, &pub, PUBCOMP);
}
void MQTTGWPublishHandler::handleAggregatePublish(Client* client, MQTTGWPacket* packet)
{
Publish pub;
packet->getPUBLISH(&pub);
WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(),
RIGHTARROW, client->getClientId(), "is sleeping. a message was saved.");
if (pub.header.bits.qos == 1)
{
replyACK(client, &pub, PUBACK);
}
else if ( pub.header.bits.qos == 2)
{
replyACK(client, &pub, PUBREC);
}
MQTTGWPacket* msg = new MQTTGWPacket();
*msg = *packet;
if ( msg->getType() == 0 )
{
WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER);
delete msg;
return;
}
string* topicName = new string(pub.topic);
Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL);
AggregateTopicElement* list = _gateway->getAdapterManager()->createClientList(&topic);
if ( list != nullptr )
{
ClientTopicElement* p = list->getFirstElement();
while ( p )
{
Client* devClient = p->getClient();
if ( devClient != nullptr )
{
Event* ev = new Event();
ev->setBrokerRecvEvent(devClient, packet);
_gateway->getPacketEventQue()->post(ev);
}
else
{
break;
}
p = list->getNextElement(p);
}
delete list;
}
}

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,253 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWDefines.h"
#include "MQTTSNGateway.h"
#include "SensorNetwork.h"
#include "MQTTSNGWProcess.h"
#include "MQTTSNGWVersion.h"
#include "MQTTSNGWClientRecvTask.h"
#include "MQTTSNGWClientSendTask.h"
#include "MQTTSNGWClient.h"
#include "MQTTSNGWAggregater.h"
#include "MQTTSNGWQoSm1Proxy.h"
#include <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(MQTTSNPacket* packet, ClientRecvTask* task)
{
char buf[128];
WirelessNodeId nodeId;
SensorNetAddress* senderAddr = _gateway->getSensorNetwork()->getSenderAddress();
Client* client = nullptr;
if ( packet->getType() == MQTTSN_ENCAPSULATED )
{
Forwarder* fwd = getForwarderList()->getForwarder(senderAddr);
if ( fwd == nullptr )
{
task->log(0, packet, 0);
WRITELOG("%s Forwarder %s is not authenticated.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER);
delete packet;
return client;
}
else
{
MQTTSNString fwdName = MQTTSNString_initializer;
fwdName.cstring = const_cast<char *>( fwd->getName() );
task->log(0, packet, &fwdName);
/* get the packet from the encapsulation message */
MQTTSNGWEncapsulatedPacket encap;
encap.desirialize(packet->getPacketData(), packet->getPacketLength());
nodeId.setId( encap.getWirelessNodeId() );
client = fwd->getClient(&nodeId);
delete packet;
packet = encap.getMQTTSNPacket();
}
}
else
{
/* Check the client belonging to QoS-1Proxy ? */
if ( _qosm1Proxy->isActive() )
{
/* get ClientId not Client which can send QoS-1 PUBLISH */
const char* clientName = _qosm1Proxy->getClientId(senderAddr);
if ( clientName )
{
if ( !packet->isQoSMinusPUBLISH() )
{
client = _qosm1Proxy->getClient();
task->log(clientName, packet);
WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, senderAddr->sprint(buf), ERRMSG_FOOTER);
delete packet;
return client;
}
}
}
}
if ( client == nullptr )
{
/* get client from the ClientList of Gateway by sensorNetAddress. */
client = _gateway->getClientList()->getClient(senderAddr);
}
return client;
}
Client* AdapterManager::getClient(Client& client)
{
bool secure = client.isSecureNetwork();
Client* newClient = &client;
if ( client.isQoSm1() )
{
newClient = _qosm1Proxy->getAdapterClient(&client);
_qosm1Proxy->resetPingTimer(secure);
}
else if ( client.isAggregated() )
{
newClient = _aggregater->getAdapterClient(&client);
_aggregater->resetPingTimer(secure);
}
return newClient;
}
int AdapterManager::unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task)
{
char pbuf[SIZE_OF_LOG_PACKET * 3];
Forwarder* fwd = client->getForwarder();
int rc = 0;
if ( fwd )
{
MQTTSNGWEncapsulatedPacket encap(packet);
WirelessNodeId* wnId = fwd->getWirelessNodeId(client);
encap.setWirelessNodeId(wnId);
WRITELOG(FORMAT_Y_W_G, currentDateTime(), encap.getName(), RIGHTARROW, fwd->getId(), encap.print(pbuf));
task->log(client, packet);
rc = encap.unicast(_gateway->getSensorNetwork(),fwd->getSensorNetAddr());
}
else
{
task->log(client, packet);
if ( client->isQoSm1Proxy() )
{
_qosm1Proxy->send(packet, client);
}
else if ( client->isAggregater() )
{
_aggregater->send(packet, client);
}
else
{
rc = packet->unicast(_gateway->getSensorNetwork(), client->getSensorNetAddress());
}
}
return rc;
}
void AdapterManager::checkConnection(void)
{
if ( _aggregater->isActive())
{
_aggregater->checkConnection();
}
else if ( _qosm1Proxy->isActive())
{
_qosm1Proxy->checkConnection();
}
}
Client* AdapterManager::convertClient(uint16_t msgId, uint16_t* clientMsgId)
{
return _aggregater->convertClient(msgId, clientMsgId);
}
bool AdapterManager::isAggregaterActive(void)
{
return _aggregater->isActive();
}
AggregateTopicElement* AdapterManager::createClientList(Topic* topic)
{
return _aggregater->createClientList(topic);
}
int AdapterManager::addAggregateTopic(Topic* topic, Client* client)
{
return _aggregater->addAggregateTopic(topic, client);
}
void AdapterManager::removeAggregateTopic(Topic* topic, Client* client)
{
_aggregater->removeAggregateTopic(topic, client);
}
void AdapterManager::removeAggregateTopicList(Topics* topics, Client* client)
{
_aggregater->removeAggregateTopicList(topics, client);
}

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 MQTTSNPacket;
class MQTTSNGWPacket;
class ClientRecvTask;
class ClientSendTask;
/*=====================================
Class AdapterManager
=====================================*/
class AdapterManager
{
public:
AdapterManager(Gateway* gw);
~AdapterManager(void);
void initialize(void);
ForwarderList* getForwarderList(void);
QoSm1Proxy* getQoSm1Proxy(void);
Aggregater* getAggregater(void);
void checkConnection(void);
bool isAggregatedClient(Client* client);
Client* getClient(MQTTSNPacket* packet, ClientRecvTask* task);
Client* getClient(Client& client);
Client* convertClient(uint16_t msgId, uint16_t* clientMsgId);
int unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task);
bool isAggregaterActive(void);
AggregateTopicElement* createClientList(Topic* topic);
int addAggregateTopic(Topic* topic, Client* client);
void removeAggregateTopic(Topic* topic, Client* client);
void removeAggregateTopicList(Topics* topics, Client* client);
private:
Gateway* _gateway {nullptr};
ForwarderList* _forwarders {nullptr};
QoSm1Proxy* _qosm1Proxy {nullptr};
Aggregater* _aggregater {nullptr};
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_ */

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,143 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWAggregater.h"
#include "MQTTSNGateway.h"
#include "MQTTSNGWClient.h"
#include "MQTTSNGWAdapter.h"
#include "MQTTSNGWAdapterManager.h"
#include "MQTTSNGWMessageIdTable.h"
#include "MQTTSNGWTopic.h"
#include <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(_gateway, AGGREGATER_TYPE);
setup((const char*)(_gateway->getGWParams()->gatewayName), Atype_Aggregater);
_isActive = true;
}
}
//testMessageIdTable();
}
bool Aggregater::isActive(void)
{
return _isActive;
}
uint16_t Aggregater::msgId(void)
{
return Adapter::getSecureClient()->getNextPacketId();
}
Client* Aggregater::convertClient(uint16_t msgId, uint16_t* clientMsgId)
{
return _msgIdTable.getClientMsgId(msgId, clientMsgId);
}
uint16_t Aggregater::addMessageIdTable(Client* client, uint16_t msgId)
{
/* set Non secure client`s nextMsgId. otherwise Id is duplicated.*/
MessageIdElement* elm = _msgIdTable.add(this, client, msgId);
if ( elm == nullptr )
{
return 0;
}
else
{
return elm->_msgId;
}
}
uint16_t Aggregater::getMsgId(Client* client, uint16_t clientMsgId)
{
return _msgIdTable.getMsgId(client, clientMsgId);
}
void Aggregater::removeAggregateTopic(Topic* topic, Client* client)
{
// ToDo: AggregateGW this method called when the client disconnect and erase it`s Topics. this method call */
}
void Aggregater::removeAggregateTopicList(Topics* topics, Client* client)
{
// ToDo: AggregateGW this method called when the client disconnect and erase it`s Topics. this method call */
}
int Aggregater::addAggregateTopic(Topic* topic, Client* client)
{
// ToDo: AggregateGW */
return 0;
}
AggregateTopicElement* Aggregater::createClientList(Topic* topic)
{
// ToDo: AggregateGW */
return 0;
}
bool Aggregater::testMessageIdTable(void)
{
Client* client = new Client();
uint16_t msgId = 0;
printf("msgId=%d\n", addMessageIdTable(client,1));
printf("msgId=%d\n", addMessageIdTable(client,2));
printf("msgId=%d\n", addMessageIdTable(client,3));
printf("msgId=%d\n", addMessageIdTable(client,1));
printf("msgId=%d\n", addMessageIdTable(client,2));
printf("msgId=%d\n", addMessageIdTable(client,3));
printf("msgId=%d\n", addMessageIdTable(client,4));
printf("msgId=%d\n", addMessageIdTable(client,4));
printf("msgId=%d\n", addMessageIdTable(client,4));
convertClient(1,&msgId);
printf("msgId=%d\n",msgId);
convertClient(2,&msgId);
printf("msgId=%d\n",msgId);
convertClient(5,&msgId);
printf("msgId=%d\n",msgId);
convertClient(4,&msgId);
printf("msgId=%d\n",msgId);
convertClient(3,&msgId);
printf("msgId=%d\n",msgId);
return true;
}

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,8 +177,8 @@ 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);
@@ -292,8 +220,15 @@ public:
Forwarder* getForwarder(void); Forwarder* getForwarder(void);
void setForwarder(Forwarder* forwader); void setForwarder(Forwarder* forwader);
void setPorxy(bool isProxy); void setAdapterType(AdapterType type);
bool isProxy(void); 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);
@@ -355,8 +290,7 @@ private:
SensorNetAddress _sensorNetAddr; SensorNetAddress _sensorNetAddr;
Forwarder* _forwarder; Forwarder* _forwarder;
bool _isProxy; ClientType _clientType;
bool _sessionStatus; bool _sessionStatus;
bool _hasPredefTopic; bool _hasPredefTopic;
@@ -365,32 +299,6 @@ private:
Client* _prevClient; Client* _prevClient;
}; };
/*=====================================
Class ClientList
=====================================*/
class ClientList
{
public:
ClientList();
~ClientList();
bool authorize(const char* fileName);
bool setPredefinedTopics(const char* fileName);
void erase(Client*&);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure);
Client* getClient(SensorNetAddress* addr);
Client* getClient(MQTTSNString* clientId);
uint16_t getClientCount(void);
Client* getClient(void);
bool isAuthorized();
private:
Client* createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t toipcId);
Client* _firstClient;
Client* _endClient;
Mutex _mutex;
uint16_t _clientCnt;
bool _authorize;
};
} }

View File

@@ -0,0 +1,460 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
* Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/
#include "MQTTSNGWClientList.h"
#include <string.h>
#include <string>
/*=====================================
Class ClientList
=====================================*/
ClientList::ClientList()
{
_clientCnt = 0;
_authorize = false;
_firstClient = nullptr;
_endClient = nullptr;
}
ClientList::~ClientList()
{
_mutex.lock();
Client* cl = _firstClient;
Client* ncl;
while (cl != nullptr)
{
ncl = cl->_nextClient;
delete cl;
cl = ncl;
};
_mutex.unlock();
}
void ClientList::initialize(Gateway* gw, bool aggregate)
{
if (gw->getGWParams()->clientAuthentication )
{
int type = TRANSPEARENT_TYPE;
if ( aggregate )
{
type = AGGREGATER_TYPE;
}
setClientList(gw, type);
_authorize = true;
}
}
void ClientList::setClientList(Gateway* gw, int type)
{
char param[MQTTSNGW_PARAM_MAX];
string fileName;
GatewayParams* params = gw->getGWParams();
if (gw->getParam("ClientsList", param) == 0)
{
fileName = string(param);
}
else
{
fileName = params->configDir + string(CLIENT_LIST);
}
if (!createList(fileName.c_str(), type))
{
throw Exception("ClientList::initialize(): No client list defined by the configuration.");
}
params->clientListName = strdup(fileName.c_str());
}
void ClientList::setPredefinedTopics(Gateway* gw, bool aggrecate)
{
char param[MQTTSNGW_PARAM_MAX];
string fileName;
GatewayParams* params = gw->getGWParams();
if (gw->getParam("PredefinedTopicList", param) == 0)
{
fileName = string(param);
}
else
{
fileName = params->configDir + string(PREDEFINEDTOPIC_FILE);
}
if ( readPredefinedList(fileName.c_str(), aggrecate) )
{
params->predefinedTopicFileName = strdup(fileName.c_str());
}
}
/**
* Create ClientList from a client list file.
* @param File name of the client list
* @return true: Reject client connection that is not registered in the client list
*
* File format is:
* Lines bigning with # are comment line.
* ClientId, SensorNetAddress, "unstableLine", "secureConnection"
* in case of UDP, SensorNetAddress format is portNo@IPAddress.
* if the SensorNetwork is not stable, write unstableLine.
* if BrokerConnection is SSL, write secureConnection.
* if the client send PUBLISH QoS-1, QoS-1 is required.
*
* Ex:
* #Client List
* ClientId1,11200@192.168.10.10
* ClientID2,35000@192.168.50.200,unstableLine
* ClientID3,40000@192.168.200.50,secureConnection
* ClientID4,41000@192.168.200.51,unstableLine,secureConnection
* ClientID5,41000@192.168.200.51,unstableLine,secureConnection,QoS-1
*/
bool ClientList::createList(const char* fileName, int type)
{
FILE* fp;
char buf[MAX_CLIENTID_LENGTH + 256];
size_t pos;
bool secure;
bool stable;
bool qos_1;
bool rc = true;
SensorNetAddress netAddr;
MQTTSNString clientId = MQTTSNString_initializer;
if ((fp = fopen(fileName, "r")) != 0)
{
while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0)
{
if (*buf == '#')
{
continue;
}
string data = string(buf);
while ((pos = data.find_first_of("  \t\n")) != string::npos)
{
data.erase(pos, 1);
}
if (data.empty())
{
continue;
}
pos = data.find_first_of(",");
string id = data.substr(0, pos);
clientId.cstring = strdup(id.c_str());
string addr = data.substr(pos + 1);
if (netAddr.setAddress(&addr) == 0)
{
qos_1 = (data.find("QoS-1") != string::npos);
secure = (data.find("secureConnection") != string::npos);
stable = !(data.find("unstableLine") != string::npos);
if ( (qos_1 && type == QOSM1PROXY_TYPE) || (!qos_1 && type == AGGREGATER_TYPE) )
{
createClient(&netAddr, &clientId, stable, secure, type);
}
else
{
createClient(&netAddr, &clientId, stable, secure, TRANSPEARENT_TYPE);
}
}
else
{
WRITELOG("Invalid address %s\n", data.c_str());
rc = false;
}
free(clientId.cstring);
}
fclose(fp);
}
return rc;
}
bool ClientList::readPredefinedList(const char* fileName, bool aggregate)
{
FILE* fp;
char buf[MAX_CLIENTID_LENGTH + 256];
size_t pos0, pos1;
MQTTSNString clientId = MQTTSNString_initializer;;
bool rc = false;
if ((fp = fopen(fileName, "r")) != 0)
{
while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0)
{
if (*buf == '#')
{
continue;
}
string data = string(buf);
while ((pos0 = data.find_first_of("  \t\n")) != string::npos)
{
data.erase(pos0, 1);
}
if (data.empty())
{
continue;
}
pos0 = data.find_first_of(",");
pos1 = data.find(",", pos0 + 1) ;
string id = data.substr(0, pos0);
clientId.cstring = strdup(id.c_str());
string topicName = data.substr(pos0 + 1, pos1 - pos0 -1);
uint16_t topicID = stoul(data.substr(pos1 + 1));
createPredefinedTopic( &clientId, topicName, topicID, aggregate);
free(clientId.cstring);
}
fclose(fp);
rc = true;
}
else
{
WRITELOG("ClientList can not open the Predefined Topic List. %s\n", fileName);
return false;
}
return rc;
}
void ClientList::erase(Client*& client)
{
if ( !_authorize && client->erasable())
{
_mutex.lock();
Client* prev = client->_prevClient;
Client* next = client->_nextClient;
if (prev)
{
prev->_nextClient = next;
}
else
{
_firstClient = next;
}
if (next)
{
next->_prevClient = prev;
}
else
{
_endClient = prev;
}
_clientCnt--;
Forwarder* fwd = client->getForwarder();
if ( fwd )
{
fwd->eraseClient(client);
}
delete client;
client = nullptr;
_mutex.unlock();
}
}
Client* ClientList::getClient(SensorNetAddress* addr)
{
if ( addr )
{
_mutex.lock();
Client* client = _firstClient;
while (client != nullptr)
{
if (client->getSensorNetAddress()->isMatch(addr) )
{
_mutex.unlock();
return client;
}
client = client->_nextClient;
}
_mutex.unlock();
}
return 0;
}
Client* ClientList::getClient(int index)
{
Client* client = _firstClient;
int p = 0;
while ( client != nullptr )
{
if ( p == index )
{
return client;
}
else
{
client = client->_nextClient;
p++;
}
}
return nullptr;
}
Client* ClientList::getClient(MQTTSNString* clientId)
{
_mutex.lock();
Client* client = _firstClient;
const char* clID =clientId->cstring;
if (clID == nullptr )
{
clID = clientId->lenstring.data;
}
while (client != nullptr)
{
if (strncmp((const char*)client->getClientId(), clID, MQTTSNstrlen(*clientId)) == 0 )
{
_mutex.unlock();
return client;
}
client = client->_nextClient;
}
_mutex.unlock();
return 0;
}
Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, int type)
{
return createClient(addr, clientId, false, false, type);
}
Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type)
{
Client* client = nullptr;
/* anonimous clients */
if ( _clientCnt > MAX_CLIENTS )
{
return 0; // full of clients
}
client = getClient(addr);
if ( client )
{
return client;
}
/* creat a new client */
client = new Client(secure);
if ( addr )
{
client->setClientAddress(addr);
}
client->setSensorNetType(unstableLine);
if ( MQTTSNstrlen(*clientId) )
{
client->setClientId(*clientId);
}
else
{
MQTTSNString dummyId MQTTSNString_initializer;;
dummyId.cstring = strdup("");
client->setClientId(dummyId);
free(dummyId.cstring);
}
if ( type == AGGREGATER_TYPE )
{
client->setAggregated();
}
else if ( type == QOSM1PROXY_TYPE )
{
client->setQoSm1();
}
_mutex.lock();
/* add the list */
if ( _firstClient == nullptr )
{
_firstClient = client;
_endClient = client;
}
else
{
_endClient->_nextClient = client;
client->_prevClient = _endClient;
_endClient = client;
}
_clientCnt++;
_mutex.unlock();
return client;
}
Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t topicId, bool aggregate)
{
Client* client = getClient(clientId);
if ( _authorize && client == nullptr)
{
return 0;
}
/* anonimous clients */
if ( _clientCnt > MAX_CLIENTS )
{
return nullptr; // full of clients
}
if ( client == nullptr )
{
/* creat a new client */
client = new Client();
client->setClientId(*clientId);
if ( aggregate )
{
client->setAggregated();
}
_mutex.lock();
/* add the list */
if ( _firstClient == nullptr )
{
_firstClient = client;
_endClient = client;
}
else
{
_endClient->_nextClient = client;
client->_prevClient = _endClient;
_endClient = client;
}
_clientCnt++;
_mutex.unlock();
}
// create Topic & Add it
client->getTopics()->add((const char*)topicName.c_str(), topicId);
client->_hasPredefTopic = true;
return client;
}
uint16_t ClientList::getClientCount()
{
return _clientCnt;
}
bool ClientList::isAuthorized()
{
return _authorize;
}

View File

@@ -0,0 +1,70 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
* Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_
#include "MQTTSNGWClient.h"
#include "MQTTSNGateway.h"
namespace MQTTSNGW
{
#define TRANSPEARENT_TYPE 0
#define QOSM1PROXY_TYPE 1
#define AGGREGATER_TYPE 2
class Client;
/*=====================================
Class ClientList
=====================================*/
class ClientList
{
public:
ClientList();
~ClientList();
void initialize(Gateway* gw, bool aggregate);
void setClientList(Gateway* gw, int type);
void setPredefinedTopics(Gateway* gw, bool aggregate);
void erase(Client*&);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId,int type);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type);
bool createList(const char* fileName, int type);
Client* getClient(SensorNetAddress* addr);
Client* getClient(MQTTSNString* clientId);
Client* getClient(int index);
uint16_t getClientCount(void);
Client* getClient(void);
bool isAuthorized();
private:
bool readPredefinedList(const char* fileName, bool _aggregate);
Client* createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t toipcId, bool _aggregate);
Client* _firstClient;
Client* _endClient;
Mutex _mutex;
uint16_t _clientCnt;
bool _authorize {false};
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_ */

View File

@@ -15,12 +15,12 @@
**************************************************************************************/ **************************************************************************************/
#include "MQTTSNGWClientRecvTask.h" #include "MQTTSNGWClientRecvTask.h"
#include "MQTTSNGateway.h"
#include "MQTTSNPacket.h" #include "MQTTSNPacket.h"
#include "MQTTSNGWQoSm1Proxy.h"
#include "MQTTSNGWEncapsulatedPacket.h" #include "MQTTSNGWEncapsulatedPacket.h"
#include <cstring> #include <cstring>
#include "MQTTSNGWForwarder.h" //#include "MQTTSNGWForwarder.h"
using namespace MQTTSNGW; using namespace MQTTSNGW;
char* currentDateTime(void); char* currentDateTime(void);
@@ -57,14 +57,18 @@ void ClientRecvTask::initialize(int argc, char** argv)
*/ */
void ClientRecvTask::run() void ClientRecvTask::run()
{ {
Event* ev = 0; Event* ev = nullptr;
Client* client = 0; Client* client = nullptr;
char buf[128]; AdapterManager* adpMgr = _gateway->getAdapterManager();
bool isAggrActive = adpMgr->isAggregaterActive();
ClientList* clientList = _gateway->getClientList();
EventQue* packetEventQue = _gateway->getPacketEventQue();
char buf[128];
while (true) while (true)
{ {
Forwarder* fwd = 0; Forwarder* fwd = nullptr;
WirelessNodeId nodeId; WirelessNodeId nodeId;
MQTTSNPacket* packet = new MQTTSNPacket(); MQTTSNPacket* packet = new MQTTSNPacket();
@@ -95,73 +99,11 @@ void ClientRecvTask::run()
log(0, packet, 0); 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;
} }
client = adpMgr->getClient(packet, this);
if ( packet->getType() == MQTTSN_ENCAPSULATED )
{
fwd = _gateway->getForwarderList()->getForwarder(_sensorNetwork->getSenderAddress());
if ( fwd == 0 )
{
log(0, packet, 0);
WRITELOG("%s Forwarder %s is not authenticated.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER);
delete packet;
continue;
}
else
{
MQTTSNString fwdName = MQTTSNString_initializer;
fwdName.cstring = const_cast<char *>( fwd->getName() );
log(0, packet, &fwdName);
/* get the packet from the encapsulation message */
MQTTSNGWEncapsulatedPacket encap;
encap.desirialize(packet->getPacketData(), packet->getPacketLength());
nodeId.setId( encap.getWirelessNodeId() );
client = fwd->getClient(&nodeId);
delete packet;
packet = encap.getMQTTSNPacket();
}
}
else
{
client = 0;
/* when QoSm1Proxy is available, select QoS-1 PUBLISH message */
QoSm1Proxy* pxy = _gateway->getQoSm1Proxy();
if ( pxy )
{
/* get ClientId not Client which can send QoS-1 PUBLISH */
const char* clientName = pxy->getClientId(_sensorNetwork->getSenderAddress());
if ( clientName )
{
if ( packet->isQoSMinusPUBLISH() )
{
/* QoS1Proxy takes responsibility of the client */
client = _gateway->getQoSm1Proxy()->getClient();
}
else
{
client = _gateway->getQoSm1Proxy()->getClient();
log(clientName, packet);
WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER);
delete packet;
continue;
}
}
}
if ( client == 0 )
{
/* get client from the ClientList of Gateway by sensorNetAddress. */
client = _gateway->getClientList()->getClient(_sensorNetwork->getSenderAddress());
}
}
if ( client ) if ( client )
{ {
@@ -169,7 +111,7 @@ void ClientRecvTask::run()
log(client, packet, 0); 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
{ {
@@ -186,14 +128,14 @@ void ClientRecvTask::run()
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);
@@ -208,7 +150,7 @@ void ClientRecvTask::run()
else else
{ {
/* create a new client */ /* create a new client */
client = _gateway->getClientList()->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, false, false); client = clientList->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, isAggrActive);
} }
} }
@@ -224,7 +166,7 @@ void ClientRecvTask::run()
/* post Client RecvEvent */ /* 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
{ {

View File

@@ -21,6 +21,7 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class AdapterManager;
/*===================================== /*=====================================
Class ClientRecvTask Class ClientRecvTask
@@ -28,15 +29,17 @@ 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); void log(Client*, MQTTSNPacket*, MQTTSNString* id);
void log(const char* clientId, MQTTSNPacket* packet); 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,27 +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);
if ( client->isProxy() )
{
_gateway->getQoSm1Proxy()->send(packet);
continue;
}
rc = packet->unicast(_sensorNetwork, client->getSensorNetAddress());
}
} }
else if (ev->getEventType() == EtBroadcast) else if (ev->getEventType() == EtBroadcast)
{ {
@@ -140,9 +121,3 @@ void ClientSendTask::log(Client* client, MQTTSNPacket* packet)
} }
} }
void ClientSendTask::log(Forwarder* forwarder, MQTTSNGWEncapsulatedPacket* packet)
{
char pbuf[SIZE_OF_LOG_PACKET * 3];
const char* forwarderId = forwarder->getId();
WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, forwarderId, packet->print(pbuf));
}

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,7 @@ 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));
if ( !client->isProxy() ) if ( !client->isAdapter() )
{ {
client->disconnected(); client->disconnected();
} }
@@ -104,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;
@@ -291,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

@@ -27,7 +27,6 @@ namespace MQTTSNGW
#define CLIENT_LIST "clients.conf" #define CLIENT_LIST "clients.conf"
#define PREDEFINEDTOPIC_FILE "predefinedTopic.conf" #define PREDEFINEDTOPIC_FILE "predefinedTopic.conf"
#define FORWARDER_LIST "forwarders.conf" #define FORWARDER_LIST "forwarders.conf"
#define QOS_1CLIENT_LIST "qos-1clients.conf"
/*========================================================== /*==========================================================
* Gateway default parameters * Gateway default parameters
@@ -41,6 +40,7 @@ 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)

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

@@ -20,13 +20,13 @@
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()
@@ -43,6 +43,35 @@ ForwarderList::~ForwarderList()
} }
} }
void ForwarderList::initialize(Gateway* gw)
{
char param[MQTTSNGW_PARAM_MAX];
string fileName;
GatewayParams* params = gw->getGWParams();
if (gw->getParam("Forwarder", param) == 0 )
{
if (!strcasecmp(param, "YES") )
{
if (gw->getParam("ForwardersList", param) == 0)
{
fileName = string(param);
}
else
{
fileName = params->configDir + string(FORWARDER_LIST);
}
if ( !setFowerder(fileName.c_str()) )
{
throw Exception("ForwarderList::initialize: No ForwardersList file defined by the configuration..");
}
params->forwarderListName = strdup(fileName.c_str());
}
}
}
Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr) Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr)
{ {
Forwarder* p = _head; Forwarder* p = _head;
@@ -111,7 +140,7 @@ bool ForwarderList::setFowerder(const char* fileName)
Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, string* forwarderId) 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;
} }
@@ -120,7 +149,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;
@@ -136,20 +165,20 @@ 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, string* forwarderId)
{ {
_forwarderName = *forwarderId; _forwarderName = *forwarderId;
_sensorNetAddr = *addr; _sensorNetAddr = *addr;
_headClient = 0; _headClient = nullptr;
_next = 0; _next = nullptr;
} }
Forwarder::~Forwarder(void) Forwarder::~Forwarder(void)
@@ -174,11 +203,11 @@ const char* Forwarder::getId(void)
void Forwarder::addClient(Client* client, WirelessNodeId* id) void Forwarder::addClient(Client* client, WirelessNodeId* id)
{ {
ForwarderElement* p = _headClient; ForwarderElement* p = _headClient;
ForwarderElement* prev = 0; ForwarderElement* prev = nullptr;
client->setForwarder(this); client->setForwarder(this);
if ( p != 0 ) if ( p != nullptr )
{ {
while ( p ) while ( p )
{ {
@@ -209,7 +238,7 @@ 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();
ForwarderElement* p = _headClient; ForwarderElement* p = _headClient;
while ( p ) while ( p )
@@ -235,7 +264,7 @@ 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();
ForwarderElement* p = _headClient; ForwarderElement* p = _headClient;
while ( p ) while ( p )
@@ -256,7 +285,7 @@ WirelessNodeId* Forwarder::getWirelessNodeId(Client* client)
void Forwarder::eraseClient(Client* client) void Forwarder::eraseClient(Client* client)
{ {
ForwarderElement* prev = 0; ForwarderElement* prev = nullptr;
_mutex.lock(); _mutex.lock();
ForwarderElement* p = _headClient; ForwarderElement* p = _headClient;
@@ -314,7 +343,7 @@ void ForwarderElement::setClient(Client* client)
void ForwarderElement::setWirelessNodeId(WirelessNodeId* id) void ForwarderElement::setWirelessNodeId(WirelessNodeId* id)
{ {
if ( _wirelessNodeId == 0 ) if ( _wirelessNodeId == nullptr )
{ {
_wirelessNodeId = new WirelessNodeId(); _wirelessNodeId = new WirelessNodeId();
} }

View File

@@ -18,22 +18,27 @@
#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 ForwarderElement
=====================================*/
class ForwarderElement class ForwarderElement
{ {
friend class Forwarder; friend class Forwarder;
public: public:
ForwarderElement(); ForwarderElement();
~ForwarderElement(); ~ForwarderElement();
void setClient(Client* client); void setClient(Client* client);
void setWirelessNodeId(WirelessNodeId* id); void setWirelessNodeId(WirelessNodeId* id);
private: private:
@@ -42,15 +47,18 @@ private:
ForwarderElement* _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, string* 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,17 +70,21 @@ public:
private: private:
string _forwarderName; string _forwarderName;
SensorNetAddress _sensorNetAddr; SensorNetAddress _sensorNetAddr;
ForwarderElement* _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); bool setFowerder(const char* fileName);
Forwarder* addForwarder(SensorNetAddress* addr, string* forwarderId); Forwarder* addForwarder(SensorNetAddress* addr, string* forwarderId);

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)
@@ -154,6 +172,11 @@ int MQTTSNPacket::setConnect(void)
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];
@@ -455,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);
@@ -80,8 +81,12 @@ public:
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); 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);
@@ -114,12 +127,8 @@ void PacketHandleTask::run()
_advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL);
} }
/*------ Check QoS-1 Proxy Connect or PINGREQ ------*/ /*------ Check Adapters Connect or PINGREQ ------*/
QoSm1Proxy* pxy = _gateway->getQoSm1Proxy(); adpMgr->checkConnection();
if ( pxy )
{
pxy->checkConnection();
}
} }
/*------ Handle SEARCHGW Message ---------*/ /*------ Handle SEARCHGW Message ---------*/
@@ -137,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;
@@ -47,34 +48,26 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
char shortTopic[2]; char shortTopic[2];
if ( !client->isActive() ) if ( !_gateway->getAdapterManager()->getQoSm1Proxy()->isActive() )
{ {
if ( client->isProxy() ) if ( client->isQoSm1() )
{ {
client->setProxyPacket(packet); _gateway->getAdapterManager()->getQoSm1Proxy()->savePacket(client, packet);
return nullptr;
} }
else
{
/* Reply DISCONNECT to the client */
Event* ev = new Event();
MQTTSNPacket* disconnect = new MQTTSNPacket();
disconnect->setDISCONNECT(0);
ev->setClientSendEvent(client, disconnect);
_gateway->getClientSendQue()->post(ev);
}
return;
} }
if ( packet->getPUBLISH(&dup, &qos, &retained, &msgId, &topicid, &payload, &payloadlen) ==0 ) 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 == 3 ? 0 : 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 )
{ {
@@ -90,7 +83,7 @@ void MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet)
if( !topic && qos == 3 ) if( !topic && qos == 3 )
{ {
WRITELOG("%s Invali TopicId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); WRITELOG("%s Invali TopicId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return; return nullptr;
} }
if( !topic && msgId && qos > 0 && qos < 3 ) if( !topic && msgId && qos > 0 && qos < 3 )
@@ -101,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 )
{ {
@@ -120,14 +113,17 @@ 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);
_gateway->getBrokerSendQue()->post(ev1);
/* reset PINGREQ of ClientProxy */ if ( !_gateway->getAdapterManager()->isAggregaterActive() )
if ( qos == 3 )
{ {
_gateway->getQoSm1Proxy()->resetPingTimer(); Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, publish);
_gateway->getBrokerSendQue()->post(ev1);
return nullptr;
}
else
{
return publish;
} }
} }
@@ -146,11 +142,14 @@ void MQTTSNPublishHandler::handlePuback(Client* client, MQTTSNPacket* packet)
if ( rc == MQTTSN_RC_ACCEPTED) 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)
{ {
@@ -219,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();
@@ -239,3 +238,49 @@ void MQTTSNPublishHandler::handleRegAck( Client* client, MQTTSNPacket* packet)
} }
} }
void MQTTSNPublishHandler::handleAggregatePublish(Client* client, MQTTSNPacket* packet)
{
int msgId = 0;
MQTTGWPacket* publish = handlePublish(client, packet);
if ( publish != nullptr )
{
if ( publish->getMsgId() > 0 )
{
if ( packet->isDuplicate() )
{
msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId());
}
else
{
msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId());
}
publish->setMsgId(msgId);
}
Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, publish);
_gateway->getBrokerSendQue()->post(ev1);
}
}
void MQTTSNPublishHandler::handleAggregateAck(Client* client, MQTTSNPacket* packet, int type)
{
if ( type == MQTTSN_PUBREC )
{
uint16_t msgId;
if ( packet->getACK(&msgId) == 0 )
{
return;
}
MQTTSNPacket* ackPacket = new MQTTSNPacket();
ackPacket->setPUBREL(msgId);
Event* ev = new Event();
ev->setClientSendEvent(client, ackPacket);
_gateway->getClientSendQue()->post(ev);
}
return;
}

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

@@ -1,275 +0,0 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWQoS-1Proxy.h"
#include "MQTTSNGWDefines.h"
#include "MQTTSNGateway.h"
#include "SensorNetwork.h"
#include <string>
#include <string.h>
#include <stdio.h>
#define QOSM1_PROXY_KEEPALIVE_DURATION 900 // Secs
#define QOSM1_PROXY_RESPONSE_DURATION 10 // Secs
#define QOSM1_PROXY_MAX_RETRY_CNT 3
using namespace MQTTSNGW;
/*
* Class ClientProxyElement
*/
QoSm1ProxyElement::QoSm1ProxyElement(void)
: _clientId{0}
, _next{0}
{
}
QoSm1ProxyElement::QoSm1ProxyElement(SensorNetAddress* addr, string* clientId)
: _next{0}
{
_clientId = *clientId;
_sensorNetAddr = *addr;
}
QoSm1ProxyElement::~QoSm1ProxyElement(void)
{
}
/*
* Class ClientProxy
*/
QoSm1Proxy:: QoSm1Proxy(void)
: _head{0}
, _isWaitingResp{false}
, _retryCnt{0}
{
_gateway = 0;
_client = 0;
}
QoSm1Proxy:: QoSm1Proxy(Gateway* gw)
: _head{0}
, _isWaitingResp{false}
, _retryCnt{0}
{
_gateway = gw;
_client = 0;
}
QoSm1Proxy::~QoSm1Proxy(void)
{
if ( _head )
{
QoSm1ProxyElement* p = _head;
while ( p )
{
QoSm1ProxyElement* next = p->_next;
delete p;
p = next;
}
}
}
void QoSm1Proxy::setGateway(Gateway* gw)
{
_gateway = gw;
}
QoSm1ProxyElement* QoSm1Proxy::add(SensorNetAddress* addr, string* clientId)
{
QoSm1ProxyElement* elm = new QoSm1ProxyElement(addr, clientId);
if ( _head == 0 )
{
_head = elm;
}
else
{
QoSm1ProxyElement* p = _head;
while ( p )
{
if ( p->_next == 0 )
{
p->_next = elm;
break;
}
else
{
p = p->_next;
}
}
}
return elm;
}
const char* QoSm1Proxy::getClientId(SensorNetAddress* addr)
{
QoSm1ProxyElement* p = _head;
while ( p )
{
if ( p->_sensorNetAddr.isMatch(addr) )
{
return p->_clientId.c_str();
break;
}
p = p->_next;
}
return 0;
}
void QoSm1Proxy::setClient(Client* client)
{
_client = client;
}
Client* QoSm1Proxy::getClient(void)
{
return _client;
}
bool QoSm1Proxy::setClientProxy(const char* fileName)
{
FILE* fp;
char buf[MAX_CLIENTID_LENGTH + 256];
size_t pos;
SensorNetAddress netAddr;
if ((fp = fopen(fileName, "r")) != 0)
{
while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0)
{
if (*buf == '#')
{
continue;
}
string data = string(buf);
while ((pos = data.find_first_of("  \t\n")) != string::npos)
{
data.erase(pos, 1);
}
if (data.empty())
{
continue;
}
pos = data.find_first_of(",");
string id = data.substr(0, pos);
string addr = data.substr(pos + 1);
if (netAddr.setAddress(&addr) == 0)
{
add(&netAddr, &id);
}
else
{
WRITELOG("Invalid address %s\n", data.c_str());
return false;
}
}
fclose(fp);
}
else
{
WRITELOG("Can not open the QoS_1Client List. %s\n", fileName);
return false;
}
return true;
}
void QoSm1Proxy::checkConnection(void)
{
if ( _client->isDisconnect() || ( _client->isConnecting() && _responseTimer.isTimeup()) )
{
_client->connectSended();
_responseTimer.start(QOSM1_PROXY_RESPONSE_DURATION * 1000UL);
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
options.clientID.cstring = _client->getClientId();
options.duration = QOSM1_PROXY_KEEPALIVE_DURATION;
MQTTSNPacket* packet = new MQTTSNPacket();
packet->setCONNECT(&options);
Event* ev = new Event();
ev->setClientRecvEvent(_client, packet);
_gateway->getPacketEventQue()->post(ev);
}
else if ( (_client->isActive() && _keepAliveTimer.isTimeup() ) || (_isWaitingResp && _responseTimer.isTimeup() ) )
{
MQTTSNPacket* packet = new MQTTSNPacket();
MQTTSNString clientId = MQTTSNString_initializer;
packet->setPINGREQ(&clientId);
Event* ev = new Event();
ev->setClientRecvEvent(_client, packet);
_gateway->getPacketEventQue()->post(ev);
_responseTimer.start(QOSM1_PROXY_RESPONSE_DURATION * 1000UL);
_isWaitingResp = true;
if ( ++_retryCnt > QOSM1_PROXY_MAX_RETRY_CNT )
{
_client->disconnected();
}
resetPingTimer();
}
}
void QoSm1Proxy::resetPingTimer(void)
{
_keepAliveTimer.start(QOSM1_PROXY_KEEPALIVE_DURATION * 1000UL);
}
void QoSm1Proxy::send(MQTTSNPacket* packet)
{
if ( packet->getType() == MQTTSN_CONNACK )
{
resetPingTimer();
_responseTimer.stop();
_retryCnt = 0;
sendStoredPublish();
}
else if ( packet->getType() == MQTTSN_PINGRESP )
{
_responseTimer.stop();
_isWaitingResp = false;
_retryCnt = 0;
resetPingTimer();
}
else if ( packet->getType() == MQTTSN_DISCONNECT )
{
// blank
}
}
void QoSm1Proxy::sendStoredPublish(void)
{
MQTTSNPacket* msg = 0;
while ( ( msg = _client->getProxyPacket() ) != 0 )
{
_client->deleteFirstProxyPacket(); // pop the que to delete element.
Event* ev = new Event();
ev->setClientRecvEvent(_client, msg);
_gateway->getPacketEventQue()->post(ev);
}
}

View File

@@ -1,79 +0,0 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_
#include "MQTTSNGateway.h"
#include "MQTTGWPacket.h"
#include "MQTTSNGWClient.h"
#include "SensorNetwork.h"
#include "MQTTSNGWProcess.h"
namespace MQTTSNGW
{
class Gateway;
class QoSm1ProxyElement
{
friend class QoSm1Proxy;
public:
QoSm1ProxyElement(void);
QoSm1ProxyElement(SensorNetAddress* addr, string* clientId);
~QoSm1ProxyElement(void);
private:
SensorNetAddress _sensorNetAddr;
string _clientId;
QoSm1ProxyElement* _next;
};
class QoSm1Proxy
{
public:
QoSm1Proxy(void);
QoSm1Proxy(Gateway* gw);
~QoSm1Proxy(void);
bool setClientProxy(const char* fileName);
QoSm1ProxyElement* add(SensorNetAddress* addr, string* clientId);
const char* getClientId(SensorNetAddress* addr);
void setClient(Client*);
Client* getClient(void);
void setGateway(Gateway* gw);
void setKeepAlive(uint16_t secs);
void checkConnection(void);
void resetPingTimer(void);
void send(MQTTSNPacket* packet);
private:
void sendStoredPublish(void);
Gateway* _gateway;
Client* _client;
QoSm1ProxyElement* _head;
Timer _keepAliveTimer;
Timer _responseTimer;
bool _isWaitingResp;
int _retryCnt;
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWQOS_1PROXY_H_ */

View File

@@ -0,0 +1,75 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWQoSm1Proxy.h"
#include "MQTTSNGateway.h"
#include "SensorNetwork.h"
#include "MQTTSNGWClientList.h"
#include <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(_gateway, QOSM1PROXY_TYPE);
/* set ClientId of this Proxy */
const char* name = CLIENTPROXY;
if (_gateway->getParam("QoS-1ProxyName", param) == 0 )
{
name = param;
}
/* initialize Adapter */
setup(name, Atype_QoSm1Proxy);
_isActive = true;
}
}
}
bool QoSm1Proxy::isActive(void)
{
return _isActive;
}

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.1" #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,32 +28,13 @@ char* currentDateTime(void);
/*===================================== /*=====================================
Class Gateway Class Gateway
=====================================*/ =====================================*/
Gateway::Gateway() Gateway::Gateway(void)
{ {
theMultiTaskProcess = this; theMultiTaskProcess = this;
theProcess = this; theProcess = this;
_qosm1Proxy = 0; _packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS);
_params.loginId = 0; _clientList = new ClientList();
_params.password = 0; _adapterManager = new AdapterManager(this);
_params.keepAlive = 0;
_params.gatewayId = 0;
_params.mqttVersion = 0;
_params.maxInflightMsgs = 0;
_params.gatewayName = 0;
_params.brokerName = 0;
_params.port = 0;
_params.portSecure = 0;
_params.rootCApath = 0;
_params.rootCAfile = 0;
_params.certKey = 0;
_params.privateKey = 0;
_params.clientListName = 0;
_params.configName = 0;
_params.predefinedTopicFileName = 0;
_params.forwarderListName = 0;
_params.qosMinusClientListName = 0;
_params.qosm1proxyName = 0;
_packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS);
} }
Gateway::~Gateway() Gateway::~Gateway()
@@ -116,25 +99,34 @@ Gateway::~Gateway()
{ {
free(_params.qosMinusClientListName); free(_params.qosMinusClientListName);
} }
if ( _params.qosm1proxyName )
{
free(_params.qosm1proxyName);
}
if ( _qosm1Proxy ) if ( _adapterManager )
{ {
delete _qosm1Proxy; delete _adapterManager;
} }
if ( _clientList )
{
delete _clientList;
}
}
int Gateway::getParam(const char* parameter, char* value)
{
return MultiTaskProcess::getParam(parameter, value);
} }
void Gateway::initialize(int argc, char** argv) void Gateway::initialize(int argc, char** argv)
{ {
char param[MQTTSNGW_PARAM_MAX]; char param[MQTTSNGW_PARAM_MAX];
string fileName; string fileName;
bool secure = false;
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);
@@ -180,6 +172,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)
{ {
@@ -193,7 +190,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);
@@ -218,113 +214,23 @@ void Gateway::initialize(int argc, char** argv)
{ {
if (!strcasecmp(param, "YES")) if (!strcasecmp(param, "YES"))
{ {
secure = true; _params.clientAuthentication = true;
if (getParam("ClientsList", param) == 0)
{
fileName = string(param);
}
else
{
fileName = *getConfigDirName() + string(CLIENT_LIST);
}
if (!_clientList.authorize(fileName.c_str()))
{
throw Exception("Gateway::initialize: No client list defined by the configuration.");
}
_params.clientListName = strdup(fileName.c_str());
} }
} }
/* Set QoSm1Proxy's Client */ /* ClientList and Adapters Initialize */
_adapterManager->initialize();
if (getParam("QoS-1", param) == 0 ) bool aggregate = _adapterManager->isAggregaterActive();
{ _clientList->initialize(this, aggregate);
if (!strcasecmp(param, "YES") )
{
/* Set QoSm1Proxy's Client */
_qosm1Proxy = new QoSm1Proxy(this);
MQTTSNString id = MQTTSNString_initializer;
if (getParam("QoS-1ProxyName", param) == 0 )
{
string name = string(param);
id.cstring = const_cast<char*>(name.c_str());
}
else
{
id.cstring = const_cast<char*>(CLIENTPROXY);
}
Client* client = _clientList.createClient(0, &id, true, secure);
_qosm1Proxy->setClient(client);
client->setPorxy(true);
_qosm1Proxy->setGateway(this);
if (getParam("QoS-1ClientsList", param) == 0)
{
fileName = string(param);
}
else
{
fileName = *getConfigDirName() + string(QOS_1CLIENT_LIST);
}
if ( !_qosm1Proxy->setClientProxy(fileName.c_str()) )
{
throw Exception("Gateway::initialize: No QoS-1ClientsList file defined by the configuration..");
}
_params.qosMinusClientListName = strdup(fileName.c_str());
}
}
if (getParam("PredefinedTopic", param) == 0 )
{
if (!strcasecmp(param, "YES") )
{
if (getParam("PredefinedTopicList", param) == 0)
{
fileName = string(param);
}
else
{
fileName = *getConfigDirName() + string(PREDEFINEDTOPIC_FILE);
}
if (!_clientList.setPredefinedTopics(fileName.c_str()))
{
throw Exception("Gateway::initialize: No PredefinedTopic file defined by the configuration..");
}
_params.predefinedTopicFileName = strdup(fileName.c_str());
}
}
if (getParam("Forwarder", param) == 0 )
{
if (!strcasecmp(param, "YES") )
{
if (getParam("ForwardersList", param) == 0)
{
fileName = string(param);
}
else
{
fileName = *getConfigDirName() + string(FORWARDER_LIST);
}
if ( !_forwarderList.setFowerder(fileName.c_str()) )
{
throw Exception("Gateway::initialize: No ForwardersList file defined by the configuration..");
}
_params.forwarderListName = strdup(fileName.c_str());
}
}
fileName = *getConfigDirName() + *getConfigFileName();
_params.configName = strdup(fileName.c_str());
/* Setup predefined topics */
_clientList->setPredefinedTopics(this, aggregate);
} }
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);
@@ -335,30 +241,36 @@ 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 ( getClientList()->isAuthorized() )
{ {
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 ) if ( _params.forwarderListName )
{ {
WRITELOG(" Forwarders: %s\n", _params.forwarderListName); WRITELOG(" Forwarders: %s\n", _params.forwarderListName);
} }
if ( _params.qosMinusClientListName ) if ( _params.qosMinusClientListName )
{ {
WRITELOG(" QoS-1File: %s\n", _params.qosMinusClientListName); WRITELOG(" QoS-1File: %s\n", _params.qosMinusClientListName);
} }
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\n\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 */
@@ -396,12 +308,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()
@@ -419,11 +326,18 @@ GatewayParams* Gateway::getGWParams(void)
return &_params; return &_params;
} }
QoSm1Proxy* Gateway::getQoSm1Proxy(void) AdapterManager* Gateway::getAdapterManager(void)
{ {
return _qosm1Proxy; return _adapterManager;
} }
bool Gateway::hasSecureConnection(void)
{
return ( _params.certKey
&& _params.privateKey
&& _params.rootCApath
&& _params.rootCAfile );
}
/*===================================== /*=====================================
Class EventQue Class EventQue
=====================================*/ =====================================*/
@@ -450,9 +364,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 )
{ {
@@ -520,11 +434,7 @@ int EventQue::size()
=====================================*/ =====================================*/
Event::Event() Event::Event()
{ {
_eventType = Et_NA;
_client = 0;
_sensorNetAddr = 0;
_mqttSNPacket = 0;
_mqttGWPacket = 0;
} }
Event::~Event() Event::~Event()
@@ -620,3 +530,5 @@ MQTTGWPacket* Event::getMQTTGWPacket(void)
{ {
return _mqttGWPacket; return _mqttGWPacket;
} }

View File

@@ -16,12 +16,10 @@
#ifndef MQTTSNGATEWAY_H_ #ifndef MQTTSNGATEWAY_H_
#define MQTTSNGATEWAY_H_ #define MQTTSNGATEWAY_H_
#include "MQTTSNGWClient.h" #include <MQTTSNGWAdapterManager.h>
#include "MQTTSNGWProcess.h" #include "MQTTSNGWProcess.h"
#include "MQTTSNPacket.h" #include "MQTTSNPacket.h"
#include "MQTTSNGWClient.h"
#include "MQTTSNGWForwarder.h"
#include "MQTTSNGWQoS-1Proxy.h"
namespace MQTTSNGW namespace MQTTSNGW
{ {
@@ -46,6 +44,7 @@ namespace MQTTSNGW
#define CLIENTS "Clients" #define CLIENTS "Clients"
#define UNKNOWNCL "Unknown Client !" #define UNKNOWNCL "Unknown Client !"
#define CLIENTPROXY "ClientProxy" #define CLIENTPROXY "ClientProxy"
#define CLIENTPROXY_SECURE "ClientProxyS"
#define LEFTARROW "<---" #define LEFTARROW "<---"
#define RIGHTARROW "--->" #define RIGHTARROW "--->"
@@ -77,6 +76,8 @@ namespace MQTTSNGW
/*===================================== /*=====================================
Class Event Class Event
====================================*/ ====================================*/
class Client;
enum EventType{ enum EventType{
Et_NA = 0, Et_NA = 0,
EtStop, EtStop,
@@ -109,13 +110,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
====================================*/ ====================================*/
@@ -136,41 +138,48 @@ 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};
char* qosm1proxyName; char* predefinedTopicFileName {nullptr};
char* qosMinusClientListName; char* forwarderListName {nullptr};
}GatewayParams; char* qosMinusClientListName {nullptr};
bool clientAuthentication {false};
};
/*===================================== /*=====================================
Class Gateway Class Gateway
=====================================*/ =====================================*/
class QoSm1Proxy; 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);
@@ -179,22 +188,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);
QoSm1Proxy* getQoSm1Proxy(void); AdapterManager* getAdapterManager(void);
int getParam(const char* parameter, char* value);
bool hasSecureConnection(void);
private: private:
ClientList _clientList; GatewayParams _params;
QoSm1Proxy* _qosm1Proxy; ClientList* _clientList {nullptr};
ForwarderList _forwarderList;
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());