Merge pull request #245 from eclipse/develop

Update Gateway
This commit is contained in:
Tomoaki Yamaguchi
2021-09-16 15:32:13 +09:00
committed by GitHub
138 changed files with 13504 additions and 7737 deletions

232
.cproject
View File

@@ -1,352 +1,192 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.config.gnu.exe.debug.1685199227">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.debug.1685199227" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1685199227" name="Debug" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.exe.debug">
<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1685199227." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.102264757" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.2137160061" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
<builder buildPath="${workspace_loc:/MQTTSN-embedded-C}/Debug" id="cdt.managedbuild.target.gnu.builder.exe.debug.767762182" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
<builder buildPath="${workspace_loc:/MQTTSN-embedded-C}/Debug" id="cdt.managedbuild.target.gnu.builder.exe.debug.767762182" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.602829827" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.109068141" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
<option id="gnu.cpp.compiler.exe.debug.option.optimization.level.1710260957" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
<option id="gnu.cpp.compiler.exe.debug.option.debugging.level.1258567310" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.std.1678347248" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.flags.1711182709" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=c++11" valueType="string"/>
<option id="gnu.cpp.compiler.exe.debug.option.debugging.level.1258567310" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.default" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.std.1678347248" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.c++11" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.flags.1711182709" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="" valueType="string"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1361987608" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/GatewayTester/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/dtls}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNPacket/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNClient/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/udp}&quot;"/>
</option>
<option id="gnu.cpp.compiler.option.debugging.sanitleak.778932189" name="Sanitize memory leak (-fsanitize=leak)" superClass="gnu.cpp.compiler.option.debugging.sanitleak" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="gnu.cpp.compiler.option.debugging.sanitpointers.435146187" name="Sanitize pointer operations (-fsanitize=pointer-compare -fsanitize=pointer-subtract)" superClass="gnu.cpp.compiler.option.debugging.sanitpointers" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="gnu.cpp.compiler.option.debugging.sanitaddress.501742254" name="Sanitize address (-fsanitize=address)" superClass="gnu.cpp.compiler.option.debugging.sanitaddress" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.preprocessor.def.1354093543" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="DTLS"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1626802967" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2017162618" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.1941536725" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
<option id="gnu.c.compiler.exe.debug.option.debugging.level.1668726974" name="Debug Level" superClass="gnu.c.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.preprocessor.def.symbols.798283837" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="OPENSSL_API_COMPAT=30000"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.1870583388" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/dtls}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.814497727" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1881440001" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug">
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.910023243" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.581660133" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1848275182" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="pthread"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="ssl"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="crypto"/>
<listOptionValue builtIn="false" value="ssl"/>
<listOptionValue builtIn="false" value="crypto"/>
<listOptionValue builtIn="false" value="pthread"/>
<listOptionValue builtIn="false" value="bluetooth"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.170974409" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
<listOptionValue builtIn="false" value="/usr/local/lib"/>
</option>
<option id="gnu.cpp.link.option.shared.1648098307" name="Shared (-shared)" superClass="gnu.cpp.link.option.shared" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.98211496" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.exe.debug.1531154076" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1193873077" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="MQTTSNGateway/src/linux/loralink|MQTTSNGateway/GatewayTester|MQTTSNGateway/GatewayTester/samples|MQTTSNGateway/src/linux/udp6|MQTTSNClient|MQTTSNGateway/src/MQTTSNGWProxy.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|ClientPubQoS-1|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
<entry excluding="GatewayTester|src/linux/udp6|src/linux/udp|src/linux/dtls/SensorNetSubTask.cpp|GatewayTester/samples/ClientSub|GatewayTester/samples/ClientPubQoS-1|GatewayTester/samples/ClientPub|src/linux/rfcomm|src/tests|src/linux/xbee|src/mainLogmonitor.cpp|src/linux/loralink" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway"/>
<entry excluding="mainTest.cpp|ClientSub|ClientPubQoS-1|ClientPub" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTSNGateway/GatewayTester/samples"/>
<entry excluding="samples|test" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
<cconfiguration id="cdt.managedbuild.config.gnu.exe.release.561557339">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.release.561557339" moduleId="org.eclipse.cdt.core.settings" name="Release">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.561557339" name="Release" parent="cdt.managedbuild.config.gnu.exe.release">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.561557339" name="Release" optionalBuildProperties="" parent="cdt.managedbuild.config.gnu.exe.release">
<folderInfo id="cdt.managedbuild.config.gnu.exe.release.561557339." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.474335535" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release">
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.338327831" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/>
<builder buildPath="${workspace_loc:/MQTTSN-embedded-C}/Release" id="cdt.managedbuild.target.gnu.builder.exe.release.1268563010" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.release"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.1908794347" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1903732701" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release">
<option id="gnu.cpp.compiler.exe.release.option.optimization.level.15425920" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
<option id="gnu.cpp.compiler.exe.release.option.debugging.level.857802503" name="Debug Level" superClass="gnu.cpp.compiler.exe.release.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.flags.1078302249" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=c++11" valueType="string"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.2114194326" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/udp}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNPacket/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/GatewayTester/src}&quot;"/>
</option>
<option id="gnu.cpp.compiler.option.dialect.std.216116103" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1606625536" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.246546722" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release">
<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.exe.release.option.optimization.level.1094525037" name="Optimization Level" superClass="gnu.c.compiler.exe.release.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
<option id="gnu.c.compiler.exe.release.option.debugging.level.162341902" name="Debug Level" superClass="gnu.c.compiler.exe.release.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.456127079" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.release.2140499460" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release">
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.46435036" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1623573602" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.68366124" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="pthread"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="ssl"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="crypto"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.1879517971" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
<listOptionValue builtIn="false" value="/usr/local/lib"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.2044523925" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.exe.release.67939689" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.651929038" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="MQTTSNGateway/src/tests/mainTestProcess.cpp|MQTTSNGateway/src/linux|MQTTSNPacket/src|MQTTSNGateway/GatewayTester|MQTTSNGateway/GatewayTester/samples|MQTTSNClient|MQTTSNPacket/test|MQTTSNPacket/samples|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|ClientPubQoS-1" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
<entry excluding="udp6|xbee|loralink" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTSNGateway/src/linux"/>
<entry excluding="MQTTSNPacket/test|MQTTSNPacket/samples|MQTTSNGateway/GatewayTester/samples/ClientPub|MQTTSNGateway/src/tests/mainTestProcess.cpp|MQTTSNGateway/src/linux|MQTTSNGateway|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp|MQTTSNGateway/GatewayTester/samples/ClientSub|MQTTSNClient|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|MQTTSNGateway/src|MQTTSNPacket/src|MQTTSNGateway/GatewayTester|ClientPubQoS-1" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
<entry excluding="mainTest.cpp|ClientSub|ClientPubQoS-1|ClientPub" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTSNGateway/GatewayTester/samples"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTSNGateway/src"/>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket/src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="MQTTSN-embedded-C.cdt.managedbuild.target.gnu.exe.317758410" name="Executable" projectType="cdt.managedbuild.target.gnu.exe"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug"/>
<configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/MQTTSN-embedded-C"/>
</configuration>
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/MQTTSN-embedded-C"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1685199227;cdt.managedbuild.config.gnu.exe.debug.1685199227.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2017162618;cdt.managedbuild.tool.gnu.c.compiler.input.814497727">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.561557339;cdt.managedbuild.config.gnu.exe.release.561557339.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1903732701;cdt.managedbuild.tool.gnu.cpp.compiler.input.1606625536">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1685199227;cdt.managedbuild.config.gnu.exe.debug.1685199227.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.109068141;cdt.managedbuild.tool.gnu.cpp.compiler.input.1626802967">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.561557339;cdt.managedbuild.config.gnu.exe.release.561557339.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.246546722;cdt.managedbuild.tool.gnu.c.compiler.input.456127079">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1685199227;cdt.managedbuild.config.gnu.exe.debug.1685199227.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2017162618;cdt.managedbuild.tool.gnu.c.compiler.input.814497727">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.561557339;cdt.managedbuild.config.gnu.exe.release.561557339.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1903732701;cdt.managedbuild.tool.gnu.cpp.compiler.input.1606625536">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
</cproject>

11
.gitignore vendored
View File

@@ -5,8 +5,15 @@
*.pyc
/doc/MQTTSNClient/
/doc/MQTTSNPacket/
/rbmutex.key
/ringbuffer.key
rbmutex.key
ringbuffer.key
/Release/
/Debug/
/core
Build/
*.a
CMakeFiles/
*.cmake
CMakeCache.txt
bin/
/build.gateway/

View File

@@ -1,48 +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="-179845344490928458" 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">
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-176156747064280842" 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="-179845344490928458" 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">
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-176157551606184930" 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

@@ -0,0 +1,77 @@
eclipse.preferences.version=1
fr.ac6.mcu.ide.source.checker.libnano.problem=Error
fr.ac6.mcu.ide.source.checker.libnano.problem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Float formatting support\\")"}
org.eclipse.cdt.codan.checkers.errnoreturn=Warning
org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false}
org.eclipse.cdt.codan.checkers.errreturnvalue=Error
org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"}
org.eclipse.cdt.codan.checkers.nocommentinside=-Error
org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"}
org.eclipse.cdt.codan.checkers.nolinecomment=-Error
org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"}
org.eclipse.cdt.codan.checkers.noreturn=Error
org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false}
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"}
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"}
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"}
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"}
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false}
org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"}
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true}
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"}
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"}
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"}
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"}
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"}
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"}
org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"}
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"}
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"}
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"}
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"}
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false}
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false}
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")}
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"}
org.eclipse.cdt.qt.core.qtproblem=Warning
org.eclipse.cdt.qt.core.qtproblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_ON_FILE_OPEN\=>true,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>null}

View File

@@ -0,0 +1,2 @@
eclipse.preferences.version=1
formatter_settings_version=1

View File

@@ -13,20 +13,12 @@ addons:
- g++-4.8
- cmake
- cmake-data
- bluez
- libbluetooth-dev
script:
- ./travis-build.sh
- cd MQTTSNGateway
- make SENSORNET="xbee"
- make SENSORNET="udp"
- make SENSORNET="udp6"
- make test
- cd GatewayTester
- make
notifications:
emails:
- tomoaki@tomy-tech.com

View File

@@ -14,7 +14,7 @@
# Ian Craggs - initial version
#*******************************************************************************/
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
PROJECT("paho-mqttsn" CXX)
MESSAGE(STATUS "CMake version: " ${CMAKE_VERSION})
MESSAGE(STATUS "CMake system name: " ${CMAKE_SYSTEM_NAME})
@@ -39,3 +39,4 @@ INCLUDE(CPack)
ENABLE_TESTING()
ADD_SUBDIRECTORY(MQTTSNPacket)
ADD_SUBDIRECTORY(MQTTSNGateway)

View File

@@ -0,0 +1,16 @@
#*******************************************************************************
# Copyright (c) 2022 a1lu
#
# 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:
# a1lu - initial version
#*******************************************************************************/
ADD_SUBDIRECTORY(src)

Binary file not shown.

View File

@@ -20,6 +20,10 @@ CPPSRCS := \
$(SUBDIR)/LGwProxy.cpp \
$(SUBDIR)/LMqttsnClient.cpp \
$(SUBDIR)/LNetworkUdp.cpp \
$(SUBDIR)/LNetworkUdp6.cpp \
$(SUBDIR)/LNetworkRfcomm.cpp \
$(SUBDIR)/LNetworkDtls.cpp \
$(SUBDIR)/LNetworkDtls6.cpp \
$(SUBDIR)/LPublishManager.cpp \
$(SUBDIR)/LRegisterManager.cpp \
$(SUBDIR)/LSubscribeManager.cpp \
@@ -36,12 +40,14 @@ $(SUBDIR)/Util.cpp \
CXX := g++
CPPFLAGS +=
INCLUDES += -I$(SUBDIR)
DEFS :=
LIBS +=
INCLUDES += -I$(SUBDIR) -I/usr/local/opt/openssl/include
DEF1 :=
DEF2 :=
DEFS := -D$(SN) $(DEF1) $(DEF2)
LIBS += -L/usr/local/lib -L/usr/local/opt/openssl/lib
LDFLAGS :=
CXXFLAGS := -Wall -O3 -std=c++11
LDADD :=
LDADD := -lssl -lcrypto $(LDADDBLT)
OUTDIR := Build
PROG := $(OUTDIR)/$(PROGTEST)
@@ -75,23 +81,23 @@ $(PROGQOS): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCQOS)/$(QOSAPPL).o
$(OUTDIR)/$(SUBDIR)/%.o:$(SUBDIR)/%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/%.o:$(SRCDIR)/%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(SRCPUB)/%.o:$(SRCDIR)/$(SRCPUB)%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(SRCSUB)/%.o:$(SRCDIR)/$(SRCSUB)%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(SRCQOS)/%.o:$(SRCDIR)/$(SRCQOS)%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
clean:
rm -rf $(OUTDIR)

View File

@@ -1,28 +1,7 @@
###Gateway Test Program.
# Gateway Test Program.
**sample/mainTest.cpp** is a Test sample coading.
Each test is described as one function. test1(), test2()...
````
/*------------------------------------------------------
* Test functions
*
* you can use 4 commands in Test functions
*
* 1) PUBLISH(const char* topicName,
* uint8_t* payload,
* uint16_t len,
* uint8_t qos,
* bool retain = false);
*
* 2) SUBSCRIBE(const char* topicName,
* TopicCallback onPublish,
* uint8_t qos);
*
* 3) UNSUBSCRIBE(const char* topicName);
*
* 4) DISCONNECT(uint16_t sleepInSecs);
*
*------------------------------------------------------*/
```
void test1(void)
{
char payload[300];
@@ -36,9 +15,35 @@ void test2(void)
uint8_t qos = 1;
SUBSCRIBE(topic2, on_publish02, qos);
}
````
**TEST_LIST** is a test senario. Test functions are executed one by one.
````
*---------------------------------------------------------------------------
*
* MQTT-SN GATEWAY TEST CLIENT
*
* Supported functions.
*
* void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
*
* void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
*
* void DISCONNECT ( uint16_t sleepInSecs );
*
* void CONNECT ( void );
*
* void DISPLAY( format, .....); <== instead of printf()
*--------------------------------------------------------------------------
```
**TEST_LIST** is a test senario. Test functions are executed interactively.
```
/*------------------------------------------------------
* A List of Test Tasks
*------------------------------------------------------*/
@@ -52,68 +57,61 @@ TEST_LIST = {// e.g. TEST( Label, Test),
TEST("Disconnect", test5),
END_OF_TEST_LIST
};
````
### **step1. Build **
````
$ git clone https://github.com/eclipse/paho.mqtt-sn.embedded-c
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester
$ make
$ make install
$ make clean
```
MQTT-SNGatewayTester program is copied into ../../../ directory.
**UDP**, **DTLS**, **UDP6**, **DTLS6** or **Bluetooth** is available as a sensor network.
```
/*------------------------------------------------------
* UDP, DTLS Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = { "GatewayTestClient", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* UDP6, DTLS6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "GatewayTestClient", // ClientId
"ff12::feed:caca:dead", // Multicast group IP
"wlp4s0",
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "GatewayTestClient", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
```
### **step2. Execute Gateway Tester.**
## How to Build
```
copy codes from the github.
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester
$ ./build.sh [udp | udp6 | dtls | dtls6 | rfcomm]
```
````
$ cd ../../..
$ ./MQTT-SNGatewayTester
## Execute Gateway Tester
```
$ ./Build/MQTT-SNGatewayTester
***************************************************************************
* MQTT-SN Gateway Tester
* MQTT-SN Gateway Tester DTLS
* Part of Project Paho in Eclipse
* (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)
*
* Author : Tomoaki YAMAGUCHI
* Version: 0.0.0
* Version: 2.0.0
***************************************************************************
Attempting to Connect the Broker.....
Execute "Step0:Connect" ? ( y/n ) :
sendto 225.1.1.1 :1883 03 01 00
recved 192.168.11.5 :1883 03 01 00
sendto 225.1.1.1 :1883 03 01 00
recved 192.168.11.5 :1883 03 01 00
recved 192.168.11.17 :10000 03 02 01
sendto 192.168.11.17 :10000 13 04 0c 01 03 84 47 61 74 65 77 61 79 54 65 73 74 65 72
recved 192.168.11.17 :10000 02 06
sendto 192.168.11.17 :10000 0c 07 00 77 69 6c 6c 54 6f 70 69 63
recved 192.168.11.17 :10000 02 08
sendto 192.168.11.17 :10000 0d 09 77 69 6c 6c 4d 65 73 73 61 67 65
recved 192.168.11.17 :10000 03 05 00
Connected to the Broker
Attempting OnConnect.....
sendto 192.168.11.17 :10000 13 12 20 00 01 74 79 34 74 77 2f 63 6c 69 65 6e 74 49 64
recved 192.168.11.17 :10000 08 13 20 00 01 00 01 00
SUBSCRIBE complete. ty4tw/clientId
OnConnect complete
Test Ready.
Execute Publish topic1 Test ? ( Y/N ) :
````
```

View File

@@ -0,0 +1,23 @@
#!/bin/bash
DEF1="DEF1=${2}"
DEF2="DEF2=${3}"
if [ $1 == "udp" ] ; then
make SN=UDP $DEF1 $DEF2
elif [ $1 == "udp6" ] ; then
make SN=UDP6 $DEF1 $DEF2
elif [ $1 == "rfcomm" ] ; then
export LDADDBLT=-lbluetooth
make SN=RFCOMM $DEF1 $DEF2
elif [ $1 == "dtls" ] ; then
make SN=DTLS $DEF1 $DEF2
elif [ $1 == "dtls6" ] ; then
make SN=DTLS6 $DEF1 $DEF2
elif [ $1 == "clean" ] ; then
make clean
else
echo "Usage: build.sh [ udp | udp6 | rfcomm | dtls | dtls6 | clean]"
fi

View File

@@ -51,13 +51,30 @@ extern LScreen* theScreen;
/*------------------------------------------------------
* UDP Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = {
"ClientPUB", // ClientId
UDPCONF = { "ClientPUB", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20010, // Local PortNo
};
/*------------------------------------------------------
* UDP6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "ClientPUB", // ClientId
"ff1e:feed:caca:dead::1", // Multicast group IP
"wlp4s0", // Network Interface
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "ClientPUB", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
/*------------------------------------------------------
* Client Configuration (theMqcon)
*------------------------------------------------------*/
@@ -117,7 +134,7 @@ void publishTopic57(void)
char payload[300];
sprintf(payload, "publish \"ty4tw/topic57\" \n");
uint8_t qos = 0;
PUBLISH(topic2,(uint8_t*)payload, strlen(payload), qos);
PUBLISH(topic57, (uint8_t* )payload, strlen(payload), qos);
}

View File

@@ -51,13 +51,30 @@ extern LScreen* theScreen;
/*------------------------------------------------------
* UDP Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = {
"QoS-1_Client01", // ClientId
UDPCONF = { "QoS-1_Client01", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20001, // Local PortNo
};
/*------------------------------------------------------
* UDP6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "QoS-1_Client01", // ClientId
"ff1e:feed:caca:dead::1", // Multicast group IP
"wlp4s0", // Network Interface
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "QoS-1_Client01", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
/*------------------------------------------------------
* Client Configuration (theMqcon)
*------------------------------------------------------*/

View File

@@ -51,13 +51,30 @@ extern LScreen* theScreen;
/*------------------------------------------------------
* UDP Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = {
"ClientSUB", // ClientId
UDPCONF = { "ClientSUB", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20011, // Local PortNo
};
/*------------------------------------------------------
* UDP6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "ClientSUB", // ClientId
"ff1e:feed:caca:dead::1", // Multicast group IP
"wlp4s0", // Network Interface
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "ClientSUB", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
/*------------------------------------------------------
* Client Configuration (theMqcon)
*------------------------------------------------------*/

View File

@@ -49,20 +49,36 @@ extern LMqttsnClient* theClient;
extern LScreen* theScreen;
/*------------------------------------------------------
* UDP Configuration (theNetcon)
* UDP,DTLS Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = {
"GatewayTestClient", // ClientId
UDPCONF = { "GatewayTestClient", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* UDP6, DTLS6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "GatewayTestClient", // ClientId
"ff1e:feed:caca:dead::1", // Multicast group IP
"wlp4s0", // Network Interface
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "GatewayTestClient", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
/*------------------------------------------------------
* Client Configuration (theMqcon)
*------------------------------------------------------*/
MQTTSNCONF = {
60, //KeepAlive [seconds]
MQTTSNCONF = { 60, //KeepAlive [seconds]
true, //Clean session
300, //Sleep duration [seconds]
"", //WillTopic
@@ -78,12 +94,12 @@ const char* topic1 = "ty4tw/topic1";
const char* topic2 = "ty4tw/topic2";
const char* topic3 = "ty4tw/topic3";
const char* topic4 = "ty4tw/topic4";
const char* topic40 = "ty4tw/#";
const char* topic51 = "ty4tw/topic5/1";
const char* topic52 = "ty4tw/topic5/2";
const char* topic53 = "ty4tw/topic5/3";
const char* topic50 = "ty4tw/topic5/+";
/*------------------------------------------------------
* Callback routines for Subscribed Topics
*------------------------------------------------------*/
@@ -112,37 +128,40 @@ int on_Topic03(uint8_t* pload, uint16_t ploadlen)
return 0;
}
int on_TopicWildcard(uint8_t* pload, uint16_t ploadlen)
{
DISPLAY("\n\nNew callback recv TopicWildcard\n");
pload[ploadlen - 1] = 0; // set null terminator
DISPLAY("Payload -->%s <--\n\n", pload);
return 0;
}
/*------------------------------------------------------
* A Link list of Callback routines and Topics
*------------------------------------------------------*/
SUBSCRIBE_LIST = {// e.g. SUB(TopicType, topicName, TopicId, callback, QoSx),
SUBSCRIBE_LIST =
{ // e.g. SUB(TopicType, topicName, TopicId, callback, QoSx),
SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic1, 0, on_Topic01, QoS1),
SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic2, 0, on_Topic02, QoS1),
END_OF_SUBSCRIBE_LIST
};
/*------------------------------------------------------
* Test functions
*------------------------------------------------------*/
void subscribePredefTopic1(void)
{
SUBSCRIBE(1, on_Topic03, QoS1);
SUBSCRIBE_PREDEF(1, on_Topic03, QoS1);
}
void publishTopic1(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/Topic1\" \n");
sprintf(payload, "publish \"ty4tw/topic1\" \n");
PUBLISH(topic1, (uint8_t* )payload, strlen(payload), QoS0);
}
void subscribeTopic10(void)
{
SUBSCRIBE(10, on_Topic02, QoS1);
}
void publishTopic2(void)
{
char payload[300];
@@ -150,6 +169,22 @@ void publishTopic2(void)
PUBLISH(topic2, (uint8_t* )payload, strlen(payload), QoS1);
}
void publishTopic4(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/topic40\" \n");
PUBLISH(topic4, (uint8_t* )payload, strlen(payload), QoS1);
}
void subscribeTopic10(void)
{
SUBSCRIBE_PREDEF(10, on_Topic02, QoS1);
}
void subscribeWildcardTopic(void)
{
SUBSCRIBE(topic50, on_TopicWildcard, QoS1);
}
void unsubscribe(void)
@@ -180,41 +215,70 @@ void asleep(void)
DISCONNECT(theMqcon.sleepDuration);
}
void onconnect(void)
{
ONCONNECT();
}
void connect(void)
{
CONNECT();
}
void DisableAutoPingreq(void)
{
SetAutoPingReqMode(false);
}
void CleanSessionOff(void)
{
SetCleanSession(false);
}
/*------------------------------------------------------
* A List of Test functions is valid in case of
* line 23 of LMqttsnClientApp.h is commented out.
* //#define CLIENT_MODE
*------------------------------------------------------*/
TEST_LIST = {// e.g. TEST( Label, Test),
TEST("Step0:Subscribe predef topic1", subscribePredefTopic1),
TEST("Step1:Publish topic1", publishTopic1),
TEST("Step2:Publish topic2", publishTopic2),
TEST("Step3:Subscribe PreDefined topic10. ID is not defined.", subscribeTopic10),
TEST_LIST =
{ // e.g. TEST( Label, Test),
TEST("Step0:Connect", connect),
TEST("Step1:Subscribe list", onconnect),
TEST("Step2:Subscribe predef topic1", subscribePredefTopic1),
TEST("Step3:Publish topic1", publishTopic1),
TEST("Step4:Publish topic2", publishTopic2),
TEST("Step5:Unsubscribe topic2", unsubscribe),
TEST("Step5:Subscribe PreDefined topic10. ID is not defined.", subscribeTopic10),
TEST("Step6:Publish topic2", publishTopic2),
TEST("Step7:subscribe again", subscribechangeCallback),
TEST("Step7:Unsubscribe topic2", unsubscribe),
TEST("Step8:Publish topic2", publishTopic2),
TEST("Step9:Sleep ", asleep),
TEST("Step10:Publish topic1", publishTopic1),
TEST("Step11:Disconnect", disconnect),
TEST("Step9:subscribe again", subscribechangeCallback),
TEST("Step10:Publish topic2", publishTopic2),
TEST("Step11:Sleep ", asleep),
TEST("Step12:Publish topic1", publishTopic1),
TEST("Step13:Disconnect", disconnect),
TEST("Step14:Publish topic2", publishTopic1),
TEST("Step15:Connect", connect),
TEST("Step16:Publish topic2", publishTopic2),
TEST("Step17:Auto Pingreq mode off", DisableAutoPingreq),
TEST("Step18:Publish topic2", publishTopic1),
TEST("Step19:Disconnect", disconnect),
END_OF_TEST_LIST
};
/*------------------------------------------------------
* List of tasks is valid in case of line23 of
* LMqttsnClientApp.h is uncommented.
* #define CLIENT_MODE
*------------------------------------------------------*/
TASK_LIST = {// e.g. TASK( task, executing duration in second),
TASK_LIST =
{ // e.g. TASK( task, executing duration in second),
TASK(publishTopic1, 4),// publishTopic1() is executed every 4 seconds
TASK(publishTopic2, 7),// publishTopic2() is executed every 7 seconds
END_OF_TASK_LIST
};
/*------------------------------------------------------
* Initialize function
*------------------------------------------------------*/
@@ -223,5 +287,4 @@ void setup(void)
SetForwarderMode(false);
}
/***************** END OF PROGRAM ********************/

View File

@@ -57,6 +57,8 @@ LGwProxy::LGwProxy()
_initialized = 0;
_isForwarderMode = false;
_isQoSMinus1Mode = false;
_isPingReqMode = true;
_isAutoConnectMode = true;
}
LGwProxy::~LGwProxy()
@@ -64,16 +66,20 @@ LGwProxy::~LGwProxy()
_topicTbl.clearTopic();
}
void LGwProxy::initialize(LUdpConfig netconf, LMqttsnConfig mqconf)
void LGwProxy::initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf)
{
_network.initialize(netconf);
_clientId = netconf.clientId;
_willTopic = mqconf.willTopic;
_willMsg = mqconf.willMsg;
_qosWill = mqconf.willQos;
_retainWill = mqconf.willRetain;
_cleanSession = mqconf.cleanSession;
_tkeepAlive = mqconf.keepAlive;
if (_network.initialize(netconf) == false)
{
DISPLAY("Can't open SensorNetwork\n");
exit(-1);
}
_clientId = netconf->clientId;
_willTopic = mqconf->willTopic;
_willMsg = mqconf->willMsg;
_qosWill = mqconf->willQos;
_retainWill = mqconf->willRetain;
_cleanSession = mqconf->cleanSession;
_tkeepAlive = mqconf->keepAlive;
_initialized = 1;
}
@@ -85,6 +91,12 @@ void LGwProxy::connect()
{
pos = _msg;
if (!_network.isBroadcastable() && _status == GW_LOST)
{
_status = GW_CONNECTING;
continue;
}
if (_status == GW_LOST)
{
@@ -188,7 +200,24 @@ int LGwProxy::getConnectResponce(void)
{
_network.setGwAddress();
_gwId = _mqttsnMsg[1];
#if defined(DTLS) || defined(DTLS6)
for (int i = 0; i < MQTTSN_RETRY_COUNT; i++)
{
if (_network.sslConnect() > 0)
{
_status = GW_CONNECTING;
DISPLAY("\033[0m\033[0;32m\n\nLGwProxy::getConnectResponce DTLS connection established.\033[0m\033[0;37m\n\n");
break;
}
else
{
DISPLAY("\033[0m\033[0;32m\n\nLGwProxy::getConnectResponce DTLS connection failed.\033[0m\033[0;37m\n\n");
}
}
#else
_status = GW_CONNECTING;
#endif
}
else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLTOPICREQ && _status == GW_WAIT_WILLTOPICREQ)
{
@@ -230,11 +259,14 @@ int LGwProxy::getConnectResponce(void)
}
void LGwProxy::reconnect(void)
{
if (_isAutoConnectMode)
{
D_MQTTLOG("...Gateway reconnect\r\n");
_status = GW_DISCONNECTED;
connect();
}
}
void LGwProxy::disconnect(uint16_t secs)
{
@@ -395,7 +427,7 @@ int LGwProxy::getMessage(void)
}
else if (_mqttsnMsg[0] == MQTTSN_TYPE_DISCONNECT)
{
_status = GW_LOST;
_status = GW_DISCONNECTED;
_gwAliveTimer.stop();
_keepAliveTimer.stop();
}
@@ -586,7 +618,7 @@ uint16_t LGwProxy::getNextMsgId(void)
void LGwProxy::checkPingReq(void)
{
if ( _isQoSMinus1Mode )
if (_isQoSMinus1Mode || _isPingReqMode == false)
{
return;
}
@@ -671,3 +703,23 @@ void LGwProxy::setQoSMinus1Mode(bool valid)
{
_isQoSMinus1Mode = valid;
}
void LGwProxy::setPingReqMode(bool valid)
{
_isPingReqMode = valid;
}
void LGwProxy::setAutoConnectMode(bool valid)
{
_isAutoConnectMode = valid;
}
void LGwProxy::setSessionMode(bool valid)
{
_cleanSession = valid;
}
uint8_t LGwProxy::getStatus(void)
{
return _status;
}

View File

@@ -23,6 +23,10 @@
#include "LMqttsnClientApp.h"
#include "LNetworkUdp.h"
#include "LNetworkUdp6.h"
#include "LNetworkRfcomm.h"
#include "LNetworkDtls.h"
#include "LNetworkDtls6.h"
#include "LRegisterManager.h"
#include "LTimer.h"
#include "LTopicTable.h"
@@ -42,6 +46,7 @@ using namespace std;
#define GW_SLEEPING 10
#define GW_DISCONNECTED 11
#define GW_SLEPT 12
#define SSL_CONNECTING 13
#define GW_WAIT_PINGRESP 1
@@ -54,7 +59,7 @@ public:
LGwProxy();
~LGwProxy();
void initialize(LUdpConfig netconf, LMqttsnConfig mqconf);
void initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf);
void connect(void);
void disconnect(uint16_t sec = 0);
int getMessage(void);
@@ -67,6 +72,9 @@ public:
void setAdvertiseDuration(uint16_t duration);
void setForwarderMode(bool valid);
void setQoSMinus1Mode(bool valid);
void setPingReqMode(bool valid);
void setAutoConnectMode(bool valid);
void setSessionMode(bool valid);
void reconnect(void);
int writeMsg(const uint8_t* msg);
void setPingReqTimer(void);
@@ -74,6 +82,7 @@ public:
LTopicTable* getTopicTable(void);
LRegisterManager* getRegisterManager(void);
const char* getClientId(void);
uint8_t getStatus(void);
private:
int readMsg(void);
void writeGwMsg(void);
@@ -111,6 +120,8 @@ private:
uint16_t _tWake;
bool _isForwarderMode;
bool _isQoSMinus1Mode;
bool _isPingReqMode;
bool _isAutoConnectMode;
char _msg[MQTTSN_MAX_MSG_LENGTH + 1];
};

View File

@@ -29,7 +29,7 @@ extern TaskList theTaskList[];
extern TestList theTestList[];
extern OnPublishList theOnPublishList[];
extern MQTTSNCONF;
extern UDPCONF;
extern SENSORNET_CONFIG_t theNetcon;
extern void setup(void);
/*=====================================
@@ -50,7 +50,20 @@ int main(int argc, char** argv)
#ifndef CLIENT_MODE
char c = 0;
printf("\n%s", PAHO_COPYRIGHT4);
printf("\n%s\n", PAHO_COPYRIGHT0);
printf("\n%s", PAHO_COPYRIGHT0);
#if defined(UDP)
printf("UDP ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo);
#elif defined(UDP6)
printf("UDP6 ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo);
#elif defined(DTLS)
printf("DTLS ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo);
#elif defined(DTLS6)
printf("DTLS6 ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo);
#elif defined(RFCOMM)
printf("RFCOMM ClientId:%s channel:%d\n", theNetcon.clientId, theNetcon.channel);
#else
printf("\n");
#endif
printf("%s\n", PAHO_COPYRIGHT1);
printf("%s\n", PAHO_COPYRIGHT2);
printf(" *\n%s\n", PAHO_COPYRIGHT3);
@@ -77,11 +90,13 @@ int main(int argc, char** argv)
break;
}
}
theClient->setAutoConnectMode(false);
theClient->getPublishManager()->setAutoConnectMode(false);
#endif
setup();
theClient->addTask(theClientMode);
theClient->initialize( theNetcon, theMqcon);
theClient->initialize( &theNetcon, &theMqcon);
do
{
theClient->run();
@@ -98,7 +113,7 @@ int main(int argc, char** argv)
======================================*/
LMqttsnClient::LMqttsnClient()
{
_isAutoConnect = true;
}
LMqttsnClient::~LMqttsnClient()
@@ -106,10 +121,10 @@ LMqttsnClient::~LMqttsnClient()
}
void LMqttsnClient::initialize(LUdpConfig netconf, LMqttsnConfig mqconf)
void LMqttsnClient::initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf)
{
_gwProxy.initialize(netconf, mqconf);
setSleepDuration(mqconf.sleepDuration);
setSleepDuration(mqconf->sleepDuration);
}
void LMqttsnClient::addTask(bool clientMode)
@@ -183,9 +198,10 @@ void LMqttsnClient::subscribe(const char* topicName, TopicCallback onPublish, ui
_subMgr.subscribe(topicName, onPublish, qos);
}
void LMqttsnClient::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos)
void LMqttsnClient::subscribePredefinedId(uint16_t topicId, TopicCallback onPublish,
uint8_t qos)
{
_subMgr.subscribe(topicId, onPublish, qos);
_subMgr.subscribePredefinedId(topicId, onPublish, qos);
}
void LMqttsnClient::unsubscribe(const char* topicName)
@@ -204,11 +220,21 @@ void LMqttsnClient::disconnect(uint16_t sleepInSecs)
}
void LMqttsnClient::run()
{
if (_isAutoConnect)
{
_gwProxy.connect();
}
_taskMgr.run();
}
void LMqttsnClient::setAutoConnectMode(uint8_t flg)
{
_isAutoConnect = flg;
_pubMgr.setAutoConnectMode(flg);
_gwProxy.setAutoConnectMode(flg);
}
void LMqttsnClient::setSleepMode(uint32_t duration)
{
// ToDo: set WDT and sleep mode
@@ -226,9 +252,12 @@ void LMqttsnClient::setSleepDuration(uint32_t duration)
}
void LMqttsnClient::onConnect(void)
{
if (_isAutoConnect)
{
_subMgr.onConnect();
}
}
const char* LMqttsnClient::getClientId(void)
{

View File

@@ -54,15 +54,16 @@ public:
void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false);
void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false);
void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos);
void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos);
void subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos);
void unsubscribe(const char* topicName);
void unsubscribe(const uint16_t topicId);
void disconnect(uint16_t sleepInSecs);
void initialize(LUdpConfig netconf, LMqttsnConfig mqconf);
void initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf);
void run(void);
void addTask(bool test);
void setSleepDuration(uint32_t duration);
void setSleepMode(uint32_t duration);
void setAutoConnectMode(uint8_t flg);
void sleep(void);
const char* getClientId(void);
uint16_t getTopicId(const char* topicName);
@@ -78,6 +79,7 @@ private:
LSubscribeManager _subMgr;
LGwProxy _gwProxy;
uint32_t _sleepDuration;
uint8_t _isAutoConnect;
};

View File

@@ -17,17 +17,17 @@
#ifndef MQTTSNCLIENTAPP_H_
#define MQTTSNCLIENTAPP_H_
/*======================================
* Program mode Flag
======================================*/
//#define CLIENT_MODE
/*======================================
* Debug Flag
======================================*/
//#define DEBUG_NW
//#define DEBUG_MQTTSN
/*======================================
* Program mode Flag
======================================*/
//#define CLIENT_MODE
/****************************************
MQTT-SN Parameters
*****************************************/
@@ -55,7 +55,8 @@ typedef signed int int32_t;
Application config structures
*****************************************/
struct LMqttsnConfig{
struct LMqttsnConfig
{
uint16_t keepAlive;
bool cleanSession;
uint32_t sleepDuration;
@@ -65,13 +66,30 @@ struct LMqttsnConfig{
bool willRetain;
};
struct LUdpConfig{
struct LUdpConfig
{
const char* clientId;
uint8_t ipAddress[4];
uint16_t gPortNo;
uint16_t uPortNo;
};
struct LUdp6Config
{
const char* clientId;
const char* ipAddress;
const char *interface;
uint16_t gPortNo;
uint16_t uPortNo;
};
struct LRfcommConfig
{
const char* clientId;
const char* gwAddress;
uint8_t channel;
};
typedef enum
{
@@ -85,13 +103,50 @@ typedef enum
MACROs for Application
=======================================*/
#define MQTTSN_CONFIG MqttsnConfig theMqttsnConfig
#define NETWORK_CONFIG UdpConfig theNetworkConfig
#define MQTTSNCONF LMqttsnConfig theMqcon
#if defined(UDP)
#define UDPCONF LUdpConfig theNetcon
#define UDP6CONF LUdp6Config theU6Conf
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdpConfig
#elif defined(UDP6)
#define UDP6CONF LUdp6Config theNetcon
#define UDPCONF LUdpConfig theUConf
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdp6Config
#elif defined(RFCOMM)
#define RFCOMMCONF LRfcommConfig theNetcon
#define UDPCONF LUdpConfig theUConf
#define UDP6CONF LUdp6Config theU6Conf
#define SENSORNET_CONFIG_t LRfcommConfig
#elif defined(DTLS)
#define UDPCONF LUdpConfig theNetcon
#define UDP6CONF LUdp6Config theU6Conf
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdpConfig
#elif defined(DTLS6)
#define UDPCONF LUdpConfig theUConf
#define UDP6CONF LUdp6Config theNetcon
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdp6Config
#else
#error "UDP, UDP6, DTLS, DTLS6 or RFCOMM is not defined in LMqttsnClientApp.h"
#endif
#define CONNECT(...) theClient->getGwProxy()->connect(__VA_ARGS__)
#define PUBLISH(...) theClient->publish(__VA_ARGS__)
#define SUBSCRIBE(...) theClient->subscribe(__VA_ARGS__)
#define SUBSCRIBE_PREDEF(...) theClient->subscribePredefinedId(__VA_ARGS__)
#define UNSUBSCRIBE(...) theClient->unsubscribe(__VA_ARGS__)
#define DISCONNECT(...) theClient->disconnect(__VA_ARGS__)
#define ONCONNECT() theClient->getSubscribeManager()->onConnect()
#define TASK_LIST TaskList theTaskList[]
#define TASK(...) {__VA_ARGS__, 0, 0}
@@ -102,11 +157,13 @@ typedef enum
#define SUBSCRIBE_LIST OnPublishList theOnPublishList[]
#define SUB(...) {__VA_ARGS__}
#define END_OF_SUBSCRIBE_LIST {MQTTSN_TOPIC_TYPE_NORMAL,0,0,0, 0}
#define UDPCONF LUdpConfig theNetcon
#define MQTTSNCONF LMqttsnConfig theMqcon
#define SetForwarderMode(...) theClient->getGwProxy()->setForwarderMode(__VA_ARGS__)
#define SetQoSMinus1Mode(...) theClient->getGwProxy()->setQoSMinus1Mode(__VA_ARGS__)
#define SetAutoConnectMode(...) theClient->setAutoConnectMode(__VA_ARGS__)
#define SetAutoPingReqMode(...) theClient->getGwProxy()->setPingReqMode(__VA_ARGS__)
#define SetCleanSession(...) theClient->getGwProxy()->setSessionMode(__VA_ARGS__)
#ifdef CLIENT_MODE
#define DISPLAY(...)
#define PROMPT(...)
@@ -195,11 +252,11 @@ typedef enum
/*=================================
* Starting prompt
==================================*/
#define TESTER_VERSION " * Version: 2.0.0"
#define TESTER_VERSION " * Version: 2.1.0"
#define PAHO_COPYRIGHT0 " * MQTT-SN Gateway Tester"
#define PAHO_COPYRIGHT0 " * "
#define PAHO_COPYRIGHT1 " * Part of Project Paho in Eclipse"
#define PAHO_COPYRIGHT2 " * (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)"
#define PAHO_COPYRIGHT2 " * (https://github.com/eclipse/paho.mqtt-sn.embedded-c.git)"
#define PAHO_COPYRIGHT3 " * Author : Tomoaki YAMAGUCHI"
#define PAHO_COPYRIGHT4 " ***************************************************************************"

View File

@@ -0,0 +1,544 @@
/**************************************************************************************
* 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
**************************************************************************************/
#ifdef DTLS
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "LMqttsnClientApp.h"
#include "LNetworkDtls.h"
#include "LTimer.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t* pos);
extern uint32_t getUint32(const uint8_t* pos);
extern LScreen* theScreen;
extern bool theClientMode;
/* Certificate verification. Returns 1 if trusted, else 0 */
int verify_cert(int ok, X509_STORE_CTX *ctx);
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork()
{
_sleepflg = false;
resetGwAddress();
}
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
{
return LDtlsPort::multicast(xmitData, (uint32_t) dataLen);
}
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
{
return LDtlsPort::unicast(xmitData, dataLen);
}
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
uint16_t recvLen = 0;
if (checkRecvBuf())
{
recvLen = LDtlsPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
if (_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo))
{
return 0;
}
if (recvLen < 0)
{
*len = recvLen;
return 0;
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}
else
{
*len = _rxDataBuf[0];
}
return _rxDataBuf;
}
}
return 0;
}
void LNetwork::setGwAddress(void)
{
_gwPortNo = _portNo;
_gwIpAddress = _ipAddress;
}
void LNetwork::resetGwAddress(void)
{
_gwIpAddress = 0;
_gwPortNo = 0;
}
bool LNetwork::initialize(LUdpConfig *config)
{
return LDtlsPort::open(config);
}
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return true;
}
int LNetwork::sslConnect(void)
{
return LDtlsPort::sslConnect(_gwIpAddress, _gwPortNo);
}
/*=========================================
Class DtlsPort
=========================================*/
LDtlsPort::LDtlsPort()
{
_disconReq = false;
_sockfdMcast = 0;
_sockfdSsl = 0;
_castStat = 0;
}
LDtlsPort::~LDtlsPort()
{
close();
}
void LDtlsPort::close()
{
if (_sockfdMcast > 0)
{
::close(_sockfdMcast);
_sockfdMcast = 0;
if (_sockfdSsl > 0)
{
::close(_sockfdSsl);
_sockfdSsl = 0;
}
}
}
bool LDtlsPort::open(LUdpConfig *config)
{
char errmsg[256];
int optval = 0;
uint8_t sav = config->ipAddress[3];
config->ipAddress[3] = config->ipAddress[0];
config->ipAddress[0] = sav;
sav = config->ipAddress[2];
config->ipAddress[2] = config->ipAddress[1];
config->ipAddress[1] = sav;
_gIpAddr = getUint32((const uint8_t*) config->ipAddress);
_gPortNo = htons(config->gPortNo);
_uPortNo = htons(config->uPortNo);
if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0)
{
return false;
}
SSL_load_error_strings();
SSL_library_init();
_ctx = SSL_CTX_new(DTLS_client_method());
if (_ctx == 0)
{
ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg));
DISPLAY("SSL_CTX_new() %s\n", errmsg);
return false;
}
/* Client certification and cookie are not required */
SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_cert);
/* setup Multicast socket */
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, 0);
if (_sockfdMcast < 0)
{
return false;
}
struct sockaddr_in addrm;
addrm.sin_family = AF_INET;
addrm.sin_port = _gPortNo;
addrm.sin_addr.s_addr = INADDR_ANY;
optval = 1;
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (::bind(_sockfdMcast, (struct sockaddr*) &addrm, sizeof(addrm)) < 0)
{
return false;
}
optval = 1;
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in LDtlsPort::open\033[0m\033[0;37m\n");
close();
return false;
}
ip_mreq mreq;
mreq.imr_interface.s_addr = INADDR_ANY;
mreq.imr_multiaddr.s_addr = _gIpAddr;
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in LDtlsPort::open\033[0m\033[0;37m\n");
close();
return false;
}
return true;
}
bool LDtlsPort::isUnicast()
{
return (_castStat == STAT_UNICAST);
}
int LDtlsPort::unicast(const uint8_t *buf, uint32_t length)
{
int status = SSL_write(_ssl, buf, length);
if (status <= 0)
{
int rc = 0;
SSL_get_error(_ssl, rc);
DISPLAY("errno == %d in LDtlsPort::unicast\n", rc);
}
else
{
D_NWLOG("sendto gateway via DTLS ");
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34msendto the gateway via SSL ");
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
int LDtlsPort::multicast(const uint8_t *buf, uint32_t length)
{
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = _gPortNo;
dest.sin_addr.s_addr = _gIpAddr;
int status = ::sendto(_sockfdMcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
if (status < 0)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtlsPort::multicast\033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno == %d in LDtlsPort::multicast\033[0m\033[0;37m\n", errno);
return errno;
}
else
{
D_NWLOG("sendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo));
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
DISPLAY(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo));
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
}
bool LDtlsPort::checkRecvBuf()
{
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 50000; // 50 msec
uint8_t buf[2];
fd_set recvfds;
int maxSock = 0;
FD_ZERO(&recvfds);
if (_sockfdMcast)
{
FD_SET(_sockfdMcast, &recvfds);
}
if (_sockfdSsl)
{
FD_SET(_sockfdSsl, &recvfds);
}
if (_sockfdMcast > _sockfdSsl)
{
maxSock = _sockfdMcast;
}
else
{
maxSock = _sockfdSsl;
}
select(maxSock + 1, &recvfds, 0, 0, &timeout);
if (FD_ISSET(_sockfdMcast, &recvfds))
{
if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_MULTICAST;
return true;
}
}
else if (FD_ISSET(_sockfdSsl, &recvfds))
{
if (::recv(_sockfdSsl, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_SSL;
return true;
}
}
_castStat = STAT_NONE;
return false;
}
int LDtlsPort::recv(uint8_t *buf, uint16_t len, bool flg, uint32_t *ipAddressPtr, in_port_t *portPtr)
{
int flags = flg ? MSG_DONTWAIT : 0;
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
}
int LDtlsPort::recvfrom(uint8_t *buf, uint16_t length, int flags, uint32_t *ipAddressPtr, in_port_t *portPtr)
{
struct sockaddr_in sender;
int status = 0;
socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
if (_castStat == STAT_SSL)
{
D_NWLOG("Ucast ");
if (SSL_read(_ssl, buf, length) == 0)
{
return 0;
}
}
else if (_castStat == STAT_MULTICAST)
{
D_NWLOG("Mcast ");
status = ::recvfrom(_sockfdMcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
}
else
{
return 0;
}
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtlsPort::recvfrom \033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno == %d in LDtlsPort::recvfrom \033[0m\033[0;37m\n", errno);
}
else if (status > 0)
{
*ipAddressPtr = sender.sin_addr.s_addr;
*portPtr = sender.sin_port;
D_NWLOG("recved %-15s:%-6u", inet_ntoa(sender.sin_addr), ntohs(*portPtr));
for (uint16_t i = 0; i < status; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", inet_ntoa(sender.sin_addr), ntohs(*portPtr));
pos = strlen(sbuf);
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
else
{
return 0;
}
return status;
}
int LDtlsPort::sslConnect(uint32_t ipAddress, in_port_t portNo)
{
int reuse = 1;
if (_ssl != 0)
{
D_NWLOG("LDtlsPort::sslConnect SSL exists.\n");
SSL_shutdown(_ssl);
SSL_free(_ssl);
_sockfdSsl = 0;
_ssl = 0;
}
if (_sockfdSsl > 0)
{
D_NWLOG("LDtlsPort::sslConnect socket exists.\n");
::close(_sockfdSsl);
}
_sockfdSsl = socket(AF_INET, SOCK_DGRAM, 0);
if (_sockfdSsl < 0)
{
D_NWLOG("LDtlsPort::sslConnect Can't create a socket\n");
return -1;
}
setsockopt(_sockfdSsl, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = _uPortNo;
addr.sin_addr.s_addr = INADDR_ANY;
if (::bind(_sockfdSsl, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{
::close(_sockfdSsl);
_sockfdSsl = 0;
D_NWLOG("LDtlsPort::sslConnect Can't bind a socket\n");
return -1;
}
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = portNo;
dest.sin_addr.s_addr = ipAddress;
int rc = 0;
errno = 0;
BIO *cbio = BIO_new_dgram(_sockfdSsl, BIO_NOCLOSE);
connect(_sockfdSsl, (sockaddr*) &dest, sizeof(sockaddr_in));
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest);
_ssl = SSL_new(_ctx);
SSL_set_bio(_ssl, cbio, cbio);
D_NWLOG("LDtlsPort::sslConnect connect to %-15s:%-6u\n", inet_ntoa(dest.sin_addr), htons(dest.sin_port));
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
int stat = SSL_connect(_ssl);
if (stat != 1)
{
rc = -1;
D_NWLOG("SSL fail to connect\n");
}
else
{
rc = 1;
D_NWLOG("SSL connected\n");
}
return rc;
}
int verify_cert(int ok, X509_STORE_CTX *ctx)
{
return 1;
}
#endif

View File

@@ -0,0 +1,118 @@
/**************************************************************************************
* 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 NETWORKDTLS_H_
#define NETWORKDTLS_H_
#ifdef DTLS
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
using namespace std;
namespace linuxAsyncClient {
#define STAT_NONE 0
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
#define STAT_SSL 3
/*========================================
Class LDtlsPort
=======================================*/
class LDtlsPort
{
friend class LNetwork;
public:
LDtlsPort();
virtual ~LDtlsPort();
bool open(LUdpConfig* config);
int unicast(const uint8_t *buf, uint32_t length);
int multicast( const uint8_t* buf, uint32_t length );
int recv(uint8_t* buf, uint16_t len, bool nonblock, uint32_t* ipaddress, in_port_t* port );
int recv(uint8_t* buf, int flags);
bool checkRecvBuf();
bool isUnicast();
SSL* getSSL(void);
int sslConnect(uint32_t ipAddress, in_port_t port);
private:
void close();
int recvfrom ( uint8_t* buf, uint16_t len, int flags, uint32_t* ipaddress, in_port_t* port );
int _sockfdMcast;
int _sockfdSsl;
SSL_CTX *_ctx;
SSL *_ssl;
in_port_t _gPortNo;
in_port_t _uPortNo;
uint32_t _gIpAddr;
uint8_t _castStat;
bool _disconReq;
};
#define NO_ERROR 0
#define PACKET_EXCEEDS_LENGTH 1
/*===========================================
Class Network
============================================*/
class LNetwork: public LDtlsPort
{
public:
LNetwork();
~LNetwork();
int broadcast(const uint8_t* payload, uint16_t payloadLen);
int unicast(const uint8_t* payload, uint16_t payloadLen);
void setGwAddress(void);
void resetGwAddress(void);
bool initialize(LUdpConfig* config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
int sslConnect(void);
private:
void setSleep();
int readApiFrame(void);
uint32_t _gwIpAddress;
uint32_t _ipAddress;
in_port_t _gwPortNo;
in_port_t _portNo;
int _returnCode;
bool _sleepflg;
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
};
} /* end of namespace */
#endif /* DTLS */
#endif /* NETWORKDTLS_H_ */

View File

@@ -0,0 +1,586 @@
/**************************************************************************************
* Copyright (c) 2021, 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
**************************************************************************************/
#ifdef DTLS6
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <net/if.h>
#include <termios.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <poll.h>
#include "LMqttsnClientApp.h"
#include "LNetworkDtls6.h"
#include "LTimer.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t *pos);
extern uint32_t getUint32(const uint8_t *pos);
extern LScreen *theScreen;
extern bool theClientMode;
/* Certificate verification. Returns 1 if trusted, else 0 */
int verify_cert(int ok, X509_STORE_CTX *ctx);
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork()
{
_sleepflg = false;
resetGwAddress();
}
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
{
return LDtls6Port::multicast(xmitData, (uint32_t) dataLen);
}
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
{
return LDtls6Port::unicast(xmitData, dataLen);
}
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
if (checkRecvBuf())
{
uint16_t recvLen = LDtls6Port::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
int addrFlg = memcmp(_ipAddress.s6_addr, _gwIpAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
if (isUnicast() && addrFlg && (_portNo != _gwPortNo))
{
return 0;
}
if (recvLen < 0)
{
*len = recvLen;
return 0;
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}
else
{
*len = _rxDataBuf[0];
}
return _rxDataBuf;
}
}
return 0;
}
void LNetwork::setGwAddress(void)
{
_gwPortNo = _portNo;
memcpy(&_gwIpAddress.s6_addr, &_ipAddress.s6_addr, sizeof(_ipAddress.s6_addr));
}
void LNetwork::resetGwAddress(void)
{
memset(&_gwIpAddress, 0, sizeof(_gwIpAddress));
_gwPortNo = 0;
}
bool LNetwork::initialize(LUdp6Config *config)
{
return LDtls6Port::open(config);
}
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return true;
}
int LNetwork::sslConnect(void)
{
return LDtls6Port::sslConnect(_gwIpAddress, _gwPortNo);
}
/*=========================================
Class Dtls6Port
=========================================*/
LDtls6Port::LDtls6Port()
{
_disconReq = false;
_castStat = STAT_NONE;
_ifIndex = 0;
_gIpAddrStr = nullptr;
_sockfdMcast = 0;
_sockfdSsl = 0;
_ctx = nullptr;
_ssl = nullptr;
_gPortNo = _uPortNo = 0;
}
LDtls6Port::~LDtls6Port()
{
close();
if (_gIpAddrStr)
{
free(_gIpAddrStr);
}
}
void LDtls6Port::close()
{
if (_sockfdMcast > 0)
{
::close(_sockfdMcast);
_sockfdMcast = 0;
if (_sockfdSsl > 0)
{
::close(_sockfdSsl);
_sockfdSsl = 0;
}
}
}
bool LDtls6Port::open(LUdp6Config *config)
{
int optval = 1;
sockaddr_in6 addr6;
char errmsg[256];
_gPortNo = htons(config->gPortNo);
_uPortNo = htons(config->uPortNo);
if (_gPortNo == 0 || _uPortNo == 0)
{
return false;
}
SSL_load_error_strings();
SSL_library_init();
_ctx = SSL_CTX_new(DTLS_client_method());
if (_ctx == 0)
{
ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg));
DISPLAY("SSL_CTX_new() %s\n", errmsg);
return false;
}
/* Client certification and cookie are not required */
SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_cert);
if (strlen(config->interface) > 0)
{
_ifIndex = if_nametoindex(config->interface);
_interfaceName = config->interface;
}
/* create a multicast socket */
_sockfdMcast = socket(AF_INET6, SOCK_DGRAM, 0);
if (_sockfdMcast < 0)
{
return false;
}
optval = 1;
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = _gPortNo;
addr6.sin6_addr = in6addr_any;
if (::bind(_sockfdMcast, (sockaddr*) &addr6, sizeof(addr6)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s ::bind() in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
return false;
}
ipv6_mreq addrm;
addrm.ipv6mr_interface = _ifIndex;
inet_pton(AF_INET6, config->ipAddress, &addrm.ipv6mr_multiaddr);
if (setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
optval = 1;
if (setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s IPV6_MULTICAST_LOOP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
_gIpAddr.sin6_family = AF_INET6;
_gIpAddr.sin6_port = _gPortNo;
memcpy(&_gIpAddr.sin6_addr, (const void*) &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr));
_gIpAddrStr = strdup(config->ipAddress);
return true;
}
bool LDtls6Port::isUnicast()
{
return (_castStat == STAT_UNICAST);
}
int LDtls6Port::unicast(const uint8_t *buf, uint32_t length)
{
int status = SSL_write(_ssl, buf, length);
if (status <= 0)
{
int rc = 0;
SSL_get_error(_ssl, rc);
DISPLAY("errno == %d in LDtls6Port::unicast\n", rc);
}
else
{
D_NWLOG("sendto gateway via DTLS6 ");
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34msendto the gateway via SSL ");
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
int LDtls6Port::multicast(const uint8_t *buf, uint32_t length)
{
char sbuf[SCREEN_BUFF_SIZE];
char portStr[8];
sprintf(portStr, "%d", ntohs(_gIpAddr.sin6_port));
int status = ::sendto(_sockfdMcast, buf, length, 0, (sockaddr*) &_gIpAddr, sizeof(_gIpAddr));
if (status < 0)
{
DISPLAY("\033[0m\033[0;31merrno == %d in LDtls6Port::multicast\033[0m\033[0;37m\n", errno);
return errno;
}
else
{
D_NWLOG("multicast to [%s]:%-6s", _gIpAddrStr, portStr);
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
memset(sbuf, 0, SCREEN_BUFF_SIZE);
int pos = 0;
sprintf(sbuf, "\033[0;34mmulticast to [%s]:%-6s", _gIpAddrStr, portStr);
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
}
bool LDtls6Port::checkRecvBuf()
{
timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 50000; // 50 msec
uint8_t buf[2];
fd_set recvfds;
int maxSock = 0;
FD_ZERO(&recvfds);
if (_sockfdMcast)
{
FD_SET(_sockfdMcast, &recvfds);
}
if (_sockfdSsl)
{
FD_SET(_sockfdSsl, &recvfds);
}
if (_sockfdMcast > _sockfdSsl)
{
maxSock = _sockfdMcast;
}
else
{
maxSock = _sockfdSsl;
}
select(maxSock + 1, &recvfds, 0, 0, &timeout);
if (FD_ISSET(_sockfdMcast, &recvfds))
{
if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_MULTICAST;
return true;
}
}
else if (FD_ISSET(_sockfdSsl, &recvfds))
{
if (::recv(_sockfdSsl, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_SSL;
return true;
}
}
_castStat = STAT_NONE;
return false;
}
int LDtls6Port::recv(uint8_t *buf, uint16_t len, bool flg, in6_addr *ipAddressPtr, in_port_t *portPtr)
{
int flags = flg ? MSG_DONTWAIT : 0;
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
}
int LDtls6Port::recvfrom(uint8_t *buf, uint16_t length, int flags, in6_addr *ipAddressPtr, in_port_t *portPtr)
{
sockaddr_in6 sender;
int status = 0;
socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
char addrBuf[INET6_ADDRSTRLEN];
if (_castStat == STAT_SSL)
{
D_NWLOG("Ucast ");
if (SSL_read(_ssl, buf, length) == 0)
{
return 0;
}
}
else if (_castStat == STAT_MULTICAST)
{
D_NWLOG("Mcast ");
status = ::recvfrom(_sockfdMcast, buf, length, flags, (sockaddr*) &sender, &addrlen);
}
else
{
return 0;
}
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtls6Port::recvfrom \033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno == %d in LDtls6Port::recvfrom \033[0m\033[0;37m\n", errno);
}
else if (status > 0)
{
inet_ntop(AF_INET6, &sender.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
memcpy(ipAddressPtr->s6_addr, (const void*) sender.sin6_addr.s6_addr, sizeof(sender.sin6_addr.s6_addr));
*portPtr = sender.sin6_port;
D_NWLOG("recved %-15s:%-6u", addrBuf, htons(*portPtr));
for (uint16_t i = 0; i < status; i++)
{
D_NWLOG(" %02x", *(buf + i));
}D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", addrBuf, htons(*portPtr));
pos = strlen(sbuf);
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
else
{
return 0;
}
return status;
}
int LDtls6Port::sslConnect(in6_addr ipAddress, in_port_t portNo)
{
int optval = 1;
if (_ssl != 0)
{
D_NWLOG("LDtls6Port::sslConnect SSL exists.\n");
SSL_shutdown(_ssl);
SSL_free(_ssl);
_sockfdSsl = 0;
_ssl = 0;
}
if (_sockfdSsl > 0)
{
D_NWLOG("LDtls6Port::sslConnect socket exists.\n");
::close(_sockfdSsl);
}
_sockfdSsl = socket(AF_INET6, SOCK_DGRAM, 0);
if (_sockfdSsl <= 0)
{
D_NWLOG("LDtls6Port::sslConnect Can't create a socket\n");
return -1;
}
optval = 1;
setsockopt(_sockfdSsl, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
setsockopt(_sockfdSsl, SOL_SOCKET, SO_REUSEADDR || SO_REUSEPORT, &optval, sizeof(optval));
if (_ifIndex > 0)
{
#ifdef __APPLE__
setsockopt(_sockfdSsl, IPPROTO_IP, IP_BOUND_IF, &_ifIndex, sizeof(_ifIndex));
#else
setsockopt(_sockfdSsl, SOL_SOCKET, SO_BINDTODEVICE, _interfaceName.c_str(), _interfaceName.size());
#endif
}
sockaddr_in6 addr;
addr.sin6_family = AF_INET6;
addr.sin6_port = _uPortNo;
addr.sin6_addr = in6addr_any;
if (::bind(_sockfdSsl, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{
::close(_sockfdSsl);
D_NWLOG("LDtlsPort::sslConnect Can't bind a socket\n");
return -1;
}
// Destination is a gateway address and portNo
int rc = 0;
sockaddr_in6 dest;
dest.sin6_family = AF_INET6;
dest.sin6_port = portNo;
memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr));
BIO *cbio = BIO_new_dgram(_sockfdSsl, BIO_NOCLOSE);
if (connect(_sockfdSsl, (sockaddr*) &dest, sizeof(sockaddr_in6)) < 0)
{
D_NWLOG("socket can't connect %s\n",strerror(errno));
return -1;
}
if (BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest) <0)
{
D_NWLOG("BIO_ctrl %s\n",strerror(errno));
return -1;
}
_ssl = SSL_new(_ctx);
if (_ssl == nullptr)
{
D_NWLOG("SSL_new %s\n",strerror(errno));
return -1;
}
SSL_set_bio(_ssl, cbio, cbio);
#ifdef DEBUG_NW
char addrBuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &dest.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
D_NWLOG("connect to %-15s:%-6u\n", addrBuf, ntohs(dest.sin6_port));
#endif
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
errno = 0;
int stat = SSL_connect(_ssl);
if (stat != 1)
{
rc = -1;
D_NWLOG("SSL fail to connect %s\n",strerror(errno));
}
else
{
rc = 1;
D_NWLOG("SSL connected\n");
}
return rc;
}
int verify_cert(int ok, X509_STORE_CTX *ctx)
{
return 1;
}
#endif

View File

@@ -0,0 +1,122 @@
/**************************************************************************************
* Copyright (c) 2021, 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 NETWORKDTLS6_H_
#define NETWORKDTLS6_H_
#ifdef DTLS6
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <poll.h>
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
#define STAT_NONE 0
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
#define STAT_SSL 3
using namespace std;
namespace linuxAsyncClient {
/*========================================
Class LDtls6Port
=======================================*/
class LDtls6Port
{
friend class LNetwork;
public:
LDtls6Port();
virtual ~LDtls6Port();
bool open(LUdp6Config* config);
int unicast(const uint8_t *buf, uint32_t length);
int multicast( const uint8_t* buf, uint32_t length );
int recv(uint8_t* buf, uint16_t len, bool nonblock, in6_addr* ipaddress, in_port_t* port );
int recv(uint8_t* buf, int flags);
bool checkRecvBuf();
bool isUnicast();
SSL* getSSL(void);
int sslConnect(in6_addr ipAddress, uint16_t port);
private:
void close();
int recvfrom ( uint8_t* buf, uint16_t len, int flags, in6_addr* ipaddress, in_port_t* port );
int _sockfdMcast;
int _sockfdSsl;
SSL_CTX *_ctx;
SSL *_ssl;
in_port_t _gPortNo;
in_port_t _uPortNo;
sockaddr_in6 _gIpAddr;
char *_gIpAddrStr;
uint32_t _ifIndex;
string _interfaceName;
uint8_t _castStat;
bool _disconReq;
};
#define NO_ERROR 0
#define PACKET_EXCEEDS_LENGTH 1
/*===========================================
Class Network
============================================*/
class LNetwork: public LDtls6Port
{
public:
LNetwork();
~LNetwork();
int broadcast(const uint8_t* payload, uint16_t payloadLen);
int unicast(const uint8_t* payload, uint16_t payloadLen);
void setGwAddress(void);
void resetGwAddress(void);
bool initialize(LUdp6Config* config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
int sslConnect(void);
private:
void setSleep();
int readApiFrame(void);
in6_addr _gwIpAddress;
in6_addr _ipAddress;
in_port_t _gwPortNo;
in_port_t _portNo;
int _returnCode;
bool _sleepflg;
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
};
} /* end of namespace */
#endif /* DTLS6 */
#endif /* NETWORKDTLS6_H_ */

View File

@@ -0,0 +1,286 @@
/**************************************************************************************
* Copyright (c) 2021, 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
**************************************************************************************/
#ifdef RFCOMM
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include "LMqttsnClientApp.h"
#include "LNetworkRfcomm.h"
#include "LTimer.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t* pos);
extern uint32_t getUint32(const uint8_t* pos);
extern LScreen* theScreen;
extern bool theClientMode;
extern LRfcommConfig theNetcon;
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork()
{
_sleepflg = false;
_returnCode = 0;
}
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t* xmitData, uint16_t dataLen)
{
return LRfcommPort::unicast(xmitData, dataLen);
}
int LNetwork::unicast(const uint8_t* xmitData, uint16_t dataLen)
{
return LRfcommPort::unicast(xmitData, dataLen);
}
uint8_t* LNetwork::getMessage(int* len)
{
*len = 0;
if (checkRecvBuf())
{
uint16_t recvLen = LRfcommPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false);
if (recvLen < 0)
{
*len = recvLen;
return 0;
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}
else
{
*len = _rxDataBuf[0];
}
return _rxDataBuf;
}
}
return 0;
}
void LNetwork::setGwAddress(void)
{
}
void LNetwork::setFixedGwAddress(void)
{
_channel = LRfcommPort::_channel;
str2ba( theNetcon.gwAddress, (bdaddr_t*)_gwAddress);
}
bool LNetwork::initialize(LRfcommConfig* config)
{
return LRfcommPort::open(config);
}
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return false;
}
/*=========================================
Class RFCOMM Stack
=========================================*/
LRfcommPort::LRfcommPort()
{
_disconReq = false;
_sockRfcomm = 0;
_channel = 0;
}
LRfcommPort::~LRfcommPort()
{
close();
}
void LRfcommPort::close()
{
if (_sockRfcomm > 0)
{
::close(_sockRfcomm);
_sockRfcomm = 0;
}
}
bool LRfcommPort::open(LRfcommConfig* config)
{
const int reuse = 1;
str2ba(config->gwAddress, (bdaddr_t*)_gwAddress);
_channel = config->channel;
if (_channel == 0 || _gwAddress == 0 )
{
D_NWLOG("\033[0m\033[0;31merror Bluetooth Address in LRfcommPort::open\033[0m\033[0;37m\n");
DISPLAY("\033[0m\033[0;31m\nerror Bluetooth Address in LRfcommPort::open\033[0m\033[0;37m\n");
return false;
}
_sockRfcomm = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if (_sockRfcomm < 0)
{
D_NWLOG("\033[0m\033[0;31merror Can't create socket in LRfcommPort::open\033[0m\033[0;37m\n");
DISPLAY("\033[0m\033[0;31m\nerror Can't create socket in LRfcommPort::open\033[0m\033[0;37m\n");
return false;
}
setsockopt(_sockRfcomm, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
struct sockaddr_rc addru = { 0 };
addru.rc_family = AF_BLUETOOTH;
addru.rc_channel = _channel;
memcpy(&addru.rc_bdaddr, _gwAddress, 6);
char bufgw[30];
ba2str(&addru.rc_bdaddr, bufgw);
DISPLAY("GW MAC = %s RFCOMM CH = %d\n", bufgw, addru.rc_channel);
// connect to server
errno = 0;
int status = connect(_sockRfcomm, (struct sockaddr *) &addru, sizeof(addru));
if (status < 0)
{
D_NWLOG("\033[0m\033[0;31merror = %d Can't connect to GW in LRfcommPort::open\033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merror = %d Can't connect to GW Ble socket in LRfcommPort::open\033[0m\033[0;37m\n",errno);
close();
return false;
}
return true;
}
int LRfcommPort::unicast(const uint8_t* buf, uint32_t length)
{
int status = ::write(_sockRfcomm, buf, length);
if (status < 0)
{
D_NWLOG("errno == %d in LRfcommPort::unicast\n", errno);
DISPLAY("errno == %d in LRfcommPort::unicast\n", errno);
}
else
{
D_NWLOG("sendto %-2d", _channel);
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34msendto %-2dch", _channel);
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
bool LRfcommPort::checkRecvBuf()
{
uint8_t buf[2];
if (::recv(_sockRfcomm, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
return true;
}
return false;
}
int LRfcommPort::recv(uint8_t* buf, uint16_t length, bool flg)
{
int flags = flg ? MSG_DONTWAIT : 0;
int status = ::recv(_sockRfcomm, buf, length, flags);
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno = %d in LRfcommPort::recv \033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno = %d in LRfcommPort::recv \033[0m\033[0;37m\n", errno);
}
else if (status > 0)
{
D_NWLOG("\nrecved ");
for (uint16_t i = 0; i < status; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34mrecved ");
pos = strlen(sbuf);
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
else
{
return 0;
}
return status;
}
#endif

View File

@@ -0,0 +1,102 @@
/**************************************************************************************
* Copyright (c) 2021, 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 NETWORKRFCOMM_H_
#define NETWORKRFCOMM_H_
#ifdef RFCOMM
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <bluetooth/bluetooth.h>
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
using namespace std;
namespace linuxAsyncClient
{
/*========================================
Class LRfcommPort
=======================================*/
class LRfcommPort
{
friend class LNetwork;
public:
LRfcommPort();
virtual ~LRfcommPort();
bool open(LRfcommConfig* config);
int unicast(const uint8_t* buf, uint32_t length);
int recv(uint8_t* buf, uint16_t len, bool nonblock);
bool checkRecvBuf();
bool isUnicast();
private:
void close();
int _sockRfcomm;
uint8_t _gwAddress[6];
uint8_t _channel;
bool _disconReq;
};
#define NO_ERROR 0
#define PACKET_EXCEEDS_LENGTH 1
/*===========================================
Class Network
============================================*/
class LNetwork: public LRfcommPort
{
public:
LNetwork();
~LNetwork();
int broadcast(const uint8_t* payload, uint16_t payloadLen);
int unicast(const uint8_t* payload, uint16_t payloadLen);
void setGwAddress(void);
void resetGwAddress(void);
void setFixedGwAddress(void);
bool initialize(LRfcommConfig* config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
private:
void setSleep();
int readApiFrame(void);
int _returnCode;
bool _sleepflg;
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
};
} /* end of namespace */
#endif /* RFCOMM */
#endif /* NETWORKRFCOM_H_ */

View File

@@ -13,6 +13,7 @@
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifdef UDP
#include <stdio.h>
#include <sys/time.h>
@@ -25,12 +26,11 @@
#include <fcntl.h>
#include <termios.h>
#include "LMqttsnClientApp.h"
#include "LNetworkUdp.h"
#include "LTimer.h"
#include "LScreen.h"
#include "LMqttsnClientApp.h"
using namespace std;
using namespace linuxAsyncClient;
@@ -41,39 +41,51 @@ extern bool theClientMode;
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork(){
LNetwork::LNetwork()
{
_sleepflg = false;
resetGwAddress();
}
LNetwork::~LNetwork(){
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t* xmitData, uint16_t dataLen){
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
{
return LUdpPort::multicast(xmitData, (uint32_t) dataLen);
}
int LNetwork::unicast(const uint8_t* xmitData, uint16_t dataLen){
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
{
return LUdpPort::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo);
}
uint8_t* LNetwork::getMessage(int* len){
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
if (checkRecvBuf()){
if (checkRecvBuf())
{
uint16_t recvLen = LUdpPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
if(_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo)){
if (_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo))
{
return 0;
}
if(recvLen < 0){
if (recvLen < 0)
{
*len = recvLen;
return 0;
}else{
if(_rxDataBuf[0] == 0x01){
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}else{
}
else
{
*len = _rxDataBuf[0];
}
//if(recvLen != *len){
@@ -87,111 +99,125 @@ uint8_t* LNetwork::getMessage(int* len){
return 0;
}
void LNetwork::setGwAddress(void){
void LNetwork::setGwAddress(void)
{
_gwPortNo = _portNo;
_gwIpAddress = _ipAddress;
}
void LNetwork::setFixedGwAddress(void){
void LNetwork::setFixedGwAddress(void)
{
_gwPortNo = LUdpPort::_gPortNo;
_gwIpAddress = LUdpPort::_gIpAddr;
}
void LNetwork::resetGwAddress(void){
void LNetwork::resetGwAddress(void)
{
_gwIpAddress = 0;
_gwPortNo = 0;
}
bool LNetwork::initialize(LUdpConfig config){
bool LNetwork::initialize(LUdpConfig *config)
{
return LUdpPort::open(config);
}
void LNetwork::setSleep(){
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return true;
}
/*=========================================
Class udpStack
=========================================*/
LUdpPort::LUdpPort(){
LUdpPort::LUdpPort()
{
_disconReq = false;
_sockfdUcast = -1;
_sockfdMcast = -1;
_castStat = 0;
}
LUdpPort::~LUdpPort(){
LUdpPort::~LUdpPort()
{
close();
}
void LUdpPort::close(){
if(_sockfdMcast > 0){
void LUdpPort::close()
{
if (_sockfdMcast > 0)
{
::close(_sockfdMcast);
_sockfdMcast = -1;
if(_sockfdUcast > 0){
if (_sockfdUcast > 0)
{
::close(_sockfdUcast);
_sockfdUcast = -1;
}
}
}
bool LUdpPort::open(LUdpConfig config){
const int reuse = 1;
char loopch = 1;
bool LUdpPort::open(LUdpConfig *config)
{
int optval = 0;
uint8_t sav = config.ipAddress[3];
config.ipAddress[3] = config.ipAddress[0];
config.ipAddress[0] = sav;
sav = config.ipAddress[2];
config.ipAddress[2] = config.ipAddress[1];
config.ipAddress[1] = sav;
uint8_t sav = config->ipAddress[3];
config->ipAddress[3] = config->ipAddress[0];
config->ipAddress[0] = sav;
sav = config->ipAddress[2];
config->ipAddress[2] = config->ipAddress[1];
config->ipAddress[1] = sav;
_gPortNo = htons(config.gPortNo);
_gIpAddr = getUint32((const uint8_t*)config.ipAddress);
_uPortNo = htons(config.uPortNo);
_gPortNo = htons(config->gPortNo);
_gIpAddr = getUint32((const uint8_t*) config->ipAddress);
_uPortNo = htons(config->uPortNo);
if( _gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0){
if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0)
{
return false;
}
_sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0);
if (_sockfdUcast < 0){
if (_sockfdUcast < 0)
{
return false;
}
setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
optval = 1;
setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
struct sockaddr_in addr;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = _uPortNo;
addr.sin_addr.s_addr = INADDR_ANY;
if( ::bind ( _sockfdUcast, (struct sockaddr*)&addr, sizeof(addr)) <0){
if (::bind(_sockfdUcast, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s ::bind() to unicast address\033[0m\033[0;37m\n", strerror(errno));
return false;
}
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_sockfdMcast < 0){
if (_sockfdMcast < 0)
{
return false;
}
struct sockaddr_in addrm;
sockaddr_in addrm;
addrm.sin_family = AF_INET;
addrm.sin_port = _gPortNo;
addrm.sin_addr.s_addr = htonl(INADDR_ANY);
addrm.sin_addr.s_addr = INADDR_ANY;
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
optval = 1;
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if( ::bind ( _sockfdMcast, (struct sockaddr*)&addrm, sizeof(addrm)) <0){
return false;
}
if(setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP,(char*)&loopch, sizeof(loopch)) <0 ){
D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n");
DISPLAY("\033[0m\033[0;31m\nerror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n");
close();
if (::bind(_sockfdMcast, (struct sockaddr*) &addrm, sizeof(addrm)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s ::bind() in UdpPort::open\033[0m\033[0;37m\n", strerror(errno));
return false;
}
@@ -199,36 +225,47 @@ bool LUdpPort::open(LUdpConfig config){
mreq.imr_interface.s_addr = INADDR_ANY;
mreq.imr_multiaddr.s_addr = _gIpAddr;
if( setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq) )< 0){
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in UdpPort::open\033[0m\033[0;37m\n");
DISPLAY("\033[0m\033[0;31m\nerror IP_ADD_MEMBERSHIP in UdpPort::open\033[0m\033[0;37m\n");
close();
return false;
}
optval= 1;
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n");
close();
return false;
}
return true;
}
bool LUdpPort::isUnicast(){
bool LUdpPort::isUnicast()
{
return (_castStat == STAT_UNICAST);
}
int LUdpPort::unicast(const uint8_t* buf, uint32_t length, uint32_t ipAddress, uint16_t port ){
int LUdpPort::unicast(const uint8_t *buf, uint32_t length, uint32_t ipAddress, uint16_t port)
{
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = port;
dest.sin_addr.s_addr = ipAddress;
int status = ::sendto(_sockfdUcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
if( status < 0){
if (status < 0)
{
D_NWLOG("errno == %d in UdpPort::unicast\n", errno);
DISPLAY("errno == %d in UdpPort::unicast\n", errno);
}else{
D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(port));
for(uint16_t i = 0; i < length ; i++){
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
else
{
D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(port));
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
} D_NWLOG("\n");
if (!theClientMode)
{
@@ -236,7 +273,8 @@ int LUdpPort::unicast(const uint8_t* buf, uint32_t length, uint32_t ipAddress, u
int pos = 0;
sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(port));
pos = strlen(sbuf);
for(uint16_t i = 0; i < length ; i++){
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
@@ -245,32 +283,32 @@ int LUdpPort::unicast(const uint8_t* buf, uint32_t length, uint32_t ipAddress, u
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
int LUdpPort::multicast( const uint8_t* buf, uint32_t length ){
int LUdpPort::multicast(const uint8_t *buf, uint32_t length)
{
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = _gPortNo;
dest.sin_addr.s_addr = _gIpAddr;
int status = ::sendto(_sockfdMcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
if( status < 0){
if (status < 0)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno);
return errno;
}else{
}
else
{
D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(_gPortNo));
for(uint16_t i = 0; i < length ; i++){
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
DISPLAY(" %02x", *(buf + i));
}
D_NWLOG("\n");
} D_NWLOG("\n");
if (!theClientMode)
{
@@ -278,7 +316,8 @@ int LUdpPort::multicast( const uint8_t* buf, uint32_t length ){
int pos = 0;
sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo));
pos = strlen(sbuf);
for(uint16_t i = 0; i < length ; i++){
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
@@ -294,7 +333,8 @@ int LUdpPort::multicast( const uint8_t* buf, uint32_t length ){
}
bool LUdpPort::checkRecvBuf(){
bool LUdpPort::checkRecvBuf()
{
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 50000; // 50 msec
@@ -307,21 +347,29 @@ bool LUdpPort::checkRecvBuf(){
FD_SET(_sockfdUcast, &recvfds);
FD_SET(_sockfdMcast, &recvfds);
if(_sockfdMcast > _sockfdUcast){
if (_sockfdMcast > _sockfdUcast)
{
maxSock = _sockfdMcast;
}else{
}
else
{
maxSock = _sockfdUcast;
}
select(maxSock + 1, &recvfds, 0, 0, &timeout);
if(FD_ISSET(_sockfdUcast, &recvfds)){
if( ::recv(_sockfdUcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0){
if (FD_ISSET(_sockfdUcast, &recvfds))
{
if (::recv(_sockfdUcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_UNICAST;
return true;
}
}else if(FD_ISSET(_sockfdMcast, &recvfds)){
if( ::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0){
}
else if (FD_ISSET(_sockfdMcast, &recvfds))
{
if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_MULTICAST;
return true;
}
@@ -330,36 +378,47 @@ bool LUdpPort::checkRecvBuf(){
return false;
}
int LUdpPort::recv(uint8_t* buf, uint16_t len, bool flg, uint32_t* ipAddressPtr, uint16_t* portPtr){
int LUdpPort::recv(uint8_t *buf, uint16_t len, bool flg, uint32_t *ipAddressPtr, uint16_t *portPtr)
{
int flags = flg ? MSG_DONTWAIT : 0;
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
}
int LUdpPort::recvfrom (uint8_t* buf, uint16_t length, int flags, uint32_t* ipAddressPtr, uint16_t* portPtr ){
int LUdpPort::recvfrom(uint8_t *buf, uint16_t length, int flags, uint32_t *ipAddressPtr, uint16_t *portPtr)
{
struct sockaddr_in sender;
int status;
socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
if(isUnicast()){
if (isUnicast())
{
D_NWLOG("Ucast ");
status = ::recvfrom(_sockfdUcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
}else if(_castStat == STAT_MULTICAST){
}
else if (_castStat == STAT_MULTICAST)
{
D_NWLOG("Mcast ");
status = ::recvfrom(_sockfdMcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
}else{
}
else
{
return 0;
}
if (status < 0 && errno != EAGAIN) {
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::recvfrom \033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno == %d in UdpPort::recvfrom \033[0m\033[0;37m\n", errno);
}else if(status > 0){
}
else if (status > 0)
{
*ipAddressPtr = sender.sin_addr.s_addr;
*portPtr = sender.sin_port;
D_NWLOG("\nrecved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr));
for(uint16_t i = 0; i < status ; i++){
D_NWLOG("recved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr));
for (uint16_t i = 0; i < status; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
} D_NWLOG("\n");
if (!theClientMode)
{
@@ -367,7 +426,8 @@ int LUdpPort::recvfrom (uint8_t* buf, uint16_t length, int flags, uint32_t* ipAd
int pos = 0;
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", inet_ntoa(sender.sin_addr), htons(*portPtr));
pos = strlen(sbuf);
for(uint16_t i = 0; i < status ; i++){
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
@@ -379,11 +439,13 @@ int LUdpPort::recvfrom (uint8_t* buf, uint16_t length, int flags, uint32_t* ipAd
theScreen->display(sbuf);
}
return status;
}else{
}
else
{
return 0;
}
return status;
}
#endif

View File

@@ -17,6 +17,8 @@
#ifndef NETWORKUDP_H_
#define NETWORKUDP_H_
#ifdef UDP
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
@@ -27,8 +29,6 @@
#include <string>
#include <arpa/inet.h>
#include "LMqttsnClientApp.h"
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
@@ -49,7 +49,7 @@ public:
LUdpPort();
virtual ~LUdpPort();
bool open(LUdpConfig config);
bool open(LUdpConfig* config);
int unicast(const uint8_t* buf, uint32_t length, uint32_t ipaddress, uint16_t port );
int multicast( const uint8_t* buf, uint32_t length );
@@ -87,8 +87,9 @@ public:
void setGwAddress(void);
void resetGwAddress(void);
void setFixedGwAddress(void);
bool initialize(LUdpConfig config);
bool initialize(LUdpConfig* config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
private:
void setSleep();
int readApiFrame(void);
@@ -103,6 +104,6 @@ private:
};
} /* end of namespace */
#endif /* UDP */
#endif /* NETWORKUDP_H_ */

View File

@@ -0,0 +1,433 @@
/**************************************************************************************
* Copyright (c) 2021, 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
**************************************************************************************/
#ifdef UDP6
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <netinet/in.h>
#include <net/if.h>
#include "LMqttsnClientApp.h"
#include "LNetworkUdp6.h"
#include "LTimer.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t *pos);
extern uint32_t getUint32(const uint8_t *pos);
extern LScreen *theScreen;
extern bool theClientMode;
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork()
{
_sleepflg = false;
resetGwAddress();
}
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
{
return LUdp6Port::multicast(xmitData, (uint32_t) dataLen);
}
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
{
return LUdp6Port::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo);
}
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
if (checkRecvBuf())
{
uint16_t recvLen = LUdp6Port::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
int diffAddr = memcmp(_ipAddress.s6_addr, _gwIpAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
if (isUnicast() && diffAddr && (_portNo != _gwPortNo))
{
return 0;
}
if (recvLen < 0)
{
*len = recvLen;
return 0;
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}
else
{
*len = _rxDataBuf[0];
}
return _rxDataBuf;
}
}
return 0;
}
void LNetwork::setGwAddress(void)
{
memcpy(_gwIpAddress.s6_addr, _ipAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
_gwPortNo = _portNo;
}
void LNetwork::resetGwAddress(void)
{
memset(_gwIpAddress.s6_addr, 0, sizeof(_gwIpAddress.s6_addr));
_gwPortNo = 0;
}
bool LNetwork::initialize(LUdp6Config *config)
{
return LUdp6Port::open(config);
}
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return true;
}
/*=========================================
Class udp6Stack
=========================================*/
LUdp6Port::LUdp6Port()
{
_disconReq = false;
memset(_pollfds, 0, sizeof(_pollfds));
_sock = 0;
_interface = NULL;
_gIpAddrStr = NULL;
}
LUdp6Port::~LUdp6Port()
{
close();
if (_gIpAddrStr)
{
free(_gIpAddrStr);
}
if (_interface)
{
free(_interface);
}
}
void LUdp6Port::close()
{
for (int i = 0; i < 2; i++)
{
if (_pollfds[i].fd > 0)
{
::close(_pollfds[i].fd);
_pollfds[i].fd = 0;
}
}
}
bool LUdp6Port::open(LUdp6Config *config)
{
int optval = 1;
int sock = 0;
uint32_t ifindex = 0;
sockaddr_in6 addr6;
_gPortNo = htons(config->gPortNo);
_uPortNo = htons(config->uPortNo);
if (_gPortNo == 0 || _uPortNo == 0)
{
return false;
}
/* create a unicast socket */
sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0)
{
return false;
}
optval = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (strlen(config->interface) > 0)
{
ifindex = if_nametoindex(config->interface);
#ifdef __APPLE__
setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
#else
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, config->interface, strlen(config->interface));
#endif
}
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = _uPortNo;
addr6.sin6_addr = in6addr_any;
if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s ::bind() to unicast address\033[0m\033[0;37m\n", strerror(errno));
return false;
}
_pollfds[0].fd = sock;
_pollfds[0].events = POLLIN;
/* create a multicast socket */
sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0)
{
return false;
}
optval = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = _gPortNo;
addr6.sin6_addr = in6addr_any;
if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s ::bind() in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
return false;
}
ipv6_mreq addrm;
addrm.ipv6mr_interface = ifindex;
inet_pton(AF_INET6, config->ipAddress, &addrm.ipv6mr_multiaddr);
if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
optval = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s IPV6_MULTICAST_LOOP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
_pollfds[1].fd = sock;
_pollfds[1].events = POLLIN;
_gIpAddr.sin6_family = AF_INET6;
_gIpAddr.sin6_port = _gPortNo;
memcpy(&_gIpAddr.sin6_addr, (const void*) &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr));
_gIpAddrStr = strdup(config->ipAddress);
return true;
}
int LUdp6Port::unicast(const uint8_t *buf, uint32_t length, in6_addr ipAddress, uint16_t port)
{
struct sockaddr_in6 dest;
dest.sin6_family = AF_INET6;
dest.sin6_port = port;
memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr));
char addrBuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &dest.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
D_NWLOG("unicast to [%s]:%-6u", addrBuf, htons(port));
int status = ::sendto(_pollfds[0].fd, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
if (status < 0)
{
D_NWLOG(" errno = %d %s in Udp6Port::unicast\n", errno, strerror(errno));
}
else
{
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34municast to [%s[:%-6u", addrBuf, htons(port));
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
int LUdp6Port::multicast(const uint8_t *buf, uint32_t length)
{
char sbuf[SCREEN_BUFF_SIZE];
char portStr[8];
sprintf(portStr, "%d", ntohs(_gPortNo));
int status = ::sendto(_pollfds[1].fd, buf, length, 0, (sockaddr*) &_gIpAddr, sizeof(_gIpAddr));
if (status < 0)
{
D_NWLOG("multicast to [%s]:%-6s ", _gIpAddrStr, portStr);
D_NWLOG("\033[0m\033[0;31merrno = %d %s in Udp6Port::multicast\033[0m\033[0;37m\n", errno, strerror(errno));
return errno;
}
else
{
D_NWLOG("multicast to [%s]:%-6s", _gIpAddrStr, portStr);
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
memset(sbuf, 0, SCREEN_BUFF_SIZE);
int pos = 0;
sprintf(sbuf, "\033[0;34mmulticast to [%s]:%-6s", _gIpAddrStr, portStr);
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
}
bool LUdp6Port::checkRecvBuf()
{
uint8_t buf[2];
int cnt = poll(_pollfds, 2, 50); // Timeout 50m secs
if (cnt == 0)
{
return false;
}
for (int i = 0; i < 2; i++)
{
if (_pollfds[i].revents & POLLIN)
{
if (::recv(_pollfds[i].fd, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_sock = _pollfds[i].fd;
return true;
}
}
}
return false;
}
int LUdp6Port::recv(uint8_t *buf, uint16_t len, bool flg, in6_addr *ipAddressPtr, uint16_t *portPtr)
{
int flags = flg ? MSG_DONTWAIT : 0;
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
}
int LUdp6Port::recvfrom(uint8_t *buf, uint16_t length, int flags, in6_addr *ipAddressPtr, uint16_t *portPtr)
{
struct sockaddr_in6 sender;
int status;
socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
char addrBuf[INET6_ADDRSTRLEN];
status = ::recvfrom(_sock, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in Udp6Port::recvfrom \033[0m\033[0;37m\n", errno);
}
if (status > 0)
{
inet_ntop(AF_INET6, &sender.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
memcpy(ipAddressPtr->s6_addr, (const void*) sender.sin6_addr.s6_addr, sizeof(sender.sin6_addr.s6_addr));
*portPtr = sender.sin6_port;
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34mrecv from [%s]:%-6u", addrBuf, htons(*portPtr));
pos = strlen(sbuf);
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
else
{
return 0;
}
return status;
}
bool LUdp6Port::isUnicast(void)
{
return (_sock == _pollfds[0].fd && _sock > 0);
}
#endif /* UDP6 */

View File

@@ -0,0 +1,113 @@
/**************************************************************************************
* Copyright (c) 2021, 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 NETWORKUDP6_H_
#define NETWORKUDP6_H_
#ifdef UDP6
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <poll.h>
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
using namespace std;
namespace linuxAsyncClient {
/*========================================
Class LUpd6Port
=======================================*/
class LUdp6Port
{
friend class LNetwork;
public:
LUdp6Port();
virtual ~LUdp6Port();
bool open(LUdp6Config *config);
int unicast(const uint8_t *buf, uint32_t length, in6_addr ipaddress, uint16_t port);
int multicast( const uint8_t* buf, uint32_t length );
int recv(uint8_t *buf, uint16_t len, bool nonblock, in6_addr *ipaddress, uint16_t *port);
int recv(uint8_t* buf, int flags);
bool checkRecvBuf();
bool isUnicast();
private:
void close();
int recvfrom(uint8_t *buf, uint16_t len, int flags, in6_addr *ipaddress, uint16_t *port);
pollfd _pollfds[2];
uint16_t _gPortNo;
uint16_t _uPortNo;
sockaddr_in6 _gIpAddr;
char *_gIpAddrStr;
char* _interface;
int _sock;
bool _disconReq;
};
#define NO_ERROR 0
#define PACKET_EXCEEDS_LENGTH 1
/*===========================================
Class Network
============================================*/
class LNetwork: public LUdp6Port
{
public:
LNetwork();
~LNetwork();
int broadcast(const uint8_t* payload, uint16_t payloadLen);
int unicast(const uint8_t* payload, uint16_t payloadLen);
void setGwAddress(void);
void resetGwAddress(void);
bool initialize(LUdp6Config *config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
private:
void setSleep();
int readApiFrame(void);
in6_addr _gwIpAddress;
in6_addr _ipAddress;
uint16_t _gwPortNo;
uint16_t _portNo;
int _returnCode;
bool _sleepflg;
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
};
} /* end of namespace */
#endif /* UDP6 */
#endif /* NETWORKUDP_H_ */

View File

@@ -44,6 +44,7 @@ LPublishManager::LPublishManager()
_last = 0;
_elmCnt = 0;
_publishedFlg = SAVE_TASK_INDEX;
_autoConnectFlg = false;
}
LPublishManager::~LPublishManager()
@@ -115,7 +116,10 @@ void LPublishManager::sendPublish(PubElement* elm)
return;
}
if (_autoConnectFlg)
{
theClient->getGwProxy()->connect();
}
uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1];
uint8_t org = 0;
@@ -310,6 +314,11 @@ void LPublishManager::checkTimeout(void)
}
}
void LPublishManager::setAutoConnectMode(bool flg)
{
_autoConnectFlg = flg;
}
PubElement* LPublishManager::getElement(uint16_t msgId)
{
PubElement* elm = _first;

View File

@@ -70,6 +70,7 @@ public:
void sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType);
bool isDone(void);
bool isMaxFlight(void);
void setAutoConnectMode(bool);
private:
PubElement* getElement(uint16_t msgId);
PubElement* getElement(const char* topicName);
@@ -84,6 +85,7 @@ private:
PubElement* _last;
uint8_t _elmCnt;
uint8_t _publishedFlg;
uint8_t _autoConnectFlg;
};
} /* tomyAsyncClient */

View File

@@ -67,7 +67,9 @@ void LSubscribeManager::onConnect(void)
{
if ( theOnPublishList[i].type == MQTTSN_TOPIC_TYPE_PREDEFINED)
{
subscribe(theOnPublishList[i].id, theOnPublishList[i].pubCallback, theOnPublishList[i].qos);
subscribePredefinedId(theOnPublishList[i].id,
theOnPublishList[i].pubCallback,
theOnPublishList[i].qos);
}
else
{
@@ -122,6 +124,7 @@ void LSubscribeManager::send(SubElement* elm)
{
return;
}
uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1];
if (elm->topicType == MQTTSN_TOPIC_TYPE_PREDEFINED)
{
@@ -169,7 +172,7 @@ void LSubscribeManager::subscribe(const char* topicName, TopicCallback onPublish
send(elm);
}
void LSubscribeManager::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos)
void LSubscribeManager::subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos)
{
SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, 0, MQTTSN_TOPIC_TYPE_PREDEFINED, topicId, qos, onPublish);
send(elm);
@@ -262,7 +265,9 @@ void LSubscribeManager::responce(const uint8_t* msg)
}
else
{
DISPLAY("\033[0m\033[0;31m UNSUBACK Invalid messageId. \033[0m\033[0;37m\n\n");
DISPLAY(
"\033[0m\033[0;31m UNSUBACK Invalid messageId=%04x. \033[0m\033[0;37m\n\n",
msgId);
}
}
}

View File

@@ -56,7 +56,7 @@ public:
~LSubscribeManager();
void onConnect(void);
void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos);
void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos);
void subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos);
void unsubscribe(const char* topicName);
void unsubscribe(uint16_t topicId);
void responce(const uint8_t* msg);

View File

@@ -14,7 +14,6 @@
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include <stdio.h>
#include <string.h>
@@ -34,25 +33,30 @@ extern bool theClientMode;
/*=====================================
TaskManager
======================================*/
LTaskManager::LTaskManager(void){
LTaskManager::LTaskManager(void)
{
_tasks = 0;
_tests = 0;
_index = 0;
}
LTaskManager::~LTaskManager(void){
LTaskManager::~LTaskManager(void)
{
}
void LTaskManager::add(TaskList* task){
void LTaskManager::add(TaskList* task)
{
_tasks = task;
}
void LTaskManager::add(TestList* test){
void LTaskManager::add(TestList* test)
{
_tests = test;
}
void LTaskManager::run(void){
void LTaskManager::run(void)
{
int i = 0;
char c = 0;
bool cancelFlg = false;
@@ -99,9 +103,8 @@ void LTaskManager::run(void){
{
theClient->getGwProxy()->getMessage();
}
while(theClient->getPublishManager()->isMaxFlight() ||
!theClient->getSubscribeManager()->isDone() ||
!theClient->getRegisterManager()->isDone());
while (theClient->getPublishManager()->isMaxFlight() || !theClient->getSubscribeManager()->isDone()
|| !theClient->getRegisterManager()->isDone());
if (theClient->getPublishManager()->isDone())
{
@@ -122,8 +125,7 @@ void LTaskManager::run(void){
theClient->getGwProxy()->getMessage();
for (_index = 0; _tasks[_index].callback > task.callback; _index++)
{
if ((_tasks[_index].prevTime + _tasks[_index].interval <= time(NULL)) &&
_tasks[_index].count == 0)
if ((_tasks[_index].prevTime + _tasks[_index].interval <= time(NULL)) && _tasks[_index].count == 0)
{
_tasks[_index].prevTime = time(NULL);
(_tasks[_index].callback)();
@@ -134,9 +136,8 @@ void LTaskManager::run(void){
{
theClient->getGwProxy()->getMessage();
}
while(theClient->getPublishManager()->isMaxFlight() ||
!theClient->getSubscribeManager()->isDone() ||
!theClient->getRegisterManager()->isDone());
while (theClient->getPublishManager()->isMaxFlight() || !theClient->getSubscribeManager()->isDone()
|| !theClient->getRegisterManager()->isDone());
if (theClient->getPublishManager()->isDone())
{
@@ -146,11 +147,13 @@ void LTaskManager::run(void){
}
}
uint8_t LTaskManager::getIndex(void){
uint8_t LTaskManager::getIndex(void)
{
return _index;
}
void LTaskManager::done(uint8_t index){
void LTaskManager::done(uint8_t index)
{
if (_tasks)
{
if (_tasks[index].count > 0)
@@ -167,7 +170,8 @@ void LTaskManager::done(uint8_t index){
}
}
void LTaskManager::suspend(uint8_t index){
void LTaskManager::suspend(uint8_t index)
{
if (_tasks)
{
_tasks[index].count++;

View File

@@ -1,164 +0,0 @@
PROGNAME := MQTT-SNGateway
APPL := mainGateway
LPROGNAME := MQTT-SNLogmonitor
LAPPL := mainLogmonitor
TESTPROGNAME := testPFW
TESTAPPL := mainTestProcess
CONFIG := gateway.conf
CLIENTS := clients.conf
PREDEFTOPIC := predefinedTopic.conf
SRCDIR := src
SUBDIR := ../MQTTSNPacket/src
OS := linux
SENSORNET := udp
TEST := tests
INSTALL_DIR=../../
CONFIG_DIR=../../
CPPSRCS := \
$(SRCDIR)/MQTTGWConnectionHandler.cpp \
$(SRCDIR)/MQTTGWPacket.cpp \
$(SRCDIR)/MQTTGWPublishHandler.cpp \
$(SRCDIR)/MQTTGWSubscribeHandler.cpp \
$(SRCDIR)/MQTTSNGateway.cpp \
$(SRCDIR)/MQTTSNGWBrokerRecvTask.cpp \
$(SRCDIR)/MQTTSNGWBrokerSendTask.cpp \
$(SRCDIR)/MQTTSNGWClient.cpp \
$(SRCDIR)/MQTTSNGWClientRecvTask.cpp \
$(SRCDIR)/MQTTSNGWClientSendTask.cpp \
$(SRCDIR)/MQTTSNGWConnectionHandler.cpp \
$(SRCDIR)/MQTTSNGWLogmonitor.cpp \
$(SRCDIR)/MQTTSNGWPacket.cpp \
$(SRCDIR)/MQTTSNGWPacketHandleTask.cpp \
$(SRCDIR)/MQTTSNGWProcess.cpp \
$(SRCDIR)/MQTTSNGWPublishHandler.cpp \
$(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \
$(SRCDIR)/MQTTSNGWEncapsulatedPacket.cpp \
$(SRCDIR)/MQTTSNGWForwarder.cpp \
$(SRCDIR)/MQTTSNGWQoSm1Proxy.cpp \
$(SRCDIR)/MQTTSNGWAdapter.cpp \
$(SRCDIR)/MQTTSNGWAggregater.cpp \
$(SRCDIR)/MQTTSNGWClientList.cpp \
$(SRCDIR)/MQTTSNGWTopic.cpp \
$(SRCDIR)/MQTTSNGWAdapterManager.cpp \
$(SRCDIR)/MQTTSNAggregateConnectionHandler.cpp \
$(SRCDIR)/MQTTSNGWMessageIdTable.cpp \
$(SRCDIR)/MQTTSNGWAggregateTopicTable.cpp \
$(SRCDIR)/$(OS)/$(SENSORNET)/SensorNetwork.cpp \
$(SRCDIR)/$(OS)/Timer.cpp \
$(SRCDIR)/$(OS)/Network.cpp \
$(SRCDIR)/$(OS)/Threading.cpp \
$(SRCDIR)/$(TEST)/TestProcess.cpp \
$(SRCDIR)/$(TEST)/TestQue.cpp \
$(SRCDIR)/$(TEST)/TestTree23.cpp \
$(SRCDIR)/$(TEST)/TestTopics.cpp \
$(SRCDIR)/$(TEST)/TestTopicIdMap.cpp \
$(SRCDIR)/$(TEST)/TestTask.cpp
CSRCS := $(SUBDIR)/MQTTSNConnectClient.c \
$(SUBDIR)/MQTTSNConnectServer.c \
$(SUBDIR)/MQTTSNDeserializePublish.c \
$(SUBDIR)/MQTTSNPacket.c \
$(SUBDIR)/MQTTSNSearchClient.c \
$(SUBDIR)/MQTTSNSearchServer.c \
$(SUBDIR)/MQTTSNSerializePublish.c \
$(SUBDIR)/MQTTSNSubscribeClient.c \
$(SUBDIR)/MQTTSNSubscribeServer.c \
$(SUBDIR)/MQTTSNUnsubscribeClient.c \
$(SUBDIR)/MQTTSNUnsubscribeServer.c
CPPFLAGS +=
INCLUDE :=
INCLUDES += $(INCLUDE) -I$(SRCDIR) \
-I$(SRCDIR)/$(OS) \
-I$(SRCDIR)/$(OS)/$(SENSORNET) \
-I$(SUBDIR) \
-I$(SRCDIR)/$(TEST) \
-I/usr/local/opt/openssl/include/
# preprocessor defines
DEFS :=
CXX := g++
LIB :=
LIBS += $(LIB) -L/usr/local/lib -L/usr/local/opt/openssl/lib/
LDFLAGS :=
CXXFLAGS := -Wall -O3 -std=c++11
LDADD := -lpthread -lssl -lcrypto
OUTDIR := Build
PROG := $(OUTDIR)/$(PROGNAME)
LPROG := $(OUTDIR)/$(LPROGNAME)
TPROG := $(OUTDIR)/$(TESTPROGNAME)
OBJS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.o)
OBJS += $(CSRCS:%.c=$(OUTDIR)/%.o)
DEPS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.d)
DEPS += $(CSRCS:%.c=$(OUTDIR)/%.d)
.PHONY: install clean exectest
all: $(PROG) $(LPROG) $(TPROG)
monitor: $(LPROG)
test: $(TPROG) $(LPROG) exectest
-include $(DEPS)
$(PROG): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(APPL).o
$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) $(LDADD)
$(LPROG): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(LAPPL).o
$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) $(LDADD)
$(TPROG): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(TEST)/$(TESTAPPL).o
$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) $(LDADD)
$(OUTDIR)/$(SRCDIR)/%.o:$(SRCDIR)/%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(APPL).o:$(SRCDIR)/$(APPL).cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(TEST)/$(TESTAPPL).o:$(SRCDIR)/$(TEST)/$(TESTAPPL).cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(LAPPL).o:$(SRCDIR)/$(LAPPL).cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SUBDIR)/%.o:$(SUBDIR)/%.c
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
clean:
rm -rf $(OUTDIR)
install:
cp -pf $(PROG) $(INSTALL_DIR)
cp -pf $(LPROG) $(INSTALL_DIR)
cp -pf $(CONFIG) $(CONFIG_DIR)
cp -pf $(CLIENTS) $(CONFIG_DIR)
cp -pf $(PREDEFTOPIC) $(CONFIG_DIR)
exectest:
./$(OUTDIR)/$(TESTPROGNAME) -f ./gateway.conf

View File

@@ -1,145 +1,211 @@
# MQTT-SN Transparent / Aggregating Gateway
**MQTT-SN** requires a MQTT-SN Gateway which acts as a protocol converter to convert **MQTT-SN messages to MQTT messages**. MQTT-SN client over SensorNetwork can not communicate directly with MQTT broker(TCP/IP).
MQTT-SN requires a MQTT-SN Gateway which acts as a protocol converter to convert MQTT-SN messages to MQTT messages.
MQTT-SN client over SensorNetwork can not communicate directly with MQTT broker(TCP/IP).
This Gateway can run as a transparent or aggregating Gateway by specifying the gateway.conf.
### **step1. Build the gateway**
````
$ git clone -b develop https://github.com/eclipse/paho.mqtt-sn.embedded-c
### step1. Build the gateway
copy and expand source code then,
```
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway
$ make [SENSORNET={udp6|xbee|loralink}]
$ make install
$ make clean
````
By default, a gateway for UDP is built.
In order to create a gateway for UDP6, XBee or LoRaLink, SENSORNET argument is required.
```
In order to build a gateway, one sensor network argument is required.
```
$ ./build.sh [udp|udp6|xbee|loralink|rfcomm|dtls|dtls6]
```
MQTT-SNGateway, MQTT-SNLogmonitor and *.conf files are copied into ../ directory.
If you want to install the gateway into specific directories, enter a command line as follows:
````
$ make install INSTALL_DIR=/path/to/your_directory CONFIG_DIR=/path/to/your_directory
````
MQTT-SNGateway and MQTT-SNLogmonitor (executable programs) are built in ./bin directory.
### step2. Execute the Gateway.
### **step2. Execute the Gateway.**
````
$ cd ../../
$ ./MQTT-SNGateway [-f Config file name]
````
```
$ cd bin
$ ./MQTT-SNGateway
```
If you get the error message as follows:
````
what(): RingBuffer can't create a shared memory.
Aborted (core dumped)
````
RingBuffer can't create a shared memory. ABORT Gateway!!!
You have to start using sudo command only once for the first time.
````
$ sudo ./MQTT-SNGateway [-f Config file name]
````
### **How to Change the configuration of the gateway**
**../gateway.conf** Contents are follows:
<pre><dev>
```
$ sudo ./MQTT-SNGateway
```
## Contents of the gateway configuration file
**gateway.conf** is in bin directory. It's contents are follows:
```
#**************************************************************************
# Copyright (c) 2016-2021, 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.
#***************************************************************************
#
# config file of MQTT-SN Gateway
#
BrokerName=mqtt.eclipse.org
GatewayID=1
GatewayName=PahoGateway-01
MaxNumberOfClients=30
KeepAlive=60
#LoginID=your_ID
#Password=your_Password
BrokerName=mqtt.eclipseprojects.io
BrokerPortNo=1883
BrokerSecurePortNo=8883
```
**GatewayID** is a gateway ID which used by GWINFO message.
**GatewayName** is a name of the gateway.
**MaxNumberOfClients** is a maxmum number of clients. Clients are dynamically allocated.
**KeepAlive** is KeepAlive time in seconds.
**LoginID** is used by CONNECT message.
**Password** is used by CONNECT message.
**BrokerName**is a domain name or IP address of a broker.
**BrokerPortNo** is a broker's port no.
**BrokerSecurePortNo** is a broker's port no of TLS connection.
```
#
# CertsKey for TLS connections to a broker
#
#RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/
#CertsKey=/path/to/certKey.pem
#PrivateKey=/path/to/privateKey.pem
```
**RootCAfile** is a CA file name.
**RootCApath** is a CA path. **SSL_CTX_load_verify_locations(ctx, CAfile, CApath)** function requires these parameters.
**CertsKey** is a certificate pem file.
**PrivateKey** is a private key pem file.
Clients can connect to the broker via TLS by setting '**Secure Connection**' for each client in the client conf file.
```
#
# When AggregatingGateway=YES or ClientAuthentication=YES,
# All clients must be specified by the ClientList File
#
ClientAuthentication=NO
AggregatingGateway=NO
QoS-1=NO
Forwarder=NO
#ClientsList=/path/to/your_clients.conf
PredefinedTopic=NO
#PredefinedTopicList=/path/to/your_predefinedTopic.conf
ClientAuthentication=NO
#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
ClientsList=/path/to/your_clients.conf
PredefinedTopicList=/path/to/your_predefinedTopic.conf
```
The gateway runs as a aggregating gateway when **AggregatingGateway** is 'YES'.
If **QoS-1** is 'YES, the gateway prepares a proxy for the QoS-1 client. QoS-1 client has a 'QoS-1' parameter in a clients.conf file. For QoS-1 clients, set the QoS-1 parameters in the clients.conf file.
If **Forwarder** is 'YES', the gateway prepare a forwarder agent.
If **ClientAuthentication** is 'YES', the client cannot connect unless it is registered in the clients.conf file.
**ClientsList** defines clients and those address so on.
**PredefinedTopicList** file defines Predefined Topic.
# UDP
```
#==============================
# SensorNetworks parameters
#==============================
#
# UDP | DTLS
#
GatewayPortNo=10000
MulticastIP=225.1.1.1
MulticastPortNo=1883
MulticastIP=225.1.1.1
MulticastTTL=1
```
**GatewayPortNo** is a unicast port no of the gateway.
**MulticastIP** and **MulticastPortNo** are for GWSEARCH messages. Clients can get the gateway address (Gateway IP address and GatewayPortNo) from GWINFO message by means of std::recvfrom().
Client needs to know the MulticastIP and MulticastPortNo to send a SEARCHGW message.
**MulticastTTL** is a multicast TTL.
```
#
# UDP6 | DTLS6
#
# UDP6
GatewayUDP6Bind=FFFF:FFFE::1
GatewayUDP6Port=10000
GatewayUDP6Broadcast=FF02::1
GatewayUDP6If=wpan0
GatewayUDP6Hops=1
GatewayIPv6PortNo=10000
MulticastIPv6PortNo=1883
MulticastIPv6=ff1e:feed:caca:dead::feed:caca:dead
MulticastIPv6If=wlp4s0
MulticastHops=1
```
**GatewayIPv6PortNo** is a unicast port no of the gateway.
**MulticastIPv6PortNo** and **MulticastIPv6** are for GWSEARCH messages. Set the Global scope Multicast address so that the Global address is used for sending GWINFO.
Clients can get the gateway address (Gateway IPv6 address and GatewayPortNo) from GWINFO message by means of std::recvfrom().
**MulticastIPv6If** is a multicast interface name.
**MulticastHops** is a multicast hops.
```
#
# DTLS | DTLS6 DTLS CertsKey
#
DtlsCertsKey=/etc/ssl/certs/gateway.pem
DtlsPrivKey=/etc/ssl/private/privkey.pem
```
**DtlsCertsKey** is a certs Key pem file for DTLS connection.
**DtlsPrivKey** is a private key pem file for DTLS connection.
```
#
# XBee
#
Baudrate=38400
SerialDevice=/dev/ttyUSB0
ApiMode=2
```
**Baudrate** is a baudrate of xbee.
```
#
# LoRaLink
#
BaudrateLoRaLink=115200
DeviceRxLoRaLink=/dev/ttyLoRaLinkRx
DeviceTxLoRaLink=/dev/ttyLoRaLinkTx
DeviceRxLoRaLink=/dev/loralinkRx
DeviceTxLoRaLink=/dev/loralinkTx
```
https://github.com/ty4tw/MQTT-SN-LoRa
```
#
# Bluetooth RFCOMM
#
RFCOMMAddress=60:57:18:06:8B:72.*
```
**RFCOMMAddress** is a bluetooth mac address and channel. channel should be * for the gateway.
```
#
# LOG
ShearedMemory=NO;
#
</dev></pre>
ShearedMemory=NO
```
**BrokerName** to specify a domain name of the Broker, and **BrokerPortNo** is a port No of the Broker. **BrokerSecurePortNo** is for TLS connection.
**MulticastIP** and **MulticastPortNo** is a multicast address for GWSEARCH messages. Gateway is waiting GWSEARCH and when receiving it send GWINFO message via MulticastIP address. Clients can get the gateway address (Gateway IP address and **GatewayPortNo**) from GWINFO message by means of std::recvfrom().
Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW message.
**GatewayId** is used by GWINFO message.
**KeepAlive** is a duration of ADVERTISE message in seconds.
when **AggregatingGateway** or **ClientAuthentication** is **YES**, All clients which connect to the gateway must be declared by a **ClientsList** file.
Format of the file is ClientId and SensorNetwork Address. e.g. IP address and Port No etc, in CSV. more detail see clients.conf.
When **QoS-1** is **YES**, QoS-1 PUBLISH is available. All clients which send QoS-1 PUBLISH must be specified by Client.conf file.
When **PredefinedTopic** is **YES**, **Pre-definedTopicId**s specified by **PredefinedTopicList** are effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format.
When **Forwarder** is **YES**, Forwarder Encapsulation Message is available. Connectable Forwarders must be declared by a **ClientsList** file.
### ** How to monitor the gateway from remote. **
### How to monitor the gateway from a remote terminal.
Change gateway.conf as follows:
```
# LOG
ShearedMemory=YES;
````
```
Restart the gateway with sudo only once to create shared memories.
open ssh terminal and execute LogMonitor.
`$ ./MQTT-SNLogmonitor`
```
$ cd bin
$ ./MQTT-SNLogmonitor
```
Now you can get the Log on your terminal.
## ** Tips **
Uncomment the line 62, 63 in MQTTSNDefines.h then you can get more precise logs.
##### Tips
Use compiler definitions then you can get more precise logs.
**-DDEBUG_NW** is a flag for debug logs of Sensor network.
**-DDEBUG_MQTTSN** is a flag for debug logs of MQTT-SN message haandling.
One or both flags can be specified.
```
/*=================================
* Log controls
==================================*/
//#define DEBUG // print out log for debug
//#define DEBUG_NWSTACK // print out SensorNetwork log
./build.sh udp -DDEBUG -DDEBUG_NW
```

42
MQTTSNGateway/build.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
build () {
echo "Start building MQTT-SN Gateway $1"
cd $SCRIPT_DIR/..
BDIR='build.gateway'
if [ ! -d ./$BDIR ]; then
mkdir $BDIR
fi
cd $BDIR
cmake .. -DSENSORNET=$1 -DDEFS="${2} ${3}"
make MQTTSNPacket
make MQTT-SNGateway
make MQTT-SNLogmonitor
cd ../MQTTSNGateway
cp *.conf ./bin/
}
SCRIPT_DIR=$(cd $(dirname $0); pwd)
if [ $1 == "udp" ] ; then
build $1 $2 $3
elif [ $1 == "udp6" ] ; then
build $1 $2 $3
elif [ $1 == "xbee" ] ; then
build $1 $2 $3
elif [ $1 == "loralink" ]; then
build $1 $2 $3
elif [ $1 == "rfcomm" ] ; then
build $1 $2 $3
elif [ $1 == "dtls" ] ; then
build $1 $2 $3
elif [ $1 == "dtls6" ] ; then
build dtls "${2} ${3} -DDTLS6"
elif [ $1 == "clean" ] ; then
rm -rf ../builg.gateway
else
echo "Usage: build.sh [ udp | udp6 | xbee | loralink | rfcomm | dtls | dtls6 | clean]"
fi

View File

@@ -15,10 +15,10 @@
# Lines bigning with # are comment line.
# ClientId, SensorNetAddress, "unstableLine", "secureConnection"
# in case of UDP, SensorNetAddress format is IPAddress: port no.
# if the SensorNetwork is not stable, write "unstableLine".
# if Broker's Connection is SSL, write "secureConnection".
# if the client is a forwarder, "forwarder" is required.
# if the client send PUBLISH QoS-1, "QoS-1" is required.
# if the SensorNetwork is not stable, specify "unstableLine".
# if Broker's Connection is TLS, specify "secureConnection".
# if the client is a forwarder,specify "forwarder".
# if the client send PUBLISH QoS-1, specify "QoS-1".
#
# Ex:
# #Client List
@@ -31,6 +31,17 @@
#
# SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function.
#
# UDP6 (IPv6 UDP) [IPv6 address]:PortNo
# RFCOMM Device_address.channel (1-30)
# XBee FFFFFFFFFFFFFFFF 8bytes Hex
# LoRaLink 1-254
#
#
# This is a sample of UDP.
#
# REWRITE ALL ACCORDING TO YOUR CLIENTS.
#
GatewayTester, 172.16.1.11:20020
ClientPUB,172.16.1.11:2010
Client01,172.16.1.11:12001

View File

@@ -1,5 +1,5 @@
#**************************************************************************
# Copyright (c) 2016-2019, Tomoaki Yamaguchi
# Copyright (c) 2016-2021, Tomoaki Yamaguchi
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
@@ -14,55 +14,95 @@
# config file of MQTT-SN Gateway
#
BrokerName=mqtt.eclipse.org
GatewayID=1
GatewayName=PahoGateway-01
MaxNumberOfClients=30
KeepAlive=60
#LoginID=your_ID
#Password=your_Password
BrokerName=mqtt.eclipseprojects.io
BrokerPortNo=1883
BrokerSecurePortNo=8883
#
# CertsKey for TLS connections to a broker
#
#RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/
#CertsKey=/path/to/certKey.pem
#PrivateKey=/path/to/privateKey.pem
#
# When AggregatingGateway=YES or ClientAuthentication=YES,
# All clients must be specified by the ClientList File
#
ClientAuthentication=NO
AggregatingGateway=NO
QoS-1=NO
Forwarder=NO
#ClientsList=/path/to/your_clients.conf
PredefinedTopic=NO
#PredefinedTopicList=/path/to/your_predefinedTopic.conf
ClientAuthentication=NO
#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
ClientsList=/path/to/your_clients.conf
PredefinedTopicList=/path/to/your_predefinedTopic.conf
# UDP
#==============================
# SensorNetworks parameters
#==============================
#
# UDP | DTLS
#
GatewayPortNo=10000
MulticastIP=225.1.1.1
MulticastPortNo=1883
MulticastIP=225.1.1.1
MulticastTTL=1
# UDP6
GatewayUDP6Bind=FFFF:FFFE::1
GatewayUDP6Port=10000
GatewayUDP6Broadcast=FF02::1
GatewayUDP6If=wpan0
GatewayUDP6Hops=1
#
# UDP6 | DTLS6
#
GatewayIPv6PortNo=10000
MulticastIPv6PortNo=1883
MulticastIPv6=ff1e:feed:caca:dead::1
MulticastIPv6If=wlp4s0
MulticastHops=1
#
# DTLS | DTLS6
#
DtlsCertsKey=/etc/ssl/certs/gateway.pem
DtlsPrivKey=/etc/ssl/private/privkey.pem
#
# XBee
#
Baudrate=38400
SerialDevice=/dev/ttyUSB0
ApiMode=2
# LOG
ShearedMemory=NO;
#
# LoRaLink
#
BaudrateLoRaLink=115200
DeviceRxLoRaLink=/dev/loralinkRx
DeviceTxLoRaLink=/dev/loralinkTx
#
# Bluetooth RFCOMM
#
RFCOMMAddress=60:57:18:06:8B:72.*
#
# LOG
#
ShearedMemory=NO

View File

@@ -0,0 +1,151 @@
#*******************************************************************************
# Copyright (c) 2022 a1lu
#
# 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:
# a1lu - initial version
# ty4tw - modify
#*******************************************************************************/
PROJECT(mqtt-sn-gateway CXX)
SET(GW_VERSION_MAJOR 1)
SET(GW_VERSION_MINOR 5)
SET(GW_VERSION_PATCH 1)
SET(GATEWAY_VERSION ${GW_VERSION_MAJOR}.${GW_VERSION_MINOR}.${GW_VERSION_PATCH})
MESSAGE(STATUS "VERSION : ${GATEWAY_VERSION}")
configure_file( MQTTSNGWVersion.h.in ${CMAKE_CURRENT_SOURCE_DIR}/MQTTSNGWVersion.h )
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../bin)
SET(CMAKE_CXX_STANDARD 11)
SET(OS linux)
IF(NOT DEFINED SENSORNET)
SET(SENSORNET udp)
ENDIF()
MESSAGE(STATUS "SENSORNET: " ${SENSORNET})
ADD_DEFINITIONS(${DEFS})
MESSAGE(STATUS "Definitions: " ${DEFS})
ADD_LIBRARY(mqtt-sngateway_common
MQTTGWConnectionHandler.cpp
MQTTGWPacket.cpp
MQTTGWPublishHandler.cpp
MQTTGWSubscribeHandler.cpp
MQTTSNGateway.cpp
MQTTSNGWBrokerRecvTask.cpp
MQTTSNGWBrokerSendTask.cpp
MQTTSNGWClient.cpp
MQTTSNGWClientRecvTask.cpp
MQTTSNGWClientSendTask.cpp
MQTTSNGWConnectionHandler.cpp
MQTTSNGWLogmonitor.cpp
MQTTSNGWPacket.cpp
MQTTSNGWPacketHandleTask.cpp
MQTTSNGWProcess.cpp
MQTTSNGWPublishHandler.cpp
MQTTSNGWSubscribeHandler.cpp
MQTTSNGWEncapsulatedPacket.cpp
MQTTSNGWForwarder.cpp
MQTTSNGWQoSm1Proxy.cpp
MQTTSNGWAdapter.cpp
MQTTSNGWAggregater.cpp
MQTTSNGWClientList.cpp
MQTTSNGWTopic.cpp
MQTTSNGWAdapterManager.cpp
MQTTSNAggregateConnectionHandler.cpp
MQTTSNGWMessageIdTable.cpp
MQTTSNGWAggregateTopicTable.cpp
${OS}/${SENSORNET}/SensorNetwork.cpp
${OS}/${SENSORNET}/SensorNetwork.h
${OS}/Timer.cpp
${OS}/Timer.h
${OS}/Network.cpp
${OS}/Network.h
${OS}/Threading.cpp
${OS}/Threading.h
)
# linux
link_directories("/usr/local/lib")
# Mac
link_directories("/usr/local/opt/openssl/lib")
TARGET_INCLUDE_DIRECTORIES(mqtt-sngateway_common
PUBLIC
.
${OS}
${OS}/${SENSORNET}
../../MQTTSNPacket/src
/usr/local/include
/usr/local/opt/openssl/include
)
IF(SENSORNET MATCHES "rfcomm")
TARGET_LINK_LIBRARIES(mqtt-sngateway_common
PRIVATE
MQTTSNPacket
pthread
ssl
crypto
bluetooth
)
ELSE()
TARGET_LINK_LIBRARIES(mqtt-sngateway_common
PRIVATE
MQTTSNPacket
pthread
ssl
crypto
)
ENDIF()
ADD_EXECUTABLE(MQTT-SNGateway
mainGateway.cpp
)
TARGET_LINK_LIBRARIES(MQTT-SNGateway
mqtt-sngateway_common
)
ADD_EXECUTABLE(MQTT-SNLogmonitor
mainLogmonitor.cpp
)
TARGET_LINK_LIBRARIES(MQTT-SNLogmonitor
mqtt-sngateway_common
)
ADD_EXECUTABLE(testPFW
tests/mainTestProcess.cpp
tests/TestProcess.cpp
tests/TestQue.cpp
tests/TestTree23.cpp
tests/TestTopics.cpp
tests/TestTopicIdMap.cpp
tests/TestTask.cpp
)
TARGET_LINK_LIBRARIES(testPFW
mqtt-sngateway_common
)
ADD_TEST(NAME testPFW
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/..
COMMAND testPFW -f ./gateway.conf)

View File

@@ -49,8 +49,7 @@ void MQTTGWConnectionHandler::handleConnack(Client* client, MQTTGWPacket* packet
else if (resp.rc == MQTT_IDENTIFIER_REJECTED)
{
rc = MQTTSN_RC_NOT_SUPPORTED;
WRITELOG(" ClientID : %s ClientID is collect UTF-8 but not allowed by the Server.\n",
client->getClientId());
WRITELOG(" ClientID : %s ClientID is collect UTF-8 but not allowed by the Server.\n", client->getClientId());
}
else if (resp.rc == MQTT_SERVER_UNAVAILABLE)
{

View File

@@ -28,9 +28,8 @@ void writeInt(unsigned char** pptr, int msgId);
/**
* List of the predefined MQTT v3 packet names.
*/
static const char* mqtt_packet_names[] =
{ "RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP", "SUBSCRIBE", "SUBACK",
"UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT" };
static const char* mqtt_packet_names[] = { "RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP",
"SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT" };
/**
* Encodes the message length according to the MQTT algorithm
@@ -49,7 +48,8 @@ int MQTTPacket_encode(char* buf, int length)
if (length > 0)
d |= 0x80;
buf[rc++] = d;
} while (length > 0);
}
while (length > 0);
return rc;
}
@@ -205,7 +205,8 @@ int MQTTGWPacket::recv(Network* network)
}
_remainingLength += (c & 127) * multiplier;
multiplier *= 128;
} while ((c & 128) != 0);
}
while ((c & 128) != 0);
if (_remainingLength > 0)
{

View File

@@ -31,18 +31,29 @@ typedef void* (*pf)(unsigned char, char*, size_t);
enum msgTypes
{
CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
PINGREQ, PINGRESP, DISCONNECT
CONNECT = 1,
CONNACK,
PUBLISH,
PUBACK,
PUBREC,
PUBREL,
PUBCOMP,
SUBSCRIBE,
SUBACK,
UNSUBSCRIBE,
UNSUBACK,
PINGREQ,
PINGRESP,
DISCONNECT
};
/**
* Bitfields for the MQTT header byte.
*/
typedef union
{
/*unsigned*/ char byte; /**< the whole byte */
/*unsigned*/
char byte; /**< the whole byte */
#if defined(REVERSED)
struct
{
@@ -62,12 +73,12 @@ typedef union
#endif
} Header;
/**
* Data for a connect packet.
*/
enum MQTT_connackCodes{
enum MQTT_connackCodes
{
MQTT_CONNECTION_ACCEPTED,
MQTT_UNACCEPTABLE_PROTOCOL_VERSION,
MQTT_IDENTIFIER_REJECTED,
@@ -121,8 +132,6 @@ typedef struct
#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.
*/
@@ -160,7 +169,6 @@ typedef struct
char rc; /**< connack return code */
} Connack;
/**
* Data for a publish packet.
*/
@@ -214,11 +222,13 @@ public:
int getSUBACK(unsigned short* msgId, unsigned char* rc);
int getPUBLISH(Publish* pub);
int setCONNECT(Connect* conect, unsigned char* username, unsigned char* password);
int setCONNECT(Connect* conect, unsigned char* username,
unsigned char* password);
int setPUBLISH(Publish* pub);
int setAck(unsigned char msgType, unsigned short msgid);
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);
UTF8String getTopic(void);

View File

@@ -39,7 +39,8 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
{
if (!client->isActive() && !client->isSleep() && !client->isAwake())
{
WRITELOG("%s The client is neither active nor sleep %s%s\n", ERRMSG_HEADER, client->getStatus(), ERRMSG_FOOTER);
WRITELOG("%s The client is neither active nor sleep %s%s\n",
ERRMSG_HEADER, client->getStatus(), ERRMSG_FOOTER);
return;
}
@@ -65,7 +66,8 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
*msg = *packet;
if (msg->getType() == 0)
{
WRITELOG("%s MQTTGWPublishHandler::handlePublish can't allocate memories for Packet.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER);
WRITELOG("%s MQTTGWPublishHandler::handlePublish can't allocate memories for Packet.%s\n",
ERRMSG_HEADER, ERRMSG_FOOTER);
delete msg;
return;
}
@@ -99,16 +101,17 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
topicId.type = tp->getType();
topicId.data.long_.len = pub.topiclen;
topicId.data.long_.name = pub.topic;
topicId.data.id = tp->getTopicId();
}
else
{
/* This message might be subscribed with wild card. */
/* This message might be subscribed with wild card or not cleanSession*/
topicId.type = MQTTSN_TOPIC_TYPE_NORMAL;
Topic* topic = client->getTopics()->match(&topicId);
if (topic == nullptr)
if (topic == nullptr && client->isCleanSession())
{
WRITELOG(" Invalid Topic. PUBLISH message is canceled.\n");
WRITELOG("%sMQTTGWPublishHandler Invalid Topic. PUBLISH message is discarded.%s\n",
ERRMSG_HEADER, ERRMSG_FOOTER);
if (pub.header.bits.qos == 1)
{
replyACK(client, &pub, PUBACK);
@@ -122,10 +125,25 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
return;
}
if (topic == nullptr)
{
topicId.type = MQTTSN_TOPIC_TYPE_NORMAL;
topicId.data.long_.len = pub.topiclen;
topicId.data.long_.name = pub.topic;
topicId.data.id = 0;
}
/* add the Topic and get a TopicId */
topic = client->getTopics()->add(&topicId);
if (topic == nullptr)
{
WRITELOG(
"%sMQTTGWPublishHandler Can't Add a Topic. MAX_TOPIC_PAR_CLIENT is exceeded. PUBLISH message is discarded.%s\n",
ERRMSG_HEADER, ERRMSG_FOOTER);
delete snPacket;
return;
}
id = topic->getTopicId();
if (id > 0)
{
/* create REGISTER */
@@ -145,15 +163,15 @@ void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
/* send PUBLISH */
topicId.data.id = id;
snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos,
(uint8_t) pub.header.bits.retain, (uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload,
pub.payloadlen);
snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, (uint8_t) pub.header.bits.retain,
(uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, pub.payloadlen);
client->getWaitREGACKPacketList()->setPacket(snPacket, regackMsgId);
return;
}
else
{
WRITELOG("%sMQTTGWPublishHandler Can't create a Topic.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER);
WRITELOG("%sMQTTGWPublishHandler Can't create a Topic. PUBLISH message is discarded.%s\n",
ERRMSG_HEADER, ERRMSG_FOOTER);
delete snPacket;
return;
}
@@ -193,7 +211,8 @@ void MQTTGWPublishHandler::handlePuback(Client* client, MQTTGWPacket* packet)
_gateway->getClientSendQue()->post(ev1);
return;
}
WRITELOG(" PUBACK from the Broker is invalid. PacketID : %04X ClientID : %s \n", (uint16_t)ack.msgId, client->getClientId());
WRITELOG(" PUBACK from the Broker is invalid. PacketID : %04X ClientID : %s \n", (uint16_t) ack.msgId,
client->getClientId());
}
void MQTTGWPublishHandler::handleAck(Client* client, MQTTGWPacket* packet, int type)
@@ -234,8 +253,6 @@ void MQTTGWPublishHandler::handleAck(Client* client, MQTTGWPacket* packet, int t
}
}
void MQTTGWPublishHandler::handleAggregatePuback(Client* client, MQTTGWPacket* packet)
{
uint16_t msgId = packet->getMsgId();
@@ -272,7 +289,6 @@ void MQTTGWPublishHandler::handleAggregatePublish(Client* client, MQTTGWPacket*
Publish pub;
packet->getPUBLISH(&pub);
string* topicName = new string(pub.topic, pub.topiclen); // topic deletes topicName when the topic is deleted
Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL);
@@ -287,7 +303,8 @@ void MQTTGWPublishHandler::handleAggregatePublish(Client* client, MQTTGWPacket*
if (msg->getType() == 0)
{
WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER);
WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n",
ERRMSG_HEADER, ERRMSG_FOOTER);
delete msg;
break;
}

View File

@@ -45,6 +45,4 @@ private:
}
#endif /* MQTTGWPUBLISHHANDLER_H_ */

View File

@@ -96,4 +96,3 @@ void MQTTGWSubscribeHandler::handleAggregateUnsuback(Client* client, MQTTGWPacke
}
}

View File

@@ -36,7 +36,6 @@ MQTTSNAggregateConnectionHandler::~MQTTSNAggregateConnectionHandler()
}
/*
* CONNECT
*/
@@ -70,7 +69,6 @@ void MQTTSNAggregateConnectionHandler::handleConnect(Client* client, MQTTSNPacke
/* CONNECT was not sent yet. prepare Connect data */
client->setSessionStatus(false);
if (data.cleansession)
{
@@ -120,7 +118,6 @@ void MQTTSNAggregateConnectionHandler::handleConnect(Client* client, MQTTSNPacke
}
}
/*
* WILLMSG
*/

View File

@@ -24,7 +24,6 @@
#include <string.h>
using namespace MQTTSNGW;
/*=====================================
Class Adapter
=====================================*/
@@ -48,7 +47,6 @@ Adapter::~Adapter(void)
}
}
void Adapter::setup(const char* adpterName, AdapterType adapterType)
{
_isSecure = false;
@@ -69,12 +67,12 @@ void Adapter::setup(const char* adpterName, AdapterType adapterType)
setClient(client, false);
client->setAdapterType(adapterType);
client = _gateway->getClientList()->createClient(0, &idSecure, true, true, TRANSPEARENT_TYPE);
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);
@@ -174,7 +172,8 @@ void Adapter::send(MQTTSNPacket* packet, Client* client)
}
else
{
WRITELOG("%s %s No Secure connections %s 's packet is discarded.%s\n", ERRMSG_HEADER, client->getClientId() , ERRMSG_FOOTER);
WRITELOG("%s %s No Secure connections %s 's packet is discarded.%s\n",
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return;
}
}
@@ -212,7 +211,6 @@ void Adapter::savePacket(Client* client, MQTTSNPacket* packet)
}
}
Client* Adapter::getAdapterClient(Client* client)
{
if (client->isSecureNetwork())
@@ -276,7 +274,6 @@ void Proxy::checkConnection(Client* client)
}
}
void Proxy::resetPingTimer(void)
{
_keepAliveTimer.start(PROXY_KEEPALIVE_DURATION * 1000UL);

View File

@@ -31,7 +31,8 @@ class EventQue;
class Timer;
/* When you add a new type, Client::setAdapterType() and Client::isAdapter() functions must be modified. */
typedef enum{
typedef enum
{
Atype_QoSm1Proxy, Atype_Aggregater
} AdapterType;
@@ -69,7 +70,6 @@ private:
bool _isSecure { false };
};
/*=====================================
Class Proxy
=====================================*/
@@ -88,7 +88,8 @@ public:
private:
void sendSuspendedPacket(void);
Gateway* _gateway;
EventQue* _suspendedPacketEventQue {nullptr};
EventQue* _suspendedPacketEventQue
{ nullptr };
Timer _keepAliveTimer;
Timer _responseTimer;
bool _isWaitingResp { false };

View File

@@ -39,7 +39,6 @@ AdapterManager::AdapterManager(Gateway* gw)
_aggregater = new Aggregater(gw);
}
void AdapterManager::initialize(char* gwName, bool aggregate, bool forwarder, bool qosM1)
{
if (aggregate)

View File

@@ -49,7 +49,8 @@ public:
bool isAggregatedClient(Client* client);
Client* getClient(Client* client);
Client* convertClient(uint16_t msgId, uint16_t* clientMsgId);
int unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task);
int unicastToClient(Client* client, MQTTSNPacket* packet,
ClientSendTask* task);
bool isAggregaterActive(void);
private:
@@ -59,8 +60,5 @@ private:
Aggregater* _aggregater { nullptr };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_ */

View File

@@ -68,7 +68,8 @@ public:
ClientTopicElement* add(Client* client);
ClientTopicElement* getFirstClientTopicElement(void);
ClientTopicElement* getNextClientTopicElement(ClientTopicElement* elmClient);
ClientTopicElement* getNextClientTopicElement(
ClientTopicElement* elmClient);
void eraseClient(Client* client);
ClientTopicElement* find(Client* client);
@@ -103,6 +104,4 @@ private:
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATETOPICTABLE_H_ */

View File

@@ -26,7 +26,8 @@
using namespace MQTTSNGW;
Aggregater::Aggregater(Gateway* gw) : Adapter(gw)
Aggregater::Aggregater(Gateway* gw) :
Adapter(gw)
{
_gateway = gw;
}
@@ -63,7 +64,6 @@ 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.*/
@@ -89,7 +89,6 @@ AggregateTopicElement* Aggregater::addAggregateTopic(Topic* topic, Client* clien
return _topicTable.add(topic, client);
}
void Aggregater::removeAggregateTopic(Topic* topic, Client* client)
{
_topicTable.erase(topic, client);

View File

@@ -73,10 +73,6 @@ private:
bool _isSecure { false };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATER_H_ */

View File

@@ -17,6 +17,7 @@
#include "MQTTSNGWBrokerRecvTask.h"
#include "MQTTSNGWClient.h"
#include "MQTTSNGWClientList.h"
#include "MQTTSNGateway.h"
#include <unistd.h>
using namespace std;
@@ -32,11 +33,11 @@ BrokerRecvTask::BrokerRecvTask(Gateway* gateway)
_gateway = gateway;
_gateway->attach((Thread*) this);
_light = nullptr;
setTaskName("BrokerRecvTask");
}
BrokerRecvTask::~BrokerRecvTask()
{
}
/**
@@ -64,7 +65,7 @@ void BrokerRecvTask::run(void)
_light->blueLight(false);
if (CHK_SIGINT)
{
WRITELOG("\n%s BrokerRecvTask stopped.", currentDateTime());
WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
return;
}
timeout.tv_sec = 0;
@@ -100,6 +101,7 @@ void BrokerRecvTask::run(void)
{
/* Check sockets is ready to read */
int activity = select(maxSock + 1, &rset, 0, 0, &timeout);
if (activity > 0)
{
client = _gateway->getClientList()->getClient(0);
@@ -134,47 +136,43 @@ void BrokerRecvTask::run(void)
{
if (rc == 0) // Disconnected
{
WRITELOG("%s BrokerRecvTask %s is disconnected by the broker.%s\n",
ERRMSG_HEADER, client->getClientId(),
ERRMSG_FOOTER);
client->getNetwork()->close();
delete packet;
/* delete client when the client is not authorized & session is clean */
_gateway->getClientList()->erase(client);
if ( client )
{
client = client->getNextClient();
}
continue;
client->disconnected();
}
else if (rc == -1)
{
WRITELOG("%s BrokerRecvTask can't receive a packet from the broker errno=%d %s%s\n", ERRMSG_HEADER, errno, client->getClientId(), ERRMSG_FOOTER);
WRITELOG("%s BrokerRecvTask can't receive a packet from the broker errno=%d %s%s\n",
ERRMSG_HEADER, errno, client->getClientId(),
ERRMSG_FOOTER);
}
else if (rc == -2)
{
WRITELOG("%s BrokerRecvTask receive invalid length of packet from the broker. DISCONNECT %s %s\n", ERRMSG_HEADER, client->getClientId(),ERRMSG_FOOTER);
WRITELOG(
"%s BrokerRecvTask receive invalid length of packet from the broker. DISCONNECT %s %s\n",
ERRMSG_HEADER, client->getClientId(),
ERRMSG_FOOTER);
}
else if (rc == -3)
{
WRITELOG("%s BrokerRecvTask can't get memories for the packet %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
WRITELOG("%s BrokerRecvTask can't allocate memories for the packet %s%s\n",
ERRMSG_HEADER, client->getClientId(),
ERRMSG_FOOTER);
}
delete packet;
if ((rc == -1 || rc == -2) && (client->isActive() || client->isSleep() || client->isAwake()))
{
/* disconnect the client */
packet = new MQTTGWPacket();
packet->setHeader(DISCONNECT);
ev = new Event();
ev->setBrokerRecvEvent(client, packet);
_gateway->getPacketEventQue()->post(ev);
client->getNetwork()->close();
client->disconnected();
}
}
}
}
nextClient:
client = client->getNextClient();
nextClient: client = client->getNextClient();
}
}
}
@@ -196,17 +194,20 @@ int BrokerRecvTask::log(Client* client, MQTTGWPacket* packet)
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROWB, client->getClientId(), packet->print(pbuf));
break;
case PUBLISH:
WRITELOG(FORMAT_W_MSGID_Y_W_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, client->getClientId(), packet->print(pbuf));
WRITELOG(FORMAT_W_MSGID_Y_W_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB,
client->getClientId(), packet->print(pbuf));
break;
case PUBACK:
case PUBREC:
case PUBREL:
case PUBCOMP:
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, client->getClientId(), packet->print(pbuf));
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB,
client->getClientId(), packet->print(pbuf));
break;
case SUBACK:
case UNSUBACK:
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, client->getClientId(), packet->print(pbuf));
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB,
client->getClientId(), packet->print(pbuf));
break;
case PINGRESP:
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROWB, client->getClientId(), packet->print(pbuf));

View File

@@ -28,7 +28,7 @@ namespace MQTTSNGW
class BrokerRecvTask: public Thread
{
MAGIC_WORD_FOR_THREAD;
;
public:
BrokerRecvTask(Gateway* gateway);
~BrokerRecvTask();
@@ -44,5 +44,4 @@ private:
}
#endif /* MQTTSNGWBROKERRECVTASK_H_ */

View File

@@ -37,11 +37,11 @@ BrokerSendTask::BrokerSendTask(Gateway* gateway)
_gateway->attach((Thread*) this);
_gwparams = nullptr;
_light = nullptr;
setTaskName("BrokerSendTask");
}
BrokerSendTask::~BrokerSendTask()
{
// WRITELOG("BrokerSendTask is deleted normally.\r\n");
}
/**
@@ -70,7 +70,7 @@ void BrokerSendTask::run()
if (ev->getEventType() == EtStop)
{
WRITELOG("\n%s BrokerSendTask stopped.", currentDateTime());
WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
delete ev;
return;
}
@@ -94,8 +94,9 @@ void BrokerSendTask::run()
if (client->isSecureNetwork())
{
rc = client->getNetwork()->connect((const char*)_gwparams->brokerName, (const char*)_gwparams->portSecure, (const char*)_gwparams->rootCApath,
(const char*)_gwparams->rootCAfile, (const char*)_gwparams->certKey, (const char*)_gwparams->privateKey);
rc = client->getNetwork()->connect((const char*) _gwparams->brokerName, (const char*) _gwparams->portSecure,
(const char*) _gwparams->rootCApath, (const char*) _gwparams->rootCAfile,
(const char*) _gwparams->certKey, (const char*) _gwparams->privateKey);
}
else
{
@@ -151,7 +152,6 @@ void BrokerSendTask::run()
}
}
/**
* write message content into stdout or Ringbuffer
*/
@@ -163,10 +163,12 @@ void BrokerSendTask::log(Client* client, MQTTGWPacket* packet)
switch (packet->getType())
{
case CONNECT:
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROWB, client->getClientId(), packet->print(pbuf));
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(),
RIGHTARROWB, client->getClientId(), packet->print(pbuf));
break;
case PUBLISH:
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB, client->getClientId(), packet->print(pbuf));
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB,
client->getClientId(), packet->print(pbuf));
break;
case SUBSCRIBE:
case UNSUBSCRIBE:
@@ -174,13 +176,16 @@ void BrokerSendTask::log(Client* client, MQTTGWPacket* packet)
case PUBREC:
case PUBREL:
case PUBCOMP:
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB, client->getClientId(), packet->print(pbuf));
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB,
client->getClientId(), packet->print(pbuf));
break;
case PINGREQ:
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROWB, client->getClientId(), packet->print(pbuf));
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(),
RIGHTARROWB, client->getClientId(), packet->print(pbuf));
break;
case DISCONNECT:
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROWB, client->getClientId(), packet->print(pbuf));
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(),
RIGHTARROWB, client->getClientId(), packet->print(pbuf));
break;
default:
break;

View File

@@ -28,17 +28,17 @@
using namespace MQTTSNGW;
char* currentDateTime(void);
/*=====================================
Class Client
=====================================*/
static const char* theClientStatus[] = { "Disconnected", "TryConnecting", "Connecting", "Active", "Asleep", "Awake", "Lost" };
static const char* theClientStatus[] = { "InPool", "Disconnected", "TryConnecting", "Connecting", "Active", "Asleep", "Awake",
"Lost" };
Client::Client(bool secure)
{
_packetId = 0;
_snMsgId = 0;
_status = Cstat_Disconnected;
_status = Cstat_Free;
_keepAliveMsec = 0;
_topics = new Topics();
_clientId = nullptr;
@@ -58,7 +58,7 @@ Client::Client(bool secure)
_hasPredefTopic = false;
_holdPingRequest = false;
_forwarder = nullptr;
_clientType = Ctype_Regular;
_clientType = Ctype_Normal;
}
Client::~Client()
@@ -177,13 +177,14 @@ void Client::clearWaitedSubTopicId(void)
_waitedSubTopicIdMap.clear();
}
void Client::setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type)
void Client::setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic)
{
_waitedPubTopicIdMap.add(msgId, topicId, type);
_waitedPubTopicIdMap.add(msgId, topicId, topic);
}
void Client::setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type)
void Client::setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic)
{
_waitedSubTopicIdMap.add(msgId, topicId, type);
_waitedSubTopicIdMap.add(msgId, topicId, topic);
}
bool Client::checkTimeover(void)
@@ -280,8 +281,7 @@ void Client::updateStatus(MQTTSNPacket* packet)
default:
break;
}
}
DEBUGLOG("Client Status = %s\n", theClientStatus[_status]);
}DEBUGLOG("Client Status = %s\n", theClientStatus[_status]);
}
void Client::updateStatus(ClientStatus stat)
@@ -317,6 +317,11 @@ void Client::tryConnect(void)
_status = Cstat_TryConnecting;
}
bool Client::isCleanSession(void)
{
return _sessionStatus;
}
bool Client::isConnectSendable(void)
{
if (_status == Cstat_Lost || _status == Cstat_TryConnecting)
@@ -537,7 +542,7 @@ void Client::setAdapterType(AdapterType type)
_clientType = Ctype_Aggregater;
break;
default:
throw Exception("Client::setAdapterType(): Invalid Type.");
throw EXCEPTION("Client::setAdapterType(): Invalid Type.", 0);
break;
}
}
@@ -577,8 +582,6 @@ bool Client::isHoldPingReqest(void)
return _holdPingRequest;
}
/*=====================================
Class WaitREGACKPacket
=====================================*/
@@ -691,4 +694,3 @@ uint8_t WaitREGACKPacketList::getCount(void)
return _cnt;
}

View File

@@ -49,7 +49,6 @@ public:
_que = new Que<T>;
}
~PacketQue()
{
clear();
@@ -72,8 +71,7 @@ public:
}
}
int
post(T* packet)
int post(T* packet)
{
int rc;
_mutex.lock();
@@ -113,8 +111,6 @@ private:
Mutex _mutex;
};
/*=====================================
Class WaitREGACKPacket
=====================================*/
@@ -151,19 +147,29 @@ private:
waitREGACKPacket* _end;
};
/*=====================================
Class Client
=====================================*/
typedef enum
{
Cstat_Disconnected = 0, Cstat_TryConnecting, Cstat_Connecting, Cstat_Active, Cstat_Asleep, Cstat_Awake, Cstat_Lost
Cstat_Free = 0,
Cstat_Disconnected,
Cstat_TryConnecting,
Cstat_Connecting,
Cstat_Active,
Cstat_Asleep,
Cstat_Awake,
Cstat_Lost
} ClientStatus;
typedef enum
{
Ctype_Regular = 0, Ctype_Forwarded, Ctype_QoS_1, Ctype_Aggregated, Ctype_Proxy, Ctype_Aggregater
Ctype_Normal = 0,
Ctype_Forwarded,
Ctype_QoS_1,
Ctype_Aggregated,
Ctype_Proxy,
Ctype_Aggregater
} ClientType;
class Forwarder;
@@ -171,6 +177,7 @@ class Forwarder;
class Client
{
friend class ClientList;
friend class ClientsPool;
public:
Client(bool secure = false);
Client(uint8_t maxInflightMessages, bool secure);
@@ -193,8 +200,8 @@ public:
int setClientSleepPacket(MQTTGWPacket*);
int setProxyPacket(MQTTSNPacket* packet);
void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic);
void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic);
bool checkTimeover(void);
void updateStatus(MQTTSNPacket*);
@@ -249,6 +256,7 @@ public:
bool isSecureNetwork(void);
bool isSensorNetStable(void);
bool isWaitWillMsg(void);
bool isCleanSession(void);
void holdPingRequest(void);
void resetPingRequest(void);
@@ -299,7 +307,5 @@ private:
Client* _prevClient;
};
}
#endif /* MQTTSNGWCLIENT_H_ */

View File

@@ -20,18 +20,20 @@
#include <string>
using namespace MQTTSNGW;
extern Gateway* theGateway;
char* currentDateTime(void);
/*=====================================
Class ClientList
=====================================*/
const char* common_topic = "*";
ClientList::ClientList()
ClientList::ClientList(Gateway* gw)
{
_clientCnt = 0;
_authorize = false;
_firstClient = nullptr;
_endClient = nullptr;
_clientsPool = new ClientsPool();
_gateway = gw;
}
ClientList::~ClientList()
@@ -46,12 +48,20 @@ ClientList::~ClientList()
delete cl;
cl = ncl;
};
if (_clientsPool)
{
delete _clientsPool;
}
_mutex.unlock();
}
void ClientList::initialize(bool aggregate)
{
if (theGateway->getGWParams()->clientAuthentication )
_maxClients = _gateway->getGWParams()->maxClients;
_clientsPool->allocate(_gateway->getGWParams()->maxClients);
if (_gateway->getGWParams()->clientAuthentication)
{
int type = TRANSPEARENT_TYPE;
if (aggregate)
@@ -62,7 +72,7 @@ void ClientList::initialize(bool aggregate)
_authorize = true;
}
if ( theGateway->getGWParams()->predefinedTopic )
if (_gateway->getGWParams()->predefinedTopic)
{
setPredefinedTopics(aggregate);
}
@@ -70,17 +80,17 @@ void ClientList::initialize(bool aggregate)
void ClientList::setClientList(int type)
{
if (!createList(theGateway->getGWParams()->clientListName, type))
if (!createList(_gateway->getGWParams()->clientListName, type))
{
throw Exception("ClientList::setClientList No client list defined by config file.");
throw EXCEPTION("ClientList::setClientList Client list not found!", 0);
}
}
void ClientList::setPredefinedTopics(bool aggrecate)
{
if ( !readPredefinedList(theGateway->getGWParams()->predefinedTopicFileName, aggrecate) )
if (!readPredefinedList(_gateway->getGWParams()->predefinedTopicFileName, aggrecate))
{
throw Exception("ClientList::setPredefinedTopics No predefindTopi list defined by config file.");
throw EXCEPTION("ClientList::setPredefinedTopics PredefindTopic list not found!", 0);
}
}
@@ -154,7 +164,7 @@ bool ClientList::createList(const char* fileName, int type)
}
else if (forwarder && type == FORWARDER_TYPE)
{
theGateway->getAdapterManager()->getForwarderList()->addForwarder(&netAddr, &clientId);
_gateway->getAdapterManager()->getForwarderList()->addForwarder(&netAddr, &clientId);
}
else if (type == TRANSPEARENT_TYPE)
{
@@ -179,7 +189,8 @@ bool ClientList::readPredefinedList(const char* fileName, bool aggregate)
FILE* fp;
char buf[MAX_CLIENTID_LENGTH + 256];
size_t pos0, pos1;
MQTTSNString clientId = MQTTSNString_initializer;;
MQTTSNString clientId = MQTTSNString_initializer;
;
bool rc = false;
if ((fp = fopen(fileName, "r")) != 0)
@@ -297,7 +308,6 @@ Client* ClientList::getClient(int index)
return nullptr;
}
Client* ClientList::getClient(MQTTSNString* clientId)
{
_mutex.lock();
@@ -329,22 +339,23 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId,
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);
Client* client = getClient(addr);
if (client)
{
return client;
}
/* creat a new client */
client = new Client(secure);
/* acquire a free client */
client = _clientsPool->getClient();
if (!client)
{
WRITELOG("%s%sMax number of Clients%s\n", currentDateTime(),
ERRMSG_HEADER, ERRMSG_FOOTER);
return nullptr;
}
client->disconnected();
if (addr)
{
client->setClientAddress(addr);
@@ -370,6 +381,7 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId,
{
client->setQoSm1();
}
client->getNetwork()->setSecure(secure);
_mutex.lock();
@@ -400,7 +412,7 @@ Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicN
if (strcmp(clientId->cstring, common_topic) == 0)
{
theGateway->getTopics()->add((const char*)topicName.c_str(), topicId);
_gateway->getTopics()->add((const char*) topicName.c_str(), topicId);
return nullptr;
}
else
@@ -412,37 +424,11 @@ Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicN
return nullptr;
}
/* anonimous clients */
if ( _clientCnt > MAX_CLIENTS )
{
return nullptr; // full of clients
}
client = createClient(NULL, clientId, aggregate);
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();
return nullptr;
}
// create Topic & Add it
@@ -462,4 +448,70 @@ bool ClientList::isAuthorized()
return _authorize;
}
/******************************
* Class ClientsPool
******************************/
ClientsPool::ClientsPool()
{
_clientCnt = 0;
_firstClient = nullptr;
_endClient = nullptr;
}
ClientsPool::~ClientsPool()
{
Client* cl = _firstClient;
Client* ncl;
while (cl != nullptr)
{
ncl = cl->_nextClient;
delete cl;
cl = ncl;
};
}
void ClientsPool::allocate(int maxClients)
{
Client* cl = nullptr;
_firstClient = new Client();
for (int i = 0; i < maxClients; i++)
{
if ((cl = new Client()) == nullptr)
{
throw Exception("ClientsPool::Can't allocate max number of clients\n", 0);
}
cl->_nextClient = _firstClient;
_firstClient = cl;
_clientCnt++;
}
}
Client* ClientsPool::getClient(void)
{
Client *cl = nullptr;
while (_firstClient != nullptr)
{
cl = _firstClient;
_firstClient = cl->_nextClient;
cl->_nextClient = nullptr;
_clientCnt--;
break;
}
return cl;
}
void ClientsPool::setClient(Client* client)
{
if (client)
{
client->_nextClient = _firstClient;
_firstClient = client;
_clientCnt++;
}
}

View File

@@ -30,21 +30,41 @@ namespace MQTTSNGW
class Client;
/*=====================================
Class ClientsPool
=====================================*/
class ClientsPool
{
public:
ClientsPool();
~ClientsPool();
void allocate(int maxClients);
Client* getClient(void);
void setClient(Client* client);
private:
Client* _firstClient;
Client* _endClient;
int _clientCnt;
};
/*=====================================
Class ClientList
=====================================*/
class ClientList
{
public:
ClientList();
ClientList(Gateway* gw);
~ClientList();
void initialize(bool aggregate);
void setClientList(int type);
void setPredefinedTopics(bool aggregate);
void erase(Client*&);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId,int type);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type);
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);
@@ -55,18 +75,18 @@ public:
private:
bool readPredefinedList(const char* fileName, bool _aggregate);
Gateway* _gateway {nullptr};
Client* createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t toipcId, bool _aggregate);
ClientsPool* _clientsPool;
Gateway* _gateway;
Client* createPredefinedTopic(MQTTSNString* clientId, string topicName,
uint16_t toipcId, bool _aggregate);
Client* _firstClient;
Client* _endClient;
Mutex _mutex;
uint16_t _clientCnt;
uint16_t _maxClients;
bool _authorize { false };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_ */

View File

@@ -20,8 +20,6 @@
#include "MQTTSNGWEncapsulatedPacket.h"
#include <cstring>
//#include "MQTTSNGWForwarder.h"
using namespace MQTTSNGW;
char* currentDateTime(void);
/*=====================================
@@ -32,27 +30,20 @@ ClientRecvTask::ClientRecvTask(Gateway* gateway)
_gateway = gateway;
_gateway->attach((Thread*) this);
_sensorNetwork = _gateway->getSensorNetwork();
setTaskName("ClientRecvTask");
}
ClientRecvTask::~ClientRecvTask()
{
}
/**
* Initialize SensorNetwork
*/
void ClientRecvTask::initialize(int argc, char** argv)
{
if ( _sensorNetwork->initialize() < 0 )
{
throw Exception(" Can't open the sensor network.\n");
}
}
/*
* Receive a packet from clients via sensor netwwork
* and generate a event to execute the packet handling procedure
* and creats a event to execute the packet handling procedure
* of MQTTSNPacketHandlingTask.
*/
void ClientRecvTask::run()
@@ -63,6 +54,7 @@ void ClientRecvTask::run()
int clientType = adpMgr->isAggregaterActive() ? AGGREGATER_TYPE : TRANSPEARENT_TYPE;
ClientList* clientList = _gateway->getClientList();
EventQue* packetEventQue = _gateway->getPacketEventQue();
EventQue* clientsendQue = _gateway->getClientSendQue();
char buf[128];
@@ -77,7 +69,7 @@ void ClientRecvTask::run()
if (CHK_SIGINT)
{
WRITELOG("\n%s ClientRecvTask stopped.", currentDateTime());
WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
delete packet;
return;
}
@@ -104,12 +96,11 @@ void ClientRecvTask::run()
continue;
}
SensorNetAddress* senderAddr = _gateway->getSensorNetwork()->getSenderAddress();
SensorNetAddress senderAddr = *_gateway->getSensorNetwork()->getSenderAddress();
if (packet->getType() == MQTTSN_ENCAPSULATED)
{
fwd = _gateway->getAdapterManager()->getForwarderList()->getForwarder(senderAddr);
fwd = _gateway->getAdapterManager()->getForwarderList()->getForwarder(&senderAddr);
if (fwd != nullptr)
{
@@ -131,7 +122,7 @@ void ClientRecvTask::run()
if (qosm1Proxy->isActive())
{
const char* clientName = qosm1Proxy->getClientId(senderAddr);
const char *clientName = qosm1Proxy->getClientId(&senderAddr);
if (clientName != nullptr)
{
@@ -140,7 +131,8 @@ void ClientRecvTask::run()
if (!packet->isQoSMinusPUBLISH())
{
log(clientName, packet);
WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, senderAddr->sprint(buf), ERRMSG_FOOTER);
WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n",
ERRMSG_HEADER, clientName, senderAddr.sprint(buf), ERRMSG_FOOTER);
delete packet;
continue;
}
@@ -149,18 +141,35 @@ void ClientRecvTask::run()
if (client == nullptr)
{
client = _gateway->getClientList()->getClient(senderAddr);
client = _gateway->getClientList()->getClient(&senderAddr);
}
}
if (client != nullptr)
{
/* write log and post Event */
log(client, packet, 0);
if (client->isDisconnect() && packet->getType() != MQTTSN_CONNECT)
{
WRITELOG("%s MQTTSNGWClientRecvTask %s is not connecting.%s\n",
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
/* send DISCONNECT to the client, if it is not connected */
MQTTSNPacket* snPacket = new MQTTSNPacket();
snPacket->setDISCONNECT(0);
ev = new Event();
ev->setClientSendEvent(client, snPacket);
clientsendQue->post(ev);
delete packet;
continue;
}
else
{
ev = new Event();
ev->setClientRecvEvent(client, packet);
packetEventQue->post(ev);
}
}
else
{
/* new client */
@@ -171,7 +180,9 @@ void ClientRecvTask::run()
if (!packet->getCONNECT(&data))
{
log(0, packet, &data.clientID);
WRITELOG("%s CONNECT message form %s is incorrect.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER);
WRITELOG("%s CONNECT message form %s is incorrect.%s\n",
ERRMSG_HEADER, senderAddr.sprint(buf),
ERRMSG_FOOTER);
delete packet;
continue;
}
@@ -195,13 +206,13 @@ void ClientRecvTask::run()
/* Authentication is not required */
if (_gateway->getGWParams()->clientAuthentication == false)
{
client->setClientAddress(senderAddr);
client->setClientAddress(&senderAddr);
}
}
else
{
/* create a new client */
client = clientList->createClient(senderAddr, &data.clientID, clientType);
client = clientList->createClient(&senderAddr, &data.clientID, clientType);
}
}
@@ -209,7 +220,9 @@ void ClientRecvTask::run()
if (client == nullptr)
{
WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER);
WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n",
ERRMSG_HEADER, senderAddr.sprint(buf),
ERRMSG_FOOTER);
delete packet;
continue;
}
@@ -224,11 +237,16 @@ void ClientRecvTask::run()
log(client, packet, 0);
if (packet->getType() == MQTTSN_ENCAPSULATED)
{
WRITELOG("%s MQTTSNGWClientRecvTask Forwarder(%s) is not declared by ClientList file. message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER);
WRITELOG(
"%s MQTTSNGWClientRecvTask Forwarder(%s) is not declared by ClientList file. message has been discarded.%s\n",
ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf),
ERRMSG_FOOTER);
}
else
{
WRITELOG("%s MQTTSNGWClientRecvTask Client(%s) is not connecting. message has been discarded.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER);
WRITELOG("%s MQTTSNGWClientRecvTask Client(%s) is not connecting. message has been discarded.%s\n",
ERRMSG_HEADER, senderAddr.sprint(buf),
ERRMSG_FOOTER);
}
delete packet;
}
@@ -275,11 +293,13 @@ void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet)
switch (packet->getType())
{
case MQTTSN_SEARCHGW:
WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, CLIENT, packet->print(pbuf));
WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(),
LEFTARROW, CLIENT, packet->print(pbuf));
break;
case MQTTSN_CONNECT:
case MQTTSN_PINGREQ:
WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));
WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(),
LEFTARROW, clientId, packet->print(pbuf));
break;
case MQTTSN_DISCONNECT:
case MQTTSN_WILLTOPICUPD:
@@ -292,14 +312,16 @@ void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet)
case MQTTSN_REGISTER:
case MQTTSN_SUBSCRIBE:
case MQTTSN_UNSUBSCRIBE:
WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf));
WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId,
packet->print(pbuf));
break;
case MQTTSN_REGACK:
case MQTTSN_PUBACK:
case MQTTSN_PUBREC:
case MQTTSN_PUBREL:
case MQTTSN_PUBCOMP:
WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf));
WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId,
packet->print(pbuf));
break;
case MQTTSN_ENCAPSULATED:
WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));

View File

@@ -31,11 +31,11 @@ ClientSendTask::ClientSendTask(Gateway* gateway)
_gateway = gateway;
_gateway->attach((Thread*) this);
_sensorNetwork = _gateway->getSensorNetwork();
setTaskName("ClientSendTask");
}
ClientSendTask::~ClientSendTask()
{
// WRITELOG("ClientSendTask is deleted normally.\r\n");
}
void ClientSendTask::run()
@@ -51,7 +51,7 @@ void ClientSendTask::run()
if (ev->getEventType() == EtStop || _gateway->IsStopping())
{
WRITELOG("\n%s ClientSendTask stopped.", currentDateTime());
WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
delete ev;
break;
}
@@ -85,7 +85,8 @@ void ClientSendTask::run()
if (rc < 0)
{
WRITELOG("%s ClientSendTask can't send a packet to the client %s. Error=%d%s\n",
ERRMSG_HEADER, (client ? (const char*)client->getClientId() : UNKNOWNCL ), errno, ERRMSG_FOOTER);
ERRMSG_HEADER, (client ? (const char*) client->getClientId() : UNKNOWNCL),
errno, ERRMSG_FOOTER);
}
}
delete ev;
@@ -102,7 +103,8 @@ void ClientSendTask::log(Client* client, MQTTSNPacket* packet)
{
case MQTTSN_ADVERTISE:
case MQTTSN_GWINFO:
WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, CLIENTS, packet->print(pbuf));
WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW,
CLIENTS, packet->print(pbuf));
break;
case MQTTSN_CONNACK:
case MQTTSN_DISCONNECT:
@@ -115,7 +117,8 @@ void ClientSendTask::log(Client* client, MQTTSNPacket* packet)
break;
case MQTTSN_REGISTER:
case MQTTSN_PUBLISH:
WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId, packet->print(pbuf));
WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId,
packet->print(pbuf));
break;
case MQTTSN_REGACK:
case MQTTSN_PUBACK:
@@ -124,7 +127,8 @@ void ClientSendTask::log(Client* client, MQTTSNPacket* packet)
case MQTTSN_PUBCOMP:
case MQTTSN_SUBACK:
case MQTTSN_UNSUBACK:
WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId, packet->print(pbuf));
WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId,
packet->print(pbuf));
break;
default:
break;

View File

@@ -125,7 +125,8 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet
/* renew the TopicList */
if (topics)
{
topics->eraseNormal();;
topics->eraseNormal();
;
}
client->setSessionStatus(true);
}
@@ -146,7 +147,8 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet
/* CONNECT message was not qued in.
* create CONNECT message & send it to the broker */
MQTTGWPacket* mqMsg = new MQTTGWPacket();
mqMsg->setCONNECT(client->getConnectData(), (unsigned char*)_gateway->getGWParams()->loginId, (unsigned char*)_gateway->getGWParams()->password);
mqMsg->setCONNECT(client->getConnectData(), (unsigned char*) _gateway->getGWParams()->loginId,
(unsigned char*) _gateway->getGWParams()->password);
Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, mqMsg);
_gateway->getBrokerSendQue()->post(ev1);
@@ -209,7 +211,8 @@ void MQTTSNConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet
/* create CONNECT message */
MQTTGWPacket* mqttPacket = new MQTTGWPacket();
connectData->willMsg = client->getWillMsg();
mqttPacket->setCONNECT(connectData, (unsigned char*)_gateway->getGWParams()->loginId, (unsigned char*)_gateway->getGWParams()->password);
mqttPacket->setCONNECT(connectData, (unsigned char*) _gateway->getGWParams()->loginId,
(unsigned char*) _gateway->getGWParams()->password);
/* Send CONNECT to the broker */
Event* evt = new Event();

View File

@@ -37,7 +37,7 @@ namespace MQTTSNGW
/*=================================
* MQTT-SN Parametrs
==================================*/
#define MAX_CLIENTS (100) // Number of Clients can be handled.
#define MAX_CLIENTS (100) // Default number of Clients can be handled.
#define MAX_CLIENTID_LENGTH (64) // Max length of clientID
#define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages
#define MAX_MESSAGEID_TABLE_SIZE (500) // Number of MessageIdTable size
@@ -60,14 +60,19 @@ typedef unsigned int uint32_t;
/*=================================
* Log controls
==================================*/
//#define DEBUG // print out log for debug
//#define DEBUG_NWSTACK // print out SensorNetwork log
#ifdef DEBUG
//#define DEBUG_MQTTSN // print out log for debug
//#define DEBUG_NW // print out SensorNetwork log
#ifdef DEBUG_MQTTSN
#define DEBUGLOG(...) printf(__VA_ARGS__)
#else
#define DEBUGLOG(...)
#endif
#ifdef DEBUG_NW
#define D_NWSTACK(...) printf(__VA_ARGS__)
#else
#define D_NWSTACK(...)
#endif
}
#endif /* MQTTSNGWDEFINES_H_ */

View File

@@ -21,10 +21,8 @@
using namespace MQTTSNGW;
using namespace std;
WirelessNodeId::WirelessNodeId()
:
_len{0},
_nodeId{0}
WirelessNodeId::WirelessNodeId() :
_len { 0 }, _nodeId { 0 }
{
}
@@ -77,16 +75,14 @@ bool WirelessNodeId::operator ==(WirelessNodeId& id)
/*
* Class MQTTSNGWEncapsulatedPacket
*/
MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket()
: _mqttsn{0},
_ctrl{0}
MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket() :
_mqttsn { 0 }, _ctrl { 0 }
{
}
MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket(MQTTSNPacket* packet)
: _mqttsn{packet},
_ctrl{0}
MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket(MQTTSNPacket* packet) :
_mqttsn { packet }, _ctrl { 0 }
{
}

View File

@@ -60,6 +60,4 @@ private:
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWENCAPSULATEDPACKET_H_ */

View File

@@ -44,14 +44,12 @@ ForwarderList::~ForwarderList()
}
}
void ForwarderList::initialize(Gateway* gw)
{
/* Create Fowarders from clients.conf */
gw->getClientList()->setClientList(FORWARDER_TYPE);
}
Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr)
{
Forwarder* p = _head;
@@ -251,10 +249,8 @@ SensorNetAddress* Forwarder::getSensorNetAddr(void)
* Class ForwardedClient
*/
ForwarderElement::ForwarderElement()
: _client{0}
, _wirelessNodeId{0}
, _next{0}
ForwarderElement::ForwarderElement() :
_client { 0 }, _wirelessNodeId { 0 }, _next { 0 }
{
}

View File

@@ -22,7 +22,6 @@
#include "MQTTSNGWEncapsulatedPacket.h"
#include "SensorNetwork.h"
namespace MQTTSNGW
{
class Gateway;
@@ -94,6 +93,4 @@ private:
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWFORWARDER_H_ */

View File

@@ -115,7 +115,6 @@ MessageIdElement* MessageIdTable::find(Client* client, uint16_t clientMsgId)
return p;
}
Client* MessageIdTable::getClientMsgId(uint16_t msgId, uint16_t* clientMsgId)
{
Client* clt = nullptr;
@@ -179,7 +178,6 @@ void MessageIdTable::clear(MessageIdElement* elm)
}
}
uint16_t MessageIdTable::getMsgId(Client* client, uint16_t clientMsgId)
{
uint16_t msgId = 0;
@@ -194,18 +192,14 @@ uint16_t MessageIdTable::getMsgId(Client* client, uint16_t clientMsgId)
/*===============================
* Class MessageIdElement
===============================*/
MessageIdElement::MessageIdElement(void)
: _msgId{0}
, _clientMsgId {0}
, _client {nullptr}
, _next {nullptr}
, _prev {nullptr}
MessageIdElement::MessageIdElement(void) :
_msgId { 0 }, _clientMsgId { 0 }, _client { nullptr }, _next { nullptr }, _prev { nullptr }
{
}
MessageIdElement::MessageIdElement(uint16_t msgId, Client* client, uint16_t clientMsgId)
: MessageIdElement()
MessageIdElement::MessageIdElement(uint16_t msgId, Client* client, uint16_t clientMsgId) :
MessageIdElement()
{
_msgId = msgId;
_client = client;

View File

@@ -37,7 +37,8 @@ public:
MessageIdTable();
~MessageIdTable();
MessageIdElement* add(Aggregater* aggregater, Client* client, uint16_t clientMsgId);
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);
@@ -72,7 +73,6 @@ private:
MessageIdElement* _prev;
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWMESSAGEIDTABLE_H_ */

View File

@@ -100,10 +100,6 @@ int MQTTSNPacket::recv(SensorNetwork* network)
{
len = desirialize(buf, len);
}
else
{
len = 0;
}
return len;
}
@@ -149,8 +145,7 @@ int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration)
{
unsigned char buf[5];
int buflen = sizeof(buf);
int len = MQTTSNSerialize_advertise(buf, buflen, (unsigned char) gatewayid,
(unsigned short) duration);
int len = MQTTSNSerialize_advertise(buf, buflen, (unsigned char) gatewayid, (unsigned short) duration);
return desirialize(buf, len);
}
@@ -205,8 +200,7 @@ int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* to
{
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
int buflen = sizeof(buf);
int len = MQTTSNSerialize_register(buf, buflen, (unsigned short) topicId, (unsigned short) msgId,
topicName);
int len = MQTTSNSerialize_register(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, topicName);
return desirialize(buf, len);
}
@@ -214,18 +208,17 @@ int MQTTSNPacket::setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode
{
unsigned char buf[7];
int buflen = sizeof(buf);
int len = MQTTSNSerialize_regack(buf, buflen, (unsigned short) topicId, (unsigned short) msgId,
(unsigned char) returnCode);
int len = MQTTSNSerialize_regack(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode);
return desirialize(buf, len);
}
int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, MQTTSN_topicid topic,
uint8_t* payload, uint16_t payloadlen)
int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, MQTTSN_topicid topic, uint8_t* payload,
uint16_t payloadlen)
{
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
int buflen = sizeof(buf);
int len = MQTTSNSerialize_publish(buf, buflen, (unsigned char) dup, qos, (unsigned char) retained,
(unsigned short) msgId, topic, (unsigned char*) payload, (int) payloadlen);
int len = MQTTSNSerialize_publish(buf, buflen, (unsigned char) dup, qos, (unsigned char) retained, (unsigned short) msgId,
topic, (unsigned char*) payload, (int) payloadlen);
return desirialize(buf, len);
}
@@ -233,8 +226,7 @@ int MQTTSNPacket::setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode
{
unsigned char buf[7];
int buflen = sizeof(buf);
int len = MQTTSNSerialize_puback(buf, buflen, (unsigned short) topicId, (unsigned short) msgId,
(unsigned char) returnCode);
int len = MQTTSNSerialize_puback(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode);
return desirialize(buf, len);
}
@@ -266,8 +258,8 @@ int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t r
{
unsigned char buf[8];
int buflen = sizeof(buf);
int len = MQTTSNSerialize_suback(buf, buflen, qos, (unsigned short) topicId,
(unsigned short) msgId, (unsigned char) returnCode);
int len = MQTTSNSerialize_suback(buf, buflen, qos, (unsigned short) topicId, (unsigned short) msgId,
(unsigned char) returnCode);
return desirialize(buf, len);
}
@@ -354,26 +346,26 @@ int MQTTSNPacket::getWILLMSG(MQTTSNString* willmsg)
int MQTTSNPacket::getREGISTER(uint16_t* topicId, uint16_t* msgId, MQTTSNString* topicName)
{
return MQTTSNDeserialize_register((unsigned short*) topicId, (unsigned short*) msgId, topicName,
_buf, _bufLen);
return MQTTSNDeserialize_register((unsigned short*) topicId, (unsigned short*) msgId, topicName, _buf, _bufLen);
}
int MQTTSNPacket::getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode)
{
return MQTTSNDeserialize_regack((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf, _bufLen);
return MQTTSNDeserialize_regack((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf,
_bufLen);
}
int MQTTSNPacket::getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId, MQTTSN_topicid* topic,
uint8_t** payload, int* payloadlen)
{
return MQTTSNDeserialize_publish((unsigned char*) dup, qos, (unsigned char*) retained, (unsigned short*) msgId,
topic, (unsigned char**) payload, (int*) payloadlen, _buf, _bufLen);
return MQTTSNDeserialize_publish((unsigned char*) dup, qos, (unsigned char*) retained, (unsigned short*) msgId, topic,
(unsigned char**) payload, (int*) payloadlen, _buf, _bufLen);
}
int MQTTSNPacket::getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode)
{
return MQTTSNDeserialize_puback((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode,
_buf, _bufLen);
return MQTTSNDeserialize_puback((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf,
_bufLen);
}
int MQTTSNPacket::getACK(uint16_t* msgId)

View File

@@ -22,6 +22,7 @@
namespace MQTTSNGW
{
class SensorNetwork;
class MQTTSNPacket
{
@@ -53,7 +54,8 @@ public:
int setPUBREC(uint16_t msgId);
int setPUBREL(uint16_t msgId);
int setPUBCOMP(uint16_t msgId);
int setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode);
int setSUBACK(int qos, uint16_t topicId, uint16_t msgId,
uint8_t returnCode);
int setUNSUBACK(uint16_t msgId);
int setPINGRESP(void);
int setDISCONNECT(uint16_t duration);
@@ -66,19 +68,23 @@ public:
int getSERCHGW(uint8_t* radius);
int getCONNECT(MQTTSNPacket_connectData* option);
int getCONNACK(uint8_t* returnCode);
int getWILLTOPIC(int* willQoS, uint8_t* willRetain, MQTTSNString* willTopic);
int getWILLTOPIC(int* willQoS, uint8_t* willRetain,
MQTTSNString* willTopic);
int getWILLMSG(MQTTSNString* willmsg);
int getREGISTER(uint16_t* topicId, uint16_t* msgId, MQTTSNString* topicName);
int getREGISTER(uint16_t* topicId, uint16_t* msgId,
MQTTSNString* topicName);
int getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode);
int getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId,
MQTTSN_topicid* topic, unsigned char** payload, int* payloadlen);
int getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode);
int getACK(uint16_t* msgId);
int getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId, MQTTSN_topicid* topicFilter);
int getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId,
MQTTSN_topicid* topicFilter);
int getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter);
int getPINGREQ(void);
int getDISCONNECT(uint16_t* duration);
int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic);
int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain,
MQTTSNString* willTopic);
int getWILLMSGUPD(MQTTSNString* willMsg);
bool isAccepted(void);

View File

@@ -38,6 +38,7 @@ using namespace MQTTSNGW;
#define EVENT_QUE_TIME_OUT 2000 // 2000 msecs
char* currentDateTime(void);
/*=====================================
Class PacketHandleTask
=====================================*/
@@ -54,6 +55,7 @@ PacketHandleTask::PacketHandleTask(Gateway* gateway)
_mqttsnSubscribe = new MQTTSNSubscribeHandler(_gateway);
_mqttsnAggrConnection = new MQTTSNAggregateConnectionHandler(_gateway);
setTaskName("PacketHandleTask");
}
/**
@@ -113,7 +115,7 @@ void PacketHandleTask::run()
if (ev->getEventType() == EtStop)
{
WRITELOG("\n%s PacketHandleTask stopped.", currentDateTime());
WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
delete ev;
return;
}
@@ -155,7 +157,6 @@ void PacketHandleTask::run()
transparentPacketHandler(client, snPacket);
}
/* Reset the Timer for PINGREQ. */
client->updateStatus(snPacket);
}
@@ -166,7 +167,6 @@ void PacketHandleTask::run()
brPacket = ev->getMQTTGWPacket();
DEBUGLOG(" PacketHandleTask gets %s %s from the broker.\n", brPacket->getName(), brPacket->getMsgId(msgId));
if (client->isAggregater())
{
aggregatePacketHandler(client, brPacket);
@@ -180,8 +180,6 @@ void PacketHandleTask::run()
}
}
void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTSNPacket* packet)
{
switch (packet->getType())
@@ -239,7 +237,6 @@ void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTSNPacket* packe
}
}
void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTGWPacket* packet)
{
switch (packet->getType())
@@ -333,7 +330,6 @@ void PacketHandleTask::transparentPacketHandler(Client*client, MQTTSNPacket* pac
}
}
void PacketHandleTask::transparentPacketHandler(Client*client, MQTTGWPacket* packet)
{
switch (packet->getType())

View File

@@ -60,7 +60,8 @@ private:
void transparentPacketHandler(Client*client, MQTTSNPacket* packet);
void transparentPacketHandler(Client*client, MQTTGWPacket* packet);
Gateway* _gateway {nullptr};
Gateway* _gateway
{ nullptr };
Timer _advertiseTimer;
Timer _sendUnixTimer;
MQTTGWConnectionHandler* _mqttConnection { nullptr };
@@ -69,11 +70,9 @@ private:
MQTTSNConnectionHandler* _mqttsnConnection { nullptr };
MQTTSNPublishHandler* _mqttsnPublish { nullptr };
MQTTSNSubscribeHandler* _mqttsnSubscribe { nullptr };
MQTTSNAggregateConnectionHandler* _mqttsnAggrConnection { nullptr };
};
}
#endif /* MQTTSNGWPACKETHANDLETASK_H_ */

View File

@@ -13,10 +13,10 @@
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <stdarg.h>
#include <signal.h>
#include <Timer.h>
@@ -57,6 +57,8 @@ Process::Process()
_configDir = CONFIG_DIRECTORY;
_configFile = CONFIG_FILE;
_log = 0;
_rbsem = NULL;
_rb = NULL;
}
Process::~Process()
@@ -98,7 +100,7 @@ void Process::initialize(int argc, char** argv)
}
else
{
_configFile = config.substr(pos + 1, config.size() - pos - 1);;
_configFile = config.substr(pos + 1, config.size() - pos - 1);
_configDir = config.substr(0, pos + 1);
}
}
@@ -155,6 +157,8 @@ int Process::getParam(const char* parameter, char* value)
{
char str[MQTTSNGW_PARAM_MAX];
char param[MQTTSNGW_PARAM_MAX];
memset(str, 0, sizeof(str));
memset(param, 0, sizeof(param));
FILE *fp;
int i = 0, j = 0;
@@ -162,27 +166,41 @@ int Process::getParam(const char* parameter, char* value)
if ((fp = fopen(configPath.c_str(), "r")) == NULL)
{
throw Exception("No config file:[" + configPath + "]\n");
throw Exception("Config file not found:\n\nUsage: Command -f path/config_file_name\n", 0);
}
int paramlen = strlen(parameter);
while (true)
{
int pos = 0;
int len = 0;
if (fgets(str, MQTTSNGW_PARAM_MAX - 1, fp) == NULL)
{
fclose(fp);
return -3;
}
if (!strncmp(str, parameter, strlen(parameter)))
if (str[0] == '#' || str[0] == '\n')
{
while (str[i++] != '=')
{
;
continue;
}
while (str[i] != '\n')
len = strlen(str);
for (pos = 0; i < len; pos++)
{
param[j++] = str[i++];
if (str[pos] == '=')
{
break;
}
param[j] = '\0';
}
if (pos == paramlen)
{
if (strncmp(str, parameter, paramlen) == 0)
{
strcpy(param, str + pos + 1);
param[len - pos - 2] = '\0';
for (i = strlen(param) - 1; i >= 0 && isspace(param[i]); i--)
;
@@ -201,6 +219,7 @@ int Process::getParam(const char* parameter, char* value)
return 0;
}
}
}
fclose(fp);
return -2;
}
@@ -277,8 +296,6 @@ void MultiTaskProcess::run(void)
_threadList[i]->start();
}
try
{
while (true)
{
if (theProcess->checkSignal() == SIGINT)
@@ -288,15 +305,6 @@ void MultiTaskProcess::run(void)
sleep(1);
}
}
catch(Exception* ex)
{
ex->writeMessage();
}
catch(...)
{
throw;
}
}
void MultiTaskProcess::waitStop(void)
{
@@ -314,6 +322,11 @@ void MultiTaskProcess::threadStopped(void)
}
void MultiTaskProcess::abort(void)
{
signalHandler(SIGINT);
}
void MultiTaskProcess::attach(Thread* thread)
{
_mutex.lock();
@@ -325,7 +338,7 @@ void MultiTaskProcess::attach(Thread* thread)
else
{
_mutex.unlock();
throw Exception("Full of Threads");
throw Exception("The maximum number of threads has been exceeded.", -1);
}
_mutex.unlock();
}
@@ -335,40 +348,26 @@ int MultiTaskProcess::getParam(const char* parameter, char* value)
_mutex.lock();
int rc = Process::getParam(parameter, value);
_mutex.unlock();
if (rc == -1)
{
throw Exception("No config file.");
}
return rc;
}
/*=====================================
Class Exception
======================================*/
Exception::Exception(const string& message)
Exception::Exception(const char* message, const int errNo)
{
_message = message;
_exNo = 0;
_fileName = 0;
_functionName = 0;
_line = 0;
}
Exception::Exception(const int exNo, const string& message)
{
_message = message;
_exNo = exNo;
_errNo = errNo;
_fileName = nullptr;
_functionName = nullptr;
_line = 0;
}
Exception::Exception(const int exNo, const string& message, const char* file,
const char* function, const int line)
Exception::Exception(const char* message, const int errNo, const char* file, const char* function, const int line)
{
_message = message;
_exNo = exNo;
_fileName = file;
_errNo = errNo;
_fileName = getFileName(file);
;
_functionName = function;
_line = line;
}
@@ -380,7 +379,7 @@ Exception::~Exception() throw ()
const char* Exception::what() const throw ()
{
return _message.c_str();
return _message;
}
const char* Exception::getFileName()
@@ -398,20 +397,49 @@ const int Exception::getLineNo()
return _line;
}
const int Exception::getExceptionNo()
const int Exception::getErrNo()
{
return _exNo;
return _errNo;
}
void Exception::writeMessage()
{
if (getExceptionNo() == 0 )
if (_fileName == nullptr)
{
WRITELOG("%s %s\n", currentDateTime(), what());
if (_errNo == 0)
{
WRITELOG("%s%s %s%s\n", currentDateTime(), RED_HDR, _message, CLR_HDR);
}
else
{
WRITELOG("%s:%-6d %s line %-4d %s() : %s\n", currentDateTime(), getExceptionNo(),
getFileName(), getLineNo(), getFunctionName(), what());
WRITELOG("%s%s %s.\n errno=%d : %s%s\n", currentDateTime(), RED_HDR, _message, _errNo,
strerror(_errNo), CLR_HDR);
}
}
else
{
if (_errNo == 0)
{
WRITELOG("%s%s %s. %s line %-4d %s()%s\n", currentDateTime(), RED_HDR, _message, _fileName, _line, _functionName,
CLR_HDR);
}
else
{
WRITELOG("%s%s %s. %s line %-4d %s()\n errno=%d : %s%s\n", currentDateTime(), RED_HDR, _message,
_fileName, _line, _functionName, _errNo, strerror(_errNo), CLR_HDR);
}
}
}
const char* Exception::getFileName(const char* file)
{
for (int len = strlen(file); len > 0; len--)
{
if (*(file + len) == '/')
{
return file + len + 1;
}
}
return file;
}

View File

@@ -41,6 +41,8 @@ namespace MQTTSNGW
#define WRITELOG theProcess->putLog
#define CHK_SIGINT (theProcess->checkSignal() == SIGINT)
#define UNUSED(x) ((void)(x))
#define EXCEPTION(...) Exception(__VA_ARGS__, __FILE__, __func__, __LINE__)
/*=================================
Class Process
==================================*/
@@ -86,6 +88,7 @@ public:
void waitStop(void);
void threadStopped(void);
void attach(Thread* thread);
void abort(void);
private:
Thread* _threadList[MQTTSNGW_MAX_TASK];
@@ -100,27 +103,25 @@ private:
class Exception: public exception
{
public:
Exception(const string& message);
Exception(const int exNo, const string& message);
Exception(const int exNo, const string& message,
const char* file, const char* func, const int line);
Exception(const char* message, const int errNo);
Exception(const char* message, const int errNo, const char* file, const char* func, int line);
virtual ~Exception() throw ();
const char* getFileName();
const char* getFunctionName();
const int getLineNo();
const int getExceptionNo();
const int getErrNo();
virtual const char* what() const throw ();
void writeMessage();
private:
int _exNo;
string _message;
const char* getFileName(const char* file);
int _errNo;
const char* _message;
const char* _fileName;
const char* _functionName;
int _line;
};
/*=====================================
Class QueElement
====================================*/
@@ -263,7 +264,8 @@ private:
#define TREE23_TRI_NODE (3)
template<typename K, typename V>
class Tree23Elm{
class Tree23Elm
{
template<typename T, typename U> friend class Tree23;
public:
Tree23Elm()
@@ -292,9 +294,9 @@ private:
V* _val;
};
template<typename K, typename V>
class Tree23Node{
class Tree23Node
{
template<typename S, typename W> friend class Tree23;
public:
Tree23Node(const int type)
@@ -320,7 +322,8 @@ public:
_left = _midle = _right = NULL;
}
Tree23Node(const int type, Tree23Elm<K, V>* telm, Tree23Node<K, V>* left, Tree23Node<K, V>* right)
Tree23Node(const int type, Tree23Elm<K, V>* telm, Tree23Node<K, V>* left,
Tree23Node<K, V>* right)
{
_type = type;
_telm0 = telm;
@@ -330,7 +333,9 @@ public:
_right = right;
}
Tree23Node(const int type, Tree23Elm<K, V>* telm0, Tree23Elm<K, V>* telm1, Tree23Node<K, V>* left, Tree23Node<K, V>* midle, Tree23Node<K, V>* right)
Tree23Node(const int type, Tree23Elm<K, V>* telm0, Tree23Elm<K, V>* telm1,
Tree23Node<K, V>* left, Tree23Node<K, V>* midle,
Tree23Node<K, V>* right)
{
_type = type;
_telm0 = telm0;
@@ -355,7 +360,8 @@ private:
};
template<typename K, typename V>
class Tree23{
class Tree23
{
public:
Tree23()
{
@@ -534,7 +540,8 @@ public:
switch (node->_type)
{
case 2:
if ( cmp0 < 0 ) node = node->_left;
if (cmp0 < 0)
node = node->_left;
else if (cmp0 == 0)
{
return true;
@@ -574,7 +581,6 @@ public:
return false;
}
V* getVal(K* key)
{
Tree23Node<K, V>* node = _root;
@@ -634,7 +640,8 @@ private:
Tree23Node<K, V>* n = node->_left;
if (n != NULL && n->_type == TREE23_INSERT_ACTIVE)
{
return new Tree23Node<K, V>(TREE23_TRI_NODE, n->_telm0, node->_telm0, n->_left, n->_right, node->_right);
return new Tree23Node<K, V>(TREE23_TRI_NODE, n->_telm0,
node->_telm0, n->_left, n->_right, node->_right);
}
return node;
}
@@ -645,8 +652,10 @@ private:
if (n != NULL && n->_type == TREE23_INSERT_ACTIVE)
{
n->_type = TREE23_BI_NODE;
Tree23Node<K, V>* nn = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1, node->_midle, node->_right);
return new Tree23Node<K, V>(TREE23_INSERT_ACTIVE, node->_telm0, n, nn);
Tree23Node<K, V>* nn = new Tree23Node<K, V>(TREE23_BI_NODE,
node->_telm1, node->_midle, node->_right);
return new Tree23Node<K, V>(TREE23_INSERT_ACTIVE, node->_telm0, n,
nn);
}
return node;
}
@@ -656,7 +665,8 @@ private:
Tree23Node<K, V>* n = node->_right;
if (n != NULL && n->_type == TREE23_INSERT_ACTIVE)
{
return new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0, n->_telm0, node->_left, n->_left, n->_right);
return new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0,
n->_telm0, node->_left, n->_left, n->_right);
}
return node;
}
@@ -664,10 +674,13 @@ private:
Tree23Node<K, V>* addRight3(Tree23Node<K, V>* node)
{
Tree23Node<K, V>* n = node->_right;
if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) {
if (n != NULL && n->_type == TREE23_INSERT_ACTIVE)
{
n->_type = TREE23_BI_NODE;
Tree23Node<K, V>* nn = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, node->_left, node->_midle);
return new Tree23Node<K, V>(TREE23_INSERT_ACTIVE, node->_telm1, nn, n);
Tree23Node<K, V>* nn = new Tree23Node<K, V>(TREE23_BI_NODE,
node->_telm0, node->_left, node->_midle);
return new Tree23Node<K, V>(TREE23_INSERT_ACTIVE, node->_telm1, nn,
n);
}
return node;
}
@@ -677,14 +690,15 @@ private:
Tree23Node<K, V>* n = node->_midle;
if (n != NULL && n->_type == TREE23_INSERT_ACTIVE)
{
n->_left = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, node->_left, n->_left);
n->_right = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1, n->_right, node->_right);
n->_left = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0,
node->_left, n->_left);
n->_right = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1,
n->_right, node->_right);
return n;
}
return node;
}
Tree23Node<K, V>* removeMax(Tree23Node<K, V>* node, Tree23Elm<K, V>* elm)
{
if (node->_right == NULL)
@@ -719,7 +733,6 @@ private:
return NULL;
}
Tree23Node<K, V>* removeLeft2(Tree23Node<K, V>* node)
{
Tree23Node<K, V>* n = node->_left;
@@ -733,12 +746,16 @@ private:
switch (r->_type)
{
case 2:
midle = new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0, r->_telm0, n->_midle, r->_left, r->_right);
midle = new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0,
r->_telm0, n->_midle, r->_left, r->_right);
return new Tree23Node<K, V>(TREE23_DELETE_ACTIVE, midle);
case 3:
left = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, n->_midle, r->_left);
right = new Tree23Node<K, V>(TREE23_BI_NODE, r->_telm1, r->_midle, r->_right);
return new Tree23Node<K, V>(TREE23_BI_NODE, r->_telm0, left, right);
left = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0,
n->_midle, r->_left);
right = new Tree23Node<K, V>(TREE23_BI_NODE, r->_telm1,
r->_midle, r->_right);
return new Tree23Node<K, V>(TREE23_BI_NODE, r->_telm0, left,
right);
default:
break;
}
@@ -759,12 +776,16 @@ private:
switch (l->_type)
{
case 2:
midle = new Tree23Node<K, V>(TREE23_TRI_NODE, l->_telm0, node->_telm0, l->_left, l->_right, n->_midle);
midle = new Tree23Node<K, V>(TREE23_TRI_NODE, l->_telm0,
node->_telm0, l->_left, l->_right, n->_midle);
return new Tree23Node<K, V>(-1, midle);
case 3:
right = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, l->_right, n->_midle);
left = new Tree23Node<K, V>(TREE23_BI_NODE, l->_telm0, l->_left, l->_midle);
return new Tree23Node<K, V>(TREE23_BI_NODE, l->_telm1, left, right);
right = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0,
l->_right, n->_midle);
left = new Tree23Node<K, V>(TREE23_BI_NODE, l->_telm0, l->_left,
l->_midle);
return new Tree23Node<K, V>(TREE23_BI_NODE, l->_telm1, left,
right);
default:
break;
}
@@ -782,14 +803,20 @@ private:
Tree23Node<K, V>* left;
Tree23Node<K, V>* midle;
switch (m->_type) {
switch (m->_type)
{
case 2:
left = new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0, m->_telm0, n->_midle, m->_left, m->_right);
return new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1, left, r);
left = new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0,
m->_telm0, n->_midle, m->_left, m->_right);
return new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1, left,
r);
case 3:
left = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, n->_midle, m->_left);
midle = new Tree23Node<K, V>(TREE23_BI_NODE, m->_telm1, m->_midle, m->_right);
return new Tree23Node<K, V>(TREE23_TRI_NODE, m->_telm0, node->_telm1, left, midle, r);
left = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0,
n->_midle, m->_left);
midle = new Tree23Node<K, V>(TREE23_BI_NODE, m->_telm1,
m->_midle, m->_right);
return new Tree23Node<K, V>(TREE23_TRI_NODE, m->_telm0,
node->_telm1, left, midle, r);
default:
break;
}
@@ -809,12 +836,17 @@ private:
switch (r->_type)
{
case 2:
right = new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm1, r->_telm0, n->_midle, r->_left, r->_right);
return new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, l, right);
right = new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm1,
r->_telm0, n->_midle, r->_left, r->_right);
return new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, l,
right);
case 3:
midle = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1, n->_midle, r->_left);
right = new Tree23Node<K, V>(TREE23_BI_NODE, r->_telm1, r->_midle, r->_right);
return new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0, r->_telm0, l, midle, right);
midle = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1,
n->_midle, r->_left);
right = new Tree23Node<K, V>(TREE23_BI_NODE, r->_telm1,
r->_midle, r->_right);
return new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0,
r->_telm0, l, midle, right);
default:
break;
}
@@ -834,12 +866,17 @@ private:
switch (m->_type)
{
case 2:
right = new Tree23Node<K, V>(TREE23_TRI_NODE, m->_telm0, node->_telm1, m->_left, m->_right, n->_midle);
return new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, l, right);
right = new Tree23Node<K, V>(TREE23_TRI_NODE, m->_telm0,
node->_telm1, m->_left, m->_right, n->_midle);
return new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm0, l,
right);
case 3:
right = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1, m->_right, n->_midle);
midle = new Tree23Node<K, V>(TREE23_BI_NODE, m->_telm0, m->_left, m->_midle);
return new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0, m->_telm1, l, midle, right);
right = new Tree23Node<K, V>(TREE23_BI_NODE, node->_telm1,
m->_right, n->_midle);
midle = new Tree23Node<K, V>(TREE23_BI_NODE, m->_telm0,
m->_left, m->_midle);
return new Tree23Node<K, V>(TREE23_TRI_NODE, node->_telm0,
m->_telm1, l, midle, right);
default:
break;
}
@@ -847,7 +884,6 @@ private:
return node;
}
Tree23Node<K, V>* _root;
};
@@ -873,18 +909,23 @@ public:
{
return _elm;
}
~ListElm(){}
~ListElm()
{
}
private:
ListElm<T>* getNext(void){return _next;}
ListElm<T>* getNext(void)
{
return _next;
}
T* _elm;
ListElm<T>* _prev;
ListElm<T>* _next;
};
template<typename T>
class List{
class List
{
public:
List()
{
@@ -970,14 +1011,12 @@ public:
return _size;
}
private:
ListElm<T>* _head;
ListElm<T>* _tail;
int _size;
};
extern Process* theProcess;
extern MultiTaskProcess* theMultiTaskProcess;

View File

@@ -41,6 +41,7 @@ MQTTGWPacket* MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket*
int qos;
uint8_t retained;
uint16_t msgId;
uint16_t tid;
uint8_t* payload;
MQTTSN_topicid topicid;
int payloadlen;
@@ -66,6 +67,7 @@ MQTTGWPacket* MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket*
pub.header.bits.dup = dup;
pub.header.bits.qos = (qos == 3 ? 0 : qos);
pub.header.bits.retain = retained;
tid = topicid.data.id;
Topic* topic = nullptr;
@@ -114,12 +116,14 @@ MQTTGWPacket* MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket*
{
pub.topic = (char*) topic->getTopicName()->data();
pub.topiclen = topic->getTopicName()->length();
topicid.data.long_.name = pub.topic;
topicid.data.long_.len = pub.topiclen;
}
}
/* Save a msgId & a TopicId pare for PUBACK */
if (msgId && qos > 0 && qos < 3)
{
client->setWaitedPubTopicId(msgId, topicid.data.id, topicid.type);
client->setWaitedPubTopicId(msgId, tid, &topicid);
}
pub.payload = (char*) payload;
@@ -194,7 +198,8 @@ void MQTTSNPublishHandler::handleRegister(Client* client, MQTTSNPacket* packet)
{
uint16_t id;
uint16_t msgId;
MQTTSNString topicName = MQTTSNString_initializer;;
MQTTSNString topicName = MQTTSNString_initializer;
;
MQTTSN_topicid topicid;
if (client->isActive() || client->isAwake())
@@ -230,6 +235,7 @@ void MQTTSNPublishHandler::handleRegAck( Client* client, MQTTSNPacket* packet)
return;
}
/* get PUBLISH message */
MQTTSNPacket* regAck = client->getWaitREGACKPacketList()->getPacket(msgId);
if (regAck != nullptr)
@@ -239,6 +245,7 @@ void MQTTSNPublishHandler::handleRegAck( Client* client, MQTTSNPacket* packet)
ev->setClientSendEvent(client, regAck);
_gateway->getClientSendQue()->post(ev);
}
if (client->isHoldPingReqest() && client->getWaitREGACKPacketList()->getCount() == 0)
{
/* send PINGREQ to the broker */
@@ -253,9 +260,6 @@ void MQTTSNPublishHandler::handleRegAck( Client* client, MQTTSNPacket* packet)
}
void MQTTSNPublishHandler::handleAggregatePublish(Client* client, MQTTSNPacket* packet)
{
int msgId = 0;

View File

@@ -21,13 +21,13 @@
#include <string>
#include <string.h>
using namespace MQTTSNGW;
/*=====================================
Class QoSm1Proxy
=====================================*/
QoSm1Proxy:: QoSm1Proxy(Gateway* gw) : Adapter(gw)
QoSm1Proxy::QoSm1Proxy(Gateway* gw) :
Adapter(gw)
{
_gateway = gw;
}
@@ -37,7 +37,6 @@ QoSm1Proxy::~QoSm1Proxy(void)
}
void QoSm1Proxy::initialize(char* gwName)
{
if (_gateway->hasSecureConnection())
@@ -54,7 +53,6 @@ void QoSm1Proxy::initialize(char* gwName)
_isActive = true;
}
bool QoSm1Proxy::isActive(void)
{
return _isActive;

View File

@@ -45,9 +45,6 @@ private:
bool _isSecure { false };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWQOSM1PROXY_H_ */

View File

@@ -62,10 +62,17 @@ MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPack
if (!topic)
{
/* Search the topic in Client common topic table */
topic = _gateway->getTopics()->getTopicById(&topicFilter);
if (topic)
{
topic = client->getTopics()->add(topic->getTopicName()->c_str(), topic->getTopicId());
if (topic == nullptr)
{
WRITELOG("%s Client(%s) can't add the Topic.%s\n",
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
goto RespExit;
}
}
else
{
@@ -85,8 +92,9 @@ MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPack
topic = client->getTopics()->add(&topicFilter);
if (topic == nullptr)
{
WRITELOG("%s Client(%s) can't add the Topic.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return nullptr;
WRITELOG("%s Client(%s) can't add the Topic.%s\n",
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
goto RespExit;
}
}
topicId = topic->getTopicId();
@@ -106,7 +114,7 @@ MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPack
subscribe->setSUBSCRIBE(topicstr, (uint8_t) qos, (uint16_t) msgId);
}
client->setWaitedSubTopicId(msgId, topicId, topicFilter.type);
client->setWaitedSubTopicId(msgId, topicId, &topicFilter);
if (!client->isAggregated())
{
@@ -120,10 +128,8 @@ MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPack
return subscribe;
}
RespExit:
MQTTSNPacket* sSuback = new MQTTSNPacket();
sSuback->setSUBACK(qos, topicFilter.data.id, msgId, MQTTSN_RC_NOT_SUPPORTED);
RespExit: MQTTSNPacket* sSuback = new MQTTSNPacket();
sSuback->setSUBACK(qos, topicFilter.data.id, msgId, MQTTSN_RC_REJECTED_INVALID_TOPIC_ID);
evsuback = new Event();
evsuback->setClientSendEvent(client, sSuback);
_gateway->getClientSendQue()->post(evsuback);
@@ -146,7 +152,6 @@ MQTTGWPacket* MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPa
return nullptr;
}
if (topicFilter.type == MQTTSN_TOPIC_TYPE_SHORT)
{
char shortTopic[3];
@@ -216,7 +221,8 @@ void MQTTSNSubscribeHandler::handleAggregateSubscribe(Client* client, MQTTSNPack
if (msgId == 0)
{
WRITELOG("%s MQTTSNSubscribeHandler can't create MessageIdTableElement %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
WRITELOG("%s MQTTSNSubscribeHandler can't create MessageIdTableElement %s%s\n",
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return;
}
@@ -250,7 +256,8 @@ void MQTTSNSubscribeHandler::handleAggregateUnsubscribe(Client* client, MQTTSNPa
if (msgId == 0)
{
WRITELOG("%s MQTTSNUnsubscribeHandler can't create MessageIdTableElement %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
WRITELOG("%s MQTTSNUnsubscribeHandler can't create MessageIdTableElement %s%s\n",
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return;
}

View File

@@ -42,5 +42,4 @@ private:
}
#endif /* MQTTSNGWSUBSCRIBEHANDLER_H_ */

View File

@@ -252,7 +252,6 @@ Topic* Topics::add(const char* topicName, uint16_t id)
topicId.data.long_.name = (char*) const_cast<char*>(topicName);
topicId.data.long_.len = strlen(topicName);
Topic* topic = getTopicByName(&topicId);
if (topic)
@@ -331,7 +330,6 @@ Topic* Topics::match(const MQTTSN_topicid* topicid)
return 0;
}
void Topics::eraseNormal(void)
{
Topic* topic = _first;
@@ -398,13 +396,22 @@ uint8_t Topics::getCount(void)
/*=====================================
Class TopicIdMap
=====================================*/
TopicIdMapElement::TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type)
TopicIdMapElement::TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic)
{
_msgId = msgId;
_topicId = topicId;
_type = type;
_type = topic->type;
_wildcard = 0;
_next = nullptr;
_prev = nullptr;
if (_type == MQTTSN_TOPIC_TYPE_NORMAL)
{
if (strchr(topic->data.long_.name, '#') != 0 || strchr(topic->data.long_.name, '+') != 0)
{
_wildcard = 1;
}
}
}
TopicIdMapElement::~TopicIdMapElement()
@@ -418,9 +425,16 @@ MQTTSN_topicTypes TopicIdMapElement::getTopicType(void)
}
uint16_t TopicIdMapElement::getTopicId(void)
{
if (_wildcard > 0)
{
return 0;
}
else
{
return _topicId;
}
}
TopicIdMap::TopicIdMap()
{
@@ -456,9 +470,9 @@ TopicIdMapElement* TopicIdMap::getElement(uint16_t msgId)
return 0;
}
TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type)
TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic)
{
if ( _cnt > _maxInflight * 2 || ( topicId == 0 && type != MQTTSN_TOPIC_TYPE_SHORT ) )
if (_cnt > _maxInflight * 2 || (topicId == 0 && topic->type != MQTTSN_TOPIC_TYPE_SHORT))
{
return 0;
}
@@ -467,7 +481,7 @@ TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topi
erase(msgId);
}
TopicIdMapElement* elm = new TopicIdMapElement(msgId, topicId, type);
TopicIdMapElement* elm = new TopicIdMapElement(msgId, topicId, topic);
if (elm == 0)
{
return 0;
@@ -534,5 +548,3 @@ void TopicIdMap::clear(void)
_cnt = 0;
}

View File

@@ -24,7 +24,6 @@
namespace MQTTSNGW
{
/*=====================================
Class Topic
======================================*/
@@ -82,7 +81,7 @@ class TopicIdMapElement
{
friend class TopicIdMap;
public:
TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic);
~TopicIdMapElement();
MQTTSN_topicTypes getTopicType(void);
uint16_t getTopicId(void);
@@ -90,6 +89,7 @@ public:
private:
uint16_t _msgId;
uint16_t _topicId;
uint8_t _wildcard;
MQTTSN_topicTypes _type;
TopicIdMapElement* _next;
TopicIdMapElement* _prev;
@@ -101,7 +101,7 @@ public:
TopicIdMap();
~TopicIdMap();
TopicIdMapElement* getElement(uint16_t msgId);
TopicIdMapElement* add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
TopicIdMapElement* add(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic);
void erase(uint16_t msgId);
void clear(void);
private:
@@ -112,9 +112,6 @@ private:
int _maxInflight;
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWTOPIC_H_ */

View File

@@ -17,6 +17,6 @@
#ifndef MQTTSNGWVERSION_H_IN_
#define MQTTSNGWVERSION_H_IN_
#define PAHO_GATEWAY_VERSION "1.4.0"
#define PAHO_GATEWAY_VERSION "1.6.0"
#endif /* MQTTSNGWVERSION_H_IN_ */

View File

@@ -32,10 +32,10 @@ MQTTSNGW::Gateway* theGateway = nullptr;
Gateway::Gateway(void)
{
theGateway = this;
theMultiTaskProcess = this;
theProcess = this;
_packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS);
_clientList = new ClientList();
_clientList = new ClientList(this);
_adapterManager = new AdapterManager(this);
_topics = new Topics();
_stopFlg = false;
@@ -95,11 +95,22 @@ Gateway::~Gateway()
{
free(_params.configName);
}
if (_params.qosMinusClientListName)
{
free(_params.qosMinusClientListName);
}
if (_params.rfcommAddr)
{
free(_params.rfcommAddr);
}
if (_params.gwCertskey)
{
free(_params.gwCertskey);
}
if (_params.gwPrivatekey)
{
free(_params.gwPrivatekey);
}
if (_adapterManager)
{
@@ -109,12 +120,10 @@ Gateway::~Gateway()
{
delete _clientList;
}
if (_topics)
{
delete _topics;
}
// WRITELOG("Gateway is deleted normally.\r\n");
}
int Gateway::getParam(const char* parameter, char* value)
@@ -174,6 +183,14 @@ void Gateway::initialize(int argc, char** argv)
{
_params.rootCAfile = strdup(param);
}
if (getParam("DtlsCertsKey", param) == 0)
{
_params.gwCertskey = strdup(param);
}
if (getParam("DtlsPrivKey", param) == 0)
{
_params.gwPrivatekey = strdup(param);
}
if (getParam("GatewayID", param) == 0)
{
@@ -182,7 +199,7 @@ void Gateway::initialize(int argc, char** argv)
if (_params.gatewayId == 0 || _params.gatewayId > 255)
{
throw Exception( "Gateway::initialize: invalid Gateway Id");
throw Exception("Gateway::initialize: invalid Gateway Id", 0);
}
if (getParam("GatewayName", param) == 0)
@@ -192,7 +209,7 @@ void Gateway::initialize(int argc, char** argv)
if (_params.gatewayName == 0)
{
throw Exception( "Gateway::initialize: Gateway Name is missing.");
throw Exception("Gateway::initialize: Gateway Name is missing.", 0);
}
_params.mqttVersion = DEFAULT_MQTT_VERSION;
@@ -201,7 +218,7 @@ void Gateway::initialize(int argc, char** argv)
_params.mqttVersion = atoi(param);
}
_params.maxInflightMsgs = DEFAULT_MQTT_VERSION;
_params.maxInflightMsgs = MAX_INFLIGHTMESSAGES;
if (getParam("MaxInflightMsgs", param) == 0)
{
_params.maxInflightMsgs = atoi(param);
@@ -272,12 +289,28 @@ void Gateway::initialize(int argc, char** argv)
}
}
_params.maxClients = MAX_CLIENTS;
if (getParam("MaxNumberOfClients", param) == 0)
{
_params.maxClients = atoi(param);
}
if (getParam("RFCOMMAddress", param) == 0)
{
_params.rfcommAddr = strdup(param);
}
/* Setup max PacketEventQue size */
_packetEventQue.setMaxSize(_params.maxInflightMsgs * _params.maxClients);
/* Initialize adapters */
_adapterManager->initialize(_params.gatewayName, _params.aggregatingGw, _params.forwarder, _params.qosMinus1);
/* Setup ClientList and Predefined topics */
_clientList->initialize(_params.aggregatingGw);
/* SensorNetwork initialize */
_sensorNetwork.initialize();
}
void Gateway::run(void)
@@ -291,7 +324,6 @@ void Gateway::run(void)
WRITELOG(" *\n%s\n", PAHO_COPYRIGHT3);
WRITELOG(" * Version: %s\n", PAHO_GATEWAY_VERSION);
WRITELOG("%s\n", PAHO_COPYRIGHT4);
WRITELOG("\n%s %s has been started.\n\n", currentDateTime(), _params.gatewayName);
WRITELOG(" ConfigFile : %s\n", _params.configName);
if (_params.clientListName)
@@ -304,18 +336,24 @@ void Gateway::run(void)
WRITELOG(" PreDefFile : %s\n", _params.predefinedTopicFileName);
}
WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription());
WRITELOG(" Broker : %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure);
WRITELOG(" RootCApath : %s\n", _params.rootCApath);
WRITELOG(" RootCAfile : %s\n", _params.rootCAfile);
WRITELOG(" CertKey : %s\n", _params.certKey);
WRITELOG(" PrivateKey: %s\n\n\n", _params.privateKey);
WRITELOG(" PrivateKey : %s\n", _params.privateKey);
WRITELOG(" SensorN/W : %s\n", _sensorNetwork.getDescription());
#ifdef DTLS
WRITELOG(" DtlsCertsKey: %s\n", _params.gwCertskey);
WRITELOG(" DtlsPrivKey : %s\n", _params.gwPrivatekey);
#endif
WRITELOG(" Max Clients : %d\n\n", _params.maxClients);
WRITELOG("%s %s starts running.\n\n", currentDateTime(), _params.gatewayName);
_stopFlg = false;
/* Run Tasks until CTRL+C entred */
/* Run Tasks until CTRL+C entered or Exception occurred */
MultiTaskProcess::run();
WRITELOG("\n");
_stopFlg = true;
/* stop Tasks */
@@ -332,7 +370,7 @@ void Gateway::run(void)
/* wait until all Task stop */
MultiTaskProcess::waitStop();
WRITELOG("\n\n%s MQTT-SN Gateway stopped.\n\n", currentDateTime());
WRITELOG("\n%s MQTT-SN Gateway stopped.\n\n", currentDateTime());
_lightIndicator.allLightOff();
}
@@ -388,17 +426,14 @@ Topics* Gateway::getTopics(void)
bool Gateway::hasSecureConnection(void)
{
return ( _params.certKey
&& _params.privateKey
&& _params.rootCApath
&& _params.rootCAfile );
return (_params.certKey && _params.privateKey && _params.rootCApath && _params.rootCAfile);
}
/*=====================================
Class EventQue
=====================================*/
EventQue::EventQue()
{
}
EventQue::~EventQue()
@@ -483,7 +518,6 @@ int EventQue::size()
return sz;
}
/*=====================================
Class Event
=====================================*/
@@ -586,4 +620,3 @@ MQTTGWPacket* Event::getMQTTGWPacket(void)
return _mqttGWPacket;
}

View File

@@ -20,6 +20,7 @@
#include "MQTTSNGWProcess.h"
#include "MQTTSNPacket.h"
#include "MQTTSNGWClient.h"
#include "MQTTSNGWProcess.h"
namespace MQTTSNGW
{
@@ -28,7 +29,7 @@ namespace MQTTSNGW
==================================*/
#define PAHO_COPYRIGHT0 " * MQTT-SN Gateway"
#define PAHO_COPYRIGHT1 " * Part of Project Paho in Eclipse"
#define PAHO_COPYRIGHT2 " * (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)"
#define PAHO_COPYRIGHT2 " * (https://github.com/eclipse/paho.mqtt-sn.embedded-c.git)"
#define PAHO_COPYRIGHT3 " * Author : Tomoaki YAMAGUCHI"
#define PAHO_COPYRIGHT4 " ***************************************************************************"
/*==========================================================
@@ -76,7 +77,8 @@ namespace MQTTSNGW
====================================*/
class Client;
enum EventType{
enum EventType
{
Et_NA = 0,
EtStop,
EtTimeout,
@@ -88,8 +90,8 @@ enum EventType{
EtSensornetSend
};
class Event{
class Event
{
public:
Event();
~Event();
@@ -115,7 +117,6 @@ private:
MQTTGWPacket* _mqttGWPacket { nullptr };
};
/*=====================================
Class EventQue
====================================*/
@@ -136,8 +137,6 @@ private:
Semaphore _sem;
};
/*=====================================
Class GatewayParams
====================================*/
@@ -168,17 +167,21 @@ public:
bool aggregatingGw { false };
bool qosMinus1 { false };
bool forwarder { false };
int maxClients {0};
char* rfcommAddr { nullptr };
char* gwCertskey { nullptr };
char* gwPrivatekey { nullptr };
};
/*=====================================
Class Gateway
=====================================*/
class AdapterManager;
class ClientList;
class ClientsPool;
class Gateway: public MultiTaskProcess{
class Gateway: public MultiTaskProcess
{
public:
Gateway(void);
~Gateway();
@@ -196,24 +199,23 @@ public:
int getParam(const char* parameter, char* value);
char* getClientListFileName(void);
char* getPredefinedTopicFileName(void);
bool hasSecureConnection(void);
Topics* getTopics(void);
bool IsStopping(void);
void requestSensorNetSubTask(void);
private:
GatewayParams _params;
ClientList* _clientList {nullptr};
ClientList* _clientList;
EventQue _packetEventQue;
EventQue _brokerSendQue;
EventQue _clientSendQue;
LightIndicator _lightIndicator;
SensorNetwork _sensorNetwork;
AdapterManager* _adapterManager {nullptr};
AdapterManager* _adapterManager;
Topics* _topics;
bool _stopFlg;
};
}
#endif /* MQTTSNGATEWAY_H_ */

View File

@@ -279,6 +279,7 @@ bool Network::connect(const char* host, const char* port, const char* caPath, co
char errmsg[256];
char peer_CN[256];
bool rc;
X509* peer = nullptr;
_mutex.lock();
try
@@ -385,7 +386,7 @@ bool Network::connect(const char* host, const char* port, const char* caPath, co
throw false;
}
X509* peer = SSL_get_peer_certificate(_ssl);
peer = SSL_get_peer_certificate(_ssl);
X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, peer_CN, 256);
char* pos = peer_CN;
if ( *pos == '*')
@@ -413,7 +414,12 @@ bool Network::connect(const char* host, const char* port, const char* caPath, co
{
rc = x;
}
_mutex.unlock();
if (peer != nullptr)
{
X509_free(peer);
}
return rc;
}
@@ -650,3 +656,7 @@ bool Network::isSecure()
return _secureFlg;
}
void Network::setSecure(bool secureFlg)
{
_secureFlg = secureFlg;
}

View File

@@ -80,6 +80,7 @@ public:
bool isValid(void);
bool isSecure(void);
int getSock(void);
void setSecure(bool secureFlg);
private:
static SSL_CTX* _ctx;

View File

@@ -79,23 +79,23 @@ Mutex::Mutex(const char* fileName)
if ((_shmid = shmget(key, sizeof(pthread_mutex_t), IPC_CREAT | 0666)) < 0)
{
throw Exception( -1, "Mutex can't create a shared memory.");
throw Exception("Mutex can't create a shared memory.", -1);
}
_pmutex = (pthread_mutex_t*) shmat(_shmid, NULL, 0);
if (_pmutex == (void*) -1)
{
throw Exception( -1, "Mutex can't attach shared memory.");
throw Exception("Mutex can't attach shared memory.", -1);
}
pthread_mutexattr_init(&attr);
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) != 0)
{
throw Exception( -1, "Mutex can't set the process-shared flag");
throw Exception("Mutex can't set the process-shared flag", -1);
}
if (pthread_mutex_init(_pmutex, &attr) != 0)
{
throw Exception( -1, "Mutex can't initialize.");
throw Exception("Mutex can't initialize.", -1);
}
}
@@ -121,44 +121,37 @@ Mutex::~Mutex(void)
void Mutex::lock(void)
{
int rc = 0;
if (_pmutex)
{
pthread_mutex_lock(_pmutex);
rc = pthread_mutex_lock(_pmutex);
}
else
{
try
{
if (pthread_mutex_lock(&_mutex))
{
throw;
rc = pthread_mutex_lock(&_mutex);
}
} catch (char* errmsg)
if (rc)
{
throw Exception( -1, "The same thread can't aquire a mutex twice.");
}
throw Exception("Mutex lock error", errno);
}
}
void Mutex::unlock(void)
{
int rc = 0;
if (_pmutex)
{
pthread_mutex_unlock(_pmutex);
rc = pthread_mutex_unlock(_pmutex);
}
else
{
try
{
if (pthread_mutex_unlock(&_mutex))
{
throw;
rc = pthread_mutex_unlock(&_mutex);
}
} catch (char* errmsg)
if (rc)
{
throw Exception( -1, "Mutex can't unlock.");
}
throw Exception("Mutex lock error", errno);
}
}
@@ -225,12 +218,12 @@ NamedSemaphore::NamedSemaphore(const char* name, unsigned int val)
_psem = sem_open(name, O_CREAT, 0666, val);
if (_psem == SEM_FAILED)
{
throw Exception( -1, "Semaphore can't be created.");
throw Exception("Semaphore can't be created.", -1);
}
_name = strdup(name);
if (_name == NULL)
{
throw Exception( -1, "Semaphore can't allocate memories.");
throw Exception("Semaphore can't allocate memories.", -1);
}
}
@@ -263,11 +256,6 @@ void NamedSemaphore::timedwait(uint16_t millsec)
/*=========================================
Class RingBuffer
=========================================*/
RingBuffer::RingBuffer()
{
RingBuffer(MQTTSNGW_KEY_DIRECTORY);
}
RingBuffer::RingBuffer(const char* keyDirectory)
{
int fp = 0;
@@ -303,7 +291,7 @@ RingBuffer::RingBuffer(const char* keyDirectory)
}
else
{
throw Exception(-1, "RingBuffer can't attach shared memory.");
throw Exception("RingBuffer can't attach shared memory.", -1);
}
}
else if ((_shmid = shmget(key, PROCESS_LOG_BUFFER_SIZE, IPC_CREAT | 0666)) != -1)
@@ -318,12 +306,12 @@ RingBuffer::RingBuffer(const char* keyDirectory)
}
else
{
throw Exception(-1, "RingBuffer can't create a shared memory.");
throw Exception("RingBuffer can't create a shared memory.", -1);
}
}
else
{
throw Exception(-1, "RingBuffer can't create a shared memory.");
throw Exception( "RingBuffer can't create a shared memory.", -1);
}
_pmx = new Mutex(MQTTSNGW_RB_MUTEX_KEY);
@@ -495,7 +483,7 @@ void RingBuffer::reset()
}
else
{
throw Exception(-1, "RingBuffer can't reset. need to clear shared memory.");
throw Exception("RingBuffer can't reset. need to clear shared memory.", -1);
}
_pmx->unlock();
}
@@ -506,6 +494,7 @@ void RingBuffer::reset()
Thread::Thread()
{
_threadID = 0;
_taskName = nullptr;
}
Thread::~Thread()
@@ -539,11 +528,6 @@ int Thread::start(void)
return pthread_create(&_threadID, 0, _run, runnable);
}
void Thread::stopProcess(void)
{
theMultiTaskProcess->threadStopped();
}
void Thread::stop(void)
{
if ( _threadID )
@@ -552,3 +536,13 @@ void Thread::stop(void)
_threadID = 0;
}
}
void Thread::setTaskName(const char* name)
{
_taskName = name;
}
const char* Thread::getTaskName(void)
{
return _taskName;
}

View File

@@ -31,6 +31,9 @@ namespace MQTTSNGW
#define MQTTSNGW_RB_MUTEX_KEY "rbmutex.key"
#define MQTTSNGW_RB_SEMAPHOR_NAME "/rbsemaphor"
#define RED_HDR "\033[0m\033[0;31m"
#define CLR_HDR "\033[0m\033[0;37m"
/*=====================================
Class Mutex
====================================*/
@@ -92,8 +95,7 @@ private:
class RingBuffer
{
public:
RingBuffer();
RingBuffer(const char* keyDirctory);
RingBuffer(const char* keyDirectory = MQTTSNGW_KEY_DIRECTORY);
~RingBuffer();
void put(char* buffer);
int get(char* buffer, int bufferLength);
@@ -127,12 +129,14 @@ public: void EXECRUN() \
try \
{ \
run(); \
stopProcess(); \
} \
catch(...) \
catch ( Exception &ex ) \
{ \
throw; \
ex.writeMessage(); \
WRITELOG("%s%s caught an exception and stopped.%s\n", RED_HDR, getTaskName(), CLR_HDR); \
theMultiTaskProcess->abort(); \
} \
theMultiTaskProcess->threadStopped(); \
}
/*=====================================
@@ -146,12 +150,15 @@ public:
static pthread_t getID();
static bool equals(pthread_t*, pthread_t*);
virtual void initialize(int argc, char** argv);
void stopProcess(void);
void waitStop(void);
void stop(void);
const char* getTaskName(void);
void setTaskName(const char* name);
void abort(int threadNo);
private:
static void* _run(void*);
pthread_t _threadID;
const char* _taskName;
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,163 @@
/**************************************************************************************
* Copyright (c) 2021, 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 SENSORNETWORK_H_
#define SENSORNETWORK_H_
#include "MQTTSNGWDefines.h"
#include "Threading.h"
#include <netinet/ip.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string>
#include <poll.h>
using namespace std;
namespace MQTTSNGW
{
/*===========================================
Class SensorNetAddreess
============================================*/
typedef struct
{
int af;
union
{
struct in_addr ad4;
struct in6_addr ad6;
} addr;
} ipAddr_t;
class SensorNetAddress
{
public:
SensorNetAddress();
~SensorNetAddress();
void setAddress(ipAddr_t *Address, uint16_t port);
int setAddress(string *ipAddrPort);
int setIpAddress(string *IpAddress);
void setFamily(int type);
int getFamily(void);
void setPort(in_port_t port);
void setSockaddr4(sockaddr_in *sockaddr);
void setSockaddr6(sockaddr_in6 *sockaddr);
void cpyAddr4(sockaddr_in *sockaddr);
void cpyAddr6(sockaddr_in6 *sockaddr);
void cpyAddr(SensorNetAddress *addr);
in_port_t getPort(void);
ipAddr_t* getIpAddress(void);
void setIndex(int index);
int getIndex(void);
void clear(void);
bool isMatch(SensorNetAddress *addr);
SensorNetAddress& operator =(SensorNetAddress &addr);
char* sprint(char *buf);
private:
int _pfdsIndex;
in_port_t _portNo;
ipAddr_t _ipAddr;
};
/*===========================================
Class Connections
============================================*/
#define POLL_UCAST 0
#define POLL_MCAST 1
#define POLL_SSL 2
typedef struct
{
int af;
SSL *ssl;
} afSSL_t;
class Connections
{
public:
Connections();
~Connections();
void initialize(int maxClient);
void close(int index);
int poll(int timeout);
int addClientSock(int sock);
int addClientSSL(SSL *ssl, int sock);
void setSockMulticast(int sock);
void setSockUnicast(int sock);
int getNumOfConnections(void);
int getNumOfClients(void);
SSL* getClientSSL(int index);
int getEventClient(int index);
int getSockClient(int index);
int getSockMulticast(void);
int getSockUnicast(void);
int getEventMulticast(void);
int getEventUnicast(void);
int getEventListen(void);
void closeSSL(int index);
void print(void);
private:
pollfd *_pollfds;
SSL **_ssls;
int _maxfds;
int _numfds;
Mutex _mutex;
};
/*===========================================
Class SensorNetwork
============================================*/
class SensorNetwork
{
friend class SensorNetSubTask;
public:
SensorNetwork();
~SensorNetwork();
int unicast(const uint8_t *payload, uint16_t payloadLength, SensorNetAddress *sendto);
int broadcast(const uint8_t *payload, uint16_t payloadLength);
int read(uint8_t *buf, uint16_t bufLen);
void initialize(void);
const char* getDescription(void);
SensorNetAddress* getSenderAddress(void);
Connections* getConnections(void);
void close();
private:
int openV4(string *ipAddress, uint16_t multiPortNo, uint16_t uniPortNo, uint32_t ttl);
int openV6(string *ipAddress, string *interface, uint16_t multiPortNo, uint16_t uniPortNo, uint32_t hops);
int multicastRecv(uint8_t *buf, uint16_t len);
int getSendClient(int index, SensorNetAddress *addr);
int getSenderAddress(int sock, SensorNetAddress *addr);
int getUnicastClient(SensorNetAddress *addr);
void clearRecvData(int sock);
Mutex _mutex;
SensorNetAddress _senderAddr;
SensorNetAddress _multicastAddr;
SensorNetAddress _unicastAddr;
string _description;
SSL_CTX *_dtlsctx;
Connections *_conns;
sockaddr_in _serverAddr4;
sockaddr_in6 _serverAddr6;
int _af;
};
}
#endif /* SENSORNETWORK_H_ */

View File

@@ -119,7 +119,7 @@ int SensorNetwork::read(uint8_t* buf, uint16_t bufLen)
return LoRaLink::recv(buf, bufLen, &_clientAddr);
}
int SensorNetwork::initialize(void)
void SensorNetwork::initialize(void)
{
char param[MQTTSNGW_PARAM_MAX];
uint32_t baudrate = 115200;
@@ -135,15 +135,22 @@ int SensorNetwork::initialize(void)
theProcess->getParam("DeviceRxLoRaLink", param);
_description += ", SerialRx ";
_description += param;
errno = 0;
if ( LoRaLink::open(LORALINK_MODEM_RX, param, baudrate) < 0 )
{
return -1;
throw EXCEPTION("Can't open a LoRaLink", errno);
}
theProcess->getParam("DeviceTxLoRaLink", param);
_description += ", SerialTx ";
_description += param;
return LoRaLink::open(LORALINK_MODEM_TX, param, baudrate);
errno = 0;
if ( LoRaLink::open(LORALINK_MODEM_TX, param, baudrate) < 0 )
{
throw EXCEPTION("Can't open a LoRaLink", errno);
}
}
const char* SensorNetwork::getDescription(void)
@@ -376,7 +383,7 @@ bool LoRaLink::readApiFrame(LoRaLinkFrame_t* api, LoRaLinkReadParameters_t* para
int LoRaLink::send(LoRaLinkPayloadType_t type, const uint8_t* payload, uint16_t pLen, SensorNetAddress* addr)
{
D_NWSTACK("\r\n===> Send: ");
D_LRSTACK("\r\n===> Send: ");
uint8_t buf[2] = { 0 };
uint8_t chks = 0;
uint16_t len = pLen + 3; // 3 = DestAddr[1] + PayloadType[1] + Crc[1]
@@ -397,7 +404,7 @@ int LoRaLink::send(LoRaLinkPayloadType_t type, const uint8_t* payload, uint16_t
send(type);
chks += type;
D_NWSTACK("\r\n Payload: ");
D_LRSTACK("\r\n Payload: ");
for ( uint8_t i = 0; i < pLen; i++ ){
send(payload[i]); // Payload
@@ -405,21 +412,21 @@ int LoRaLink::send(LoRaLinkPayloadType_t type, const uint8_t* payload, uint16_t
}
chks = 0xff - chks;
D_NWSTACK(" checksum ");
D_LRSTACK(" checksum ");
send(chks);
D_NWSTACK("\r\n");
D_LRSTACK("\r\n");
/* wait ACK */
_sem.timedwait(LORALINK_TIMEOUT_ACK);
if ( _respCd == LORALINK_NO_FREE_CH )
{
D_NWSTACK(" Channel isn't free\r\n");
D_LRSTACK(" Channel isn't free\r\n");
return -1;
}
else if ( _respCd != LORALINK_ACK )
{
D_NWSTACK(" Not Acknowleged\r\n");
D_LRSTACK(" Not Acknowleged\r\n");
return -1;
}
return (int)pLen;
@@ -472,7 +479,7 @@ int LoRaLink::recv(uint8_t* buf)
/*
if ( *buf == ESCAPE )
{
D_NWSTACK( " %02x",buf[0] );
D_LRSTACK( " %02x",buf[0] );
if ( read(fd, buf, 1) == 1 )
{
*buf = PAD ^ *buf;
@@ -484,7 +491,7 @@ int LoRaLink::recv(uint8_t* buf)
}
*/
D_NWSTACK( " %02x",buf[0] );
D_LRSTACK(" %02x", buf[0]);
return 0;
}
}
@@ -545,7 +552,7 @@ bool SerialPort::send(unsigned char b)
}
else
{
D_NWSTACK( " %02x", b);
D_LRSTACK(" %02x", b);
return true;
}
}

View File

@@ -25,12 +25,11 @@ using namespace std;
namespace MQTTSNGW
{
//#define DEBUG_NWSTACK
#ifdef DEBUG_NWSTACK
#define D_NWSTACK(...) printf(__VA_ARGS__); fflush(stdout)
#ifdef DEBUG_NW
#define D_LRSTACK(...) printf(__VA_ARGS__); fflush(stdout)
#else
#define D_NWSTACK(...)
#define D_LRSTACK(...)
#endif
@@ -173,7 +172,7 @@ public:
int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto);
int broadcast(const uint8_t* payload, uint16_t payloadLength);
int read(uint8_t* buf, uint16_t bufLen);
int initialize(void);
void initialize(void);
const char* getDescription(void);
SensorNetAddress* getSenderAddress(void);

View File

@@ -0,0 +1,422 @@
/**************************************************************************************
* 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 <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <string.h>
#include <regex>
#include <string>
#include <stdlib.h>
#include "SensorNetwork.h"
#include "MQTTSNGWProcess.h"
using namespace std;
using namespace MQTTSNGW;
/*===========================================
* Class SensorNetAddreess
* These 4 methods are minimum requirements for the SensorNetAddress class.
* isMatch(SensorNetAddress* )
* operator =(SensorNetAddress& )
* setAddress(string* )
* sprint(char* )
* BlePort class requires these 3 methods.
* getIpAddress(void)
* getPortNo(void)
* setAddress(uint32_t BtAddr, uint16_t channel)
============================================*/
bdaddr_t NullAddr = { 0, 0, 0, 0, 0, 0 };
SensorNetAddress::SensorNetAddress()
{
_channel = 0;
bacpy(&_bdAddr, &NullAddr);
}
SensorNetAddress::~SensorNetAddress()
{
}
bdaddr_t* SensorNetAddress::getAddress(void)
{
return &_bdAddr;
}
uint16_t SensorNetAddress::getPortNo(void)
{
return _channel;
}
void SensorNetAddress::setAddress(bdaddr_t BdAddr, uint16_t channel)
{
bacpy(&_bdAddr, &BdAddr);
_channel = channel;
}
/**
* Set Address data to SensorNetAddress
*
* @param *dev_channel is "Device_Address.Channel" format string
* @return success = 0, Invalid format = -1
*
* Valid channels are 1 to 30.
*
* Client01,XX:XX:XX:XX:XX:XX.1
*
*/
int SensorNetAddress::setAddress(string* dev_channel)
{
int rc = -1;
size_t pos = dev_channel->find_first_of(".");
if (pos == string::npos)
{
_channel = 0;
memset(&_bdAddr, 0, sizeof(bdaddr_t));
return rc;
}
string dvAddr = dev_channel->substr(0, pos);
string strchannel = dev_channel->substr(pos + 1);
if (strchannel == "*")
{
_channel = 0;
}
else
{
_channel = atoi(strchannel.c_str());
}
str2ba(dvAddr.c_str(), &_bdAddr);
if ((_channel < 0 && _channel > 30) || bacmp(&_bdAddr, &NullAddr) == 0)
{
return rc;
}
return 0;
}
bool SensorNetAddress::isMatch(SensorNetAddress* addr)
{
return ((this->_channel == addr->_channel) && bacmp(&this->_bdAddr, &addr->_bdAddr) == 0);
}
SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress& addr)
{
this->_channel = addr._channel;
this->_bdAddr = addr._bdAddr;
return *this;
}
char* SensorNetAddress::sprint(char* buf)
{
ba2str(const_cast<bdaddr_t*>(&_bdAddr), buf);
sprintf(buf + strlen(buf), ".%d", _channel);
return buf;
}
/*================================================================
Class SensorNetwork
getDescpription( ) is used by Gateway::initialize( )
initialize( ) is used by Gateway::initialize( )
getSenderAddress( ) is used by ClientRecvTask::run( )
broadcast( ) is used by MQTTSNPacket::broadcast( )
unicast( ) is used by MQTTSNPacket::unicast( )
read( ) is used by MQTTSNPacket::recv( )
================================================================*/
SensorNetwork::SensorNetwork()
{
}
SensorNetwork::~SensorNetwork()
{
}
int SensorNetwork::unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendToAddr)
{
uint16_t ch = sendToAddr->getPortNo();
RfcommPort* blep = &_rfPorts[ch - 1];
int rc = 0;
errno = 0;
if ((rc = blep->send(payload, (uint32_t) payloadLength)) < 0)
{
D_NWSTACK("errno == %d in BlePort::sendto %d\n", errno, ch);
} D_NWSTACK("sendto %u length = %d\n", ch, rc);
return rc;
}
int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength)
{
int rc = 0;
for (int i = 0; i < MAX_RFCOMM_CH; i++)
{
errno = 0;
if (_rfPorts[i].getSock() > 0)
{
if ((rc = _rfPorts[i].send(payload, (uint32_t) payloadLength)) < 0)
{
D_NWSTACK("errno == %d in BlePort::sendto %d\n", errno, i + 1);
}D_NWSTACK("sendto %u length = %d\n", i + 1, rc);
}
}
return rc;
}
int SensorNetwork::read(uint8_t* buf, uint16_t bufLen)
{
struct timeval timeout;
fd_set recvfds;
int maxSock = 0;
timeout.tv_sec = 1;
timeout.tv_usec = 0; // 1 sec
FD_ZERO(&recvfds);
for (int i = 0; i < MAX_RFCOMM_CH; i++)
{
if (_rfPorts[i]._rfCommSock > 0)
{
if (maxSock < _rfPorts[i]._rfCommSock)
{
maxSock = _rfPorts[i]._rfCommSock;
}
FD_SET(_rfPorts[i]._rfCommSock, &recvfds);
}
else if (_rfPorts[i]._listenSock > 0)
{
if (maxSock < _rfPorts[i]._listenSock)
{
maxSock = _rfPorts[i]._listenSock;
}
FD_SET(_rfPorts[i]._listenSock, &recvfds);
}
}
int rc = 0;
if (select(maxSock + 1, &recvfds, 0, 0, &timeout) > 0)
{
for (int i = 0; i < MAX_RFCOMM_CH; i++)
{
if (_rfPorts[i]._rfCommSock > 0)
{
if (FD_ISSET(_rfPorts[i]._rfCommSock, &recvfds))
{
rc = _rfPorts[i].recv(buf, bufLen);
if (rc == -1)
{
_rfPorts[i].close();
}
}
}
else if (_rfPorts[i]._listenSock > 0)
{
if (FD_ISSET(_rfPorts[i]._listenSock, &recvfds))
{
int sock = _rfPorts[i].accept(&_senderAddr);
if (sock > 0)
{
_rfPorts[i]._rfCommSock = sock;
}
}
}
}
}
return rc;
}
/**
* Prepare UDP sockets and description of SensorNetwork like
* "UDP Multicast 225.1.1.1:1883 Gateway Port 10000".
* The description is for a start up prompt.
*/
void SensorNetwork::initialize(void)
{
char param[MQTTSNGW_PARAM_MAX];
string devAddr;
SensorNetAddress sa;
/*
* theProcess->getParam( ) copies
* a text specified by "Key" into param[] from the Gateway.conf
*
* in Gateway.conf e.g.
*
* # BLE
* RFCOMM=XX:XX:XX:XX:XX:XX.0
*
*/
if (theProcess->getParam("RFCOMMAddress", param) == 0)
{
devAddr = param;
_description = "Bluetooth RFCOMM ";
_description += param;
}
errno = 0;
if (sa.setAddress(&devAddr) == -1)
{
throw EXCEPTION("Invalid Bluetooth Address", errno);
}
/* Prepare BLE sockets */
WRITELOG("Initialize RFCOMM\n");
int rc = MAX_RFCOMM_CH;
for (uint16_t i = 0; i < MAX_RFCOMM_CH; i++)
{
rc += _rfPorts[i].open(sa.getAddress(), i + 1);
}
if (rc == 0)
{
throw EXCEPTION("Can't open Bluetooth RFComms", errno);
}
}
const char* SensorNetwork::getDescription(void)
{
return _description.c_str();
}
SensorNetAddress* SensorNetwork::getSenderAddress(void)
{
return &_senderAddr;
}
/*=========================================
Class BleStack
=========================================*/
RfcommPort::RfcommPort()
{
_disconReq = false;
_rfCommSock = 0;
_listenSock = 0;
_channel = 0;
}
RfcommPort::~RfcommPort()
{
close();
if (_listenSock > 0)
{
::close(_listenSock);
}
}
void RfcommPort::close(void)
{
if (_rfCommSock > 0)
{
::close(_rfCommSock);
_rfCommSock = 0;
}
}
int RfcommPort::open(bdaddr_t* devAddr, uint16_t channel)
{
const int reuse = 1;
if (channel < 1 || channel > 30)
{
D_NWSTACK("error Channel undefined in BlePort::open\n");
return 0;
}
/*------ Create unicast socket --------*/
_listenSock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if (_listenSock < 0)
{
D_NWSTACK("error can't create Rfcomm socket in BlePort::open\n");
return 0;
}
sockaddr_rc addru;
addru.rc_family = AF_BLUETOOTH;
addru.rc_channel = channel;
bacpy(&addru.rc_bdaddr, devAddr);
uint8_t buf[20];
ba2str(devAddr, (char*) buf);
setsockopt(_listenSock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
errno = 0;
if (::bind(_listenSock, (sockaddr*) &addru, sizeof(addru)) < 0)
{
WRITELOG("\033[0m\033[0;31mCan't bind RFCOMM CH = %d %s\033[0m\033[0;37m\n", channel, strerror(errno));
::close(_listenSock);
return 0;
}
_channel = channel;
::listen(_listenSock, 1);
WRITELOG("Listen RFCOMM CH = %d\n", channel);
return 1;
}
int RfcommPort::send(const uint8_t* buf, uint32_t length)
{
return ::send(_rfCommSock, buf, length, 0);
}
int RfcommPort::recv(uint8_t* buf, uint16_t len)
{
int rc = 0;
errno = 0;
rc = ::read(_rfCommSock, buf, len);
if (rc < 0 && errno != EAGAIN)
{
D_NWSTACK("errno = %d in BlePort::recv\n", errno);
return -1;
}
return rc;
}
int RfcommPort::accept(SensorNetAddress* addr)
{
struct sockaddr_rc devAddr = { 0 };
socklen_t opt = sizeof(devAddr);
int sock = 0;
errno = 0;
sock = ::accept(_listenSock, (sockaddr *) &devAddr, &opt);
if (sock < 0 && errno != EAGAIN)
{
D_NWSTACK("errno == %d in BlePort::recv\n", errno);
return -1;
}
bdaddr_t bdAddr = devAddr.rc_bdaddr;
addr->setAddress(bdAddr, _channel);
return sock;
}
int RfcommPort::getSock(void)
{
return _rfCommSock;
}

View File

@@ -0,0 +1,98 @@
/**************************************************************************************
* 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 SENSORNETWORK_H_
#define SENSORNETWORK_H_
#include "MQTTSNGWDefines.h"
#include <string>
#include <bluetooth/bluetooth.h>
using namespace std;
namespace MQTTSNGW
{
#define MAX_RFCOMM_CH 30
/*===========================================
Class SensorNetAddreess
============================================*/
class SensorNetAddress
{
public:
SensorNetAddress();
~SensorNetAddress();
void setAddress(bdaddr_t bdAddr, uint16_t channel);
int setAddress(string* data);
uint16_t getPortNo(void);
bdaddr_t* getAddress(void);
bool isMatch(SensorNetAddress* addr);
SensorNetAddress& operator =(SensorNetAddress& addr);
char* sprint(char* buf);
private:
uint16_t _channel;
bdaddr_t _bdAddr;
};
/*========================================
Class RfcommPort
=======================================*/
class RfcommPort
{
friend class SensorNetwork;
public:
RfcommPort();
virtual ~RfcommPort();
int open(bdaddr_t* devAddress, uint16_t channel);
void close(void);
int send(const uint8_t* buf, uint32_t length);
int recv(uint8_t* buf, uint16_t len);
int getSock(void);
int accept(SensorNetAddress* addr);
private:
int _rfCommSock;
int _listenSock;
uint16_t _channel;
bool _disconReq;
};
/*===========================================
Class SensorNetwork
============================================*/
class SensorNetwork
{
public:
SensorNetwork();
~SensorNetwork();
int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto);
int broadcast(const uint8_t* payload, uint16_t payloadLength);
int read(uint8_t* buf, uint16_t bufLen);
void initialize(void);
const char* getDescription(void);
SensorNetAddress* getSenderAddress(void);
private:
// sockets for RFCOMM
RfcommPort _rfPorts[MAX_RFCOMM_CH];
SensorNetAddress _senderAddr;
string _description;
};
}
#endif /* SENSORNETWORK_H_ */

View File

@@ -20,10 +20,13 @@
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <string.h>
#include <regex>
#include <string>
#include <stdlib.h>
#include <poll.h>
#include "SensorNetwork.h"
#include "MQTTSNGWProcess.h"
@@ -142,7 +145,7 @@ char* SensorNetAddress::sprint(char* buf)
In Gateway version 1.0
getDescpription( ) is used by Gateway::initialize( )
initialize( ) is used by ClientSendTask::initialize( )
initialize( ) is used by Gateway::initialize( )
getSenderAddress( ) is used by ClientRecvTask::run( )
broadcast( ) is used by MQTTSNPacket::broadcast( )
unicast( ) is used by MQTTSNPacket::unicast( )
@@ -170,16 +173,15 @@ int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength)
int SensorNetwork::read(uint8_t* buf, uint16_t bufLen)
{
return UDPPort::recv(buf, bufLen, &_clientAddr);
return UDPPort::recv(buf, bufLen, &_senderAddr);
}
/**
* Prepare UDP sockets and description of SensorNetwork like
* "UDP Multicast 225.1.1.1:1883 Gateway Port 10000".
* The description is for a start up prompt.
* @return success = 0, error = -1
*/
int SensorNetwork::initialize(void)
void SensorNetwork::initialize(void)
{
char param[MQTTSNGW_PARAM_MAX];
uint16_t multicastPortNo = 0;
@@ -213,18 +215,22 @@ int SensorNetwork::initialize(void)
if (theProcess->getParam("GatewayPortNo", param) == 0)
{
unicastPortNo = atoi(param);
_description += " Gateway Port ";
_description += ", Gateway Port:";
_description += param;
}
if (theProcess->getParam("MulticastTTL", param) == 0)
{
ttl = atoi(param);
_description += " TTL: ";
_description += ", TTL:";
_description += param;
}
/* Prepare UDP sockets */
return UDPPort::open(ip.c_str(), multicastPortNo, unicastPortNo, ttl);
/* setup UDP sockets */
errno = 0;
if ( UDPPort::open(ip.c_str(), multicastPortNo, unicastPortNo, ttl) < 0 )
{
throw EXCEPTION("Can't open a UDP", errno);
}
}
const char* SensorNetwork::getDescription(void)
@@ -234,7 +240,7 @@ const char* SensorNetwork::getDescription(void)
SensorNetAddress* SensorNetwork::getSenderAddress(void)
{
return &_clientAddr;
return &_senderAddr;
}
/*=========================================
@@ -244,8 +250,7 @@ SensorNetAddress* SensorNetwork::getSenderAddress(void)
UDPPort::UDPPort()
{
_disconReq = false;
_sockfdUnicast = -1;
_sockfdMulticast = -1;
memset(_pollFds, 0, sizeof(_pollFds));
}
UDPPort::~UDPPort()
@@ -255,22 +260,20 @@ UDPPort::~UDPPort()
void UDPPort::close(void)
{
if (_sockfdUnicast > 0)
for (int i = 0; i < 2; i++)
{
::close(_sockfdUnicast);
_sockfdUnicast = -1;
if (_pollFds[i].fd > 0)
{
::close(_pollFds[i].fd);
_pollFds[i].fd = 0;
}
if (_sockfdMulticast > 0)
{
::close(_sockfdMulticast);
_sockfdMulticast = -1;
}
}
int UDPPort::open(const char* ipAddress, uint16_t multiPortNo, uint16_t uniPortNo, unsigned int ttl)
int UDPPort::open(const char *multicastIP, uint16_t multiPortNo, uint16_t uniPortNo, unsigned int ttl)
{
char loopch = 0;
const int reuse = 1;
int optval = 0;
int sock = 0;
if (uniPortNo == 0 || multiPortNo == 0)
{
@@ -278,90 +281,87 @@ int UDPPort::open(const char* ipAddress, uint16_t multiPortNo, uint16_t uniPortN
return -1;
}
uint32_t ip = inet_addr(ipAddress);
_grpAddr.setAddress(ip, htons(multiPortNo));
_clientAddr.setAddress(ip, htons(uniPortNo));
_ttl = ttl;
/*------ Create unicast socket --------*/
_sockfdUnicast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_sockfdUnicast < 0)
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
D_NWSTACK("error can't create unicast socket in UDPPort::open\n");
return -1;
}
setsockopt(_sockfdUnicast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
sockaddr_in addru;
addru.sin_family = AF_INET;
addru.sin_port = htons(uniPortNo);
addru.sin_addr.s_addr = INADDR_ANY;
if (::bind(_sockfdUnicast, (sockaddr*) &addru, sizeof(addru)) < 0)
if (::bind(sock, (sockaddr*) &addru, sizeof(addru)) < 0)
{
D_NWSTACK("error can't bind unicast socket in UDPPort::open\n");
return -1;
}
if (setsockopt(_sockfdUnicast, IPPROTO_IP, IP_MULTICAST_LOOP, (char*) &loopch, sizeof(loopch)) < 0)
{
D_NWSTACK("error IP_MULTICAST_LOOP in UDPPort::open\n");
close();
return -1;
}
_pollFds[0].fd = sock;
_pollFds[0].events = POLLIN;
/*------ Create Multicast socket --------*/
_sockfdMulticast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_sockfdMulticast < 0)
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
D_NWSTACK("error can't create multicast socket in UDPPort::open\n");
close();
return -1;
}
setsockopt(_sockfdMulticast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
optval = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
sockaddr_in addrm;
addrm.sin_family = AF_INET;
addrm.sin_port = _grpAddr.getPortNo();
addrm.sin_port = htons(multiPortNo);
addrm.sin_addr.s_addr = INADDR_ANY;
if (::bind(_sockfdMulticast, (sockaddr*) &addrm, sizeof(addrm)) < 0)
if (::bind(sock, (sockaddr*) &addrm, sizeof(addrm)) < 0)
{
D_NWSTACK("error can't bind multicast socket in UDPPort::open\n");
return -1;
}
if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_MULTICAST_LOOP, (char*) &loopch, sizeof(loopch)) < 0)
ip_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_interface.s_addr = INADDR_ANY;
mreq.imr_multiaddr.s_addr = inet_addr(multicastIP);
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n");
close();
return -1;
}
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
{
D_NWSTACK("error Multicast IP_MULTICAST_TTL in UDPPort::open\n");
close();
return -1;
}
#ifdef DEBUG_NW
optval = 1;
#else
optval = 0;
#endif
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
{
D_NWSTACK("error IP_MULTICAST_LOOP in UDPPort::open\n");
close();
return -1;
}
ip_mreq mreq;
mreq.imr_interface.s_addr = INADDR_ANY;
mreq.imr_multiaddr.s_addr = _grpAddr.getIpAddress();
_multicastAddr.setAddress(inet_addr(multicastIP), htons(multiPortNo));
_pollFds[1].fd = sock;
_pollFds[1].events = POLLIN;
if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n");
close();
return -1;
}
if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,sizeof(ttl)) < 0)
{
D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n");
close();
return -1;
}
if (setsockopt(_sockfdUnicast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
D_NWSTACK("error Unicast IP_ADD_MEMBERSHIP in UDPPort::open\n");
close();
return -1;
}
return 0;
}
@@ -372,52 +372,33 @@ int UDPPort::unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* addr
dest.sin_port = addr->getPortNo();
dest.sin_addr.s_addr = addr->getIpAddress();
int status = ::sendto(_sockfdUnicast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
int status = ::sendto(_pollFds[0].fd, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
if (status < 0)
{
D_NWSTACK("errno == %d in UDPPort::sendto\n", errno);
}
D_NWSTACK("sendto %s:%u length = %d\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), status);
return status;
}
int UDPPort::broadcast(const uint8_t* buf, uint32_t length)
{
return unicast(buf, length, &_grpAddr);
return unicast(buf, length, &_multicastAddr);
}
int UDPPort::recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr)
{
struct timeval timeout;
fd_set recvfds;
int maxSock = 0;
timeout.tv_sec = 1;
timeout.tv_usec = 0; // 1 sec
FD_ZERO(&recvfds);
FD_SET(_sockfdUnicast, &recvfds);
FD_SET(_sockfdMulticast, &recvfds);
if (_sockfdMulticast > _sockfdUnicast)
{
maxSock = _sockfdMulticast;
}
else
{
maxSock = _sockfdUnicast;
}
int rc = 0;
if ( select(maxSock + 1, &recvfds, 0, 0, &timeout) > 0 )
poll(_pollFds, 2, 2000); // Timeout 2 seconds
if (_pollFds[0].revents == POLLIN)
{
if (FD_ISSET(_sockfdUnicast, &recvfds))
{
rc = recvfrom(_sockfdUnicast, buf, len, 0, addr);
rc = recvfrom(_pollFds[0].fd, buf, len, 0, addr);
}
else if (FD_ISSET(_sockfdMulticast, &recvfds))
else if (_pollFds[1].revents == POLLIN)
{
rc = recvfrom(_sockfdMulticast, buf, len, 0, &_grpAddr);
}
rc = recvfrom(_pollFds[1].fd, buf, len, 0, addr);
}
return rc;
}

Some files were not shown because too many files have changed in this diff Show More