This branch for debugging DTLS #90, #150, #195, #227

The purpose of this branch is to share work in process.
Change sellect() of UDP to poll()
Rewrite UDP6 for DTLS6

Known bug: can't reconnect DTLS

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
This commit is contained in:
tomoaki
2021-06-11 10:54:20 +09:00
parent 83c30d662f
commit 5fb4312aad
52 changed files with 5101 additions and 1790 deletions

541
.cproject
View File

@@ -1,354 +1,191 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage"> <?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<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">
<cconfiguration id="cdt.managedbuild.config.gnu.exe.debug.1685199227"> <externalSettings/>
<extensions>
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.debug.1685199227" moduleId="org.eclipse.cdt.core.settings" name="Debug"> <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"/>
<externalSettings/> <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"/>
<extensions> <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"/>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/> </extensions>
</storageModule>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <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">
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <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">
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <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" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> <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">
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <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.default" valueType="enumerated"/>
</extensions> <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"/>
</storageModule> <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;"/>
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> <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;"/>
<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"> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNPacket/src}&quot;"/>
<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1685199227." name="/" resourcePath=""> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNClient/src}&quot;"/>
</option>
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.102264757" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug"> <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"/>
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.2137160061" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/> <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">
<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"/> <listOptionValue builtIn="false" value="DTLS"/>
<listOptionValue builtIn="false" value="DEBUG_NW"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.602829827" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> </option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1626802967" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.109068141" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug"> </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 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 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 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 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 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>
<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">
<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"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/dtls}&quot;"/>
</option>
<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"> <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.814497727" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src}&quot;"/> <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">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/GatewayTester/src}&quot;"/> <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux}&quot;"/> </inputType>
</tool>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNPacket/src}&quot;"/> <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" value="&quot;${workspace_loc:/${ProjName}/MQTTSNClient/src}&quot;"/> <listOptionValue builtIn="false" value="ssl"/>
<listOptionValue builtIn="false" value="crypto"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/udp}&quot;"/> <listOptionValue builtIn="false" value="pthread"/>
<listOptionValue builtIn="false" value="bluetooth"/>
</option> </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">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1626802967" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> <listOptionValue builtIn="false" value="/usr/local/lib"/>
</option>
</tool> <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">
<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2017162618" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug"> <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
<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"/> </inputType>
</tool>
<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"/> <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"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.814497727" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> </tool>
</toolChain>
</tool> </folderInfo>
<sourceEntries>
<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1881440001" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug"> <entry excluding="src/linux/udp6|src/linux/udp|GatewayTester|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="samples|test" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket"/>
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.910023243" superClass="cdt.managedbuild.tool.gnu.c.linker.input"> </sourceEntries>
</configuration>
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> </storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/> </cconfiguration>
<cconfiguration id="cdt.managedbuild.config.gnu.exe.release.561557339">
</inputType> <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/>
</tool> <extensions>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.581660133" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug"> <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"/>
<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"> <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"/>
<listOptionValue builtIn="false" value="pthread"/> <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
<listOptionValue builtIn="false" value="ssl"/> </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<listOptionValue builtIn="false" value="crypto"/> <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="">
<listOptionValue builtIn="false" value="bluetooth"/> <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"/>
</option> <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"/>
<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"> <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"/>
<listOptionValue builtIn="false" value="/usr/local/lib"/> <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> <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;"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.98211496" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNPacket/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux}&quot;"/>
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/GatewayTester/src}&quot;"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/> </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> <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1606625536" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
</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"/>
<tool id="cdt.managedbuild.tool.gnu.assembler.exe.debug.1531154076" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug"> <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"/>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1193873077" superClass="cdt.managedbuild.tool.gnu.assembler.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">
</tool> <inputType id="cdt.managedbuild.tool.gnu.c.linker.input.46435036" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
</toolChain> <additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</folderInfo> </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">
<sourceEntries> <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"/>
<entry excluding="src/linux/rfcomm|src/linux/udp6|src/tests|GatewayTester|src/linux/xbee|GatewayTester/samples|src/mainLogmonitor.cpp|src/linux/loralink|GatewayTester/src" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway"/> <listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="ssl"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="crypto"/>
<entry excluding="samples|src" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway/GatewayTester"/> </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">
<entry excluding="samples|test" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket"/> <listOptionValue builtIn="false" value="/usr/local/lib"/>
</option>
</sourceEntries> <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.2044523925" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
</configuration> <additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</storageModule> </tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.exe.release.67939689" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release">
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> <inputType id="cdt.managedbuild.tool.gnu.assembler.input.651929038" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</cconfiguration> </toolChain>
</folderInfo>
<cconfiguration id="cdt.managedbuild.config.gnu.exe.release.561557339"> <sourceEntries>
<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=""/>
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.release.561557339" moduleId="org.eclipse.cdt.core.settings" name="Release"> <entry excluding="linux/udp6|linux/udp" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTSNGateway/src"/>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket/src"/>
<externalSettings/> </sourceEntries>
</configuration>
<extensions> </storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/> </cconfiguration>
</storageModule>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <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"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> </storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> <configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/MQTTSN-embedded-C"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> </configuration>
</storageModule>
</extensions> <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
</storageModule> <storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> <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=""/>
<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"> </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">
<folderInfo id="cdt.managedbuild.config.gnu.exe.release.561557339." name="/" resourcePath=""> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.474335535" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release"> <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=""/>
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.338327831" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/> </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">
<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"/> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.1908794347" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> </storageModule>
</cproject>
<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="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="linux/rfcomm|linux/ble" 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>
</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.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>

View File

@@ -1,48 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project> <project>
<configuration id="cdt.managedbuild.config.gnu.exe.debug.1685199227" name="Debug">
<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"/>
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <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"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> </extension>
</configuration>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-152611677936340298" 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"> <configuration id="cdt.managedbuild.config.gnu.exe.release.561557339" name="Release">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<language-scope id="org.eclipse.cdt.core.gcc"/> <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<language-scope id="org.eclipse.cdt.core.g++"/> <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="-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">
</provider> <language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</extension> </provider>
</extension>
</configuration> </configuration>
</project>
<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="-152611677936340298" 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

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

View File

@@ -2,27 +2,6 @@
**sample/mainTest.cpp** is a Test sample coading. **sample/mainTest.cpp** is a Test sample coading.
Each test is described as one function. test1(), test2()... 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) void test1(void)
{ {
char payload[300]; char payload[300];
@@ -36,8 +15,34 @@ void test2(void)
uint8_t qos = 1; uint8_t qos = 1;
SUBSCRIBE(topic2, on_publish02, qos); SUBSCRIBE(topic2, on_publish02, qos);
} }
*---------------------------------------------------------------------------
*
* 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 one by one. **TEST_LIST** is a test senario. Test functions are executed interactively.
``` ```
/*------------------------------------------------------ /*------------------------------------------------------
* A List of Test Tasks * A List of Test Tasks
@@ -54,80 +59,59 @@ TEST_LIST = {// e.g. TEST( Label, Test),
}; };
``` ```
## step1. Define a sensor network
**UDP** or **Bluetooth** is available as a sensor network. **UDP**, **DTLS**, **UDP6**, **DTLS6** or **Bluetooth** is available as a sensor network.
Uncomment a line \#define UDP or RFCOMM in LMqttsnClientApp.h file. ```
/*------------------------------------------------------
* 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
};
``` ```
/*======================================
* Program mode Flag
======================================*/
//#define CLIENT_MODE
#define UDP
//#define RFCOMM
```
## step2. Build ## How to Build
``` ```
$ git clone https://github.com/eclipse/paho.mqtt-sn.embedded-c copy codes from the github.
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester $ cd paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester
$ make $ ./build.sh [udp | udp6 | dtls | dtls6 | rfcomm]
$ make install
$ make clean
``` ```
MQTT-SNGatewayTester program is copied into ../../../ directory.
## **step3. Execute Gateway Tester.** ## Execute Gateway Tester
``` ```
$ cd ../../.. $ ./Build/MQTT-SNGatewayTester
$ ./MQTT-SNGatewayTester
*************************************************************************** ***************************************************************************
* MQTT-SN Gateway Tester * MQTT-SN Gateway Tester DTLS
* Part of Project Paho in Eclipse * Part of Project Paho in Eclipse
* (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/) * (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)
* *
* Author : Tomoaki YAMAGUCHI * Author : Tomoaki YAMAGUCHI
* Version: 0.0.0 * Version: 2.0.0
*************************************************************************** ***************************************************************************
Attempting to Connect the Broker..... 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,22 @@
#!/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
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,17 +51,26 @@ extern LScreen* theScreen;
/*------------------------------------------------------ /*------------------------------------------------------
* UDP Configuration (theNetcon) * UDP Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
UDPCONF = { UDPCONF = { "ClientPUB", // ClientId
"ClientPUB", // ClientId { 225, 1, 1, 1 }, // Multicast group IP
{225,1,1,1}, // Multicast group IP 1883, // Multicast group Port
1883, // Multicast group Port 20010, // Local PortNo
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) * RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
RFCOMMCONF = { "GatewayTestClient", // ClientId RFCOMMCONF = { "ClientPUB", // ClientId
"60:57:18:06:8B:72", // GW Address "60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel 1, // Rfcomm channel
}; };

View File

@@ -51,17 +51,26 @@ extern LScreen* theScreen;
/*------------------------------------------------------ /*------------------------------------------------------
* UDP Configuration (theNetcon) * UDP Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
UDPCONF = { UDPCONF = { "QoS-1_Client01", // ClientId
"QoS-1_Client01", // ClientId { 225, 1, 1, 1 }, // Multicast group IP
{225,1,1,1}, // Multicast group IP 1883, // Multicast group Port
1883, // Multicast group Port 20001, // Local PortNo
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) * RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
RFCOMMCONF = { "GatewayTestClient", // ClientId RFCOMMCONF = { "QoS-1_Client01", // ClientId
"60:57:18:06:8B:72", // GW Address "60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel 1, // Rfcomm channel
}; };

View File

@@ -51,17 +51,26 @@ extern LScreen* theScreen;
/*------------------------------------------------------ /*------------------------------------------------------
* UDP Configuration (theNetcon) * UDP Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
UDPCONF = { UDPCONF = { "ClientSUB", // ClientId
"ClientSUB", // ClientId { 225, 1, 1, 1 }, // Multicast group IP
{225,1,1,1}, // Multicast group IP 1883, // Multicast group Port
1883, // Multicast group Port 20011, // Local PortNo
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) * RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
RFCOMMCONF = { "GatewayTestClient", // ClientId RFCOMMCONF = { "ClientSUB", // ClientId
"60:57:18:06:8B:72", // GW Address "60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel 1, // Rfcomm channel
}; };

View File

@@ -20,13 +20,13 @@
* *
* void PUBLISH ( uint16_t topicId, 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 ( const char* topicName, TopicCallback onPublish, uint8_t qos );
* *
* void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos ); * void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
* *
* void UNSUBSCRIBE ( const char* topicName ); * void UNSUBSCRIBE ( const char* topicName );
* *
* void UNSUBSCRIBE ( uint16_t topicId ); * void UNSUBSCRIBE ( uint16_t topicId );
* *
* void DISCONNECT ( uint16_t sleepInSecs ); * void DISCONNECT ( uint16_t sleepInSecs );
* *
@@ -49,7 +49,7 @@ extern LMqttsnClient* theClient;
extern LScreen* theScreen; extern LScreen* theScreen;
/*------------------------------------------------------ /*------------------------------------------------------
* UDP Configuration (theNetcon) * UDP,DTLS Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
UDPCONF = { "GatewayTestClient", // ClientId UDPCONF = { "GatewayTestClient", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP { 225, 1, 1, 1 }, // Multicast group IP
@@ -57,6 +57,16 @@ UDPCONF = { "GatewayTestClient", // ClientId
20020, // Local PortNo 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) * RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/

View File

@@ -200,6 +200,15 @@ int LGwProxy::getConnectResponce(void)
{ {
_network.setGwAddress(); _network.setGwAddress();
_gwId = _mqttsnMsg[1]; _gwId = _mqttsnMsg[1];
#if defined(DTLS) || defined(DTLS6)
if (_network.sslConnect() < 0)
{
DISPLAY(
"\033[0m\033[0;32m\n\nLGwProxy::getConnectResponce Can't connect the Gateway via SSL.\033[0m\033[0;37m\n\n");
return 0;
}
#endif
_status = GW_CONNECTING; _status = GW_CONNECTING;
} }
else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLTOPICREQ && _status == GW_WAIT_WILLTOPICREQ) else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLTOPICREQ && _status == GW_WAIT_WILLTOPICREQ)

View File

@@ -23,7 +23,10 @@
#include "LMqttsnClientApp.h" #include "LMqttsnClientApp.h"
#include "LNetworkUdp.h" #include "LNetworkUdp.h"
#include "LNetworkUdp6.h"
#include "LNetworkRfcomm.h" #include "LNetworkRfcomm.h"
#include "LNetworkDtls.h"
#include "LNetworkDtls6.h"
#include "LRegisterManager.h" #include "LRegisterManager.h"
#include "LTimer.h" #include "LTimer.h"
#include "LTopicTable.h" #include "LTopicTable.h"
@@ -43,6 +46,7 @@ using namespace std;
#define GW_SLEEPING 10 #define GW_SLEEPING 10
#define GW_DISCONNECTED 11 #define GW_DISCONNECTED 11
#define GW_SLEPT 12 #define GW_SLEPT 12
#define SSL_CONNECTING 13
#define GW_WAIT_PINGRESP 1 #define GW_WAIT_PINGRESP 1

View File

@@ -53,8 +53,14 @@ int main(int argc, char** argv)
printf("\n%s", PAHO_COPYRIGHT0); printf("\n%s", PAHO_COPYRIGHT0);
#if defined(UDP) #if defined(UDP)
printf(" UDP\n"); printf(" UDP\n");
#elif defined(UDP6)
printf(" UDP6\n");
#elif defined(RFCOMM) #elif defined(RFCOMM)
printf(" RFCOMM\n"); printf(" RFCOMM\n");
#elif defined(DTLS)
printf(" DTLS\n");
#elif defined(DTLS6)
printf(" DTLS6\n");
#else #else
printf("\n"); printf("\n");
#endif #endif

View File

@@ -17,17 +17,16 @@
#ifndef MQTTSNCLIENTAPP_H_ #ifndef MQTTSNCLIENTAPP_H_
#define MQTTSNCLIENTAPP_H_ #define MQTTSNCLIENTAPP_H_
/*======================================
* Debug Flag
======================================*/
//#define DEBUG_NW
//#define DEBUG_MQTTSN
/*====================================== /*======================================
* Program mode Flag * Program mode Flag
======================================*/ ======================================*/
//#define CLIENT_MODE //#define CLIENT_MODE
#define UDP
//#define RFCOMM
/*======================================
* Debug Flag
======================================*/
#define DEBUG_NW
//#define DEBUG_MQTTSN
/**************************************** /****************************************
MQTT-SN Parameters MQTT-SN Parameters
@@ -75,6 +74,15 @@ struct LUdpConfig
uint16_t uPortNo; uint16_t uPortNo;
}; };
struct LUdp6Config
{
const char* clientId;
const char* ipAddress;
const char *interface;
uint16_t gPortNo;
uint16_t uPortNo;
};
struct LRfcommConfig struct LRfcommConfig
{ {
const char* clientId; const char* clientId;
@@ -97,20 +105,40 @@ typedef enum
#define MQTTSN_CONFIG MqttsnConfig theMqttsnConfig #define MQTTSN_CONFIG MqttsnConfig theMqttsnConfig
#define MQTTSNCONF LMqttsnConfig theMqcon #define MQTTSNCONF LMqttsnConfig theMqcon
#ifdef UDP #if defined(UDP)
#define NETWORK_CONFIG UdpConfig theNetworkConfig
#define UDPCONF LUdpConfig theNetcon #define UDPCONF LUdpConfig theNetcon
#define RFCOMMCONF LRfcommConfig theConf #define UDP6CONF LUdp6Config theU6Conf
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdpConfig #define SENSORNET_CONFIG_t LUdpConfig
#else
#ifdef RFCOMM #elif defined(UDP6)
#define NETWORK_CONFIG BleConfig theNetworkConfig #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 RFCOMMCONF LRfcommConfig theNetcon
#define UDPCONF LUdpConfig theConf #define UDPCONF LUdpConfig theUConf
#define UDP6CONF LUdp6Config theU6Conf
#define SENSORNET_CONFIG_t LRfcommConfig #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 #endif
#error "UDP and RFCOMM are not defined in LMqttsnClientApp.h"
#endif
#define CONNECT(...) theClient->getGwProxy()->connect(__VA_ARGS__) #define CONNECT(...) theClient->getGwProxy()->connect(__VA_ARGS__)
#define PUBLISH(...) theClient->publish(__VA_ARGS__) #define PUBLISH(...) theClient->publish(__VA_ARGS__)

View File

@@ -0,0 +1,537 @@
/**************************************************************************************
* 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");
DISPLAY("\033[0m\033[0;31m\nerror 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");
DISPLAY("\033[0m\033[0;31m\nerror 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);
D_NWLOG("errno == %d in LDtlsPort::unicast\n", 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 = 0;
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)
{
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 || SO_REUSEPORT, &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)
{
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));
int stat = SSL_connect(_ssl);
if (stat != 1)
{
rc = -1;
D_NWLOG("SSL fail to connect\n");
}
else
{
D_NWLOG("SSL connected\n");
}
return rc;
}
int verify_cert(int ok, X509_STORE_CTX *ctx)
{
return 1;
}
#endif

View File

@@ -0,0 +1,117 @@
/**************************************************************************************
* 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
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
#define STAT_SSL 3
using namespace std;
namespace linuxAsyncClient {
/*========================================
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,533 @@
/**************************************************************************************
* 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 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)
{
_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;
memset(_pollfds, 0, sizeof(_pollfds));
_sock = 0;
_castStat = 0;
_ifIndex = 0;
_gIpAddrStr = NULL;
}
LDtls6Port::~LDtls6Port()
{
close();
if (_gIpAddrStr)
{
free(_gIpAddrStr);
}
}
void LDtls6Port::close()
{
for (int i = 0; i < 2; i++)
{
if (_pollfds[i].fd > 0)
{
::close(_pollfds[i].fd);
_pollfds[i].fd = 0;
}
}
}
bool LDtls6Port::open(LUdp6Config *config)
{
int optval = 1;
int sock = 0;
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 */
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 = 0;
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;
}
bool LDtls6Port::isUnicast()
{
return (_sock == _pollfds[0].fd && _sock > 0);
}
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 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 LDtls6Port::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 LDtls6Port::checkRecvBuf()
{
uint8_t buf[2];
int cnt = poll(_pollfds, 2, 2000); // Timeout 2secs
if (cnt == 0)
{
return false;
}
if (_pollfds[0].revents & POLLIN)
{
if (::recv(_pollfds[0].fd, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_SSL;
_sock = _pollfds[0].fd;
return true;
}
}
else if (_pollfds[1].revents & POLLIN)
{
if (::recv(_pollfds[1].fd, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_MULTICAST;
_sock = _pollfds[1].fd;
return true;
}
}
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(_sock, 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, uint16_t portNo)
{
int optval = 1;
int sock = _pollfds[0].fd;
if (_ssl != 0)
{
SSL_free(_ssl);
}
if (sock > 0)
{
::close(sock);
}
sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock <= 0)
{
return -1;
}
optval = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR || SO_REUSEPORT, &optval, sizeof(optval));
if (_ifIndex > 0)
{
#ifdef __APPLE__
setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &_ifIndex, sizeof(_ifIndex));
#else
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, _interfaceName.c_str(), _interfaceName.size());
#endif
}
struct sockaddr_in6 addr;
addr.sin6_family = AF_INET6;
addr.sin6_port = _uPortNo;
addr.sin6_addr = in6addr_any;
if (::bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{
return -1;
}
_pollfds[0].fd = sock;
_pollfds[0].events = POLLIN;
uint16_t listenPort = htons(portNo);
struct sockaddr_in6 dest;
dest.sin6_family = AF_INET6;
dest.sin6_port = htons(listenPort);
memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr));
int rc = 0;
BIO *cbio = BIO_new_dgram(sock, BIO_NOCLOSE);
connect(sock, (sockaddr*) &dest, sizeof(sockaddr_in6));
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest);
_ssl = SSL_new(_ctx);
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
errno = 0;
int stat = SSL_connect(_ssl);
if (stat != 1)
{
rc = -1;
D_NWLOG("SSL fail to connect %s\n",strerror(errno));
}
else
{
D_NWLOG("SSL connected\n");
}
return rc;
}
int verify_cert(int ok, X509_STORE_CTX *ctx)
{
return 1;
}
#endif

View File

@@ -0,0 +1,121 @@
/**************************************************************************************
* 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_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 );
SSL_CTX *_ctx;
SSL *_ssl;
pollfd _pollfds[2];
in_port_t _gPortNo;
in_port_t _uPortNo;
sockaddr_in6 _gIpAddr;
char *_gIpAddrStr;
uint32_t _ifIndex;
string _interfaceName;
uint8_t _castStat;
int _sock;
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

@@ -13,7 +13,6 @@
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#include "LMqttsnClientApp.h"
#ifdef RFCOMM #ifdef RFCOMM
#include <stdio.h> #include <stdio.h>
@@ -29,6 +28,7 @@
#include <bluetooth/bluetooth.h> #include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h> #include <bluetooth/rfcomm.h>
#include "LMqttsnClientApp.h"
#include "LNetworkRfcomm.h" #include "LNetworkRfcomm.h"
#include "LTimer.h" #include "LTimer.h"
#include "LScreen.h" #include "LScreen.h"

View File

@@ -17,7 +17,6 @@
#ifndef NETWORKRFCOMM_H_ #ifndef NETWORKRFCOMM_H_
#define NETWORKRFCOMM_H_ #define NETWORKRFCOMM_H_
#include "LMqttsnClientApp.h"
#ifdef RFCOMM #ifdef RFCOMM
#include <sys/time.h> #include <sys/time.h>

View File

@@ -13,7 +13,6 @@
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#include "LMqttsnClientApp.h"
#ifdef UDP #ifdef UDP
#include <stdio.h> #include <stdio.h>
@@ -27,89 +26,105 @@
#include <fcntl.h> #include <fcntl.h>
#include <termios.h> #include <termios.h>
#include "LMqttsnClientApp.h"
#include "LNetworkUdp.h" #include "LNetworkUdp.h"
#include "LTimer.h" #include "LTimer.h"
#include "LScreen.h" #include "LScreen.h"
using namespace std; using namespace std;
using namespace linuxAsyncClient; using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t* pos); extern uint16_t getUint16(const uint8_t *pos);
extern uint32_t getUint32(const uint8_t* pos); extern uint32_t getUint32(const uint8_t *pos);
extern LScreen* theScreen; extern LScreen *theScreen;
extern bool theClientMode; extern bool theClientMode;
/*========================================= /*=========================================
Class LNetwork Class LNetwork
=========================================*/ =========================================*/
LNetwork::LNetwork(){ LNetwork::LNetwork()
_sleepflg = false; {
resetGwAddress(); _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); {
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); {
return LUdpPort::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo);
} }
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
if (checkRecvBuf())
{
uint16_t recvLen = LUdpPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
if (_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo))
{
return 0;
}
uint8_t* LNetwork::getMessage(int* len){ if (recvLen < 0)
*len = 0; {
if (checkRecvBuf()){ *len = recvLen;
uint16_t recvLen = LUdpPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo); return 0;
if(_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo)){ }
return 0; else
} {
if (_rxDataBuf[0] == 0x01)
if(recvLen < 0){ {
*len = recvLen; *len = getUint16(_rxDataBuf + 1);
return 0; }
}else{ else
if(_rxDataBuf[0] == 0x01){ {
*len = getUint16(_rxDataBuf + 1 ); *len = _rxDataBuf[0];
}else{ }
*len = _rxDataBuf[0]; //if(recvLen != *len){
} // *len = 0;
//if(recvLen != *len){ // return 0;
// *len = 0; //}else{
// return 0; return _rxDataBuf;
//}else{ //}
return _rxDataBuf; }
//} }
} return 0;
}
return 0;
} }
void LNetwork::setGwAddress(void){ void LNetwork::setGwAddress(void)
_gwPortNo = _portNo; {
_gwIpAddress = _ipAddress; _gwPortNo = _portNo;
_gwIpAddress = _ipAddress;
} }
void LNetwork::setFixedGwAddress(void){ void LNetwork::setFixedGwAddress(void)
{
_gwPortNo = LUdpPort::_gPortNo; _gwPortNo = LUdpPort::_gPortNo;
_gwIpAddress = LUdpPort::_gIpAddr; _gwIpAddress = LUdpPort::_gIpAddr;
} }
void LNetwork::resetGwAddress(void){ void LNetwork::resetGwAddress(void)
_gwIpAddress = 0; {
_gwPortNo = 0; _gwIpAddress = 0;
_gwPortNo = 0;
} }
bool LNetwork::initialize(LUdpConfig *config)
bool LNetwork::initialize(LUdpConfig* config){ {
return LUdpPort::open(config); return LUdpPort::open(config);
} }
void LNetwork::setSleep(){ void LNetwork::setSleep()
_sleepflg = true; {
_sleepflg = true;
} }
bool LNetwork::isBroadcastable() bool LNetwork::isBroadcastable()
@@ -117,7 +132,7 @@ bool LNetwork::isBroadcastable()
return true; return true;
} }
/*========================================= /*=========================================
Class udpStack Class udpStack
=========================================*/ =========================================*/
LUdpPort::LUdpPort() LUdpPort::LUdpPort()
{ {
@@ -132,267 +147,302 @@ LUdpPort::~LUdpPort()
close(); close();
} }
void LUdpPort::close()
void LUdpPort::close(){
if(_sockfdMcast > 0)
{
::close( _sockfdMcast);
_sockfdMcast = -1;
if(_sockfdUcast > 0)
{
::close( _sockfdUcast);
_sockfdUcast = -1;
}
}
}
bool LUdpPort::open(LUdpConfig* config)
{ {
const int reuse = 1; if (_sockfdMcast > 0)
char loopch = 1; {
::close(_sockfdMcast);
uint8_t sav = config->ipAddress[3]; _sockfdMcast = -1;
config->ipAddress[3] = config->ipAddress[0]; if (_sockfdUcast > 0)
config->ipAddress[0] = sav; {
sav = config->ipAddress[2]; ::close(_sockfdUcast);
config->ipAddress[2] = config->ipAddress[1]; _sockfdUcast = -1;
config->ipAddress[1] = sav; }
}
_gPortNo = htons(config->gPortNo);
_gIpAddr = getUint32((const uint8_t*)config->ipAddress);
_uPortNo = htons(config->uPortNo);
if( _gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0){
return false;
}
_sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0);
if (_sockfdUcast < 0){
return false;
}
setsockopt(_sockfdUcast, 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 ( _sockfdUcast, (struct sockaddr*)&addr, sizeof(addr)) <0){
return false;
}
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_sockfdMcast < 0){
return false;
}
struct sockaddr_in addrm;
addrm.sin_family = AF_INET;
addrm.sin_port = _gPortNo;
addrm.sin_addr.s_addr = htonl(INADDR_ANY);
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
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();
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 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;
}
return true;
} }
bool LUdpPort::isUnicast(){ bool LUdpPort::open(LUdpConfig *config)
return ( _castStat == STAT_UNICAST); {
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;
_gPortNo = htons(config->gPortNo);
_gIpAddr = getUint32((const uint8_t*) config->ipAddress);
_uPortNo = htons(config->uPortNo);
if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0)
{
return false;
}
_sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0);
if (_sockfdUcast < 0)
{
return false;
}
optval = 1;
setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
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)
{
return false;
}
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_sockfdMcast < 0)
{
return false;
}
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;
}
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 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()
int LUdpPort::unicast(const uint8_t* buf, uint32_t length, uint32_t ipAddress, uint16_t port ){ {
struct sockaddr_in dest; return (_castStat == STAT_UNICAST);
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){
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");
if ( !theClientMode )
{
char sbuf[SCREEN_BUFF_SIZE];
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++){
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 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 LUdpPort::multicast( const uint8_t* buf, uint32_t length ){ int status = ::sendto(_sockfdUcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
struct sockaddr_in dest; if (status < 0)
dest.sin_family = AF_INET; {
dest.sin_port = _gPortNo; D_NWLOG("errno == %d in UdpPort::unicast\n", errno);
dest.sin_addr.s_addr = _gIpAddr; }
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");
int status = ::sendto( _sockfdMcast, buf, length, 0, (const sockaddr*)&dest, sizeof(dest) ); if (!theClientMode)
if( status < 0){ {
D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno); char sbuf[SCREEN_BUFF_SIZE];
DISPLAY("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno); int pos = 0;
return errno; sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(port));
}else{ pos = strlen(sbuf);
D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(_gPortNo)); 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");
}
}
return status;
}
for(uint16_t i = 0; i < length ; i++){ int LUdpPort::multicast(const uint8_t *buf, uint32_t length)
D_NWLOG(" %02x", *(buf + i)); {
DISPLAY(" %02x", *(buf + i)); struct sockaddr_in dest;
} dest.sin_family = AF_INET;
D_NWLOG("\n"); dest.sin_port = _gPortNo;
dest.sin_addr.s_addr = _gIpAddr;
if ( !theClientMode ) int status = ::sendto(_sockfdMcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
{ if (status < 0)
char sbuf[SCREEN_BUFF_SIZE]; {
int pos = 0; D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno);
sprintf(sbuf,"\033[0;34msendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(_gPortNo)); return errno;
pos = strlen(sbuf); }
for(uint16_t i = 0; i < length ; i++){ else
sprintf(sbuf + pos, " %02x", *(buf + i)); {
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20 ) D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(_gPortNo));
{
break; for (uint16_t i = 0; i < length; i++)
} {
pos += 3; D_NWLOG(" %02x", *(buf + i));
} } D_NWLOG("\n");
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf); if (!theClientMode)
} {
return status; 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 LUdpPort::checkRecvBuf(){ bool LUdpPort::checkRecvBuf()
struct timeval timeout; {
timeout.tv_sec = 0; struct timeval timeout;
timeout.tv_usec = 50000; // 50 msec timeout.tv_sec = 0;
timeout.tv_usec = 50000; // 50 msec
uint8_t buf[2]; uint8_t buf[2];
fd_set recvfds; fd_set recvfds;
int maxSock = 0; int maxSock = 0;
FD_ZERO(&recvfds); FD_ZERO(&recvfds);
FD_SET(_sockfdUcast, &recvfds); FD_SET(_sockfdUcast, &recvfds);
FD_SET(_sockfdMcast, &recvfds); FD_SET(_sockfdMcast, &recvfds);
if(_sockfdMcast > _sockfdUcast){ if (_sockfdMcast > _sockfdUcast)
maxSock = _sockfdMcast; {
}else{ maxSock = _sockfdMcast;
maxSock = _sockfdUcast; }
} else
{
maxSock = _sockfdUcast;
}
select(maxSock + 1, &recvfds, 0, 0, &timeout); select(maxSock + 1, &recvfds, 0, 0, &timeout);
if(FD_ISSET(_sockfdUcast, &recvfds)){ if (FD_ISSET(_sockfdUcast, &recvfds))
if( ::recv(_sockfdUcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0){ {
_castStat = STAT_UNICAST; if (::recv(_sockfdUcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
return true; {
} _castStat = STAT_UNICAST;
}else if(FD_ISSET(_sockfdMcast, &recvfds)){ return true;
if( ::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0){ }
_castStat = STAT_MULTICAST; }
return true; else if (FD_ISSET(_sockfdMcast, &recvfds))
} {
} if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
_castStat = 0; {
return false; _castStat = STAT_MULTICAST;
return true;
}
}
_castStat = 0;
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 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; struct sockaddr_in sender;
socklen_t addrlen = sizeof(sender); int status;
memset(&sender, 0, addrlen); socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
if(isUnicast()){ if (isUnicast())
status = ::recvfrom( _sockfdUcast, buf, length, flags, (struct sockaddr*)&sender, &addrlen ); {
}else if(_castStat == STAT_MULTICAST){ D_NWLOG("Ucast ");
status = ::recvfrom( _sockfdMcast, buf, length, flags, (struct sockaddr*)&sender, &addrlen ); status = ::recvfrom(_sockfdUcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
}else{ }
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) { 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); D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::recvfrom \033[0m\033[0;37m\n", errno);
}else if(status > 0){ }
*ipAddressPtr = sender.sin_addr.s_addr; else if (status > 0)
*portPtr = sender.sin_port; {
D_NWLOG("\nrecved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr)); *ipAddressPtr = sender.sin_addr.s_addr;
for(uint16_t i = 0; i < status ; i++){ *portPtr = sender.sin_port;
D_NWLOG(" %02x", *(buf + i)); D_NWLOG("recved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr));
} for (uint16_t i = 0; i < status; i++)
D_NWLOG("\n"); {
D_NWLOG(" %02x", *(buf + i));
} D_NWLOG("\n");
if ( !theClientMode ) if (!theClientMode)
{ {
char sbuf[SCREEN_BUFF_SIZE]; char sbuf[SCREEN_BUFF_SIZE];
int pos = 0; int pos = 0;
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr)); sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", inet_ntoa(sender.sin_addr), htons(*portPtr));
pos = strlen(sbuf); 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 ) sprintf(sbuf + pos, " %02x", *(buf + i));
{ if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
break; {
} break;
pos += 3; }
} pos += 3;
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); }
theScreen->display(sbuf); sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
} theScreen->display(sbuf);
return status; }
}else{ return status;
return 0; }
} else
return status; {
return 0;
}
return status;
} }
#endif #endif

View File

@@ -17,7 +17,6 @@
#ifndef NETWORKUDP_H_ #ifndef NETWORKUDP_H_
#define NETWORKUDP_H_ #define NETWORKUDP_H_
#include "LMqttsnClientApp.h"
#ifdef UDP #ifdef UDP
#include <sys/time.h> #include <sys/time.h>
@@ -30,7 +29,6 @@
#include <string> #include <string>
#include <arpa/inet.h> #include <arpa/inet.h>
#define SOCKET_MAXHOSTNAME 200 #define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5 #define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500 #define SOCKET_MAXRECV 500

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, 2000); // Timeout 2secs
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

@@ -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,142 +1,211 @@
MQTT-SN Transparent / Aggregating Gateway # 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** 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 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. This Gateway can run as a transparent or aggregating Gateway by specifying the gateway.conf.
### step1. Build the gateway
### **step1. Build the gateway** copy and expand source code then,
```` ```
$ git clone -b develop https://github.com/eclipse/paho.mqtt-sn.embedded-c $ cd paho.mqtt-sn.embedded-c/MQTTSNGateway
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway ```
In order to build a gateway, one sensor network argument is required.
```
$ ./build.sh [udp|udp6|xbee|loralink|rfcomm] $ ./build.sh [udp|udp6|xbee|loralink|rfcomm]
```
````
In order to build a gateway, an argument is required.
MQTT-SNGateway and MQTT-SNLogmonitor (executable programs) are built in the Build directory.
### **step2. Execute the Gateway.**
```` MQTT-SNGateway and MQTT-SNLogmonitor (executable programs) are built in ./bin directory.
### step2. Execute the Gateway.
```
$ cd bin $ cd bin
$ ./MQTT-SNGateway $ ./MQTT-SNGateway
```` ```
If you get the error message as follows: If you get the error message as follows:
````
RingBuffer can't create a shared memory. RingBuffer can't create a shared memory. ABORT Gateway!!!
ABORT Gateway!!!
````
You have to start using sudo command only once for the first time. You have to start using sudo command only once for the first time.
```` ```
$ sudo ./MQTT-SNGateway $ sudo ./MQTT-SNGateway
```` ```
## Contents of the gateway configuration file
**gateway.conf** is in bin directory. It's contents are follows:
### **How to Change the configuration of the gateway** ```
**gateway.conf** Contents are follows: #**************************************************************************
# Copyright (c) 2016-2021, Tomoaki Yamaguchi
<pre><dev> #
# 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 # config file of MQTT-SN Gateway
# #
GatewayID=1
GatewayName=PahoGateway-01
MaxNumberOfClients=30
KeepAlive=60
#LoginID=your_ID
#Password=your_Password
BrokerName=mqtt.eclipseprojects.io BrokerName=mqtt.eclipseprojects.io
BrokerPortNo=1883 BrokerPortNo=1883
BrokerSecurePortNo=8883 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, # When AggregatingGateway=YES or ClientAuthentication=YES,
# All clients must be specified by the ClientList File # All clients must be specified by the ClientList File
# #
ClientAuthentication=NO
AggregatingGateway=NO AggregatingGateway=NO
QoS-1=NO QoS-1=NO
Forwarder=NO Forwarder=NO
MaxNumberOfClients=30;
#ClientsList=/path/to/your_clients.conf
PredefinedTopic=NO PredefinedTopic=NO
#PredefinedTopicList=/path/to/your_predefinedTopic.conf ClientAuthentication=NO
#RootCAfile=/etc/ssl/certs/ca-certificates.crt ClientsList=/path/to/your_clients.conf
#RootCApath=/etc/ssl/certs/ PredefinedTopicList=/path/to/your_predefinedTopic.conf
#CertsFile=/path/to/certKey.pem ```
#PrivateKey=/path/to/privateKey.pem 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.
GatewayID=1 If **Forwarder** is 'YES', the gateway prepare a forwarder agent.
GatewayName=PahoGateway-01 If **ClientAuthentication** is 'YES', the client cannot connect unless it is registered in the clients.conf file.
KeepAlive=900 **ClientsList** defines clients and those address so on.
#LoginID=your_ID **PredefinedTopicList** file defines Predefined Topic.
#Password=your_Password
# UDP ```
#==============================
# SensorNetworks parameters
#==============================
#
# UDP | DTLS
#
GatewayPortNo=10000 GatewayPortNo=10000
MulticastIP=225.1.1.1
MulticastPortNo=1883 MulticastPortNo=1883
MulticastTTL=1 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 GatewayIPv6PortNo=10000
GatewayUDP6Bind=FFFF:FFFE::1 MulticastIPv6PortNo=1883
GatewayUDP6Port=10000 MulticastIPv6=ff1e:feed:caca:dead::feed:caca:dead
GatewayUDP6Broadcast=FF02::1 MulticastIPv6If=wlp4s0
GatewayUDP6If=wpan0 MulticastHops=1
GatewayUDP6Hops=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 # XBee
#
Baudrate=38400 Baudrate=38400
SerialDevice=/dev/ttyUSB0 SerialDevice=/dev/ttyUSB0
ApiMode=2 ApiMode=2
```
**Baudrate** is a baudrate of xbee.
```
#
# LoRaLink
#
#LoRaLink
BaudrateLoRaLink=115200 BaudrateLoRaLink=115200
DeviceRxLoRaLink=/dev/ttyLoRaLinkRx DeviceRxLoRaLink=/dev/loralinkRx
DeviceTxLoRaLink=/dev/ttyLoRaLinkTx DeviceTxLoRaLink=/dev/loralinkTx
```
https://github.com/ty4tw/MQTT-SN-LoRa
```
#
# Bluetooth RFCOMM # Bluetooth RFCOMM
#
RFCOMMAddress=60:57:18:06:8B:72.* RFCOMMAddress=60:57:18:06:8B:72.*
```
**RFCOMMAddress** is a bluetooth mac address and channel. channel should be * for the gateway.
```
#
# LOG # 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. ### How to monitor the gateway from a remote terminal.
**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.
**MaxNumberOfClients** Maximum number of clients allocated.
### ** How to monitor the gateway from remote. **
Change gateway.conf as follows: Change gateway.conf as follows:
``` ```
# LOG # LOG
ShearedMemory=YES; ShearedMemory=YES;
```` ```
Restart the gateway with sudo only once to create shared memories.
Restart the gateway with sudo only once to create shared memories.
open ssh terminal and execute LogMonitor. open ssh terminal and execute LogMonitor.
``` ```
$ cd bin $ cd bin
$ ./MQTT-SNLogmonitor $ ./MQTT-SNLogmonitor
``` ```
Now you can get the Log on your terminal. Now you can get the Log on your terminal.
## ** Tips ** ##### Tips
Uncomment the line 62, 63 in MQTTSNDefines.h then you can get more precise logs. 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.
```
./build.sh udp -DDEBUG -DDEBUG_NW
``` ```
/*=================================
* Log controls
==================================*/
//#define DEBUG // print out log for debug
//#define DEBUG_NWSTACK // print out SensorNetwork log
```

View File

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

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

View File

@@ -35,6 +35,9 @@ IF(NOT DEFINED SENSORNET)
ENDIF() ENDIF()
MESSAGE(STATUS "SENSORNET: " ${SENSORNET}) MESSAGE(STATUS "SENSORNET: " ${SENSORNET})
ADD_DEFINITIONS(${DEFS})
MESSAGE(STATUS "Definitions: " ${DEFS})
ADD_LIBRARY(mqtt-sngateway_common ADD_LIBRARY(mqtt-sngateway_common
MQTTGWConnectionHandler.cpp MQTTGWConnectionHandler.cpp
MQTTGWPacket.cpp MQTTGWPacket.cpp
@@ -74,8 +77,11 @@ ADD_LIBRARY(mqtt-sngateway_common
${OS}/Threading.h ${OS}/Threading.h
) )
# linux
link_directories("/usr/local/lib") link_directories("/usr/local/lib")
link_directories("/usr/local/opt/openssl/lib")
# Mac
link_directories("/usr/local/opt/openssl")
TARGET_INCLUDE_DIRECTORIES(mqtt-sngateway_common TARGET_INCLUDE_DIRECTORIES(mqtt-sngateway_common
@@ -84,7 +90,7 @@ TARGET_INCLUDE_DIRECTORIES(mqtt-sngateway_common
${OS} ${OS}
${OS}/${SENSORNET} ${OS}/${SENSORNET}
../../MQTTSNPacket/src ../../MQTTSNPacket/src
/usr/local/opt/openssl/include /usr/local/include
) )
IF(SENSORNET MATCHES "rfcomm") IF(SENSORNET MATCHES "rfcomm")

View File

@@ -17,6 +17,7 @@
#include "MQTTSNGWBrokerRecvTask.h" #include "MQTTSNGWBrokerRecvTask.h"
#include "MQTTSNGWClient.h" #include "MQTTSNGWClient.h"
#include "MQTTSNGWClientList.h" #include "MQTTSNGWClientList.h"
#include "MQTTSNGateway.h"
#include <unistd.h> #include <unistd.h>
using namespace std; using namespace std;

View File

@@ -58,6 +58,7 @@ ClientList::~ClientList()
void ClientList::initialize(bool aggregate) void ClientList::initialize(bool aggregate)
{ {
_maxClients = _gateway->getGWParams()->maxClients;
_clientsPool->allocate(_gateway->getGWParams()->maxClients); _clientsPool->allocate(_gateway->getGWParams()->maxClients);
if (_gateway->getGWParams()->clientAuthentication) if (_gateway->getGWParams()->clientAuthentication)
@@ -380,6 +381,7 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId,
{ {
client->setQoSm1(); client->setQoSm1();
} }
client->getNetwork()->setSecure(secure);
_mutex.lock(); _mutex.lock();
@@ -402,16 +404,18 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId,
Client* ClientList::createPredefinedTopic(MQTTSNString* clientId, string topicName, uint16_t topicId, bool aggregate) Client* ClientList::createPredefinedTopic(MQTTSNString* clientId, string topicName, uint16_t topicId, bool aggregate)
{ {
Client *client = nullptr;
if (topicId == 0) if (topicId == 0)
{ {
WRITELOG("Invalid TopicId. Predefined Topic %s, TopicId is 0. \n", topicName.c_str()); WRITELOG("Invalid TopicId. Predefined Topic %s, TopicId is 0. \n", topicName.c_str());
return nullptr; goto exit;
} }
if (strcmp(clientId->cstring, common_topic) == 0) if (strcmp(clientId->cstring, common_topic) == 0)
{ {
_gateway->getTopics()->add((const char*) topicName.c_str(), topicId); _gateway->getTopics()->add((const char*) topicName.c_str(), topicId);
return nullptr; goto exit;
} }
else else
{ {
@@ -419,47 +423,19 @@ Client* ClientList::createPredefinedTopic(MQTTSNString* clientId, string topicNa
if (_authorize && client == nullptr) if (_authorize && client == nullptr)
{ {
return nullptr; goto exit;
} }
/* anonimous clients */ client = createClient(NULL, clientId, aggregate);
if (_clientCnt > MAX_CLIENTS) if (client)
{ {
return nullptr; // full of clients // create Topic & Add it
client->getTopics()->add((const char*) topicName.c_str(), topicId);
client->_hasPredefTopic = true;
} }
if (client == nullptr)
{
/* creat a new client */
client = new Client();
client->setClientId(*clientId);
if (aggregate)
{
client->setAggregated();
}
_mutex.lock();
/* add the list */
if (_firstClient == nullptr)
{
_firstClient = client;
_endClient = client;
}
else
{
_endClient->_nextClient = client;
client->_prevClient = _endClient;
_endClient = client;
}
_clientCnt++;
_mutex.unlock();
}
// create Topic & Add it
client->getTopics()->add((const char*) topicName.c_str(), topicId);
client->_hasPredefTopic = true;
return client;
} }
exit:
return client;
} }
uint16_t ClientList::getClientCount() uint16_t ClientList::getClientCount()
@@ -517,15 +493,17 @@ void ClientsPool::allocate(int maxClients)
Client* ClientsPool::getClient(void) Client* ClientsPool::getClient(void)
{ {
Client *cl = nullptr;
while (_firstClient != nullptr) while (_firstClient != nullptr)
{ {
Client* cl = _firstClient; cl = _firstClient;
_firstClient = cl->_nextClient; _firstClient = cl->_nextClient;
cl->_nextClient = nullptr; cl->_nextClient = nullptr;
_clientCnt--; _clientCnt--;
return cl; break;
} }
return nullptr; return cl;
} }
void ClientsPool::setClient(Client* client) void ClientsPool::setClient(Client* client)

View File

@@ -83,6 +83,7 @@ private:
Client* _endClient; Client* _endClient;
Mutex _mutex; Mutex _mutex;
uint16_t _clientCnt; uint16_t _clientCnt;
uint16_t _maxClients;
bool _authorize { false }; bool _authorize { false };
}; };

View File

@@ -37,7 +37,7 @@ namespace MQTTSNGW
/*================================= /*=================================
* MQTT-SN Parametrs * 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_CLIENTID_LENGTH (64) // Max length of clientID
#define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages #define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages
#define MAX_MESSAGEID_TABLE_SIZE (500) // Number of MessageIdTable size #define MAX_MESSAGEID_TABLE_SIZE (500) // Number of MessageIdTable size
@@ -60,13 +60,19 @@ typedef unsigned int uint32_t;
/*================================= /*=================================
* Log controls * Log controls
==================================*/ ==================================*/
//#define DEBUG // print out log for debug //#define DEBUG_MQTTSN // print out log for debug
//#define DEBUG_NWSTACK // print out SensorNetwork log //#define DEBUG_NW // print out SensorNetwork log
#ifdef DEBUG #ifdef DEBUG_MQTTSN
#define DEBUGLOG(...) printf(__VA_ARGS__) #define DEBUGLOG(...) printf(__VA_ARGS__)
#else #else
#define DEBUGLOG(...) #define DEBUGLOG(...)
#endif #endif
#ifdef DEBUG_NW
#define D_NWSTACK(...) printf(__VA_ARGS__)
#else
#define D_NWSTACK(...)
#endif
} }
#endif /* MQTTSNGWDEFINES_H_ */ #endif /* MQTTSNGWDEFINES_H_ */

View File

@@ -100,10 +100,6 @@ int MQTTSNPacket::recv(SensorNetwork* network)
{ {
len = desirialize(buf, len); len = desirialize(buf, len);
} }
else
{
len = 0;
}
return len; return len;
} }

View File

@@ -22,6 +22,7 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class SensorNetwork;
class MQTTSNPacket class MQTTSNPacket
{ {

View File

@@ -38,6 +38,7 @@ using namespace MQTTSNGW;
#define EVENT_QUE_TIME_OUT 2000 // 2000 msecs #define EVENT_QUE_TIME_OUT 2000 // 2000 msecs
char* currentDateTime(void); char* currentDateTime(void);
/*===================================== /*=====================================
Class PacketHandleTask Class PacketHandleTask
=====================================*/ =====================================*/

View File

@@ -16,6 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <string>
#include <stdarg.h> #include <stdarg.h>
#include <signal.h> #include <signal.h>
#include <Timer.h> #include <Timer.h>
@@ -156,6 +157,8 @@ int Process::getParam(const char* parameter, char* value)
{ {
char str[MQTTSNGW_PARAM_MAX]; char str[MQTTSNGW_PARAM_MAX];
char param[MQTTSNGW_PARAM_MAX]; char param[MQTTSNGW_PARAM_MAX];
memset(str, 0, sizeof(str));
memset(param, 0, sizeof(param));
FILE *fp; FILE *fp;
int i = 0, j = 0; int i = 0, j = 0;
@@ -166,40 +169,55 @@ int Process::getParam(const char* parameter, char* value)
throw Exception("Config file not found:\n\nUsage: Command -f path/config_file_name\n", 0); throw Exception("Config file not found:\n\nUsage: Command -f path/config_file_name\n", 0);
} }
int paramlen = strlen(parameter);
while (true) while (true)
{ {
int pos = 0;
int len = 0;
if (fgets(str, MQTTSNGW_PARAM_MAX - 1, fp) == NULL) if (fgets(str, MQTTSNGW_PARAM_MAX - 1, fp) == NULL)
{ {
fclose(fp); fclose(fp);
return -3; return -3;
} }
if (!strncmp(str, parameter, strlen(parameter))) if (str[0] == '#' || str[0] == '\n')
{ {
while (str[i++] != '=') continue;
{ }
;
}
while (str[i] != '\n')
{
param[j++] = str[i++];
}
param[j] = '\0';
for (i = strlen(param) - 1; i >= 0 && isspace(param[i]); i--) len = strlen(str);
; for (pos = 0; i < len; pos++)
param[i + 1] = '\0'; {
for (i = 0; isspace(param[i]); i++) if (str[pos] == '=')
;
if (i > 0)
{ {
j = 0; break;
while (param[i]) }
param[j++] = param[i++]; }
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--)
;
param[i + 1] = '\0';
for (i = 0; isspace(param[i]); i++)
;
if (i > 0)
{
j = 0;
while (param[i])
param[j++] = param[i++];
param[j] = '\0';
}
strcpy(value, param);
fclose(fp);
return 0;
} }
strcpy(value, param);
fclose(fp);
return 0;
} }
} }
fclose(fp); fclose(fp);

View File

@@ -32,9 +32,9 @@ MQTTSNGW::Gateway* theGateway = nullptr;
Gateway::Gateway(void) Gateway::Gateway(void)
{ {
theGateway = this;
theMultiTaskProcess = this; theMultiTaskProcess = this;
theProcess = this; theProcess = this;
_packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS);
_clientList = new ClientList(this); _clientList = new ClientList(this);
_adapterManager = new AdapterManager(this); _adapterManager = new AdapterManager(this);
_topics = new Topics(); _topics = new Topics();
@@ -95,15 +95,21 @@ Gateway::~Gateway()
{ {
free(_params.configName); free(_params.configName);
} }
if (_params.qosMinusClientListName) if (_params.qosMinusClientListName)
{ {
free(_params.qosMinusClientListName); free(_params.qosMinusClientListName);
} }
if (_params.rfcommAddr)
if (_params.bleAddress)
{ {
free(_params.bleAddress); free(_params.rfcommAddr);
}
if (_params.gwCertskey)
{
free(_params.gwCertskey);
}
if (_params.gwPrivatekey)
{
free(_params.gwPrivatekey);
} }
if (_adapterManager) if (_adapterManager)
@@ -114,7 +120,6 @@ Gateway::~Gateway()
{ {
delete _clientList; delete _clientList;
} }
if (_topics) if (_topics)
{ {
delete _topics; delete _topics;
@@ -178,6 +183,14 @@ void Gateway::initialize(int argc, char** argv)
{ {
_params.rootCAfile = strdup(param); _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) if (getParam("GatewayID", param) == 0)
{ {
@@ -282,11 +295,14 @@ void Gateway::initialize(int argc, char** argv)
_params.maxClients = atoi(param); _params.maxClients = atoi(param);
} }
if (getParam("BleAddress", param) == 0) if (getParam("RFCOMMAddress", param) == 0)
{ {
_params.bleAddress = strdup(param); _params.rfcommAddr = strdup(param);
} }
/* Setup max PacketEventQue size */
_packetEventQue.setMaxSize(_params.maxInflightMsgs * _params.maxClients);
/* Initialize adapters */ /* Initialize adapters */
_adapterManager->initialize(_params.gatewayName, _params.aggregatingGw, _params.forwarder, _params.qosMinus1); _adapterManager->initialize(_params.gatewayName, _params.aggregatingGw, _params.forwarder, _params.qosMinus1);
@@ -308,26 +324,30 @@ void Gateway::run(void)
WRITELOG(" *\n%s\n", PAHO_COPYRIGHT3); WRITELOG(" *\n%s\n", PAHO_COPYRIGHT3);
WRITELOG(" * Version: %s\n", PAHO_GATEWAY_VERSION); WRITELOG(" * Version: %s\n", PAHO_GATEWAY_VERSION);
WRITELOG("%s\n", PAHO_COPYRIGHT4); WRITELOG("%s\n", PAHO_COPYRIGHT4);
WRITELOG("\n%s %s has been started.\n\n", currentDateTime(), _params.gatewayName); WRITELOG(" ConfigFile : %s\n", _params.configName);
WRITELOG(" ConfigFile: %s\n", _params.configName);
if (_params.clientListName) if (_params.clientListName)
{ {
WRITELOG(" ClientList: %s\n", _params.clientListName); WRITELOG(" ClientList : %s\n", _params.clientListName);
} }
if (_params.predefinedTopicFileName) if (_params.predefinedTopicFileName)
{ {
WRITELOG(" PreDefFile: %s\n", _params.predefinedTopicFileName); WRITELOG(" PreDefFile : %s\n", _params.predefinedTopicFileName);
} }
WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription()); WRITELOG(" Broker : %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure);
WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); WRITELOG(" RootCApath : %s\n", _params.rootCApath);
WRITELOG(" Max number of Clients: %d\n", _params.maxClients); WRITELOG(" RootCAfile : %s\n", _params.rootCAfile);
WRITELOG(" RootCApath: %s\n", _params.rootCApath); WRITELOG(" CertKey : %s\n", _params.certKey);
WRITELOG(" RootCAfile: %s\n", _params.rootCAfile); WRITELOG(" PrivateKey : %s\n", _params.privateKey);
WRITELOG(" CertKey: %s\n", _params.certKey); WRITELOG(" SensorN/W : %s\n", _sensorNetwork.getDescription());
WRITELOG(" PrivateKey: %s\n\n\n", _params.privateKey); #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; _stopFlg = false;
@@ -408,12 +428,12 @@ bool Gateway::hasSecureConnection(void)
{ {
return (_params.certKey && _params.privateKey && _params.rootCApath && _params.rootCAfile); return (_params.certKey && _params.privateKey && _params.rootCApath && _params.rootCAfile);
} }
/*===================================== /*=====================================
Class EventQue Class EventQue
=====================================*/ =====================================*/
EventQue::EventQue() EventQue::EventQue()
{ {
} }
EventQue::~EventQue() EventQue::~EventQue()

View File

@@ -168,7 +168,9 @@ public:
bool qosMinus1 { false }; bool qosMinus1 { false };
bool forwarder { false }; bool forwarder { false };
int maxClients {0}; int maxClients {0};
char* bleAddress { nullptr }; char* rfcommAddr { nullptr };
char* gwCertskey { nullptr };
char* gwPrivatekey { nullptr };
}; };
/*===================================== /*=====================================
@@ -197,10 +199,10 @@ public:
int getParam(const char* parameter, char* value); int getParam(const char* parameter, char* value);
char* getClientListFileName(void); char* getClientListFileName(void);
char* getPredefinedTopicFileName(void); char* getPredefinedTopicFileName(void);
bool hasSecureConnection(void); bool hasSecureConnection(void);
Topics* getTopics(void); Topics* getTopics(void);
bool IsStopping(void); bool IsStopping(void);
void requestSensorNetSubTask(void);
private: private:
GatewayParams _params; GatewayParams _params;
@@ -214,7 +216,6 @@ private:
Topics* _topics; Topics* _topics;
bool _stopFlg; bool _stopFlg;
}; };
} }
#endif /* MQTTSNGATEWAY_H_ */ #endif /* MQTTSNGATEWAY_H_ */

View File

@@ -656,3 +656,7 @@ bool Network::isSecure()
return _secureFlg; return _secureFlg;
} }
void Network::setSecure(bool secureFlg)
{
_secureFlg = secureFlg;
}

View File

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

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);
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);
int searchClient(SensorNetAddress *addr);
private:
pollfd *_pollfds;
SSL **_ssls;
SensorNetAddress **_clientAddr;
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);
void close();
private:
int openV4(string *ipAddress, uint16_t multiPortNo, uint16_t uniPortNo, uint16_t listenPortNo, uint32_t ttl);
int openV6(string *ipAddress, string *interface, uint16_t multiPortNo, uint16_t uniPortNo, uint16_t listenPortNo,
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

@@ -383,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) 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 buf[2] = { 0 };
uint8_t chks = 0; uint8_t chks = 0;
uint16_t len = pLen + 3; // 3 = DestAddr[1] + PayloadType[1] + Crc[1] uint16_t len = pLen + 3; // 3 = DestAddr[1] + PayloadType[1] + Crc[1]
@@ -404,7 +404,7 @@ int LoRaLink::send(LoRaLinkPayloadType_t type, const uint8_t* payload, uint16_t
send(type); send(type);
chks += type; chks += type;
D_NWSTACK("\r\n Payload: "); D_LRSTACK("\r\n Payload: ");
for ( uint8_t i = 0; i < pLen; i++ ){ for ( uint8_t i = 0; i < pLen; i++ ){
send(payload[i]); // Payload send(payload[i]); // Payload
@@ -412,21 +412,21 @@ int LoRaLink::send(LoRaLinkPayloadType_t type, const uint8_t* payload, uint16_t
} }
chks = 0xff - chks; chks = 0xff - chks;
D_NWSTACK(" checksum "); D_LRSTACK(" checksum ");
send(chks); send(chks);
D_NWSTACK("\r\n"); D_LRSTACK("\r\n");
/* wait ACK */ /* wait ACK */
_sem.timedwait(LORALINK_TIMEOUT_ACK); _sem.timedwait(LORALINK_TIMEOUT_ACK);
if ( _respCd == LORALINK_NO_FREE_CH ) if ( _respCd == LORALINK_NO_FREE_CH )
{ {
D_NWSTACK(" Channel isn't free\r\n"); D_LRSTACK(" Channel isn't free\r\n");
return -1; return -1;
} }
else if ( _respCd != LORALINK_ACK ) else if ( _respCd != LORALINK_ACK )
{ {
D_NWSTACK(" Not Acknowleged\r\n"); D_LRSTACK(" Not Acknowleged\r\n");
return -1; return -1;
} }
return (int)pLen; return (int)pLen;
@@ -479,7 +479,7 @@ int LoRaLink::recv(uint8_t* buf)
/* /*
if ( *buf == ESCAPE ) if ( *buf == ESCAPE )
{ {
D_NWSTACK( " %02x",buf[0] ); D_LRSTACK( " %02x",buf[0] );
if ( read(fd, buf, 1) == 1 ) if ( read(fd, buf, 1) == 1 )
{ {
*buf = PAD ^ *buf; *buf = PAD ^ *buf;
@@ -491,7 +491,7 @@ int LoRaLink::recv(uint8_t* buf)
} }
*/ */
D_NWSTACK( " %02x",buf[0] ); D_LRSTACK(" %02x", buf[0]);
return 0; return 0;
} }
} }
@@ -552,7 +552,7 @@ bool SerialPort::send(unsigned char b)
} }
else else
{ {
D_NWSTACK( " %02x", b); D_LRSTACK(" %02x", b);
return true; return true;
} }
} }

View File

@@ -11,7 +11,7 @@
* http://www.eclipse.org/org/documents/edl-v10.php. * http://www.eclipse.org/org/documents/edl-v10.php.
* *
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation * Tomoaki Yamaguchi - initial API and implementation
**************************************************************************************/ **************************************************************************************/
#ifndef SENSORNETWORKX_H_ #ifndef SENSORNETWORKX_H_
#define SENSORNETWORKX_H_ #define SENSORNETWORKX_H_
@@ -25,12 +25,11 @@ using namespace std;
namespace MQTTSNGW namespace MQTTSNGW
{ {
//#define DEBUG_NWSTACK
#ifdef DEBUG_NWSTACK #ifdef DEBUG_NW
#define D_NWSTACK(...) printf(__VA_ARGS__); fflush(stdout) #define D_LRSTACK(...) printf(__VA_ARGS__); fflush(stdout)
#else #else
#define D_NWSTACK(...) #define D_LRSTACK(...)
#endif #endif

View File

@@ -26,12 +26,6 @@ using namespace std;
namespace MQTTSNGW namespace MQTTSNGW
{ {
#ifdef DEBUG_NWSTACK
#define D_NWSTACK(...) printf(__VA_ARGS__)
#else
#define D_NWSTACK(...)
#endif
#define MAX_RFCOMM_CH 30 #define MAX_RFCOMM_CH 30
/*=========================================== /*===========================================

View File

@@ -20,10 +20,13 @@
#include <netinet/ip.h> #include <netinet/ip.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <string.h> #include <string.h>
#include <regex> #include <regex>
#include <string> #include <string>
#include <stdlib.h> #include <stdlib.h>
#include <poll.h>
#include "SensorNetwork.h" #include "SensorNetwork.h"
#include "MQTTSNGWProcess.h" #include "MQTTSNGWProcess.h"
@@ -196,33 +199,33 @@ void SensorNetwork::initialize(void)
* MulticastIP=225.1.1.1 * MulticastIP=225.1.1.1
* MulticastPortNo=1883 * MulticastPortNo=1883
* *
*/ */
if (theProcess->getParam("MulticastIP", param) == 0) if (theProcess->getParam("MulticastIP", param) == 0)
{ {
ip = param; ip = param;
_description = "UDP Multicast "; _description = "UDP Multicast ";
_description += param; _description += param;
} }
if (theProcess->getParam("MulticastPortNo", param) == 0) if (theProcess->getParam("MulticastPortNo", param) == 0)
{ {
multicastPortNo = atoi(param); multicastPortNo = atoi(param);
_description += ":"; _description += ":";
_description += param; _description += param;
} }
if (theProcess->getParam("GatewayPortNo", param) == 0) if (theProcess->getParam("GatewayPortNo", param) == 0)
{ {
unicastPortNo = atoi(param); unicastPortNo = atoi(param);
_description += " Gateway Port "; _description += ", Gateway Port:";
_description += param; _description += param;
} }
if (theProcess->getParam("MulticastTTL", param) == 0) if (theProcess->getParam("MulticastTTL", param) == 0)
{ {
ttl = atoi(param); ttl = atoi(param);
_description += " TTL: "; _description += ", TTL:";
_description += param; _description += param;
} }
/* Prepare UDP sockets */ /* setup UDP sockets */
errno = 0; errno = 0;
if ( UDPPort::open(ip.c_str(), multicastPortNo, unicastPortNo, ttl) < 0 ) if ( UDPPort::open(ip.c_str(), multicastPortNo, unicastPortNo, ttl) < 0 )
{ {
@@ -247,9 +250,7 @@ SensorNetAddress* SensorNetwork::getSenderAddress(void)
UDPPort::UDPPort() UDPPort::UDPPort()
{ {
_disconReq = false; _disconReq = false;
_sockfdUnicast = -1; memset(_pollFds, 0, sizeof(_pollFds));
_sockfdMulticast = -1;
_ttl = 0;
} }
UDPPort::~UDPPort() UDPPort::~UDPPort()
@@ -259,130 +260,126 @@ UDPPort::~UDPPort()
void UDPPort::close(void) void UDPPort::close(void)
{ {
if (_sockfdUnicast > 0) for (int i = 0; i < 2; i++)
{ {
::close(_sockfdUnicast); if (_pollFds[i].fd > 0)
_sockfdUnicast = -1; {
} ::close(_pollFds[i].fd);
if (_sockfdMulticast > 0) _pollFds[i].fd = 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; int optval = 0;
const int reuse = 1; int sock = 0;
if (uniPortNo == 0 || multiPortNo == 0) if (uniPortNo == 0 || multiPortNo == 0)
{ {
D_NWSTACK("error portNo undefined in UDPPort::open\n"); D_NWSTACK("error portNo undefined in UDPPort::open\n");
return -1; return -1;
} }
uint32_t ip = inet_addr(ipAddress); /*------ Create unicast socket --------*/
_multicastAddr.setAddress(ip, htons(multiPortNo)); sock = socket(AF_INET, SOCK_DGRAM, 0);
_unicastAddr.setAddress(ip, htons(uniPortNo)); if (sock < 0)
_ttl = ttl; {
D_NWSTACK("error can't create unicast socket in UDPPort::open\n");
return -1;
}
/*------ Create unicast socket --------*/ sockaddr_in addru;
_sockfdUnicast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); addru.sin_family = AF_INET;
if (_sockfdUnicast < 0) addru.sin_port = htons(uniPortNo);
{ addru.sin_addr.s_addr = INADDR_ANY;
D_NWSTACK("error can't create unicast socket in UDPPort::open\n");
return -1;
}
setsockopt(_sockfdUnicast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); if (::bind(sock, (sockaddr*) &addru, sizeof(addru)) < 0)
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)
{ {
D_NWSTACK("error can't bind unicast socket in UDPPort::open\n"); D_NWSTACK("error can't bind unicast socket in UDPPort::open\n");
return -1; 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;
}
/*------ Create Multicast socket --------*/ _pollFds[0].fd = sock;
_sockfdMulticast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); _pollFds[0].events = POLLIN;
if (_sockfdMulticast < 0)
/*------ Create Multicast socket --------*/
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{ {
D_NWSTACK("error can't create multicast socket in UDPPort::open\n"); D_NWSTACK("error can't create multicast socket in UDPPort::open\n");
close(); close();
return -1; 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; sockaddr_in addrm;
addrm.sin_family = AF_INET; addrm.sin_family = AF_INET;
addrm.sin_port = _multicastAddr.getPortNo(); addrm.sin_port = htons(multiPortNo);
addrm.sin_addr.s_addr = INADDR_ANY; 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"); D_NWSTACK("error can't bind multicast socket in UDPPort::open\n");
return -1; return -1;
} }
if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_MULTICAST_LOOP, (char*) &loopch, sizeof(loopch)) < 0)
{
D_NWSTACK("error IP_MULTICAST_LOOP in UDPPort::open\n");
close();
return -1;
}
ip_mreq mreq; ip_mreq mreq;
mreq.imr_interface.s_addr = INADDR_ANY; memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr.s_addr = _multicastAddr.getIpAddress(); mreq.imr_interface.s_addr = INADDR_ANY;
mreq.imr_multiaddr.s_addr = inet_addr(multicastIP);
if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{ {
D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n");
close(); close();
return -1; return -1;
} }
if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,sizeof(ttl)) < 0) if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
{ {
D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); D_NWSTACK("error Multicast IP_MULTICAST_TTL in UDPPort::open\n");
close(); close();
return -1; return -1;
} }
if (setsockopt(_sockfdUnicast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) #ifdef DEBUG_NW
{ optval = 1;
D_NWSTACK("error Unicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); #else
close(); optval = 0;
return -1; #endif
}
return 0; 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;
}
_multicastAddr.setAddress(inet_addr(multicastIP), htons(multiPortNo));
_pollFds[1].fd = sock;
_pollFds[1].events = POLLIN;
return 0;
} }
int UDPPort::unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* addr) int UDPPort::unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* addr)
{ {
sockaddr_in dest; sockaddr_in dest;
dest.sin_family = AF_INET; dest.sin_family = AF_INET;
dest.sin_port = addr->getPortNo(); dest.sin_port = addr->getPortNo();
dest.sin_addr.s_addr = addr->getIpAddress(); 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) if (status < 0)
{ {
D_NWSTACK("errno == %d in UDPPort::sendto\n", errno); 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; 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) int UDPPort::broadcast(const uint8_t* buf, uint32_t length)
@@ -392,55 +389,35 @@ int UDPPort::broadcast(const uint8_t* buf, uint32_t length)
int UDPPort::recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr) int UDPPort::recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr)
{ {
struct timeval timeout; int rc = 0;
fd_set recvfds; poll(_pollFds, 2, 2000); // Timeout 2 seconds
int maxSock = 0;
timeout.tv_sec = 1; if (_pollFds[0].revents == POLLIN)
timeout.tv_usec = 0; // 1 sec {
FD_ZERO(&recvfds); rc = recvfrom(_pollFds[0].fd, buf, len, 0, addr);
FD_SET(_sockfdUnicast, &recvfds); }
FD_SET(_sockfdMulticast, &recvfds); else if (_pollFds[1].revents == POLLIN)
{
if (_sockfdMulticast > _sockfdUnicast) rc = recvfrom(_pollFds[1].fd, buf, len, 0, addr);
{ }
maxSock = _sockfdMulticast; return rc;
}
else
{
maxSock = _sockfdUnicast;
}
int rc = 0;
if ( select(maxSock + 1, &recvfds, 0, 0, &timeout) > 0 )
{
if (FD_ISSET(_sockfdUnicast, &recvfds))
{
rc = recvfrom(_sockfdUnicast, buf, len, 0, addr);
}
else if (FD_ISSET(_sockfdMulticast, &recvfds))
{
rc = recvfrom(_sockfdMulticast, buf, len, 0, &_multicastAddr);
}
}
return rc;
} }
int UDPPort::recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr) int UDPPort::recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr)
{ {
sockaddr_in sender; sockaddr_in sender;
socklen_t addrlen = sizeof(sender); socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen); memset(&sender, 0, addrlen);
int status = ::recvfrom(sockfd, buf, len, flags, (sockaddr*) &sender, &addrlen); int status = ::recvfrom(sockfd, buf, len, flags, (sockaddr*) &sender, &addrlen);
if (status < 0 && errno != EAGAIN) if (status < 0 && errno != EAGAIN)
{ {
D_NWSTACK("errno == %d in UDPPort::recvfrom\n", errno); D_NWSTACK("errno == %d in UDPPort::recvfrom\n", errno);
return -1; return -1;
} }
addr->setAddress(sender.sin_addr.s_addr, sender.sin_port); addr->setAddress(sender.sin_addr.s_addr, sender.sin_port);
D_NWSTACK("recved from %s:%d length = %d\n", inet_ntoa(sender.sin_addr),ntohs(sender.sin_port), status); D_NWSTACK("recved from %s:%d length = %d\n", inet_ntoa(sender.sin_addr),ntohs(sender.sin_port), status);
return status; return status;
} }

View File

@@ -19,18 +19,13 @@
#include "MQTTSNGWDefines.h" #include "MQTTSNGWDefines.h"
#include <string> #include <string>
#include <poll.h>
using namespace std; using namespace std;
namespace MQTTSNGW namespace MQTTSNGW
{ {
#ifdef DEBUG_NWSTACK
#define D_NWSTACK(...) printf(__VA_ARGS__)
#else
#define D_NWSTACK(...)
#endif
/*=========================================== /*===========================================
Class SensorNetAddreess Class SensorNetAddreess
============================================*/ ============================================*/
@@ -70,13 +65,9 @@ private:
void setNonBlocking(const bool); void setNonBlocking(const bool);
int recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr); int recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr);
int _sockfdUnicast; pollfd _pollFds[2];
int _sockfdMulticast;
SensorNetAddress _multicastAddr;
SensorNetAddress _unicastAddr;
bool _disconReq; bool _disconReq;
unsigned int _ttl; SensorNetAddress _multicastAddr;
}; };
/*=========================================== /*===========================================

View File

@@ -1,6 +1,6 @@
/************************************************************************************** /**************************************************************************************
* Copyright (c) 2017, Benjamin Aigner * Copyright (c) 2017, Benjamin Aigner
* Copyright (c) 2016, Tomoaki Yamaguchi (original UDPv4 implementation) * Copyright (c) 2021, Tomoaki Yamaguchi
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
@@ -20,8 +20,10 @@
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#include <net/if.h> #include <net/if.h>
#include <ifaddrs.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <string.h> #include <string.h>
@@ -40,61 +42,57 @@ using namespace MQTTSNGW;
============================================*/ ============================================*/
SensorNetAddress::SensorNetAddress() SensorNetAddress::SensorNetAddress()
{ {
_portNo = 0; memset((void*) &_IpAddr, 0, sizeof(_IpAddr));
memset((void *)&_IpAddr,0,sizeof(_IpAddr));
} }
SensorNetAddress::~SensorNetAddress() SensorNetAddress::~SensorNetAddress()
{ {
} }
struct sockaddr_in6 *SensorNetAddress::getIpAddress(void) sockaddr_in6* SensorNetAddress::getIpAddress(void)
{ {
return &_IpAddr; return &_IpAddr;
} }
uint16_t SensorNetAddress::getPortNo(void) uint16_t SensorNetAddress::getPortNo(void)
{ {
return _portNo; return _IpAddr.sin6_port;
} }
void SensorNetAddress::setAddress(struct sockaddr_in6 *IpAddr, uint16_t port) void SensorNetAddress::setAddress(struct sockaddr_in6 *IpAddr)
{ {
memcpy((void *)&_IpAddr,IpAddr,sizeof(_IpAddr)); memcpy((void*) &_IpAddr, IpAddr, sizeof(_IpAddr));
_portNo = port;
} }
/** /**
* convert Text data to SensorNetAddress * convert Text data to SensorNetAddress
* @param data is a IPV6_Address:PortNo format string * @param data is a string [IPV6_Address]:PortNo
* @return success = 0, Invalid format = -1 * @return success = 0, Invalid format = -1
*/ */
int SensorNetAddress::setAddress(string* data) int SensorNetAddress::setAddress(string* data)
{ {
size_t pos = data->find_last_of("]:");
size_t pos = data->find_last_of(":"); if (pos != string::npos)
{
int portNo = 0;
string port = data->substr(pos + 1);
if ( pos != string::npos) if ((portNo = atoi(port.c_str())) > 0)
{ {
int portNo = 0; _IpAddr.sin6_port = htons(portNo);
string port = data->substr(pos + 1); _IpAddr.sin6_family = AF_INET6;
string ip = data->substr(1, pos - 2);
const char *cstr = ip.c_str();
if ( ( portNo = atoi(port.c_str()) ) > 0 ) if (inet_pton(AF_INET6, cstr, &(_IpAddr.sin6_addr)) == 1)
{ {
_portNo = htons(portNo); return 0;
}
string ip = data->substr(1,pos - 1); }
const char *cstr = ip.c_str(); }
memset((void*) &_IpAddr, 0, sizeof(_IpAddr));
if (inet_pton(AF_INET6, cstr, &(_IpAddr.sin6_addr)) == 1 ) return -1;
{
return 0;
}
}
}
_portNo = 0;
memset((void *)&_IpAddr,0,sizeof(_IpAddr));
return -1;
} }
/** /**
@@ -104,43 +102,42 @@ int SensorNetAddress::setAddress(string* data)
*/ */
int SensorNetAddress::setAddress(const char* data) int SensorNetAddress::setAddress(const char* data)
{ {
if ( inet_pton(AF_INET6, data, &(_IpAddr.sin6_addr)) == 1 ) if (inet_pton(AF_INET6, data, &(_IpAddr.sin6_addr)) == 1)
{ {
return 0; _IpAddr.sin6_family = AF_INET6;
} return 0;
else }
{ else
return -1; {
} return -1;
}
} }
char* SensorNetAddress::getAddress(void) char* SensorNetAddress::getAddress(void)
{ {
inet_ntop(AF_INET6, &(_IpAddr.sin6_addr), _addrString, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &(_IpAddr.sin6_addr), _addrString, INET6_ADDRSTRLEN);
return _addrString; return _addrString;
} }
bool SensorNetAddress::isMatch(SensorNetAddress* addr) bool SensorNetAddress::isMatch(SensorNetAddress* addr)
{ {
return (this->_portNo == addr->_portNo) && \ return (this->_IpAddr.sin6_port == addr->_IpAddr.sin6_port)
(memcmp(this->_IpAddr.sin6_addr.s6_addr, addr->_IpAddr.sin6_addr.s6_addr, sizeof(this->_IpAddr.sin6_addr.s6_addr)) == 0); && (memcmp(this->_IpAddr.sin6_addr.s6_addr, addr->_IpAddr.sin6_addr.s6_addr,
sizeof(this->_IpAddr.sin6_addr.s6_addr)) == 0);
} }
SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress& addr) SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress& addr)
{ {
this->_portNo = addr._portNo; memcpy(&this->_IpAddr, &addr._IpAddr, sizeof(this->_IpAddr));
memcpy(&this->_IpAddr.sin6_addr, &addr._IpAddr.sin6_addr, sizeof(this->_IpAddr.sin6_addr)); return *this;
return *this;
} }
char* SensorNetAddress::sprint(char* buf) char* SensorNetAddress::sprint(char* buf)
{ {
char ip[INET6_ADDRSTRLEN]; sprintf(buf, "[%s]:", getAddress());
inet_ntop(AF_INET6, &(_IpAddr.sin6_addr), ip, INET6_ADDRSTRLEN); sprintf(buf + strlen(buf), "%d", ntohs(_IpAddr.sin6_port));
sprintf( buf, "%s:", ip); return buf;
sprintf( buf + strlen(buf), "%d", ntohs(_portNo));
return buf;
} }
/*=========================================== /*===========================================
@@ -156,75 +153,74 @@ SensorNetwork::~SensorNetwork()
int SensorNetwork::unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendToAddr) int SensorNetwork::unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendToAddr)
{ {
return UDPPort6::unicast(payload, payloadLength, sendToAddr); return UDPPort6::unicast(payload, payloadLength, sendToAddr);
} }
int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength) int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength)
{ {
return UDPPort6::broadcast(payload, payloadLength); return UDPPort6::broadcast(payload, payloadLength);
} }
int SensorNetwork::read(uint8_t* buf, uint16_t bufLen) int SensorNetwork::read(uint8_t* buf, uint16_t bufLen)
{ {
return UDPPort6::recv(buf, bufLen, &_clientAddr); return UDPPort6::recv(buf, bufLen, &_clientAddr);
} }
void SensorNetwork::initialize(void) void SensorNetwork::initialize(void)
{ {
char param[MQTTSNGW_PARAM_MAX]; char param[MQTTSNGW_PARAM_MAX];
uint16_t unicastPortNo = 0; uint16_t unicastPortNo = 0;
string ip; uint16_t multicastPortNo = 0;
string broadcast; string ip;
string interface; string multicast;
unsigned int hops = 1; string interface;
uint32_t hops = 1;
if (theProcess->getParam("GatewayUDP6Bind", param) == 0) if (theProcess->getParam("MulticastIPv6", param) == 0)
{ {
ip = param; multicast = param;
_description = "GatewayUDP6Bind: "; _description += "Multicast Address: [";
_description += param; _description += param;
} }
if (theProcess->getParam("GatewayUDP6Port", param) == 0) if (theProcess->getParam("MulticastIPv6PortNo", param) == 0)
{ {
unicastPortNo = atoi(param); multicastPortNo = atoi(param);
_description += " Gateway Port: "; _description += "]:";
_description += param; _description += param;
} }
if (theProcess->getParam("GatewayUDP6Broadcast", param) == 0) if (theProcess->getParam("GatewayIPv6PortNo", param) == 0)
{ {
broadcast = param; unicastPortNo = atoi(param);
_description += " Broadcast Address: "; _description += ", Gateway Port:";
_description += param; _description += param;
} }
if (theProcess->getParam("GatewayUDP6If", param) == 0) if (theProcess->getParam("MulticastIPv6If", param) == 0)
{ {
interface = param; interface = param;
_description += " Interface: "; _description += ", Interface: ";
_description += param; _description += param;
} }
if (theProcess->getParam("GatewayUDP6Hops", param) == 0) if (theProcess->getParam("MulticastHops", param) == 0)
{ {
hops = atoi(param); hops = atoi(param);
_description += " Hops: "; _description += ", Hops:";
_description += param; _description += param;
} }
errno = 0; if (UDPPort6::open(unicastPortNo, multicastPortNo, multicast.c_str(), interface.c_str(), hops) < 0)
{
if ( UDPPort6::open(ip.c_str(), unicastPortNo, broadcast.c_str(), interface.c_str(), hops) < 0 ) throw EXCEPTION("Can't open a UDP6", errno);
{ }
throw EXCEPTION("Can't open a UDP6", errno);
}
} }
const char* SensorNetwork::getDescription(void) const char* SensorNetwork::getDescription(void)
{ {
return _description.c_str(); return _description.c_str();
} }
SensorNetAddress* SensorNetwork::getSenderAddress(void) SensorNetAddress* SensorNetwork::getSenderAddress(void)
{ {
return &_clientAddr; return &_clientAddr;
} }
/*========================================= /*=========================================
@@ -233,278 +229,241 @@ SensorNetAddress* SensorNetwork::getSenderAddress(void)
UDPPort6::UDPPort6() UDPPort6::UDPPort6()
{ {
_disconReq = false; _disconReq = false;
_sockfdUnicast = -1; _hops = 0;
_sockfdMulticast = -1;
} }
UDPPort6::~UDPPort6() UDPPort6::~UDPPort6()
{ {
close(); close();
} }
void UDPPort6::close(void) void UDPPort6::close(void)
{ {
if (_sockfdUnicast > 0) for (int i = 0; i < 2; i++)
{ {
::close(_sockfdUnicast); if (_pollfds[i].fd > 0)
_sockfdUnicast = -1; {
} ::close(_pollfds[i].fd);
if (_sockfdMulticast > 0) _pollfds[i].fd = 0;
{ }
::close(_sockfdMulticast); }
_sockfdMulticast = -1;
}
} }
int UDPPort6::open(const char* ipAddress, uint16_t uniPortNo, const char* broadcastAddr, const char* interfaceName, unsigned int hops) int UDPPort6::open(uint16_t uniPortNo, uint16_t multiPortNo, const char *multicastAddr, const char *interfaceName,
uint32_t hops)
{ {
struct addrinfo hints, *res; int optval = 0;
int errnu; int sock = 0;
const int reuse = 1; sockaddr_in6 addr6;
uint32_t ifindex = 0;
if (uniPortNo == 0) errno = 0;
{
WRITELOG("error portNo undefined in UDPPort::open\n");
return -1;
}
if (uniPortNo == 0 || multiPortNo == 0)
{
D_NWSTACK("error portNo undefined in UDPPort6::open\n");
return -1;
}
memset(&hints, 0, sizeof hints); // Create a unicast socket
hints.ai_family = AF_INET6; // use IPv6 sock = socket(AF_INET6, SOCK_DGRAM, 0);
hints.ai_socktype = SOCK_DGRAM; if (sock < 0)
hints.ai_flags = AI_PASSIVE; //use local IF address {
D_NWSTACK("UDP6::open - unicast socket: %s", strerror(errno));
return -1;
}
getaddrinfo(NULL, std::to_string(uniPortNo).c_str(), &hints, &res); _pollfds[0].fd = sock;
_pollfds[0].events = POLLIN;
_sockfdMulticast = socket(res->ai_family, res->ai_socktype, res->ai_protocol); optval = 1;
if(_sockfdMulticast <0) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &optval, sizeof(optval));
{
WRITELOG("UDP6::open - multicast: %s",strerror(_sockfdMulticast));
return errno;
}
//select the interface optval = 1;
unsigned int ifindex; if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &optval, sizeof(optval)) < 0)
ifindex = if_nametoindex(interfaceName); {
errnu = setsockopt(_sockfdMulticast, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex,sizeof(ifindex)); D_NWSTACK("\033[0m\033[0;31m unicast socket error %s IPV6_V6ONLY\033[0m\033[0;37m\n", strerror(errno));
if(errnu <0) close();
{ return -1;
WRITELOG("UDP6::open - limit IF: %s",strerror(errnu)); }
return errnu;
}
strcpy(_interfaceName,interfaceName); if (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof(hops)) < 0)
{
D_NWSTACK("\033[0m\033[0;31m error %s IPV6_UNICAST_HOPS\033[0m\033[0;37m\n", strerror(errno));
close();
return -1;
}
//restrict the socket to IPv6 only if (strlen(interfaceName) > 0)
int on = 1; {
errnu = setsockopt(_sockfdMulticast, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); ifindex = if_nametoindex(interfaceName);
if(errnu <0)
{
WRITELOG("UDP6::open - limit IPv6: %s",strerror(errnu));
return errnu;
}
errnu = setsockopt(_sockfdMulticast, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops,sizeof(hops));
if(errnu <0)
{
WRITELOG("UDP6::open - limit HOPS: %s",strerror(errnu));
return errnu;
}
_uniPortNo = uniPortNo;
_hops = hops;
freeaddrinfo(res);
//init the structs for getaddrinfo
//according to: https://beej.us/guide/bgnet/output/html/multipage/
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET6; // use IPv6, whichever
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
//no specific address, bind to available ones...
getaddrinfo(NULL, std::to_string(uniPortNo).c_str(), &hints, &res);
//create the socket
_sockfdUnicast = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (_sockfdUnicast < 0)
{
WRITELOG("UDP6::open - unicast socket: %s",strerror(_sockfdUnicast));
return -1;
}
//if given, set a given device name to bind to
if(strlen(interfaceName) > 0)
{
#ifdef __APPLE__ #ifdef __APPLE__
int idx = if_nametoindex(interfaceName); setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
setsockopt(_sockfdUnicast, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)); #else
#else setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, interfaceName, strlen(interfaceName));
//socket option: bind to a given interface name
setsockopt(_sockfdUnicast, SOL_SOCKET, SO_BINDTODEVICE, interfaceName, strlen(interfaceName));
#endif #endif
} }
//socket option: reuse address memset(&addr6, 0, sizeof(addr6));
setsockopt(_sockfdUnicast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(uniPortNo);
addr6.sin6_addr = in6addr_any;
//finally: bind... if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
errnu = ::bind(_sockfdUnicast, res->ai_addr, res->ai_addrlen); {
if (errnu < 0) D_NWSTACK("error can't bind unicast socket in UDPPort6::open: %s\n", strerror(errno));
{ close();
WRITELOG("error can't bind unicast socket in UDPPort::open: %s\n",strerror(errnu)); return -1;
return -1; }
}
//if given, set a broadcast address; otherwise it will be ::
if(strlen(broadcastAddr) > 0) // create a MULTICAST socket
{
_grpAddr.setAddress(broadcastAddr); sock = socket(AF_INET6, SOCK_DGRAM, 0);
} else { if (sock < 0)
_grpAddr.setAddress("::"); {
} D_NWSTACK("UDP6::open - multicast: %s", strerror(errno));
//everything went fine... close();
freeaddrinfo(res); return -1;
return 0; }
_pollfds[1].fd = sock;
_pollfds[1].events = POLLIN;
optval = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*) &optval, sizeof(optval)) < 0)
{
D_NWSTACK("\033[0m\033[0;31m multicast socket error %s SO_REUSEADDR\033[0m\033[0;37m\n", strerror(errno));
close();
return -1;
}
optval = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &optval, sizeof(optval)) < 0)
{
D_NWSTACK("\033[0m\033[0;31m multicast socket error %s IPV6_V6ONLY\033[0m\033[0;37m\n", strerror(errno));
close();
return -1;
}
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(multiPortNo);
addr6.sin6_addr = in6addr_any;
if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
{
close();
D_NWSTACK("error can't bind multicast socket in UDPPort6::open: %s\n", strerror(errno));
return -1;
}
ipv6_mreq addrm;
addrm.ipv6mr_interface = ifindex;
inet_pton(AF_INET6, multicastAddr, &addrm.ipv6mr_multiaddr);
if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0)
{
D_NWSTACK("\033[0m\033[0;31m error %d IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", errno);
close();
return false;
}
#ifdef DEBUG_NW
optval = 1;
#else
optval = 0;
#endif
if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char*) &optval, sizeof(optval)) < 0)
{
D_NWSTACK("\033[0m\033[0;31m error %s IPV6_MULTICAST_LOOP\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0)
{
D_NWSTACK("\033[0m\033[0;31m error %s IPV6_MULTICAST_HOPS\033[0m\033[0;37m\n", strerror(errno));
close();
return -1;
}
memcpy(&addr6.sin6_addr, &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr));
_grpAddr.setAddress(&addr6);
return 0;
} }
int UDPPort6::unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* addr) int UDPPort6::unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* addr)
{ {
char destStr[INET6_ADDRSTRLEN+10]; sockaddr_in6 dest;
struct addrinfo hints, *res; memset(&dest, 0, sizeof(dest));
memset(&hints, 0, sizeof hints); dest.sin6_family = AF_INET6;
hints.ai_family = AF_INET6; // use IPv6 dest.sin6_port = addr->getPortNo();
hints.ai_socktype = SOCK_DGRAM; memcpy(dest.sin6_addr.s6_addr, (const void*) &addr->getIpAddress()->sin6_addr, sizeof(in6_addr));
int err = 0; #ifdef DEBUG_NW
int port = 0; char addrBuf[INET6_ADDRSTRLEN];
string portStr; addr->sprint(addrBuf);
if(addr->getPortNo() != 0) D_NWSTACK("sendto %s\n", addrBuf);
{ #endif
port = htons(addr->getPortNo());
portStr = to_string(port);
} else {
port = _uniPortNo;
portStr = to_string(port);
}
errno = 0; int status = ::sendto(_pollfds[0].fd, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
if(strlen(_interfaceName) != 0) if (status < 0)
{ {
strcpy(destStr, addr->getAddress()); D_NWSTACK("%s in UDPPor6t::sendto\n", strerror(errno));
strcat(destStr,"%"); }
strcat(destStr,_interfaceName); return status;
if(IN6_IS_ADDR_LINKLOCAL(&addr->getIpAddress()->sin6_addr))
{
err = getaddrinfo(destStr, portStr.c_str(), &hints, &res);
}
else
{
err = getaddrinfo(addr->getAddress(), portStr.c_str(), &hints, &res);
}
} else {
strcpy(destStr, addr->getAddress());
err = getaddrinfo(addr->getAddress(), portStr.c_str(), &hints, &res);
}
if ( err != 0)
{
WRITELOG("UDP6::broadcast - getaddrinfo: %s",strerror(errno));
return err;
}
int status = ::sendto(_sockfdUnicast, buf, length, 0, res->ai_addr, res->ai_addrlen);
if (status < 0)
{
WRITELOG("errno in UDPPort::unicast(sendto): %d, %s\n",status,strerror(errno));
}
return status;
} }
int UDPPort6::broadcast(const uint8_t* buf, uint32_t length) int UDPPort6::broadcast(const uint8_t* buf, uint32_t length)
{ {
struct addrinfo hint,*info; int err = unicast(buf, length, &_grpAddr);
int err;
memset( &hint, 0, sizeof( hint ) );
hint.ai_family = AF_INET6; if (err < 0)
hint.ai_socktype = SOCK_DGRAM; {
hint.ai_protocol = 0; D_NWSTACK("UDP6::broadcast - sendto: %s", strerror(errno));
return err;
}
errno = 0; return 0;
if(strlen(_interfaceName) != 0)
{
char destStr[80];
strcpy(destStr, _grpAddr.getAddress());
strcat(destStr,"%");
strcat(destStr,_interfaceName);
if(IN6_IS_ADDR_MC_NODELOCAL(&_grpAddr.getIpAddress()->sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&_grpAddr.getIpAddress()->sin6_addr))
{
err = getaddrinfo(destStr, std::to_string(_uniPortNo).c_str(), &hint, &info );
}
else
{
err = getaddrinfo(_grpAddr.getAddress(), std::to_string(_uniPortNo).c_str(), &hint, &info );
}
} else {
err = getaddrinfo(_grpAddr.getAddress(), std::to_string(_uniPortNo).c_str(), &hint, &info );
}
if( err != 0 ) {
WRITELOG("UDP6::broadcast - getaddrinfo: %s",strerror(errno));
return err;
}
err = sendto(_sockfdMulticast, buf, length, 0, info->ai_addr, info->ai_addrlen );
if(err < 0 ) {
WRITELOG("UDP6::broadcast - sendto: %s",strerror(errno));
return err;
}
return 0;
} }
int UDPPort6::recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr) int UDPPort6::recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr)
{ {
struct timeval timeout; int rc = poll(_pollfds, 2, 2000); // Timeout 2secs
fd_set recvfds; if (rc == 0)
{
return rc;
}
timeout.tv_sec = 1; for (int i = 0; i < 2; i++)
timeout.tv_usec = 0; // 1 sec {
FD_ZERO(&recvfds); if (_pollfds[i].revents & POLLIN)
FD_SET(_sockfdUnicast, &recvfds); {
return recvfrom(_pollfds[i].fd, buf, len, 0, addr);
int rc = 0; }
if ( select(_sockfdUnicast + 1, &recvfds, 0, 0, &timeout) > 0 ) }
{ return 0;
if (FD_ISSET(_sockfdUnicast, &recvfds))
{
rc = recvfrom(_sockfdUnicast, buf, len, 0, addr);
}
}
return rc;
} }
int UDPPort6::recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr) int UDPPort6::recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr)
{ {
sockaddr_in6 sender; sockaddr_in6 sender;
socklen_t addrlen = sizeof(sender); socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen); memset(&sender, 0, addrlen);
int status = ::recvfrom(sockfd, buf, len, flags, (sockaddr*) &sender, &addrlen); int status = ::recvfrom(sockfd, buf, len, flags, (sockaddr*) &sender, &addrlen);
if (status < 0 && errno != EAGAIN) if (status < 0 && errno != EAGAIN)
{ {
WRITELOG("errno == %d in UDPPort::recvfrom: %s\n",errno,strerror(errno)); D_NWSTACK("errno in UDPPort6::recvfrom: %s\n", strerror(errno));
return -1; return -1;
} }
addr->setAddress(&sender, (uint16_t)sender.sin6_port); addr->setAddress(&sender);
//D_NWSTACK("recved from %s:%d length = %d\n", inet_ntoa(sender.sin_addr),ntohs(sender.sin_port), status);
return status; #ifdef DEBUG_NW
char addrBuf[INET6_ADDRSTRLEN];
addr->sprint(addrBuf);
D_NWSTACK("sendto %s length = %d\n", addrBuf, status);
#endif
return status;
} }

View File

@@ -12,7 +12,7 @@
* http://www.eclipse.org/org/documents/edl-v10.php. * http://www.eclipse.org/org/documents/edl-v10.php.
* *
* Contributors: * Contributors:
* Benjamin Aigner - port to UDPv6, used by RFC7668 (6lowpan over Bluetooth LE) * Benjamin Aigner - port to UDPv6, used by RFC7668 (6lowpan over Bluetooth LE)
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
@@ -22,69 +22,59 @@
#include "MQTTSNGWDefines.h" #include "MQTTSNGWDefines.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <string> #include <string>
#include <poll.h>
using namespace std; using namespace std;
namespace MQTTSNGW namespace MQTTSNGW
{ {
#ifdef DEBUG_NWSTACK
#define D_NWSTACK(...) printf(__VA_ARGS__)
#else
#define D_NWSTACK(...)
#endif
/*=========================================== /*===========================================
Class SensorNetAddreess Class SensorNetAddreess
============================================*/ ============================================*/
class SensorNetAddress class SensorNetAddress
{ {
public: public:
SensorNetAddress(); SensorNetAddress();
~SensorNetAddress(); ~SensorNetAddress();
void setAddress(struct sockaddr_in6 *IpAddr, uint16_t port); void setAddress(sockaddr_in6 *IpAddr);
int setAddress(string* data); int setAddress(string* data);
int setAddress(const char* data); int setAddress(const char* data);
uint16_t getPortNo(void); uint16_t getPortNo(void);
struct sockaddr_in6 *getIpAddress(void); sockaddr_in6* getIpAddress(void);
char* getAddress(void); char* getAddress(void);
bool isMatch(SensorNetAddress* addr); bool isMatch(SensorNetAddress* addr);
SensorNetAddress& operator =(SensorNetAddress& addr); SensorNetAddress& operator =(SensorNetAddress& addr);
char* sprint(char* buf); char* sprint(char* buf);
private: private:
uint16_t _portNo; char _addrString[INET6_ADDRSTRLEN + 1];
char _addrString[INET6_ADDRSTRLEN+1]; sockaddr_in6 _IpAddr;
struct sockaddr_in6 _IpAddr;
}; };
/*======================================== /*========================================
Class UpdPort Class UpdPort6
=======================================*/ =======================================*/
class UDPPort6 class UDPPort6
{ {
public: public:
UDPPort6(); UDPPort6();
virtual ~UDPPort6(); virtual ~UDPPort6();
int open(const char* ipAddress, uint16_t uniPortNo, const char* broadcastAddr, const char* interfaceName, unsigned int hops); int open(uint16_t uniPortNo, uint16_t multiPortNo, const char *broadcastAddr, const char *interfaceName, uint32_t hops);
void close(void); void close(void);
int unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* sendToAddr); int unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* sendToAddr);
int broadcast(const uint8_t* buf, uint32_t length); int broadcast(const uint8_t* buf, uint32_t length);
int recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr); int recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr);
private: private:
void setNonBlocking(const bool); void setNonBlocking(const bool);
int recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr); int recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr);
int _sockfdUnicast; pollfd _pollfds[2];
int _sockfdMulticast; SensorNetAddress _grpAddr;
char _interfaceName[10]; SensorNetAddress _clientAddr;
bool _disconReq;
SensorNetAddress _grpAddr; uint32_t _hops;
SensorNetAddress _clientAddr;
uint16_t _uniPortNo;
bool _disconReq;
unsigned int _hops;
}; };
/*=========================================== /*===========================================
@@ -93,19 +83,19 @@ private:
class SensorNetwork: public UDPPort6 class SensorNetwork: public UDPPort6
{ {
public: public:
SensorNetwork(); SensorNetwork();
~SensorNetwork(); ~SensorNetwork();
int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto); int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto);
int broadcast(const uint8_t* payload, uint16_t payloadLength); int broadcast(const uint8_t* payload, uint16_t payloadLength);
int read(uint8_t* buf, uint16_t bufLen); int read(uint8_t* buf, uint16_t bufLen);
void initialize(void); void initialize(void);
const char* getDescription(void); const char* getDescription(void);
SensorNetAddress* getSenderAddress(void); SensorNetAddress* getSenderAddress(void);
private: private:
SensorNetAddress _clientAddr; // Sender's address. not gateway's one. SensorNetAddress _clientAddr; // Sender's address. not gateway's one.
string _description; string _description;
}; };
} }

View File

@@ -25,13 +25,6 @@ using namespace std;
namespace MQTTSNGW namespace MQTTSNGW
{ {
//#define DEBUG_NWSTACK
#ifdef DEBUG_NWSTACK
#define D_NWSTACK(...) printf(__VA_ARGS__)
#else
#define D_NWSTACK(...)
#endif
#define API_XMITREQUEST 0x10 #define API_XMITREQUEST 0x10
#define API_RESPONSE 0x90 #define API_RESPONSE 0x90

View File

@@ -21,7 +21,6 @@
#include "MQTTSNGWPacketHandleTask.h" #include "MQTTSNGWPacketHandleTask.h"
using namespace MQTTSNGW; using namespace MQTTSNGW;
/* /*
* Gateway Application * Gateway Application
*/ */

View File

@@ -15,10 +15,15 @@ cmake .. -DSENSORNET=xbee
make MQTT-SNGateway make MQTT-SNGateway
cmake .. -DSENSORNET=udp6 cmake .. -DSENSORNET=udp6
make MQTT-SNGateway make MQTT-SNGateway
cmake .. -DSENSORNET=dtls
make MQTT-SNGateway
cmake .. -DSENSORNET=udp cmake .. -DSENSORNET=udp
make MQTT-SNGateway make MQTT-SNGateway
cd ../MQTTSNGateway/GatewayTester cd ../MQTTSNGateway/GatewayTester
make make SENSORNET=UDP6
make SENSORNET=DTLS
make SENSORNET=DTLS6
make SENSORNET=RFCOMM
make SENSORNET=UDP