diff --git a/.cproject b/.cproject index bf962d5..c21710c 100644 --- a/.cproject +++ b/.cproject @@ -1,352 +1,192 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore index ee251ce..9e7e964 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,15 @@ *.pyc /doc/MQTTSNClient/ /doc/MQTTSNPacket/ -/rbmutex.key -/ringbuffer.key +rbmutex.key +ringbuffer.key /Release/ /Debug/ /core +Build/ +*.a +CMakeFiles/ +*.cmake +CMakeCache.txt +bin/ +/build.gateway/ \ No newline at end of file diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index e5b4485..3cabd84 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -1,48 +1,25 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.settings/org.eclipse.cdt.codan.core.prefs b/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 0000000..a159526 --- /dev/null +++ b/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,77 @@ +eclipse.preferences.version=1 +fr.ac6.mcu.ide.source.checker.libnano.problem=Error +fr.ac6.mcu.ide.source.checker.libnano.problem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Float formatting support\\")"} +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} +org.eclipse.cdt.codan.checkers.nocommentinside=-Error +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} +org.eclipse.cdt.codan.checkers.nolinecomment=-Error +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} +org.eclipse.cdt.qt.core.qtproblem=Warning +org.eclipse.cdt.qt.core.qtproblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_ON_FILE_OPEN\=>true,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>null} diff --git a/.settings/org.eclipse.cdt.ui.prefs b/.settings/org.eclipse.cdt.ui.prefs new file mode 100644 index 0000000..4ee12a4 --- /dev/null +++ b/.settings/org.eclipse.cdt.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +formatter_settings_version=1 diff --git a/.travis.yml b/.travis.yml index ed564b5..aec373c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,19 +13,11 @@ addons: - g++-4.8 - cmake - cmake-data + - bluez + - libbluetooth-dev script: - ./travis-build.sh - - - cd MQTTSNGateway - - make SENSORNET="xbee" - - make SENSORNET="udp" - - make SENSORNET="udp6" - - - make test - - - cd GatewayTester - - make notifications: emails: diff --git a/CMakeLists.txt b/CMakeLists.txt index bdb6b98..66cfb53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ # Ian Craggs - initial version #*******************************************************************************/ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 3.1) PROJECT("paho-mqttsn" CXX) MESSAGE(STATUS "CMake version: " ${CMAKE_VERSION}) MESSAGE(STATUS "CMake system name: " ${CMAKE_SYSTEM_NAME}) @@ -39,3 +39,4 @@ INCLUDE(CPack) ENABLE_TESTING() ADD_SUBDIRECTORY(MQTTSNPacket) +ADD_SUBDIRECTORY(MQTTSNGateway) \ No newline at end of file diff --git a/MQTTSNGateway/CMakeLists.txt b/MQTTSNGateway/CMakeLists.txt new file mode 100644 index 0000000..51a8eec --- /dev/null +++ b/MQTTSNGateway/CMakeLists.txt @@ -0,0 +1,16 @@ +#******************************************************************************* +# Copyright (c) 2022 a1lu +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# and Eclipse Distribution License v1.0 which accompany this distribution. +# +# The Eclipse Public License is available at +# http://www.eclipse.org/legal/epl-v10.html +# and the Eclipse Distribution License is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# Contributors: +# a1lu - initial version +#*******************************************************************************/ +ADD_SUBDIRECTORY(src) \ No newline at end of file diff --git a/MQTTSNGateway/Gateway Overview.pdf b/MQTTSNGateway/Gateway Overview.pdf new file mode 100644 index 0000000..d00eca8 Binary files /dev/null and b/MQTTSNGateway/Gateway Overview.pdf differ diff --git a/MQTTSNGateway/GatewayTester/Makefile b/MQTTSNGateway/GatewayTester/Makefile index 0ed4a27..a4ec071 100644 --- a/MQTTSNGateway/GatewayTester/Makefile +++ b/MQTTSNGateway/GatewayTester/Makefile @@ -20,6 +20,10 @@ CPPSRCS := \ $(SUBDIR)/LGwProxy.cpp \ $(SUBDIR)/LMqttsnClient.cpp \ $(SUBDIR)/LNetworkUdp.cpp \ +$(SUBDIR)/LNetworkUdp6.cpp \ +$(SUBDIR)/LNetworkRfcomm.cpp \ +$(SUBDIR)/LNetworkDtls.cpp \ +$(SUBDIR)/LNetworkDtls6.cpp \ $(SUBDIR)/LPublishManager.cpp \ $(SUBDIR)/LRegisterManager.cpp \ $(SUBDIR)/LSubscribeManager.cpp \ @@ -36,12 +40,14 @@ $(SUBDIR)/Util.cpp \ CXX := g++ CPPFLAGS += -INCLUDES += -I$(SUBDIR) -DEFS := -LIBS += +INCLUDES += -I$(SUBDIR) -I/usr/local/opt/openssl/include +DEF1 := +DEF2 := +DEFS := -D$(SN) $(DEF1) $(DEF2) +LIBS += -L/usr/local/lib -L/usr/local/opt/openssl/lib LDFLAGS := CXXFLAGS := -Wall -O3 -std=c++11 -LDADD := +LDADD := -lssl -lcrypto $(LDADDBLT) OUTDIR := Build PROG := $(OUTDIR)/$(PROGTEST) @@ -75,23 +81,23 @@ $(PROGQOS): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCQOS)/$(QOSAPPL).o $(OUTDIR)/$(SUBDIR)/%.o:$(SUBDIR)/%.cpp @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< + $(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< $(OUTDIR)/$(SRCDIR)/%.o:$(SRCDIR)/%.cpp @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< + $(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< $(OUTDIR)/$(SRCDIR)/$(SRCPUB)/%.o:$(SRCDIR)/$(SRCPUB)%.cpp @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< + $(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/%.o:$(SRCDIR)/$(SRCSUB)%.cpp @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< + $(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< $(OUTDIR)/$(SRCDIR)/$(SRCQOS)/%.o:$(SRCDIR)/$(SRCQOS)%.cpp @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< + $(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< clean: rm -rf $(OUTDIR) diff --git a/MQTTSNGateway/GatewayTester/README.md b/MQTTSNGateway/GatewayTester/README.md index 2efa9bb..514d37d 100644 --- a/MQTTSNGateway/GatewayTester/README.md +++ b/MQTTSNGateway/GatewayTester/README.md @@ -1,119 +1,117 @@ -###Gateway Test Program. +# Gateway Test Program. **sample/mainTest.cpp** is a Test sample coading. Each test is described as one function. test1(), test2()... -```` -/*------------------------------------------------------ - * Test functions - * - * you can use 4 commands in Test functions - * - * 1) PUBLISH(const char* topicName, - * uint8_t* payload, - * uint16_t len, - * uint8_t qos, - * bool retain = false); - * - * 2) SUBSCRIBE(const char* topicName, - * TopicCallback onPublish, - * uint8_t qos); - * - * 3) UNSUBSCRIBE(const char* topicName); - * - * 4) DISCONNECT(uint16_t sleepInSecs); - * - *------------------------------------------------------*/ - +``` void test1(void) { - char payload[300]; - sprintf(payload, "ESP8266-08b133 "); - uint8_t qos = 0; - PUBLISH(topic1,(uint8_t*)payload, strlen(payload), qos); + char payload[300]; + sprintf(payload, "ESP8266-08b133 "); + uint8_t qos = 0; + PUBLISH(topic1,(uint8_t*)payload, strlen(payload), qos); } void test2(void) { - uint8_t qos = 1; - SUBSCRIBE(topic2, on_publish02, qos); + uint8_t qos = 1; + SUBSCRIBE(topic2, on_publish02, qos); } -```` -**TEST_LIST** is a test senario. Test functions are executed one by one. -```` + + *--------------------------------------------------------------------------- + * + * MQTT-SN GATEWAY TEST CLIENT + * + * Supported functions. + * + * void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false ); + * + * void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false ); + * + * void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos ); + * + * void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos ); + * + * void UNSUBSCRIBE ( const char* topicName ); + * + * void UNSUBSCRIBE ( uint16_t topicId ); + * + * void DISCONNECT ( uint16_t sleepInSecs ); + * + * void CONNECT ( void ); + * + * void DISPLAY( format, .....); <== instead of printf() + *-------------------------------------------------------------------------- + +``` +**TEST_LIST** is a test senario. Test functions are executed interactively. +``` /*------------------------------------------------------ * A List of Test Tasks *------------------------------------------------------*/ TEST_LIST = {// e.g. TEST( Label, Test), - TEST("Publish topic1", test1), - TEST("Subscribe topic2", test2), - TEST("Publish topic2", test3), - TEST("Unsubscribe topic2", test4), - TEST("Publish topic2", test3), - TEST("Disconnect", test5), - END_OF_TEST_LIST - }; -```` + TEST("Publish topic1", test1), + TEST("Subscribe topic2", test2), + TEST("Publish topic2", test3), + TEST("Unsubscribe topic2", test4), + TEST("Publish topic2", test3), + TEST("Disconnect", test5), + END_OF_TEST_LIST + }; + +``` -### **step1. Build ** -```` -$ git clone https://github.com/eclipse/paho.mqtt-sn.embedded-c +**UDP**, **DTLS**, **UDP6**, **DTLS6** or **Bluetooth** is available as a sensor network. +``` +/*------------------------------------------------------ + * UDP, DTLS Configuration (theNetcon) + *------------------------------------------------------*/ +UDPCONF = { "GatewayTestClient", // ClientId + { 225, 1, 1, 1 }, // Multicast group IP + 1883, // Multicast group Port + 20020, // Local PortNo + }; + +/*------------------------------------------------------ + * UDP6, DTLS6 Configuration (theNetcon) + *------------------------------------------------------*/ +UDP6CONF = { "GatewayTestClient", // ClientId + "ff12::feed:caca:dead", // Multicast group IP + "wlp4s0", + 1883, // Multicast group Port + 20020, // Local PortNo + }; + +/*------------------------------------------------------ + * RFCOMM Configuration (theNetcon) + *------------------------------------------------------*/ +RFCOMMCONF = { "GatewayTestClient", // ClientId + "60:57:18:06:8B:72", // GW Address + 1, // Rfcomm channel + }; +``` + + +## How to Build +``` +copy codes from the github. $ cd paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester -$ make -$ make install -$ make clean +$ ./build.sh [udp | udp6 | dtls | dtls6 | rfcomm] ``` -MQTT-SNGatewayTester program is copied into ../../../ directory. -### **step2. Execute Gateway Tester.** - -```` -$ cd ../../.. -$ ./MQTT-SNGatewayTester +## Execute Gateway Tester +``` +$ ./Build/MQTT-SNGatewayTester *************************************************************************** - * MQTT-SN Gateway Tester + * MQTT-SN Gateway Tester DTLS * Part of Project Paho in Eclipse * (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/) * * Author : Tomoaki YAMAGUCHI - * Version: 0.0.0 + * Version: 2.0.0 *************************************************************************** - Attempting to Connect the Broker..... +Execute "Step0:Connect" ? ( y/n ) : -sendto 225.1.1.1 :1883 03 01 00 - -recved 192.168.11.5 :1883 03 01 00 -sendto 225.1.1.1 :1883 03 01 00 - -recved 192.168.11.5 :1883 03 01 00 - -recved 192.168.11.17 :10000 03 02 01 -sendto 192.168.11.17 :10000 13 04 0c 01 03 84 47 61 74 65 77 61 79 54 65 73 74 65 72 - -recved 192.168.11.17 :10000 02 06 -sendto 192.168.11.17 :10000 0c 07 00 77 69 6c 6c 54 6f 70 69 63 - -recved 192.168.11.17 :10000 02 08 -sendto 192.168.11.17 :10000 0d 09 77 69 6c 6c 4d 65 73 73 61 67 65 - -recved 192.168.11.17 :10000 03 05 00 - - - Connected to the Broker - - Attempting OnConnect..... -sendto 192.168.11.17 :10000 13 12 20 00 01 74 79 34 74 77 2f 63 6c 69 65 6e 74 49 64 - -recved 192.168.11.17 :10000 08 13 20 00 01 00 01 00 - - - SUBSCRIBE complete. ty4tw/clientId - - OnConnect complete - Test Ready. - -Execute Publish topic1 Test ? ( Y/N ) : - -```` +``` diff --git a/MQTTSNGateway/GatewayTester/build.sh b/MQTTSNGateway/GatewayTester/build.sh new file mode 100755 index 0000000..538ba14 --- /dev/null +++ b/MQTTSNGateway/GatewayTester/build.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +DEF1="DEF1=${2}" +DEF2="DEF2=${3}" + +if [ $1 == "udp" ] ; then + make SN=UDP $DEF1 $DEF2 +elif [ $1 == "udp6" ] ; then + make SN=UDP6 $DEF1 $DEF2 +elif [ $1 == "rfcomm" ] ; then + export LDADDBLT=-lbluetooth + make SN=RFCOMM $DEF1 $DEF2 +elif [ $1 == "dtls" ] ; then + make SN=DTLS $DEF1 $DEF2 +elif [ $1 == "dtls6" ] ; then + make SN=DTLS6 $DEF1 $DEF2 +elif [ $1 == "clean" ] ; then + make clean +else + echo "Usage: build.sh [ udp | udp6 | rfcomm | dtls | dtls6 | clean]" +fi + + diff --git a/MQTTSNGateway/GatewayTester/samples/ClientPub/mainPub.cpp b/MQTTSNGateway/GatewayTester/samples/ClientPub/mainPub.cpp index c9a571c..80fe65a 100644 --- a/MQTTSNGateway/GatewayTester/samples/ClientPub/mainPub.cpp +++ b/MQTTSNGateway/GatewayTester/samples/ClientPub/mainPub.cpp @@ -51,12 +51,29 @@ extern LScreen* theScreen; /*------------------------------------------------------ * UDP Configuration (theNetcon) *------------------------------------------------------*/ -UDPCONF = { - "ClientPUB", // ClientId - {225,1,1,1}, // Multicast group IP - 1883, // Multicast group Port - 20010, // Local PortNo -}; +UDPCONF = { "ClientPUB", // ClientId + { 225, 1, 1, 1 }, // Multicast group IP + 1883, // Multicast group Port + 20010, // Local PortNo + }; + +/*------------------------------------------------------ + * UDP6 Configuration (theNetcon) + *------------------------------------------------------*/ +UDP6CONF = { "ClientPUB", // ClientId + "ff1e:feed:caca:dead::1", // Multicast group IP + "wlp4s0", // Network Interface + 1883, // Multicast group Port + 20020, // Local PortNo + }; + +/*------------------------------------------------------ + * RFCOMM Configuration (theNetcon) + *------------------------------------------------------*/ +RFCOMMCONF = { "ClientPUB", // ClientId + "60:57:18:06:8B:72", // GW Address + 1, // Rfcomm channel + }; /*------------------------------------------------------ * Client Configuration (theMqcon) @@ -117,7 +134,7 @@ void publishTopic57(void) char payload[300]; sprintf(payload, "publish \"ty4tw/topic57\" \n"); uint8_t qos = 0; - PUBLISH(topic2,(uint8_t*)payload, strlen(payload), qos); + PUBLISH(topic57, (uint8_t* )payload, strlen(payload), qos); } diff --git a/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp b/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp index 34151ed..ce44ba5 100644 --- a/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp +++ b/MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1/mainPubQoS-1.cpp @@ -51,12 +51,29 @@ extern LScreen* theScreen; /*------------------------------------------------------ * UDP Configuration (theNetcon) *------------------------------------------------------*/ -UDPCONF = { - "QoS-1_Client01", // ClientId - {225,1,1,1}, // Multicast group IP - 1883, // Multicast group Port - 20001, // Local PortNo -}; +UDPCONF = { "QoS-1_Client01", // ClientId + { 225, 1, 1, 1 }, // Multicast group IP + 1883, // Multicast group Port + 20001, // Local PortNo + }; + +/*------------------------------------------------------ + * UDP6 Configuration (theNetcon) + *------------------------------------------------------*/ +UDP6CONF = { "QoS-1_Client01", // ClientId + "ff1e:feed:caca:dead::1", // Multicast group IP + "wlp4s0", // Network Interface + 1883, // Multicast group Port + 20020, // Local PortNo + }; + +/*------------------------------------------------------ + * RFCOMM Configuration (theNetcon) + *------------------------------------------------------*/ +RFCOMMCONF = { "QoS-1_Client01", // ClientId + "60:57:18:06:8B:72", // GW Address + 1, // Rfcomm channel + }; /*------------------------------------------------------ * Client Configuration (theMqcon) diff --git a/MQTTSNGateway/GatewayTester/samples/ClientSub/mainSub.cpp b/MQTTSNGateway/GatewayTester/samples/ClientSub/mainSub.cpp index 9bf8c1b..63cd404 100644 --- a/MQTTSNGateway/GatewayTester/samples/ClientSub/mainSub.cpp +++ b/MQTTSNGateway/GatewayTester/samples/ClientSub/mainSub.cpp @@ -51,12 +51,29 @@ extern LScreen* theScreen; /*------------------------------------------------------ * UDP Configuration (theNetcon) *------------------------------------------------------*/ -UDPCONF = { - "ClientSUB", // ClientId - {225,1,1,1}, // Multicast group IP - 1883, // Multicast group Port - 20011, // Local PortNo -}; +UDPCONF = { "ClientSUB", // ClientId + { 225, 1, 1, 1 }, // Multicast group IP + 1883, // Multicast group Port + 20011, // Local PortNo + }; + +/*------------------------------------------------------ + * UDP6 Configuration (theNetcon) + *------------------------------------------------------*/ +UDP6CONF = { "ClientSUB", // ClientId + "ff1e:feed:caca:dead::1", // Multicast group IP + "wlp4s0", // Network Interface + 1883, // Multicast group Port + 20020, // Local PortNo + }; + +/*------------------------------------------------------ + * RFCOMM Configuration (theNetcon) + *------------------------------------------------------*/ +RFCOMMCONF = { "ClientSUB", // ClientId + "60:57:18:06:8B:72", // GW Address + 1, // Rfcomm channel + }; /*------------------------------------------------------ * Client Configuration (theMqcon) diff --git a/MQTTSNGateway/GatewayTester/samples/mainTest.cpp b/MQTTSNGateway/GatewayTester/samples/mainTest.cpp index 934a419..0c39184 100644 --- a/MQTTSNGateway/GatewayTester/samples/mainTest.cpp +++ b/MQTTSNGateway/GatewayTester/samples/mainTest.cpp @@ -20,13 +20,13 @@ * * 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 ); * @@ -49,27 +49,43 @@ extern LMqttsnClient* theClient; extern LScreen* theScreen; /*------------------------------------------------------ - * UDP Configuration (theNetcon) + * UDP,DTLS Configuration (theNetcon) *------------------------------------------------------*/ -UDPCONF = { - "GatewayTestClient", // ClientId - {225,1,1,1}, // Multicast group IP - 1883, // Multicast group Port - 20020, // Local PortNo -}; +UDPCONF = { "GatewayTestClient", // ClientId + { 225, 1, 1, 1 }, // Multicast group IP + 1883, // Multicast group Port + 20020, // Local PortNo + }; + +/*------------------------------------------------------ + * UDP6, DTLS6 Configuration (theNetcon) + *------------------------------------------------------*/ +UDP6CONF = { "GatewayTestClient", // ClientId + "ff1e:feed:caca:dead::1", // Multicast group IP + "wlp4s0", // Network Interface + 1883, // Multicast group Port + 20020, // Local PortNo + }; + +/*------------------------------------------------------ + * RFCOMM Configuration (theNetcon) + *------------------------------------------------------*/ +RFCOMMCONF = { "GatewayTestClient", // ClientId + "60:57:18:06:8B:72", // GW Address + 1, // Rfcomm channel + }; /*------------------------------------------------------ * Client Configuration (theMqcon) *------------------------------------------------------*/ -MQTTSNCONF = { - 60, //KeepAlive [seconds] - true, //Clean session - 300, //Sleep duration [seconds] - "", //WillTopic - "", //WillMessage - 0, //WillQos - false //WillRetain -}; +MQTTSNCONF = { 60, //KeepAlive [seconds] + true, //Clean session + 300, //Sleep duration [seconds] + "", //WillTopic + "", //WillMessage + 0, //WillQos + false //WillRetain + }; /*------------------------------------------------------ * Define Topics @@ -78,37 +94,45 @@ const char* topic1 = "ty4tw/topic1"; const char* topic2 = "ty4tw/topic2"; const char* topic3 = "ty4tw/topic3"; const char* topic4 = "ty4tw/topic4"; +const char* topic40 = "ty4tw/#"; const char* topic51 = "ty4tw/topic5/1"; const char* topic52 = "ty4tw/topic5/2"; const char* topic53 = "ty4tw/topic5/3"; const char* topic50 = "ty4tw/topic5/+"; - /*------------------------------------------------------ * Callback routines for Subscribed Topics *------------------------------------------------------*/ int on_Topic01(uint8_t* pload, uint16_t ploadlen) { DISPLAY("\n\nTopic1 recv.\n"); - char c = pload[ploadlen-1]; - pload[ploadlen-1]= 0; // set null terminator - DISPLAY("Payload -->%s%c<--\n\n",pload, c); + char c = pload[ploadlen - 1]; + pload[ploadlen - 1] = 0; // set null terminator + DISPLAY("Payload -->%s%c<--\n\n", pload, c); return 0; } int on_Topic02(uint8_t* pload, uint16_t ploadlen) { DISPLAY("\n\nTopic2 recv.\n"); - pload[ploadlen-1]= 0; // set null terminator - DISPLAY("Payload -->%s <--\n\n",pload); + pload[ploadlen - 1] = 0; // set null terminator + DISPLAY("Payload -->%s <--\n\n", pload); return 0; } int on_Topic03(uint8_t* pload, uint16_t ploadlen) { DISPLAY("\n\nNew callback recv Topic3\n"); - pload[ploadlen-1]= 0; // set null terminator - DISPLAY("Payload -->%s <--\n\n",pload); + pload[ploadlen - 1] = 0; // set null terminator + DISPLAY("Payload -->%s <--\n\n", pload); + return 0; +} + +int on_TopicWildcard(uint8_t* pload, uint16_t ploadlen) +{ + DISPLAY("\n\nNew callback recv TopicWildcard\n"); + pload[ploadlen - 1] = 0; // set null terminator + DISPLAY("Payload -->%s <--\n\n", pload); return 0; } @@ -116,40 +140,51 @@ int on_Topic03(uint8_t* pload, uint16_t ploadlen) * A Link list of Callback routines and Topics *------------------------------------------------------*/ -SUBSCRIBE_LIST = {// e.g. SUB(TopicType, topicName, TopicId, callback, QoSx), - SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic1, 0, on_Topic01, QoS1), - SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic2, 0, on_Topic02, QoS1), - END_OF_SUBSCRIBE_LIST - }; - +SUBSCRIBE_LIST = +{ // e.g. SUB(TopicType, topicName, TopicId, callback, QoSx), + SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic1, 0, on_Topic01, QoS1), + SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic2, 0, on_Topic02, QoS1), + END_OF_SUBSCRIBE_LIST +}; /*------------------------------------------------------ * Test functions *------------------------------------------------------*/ void subscribePredefTopic1(void) { - SUBSCRIBE(1, on_Topic03, QoS1); + SUBSCRIBE_PREDEF(1, on_Topic03, QoS1); } void publishTopic1(void) { char payload[300]; - sprintf(payload, "publish \"ty4tw/Topic1\" \n"); - PUBLISH(topic1,(uint8_t*)payload, strlen(payload), QoS0); -} - -void subscribeTopic10(void) -{ - SUBSCRIBE(10, on_Topic02, QoS1); + sprintf(payload, "publish \"ty4tw/topic1\" \n"); + PUBLISH(topic1, (uint8_t* )payload, strlen(payload), QoS0); } void publishTopic2(void) { char payload[300]; sprintf(payload, "publish \"ty4tw/topic2\" \n"); - PUBLISH(topic2,(uint8_t*)payload, strlen(payload), QoS1); + PUBLISH(topic2, (uint8_t* )payload, strlen(payload), QoS1); } +void publishTopic4(void) +{ + char payload[300]; + sprintf(payload, "publish \"ty4tw/topic40\" \n"); + PUBLISH(topic4, (uint8_t* )payload, strlen(payload), QoS1); +} + +void subscribeTopic10(void) +{ + SUBSCRIBE_PREDEF(10, on_Topic02, QoS1); +} + +void subscribeWildcardTopic(void) +{ + SUBSCRIBE(topic50, on_TopicWildcard, QoS1); +} void unsubscribe(void) @@ -167,7 +202,7 @@ void test3(void) char payload[300]; sprintf(payload, "TEST3 "); uint8_t qos = 0; - PUBLISH(topic2,(uint8_t*)payload, strlen(payload), qos); + PUBLISH(topic2, (uint8_t* )payload, strlen(payload), qos); } void disconnect(void) @@ -180,48 +215,76 @@ void asleep(void) DISCONNECT(theMqcon.sleepDuration); } +void onconnect(void) +{ + ONCONNECT(); +} + +void connect(void) +{ + CONNECT(); +} + +void DisableAutoPingreq(void) +{ + SetAutoPingReqMode(false); +} + +void CleanSessionOff(void) +{ + SetCleanSession(false); +} + /*------------------------------------------------------ * A List of Test functions is valid in case of * line 23 of LMqttsnClientApp.h is commented out. * //#define CLIENT_MODE *------------------------------------------------------*/ -TEST_LIST = {// e.g. TEST( Label, Test), - TEST("Step0:Subscribe predef topic1", subscribePredefTopic1), - TEST("Step1:Publish topic1", publishTopic1), - TEST("Step2:Publish topic2", publishTopic2), - TEST("Step3:Subscribe PreDefined topic10. ID is not defined.", subscribeTopic10), - TEST("Step4:Publish topic2", publishTopic2), - TEST("Step5:Unsubscribe topic2", unsubscribe), - TEST("Step6:Publish topic2", publishTopic2), - TEST("Step7:subscribe again", subscribechangeCallback), - TEST("Step8:Publish topic2", publishTopic2), - TEST("Step9:Sleep ", asleep), - TEST("Step10:Publish topic1", publishTopic1), - TEST("Step11:Disconnect", disconnect), - END_OF_TEST_LIST - }; +TEST_LIST = +{ // e.g. TEST( Label, Test), + TEST("Step0:Connect", connect), + TEST("Step1:Subscribe list", onconnect), + TEST("Step2:Subscribe predef topic1", subscribePredefTopic1), + TEST("Step3:Publish topic1", publishTopic1), + TEST("Step4:Publish topic2", publishTopic2), + TEST("Step5:Subscribe PreDefined topic10. ID is not defined.", subscribeTopic10), + TEST("Step6:Publish topic2", publishTopic2), + TEST("Step7:Unsubscribe topic2", unsubscribe), + TEST("Step8:Publish topic2", publishTopic2), + TEST("Step9:subscribe again", subscribechangeCallback), + TEST("Step10:Publish topic2", publishTopic2), + TEST("Step11:Sleep ", asleep), + TEST("Step12:Publish topic1", publishTopic1), + TEST("Step13:Disconnect", disconnect), + TEST("Step14:Publish topic2", publishTopic1), + TEST("Step15:Connect", connect), + TEST("Step16:Publish topic2", publishTopic2), + TEST("Step17:Auto Pingreq mode off", DisableAutoPingreq), + TEST("Step18:Publish topic2", publishTopic1), + TEST("Step19:Disconnect", disconnect), + END_OF_TEST_LIST +}; /*------------------------------------------------------ * List of tasks is valid in case of line23 of * LMqttsnClientApp.h is uncommented. * #define CLIENT_MODE *------------------------------------------------------*/ -TASK_LIST = {// e.g. TASK( task, executing duration in second), - TASK(publishTopic1, 4), // publishTopic1() is executed every 4 seconds - TASK(publishTopic2, 7), // publishTopic2() is executed every 7 seconds - END_OF_TASK_LIST - }; - +TASK_LIST = +{ // e.g. TASK( task, executing duration in second), + TASK(publishTopic1, 4),// publishTopic1() is executed every 4 seconds + TASK(publishTopic2, 7),// publishTopic2() is executed every 7 seconds + END_OF_TASK_LIST +}; /*------------------------------------------------------ * Initialize function *------------------------------------------------------*/ void setup(void) { - SetForwarderMode(false); + SetForwarderMode(false); } - /***************** END OF PROGRAM ********************/ diff --git a/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp b/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp index cdacac1..3e71f83 100644 --- a/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp +++ b/MQTTSNGateway/GatewayTester/src/LGwProxy.cpp @@ -57,6 +57,8 @@ LGwProxy::LGwProxy() _initialized = 0; _isForwarderMode = false; _isQoSMinus1Mode = false; + _isPingReqMode = true; + _isAutoConnectMode = true; } LGwProxy::~LGwProxy() @@ -64,16 +66,20 @@ LGwProxy::~LGwProxy() _topicTbl.clearTopic(); } -void LGwProxy::initialize(LUdpConfig netconf, LMqttsnConfig mqconf) +void LGwProxy::initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf) { - _network.initialize(netconf); - _clientId = netconf.clientId; - _willTopic = mqconf.willTopic; - _willMsg = mqconf.willMsg; - _qosWill = mqconf.willQos; - _retainWill = mqconf.willRetain; - _cleanSession = mqconf.cleanSession; - _tkeepAlive = mqconf.keepAlive; + if (_network.initialize(netconf) == false) + { + DISPLAY("Can't open SensorNetwork\n"); + exit(-1); + } + _clientId = netconf->clientId; + _willTopic = mqconf->willTopic; + _willMsg = mqconf->willMsg; + _qosWill = mqconf->willQos; + _retainWill = mqconf->willRetain; + _cleanSession = mqconf->cleanSession; + _tkeepAlive = mqconf->keepAlive; _initialized = 1; } @@ -85,6 +91,12 @@ void LGwProxy::connect() { pos = _msg; + if (!_network.isBroadcastable() && _status == GW_LOST) + { + _status = GW_CONNECTING; + continue; + } + if (_status == GW_LOST) { @@ -188,7 +200,24 @@ int LGwProxy::getConnectResponce(void) { _network.setGwAddress(); _gwId = _mqttsnMsg[1]; + +#if defined(DTLS) || defined(DTLS6) + for (int i = 0; i < MQTTSN_RETRY_COUNT; i++) + { + if (_network.sslConnect() > 0) + { + _status = GW_CONNECTING; + DISPLAY("\033[0m\033[0;32m\n\nLGwProxy::getConnectResponce DTLS connection established.\033[0m\033[0;37m\n\n"); + break; + } + else + { + DISPLAY("\033[0m\033[0;32m\n\nLGwProxy::getConnectResponce DTLS connection failed.\033[0m\033[0;37m\n\n"); + } + } +#else _status = GW_CONNECTING; +#endif } else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLTOPICREQ && _status == GW_WAIT_WILLTOPICREQ) { @@ -231,9 +260,12 @@ int LGwProxy::getConnectResponce(void) void LGwProxy::reconnect(void) { - D_MQTTLOG("...Gateway reconnect\r\n"); - _status = GW_DISCONNECTED; - connect(); + if (_isAutoConnectMode) + { + D_MQTTLOG("...Gateway reconnect\r\n"); + _status = GW_DISCONNECTED; + connect(); + } } void LGwProxy::disconnect(uint16_t secs) @@ -395,7 +427,7 @@ int LGwProxy::getMessage(void) } else if (_mqttsnMsg[0] == MQTTSN_TYPE_DISCONNECT) { - _status = GW_LOST; + _status = GW_DISCONNECTED; _gwAliveTimer.stop(); _keepAliveTimer.stop(); } @@ -586,7 +618,7 @@ uint16_t LGwProxy::getNextMsgId(void) void LGwProxy::checkPingReq(void) { - if ( _isQoSMinus1Mode ) + if (_isQoSMinus1Mode || _isPingReqMode == false) { return; } @@ -671,3 +703,23 @@ void LGwProxy::setQoSMinus1Mode(bool valid) { _isQoSMinus1Mode = valid; } + +void LGwProxy::setPingReqMode(bool valid) +{ + _isPingReqMode = valid; +} + +void LGwProxy::setAutoConnectMode(bool valid) +{ + _isAutoConnectMode = valid; +} + +void LGwProxy::setSessionMode(bool valid) +{ + _cleanSession = valid; +} + +uint8_t LGwProxy::getStatus(void) +{ + return _status; +} diff --git a/MQTTSNGateway/GatewayTester/src/LGwProxy.h b/MQTTSNGateway/GatewayTester/src/LGwProxy.h index 814affc..48bba97 100644 --- a/MQTTSNGateway/GatewayTester/src/LGwProxy.h +++ b/MQTTSNGateway/GatewayTester/src/LGwProxy.h @@ -23,6 +23,10 @@ #include "LMqttsnClientApp.h" #include "LNetworkUdp.h" +#include "LNetworkUdp6.h" +#include "LNetworkRfcomm.h" +#include "LNetworkDtls.h" +#include "LNetworkDtls6.h" #include "LRegisterManager.h" #include "LTimer.h" #include "LTopicTable.h" @@ -42,6 +46,7 @@ using namespace std; #define GW_SLEEPING 10 #define GW_DISCONNECTED 11 #define GW_SLEPT 12 +#define SSL_CONNECTING 13 #define GW_WAIT_PINGRESP 1 @@ -54,7 +59,7 @@ public: LGwProxy(); ~LGwProxy(); - void initialize(LUdpConfig netconf, LMqttsnConfig mqconf); + void initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf); void connect(void); void disconnect(uint16_t sec = 0); int getMessage(void); @@ -67,6 +72,9 @@ public: void setAdvertiseDuration(uint16_t duration); void setForwarderMode(bool valid); void setQoSMinus1Mode(bool valid); + void setPingReqMode(bool valid); + void setAutoConnectMode(bool valid); + void setSessionMode(bool valid); void reconnect(void); int writeMsg(const uint8_t* msg); void setPingReqTimer(void); @@ -74,6 +82,7 @@ public: LTopicTable* getTopicTable(void); LRegisterManager* getRegisterManager(void); const char* getClientId(void); + uint8_t getStatus(void); private: int readMsg(void); void writeGwMsg(void); @@ -109,8 +118,10 @@ private: LTimer _keepAliveTimer; uint16_t _tSleep; uint16_t _tWake; - bool _isForwarderMode; - bool _isQoSMinus1Mode; + bool _isForwarderMode; + bool _isQoSMinus1Mode; + bool _isPingReqMode; + bool _isAutoConnectMode; char _msg[MQTTSN_MAX_MSG_LENGTH + 1]; }; diff --git a/MQTTSNGateway/GatewayTester/src/LMqttsnClient.cpp b/MQTTSNGateway/GatewayTester/src/LMqttsnClient.cpp index b6759dc..c27ee8a 100644 --- a/MQTTSNGateway/GatewayTester/src/LMqttsnClient.cpp +++ b/MQTTSNGateway/GatewayTester/src/LMqttsnClient.cpp @@ -29,7 +29,7 @@ extern TaskList theTaskList[]; extern TestList theTestList[]; extern OnPublishList theOnPublishList[]; extern MQTTSNCONF; -extern UDPCONF; +extern SENSORNET_CONFIG_t theNetcon; extern void setup(void); /*===================================== @@ -50,7 +50,20 @@ int main(int argc, char** argv) #ifndef CLIENT_MODE char c = 0; printf("\n%s", PAHO_COPYRIGHT4); - printf("\n%s\n", PAHO_COPYRIGHT0); + printf("\n%s", PAHO_COPYRIGHT0); +#if defined(UDP) + printf("UDP ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo); +#elif defined(UDP6) + printf("UDP6 ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo); +#elif defined(DTLS) + printf("DTLS ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo); +#elif defined(DTLS6) + printf("DTLS6 ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo); +#elif defined(RFCOMM) + printf("RFCOMM ClientId:%s channel:%d\n", theNetcon.clientId, theNetcon.channel); +#else + printf("\n"); +#endif printf("%s\n", PAHO_COPYRIGHT1); printf("%s\n", PAHO_COPYRIGHT2); printf(" *\n%s\n", PAHO_COPYRIGHT3); @@ -77,11 +90,13 @@ int main(int argc, char** argv) break; } } + theClient->setAutoConnectMode(false); + theClient->getPublishManager()->setAutoConnectMode(false); #endif setup(); theClient->addTask(theClientMode); - theClient->initialize( theNetcon, theMqcon); + theClient->initialize( &theNetcon, &theMqcon); do { theClient->run(); @@ -98,7 +113,7 @@ int main(int argc, char** argv) ======================================*/ LMqttsnClient::LMqttsnClient() { - + _isAutoConnect = true; } LMqttsnClient::~LMqttsnClient() @@ -106,10 +121,10 @@ LMqttsnClient::~LMqttsnClient() } -void LMqttsnClient::initialize(LUdpConfig netconf, LMqttsnConfig mqconf) +void LMqttsnClient::initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf) { _gwProxy.initialize(netconf, mqconf); - setSleepDuration(mqconf.sleepDuration); + setSleepDuration(mqconf->sleepDuration); } void LMqttsnClient::addTask(bool clientMode) @@ -183,9 +198,10 @@ void LMqttsnClient::subscribe(const char* topicName, TopicCallback onPublish, ui _subMgr.subscribe(topicName, onPublish, qos); } -void LMqttsnClient::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos) +void LMqttsnClient::subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, + uint8_t qos) { - _subMgr.subscribe(topicId, onPublish, qos); + _subMgr.subscribePredefinedId(topicId, onPublish, qos); } void LMqttsnClient::unsubscribe(const char* topicName) @@ -205,10 +221,20 @@ void LMqttsnClient::disconnect(uint16_t sleepInSecs) void LMqttsnClient::run() { - _gwProxy.connect(); + if (_isAutoConnect) + { + _gwProxy.connect(); + } _taskMgr.run(); } +void LMqttsnClient::setAutoConnectMode(uint8_t flg) +{ + _isAutoConnect = flg; + _pubMgr.setAutoConnectMode(flg); + _gwProxy.setAutoConnectMode(flg); +} + void LMqttsnClient::setSleepMode(uint32_t duration) { // ToDo: set WDT and sleep mode @@ -227,7 +253,10 @@ void LMqttsnClient::setSleepDuration(uint32_t duration) void LMqttsnClient::onConnect(void) { + if (_isAutoConnect) + { _subMgr.onConnect(); + } } const char* LMqttsnClient::getClientId(void) diff --git a/MQTTSNGateway/GatewayTester/src/LMqttsnClient.h b/MQTTSNGateway/GatewayTester/src/LMqttsnClient.h index de60310..d46c61f 100644 --- a/MQTTSNGateway/GatewayTester/src/LMqttsnClient.h +++ b/MQTTSNGateway/GatewayTester/src/LMqttsnClient.h @@ -54,15 +54,16 @@ public: void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false); void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false); void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos); - void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos); + void subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos); void unsubscribe(const char* topicName); void unsubscribe(const uint16_t topicId); void disconnect(uint16_t sleepInSecs); - void initialize(LUdpConfig netconf, LMqttsnConfig mqconf); + void initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf); void run(void); void addTask(bool test); void setSleepDuration(uint32_t duration); void setSleepMode(uint32_t duration); + void setAutoConnectMode(uint8_t flg); void sleep(void); const char* getClientId(void); uint16_t getTopicId(const char* topicName); @@ -78,6 +79,7 @@ private: LSubscribeManager _subMgr; LGwProxy _gwProxy; uint32_t _sleepDuration; + uint8_t _isAutoConnect; }; diff --git a/MQTTSNGateway/GatewayTester/src/LMqttsnClientApp.h b/MQTTSNGateway/GatewayTester/src/LMqttsnClientApp.h index b848e4c..8182f3a 100644 --- a/MQTTSNGateway/GatewayTester/src/LMqttsnClientApp.h +++ b/MQTTSNGateway/GatewayTester/src/LMqttsnClientApp.h @@ -17,17 +17,17 @@ #ifndef MQTTSNCLIENTAPP_H_ #define MQTTSNCLIENTAPP_H_ -/*====================================== - * Program mode Flag - ======================================*/ -//#define CLIENT_MODE - /*====================================== * Debug Flag ======================================*/ //#define DEBUG_NW //#define DEBUG_MQTTSN +/*====================================== + * Program mode Flag + ======================================*/ +//#define CLIENT_MODE + /**************************************** MQTT-SN Parameters *****************************************/ @@ -55,7 +55,8 @@ typedef signed int int32_t; Application config structures *****************************************/ -struct LMqttsnConfig{ +struct LMqttsnConfig +{ uint16_t keepAlive; bool cleanSession; uint32_t sleepDuration; @@ -65,13 +66,30 @@ struct LMqttsnConfig{ bool willRetain; }; -struct LUdpConfig{ +struct LUdpConfig +{ const char* clientId; uint8_t ipAddress[4]; uint16_t gPortNo; uint16_t uPortNo; }; +struct LUdp6Config +{ + const char* clientId; + const char* ipAddress; + const char *interface; + uint16_t gPortNo; + uint16_t uPortNo; +}; + +struct LRfcommConfig +{ + const char* clientId; + const char* gwAddress; + uint8_t channel; +}; + typedef enum { @@ -85,13 +103,50 @@ typedef enum MACROs for Application =======================================*/ #define MQTTSN_CONFIG MqttsnConfig theMqttsnConfig -#define NETWORK_CONFIG UdpConfig theNetworkConfig +#define MQTTSNCONF LMqttsnConfig theMqcon + +#if defined(UDP) +#define UDPCONF LUdpConfig theNetcon +#define UDP6CONF LUdp6Config theU6Conf +#define RFCOMMCONF LRfcommConfig theRfConf +#define SENSORNET_CONFIG_t LUdpConfig + +#elif defined(UDP6) +#define UDP6CONF LUdp6Config theNetcon +#define UDPCONF LUdpConfig theUConf +#define RFCOMMCONF LRfcommConfig theRfConf +#define SENSORNET_CONFIG_t LUdp6Config + +#elif defined(RFCOMM) +#define RFCOMMCONF LRfcommConfig theNetcon +#define UDPCONF LUdpConfig theUConf +#define UDP6CONF LUdp6Config theU6Conf +#define SENSORNET_CONFIG_t LRfcommConfig + +#elif defined(DTLS) +#define UDPCONF LUdpConfig theNetcon +#define UDP6CONF LUdp6Config theU6Conf +#define RFCOMMCONF LRfcommConfig theRfConf +#define SENSORNET_CONFIG_t LUdpConfig + +#elif defined(DTLS6) +#define UDPCONF LUdpConfig theUConf +#define UDP6CONF LUdp6Config theNetcon +#define RFCOMMCONF LRfcommConfig theRfConf +#define SENSORNET_CONFIG_t LUdp6Config +#else +#error "UDP, UDP6, DTLS, DTLS6 or RFCOMM is not defined in LMqttsnClientApp.h" +#endif + + #define CONNECT(...) theClient->getGwProxy()->connect(__VA_ARGS__) #define PUBLISH(...) theClient->publish(__VA_ARGS__) #define SUBSCRIBE(...) theClient->subscribe(__VA_ARGS__) +#define SUBSCRIBE_PREDEF(...) theClient->subscribePredefinedId(__VA_ARGS__) #define UNSUBSCRIBE(...) theClient->unsubscribe(__VA_ARGS__) #define DISCONNECT(...) theClient->disconnect(__VA_ARGS__) +#define ONCONNECT() theClient->getSubscribeManager()->onConnect() #define TASK_LIST TaskList theTaskList[] #define TASK(...) {__VA_ARGS__, 0, 0} @@ -102,11 +157,13 @@ typedef enum #define SUBSCRIBE_LIST OnPublishList theOnPublishList[] #define SUB(...) {__VA_ARGS__} #define END_OF_SUBSCRIBE_LIST {MQTTSN_TOPIC_TYPE_NORMAL,0,0,0, 0} -#define UDPCONF LUdpConfig theNetcon -#define MQTTSNCONF LMqttsnConfig theMqcon + + #define SetForwarderMode(...) theClient->getGwProxy()->setForwarderMode(__VA_ARGS__) #define SetQoSMinus1Mode(...) theClient->getGwProxy()->setQoSMinus1Mode(__VA_ARGS__) - +#define SetAutoConnectMode(...) theClient->setAutoConnectMode(__VA_ARGS__) +#define SetAutoPingReqMode(...) theClient->getGwProxy()->setPingReqMode(__VA_ARGS__) +#define SetCleanSession(...) theClient->getGwProxy()->setSessionMode(__VA_ARGS__) #ifdef CLIENT_MODE #define DISPLAY(...) #define PROMPT(...) @@ -195,11 +252,11 @@ typedef enum /*================================= * Starting prompt ==================================*/ -#define TESTER_VERSION " * Version: 2.0.0" +#define TESTER_VERSION " * Version: 2.1.0" -#define PAHO_COPYRIGHT0 " * MQTT-SN Gateway Tester" +#define PAHO_COPYRIGHT0 " * " #define PAHO_COPYRIGHT1 " * Part of Project Paho in Eclipse" -#define PAHO_COPYRIGHT2 " * (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)" +#define PAHO_COPYRIGHT2 " * (https://github.com/eclipse/paho.mqtt-sn.embedded-c.git)" #define PAHO_COPYRIGHT3 " * Author : Tomoaki YAMAGUCHI" #define PAHO_COPYRIGHT4 " ***************************************************************************" diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkDtls.cpp b/MQTTSNGateway/GatewayTester/src/LNetworkDtls.cpp new file mode 100644 index 0000000..a0adbe6 --- /dev/null +++ b/MQTTSNGateway/GatewayTester/src/LNetworkDtls.cpp @@ -0,0 +1,544 @@ +/************************************************************************************** + * Copyright (c) 2016, Tomoaki Yamaguchi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation + **************************************************************************************/ +#ifdef DTLS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "LMqttsnClientApp.h" +#include "LNetworkDtls.h" +#include "LTimer.h" +#include "LScreen.h" + +using namespace std; +using namespace linuxAsyncClient; + +extern uint16_t getUint16(const uint8_t* pos); +extern uint32_t getUint32(const uint8_t* pos); +extern LScreen* theScreen; +extern bool theClientMode; + +/* Certificate verification. Returns 1 if trusted, else 0 */ +int verify_cert(int ok, X509_STORE_CTX *ctx); + +/*========================================= + Class LNetwork + =========================================*/ +LNetwork::LNetwork() +{ + _sleepflg = false; + resetGwAddress(); +} + +LNetwork::~LNetwork() +{ +} + +int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen) +{ + return LDtlsPort::multicast(xmitData, (uint32_t) dataLen); +} + +int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen) +{ + return LDtlsPort::unicast(xmitData, dataLen); +} + + +uint8_t* LNetwork::getMessage(int *len) +{ + *len = 0; + uint16_t recvLen = 0; + if (checkRecvBuf()) + { + recvLen = LDtlsPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo); + if (_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo)) + { + return 0; + } + + if (recvLen < 0) + { + *len = recvLen; + return 0; + } + else + { + if (_rxDataBuf[0] == 0x01) + { + *len = getUint16(_rxDataBuf + 1); + } + else + { + *len = _rxDataBuf[0]; + } + return _rxDataBuf; + } + } + return 0; +} + +void LNetwork::setGwAddress(void) +{ + _gwPortNo = _portNo; + _gwIpAddress = _ipAddress; +} + +void LNetwork::resetGwAddress(void) +{ + _gwIpAddress = 0; + _gwPortNo = 0; +} + + +bool LNetwork::initialize(LUdpConfig *config) +{ + return LDtlsPort::open(config); +} + +void LNetwork::setSleep() +{ + _sleepflg = true; +} + +bool LNetwork::isBroadcastable() +{ + return true; +} + +int LNetwork::sslConnect(void) +{ + return LDtlsPort::sslConnect(_gwIpAddress, _gwPortNo); +} + +/*========================================= + Class DtlsPort + =========================================*/ +LDtlsPort::LDtlsPort() +{ + _disconReq = false; + _sockfdMcast = 0; + _sockfdSsl = 0; + _castStat = 0; +} + +LDtlsPort::~LDtlsPort() +{ + close(); +} + + +void LDtlsPort::close() +{ + if (_sockfdMcast > 0) + { + ::close(_sockfdMcast); + _sockfdMcast = 0; + if (_sockfdSsl > 0) + { + ::close(_sockfdSsl); + _sockfdSsl = 0; + } + } +} + +bool LDtlsPort::open(LUdpConfig *config) +{ + char errmsg[256]; + int optval = 0; + + uint8_t sav = config->ipAddress[3]; + config->ipAddress[3] = config->ipAddress[0]; + config->ipAddress[0] = sav; + sav = config->ipAddress[2]; + config->ipAddress[2] = config->ipAddress[1]; + config->ipAddress[1] = sav; + + _gIpAddr = getUint32((const uint8_t*) config->ipAddress); + _gPortNo = htons(config->gPortNo); + _uPortNo = htons(config->uPortNo); + + if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0) + { + return false; + } + + SSL_load_error_strings(); + SSL_library_init(); + _ctx = SSL_CTX_new(DTLS_client_method()); + + if (_ctx == 0) + { + ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); + DISPLAY("SSL_CTX_new() %s\n", errmsg); + return false; + } + + /* Client certification and cookie are not required */ + SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_cert); + + /* setup Multicast socket */ + _sockfdMcast = socket(AF_INET, SOCK_DGRAM, 0); + if (_sockfdMcast < 0) + { + return false; + } + + struct sockaddr_in addrm; + addrm.sin_family = AF_INET; + addrm.sin_port = _gPortNo; + addrm.sin_addr.s_addr = INADDR_ANY; + + optval = 1; + setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + if (::bind(_sockfdMcast, (struct sockaddr*) &addrm, sizeof(addrm)) < 0) + { + return false; + } + + optval = 1; + if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in LDtlsPort::open\033[0m\033[0;37m\n"); + close(); + return false; + } + + ip_mreq mreq; + mreq.imr_interface.s_addr = INADDR_ANY; + mreq.imr_multiaddr.s_addr = _gIpAddr; + + if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in LDtlsPort::open\033[0m\033[0;37m\n"); + close(); + return false; + } + return true; +} + +bool LDtlsPort::isUnicast() +{ + return (_castStat == STAT_UNICAST); +} + + +int LDtlsPort::unicast(const uint8_t *buf, uint32_t length) +{ + int status = SSL_write(_ssl, buf, length); + if (status <= 0) + { + int rc = 0; + SSL_get_error(_ssl, rc); + DISPLAY("errno == %d in LDtlsPort::unicast\n", rc); + } + else + { + D_NWLOG("sendto gateway via DTLS "); + for (uint16_t i = 0; i < length; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } + D_NWLOG("\n"); + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34msendto the gateway via SSL "); + pos = strlen(sbuf); + for (uint16_t i = 0; i < length; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + } + return status; +} + + +int LDtlsPort::multicast(const uint8_t *buf, uint32_t length) +{ + struct sockaddr_in dest; + dest.sin_family = AF_INET; + dest.sin_port = _gPortNo; + dest.sin_addr.s_addr = _gIpAddr; + + int status = ::sendto(_sockfdMcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest)); + if (status < 0) + { + D_NWLOG("\033[0m\033[0;31merrno == %d in LDtlsPort::multicast\033[0m\033[0;37m\n", errno); + DISPLAY("\033[0m\033[0;31merrno == %d in LDtlsPort::multicast\033[0m\033[0;37m\n", errno); + return errno; + } + else + { + D_NWLOG("sendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo)); + + for (uint16_t i = 0; i < length; i++) + { + D_NWLOG(" %02x", *(buf + i)); + DISPLAY(" %02x", *(buf + i)); + } + D_NWLOG("\n"); + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo)); + pos = strlen(sbuf); + for (uint16_t i = 0; i < length; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + return status; + } + +} + +bool LDtlsPort::checkRecvBuf() +{ + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 50000; // 50 msec + + uint8_t buf[2]; + fd_set recvfds; + int maxSock = 0; + + FD_ZERO(&recvfds); + if (_sockfdMcast) + { + FD_SET(_sockfdMcast, &recvfds); + } + if (_sockfdSsl) + { + FD_SET(_sockfdSsl, &recvfds); + } + + if (_sockfdMcast > _sockfdSsl) + { + maxSock = _sockfdMcast; + } + else + { + maxSock = _sockfdSsl; + } + + select(maxSock + 1, &recvfds, 0, 0, &timeout); + + if (FD_ISSET(_sockfdMcast, &recvfds)) + { + if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0) + { + _castStat = STAT_MULTICAST; + return true; + } + } + else if (FD_ISSET(_sockfdSsl, &recvfds)) + { + if (::recv(_sockfdSsl, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0) + { + _castStat = STAT_SSL; + return true; + } + } + _castStat = STAT_NONE; + return false; +} + +int LDtlsPort::recv(uint8_t *buf, uint16_t len, bool flg, uint32_t *ipAddressPtr, in_port_t *portPtr) +{ + int flags = flg ? MSG_DONTWAIT : 0; + return recvfrom(buf, len, flags, ipAddressPtr, portPtr); +} + +int LDtlsPort::recvfrom(uint8_t *buf, uint16_t length, int flags, uint32_t *ipAddressPtr, in_port_t *portPtr) +{ + struct sockaddr_in sender; + int status = 0; + socklen_t addrlen = sizeof(sender); + memset(&sender, 0, addrlen); + + if (_castStat == STAT_SSL) + { + D_NWLOG("Ucast "); + if (SSL_read(_ssl, buf, length) == 0) + { + return 0; + } + } + else if (_castStat == STAT_MULTICAST) + { + D_NWLOG("Mcast "); + status = ::recvfrom(_sockfdMcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen); + } + else + { + return 0; + } + + if (status < 0 && errno != EAGAIN) + { + D_NWLOG("\033[0m\033[0;31merrno == %d in LDtlsPort::recvfrom \033[0m\033[0;37m\n", errno); + DISPLAY("\033[0m\033[0;31merrno == %d in LDtlsPort::recvfrom \033[0m\033[0;37m\n", errno); + } + else if (status > 0) + { + *ipAddressPtr = sender.sin_addr.s_addr; + *portPtr = sender.sin_port; + + D_NWLOG("recved %-15s:%-6u", inet_ntoa(sender.sin_addr), ntohs(*portPtr)); + + for (uint16_t i = 0; i < status; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } + D_NWLOG("\n"); + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", inet_ntoa(sender.sin_addr), ntohs(*portPtr)); + pos = strlen(sbuf); + for (uint16_t i = 0; i < status; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + return status; + } + else + { + return 0; + } + return status; +} + +int LDtlsPort::sslConnect(uint32_t ipAddress, in_port_t portNo) +{ + int reuse = 1; + if (_ssl != 0) + { + D_NWLOG("LDtlsPort::sslConnect SSL exists.\n"); + SSL_shutdown(_ssl); + SSL_free(_ssl); + _sockfdSsl = 0; + _ssl = 0; + } + + if (_sockfdSsl > 0) + { + D_NWLOG("LDtlsPort::sslConnect socket exists.\n"); + ::close(_sockfdSsl); + } + + _sockfdSsl = socket(AF_INET, SOCK_DGRAM, 0); + if (_sockfdSsl < 0) + { + D_NWLOG("LDtlsPort::sslConnect Can't create a socket\n"); + return -1; + } + setsockopt(_sockfdSsl, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = _uPortNo; + addr.sin_addr.s_addr = INADDR_ANY; + if (::bind(_sockfdSsl, (struct sockaddr*) &addr, sizeof(addr)) < 0) + { + ::close(_sockfdSsl); + _sockfdSsl = 0; + D_NWLOG("LDtlsPort::sslConnect Can't bind a socket\n"); + return -1; + } + + struct sockaddr_in dest; + dest.sin_family = AF_INET; + dest.sin_port = portNo; + dest.sin_addr.s_addr = ipAddress; + int rc = 0; + errno = 0; + BIO *cbio = BIO_new_dgram(_sockfdSsl, BIO_NOCLOSE); + connect(_sockfdSsl, (sockaddr*) &dest, sizeof(sockaddr_in)); + BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest); + _ssl = SSL_new(_ctx); + SSL_set_bio(_ssl, cbio, cbio); + + D_NWLOG("LDtlsPort::sslConnect connect to %-15s:%-6u\n", inet_ntoa(dest.sin_addr), htons(dest.sin_port)); + + timeval timeout; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); + + int stat = SSL_connect(_ssl); + if (stat != 1) + { + rc = -1; + D_NWLOG("SSL fail to connect\n"); + } + else + { + rc = 1; + D_NWLOG("SSL connected\n"); + } + return rc; +} + +int verify_cert(int ok, X509_STORE_CTX *ctx) +{ + return 1; +} + + +#endif + diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkDtls.h b/MQTTSNGateway/GatewayTester/src/LNetworkDtls.h new file mode 100644 index 0000000..5fac0b0 --- /dev/null +++ b/MQTTSNGateway/GatewayTester/src/LNetworkDtls.h @@ -0,0 +1,118 @@ +/************************************************************************************** + * Copyright (c) 2016, Tomoaki Yamaguchi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation + **************************************************************************************/ + +#ifndef NETWORKDTLS_H_ +#define NETWORKDTLS_H_ + +#ifdef DTLS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SOCKET_MAXHOSTNAME 200 +#define SOCKET_MAXCONNECTIONS 5 +#define SOCKET_MAXRECV 500 +#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size + + +using namespace std; + +namespace linuxAsyncClient { +#define STAT_NONE 0 +#define STAT_UNICAST 1 +#define STAT_MULTICAST 2 +#define STAT_SSL 3 +/*======================================== + Class LDtlsPort + =======================================*/ +class LDtlsPort +{ + friend class LNetwork; +public: + LDtlsPort(); + virtual ~LDtlsPort(); + + bool open(LUdpConfig* config); + + int unicast(const uint8_t *buf, uint32_t length); + int multicast( const uint8_t* buf, uint32_t length ); + int recv(uint8_t* buf, uint16_t len, bool nonblock, uint32_t* ipaddress, in_port_t* port ); + int recv(uint8_t* buf, int flags); + bool checkRecvBuf(); + bool isUnicast(); + SSL* getSSL(void); + int sslConnect(uint32_t ipAddress, in_port_t port); +private: + void close(); + int recvfrom ( uint8_t* buf, uint16_t len, int flags, uint32_t* ipaddress, in_port_t* port ); + + int _sockfdMcast; + int _sockfdSsl; + SSL_CTX *_ctx; + SSL *_ssl; + in_port_t _gPortNo; + in_port_t _uPortNo; + uint32_t _gIpAddr; + uint8_t _castStat; + bool _disconReq; + +}; + +#define NO_ERROR 0 +#define PACKET_EXCEEDS_LENGTH 1 +/*=========================================== + Class Network + ============================================*/ +class LNetwork: public LDtlsPort +{ +public: + LNetwork(); + ~LNetwork(); + + int broadcast(const uint8_t* payload, uint16_t payloadLen); + int unicast(const uint8_t* payload, uint16_t payloadLen); + void setGwAddress(void); + void resetGwAddress(void); + bool initialize(LUdpConfig* config); + uint8_t* getMessage(int* len); + bool isBroadcastable(); + int sslConnect(void); +private: + void setSleep(); + int readApiFrame(void); + + uint32_t _gwIpAddress; + uint32_t _ipAddress; + in_port_t _gwPortNo; + in_port_t _portNo; + int _returnCode; + bool _sleepflg; + uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h + +}; + +} /* end of namespace */ +#endif /* DTLS */ +#endif /* NETWORKDTLS_H_ */ diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkDtls6.cpp b/MQTTSNGateway/GatewayTester/src/LNetworkDtls6.cpp new file mode 100644 index 0000000..83006f9 --- /dev/null +++ b/MQTTSNGateway/GatewayTester/src/LNetworkDtls6.cpp @@ -0,0 +1,586 @@ +/************************************************************************************** + * Copyright (c) 2021, Tomoaki Yamaguchi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation + **************************************************************************************/ +#ifdef DTLS6 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "LMqttsnClientApp.h" +#include "LNetworkDtls6.h" +#include "LTimer.h" +#include "LScreen.h" + +using namespace std; +using namespace linuxAsyncClient; + +extern uint16_t getUint16(const uint8_t *pos); +extern uint32_t getUint32(const uint8_t *pos); +extern LScreen *theScreen; +extern bool theClientMode; + +/* Certificate verification. Returns 1 if trusted, else 0 */ +int verify_cert(int ok, X509_STORE_CTX *ctx); + +/*========================================= + Class LNetwork + =========================================*/ +LNetwork::LNetwork() +{ + _sleepflg = false; + resetGwAddress(); +} + +LNetwork::~LNetwork() +{ +} + +int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen) +{ + return LDtls6Port::multicast(xmitData, (uint32_t) dataLen); +} + +int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen) +{ + return LDtls6Port::unicast(xmitData, dataLen); +} + +uint8_t* LNetwork::getMessage(int *len) +{ + *len = 0; + if (checkRecvBuf()) + { + uint16_t recvLen = LDtls6Port::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo); + int addrFlg = memcmp(_ipAddress.s6_addr, _gwIpAddress.s6_addr, sizeof(_gwIpAddress.s6_addr)); + if (isUnicast() && addrFlg && (_portNo != _gwPortNo)) + { + return 0; + } + + if (recvLen < 0) + { + *len = recvLen; + return 0; + } + else + { + if (_rxDataBuf[0] == 0x01) + { + *len = getUint16(_rxDataBuf + 1); + } + else + { + *len = _rxDataBuf[0]; + } + return _rxDataBuf; + } + } + return 0; +} + +void LNetwork::setGwAddress(void) +{ + _gwPortNo = _portNo; + memcpy(&_gwIpAddress.s6_addr, &_ipAddress.s6_addr, sizeof(_ipAddress.s6_addr)); + +} + +void LNetwork::resetGwAddress(void) +{ + memset(&_gwIpAddress, 0, sizeof(_gwIpAddress)); + _gwPortNo = 0; +} + +bool LNetwork::initialize(LUdp6Config *config) +{ + return LDtls6Port::open(config); +} + +void LNetwork::setSleep() +{ + _sleepflg = true; +} + +bool LNetwork::isBroadcastable() +{ + return true; +} + +int LNetwork::sslConnect(void) +{ + return LDtls6Port::sslConnect(_gwIpAddress, _gwPortNo); +} + +/*========================================= + Class Dtls6Port + =========================================*/ +LDtls6Port::LDtls6Port() +{ + _disconReq = false; + _castStat = STAT_NONE; + _ifIndex = 0; + _gIpAddrStr = nullptr; + _sockfdMcast = 0; + _sockfdSsl = 0; + _ctx = nullptr; + _ssl = nullptr; + _gPortNo = _uPortNo = 0; +} + +LDtls6Port::~LDtls6Port() +{ + close(); + if (_gIpAddrStr) + { + free(_gIpAddrStr); + } +} + +void LDtls6Port::close() +{ + if (_sockfdMcast > 0) + { + ::close(_sockfdMcast); + _sockfdMcast = 0; + if (_sockfdSsl > 0) + { + ::close(_sockfdSsl); + _sockfdSsl = 0; + } + } +} + +bool LDtls6Port::open(LUdp6Config *config) +{ + int optval = 1; + sockaddr_in6 addr6; + char errmsg[256]; + + _gPortNo = htons(config->gPortNo); + _uPortNo = htons(config->uPortNo); + + if (_gPortNo == 0 || _uPortNo == 0) + { + return false; + } + + SSL_load_error_strings(); + SSL_library_init(); + _ctx = SSL_CTX_new(DTLS_client_method()); + + if (_ctx == 0) + { + ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); + DISPLAY("SSL_CTX_new() %s\n", errmsg); + return false; + } + + /* Client certification and cookie are not required */ + SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_cert); + + if (strlen(config->interface) > 0) + { + _ifIndex = if_nametoindex(config->interface); + _interfaceName = config->interface; + } + + /* create a multicast socket */ + _sockfdMcast = socket(AF_INET6, SOCK_DGRAM, 0); + if (_sockfdMcast < 0) + { + return false; + } + + optval = 1; + setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)); + + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = _gPortNo; + addr6.sin6_addr = in6addr_any; + + if (::bind(_sockfdMcast, (sockaddr*) &addr6, sizeof(addr6)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s ::bind() in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno)); + return false; + } + + ipv6_mreq addrm; + addrm.ipv6mr_interface = _ifIndex; + inet_pton(AF_INET6, config->ipAddress, &addrm.ipv6mr_multiaddr); + if (setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno)); + close(); + return false; + } + + optval = 1; + if (setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s IPV6_MULTICAST_LOOP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno)); + close(); + return false; + } + + _gIpAddr.sin6_family = AF_INET6; + _gIpAddr.sin6_port = _gPortNo; + memcpy(&_gIpAddr.sin6_addr, (const void*) &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr)); + _gIpAddrStr = strdup(config->ipAddress); + return true; +} + +bool LDtls6Port::isUnicast() +{ + return (_castStat == STAT_UNICAST); +} + +int LDtls6Port::unicast(const uint8_t *buf, uint32_t length) +{ + int status = SSL_write(_ssl, buf, length); + if (status <= 0) + { + int rc = 0; + SSL_get_error(_ssl, rc); + DISPLAY("errno == %d in LDtls6Port::unicast\n", rc); + } + else + { + D_NWLOG("sendto gateway via DTLS6 "); + for (uint16_t i = 0; i < length; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } + + D_NWLOG("\n"); + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34msendto the gateway via SSL "); + pos = strlen(sbuf); + for (uint16_t i = 0; i < length; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + } + return status; +} + +int LDtls6Port::multicast(const uint8_t *buf, uint32_t length) +{ + char sbuf[SCREEN_BUFF_SIZE]; + char portStr[8]; + sprintf(portStr, "%d", ntohs(_gIpAddr.sin6_port)); + + int status = ::sendto(_sockfdMcast, buf, length, 0, (sockaddr*) &_gIpAddr, sizeof(_gIpAddr)); + if (status < 0) + { + DISPLAY("\033[0m\033[0;31merrno == %d in LDtls6Port::multicast\033[0m\033[0;37m\n", errno); + return errno; + } + else + { + D_NWLOG("multicast to [%s]:%-6s", _gIpAddrStr, portStr); + for (uint16_t i = 0; i < length; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } + + D_NWLOG("\n"); + + if (!theClientMode) + { + memset(sbuf, 0, SCREEN_BUFF_SIZE); + int pos = 0; + sprintf(sbuf, "\033[0;34mmulticast to [%s]:%-6s", _gIpAddrStr, portStr); + pos = strlen(sbuf); + for (uint16_t i = 0; i < length; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + return status; + } +} + +bool LDtls6Port::checkRecvBuf() +{ + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 50000; // 50 msec + + uint8_t buf[2]; + fd_set recvfds; + int maxSock = 0; + + FD_ZERO(&recvfds); + if (_sockfdMcast) + { + FD_SET(_sockfdMcast, &recvfds); + } + if (_sockfdSsl) + { + FD_SET(_sockfdSsl, &recvfds); + } + + if (_sockfdMcast > _sockfdSsl) + { + maxSock = _sockfdMcast; + } + else + { + maxSock = _sockfdSsl; + } + + select(maxSock + 1, &recvfds, 0, 0, &timeout); + + if (FD_ISSET(_sockfdMcast, &recvfds)) + { + if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0) + { + _castStat = STAT_MULTICAST; + return true; + } + } + else if (FD_ISSET(_sockfdSsl, &recvfds)) + { + if (::recv(_sockfdSsl, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0) + { + _castStat = STAT_SSL; + return true; + } + } + _castStat = STAT_NONE; + return false; +} + +int LDtls6Port::recv(uint8_t *buf, uint16_t len, bool flg, in6_addr *ipAddressPtr, in_port_t *portPtr) +{ + int flags = flg ? MSG_DONTWAIT : 0; + return recvfrom(buf, len, flags, ipAddressPtr, portPtr); +} + +int LDtls6Port::recvfrom(uint8_t *buf, uint16_t length, int flags, in6_addr *ipAddressPtr, in_port_t *portPtr) +{ + sockaddr_in6 sender; + int status = 0; + socklen_t addrlen = sizeof(sender); + memset(&sender, 0, addrlen); + char addrBuf[INET6_ADDRSTRLEN]; + + if (_castStat == STAT_SSL) + { + D_NWLOG("Ucast "); + if (SSL_read(_ssl, buf, length) == 0) + { + return 0; + } + } + else if (_castStat == STAT_MULTICAST) + { + D_NWLOG("Mcast "); + status = ::recvfrom(_sockfdMcast, buf, length, flags, (sockaddr*) &sender, &addrlen); + } + else + { + return 0; + } + + if (status < 0 && errno != EAGAIN) + { + D_NWLOG("\033[0m\033[0;31merrno == %d in LDtls6Port::recvfrom \033[0m\033[0;37m\n", errno); + DISPLAY("\033[0m\033[0;31merrno == %d in LDtls6Port::recvfrom \033[0m\033[0;37m\n", errno); + } + else if (status > 0) + { + inet_ntop(AF_INET6, &sender.sin6_addr, addrBuf, INET6_ADDRSTRLEN); + memcpy(ipAddressPtr->s6_addr, (const void*) sender.sin6_addr.s6_addr, sizeof(sender.sin6_addr.s6_addr)); + *portPtr = sender.sin6_port; + + D_NWLOG("recved %-15s:%-6u", addrBuf, htons(*portPtr)); + + for (uint16_t i = 0; i < status; i++) + { + D_NWLOG(" %02x", *(buf + i)); + }D_NWLOG("\n"); + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", addrBuf, htons(*portPtr)); + pos = strlen(sbuf); + for (uint16_t i = 0; i < status; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + return status; + } + else + { + return 0; + } + return status; +} + +int LDtls6Port::sslConnect(in6_addr ipAddress, in_port_t portNo) +{ + int optval = 1; + + if (_ssl != 0) + { + D_NWLOG("LDtls6Port::sslConnect SSL exists.\n"); + SSL_shutdown(_ssl); + SSL_free(_ssl); + _sockfdSsl = 0; + _ssl = 0; + } + + if (_sockfdSsl > 0) + { + D_NWLOG("LDtls6Port::sslConnect socket exists.\n"); + ::close(_sockfdSsl); + } + + _sockfdSsl = socket(AF_INET6, SOCK_DGRAM, 0); + if (_sockfdSsl <= 0) + { + D_NWLOG("LDtls6Port::sslConnect Can't create a socket\n"); + return -1; + } + optval = 1; + setsockopt(_sockfdSsl, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)); + setsockopt(_sockfdSsl, SOL_SOCKET, SO_REUSEADDR || SO_REUSEPORT, &optval, sizeof(optval)); + + if (_ifIndex > 0) + { +#ifdef __APPLE__ + setsockopt(_sockfdSsl, IPPROTO_IP, IP_BOUND_IF, &_ifIndex, sizeof(_ifIndex)); +#else + setsockopt(_sockfdSsl, SOL_SOCKET, SO_BINDTODEVICE, _interfaceName.c_str(), _interfaceName.size()); +#endif + } + + sockaddr_in6 addr; + addr.sin6_family = AF_INET6; + addr.sin6_port = _uPortNo; + addr.sin6_addr = in6addr_any; + + if (::bind(_sockfdSsl, (struct sockaddr*) &addr, sizeof(addr)) < 0) + { + ::close(_sockfdSsl); + D_NWLOG("LDtlsPort::sslConnect Can't bind a socket\n"); + return -1; + } + + // Destination is a gateway address and portNo + int rc = 0; + sockaddr_in6 dest; + dest.sin6_family = AF_INET6; + dest.sin6_port = portNo; + memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr)); + + BIO *cbio = BIO_new_dgram(_sockfdSsl, BIO_NOCLOSE); + if (connect(_sockfdSsl, (sockaddr*) &dest, sizeof(sockaddr_in6)) < 0) + { + D_NWLOG("socket can't connect %s\n",strerror(errno)); + return -1; + } + + if (BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest) <0) + { + D_NWLOG("BIO_ctrl %s\n",strerror(errno)); + return -1; + } + + _ssl = SSL_new(_ctx); + if (_ssl == nullptr) + { + D_NWLOG("SSL_new %s\n",strerror(errno)); + return -1; + } + SSL_set_bio(_ssl, cbio, cbio); + +#ifdef DEBUG_NW + char addrBuf[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &dest.sin6_addr, addrBuf, INET6_ADDRSTRLEN); + D_NWLOG("connect to %-15s:%-6u\n", addrBuf, ntohs(dest.sin6_port)); +#endif + + timeval timeout; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); + errno = 0; + + int stat = SSL_connect(_ssl); + if (stat != 1) + { + rc = -1; + D_NWLOG("SSL fail to connect %s\n",strerror(errno)); + } + else + { + rc = 1; + D_NWLOG("SSL connected\n"); + } + return rc; +} + +int verify_cert(int ok, X509_STORE_CTX *ctx) +{ + return 1; +} + +#endif + diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkDtls6.h b/MQTTSNGateway/GatewayTester/src/LNetworkDtls6.h new file mode 100644 index 0000000..05c8cff --- /dev/null +++ b/MQTTSNGateway/GatewayTester/src/LNetworkDtls6.h @@ -0,0 +1,122 @@ +/************************************************************************************** + * Copyright (c) 2021, Tomoaki Yamaguchi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation + **************************************************************************************/ + +#ifndef NETWORKDTLS6_H_ +#define NETWORKDTLS6_H_ + +#ifdef DTLS6 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SOCKET_MAXHOSTNAME 200 +#define SOCKET_MAXCONNECTIONS 5 +#define SOCKET_MAXRECV 500 +#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size + +#define STAT_NONE 0 +#define STAT_UNICAST 1 +#define STAT_MULTICAST 2 +#define STAT_SSL 3 + +using namespace std; + +namespace linuxAsyncClient { +/*======================================== + Class LDtls6Port + =======================================*/ +class LDtls6Port +{ + friend class LNetwork; +public: + LDtls6Port(); + virtual ~LDtls6Port(); + + bool open(LUdp6Config* config); + + int unicast(const uint8_t *buf, uint32_t length); + int multicast( const uint8_t* buf, uint32_t length ); + int recv(uint8_t* buf, uint16_t len, bool nonblock, in6_addr* ipaddress, in_port_t* port ); + int recv(uint8_t* buf, int flags); + bool checkRecvBuf(); + bool isUnicast(); + SSL* getSSL(void); + int sslConnect(in6_addr ipAddress, uint16_t port); +private: + void close(); + int recvfrom ( uint8_t* buf, uint16_t len, int flags, in6_addr* ipaddress, in_port_t* port ); + + int _sockfdMcast; + int _sockfdSsl; + SSL_CTX *_ctx; + SSL *_ssl; + in_port_t _gPortNo; + in_port_t _uPortNo; + sockaddr_in6 _gIpAddr; + char *_gIpAddrStr; + uint32_t _ifIndex; + string _interfaceName; + uint8_t _castStat; + bool _disconReq; + +}; + +#define NO_ERROR 0 +#define PACKET_EXCEEDS_LENGTH 1 +/*=========================================== + Class Network + ============================================*/ +class LNetwork: public LDtls6Port +{ +public: + LNetwork(); + ~LNetwork(); + + int broadcast(const uint8_t* payload, uint16_t payloadLen); + int unicast(const uint8_t* payload, uint16_t payloadLen); + void setGwAddress(void); + void resetGwAddress(void); + bool initialize(LUdp6Config* config); + uint8_t* getMessage(int* len); + bool isBroadcastable(); + int sslConnect(void); +private: + void setSleep(); + int readApiFrame(void); + + in6_addr _gwIpAddress; + in6_addr _ipAddress; + in_port_t _gwPortNo; + in_port_t _portNo; + int _returnCode; + bool _sleepflg; + uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h + +}; + +} /* end of namespace */ +#endif /* DTLS6 */ +#endif /* NETWORKDTLS6_H_ */ diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkRfcomm.cpp b/MQTTSNGateway/GatewayTester/src/LNetworkRfcomm.cpp new file mode 100644 index 0000000..e4b5a40 --- /dev/null +++ b/MQTTSNGateway/GatewayTester/src/LNetworkRfcomm.cpp @@ -0,0 +1,286 @@ +/************************************************************************************** + * Copyright (c) 2021, Tomoaki Yamaguchi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation + **************************************************************************************/ +#ifdef RFCOMM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LMqttsnClientApp.h" +#include "LNetworkRfcomm.h" +#include "LTimer.h" +#include "LScreen.h" + +using namespace std; +using namespace linuxAsyncClient; + +extern uint16_t getUint16(const uint8_t* pos); +extern uint32_t getUint32(const uint8_t* pos); +extern LScreen* theScreen; +extern bool theClientMode; +extern LRfcommConfig theNetcon; +/*========================================= + Class LNetwork + =========================================*/ +LNetwork::LNetwork() +{ + _sleepflg = false; + _returnCode = 0; +} + +LNetwork::~LNetwork() +{ + +} + +int LNetwork::broadcast(const uint8_t* xmitData, uint16_t dataLen) +{ + return LRfcommPort::unicast(xmitData, dataLen); +} + +int LNetwork::unicast(const uint8_t* xmitData, uint16_t dataLen) +{ + return LRfcommPort::unicast(xmitData, dataLen); +} + +uint8_t* LNetwork::getMessage(int* len) +{ + *len = 0; + if (checkRecvBuf()) + { + uint16_t recvLen = LRfcommPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false); + + if (recvLen < 0) + { + *len = recvLen; + return 0; + } + else + { + if (_rxDataBuf[0] == 0x01) + { + *len = getUint16(_rxDataBuf + 1); + } + else + { + *len = _rxDataBuf[0]; + } + return _rxDataBuf; + } + } + return 0; +} + +void LNetwork::setGwAddress(void) +{ +} + +void LNetwork::setFixedGwAddress(void) +{ + _channel = LRfcommPort::_channel; + str2ba( theNetcon.gwAddress, (bdaddr_t*)_gwAddress); +} + +bool LNetwork::initialize(LRfcommConfig* config) +{ + return LRfcommPort::open(config); +} + +void LNetwork::setSleep() +{ + _sleepflg = true; +} + +bool LNetwork::isBroadcastable() +{ + return false; +} + +/*========================================= + Class RFCOMM Stack + =========================================*/ +LRfcommPort::LRfcommPort() +{ + _disconReq = false; + _sockRfcomm = 0; + _channel = 0; +} + +LRfcommPort::~LRfcommPort() +{ + close(); +} + +void LRfcommPort::close() +{ + if (_sockRfcomm > 0) + { + ::close(_sockRfcomm); + _sockRfcomm = 0; + } +} + +bool LRfcommPort::open(LRfcommConfig* config) +{ + const int reuse = 1; + str2ba(config->gwAddress, (bdaddr_t*)_gwAddress); + _channel = config->channel; + + if (_channel == 0 || _gwAddress == 0 ) + { + D_NWLOG("\033[0m\033[0;31merror Bluetooth Address in LRfcommPort::open\033[0m\033[0;37m\n"); + DISPLAY("\033[0m\033[0;31m\nerror Bluetooth Address in LRfcommPort::open\033[0m\033[0;37m\n"); + return false; + } + + _sockRfcomm = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (_sockRfcomm < 0) + { + D_NWLOG("\033[0m\033[0;31merror Can't create socket in LRfcommPort::open\033[0m\033[0;37m\n"); + DISPLAY("\033[0m\033[0;31m\nerror Can't create socket in LRfcommPort::open\033[0m\033[0;37m\n"); + return false; + } + + setsockopt(_sockRfcomm, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + + struct sockaddr_rc addru = { 0 }; + addru.rc_family = AF_BLUETOOTH; + addru.rc_channel = _channel; + memcpy(&addru.rc_bdaddr, _gwAddress, 6); + + char bufgw[30]; + ba2str(&addru.rc_bdaddr, bufgw); + DISPLAY("GW MAC = %s RFCOMM CH = %d\n", bufgw, addru.rc_channel); + + // connect to server + errno = 0; + int status = connect(_sockRfcomm, (struct sockaddr *) &addru, sizeof(addru)); + if (status < 0) + { + D_NWLOG("\033[0m\033[0;31merror = %d Can't connect to GW in LRfcommPort::open\033[0m\033[0;37m\n", errno); + DISPLAY("\033[0m\033[0;31merror = %d Can't connect to GW Ble socket in LRfcommPort::open\033[0m\033[0;37m\n",errno); + close(); + return false; + } + return true; +} + +int LRfcommPort::unicast(const uint8_t* buf, uint32_t length) +{ + int status = ::write(_sockRfcomm, buf, length); + if (status < 0) + { + D_NWLOG("errno == %d in LRfcommPort::unicast\n", errno); + DISPLAY("errno == %d in LRfcommPort::unicast\n", errno); + } + else + { + D_NWLOG("sendto %-2d", _channel); + for (uint16_t i = 0; i < length; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } + D_NWLOG("\n"); + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34msendto %-2dch", _channel); + pos = strlen(sbuf); + for (uint16_t i = 0; i < length; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + } + return status; +} + +bool LRfcommPort::checkRecvBuf() +{ + uint8_t buf[2]; + if (::recv(_sockRfcomm, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0) + { + return true; + } + return false; +} + +int LRfcommPort::recv(uint8_t* buf, uint16_t length, bool flg) +{ + int flags = flg ? MSG_DONTWAIT : 0; + int status = ::recv(_sockRfcomm, buf, length, flags); + + if (status < 0 && errno != EAGAIN) + { + D_NWLOG("\033[0m\033[0;31merrno = %d in LRfcommPort::recv \033[0m\033[0;37m\n", errno); + DISPLAY("\033[0m\033[0;31merrno = %d in LRfcommPort::recv \033[0m\033[0;37m\n", errno); + } + else if (status > 0) + { + D_NWLOG("\nrecved "); + for (uint16_t i = 0; i < status; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } + D_NWLOG("\n"); + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34mrecved "); + pos = strlen(sbuf); + for (uint16_t i = 0; i < status; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + return status; + } + else + { + return 0; + } + return status; +} + +#endif + diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkRfcomm.h b/MQTTSNGateway/GatewayTester/src/LNetworkRfcomm.h new file mode 100644 index 0000000..d96a5f8 --- /dev/null +++ b/MQTTSNGateway/GatewayTester/src/LNetworkRfcomm.h @@ -0,0 +1,102 @@ +/************************************************************************************** + * Copyright (c) 2021, Tomoaki Yamaguchi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation + **************************************************************************************/ + +#ifndef NETWORKRFCOMM_H_ +#define NETWORKRFCOMM_H_ + +#ifdef RFCOMM + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SOCKET_MAXHOSTNAME 200 +#define SOCKET_MAXCONNECTIONS 5 +#define SOCKET_MAXRECV 500 +#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size + +#define STAT_UNICAST 1 +#define STAT_MULTICAST 2 + +using namespace std; + +namespace linuxAsyncClient +{ +/*======================================== + Class LRfcommPort + =======================================*/ +class LRfcommPort +{ + friend class LNetwork; +public: + LRfcommPort(); + virtual ~LRfcommPort(); + bool open(LRfcommConfig* config); + int unicast(const uint8_t* buf, uint32_t length); + int recv(uint8_t* buf, uint16_t len, bool nonblock); + bool checkRecvBuf(); + bool isUnicast(); + +private: + void close(); + + int _sockRfcomm; + uint8_t _gwAddress[6]; + uint8_t _channel; + bool _disconReq; + +}; + +#define NO_ERROR 0 +#define PACKET_EXCEEDS_LENGTH 1 +/*=========================================== + Class Network + ============================================*/ +class LNetwork: public LRfcommPort +{ +public: + LNetwork(); + ~LNetwork(); + + int broadcast(const uint8_t* payload, uint16_t payloadLen); + int unicast(const uint8_t* payload, uint16_t payloadLen); + void setGwAddress(void); + void resetGwAddress(void); + void setFixedGwAddress(void); + bool initialize(LRfcommConfig* config); + uint8_t* getMessage(int* len); + bool isBroadcastable(); + +private: + void setSleep(); + int readApiFrame(void); + + int _returnCode; + bool _sleepflg; + uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h + +}; + +} /* end of namespace */ +#endif /* RFCOMM */ +#endif /* NETWORKRFCOM_H_ */ diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkUdp.cpp b/MQTTSNGateway/GatewayTester/src/LNetworkUdp.cpp index 9471792..c0ac9e9 100644 --- a/MQTTSNGateway/GatewayTester/src/LNetworkUdp.cpp +++ b/MQTTSNGateway/GatewayTester/src/LNetworkUdp.cpp @@ -13,6 +13,7 @@ * Contributors: * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ +#ifdef UDP #include #include @@ -25,365 +26,426 @@ #include #include +#include "LMqttsnClientApp.h" #include "LNetworkUdp.h" #include "LTimer.h" #include "LScreen.h" -#include "LMqttsnClientApp.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 uint16_t getUint16(const uint8_t *pos); +extern uint32_t getUint32(const uint8_t *pos); +extern LScreen *theScreen; extern bool theClientMode; /*========================================= - Class LNetwork + Class LNetwork =========================================*/ -LNetwork::LNetwork(){ - _sleepflg = false; - resetGwAddress(); +LNetwork::LNetwork() +{ + _sleepflg = false; + resetGwAddress(); } -LNetwork::~LNetwork(){ +LNetwork::~LNetwork() +{ } -int LNetwork::broadcast(const uint8_t* xmitData, uint16_t dataLen){ - return LUdpPort::multicast(xmitData, (uint32_t)dataLen); +int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen) +{ + return LUdpPort::multicast(xmitData, (uint32_t) dataLen); } -int LNetwork::unicast(const uint8_t* xmitData, uint16_t dataLen){ - return LUdpPort::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo); +int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen) +{ + 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){ - *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; - } - - if(recvLen < 0){ - *len = recvLen; - return 0; - }else{ - if(_rxDataBuf[0] == 0x01){ - *len = getUint16(_rxDataBuf + 1 ); - }else{ - *len = _rxDataBuf[0]; - } - //if(recvLen != *len){ - // *len = 0; - // return 0; - //}else{ - return _rxDataBuf; - //} - } - } - return 0; + if (recvLen < 0) + { + *len = recvLen; + return 0; + } + else + { + if (_rxDataBuf[0] == 0x01) + { + *len = getUint16(_rxDataBuf + 1); + } + else + { + *len = _rxDataBuf[0]; + } + //if(recvLen != *len){ + // *len = 0; + // return 0; + //}else{ + return _rxDataBuf; + //} + } + } + return 0; } -void LNetwork::setGwAddress(void){ - _gwPortNo = _portNo; - _gwIpAddress = _ipAddress; +void LNetwork::setGwAddress(void) +{ + _gwPortNo = _portNo; + _gwIpAddress = _ipAddress; } -void LNetwork::setFixedGwAddress(void){ +void LNetwork::setFixedGwAddress(void) +{ _gwPortNo = LUdpPort::_gPortNo; _gwIpAddress = LUdpPort::_gIpAddr; } -void LNetwork::resetGwAddress(void){ - _gwIpAddress = 0; - _gwPortNo = 0; +void LNetwork::resetGwAddress(void) +{ + _gwIpAddress = 0; + _gwPortNo = 0; } - -bool LNetwork::initialize(LUdpConfig config){ - return LUdpPort::open(config); +bool LNetwork::initialize(LUdpConfig *config) +{ + return LUdpPort::open(config); } -void LNetwork::setSleep(){ - _sleepflg = true; +void LNetwork::setSleep() +{ + _sleepflg = true; } +bool LNetwork::isBroadcastable() +{ + return true; +} /*========================================= - Class udpStack + Class udpStack =========================================*/ -LUdpPort::LUdpPort(){ +LUdpPort::LUdpPort() +{ _disconReq = false; _sockfdUcast = -1; _sockfdMcast = -1; _castStat = 0; } -LUdpPort::~LUdpPort(){ +LUdpPort::~LUdpPort() +{ close(); } - -void LUdpPort::close(){ - if(_sockfdMcast > 0){ - ::close( _sockfdMcast); - _sockfdMcast = -1; - if(_sockfdUcast > 0){ - ::close( _sockfdUcast); - _sockfdUcast = -1; - } - } +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; - char loopch = 1; +bool LUdpPort::open(LUdpConfig *config) +{ + int optval = 0; - uint8_t sav = config.ipAddress[3]; - config.ipAddress[3] = config.ipAddress[0]; - config.ipAddress[0] = sav; - sav = config.ipAddress[2]; - config.ipAddress[2] = config.ipAddress[1]; - config.ipAddress[1] = sav; + uint8_t sav = config->ipAddress[3]; + config->ipAddress[3] = config->ipAddress[0]; + config->ipAddress[0] = sav; + sav = config->ipAddress[2]; + config->ipAddress[2] = config->ipAddress[1]; + config->ipAddress[1] = sav; - _gPortNo = htons(config.gPortNo); - _gIpAddr = getUint32((const uint8_t*)config.ipAddress); - _uPortNo = htons(config.uPortNo); + _gPortNo = htons(config->gPortNo); + _gIpAddr = getUint32((const uint8_t*) config->ipAddress); + _uPortNo = htons(config->uPortNo); - if( _gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0){ - return false; - } + if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0) + { + return false; + } - _sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0); - if (_sockfdUcast < 0){ - return false; - } + _sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0); + if (_sockfdUcast < 0) + { + return false; + } - setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + optval = 1; + setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = _uPortNo; - addr.sin_addr.s_addr = INADDR_ANY; + 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; - } + if (::bind(_sockfdUcast, (struct sockaddr*) &addr, sizeof(addr)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s ::bind() to unicast address\033[0m\033[0;37m\n", strerror(errno)); + return false; + } - _sockfdMcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (_sockfdMcast < 0){ - 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); + sockaddr_in addrm; + addrm.sin_family = AF_INET; + addrm.sin_port = _gPortNo; + addrm.sin_addr.s_addr = INADDR_ANY; - setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + optval = 1; + setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - if( ::bind ( _sockfdMcast, (struct sockaddr*)&addrm, sizeof(addrm)) <0){ - return false; - } + if (::bind(_sockfdMcast, (struct sockaddr*) &addrm, sizeof(addrm)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s ::bind() in UdpPort::open\033[0m\033[0;37m\n", strerror(errno)); + return false; + } - 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; - 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; + } - 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; + 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(){ - return ( _castStat == STAT_UNICAST); +bool LUdpPort::isUnicast() +{ + return (_castStat == STAT_UNICAST); } +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::unicast(const uint8_t* buf, uint32_t length, uint32_t ipAddress, uint16_t port ){ - struct sockaddr_in dest; - dest.sin_family = AF_INET; - dest.sin_port = port; - dest.sin_addr.s_addr = ipAddress; + int status = ::sendto(_sockfdUcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest)); + if (status < 0) + { + D_NWLOG("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"); - 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; + 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"); + } + } + return status; } +int LUdpPort::multicast(const uint8_t *buf, uint32_t length) +{ + struct sockaddr_in dest; + dest.sin_family = AF_INET; + dest.sin_port = _gPortNo; + dest.sin_addr.s_addr = _gIpAddr; -int LUdpPort::multicast( const uint8_t* buf, uint32_t length ){ - struct sockaddr_in dest; - dest.sin_family = AF_INET; - dest.sin_port = _gPortNo; - dest.sin_addr.s_addr = _gIpAddr; + int status = ::sendto(_sockfdMcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest)); + if (status < 0) + { + D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno); + return errno; + } + else + { + D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(_gPortNo)); - int status = ::sendto( _sockfdMcast, buf, length, 0, (const sockaddr*)&dest, sizeof(dest) ); - if( status < 0){ - D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno); - DISPLAY("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno); - return errno; - }else{ - 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)); + } D_NWLOG("\n"); - 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; - } + 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 LUdpPort::checkRecvBuf(){ - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 50000; // 50 msec +bool LUdpPort::checkRecvBuf() +{ + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 50000; // 50 msec - uint8_t buf[2]; - fd_set recvfds; - int maxSock = 0; + uint8_t buf[2]; + fd_set recvfds; + int maxSock = 0; - FD_ZERO(&recvfds); - FD_SET(_sockfdUcast, &recvfds); - FD_SET(_sockfdMcast, &recvfds); + FD_ZERO(&recvfds); + FD_SET(_sockfdUcast, &recvfds); + FD_SET(_sockfdMcast, &recvfds); - if(_sockfdMcast > _sockfdUcast){ - maxSock = _sockfdMcast; - }else{ - maxSock = _sockfdUcast; - } + if (_sockfdMcast > _sockfdUcast) + { + maxSock = _sockfdMcast; + } + else + { + maxSock = _sockfdUcast; + } - select(maxSock + 1, &recvfds, 0, 0, &timeout); + select(maxSock + 1, &recvfds, 0, 0, &timeout); - if(FD_ISSET(_sockfdUcast, &recvfds)){ - if( ::recv(_sockfdUcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0){ - _castStat = STAT_UNICAST; - return true; - } - }else if(FD_ISSET(_sockfdMcast, &recvfds)){ - if( ::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0){ - _castStat = STAT_MULTICAST; - return true; - } - } - _castStat = 0; - return false; + if (FD_ISSET(_sockfdUcast, &recvfds)) + { + if (::recv(_sockfdUcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0) + { + _castStat = STAT_UNICAST; + return true; + } + } + else if (FD_ISSET(_sockfdMcast, &recvfds)) + { + if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0) + { + _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 flags = flg ? MSG_DONTWAIT : 0; - return recvfrom (buf, len, flags, ipAddressPtr, portPtr ); +int LUdpPort::recv(uint8_t *buf, uint16_t len, bool flg, uint32_t *ipAddressPtr, uint16_t *portPtr) +{ + int flags = flg ? MSG_DONTWAIT : 0; + return recvfrom(buf, len, flags, ipAddressPtr, portPtr); } -int LUdpPort::recvfrom (uint8_t* buf, uint16_t length, int flags, uint32_t* ipAddressPtr, uint16_t* portPtr ){ - struct sockaddr_in sender; - int status; - socklen_t addrlen = sizeof(sender); - memset(&sender, 0, addrlen); +int LUdpPort::recvfrom(uint8_t *buf, uint16_t length, int flags, uint32_t *ipAddressPtr, uint16_t *portPtr) +{ + struct sockaddr_in sender; + int status; + socklen_t addrlen = sizeof(sender); + memset(&sender, 0, addrlen); - if(isUnicast()){ - status = ::recvfrom( _sockfdUcast, buf, length, flags, (struct sockaddr*)&sender, &addrlen ); - }else if(_castStat == STAT_MULTICAST){ - status = ::recvfrom( _sockfdMcast, buf, length, flags, (struct sockaddr*)&sender, &addrlen ); - }else{ - return 0; - } + if (isUnicast()) + { + D_NWLOG("Ucast "); + status = ::recvfrom(_sockfdUcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen); + } + 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 UdpPort::recvfrom \033[0m\033[0;37m\n", errno); - DISPLAY("\033[0m\033[0;31merrno == %d in UdpPort::recvfrom \033[0m\033[0;37m\n", errno); - }else if(status > 0){ - *ipAddressPtr = sender.sin_addr.s_addr; - *portPtr = sender.sin_port; - D_NWLOG("\nrecved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr)); - for(uint16_t i = 0; i < status ; i++){ - D_NWLOG(" %02x", *(buf + i)); - } - D_NWLOG("\n"); + if (status < 0 && errno != EAGAIN) + { + 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; + *portPtr = sender.sin_port; + D_NWLOG("recved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr)); + for (uint16_t i = 0; i < status; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } D_NWLOG("\n"); - if ( !theClientMode ) - { - char sbuf[SCREEN_BUFF_SIZE]; - int pos = 0; - sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr)); - pos = strlen(sbuf); - for(uint16_t i = 0; i < status ; i++){ - 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; + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", inet_ntoa(sender.sin_addr), htons(*portPtr)); + pos = strlen(sbuf); + for (uint16_t i = 0; i < status; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + return status; + } + else + { + return 0; + } + return status; } - +#endif diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkUdp.h b/MQTTSNGateway/GatewayTester/src/LNetworkUdp.h index 2430d37..31bfdf9 100644 --- a/MQTTSNGateway/GatewayTester/src/LNetworkUdp.h +++ b/MQTTSNGateway/GatewayTester/src/LNetworkUdp.h @@ -17,6 +17,8 @@ #ifndef NETWORKUDP_H_ #define NETWORKUDP_H_ +#ifdef UDP + #include #include #include @@ -27,8 +29,6 @@ #include #include -#include "LMqttsnClientApp.h" - #define SOCKET_MAXHOSTNAME 200 #define SOCKET_MAXCONNECTIONS 5 #define SOCKET_MAXRECV 500 @@ -49,7 +49,7 @@ public: LUdpPort(); virtual ~LUdpPort(); - bool open(LUdpConfig config); + bool open(LUdpConfig* config); int unicast(const uint8_t* buf, uint32_t length, uint32_t ipaddress, uint16_t port ); int multicast( const uint8_t* buf, uint32_t length ); @@ -87,8 +87,9 @@ public: void setGwAddress(void); void resetGwAddress(void); void setFixedGwAddress(void); - bool initialize(LUdpConfig config); + bool initialize(LUdpConfig* config); uint8_t* getMessage(int* len); + bool isBroadcastable(); private: void setSleep(); int readApiFrame(void); @@ -103,6 +104,6 @@ private: }; - } /* end of namespace */ +#endif /* UDP */ #endif /* NETWORKUDP_H_ */ diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkUdp6.cpp b/MQTTSNGateway/GatewayTester/src/LNetworkUdp6.cpp new file mode 100644 index 0000000..0d1167f --- /dev/null +++ b/MQTTSNGateway/GatewayTester/src/LNetworkUdp6.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "LMqttsnClientApp.h" +#include "LNetworkUdp6.h" +#include "LTimer.h" +#include "LScreen.h" + +using namespace std; +using namespace linuxAsyncClient; + +extern uint16_t getUint16(const uint8_t *pos); +extern uint32_t getUint32(const uint8_t *pos); +extern LScreen *theScreen; +extern bool theClientMode; +/*========================================= + Class LNetwork + =========================================*/ +LNetwork::LNetwork() +{ + _sleepflg = false; + resetGwAddress(); +} + +LNetwork::~LNetwork() +{ + +} + +int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen) +{ + return LUdp6Port::multicast(xmitData, (uint32_t) dataLen); +} + +int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen) +{ + return LUdp6Port::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo); +} + +uint8_t* LNetwork::getMessage(int *len) +{ + *len = 0; + if (checkRecvBuf()) + { + uint16_t recvLen = LUdp6Port::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo); + int diffAddr = memcmp(_ipAddress.s6_addr, _gwIpAddress.s6_addr, sizeof(_gwIpAddress.s6_addr)); + if (isUnicast() && diffAddr && (_portNo != _gwPortNo)) + { + return 0; + } + + if (recvLen < 0) + { + *len = recvLen; + return 0; + } + else + { + if (_rxDataBuf[0] == 0x01) + { + *len = getUint16(_rxDataBuf + 1); + } + else + { + *len = _rxDataBuf[0]; + } + return _rxDataBuf; + } + } + return 0; +} + +void LNetwork::setGwAddress(void) +{ + memcpy(_gwIpAddress.s6_addr, _ipAddress.s6_addr, sizeof(_gwIpAddress.s6_addr)); + _gwPortNo = _portNo; +} + +void LNetwork::resetGwAddress(void) +{ + memset(_gwIpAddress.s6_addr, 0, sizeof(_gwIpAddress.s6_addr)); + _gwPortNo = 0; +} + +bool LNetwork::initialize(LUdp6Config *config) +{ + return LUdp6Port::open(config); +} + +void LNetwork::setSleep() +{ + _sleepflg = true; +} + +bool LNetwork::isBroadcastable() +{ + return true; +} +/*========================================= + Class udp6Stack + =========================================*/ +LUdp6Port::LUdp6Port() +{ + _disconReq = false; + memset(_pollfds, 0, sizeof(_pollfds)); + _sock = 0; + _interface = NULL; + _gIpAddrStr = NULL; +} + +LUdp6Port::~LUdp6Port() +{ + close(); + if (_gIpAddrStr) + { + free(_gIpAddrStr); + } + if (_interface) + { + free(_interface); + } +} + +void LUdp6Port::close() +{ + for (int i = 0; i < 2; i++) + { + if (_pollfds[i].fd > 0) + { + ::close(_pollfds[i].fd); + _pollfds[i].fd = 0; + } + } +} + +bool LUdp6Port::open(LUdp6Config *config) +{ + int optval = 1; + int sock = 0; + uint32_t ifindex = 0; + sockaddr_in6 addr6; + + _gPortNo = htons(config->gPortNo); + _uPortNo = htons(config->uPortNo); + + if (_gPortNo == 0 || _uPortNo == 0) + { + return false; + } + + /* create a unicast socket */ + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) + { + return false; + } + + optval = 1; + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + if (strlen(config->interface) > 0) + { + ifindex = if_nametoindex(config->interface); +#ifdef __APPLE__ + setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex)); +#else + setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, config->interface, strlen(config->interface)); +#endif + } + + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = _uPortNo; + addr6.sin6_addr = in6addr_any; + + if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s ::bind() to unicast address\033[0m\033[0;37m\n", strerror(errno)); + return false; + } + _pollfds[0].fd = sock; + _pollfds[0].events = POLLIN; + + /* create a multicast socket */ + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) + { + return false; + } + + optval = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)); + + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = _gPortNo; + addr6.sin6_addr = in6addr_any; + + if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s ::bind() in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno)); + return false; + } + + + ipv6_mreq addrm; + addrm.ipv6mr_interface = ifindex; + inet_pton(AF_INET6, config->ipAddress, &addrm.ipv6mr_multiaddr); + if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno)); + close(); + return false; + } + optval = 1; + if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0) + { + D_NWLOG("\033[0m\033[0;31merror %s IPV6_MULTICAST_LOOP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno)); + close(); + return false; + } + _pollfds[1].fd = sock; + _pollfds[1].events = POLLIN; + _gIpAddr.sin6_family = AF_INET6; + _gIpAddr.sin6_port = _gPortNo; + memcpy(&_gIpAddr.sin6_addr, (const void*) &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr)); + _gIpAddrStr = strdup(config->ipAddress); + return true; +} + +int LUdp6Port::unicast(const uint8_t *buf, uint32_t length, in6_addr ipAddress, uint16_t port) +{ + struct sockaddr_in6 dest; + dest.sin6_family = AF_INET6; + dest.sin6_port = port; + memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr)); + + char addrBuf[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &dest.sin6_addr, addrBuf, INET6_ADDRSTRLEN); + D_NWLOG("unicast to [%s]:%-6u", addrBuf, htons(port)); + + int status = ::sendto(_pollfds[0].fd, buf, length, 0, (const sockaddr*) &dest, sizeof(dest)); + if (status < 0) + { + D_NWLOG(" errno = %d %s in Udp6Port::unicast\n", errno, strerror(errno)); + } + else + { + for (uint16_t i = 0; i < length; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } + D_NWLOG("\n"); + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34municast to [%s[:%-6u", addrBuf, htons(port)); + pos = strlen(sbuf); + for (uint16_t i = 0; i < length; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + } + return status; +} + +int LUdp6Port::multicast(const uint8_t *buf, uint32_t length) +{ + char sbuf[SCREEN_BUFF_SIZE]; + char portStr[8]; + sprintf(portStr, "%d", ntohs(_gPortNo)); + + int status = ::sendto(_pollfds[1].fd, buf, length, 0, (sockaddr*) &_gIpAddr, sizeof(_gIpAddr)); + if (status < 0) + { + D_NWLOG("multicast to [%s]:%-6s ", _gIpAddrStr, portStr); + D_NWLOG("\033[0m\033[0;31merrno = %d %s in Udp6Port::multicast\033[0m\033[0;37m\n", errno, strerror(errno)); + return errno; + } + else + { + D_NWLOG("multicast to [%s]:%-6s", _gIpAddrStr, portStr); + for (uint16_t i = 0; i < length; i++) + { + D_NWLOG(" %02x", *(buf + i)); + } + D_NWLOG("\n"); + + if (!theClientMode) + { + memset(sbuf, 0, SCREEN_BUFF_SIZE); + int pos = 0; + sprintf(sbuf, "\033[0;34mmulticast to [%s]:%-6s", _gIpAddrStr, portStr); + pos = strlen(sbuf); + for (uint16_t i = 0; i < length; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + return status; + } +} + +bool LUdp6Port::checkRecvBuf() +{ + uint8_t buf[2]; + + int cnt = poll(_pollfds, 2, 50); // Timeout 50m secs + if (cnt == 0) + { + return false; + } + + for (int i = 0; i < 2; i++) + { + if (_pollfds[i].revents & POLLIN) + { + if (::recv(_pollfds[i].fd, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0) + { + _sock = _pollfds[i].fd; + return true; + } + } + } + return false; + +} + +int LUdp6Port::recv(uint8_t *buf, uint16_t len, bool flg, in6_addr *ipAddressPtr, uint16_t *portPtr) +{ + int flags = flg ? MSG_DONTWAIT : 0; + return recvfrom(buf, len, flags, ipAddressPtr, portPtr); +} + +int LUdp6Port::recvfrom(uint8_t *buf, uint16_t length, int flags, in6_addr *ipAddressPtr, uint16_t *portPtr) +{ + struct sockaddr_in6 sender; + int status; + socklen_t addrlen = sizeof(sender); + memset(&sender, 0, addrlen); + char addrBuf[INET6_ADDRSTRLEN]; + + status = ::recvfrom(_sock, buf, length, flags, (struct sockaddr*) &sender, &addrlen); + + if (status < 0 && errno != EAGAIN) + { + D_NWLOG("\033[0m\033[0;31merrno == %d in Udp6Port::recvfrom \033[0m\033[0;37m\n", errno); + } + + if (status > 0) + { + inet_ntop(AF_INET6, &sender.sin6_addr, addrBuf, INET6_ADDRSTRLEN); + memcpy(ipAddressPtr->s6_addr, (const void*) sender.sin6_addr.s6_addr, sizeof(sender.sin6_addr.s6_addr)); + *portPtr = sender.sin6_port; + + if (!theClientMode) + { + char sbuf[SCREEN_BUFF_SIZE]; + int pos = 0; + sprintf(sbuf, "\033[0;34mrecv from [%s]:%-6u", addrBuf, htons(*portPtr)); + pos = strlen(sbuf); + for (uint16_t i = 0; i < status; i++) + { + sprintf(sbuf + pos, " %02x", *(buf + i)); + if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) + { + break; + } + pos += 3; + } + sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); + theScreen->display(sbuf); + } + return status; + } + else + { + return 0; + } + return status; +} + +bool LUdp6Port::isUnicast(void) +{ + return (_sock == _pollfds[0].fd && _sock > 0); +} +#endif /* UDP6 */ + diff --git a/MQTTSNGateway/GatewayTester/src/LNetworkUdp6.h b/MQTTSNGateway/GatewayTester/src/LNetworkUdp6.h new file mode 100644 index 0000000..3d6883a --- /dev/null +++ b/MQTTSNGateway/GatewayTester/src/LNetworkUdp6.h @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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_ */ diff --git a/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp b/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp index 78a84db..3632e0b 100644 --- a/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp +++ b/MQTTSNGateway/GatewayTester/src/LPublishManager.cpp @@ -44,6 +44,7 @@ LPublishManager::LPublishManager() _last = 0; _elmCnt = 0; _publishedFlg = SAVE_TASK_INDEX; + _autoConnectFlg = false; } LPublishManager::~LPublishManager() @@ -115,7 +116,10 @@ void LPublishManager::sendPublish(PubElement* elm) return; } - theClient->getGwProxy()->connect(); + if (_autoConnectFlg) + { + theClient->getGwProxy()->connect(); + } uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1]; uint8_t org = 0; @@ -310,6 +314,11 @@ void LPublishManager::checkTimeout(void) } } +void LPublishManager::setAutoConnectMode(bool flg) +{ + _autoConnectFlg = flg; +} + PubElement* LPublishManager::getElement(uint16_t msgId) { PubElement* elm = _first; diff --git a/MQTTSNGateway/GatewayTester/src/LPublishManager.h b/MQTTSNGateway/GatewayTester/src/LPublishManager.h index 6085218..6520733 100644 --- a/MQTTSNGateway/GatewayTester/src/LPublishManager.h +++ b/MQTTSNGateway/GatewayTester/src/LPublishManager.h @@ -70,6 +70,7 @@ public: void sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType); bool isDone(void); bool isMaxFlight(void); + void setAutoConnectMode(bool); private: PubElement* getElement(uint16_t msgId); PubElement* getElement(const char* topicName); @@ -84,7 +85,8 @@ private: PubElement* _last; uint8_t _elmCnt; uint8_t _publishedFlg; + uint8_t _autoConnectFlg; }; - + } /* tomyAsyncClient */ #endif /* PUBLISHMANAGER_H_ */ diff --git a/MQTTSNGateway/GatewayTester/src/LSubscribeManager.cpp b/MQTTSNGateway/GatewayTester/src/LSubscribeManager.cpp index 5158003..8630c29 100644 --- a/MQTTSNGateway/GatewayTester/src/LSubscribeManager.cpp +++ b/MQTTSNGateway/GatewayTester/src/LSubscribeManager.cpp @@ -67,7 +67,9 @@ void LSubscribeManager::onConnect(void) { if ( theOnPublishList[i].type == MQTTSN_TOPIC_TYPE_PREDEFINED) { - subscribe(theOnPublishList[i].id, theOnPublishList[i].pubCallback, theOnPublishList[i].qos); + subscribePredefinedId(theOnPublishList[i].id, + theOnPublishList[i].pubCallback, + theOnPublishList[i].qos); } else { @@ -122,6 +124,7 @@ void LSubscribeManager::send(SubElement* elm) { return; } + uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1]; if (elm->topicType == MQTTSN_TOPIC_TYPE_PREDEFINED) { @@ -169,7 +172,7 @@ void LSubscribeManager::subscribe(const char* topicName, TopicCallback onPublish send(elm); } -void LSubscribeManager::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos) +void LSubscribeManager::subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos) { SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, 0, MQTTSN_TOPIC_TYPE_PREDEFINED, topicId, qos, onPublish); send(elm); @@ -262,7 +265,9 @@ void LSubscribeManager::responce(const uint8_t* msg) } else { - DISPLAY("\033[0m\033[0;31m UNSUBACK Invalid messageId. \033[0m\033[0;37m\n\n"); + DISPLAY( + "\033[0m\033[0;31m UNSUBACK Invalid messageId=%04x. \033[0m\033[0;37m\n\n", + msgId); } } } diff --git a/MQTTSNGateway/GatewayTester/src/LSubscribeManager.h b/MQTTSNGateway/GatewayTester/src/LSubscribeManager.h index 1db3617..6c56055 100644 --- a/MQTTSNGateway/GatewayTester/src/LSubscribeManager.h +++ b/MQTTSNGateway/GatewayTester/src/LSubscribeManager.h @@ -56,7 +56,7 @@ public: ~LSubscribeManager(); void onConnect(void); void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos); - void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos); + void subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos); void unsubscribe(const char* topicName); void unsubscribe(uint16_t topicId); void responce(const uint8_t* msg); diff --git a/MQTTSNGateway/GatewayTester/src/LTaskManager.cpp b/MQTTSNGateway/GatewayTester/src/LTaskManager.cpp index 1ec298b..b8ce3d6 100644 --- a/MQTTSNGateway/GatewayTester/src/LTaskManager.cpp +++ b/MQTTSNGateway/GatewayTester/src/LTaskManager.cpp @@ -14,7 +14,6 @@ * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ - #include #include @@ -32,148 +31,153 @@ extern LMqttsnClient* theClient; extern LScreen* theScreen; extern bool theClientMode; /*===================================== - TaskManager + TaskManager ======================================*/ -LTaskManager::LTaskManager(void){ - _tasks = 0; - _tests = 0; - _index = 0; +LTaskManager::LTaskManager(void) +{ + _tasks = 0; + _tests = 0; + _index = 0; } -LTaskManager::~LTaskManager(void){ - +LTaskManager::~LTaskManager(void) +{ + } -void LTaskManager::add(TaskList* task){ +void LTaskManager::add(TaskList* task) +{ _tasks = task; } -void LTaskManager::add(TestList* test){ +void LTaskManager::add(TestList* test) +{ _tests = test; } -void LTaskManager::run(void){ - int i = 0; - char c = 0; - bool cancelFlg = false; - TestList test = {0}; - TaskList task = {0}; +void LTaskManager::run(void) +{ + int i = 0; + char c = 0; + bool cancelFlg = false; + TestList test = { 0 }; + TaskList task = { 0 }; - if ( !theClientMode ) - { - theClient->getGwProxy()->getMessage(); + if (!theClientMode) + { + theClient->getGwProxy()->getMessage(); - for (i = 0; _tests[i].testTask > test.testTask; i++) - { - PROMPT("Execute \"%s\" ? ( y/n ) : ", _tests[i].testLabel); - while (true) - { - if (CHECKKEYIN(&c)) - { - if ( toupper(c) == 'N' ) - { + for (i = 0; _tests[i].testTask > test.testTask; i++) + { + PROMPT("Execute \"%s\" ? ( y/n ) : ", _tests[i].testLabel); + while (true) + { + if (CHECKKEYIN(&c)) + { + if (toupper(c) == 'N') + { - DISPLAY("\033[0m\033[0;32m\n**** %s is canceled ****\033[0m\033[0;37m\n\n", _tests[i].testLabel); - theScreen->prompt(""); - cancelFlg = true; - break; - } - else if ( toupper(c) == 'Y' ) - { - DISPLAY("\033[0m\033[0;32m\n\n**** %s start ****\033[0m\033[0;37m\n", _tests[i].testLabel); - theScreen->prompt(""); - (_tests[i].testTask)(); - cancelFlg = false; - break; - } - } - else - { - theClient->getGwProxy()->getMessage(); - } - } + DISPLAY("\033[0m\033[0;32m\n**** %s is canceled ****\033[0m\033[0;37m\n\n", _tests[i].testLabel); + theScreen->prompt(""); + cancelFlg = true; + break; + } + else if (toupper(c) == 'Y') + { + DISPLAY("\033[0m\033[0;32m\n\n**** %s start ****\033[0m\033[0;37m\n", _tests[i].testLabel); + theScreen->prompt(""); + (_tests[i].testTask)(); + cancelFlg = false; + break; + } + } + else + { + theClient->getGwProxy()->getMessage(); + } + } - while ( true ) - { - do - { - theClient->getGwProxy()->getMessage(); - } - while(theClient->getPublishManager()->isMaxFlight() || - !theClient->getSubscribeManager()->isDone() || - !theClient->getRegisterManager()->isDone()); + while (true) + { + do + { + theClient->getGwProxy()->getMessage(); + } + while (theClient->getPublishManager()->isMaxFlight() || !theClient->getSubscribeManager()->isDone() + || !theClient->getRegisterManager()->isDone()); - if (theClient->getPublishManager()->isDone()) - { - break; - } - } - if ( !cancelFlg ) - { - DISPLAY("\033[0m\033[0;32m\n**** %s complete ****\033[0m\033[0;37m\n\n", _tests[i].testLabel); - } - } - DISPLAY("\033[0m\033[0;32m\n\n######### All tests complete! ###########\033[0m\033[0;37m\n\n"); - } - else - { - while (true) - { - theClient->getGwProxy()->getMessage(); - for (_index = 0; _tasks[_index].callback > task.callback; _index++) - { - if ((_tasks[_index].prevTime + _tasks[_index].interval <= time(NULL)) && - _tasks[_index].count == 0) - { - _tasks[_index].prevTime = time(NULL); - (_tasks[_index].callback)(); - } - } + if (theClient->getPublishManager()->isDone()) + { + break; + } + } + if (!cancelFlg) + { + DISPLAY("\033[0m\033[0;32m\n**** %s complete ****\033[0m\033[0;37m\n\n", _tests[i].testLabel); + } + } + DISPLAY("\033[0m\033[0;32m\n\n######### All tests complete! ###########\033[0m\033[0;37m\n\n"); + } + else + { + while (true) + { + theClient->getGwProxy()->getMessage(); + for (_index = 0; _tasks[_index].callback > task.callback; _index++) + { + if ((_tasks[_index].prevTime + _tasks[_index].interval <= time(NULL)) && _tasks[_index].count == 0) + { + _tasks[_index].prevTime = time(NULL); + (_tasks[_index].callback)(); + } + } - do - { - theClient->getGwProxy()->getMessage(); - } - while(theClient->getPublishManager()->isMaxFlight() || - !theClient->getSubscribeManager()->isDone() || - !theClient->getRegisterManager()->isDone()); + do + { + theClient->getGwProxy()->getMessage(); + } + while (theClient->getPublishManager()->isMaxFlight() || !theClient->getSubscribeManager()->isDone() + || !theClient->getRegisterManager()->isDone()); - if (theClient->getPublishManager()->isDone()) - { - break; - } - } - } + if (theClient->getPublishManager()->isDone()) + { + break; + } + } + } } -uint8_t LTaskManager::getIndex(void){ - return _index; +uint8_t LTaskManager::getIndex(void) +{ + return _index; } -void LTaskManager::done(uint8_t index){ - if (_tasks ) - { - if (_tasks[index].count > 0) - { - _tasks[index].count--; - } - } - if (_tests ) - { - if (_tests[index].count > 0) - { - _tests[index].count--; - } - } +void LTaskManager::done(uint8_t index) +{ + if (_tasks) + { + if (_tasks[index].count > 0) + { + _tasks[index].count--; + } + } + if (_tests) + { + if (_tests[index].count > 0) + { + _tests[index].count--; + } + } } -void LTaskManager::suspend(uint8_t index){ - if ( _tasks ) - { - _tasks[index].count++; - } - if ( _tests ) - { - _tests[index].count++; - } +void LTaskManager::suspend(uint8_t index) +{ + if (_tasks) + { + _tasks[index].count++; + } + if (_tests) + { + _tests[index].count++; + } } diff --git a/MQTTSNGateway/Makefile b/MQTTSNGateway/Makefile deleted file mode 100644 index 7e096e9..0000000 --- a/MQTTSNGateway/Makefile +++ /dev/null @@ -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 - - \ No newline at end of file diff --git a/MQTTSNGateway/README.md b/MQTTSNGateway/README.md index c7a791c..21f9d4e 100644 --- a/MQTTSNGateway/README.md +++ b/MQTTSNGateway/README.md @@ -1,145 +1,211 @@ # MQTT-SN Transparent / Aggregating Gateway +MQTT-SN requires a MQTT-SN Gateway which acts as a protocol converter to convert MQTT-SN messages to MQTT messages. +MQTT-SN client over SensorNetwork can not communicate directly with MQTT broker(TCP/IP). +This Gateway can run as a transparent or aggregating Gateway by specifying the gateway.conf. +### step1. Build the gateway +copy and expand source code then, +``` +$ 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|dtls|dtls6] +``` -**MQTT-SN** requires a MQTT-SN Gateway which acts as a protocol converter to convert **MQTT-SN messages to MQTT messages**. MQTT-SN client over SensorNetwork can not communicate directly with MQTT broker(TCP/IP). -This Gateway can run as a transparent or aggregating Gateway by specifying the gateway.conf. +MQTT-SNGateway and MQTT-SNLogmonitor (executable programs) are built in ./bin directory. -### **step1. Build the gateway** -```` -$ git clone -b develop https://github.com/eclipse/paho.mqtt-sn.embedded-c -$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway -$ make [SENSORNET={udp6|xbee|loralink}] -$ make install -$ make clean -```` -By default, a gateway for UDP is built. -In order to create a gateway for UDP6, XBee or LoRaLink, SENSORNET argument is required. - -MQTT-SNGateway, MQTT-SNLogmonitor and *.conf files are copied into ../ directory. -If you want to install the gateway into specific directories, enter a command line as follows: -```` -$ make install INSTALL_DIR=/path/to/your_directory CONFIG_DIR=/path/to/your_directory -```` +### step2. Execute the Gateway. - -### **step2. Execute the Gateway.** - -```` -$ cd ../../ -$ ./MQTT-SNGateway [-f Config file name] -```` +``` +$ cd bin +$ ./MQTT-SNGateway +``` If you get the error message as follows: -```` -what(): RingBuffer can't create a shared memory. -Aborted (core dumped) -```` + +RingBuffer can't create a shared memory. ABORT Gateway!!! You have to start using sudo command only once for the first time. -```` -$ sudo ./MQTT-SNGateway [-f Config file name] -```` - -### **How to Change the configuration of the gateway** -**../gateway.conf** Contents are follows: - -
    
+```
+$ sudo ./MQTT-SNGateway 
+```
+## Contents of the gateway configuration file
+**gateway.conf** is in bin directory.  It's contents are follows: 
 
+```
+#**************************************************************************
+# Copyright (c) 2016-2021, Tomoaki Yamaguchi
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+# The Eclipse Public License is available at
+#    http://www.eclipse.org/legal/epl-v10.html
+# and the Eclipse Distribution License is available at
+#   http://www.eclipse.org/org/documents/edl-v10.php.
+#***************************************************************************
+#
 # config file of MQTT-SN Gateway
 #
 
-BrokerName=mqtt.eclipse.org
+GatewayID=1
+GatewayName=PahoGateway-01
+MaxNumberOfClients=30
+KeepAlive=60
+#LoginID=your_ID
+#Password=your_Password
+
+BrokerName=mqtt.eclipseprojects.io
 BrokerPortNo=1883
 BrokerSecurePortNo=8883
+```
+**GatewayID** is a gateway ID which  used by GWINFO message.    
+**GatewayName** is a name of the gateway.    
+**MaxNumberOfClients** is a maxmum number of clients. Clients are dynamically allocated.    
+**KeepAlive** is KeepAlive time in seconds.   
+**LoginID** is used by CONNECT message.  
+**Password** is used by CONNECT message.    
+**BrokerName**is a domain name or IP address of a broker.    
+**BrokerPortNo** is a broker's port no.    
+**BrokerSecurePortNo** is a broker's port no of TLS connection.    
+```
+#
+# CertsKey for TLS connections to a broker
+#
 
+#RootCAfile=/etc/ssl/certs/ca-certificates.crt
+#RootCApath=/etc/ssl/certs/
+#CertsKey=/path/to/certKey.pem
+#PrivateKey=/path/to/privateKey.pem
+```
+**RootCAfile** is a CA file name.    
+**RootCApath** is a CA path. **SSL_CTX_load_verify_locations(ctx, CAfile, CApath)** function requires these parameters.        
+**CertsKey** is a certificate pem file.    
+**PrivateKey** is a private key pem file.   
+Clients can connect to the broker via TLS by setting '**Secure Connection**' for each client in the client conf file.   
+```
 #
 # When AggregatingGateway=YES or ClientAuthentication=YES,
 # All clients must be specified by the ClientList File  
 #
 
-ClientAuthentication=NO
 AggregatingGateway=NO
 QoS-1=NO
 Forwarder=NO
-
-#ClientsList=/path/to/your_clients.conf
-
 PredefinedTopic=NO
-#PredefinedTopicList=/path/to/your_predefinedTopic.conf
+ClientAuthentication=NO
 
-#RootCAfile=/etc/ssl/certs/ca-certificates.crt
-#RootCApath=/etc/ssl/certs/
-#CertsFile=/path/to/certKey.pem
-#PrivateKey=/path/to/privateKey.pem
-
-GatewayID=1
-GatewayName=PahoGateway-01
-KeepAlive=900
-#LoginID=your_ID
-#Password=your_Password
+ClientsList=/path/to/your_clients.conf
+PredefinedTopicList=/path/to/your_predefinedTopic.conf
+```
+The gateway runs as a aggregating gateway when **AggregatingGateway** is 'YES'.   
+If **QoS-1** is 'YES, the gateway prepares a proxy for the QoS-1 client. QoS-1 client has a 'QoS-1' parameter in a clients.conf file. For QoS-1 clients, set the QoS-1 parameters in the clients.conf file.
+If **Forwarder** is 'YES', the gateway prepare a forwarder agent.   
+If **ClientAuthentication** is 'YES', the client cannot connect unless it is registered in the clients.conf file.  
+**ClientsList** defines clients and those address so on.    
+**PredefinedTopicList** file defines Predefined Topic.    
 
 
-# UDP
+```
+#==============================
+#  SensorNetworks parameters
+#==============================
+#
+# UDP | DTLS 
+# 
+
 GatewayPortNo=10000
-MulticastIP=225.1.1.1
 MulticastPortNo=1883
-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
-GatewayUDP6Bind=FFFF:FFFE::1 
-GatewayUDP6Port=10000
-GatewayUDP6Broadcast=FF02::1
-GatewayUDP6If=wpan0
-GatewayUDP6Hops=1
+GatewayIPv6PortNo=10000
+MulticastIPv6PortNo=1883
+MulticastIPv6=ff1e:feed:caca:dead::feed:caca:dead
+MulticastIPv6If=wlp4s0
+MulticastHops=1
+```
+**GatewayIPv6PortNo** is a unicast port no of the gateway.
+**MulticastIPv6PortNo** and **MulticastIPv6** are for GWSEARCH messages. Set the Global scope Multicast address so that the Global address is used for sending GWINFO.   
+Clients can get the gateway address (Gateway IPv6 address and GatewayPortNo) from GWINFO message by means of std::recvfrom(). 
+**MulticastIPv6If** is a  multicast interface name.    
+**MulticastHops** is a multicast hops.    
+```
+#
+# DTLS | DTLS6  DTLS CertsKey  
+#
 
+DtlsCertsKey=/etc/ssl/certs/gateway.pem
+DtlsPrivKey=/etc/ssl/private/privkey.pem
+```
+**DtlsCertsKey** is a certs Key pem file for DTLS connection.        
+**DtlsPrivKey** is a private key pem file for DTLS connection.    
+```
+#
 # XBee
+#
+
 Baudrate=38400
 SerialDevice=/dev/ttyUSB0
 ApiMode=2
+```
+**Baudrate** is a baudrate of xbee.    
+```
+#
+# LoRaLink
+#
 
-#LoRaLink
 BaudrateLoRaLink=115200
-DeviceRxLoRaLink=/dev/ttyLoRaLinkRx
-DeviceTxLoRaLink=/dev/ttyLoRaLinkTx
+DeviceRxLoRaLink=/dev/loralinkRx
+DeviceTxLoRaLink=/dev/loralinkTx
+```
+https://github.com/ty4tw/MQTT-SN-LoRa    
 
+```
+#
+# Bluetooth RFCOMM
+#
+
+RFCOMMAddress=60:57:18:06:8B:72.*
+```
+**RFCOMMAddress** is a bluetooth mac address and channel. channel should be * for the gateway.
+```
+#
 # LOG
-ShearedMemory=NO;
+#
 
-
+ShearedMemory=NO +``` -**BrokerName** to specify a domain name of the Broker, and **BrokerPortNo** is a port No of the Broker. **BrokerSecurePortNo** is for TLS connection. -**MulticastIP** and **MulticastPortNo** is a multicast address for GWSEARCH messages. Gateway is waiting GWSEARCH and when receiving it send GWINFO message via MulticastIP address. Clients can get the gateway address (Gateway IP address and **GatewayPortNo**) from GWINFO message by means of std::recvfrom(). -Client should know the MulticastIP and MulticastPortNo to send a SEARCHGW message. -**GatewayId** is used by GWINFO message. -**KeepAlive** is a duration of ADVERTISE message in seconds. -when **AggregatingGateway** or **ClientAuthentication** is **YES**, All clients which connect to the gateway must be declared by a **ClientsList** file. -Format of the file is ClientId and SensorNetwork Address. e.g. IP address and Port No etc, in CSV. more detail see clients.conf. -When **QoS-1** is **YES**, QoS-1 PUBLISH is available. All clients which send QoS-1 PUBLISH must be specified by Client.conf file. -When **PredefinedTopic** is **YES**, **Pre-definedTopicId**s specified by **PredefinedTopicList** are effective. This file defines Pre-definedTopics of the clients. In this file, ClientID,TopicName and TopicID are declared in CSV format. -When **Forwarder** is **YES**, Forwarder Encapsulation Message is available. Connectable Forwarders must be declared by a **ClientsList** file. - -### ** How to monitor the gateway from remote. ** +### How to monitor the gateway from a remote terminal. Change gateway.conf as follows: ``` # LOG ShearedMemory=YES; -```` - -Restart the gateway with sudo only once to create shared memories. - +``` +Restart the gateway with sudo only once to create shared memories. open ssh terminal and execute LogMonitor. - -`$ ./MQTT-SNLogmonitor` - +``` + $ cd bin + $ ./MQTT-SNLogmonitor +``` Now you can get the Log on your terminal. -## ** Tips ** -Uncomment the line 62, 63 in MQTTSNDefines.h then you can get more precise logs. +##### Tips +Use compiler definitions then you can get more precise logs. +**-DDEBUG_NW** is a flag for debug logs of Sensor network. +**-DDEBUG_MQTTSN** is a flag for debug logs of MQTT-SN message haandling. +One or both flags can be specified. + ``` -/*================================= - * Log controls - ==================================*/ -//#define DEBUG // print out log for debug -//#define DEBUG_NWSTACK // print out SensorNetwork log +./build.sh udp -DDEBUG -DDEBUG_NW ``` - - - diff --git a/MQTTSNGateway/build.sh b/MQTTSNGateway/build.sh new file mode 100755 index 0000000..6dc49c0 --- /dev/null +++ b/MQTTSNGateway/build.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +build () { + echo "Start building MQTT-SN Gateway $1" + + cd $SCRIPT_DIR/.. + BDIR='build.gateway' + if [ ! -d ./$BDIR ]; then + mkdir $BDIR + fi + cd $BDIR + cmake .. -DSENSORNET=$1 -DDEFS="${2} ${3}" + make MQTTSNPacket + make MQTT-SNGateway + make MQTT-SNLogmonitor + cd ../MQTTSNGateway + cp *.conf ./bin/ +} + +SCRIPT_DIR=$(cd $(dirname $0); pwd) + +if [ $1 == "udp" ] ; then + build $1 $2 $3 +elif [ $1 == "udp6" ] ; then + build $1 $2 $3 +elif [ $1 == "xbee" ] ; then + build $1 $2 $3 +elif [ $1 == "loralink" ]; then + build $1 $2 $3 +elif [ $1 == "rfcomm" ] ; then + build $1 $2 $3 +elif [ $1 == "dtls" ] ; then + build $1 $2 $3 +elif [ $1 == "dtls6" ] ; then + build dtls "${2} ${3} -DDTLS6" +elif [ $1 == "clean" ] ; then + rm -rf ../builg.gateway +else + echo "Usage: build.sh [ udp | udp6 | xbee | loralink | rfcomm | dtls | dtls6 | clean]" +fi + + diff --git a/MQTTSNGateway/clients.conf b/MQTTSNGateway/clients.conf index a2c005c..d91d2a5 100644 --- a/MQTTSNGateway/clients.conf +++ b/MQTTSNGateway/clients.conf @@ -15,10 +15,10 @@ # Lines bigning with # are comment line. # ClientId, SensorNetAddress, "unstableLine", "secureConnection" # in case of UDP, SensorNetAddress format is IPAddress: port no. -# if the SensorNetwork is not stable, write "unstableLine". -# if Broker's Connection is SSL, write "secureConnection". -# if the client is a forwarder, "forwarder" is required. -# if the client send PUBLISH QoS-1, "QoS-1" is required. +# if the SensorNetwork is not stable, specify "unstableLine". +# if Broker's Connection is TLS, specify "secureConnection". +# if the client is a forwarder,specify "forwarder". +# if the client send PUBLISH QoS-1, specify "QoS-1". # # Ex: # #Client List @@ -31,6 +31,17 @@ # # SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function. # +# UDP6 (IPv6 UDP) [IPv6 address]:PortNo +# RFCOMM Device_address.channel (1-30) +# XBee FFFFFFFFFFFFFFFF 8bytes Hex +# LoRaLink 1-254 +# +# +# This is a sample of UDP. +# +# REWRITE ALL ACCORDING TO YOUR CLIENTS. +# + GatewayTester, 172.16.1.11:20020 ClientPUB,172.16.1.11:2010 Client01,172.16.1.11:12001 diff --git a/MQTTSNGateway/gateway.conf b/MQTTSNGateway/gateway.conf index 73f110e..b3ad2a4 100644 --- a/MQTTSNGateway/gateway.conf +++ b/MQTTSNGateway/gateway.conf @@ -1,5 +1,5 @@ #************************************************************************** -# Copyright (c) 2016-2019, Tomoaki Yamaguchi +# Copyright (c) 2016-2021, Tomoaki Yamaguchi # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 @@ -14,55 +14,95 @@ # config file of MQTT-SN Gateway # -BrokerName=mqtt.eclipse.org +GatewayID=1 +GatewayName=PahoGateway-01 +MaxNumberOfClients=30 +KeepAlive=60 +#LoginID=your_ID +#Password=your_Password + +BrokerName=mqtt.eclipseprojects.io BrokerPortNo=1883 BrokerSecurePortNo=8883 +# +# CertsKey for TLS connections to a broker +# + +#RootCAfile=/etc/ssl/certs/ca-certificates.crt +#RootCApath=/etc/ssl/certs/ +#CertsKey=/path/to/certKey.pem +#PrivateKey=/path/to/privateKey.pem + # # When AggregatingGateway=YES or ClientAuthentication=YES, # All clients must be specified by the ClientList File # -ClientAuthentication=NO AggregatingGateway=NO QoS-1=NO Forwarder=NO - -#ClientsList=/path/to/your_clients.conf - PredefinedTopic=NO -#PredefinedTopicList=/path/to/your_predefinedTopic.conf +ClientAuthentication=NO -#RootCAfile=/etc/ssl/certs/ca-certificates.crt -#RootCApath=/etc/ssl/certs/ -#CertsFile=/path/to/certKey.pem -#PrivateKey=/path/to/privateKey.pem - -GatewayID=1 -GatewayName=PahoGateway-01 -KeepAlive=900 -#LoginID=your_ID -#Password=your_Password +ClientsList=/path/to/your_clients.conf +PredefinedTopicList=/path/to/your_predefinedTopic.conf -# UDP +#============================== +# SensorNetworks parameters +#============================== +# +# UDP | DTLS +# + GatewayPortNo=10000 -MulticastIP=225.1.1.1 MulticastPortNo=1883 +MulticastIP=225.1.1.1 MulticastTTL=1 -# UDP6 -GatewayUDP6Bind=FFFF:FFFE::1 -GatewayUDP6Port=10000 -GatewayUDP6Broadcast=FF02::1 -GatewayUDP6If=wpan0 -GatewayUDP6Hops=1 +# +# UDP6 | DTLS6 +# +GatewayIPv6PortNo=10000 +MulticastIPv6PortNo=1883 +MulticastIPv6=ff1e:feed:caca:dead::1 +MulticastIPv6If=wlp4s0 +MulticastHops=1 + +# +# DTLS | DTLS6 +# + +DtlsCertsKey=/etc/ssl/certs/gateway.pem +DtlsPrivKey=/etc/ssl/private/privkey.pem + +# # XBee +# + Baudrate=38400 SerialDevice=/dev/ttyUSB0 ApiMode=2 -# LOG -ShearedMemory=NO; +# +# LoRaLink +# + +BaudrateLoRaLink=115200 +DeviceRxLoRaLink=/dev/loralinkRx +DeviceTxLoRaLink=/dev/loralinkTx + +# +# Bluetooth RFCOMM +# + +RFCOMMAddress=60:57:18:06:8B:72.* + +# +# LOG +# + +ShearedMemory=NO diff --git a/MQTTSNGateway/src/CMakeLists.txt b/MQTTSNGateway/src/CMakeLists.txt new file mode 100644 index 0000000..2e81bc1 --- /dev/null +++ b/MQTTSNGateway/src/CMakeLists.txt @@ -0,0 +1,151 @@ +#******************************************************************************* +# Copyright (c) 2022 a1lu +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# and Eclipse Distribution License v1.0 which accompany this distribution. +# +# The Eclipse Public License is available at +# http://www.eclipse.org/legal/epl-v10.html +# and the Eclipse Distribution License is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# Contributors: +# a1lu - initial version +# ty4tw - modify +#*******************************************************************************/ +PROJECT(mqtt-sn-gateway CXX) + +SET(GW_VERSION_MAJOR 1) +SET(GW_VERSION_MINOR 5) +SET(GW_VERSION_PATCH 1) + +SET(GATEWAY_VERSION ${GW_VERSION_MAJOR}.${GW_VERSION_MINOR}.${GW_VERSION_PATCH}) +MESSAGE(STATUS "VERSION : ${GATEWAY_VERSION}") + +configure_file( MQTTSNGWVersion.h.in ${CMAKE_CURRENT_SOURCE_DIR}/MQTTSNGWVersion.h ) + +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../bin) +SET(CMAKE_CXX_STANDARD 11) + +SET(OS linux) + +IF(NOT DEFINED SENSORNET) + SET(SENSORNET udp) +ENDIF() +MESSAGE(STATUS "SENSORNET: " ${SENSORNET}) + +ADD_DEFINITIONS(${DEFS}) +MESSAGE(STATUS "Definitions: " ${DEFS}) + +ADD_LIBRARY(mqtt-sngateway_common + MQTTGWConnectionHandler.cpp + MQTTGWPacket.cpp + MQTTGWPublishHandler.cpp + MQTTGWSubscribeHandler.cpp + MQTTSNGateway.cpp + MQTTSNGWBrokerRecvTask.cpp + MQTTSNGWBrokerSendTask.cpp + MQTTSNGWClient.cpp + MQTTSNGWClientRecvTask.cpp + MQTTSNGWClientSendTask.cpp + MQTTSNGWConnectionHandler.cpp + MQTTSNGWLogmonitor.cpp + MQTTSNGWPacket.cpp + MQTTSNGWPacketHandleTask.cpp + MQTTSNGWProcess.cpp + MQTTSNGWPublishHandler.cpp + MQTTSNGWSubscribeHandler.cpp + MQTTSNGWEncapsulatedPacket.cpp + MQTTSNGWForwarder.cpp + MQTTSNGWQoSm1Proxy.cpp + MQTTSNGWAdapter.cpp + MQTTSNGWAggregater.cpp + MQTTSNGWClientList.cpp + MQTTSNGWTopic.cpp + MQTTSNGWAdapterManager.cpp + MQTTSNAggregateConnectionHandler.cpp + MQTTSNGWMessageIdTable.cpp + MQTTSNGWAggregateTopicTable.cpp + ${OS}/${SENSORNET}/SensorNetwork.cpp + ${OS}/${SENSORNET}/SensorNetwork.h + ${OS}/Timer.cpp + ${OS}/Timer.h + ${OS}/Network.cpp + ${OS}/Network.h + ${OS}/Threading.cpp + ${OS}/Threading.h + ) + +# linux +link_directories("/usr/local/lib") + +# Mac +link_directories("/usr/local/opt/openssl/lib") + + +TARGET_INCLUDE_DIRECTORIES(mqtt-sngateway_common + PUBLIC + . + ${OS} + ${OS}/${SENSORNET} + ../../MQTTSNPacket/src + /usr/local/include + /usr/local/opt/openssl/include + ) + +IF(SENSORNET MATCHES "rfcomm") + +TARGET_LINK_LIBRARIES(mqtt-sngateway_common + PRIVATE + MQTTSNPacket + pthread + ssl + crypto + bluetooth + ) +ELSE() + +TARGET_LINK_LIBRARIES(mqtt-sngateway_common + PRIVATE + MQTTSNPacket + pthread + ssl + crypto + ) + +ENDIF() + +ADD_EXECUTABLE(MQTT-SNGateway + mainGateway.cpp + ) + +TARGET_LINK_LIBRARIES(MQTT-SNGateway + mqtt-sngateway_common + ) + +ADD_EXECUTABLE(MQTT-SNLogmonitor + mainLogmonitor.cpp + ) + +TARGET_LINK_LIBRARIES(MQTT-SNLogmonitor + mqtt-sngateway_common + ) + +ADD_EXECUTABLE(testPFW + tests/mainTestProcess.cpp + tests/TestProcess.cpp + tests/TestQue.cpp + tests/TestTree23.cpp + tests/TestTopics.cpp + tests/TestTopicIdMap.cpp + tests/TestTask.cpp + ) +TARGET_LINK_LIBRARIES(testPFW + mqtt-sngateway_common + ) + + +ADD_TEST(NAME testPFW + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/.. + COMMAND testPFW -f ./gateway.conf) diff --git a/MQTTSNGateway/src/MQTTGWConnectionHandler.cpp b/MQTTSNGateway/src/MQTTGWConnectionHandler.cpp index 0e5d85e..621b950 100644 --- a/MQTTSNGateway/src/MQTTGWConnectionHandler.cpp +++ b/MQTTSNGateway/src/MQTTGWConnectionHandler.cpp @@ -22,7 +22,7 @@ using namespace MQTTSNGW; MQTTGWConnectionHandler::MQTTGWConnectionHandler(Gateway* gateway) { - _gateway = gateway; + _gateway = gateway; } MQTTGWConnectionHandler::~MQTTGWConnectionHandler() @@ -32,68 +32,67 @@ MQTTGWConnectionHandler::~MQTTGWConnectionHandler() void MQTTGWConnectionHandler::handleConnack(Client* client, MQTTGWPacket* packet) { - uint8_t rc = MQTT_SERVER_UNAVAILABLE; - Connack resp; - packet->getCONNACK(&resp); + uint8_t rc = MQTT_SERVER_UNAVAILABLE; + Connack resp; + packet->getCONNACK(&resp); - /* convert MQTT ReturnCode to MQTT-SN one */ - if (resp.rc == MQTT_CONNECTION_ACCEPTED) - { - rc = MQTTSN_RC_ACCEPTED; - } - else if (resp.rc == MQTT_UNACCEPTABLE_PROTOCOL_VERSION) - { - rc = MQTTSN_RC_NOT_SUPPORTED; - WRITELOG(" ClientID : %s Requested Protocol version is not supported.\n", client->getClientId()); - } - else if (resp.rc == MQTT_IDENTIFIER_REJECTED) - { - rc = MQTTSN_RC_NOT_SUPPORTED; - WRITELOG(" ClientID : %s ClientID is collect UTF-8 but not allowed by the Server.\n", - client->getClientId()); - } - else if (resp.rc == MQTT_SERVER_UNAVAILABLE) - { - rc = MQTTSN_RC_REJECTED_CONGESTED; - WRITELOG(" ClientID : %s The Network Connection has been made but the MQTT service is unavailable.\n", - client->getClientId()); - } - else if (resp.rc == MQTT_BAD_USERNAME_OR_PASSWORD) - { - rc = MQTTSN_RC_NOT_SUPPORTED; - WRITELOG(" Gateway Configuration Error: The data in the user name or password is malformed.\n"); - } - else if (resp.rc == MQTT_NOT_AUTHORIZED) - { - rc = MQTTSN_RC_NOT_SUPPORTED; - WRITELOG(" Gateway Configuration Error: The Client is not authorized to connect.\n"); - } + /* convert MQTT ReturnCode to MQTT-SN one */ + if (resp.rc == MQTT_CONNECTION_ACCEPTED) + { + rc = MQTTSN_RC_ACCEPTED; + } + else if (resp.rc == MQTT_UNACCEPTABLE_PROTOCOL_VERSION) + { + rc = MQTTSN_RC_NOT_SUPPORTED; + WRITELOG(" ClientID : %s Requested Protocol version is not supported.\n", client->getClientId()); + } + else if (resp.rc == MQTT_IDENTIFIER_REJECTED) + { + rc = MQTTSN_RC_NOT_SUPPORTED; + WRITELOG(" ClientID : %s ClientID is collect UTF-8 but not allowed by the Server.\n", client->getClientId()); + } + else if (resp.rc == MQTT_SERVER_UNAVAILABLE) + { + rc = MQTTSN_RC_REJECTED_CONGESTED; + WRITELOG(" ClientID : %s The Network Connection has been made but the MQTT service is unavailable.\n", + client->getClientId()); + } + else if (resp.rc == MQTT_BAD_USERNAME_OR_PASSWORD) + { + rc = MQTTSN_RC_NOT_SUPPORTED; + WRITELOG(" Gateway Configuration Error: The data in the user name or password is malformed.\n"); + } + else if (resp.rc == MQTT_NOT_AUTHORIZED) + { + rc = MQTTSN_RC_NOT_SUPPORTED; + WRITELOG(" Gateway Configuration Error: The Client is not authorized to connect.\n"); + } - MQTTSNPacket* snPacket = new MQTTSNPacket(); - snPacket->setCONNACK(rc); + MQTTSNPacket* snPacket = new MQTTSNPacket(); + snPacket->setCONNACK(rc); - Event* ev1 = new Event(); - ev1->setClientSendEvent(client, snPacket); - client->connackSended(rc); // update the client's status - _gateway->getClientSendQue()->post(ev1); + Event* ev1 = new Event(); + ev1->setClientSendEvent(client, snPacket); + client->connackSended(rc); // update the client's status + _gateway->getClientSendQue()->post(ev1); } void MQTTGWConnectionHandler::handlePingresp(Client* client, MQTTGWPacket* packet) { - MQTTSNPacket* snPacket = new MQTTSNPacket(); - snPacket->setPINGRESP(); - Event* ev1 = new Event(); - ev1->setClientSendEvent(client, snPacket); - client->updateStatus(snPacket); - _gateway->getClientSendQue()->post(ev1); + MQTTSNPacket* snPacket = new MQTTSNPacket(); + snPacket->setPINGRESP(); + Event* ev1 = new Event(); + ev1->setClientSendEvent(client, snPacket); + client->updateStatus(snPacket); + _gateway->getClientSendQue()->post(ev1); } void MQTTGWConnectionHandler::handleDisconnect(Client* client, MQTTGWPacket* packet) { - MQTTSNPacket* snPacket = new MQTTSNPacket(); - snPacket->setDISCONNECT(0); - client->disconnected(); - client->getNetwork()->close(); - Event* ev1 = new Event(); - ev1->setClientSendEvent(client, snPacket); + MQTTSNPacket* snPacket = new MQTTSNPacket(); + snPacket->setDISCONNECT(0); + client->disconnected(); + client->getNetwork()->close(); + Event* ev1 = new Event(); + ev1->setClientSendEvent(client, snPacket); } diff --git a/MQTTSNGateway/src/MQTTGWConnectionHandler.h b/MQTTSNGateway/src/MQTTGWConnectionHandler.h index 125350d..d736c61 100644 --- a/MQTTSNGateway/src/MQTTGWConnectionHandler.h +++ b/MQTTSNGateway/src/MQTTGWConnectionHandler.h @@ -26,13 +26,13 @@ namespace MQTTSNGW class MQTTGWConnectionHandler { public: - MQTTGWConnectionHandler(Gateway* gateway); - ~MQTTGWConnectionHandler(); - void handleConnack(Client* client, MQTTGWPacket* packet); - void handlePingresp(Client* client, MQTTGWPacket* packet); - void handleDisconnect(Client* client, MQTTGWPacket* packet); + MQTTGWConnectionHandler(Gateway* gateway); + ~MQTTGWConnectionHandler(); + void handleConnack(Client* client, MQTTGWPacket* packet); + void handlePingresp(Client* client, MQTTGWPacket* packet); + void handleDisconnect(Client* client, MQTTGWPacket* packet); private: - Gateway* _gateway; + Gateway* _gateway; }; } diff --git a/MQTTSNGateway/src/MQTTGWPacket.cpp b/MQTTSNGateway/src/MQTTGWPacket.cpp index 45cb9d8..921bcee 100644 --- a/MQTTSNGateway/src/MQTTGWPacket.cpp +++ b/MQTTSNGateway/src/MQTTGWPacket.cpp @@ -28,9 +28,8 @@ void writeInt(unsigned char** pptr, int msgId); /** * List of the predefined MQTT v3 packet names. */ -static const char* mqtt_packet_names[] = -{ "RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP", "SUBSCRIBE", "SUBACK", - "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT" }; +static const char* mqtt_packet_names[] = { "RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP", + "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT" }; /** * Encodes the message length according to the MQTT algorithm @@ -40,17 +39,18 @@ static const char* mqtt_packet_names[] = */ int MQTTPacket_encode(char* buf, int length) { - int rc = 0; - do - { - char d = length % 128; - length /= 128; - /* if there are more digits to encode, set the top bit of this digit */ - if (length > 0) - d |= 0x80; - buf[rc++] = d; - } while (length > 0); - return rc; + int rc = 0; + do + { + char d = length % 128; + length /= 128; + /* if there are more digits to encode, set the top bit of this digit */ + if (length > 0) + d |= 0x80; + buf[rc++] = d; + } + while (length > 0); + return rc; } /** @@ -60,10 +60,10 @@ int MQTTPacket_encode(char* buf, int length) */ int readInt(char** pptr) { - char* ptr = *pptr; - int len = 256 * ((unsigned char) (*ptr)) + (unsigned char) (*(ptr + 1)); - *pptr += 2; - return len; + char* ptr = *pptr; + int len = 256 * ((unsigned char) (*ptr)) + (unsigned char) (*(ptr + 1)); + *pptr += 2; + return len; } /** @@ -80,20 +80,20 @@ int readInt(char** pptr) */ char* readUTFlen(char** pptr, char* enddata, int* len) { - char* string = NULL; + char* string = NULL; - if (enddata - (*pptr) > 1) /* enough length to read the integer? */ - { - *len = readInt(pptr); - if (&(*pptr)[*len] <= enddata) - { - string = (char*)calloc(*len + 1, 1); - memcpy(string, *pptr, (size_t)*len); - string[*len] = '\0'; - *pptr += *len; - } - } - return string; + if (enddata - (*pptr) > 1) /* enough length to read the integer? */ + { + *len = readInt(pptr); + if (&(*pptr)[*len] <= enddata) + { + string = (char*) calloc(*len + 1, 1); + memcpy(string, *pptr, (size_t) *len); + string[*len] = '\0'; + *pptr += *len; + } + } + return string; } /** @@ -108,8 +108,8 @@ char* readUTFlen(char** pptr, char* enddata, int* len) */ char* readUTF(char** pptr, char* enddata) { - int len; - return readUTFlen(pptr, enddata, &len); + int len; + return readUTFlen(pptr, enddata, &len); } /** @@ -119,9 +119,9 @@ char* readUTF(char** pptr, char* enddata) */ unsigned char readChar(char** pptr) { - unsigned char c = **pptr; - (*pptr)++; - return c; + unsigned char c = **pptr; + (*pptr)++; + return c; } /** @@ -131,8 +131,8 @@ unsigned char readChar(char** pptr) */ void writeChar(unsigned char** pptr, char c) { - **pptr = c; - (*pptr)++; + **pptr = c; + (*pptr)++; } /** @@ -142,10 +142,10 @@ void writeChar(unsigned char** pptr, char c) */ void writeInt(unsigned char** pptr, int anInt) { - **pptr = (unsigned char)(anInt / 256); - (*pptr)++; - **pptr = (unsigned char)(anInt % 256); - (*pptr)++; + **pptr = (unsigned char) (anInt / 256); + (*pptr)++; + **pptr = (unsigned char) (anInt % 256); + (*pptr)++; } /** @@ -155,10 +155,10 @@ void writeInt(unsigned char** pptr, int anInt) */ void writeUTF(unsigned char** pptr, const char* string) { - int len = (int)strlen(string); - writeInt(pptr, len); - memcpy(*pptr, string, (size_t)len); - *pptr += len; + int len = (int) strlen(string); + writeInt(pptr, len); + memcpy(*pptr, string, (size_t) len); + *pptr += len; } /** @@ -167,479 +167,480 @@ void writeUTF(unsigned char** pptr, const char* string) */ MQTTGWPacket::MQTTGWPacket() { - _data = 0; - _header.byte = 0; - _remainingLength = 0; + _data = 0; + _header.byte = 0; + _remainingLength = 0; } MQTTGWPacket::~MQTTGWPacket() { - if (_data) - { - free(_data); - } + if (_data) + { + free(_data); + } } int MQTTGWPacket::recv(Network* network) { - int len = 0; - int multiplier = 1; - unsigned char c; + int len = 0; + int multiplier = 1; + unsigned char c; - /* read First Byte of Packet */ - int rc = network->recv((unsigned char*)&_header.byte, 1); - if ( rc <= 0) - { - return rc; - } - /* read RemainingLength */ - do - { - if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) - { - return -2; - } - if (network->recv(&c, 1) == -1) - { - return -1; - } - _remainingLength += (c & 127) * multiplier; - multiplier *= 128; - } while ((c & 128) != 0); + /* read First Byte of Packet */ + int rc = network->recv((unsigned char*) &_header.byte, 1); + if (rc <= 0) + { + return rc; + } + /* read RemainingLength */ + do + { + if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) + { + return -2; + } + if (network->recv(&c, 1) == -1) + { + return -1; + } + _remainingLength += (c & 127) * multiplier; + multiplier *= 128; + } + while ((c & 128) != 0); - if ( _remainingLength > 0 ) - { - /* allocate buffer */ - _data = (unsigned char*)calloc(_remainingLength, 1); - if ( !_data ) - { - return -3; - } + if (_remainingLength > 0) + { + /* allocate buffer */ + _data = (unsigned char*) calloc(_remainingLength, 1); + if (!_data) + { + return -3; + } - /* read Payload */ - int remlen = network->recv(_data, _remainingLength); + /* read Payload */ + int remlen = network->recv(_data, _remainingLength); - if (remlen == -1 ) - { - return -1; - } - else if ( remlen != _remainingLength ) - { - return -2; - } - } - return 1 + len + _remainingLength; + if (remlen == -1) + { + return -1; + } + else if (remlen != _remainingLength) + { + return -2; + } + } + return 1 + len + _remainingLength; } int MQTTGWPacket::send(Network* network) { - unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; - memset(buf, 0, MQTTSNGW_MAX_PACKET_SIZE); - int len = getPacketData(buf); - return network->send(buf, len); + unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; + memset(buf, 0, MQTTSNGW_MAX_PACKET_SIZE); + int len = getPacketData(buf); + return network->send(buf, len); } int MQTTGWPacket::getAck(Ack* ack) { - if (PUBACK != _header.bits.type && PUBREC != _header.bits.type && PUBREL != _header.bits.type - && PUBCOMP != _header.bits.type && UNSUBACK != _header.bits.type) - { - return 0; - } - char* ptr = (char*) _data; - ack->header.byte = _header.byte; - ack->msgId = readInt((char**) &ptr); - return 1; + if (PUBACK != _header.bits.type && PUBREC != _header.bits.type && PUBREL != _header.bits.type + && PUBCOMP != _header.bits.type && UNSUBACK != _header.bits.type) + { + return 0; + } + char* ptr = (char*) _data; + ack->header.byte = _header.byte; + ack->msgId = readInt((char**) &ptr); + return 1; } int MQTTGWPacket::getCONNACK(Connack* resp) { - if (_header.bits.type != CONNACK) - { - return 0; - } - char* ptr = (char*) _data; - resp->header.byte = _header.byte; - resp->flags.all = *ptr++; - resp->rc = readChar(&ptr); - return 1; + if (_header.bits.type != CONNACK) + { + return 0; + } + char* ptr = (char*) _data; + resp->header.byte = _header.byte; + resp->flags.all = *ptr++; + resp->rc = readChar(&ptr); + return 1; } int MQTTGWPacket::getSUBACK(unsigned short* msgId, unsigned char* rc) { - if (_header.bits.type != SUBACK) - { - return 0; - } - char *ptr = (char*) _data; - *msgId = readInt((char**) &ptr); - *rc = readChar(&ptr); - return 1; + if (_header.bits.type != SUBACK) + { + return 0; + } + char *ptr = (char*) _data; + *msgId = readInt((char**) &ptr); + *rc = readChar(&ptr); + return 1; } int MQTTGWPacket::getPUBLISH(Publish* pub) { - if (_header.bits.type != PUBLISH) - { - return 0; - } - char* ptr = (char*) _data; - pub->header = _header; - pub->topiclen = readInt((char**) &ptr); - pub->topic = (char*) _data + 2; - ptr += pub->topiclen; - if (_header.bits.qos > 0) - { - pub->msgId = readInt(&ptr); - pub->payloadlen = _remainingLength - pub->topiclen - 4; - } - else - { - pub->msgId = 0; - pub->payloadlen = _remainingLength - pub->topiclen - 2; - } - pub->payload = ptr; - return 1; + if (_header.bits.type != PUBLISH) + { + return 0; + } + char* ptr = (char*) _data; + pub->header = _header; + pub->topiclen = readInt((char**) &ptr); + pub->topic = (char*) _data + 2; + ptr += pub->topiclen; + if (_header.bits.qos > 0) + { + pub->msgId = readInt(&ptr); + pub->payloadlen = _remainingLength - pub->topiclen - 4; + } + else + { + pub->msgId = 0; + pub->payloadlen = _remainingLength - pub->topiclen - 2; + } + pub->payload = ptr; + return 1; } int MQTTGWPacket::setCONNECT(Connect* connect, unsigned char* username, unsigned char* password) { - clearData(); - _header = connect->header; + clearData(); + _header = connect->header; - _remainingLength = ((connect->version == 3) ? 12 : 10) + (int)strlen(connect->clientID) + 2; - if (connect->flags.bits.will) - { - _remainingLength += (int)strlen(connect->willTopic) + 2 + (int)strlen(connect->willMsg) + 2; - } - if ( connect->flags.bits.username ) - { - _remainingLength += (int)strlen((char*) username) + 2; - } - if (connect->flags.bits.password) - { - _remainingLength += (int)strlen((char*) password) + 2; - } + _remainingLength = ((connect->version == 3) ? 12 : 10) + (int) strlen(connect->clientID) + 2; + if (connect->flags.bits.will) + { + _remainingLength += (int) strlen(connect->willTopic) + 2 + (int) strlen(connect->willMsg) + 2; + } + if (connect->flags.bits.username) + { + _remainingLength += (int) strlen((char*) username) + 2; + } + if (connect->flags.bits.password) + { + _remainingLength += (int) strlen((char*) password) + 2; + } - _data = (unsigned char*)calloc(_remainingLength, 1); - unsigned char* ptr = _data; + _data = (unsigned char*) calloc(_remainingLength, 1); + unsigned char* ptr = _data; - if (connect->version == 3) - { - writeUTF(&ptr, "MQIsdp"); - writeChar(&ptr, (char) 3); - } - else if (connect->version == 4) - { - writeUTF(&ptr, "MQTT"); - writeChar(&ptr, (char) 4); - } - else - { - return 0; - } + if (connect->version == 3) + { + writeUTF(&ptr, "MQIsdp"); + writeChar(&ptr, (char) 3); + } + else if (connect->version == 4) + { + writeUTF(&ptr, "MQTT"); + writeChar(&ptr, (char) 4); + } + else + { + return 0; + } - writeChar(&ptr, connect->flags.all); - writeInt(&ptr, connect->keepAliveTimer); - writeUTF(&ptr, connect->clientID); - if (connect->flags.bits.will) - { - writeUTF(&ptr, connect->willTopic); - writeUTF(&ptr, connect->willMsg); - } + writeChar(&ptr, connect->flags.all); + writeInt(&ptr, connect->keepAliveTimer); + writeUTF(&ptr, connect->clientID); + if (connect->flags.bits.will) + { + writeUTF(&ptr, connect->willTopic); + writeUTF(&ptr, connect->willMsg); + } - if (connect->flags.bits.username) - { - writeUTF(&ptr, (const char*) username); - } - if (connect->flags.bits.password) - { - writeUTF(&ptr, (const char*) password); - } - return 1; + if (connect->flags.bits.username) + { + writeUTF(&ptr, (const char*) username); + } + if (connect->flags.bits.password) + { + writeUTF(&ptr, (const char*) password); + } + return 1; } int MQTTGWPacket::setSUBSCRIBE(const char* topic, unsigned char qos, unsigned short msgId) { - clearData(); - _header.byte = 0; - _header.bits.type = SUBSCRIBE; - _header.bits.qos = 1; // Reserved - _remainingLength = (int)strlen(topic) + 5; - _data = (unsigned char*)calloc(_remainingLength, 1); - if (_data) - { - unsigned char* ptr = _data; - writeInt(&ptr, msgId); - writeUTF(&ptr, topic); - writeChar(&ptr, (char) qos); - return 1; - } - clearData(); - return 0; + clearData(); + _header.byte = 0; + _header.bits.type = SUBSCRIBE; + _header.bits.qos = 1; // Reserved + _remainingLength = (int) strlen(topic) + 5; + _data = (unsigned char*) calloc(_remainingLength, 1); + if (_data) + { + unsigned char* ptr = _data; + writeInt(&ptr, msgId); + writeUTF(&ptr, topic); + writeChar(&ptr, (char) qos); + return 1; + } + clearData(); + return 0; } int MQTTGWPacket::setUNSUBSCRIBE(const char* topic, unsigned short msgid) { - clearData(); - _header.byte = 0; - _header.bits.type = UNSUBSCRIBE; - _header.bits.qos = 1; - _remainingLength = (int)strlen(topic) + 4; - _data = (unsigned char*)calloc(_remainingLength, 1); - if (_data) - { - unsigned char* ptr = _data; - writeInt(&ptr, msgid); - writeUTF(&ptr, topic); - return 1; - } - clearData(); - return 0; + clearData(); + _header.byte = 0; + _header.bits.type = UNSUBSCRIBE; + _header.bits.qos = 1; + _remainingLength = (int) strlen(topic) + 4; + _data = (unsigned char*) calloc(_remainingLength, 1); + if (_data) + { + unsigned char* ptr = _data; + writeInt(&ptr, msgid); + writeUTF(&ptr, topic); + return 1; + } + clearData(); + return 0; } int MQTTGWPacket::setPUBLISH(Publish* pub) { - clearData(); - _header.byte = pub->header.byte; - _header.bits.type = PUBLISH; - _remainingLength = 4 + pub->topiclen + pub->payloadlen; - _data = (unsigned char*)calloc(_remainingLength, 1); - if (_data) - { - unsigned char* ptr = _data; - writeInt(&ptr, pub->topiclen); - memcpy(ptr, pub->topic, pub->topiclen); - ptr += pub->topiclen; - if ( _header.bits.qos > 0 ) - { - writeInt(&ptr, pub->msgId); - } - else - { - _remainingLength -= 2; - } - memcpy(ptr, pub->payload, pub->payloadlen); - return 1; - } - else - { - clearData(); - return 0; - } + clearData(); + _header.byte = pub->header.byte; + _header.bits.type = PUBLISH; + _remainingLength = 4 + pub->topiclen + pub->payloadlen; + _data = (unsigned char*) calloc(_remainingLength, 1); + if (_data) + { + unsigned char* ptr = _data; + writeInt(&ptr, pub->topiclen); + memcpy(ptr, pub->topic, pub->topiclen); + ptr += pub->topiclen; + if (_header.bits.qos > 0) + { + writeInt(&ptr, pub->msgId); + } + else + { + _remainingLength -= 2; + } + memcpy(ptr, pub->payload, pub->payloadlen); + return 1; + } + else + { + clearData(); + return 0; + } } int MQTTGWPacket::setAck(unsigned char msgType, unsigned short msgid) { - clearData(); - _remainingLength = 2; - _header.bits.type = msgType; - _header.bits.qos = (msgType == PUBREL) ? 1 : 0; + clearData(); + _remainingLength = 2; + _header.bits.type = msgType; + _header.bits.qos = (msgType == PUBREL) ? 1 : 0; - _data = (unsigned char*)calloc(_remainingLength, 1); - if (_data) - { - unsigned char* data = _data; - writeInt(&data, msgid); - return 1; - } - return 0; + _data = (unsigned char*) calloc(_remainingLength, 1); + if (_data) + { + unsigned char* data = _data; + writeInt(&data, msgid); + return 1; + } + return 0; } int MQTTGWPacket::setHeader(unsigned char msgType) { - clearData(); - if (msgType < CONNECT || msgType > DISCONNECT) - { - return 0; - } - _header.bits.type = msgType; - return 0; + clearData(); + if (msgType < CONNECT || msgType > DISCONNECT) + { + return 0; + } + _header.bits.type = msgType; + return 0; } int MQTTGWPacket::getType(void) { - return _header.bits.type; + return _header.bits.type; } const char* MQTTGWPacket::getName(void) { - return getType() > DISCONNECT ? "UNKNOWN" : mqtt_packet_names[getType()]; + return getType() > DISCONNECT ? "UNKNOWN" : mqtt_packet_names[getType()]; } int MQTTGWPacket::getPacketData(unsigned char* buf) { - unsigned char* ptr = buf; - *ptr++ = _header.byte; - int len = MQTTPacket_encode((char*)ptr, _remainingLength); - ptr += len; - memcpy(ptr, _data, _remainingLength); - return 1 + len + _remainingLength; + unsigned char* ptr = buf; + *ptr++ = _header.byte; + int len = MQTTPacket_encode((char*) ptr, _remainingLength); + ptr += len; + memcpy(ptr, _data, _remainingLength); + return 1 + len + _remainingLength; } int MQTTGWPacket::getPacketLength(void) { - char buf[4]; - return 1 + MQTTPacket_encode(buf, _remainingLength) + _remainingLength; + char buf[4]; + return 1 + MQTTPacket_encode(buf, _remainingLength) + _remainingLength; } void MQTTGWPacket::clearData(void) { - if (_data) - { - free(_data); - } - _header.byte = 0; - _remainingLength = 0; + if (_data) + { + free(_data); + } + _header.byte = 0; + _remainingLength = 0; } char* MQTTGWPacket::getMsgId(char* pbuf) { - int type = getType(); + int type = getType(); - switch ( type ) - { - case PUBLISH: - Publish pub; - pub.msgId = 0; - getPUBLISH(&pub); - if ( _header.bits.dup ) - { - sprintf(pbuf, "+%04X", pub.msgId); - } - else - { - sprintf(pbuf, " %04X", pub.msgId); - } - break; - case SUBSCRIBE: - case UNSUBSCRIBE: - case PUBACK: - case PUBREC: - case PUBREL: - case PUBCOMP: - case SUBACK: - case UNSUBACK: - sprintf(pbuf, " %02X%02X", _data[0], _data[1]); - break; - default: - sprintf(pbuf, " "); - break; - } - if ( strcmp(pbuf, " 0000") == 0 ) - { - sprintf(pbuf, " "); - } - return pbuf; + switch (type) + { + case PUBLISH: + Publish pub; + pub.msgId = 0; + getPUBLISH(&pub); + if (_header.bits.dup) + { + sprintf(pbuf, "+%04X", pub.msgId); + } + else + { + sprintf(pbuf, " %04X", pub.msgId); + } + break; + case SUBSCRIBE: + case UNSUBSCRIBE: + case PUBACK: + case PUBREC: + case PUBREL: + case PUBCOMP: + case SUBACK: + case UNSUBACK: + sprintf(pbuf, " %02X%02X", _data[0], _data[1]); + break; + default: + sprintf(pbuf, " "); + break; + } + if (strcmp(pbuf, " 0000") == 0) + { + sprintf(pbuf, " "); + } + return pbuf; } int MQTTGWPacket::getMsgId(void) { - int type = getType(); - int msgId = 0; + int type = getType(); + int msgId = 0; - switch ( type ) - { - case PUBLISH: - Publish pub; - pub.msgId = 0; - getPUBLISH(&pub); - msgId = pub.msgId; - break; - case PUBACK: - case PUBREC: - case PUBREL: - case PUBCOMP: - case SUBSCRIBE: - case UNSUBSCRIBE: - case SUBACK: - case UNSUBACK: - msgId = 256 * (unsigned char)_data[0] + (unsigned char)_data[1]; - break; - default: - break; - } - return msgId; + switch (type) + { + case PUBLISH: + Publish pub; + pub.msgId = 0; + getPUBLISH(&pub); + msgId = pub.msgId; + break; + case PUBACK: + case PUBREC: + case PUBREL: + case PUBCOMP: + case SUBSCRIBE: + case UNSUBSCRIBE: + case SUBACK: + case UNSUBACK: + msgId = 256 * (unsigned char) _data[0] + (unsigned char) _data[1]; + break; + default: + break; + } + return msgId; } void MQTTGWPacket::setMsgId(int msgId) { - int type = getType(); - unsigned char* ptr = 0; + int type = getType(); + unsigned char* ptr = 0; - switch ( type ) - { - case PUBLISH: - Publish pub; - pub.topiclen = 0; - pub.msgId = 0; - getPUBLISH(&pub); - pub.msgId = msgId; - ptr = _data + pub.topiclen; - writeInt(&ptr, pub.msgId); - *ptr++ = (unsigned char)(msgId / 256); - *ptr = (unsigned char)(msgId % 256); - break; - case SUBSCRIBE: - case UNSUBSCRIBE: - case PUBACK: - case PUBREC: - case PUBREL: - case PUBCOMP: - case SUBACK: - case UNSUBACK: - ptr = _data; - *ptr++ = (unsigned char)(msgId / 256); - *ptr = (unsigned char)(msgId % 256); - break; - default: - break; - } + switch (type) + { + case PUBLISH: + Publish pub; + pub.topiclen = 0; + pub.msgId = 0; + getPUBLISH(&pub); + pub.msgId = msgId; + ptr = _data + pub.topiclen; + writeInt(&ptr, pub.msgId); + *ptr++ = (unsigned char) (msgId / 256); + *ptr = (unsigned char) (msgId % 256); + break; + case SUBSCRIBE: + case UNSUBSCRIBE: + case PUBACK: + case PUBREC: + case PUBREL: + case PUBCOMP: + case SUBACK: + case UNSUBACK: + ptr = _data; + *ptr++ = (unsigned char) (msgId / 256); + *ptr = (unsigned char) (msgId % 256); + break; + default: + break; + } } char* MQTTGWPacket::print(char* pbuf) { - uint8_t packetData[MQTTSNGW_MAX_PACKET_SIZE]; - char* ptr = pbuf; - char** pptr = &pbuf; - int len = getPacketData(packetData); - int size = len > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : len; - for (int i = 0; i < size; i++) - { - sprintf(*pptr, " %02X", packetData[i]); - *pptr += 3; - } - **pptr = 0; - return ptr; + uint8_t packetData[MQTTSNGW_MAX_PACKET_SIZE]; + char* ptr = pbuf; + char** pptr = &pbuf; + int len = getPacketData(packetData); + int size = len > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : len; + for (int i = 0; i < size; i++) + { + sprintf(*pptr, " %02X", packetData[i]); + *pptr += 3; + } + **pptr = 0; + return ptr; } MQTTGWPacket& MQTTGWPacket::operator =(MQTTGWPacket& packet) { - clearData(); - this->_header.byte = packet._header.byte; - this->_remainingLength = packet._remainingLength; - _data = (unsigned char*)calloc(_remainingLength, 1); - if (_data) - { - memcpy(this->_data, packet._data, _remainingLength); - } - else - { - clearData(); - } - return *this; + clearData(); + this->_header.byte = packet._header.byte; + this->_remainingLength = packet._remainingLength; + _data = (unsigned char*) calloc(_remainingLength, 1); + if (_data) + { + memcpy(this->_data, packet._data, _remainingLength); + } + else + { + clearData(); + } + return *this; } UTF8String MQTTGWPacket::getTopic(void) { - UTF8String str = {0, nullptr}; - if ( _header.bits.type == SUBSCRIBE || _header.bits.type == UNSUBSCRIBE ) - { - char* ptr = (char*)(_data + 2); - str.len = readInt(&ptr); - str.data = (char*)(_data + 4); - } - return str; + UTF8String str = { 0, nullptr }; + if (_header.bits.type == SUBSCRIBE || _header.bits.type == UNSUBSCRIBE) + { + char* ptr = (char*) (_data + 2); + str.len = readInt(&ptr); + str.data = (char*) (_data + 4); + } + return str; } diff --git a/MQTTSNGateway/src/MQTTGWPacket.h b/MQTTSNGateway/src/MQTTGWPacket.h index fb2ad86..46df326 100644 --- a/MQTTSNGateway/src/MQTTGWPacket.h +++ b/MQTTSNGateway/src/MQTTGWPacket.h @@ -31,89 +31,100 @@ typedef void* (*pf)(unsigned char, char*, size_t); enum msgTypes { - CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, - PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, - PINGREQ, PINGRESP, DISCONNECT + CONNECT = 1, + CONNACK, + PUBLISH, + PUBACK, + PUBREC, + PUBREL, + PUBCOMP, + SUBSCRIBE, + SUBACK, + UNSUBSCRIBE, + UNSUBACK, + PINGREQ, + PINGRESP, + DISCONNECT }; - /** * Bitfields for the MQTT header byte. */ typedef union { - /*unsigned*/ char byte; /**< the whole byte */ + /*unsigned*/ + char byte; /**< the whole byte */ #if defined(REVERSED) - struct - { - unsigned int type : 4; /**< message type nibble */ - bool dup : 1; /**< DUP flag bit */ - unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ - bool retain : 1; /**< retained flag bit */ - } bits; + struct + { + unsigned int type : 4; /**< message type nibble */ + bool dup : 1; /**< DUP flag bit */ + unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ + bool retain : 1; /**< retained flag bit */ + }bits; #else - struct - { - bool retain : 1; /**< retained flag bit */ - unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ - bool dup : 1; /**< DUP flag bit */ - unsigned int type : 4; /**< message type nibble */ - } bits; + struct + { + bool retain :1; /**< retained flag bit */ + unsigned int qos :2; /**< QoS value, 0, 1 or 2 */ + bool dup :1; /**< DUP flag bit */ + unsigned int type :4; /**< message type nibble */ + } bits; #endif } Header; - /** * Data for a connect packet. */ -enum MQTT_connackCodes{ - MQTT_CONNECTION_ACCEPTED , - MQTT_UNACCEPTABLE_PROTOCOL_VERSION, - MQTT_IDENTIFIER_REJECTED, - MQTT_SERVER_UNAVAILABLE, - MQTT_BAD_USERNAME_OR_PASSWORD, - MQTT_NOT_AUTHORIZED +enum MQTT_connackCodes +{ + MQTT_CONNECTION_ACCEPTED, + MQTT_UNACCEPTABLE_PROTOCOL_VERSION, + MQTT_IDENTIFIER_REJECTED, + MQTT_SERVER_UNAVAILABLE, + MQTT_BAD_USERNAME_OR_PASSWORD, + MQTT_NOT_AUTHORIZED }; typedef struct { - Header header; /**< MQTT header byte */ - union - { - unsigned char all; /**< all connect flags */ + Header header; /**< MQTT header byte */ + union + { + unsigned char all; /**< all connect flags */ #if defined(REVERSED) - struct - { - bool username : 1; /**< 3.1 user name */ - bool password : 1; /**< 3.1 password */ - bool willRetain : 1; /**< will retain setting */ - unsigned int willQoS : 2; /**< will QoS value */ - bool will : 1; /**< will flag */ - bool cleanstart : 1; /**< cleansession flag */ - int : 1; /**< unused */ - } bits; + struct + { + bool username : 1; /**< 3.1 user name */ + bool password : 1; /**< 3.1 password */ + bool willRetain : 1; /**< will retain setting */ + unsigned int willQoS : 2; /**< will QoS value */ + bool will : 1; /**< will flag */ + bool cleanstart : 1; /**< cleansession flag */ + int : 1; /**< unused */ + }bits; #else - struct - { - int : 1; /**< unused */ - bool cleanstart : 1; /**< cleansession flag */ - bool will : 1; /**< will flag */ - unsigned int willQoS : 2; /**< will QoS value */ - bool willRetain : 1; /**< will retain setting */ - bool password : 1; /**< 3.1 password */ - bool username : 1; /**< 3.1 user name */ - } bits; + struct + { + int :1; /**< unused */ + bool cleanstart :1; /**< cleansession flag */ + bool will :1; /**< will flag */ + unsigned int willQoS :2; /**< will QoS value */ + bool willRetain :1; /**< will retain setting */ + bool password :1; /**< 3.1 password */ + bool username :1; /**< 3.1 user name */ + } bits; #endif - } flags; /**< connect flags byte */ + } flags; /**< connect flags byte */ - char *Protocol, /**< MQTT protocol name */ - *clientID, /**< string client id */ - *willTopic, /**< will topic */ - *willMsg; /**< will payload */ + char *Protocol, /**< MQTT protocol name */ + *clientID, /**< string client id */ + *willTopic, /**< will topic */ + *willMsg; /**< will payload */ - int keepAliveTimer; /**< keepalive timeout value in seconds */ - unsigned char version; /**< MQTT version number */ + int keepAliveTimer; /**< keepalive timeout value in seconds */ + unsigned char version; /**< MQTT version number */ } Connect; #define MQTTPacket_Connect_Initializer {{0}, {0}, nullptr, nullptr, nullptr, nullptr, 0, 0} @@ -121,57 +132,54 @@ typedef struct #define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \ MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} } - - /** * Data for a willMessage. */ typedef struct { - char* topic; - char* msg; - int retained; - int qos; -}willMessages; + char* topic; + char* msg; + int retained; + int qos; +} willMessages; /** * Data for a connack packet. */ typedef struct { - Header header; /**< MQTT header byte */ - union - { - unsigned char all; /**< all connack flags */ + Header header; /**< MQTT header byte */ + union + { + unsigned char all; /**< all connack flags */ #if defined(REVERSED) - struct - { - unsigned int reserved : 7; /**< message type nibble */ - bool sessionPresent : 1; /**< was a session found on the server? */ - } bits; + struct + { + unsigned int reserved : 7; /**< message type nibble */ + bool sessionPresent : 1; /**< was a session found on the server? */ + }bits; #else - struct - { - bool sessionPresent : 1; /**< was a session found on the server? */ - unsigned int reserved : 7; /**< message type nibble */ - } bits; + struct + { + bool sessionPresent :1; /**< was a session found on the server? */ + unsigned int reserved :7; /**< message type nibble */ + } bits; #endif - } flags; /**< connack flags byte */ - char rc; /**< connack return code */ + } flags; /**< connack flags byte */ + char rc; /**< connack return code */ } Connack; - /** * Data for a publish packet. */ typedef struct { - Header header; /**< MQTT header byte */ - char* topic; /**< topic string */ - int topiclen; - int msgId; /**< MQTT message id */ - char* payload; /**< binary payload, length delimited */ - int payloadlen; /**< payload length */ + Header header; /**< MQTT header byte */ + char* topic; /**< topic string */ + int topiclen; + int msgId; /**< MQTT message id */ + char* payload; /**< binary payload, length delimited */ + int payloadlen; /**< payload length */ } Publish; #define MQTTPacket_Publish_Initializer {{0}, nullptr, 0, 0, nullptr, 0} @@ -181,8 +189,8 @@ typedef struct */ typedef struct { - Header header; /**< MQTT header byte */ - int msgId; /**< MQTT message id */ + Header header; /**< MQTT header byte */ + int msgId; /**< MQTT message id */ } Ack; /** @@ -190,8 +198,8 @@ typedef struct */ typedef struct { - unsigned char len; - char* data; + unsigned char len; + char* data; } UTF8String; /** @@ -200,39 +208,41 @@ typedef struct class MQTTGWPacket { public: - MQTTGWPacket(); - ~MQTTGWPacket(); - int recv(Network* network); - int send(Network* network); - int getType(void); - int getPacketData(unsigned char* buf); - int getPacketLength(void); - const char* getName(void); + MQTTGWPacket(); + ~MQTTGWPacket(); + int recv(Network* network); + int send(Network* network); + int getType(void); + int getPacketData(unsigned char* buf); + int getPacketLength(void); + const char* getName(void); - int getAck(Ack* ack); - int getCONNACK(Connack* resp); - int getSUBACK(unsigned short* msgId, unsigned char* rc); - int getPUBLISH(Publish* pub); + int getAck(Ack* ack); + int getCONNACK(Connack* resp); + int getSUBACK(unsigned short* msgId, unsigned char* rc); + int getPUBLISH(Publish* pub); - int setCONNECT(Connect* conect, unsigned char* username, unsigned char* password); - int setPUBLISH(Publish* pub); - int setAck(unsigned char msgType, unsigned short msgid); - int setHeader(unsigned char msgType); - int setSUBSCRIBE(const char* topic, unsigned char qos, unsigned short msgId); - int setUNSUBSCRIBE(const char* topics, unsigned short msgid); + int setCONNECT(Connect* conect, unsigned char* username, + unsigned char* password); + int setPUBLISH(Publish* pub); + int setAck(unsigned char msgType, unsigned short msgid); + int setHeader(unsigned char msgType); + int setSUBSCRIBE(const char* topic, unsigned char qos, + unsigned short msgId); + int setUNSUBSCRIBE(const char* topics, unsigned short msgid); - UTF8String getTopic(void); - char* getMsgId(char* buf); - int getMsgId(void); - void setMsgId(int msgId); - char* print(char* buf); - MQTTGWPacket& operator =(MQTTGWPacket& packet); + UTF8String getTopic(void); + char* getMsgId(char* buf); + int getMsgId(void); + void setMsgId(int msgId); + char* print(char* buf); + MQTTGWPacket& operator =(MQTTGWPacket& packet); private: - void clearData(void); - Header _header; - int _remainingLength; - unsigned char* _data; + void clearData(void); + Header _header; + int _remainingLength; + unsigned char* _data; }; } diff --git a/MQTTSNGateway/src/MQTTGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTGWPublishHandler.cpp index e3abc79..6185b92 100644 --- a/MQTTSNGateway/src/MQTTGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTGWPublishHandler.cpp @@ -27,7 +27,7 @@ char* currentDateTime(void); MQTTGWPublishHandler::MQTTGWPublishHandler(Gateway* gateway) { - _gateway = gateway; + _gateway = gateway; } MQTTGWPublishHandler::~MQTTGWPublishHandler() @@ -37,266 +37,283 @@ MQTTGWPublishHandler::~MQTTGWPublishHandler() void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet) { - if ( !client->isActive() && !client->isSleep() && !client->isAwake()) - { - WRITELOG("%s The client is neither active nor sleep %s%s\n", ERRMSG_HEADER, client->getStatus(), ERRMSG_FOOTER); - return; - } + if (!client->isActive() && !client->isSleep() && !client->isAwake()) + { + WRITELOG("%s The client is neither active nor sleep %s%s\n", + ERRMSG_HEADER, client->getStatus(), ERRMSG_FOOTER); + return; + } - /* client is sleeping. save PUBLISH */ - if ( client->isSleep() ) - { - Publish pub; - packet->getPUBLISH(&pub); + /* client is sleeping. save PUBLISH */ + if (client->isSleep()) + { + Publish pub; + packet->getPUBLISH(&pub); - WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), - RIGHTARROW, client->getClientId(), "is sleeping. a message was saved."); + WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), + RIGHTARROW, client->getClientId(), "is sleeping. a message was saved."); - if (pub.header.bits.qos == 1) - { - replyACK(client, &pub, PUBACK); - } - else if ( pub.header.bits.qos == 2) - { - replyACK(client, &pub, PUBREC); - } + if (pub.header.bits.qos == 1) + { + replyACK(client, &pub, PUBACK); + } + else if (pub.header.bits.qos == 2) + { + replyACK(client, &pub, PUBREC); + } - MQTTGWPacket* msg = new MQTTGWPacket(); - *msg = *packet; - if ( msg->getType() == 0 ) - { - WRITELOG("%s MQTTGWPublishHandler::handlePublish can't allocate memories for Packet.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER); - delete msg; - return; - } - client->setClientSleepPacket(msg); - return; - } + MQTTGWPacket* msg = new MQTTGWPacket(); + *msg = *packet; + if (msg->getType() == 0) + { + WRITELOG("%s MQTTGWPublishHandler::handlePublish can't allocate memories for Packet.%s\n", + ERRMSG_HEADER, ERRMSG_FOOTER); + delete msg; + return; + } + client->setClientSleepPacket(msg); + return; + } - Publish pub; - packet->getPUBLISH(&pub); + Publish pub; + packet->getPUBLISH(&pub); - MQTTSNPacket* snPacket = new MQTTSNPacket(); + MQTTSNPacket* snPacket = new MQTTSNPacket(); - /* create MQTTSN_topicid */ - MQTTSN_topicid topicId; - uint16_t id = 0; + /* create MQTTSN_topicid */ + MQTTSN_topicid topicId; + uint16_t id = 0; - if (pub.topiclen <= 2) - { - topicId.type = MQTTSN_TOPIC_TYPE_SHORT; - *(topicId.data.short_name) = *pub.topic; - *(topicId.data.short_name + 1) = *(pub.topic + 1); - } - else - { + if (pub.topiclen <= 2) + { + topicId.type = MQTTSN_TOPIC_TYPE_SHORT; + *(topicId.data.short_name) = *pub.topic; + *(topicId.data.short_name + 1) = *(pub.topic + 1); + } + else + { topicId.data.long_.len = pub.topiclen; topicId.data.long_.name = pub.topic; Topic* tp = client->getTopics()->getTopicByName(&topicId); - if ( tp ) + if (tp) { topicId.type = tp->getType(); topicId.data.long_.len = pub.topiclen; topicId.data.long_.name = pub.topic; - topicId.data.id = tp->getTopicId(); } - else - { - /* This message might be subscribed with wild card. */ - topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; - Topic* topic = client->getTopics()->match(&topicId); - if (topic == nullptr) - { - WRITELOG(" Invalid Topic. PUBLISH message is canceled.\n"); - if (pub.header.bits.qos == 1) - { - replyACK(client, &pub, PUBACK); - } - else if ( pub.header.bits.qos == 2 ) - { - replyACK(client, &pub, PUBREC); - } + else + { + /* This message might be subscribed with wild card or not cleanSession*/ + topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; + Topic* topic = client->getTopics()->match(&topicId); - delete snPacket; - return; - } + if (topic == nullptr && client->isCleanSession()) + { + WRITELOG("%sMQTTGWPublishHandler Invalid Topic. PUBLISH message is discarded.%s\n", + ERRMSG_HEADER, ERRMSG_FOOTER); + if (pub.header.bits.qos == 1) + { + replyACK(client, &pub, PUBACK); + } + else if (pub.header.bits.qos == 2) + { + replyACK(client, &pub, PUBREC); + } - /* add the Topic and get a TopicId */ - topic = client->getTopics()->add(&topicId); - id = topic->getTopicId(); + delete snPacket; + return; + } - if (id > 0) - { - /* create REGISTER */ - MQTTSNPacket* regPacket = new MQTTSNPacket(); + if (topic == nullptr) + { + topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; + topicId.data.long_.len = pub.topiclen; + topicId.data.long_.name = pub.topic; + topicId.data.id = 0; + } - MQTTSNString topicName = MQTTSNString_initializer; - topicName.lenstring.len = topicId.data.long_.len; - topicName.lenstring.data = topicId.data.long_.name; + /* add the Topic and get a TopicId */ + topic = client->getTopics()->add(&topicId); + if (topic == nullptr) + { + WRITELOG( + "%sMQTTGWPublishHandler Can't Add a Topic. MAX_TOPIC_PAR_CLIENT is exceeded. PUBLISH message is discarded.%s\n", + ERRMSG_HEADER, ERRMSG_FOOTER); + delete snPacket; + return; + } + id = topic->getTopicId(); + if (id > 0) + { + /* create REGISTER */ + MQTTSNPacket* regPacket = new MQTTSNPacket(); - uint16_t regackMsgId = client->getNextSnMsgId(); - regPacket->setREGISTER(id, regackMsgId, &topicName); + MQTTSNString topicName = MQTTSNString_initializer; + topicName.lenstring.len = topicId.data.long_.len; + topicName.lenstring.data = topicId.data.long_.name; - /* send REGISTER */ - Event* evrg = new Event(); - evrg->setClientSendEvent(client, regPacket); - _gateway->getClientSendQue()->post(evrg); + uint16_t regackMsgId = client->getNextSnMsgId(); + regPacket->setREGISTER(id, regackMsgId, &topicName); - /* send PUBLISH */ - topicId.data.id = id; - snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, - (uint8_t) pub.header.bits.retain, (uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, - pub.payloadlen); - client->getWaitREGACKPacketList()->setPacket(snPacket, regackMsgId); - return; - } - else - { - WRITELOG("%sMQTTGWPublishHandler Can't create a Topic.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER); - delete snPacket; - return; - } - } - } + /* send REGISTER */ + Event* evrg = new Event(); + evrg->setClientSendEvent(client, regPacket); + _gateway->getClientSendQue()->post(evrg); - snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, (uint8_t) pub.header.bits.retain, - (uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, pub.payloadlen); - Event* ev1 = new Event(); - ev1->setClientSendEvent(client, snPacket); - _gateway->getClientSendQue()->post(ev1); + /* send PUBLISH */ + topicId.data.id = id; + snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, (uint8_t) pub.header.bits.retain, + (uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, pub.payloadlen); + client->getWaitREGACKPacketList()->setPacket(snPacket, regackMsgId); + return; + } + else + { + WRITELOG("%sMQTTGWPublishHandler Can't create a Topic. PUBLISH message is discarded.%s\n", + ERRMSG_HEADER, ERRMSG_FOOTER); + delete snPacket; + return; + } + } + } + + snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, (uint8_t) pub.header.bits.retain, + (uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, pub.payloadlen); + Event* ev1 = new Event(); + ev1->setClientSendEvent(client, snPacket); + _gateway->getClientSendQue()->post(ev1); } void MQTTGWPublishHandler::replyACK(Client* client, Publish* pub, int type) { - MQTTGWPacket* pubAck = new MQTTGWPacket(); - pubAck->setAck(type, (uint16_t)pub->msgId); - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, pubAck); - _gateway->getBrokerSendQue()->post(ev1); + MQTTGWPacket* pubAck = new MQTTGWPacket(); + pubAck->setAck(type, (uint16_t) pub->msgId); + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, pubAck); + _gateway->getBrokerSendQue()->post(ev1); } void MQTTGWPublishHandler::handlePuback(Client* client, MQTTGWPacket* packet) { - Ack ack; - packet->getAck(&ack); - TopicIdMapElement* topicId = client->getWaitedPubTopicId((uint16_t)ack.msgId); - if (topicId) - { - MQTTSNPacket* mqttsnPacket = new MQTTSNPacket(); - mqttsnPacket->setPUBACK(topicId->getTopicId(), (uint16_t)ack.msgId, 0); + Ack ack; + packet->getAck(&ack); + TopicIdMapElement* topicId = client->getWaitedPubTopicId((uint16_t) ack.msgId); + if (topicId) + { + MQTTSNPacket* mqttsnPacket = new MQTTSNPacket(); + mqttsnPacket->setPUBACK(topicId->getTopicId(), (uint16_t) ack.msgId, 0); - client->eraseWaitedPubTopicId((uint16_t)ack.msgId); - Event* ev1 = new Event(); - ev1->setClientSendEvent(client, mqttsnPacket); - _gateway->getClientSendQue()->post(ev1); - return; - } - WRITELOG(" PUBACK from the Broker is invalid. PacketID : %04X ClientID : %s \n", (uint16_t)ack.msgId, client->getClientId()); + client->eraseWaitedPubTopicId((uint16_t) ack.msgId); + Event* ev1 = new Event(); + ev1->setClientSendEvent(client, mqttsnPacket); + _gateway->getClientSendQue()->post(ev1); + return; + } + WRITELOG(" PUBACK from the Broker is invalid. PacketID : %04X ClientID : %s \n", (uint16_t) ack.msgId, + client->getClientId()); } void MQTTGWPublishHandler::handleAck(Client* client, MQTTGWPacket* packet, int type) { - Ack ack; - packet->getAck(&ack); + Ack ack; + packet->getAck(&ack); - if ( client->isActive() || client->isAwake() ) - { - MQTTSNPacket* mqttsnPacket = new MQTTSNPacket(); - if (type == PUBREC) - { - mqttsnPacket->setPUBREC((uint16_t) ack.msgId); - } - else if (type == PUBREL) - { - mqttsnPacket->setPUBREL((uint16_t) ack.msgId); - } - else if (type == PUBCOMP) - { - mqttsnPacket->setPUBCOMP((uint16_t) ack.msgId); - } + if (client->isActive() || client->isAwake()) + { + MQTTSNPacket* mqttsnPacket = new MQTTSNPacket(); + if (type == PUBREC) + { + mqttsnPacket->setPUBREC((uint16_t) ack.msgId); + } + else if (type == PUBREL) + { + mqttsnPacket->setPUBREL((uint16_t) ack.msgId); + } + else if (type == PUBCOMP) + { + mqttsnPacket->setPUBCOMP((uint16_t) ack.msgId); + } - Event* ev1 = new Event(); - ev1->setClientSendEvent(client, mqttsnPacket); - _gateway->getClientSendQue()->post(ev1); - } - else if ( client->isSleep() ) - { - if (type == PUBREL) - { - MQTTGWPacket* pubComp = new MQTTGWPacket(); - pubComp->setAck(PUBCOMP, (uint16_t)ack.msgId); - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, pubComp); - _gateway->getBrokerSendQue()->post(ev1); - } - } + Event* ev1 = new Event(); + ev1->setClientSendEvent(client, mqttsnPacket); + _gateway->getClientSendQue()->post(ev1); + } + else if (client->isSleep()) + { + if (type == PUBREL) + { + MQTTGWPacket* pubComp = new MQTTGWPacket(); + pubComp->setAck(PUBCOMP, (uint16_t) ack.msgId); + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, pubComp); + _gateway->getBrokerSendQue()->post(ev1); + } + } } - - void MQTTGWPublishHandler::handleAggregatePuback(Client* client, MQTTGWPacket* packet) { - uint16_t msgId = packet->getMsgId(); - uint16_t clientMsgId = 0; - Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId); - if ( newClient != nullptr ) - { - packet->setMsgId((int)clientMsgId); - handlePuback(newClient, packet); - } + uint16_t msgId = packet->getMsgId(); + uint16_t clientMsgId = 0; + Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId); + if (newClient != nullptr) + { + packet->setMsgId((int) clientMsgId); + handlePuback(newClient, packet); + } } void MQTTGWPublishHandler::handleAggregateAck(Client* client, MQTTGWPacket* packet, int type) { - uint16_t msgId = packet->getMsgId(); - uint16_t clientMsgId = 0; - Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId); - if ( newClient != nullptr ) - { - packet->setMsgId((int)clientMsgId); - handleAck(newClient, packet,type); - } + uint16_t msgId = packet->getMsgId(); + uint16_t clientMsgId = 0; + Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId); + if (newClient != nullptr) + { + packet->setMsgId((int) clientMsgId); + handleAck(newClient, packet, type); + } } void MQTTGWPublishHandler::handleAggregatePubrel(Client* client, MQTTGWPacket* packet) { - Publish pub; - packet->getPUBLISH(&pub); - replyACK(client, &pub, PUBCOMP); + Publish pub; + packet->getPUBLISH(&pub); + replyACK(client, &pub, PUBCOMP); } void MQTTGWPublishHandler::handleAggregatePublish(Client* client, MQTTGWPacket* packet) { - Publish pub; - packet->getPUBLISH(&pub); + Publish pub; + packet->getPUBLISH(&pub); + string* topicName = new string(pub.topic, pub.topiclen); // topic deletes topicName when the topic is deleted + Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); - string* topicName = new string(pub.topic, pub.topiclen); // topic deletes topicName when the topic is deleted - Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); + // ToDo: need to refactor + ClientTopicElement* elm = _gateway->getAdapterManager()->getAggregater()->getClientElement(&topic); - // ToDo: need to refactor - ClientTopicElement* elm = _gateway->getAdapterManager()->getAggregater()->getClientElement(&topic); + while (elm != nullptr) + { + Client* devClient = elm->getClient(); + MQTTGWPacket* msg = new MQTTGWPacket(); + *msg = *packet; - while ( elm != nullptr ) - { - Client* devClient = elm->getClient(); - MQTTGWPacket* msg = new MQTTGWPacket(); - *msg = *packet; + if (msg->getType() == 0) + { + WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n", + ERRMSG_HEADER, ERRMSG_FOOTER); + delete msg; + break; + } - if ( msg->getType() == 0 ) - { - WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n", ERRMSG_HEADER,ERRMSG_FOOTER); - delete msg; - break; - } + Event* ev = new Event(); + ev->setBrokerRecvEvent(devClient, msg); + _gateway->getPacketEventQue()->post(ev); - Event* ev = new Event(); - ev->setBrokerRecvEvent(devClient, msg); - _gateway->getPacketEventQue()->post(ev); - - elm = elm->getNextClientElement(); - } + elm = elm->getNextClientElement(); + } } diff --git a/MQTTSNGateway/src/MQTTGWPublishHandler.h b/MQTTSNGateway/src/MQTTGWPublishHandler.h index fee60e8..c32faee 100644 --- a/MQTTSNGateway/src/MQTTGWPublishHandler.h +++ b/MQTTSNGateway/src/MQTTGWPublishHandler.h @@ -26,25 +26,23 @@ namespace MQTTSNGW class MQTTGWPublishHandler { public: - MQTTGWPublishHandler(Gateway* gateway); - ~MQTTGWPublishHandler(); - void handlePublish(Client* client, MQTTGWPacket* packet); - void handlePuback(Client* client, MQTTGWPacket* packet); - void handleAck(Client* client, MQTTGWPacket* packet, int type); + MQTTGWPublishHandler(Gateway* gateway); + ~MQTTGWPublishHandler(); + void handlePublish(Client* client, MQTTGWPacket* packet); + void handlePuback(Client* client, MQTTGWPacket* packet); + void handleAck(Client* client, MQTTGWPacket* packet, int type); - void handleAggregatePublish(Client* client, MQTTGWPacket* packet); - void handleAggregatePuback(Client* client, MQTTGWPacket* packet); - void handleAggregateAck(Client* client, MQTTGWPacket* packet, int type); - void handleAggregatePubrel(Client* client, MQTTGWPacket* packet); + void handleAggregatePublish(Client* client, MQTTGWPacket* packet); + void handleAggregatePuback(Client* client, MQTTGWPacket* packet); + void handleAggregateAck(Client* client, MQTTGWPacket* packet, int type); + void handleAggregatePubrel(Client* client, MQTTGWPacket* packet); private: - void replyACK(Client* client, Publish* pub, int type); + void replyACK(Client* client, Publish* pub, int type); - Gateway* _gateway; + Gateway* _gateway; }; } - - #endif /* MQTTGWPUBLISHHANDLER_H_ */ diff --git a/MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp b/MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp index 2df4815..9569442 100644 --- a/MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp +++ b/MQTTSNGateway/src/MQTTGWSubscribeHandler.cpp @@ -22,7 +22,7 @@ using namespace MQTTSNGW; MQTTGWSubscribeHandler::MQTTGWSubscribeHandler(Gateway* gateway) { - _gateway = gateway; + _gateway = gateway; } MQTTGWSubscribeHandler::~MQTTGWSubscribeHandler() @@ -32,68 +32,67 @@ MQTTGWSubscribeHandler::~MQTTGWSubscribeHandler() void MQTTGWSubscribeHandler::handleSuback(Client* client, MQTTGWPacket* packet) { - uint16_t msgId; - uint8_t rc; - uint8_t returnCode; - int qos = 0; + uint16_t msgId; + uint8_t rc; + uint8_t returnCode; + int qos = 0; - packet->getSUBACK(&msgId, &rc); - TopicIdMapElement* topicId = client->getWaitedSubTopicId(msgId); + packet->getSUBACK(&msgId, &rc); + TopicIdMapElement* topicId = client->getWaitedSubTopicId(msgId); - if (topicId) - { - MQTTSNPacket* snPacket = new MQTTSNPacket(); + if (topicId) + { + MQTTSNPacket* snPacket = new MQTTSNPacket(); - if (rc == 0x80) - { - returnCode = MQTTSN_RC_REJECTED_INVALID_TOPIC_ID; - } - else - { - returnCode = MQTTSN_RC_ACCEPTED; - qos = rc; - } - snPacket->setSUBACK(qos, topicId->getTopicId(), msgId, returnCode); - Event* evt = new Event(); - evt->setClientSendEvent(client, snPacket); - _gateway->getClientSendQue()->post(evt); + if (rc == 0x80) + { + returnCode = MQTTSN_RC_REJECTED_INVALID_TOPIC_ID; + } + else + { + returnCode = MQTTSN_RC_ACCEPTED; + qos = rc; + } + snPacket->setSUBACK(qos, topicId->getTopicId(), msgId, returnCode); + Event* evt = new Event(); + evt->setClientSendEvent(client, snPacket); + _gateway->getClientSendQue()->post(evt); client->eraseWaitedSubTopicId(msgId); - } + } } void MQTTGWSubscribeHandler::handleUnsuback(Client* client, MQTTGWPacket* packet) { - Ack ack; - packet->getAck(&ack); - MQTTSNPacket* snPacket = new MQTTSNPacket(); - snPacket->setUNSUBACK(ack.msgId); - Event* evt = new Event(); - evt->setClientSendEvent(client, snPacket); - _gateway->getClientSendQue()->post(evt); + Ack ack; + packet->getAck(&ack); + MQTTSNPacket* snPacket = new MQTTSNPacket(); + snPacket->setUNSUBACK(ack.msgId); + Event* evt = new Event(); + evt->setClientSendEvent(client, snPacket); + _gateway->getClientSendQue()->post(evt); } void MQTTGWSubscribeHandler::handleAggregateSuback(Client* client, MQTTGWPacket* packet) { - uint16_t msgId = packet->getMsgId(); - uint16_t clientMsgId = 0; - Client* newClient = _gateway->getAdapterManager()->getAggregater()->convertClient(msgId, &clientMsgId); - if ( newClient != nullptr ) - { - packet->setMsgId((int)clientMsgId); - handleSuback(newClient, packet); - } + uint16_t msgId = packet->getMsgId(); + uint16_t clientMsgId = 0; + Client* newClient = _gateway->getAdapterManager()->getAggregater()->convertClient(msgId, &clientMsgId); + if (newClient != nullptr) + { + packet->setMsgId((int) clientMsgId); + handleSuback(newClient, packet); + } } void MQTTGWSubscribeHandler::handleAggregateUnsuback(Client* client, MQTTGWPacket* packet) { - uint16_t msgId = packet->getMsgId(); - uint16_t clientMsgId = 0; - Client* newClient = _gateway->getAdapterManager()->getAggregater()->convertClient(msgId, &clientMsgId); - if ( newClient != nullptr ) - { - packet->setMsgId((int)clientMsgId); - handleUnsuback(newClient, packet); - } + uint16_t msgId = packet->getMsgId(); + uint16_t clientMsgId = 0; + Client* newClient = _gateway->getAdapterManager()->getAggregater()->convertClient(msgId, &clientMsgId); + if (newClient != nullptr) + { + packet->setMsgId((int) clientMsgId); + handleUnsuback(newClient, packet); + } } - diff --git a/MQTTSNGateway/src/MQTTGWSubscribeHandler.h b/MQTTSNGateway/src/MQTTGWSubscribeHandler.h index d52b70f..7d86a3f 100644 --- a/MQTTSNGateway/src/MQTTGWSubscribeHandler.h +++ b/MQTTSNGateway/src/MQTTGWSubscribeHandler.h @@ -27,15 +27,15 @@ namespace MQTTSNGW class MQTTGWSubscribeHandler { public: - MQTTGWSubscribeHandler(Gateway* gateway); - ~MQTTGWSubscribeHandler(); - void handleSuback(Client* clnode, MQTTGWPacket* packet); - void handleUnsuback(Client* clnode, MQTTGWPacket* packet); - void handleAggregateSuback(Client* client, MQTTGWPacket* packet); - void handleAggregateUnsuback(Client* client, MQTTGWPacket* packet); + MQTTGWSubscribeHandler(Gateway* gateway); + ~MQTTGWSubscribeHandler(); + void handleSuback(Client* clnode, MQTTGWPacket* packet); + void handleUnsuback(Client* clnode, MQTTGWPacket* packet); + void handleAggregateSuback(Client* client, MQTTGWPacket* packet); + void handleAggregateUnsuback(Client* client, MQTTGWPacket* packet); private: - Gateway* _gateway; + Gateway* _gateway; }; } diff --git a/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.cpp b/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.cpp index 90672bf..8e81351 100644 --- a/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.cpp @@ -28,7 +28,7 @@ using namespace MQTTSNGW; =====================================*/ MQTTSNAggregateConnectionHandler::MQTTSNAggregateConnectionHandler(Gateway* gateway) { - _gateway = gateway; + _gateway = gateway; } MQTTSNAggregateConnectionHandler::~MQTTSNAggregateConnectionHandler() @@ -36,124 +36,121 @@ MQTTSNAggregateConnectionHandler::~MQTTSNAggregateConnectionHandler() } - /* * CONNECT */ void MQTTSNAggregateConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet) { - MQTTSNPacket_connectData data; - if ( packet->getCONNECT(&data) == 0 ) - { - return; - } + MQTTSNPacket_connectData data; + if (packet->getCONNECT(&data) == 0) + { + return; + } - /* return CONNACK when the client is sleeping */ - if ( client->isSleep() || client->isAwake() ) - { - MQTTSNPacket* packet = new MQTTSNPacket(); - packet->setCONNACK(MQTTSN_RC_ACCEPTED); - Event* ev = new Event(); - ev->setClientSendEvent(client, packet); - _gateway->getClientSendQue()->post(ev); - sendStoredPublish(client); - return; - } + /* return CONNACK when the client is sleeping */ + if (client->isSleep() || client->isAwake()) + { + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNACK(MQTTSN_RC_ACCEPTED); + Event* ev = new Event(); + ev->setClientSendEvent(client, packet); + _gateway->getClientSendQue()->post(ev); + sendStoredPublish(client); + return; + } - //* clear ConnectData of Client */ - Connect* connectData = client->getConnectData(); - memset(connectData, 0, sizeof(Connect)); + //* clear ConnectData of Client */ + Connect* connectData = client->getConnectData(); + memset(connectData, 0, sizeof(Connect)); - client->disconnected(); + client->disconnected(); - Topics* topics = client->getTopics(); + Topics* topics = client->getTopics(); - /* CONNECT was not sent yet. prepare Connect data */ + /* CONNECT was not sent yet. prepare Connect data */ + client->setSessionStatus(false); + if (data.cleansession) + { + /* reset the table of msgNo and TopicId pare */ + client->clearWaitedPubTopicId(); + client->clearWaitedSubTopicId(); - client->setSessionStatus(false); - if (data.cleansession) - { - /* reset the table of msgNo and TopicId pare */ - client->clearWaitedPubTopicId(); - client->clearWaitedSubTopicId(); + /* renew the TopicList */ + if (topics) + { + Topic* tp = topics->getFirstTopic(); + while (tp != nullptr) + { + if (tp->getType() == MQTTSN_TOPIC_TYPE_NORMAL) + { + _gateway->getAdapterManager()->getAggregater()->removeAggregateTopic(tp, client); + } + tp = topics->getNextTopic(tp); + } + topics->eraseNormal(); + } + client->setSessionStatus(true); + } - /* renew the TopicList */ - if (topics) - { - Topic* tp = topics->getFirstTopic(); - while( tp != nullptr ) - { - if ( tp->getType() == MQTTSN_TOPIC_TYPE_NORMAL ) - { - _gateway->getAdapterManager()->getAggregater()->removeAggregateTopic(tp, client); - } - tp = topics->getNextTopic(tp); - } - topics->eraseNormal(); - } - client->setSessionStatus(true); - } + if (data.willFlag) + { + /* create & send WILLTOPICREQ message to the client */ + MQTTSNPacket* reqTopic = new MQTTSNPacket(); + reqTopic->setWILLTOPICREQ(); + Event* evwr = new Event(); + evwr->setClientSendEvent(client, reqTopic); - if (data.willFlag) - { - /* create & send WILLTOPICREQ message to the client */ - MQTTSNPacket* reqTopic = new MQTTSNPacket(); - reqTopic->setWILLTOPICREQ(); - Event* evwr = new Event(); - evwr->setClientSendEvent(client, reqTopic); - - /* Send WILLTOPICREQ to the client */ - _gateway->getClientSendQue()->post(evwr); - } - else - { - /* create CONNACK & send it to the client */ - MQTTSNPacket* packet = new MQTTSNPacket(); - packet->setCONNACK(MQTTSN_RC_ACCEPTED); - Event* ev = new Event(); - ev->setClientSendEvent(client, packet); - _gateway->getClientSendQue()->post(ev); - client->connackSended(MQTTSN_RC_ACCEPTED); - sendStoredPublish(client); - return; - } + /* Send WILLTOPICREQ to the client */ + _gateway->getClientSendQue()->post(evwr); + } + else + { + /* create CONNACK & send it to the client */ + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNACK(MQTTSN_RC_ACCEPTED); + Event* ev = new Event(); + ev->setClientSendEvent(client, packet); + _gateway->getClientSendQue()->post(ev); + client->connackSended(MQTTSN_RC_ACCEPTED); + sendStoredPublish(client); + return; + } } - /* * WILLMSG */ void MQTTSNAggregateConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet) { - if ( !client->isWaitWillMsg() ) - { - DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n"); - return; - } + if (!client->isWaitWillMsg()) + { + DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n"); + return; + } - MQTTSNString willmsg = MQTTSNString_initializer; - //Connect* connectData = client->getConnectData(); + MQTTSNString willmsg = MQTTSNString_initializer; + //Connect* connectData = client->getConnectData(); - if( client->isConnectSendable() ) - { - /* save WillMsg in the client */ - if ( packet->getWILLMSG(&willmsg) == 0 ) - { - return; - } - client->setWillMsg(willmsg); + if (client->isConnectSendable()) + { + /* save WillMsg in the client */ + if (packet->getWILLMSG(&willmsg) == 0) + { + return; + } + client->setWillMsg(willmsg); - /* Send CONNACK to the client */ - MQTTSNPacket* packet = new MQTTSNPacket(); - packet->setCONNACK(MQTTSN_RC_ACCEPTED); - Event* ev = new Event(); - ev->setClientSendEvent(client, packet); - _gateway->getClientSendQue()->post(ev); + /* Send CONNACK to the client */ + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNACK(MQTTSN_RC_ACCEPTED); + Event* ev = new Event(); + ev->setClientSendEvent(client, packet); + _gateway->getClientSendQue()->post(ev); - sendStoredPublish(client); - return; - } + sendStoredPublish(client); + return; + } } /* @@ -173,31 +170,31 @@ void MQTTSNAggregateConnectionHandler::handleDisconnect(Client* client, MQTTSNPa */ void MQTTSNAggregateConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet) { - if ( ( client->isSleep() || client->isAwake() ) && client->getClientSleepPacket() ) - { - sendStoredPublish(client); - client->holdPingRequest(); - } + if ((client->isSleep() || client->isAwake()) && client->getClientSleepPacket()) + { + sendStoredPublish(client); + client->holdPingRequest(); + } - /* create and send PINGRESP to the PacketHandler */ - client->resetPingRequest(); + /* create and send PINGRESP to the PacketHandler */ + client->resetPingRequest(); - MQTTGWPacket* pingresp = new MQTTGWPacket(); + MQTTGWPacket* pingresp = new MQTTGWPacket(); - pingresp->setHeader(PINGRESP); + pingresp->setHeader(PINGRESP); - Event* evt = new Event(); - evt->setBrokerRecvEvent(client, pingresp); - _gateway->getPacketEventQue()->post(evt); + Event* evt = new Event(); + evt->setBrokerRecvEvent(client, pingresp); + _gateway->getPacketEventQue()->post(evt); } void MQTTSNAggregateConnectionHandler::sendStoredPublish(Client* client) { MQTTGWPacket* msg = nullptr; - while ( ( msg = client->getClientSleepPacket() ) != nullptr ) + while ((msg = client->getClientSleepPacket()) != nullptr) { - client->deleteFirstClientSleepPacket(); // pop the que to delete element. + client->deleteFirstClientSleepPacket(); // pop the que to delete element. Event* ev = new Event(); ev->setBrokerRecvEvent(client, msg); diff --git a/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.h b/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.h index 53282b3..15001b7 100644 --- a/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.h +++ b/MQTTSNGateway/src/MQTTSNAggregateConnectionHandler.h @@ -28,18 +28,18 @@ class MQTTSNPacket; class MQTTSNAggregateConnectionHandler { public: - MQTTSNAggregateConnectionHandler(Gateway* gateway); - ~MQTTSNAggregateConnectionHandler(void); + MQTTSNAggregateConnectionHandler(Gateway* gateway); + ~MQTTSNAggregateConnectionHandler(void); - void handleConnect(Client* client, MQTTSNPacket* packet); - void handleWillmsg(Client* client, MQTTSNPacket* packet); - void handleDisconnect(Client* client, MQTTSNPacket* packet); - void handlePingreq(Client* client, MQTTSNPacket* packet); + void handleConnect(Client* client, MQTTSNPacket* packet); + void handleWillmsg(Client* client, MQTTSNPacket* packet); + void handleDisconnect(Client* client, MQTTSNPacket* packet); + void handlePingreq(Client* client, MQTTSNPacket* packet); private: - void sendStoredPublish(Client* client); + void sendStoredPublish(Client* client); - Gateway* _gateway; + Gateway* _gateway; }; } diff --git a/MQTTSNGateway/src/MQTTSNGWAdapter.cpp b/MQTTSNGateway/src/MQTTSNGWAdapter.cpp index 2fa37b3..8e0e347 100644 --- a/MQTTSNGateway/src/MQTTSNGWAdapter.cpp +++ b/MQTTSNGateway/src/MQTTSNGWAdapter.cpp @@ -24,116 +24,114 @@ #include using namespace MQTTSNGW; - /*===================================== - Class Adapter + Class Adapter =====================================*/ -Adapter:: Adapter(Gateway* gw) +Adapter::Adapter(Gateway* gw) { - _gateway = gw; - _proxy = new Proxy(gw); - _proxySecure = new Proxy(gw); + _gateway = gw; + _proxy = new Proxy(gw); + _proxySecure = new Proxy(gw); } Adapter::~Adapter(void) { - if ( _proxy ) + if (_proxy) { delete _proxy; } - if ( _proxySecure ) - { - delete _proxySecure; - } + if (_proxySecure) + { + delete _proxySecure; + } } - void Adapter::setup(const char* adpterName, AdapterType adapterType) { _isSecure = false; - if ( _gateway->hasSecureConnection() ) + if (_gateway->hasSecureConnection()) { - _isSecure = true; + _isSecure = true; } MQTTSNString id = MQTTSNString_initializer; - MQTTSNString idSecure = MQTTSNString_initializer; + MQTTSNString idSecure = MQTTSNString_initializer; - string name = string(adpterName); - id.cstring = const_cast(name.c_str()); - string nameSecure = string(adpterName) + "-S"; - idSecure.cstring = const_cast(nameSecure.c_str()); + string name = string(adpterName); + id.cstring = const_cast(name.c_str()); + string nameSecure = string(adpterName) + "-S"; + idSecure.cstring = const_cast(nameSecure.c_str()); - Client* client = _gateway->getClientList()->createClient(0, &id, true, false, TRANSPEARENT_TYPE); - setClient(client, false); - client->setAdapterType(adapterType); + Client* client = _gateway->getClientList()->createClient(0, &id, true, false, TRANSPEARENT_TYPE); + setClient(client, false); + client->setAdapterType(adapterType); - client = _gateway->getClientList()->createClient(0, &idSecure, true, true, TRANSPEARENT_TYPE); - setClient(client, true); - client->setAdapterType(adapterType); + client = _gateway->getClientList()->createClient(0, &idSecure, true, true, + TRANSPEARENT_TYPE); + setClient(client, true); + client->setAdapterType(adapterType); } - Client* Adapter::getClient(SensorNetAddress* addr) { - Client* client = _gateway->getClientList()->getClient(addr); - if ( !client ) - { - return nullptr; - } - else if ( client->isQoSm1() ) - { - return client; - } - else - { - return nullptr; - } -} - -const char* Adapter::getClientId(SensorNetAddress* addr) -{ - Client* client = getClient(addr); - if ( !client ) + Client* client = _gateway->getClientList()->getClient(addr); + if (!client) { - return nullptr; + return nullptr; } - else if ( client->isQoSm1() ) + else if (client->isQoSm1()) { - return client->getClientId(); + return client; } else { - return nullptr; + return nullptr; + } +} + +const char* Adapter::getClientId(SensorNetAddress* addr) +{ + Client* client = getClient(addr); + if (!client) + { + return nullptr; + } + else if (client->isQoSm1()) + { + return client->getClientId(); + } + else + { + return nullptr; } } bool Adapter::isSecure(SensorNetAddress* addr) { - Client* client = getClient(addr); - if ( !client ) - { - return false; - } - else if ( client->isSecureNetwork() ) - { - return true; - } - else - { - return false; - } + Client* client = getClient(addr); + if (!client) + { + return false; + } + else if (client->isSecureNetwork()) + { + return true; + } + else + { + return false; + } } bool Adapter::isSecure(void) { - return _isSecure; + return _isSecure; } void Adapter::setClient(Client* client, bool secure) { - if ( secure ) + if (secure) { _clientSecure = client; } @@ -157,7 +155,7 @@ void Adapter::checkConnection(void) { _proxy->checkConnection(_client); - if ( _isSecure ) + if (_isSecure) { _proxySecure->checkConnection(_clientSecure); } @@ -166,15 +164,16 @@ void Adapter::checkConnection(void) void Adapter::send(MQTTSNPacket* packet, Client* client) { Proxy* proxy = _proxy; - if ( client->isSecureNetwork() && !_isSecure ) + if (client->isSecureNetwork() && !_isSecure) { - if ( _isSecure ) + if (_isSecure) { proxy = _proxySecure; } else { - WRITELOG("%s %s No Secure connections %s 's packet is discarded.%s\n", ERRMSG_HEADER, client->getClientId() , ERRMSG_FOOTER); + WRITELOG("%s %s No Secure connections %s 's packet is discarded.%s\n", + ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); return; } } @@ -185,13 +184,13 @@ void Adapter::send(MQTTSNPacket* packet, Client* client) void Adapter::resetPingTimer(bool secure) { - if ( secure ) + if (secure) { - _proxySecure->resetPingTimer(); + _proxySecure->resetPingTimer(); } else { - _proxy->resetPingTimer(); + _proxy->resetPingTimer(); } } @@ -202,48 +201,47 @@ bool Adapter::isActive(void) void Adapter::savePacket(Client* client, MQTTSNPacket* packet) { - if ( client->isSecureNetwork()) - { - _proxySecure->savePacket(client, packet); - } - else - { - _proxy->savePacket(client, packet); - } + if (client->isSecureNetwork()) + { + _proxySecure->savePacket(client, packet); + } + else + { + _proxy->savePacket(client, packet); + } } - Client* Adapter::getAdapterClient(Client* client) { - if ( client->isSecureNetwork() ) - { - return _clientSecure; - } - else - { - return _client; - } + if (client->isSecureNetwork()) + { + return _clientSecure; + } + else + { + return _client; + } } /*===================================== - Class Proxy + Class Proxy =====================================*/ Proxy::Proxy(Gateway* gw) { - _gateway = gw; - _suspendedPacketEventQue = new EventQue(); + _gateway = gw; + _suspendedPacketEventQue = new EventQue(); } Proxy::~Proxy(void) { - if ( _suspendedPacketEventQue ) - { - delete _suspendedPacketEventQue; - } + if (_suspendedPacketEventQue) + { + delete _suspendedPacketEventQue; + } } void Proxy::checkConnection(Client* client) { - if ( client->isDisconnect() || ( client->isConnecting() && _responseTimer.isTimeup()) ) + if (client->isDisconnect() || (client->isConnecting() && _responseTimer.isTimeup())) { client->connectSended(); _responseTimer.start(PROXY_RESPONSE_DURATION * 1000UL); @@ -257,26 +255,25 @@ void Proxy::checkConnection(Client* client) ev->setClientRecvEvent(client, packet); _gateway->getPacketEventQue()->post(ev); } - else if ( (client->isActive() && _keepAliveTimer.isTimeup() ) || (_isWaitingResp && _responseTimer.isTimeup() ) ) + else if ((client->isActive() && _keepAliveTimer.isTimeup()) || (_isWaitingResp && _responseTimer.isTimeup())) { - MQTTSNPacket* packet = new MQTTSNPacket(); - MQTTSNString clientId = MQTTSNString_initializer; - packet->setPINGREQ(&clientId); - Event* ev = new Event(); - ev->setClientRecvEvent(client, packet); - _gateway->getPacketEventQue()->post(ev); - _responseTimer.start(PROXY_RESPONSE_DURATION * 1000UL); - _isWaitingResp = true; + MQTTSNPacket* packet = new MQTTSNPacket(); + MQTTSNString clientId = MQTTSNString_initializer; + packet->setPINGREQ(&clientId); + Event* ev = new Event(); + ev->setClientRecvEvent(client, packet); + _gateway->getPacketEventQue()->post(ev); + _responseTimer.start(PROXY_RESPONSE_DURATION * 1000UL); + _isWaitingResp = true; - if ( ++_retryCnt > PROXY_MAX_RETRY_CNT ) - { - client->disconnected(); - } - resetPingTimer(); + if (++_retryCnt > PROXY_MAX_RETRY_CNT) + { + client->disconnected(); + } + resetPingTimer(); } } - void Proxy::resetPingTimer(void) { _keepAliveTimer.start(PROXY_KEEPALIVE_DURATION * 1000UL); @@ -284,24 +281,24 @@ void Proxy::resetPingTimer(void) void Proxy::recv(MQTTSNPacket* packet, Client* client) { - if ( packet->getType() == MQTTSN_CONNACK ) + if (packet->getType() == MQTTSN_CONNACK) { - if ( packet->isAccepted() ) - { + if (packet->isAccepted()) + { _responseTimer.stop(); _retryCnt = 0; resetPingTimer(); sendSuspendedPacket(); - } + } } - else if ( packet->getType() == MQTTSN_PINGRESP ) + else if (packet->getType() == MQTTSN_PINGRESP) { _isWaitingResp = false; _responseTimer.stop(); - _retryCnt = 0; - resetPingTimer(); + _retryCnt = 0; + resetPingTimer(); } - else if ( packet->getType() == MQTTSN_DISCONNECT ) + else if (packet->getType() == MQTTSN_DISCONNECT) { // blank } @@ -309,18 +306,18 @@ void Proxy::recv(MQTTSNPacket* packet, Client* client) void Proxy::savePacket(Client* client, MQTTSNPacket* packet) { - MQTTSNPacket* pk = new MQTTSNPacket(*packet); - Event* ev = new Event(); - ev->setClientRecvEvent(client, pk); - _suspendedPacketEventQue->post(ev); + MQTTSNPacket* pk = new MQTTSNPacket(*packet); + Event* ev = new Event(); + ev->setClientRecvEvent(client, pk); + _suspendedPacketEventQue->post(ev); } void Proxy::sendSuspendedPacket(void) { - while ( _suspendedPacketEventQue->size() ) - { - Event* ev = _suspendedPacketEventQue->wait(); - _gateway->getPacketEventQue()->post(ev); - } + while (_suspendedPacketEventQue->size()) + { + Event* ev = _suspendedPacketEventQue->wait(); + _gateway->getPacketEventQue()->post(ev); + } } diff --git a/MQTTSNGateway/src/MQTTSNGWAdapter.h b/MQTTSNGateway/src/MQTTSNGWAdapter.h index f126bf1..20c9a87 100644 --- a/MQTTSNGateway/src/MQTTSNGWAdapter.h +++ b/MQTTSNGateway/src/MQTTSNGWAdapter.h @@ -31,17 +31,18 @@ class EventQue; class Timer; /* When you add a new type, Client::setAdapterType() and Client::isAdapter() functions must be modified. */ -typedef enum{ - Atype_QoSm1Proxy, Atype_Aggregater -}AdapterType; +typedef enum +{ + Atype_QoSm1Proxy, Atype_Aggregater +} AdapterType; /*===================================== - Class Adapter + Class Adapter =====================================*/ class Adapter { public: - Adapter(Gateway* gw); + Adapter(Gateway* gw); ~Adapter(void); void setup(const char* adpterName, AdapterType adapterType); @@ -60,18 +61,17 @@ public: void savePacket(Client* client, MQTTSNPacket* packet); private: - Gateway* _gateway {nullptr}; - Proxy* _proxy {nullptr}; - Proxy* _proxySecure {nullptr}; - Client* _client {nullptr}; - Client* _clientSecure {nullptr}; - bool _isActive {false}; - bool _isSecure{false}; + Gateway* _gateway { nullptr }; + Proxy* _proxy { nullptr }; + Proxy* _proxySecure { nullptr }; + Client* _client { nullptr }; + Client* _clientSecure { nullptr }; + bool _isActive { false }; + bool _isSecure { false }; }; - /*===================================== - Class Proxy + Class Proxy =====================================*/ class Proxy { @@ -88,11 +88,12 @@ public: private: void sendSuspendedPacket(void); Gateway* _gateway; - EventQue* _suspendedPacketEventQue {nullptr}; - Timer _keepAliveTimer; - Timer _responseTimer; - bool _isWaitingResp {false}; - int _retryCnt {0}; + EventQue* _suspendedPacketEventQue + { nullptr }; + Timer _keepAliveTimer; + Timer _responseTimer; + bool _isWaitingResp { false }; + int _retryCnt { 0 }; }; } diff --git a/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp b/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp index 0d5fa55..4fb4282 100644 --- a/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp +++ b/MQTTSNGateway/src/MQTTSNGWAdapterManager.cpp @@ -33,42 +33,41 @@ char* currentDateTime(void); =====================================*/ AdapterManager::AdapterManager(Gateway* gw) { - _gateway = gw; - _forwarders = new ForwarderList(); - _qosm1Proxy = new QoSm1Proxy(gw); - _aggregater = new Aggregater(gw); + _gateway = gw; + _forwarders = new ForwarderList(); + _qosm1Proxy = new QoSm1Proxy(gw); + _aggregater = new Aggregater(gw); } - void AdapterManager::initialize(char* gwName, bool aggregate, bool forwarder, bool qosM1) { - if ( aggregate ) + if (aggregate) { - _aggregater->initialize(gwName); + _aggregater->initialize(gwName); } - if ( qosM1 ) + if (qosM1) { - _qosm1Proxy->initialize(gwName); + _qosm1Proxy->initialize(gwName); } - if ( forwarder ) + if (forwarder) { - _forwarders->initialize(_gateway); + _forwarders->initialize(_gateway); } } AdapterManager::~AdapterManager(void) { - if ( _forwarders ) + if (_forwarders) { delete _forwarders; } - if ( _qosm1Proxy ) + if (_qosm1Proxy) { delete _qosm1Proxy; } - if ( _aggregater ) + if (_aggregater) { delete _aggregater; } @@ -91,119 +90,119 @@ Aggregater* AdapterManager::getAggregater(void) bool AdapterManager::isAggregatedClient(Client* client) { - if ( !_aggregater->isActive() || client->isQoSm1() || client->isAggregater() || client->isQoSm1Proxy()) - { - return false; - } - else - { - return true; - } + if (!_aggregater->isActive() || client->isQoSm1() || client->isAggregater() || client->isQoSm1Proxy()) + { + return false; + } + else + { + return true; + } } Client* AdapterManager::getClient(Client* client) { - bool secure = client->isSecureNetwork(); - Client* newClient = client; + bool secure = client->isSecureNetwork(); + Client* newClient = client; - if ( client->isQoSm1() ) - { - newClient = _qosm1Proxy->getAdapterClient(client); - _qosm1Proxy->resetPingTimer(secure); - } - else if ( client->isAggregated() ) - { - newClient = _aggregater->getAdapterClient(client); - _aggregater->resetPingTimer(secure); - } - else if ( client->isQoSm1Proxy() ) - { - _qosm1Proxy->resetPingTimer(secure); - } - else if ( client->isAggregater() ) - { - _aggregater->resetPingTimer(secure); - } - return newClient; + if (client->isQoSm1()) + { + newClient = _qosm1Proxy->getAdapterClient(client); + _qosm1Proxy->resetPingTimer(secure); + } + else if (client->isAggregated()) + { + newClient = _aggregater->getAdapterClient(client); + _aggregater->resetPingTimer(secure); + } + else if (client->isQoSm1Proxy()) + { + _qosm1Proxy->resetPingTimer(secure); + } + else if (client->isAggregater()) + { + _aggregater->resetPingTimer(secure); + } + return newClient; } int AdapterManager::unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task) { - char pbuf[SIZE_OF_LOG_PACKET * 3]; - Forwarder* fwd = client->getForwarder(); - int rc = 0; + char pbuf[SIZE_OF_LOG_PACKET * 3]; + Forwarder* fwd = client->getForwarder(); + int rc = 0; - if ( fwd ) - { - MQTTSNGWEncapsulatedPacket encap(packet); - WirelessNodeId* wnId = fwd->getWirelessNodeId(client); - encap.setWirelessNodeId(wnId); - task->log(client, packet); - WRITELOG(FORMAT_Y_W_G, currentDateTime(), encap.getName(), RIGHTARROW, fwd->getId(), encap.print(pbuf)); - rc = encap.unicast(_gateway->getSensorNetwork(),fwd->getSensorNetAddr()); - } - else - { - task->log(client, packet); - if ( client->isQoSm1Proxy() ) - { - _qosm1Proxy->send(packet, client); - } - else if ( client->isAggregater() ) - { - _aggregater->send(packet, client); - } - else - { - rc = packet->unicast(_gateway->getSensorNetwork(), client->getSensorNetAddress()); - } - } - return rc; + if (fwd) + { + MQTTSNGWEncapsulatedPacket encap(packet); + WirelessNodeId* wnId = fwd->getWirelessNodeId(client); + encap.setWirelessNodeId(wnId); + task->log(client, packet); + WRITELOG(FORMAT_Y_W_G, currentDateTime(), encap.getName(), RIGHTARROW, fwd->getId(), encap.print(pbuf)); + rc = encap.unicast(_gateway->getSensorNetwork(), fwd->getSensorNetAddr()); + } + else + { + task->log(client, packet); + if (client->isQoSm1Proxy()) + { + _qosm1Proxy->send(packet, client); + } + else if (client->isAggregater()) + { + _aggregater->send(packet, client); + } + else + { + rc = packet->unicast(_gateway->getSensorNetwork(), client->getSensorNetAddress()); + } + } + return rc; } void AdapterManager::checkConnection(void) { - if ( _aggregater->isActive()) - { - _aggregater->checkConnection(); - } + if (_aggregater->isActive()) + { + _aggregater->checkConnection(); + } - if ( _qosm1Proxy->isActive()) - { - _qosm1Proxy->checkConnection(); - } + if (_qosm1Proxy->isActive()) + { + _qosm1Proxy->checkConnection(); + } } Client* AdapterManager::convertClient(uint16_t msgId, uint16_t* clientMsgId) { - return _aggregater->convertClient(msgId, clientMsgId); + return _aggregater->convertClient(msgId, clientMsgId); } bool AdapterManager::isAggregaterActive(void) { - return _aggregater->isActive(); + return _aggregater->isActive(); } /* -AggregateTopicElement* AdapterManager::findTopic(Topic* topic) -{ - return _aggregater->findTopic(topic); -} + AggregateTopicElement* AdapterManager::findTopic(Topic* topic) + { + return _aggregater->findTopic(topic); + } -AggregateTopicElement* AdapterManager::addAggregateTopic(Topic* topic, Client* client) -{ - return _aggregater->addAggregateTopic(topic, client); -} + AggregateTopicElement* AdapterManager::addAggregateTopic(Topic* topic, Client* client) + { + return _aggregater->addAggregateTopic(topic, client); + } -void AdapterManager::removeAggregateTopic(Topic* topic, Client* client) -{ - //_aggregater->removeAggregateTopic(topic, client); -} + void AdapterManager::removeAggregateTopic(Topic* topic, Client* client) + { + //_aggregater->removeAggregateTopic(topic, client); + } -void AdapterManager::removeAggregateTopicList(Topics* topics, Client* client) -{ + void AdapterManager::removeAggregateTopicList(Topics* topics, Client* client) + { -} -*/ + } + */ diff --git a/MQTTSNGateway/src/MQTTSNGWAdapterManager.h b/MQTTSNGateway/src/MQTTSNGWAdapterManager.h index 58e5a03..42674be 100644 --- a/MQTTSNGateway/src/MQTTSNGWAdapterManager.h +++ b/MQTTSNGateway/src/MQTTSNGWAdapterManager.h @@ -33,12 +33,12 @@ class ClientRecvTask; class ClientSendTask; /*===================================== - Class AdapterManager + Class AdapterManager =====================================*/ class AdapterManager { public: - AdapterManager(Gateway* gw); + AdapterManager(Gateway* gw); ~AdapterManager(void); void initialize(char* gwName, bool aggregater, bool fowarder, bool qosM1); ForwarderList* getForwarderList(void); @@ -49,18 +49,16 @@ public: bool isAggregatedClient(Client* client); Client* getClient(Client* client); Client* convertClient(uint16_t msgId, uint16_t* clientMsgId); - int unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task); + int unicastToClient(Client* client, MQTTSNPacket* packet, + ClientSendTask* task); bool isAggregaterActive(void); private: - Gateway* _gateway {nullptr}; - ForwarderList* _forwarders {nullptr}; - QoSm1Proxy* _qosm1Proxy {nullptr}; - Aggregater* _aggregater {nullptr}; + Gateway* _gateway { nullptr }; + ForwarderList* _forwarders { nullptr }; + QoSm1Proxy* _qosm1Proxy { nullptr }; + Aggregater* _aggregater { nullptr }; }; - - - } #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp b/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp index 24dd23f..e5703d6 100644 --- a/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp +++ b/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.cpp @@ -21,7 +21,7 @@ =====================================*/ ClientTopicElement::ClientTopicElement(Client* client) { - _client = client; + _client = client; } ClientTopicElement::~ClientTopicElement() @@ -31,12 +31,12 @@ ClientTopicElement::~ClientTopicElement() Client* ClientTopicElement::getClient(void) { - return _client; + return _client; } ClientTopicElement* ClientTopicElement::getNextClientElement(void) { - return _next; + return _next; } /*===================================== @@ -49,122 +49,122 @@ AggregateTopicElement::AggregateTopicElement(void) AggregateTopicElement::AggregateTopicElement(Topic* topic, Client* client) { - _topic = topic; - ClientTopicElement* elm = new ClientTopicElement(client); - if ( elm != nullptr ) - { - _head = elm; - _tail = elm; - } + _topic = topic; + ClientTopicElement* elm = new ClientTopicElement(client); + if (elm != nullptr) + { + _head = elm; + _tail = elm; + } } AggregateTopicElement::~AggregateTopicElement(void) { - _mutex.lock(); - if ( _head != nullptr ) - { - ClientTopicElement* p = _tail; - while ( p ) - { - ClientTopicElement* pPrev = p; - delete p; - p = pPrev->_prev; - } - _head = _tail = nullptr; - } - _mutex.unlock(); + _mutex.lock(); + if (_head != nullptr) + { + ClientTopicElement* p = _tail; + while (p) + { + ClientTopicElement* pPrev = p; + delete p; + p = pPrev->_prev; + } + _head = _tail = nullptr; + } + _mutex.unlock(); } ClientTopicElement* AggregateTopicElement::add(Client* client) { - ClientTopicElement* elm = new ClientTopicElement(client); - if ( elm == nullptr ) - { - return nullptr; - } + ClientTopicElement* elm = new ClientTopicElement(client); + if (elm == nullptr) + { + return nullptr; + } - _mutex.lock(); + _mutex.lock(); - if ( _head == nullptr ) - { - _head = elm; - _tail = elm; - } - else - { - ClientTopicElement* p = find(client); - if ( p == nullptr ) - { - p = _tail; - _tail = elm; - elm->_prev = p; - p->_next = elm; - } - else - { - delete elm; - elm = p; - } - } - _mutex.unlock(); - return elm; + if (_head == nullptr) + { + _head = elm; + _tail = elm; + } + else + { + ClientTopicElement* p = find(client); + if (p == nullptr) + { + p = _tail; + _tail = elm; + elm->_prev = p; + p->_next = elm; + } + else + { + delete elm; + elm = p; + } + } + _mutex.unlock(); + return elm; } ClientTopicElement* AggregateTopicElement::find(Client* client) { - ClientTopicElement* p = _head; - while ( p != nullptr ) - { - if ( p->_client == client) - { - break; - } - p = p->_next; - } - return p; + ClientTopicElement* p = _head; + while (p != nullptr) + { + if (p->_client == client) + { + break; + } + p = p->_next; + } + return p; } ClientTopicElement* AggregateTopicElement::getFirstClientTopicElement(void) { - return _head; + return _head; } ClientTopicElement* AggregateTopicElement::getNextClientTopicElement(ClientTopicElement* elmClient) { - return elmClient->_next; + return elmClient->_next; } void AggregateTopicElement::eraseClient(Client* client) { - _mutex.lock(); + _mutex.lock(); - ClientTopicElement* p = find(client); - if ( p != nullptr ) - { - if ( p->_prev == nullptr ) // head element - { - _head = p->_next; - if ( p->_next == nullptr ) // head & only one - { - _tail = nullptr; - } - else - { - p->_next->_prev = nullptr; // head & midle - } - } - else if ( p->_next != nullptr ) // middle - { - p->_prev->_next = p->_next; - } - else // tail - { - p->_prev->_next = nullptr; - _tail = p->_prev; - } - delete p; - } - _mutex.unlock(); + ClientTopicElement* p = find(client); + if (p != nullptr) + { + if (p->_prev == nullptr) // head element + { + _head = p->_next; + if (p->_next == nullptr) // head & only one + { + _tail = nullptr; + } + else + { + p->_next->_prev = nullptr; // head & midle + } + } + else if (p->_next != nullptr) // middle + { + p->_prev->_next = p->_next; + } + else // tail + { + p->_prev->_next = nullptr; + _tail = p->_prev; + } + delete p; + } + _mutex.unlock(); } /*===================================== @@ -183,138 +183,138 @@ AggregateTopicTable::~AggregateTopicTable() AggregateTopicElement* AggregateTopicTable::add(Topic* topic, Client* client) { - AggregateTopicElement* elm = nullptr; - _mutex.lock(); - elm = getAggregateTopicElement(topic); - if ( elm != nullptr ) - { - if ( elm->find(client) == nullptr ) - { - elm->add(client); - } - } - else - { - Topic* newTopic = topic->duplicate(); - elm = new AggregateTopicElement(newTopic, client); - if ( _head == nullptr ) - { - _head = elm; - _tail = elm; - } - else - { - elm->_prev = _tail; - _tail->_next = elm; - _tail = elm; - } - } - _mutex.unlock(); - return elm; + AggregateTopicElement* elm = nullptr; + _mutex.lock(); + elm = getAggregateTopicElement(topic); + if (elm != nullptr) + { + if (elm->find(client) == nullptr) + { + elm->add(client); + } + } + else + { + Topic* newTopic = topic->duplicate(); + elm = new AggregateTopicElement(newTopic, client); + if (_head == nullptr) + { + _head = elm; + _tail = elm; + } + else + { + elm->_prev = _tail; + _tail->_next = elm; + _tail = elm; + } + } + _mutex.unlock(); + return elm; } void AggregateTopicTable::erase(Topic* topic, Client* client) { - AggregateTopicElement* elm = nullptr; + AggregateTopicElement* elm = nullptr; - _mutex.lock(); - elm = getAggregateTopicElement(topic); + _mutex.lock(); + elm = getAggregateTopicElement(topic); - if ( elm != nullptr ) - { - elm->eraseClient(client); - } - if ( elm->_head == nullptr ) - { - erase(elm); - } - _mutex.unlock(); - return; + if (elm != nullptr) + { + elm->eraseClient(client); + } + if (elm->_head == nullptr) + { + erase(elm); + } + _mutex.unlock(); + return; } void AggregateTopicTable::erase(AggregateTopicElement* elmTopic) { - if ( elmTopic != nullptr ) - { - if ( elmTopic->_prev == nullptr ) // head element - { - _head = elmTopic->_next; - if ( elmTopic->_next == nullptr ) // head & only one - { - _tail = nullptr; - } - else - { - elmTopic->_next->_prev = nullptr; // head & midle - } - } - else if ( elmTopic->_next != nullptr ) // middle - { - elmTopic->_prev->_next = elmTopic->_next; - } - else // tail - { - elmTopic->_prev->_next = nullptr; - _tail = elmTopic->_prev; - } - delete elmTopic; - } + if (elmTopic != nullptr) + { + if (elmTopic->_prev == nullptr) // head element + { + _head = elmTopic->_next; + if (elmTopic->_next == nullptr) // head & only one + { + _tail = nullptr; + } + else + { + elmTopic->_next->_prev = nullptr; // head & midle + } + } + else if (elmTopic->_next != nullptr) // middle + { + elmTopic->_prev->_next = elmTopic->_next; + } + else // tail + { + elmTopic->_prev->_next = nullptr; + _tail = elmTopic->_prev; + } + delete elmTopic; + } } AggregateTopicElement* AggregateTopicTable::getAggregateTopicElement(Topic* topic) { - AggregateTopicElement* elm = _head; + AggregateTopicElement* elm = _head; - while( elm != nullptr ) - { - if ( elm->_topic->isMatch(topic->_topicName) ) - { - break; - } - elm = elm->_next; - } - return elm; + while (elm != nullptr) + { + if (elm->_topic->isMatch(topic->_topicName)) + { + break; + } + elm = elm->_next; + } + return elm; } ClientTopicElement* AggregateTopicTable::getClientElement(Topic* topic) { - AggregateTopicElement* elm = getAggregateTopicElement(topic); - if ( elm != nullptr ) - { - return elm->_head; - } - else - { - return nullptr; - } + AggregateTopicElement* elm = getAggregateTopicElement(topic); + if (elm != nullptr) + { + return elm->_head; + } + else + { + return nullptr; + } } void AggregateTopicTable::print(void) { - AggregateTopicElement* elm = _head; + AggregateTopicElement* elm = _head; - printf("Beginning of AggregateTopicTable\n"); - while( elm != nullptr ) - { - printf("%s\n", elm->_topic->getTopicName()->c_str()); + printf("Beginning of AggregateTopicTable\n"); + while (elm != nullptr) + { + printf("%s\n", elm->_topic->getTopicName()->c_str()); - ClientTopicElement* clElm = elm->getFirstClientTopicElement(); - Client* client = clElm->getClient(); + ClientTopicElement* clElm = elm->getFirstClientTopicElement(); + Client* client = clElm->getClient(); - while ( client != nullptr ) - { - printf(" %s\n", client->getClientId()); - clElm = clElm->getNextClientElement(); - if ( clElm != nullptr ) - { - client = clElm->getClient(); - } - else - { - client = nullptr; - } - } - elm = elm->_next; - } - printf("End of AggregateTopicTable\n"); + while (client != nullptr) + { + printf(" %s\n", client->getClientId()); + clElm = clElm->getNextClientElement(); + if (clElm != nullptr) + { + client = clElm->getClient(); + } + else + { + client = nullptr; + } + } + elm = elm->_next; + } + printf("End of AggregateTopicTable\n"); } diff --git a/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.h b/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.h index 87d9e82..6293c0d 100644 --- a/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.h +++ b/MQTTSNGateway/src/MQTTSNGWAggregateTopicTable.h @@ -35,24 +35,24 @@ class Mutex; class AggregateTopicTable { public: - AggregateTopicTable(); - ~AggregateTopicTable(); + AggregateTopicTable(); + ~AggregateTopicTable(); - AggregateTopicElement* add(Topic* topic, Client* client); - AggregateTopicElement* getAggregateTopicElement(Topic* topic); - ClientTopicElement* getClientElement(Topic* topic); - void erase(Topic* topic, Client* client); - void clear(void); + AggregateTopicElement* add(Topic* topic, Client* client); + AggregateTopicElement* getAggregateTopicElement(Topic* topic); + ClientTopicElement* getClientElement(Topic* topic); + void erase(Topic* topic, Client* client); + void clear(void); - void print(void); + void print(void); private: - void erase(AggregateTopicElement* elmTopic); - Mutex _mutex; - AggregateTopicElement* _head {nullptr}; - AggregateTopicElement* _tail {nullptr}; - int _cnt {0}; - int _maxSize {MAX_MESSAGEID_TABLE_SIZE}; + void erase(AggregateTopicElement* elmTopic); + Mutex _mutex; + AggregateTopicElement* _head { nullptr }; + AggregateTopicElement* _tail { nullptr }; + int _cnt { 0 }; + int _maxSize { MAX_MESSAGEID_TABLE_SIZE }; }; /*===================================== @@ -68,17 +68,18 @@ public: ClientTopicElement* add(Client* client); ClientTopicElement* getFirstClientTopicElement(void); - ClientTopicElement* getNextClientTopicElement(ClientTopicElement* elmClient); + ClientTopicElement* getNextClientTopicElement( + ClientTopicElement* elmClient); void eraseClient(Client* client); ClientTopicElement* find(Client* client); private: Mutex _mutex; - Topic* _topic {nullptr}; - AggregateTopicElement* _next {nullptr}; - AggregateTopicElement* _prev {nullptr}; - ClientTopicElement* _head {nullptr}; - ClientTopicElement* _tail {nullptr}; + Topic* _topic { nullptr }; + AggregateTopicElement* _next { nullptr }; + AggregateTopicElement* _prev { nullptr }; + ClientTopicElement* _head { nullptr }; + ClientTopicElement* _tail { nullptr }; }; /*===================================== @@ -96,13 +97,11 @@ public: Client* getClient(void); private: - Client* _client {nullptr}; - ClientTopicElement* _next {nullptr}; - ClientTopicElement* _prev {nullptr}; + Client* _client { nullptr }; + ClientTopicElement* _next { nullptr }; + ClientTopicElement* _prev { nullptr }; }; } - - #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATETOPICTABLE_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWAggregater.cpp b/MQTTSNGateway/src/MQTTSNGWAggregater.cpp index 93718db..17da79f 100644 --- a/MQTTSNGateway/src/MQTTSNGWAggregater.cpp +++ b/MQTTSNGateway/src/MQTTSNGWAggregater.cpp @@ -26,9 +26,10 @@ using namespace MQTTSNGW; -Aggregater::Aggregater(Gateway* gw) : Adapter(gw) +Aggregater::Aggregater(Gateway* gw) : + Adapter(gw) { - _gateway = gw; + _gateway = gw; } Aggregater::~Aggregater(void) @@ -38,10 +39,10 @@ Aggregater::~Aggregater(void) void Aggregater::initialize(char* gwName) { - /* Create Aggregater Client */ - string name = string(gwName) + string("_Aggregater"); - setup(name.c_str(), Atype_Aggregater); - _isActive = true; + /* Create Aggregater Client */ + string name = string(gwName) + string("_Aggregater"); + setup(name.c_str(), Atype_Aggregater); + _isActive = true; //testMessageIdTable(); @@ -49,100 +50,98 @@ void Aggregater::initialize(char* gwName) bool Aggregater::isActive(void) { - return _isActive; + return _isActive; } uint16_t Aggregater::msgId(void) { - // Only SecureClient generates msgId to avoid duplication of msgId. Client does not generate it. - return Adapter::getSecureClient()->getNextPacketId(); + // Only SecureClient generates msgId to avoid duplication of msgId. Client does not generate it. + return Adapter::getSecureClient()->getNextPacketId(); } Client* Aggregater::convertClient(uint16_t msgId, uint16_t* clientMsgId) { - return _msgIdTable.getClientMsgId(msgId, clientMsgId); + return _msgIdTable.getClientMsgId(msgId, clientMsgId); } - uint16_t Aggregater::addMessageIdTable(Client* client, uint16_t msgId) { - /* set Non secure client`s nextMsgId. otherwise Id is duplicated.*/ + /* set Non secure client`s nextMsgId. otherwise Id is duplicated.*/ - MessageIdElement* elm = _msgIdTable.add(this, client, msgId); - if ( elm == nullptr ) - { - return 0; - } - else - { - return elm->_msgId; - } + MessageIdElement* elm = _msgIdTable.add(this, client, msgId); + if (elm == nullptr) + { + return 0; + } + else + { + return elm->_msgId; + } } uint16_t Aggregater::getMsgId(Client* client, uint16_t clientMsgId) { - return _msgIdTable.getMsgId(client, clientMsgId); + return _msgIdTable.getMsgId(client, clientMsgId); } AggregateTopicElement* Aggregater::addAggregateTopic(Topic* topic, Client* client) { - return _topicTable.add(topic, client); + return _topicTable.add(topic, client); } - void Aggregater::removeAggregateTopic(Topic* topic, Client* client) { - _topicTable.erase(topic, client); + _topicTable.erase(topic, client); } AggregateTopicElement* Aggregater::findTopic(Topic* topic) { - return _topicTable.getAggregateTopicElement(topic); + return _topicTable.getAggregateTopicElement(topic); } ClientTopicElement* Aggregater::getClientElement(Topic* topic) { - AggregateTopicElement* elm = findTopic(topic); - if ( elm != nullptr ) - { - return elm->getFirstClientTopicElement(); - } - else - { - return nullptr; - } + AggregateTopicElement* elm = findTopic(topic); + if (elm != nullptr) + { + return elm->getFirstClientTopicElement(); + } + else + { + return nullptr; + } } void Aggregater::printAggregateTopicTable(void) { - _topicTable.print(); + _topicTable.print(); } bool Aggregater::testMessageIdTable(void) { - Client* client = new Client(); - uint16_t msgId = 0; + Client* client = new Client(); + uint16_t msgId = 0; - printf("msgId=%d\n", addMessageIdTable(client,1)); - printf("msgId=%d\n", addMessageIdTable(client,2)); - printf("msgId=%d\n", addMessageIdTable(client,3)); - printf("msgId=%d\n", addMessageIdTable(client,1)); - printf("msgId=%d\n", addMessageIdTable(client,2)); - printf("msgId=%d\n", addMessageIdTable(client,3)); - printf("msgId=%d\n", addMessageIdTable(client,4)); - printf("msgId=%d\n", addMessageIdTable(client,4)); - printf("msgId=%d\n", addMessageIdTable(client,4)); + printf("msgId=%d\n", addMessageIdTable(client, 1)); + printf("msgId=%d\n", addMessageIdTable(client, 2)); + printf("msgId=%d\n", addMessageIdTable(client, 3)); + printf("msgId=%d\n", addMessageIdTable(client, 1)); + printf("msgId=%d\n", addMessageIdTable(client, 2)); + printf("msgId=%d\n", addMessageIdTable(client, 3)); + printf("msgId=%d\n", addMessageIdTable(client, 4)); + printf("msgId=%d\n", addMessageIdTable(client, 4)); + printf("msgId=%d\n", addMessageIdTable(client, 4)); - convertClient(1,&msgId); - printf("msgId=%d\n",msgId); - convertClient(2,&msgId); - printf("msgId=%d\n",msgId); - convertClient(5,&msgId); - printf("msgId=%d\n",msgId); - convertClient(4,&msgId); - printf("msgId=%d\n",msgId); - convertClient(3,&msgId); - printf("msgId=%d\n",msgId); - return true; + convertClient(1, &msgId); + printf("msgId=%d\n", msgId); + convertClient(2, &msgId); + printf("msgId=%d\n", msgId); + convertClient(5, &msgId); + printf("msgId=%d\n", msgId); + convertClient(4, &msgId); + printf("msgId=%d\n", msgId); + convertClient(3, &msgId); + printf("msgId=%d\n", msgId); + return true; } diff --git a/MQTTSNGateway/src/MQTTSNGWAggregater.h b/MQTTSNGateway/src/MQTTSNGWAggregater.h index 959ff87..490b71f 100644 --- a/MQTTSNGateway/src/MQTTSNGWAggregater.h +++ b/MQTTSNGateway/src/MQTTSNGWAggregater.h @@ -32,11 +32,11 @@ class AggregateTopicTable; class Topics; /*===================================== - Class Aggregater + Class Aggregater =====================================*/ -class Aggregater : public Adapter +class Aggregater: public Adapter { - friend class MessageIdTable; + friend class MessageIdTable; public: Aggregater(Gateway* gw); ~Aggregater(void); @@ -44,39 +44,35 @@ public: void initialize(char* gwName); const char* getClientId(SensorNetAddress* addr); - Client* getClient(SensorNetAddress* addr); - Client* convertClient(uint16_t msgId, uint16_t* clientMsgId); - uint16_t addMessageIdTable(Client* client, uint16_t msgId); - uint16_t getMsgId(Client* client, uint16_t clientMsgId); + Client* getClient(SensorNetAddress* addr); + Client* convertClient(uint16_t msgId, uint16_t* clientMsgId); + uint16_t addMessageIdTable(Client* client, uint16_t msgId); + uint16_t getMsgId(Client* client, uint16_t clientMsgId); - ClientTopicElement* getClientElement(Topic* topic); - ClientTopicElement* getNextClientElement(ClientTopicElement* clientElement); - Client* getClient(ClientTopicElement* clientElement); + ClientTopicElement* getClientElement(Topic* topic); + ClientTopicElement* getNextClientElement(ClientTopicElement* clientElement); + Client* getClient(ClientTopicElement* clientElement); - AggregateTopicElement* findTopic(Topic* topic); - AggregateTopicElement* addAggregateTopic(Topic* topic, Client* client); + AggregateTopicElement* findTopic(Topic* topic); + AggregateTopicElement* addAggregateTopic(Topic* topic, Client* client); - void removeAggregateTopic(Topic* topic, Client* client); - void removeAggregateAllTopic(Client* client); - bool isActive(void); + void removeAggregateTopic(Topic* topic, Client* client); + void removeAggregateAllTopic(Client* client); + bool isActive(void); - void printAggregateTopicTable(void); - bool testMessageIdTable(void); + void printAggregateTopicTable(void); + bool testMessageIdTable(void); private: - uint16_t msgId(void); - Gateway* _gateway {nullptr}; + uint16_t msgId(void); + Gateway* _gateway { nullptr }; MessageIdTable _msgIdTable; AggregateTopicTable _topicTable; - bool _isActive {false}; - bool _isSecure {false}; + bool _isActive { false }; + bool _isSecure { false }; }; - - } - - #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATER_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp index 99b0ce5..b702ab5 100644 --- a/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.cpp @@ -17,6 +17,7 @@ #include "MQTTSNGWBrokerRecvTask.h" #include "MQTTSNGWClient.h" #include "MQTTSNGWClientList.h" +#include "MQTTSNGateway.h" #include using namespace std; @@ -29,14 +30,14 @@ char* currentDateTime(void); =====================================*/ BrokerRecvTask::BrokerRecvTask(Gateway* gateway) { - _gateway = gateway; - _gateway->attach((Thread*)this); - _light = nullptr; + _gateway = gateway; + _gateway->attach((Thread*) this); + _light = nullptr; + setTaskName("BrokerRecvTask"); } BrokerRecvTask::~BrokerRecvTask() { - } /** @@ -44,7 +45,7 @@ BrokerRecvTask::~BrokerRecvTask() */ void BrokerRecvTask::initialize(int argc, char** argv) { - _light = _gateway->getLightIndicator(); + _light = _gateway->getLightIndicator(); } /** @@ -52,133 +53,130 @@ void BrokerRecvTask::initialize(int argc, char** argv) */ void BrokerRecvTask::run(void) { - struct timeval timeout; - MQTTGWPacket* packet = nullptr; - int rc; - Event* ev = nullptr; - fd_set rset; - fd_set wset; + struct timeval timeout; + MQTTGWPacket* packet = nullptr; + int rc; + Event* ev = nullptr; + fd_set rset; + fd_set wset; - while (true) - { - _light->blueLight(false); - if (CHK_SIGINT) - { - WRITELOG("\n%s BrokerRecvTask stopped.", currentDateTime()); - return; - } - timeout.tv_sec = 0; - timeout.tv_usec = 500000; // 500 msec - FD_ZERO(&rset); - FD_ZERO(&wset); - int maxSock = 0; - int sockfd = 0; + while (true) + { + _light->blueLight(false); + if (CHK_SIGINT) + { + WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName()); + return; + } + timeout.tv_sec = 0; + timeout.tv_usec = 500000; // 500 msec + FD_ZERO(&rset); + FD_ZERO(&wset); + int maxSock = 0; + int sockfd = 0; - /* Prepare sockets list to read */ - Client* client = _gateway->getClientList()->getClient(0); + /* Prepare sockets list to read */ + Client* client = _gateway->getClientList()->getClient(0); - while ( client ) - { - if (client->getNetwork()->isValid()) - { - sockfd = client->getNetwork()->getSock(); - FD_SET(sockfd, &rset); - FD_SET(sockfd, &wset); - if (sockfd > maxSock) - { - maxSock = sockfd; - } - } - client = client->getNextClient(); - } + while (client) + { + if (client->getNetwork()->isValid()) + { + sockfd = client->getNetwork()->getSock(); + FD_SET(sockfd, &rset); + FD_SET(sockfd, &wset); + if (sockfd > maxSock) + { + maxSock = sockfd; + } + } + client = client->getNextClient(); + } - if (maxSock == 0) - { - usleep(500 * 1000); - } - else - { - /* Check sockets is ready to read */ - int activity = select(maxSock + 1, &rset, 0, 0, &timeout); - if (activity > 0) - { - client = _gateway->getClientList()->getClient(0); + if (maxSock == 0) + { + usleep(500 * 1000); + } + else + { + /* Check sockets is ready to read */ + int activity = select(maxSock + 1, &rset, 0, 0, &timeout); - while ( client ) - { - _light->blueLight(false); - if (client->getNetwork()->isValid()) - { - int sockfd = client->getNetwork()->getSock(); - if (FD_ISSET(sockfd, &rset)) - { - packet = new MQTTGWPacket(); - rc = 0; - /* read sockets */ - _light->blueLight(true); - rc = packet->recv(client->getNetwork()); - if ( rc > 0 ) - { - if ( log(client, packet) == -1 ) - { - delete packet; - goto nextClient; - } + if (activity > 0) + { + client = _gateway->getClientList()->getClient(0); - /* post a BrokerRecvEvent */ - ev = new Event(); - ev->setBrokerRecvEvent(client, packet); - _gateway->getPacketEventQue()->post(ev); - } - else - { - if ( rc == 0 ) // Disconnected - { - client->getNetwork()->close(); - delete packet; + while (client) + { + _light->blueLight(false); + if (client->getNetwork()->isValid()) + { + int sockfd = client->getNetwork()->getSock(); + if (FD_ISSET(sockfd, &rset)) + { + packet = new MQTTGWPacket(); + rc = 0; + /* read sockets */ + _light->blueLight(true); + rc = packet->recv(client->getNetwork()); + if (rc > 0) + { + if (log(client, packet) == -1) + { + delete packet; + goto nextClient; + } - /* delete client when the client is not authorized & session is clean */ - _gateway->getClientList()->erase(client); + /* post a BrokerRecvEvent */ + ev = new Event(); + ev->setBrokerRecvEvent(client, packet); + _gateway->getPacketEventQue()->post(ev); + } + else + { + if (rc == 0) // Disconnected + { + WRITELOG("%s BrokerRecvTask %s is disconnected by the broker.%s\n", + ERRMSG_HEADER, client->getClientId(), + ERRMSG_FOOTER); + client->getNetwork()->close(); + client->disconnected(); + } + else if (rc == -1) + { + WRITELOG("%s BrokerRecvTask can't receive a packet from the broker errno=%d %s%s\n", + ERRMSG_HEADER, errno, client->getClientId(), + ERRMSG_FOOTER); + } + else if (rc == -2) + { + WRITELOG( + "%s BrokerRecvTask receive invalid length of packet from the broker. DISCONNECT %s %s\n", + ERRMSG_HEADER, client->getClientId(), + ERRMSG_FOOTER); + } + else if (rc == -3) + { + WRITELOG("%s BrokerRecvTask can't allocate memories for the packet %s%s\n", + ERRMSG_HEADER, client->getClientId(), + ERRMSG_FOOTER); + } - if ( client ) - { - client = client->getNextClient(); - } - continue; - } - else if (rc == -1) - { - WRITELOG("%s BrokerRecvTask can't receive a packet from the broker errno=%d %s%s\n", ERRMSG_HEADER, errno, client->getClientId(), ERRMSG_FOOTER); - } - else if ( rc == -2 ) - { - WRITELOG("%s BrokerRecvTask receive invalid length of packet from the broker. DISCONNECT %s %s\n", ERRMSG_HEADER, client->getClientId(),ERRMSG_FOOTER); - } - else if ( rc == -3 ) - { - WRITELOG("%s BrokerRecvTask can't get memories for the packet %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - } + delete packet; - delete packet; - - if ( (rc == -1 || rc == -2) && ( client->isActive() || client->isSleep() || client->isAwake() )) - { - /* disconnect the client */ - packet = new MQTTGWPacket(); - packet->setHeader(DISCONNECT); - ev = new Event(); - ev->setBrokerRecvEvent(client, packet); - _gateway->getPacketEventQue()->post(ev); - } - } - } - } - nextClient: - client = client->getNextClient(); - } - } - } - } + if ((rc == -1 || rc == -2) && (client->isActive() || client->isSleep() || client->isAwake())) + { + client->getNetwork()->close(); + client->disconnected(); + } + } + } + } + nextClient: client = client->getNextClient(); + } + } + } + } } /** @@ -186,35 +184,38 @@ void BrokerRecvTask::run(void) */ int BrokerRecvTask::log(Client* client, MQTTGWPacket* packet) { - char pbuf[(SIZE_OF_LOG_PACKET + 5 )* 3]; - char msgId[6]; - int rc = 0; + char pbuf[(SIZE_OF_LOG_PACKET + 5) * 3]; + char msgId[6]; + int rc = 0; - switch (packet->getType()) - { - case CONNACK: - WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROWB, client->getClientId(), packet->print(pbuf)); - break; - case PUBLISH: - WRITELOG(FORMAT_W_MSGID_Y_W_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, client->getClientId(), packet->print(pbuf)); - break; - case PUBACK: - case PUBREC: - case PUBREL: - case PUBCOMP: - WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, client->getClientId(), packet->print(pbuf)); - break; - case SUBACK: - case UNSUBACK: - WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, client->getClientId(), packet->print(pbuf)); - break; - case PINGRESP: - WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROWB, client->getClientId(), packet->print(pbuf)); - break; - default: - WRITELOG("Type=%x\n", packet->getType()); - rc = -1; - break; - } - return rc; + switch (packet->getType()) + { + case CONNACK: + WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROWB, client->getClientId(), packet->print(pbuf)); + break; + case PUBLISH: + WRITELOG(FORMAT_W_MSGID_Y_W_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, + client->getClientId(), packet->print(pbuf)); + break; + case PUBACK: + case PUBREC: + case PUBREL: + case PUBCOMP: + WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, + client->getClientId(), packet->print(pbuf)); + break; + case SUBACK: + case UNSUBACK: + WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB, + client->getClientId(), packet->print(pbuf)); + break; + case PINGRESP: + WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROWB, client->getClientId(), packet->print(pbuf)); + break; + default: + WRITELOG("Type=%x\n", packet->getType()); + rc = -1; + break; + } + return rc; } diff --git a/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.h b/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.h index 4177015..ae532b7 100644 --- a/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.h +++ b/MQTTSNGateway/src/MQTTSNGWBrokerRecvTask.h @@ -28,21 +28,20 @@ namespace MQTTSNGW class BrokerRecvTask: public Thread { MAGIC_WORD_FOR_THREAD; - ; + public: - BrokerRecvTask(Gateway* gateway); - ~BrokerRecvTask(); - void initialize(int argc, char** argv); - void run(void); + BrokerRecvTask(Gateway* gateway); + ~BrokerRecvTask(); + void initialize(int argc, char** argv); + void run(void); private: - int log(Client*, MQTTGWPacket*); + int log(Client*, MQTTGWPacket*); - Gateway* _gateway; - LightIndicator* _light; + Gateway* _gateway; + LightIndicator* _light; }; } - #endif /* MQTTSNGWBROKERRECVTASK_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp b/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp index ff58a8d..e061d0c 100644 --- a/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.cpp @@ -33,15 +33,15 @@ char* currentDateTime(); =====================================*/ BrokerSendTask::BrokerSendTask(Gateway* gateway) { - _gateway = gateway; - _gateway->attach((Thread*)this); - _gwparams = nullptr; - _light = nullptr; + _gateway = gateway; + _gateway->attach((Thread*) this); + _gwparams = nullptr; + _light = nullptr; + setTaskName("BrokerSendTask"); } BrokerSendTask::~BrokerSendTask() { -// WRITELOG("BrokerSendTask is deleted normally.\r\n"); } /** @@ -49,8 +49,8 @@ BrokerSendTask::~BrokerSendTask() */ void BrokerSendTask::initialize(int argc, char** argv) { - _gwparams = _gateway->getGWParams(); - _light = _gateway->getLightIndicator(); + _gwparams = _gateway->getGWParams(); + _light = _gateway->getLightIndicator(); } /** @@ -58,132 +58,137 @@ void BrokerSendTask::initialize(int argc, char** argv) */ void BrokerSendTask::run() { - Event* ev = nullptr; - MQTTGWPacket* packet = nullptr; - Client* client = nullptr; - AdapterManager* adpMgr = _gateway->getAdapterManager(); - int rc = 0; + Event* ev = nullptr; + MQTTGWPacket* packet = nullptr; + Client* client = nullptr; + AdapterManager* adpMgr = _gateway->getAdapterManager(); + int rc = 0; - while (true) - { - ev = _gateway->getBrokerSendQue()->wait(); + while (true) + { + ev = _gateway->getBrokerSendQue()->wait(); - if ( ev->getEventType() == EtStop ) - { - WRITELOG("\n%s BrokerSendTask stopped.", currentDateTime()); - delete ev; - return; - } + if (ev->getEventType() == EtStop) + { + WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName()); + delete ev; + return; + } - if ( ev->getEventType() == EtBrokerSend) - { - client = ev->getClient(); - packet = ev->getMQTTGWPacket(); + if (ev->getEventType() == EtBrokerSend) + { + client = ev->getClient(); + packet = ev->getMQTTGWPacket(); - /* Check Client is managed by Adapters */ - client = adpMgr->getClient(client); + /* Check Client is managed by Adapters */ + client = adpMgr->getClient(client); - if ( packet->getType() == CONNECT && client->getNetwork()->isValid() ) - { - client->getNetwork()->close(); - } + if (packet->getType() == CONNECT && client->getNetwork()->isValid()) + { + client->getNetwork()->close(); + } - if ( !client->getNetwork()->isValid() ) - { - /* connect to the broker and send a packet */ + if (!client->getNetwork()->isValid()) + { + /* connect to the broker and send a packet */ - if (client->isSecureNetwork()) - { - rc = client->getNetwork()->connect((const char*)_gwparams->brokerName, (const char*)_gwparams->portSecure, (const char*)_gwparams->rootCApath, - (const char*)_gwparams->rootCAfile, (const char*)_gwparams->certKey, (const char*)_gwparams->privateKey); - } - else - { - rc = client->getNetwork()->connect((const char*)_gwparams->brokerName, (const char*)_gwparams->port); - } + if (client->isSecureNetwork()) + { + rc = client->getNetwork()->connect((const char*) _gwparams->brokerName, (const char*) _gwparams->portSecure, + (const char*) _gwparams->rootCApath, (const char*) _gwparams->rootCAfile, + (const char*) _gwparams->certKey, (const char*) _gwparams->privateKey); + } + else + { + rc = client->getNetwork()->connect((const char*) _gwparams->brokerName, (const char*) _gwparams->port); + } - if ( !rc ) - { - /* disconnect the broker and the client */ - WRITELOG("%s BrokerSendTask: %s can't connect to the broker. errno=%d %s %s\n", - ERRMSG_HEADER, client->getClientId(), errno, strerror(errno), ERRMSG_FOOTER); - delete ev; - client->getNetwork()->close(); - continue; - } - } + if (!rc) + { + /* disconnect the broker and the client */ + WRITELOG("%s BrokerSendTask: %s can't connect to the broker. errno=%d %s %s\n", + ERRMSG_HEADER, client->getClientId(), errno, strerror(errno), ERRMSG_FOOTER); + delete ev; + client->getNetwork()->close(); + continue; + } + } - /* send a packet */ - _light->blueLight(true); - if ( (rc = packet->send(client->getNetwork())) > 0 ) - { - if ( packet->getType() == CONNECT ) - { - client->connectSended(); - } - else if ( packet->getType() == DISCONNECT ) - { - client->getNetwork()->close(); - client->disconnected(); - } - log(client, packet); - } - else - { - WRITELOG("%s BrokerSendTask: %s can't send a packet to the broker. errno=%d %s %s\n", - ERRMSG_HEADER, client->getClientId(), rc == -1 ? errno : 0, strerror(errno), ERRMSG_FOOTER); - if ( errno != EBADF ) - { - client->getNetwork()->close(); - } + /* send a packet */ + _light->blueLight(true); + if ((rc = packet->send(client->getNetwork())) > 0) + { + if (packet->getType() == CONNECT) + { + client->connectSended(); + } + else if (packet->getType() == DISCONNECT) + { + client->getNetwork()->close(); + client->disconnected(); + } + log(client, packet); + } + else + { + WRITELOG("%s BrokerSendTask: %s can't send a packet to the broker. errno=%d %s %s\n", + ERRMSG_HEADER, client->getClientId(), rc == -1 ? errno : 0, strerror(errno), ERRMSG_FOOTER); + if ( errno != EBADF) + { + client->getNetwork()->close(); + } - /* Disconnect the client */ - packet = new MQTTGWPacket(); - packet->setHeader(DISCONNECT); - Event* ev1 = new Event(); - ev1->setBrokerRecvEvent(client, packet); - _gateway->getPacketEventQue()->post(ev1); - } + /* Disconnect the client */ + packet = new MQTTGWPacket(); + packet->setHeader(DISCONNECT); + Event* ev1 = new Event(); + ev1->setBrokerRecvEvent(client, packet); + _gateway->getPacketEventQue()->post(ev1); + } - _light->blueLight(false); - } - delete ev; - } + _light->blueLight(false); + } + delete ev; + } } - /** * write message content into stdout or Ringbuffer */ void BrokerSendTask::log(Client* client, MQTTGWPacket* packet) { - char pbuf[(SIZE_OF_LOG_PACKET + 5 )* 3]; - char msgId[6]; + char pbuf[(SIZE_OF_LOG_PACKET + 5) * 3]; + char msgId[6]; - switch (packet->getType()) - { - case CONNECT: - WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROWB, client->getClientId(), packet->print(pbuf)); - break; - case PUBLISH: - WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB, client->getClientId(), packet->print(pbuf)); - break; - case SUBSCRIBE: - case UNSUBSCRIBE: - case PUBACK: - case PUBREC: - case PUBREL: - case PUBCOMP: - WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB, client->getClientId(), packet->print(pbuf)); - break; - case PINGREQ: - WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROWB, client->getClientId(), packet->print(pbuf)); - break; - case DISCONNECT: - WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROWB, client->getClientId(), packet->print(pbuf)); - break; - default: - break; - } + switch (packet->getType()) + { + case CONNECT: + WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), + RIGHTARROWB, client->getClientId(), packet->print(pbuf)); + break; + case PUBLISH: + WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB, + client->getClientId(), packet->print(pbuf)); + break; + case SUBSCRIBE: + case UNSUBSCRIBE: + case PUBACK: + case PUBREC: + case PUBREL: + case PUBCOMP: + WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB, + client->getClientId(), packet->print(pbuf)); + break; + case PINGREQ: + WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), + RIGHTARROWB, client->getClientId(), packet->print(pbuf)); + break; + case DISCONNECT: + WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), + RIGHTARROWB, client->getClientId(), packet->print(pbuf)); + break; + default: + break; + } } diff --git a/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h b/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h index 8244112..7361692 100644 --- a/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h +++ b/MQTTSNGateway/src/MQTTSNGWBrokerSendTask.h @@ -25,22 +25,22 @@ namespace MQTTSNGW class Adapter; /*===================================== - Class BrokerSendTask + Class BrokerSendTask =====================================*/ -class BrokerSendTask : public Thread +class BrokerSendTask: public Thread { - MAGIC_WORD_FOR_THREAD; - friend AdapterManager; +MAGIC_WORD_FOR_THREAD; + friend AdapterManager; public: - BrokerSendTask(Gateway* gateway); - ~BrokerSendTask(); - void initialize(int argc, char** argv); - void run(); + BrokerSendTask(Gateway* gateway); + ~BrokerSendTask(); + void initialize(int argc, char** argv); + void run(); private: - void log(Client*, MQTTGWPacket*); - Gateway* _gateway; - GatewayParams* _gwparams; - LightIndicator* _light; + void log(Client*, MQTTGWPacket*); + Gateway* _gateway; + GatewayParams* _gwparams; + LightIndicator* _light; }; } diff --git a/MQTTSNGateway/src/MQTTSNGWClient.cpp b/MQTTSNGateway/src/MQTTSNGWClient.cpp index 746f1af..594ac1e 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClient.cpp @@ -28,104 +28,104 @@ using namespace MQTTSNGW; char* currentDateTime(void); - /*===================================== Class Client =====================================*/ -static const char* theClientStatus[] = { "Disconnected", "TryConnecting", "Connecting", "Active", "Asleep", "Awake", "Lost" }; +static const char* theClientStatus[] = { "InPool", "Disconnected", "TryConnecting", "Connecting", "Active", "Asleep", "Awake", + "Lost" }; Client::Client(bool secure) { - _packetId = 0; - _snMsgId = 0; - _status = Cstat_Disconnected; - _keepAliveMsec = 0; - _topics = new Topics(); - _clientId = nullptr; - _willTopic = nullptr; - _willMsg = nullptr; - _connectData = MQTTPacket_Connect_Initializer; - _network = new Network(secure); - _secureNetwork = secure; - _sensorNetype = true; - _connAck = nullptr; - _waitWillMsgFlg = false; - _sessionStatus = false; - _prevClient = nullptr; - _nextClient = nullptr; - _clientSleepPacketQue.setMaxSize(MAX_SAVED_PUBLISH); - _proxyPacketQue.setMaxSize(MAX_SAVED_PUBLISH); - _hasPredefTopic = false; - _holdPingRequest = false; - _forwarder = nullptr; - _clientType = Ctype_Regular; + _packetId = 0; + _snMsgId = 0; + _status = Cstat_Free; + _keepAliveMsec = 0; + _topics = new Topics(); + _clientId = nullptr; + _willTopic = nullptr; + _willMsg = nullptr; + _connectData = MQTTPacket_Connect_Initializer; + _network = new Network(secure); + _secureNetwork = secure; + _sensorNetype = true; + _connAck = nullptr; + _waitWillMsgFlg = false; + _sessionStatus = false; + _prevClient = nullptr; + _nextClient = nullptr; + _clientSleepPacketQue.setMaxSize(MAX_SAVED_PUBLISH); + _proxyPacketQue.setMaxSize(MAX_SAVED_PUBLISH); + _hasPredefTopic = false; + _holdPingRequest = false; + _forwarder = nullptr; + _clientType = Ctype_Normal; } Client::~Client() { - if ( _topics ) - { - delete _topics; - } + if (_topics) + { + delete _topics; + } - if ( _clientId ) - { - free(_clientId); - } + if (_clientId) + { + free(_clientId); + } - if ( _willTopic ) - { - free(_willTopic); - } + if (_willTopic) + { + free(_willTopic); + } - if ( _willMsg ) - { - free(_willMsg); - } + if (_willMsg) + { + free(_willMsg); + } - if (_connAck) - { - delete _connAck; - } + if (_connAck) + { + delete _connAck; + } - if (_network) - { - delete _network; - } + if (_network) + { + delete _network; + } } TopicIdMapElement* Client::getWaitedPubTopicId(uint16_t msgId) { - return _waitedPubTopicIdMap.getElement(msgId); + return _waitedPubTopicIdMap.getElement(msgId); } TopicIdMapElement* Client::getWaitedSubTopicId(uint16_t msgId) { - return _waitedSubTopicIdMap.getElement(msgId); + return _waitedSubTopicIdMap.getElement(msgId); } MQTTGWPacket* Client::getClientSleepPacket() { - return _clientSleepPacketQue.getPacket(); + return _clientSleepPacketQue.getPacket(); } void Client::deleteFirstClientSleepPacket() { - _clientSleepPacketQue.pop(); + _clientSleepPacketQue.pop(); } int Client::setClientSleepPacket(MQTTGWPacket* packet) { - int rc = _clientSleepPacketQue.post(packet); - if ( rc ) - { - WRITELOG("%s %s is sleeping. the packet was saved.\n", currentDateTime(), _clientId); - } - else - { - WRITELOG("%s %s is sleeping but discard the packet.\n", currentDateTime(), _clientId); - } - return rc; + int rc = _clientSleepPacketQue.post(packet); + if (rc) + { + WRITELOG("%s %s is sleeping. the packet was saved.\n", currentDateTime(), _clientId); + } + else + { + WRITELOG("%s %s is sleeping but discard the packet.\n", currentDateTime(), _clientId); + } + return rc; } MQTTSNPacket* Client::getProxyPacket(void) @@ -141,7 +141,7 @@ void Client::deleteFirstProxyPacket() int Client::setProxyPacket(MQTTSNPacket* packet) { int rc = _proxyPacketQue.post(packet); - if ( rc ) + if (rc) { WRITELOG("%s %s is Disconnected. the packet was saved.\n", currentDateTime(), _clientId); } @@ -154,51 +154,52 @@ int Client::setProxyPacket(MQTTSNPacket* packet) Connect* Client::getConnectData(void) { - return &_connectData; + return &_connectData; } void Client::eraseWaitedPubTopicId(uint16_t msgId) { - _waitedPubTopicIdMap.erase(msgId); + _waitedPubTopicIdMap.erase(msgId); } void Client::eraseWaitedSubTopicId(uint16_t msgId) { - _waitedSubTopicIdMap.erase(msgId); + _waitedSubTopicIdMap.erase(msgId); } void Client::clearWaitedPubTopicId(void) { - _waitedPubTopicIdMap.clear(); + _waitedPubTopicIdMap.clear(); } void Client::clearWaitedSubTopicId(void) { - _waitedSubTopicIdMap.clear(); + _waitedSubTopicIdMap.clear(); } -void Client::setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) +void Client::setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic) { - _waitedPubTopicIdMap.add(msgId, topicId, type); + _waitedPubTopicIdMap.add(msgId, topicId, topic); } -void Client::setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) + +void Client::setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic) { - _waitedSubTopicIdMap.add(msgId, topicId, type); + _waitedSubTopicIdMap.add(msgId, topicId, topic); } bool Client::checkTimeover(void) { - return (_status == Cstat_Active && _keepAliveTimer.isTimeup()); + return (_status == Cstat_Active && _keepAliveTimer.isTimeup()); } void Client::setKeepAlive(MQTTSNPacket* packet) { - MQTTSNPacket_connectData param; - if (packet->getCONNECT(¶m)) - { - _keepAliveMsec = param.duration * 1000UL; - _keepAliveTimer.start(_keepAliveMsec * 1.5); - } + MQTTSNPacket_connectData param; + if (packet->getCONNECT(¶m)) + { + _keepAliveMsec = param.duration * 1000UL; + _keepAliveTimer.start(_keepAliveMsec * 1.5); + } } void Client::setForwarder(Forwarder* forwarder) @@ -214,102 +215,101 @@ Forwarder* Client::getForwarder(void) void Client::setSessionStatus(bool status) { - _sessionStatus = status; + _sessionStatus = status; } bool Client::erasable(void) { - return _sessionStatus && !_hasPredefTopic && _forwarder == nullptr; + return _sessionStatus && !_hasPredefTopic && _forwarder == nullptr; } void Client::updateStatus(MQTTSNPacket* packet) { - if (((_status == Cstat_Disconnected) || (_status == Cstat_Lost)) && packet->getType() == MQTTSN_CONNECT) - { - setKeepAlive(packet); - } - else if (_status == Cstat_Active) - { - switch (packet->getType()) - { - case MQTTSN_PINGREQ: - case MQTTSN_PUBLISH: - case MQTTSN_SUBSCRIBE: - case MQTTSN_UNSUBSCRIBE: - case MQTTSN_PUBACK: - case MQTTSN_PUBCOMP: - case MQTTSN_PUBREL: - case MQTTSN_PUBREC: - if ( _clientType != Ctype_Proxy ) - { - _keepAliveTimer.start(_keepAliveMsec * 1.5); - } - break; - case MQTTSN_DISCONNECT: - uint16_t duration; - packet->getDISCONNECT(&duration); - if (duration) - { - _status = Cstat_Asleep; - } - else - { - disconnected(); - } - break; - default: - break; - } - } - else if (_status == Cstat_Awake || _status == Cstat_Asleep) - { - switch (packet->getType()) - { - case MQTTSN_CONNECT: - _status = Cstat_Active; - break; - case MQTTSN_DISCONNECT: - disconnected(); - break; - case MQTTSN_PINGREQ: - _status = Cstat_Awake; - break; - case MQTTSN_PINGRESP: - _status = Cstat_Asleep; - break; - default: - break; - } - } - DEBUGLOG("Client Status = %s\n", theClientStatus[_status]); + if (((_status == Cstat_Disconnected) || (_status == Cstat_Lost)) && packet->getType() == MQTTSN_CONNECT) + { + setKeepAlive(packet); + } + else if (_status == Cstat_Active) + { + switch (packet->getType()) + { + case MQTTSN_PINGREQ: + case MQTTSN_PUBLISH: + case MQTTSN_SUBSCRIBE: + case MQTTSN_UNSUBSCRIBE: + case MQTTSN_PUBACK: + case MQTTSN_PUBCOMP: + case MQTTSN_PUBREL: + case MQTTSN_PUBREC: + if (_clientType != Ctype_Proxy) + { + _keepAliveTimer.start(_keepAliveMsec * 1.5); + } + break; + case MQTTSN_DISCONNECT: + uint16_t duration; + packet->getDISCONNECT(&duration); + if (duration) + { + _status = Cstat_Asleep; + } + else + { + disconnected(); + } + break; + default: + break; + } + } + else if (_status == Cstat_Awake || _status == Cstat_Asleep) + { + switch (packet->getType()) + { + case MQTTSN_CONNECT: + _status = Cstat_Active; + break; + case MQTTSN_DISCONNECT: + disconnected(); + break; + case MQTTSN_PINGREQ: + _status = Cstat_Awake; + break; + case MQTTSN_PINGRESP: + _status = Cstat_Asleep; + break; + default: + break; + } + }DEBUGLOG("Client Status = %s\n", theClientStatus[_status]); } void Client::updateStatus(ClientStatus stat) { - _status = stat; + _status = stat; } void Client::connectSended() { - _status = Cstat_Connecting; + _status = Cstat_Connecting; } void Client::connackSended(int rc) { - if (rc == MQTTSN_RC_ACCEPTED) - { - _status = Cstat_Active; - } - else - { - disconnected(); - } + if (rc == MQTTSN_RC_ACCEPTED) + { + _status = Cstat_Active; + } + else + { + disconnected(); + } } void Client::disconnected(void) { - _status = Cstat_Disconnected; - _waitWillMsgFlg = false; + _status = Cstat_Disconnected; + _waitWillMsgFlg = false; } void Client::tryConnect(void) @@ -317,66 +317,71 @@ void Client::tryConnect(void) _status = Cstat_TryConnecting; } +bool Client::isCleanSession(void) +{ + return _sessionStatus; +} + bool Client::isConnectSendable(void) { - if ( _status == Cstat_Lost || _status == Cstat_TryConnecting ) - { - return false; - } - else - { - return true; - } + if (_status == Cstat_Lost || _status == Cstat_TryConnecting) + { + return false; + } + else + { + return true; + } } uint16_t Client::getNextPacketId(void) { - _packetId++; - if ( _packetId == 0xffff ) - { - _packetId = 1; - } - return _packetId; + _packetId++; + if (_packetId == 0xffff) + { + _packetId = 1; + } + return _packetId; } uint8_t Client::getNextSnMsgId(void) { - _snMsgId++; - if (_snMsgId == 0) - { - _snMsgId++; - } - return _snMsgId; + _snMsgId++; + if (_snMsgId == 0) + { + _snMsgId++; + } + return _snMsgId; } Topics* Client::getTopics(void) { - return _topics; + return _topics; } Network* Client::getNetwork(void) { - return _network; + return _network; } void Client::setClientAddress(SensorNetAddress* sensorNetAddr) { - _sensorNetAddr = *sensorNetAddr; + _sensorNetAddr = *sensorNetAddr; } SensorNetAddress* Client::getSensorNetAddress(void) { - return &_sensorNetAddr; + return &_sensorNetAddr; } void Client::setSensorNetType(bool stable) { - _sensorNetype = stable; + _sensorNetype = stable; } void Client::setTopics(Topics* topics) { - _topics = topics; + _topics = topics; } ClientStatus Client::getClientStatus(void) @@ -386,32 +391,32 @@ ClientStatus Client::getClientStatus(void) void Client::setWaitWillMsgFlg(bool flg) { - _waitWillMsgFlg = flg; + _waitWillMsgFlg = flg; } bool Client::isWaitWillMsg(void) { - return _waitWillMsgFlg; + return _waitWillMsgFlg; } bool Client::isDisconnect(void) { - return (_status == Cstat_Disconnected); + return (_status == Cstat_Disconnected); } bool Client::isActive(void) { - return (_status == Cstat_Active); + return (_status == Cstat_Active); } bool Client::isSleep(void) { - return (_status == Cstat_Asleep); + return (_status == Cstat_Asleep); } bool Client::isAwake(void) { - return (_status == Cstat_Awake); + return (_status == Cstat_Awake); } bool Client::isConnecting(void) @@ -421,94 +426,94 @@ bool Client::isConnecting(void) bool Client::isSecureNetwork(void) { - return _secureNetwork; + return _secureNetwork; } bool Client::isSensorNetStable(void) { - return _sensorNetype; + return _sensorNetype; } WaitREGACKPacketList* Client::getWaitREGACKPacketList() { - return &_waitREGACKList; + return &_waitREGACKList; } Client* Client::getNextClient(void) { - return _nextClient; + return _nextClient; } void Client::setClientId(MQTTSNString id) { - if ( _clientId ) - { - free(_clientId); - } + if (_clientId) + { + free(_clientId); + } - if ( id.cstring ) - { - _clientId = (char*)calloc(strlen(id.cstring) + 1, 1); - memcpy(_clientId, id.cstring, strlen(id.cstring)); - } - else - { + if (id.cstring) + { + _clientId = (char*) calloc(strlen(id.cstring) + 1, 1); + memcpy(_clientId, id.cstring, strlen(id.cstring)); + } + else + { /* save clientId into (char*)_clientId NULL terminated */ - _clientId = (char*)calloc(MQTTSNstrlen(id) + 1, 1); - unsigned char* ptr = (unsigned char*)_clientId; - writeMQTTSNString((unsigned char**)&ptr, id); - } + _clientId = (char*) calloc(MQTTSNstrlen(id) + 1, 1); + unsigned char* ptr = (unsigned char*) _clientId; + writeMQTTSNString((unsigned char**) &ptr, id); + } } void Client::setWillTopic(MQTTSNString willTopic) { - if ( _willTopic ) - { - free(_willTopic); - } + if (_willTopic) + { + free(_willTopic); + } - _willTopic = (char*)calloc(MQTTSNstrlen(willTopic) + 1, 1); - /* save willTopic into (char*)_willTopic with NULL termination */ - unsigned char* ptr = (unsigned char*)_willTopic; - writeMQTTSNString((unsigned char**)&ptr, willTopic); + _willTopic = (char*) calloc(MQTTSNstrlen(willTopic) + 1, 1); + /* save willTopic into (char*)_willTopic with NULL termination */ + unsigned char* ptr = (unsigned char*) _willTopic; + writeMQTTSNString((unsigned char**) &ptr, willTopic); } void Client::setWillMsg(MQTTSNString willMsg) { - if ( _willMsg) - { - free(_willMsg); - } + if (_willMsg) + { + free(_willMsg); + } - _willMsg = (char*)calloc(MQTTSNstrlen(willMsg) + 1, 1); - /* save willMsg into (char*)_willMsg with NULL termination */ - unsigned char* ptr = (unsigned char*)_willMsg; - writeMQTTSNString((unsigned char**)&ptr, willMsg); + _willMsg = (char*) calloc(MQTTSNstrlen(willMsg) + 1, 1); + /* save willMsg into (char*)_willMsg with NULL termination */ + unsigned char* ptr = (unsigned char*) _willMsg; + writeMQTTSNString((unsigned char**) &ptr, willMsg); } char* Client::getClientId(void) { - return _clientId; + return _clientId; } char* Client::getWillTopic(void) { - return _willTopic; + return _willTopic; } char* Client::getWillMsg(void) { - return _willMsg; + return _willMsg; } const char* Client::getStatus(void) { - return theClientStatus[_status]; + return theClientStatus[_status]; } bool Client::isQoSm1Proxy(void) { - return _clientType == Ctype_Proxy; + return _clientType == Ctype_Proxy; } bool Client::isForwarded(void) @@ -528,23 +533,23 @@ bool Client::isAggregater(void) void Client::setAdapterType(AdapterType type) { - switch ( type ) + switch (type) { case Atype_QoSm1Proxy: - _clientType = Ctype_Proxy; - break; + _clientType = Ctype_Proxy; + break; case Atype_Aggregater: - _clientType = Ctype_Aggregater; - break; + _clientType = Ctype_Aggregater; + break; default: - throw Exception("Client::setAdapterType(): Invalid Type."); - break; + throw EXCEPTION("Client::setAdapterType(): Invalid Type.", 0); + break; } } bool Client::isAdapter(void) { - return _clientType == Ctype_Proxy || _clientType == Ctype_Aggregater; + return _clientType == Ctype_Proxy || _clientType == Ctype_Aggregater; } bool Client::isQoSm1(void) @@ -554,12 +559,12 @@ bool Client::isQoSm1(void) void Client::setQoSm1(void) { - _clientType = Ctype_QoS_1; + _clientType = Ctype_QoS_1; } void Client::setAggregated(void) { - _clientType = Ctype_Aggregated; + _clientType = Ctype_Aggregated; } void Client::holdPingRequest(void) @@ -577,22 +582,20 @@ bool Client::isHoldPingReqest(void) return _holdPingRequest; } - - /*===================================== Class WaitREGACKPacket =====================================*/ waitREGACKPacket::waitREGACKPacket(MQTTSNPacket* packet, uint16_t REGACKMsgId) { - _packet = packet; - _msgId = REGACKMsgId; - _next = nullptr; - _prev = nullptr; + _packet = packet; + _msgId = REGACKMsgId; + _next = nullptr; + _prev = nullptr; } waitREGACKPacket::~waitREGACKPacket() { - delete _packet; + delete _packet; } /*===================================== @@ -601,89 +604,89 @@ waitREGACKPacket::~waitREGACKPacket() WaitREGACKPacketList::WaitREGACKPacketList() { - _first = nullptr; - _end = nullptr; - _cnt = 0; + _first = nullptr; + _end = nullptr; + _cnt = 0; } WaitREGACKPacketList::~WaitREGACKPacketList() { - waitREGACKPacket* p = _first; - while (p) - { - waitREGACKPacket* q = p->_next; - delete p; - p = q; - } + waitREGACKPacket* p = _first; + while (p) + { + waitREGACKPacket* q = p->_next; + delete p; + p = q; + } } int WaitREGACKPacketList::setPacket(MQTTSNPacket* packet, uint16_t REGACKMsgId) { - waitREGACKPacket* elm = new waitREGACKPacket(packet, REGACKMsgId); - if (elm == nullptr) - { - return 0; - } + waitREGACKPacket* elm = new waitREGACKPacket(packet, REGACKMsgId); + if (elm == nullptr) + { + return 0; + } - if (_first == nullptr) - { - _first = elm; - _end = elm; - } - else - { - _end->_next = elm; - elm->_prev = _end; - _end = elm; - } - _cnt++; - return 1; + if (_first == nullptr) + { + _first = elm; + _end = elm; + } + else + { + _end->_next = elm; + elm->_prev = _end; + _end = elm; + } + _cnt++; + return 1; } MQTTSNPacket* WaitREGACKPacketList::getPacket(uint16_t REGACKMsgId) { - waitREGACKPacket* p = _first; - while (p) - { - if (p->_msgId == REGACKMsgId) - { - return p->_packet; - } - p = p->_next; - } - return nullptr; + waitREGACKPacket* p = _first; + while (p) + { + if (p->_msgId == REGACKMsgId) + { + return p->_packet; + } + p = p->_next; + } + return nullptr; } void WaitREGACKPacketList::erase(uint16_t REGACKMsgId) { - waitREGACKPacket* p = _first; - while (p) - { - if (p->_msgId == REGACKMsgId) - { - if (p->_prev == nullptr) - { - _first = p->_next; + waitREGACKPacket* p = _first; + while (p) + { + if (p->_msgId == REGACKMsgId) + { + if (p->_prev == nullptr) + { + _first = p->_next; - } - else - { - p->_prev->_next = p->_next; - } - if (p->_next == nullptr) - { - _end = p->_prev; - } - else - { - p->_next->_prev = p->_prev; - } - _cnt--; + } + else + { + p->_prev->_next = p->_next; + } + if (p->_next == nullptr) + { + _end = p->_prev; + } + else + { + p->_next->_prev = p->_prev; + } + _cnt--; break; // Do not delete element. Element is deleted after sending to Client. - } - p = p->_next; - } + } + p = p->_next; + } } uint8_t WaitREGACKPacketList::getCount(void) @@ -691,4 +694,3 @@ uint8_t WaitREGACKPacketList::getCount(void) return _cnt; } - diff --git a/MQTTSNGateway/src/MQTTSNGWClient.h b/MQTTSNGateway/src/MQTTSNGWClient.h index 5071710..7b7db4e 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.h +++ b/MQTTSNGateway/src/MQTTSNGWClient.h @@ -49,7 +49,6 @@ public: _que = new Que; } - ~PacketQue() { clear(); @@ -72,8 +71,7 @@ public: } } - int - post(T* packet) + int post(T* packet) { int rc; _mutex.lock(); @@ -113,8 +111,6 @@ private: Mutex _mutex; }; - - /*===================================== Class WaitREGACKPacket =====================================*/ @@ -151,26 +147,37 @@ private: waitREGACKPacket* _end; }; - - /*===================================== Class Client =====================================*/ typedef enum { - Cstat_Disconnected = 0, Cstat_TryConnecting, Cstat_Connecting, Cstat_Active, Cstat_Asleep, Cstat_Awake, Cstat_Lost + Cstat_Free = 0, + Cstat_Disconnected, + Cstat_TryConnecting, + Cstat_Connecting, + Cstat_Active, + Cstat_Asleep, + Cstat_Awake, + Cstat_Lost } ClientStatus; typedef enum { - Ctype_Regular = 0, Ctype_Forwarded, Ctype_QoS_1, Ctype_Aggregated, Ctype_Proxy, Ctype_Aggregater -}ClientType; + Ctype_Normal = 0, + Ctype_Forwarded, + Ctype_QoS_1, + Ctype_Aggregated, + Ctype_Proxy, + Ctype_Aggregater +} ClientType; class Forwarder; class Client { friend class ClientList; + friend class ClientsPool; public: Client(bool secure = false); Client(uint8_t maxInflightMessages, bool secure); @@ -191,10 +198,10 @@ public: void clearWaitedPubTopicId(void); void clearWaitedSubTopicId(void); - int setClientSleepPacket(MQTTGWPacket*); + int setClientSleepPacket(MQTTGWPacket*); int setProxyPacket(MQTTSNPacket* packet); - void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); - void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); + void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic); + void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic); bool checkTimeover(void); void updateStatus(MQTTSNPacket*); @@ -249,6 +256,7 @@ public: bool isSecureNetwork(void); bool isSensorNetStable(void); bool isWaitWillMsg(void); + bool isCleanSession(void); void holdPingRequest(void); void resetPingRequest(void); @@ -260,7 +268,7 @@ private: PacketQue _clientSleepPacketQue; PacketQue _proxyPacketQue; - WaitREGACKPacketList _waitREGACKList; + WaitREGACKPacketList _waitREGACKList; Topics* _topics; TopicIdMap _waitedPubTopicIdMap; @@ -285,7 +293,7 @@ private: uint8_t _snMsgId; Network* _network; // Broker - bool _secureNetwork; // SSL + bool _secureNetwork; // SSL bool _sensorNetype; // false: unstable network like a G3 SensorNetAddress _sensorNetAddr; @@ -299,7 +307,5 @@ private: Client* _prevClient; }; - - } #endif /* MQTTSNGWCLIENT_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.cpp b/MQTTSNGateway/src/MQTTSNGWClientList.cpp index f164996..cc5006f 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientList.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientList.cpp @@ -20,18 +20,20 @@ #include using namespace MQTTSNGW; -extern Gateway* theGateway; +char* currentDateTime(void); /*===================================== Class ClientList =====================================*/ const char* common_topic = "*"; -ClientList::ClientList() +ClientList::ClientList(Gateway* gw) { _clientCnt = 0; _authorize = false; _firstClient = nullptr; _endClient = nullptr; + _clientsPool = new ClientsPool(); + _gateway = gw; } ClientList::~ClientList() @@ -46,43 +48,51 @@ ClientList::~ClientList() delete cl; cl = ncl; }; + + if (_clientsPool) + { + delete _clientsPool; + } _mutex.unlock(); } void ClientList::initialize(bool aggregate) { - if (theGateway->getGWParams()->clientAuthentication ) + _maxClients = _gateway->getGWParams()->maxClients; + _clientsPool->allocate(_gateway->getGWParams()->maxClients); + + if (_gateway->getGWParams()->clientAuthentication) { - int type = TRANSPEARENT_TYPE; - if ( aggregate ) - { - type = AGGREGATER_TYPE; - } - setClientList(type); + int type = TRANSPEARENT_TYPE; + if (aggregate) + { + type = AGGREGATER_TYPE; + } + setClientList(type); _authorize = true; } - if ( theGateway->getGWParams()->predefinedTopic ) + if (_gateway->getGWParams()->predefinedTopic) { - setPredefinedTopics(aggregate); + setPredefinedTopics(aggregate); } } void ClientList::setClientList(int type) { - if (!createList(theGateway->getGWParams()->clientListName, type)) - { - throw Exception("ClientList::setClientList No client list defined by config file."); - } + if (!createList(_gateway->getGWParams()->clientListName, type)) + { + throw EXCEPTION("ClientList::setClientList Client list not found!", 0); + } } void ClientList::setPredefinedTopics(bool aggrecate) { - if ( !readPredefinedList(theGateway->getGWParams()->predefinedTopicFileName, aggrecate) ) - { - throw Exception("ClientList::setPredefinedTopics No predefindTopi list defined by config file."); + if (!readPredefinedList(_gateway->getGWParams()->predefinedTopicFileName, aggrecate)) + { + throw EXCEPTION("ClientList::setPredefinedTopics PredefindTopic list not found!", 0); - } + } } /** @@ -148,17 +158,17 @@ bool ClientList::createList(const char* fileName, int type) forwarder = (data.find("forwarder") != string::npos); secure = (data.find("secureConnection") != string::npos); stable = !(data.find("unstableLine") != string::npos); - if ( (qos_1 && type == QOSM1PROXY_TYPE) || (!qos_1 && type == AGGREGATER_TYPE) ) + if ((qos_1 && type == QOSM1PROXY_TYPE) || (!qos_1 && type == AGGREGATER_TYPE)) { - createClient(&netAddr, &clientId, stable, secure, type); + createClient(&netAddr, &clientId, stable, secure, type); } - else if ( forwarder && type == FORWARDER_TYPE) + else if (forwarder && type == FORWARDER_TYPE) { - theGateway->getAdapterManager()->getForwarderList()->addForwarder(&netAddr, &clientId); + _gateway->getAdapterManager()->getForwarderList()->addForwarder(&netAddr, &clientId); } - else if (type == TRANSPEARENT_TYPE ) + else if (type == TRANSPEARENT_TYPE) { - createClient(&netAddr, &clientId, stable, secure, type); + createClient(&netAddr, &clientId, stable, secure, type); } } else @@ -179,7 +189,8 @@ bool ClientList::readPredefinedList(const char* fileName, bool aggregate) FILE* fp; char buf[MAX_CLIENTID_LENGTH + 256]; size_t pos0, pos1; - MQTTSNString clientId = MQTTSNString_initializer;; + MQTTSNString clientId = MQTTSNString_initializer; + ; bool rc = false; if ((fp = fopen(fileName, "r")) != 0) @@ -201,12 +212,12 @@ bool ClientList::readPredefinedList(const char* fileName, bool aggregate) } pos0 = data.find_first_of(","); - pos1 = data.find(",", pos0 + 1) ; + pos1 = data.find(",", pos0 + 1); string id = data.substr(0, pos0); clientId.cstring = strdup(id.c_str()); - string topicName = data.substr(pos0 + 1, pos1 - pos0 -1); + string topicName = data.substr(pos0 + 1, pos1 - pos0 - 1); uint16_t topicID = stoul(data.substr(pos1 + 1)); - createPredefinedTopic( &clientId, topicName, topicID, aggregate); + createPredefinedTopic(&clientId, topicName, topicID, aggregate); free(clientId.cstring); } fclose(fp); @@ -222,7 +233,7 @@ bool ClientList::readPredefinedList(const char* fileName, bool aggregate) void ClientList::erase(Client*& client) { - if ( !_authorize && client->erasable()) + if (!_authorize && client->erasable()) { _mutex.lock(); Client* prev = client->_prevClient; @@ -247,7 +258,7 @@ void ClientList::erase(Client*& client) } _clientCnt--; Forwarder* fwd = client->getForwarder(); - if ( fwd ) + if (fwd) { fwd->eraseClient(client); } @@ -259,14 +270,14 @@ void ClientList::erase(Client*& client) Client* ClientList::getClient(SensorNetAddress* addr) { - if ( addr ) + if (addr) { _mutex.lock(); Client* client = _firstClient; while (client != nullptr) { - if (client->getSensorNetAddress()->isMatch(addr) ) + if (client->getSensorNetAddress()->isMatch(addr)) { _mutex.unlock(); return client; @@ -280,38 +291,37 @@ Client* ClientList::getClient(SensorNetAddress* addr) Client* ClientList::getClient(int index) { - Client* client = _firstClient; - int p = 0; - while ( client != nullptr ) - { - if ( p == index ) - { - return client; - } - else - { - client = client->_nextClient; - p++; - } - } - return nullptr; + Client* client = _firstClient; + int p = 0; + while (client != nullptr) + { + if (p == index) + { + return client; + } + else + { + client = client->_nextClient; + p++; + } + } + return nullptr; } - Client* ClientList::getClient(MQTTSNString* clientId) { _mutex.lock(); Client* client = _firstClient; - const char* clID =clientId->cstring; + const char* clID = clientId->cstring; - if (clID == nullptr ) + if (clID == nullptr) { clID = clientId->lenstring.data; } while (client != nullptr) { - if (strncmp((const char*)client->getClientId(), clID, MQTTSNstrlen(*clientId)) == 0 ) + if (strncmp((const char*) client->getClientId(), clID, MQTTSNstrlen(*clientId)) == 0) { _mutex.unlock(); return client; @@ -324,57 +334,59 @@ Client* ClientList::getClient(MQTTSNString* clientId) Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, int type) { - return createClient(addr, clientId, false, false, type); + return createClient(addr, clientId, false, false, type); } Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type) { - Client* client = nullptr; - - /* anonimous clients */ - if ( _clientCnt > MAX_CLIENTS ) - { - return 0; // full of clients - } - - client = getClient(addr); - if ( client ) + Client* client = getClient(addr); + if (client) { return client; } - /* creat a new client */ - client = new Client(secure); - if ( addr ) + /* acquire a free client */ + client = _clientsPool->getClient(); + + if (!client) + { + WRITELOG("%s%sMax number of Clients%s\n", currentDateTime(), + ERRMSG_HEADER, ERRMSG_FOOTER); + return nullptr; + } + + client->disconnected(); + if (addr) { client->setClientAddress(addr); } client->setSensorNetType(unstableLine); - if ( MQTTSNstrlen(*clientId) ) + if (MQTTSNstrlen(*clientId)) { client->setClientId(*clientId); } else { - MQTTSNString dummyId MQTTSNString_initializer; + MQTTSNString dummyId MQTTSNString_initializer; dummyId.cstring = strdup(""); client->setClientId(dummyId); - free(dummyId.cstring); + free(dummyId.cstring); } - if ( type == AGGREGATER_TYPE ) + if (type == AGGREGATER_TYPE) { - client->setAggregated(); + client->setAggregated(); } - else if ( type == QOSM1PROXY_TYPE ) + else if (type == QOSM1PROXY_TYPE) { client->setQoSm1(); } + client->getNetwork()->setSecure(secure); _mutex.lock(); /* add the list */ - if ( _firstClient == nullptr ) + if (_firstClient == nullptr) { _firstClient = client; _endClient = client; @@ -390,66 +402,40 @@ Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, return client; } -Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t topicId, bool aggregate) +Client* ClientList::createPredefinedTopic(MQTTSNString* clientId, string topicName, uint16_t topicId, bool aggregate) { - if ( topicId == 0 ) - { - WRITELOG("Invalid TopicId. Predefined Topic %s, TopicId is 0. \n", topicName.c_str()); - return nullptr; - } + if (topicId == 0) + { + WRITELOG("Invalid TopicId. Predefined Topic %s, TopicId is 0. \n", topicName.c_str()); + return nullptr; + } - if ( strcmp(clientId->cstring, common_topic) == 0 ) - { - theGateway->getTopics()->add((const char*)topicName.c_str(), topicId); - return nullptr; - } - else - { - Client* client = getClient(clientId); + if (strcmp(clientId->cstring, common_topic) == 0) + { + _gateway->getTopics()->add((const char*) topicName.c_str(), topicId); + return nullptr; + } + else + { + Client *client = getClient(clientId); - if ( _authorize && client == nullptr ) - { - return nullptr; - } + if (_authorize && client == nullptr) + { + return nullptr; + } - /* anonimous clients */ - if ( _clientCnt > MAX_CLIENTS ) - { - return nullptr; // full of clients - } + client = createClient(NULL, clientId, aggregate); - if ( client == nullptr ) - { - /* creat a new client */ - client = new Client(); - client->setClientId(*clientId); - if ( aggregate ) - { - client->setAggregated(); - } - _mutex.lock(); + if (client == nullptr) + { + return nullptr; + } - /* 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; - } + // create Topic & Add it + client->getTopics()->add((const char*) topicName.c_str(), topicId); + client->_hasPredefTopic = true; + return client; + } } uint16_t ClientList::getClientCount() @@ -462,4 +448,70 @@ bool ClientList::isAuthorized() return _authorize; } +/****************************** + * Class ClientsPool + ******************************/ +ClientsPool::ClientsPool() +{ + _clientCnt = 0; + _firstClient = nullptr; + _endClient = nullptr; +} + +ClientsPool::~ClientsPool() +{ + Client* cl = _firstClient; + Client* ncl; + + while (cl != nullptr) + { + ncl = cl->_nextClient; + delete cl; + cl = ncl; + }; +} + +void ClientsPool::allocate(int maxClients) +{ + Client* cl = nullptr; + + _firstClient = new Client(); + + for (int i = 0; i < maxClients; i++) + { + if ((cl = new Client()) == nullptr) + { + throw Exception("ClientsPool::Can't allocate max number of clients\n", 0); + } + cl->_nextClient = _firstClient; + _firstClient = cl; + _clientCnt++; + } + +} + +Client* ClientsPool::getClient(void) +{ + Client *cl = nullptr; + + while (_firstClient != nullptr) + { + cl = _firstClient; + _firstClient = cl->_nextClient; + cl->_nextClient = nullptr; + _clientCnt--; + break; + } + return cl; +} + +void ClientsPool::setClient(Client* client) +{ + if (client) + { + client->_nextClient = _firstClient; + _firstClient = client; + _clientCnt++; + } +} diff --git a/MQTTSNGateway/src/MQTTSNGWClientList.h b/MQTTSNGateway/src/MQTTSNGWClientList.h index 135f365..4cb2ca3 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientList.h +++ b/MQTTSNGateway/src/MQTTSNGWClientList.h @@ -30,21 +30,41 @@ namespace MQTTSNGW class Client; +/*===================================== + Class ClientsPool + =====================================*/ +class ClientsPool +{ +public: + ClientsPool(); + ~ClientsPool(); + void allocate(int maxClients); + Client* getClient(void); + void setClient(Client* client); + +private: + Client* _firstClient; + Client* _endClient; + int _clientCnt; +}; + /*===================================== Class ClientList =====================================*/ class ClientList { public: - ClientList(); + ClientList(Gateway* gw); ~ClientList(); void initialize(bool aggregate); void setClientList(int type); void setPredefinedTopics(bool aggregate); void erase(Client*&); - Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId,int type); - Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type); + Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, + int type); + Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, + bool unstableLine, bool secure, int type); bool createList(const char* fileName, int type); Client* getClient(SensorNetAddress* addr); Client* getClient(MQTTSNString* clientId); @@ -55,18 +75,18 @@ public: private: bool readPredefinedList(const char* fileName, bool _aggregate); - Gateway* _gateway {nullptr}; - Client* createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t toipcId, bool _aggregate); + ClientsPool* _clientsPool; + Gateway* _gateway; + Client* createPredefinedTopic(MQTTSNString* clientId, string topicName, + uint16_t toipcId, bool _aggregate); Client* _firstClient; Client* _endClient; Mutex _mutex; uint16_t _clientCnt; - bool _authorize {false}; + uint16_t _maxClients; + bool _authorize { false }; }; - } - - #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp index 03f3415..f4c019b 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.cpp @@ -20,8 +20,6 @@ #include "MQTTSNGWEncapsulatedPacket.h" #include -//#include "MQTTSNGWForwarder.h" - using namespace MQTTSNGW; char* currentDateTime(void); /*===================================== @@ -29,242 +27,262 @@ char* currentDateTime(void); =====================================*/ ClientRecvTask::ClientRecvTask(Gateway* gateway) { - _gateway = gateway; - _gateway->attach((Thread*)this); - _sensorNetwork = _gateway->getSensorNetwork(); + _gateway = gateway; + _gateway->attach((Thread*) this); + _sensorNetwork = _gateway->getSensorNetwork(); + setTaskName("ClientRecvTask"); } ClientRecvTask::~ClientRecvTask() { - } -/** - * Initialize SensorNetwork - */ void ClientRecvTask::initialize(int argc, char** argv) { - if ( _sensorNetwork->initialize() < 0 ) - { - throw Exception(" Can't open the sensor network.\n"); - } } /* * Receive a packet from clients via sensor netwwork - * and generate a event to execute the packet handling procedure + * and creats a event to execute the packet handling procedure * of MQTTSNPacketHandlingTask. */ void ClientRecvTask::run() { - Event* ev = nullptr; - AdapterManager* adpMgr = _gateway->getAdapterManager(); - QoSm1Proxy* qosm1Proxy = adpMgr->getQoSm1Proxy(); - int clientType = adpMgr->isAggregaterActive() ? AGGREGATER_TYPE : TRANSPEARENT_TYPE; - ClientList* clientList = _gateway->getClientList(); - EventQue* packetEventQue = _gateway->getPacketEventQue(); + Event* ev = nullptr; + AdapterManager* adpMgr = _gateway->getAdapterManager(); + QoSm1Proxy* qosm1Proxy = adpMgr->getQoSm1Proxy(); + int clientType = adpMgr->isAggregaterActive() ? AGGREGATER_TYPE : TRANSPEARENT_TYPE; + ClientList* clientList = _gateway->getClientList(); + EventQue* packetEventQue = _gateway->getPacketEventQue(); + EventQue* clientsendQue = _gateway->getClientSendQue(); - char buf[128]; + char buf[128]; - while (true) - { - Client* client = nullptr; - Forwarder* fwd = nullptr; - WirelessNodeId nodeId; + while (true) + { + Client* client = nullptr; + Forwarder* fwd = nullptr; + WirelessNodeId nodeId; - MQTTSNPacket* packet = new MQTTSNPacket(); - int packetLen = packet->recv(_sensorNetwork); + MQTTSNPacket* packet = new MQTTSNPacket(); + int packetLen = packet->recv(_sensorNetwork); - if (CHK_SIGINT) - { - WRITELOG("\n%s ClientRecvTask stopped.", currentDateTime()); - delete packet; - return; - } + if (CHK_SIGINT) + { + WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName()); + delete packet; + return; + } - if (packetLen < 2 ) - { - delete packet; - continue; - } + if (packetLen < 2) + { + delete packet; + continue; + } - if ( packet->getType() <= MQTTSN_ADVERTISE || packet->getType() == MQTTSN_GWINFO ) - { - delete packet; - continue; - } + if (packet->getType() <= MQTTSN_ADVERTISE || packet->getType() == MQTTSN_GWINFO) + { + delete packet; + continue; + } - if ( packet->getType() == MQTTSN_SEARCHGW ) - { - /* write log and post Event */ - log(0, packet, 0); - ev = new Event(); - ev->setBrodcastEvent(packet); - packetEventQue->post(ev); - continue; - } + if (packet->getType() == MQTTSN_SEARCHGW) + { + /* write log and post Event */ + log(0, packet, 0); + ev = new Event(); + ev->setBrodcastEvent(packet); + packetEventQue->post(ev); + continue; + } + SensorNetAddress senderAddr = *_gateway->getSensorNetwork()->getSenderAddress(); - SensorNetAddress* senderAddr = _gateway->getSensorNetwork()->getSenderAddress(); + if (packet->getType() == MQTTSN_ENCAPSULATED) + { + fwd = _gateway->getAdapterManager()->getForwarderList()->getForwarder(&senderAddr); - if ( packet->getType() == MQTTSN_ENCAPSULATED ) - { - fwd = _gateway->getAdapterManager()->getForwarderList()->getForwarder(senderAddr); + if (fwd != nullptr) + { + MQTTSNString fwdName = MQTTSNString_initializer; + fwdName.cstring = const_cast(fwd->getName()); + log(0, packet, &fwdName); - if ( fwd != nullptr ) - { - MQTTSNString fwdName = MQTTSNString_initializer; - fwdName.cstring = const_cast( fwd->getName() ); - log(0, packet, &fwdName); + /* get the packet from the encapsulation message */ + MQTTSNGWEncapsulatedPacket encap; + encap.desirialize(packet->getPacketData(), packet->getPacketLength()); + nodeId.setId(encap.getWirelessNodeId()); + client = fwd->getClient(&nodeId); + packet = encap.getMQTTSNPacket(); + } + } + else + { + /* Check the client belonging to QoS-1Proxy ? */ - /* get the packet from the encapsulation message */ - MQTTSNGWEncapsulatedPacket encap; - encap.desirialize(packet->getPacketData(), packet->getPacketLength()); - nodeId.setId( encap.getWirelessNodeId() ); - client = fwd->getClient(&nodeId); - packet = encap.getMQTTSNPacket(); - } - } - else - { - /* Check the client belonging to QoS-1Proxy ? */ + if (qosm1Proxy->isActive()) + { + const char *clientName = qosm1Proxy->getClientId(&senderAddr); - if ( qosm1Proxy->isActive() ) - { - const char* clientName = qosm1Proxy->getClientId(senderAddr); + if (clientName != nullptr) + { + client = qosm1Proxy->getClient(); - if ( clientName != nullptr ) - { - client = qosm1Proxy->getClient(); + if (!packet->isQoSMinusPUBLISH()) + { + log(clientName, packet); + WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", + ERRMSG_HEADER, clientName, senderAddr.sprint(buf), ERRMSG_FOOTER); + delete packet; + continue; + } + } + } - if ( !packet->isQoSMinusPUBLISH() ) - { - log(clientName, packet); - WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, senderAddr->sprint(buf), ERRMSG_FOOTER); - delete packet; - continue; - } - } - } + if (client == nullptr) + { + client = _gateway->getClientList()->getClient(&senderAddr); + } + } - if ( client == nullptr ) - { - client = _gateway->getClientList()->getClient(senderAddr); - } - } + if (client != nullptr) + { + log(client, packet, 0); - if ( client != nullptr ) - { - /* write log and post Event */ - log(client, packet, 0); - ev = new Event(); - ev->setClientRecvEvent(client,packet); - packetEventQue->post(ev); - } - else - { - /* new client */ - if (packet->getType() == MQTTSN_CONNECT) - { - MQTTSNPacket_connectData data; - memset(&data, 0, sizeof(MQTTSNPacket_connectData)); - if ( !packet->getCONNECT(&data) ) - { - log(0, packet, &data.clientID); - WRITELOG("%s CONNECT message form %s is incorrect.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER); - delete packet; - continue; - } + if (client->isDisconnect() && packet->getType() != MQTTSN_CONNECT) + { + WRITELOG("%s MQTTSNGWClientRecvTask %s is not connecting.%s\n", + ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - client = clientList->getClient(&data.clientID); + /* send DISCONNECT to the client, if it is not connected */ + MQTTSNPacket* snPacket = new MQTTSNPacket(); + snPacket->setDISCONNECT(0); + ev = new Event(); + ev->setClientSendEvent(client, snPacket); + clientsendQue->post(ev); + delete packet; + continue; + } + else + { + ev = new Event(); + ev->setClientRecvEvent(client, packet); + packetEventQue->post(ev); + } + } + else + { + /* new client */ + if (packet->getType() == MQTTSN_CONNECT) + { + MQTTSNPacket_connectData data; + memset(&data, 0, sizeof(MQTTSNPacket_connectData)); + if (!packet->getCONNECT(&data)) + { + log(0, packet, &data.clientID); + WRITELOG("%s CONNECT message form %s is incorrect.%s\n", + ERRMSG_HEADER, senderAddr.sprint(buf), + ERRMSG_FOOTER); + delete packet; + continue; + } - if ( fwd != nullptr ) - { - if ( client == nullptr ) - { - /* create a new client */ - client = clientList->createClient(0, &data.clientID, clientType); - } - /* Add to a forwarded client list of forwarder. */ + client = clientList->getClient(&data.clientID); + + if (fwd != nullptr) + { + if (client == nullptr) + { + /* create a new client */ + client = clientList->createClient(0, &data.clientID, clientType); + } + /* Add to a forwarded client list of forwarder. */ fwd->addClient(client, &nodeId); - } - else - { - if ( client ) + } + else + { + if (client) { /* Authentication is not required */ - if ( _gateway->getGWParams()->clientAuthentication == false) - { - client->setClientAddress(senderAddr); - } + if (_gateway->getGWParams()->clientAuthentication == false) + { + client->setClientAddress(&senderAddr); + } } else { /* create a new client */ - client = clientList->createClient(senderAddr, &data.clientID, clientType); + client = clientList->createClient(&senderAddr, &data.clientID, clientType); } - } + } - log(client, packet, &data.clientID); + log(client, packet, &data.clientID); - if ( client == nullptr ) - { - WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER); - delete packet; - continue; - } + if (client == nullptr) + { + WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", + ERRMSG_HEADER, senderAddr.sprint(buf), + ERRMSG_FOOTER); + delete packet; + continue; + } - /* post Client RecvEvent */ - ev = new Event(); - ev->setClientRecvEvent(client, packet); - packetEventQue->post(ev); - } - else - { - log(client, packet, 0); - if ( packet->getType() == MQTTSN_ENCAPSULATED ) - { - WRITELOG("%s MQTTSNGWClientRecvTask Forwarder(%s) is not declared by ClientList file. message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); - } - else - { - WRITELOG("%s MQTTSNGWClientRecvTask Client(%s) is not connecting. message has been discarded.%s\n", ERRMSG_HEADER, senderAddr->sprint(buf), ERRMSG_FOOTER); - } - delete packet; - } - } - } + /* post Client RecvEvent */ + ev = new Event(); + ev->setClientRecvEvent(client, packet); + packetEventQue->post(ev); + } + else + { + log(client, packet, 0); + if (packet->getType() == MQTTSN_ENCAPSULATED) + { + WRITELOG( + "%s MQTTSNGWClientRecvTask Forwarder(%s) is not declared by ClientList file. message has been discarded.%s\n", + ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), + ERRMSG_FOOTER); + } + else + { + WRITELOG("%s MQTTSNGWClientRecvTask Client(%s) is not connecting. message has been discarded.%s\n", + ERRMSG_HEADER, senderAddr.sprint(buf), + ERRMSG_FOOTER); + } + delete packet; + } + } + } } void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id) { - const char* clientId; - char cstr[MAX_CLIENTID_LENGTH + 1]; + const char* clientId; + char cstr[MAX_CLIENTID_LENGTH + 1]; - if ( id ) - { - if ( id->cstring ) - { - strncpy(cstr, id->cstring, strlen(id->cstring) ); - clientId = cstr; - } - else - { - memset((void*)cstr, 0, id->lenstring.len + 1); - strncpy(cstr, id->lenstring.data, id->lenstring.len ); + if (id) + { + if (id->cstring) + { + strncpy(cstr, id->cstring, strlen(id->cstring)); clientId = cstr; - } - } - else if ( client ) - { - clientId = client->getClientId(); - } - else - { - clientId = UNKNOWNCL; - } + } + else + { + memset((void*) cstr, 0, id->lenstring.len + 1); + strncpy(cstr, id->lenstring.data, id->lenstring.len); + clientId = cstr; + } + } + else if (client) + { + clientId = client->getClientId(); + } + else + { + clientId = UNKNOWNCL; + } - log(clientId, packet); + log(clientId, packet); } void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet) @@ -275,11 +293,13 @@ void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet) switch (packet->getType()) { case MQTTSN_SEARCHGW: - WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, CLIENT, packet->print(pbuf)); + WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), + LEFTARROW, CLIENT, packet->print(pbuf)); break; case MQTTSN_CONNECT: case MQTTSN_PINGREQ: - WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); + WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), + LEFTARROW, clientId, packet->print(pbuf)); break; case MQTTSN_DISCONNECT: case MQTTSN_WILLTOPICUPD: @@ -292,18 +312,20 @@ void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet) case MQTTSN_REGISTER: case MQTTSN_SUBSCRIBE: case MQTTSN_UNSUBSCRIBE: - WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); + WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, + packet->print(pbuf)); break; case MQTTSN_REGACK: case MQTTSN_PUBACK: case MQTTSN_PUBREC: case MQTTSN_PUBREL: case MQTTSN_PUBCOMP: - WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); + WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, + packet->print(pbuf)); break; case MQTTSN_ENCAPSULATED: - WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); - break; + WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); + break; default: WRITELOG(FORMAT_W_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); break; diff --git a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h index 30a63e9..9428d3a 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h +++ b/MQTTSNGateway/src/MQTTSNGWClientRecvTask.h @@ -24,24 +24,24 @@ namespace MQTTSNGW class AdapterManager; /*===================================== - Class ClientRecvTask + Class ClientRecvTask =====================================*/ -class ClientRecvTask:public Thread +class ClientRecvTask: public Thread { - MAGIC_WORD_FOR_THREAD; - friend AdapterManager; +MAGIC_WORD_FOR_THREAD; + friend AdapterManager; public: - ClientRecvTask(Gateway*); - ~ClientRecvTask(void); - virtual void initialize(int argc, char** argv); - void run(void); + ClientRecvTask(Gateway*); + ~ClientRecvTask(void); + virtual void initialize(int argc, char** argv); + void run(void); private: - void log(Client*, MQTTSNPacket*, MQTTSNString* id); - void log(const char* clientId, MQTTSNPacket* packet); + void log(Client*, MQTTSNPacket*, MQTTSNString* id); + void log(const char* clientId, MQTTSNPacket* packet); - Gateway* _gateway; - SensorNetwork* _sensorNetwork; + Gateway* _gateway; + SensorNetwork* _sensorNetwork; }; } diff --git a/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp b/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp index b0af063..7b07389 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClientSendTask.cpp @@ -28,106 +28,110 @@ char* currentDateTime(void); =====================================*/ ClientSendTask::ClientSendTask(Gateway* gateway) { - _gateway = gateway; - _gateway->attach((Thread*)this); - _sensorNetwork = _gateway->getSensorNetwork(); + _gateway = gateway; + _gateway->attach((Thread*) this); + _sensorNetwork = _gateway->getSensorNetwork(); + setTaskName("ClientSendTask"); } ClientSendTask::~ClientSendTask() { -// WRITELOG("ClientSendTask is deleted normally.\r\n"); } void ClientSendTask::run() { - Client* client = nullptr; - MQTTSNPacket* packet = nullptr; - AdapterManager* adpMgr = _gateway->getAdapterManager(); - int rc = 0; + Client* client = nullptr; + MQTTSNPacket* packet = nullptr; + AdapterManager* adpMgr = _gateway->getAdapterManager(); + int rc = 0; - while (true) - { - Event* ev = _gateway->getClientSendQue()->wait(); + while (true) + { + Event* ev = _gateway->getClientSendQue()->wait(); - if (ev->getEventType() == EtStop || _gateway->IsStopping() ) - { - WRITELOG("\n%s ClientSendTask stopped.", currentDateTime()); - delete ev; - break; - } + if (ev->getEventType() == EtStop || _gateway->IsStopping()) + { + WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName()); + delete ev; + break; + } - if (ev->getEventType() == EtBroadcast) - { - packet = ev->getMQTTSNPacket(); - log(client, packet); + if (ev->getEventType() == EtBroadcast) + { + packet = ev->getMQTTSNPacket(); + log(client, packet); - if ( packet->broadcast(_sensorNetwork) < 0 ) - { - WRITELOG("%s ClientSendTask can't multicast a packet Error=%d%s\n", - ERRMSG_HEADER, errno, ERRMSG_FOOTER); - } - } - else - { - if (ev->getEventType() == EtClientSend) - { - client = ev->getClient(); - packet = ev->getMQTTSNPacket(); - rc = adpMgr->unicastToClient(client, packet, this); - } - else if (ev->getEventType() == EtSensornetSend) - { - packet = ev->getMQTTSNPacket(); - log(client, packet); - rc = packet->unicast(_sensorNetwork, ev->getSensorNetAddress()); - } + if (packet->broadcast(_sensorNetwork) < 0) + { + WRITELOG("%s ClientSendTask can't multicast a packet Error=%d%s\n", + ERRMSG_HEADER, errno, ERRMSG_FOOTER); + } + } + else + { + if (ev->getEventType() == EtClientSend) + { + client = ev->getClient(); + packet = ev->getMQTTSNPacket(); + rc = adpMgr->unicastToClient(client, packet, this); + } + else if (ev->getEventType() == EtSensornetSend) + { + packet = ev->getMQTTSNPacket(); + log(client, packet); + rc = packet->unicast(_sensorNetwork, ev->getSensorNetAddress()); + } - if ( rc < 0 ) - { - WRITELOG("%s ClientSendTask can't send a packet to the client %s. Error=%d%s\n", - ERRMSG_HEADER, (client ? (const char*)client->getClientId() : UNKNOWNCL ), errno, ERRMSG_FOOTER); - } - } - delete ev; - } + if (rc < 0) + { + WRITELOG("%s ClientSendTask can't send a packet to the client %s. Error=%d%s\n", + ERRMSG_HEADER, (client ? (const char*) client->getClientId() : UNKNOWNCL), + errno, ERRMSG_FOOTER); + } + } + delete ev; + } } void ClientSendTask::log(Client* client, MQTTSNPacket* packet) { - char pbuf[SIZE_OF_LOG_PACKET * 3 + 1]; - char msgId[6]; - const char* clientId = client ? (const char*)client->getClientId() : UNKNOWNCL ; + char pbuf[SIZE_OF_LOG_PACKET * 3 + 1]; + char msgId[6]; + const char* clientId = client ? (const char*) client->getClientId() : UNKNOWNCL; - switch (packet->getType()) - { - case MQTTSN_ADVERTISE: - case MQTTSN_GWINFO: - WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, CLIENTS, packet->print(pbuf)); - break; - case MQTTSN_CONNACK: - case MQTTSN_DISCONNECT: - case MQTTSN_WILLTOPICREQ: - case MQTTSN_WILLMSGREQ: - case MQTTSN_WILLTOPICRESP: - case MQTTSN_WILLMSGRESP: - case MQTTSN_PINGRESP: - WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, clientId, packet->print(pbuf)); - break; - case MQTTSN_REGISTER: - case MQTTSN_PUBLISH: - WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId, packet->print(pbuf)); - break; - case MQTTSN_REGACK: - case MQTTSN_PUBACK: - case MQTTSN_PUBREC: - case MQTTSN_PUBREL: - case MQTTSN_PUBCOMP: - case MQTTSN_SUBACK: - case MQTTSN_UNSUBACK: - WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId, packet->print(pbuf)); - break; - default: - break; - } + switch (packet->getType()) + { + case MQTTSN_ADVERTISE: + case MQTTSN_GWINFO: + WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, + CLIENTS, packet->print(pbuf)); + break; + case MQTTSN_CONNACK: + case MQTTSN_DISCONNECT: + case MQTTSN_WILLTOPICREQ: + case MQTTSN_WILLMSGREQ: + case MQTTSN_WILLTOPICRESP: + case MQTTSN_WILLMSGRESP: + case MQTTSN_PINGRESP: + WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, clientId, packet->print(pbuf)); + break; + case MQTTSN_REGISTER: + case MQTTSN_PUBLISH: + WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId, + packet->print(pbuf)); + break; + case MQTTSN_REGACK: + case MQTTSN_PUBACK: + case MQTTSN_PUBREC: + case MQTTSN_PUBREL: + case MQTTSN_PUBCOMP: + case MQTTSN_SUBACK: + case MQTTSN_UNSUBACK: + WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId, + packet->print(pbuf)); + break; + default: + break; + } } diff --git a/MQTTSNGateway/src/MQTTSNGWClientSendTask.h b/MQTTSNGateway/src/MQTTSNGWClientSendTask.h index 3eaf84f..1e4d14d 100644 --- a/MQTTSNGateway/src/MQTTSNGWClientSendTask.h +++ b/MQTTSNGateway/src/MQTTSNGWClientSendTask.h @@ -28,18 +28,18 @@ class AdapterManager; =====================================*/ class ClientSendTask: public Thread { - MAGIC_WORD_FOR_THREAD; - friend AdapterManager; +MAGIC_WORD_FOR_THREAD; + friend AdapterManager; public: - ClientSendTask(Gateway* gateway); - ~ClientSendTask(void); - void run(void); + ClientSendTask(Gateway* gateway); + ~ClientSendTask(void); + void run(void); private: - void log(Client* client, MQTTSNPacket* packet); + void log(Client* client, MQTTSNPacket* packet); - Gateway* _gateway; - SensorNetwork* _sensorNetwork; + Gateway* _gateway; + SensorNetwork* _sensorNetwork; }; } diff --git a/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp b/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp index 76367ce..69f3b41 100644 --- a/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWConnectionHandler.cpp @@ -28,7 +28,7 @@ using namespace MQTTSNGW; =====================================*/ MQTTSNConnectionHandler::MQTTSNConnectionHandler(Gateway* gateway) { - _gateway = gateway; + _gateway = gateway; } MQTTSNConnectionHandler::~MQTTSNConnectionHandler() @@ -41,11 +41,11 @@ MQTTSNConnectionHandler::~MQTTSNConnectionHandler() */ void MQTTSNConnectionHandler::sendADVERTISE() { - MQTTSNPacket* adv = new MQTTSNPacket(); - adv->setADVERTISE(_gateway->getGWParams()->gatewayId, _gateway->getGWParams()->keepAlive); - Event* ev1 = new Event(); - ev1->setBrodcastEvent(adv); //broadcast - _gateway->getClientSendQue()->post(ev1); + MQTTSNPacket* adv = new MQTTSNPacket(); + adv->setADVERTISE(_gateway->getGWParams()->gatewayId, _gateway->getGWParams()->keepAlive); + Event* ev1 = new Event(); + ev1->setBrodcastEvent(adv); //broadcast + _gateway->getClientSendQue()->post(ev1); } /* @@ -53,14 +53,14 @@ void MQTTSNConnectionHandler::sendADVERTISE() */ void MQTTSNConnectionHandler::handleSearchgw(MQTTSNPacket* packet) { - if (packet->getType() == MQTTSN_SEARCHGW) - { - MQTTSNPacket* gwinfo = new MQTTSNPacket(); - gwinfo->setGWINFO(_gateway->getGWParams()->gatewayId); - Event* ev1 = new Event(); - ev1->setBrodcastEvent(gwinfo); - _gateway->getClientSendQue()->post(ev1); - } + if (packet->getType() == MQTTSN_SEARCHGW) + { + MQTTSNPacket* gwinfo = new MQTTSNPacket(); + gwinfo->setGWINFO(_gateway->getGWParams()->gatewayId); + Event* ev1 = new Event(); + ev1->setBrodcastEvent(gwinfo); + _gateway->getClientSendQue()->post(ev1); + } } /* @@ -68,89 +68,91 @@ void MQTTSNConnectionHandler::handleSearchgw(MQTTSNPacket* packet) */ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet) { - MQTTSNPacket_connectData data; - if ( packet->getCONNECT(&data) == 0 ) - { - return; - } + MQTTSNPacket_connectData data; + if (packet->getCONNECT(&data) == 0) + { + return; + } - /* return CONNACK when the client is sleeping */ - if ( client->isSleep() || client->isAwake() ) - { - MQTTSNPacket* packet = new MQTTSNPacket(); - packet->setCONNACK(MQTTSN_RC_ACCEPTED); - Event* ev = new Event(); - ev->setClientSendEvent(client, packet); - _gateway->getClientSendQue()->post(ev); + /* return CONNACK when the client is sleeping */ + if (client->isSleep() || client->isAwake()) + { + MQTTSNPacket* packet = new MQTTSNPacket(); + packet->setCONNACK(MQTTSN_RC_ACCEPTED); + Event* ev = new Event(); + ev->setClientSendEvent(client, packet); + _gateway->getClientSendQue()->post(ev); - sendStoredPublish(client); - return; - } + sendStoredPublish(client); + return; + } - //* clear ConnectData of Client */ - Connect* connectData = client->getConnectData(); - memset(connectData, 0, sizeof(Connect)); - if ( !client->isAdapter() ) - { - client->disconnected(); - } + //* clear ConnectData of Client */ + Connect* connectData = client->getConnectData(); + memset(connectData, 0, sizeof(Connect)); + if (!client->isAdapter()) + { + client->disconnected(); + } - Topics* topics = client->getTopics(); + Topics* topics = client->getTopics(); - /* CONNECT was not sent yet. prepare Connect data */ - connectData->header.bits.type = CONNECT; - connectData->clientID = client->getClientId(); - connectData->version = _gateway->getGWParams()->mqttVersion; - connectData->keepAliveTimer = data.duration; - connectData->flags.bits.will = data.willFlag; + /* CONNECT was not sent yet. prepare Connect data */ + connectData->header.bits.type = CONNECT; + connectData->clientID = client->getClientId(); + connectData->version = _gateway->getGWParams()->mqttVersion; + connectData->keepAliveTimer = data.duration; + connectData->flags.bits.will = data.willFlag; - if ((const char*) _gateway->getGWParams()->loginId != nullptr) - { - connectData->flags.bits.username = 1; - } + if ((const char*) _gateway->getGWParams()->loginId != nullptr) + { + connectData->flags.bits.username = 1; + } - if ((const char*) _gateway->getGWParams()->password != 0) - { - connectData->flags.bits.password = 1; - } + if ((const char*) _gateway->getGWParams()->password != 0) + { + connectData->flags.bits.password = 1; + } - client->setSessionStatus(false); - if (data.cleansession) - { - connectData->flags.bits.cleanstart = 1; - /* reset the table of msgNo and TopicId pare */ - client->clearWaitedPubTopicId(); - client->clearWaitedSubTopicId(); + client->setSessionStatus(false); + if (data.cleansession) + { + connectData->flags.bits.cleanstart = 1; + /* reset the table of msgNo and TopicId pare */ + client->clearWaitedPubTopicId(); + client->clearWaitedSubTopicId(); - /* renew the TopicList */ - if (topics) - { - topics->eraseNormal();; - } - client->setSessionStatus(true); - } + /* renew the TopicList */ + if (topics) + { + topics->eraseNormal(); + ; + } + client->setSessionStatus(true); + } - if (data.willFlag) - { - /* create & send WILLTOPICREQ message to the client */ - MQTTSNPacket* reqTopic = new MQTTSNPacket(); - reqTopic->setWILLTOPICREQ(); - Event* evwr = new Event(); - evwr->setClientSendEvent(client, reqTopic); + if (data.willFlag) + { + /* create & send WILLTOPICREQ message to the client */ + MQTTSNPacket* reqTopic = new MQTTSNPacket(); + reqTopic->setWILLTOPICREQ(); + Event* evwr = new Event(); + evwr->setClientSendEvent(client, reqTopic); - /* Send WILLTOPICREQ to the client */ - _gateway->getClientSendQue()->post(evwr); - } - else - { - /* CONNECT message was not qued in. - * create CONNECT message & send it to the broker */ - MQTTGWPacket* mqMsg = new MQTTGWPacket(); - mqMsg->setCONNECT(client->getConnectData(), (unsigned char*)_gateway->getGWParams()->loginId, (unsigned char*)_gateway->getGWParams()->password); - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, mqMsg); - _gateway->getBrokerSendQue()->post(ev1); - } + /* Send WILLTOPICREQ to the client */ + _gateway->getClientSendQue()->post(evwr); + } + else + { + /* CONNECT message was not qued in. + * create CONNECT message & send it to the broker */ + MQTTGWPacket* mqMsg = new MQTTGWPacket(); + mqMsg->setCONNECT(client->getConnectData(), (unsigned char*) _gateway->getGWParams()->loginId, + (unsigned char*) _gateway->getGWParams()->password); + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, mqMsg); + _gateway->getBrokerSendQue()->post(ev1); + } } /* @@ -158,29 +160,29 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet */ void MQTTSNConnectionHandler::handleWilltopic(Client* client, MQTTSNPacket* packet) { - int willQos; - uint8_t willRetain; - MQTTSNString willTopic = MQTTSNString_initializer; + int willQos; + uint8_t willRetain; + MQTTSNString willTopic = MQTTSNString_initializer; - if ( packet->getWILLTOPIC(&willQos, &willRetain, &willTopic) == 0 ) - { - return; - } - client->setWillTopic(willTopic); - Connect* connectData = client->getConnectData(); + if (packet->getWILLTOPIC(&willQos, &willRetain, &willTopic) == 0) + { + return; + } + client->setWillTopic(willTopic); + Connect* connectData = client->getConnectData(); - /* add the connectData for MQTT CONNECT message */ - connectData->willTopic = client->getWillTopic(); - connectData->flags.bits.willQoS = willQos; - connectData->flags.bits.willRetain = willRetain; + /* add the connectData for MQTT CONNECT message */ + connectData->willTopic = client->getWillTopic(); + connectData->flags.bits.willQoS = willQos; + connectData->flags.bits.willRetain = willRetain; - /* Send WILLMSGREQ to the client */ - client->setWaitWillMsgFlg(true); - MQTTSNPacket* reqMsg = new MQTTSNPacket(); - reqMsg->setWILLMSGREQ(); - Event* evt = new Event(); - evt->setClientSendEvent(client, reqMsg); - _gateway->getClientSendQue()->post(evt); + /* Send WILLMSGREQ to the client */ + client->setWaitWillMsgFlg(true); + MQTTSNPacket* reqMsg = new MQTTSNPacket(); + reqMsg->setWILLMSGREQ(); + Event* evt = new Event(); + evt->setClientSendEvent(client, reqMsg); + _gateway->getClientSendQue()->post(evt); } /* @@ -188,35 +190,36 @@ void MQTTSNConnectionHandler::handleWilltopic(Client* client, MQTTSNPacket* pack */ void MQTTSNConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet) { - if ( !client->isWaitWillMsg() ) - { - DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n"); - return; - } + if (!client->isWaitWillMsg()) + { + DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n"); + return; + } - MQTTSNString willmsg = MQTTSNString_initializer; - Connect* connectData = client->getConnectData(); + MQTTSNString willmsg = MQTTSNString_initializer; + Connect* connectData = client->getConnectData(); - if( client->isConnectSendable() ) - { - /* save WillMsg in the client */ - if ( packet->getWILLMSG(&willmsg) == 0 ) - { - return; - } - client->setWillMsg(willmsg); + if (client->isConnectSendable()) + { + /* save WillMsg in the client */ + if (packet->getWILLMSG(&willmsg) == 0) + { + return; + } + client->setWillMsg(willmsg); - /* create CONNECT message */ - MQTTGWPacket* mqttPacket = new MQTTGWPacket(); - connectData->willMsg = client->getWillMsg(); - mqttPacket->setCONNECT(connectData, (unsigned char*)_gateway->getGWParams()->loginId, (unsigned char*)_gateway->getGWParams()->password); + /* create CONNECT message */ + MQTTGWPacket* mqttPacket = new MQTTGWPacket(); + connectData->willMsg = client->getWillMsg(); + mqttPacket->setCONNECT(connectData, (unsigned char*) _gateway->getGWParams()->loginId, + (unsigned char*) _gateway->getGWParams()->password); - /* Send CONNECT to the broker */ - Event* evt = new Event(); - evt->setBrokerSendEvent(client, mqttPacket); - client->setWaitWillMsgFlg(false); - _gateway->getBrokerSendQue()->post(evt); - } + /* Send CONNECT to the broker */ + Event* evt = new Event(); + evt->setBrokerSendEvent(client, mqttPacket); + client->setWaitWillMsgFlg(false); + _gateway->getBrokerSendQue()->post(evt); + } } /* @@ -226,9 +229,9 @@ void MQTTSNConnectionHandler::handleDisconnect(Client* client, MQTTSNPacket* pac { uint16_t duration = 0; - if ( packet->getDISCONNECT(&duration) != 0 ) + if (packet->getDISCONNECT(&duration) != 0) { - if ( duration == 0 ) + if (duration == 0) { MQTTGWPacket* mqMsg = new MQTTGWPacket(); mqMsg->setHeader(DISCONNECT); @@ -250,12 +253,12 @@ void MQTTSNConnectionHandler::handleDisconnect(Client* client, MQTTSNPacket* pac */ void MQTTSNConnectionHandler::handleWilltopicupd(Client* client, MQTTSNPacket* packet) { - /* send NOT_SUPPORTED responce to the client */ - MQTTSNPacket* respMsg = new MQTTSNPacket(); - respMsg->setWILLTOPICRESP(MQTTSN_RC_NOT_SUPPORTED); - Event* evt = new Event(); - evt->setClientSendEvent(client, respMsg); - _gateway->getClientSendQue()->post(evt); + /* send NOT_SUPPORTED responce to the client */ + MQTTSNPacket* respMsg = new MQTTSNPacket(); + respMsg->setWILLTOPICRESP(MQTTSN_RC_NOT_SUPPORTED); + Event* evt = new Event(); + evt->setClientSendEvent(client, respMsg); + _gateway->getClientSendQue()->post(evt); } /* @@ -263,12 +266,12 @@ void MQTTSNConnectionHandler::handleWilltopicupd(Client* client, MQTTSNPacket* p */ void MQTTSNConnectionHandler::handleWillmsgupd(Client* client, MQTTSNPacket* packet) { - /* send NOT_SUPPORTED responce to the client */ - MQTTSNPacket* respMsg = new MQTTSNPacket(); - respMsg->setWILLMSGRESP(MQTTSN_RC_NOT_SUPPORTED); - Event* evt = new Event(); - evt->setClientSendEvent(client, respMsg); - _gateway->getClientSendQue()->post(evt); + /* send NOT_SUPPORTED responce to the client */ + MQTTSNPacket* respMsg = new MQTTSNPacket(); + respMsg->setWILLMSGRESP(MQTTSN_RC_NOT_SUPPORTED); + Event* evt = new Event(); + evt->setClientSendEvent(client, respMsg); + _gateway->getClientSendQue()->post(evt); } /* @@ -276,31 +279,31 @@ void MQTTSNConnectionHandler::handleWillmsgupd(Client* client, MQTTSNPacket* pac */ void MQTTSNConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet) { - if ( ( client->isSleep() || client->isAwake() ) && client->getClientSleepPacket() ) - { - sendStoredPublish(client); - client->holdPingRequest(); - } - else - { + if ((client->isSleep() || client->isAwake()) && client->getClientSleepPacket()) + { + sendStoredPublish(client); + client->holdPingRequest(); + } + else + { /* send PINGREQ to the broker */ - client->resetPingRequest(); + client->resetPingRequest(); MQTTGWPacket* pingreq = new MQTTGWPacket(); pingreq->setHeader(PINGREQ); Event* evt = new Event(); evt->setBrokerSendEvent(client, pingreq); _gateway->getBrokerSendQue()->post(evt); - } + } } void MQTTSNConnectionHandler::sendStoredPublish(Client* client) { MQTTGWPacket* msg = nullptr; - while ( ( msg = client->getClientSleepPacket() ) != nullptr ) + while ((msg = client->getClientSleepPacket()) != nullptr) { // ToDo: This version can't re-send PUBLISH when PUBACK is not returned. - client->deleteFirstClientSleepPacket(); // pop the que to delete element. + client->deleteFirstClientSleepPacket(); // pop the que to delete element. Event* ev = new Event(); ev->setBrokerRecvEvent(client, msg); diff --git a/MQTTSNGateway/src/MQTTSNGWConnectionHandler.h b/MQTTSNGateway/src/MQTTSNGWConnectionHandler.h index 6af6113..eb75177 100644 --- a/MQTTSNGateway/src/MQTTSNGWConnectionHandler.h +++ b/MQTTSNGateway/src/MQTTSNGWConnectionHandler.h @@ -25,21 +25,21 @@ namespace MQTTSNGW class MQTTSNConnectionHandler { public: - MQTTSNConnectionHandler(Gateway* gateway); - ~MQTTSNConnectionHandler(); - void sendADVERTISE(void); - void handleSearchgw(MQTTSNPacket* packet); - void handleConnect(Client* client, MQTTSNPacket* packet); - void handleWilltopic(Client* client, MQTTSNPacket* packet); - void handleWillmsg(Client* client, MQTTSNPacket* packet); - void handleDisconnect(Client* client, MQTTSNPacket* packet); - void handleWilltopicupd(Client* client, MQTTSNPacket* packet); - void handleWillmsgupd(Client* client, MQTTSNPacket* packet); - void handlePingreq(Client* client, MQTTSNPacket* packet); + MQTTSNConnectionHandler(Gateway* gateway); + ~MQTTSNConnectionHandler(); + void sendADVERTISE(void); + void handleSearchgw(MQTTSNPacket* packet); + void handleConnect(Client* client, MQTTSNPacket* packet); + void handleWilltopic(Client* client, MQTTSNPacket* packet); + void handleWillmsg(Client* client, MQTTSNPacket* packet); + void handleDisconnect(Client* client, MQTTSNPacket* packet); + void handleWilltopicupd(Client* client, MQTTSNPacket* packet); + void handleWillmsgupd(Client* client, MQTTSNPacket* packet); + void handlePingreq(Client* client, MQTTSNPacket* packet); private: - void sendStoredPublish(Client* client); + void sendStoredPublish(Client* client); - Gateway* _gateway; + Gateway* _gateway; }; } diff --git a/MQTTSNGateway/src/MQTTSNGWDefines.h b/MQTTSNGateway/src/MQTTSNGWDefines.h index d73827d..bf55b62 100644 --- a/MQTTSNGateway/src/MQTTSNGWDefines.h +++ b/MQTTSNGateway/src/MQTTSNGWDefines.h @@ -37,7 +37,7 @@ namespace MQTTSNGW /*================================= * MQTT-SN Parametrs ==================================*/ -#define MAX_CLIENTS (100) // Number of Clients can be handled. +#define MAX_CLIENTS (100) // Default number of Clients can be handled. #define MAX_CLIENTID_LENGTH (64) // Max length of clientID #define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages #define MAX_MESSAGEID_TABLE_SIZE (500) // Number of MessageIdTable size @@ -53,21 +53,26 @@ namespace MQTTSNGW /*================================= * Data Type ==================================*/ -typedef unsigned char uint8_t; +typedef unsigned char uint8_t; typedef unsigned short uint16_t; -typedef unsigned int uint32_t; +typedef unsigned int uint32_t; /*================================= * Log controls ==================================*/ -//#define DEBUG // print out log for debug -//#define DEBUG_NWSTACK // print out SensorNetwork log - -#ifdef DEBUG +//#define DEBUG_MQTTSN // print out log for debug +//#define DEBUG_NW // print out SensorNetwork log +#ifdef DEBUG_MQTTSN #define DEBUGLOG(...) printf(__VA_ARGS__) #else #define DEBUGLOG(...) #endif +#ifdef DEBUG_NW +#define D_NWSTACK(...) printf(__VA_ARGS__) +#else +#define D_NWSTACK(...) +#endif + } #endif /* MQTTSNGWDEFINES_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.cpp b/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.cpp index 750867f..24c2afe 100644 --- a/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.cpp +++ b/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.cpp @@ -21,17 +21,15 @@ using namespace MQTTSNGW; using namespace std; -WirelessNodeId::WirelessNodeId() - : - _len{0}, - _nodeId{0} +WirelessNodeId::WirelessNodeId() : + _len { 0 }, _nodeId { 0 } { } WirelessNodeId::~WirelessNodeId() { - if ( _nodeId ) + if (_nodeId) { free(_nodeId); } @@ -39,12 +37,12 @@ WirelessNodeId::~WirelessNodeId() void WirelessNodeId::setId(uint8_t* id, uint8_t len) { - if ( _nodeId ) - { - free(_nodeId); - } - uint8_t* buf = (uint8_t*)malloc(len); - if ( buf ) + if (_nodeId) + { + free(_nodeId); + } + uint8_t* buf = (uint8_t*) malloc(len); + if (buf) { memcpy(buf, id, len); _len = len; @@ -64,7 +62,7 @@ void WirelessNodeId::setId(WirelessNodeId* id) bool WirelessNodeId::operator ==(WirelessNodeId& id) { - if ( _len == id._len ) + if (_len == id._len) { return memcmp(_nodeId, id._nodeId, _len) == 0; } @@ -77,16 +75,14 @@ bool WirelessNodeId::operator ==(WirelessNodeId& id) /* * Class MQTTSNGWEncapsulatedPacket */ -MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket() - : _mqttsn{0}, - _ctrl{0} +MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket() : + _mqttsn { 0 }, _ctrl { 0 } { } -MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket(MQTTSNPacket* packet) - : _mqttsn{packet}, - _ctrl{0} +MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket(MQTTSNPacket* packet) : + _mqttsn { packet }, _ctrl { 0 } { } @@ -109,18 +105,18 @@ int MQTTSNGWEncapsulatedPacket::serialize(uint8_t* buf) buf[0] = _id._len + 3; buf[1] = MQTTSN_ENCAPSULATED; buf[2] = _ctrl; - memcpy( buf + 3, _id._nodeId, _id._len); - if ( _mqttsn ) + memcpy(buf + 3, _id._nodeId, _id._len); + if (_mqttsn) { len = _mqttsn->getPacketLength(); memcpy(buf + buf[0], _mqttsn->getPacketData(), len); } - return buf[0] + len; + return buf[0] + len; } int MQTTSNGWEncapsulatedPacket::desirialize(unsigned char* buf, unsigned short len) { - if ( _mqttsn ) + if (_mqttsn) { delete _mqttsn; _mqttsn = nullptr; diff --git a/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.h b/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.h index eb2cba6..080b9ab 100644 --- a/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.h +++ b/MQTTSNGateway/src/MQTTSNGWEncapsulatedPacket.h @@ -60,6 +60,4 @@ private: } - - #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWENCAPSULATEDPACKET_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWForwarder.cpp b/MQTTSNGateway/src/MQTTSNGWForwarder.cpp index 71b2e83..a157747 100644 --- a/MQTTSNGateway/src/MQTTSNGWForwarder.cpp +++ b/MQTTSNGateway/src/MQTTSNGWForwarder.cpp @@ -22,7 +22,7 @@ using namespace MQTTSNGW; using namespace std; /*===================================== - Class ForwarderList + Class ForwarderList =====================================*/ ForwarderList::ForwarderList() @@ -32,10 +32,10 @@ ForwarderList::ForwarderList() ForwarderList::~ForwarderList() { - if ( _head ) + if (_head) { Forwarder* p = _head; - while ( p ) + while (p) { Forwarder* next = p->_next; delete p; @@ -44,20 +44,18 @@ ForwarderList::~ForwarderList() } } - void ForwarderList::initialize(Gateway* gw) { - /* Create Fowarders from clients.conf */ - gw->getClientList()->setClientList(FORWARDER_TYPE); + /* Create Fowarders from clients.conf */ + gw->getClientList()->setClientList(FORWARDER_TYPE); } - Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr) { Forwarder* p = _head; - while ( p ) + while (p) { - if ( p->_sensorNetAddr.isMatch(addr) ) + if (p->_sensorNetAddr.isMatch(addr)) { break; } @@ -66,19 +64,19 @@ Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr) return p; } -Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId) +Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId) { Forwarder* fdr = new Forwarder(addr, forwarderId); - if ( _head == nullptr ) + if (_head == nullptr) { _head = fdr; } else { Forwarder* p = _head; - while ( p ) + while (p) { - if ( p->_next == nullptr ) + if (p->_next == nullptr) { p->_next = fdr; break; @@ -99,10 +97,10 @@ Forwarder::Forwarder() } /*===================================== - Class ForwarderList + Class ForwarderList =====================================*/ -Forwarder::Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId) +Forwarder::Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId) { _forwarderName = string(forwarderId->cstring); _sensorNetAddr = *addr; @@ -112,10 +110,10 @@ Forwarder::Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId) Forwarder::~Forwarder(void) { - if ( _headClient ) + if (_headClient) { ForwarderElement* p = _headClient; - while ( p ) + while (p) { ForwarderElement* next = p->_next; delete p; @@ -136,11 +134,11 @@ void Forwarder::addClient(Client* client, WirelessNodeId* id) client->setForwarder(this); - if ( p != nullptr ) + if (p != nullptr) { - while ( p ) + while (p) { - if ( p->_client == client ) + if (p->_client == client) { client->setForwarder(this); p->setWirelessNodeId(id); @@ -156,7 +154,7 @@ void Forwarder::addClient(Client* client, WirelessNodeId* id) fclient->setClient(client); fclient->setWirelessNodeId(id); - if ( prev ) + if (prev) { prev->_next = fclient; } @@ -171,9 +169,9 @@ Client* Forwarder::getClient(WirelessNodeId* id) Client* cl = nullptr; _mutex.lock(); ForwarderElement* p = _headClient; - while ( p ) + while (p) { - if ( *(p->_wirelessNodeId) == *id ) + if (*(p->_wirelessNodeId) == *id) { cl = p->_client; break; @@ -197,9 +195,9 @@ WirelessNodeId* Forwarder::getWirelessNodeId(Client* client) WirelessNodeId* nodeId = nullptr; _mutex.lock(); ForwarderElement* p = _headClient; - while ( p ) + while (p) { - if ( p->_client == client ) + if (p->_client == client) { nodeId = p->_wirelessNodeId; break; @@ -219,11 +217,11 @@ void Forwarder::eraseClient(Client* client) _mutex.lock(); ForwarderElement* p = _headClient; - while ( p ) + while (p) { - if ( p->_client == client ) + if (p->_client == client) { - if ( prev ) + if (prev) { prev->_next = p->_next; } @@ -251,10 +249,8 @@ SensorNetAddress* Forwarder::getSensorNetAddr(void) * Class ForwardedClient */ -ForwarderElement::ForwarderElement() - : _client{0} - , _wirelessNodeId{0} - , _next{0} +ForwarderElement::ForwarderElement() : + _client { 0 }, _wirelessNodeId { 0 }, _next { 0 } { } @@ -273,7 +269,7 @@ void ForwarderElement::setClient(Client* client) void ForwarderElement::setWirelessNodeId(WirelessNodeId* id) { - if ( _wirelessNodeId == nullptr ) + if (_wirelessNodeId == nullptr) { _wirelessNodeId = new WirelessNodeId(); } diff --git a/MQTTSNGateway/src/MQTTSNGWForwarder.h b/MQTTSNGateway/src/MQTTSNGWForwarder.h index a7279d2..9730030 100644 --- a/MQTTSNGateway/src/MQTTSNGWForwarder.h +++ b/MQTTSNGateway/src/MQTTSNGWForwarder.h @@ -22,7 +22,6 @@ #include "MQTTSNGWEncapsulatedPacket.h" #include "SensorNetwork.h" - namespace MQTTSNGW { class Gateway; @@ -30,7 +29,7 @@ class Client; class WirelessNodeId; /*===================================== - Class ForwarderElement + Class ForwarderElement =====================================*/ class ForwarderElement { @@ -48,14 +47,14 @@ private: }; /*===================================== - Class Forwarder + Class Forwarder =====================================*/ class Forwarder { friend class ForwarderList; public: Forwarder(void); - Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId); + Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId); ~Forwarder(); void initialize(void); @@ -70,13 +69,13 @@ public: private: string _forwarderName; SensorNetAddress _sensorNetAddr; - ForwarderElement* _headClient{nullptr}; - Forwarder* _next {nullptr}; + ForwarderElement* _headClient { nullptr }; + Forwarder* _next { nullptr }; Mutex _mutex; }; /*===================================== - Class ForwarderList + Class ForwarderList =====================================*/ class ForwarderList { @@ -86,7 +85,7 @@ public: void initialize(Gateway* gw); Forwarder* getForwarder(SensorNetAddress* addr); - Forwarder* addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId); + Forwarder* addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId); private: Forwarder* _head; @@ -94,6 +93,4 @@ private: } - - #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWFORWARDER_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWLogmonitor.cpp b/MQTTSNGateway/src/MQTTSNGWLogmonitor.cpp index 692e3fe..be4587f 100644 --- a/MQTTSNGateway/src/MQTTSNGWLogmonitor.cpp +++ b/MQTTSNGateway/src/MQTTSNGWLogmonitor.cpp @@ -22,7 +22,7 @@ using namespace MQTTSNGW; Logmonitor::Logmonitor() { - theProcess = this; + theProcess = this; } Logmonitor::~Logmonitor() @@ -32,17 +32,17 @@ Logmonitor::~Logmonitor() void Logmonitor::run() { - while (true) - { - const char* data = getLog(); - if ( *data == 0 ) - { - break; - } - else - { - printf("%s", data); - } - } + while (true) + { + const char* data = getLog(); + if (*data == 0) + { + break; + } + else + { + printf("%s", data); + } + } } diff --git a/MQTTSNGateway/src/MQTTSNGWLogmonitor.h b/MQTTSNGateway/src/MQTTSNGWLogmonitor.h index cb5838a..a0745bf 100644 --- a/MQTTSNGateway/src/MQTTSNGWLogmonitor.h +++ b/MQTTSNGateway/src/MQTTSNGWLogmonitor.h @@ -23,9 +23,9 @@ namespace MQTTSNGW class Logmonitor: public Process { public: - Logmonitor(); - ~Logmonitor(); - void run(); + Logmonitor(); + ~Logmonitor(); + void run(); }; } diff --git a/MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp b/MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp index b87e06c..8db2cb1 100644 --- a/MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp +++ b/MQTTSNGateway/src/MQTTSNGWMessageIdTable.cpp @@ -29,187 +29,181 @@ MessageIdTable::MessageIdTable() MessageIdTable::~MessageIdTable() { - _mutex.lock(); - if ( _head != nullptr ) - { - MessageIdElement* p = _tail; - while ( p ) - { - MessageIdElement* pPrev = p; - delete p; - _cnt--; - p = pPrev->_prev; - } - _head = _tail = nullptr; - } - _mutex.unlock(); + _mutex.lock(); + if (_head != nullptr) + { + MessageIdElement* p = _tail; + while (p) + { + MessageIdElement* pPrev = p; + delete p; + _cnt--; + p = pPrev->_prev; + } + _head = _tail = nullptr; + } + _mutex.unlock(); } MessageIdElement* MessageIdTable::add(Aggregater* aggregater, Client* client, uint16_t clientMsgId) { - if ( _cnt > _maxSize ) - { - return nullptr; - } + if (_cnt > _maxSize) + { + return nullptr; + } - MessageIdElement* elm = new MessageIdElement(0, client, clientMsgId); - if ( elm == nullptr ) - { - return nullptr; - } - _mutex.lock(); - if ( _head == nullptr ) - { - elm->_msgId = aggregater->msgId(); - _head = elm; - _tail = elm; - _cnt++; - } - else - { - MessageIdElement* p = find(client, clientMsgId); - if ( p == nullptr ) - { - elm->_msgId = aggregater->msgId(); - p = _tail; - _tail = elm; - elm->_prev = p; - p->_next = elm; - _cnt++; - } - else - { - delete elm; - elm = nullptr; - } - } - _mutex.unlock(); - return elm; + MessageIdElement* elm = new MessageIdElement(0, client, clientMsgId); + if (elm == nullptr) + { + return nullptr; + } + _mutex.lock(); + if (_head == nullptr) + { + elm->_msgId = aggregater->msgId(); + _head = elm; + _tail = elm; + _cnt++; + } + else + { + MessageIdElement* p = find(client, clientMsgId); + if (p == nullptr) + { + elm->_msgId = aggregater->msgId(); + p = _tail; + _tail = elm; + elm->_prev = p; + p->_next = elm; + _cnt++; + } + else + { + delete elm; + elm = nullptr; + } + } + _mutex.unlock(); + return elm; } MessageIdElement* MessageIdTable::find(uint16_t msgId) { - MessageIdElement* p = _head; - while ( p ) - { - if ( p->_msgId == msgId) - { - break; - } - p = p->_next; - } - return p; + MessageIdElement* p = _head; + while (p) + { + if (p->_msgId == msgId) + { + break; + } + p = p->_next; + } + return p; } MessageIdElement* MessageIdTable::find(Client* client, uint16_t clientMsgId) { - MessageIdElement* p = _head; - while ( p ) - { - if ( p->_clientMsgId == clientMsgId && p->_client == client) - { - break; - } - p = p->_next; - } - return p; + MessageIdElement* p = _head; + while (p) + { + if (p->_clientMsgId == clientMsgId && p->_client == client) + { + break; + } + p = p->_next; + } + return p; } - Client* MessageIdTable::getClientMsgId(uint16_t msgId, uint16_t* clientMsgId) { - Client* clt = nullptr; - *clientMsgId = 0; - _mutex.lock(); - MessageIdElement* p = find(msgId); - if ( p != nullptr ) - { - clt = p->_client; - *clientMsgId = p->_clientMsgId; - clear(p); - } - _mutex.unlock(); - return clt; + Client* clt = nullptr; + *clientMsgId = 0; + _mutex.lock(); + MessageIdElement* p = find(msgId); + if (p != nullptr) + { + clt = p->_client; + *clientMsgId = p->_clientMsgId; + clear(p); + } + _mutex.unlock(); + return clt; } void MessageIdTable::erase(uint16_t msgId) { - _mutex.lock(); - MessageIdElement* p = find(msgId); - clear(p); - _mutex.unlock(); + _mutex.lock(); + MessageIdElement* p = find(msgId); + clear(p); + _mutex.unlock(); } void MessageIdTable::clear(MessageIdElement* elm) { - if ( elm == nullptr ) - { - return; - } + if (elm == nullptr) + { + return; + } - if ( elm->_prev == nullptr ) - { - _head = elm->_next; - if ( _head == nullptr) - { - _tail = nullptr; - } - else - { - _head->_prev = nullptr; - } - delete elm; - _cnt--; - return; - } - else - { - elm->_prev->_next = elm->_next; - if ( elm->_next == nullptr ) - { - _tail = elm->_prev; - } - else - { - elm->_next->_prev = elm->_prev; - } - delete elm; - _cnt--; - return; - } + if (elm->_prev == nullptr) + { + _head = elm->_next; + if (_head == nullptr) + { + _tail = nullptr; + } + else + { + _head->_prev = nullptr; + } + delete elm; + _cnt--; + return; + } + else + { + elm->_prev->_next = elm->_next; + if (elm->_next == nullptr) + { + _tail = elm->_prev; + } + else + { + elm->_next->_prev = elm->_prev; + } + delete elm; + _cnt--; + return; + } } - uint16_t MessageIdTable::getMsgId(Client* client, uint16_t clientMsgId) { - uint16_t msgId = 0; - MessageIdElement* p = find(client, clientMsgId); - if ( p != nullptr ) - { - msgId = p->_msgId; - } - return msgId; + uint16_t msgId = 0; + MessageIdElement* p = find(client, clientMsgId); + if (p != nullptr) + { + msgId = p->_msgId; + } + return msgId; } /*=============================== * Class MessageIdElement ===============================*/ -MessageIdElement::MessageIdElement(void) - : _msgId{0} - , _clientMsgId {0} - , _client {nullptr} - , _next {nullptr} - , _prev {nullptr} +MessageIdElement::MessageIdElement(void) : + _msgId { 0 }, _clientMsgId { 0 }, _client { nullptr }, _next { nullptr }, _prev { nullptr } { } -MessageIdElement::MessageIdElement(uint16_t msgId, Client* client, uint16_t clientMsgId) - : MessageIdElement() +MessageIdElement::MessageIdElement(uint16_t msgId, Client* client, uint16_t clientMsgId) : + MessageIdElement() { - _msgId = msgId; - _client = client; - _clientMsgId = clientMsgId; + _msgId = msgId; + _client = client; + _clientMsgId = clientMsgId; } MessageIdElement::~MessageIdElement(void) diff --git a/MQTTSNGateway/src/MQTTSNGWMessageIdTable.h b/MQTTSNGateway/src/MQTTSNGWMessageIdTable.h index 59f7be6..2f0b5e6 100644 --- a/MQTTSNGateway/src/MQTTSNGWMessageIdTable.h +++ b/MQTTSNGateway/src/MQTTSNGWMessageIdTable.h @@ -34,22 +34,23 @@ class Aggregater; class MessageIdTable { public: - MessageIdTable(); - ~MessageIdTable(); + MessageIdTable(); + ~MessageIdTable(); - MessageIdElement* add(Aggregater* aggregater, Client* client, uint16_t clientMsgId); - Client* getClientMsgId(uint16_t msgId, uint16_t* clientMsgId); - uint16_t getMsgId(Client* client, uint16_t clientMsgId); - void erase(uint16_t msgId); - void clear(MessageIdElement* elm); + MessageIdElement* add(Aggregater* aggregater, Client* client, + uint16_t clientMsgId); + Client* getClientMsgId(uint16_t msgId, uint16_t* clientMsgId); + uint16_t getMsgId(Client* client, uint16_t clientMsgId); + void erase(uint16_t msgId); + void clear(MessageIdElement* elm); private: - MessageIdElement* find(uint16_t msgId); - MessageIdElement* find(Client* client, uint16_t clientMsgId); - MessageIdElement* _head {nullptr}; - MessageIdElement* _tail {nullptr}; - int _cnt {0}; - int _maxSize {MAX_MESSAGEID_TABLE_SIZE}; - Mutex _mutex; + MessageIdElement* find(uint16_t msgId); + MessageIdElement* find(Client* client, uint16_t clientMsgId); + MessageIdElement* _head { nullptr }; + MessageIdElement* _tail{ nullptr }; + int _cnt { 0 }; + int _maxSize { MAX_MESSAGEID_TABLE_SIZE }; + Mutex _mutex; }; /*===================================== @@ -67,12 +68,11 @@ public: private: uint16_t _msgId; uint16_t _clientMsgId; - Client* _client; + Client* _client; MessageIdElement* _next; MessageIdElement* _prev; }; - } #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWMESSAGEIDTABLE_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWPacket.cpp b/MQTTSNGateway/src/MQTTSNGWPacket.cpp index c2a017a..72189db 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacket.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPacket.cpp @@ -29,286 +29,278 @@ void writeInt(unsigned char** pptr, int msgId); MQTTSNPacket::MQTTSNPacket(void) { - _buf = nullptr; - _bufLen = 0; + _buf = nullptr; + _bufLen = 0; } MQTTSNPacket::MQTTSNPacket(MQTTSNPacket& packet) { - _buf = (unsigned char*)malloc(packet._bufLen); - if (_buf) - { - _bufLen = packet._bufLen; - memcpy(_buf, packet._buf, _bufLen); - } - else - { - _buf = nullptr; - _bufLen = 0; - } + _buf = (unsigned char*) malloc(packet._bufLen); + if (_buf) + { + _bufLen = packet._bufLen; + memcpy(_buf, packet._buf, _bufLen); + } + else + { + _buf = nullptr; + _bufLen = 0; + } } MQTTSNPacket::~MQTTSNPacket() { - if (_buf) - { - free(_buf); - } + if (_buf) + { + free(_buf); + } } int MQTTSNPacket::unicast(SensorNetwork* network, SensorNetAddress* sendTo) { - return network->unicast(_buf, _bufLen, sendTo); + return network->unicast(_buf, _bufLen, sendTo); } int MQTTSNPacket::broadcast(SensorNetwork* network) { - return network->broadcast(_buf, _bufLen); + return network->broadcast(_buf, _bufLen); } int MQTTSNPacket::serialize(uint8_t* buf) { - buf = _buf; - return _bufLen; + buf = _buf; + return _bufLen; } int MQTTSNPacket::desirialize(unsigned char* buf, unsigned short len) { - if ( _buf ) - { - free(_buf); - } + if (_buf) + { + free(_buf); + } - _buf = (unsigned char*)calloc(len, sizeof(unsigned char)); - if ( _buf ) - { - memcpy(_buf, buf, len); - _bufLen = len; - } - else - { - _bufLen = 0; - } - return _bufLen; + _buf = (unsigned char*) calloc(len, sizeof(unsigned char)); + if (_buf) + { + memcpy(_buf, buf, len); + _bufLen = len; + } + else + { + _bufLen = 0; + } + return _bufLen; } int MQTTSNPacket::recv(SensorNetwork* network) { - uint8_t buf[MQTTSNGW_MAX_PACKET_SIZE]; - int len = network->read((uint8_t*) buf, MQTTSNGW_MAX_PACKET_SIZE); - if (len > 1) - { - len = desirialize(buf, len); - } - else - { - len = 0; - } - return len; + uint8_t buf[MQTTSNGW_MAX_PACKET_SIZE]; + int len = network->read((uint8_t*) buf, MQTTSNGW_MAX_PACKET_SIZE); + if (len > 1) + { + len = desirialize(buf, len); + } + return len; } int MQTTSNPacket::getType(void) { - if ( _bufLen == 0 ) - { - return 0; - } - int value = 0; - int p = MQTTSNPacket_decode(_buf, _bufLen, &value); - return _buf[p]; + if (_bufLen == 0) + { + return 0; + } + int value = 0; + int p = MQTTSNPacket_decode(_buf, _bufLen, &value); + return _buf[p]; } bool MQTTSNPacket::isQoSMinusPUBLISH(void) { - if ( _bufLen == 0 ) + if (_bufLen == 0) { return false;; } int value = 0; int p = MQTTSNPacket_decode(_buf, _bufLen, &value); - return ( (_buf[p] == MQTTSN_PUBLISH) && ((_buf[p + 1] & 0x60 ) == 0x60 )); + return ((_buf[p] == MQTTSN_PUBLISH) && ((_buf[p + 1] & 0x60) == 0x60)); } unsigned char* MQTTSNPacket::getPacketData(void) { - return _buf; + return _buf; } int MQTTSNPacket::getPacketLength(void) { - return _bufLen; + return _bufLen; } const char* MQTTSNPacket::getName() { - return MQTTSNPacket_name(getType()); + return MQTTSNPacket_name(getType()); } int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration) { - unsigned char buf[5]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_advertise(buf, buflen, (unsigned char) gatewayid, - (unsigned short) duration); - return desirialize(buf, len); + unsigned char buf[5]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_advertise(buf, buflen, (unsigned char) gatewayid, (unsigned short) duration); + return desirialize(buf, len); } int MQTTSNPacket::setGWINFO(uint8_t gatewayId) { - unsigned char buf[3]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_gwinfo(buf, buflen, (unsigned char) gatewayId, 0, 0); - return desirialize(buf, len); + unsigned char buf[3]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_gwinfo(buf, buflen, (unsigned char) gatewayId, 0, 0); + return desirialize(buf, len); } int MQTTSNPacket::setConnect(void) { - unsigned char buf[40]; - int buflen = sizeof(buf); - MQTTSNPacket_connectData data; - data.clientID.cstring = (char*)"client01"; - int len = MQTTSNSerialize_connect(buf, buflen, &data); - return desirialize(buf, len); + unsigned char buf[40]; + int buflen = sizeof(buf); + MQTTSNPacket_connectData data; + data.clientID.cstring = (char*) "client01"; + int len = MQTTSNSerialize_connect(buf, buflen, &data); + return desirialize(buf, len); } bool MQTTSNPacket::isAccepted(void) { - return ( getType() == MQTTSN_CONNACK) && (_buf[2] == MQTTSN_RC_ACCEPTED); + return (getType() == MQTTSN_CONNACK) && (_buf[2] == MQTTSN_RC_ACCEPTED); } int MQTTSNPacket::setCONNACK(uint8_t returnCode) { - unsigned char buf[3]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_connack(buf, buflen, (int) returnCode); - return desirialize(buf, len); + unsigned char buf[3]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_connack(buf, buflen, (int) returnCode); + return desirialize(buf, len); } int MQTTSNPacket::setWILLTOPICREQ(void) { - unsigned char buf[2]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_willtopicreq(buf, buflen); - return desirialize(buf, len); + unsigned char buf[2]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_willtopicreq(buf, buflen); + return desirialize(buf, len); } int MQTTSNPacket::setWILLMSGREQ(void) { - unsigned char buf[2]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_willmsgreq(buf, buflen); - return desirialize(buf, len); + unsigned char buf[2]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_willmsgreq(buf, buflen); + return desirialize(buf, len); } int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* topicName) { - unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_register(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, - topicName); - return desirialize(buf, len); + unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_register(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, topicName); + return desirialize(buf, len); } int MQTTSNPacket::setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode) { - unsigned char buf[7]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_regack(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, - (unsigned char) returnCode); - return desirialize(buf, len); + unsigned char buf[7]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_regack(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); + return desirialize(buf, len); } -int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, MQTTSN_topicid topic, - uint8_t* payload, uint16_t payloadlen) +int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, MQTTSN_topicid topic, uint8_t* payload, + uint16_t payloadlen) { - unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_publish(buf, buflen, (unsigned char) dup, qos, (unsigned char) retained, - (unsigned short) msgId, topic, (unsigned char*) payload, (int) payloadlen); - return desirialize(buf, len); + unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_publish(buf, buflen, (unsigned char) dup, qos, (unsigned char) retained, (unsigned short) msgId, + topic, (unsigned char*) payload, (int) payloadlen); + return desirialize(buf, len); } int MQTTSNPacket::setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode) { - unsigned char buf[7]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_puback(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, - (unsigned char) returnCode); - return desirialize(buf, len); + unsigned char buf[7]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_puback(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode); + return desirialize(buf, len); } int MQTTSNPacket::setPUBREC(uint16_t msgId) { - unsigned char buf[4]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_pubrec(buf, buflen, (unsigned short) msgId); - return desirialize(buf, len); + unsigned char buf[4]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_pubrec(buf, buflen, (unsigned short) msgId); + return desirialize(buf, len); } int MQTTSNPacket::setPUBREL(uint16_t msgId) { - unsigned char buf[4]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_pubrel(buf, buflen, (unsigned short) msgId); - return desirialize(buf, len); + unsigned char buf[4]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_pubrel(buf, buflen, (unsigned short) msgId); + return desirialize(buf, len); } int MQTTSNPacket::setPUBCOMP(uint16_t msgId) { - unsigned char buf[4]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_pubcomp(buf, buflen, (unsigned short) msgId); - return desirialize(buf, len); + unsigned char buf[4]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_pubcomp(buf, buflen, (unsigned short) msgId); + return desirialize(buf, len); } int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode) { - unsigned char buf[8]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_suback(buf, buflen, qos, (unsigned short) topicId, - (unsigned short) msgId, (unsigned char) returnCode); - return desirialize(buf, len); + unsigned char buf[8]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_suback(buf, buflen, qos, (unsigned short) topicId, (unsigned short) msgId, + (unsigned char) returnCode); + return desirialize(buf, len); } int MQTTSNPacket::setUNSUBACK(uint16_t msgId) { - unsigned char buf[4]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_unsuback(buf, buflen, (unsigned short) msgId); - return desirialize(buf, len); + unsigned char buf[4]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_unsuback(buf, buflen, (unsigned short) msgId); + return desirialize(buf, len); } int MQTTSNPacket::setPINGRESP(void) { - unsigned char buf[32]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_pingresp(buf, buflen); - return desirialize(buf, len); + unsigned char buf[32]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_pingresp(buf, buflen); + return desirialize(buf, len); } int MQTTSNPacket::setDISCONNECT(uint16_t duration) { - unsigned char buf[4]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_disconnect(buf, buflen, (int) duration); - return desirialize(buf, len); + unsigned char buf[4]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_disconnect(buf, buflen, (int) duration); + return desirialize(buf, len); } int MQTTSNPacket::setWILLTOPICRESP(uint8_t returnCode) { - unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_willtopicresp(buf, buflen, (int) returnCode); - return desirialize(buf, len); + unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_willtopicresp(buf, buflen, (int) returnCode); + return desirialize(buf, len); } int MQTTSNPacket::setWILLMSGRESP(uint8_t returnCode) { - unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; - int buflen = sizeof(buf); - int len = MQTTSNSerialize_willmsgresp(buf, buflen, (int) returnCode); - return desirialize(buf, len); + unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; + int buflen = sizeof(buf); + int len = MQTTSNSerialize_willmsgresp(buf, buflen, (int) returnCode); + return desirialize(buf, len); } int MQTTSNPacket::setCONNECT(MQTTSNPacket_connectData* options) @@ -323,262 +315,262 @@ int MQTTSNPacket::setPINGREQ(MQTTSNString* clientId) { unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; int buflen = sizeof(buf); - int len = MQTTSNSerialize_pingreq( buf, buflen, *clientId); + int len = MQTTSNSerialize_pingreq(buf, buflen, *clientId); return desirialize(buf, len); } int MQTTSNPacket::getSERCHGW(uint8_t* radius) { - return MQTTSNDeserialize_searchgw((unsigned char*) radius, (unsigned char*) _buf, _bufLen); + return MQTTSNDeserialize_searchgw((unsigned char*) radius, (unsigned char*) _buf, _bufLen); } int MQTTSNPacket::getCONNECT(MQTTSNPacket_connectData* data) { - return MQTTSNDeserialize_connect(data, _buf, _bufLen); + return MQTTSNDeserialize_connect(data, _buf, _bufLen); } int MQTTSNPacket::getCONNACK(uint8_t* returnCode) { - return MQTTSNSerialize_connack(_buf, _bufLen, (int) *returnCode); + return MQTTSNSerialize_connack(_buf, _bufLen, (int) *returnCode); } int MQTTSNPacket::getWILLTOPIC(int* willQoS, uint8_t* willRetain, MQTTSNString* willTopic) { - return MQTTSNDeserialize_willtopic((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen); + return MQTTSNDeserialize_willtopic((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen); } int MQTTSNPacket::getWILLMSG(MQTTSNString* willmsg) { - return MQTTSNDeserialize_willmsg(willmsg, _buf, _bufLen); + return MQTTSNDeserialize_willmsg(willmsg, _buf, _bufLen); } int MQTTSNPacket::getREGISTER(uint16_t* topicId, uint16_t* msgId, MQTTSNString* topicName) { - return MQTTSNDeserialize_register((unsigned short*) topicId, (unsigned short*) msgId, topicName, - _buf, _bufLen); + return MQTTSNDeserialize_register((unsigned short*) topicId, (unsigned short*) msgId, topicName, _buf, _bufLen); } int MQTTSNPacket::getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode) { - return MQTTSNDeserialize_regack((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf, _bufLen); + return MQTTSNDeserialize_regack((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf, + _bufLen); } int MQTTSNPacket::getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId, MQTTSN_topicid* topic, - uint8_t** payload, int* payloadlen) + uint8_t** payload, int* payloadlen) { - return MQTTSNDeserialize_publish((unsigned char*) dup, qos, (unsigned char*) retained, (unsigned short*) msgId, - topic, (unsigned char**) payload, (int*) payloadlen, _buf, _bufLen); + return MQTTSNDeserialize_publish((unsigned char*) dup, qos, (unsigned char*) retained, (unsigned short*) msgId, topic, + (unsigned char**) payload, (int*) payloadlen, _buf, _bufLen); } int MQTTSNPacket::getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode) { - return MQTTSNDeserialize_puback((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, - _buf, _bufLen); + return MQTTSNDeserialize_puback((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf, + _bufLen); } int MQTTSNPacket::getACK(uint16_t* msgId) { - unsigned char type; - return MQTTSNDeserialize_ack(&type, (unsigned short*) msgId, _buf, _bufLen); + unsigned char type; + return MQTTSNDeserialize_ack(&type, (unsigned short*) msgId, _buf, _bufLen); } int MQTTSNPacket::getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId, MQTTSN_topicid* topicFilter) { - return MQTTSNDeserialize_subscribe((unsigned char*) dup, qos, (unsigned short*) msgId, topicFilter, _buf, _bufLen); + return MQTTSNDeserialize_subscribe((unsigned char*) dup, qos, (unsigned short*) msgId, topicFilter, _buf, _bufLen); } int MQTTSNPacket::getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter) { - return MQTTSNDeserialize_unsubscribe((unsigned short*) msgId, topicFilter, _buf, _bufLen); + return MQTTSNDeserialize_unsubscribe((unsigned short*) msgId, topicFilter, _buf, _bufLen); } int MQTTSNPacket::getPINGREQ(void) { - if (getType() == MQTTSN_PINGRESP && _bufLen > 2 ) - { - return _bufLen - 2; - } - return 0; + if (getType() == MQTTSN_PINGRESP && _bufLen > 2) + { + return _bufLen - 2; + } + return 0; } int MQTTSNPacket::getDISCONNECT(uint16_t* duration) { - int dur = 0; - int rc = MQTTSNDeserialize_disconnect(&dur, _buf, _bufLen); - *duration = (uint16_t)dur; - return rc; + int dur = 0; + int rc = MQTTSNDeserialize_disconnect(&dur, _buf, _bufLen); + *duration = (uint16_t) dur; + return rc; } int MQTTSNPacket::getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic) { - return MQTTSNDeserialize_willtopicupd((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen); + return MQTTSNDeserialize_willtopicupd((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen); } int MQTTSNPacket::getWILLMSGUPD(MQTTSNString* willMsg) { - return MQTTSNDeserialize_willmsgupd(willMsg, _buf, _bufLen); + return MQTTSNDeserialize_willmsgupd(willMsg, _buf, _bufLen); } char* MQTTSNPacket::print(char* pbuf) { - char* ptr = pbuf; - char** pptr = &pbuf; - int size = _bufLen > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : _bufLen; + char* ptr = pbuf; + char** pptr = &pbuf; + int size = _bufLen > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : _bufLen; - for (int i = 0; i < size; i++) - { - sprintf(*pptr, " %02X", *(_buf + i)); - *pptr += 3; - } - **pptr = 0; - return ptr; + for (int i = 0; i < size; i++) + { + sprintf(*pptr, " %02X", *(_buf + i)); + *pptr += 3; + } + **pptr = 0; + return ptr; } char* MQTTSNPacket::getMsgId(char* pbuf) { - int value = 0; - int p = 0; + int value = 0; + int p = 0; - switch ( getType() ) - { - case MQTTSN_PUBLISH: - p = MQTTSNPacket_decode(_buf, _bufLen, &value); - if ( _buf[p + 1] & 0x80 ) - { - sprintf(pbuf, "+%02X%02X", _buf[p + 4], _buf[p + 5]); - } - else - { - sprintf(pbuf, " %02X%02X", _buf[p + 4], _buf[p + 5]); - } - break; - case MQTTSN_PUBACK: - case MQTTSN_REGISTER: - case MQTTSN_REGACK: - sprintf(pbuf, " %02X%02X", _buf[4], _buf[5]); - break; - case MQTTSN_PUBREC: - case MQTTSN_PUBREL: - case MQTTSN_PUBCOMP: - case MQTTSN_UNSUBACK: - sprintf(pbuf, " %02X%02X", _buf[2], _buf[3]); - break; - case MQTTSN_SUBSCRIBE: - case MQTTSN_UNSUBSCRIBE: - p = MQTTSNPacket_decode(_buf, _bufLen, &value); - sprintf(pbuf, " %02X%02X", _buf[p + 2], _buf[p + 3]); - break; - case MQTTSN_SUBACK: - sprintf(pbuf, " %02X%02X", _buf[5], _buf[6]); - break; - default: - sprintf(pbuf, " "); - break; - } - if ( strcmp(pbuf, " 0000") == 0 ) - { - sprintf(pbuf, " "); - } - return pbuf; + switch (getType()) + { + case MQTTSN_PUBLISH: + p = MQTTSNPacket_decode(_buf, _bufLen, &value); + if (_buf[p + 1] & 0x80) + { + sprintf(pbuf, "+%02X%02X", _buf[p + 4], _buf[p + 5]); + } + else + { + sprintf(pbuf, " %02X%02X", _buf[p + 4], _buf[p + 5]); + } + break; + case MQTTSN_PUBACK: + case MQTTSN_REGISTER: + case MQTTSN_REGACK: + sprintf(pbuf, " %02X%02X", _buf[4], _buf[5]); + break; + case MQTTSN_PUBREC: + case MQTTSN_PUBREL: + case MQTTSN_PUBCOMP: + case MQTTSN_UNSUBACK: + sprintf(pbuf, " %02X%02X", _buf[2], _buf[3]); + break; + case MQTTSN_SUBSCRIBE: + case MQTTSN_UNSUBSCRIBE: + p = MQTTSNPacket_decode(_buf, _bufLen, &value); + sprintf(pbuf, " %02X%02X", _buf[p + 2], _buf[p + 3]); + break; + case MQTTSN_SUBACK: + sprintf(pbuf, " %02X%02X", _buf[5], _buf[6]); + break; + default: + sprintf(pbuf, " "); + break; + } + if (strcmp(pbuf, " 0000") == 0) + { + sprintf(pbuf, " "); + } + return pbuf; } int MQTTSNPacket::getMsgId(void) { - int value = 0; - int p = 0; - int msgId = 0; - char* ptr = 0; + int value = 0; + int p = 0; + int msgId = 0; + char* ptr = 0; - switch ( getType() ) - { - case MQTTSN_PUBLISH: - p = MQTTSNPacket_decode(_buf, _bufLen, &value); - ptr = (char*)_buf + p + 4; - msgId = readInt((char**)&ptr); - break; - case MQTTSN_PUBACK: - case MQTTSN_REGISTER: - case MQTTSN_REGACK: - ptr = (char*)_buf + 4; - msgId = readInt((char**)&ptr); - break; - case MQTTSN_PUBREC: - case MQTTSN_PUBREL: - case MQTTSN_PUBCOMP: - case MQTTSN_UNSUBACK: - ptr = (char*)_buf + 2; - msgId = readInt((char**)&ptr); - break; - case MQTTSN_SUBSCRIBE: - case MQTTSN_UNSUBSCRIBE: - p = MQTTSNPacket_decode(_buf, _bufLen, &value); - ptr = (char*)_buf + p + 2; - msgId = readInt((char**)&ptr); - break; - case MQTTSN_SUBACK: - ptr = (char*)_buf + 5; - msgId = readInt((char**)&ptr); - break; - default: - break; - } - return msgId; + switch (getType()) + { + case MQTTSN_PUBLISH: + p = MQTTSNPacket_decode(_buf, _bufLen, &value); + ptr = (char*) _buf + p + 4; + msgId = readInt((char**) &ptr); + break; + case MQTTSN_PUBACK: + case MQTTSN_REGISTER: + case MQTTSN_REGACK: + ptr = (char*) _buf + 4; + msgId = readInt((char**) &ptr); + break; + case MQTTSN_PUBREC: + case MQTTSN_PUBREL: + case MQTTSN_PUBCOMP: + case MQTTSN_UNSUBACK: + ptr = (char*) _buf + 2; + msgId = readInt((char**) &ptr); + break; + case MQTTSN_SUBSCRIBE: + case MQTTSN_UNSUBSCRIBE: + p = MQTTSNPacket_decode(_buf, _bufLen, &value); + ptr = (char*) _buf + p + 2; + msgId = readInt((char**) &ptr); + break; + case MQTTSN_SUBACK: + ptr = (char*) _buf + 5; + msgId = readInt((char**) &ptr); + break; + default: + break; + } + return msgId; } void MQTTSNPacket::setMsgId(uint16_t msgId) { - int value = 0; - int p = 0; - //unsigned char* ptr = 0; + int value = 0; + int p = 0; + //unsigned char* ptr = 0; - switch ( getType() ) - { - case MQTTSN_PUBLISH: - p = MQTTSNPacket_decode(_buf, _bufLen, &value); - _buf[p + 4] = (unsigned char)(msgId / 256); - _buf[p + 5] = (unsigned char)(msgId % 256); - //ptr = _buf + p + 4; - //writeInt(&ptr, msgId); - break; - case MQTTSN_PUBACK: - case MQTTSN_REGISTER: - case MQTTSN_REGACK: - _buf[4] = (unsigned char)(msgId / 256); - _buf[5] = (unsigned char)(msgId % 256); - //ptr = _buf + 4; - //writeInt(&ptr, msgId); - break; - case MQTTSN_PUBREC: - case MQTTSN_PUBREL: - case MQTTSN_PUBCOMP: - case MQTTSN_UNSUBACK: - _buf[2] = (unsigned char)(msgId / 256); - _buf[3] = (unsigned char)(msgId % 256); - //ptr = _buf + 2; - //writeInt(&ptr, msgId); - break; - case MQTTSN_SUBSCRIBE: - case MQTTSN_UNSUBSCRIBE: - p = MQTTSNPacket_decode(_buf, _bufLen, &value); - _buf[p + 2] = (unsigned char)(msgId / 256); - _buf[p + 3] = (unsigned char)(msgId % 256); - //ptr = _buf + p + 2; - //writeInt(&ptr, msgId); -break; - case MQTTSN_SUBACK: - _buf[5] = (unsigned char)(msgId / 256); - _buf[6] = (unsigned char)(msgId % 256); - //ptr = _buf + 5; - //writeInt(&ptr, msgId); -break; - default: - break; - } + switch (getType()) + { + case MQTTSN_PUBLISH: + p = MQTTSNPacket_decode(_buf, _bufLen, &value); + _buf[p + 4] = (unsigned char) (msgId / 256); + _buf[p + 5] = (unsigned char) (msgId % 256); + //ptr = _buf + p + 4; + //writeInt(&ptr, msgId); + break; + case MQTTSN_PUBACK: + case MQTTSN_REGISTER: + case MQTTSN_REGACK: + _buf[4] = (unsigned char) (msgId / 256); + _buf[5] = (unsigned char) (msgId % 256); + //ptr = _buf + 4; + //writeInt(&ptr, msgId); + break; + case MQTTSN_PUBREC: + case MQTTSN_PUBREL: + case MQTTSN_PUBCOMP: + case MQTTSN_UNSUBACK: + _buf[2] = (unsigned char) (msgId / 256); + _buf[3] = (unsigned char) (msgId % 256); + //ptr = _buf + 2; + //writeInt(&ptr, msgId); + break; + case MQTTSN_SUBSCRIBE: + case MQTTSN_UNSUBSCRIBE: + p = MQTTSNPacket_decode(_buf, _bufLen, &value); + _buf[p + 2] = (unsigned char) (msgId / 256); + _buf[p + 3] = (unsigned char) (msgId % 256); + //ptr = _buf + p + 2; + //writeInt(&ptr, msgId); + break; + case MQTTSN_SUBACK: + _buf[5] = (unsigned char) (msgId / 256); + _buf[6] = (unsigned char) (msgId % 256); + //ptr = _buf + 5; + //writeInt(&ptr, msgId); + break; + default: + break; + } } bool MQTTSNPacket::isDuplicate(void) { - int value = 0; - int p = MQTTSNPacket_decode(_buf, _bufLen, &value); - return ( _buf[p + 1] & 0x80 ); + int value = 0; + int p = MQTTSNPacket_decode(_buf, _bufLen, &value); + return (_buf[p + 1] & 0x80); } diff --git a/MQTTSNGateway/src/MQTTSNGWPacket.h b/MQTTSNGateway/src/MQTTSNGWPacket.h index 7a624a3..4ac3007 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacket.h +++ b/MQTTSNGateway/src/MQTTSNGWPacket.h @@ -22,76 +22,82 @@ namespace MQTTSNGW { +class SensorNetwork; class MQTTSNPacket { public: - MQTTSNPacket(void); - MQTTSNPacket(MQTTSNPacket &packet); - ~MQTTSNPacket(void); - int unicast(SensorNetwork* network, SensorNetAddress* sendTo); - int broadcast(SensorNetwork* network); - int recv(SensorNetwork* network); - int serialize(uint8_t* buf); - int desirialize(unsigned char* buf, unsigned short len); - int getType(void); - unsigned char* getPacketData(void); - int getPacketLength(void); - const char* getName(); + MQTTSNPacket(void); + MQTTSNPacket(MQTTSNPacket &packet); + ~MQTTSNPacket(void); + int unicast(SensorNetwork* network, SensorNetAddress* sendTo); + int broadcast(SensorNetwork* network); + int recv(SensorNetwork* network); + int serialize(uint8_t* buf); + int desirialize(unsigned char* buf, unsigned short len); + int getType(void); + unsigned char* getPacketData(void); + int getPacketLength(void); + const char* getName(); - int setConnect(void); // Debug - int setADVERTISE(uint8_t gatewayid, uint16_t duration); - int setGWINFO(uint8_t gatewayId); - int setCONNACK(uint8_t returnCode); - int setWILLTOPICREQ(void); - int setWILLMSGREQ(void); - int setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* TopicName); - int setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode); - int setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, - MQTTSN_topicid topic, uint8_t* payload, uint16_t payloadlen); - int setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode); - int setPUBREC(uint16_t msgId); - int setPUBREL(uint16_t msgId); - int setPUBCOMP(uint16_t msgId); - int setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode); - int setUNSUBACK(uint16_t msgId); - int setPINGRESP(void); - int setDISCONNECT(uint16_t duration); - int setWILLTOPICRESP(uint8_t returnCode); - int setWILLMSGRESP(uint8_t returnCode); + int setConnect(void); // Debug + int setADVERTISE(uint8_t gatewayid, uint16_t duration); + int setGWINFO(uint8_t gatewayId); + int setCONNACK(uint8_t returnCode); + int setWILLTOPICREQ(void); + int setWILLMSGREQ(void); + int setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* TopicName); + int setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode); + int setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, + MQTTSN_topicid topic, uint8_t* payload, uint16_t payloadlen); + int setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode); + int setPUBREC(uint16_t msgId); + int setPUBREL(uint16_t msgId); + int setPUBCOMP(uint16_t msgId); + int setSUBACK(int qos, uint16_t topicId, uint16_t msgId, + uint8_t returnCode); + int setUNSUBACK(uint16_t msgId); + int setPINGRESP(void); + int setDISCONNECT(uint16_t duration); + int setWILLTOPICRESP(uint8_t returnCode); + int setWILLMSGRESP(uint8_t returnCode); - int setCONNECT(MQTTSNPacket_connectData* options); - int setPINGREQ(MQTTSNString* clientId); + int setCONNECT(MQTTSNPacket_connectData* options); + int setPINGREQ(MQTTSNString* clientId); - int getSERCHGW(uint8_t* radius); - int getCONNECT(MQTTSNPacket_connectData* option); - int getCONNACK(uint8_t* returnCode); - int getWILLTOPIC(int* willQoS, uint8_t* willRetain, MQTTSNString* willTopic); - int getWILLMSG(MQTTSNString* willmsg); - int getREGISTER(uint16_t* topicId, uint16_t* msgId, MQTTSNString* topicName); - int getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode); - int getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId, - MQTTSN_topicid* topic, unsigned char** payload, int* payloadlen); - int getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode); - int getACK(uint16_t* msgId); - int getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId, MQTTSN_topicid* topicFilter); - int getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter); - int getPINGREQ(void); - int getDISCONNECT(uint16_t* duration); - int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic); - int getWILLMSGUPD(MQTTSNString* willMsg); + int getSERCHGW(uint8_t* radius); + int getCONNECT(MQTTSNPacket_connectData* option); + int getCONNACK(uint8_t* returnCode); + int getWILLTOPIC(int* willQoS, uint8_t* willRetain, + MQTTSNString* willTopic); + int getWILLMSG(MQTTSNString* willmsg); + int getREGISTER(uint16_t* topicId, uint16_t* msgId, + MQTTSNString* topicName); + int getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode); + int getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId, + MQTTSN_topicid* topic, unsigned char** payload, int* payloadlen); + int getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode); + int getACK(uint16_t* msgId); + int getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId, + MQTTSN_topicid* topicFilter); + int getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter); + int getPINGREQ(void); + int getDISCONNECT(uint16_t* duration); + int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, + MQTTSNString* willTopic); + int getWILLMSGUPD(MQTTSNString* willMsg); - bool isAccepted(void); - bool isDuplicate(void); - bool isQoSMinusPUBLISH(void); - char* getMsgId(char* buf); - int getMsgId(void); - void setMsgId(uint16_t msgId); - char* print(char* buf); + bool isAccepted(void); + bool isDuplicate(void); + bool isQoSMinusPUBLISH(void); + char* getMsgId(char* buf); + int getMsgId(void); + void setMsgId(uint16_t msgId); + char* print(char* buf); private: - unsigned char* _buf; // Ptr to a packet data - int _bufLen; // length of the packet data + unsigned char* _buf; // Ptr to a packet data + int _bufLen; // length of the packet data }; } diff --git a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp index f195d76..08d1cfb 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.cpp @@ -38,22 +38,24 @@ using namespace MQTTSNGW; #define EVENT_QUE_TIME_OUT 2000 // 2000 msecs char* currentDateTime(void); + /*===================================== Class PacketHandleTask =====================================*/ PacketHandleTask::PacketHandleTask(Gateway* gateway) { - _gateway = gateway; - _gateway->attach((Thread*)this); - _mqttConnection = new MQTTGWConnectionHandler(_gateway); - _mqttPublish = new MQTTGWPublishHandler(_gateway); - _mqttSubscribe = new MQTTGWSubscribeHandler(_gateway); - _mqttsnConnection = new MQTTSNConnectionHandler(_gateway); - _mqttsnPublish = new MQTTSNPublishHandler(_gateway); - _mqttsnSubscribe = new MQTTSNSubscribeHandler(_gateway); + _gateway = gateway; + _gateway->attach((Thread*) this); + _mqttConnection = new MQTTGWConnectionHandler(_gateway); + _mqttPublish = new MQTTGWPublishHandler(_gateway); + _mqttSubscribe = new MQTTGWSubscribeHandler(_gateway); + _mqttsnConnection = new MQTTSNConnectionHandler(_gateway); + _mqttsnPublish = new MQTTSNPublishHandler(_gateway); + _mqttsnSubscribe = new MQTTSNSubscribeHandler(_gateway); - _mqttsnAggrConnection = new MQTTSNAggregateConnectionHandler(_gateway); + _mqttsnAggrConnection = new MQTTSNAggregateConnectionHandler(_gateway); + setTaskName("PacketHandleTask"); } /** @@ -61,315 +63,309 @@ PacketHandleTask::PacketHandleTask(Gateway* gateway) */ PacketHandleTask::~PacketHandleTask() { - if ( _mqttConnection ) - { - delete _mqttConnection; - } - if ( _mqttPublish ) - { - delete _mqttPublish; - } - if ( _mqttSubscribe ) - { - delete _mqttSubscribe; - } - if ( _mqttsnConnection ) - { - delete _mqttsnConnection; - } - if ( _mqttsnPublish ) - { - delete _mqttsnPublish; - } - if ( _mqttsnSubscribe ) - { - delete _mqttsnSubscribe; - } + if (_mqttConnection) + { + delete _mqttConnection; + } + if (_mqttPublish) + { + delete _mqttPublish; + } + if (_mqttSubscribe) + { + delete _mqttSubscribe; + } + if (_mqttsnConnection) + { + delete _mqttsnConnection; + } + if (_mqttsnPublish) + { + delete _mqttsnPublish; + } + if (_mqttsnSubscribe) + { + delete _mqttsnSubscribe; + } - if ( _mqttsnAggrConnection ) - { - delete _mqttsnAggrConnection; - } + if (_mqttsnAggrConnection) + { + delete _mqttsnAggrConnection; + } } void PacketHandleTask::run() { - Event* ev = nullptr; - EventQue* eventQue = _gateway->getPacketEventQue(); + Event* ev = nullptr; + EventQue* eventQue = _gateway->getPacketEventQue(); AdapterManager* adpMgr = _gateway->getAdapterManager(); - Client* client = nullptr; - MQTTSNPacket* snPacket = nullptr; - MQTTGWPacket* brPacket = nullptr; - char msgId[6]; - memset(msgId, 0, 6); + Client* client = nullptr; + MQTTSNPacket* snPacket = nullptr; + MQTTGWPacket* brPacket = nullptr; + char msgId[6]; + memset(msgId, 0, 6); - _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); + _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); - while (true) - { - /* wait Event */ - ev = eventQue->timedwait(EVENT_QUE_TIME_OUT); + while (true) + { + /* wait Event */ + ev = eventQue->timedwait(EVENT_QUE_TIME_OUT); - if (ev->getEventType() == EtStop) - { - WRITELOG("\n%s PacketHandleTask stopped.", currentDateTime()); - delete ev; - return; - } + if (ev->getEventType() == EtStop) + { + WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName()); + delete ev; + return; + } - if (ev->getEventType() == EtTimeout) - { - /*------ Check Keep Alive Timer & send Advertise ------*/ - if (_advertiseTimer.isTimeup()) - { - _mqttsnConnection->sendADVERTISE(); - _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); - } + if (ev->getEventType() == EtTimeout) + { + /*------ Check Keep Alive Timer & send Advertise ------*/ + if (_advertiseTimer.isTimeup()) + { + _mqttsnConnection->sendADVERTISE(); + _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); + } - /*------ Check Adapters Connect or PINGREQ ------*/ - adpMgr->checkConnection(); - } + /*------ Check Adapters Connect or PINGREQ ------*/ + adpMgr->checkConnection(); + } - /*------ Handle SEARCHGW Message ---------*/ - else if (ev->getEventType() == EtBroadcast) - { - snPacket = ev->getMQTTSNPacket(); - _mqttsnConnection->handleSearchgw(snPacket); - } + /*------ Handle SEARCHGW Message ---------*/ + else if (ev->getEventType() == EtBroadcast) + { + snPacket = ev->getMQTTSNPacket(); + _mqttsnConnection->handleSearchgw(snPacket); + } - /*------ Handle Messages form Clients ---------*/ - else if (ev->getEventType() == EtClientRecv) - { - client = ev->getClient(); - snPacket = ev->getMQTTSNPacket(); + /*------ Handle Messages form Clients ---------*/ + else if (ev->getEventType() == EtClientRecv) + { + client = ev->getClient(); + snPacket = ev->getMQTTSNPacket(); - DEBUGLOG(" PacketHandleTask gets %s %s from the client.\n", snPacket->getName(), snPacket->getMsgId(msgId)); + DEBUGLOG(" PacketHandleTask gets %s %s from the client.\n", snPacket->getName(), snPacket->getMsgId(msgId)); - if ( adpMgr->isAggregatedClient(client) ) - { - aggregatePacketHandler(client, snPacket); // client is converted to Aggregater by BrokerSendTask - } - else - { - transparentPacketHandler(client, snPacket); - } + if (adpMgr->isAggregatedClient(client)) + { + aggregatePacketHandler(client, snPacket); // client is converted to Aggregater by BrokerSendTask + } + else + { + transparentPacketHandler(client, snPacket); + } + /* Reset the Timer for PINGREQ. */ + client->updateStatus(snPacket); + } + /*------ Handle Messages form Broker ---------*/ + else if (ev->getEventType() == EtBrokerRecv) + { + client = ev->getClient(); + brPacket = ev->getMQTTGWPacket(); + DEBUGLOG(" PacketHandleTask gets %s %s from the broker.\n", brPacket->getName(), brPacket->getMsgId(msgId)); - /* Reset the Timer for PINGREQ. */ - client->updateStatus(snPacket); - } - /*------ Handle Messages form Broker ---------*/ - else if ( ev->getEventType() == EtBrokerRecv ) - { - client = ev->getClient(); - brPacket = ev->getMQTTGWPacket(); - DEBUGLOG(" PacketHandleTask gets %s %s from the broker.\n", brPacket->getName(), brPacket->getMsgId(msgId)); - - - if ( client->isAggregater() ) - { - aggregatePacketHandler(client, brPacket); - } - else - { - transparentPacketHandler(client, brPacket); - } - } - delete ev; - } + if (client->isAggregater()) + { + aggregatePacketHandler(client, brPacket); + } + else + { + transparentPacketHandler(client, brPacket); + } + } + delete ev; + } } - - void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTSNPacket* packet) { - switch (packet->getType()) - { - case MQTTSN_CONNECT: - _mqttsnAggrConnection->handleConnect(client, packet); - break; - case MQTTSN_WILLTOPIC: - _mqttsnConnection->handleWilltopic(client, packet); - break; - case MQTTSN_WILLMSG: - _mqttsnAggrConnection->handleWillmsg(client, packet); - break; - case MQTTSN_DISCONNECT: - _mqttsnAggrConnection->handleDisconnect(client, packet); - break; - case MQTTSN_WILLTOPICUPD: - _mqttsnConnection->handleWilltopicupd(client, packet); - break; - case MQTTSN_WILLMSGUPD: - _mqttsnConnection->handleWillmsgupd(client, packet); - break; - case MQTTSN_PINGREQ: - _mqttsnAggrConnection->handlePingreq(client, packet); - break; - case MQTTSN_PUBLISH: - _mqttsnPublish->handleAggregatePublish(client, packet); - break; - case MQTTSN_PUBACK: - _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBACK); - break; - case MQTTSN_PUBREC: - _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBREC); - break; - case MQTTSN_PUBREL: - _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBREL); - break; - case MQTTSN_PUBCOMP: - _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBCOMP); - break; - case MQTTSN_REGISTER: - _mqttsnPublish->handleRegister(client, packet); - break; - case MQTTSN_REGACK: - _mqttsnPublish->handleRegAck(client, packet); - break; - case MQTTSN_SUBSCRIBE: - _mqttsnSubscribe->handleAggregateSubscribe(client, packet); - break; - case MQTTSN_UNSUBSCRIBE: - _mqttsnSubscribe->handleAggregateUnsubscribe(client, packet); - break; - default: - break; - } + switch (packet->getType()) + { + case MQTTSN_CONNECT: + _mqttsnAggrConnection->handleConnect(client, packet); + break; + case MQTTSN_WILLTOPIC: + _mqttsnConnection->handleWilltopic(client, packet); + break; + case MQTTSN_WILLMSG: + _mqttsnAggrConnection->handleWillmsg(client, packet); + break; + case MQTTSN_DISCONNECT: + _mqttsnAggrConnection->handleDisconnect(client, packet); + break; + case MQTTSN_WILLTOPICUPD: + _mqttsnConnection->handleWilltopicupd(client, packet); + break; + case MQTTSN_WILLMSGUPD: + _mqttsnConnection->handleWillmsgupd(client, packet); + break; + case MQTTSN_PINGREQ: + _mqttsnAggrConnection->handlePingreq(client, packet); + break; + case MQTTSN_PUBLISH: + _mqttsnPublish->handleAggregatePublish(client, packet); + break; + case MQTTSN_PUBACK: + _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBACK); + break; + case MQTTSN_PUBREC: + _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBREC); + break; + case MQTTSN_PUBREL: + _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBREL); + break; + case MQTTSN_PUBCOMP: + _mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBCOMP); + break; + case MQTTSN_REGISTER: + _mqttsnPublish->handleRegister(client, packet); + break; + case MQTTSN_REGACK: + _mqttsnPublish->handleRegAck(client, packet); + break; + case MQTTSN_SUBSCRIBE: + _mqttsnSubscribe->handleAggregateSubscribe(client, packet); + break; + case MQTTSN_UNSUBSCRIBE: + _mqttsnSubscribe->handleAggregateUnsubscribe(client, packet); + break; + default: + break; + } } - void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTGWPacket* packet) { - switch (packet->getType()) - { - case CONNACK: - _mqttConnection->handleConnack(client, packet); - break; - case PINGRESP: - _mqttConnection->handlePingresp(client, packet); - break; - case PUBLISH: - _mqttPublish->handleAggregatePublish(client, packet); - break; - case PUBACK: - _mqttPublish->handleAggregatePuback(client, packet); - break; - case PUBREC: - _mqttPublish->handleAggregateAck(client, packet, PUBREC); - break; - case PUBREL: - _mqttPublish->handleAggregatePubrel(client, packet); - break; - case PUBCOMP: - _mqttPublish->handleAggregateAck(client, packet, PUBCOMP); - break; - case SUBACK: - _mqttSubscribe->handleAggregateSuback(client, packet); - break; - case UNSUBACK: - _mqttSubscribe->handleAggregateUnsuback(client, packet); - break; - default: - break; - } + switch (packet->getType()) + { + case CONNACK: + _mqttConnection->handleConnack(client, packet); + break; + case PINGRESP: + _mqttConnection->handlePingresp(client, packet); + break; + case PUBLISH: + _mqttPublish->handleAggregatePublish(client, packet); + break; + case PUBACK: + _mqttPublish->handleAggregatePuback(client, packet); + break; + case PUBREC: + _mqttPublish->handleAggregateAck(client, packet, PUBREC); + break; + case PUBREL: + _mqttPublish->handleAggregatePubrel(client, packet); + break; + case PUBCOMP: + _mqttPublish->handleAggregateAck(client, packet, PUBCOMP); + break; + case SUBACK: + _mqttSubscribe->handleAggregateSuback(client, packet); + break; + case UNSUBACK: + _mqttSubscribe->handleAggregateUnsuback(client, packet); + break; + default: + break; + } } void PacketHandleTask::transparentPacketHandler(Client*client, MQTTSNPacket* packet) { - switch (packet->getType()) - { - case MQTTSN_CONNECT: - _mqttsnConnection->handleConnect(client, packet); - break; - case MQTTSN_WILLTOPIC: - _mqttsnConnection->handleWilltopic(client, packet); - break; - case MQTTSN_WILLMSG: - _mqttsnConnection->handleWillmsg(client, packet); - break; - case MQTTSN_DISCONNECT: - _mqttsnConnection->handleDisconnect(client, packet); - break; - case MQTTSN_WILLTOPICUPD: - _mqttsnConnection->handleWilltopicupd(client, packet); - break; - case MQTTSN_WILLMSGUPD: - _mqttsnConnection->handleWillmsgupd(client, packet); - break; - case MQTTSN_PINGREQ: - _mqttsnConnection->handlePingreq(client, packet); - break; - case MQTTSN_PUBLISH: - _mqttsnPublish->handlePublish(client, packet); - break; - case MQTTSN_PUBACK: - _mqttsnPublish->handlePuback(client, packet); - break; - case MQTTSN_PUBREC: - _mqttsnPublish->handleAck(client, packet, PUBREC); - break; - case MQTTSN_PUBREL: - _mqttsnPublish->handleAck(client, packet, PUBREL); - break; - case MQTTSN_PUBCOMP: - _mqttsnPublish->handleAck(client, packet, PUBCOMP); - break; - case MQTTSN_REGISTER: - _mqttsnPublish->handleRegister(client, packet); - break; - case MQTTSN_REGACK: - _mqttsnPublish->handleRegAck(client, packet); - break; - case MQTTSN_SUBSCRIBE: - _mqttsnSubscribe->handleSubscribe(client, packet); - break; - case MQTTSN_UNSUBSCRIBE: - _mqttsnSubscribe->handleUnsubscribe(client, packet); - break; - default: - break; - } + switch (packet->getType()) + { + case MQTTSN_CONNECT: + _mqttsnConnection->handleConnect(client, packet); + break; + case MQTTSN_WILLTOPIC: + _mqttsnConnection->handleWilltopic(client, packet); + break; + case MQTTSN_WILLMSG: + _mqttsnConnection->handleWillmsg(client, packet); + break; + case MQTTSN_DISCONNECT: + _mqttsnConnection->handleDisconnect(client, packet); + break; + case MQTTSN_WILLTOPICUPD: + _mqttsnConnection->handleWilltopicupd(client, packet); + break; + case MQTTSN_WILLMSGUPD: + _mqttsnConnection->handleWillmsgupd(client, packet); + break; + case MQTTSN_PINGREQ: + _mqttsnConnection->handlePingreq(client, packet); + break; + case MQTTSN_PUBLISH: + _mqttsnPublish->handlePublish(client, packet); + break; + case MQTTSN_PUBACK: + _mqttsnPublish->handlePuback(client, packet); + break; + case MQTTSN_PUBREC: + _mqttsnPublish->handleAck(client, packet, PUBREC); + break; + case MQTTSN_PUBREL: + _mqttsnPublish->handleAck(client, packet, PUBREL); + break; + case MQTTSN_PUBCOMP: + _mqttsnPublish->handleAck(client, packet, PUBCOMP); + break; + case MQTTSN_REGISTER: + _mqttsnPublish->handleRegister(client, packet); + break; + case MQTTSN_REGACK: + _mqttsnPublish->handleRegAck(client, packet); + break; + case MQTTSN_SUBSCRIBE: + _mqttsnSubscribe->handleSubscribe(client, packet); + break; + case MQTTSN_UNSUBSCRIBE: + _mqttsnSubscribe->handleUnsubscribe(client, packet); + break; + default: + break; + } } - void PacketHandleTask::transparentPacketHandler(Client*client, MQTTGWPacket* packet) { - switch (packet->getType()) - { - case CONNACK: - _mqttConnection->handleConnack(client, packet); - break; - case PINGRESP: - _mqttConnection->handlePingresp(client, packet); - break; - case PUBLISH: - _mqttPublish->handlePublish(client, packet); - break; - case PUBACK: - _mqttPublish->handlePuback(client, packet); - break; - case PUBREC: - _mqttPublish->handleAck(client, packet, PUBREC); - break; - case PUBREL: - _mqttPublish->handleAck(client, packet, PUBREL); - break; - case PUBCOMP: - _mqttPublish->handleAck(client, packet, PUBCOMP); - break; - case SUBACK: - _mqttSubscribe->handleSuback(client, packet); - break; - case UNSUBACK: - _mqttSubscribe->handleUnsuback(client, packet); - break; - case DISCONNECT: - client->disconnected(); // Just change Client's status to "Disconnected" - break; - default: - break; - } + switch (packet->getType()) + { + case CONNACK: + _mqttConnection->handleConnack(client, packet); + break; + case PINGRESP: + _mqttConnection->handlePingresp(client, packet); + break; + case PUBLISH: + _mqttPublish->handlePublish(client, packet); + break; + case PUBACK: + _mqttPublish->handlePuback(client, packet); + break; + case PUBREC: + _mqttPublish->handleAck(client, packet, PUBREC); + break; + case PUBREL: + _mqttPublish->handleAck(client, packet, PUBREL); + break; + case PUBCOMP: + _mqttPublish->handleAck(client, packet, PUBCOMP); + break; + case SUBACK: + _mqttSubscribe->handleSuback(client, packet); + break; + case UNSUBACK: + _mqttSubscribe->handleUnsuback(client, packet); + break; + case DISCONNECT: + client->disconnected(); // Just change Client's status to "Disconnected" + break; + default: + break; + } } diff --git a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h index a77eb65..43cc57e 100644 --- a/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h +++ b/MQTTSNGateway/src/MQTTSNGWPacketHandleTask.h @@ -40,40 +40,39 @@ class MQTTSNAggregateConnectionHandler; class Thread; class Timer; /*===================================== - Class PacketHandleTask + Class PacketHandleTask =====================================*/ -class PacketHandleTask : public Thread +class PacketHandleTask: public Thread { - MAGIC_WORD_FOR_THREAD; - friend class MQTTGWAggregatePublishHandler; - friend class MQTTGWAggregateSubscribeHandler; - friend class MQTTSNAggregateConnectionHandler; - friend class MQTTSNAggregatePublishHandler; - friend class MQTTSNAggregateSubscribeHandler; +MAGIC_WORD_FOR_THREAD; + friend class MQTTGWAggregatePublishHandler; + friend class MQTTGWAggregateSubscribeHandler; + friend class MQTTSNAggregateConnectionHandler; + friend class MQTTSNAggregatePublishHandler; + friend class MQTTSNAggregateSubscribeHandler; public: - PacketHandleTask(Gateway* gateway); - ~PacketHandleTask(); - void run(); + PacketHandleTask(Gateway* gateway); + ~PacketHandleTask(); + void run(); private: - void aggregatePacketHandler(Client*client, MQTTSNPacket* packet); - void aggregatePacketHandler(Client*client, MQTTGWPacket* packet); - void transparentPacketHandler(Client*client, MQTTSNPacket* packet); - void transparentPacketHandler(Client*client, MQTTGWPacket* packet); + void aggregatePacketHandler(Client*client, MQTTSNPacket* packet); + void aggregatePacketHandler(Client*client, MQTTGWPacket* packet); + void transparentPacketHandler(Client*client, MQTTSNPacket* packet); + void transparentPacketHandler(Client*client, MQTTGWPacket* packet); - Gateway* _gateway {nullptr}; - Timer _advertiseTimer; - Timer _sendUnixTimer; - MQTTGWConnectionHandler* _mqttConnection {nullptr}; - MQTTGWPublishHandler* _mqttPublish {nullptr}; - MQTTGWSubscribeHandler* _mqttSubscribe {nullptr}; - MQTTSNConnectionHandler* _mqttsnConnection {nullptr}; - MQTTSNPublishHandler* _mqttsnPublish {nullptr}; - MQTTSNSubscribeHandler* _mqttsnSubscribe {nullptr}; - - MQTTSNAggregateConnectionHandler* _mqttsnAggrConnection {nullptr}; + Gateway* _gateway + { nullptr }; + Timer _advertiseTimer; + Timer _sendUnixTimer; + MQTTGWConnectionHandler* _mqttConnection { nullptr }; + MQTTGWPublishHandler* _mqttPublish { nullptr }; + MQTTGWSubscribeHandler* _mqttSubscribe { nullptr }; + MQTTSNConnectionHandler* _mqttsnConnection { nullptr }; + MQTTSNPublishHandler* _mqttsnPublish { nullptr }; + MQTTSNSubscribeHandler* _mqttsnSubscribe { nullptr }; + MQTTSNAggregateConnectionHandler* _mqttsnAggrConnection { nullptr }; }; - } #endif /* MQTTSNGWPACKETHANDLETASK_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWProcess.cpp b/MQTTSNGateway/src/MQTTSNGWProcess.cpp index 90accea..9473a36 100644 --- a/MQTTSNGateway/src/MQTTSNGWProcess.cpp +++ b/MQTTSNGateway/src/MQTTSNGWProcess.cpp @@ -13,10 +13,10 @@ * Contributors: * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ - #include #include #include +#include #include #include #include @@ -44,7 +44,7 @@ volatile int theSignaled = 0; static void signalHandler(int sig) { - theSignaled = sig; + theSignaled = sig; } /*===================================== @@ -52,23 +52,25 @@ static void signalHandler(int sig) ====================================*/ Process::Process() { - _argc = 0; - _argv = 0; - _configDir = CONFIG_DIRECTORY; - _configFile = CONFIG_FILE; - _log = 0; + _argc = 0; + _argv = 0; + _configDir = CONFIG_DIRECTORY; + _configFile = CONFIG_FILE; + _log = 0; + _rbsem = NULL; + _rb = NULL; } Process::~Process() { - if (_rb ) - { - delete _rb; - } - if ( _rbsem ) - { - delete _rbsem; - } + if (_rb) + { + delete _rb; + } + if (_rbsem) + { + delete _rbsem; + } } void Process::run() @@ -78,168 +80,185 @@ void Process::run() void Process::initialize(int argc, char** argv) { - char param[MQTTSNGW_PARAM_MAX]; - _argc = argc; - _argv = argv; - signal(SIGINT, signalHandler); - signal(SIGTERM, signalHandler); - signal(SIGHUP, signalHandler); + char param[MQTTSNGW_PARAM_MAX]; + _argc = argc; + _argv = argv; + signal(SIGINT, signalHandler); + signal(SIGTERM, signalHandler); + signal(SIGHUP, signalHandler); - int opt; - while ((opt = getopt(_argc, _argv, "f:")) != -1) - { - if ( opt == 'f' ) - { - string config = string(optarg); - size_t pos = 0; - if ( (pos = config.find_last_of("/")) == string::npos ) - { - _configFile = optarg; - } - else - { - _configFile = config.substr(pos + 1, config.size() - pos - 1);; - _configDir = config.substr(0, pos + 1); - } - } - } - _rbsem = new NamedSemaphore(MQTTSNGW_RB_SEMAPHOR_NAME, 0); - _rb = new RingBuffer(_configDir.c_str()); + int opt; + while ((opt = getopt(_argc, _argv, "f:")) != -1) + { + if (opt == 'f') + { + string config = string(optarg); + size_t pos = 0; + if ((pos = config.find_last_of("/")) == string::npos) + { + _configFile = optarg; + } + else + { + _configFile = config.substr(pos + 1, config.size() - pos - 1); + _configDir = config.substr(0, pos + 1); + } + } + } + _rbsem = new NamedSemaphore(MQTTSNGW_RB_SEMAPHOR_NAME, 0); + _rb = new RingBuffer(_configDir.c_str()); - if (getParam("ShearedMemory", param) == 0) - { - if (!strcasecmp(param, "YES")) - { - _log = 1; - } - else - { - _log = 0; - } - } + if (getParam("ShearedMemory", param) == 0) + { + if (!strcasecmp(param, "YES")) + { + _log = 1; + } + else + { + _log = 0; + } + } } void Process::putLog(const char* format, ...) { - _mt.lock(); - va_list arg; - va_start(arg, format); - vsprintf(_rbdata, format, arg); - va_end(arg); - if (strlen(_rbdata)) - { - if ( _log > 0 ) - { - _rb->put(_rbdata); - _rbsem->post(); - } - else - { - printf("%s", _rbdata); - } - } - _mt.unlock(); + _mt.lock(); + va_list arg; + va_start(arg, format); + vsprintf(_rbdata, format, arg); + va_end(arg); + if (strlen(_rbdata)) + { + if (_log > 0) + { + _rb->put(_rbdata); + _rbsem->post(); + } + else + { + printf("%s", _rbdata); + } + } + _mt.unlock(); } int Process::getArgc() { - return _argc; + return _argc; } char** Process::getArgv() { - return _argv; + return _argv; } int Process::getParam(const char* parameter, char* value) { - char str[MQTTSNGW_PARAM_MAX]; - char param[MQTTSNGW_PARAM_MAX]; - FILE *fp; + char str[MQTTSNGW_PARAM_MAX]; + char param[MQTTSNGW_PARAM_MAX]; + memset(str, 0, sizeof(str)); + memset(param, 0, sizeof(param)); + FILE *fp; - int i = 0, j = 0; - string configPath = _configDir + _configFile; + int i = 0, j = 0; + string configPath = _configDir + _configFile; - if ((fp = fopen(configPath.c_str(), "r")) == NULL) - { - throw Exception("No config file:[" + configPath + "]\n"); - } + if ((fp = fopen(configPath.c_str(), "r")) == NULL) + { + throw Exception("Config file not found:\n\nUsage: Command -f path/config_file_name\n", 0); + } - while (true) - { - if (fgets(str, MQTTSNGW_PARAM_MAX - 1, fp) == NULL) - { - fclose(fp); - return -3; - } - if (!strncmp(str, parameter, strlen(parameter))) - { - while (str[i++] != '=') - { - ; - } - while (str[i] != '\n') - { - param[j++] = str[i++]; - } - param[j] = '\0'; + int paramlen = strlen(parameter); - 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; - } - } - fclose(fp); - return -2; + while (true) + { + int pos = 0; + int len = 0; + if (fgets(str, MQTTSNGW_PARAM_MAX - 1, fp) == NULL) + { + fclose(fp); + return -3; + } + if (str[0] == '#' || str[0] == '\n') + { + continue; + } + + len = strlen(str); + for (pos = 0; i < len; pos++) + { + if (str[pos] == '=') + { + break; + } + } + + 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; + } + } + } + fclose(fp); + return -2; } const char* Process::getLog() { - int len = 0; - _mt.lock(); - while ((len = _rb->get(_rbdata, PROCESS_LOG_BUFFER_SIZE)) == 0) - { - _rbsem->timedwait(1000); - if ( checkSignal() == SIGINT) - { - break; - } - } - *(_rbdata + len) = 0; - _mt.unlock(); - return _rbdata; + int len = 0; + _mt.lock(); + while ((len = _rb->get(_rbdata, PROCESS_LOG_BUFFER_SIZE)) == 0) + { + _rbsem->timedwait(1000); + if (checkSignal() == SIGINT) + { + break; + } + } + *(_rbdata + len) = 0; + _mt.unlock(); + return _rbdata; } void Process::resetRingBuffer() { - _rb->reset(); + _rb->reset(); } int Process::checkSignal(void) { - return theSignaled; + return theSignaled; } const string* Process::getConfigDirName(void) { - return &_configDir; + return &_configDir; } const string* Process::getConfigFileName(void) { - return &_configFile; + return &_configFile; } /*===================================== @@ -247,130 +266,110 @@ const string* Process::getConfigFileName(void) ====================================*/ MultiTaskProcess::MultiTaskProcess() { - theMultiTaskProcess = this; - _threadCount = 0; - _stopCount = 0; + theMultiTaskProcess = this; + _threadCount = 0; + _stopCount = 0; } MultiTaskProcess::~MultiTaskProcess() { - for (int i = 0; i < _threadCount; i++) - { - _threadList[i]->stop(); - } + for (int i = 0; i < _threadCount; i++) + { + _threadList[i]->stop(); + } } void MultiTaskProcess::initialize(int argc, char** argv) { - Process::initialize(argc, argv); - for (int i = 0; i < _threadCount; i++) - { - _threadList[i]->initialize(argc, argv); - } + Process::initialize(argc, argv); + for (int i = 0; i < _threadCount; i++) + { + _threadList[i]->initialize(argc, argv); + } } void MultiTaskProcess::run(void) { - for (int i = 0; i < _threadCount; i++) - { - _threadList[i]->start(); - } + for (int i = 0; i < _threadCount; i++) + { + _threadList[i]->start(); + } - try - { - while(true) - { - if (theProcess->checkSignal() == SIGINT) - { - return; - } - sleep(1); - } - } - catch(Exception* ex) - { - ex->writeMessage(); - } - catch(...) - { - throw; - } + while (true) + { + if (theProcess->checkSignal() == SIGINT) + { + return; + } + sleep(1); + } } void MultiTaskProcess::waitStop(void) { - while (_stopCount < _threadCount) - { - sleep(1); - } + while (_stopCount < _threadCount) + { + sleep(1); + } } void MultiTaskProcess::threadStopped(void) { - _mutex.lock(); - _stopCount++; - _mutex.unlock(); + _mutex.lock(); + _stopCount++; + _mutex.unlock(); } +void MultiTaskProcess::abort(void) +{ + signalHandler(SIGINT); +} + void MultiTaskProcess::attach(Thread* thread) { - _mutex.lock(); - if (_threadCount < MQTTSNGW_MAX_TASK) - { - _threadList[_threadCount] = thread; - _threadCount++; - } - else - { - _mutex.unlock(); - throw Exception("Full of Threads"); - } - _mutex.unlock(); + _mutex.lock(); + if (_threadCount < MQTTSNGW_MAX_TASK) + { + _threadList[_threadCount] = thread; + _threadCount++; + } + else + { + _mutex.unlock(); + throw Exception("The maximum number of threads has been exceeded.", -1); + } + _mutex.unlock(); } int MultiTaskProcess::getParam(const char* parameter, char* value) { - _mutex.lock(); - int rc = Process::getParam(parameter, value); - _mutex.unlock(); - if (rc == -1) - { - throw Exception("No config file."); - } - return rc; + _mutex.lock(); + int rc = Process::getParam(parameter, value); + _mutex.unlock(); + return rc; } /*===================================== Class Exception ======================================*/ -Exception::Exception(const string& message) +Exception::Exception(const char* message, const int errNo) { - _message = message; - _exNo = 0; - _fileName = 0; - _functionName = 0; - _line = 0; + _message = message; + _errNo = errNo; + _fileName = nullptr; + _functionName = nullptr; + _line = 0; } - -Exception::Exception(const int exNo, const string& message) +Exception::Exception(const char* message, const int errNo, const char* file, const char* function, const int line) { - _message = message; - _exNo = exNo; - _fileName = nullptr; - _functionName = nullptr; - _line = 0; -} - -Exception::Exception(const int exNo, const string& message, const char* file, - const char* function, const int line) -{ - _message = message; - _exNo = exNo; - _fileName = file; - _functionName = function; - _line = line; + _message = message; + _errNo = errNo; + _fileName = getFileName(file); + ; + _functionName = function; + _line = line; } Exception::~Exception() throw () @@ -380,38 +379,67 @@ Exception::~Exception() throw () const char* Exception::what() const throw () { - return _message.c_str(); + return _message; } const char* Exception::getFileName() { - return _fileName; + return _fileName; } const char* Exception::getFunctionName() { - return _functionName; + return _functionName; } const int Exception::getLineNo() { - return _line; + return _line; } -const int Exception::getExceptionNo() +const int Exception::getErrNo() { - return _exNo; + return _errNo; } void Exception::writeMessage() { - if (getExceptionNo() == 0 ) - { - WRITELOG("%s %s\n", currentDateTime(), what()); - } - else - { - WRITELOG("%s:%-6d %s line %-4d %s() : %s\n", currentDateTime(), getExceptionNo(), - getFileName(), getLineNo(), getFunctionName(), what()); - } + if (_fileName == nullptr) + { + if (_errNo == 0) + { + WRITELOG("%s%s %s%s\n", currentDateTime(), RED_HDR, _message, CLR_HDR); + } + else + { + WRITELOG("%s%s %s.\n errno=%d : %s%s\n", currentDateTime(), RED_HDR, _message, _errNo, + strerror(_errNo), CLR_HDR); + } + } + else + { + if (_errNo == 0) + { + WRITELOG("%s%s %s. %s line %-4d %s()%s\n", currentDateTime(), RED_HDR, _message, _fileName, _line, _functionName, + CLR_HDR); + } + else + { + WRITELOG("%s%s %s. %s line %-4d %s()\n errno=%d : %s%s\n", currentDateTime(), RED_HDR, _message, + _fileName, _line, _functionName, _errNo, strerror(_errNo), CLR_HDR); + } + } } + +const char* Exception::getFileName(const char* file) +{ + for (int len = strlen(file); len > 0; len--) + { + if (*(file + len) == '/') + { + return file + len + 1; + } + } + return file; +} + diff --git a/MQTTSNGateway/src/MQTTSNGWProcess.h b/MQTTSNGateway/src/MQTTSNGWProcess.h index 42ff2a2..7827d59 100644 --- a/MQTTSNGateway/src/MQTTSNGWProcess.h +++ b/MQTTSNGateway/src/MQTTSNGWProcess.h @@ -41,35 +41,37 @@ namespace MQTTSNGW #define WRITELOG theProcess->putLog #define CHK_SIGINT (theProcess->checkSignal() == SIGINT) #define UNUSED(x) ((void)(x)) +#define EXCEPTION(...) Exception(__VA_ARGS__, __FILE__, __func__, __LINE__) + /*================================= Class Process ==================================*/ class Process { public: - Process(); - virtual ~Process(); - virtual void initialize(int argc, char** argv); - virtual void run(void); - void putLog(const char* format, ...); - void resetRingBuffer(void); - int getArgc(void); - char** getArgv(void); - int getParam(const char* parameter, char* value); - const char* getLog(void); - int checkSignal(void); - const string* getConfigDirName(void); - const string* getConfigFileName(void); + Process(); + virtual ~Process(); + virtual void initialize(int argc, char** argv); + virtual void run(void); + void putLog(const char* format, ...); + void resetRingBuffer(void); + int getArgc(void); + char** getArgv(void); + int getParam(const char* parameter, char* value); + const char* getLog(void); + int checkSignal(void); + const string* getConfigDirName(void); + const string* getConfigFileName(void); private: - int _argc; - char** _argv; - string _configDir; - string _configFile; - RingBuffer* _rb; - NamedSemaphore* _rbsem; - Mutex _mt; - int _log; - char _rbdata[PROCESS_LOG_BUFFER_SIZE + 1]; + int _argc; + char** _argv; + string _configDir; + string _configFile; + RingBuffer* _rb; + NamedSemaphore* _rbsem; + Mutex _mt; + int _log; + char _rbdata[PROCESS_LOG_BUFFER_SIZE + 1]; }; /*===================================== @@ -78,20 +80,21 @@ private: class MultiTaskProcess: public Process { public: - MultiTaskProcess(void); - ~MultiTaskProcess(); - void initialize(int argc, char** argv); - int getParam(const char* parameter, char* value); - void run(void); - void waitStop(void); - void threadStopped(void); - void attach(Thread* thread); + MultiTaskProcess(void); + ~MultiTaskProcess(); + void initialize(int argc, char** argv); + int getParam(const char* parameter, char* value); + void run(void); + void waitStop(void); + void threadStopped(void); + void attach(Thread* thread); + void abort(void); private: - Thread* _threadList[MQTTSNGW_MAX_TASK]; - Mutex _mutex; - int _threadCount; - int _stopCount; + Thread* _threadList[MQTTSNGW_MAX_TASK]; + Mutex _mutex; + int _threadCount; + int _stopCount; }; /*===================================== @@ -100,50 +103,48 @@ private: class Exception: public exception { public: - Exception(const string& message); - Exception(const int exNo, const string& message); - Exception(const int exNo, const string& message, - const char* file, const char* func, const int line); - virtual ~Exception() throw (); - const char* getFileName(); - const char* getFunctionName(); - const int getLineNo(); - const int getExceptionNo(); - virtual const char* what() const throw (); - void writeMessage(); + Exception(const char* message, const int errNo); + Exception(const char* message, const int errNo, const char* file, const char* func, int line); + virtual ~Exception() throw (); + const char* getFileName(); + const char* getFunctionName(); + const int getLineNo(); + const int getErrNo(); + virtual const char* what() const throw (); + void writeMessage(); private: - int _exNo; - string _message; - const char* _fileName; - const char* _functionName; - int _line; + const char* getFileName(const char* file); + int _errNo; + const char* _message; + const char* _fileName; + const char* _functionName; + int _line; }; - /*===================================== Class QueElement ====================================*/ template class QueElement { - template friend class Que; + template friend class Que; public: - QueElement(T* t) - { - _element = t; - _next = nullptr; - _prev = nullptr; - } + QueElement(T* t) + { + _element = t; + _next = nullptr; + _prev = nullptr; + } - ~QueElement() - { - } + ~QueElement() + { + } private: - T* _element; - QueElement* _next; - QueElement* _prev; + T* _element; + QueElement* _next; + QueElement* _prev; }; /*===================================== @@ -153,105 +154,105 @@ template class Que { public: - Que() - { - _head = nullptr; - _tail = nullptr; - _cnt = 0; - _maxSize = 0; - } + Que() + { + _head = nullptr; + _tail = nullptr; + _cnt = 0; + _maxSize = 0; + } - ~Que() - { - QueElement* elm = _head; - while (elm) - { - QueElement* next = elm->_next; - delete elm->_element; - delete elm; - elm = next; - } - } + ~Que() + { + QueElement* elm = _head; + while (elm) + { + QueElement* next = elm->_next; + delete elm->_element; + delete elm; + elm = next; + } + } - void pop(void) - { - if ( _head ) - { - QueElement* head = _head; - if ( _head == _tail ) - { - _head = _tail = nullptr; - } - else - { - _head = head->_next; - head->_prev = nullptr; - } - delete head; - _cnt--; - } - } + void pop(void) + { + if (_head) + { + QueElement* head = _head; + if (_head == _tail) + { + _head = _tail = nullptr; + } + else + { + _head = head->_next; + head->_prev = nullptr; + } + delete head; + _cnt--; + } + } - T* front(void) - { - { - if ( _head ) - { - return _head->_element; - } - else - { - return 0; - } - } - } + T* front(void) + { + { + if (_head) + { + return _head->_element; + } + else + { + return 0; + } + } + } - int post(T* t) - { - if ( t && ( _maxSize == 0 || _cnt < _maxSize )) - { - QueElement* elm = new QueElement(t); - if ( _head ) - { - if ( _tail == _head ) - { - elm->_prev = _tail; - _tail = elm; - _head->_next = elm; - } - else - { - _tail->_next = elm; - elm->_prev = _tail; - _tail = elm; - } - } - else - { - _head = elm; - _tail = elm; - } - _cnt++; - return _cnt; - } - return 0; - } + int post(T* t) + { + if (t && (_maxSize == 0 || _cnt < _maxSize)) + { + QueElement* elm = new QueElement(t); + if (_head) + { + if (_tail == _head) + { + elm->_prev = _tail; + _tail = elm; + _head->_next = elm; + } + else + { + _tail->_next = elm; + elm->_prev = _tail; + _tail = elm; + } + } + else + { + _head = elm; + _tail = elm; + } + _cnt++; + return _cnt; + } + return 0; + } - int size(void) - { - return _cnt; - } + int size(void) + { + return _cnt; + } - void setMaxSize(int maxSize) - { - _maxSize = maxSize; - } + void setMaxSize(int maxSize) + { + _maxSize = maxSize; + } private: - int _cnt; - int _maxSize; - QueElement* _head; - QueElement* _tail; + int _cnt; + int _maxSize; + QueElement* _head; + QueElement* _tail; }; /*===================================== @@ -262,722 +263,760 @@ private: #define TREE23_BI_NODE (2) #define TREE23_TRI_NODE (3) -template -class Tree23Elm{ - template friend class Tree23; +template +class Tree23Elm +{ + template friend class Tree23; public: - Tree23Elm() - { - _key = 0; - _val = 0; - } + Tree23Elm() + { + _key = 0; + _val = 0; + } - Tree23Elm(K* key, V* val) - { - _key = key; - _val = val; - } + Tree23Elm(K* key, V* val) + { + _key = key; + _val = val; + } - ~Tree23Elm() - { + ~Tree23Elm() + { - } + } - int compare(Tree23Elm* elm) - { - return _key->compare(elm->_key); - } + int compare(Tree23Elm* elm) + { + return _key->compare(elm->_key); + } private: - K* _key; - V* _val; + K* _key; + V* _val; }; - -template -class Tree23Node{ - template friend class Tree23; +template +class Tree23Node +{ + template friend class Tree23; public: - Tree23Node(const int type) - { - _type = type; - _telm0 = _telm1 = NULL; - _left = _midle = _right = NULL; - } + Tree23Node(const int type) + { + _type = type; + _telm0 = _telm1 = NULL; + _left = _midle = _right = NULL; + } - Tree23Node(const int type, Tree23Node* midle) - { - _type = type; - _telm0 = _telm1 = NULL; - _left = _right = NULL; - _midle = midle; - } + Tree23Node(const int type, Tree23Node* midle) + { + _type = type; + _telm0 = _telm1 = NULL; + _left = _right = NULL; + _midle = midle; + } - Tree23Node(const int type, Tree23Elm* telm) - { - _type = type; - _telm0 = telm; - _telm1 = NULL; - _left = _midle = _right = NULL; - } + Tree23Node(const int type, Tree23Elm* telm) + { + _type = type; + _telm0 = telm; + _telm1 = NULL; + _left = _midle = _right = NULL; + } - Tree23Node(const int type, Tree23Elm* telm, Tree23Node* left, Tree23Node* right) - { - _type = type; - _telm0 = telm; - _telm1 = NULL; - _left = left; - _midle = NULL; - _right = right; - } + Tree23Node(const int type, Tree23Elm* telm, Tree23Node* left, + Tree23Node* right) + { + _type = type; + _telm0 = telm; + _telm1 = NULL; + _left = left; + _midle = NULL; + _right = right; + } - Tree23Node(const int type, Tree23Elm* telm0, Tree23Elm* telm1, Tree23Node* left, Tree23Node* midle, Tree23Node* right) - { - _type = type; - _telm0 = telm0; - _telm1 = telm1; - _left = left; - _midle = midle; - _right = right; - } + Tree23Node(const int type, Tree23Elm* telm0, Tree23Elm* telm1, + Tree23Node* left, Tree23Node* midle, + Tree23Node* right) + { + _type = type; + _telm0 = telm0; + _telm1 = telm1; + _left = left; + _midle = midle; + _right = right; + } - ~Tree23Node() - { + ~Tree23Node() + { - } + } private: - int _type; - Tree23Elm* _telm0; - Tree23Elm* _telm1; - Tree23Node* _left; - Tree23Node* _midle; - Tree23Node* _right; + int _type; + Tree23Elm* _telm0; + Tree23Elm* _telm1; + Tree23Node* _left; + Tree23Node* _midle; + Tree23Node* _right; }; -template -class Tree23{ +template +class Tree23 +{ public: - Tree23() - { - _root = NULL; - } + Tree23() + { + _root = NULL; + } - ~Tree23() - { - if ( _root ) - { - delete _root; - } - } + ~Tree23() + { + if (_root) + { + delete _root; + } + } - void add(K* key, V* val) - { - _root = add( _root, new Tree23Elm(key, val)); - _root->_type = abs(_root->_type); - } + void add(K* key, V* val) + { + _root = add(_root, new Tree23Elm(key, val)); + _root->_type = abs(_root->_type); + } - Tree23Node* add(Tree23Node* n, Tree23Elm* elm) - { - if ( n == 0 ) - { - return new Tree23Node(TREE23_INSERT_ACTIVE, elm); - } + Tree23Node* add(Tree23Node* n, Tree23Elm* elm) + { + if (n == 0) + { + return new Tree23Node(TREE23_INSERT_ACTIVE, elm); + } - int cmp0 = elm->compare(n->_telm0); - int cmp1 = 0; - switch ( n->_type ) - { - case 2: - if ( cmp0 < 0 ) - { - n->_left = add(n->_left, elm); - return addLeft2(n); - } - else if ( cmp0 == 0 ) - { - n->_telm0 = elm; - return n; - } - else - { - n->_right = add(n->_right, elm); - return addRight2(n); - } - break; - case 3: - cmp1 = elm->compare(n->_telm1); - if ( cmp0 < 0 ) - { - n->_left = add(n->_left, elm); - return addLeft3(n); - } - else if ( cmp0 == 0 ) - { - n->_telm0 = elm; - return n; - } - else if ( cmp1 < 0 ) - { - n->_midle = add(n->_midle, elm); - return addMidle3(n); - } - else if ( cmp1 == 0 ) - { - n->_telm1 = elm; - return n; - } - else - { - n->_right = add(n->_right, elm); - return addRight3(n); - } - break; - default: - break; - } - return 0; - } + int cmp0 = elm->compare(n->_telm0); + int cmp1 = 0; + switch (n->_type) + { + case 2: + if (cmp0 < 0) + { + n->_left = add(n->_left, elm); + return addLeft2(n); + } + else if (cmp0 == 0) + { + n->_telm0 = elm; + return n; + } + else + { + n->_right = add(n->_right, elm); + return addRight2(n); + } + break; + case 3: + cmp1 = elm->compare(n->_telm1); + if (cmp0 < 0) + { + n->_left = add(n->_left, elm); + return addLeft3(n); + } + else if (cmp0 == 0) + { + n->_telm0 = elm; + return n; + } + else if (cmp1 < 0) + { + n->_midle = add(n->_midle, elm); + return addMidle3(n); + } + else if (cmp1 == 0) + { + n->_telm1 = elm; + return n; + } + else + { + n->_right = add(n->_right, elm); + return addRight3(n); + } + break; + default: + break; + } + return 0; + } - void remove(K* k) - { - _root = remove(_root, k); - if ( _root != NULL && _root->_type == TREE23_DELETE_ACTIVE ) - { - _root = _root->_midle; - } - } + void remove(K* k) + { + _root = remove(_root, k); + if (_root != NULL && _root->_type == TREE23_DELETE_ACTIVE) + { + _root = _root->_midle; + } + } - Tree23Node* remove(Tree23Node* node, K* k) - { - if ( node == NULL ) - { - return NULL; - } - int cmp0 = k->compare(node->_telm0->_key); - int cmp1 = 0; - switch ( node->_type ) - { - case 2: - if ( cmp0 < 0 ) - { - node->_left = remove( node->_left, k); - return removeLeft2(node); - } - else if ( cmp0 == 0 ) - { - if ( node->_left == NULL) - { - return new Tree23Node(TREE23_DELETE_ACTIVE); - } - Tree23Elm* maxLeft = new Tree23Elm(); - node->_left = removeMax(node->_left, maxLeft); - node->_telm0 = maxLeft; - return removeLeft2(node); - } - else - { - node->_right = remove(node->_right, k); - return removeRight2(node); - } - case 3: - cmp1 = k->compare(node->_telm1->_key); - if ( cmp0 < 0 ) - { - node->_left = remove(node->_left, k); - return removeLeft3(node); - } - else if ( cmp0 == 0 ) - { - if ( node->_left == NULL ) - { - return new Tree23Node(TREE23_BI_NODE, node->_telm1); - } - Tree23Elm* maxLeft = new Tree23Elm(); - node->_left = removeMax(node->_left, maxLeft); - node->_telm0 = maxLeft; - return removeLeft3(node); - } - else if ( cmp1 < 0 ) - { - node->_midle = remove(node->_midle, k); - return removeMidle3(node); - } - else if ( cmp1 == 0 ) - { - if ( node->_midle == NULL ) - { - return new Tree23Node(TREE23_BI_NODE, node->_telm0); - } - Tree23Elm* maxMidle = new Tree23Elm(); - node->_midle = removeMax(node->_midle, maxMidle); - node->_telm1 = maxMidle; - return removeMidle3(node); - } - else - { - node->_right = remove(node->_right, k); - return removeRight3(node); - } - default: - break; - } - return NULL; - } + Tree23Node* remove(Tree23Node* node, K* k) + { + if (node == NULL) + { + return NULL; + } + int cmp0 = k->compare(node->_telm0->_key); + int cmp1 = 0; + switch (node->_type) + { + case 2: + if (cmp0 < 0) + { + node->_left = remove(node->_left, k); + return removeLeft2(node); + } + else if (cmp0 == 0) + { + if (node->_left == NULL) + { + return new Tree23Node(TREE23_DELETE_ACTIVE); + } + Tree23Elm* maxLeft = new Tree23Elm(); + node->_left = removeMax(node->_left, maxLeft); + node->_telm0 = maxLeft; + return removeLeft2(node); + } + else + { + node->_right = remove(node->_right, k); + return removeRight2(node); + } + case 3: + cmp1 = k->compare(node->_telm1->_key); + if (cmp0 < 0) + { + node->_left = remove(node->_left, k); + return removeLeft3(node); + } + else if (cmp0 == 0) + { + if (node->_left == NULL) + { + return new Tree23Node(TREE23_BI_NODE, node->_telm1); + } + Tree23Elm* maxLeft = new Tree23Elm(); + node->_left = removeMax(node->_left, maxLeft); + node->_telm0 = maxLeft; + return removeLeft3(node); + } + else if (cmp1 < 0) + { + node->_midle = remove(node->_midle, k); + return removeMidle3(node); + } + else if (cmp1 == 0) + { + if (node->_midle == NULL) + { + return new Tree23Node(TREE23_BI_NODE, node->_telm0); + } + Tree23Elm* maxMidle = new Tree23Elm(); + node->_midle = removeMax(node->_midle, maxMidle); + node->_telm1 = maxMidle; + return removeMidle3(node); + } + else + { + node->_right = remove(node->_right, k); + return removeRight3(node); + } + default: + break; + } + return NULL; + } - bool find(K* key) - { - Tree23Node* node = _root; - while (node != NULL) - { - int cmp0 = key->compare(node->_telm0->_key); - int cmp1 = 0; - switch (node->_type) - { - case 2: - if ( cmp0 < 0 ) node = node->_left; - else if ( cmp0 == 0 ) - { - return true; - } - else - { - node = node->_right; - } - break; - case 3: - cmp1 = key->compare(node->_telm1->_key); - if ( cmp0 < 0 ) - { - node = node->_left; - } - else if ( cmp0 == 0 ) - { - return true; - } - else if ( cmp1 < 0 ) - { - node = node->_midle; - } - else if ( cmp1 == 0 ) - { - return true; - } - else - { - node = node->_right; - } - break; - default: - break; - } - } - return false; - } + bool find(K* key) + { + Tree23Node* node = _root; + while (node != NULL) + { + int cmp0 = key->compare(node->_telm0->_key); + int cmp1 = 0; + switch (node->_type) + { + case 2: + if (cmp0 < 0) + node = node->_left; + else if (cmp0 == 0) + { + return true; + } + else + { + node = node->_right; + } + break; + case 3: + cmp1 = key->compare(node->_telm1->_key); + if (cmp0 < 0) + { + node = node->_left; + } + else if (cmp0 == 0) + { + return true; + } + else if (cmp1 < 0) + { + node = node->_midle; + } + else if (cmp1 == 0) + { + return true; + } + else + { + node = node->_right; + } + break; + default: + break; + } + } + return false; + } - - V* getVal(K* key) - { - Tree23Node* node = _root; - while (node != NULL) - { - int cmp0 = key->compare(node->_telm0->_key); - int cmp1 = 0; - switch (node->_type) - { - case 2: - if ( cmp0 < 0 ) - { - node = node->_left; - } - else if ( cmp0 == 0 ) - { - return node->_telm0->_val; - } - else - { - node = node->_right; - } - break; - case 3: - cmp1 = key->compare(node->_telm1->_key); - if ( cmp0 < 0 ) - { - node = node->_left; - } - else if ( cmp0 == 0 ) - { - return node->_telm0->_val; - } - else if ( cmp1 < 0 ) - { - node = node->_midle; - } - else if ( cmp1 == 0 ) - { - return node->_telm1->_val; - } - else - { - node = node->_right; - } - break; - default: - break; - } - } - return NULL; - } + V* getVal(K* key) + { + Tree23Node* node = _root; + while (node != NULL) + { + int cmp0 = key->compare(node->_telm0->_key); + int cmp1 = 0; + switch (node->_type) + { + case 2: + if (cmp0 < 0) + { + node = node->_left; + } + else if (cmp0 == 0) + { + return node->_telm0->_val; + } + else + { + node = node->_right; + } + break; + case 3: + cmp1 = key->compare(node->_telm1->_key); + if (cmp0 < 0) + { + node = node->_left; + } + else if (cmp0 == 0) + { + return node->_telm0->_val; + } + else if (cmp1 < 0) + { + node = node->_midle; + } + else if (cmp1 == 0) + { + return node->_telm1->_val; + } + else + { + node = node->_right; + } + break; + default: + break; + } + } + return NULL; + } private: - Tree23Node* addLeft2(Tree23Node* node) - { - Tree23Node* n = node->_left; - if ( n != NULL && n->_type == TREE23_INSERT_ACTIVE ) - { - return new Tree23Node(TREE23_TRI_NODE, n->_telm0, node->_telm0, n->_left, n->_right, node->_right); - } - return node; - } + Tree23Node* addLeft2(Tree23Node* node) + { + Tree23Node* n = node->_left; + if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) + { + return new Tree23Node(TREE23_TRI_NODE, n->_telm0, + node->_telm0, n->_left, n->_right, node->_right); + } + return node; + } - Tree23Node* addLeft3(Tree23Node* node) - { - Tree23Node* n = node->_left; - if ( n != NULL && n->_type == TREE23_INSERT_ACTIVE) - { - n->_type = TREE23_BI_NODE; - Tree23Node* nn = new Tree23Node(TREE23_BI_NODE, node->_telm1, node->_midle, node->_right); - return new Tree23Node(TREE23_INSERT_ACTIVE, node->_telm0, n, nn); - } - return node; - } + Tree23Node* addLeft3(Tree23Node* node) + { + Tree23Node* n = node->_left; + if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) + { + n->_type = TREE23_BI_NODE; + Tree23Node* nn = new Tree23Node(TREE23_BI_NODE, + node->_telm1, node->_midle, node->_right); + return new Tree23Node(TREE23_INSERT_ACTIVE, node->_telm0, n, + nn); + } + return node; + } - Tree23Node* addRight2(Tree23Node* node) - { - Tree23Node* n = node->_right; - if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) - { - return new Tree23Node(TREE23_TRI_NODE, node->_telm0, n->_telm0, node->_left, n->_left, n->_right); - } - return node; - } + Tree23Node* addRight2(Tree23Node* node) + { + Tree23Node* n = node->_right; + if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) + { + return new Tree23Node(TREE23_TRI_NODE, node->_telm0, + n->_telm0, node->_left, n->_left, n->_right); + } + return node; + } - Tree23Node* addRight3(Tree23Node* node) - { - Tree23Node* n = node->_right; - if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) { - n->_type = TREE23_BI_NODE; - Tree23Node* nn = new Tree23Node(TREE23_BI_NODE, node->_telm0, node->_left, node->_midle); - return new Tree23Node(TREE23_INSERT_ACTIVE, node->_telm1, nn, n); - } - return node; - } + Tree23Node* addRight3(Tree23Node* node) + { + Tree23Node* n = node->_right; + if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) + { + n->_type = TREE23_BI_NODE; + Tree23Node* nn = new Tree23Node(TREE23_BI_NODE, + node->_telm0, node->_left, node->_midle); + return new Tree23Node(TREE23_INSERT_ACTIVE, node->_telm1, nn, + n); + } + return node; + } - Tree23Node* addMidle3(Tree23Node* node) - { - Tree23Node* n = node->_midle; - if ( n != NULL && n->_type == TREE23_INSERT_ACTIVE ) - { - n->_left = new Tree23Node(TREE23_BI_NODE, node->_telm0, node->_left, n->_left); - n->_right = new Tree23Node(TREE23_BI_NODE, node->_telm1, n->_right, node->_right); - return n; - } - return node; - } + Tree23Node* addMidle3(Tree23Node* node) + { + Tree23Node* n = node->_midle; + if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) + { + n->_left = new Tree23Node(TREE23_BI_NODE, node->_telm0, + node->_left, n->_left); + n->_right = new Tree23Node(TREE23_BI_NODE, node->_telm1, + n->_right, node->_right); + return n; + } + return node; + } + Tree23Node* removeMax(Tree23Node* node, Tree23Elm* elm) + { + if (node->_right == NULL) + { + switch (node->_type) + { + case 2: + elm->_key = node->_telm0->_key; + elm->_val = node->_telm0->_val; + return new Tree23Node(TREE23_DELETE_ACTIVE); + case 3: + elm->_key = node->_telm1->_key; + elm->_val = node->_telm1->_val; + return new Tree23Node(TREE23_BI_NODE, node->_telm0); + default: + break; + } + } + else + { + node->_right = removeMax(node->_right, elm); + switch (node->_type) + { + case 2: + return removeRight2(node); + case 3: + return removeRight3(node); + default: + break; + } + } + return NULL; + } - Tree23Node* removeMax(Tree23Node* node, Tree23Elm* elm) - { - if (node->_right == NULL) - { - switch (node->_type) - { - case 2: - elm->_key = node->_telm0->_key; - elm->_val = node->_telm0->_val; - return new Tree23Node(TREE23_DELETE_ACTIVE); - case 3: - elm->_key = node->_telm1->_key; - elm->_val = node->_telm1->_val; - return new Tree23Node(TREE23_BI_NODE, node->_telm0); - default: - break; - } - } - else - { - node->_right = removeMax(node->_right, elm); - switch (node->_type) - { - case 2: - return removeRight2(node); - case 3: - return removeRight3(node); - default: - break; - } - } - return NULL; - } + Tree23Node* removeLeft2(Tree23Node* node) + { + Tree23Node* n = node->_left; + if (n != NULL && n->_type == TREE23_DELETE_ACTIVE) + { + Tree23Node* r = node->_right; + Tree23Node* midle; + Tree23Node* left; + Tree23Node* right; + switch (r->_type) + { + case 2: + midle = new Tree23Node(TREE23_TRI_NODE, node->_telm0, + r->_telm0, n->_midle, r->_left, r->_right); + return new Tree23Node(TREE23_DELETE_ACTIVE, midle); + case 3: + left = new Tree23Node(TREE23_BI_NODE, node->_telm0, + n->_midle, r->_left); + right = new Tree23Node(TREE23_BI_NODE, r->_telm1, + r->_midle, r->_right); + return new Tree23Node(TREE23_BI_NODE, r->_telm0, left, + right); + default: + break; + } + } + return node; + } - Tree23Node* removeLeft2(Tree23Node* node) - { - Tree23Node* n = node->_left; - if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) - { - Tree23Node* r = node->_right; - Tree23Node* midle; - Tree23Node* left; - Tree23Node* right; + Tree23Node* removeRight2(Tree23Node* node) + { + Tree23Node* n = node->_right; + if (n != NULL && n->_type == TREE23_DELETE_ACTIVE) + { + Tree23Node* l = node->_left; + Tree23Node* midle; + Tree23Node* left; + Tree23Node* right; - switch ( r->_type ) - { - case 2: - midle = new Tree23Node(TREE23_TRI_NODE, node->_telm0, r->_telm0, n->_midle, r->_left, r->_right); - return new Tree23Node(TREE23_DELETE_ACTIVE, midle); - case 3: - left = new Tree23Node(TREE23_BI_NODE, node->_telm0, n->_midle, r->_left); - right = new Tree23Node(TREE23_BI_NODE, r->_telm1, r->_midle, r->_right); - return new Tree23Node(TREE23_BI_NODE, r->_telm0, left, right); - default: - break; - } - } - return node; - } + switch (l->_type) + { + case 2: + midle = new Tree23Node(TREE23_TRI_NODE, l->_telm0, + node->_telm0, l->_left, l->_right, n->_midle); + return new Tree23Node(-1, midle); + case 3: + right = new Tree23Node(TREE23_BI_NODE, node->_telm0, + l->_right, n->_midle); + left = new Tree23Node(TREE23_BI_NODE, l->_telm0, l->_left, + l->_midle); + return new Tree23Node(TREE23_BI_NODE, l->_telm1, left, + right); + default: + break; + } + } + return node; + } - Tree23Node* removeRight2(Tree23Node* node) - { - Tree23Node* n = node->_right; - if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) - { - Tree23Node* l = node->_left; - Tree23Node* midle; - Tree23Node* left; - Tree23Node* right; + Tree23Node* removeLeft3(Tree23Node* node) + { + Tree23Node* n = node->_left; + if (n != NULL && n->_type == TREE23_DELETE_ACTIVE) + { + Tree23Node* m = node->_midle; + Tree23Node* r = node->_right; + Tree23Node* left; + Tree23Node* midle; - switch (l->_type) - { - case 2: - midle = new Tree23Node(TREE23_TRI_NODE, l->_telm0, node->_telm0, l->_left, l->_right, n->_midle); - return new Tree23Node(-1, midle); - case 3: - right = new Tree23Node(TREE23_BI_NODE, node->_telm0, l->_right, n->_midle); - left = new Tree23Node(TREE23_BI_NODE, l->_telm0, l->_left, l->_midle); - return new Tree23Node(TREE23_BI_NODE, l->_telm1, left, right); - default: - break; - } - } - return node; - } + switch (m->_type) + { + case 2: + left = new Tree23Node(TREE23_TRI_NODE, node->_telm0, + m->_telm0, n->_midle, m->_left, m->_right); + return new Tree23Node(TREE23_BI_NODE, node->_telm1, left, + r); + case 3: + left = new Tree23Node(TREE23_BI_NODE, node->_telm0, + n->_midle, m->_left); + midle = new Tree23Node(TREE23_BI_NODE, m->_telm1, + m->_midle, m->_right); + return new Tree23Node(TREE23_TRI_NODE, m->_telm0, + node->_telm1, left, midle, r); + default: + break; + } + } + return node; + } - Tree23Node* removeLeft3(Tree23Node* node) - { - Tree23Node* n = node->_left; - if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) - { - Tree23Node* m = node->_midle; - Tree23Node* r = node->_right; - Tree23Node* left; - Tree23Node* midle; + Tree23Node* removeMidle3(Tree23Node* node) + { + Tree23Node* n = node->_midle; + if (n != NULL && n->_type == TREE23_DELETE_ACTIVE) + { + Tree23Node* l = node->_left; + Tree23Node* r = node->_right; + Tree23Node* midle; + Tree23Node* right; + switch (r->_type) + { + case 2: + right = new Tree23Node(TREE23_TRI_NODE, node->_telm1, + r->_telm0, n->_midle, r->_left, r->_right); + return new Tree23Node(TREE23_BI_NODE, node->_telm0, l, + right); + case 3: + midle = new Tree23Node(TREE23_BI_NODE, node->_telm1, + n->_midle, r->_left); + right = new Tree23Node(TREE23_BI_NODE, r->_telm1, + r->_midle, r->_right); + return new Tree23Node(TREE23_TRI_NODE, node->_telm0, + r->_telm0, l, midle, right); + default: + break; + } + } + return node; + } - switch (m->_type) { - case 2: - left = new Tree23Node(TREE23_TRI_NODE, node->_telm0, m->_telm0, n->_midle, m->_left, m->_right); - return new Tree23Node(TREE23_BI_NODE, node->_telm1, left, r); - case 3: - left = new Tree23Node(TREE23_BI_NODE, node->_telm0, n->_midle, m->_left); - midle = new Tree23Node(TREE23_BI_NODE, m->_telm1, m->_midle, m->_right); - return new Tree23Node(TREE23_TRI_NODE, m->_telm0, node->_telm1, left, midle, r); - default: - break; - } - } - return node; - } + Tree23Node* removeRight3(Tree23Node* node) + { + Tree23Node* n = node->_right; + if (n != NULL && n->_type == TREE23_DELETE_ACTIVE) + { + Tree23Node* l = node->_left; + Tree23Node* m = node->_midle; + Tree23Node* midle; + Tree23Node* right; + switch (m->_type) + { + case 2: + right = new Tree23Node(TREE23_TRI_NODE, m->_telm0, + node->_telm1, m->_left, m->_right, n->_midle); + return new Tree23Node(TREE23_BI_NODE, node->_telm0, l, + right); + case 3: + right = new Tree23Node(TREE23_BI_NODE, node->_telm1, + m->_right, n->_midle); + midle = new Tree23Node(TREE23_BI_NODE, m->_telm0, + m->_left, m->_midle); + return new Tree23Node(TREE23_TRI_NODE, node->_telm0, + m->_telm1, l, midle, right); + default: + break; + } + } + return node; + } - Tree23Node* removeMidle3(Tree23Node* node) - { - Tree23Node* n = node->_midle; - if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) - { - Tree23Node* l = node->_left; - Tree23Node* r = node->_right; - Tree23Node* midle; - Tree23Node* right; - switch (r->_type) - { - case 2: - right = new Tree23Node(TREE23_TRI_NODE, node->_telm1, r->_telm0, n->_midle, r->_left, r->_right); - return new Tree23Node(TREE23_BI_NODE, node->_telm0, l, right); - case 3: - midle = new Tree23Node(TREE23_BI_NODE, node->_telm1, n->_midle, r->_left); - right = new Tree23Node(TREE23_BI_NODE, r->_telm1, r->_midle, r->_right); - return new Tree23Node(TREE23_TRI_NODE, node->_telm0, r->_telm0, l, midle, right); - default: - break; - } - } - return node; - } - - Tree23Node* removeRight3(Tree23Node* node) - { - Tree23Node* n = node->_right; - if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) - { - Tree23Node* l = node->_left; - Tree23Node* m = node->_midle; - Tree23Node* midle; - Tree23Node* right; - switch (m->_type) - { - case 2: - right = new Tree23Node(TREE23_TRI_NODE, m->_telm0, node->_telm1, m->_left, m->_right, n->_midle); - return new Tree23Node(TREE23_BI_NODE, node->_telm0, l, right); - case 3: - right = new Tree23Node(TREE23_BI_NODE, node->_telm1, m->_right, n->_midle); - midle = new Tree23Node(TREE23_BI_NODE, m->_telm0, m->_left, m->_midle); - return new Tree23Node(TREE23_TRI_NODE, node->_telm0, m->_telm1, l, midle, right); - default: - break; - } - } - return node; - } - - - Tree23Node* _root; + Tree23Node* _root; }; /*===================================== Class List =====================================*/ -template +template class ListElm { - template friend class List; + template friend class List; public: - ListElm() - { - _elm = nullptr; - _prev = _next = nullptr; - } - ListElm(T* elm) - { - _elm = elm; - _prev = _next = nullptr; - } - T* getContent(void) - { - return _elm; - } - ~ListElm(){} + ListElm() + { + _elm = nullptr; + _prev = _next = nullptr; + } + ListElm(T* elm) + { + _elm = elm; + _prev = _next = nullptr; + } + T* getContent(void) + { + return _elm; + } + ~ListElm() + { + } private: - ListElm* getNext(void){return _next;} - T* _elm; - ListElm* _prev; - ListElm* _next; + ListElm* getNext(void) + { + return _next; + } + T* _elm; + ListElm* _prev; + ListElm* _next; }; - -template -class List{ +template +class List +{ public: - List() - { - _head = _tail = nullptr; - _size = 0; - } - ~List() - { - clear(); - } + List() + { + _head = _tail = nullptr; + _size = 0; + } + ~List() + { + clear(); + } - int add(T* t) - { - ListElm* elm = new ListElm(t); - if ( elm == nullptr ) - { - return 0; - } - if ( _head == nullptr ) - { - _head = elm; - _tail = elm; - } - else - { - elm->_prev = _tail; - _tail->_next = elm; - _tail = elm; - } - _size++; - return 1; - } + int add(T* t) + { + ListElm* elm = new ListElm(t); + if (elm == nullptr) + { + return 0; + } + if (_head == nullptr) + { + _head = elm; + _tail = elm; + } + else + { + elm->_prev = _tail; + _tail->_next = elm; + _tail = elm; + } + _size++; + return 1; + } - void erase(ListElm* elm) - { - if ( _head == elm ) - { - _head = elm->_next; - _size--; - delete elm; - } - else if ( _tail == elm ) - { - _tail = elm->_prev; - elm->_prev->_next = nullptr; - _size--; - delete elm; - } - else - { - elm->_prev->_next = elm->_next; - elm->_next->_prev = elm->_prev; - _size--; - delete elm; - } - } - void clear(void) - { - ListElm* p = _head; - while ( p ) - { - ListElm* q = p->_next; - delete p; - p = q; - } - _head = nullptr; - _tail = nullptr; - _size = 0; - } + void erase(ListElm* elm) + { + if (_head == elm) + { + _head = elm->_next; + _size--; + delete elm; + } + else if (_tail == elm) + { + _tail = elm->_prev; + elm->_prev->_next = nullptr; + _size--; + delete elm; + } + else + { + elm->_prev->_next = elm->_next; + elm->_next->_prev = elm->_prev; + _size--; + delete elm; + } + } + void clear(void) + { + ListElm* p = _head; + while (p) + { + ListElm* q = p->_next; + delete p; + p = q; + } + _head = nullptr; + _tail = nullptr; + _size = 0; + } - ListElm* getElm(void) - { - return _head; - } + ListElm* getElm(void) + { + return _head; + } - ListElm* getNext(ListElm* elm) - { - return elm->getNext(); - } - - int getSize(void) - { - return _size; - } + ListElm* getNext(ListElm* elm) + { + return elm->getNext(); + } + int getSize(void) + { + return _size; + } private: - ListElm* _head; - ListElm* _tail; - int _size; + ListElm* _head; + ListElm* _tail; + int _size; }; - extern Process* theProcess; extern MultiTaskProcess* theMultiTaskProcess; diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp index 5ef8d5b..3824173 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.cpp @@ -27,7 +27,7 @@ using namespace MQTTSNGW; MQTTSNPublishHandler::MQTTSNPublishHandler(Gateway* gateway) { - _gateway = gateway; + _gateway = gateway; } MQTTSNPublishHandler::~MQTTSNPublishHandler() @@ -37,263 +37,267 @@ MQTTSNPublishHandler::~MQTTSNPublishHandler() MQTTGWPacket* MQTTSNPublishHandler::handlePublish(Client* client, MQTTSNPacket* packet) { - uint8_t dup; - int qos; - uint8_t retained; - uint16_t msgId; - uint8_t* payload; + uint8_t dup; + int qos; + uint8_t retained; + uint16_t msgId; + uint16_t tid; + uint8_t* payload; MQTTSN_topicid topicid; - int payloadlen; - Publish pub = MQTTPacket_Publish_Initializer; + int payloadlen; + Publish pub = MQTTPacket_Publish_Initializer; - char shortTopic[2]; + char shortTopic[2]; - if ( !_gateway->getAdapterManager()->getQoSm1Proxy()->isActive() ) - { - if ( client->isQoSm1() ) - { - _gateway->getAdapterManager()->getQoSm1Proxy()->savePacket(client, packet); + if (!_gateway->getAdapterManager()->getQoSm1Proxy()->isActive()) + { + if (client->isQoSm1()) + { + _gateway->getAdapterManager()->getQoSm1Proxy()->savePacket(client, packet); - return nullptr; - } - } + return nullptr; + } + } - if ( packet->getPUBLISH(&dup, &qos, &retained, &msgId, &topicid, &payload, &payloadlen) ==0 ) - { - return nullptr; - } - pub.msgId = msgId; - pub.header.bits.dup = dup; - pub.header.bits.qos = ( qos == 3 ? 0 : qos ); - pub.header.bits.retain = retained; + if (packet->getPUBLISH(&dup, &qos, &retained, &msgId, &topicid, &payload, &payloadlen) == 0) + { + return nullptr; + } + pub.msgId = msgId; + pub.header.bits.dup = dup; + pub.header.bits.qos = (qos == 3 ? 0 : qos); + pub.header.bits.retain = retained; + tid = topicid.data.id; - Topic* topic = nullptr; + Topic* topic = nullptr; - if( topicid.type == MQTTSN_TOPIC_TYPE_SHORT ) - { - shortTopic[0] = topicid.data.short_name[0]; - shortTopic[1] = topicid.data.short_name[1]; - pub.topic = shortTopic; - pub.topiclen = 2; - } - else - { - topic = client->getTopics()->getTopicById(&topicid); - if ( !topic ) - { - topic = _gateway->getTopics()->getTopicById(&topicid); - if ( topic ) - { - topic = client->getTopics()->add(topic->getTopicName()->c_str(), topic->getTopicId()); - } - } + if (topicid.type == MQTTSN_TOPIC_TYPE_SHORT) + { + shortTopic[0] = topicid.data.short_name[0]; + shortTopic[1] = topicid.data.short_name[1]; + pub.topic = shortTopic; + pub.topiclen = 2; + } + else + { + topic = client->getTopics()->getTopicById(&topicid); + if (!topic) + { + topic = _gateway->getTopics()->getTopicById(&topicid); + if (topic) + { + topic = client->getTopics()->add(topic->getTopicName()->c_str(), topic->getTopicId()); + } + } - if( !topic && qos == 3 ) - { - WRITELOG("%s Invalid TopicId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - return nullptr; - } + if (!topic && qos == 3) + { + WRITELOG("%s Invalid TopicId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + return nullptr; + } - if ( ( qos == 0 || qos == 3 ) && msgId > 0 ) - { - WRITELOG("%s Invalid MsgId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - return nullptr; - } + if ((qos == 0 || qos == 3) && msgId > 0) + { + WRITELOG("%s Invalid MsgId.%s %s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + return nullptr; + } - if( !topic && msgId && qos > 0 && qos < 3 ) - { - /* Reply PubAck with INVALID_TOPIC_ID to the client */ - MQTTSNPacket* pubAck = new MQTTSNPacket(); - pubAck->setPUBACK( topicid.data.id, msgId, MQTTSN_RC_REJECTED_INVALID_TOPIC_ID); - Event* ev1 = new Event(); - ev1->setClientSendEvent(client, pubAck); - _gateway->getClientSendQue()->post(ev1); - return nullptr; - } - if ( topic ) - { - pub.topic = (char*)topic->getTopicName()->data(); - pub.topiclen = topic->getTopicName()->length(); - } - } - /* Save a msgId & a TopicId pare for PUBACK */ - if( msgId && qos > 0 && qos < 3) - { - client->setWaitedPubTopicId(msgId, topicid.data.id, topicid.type); - } + if (!topic && msgId && qos > 0 && qos < 3) + { + /* Reply PubAck with INVALID_TOPIC_ID to the client */ + MQTTSNPacket* pubAck = new MQTTSNPacket(); + pubAck->setPUBACK(topicid.data.id, msgId, MQTTSN_RC_REJECTED_INVALID_TOPIC_ID); + Event* ev1 = new Event(); + ev1->setClientSendEvent(client, pubAck); + _gateway->getClientSendQue()->post(ev1); + return nullptr; + } + if (topic) + { + pub.topic = (char*) topic->getTopicName()->data(); + pub.topiclen = topic->getTopicName()->length(); + topicid.data.long_.name = pub.topic; + topicid.data.long_.len = pub.topiclen; + } + } + /* Save a msgId & a TopicId pare for PUBACK */ + if (msgId && qos > 0 && qos < 3) + { + client->setWaitedPubTopicId(msgId, tid, &topicid); + } - pub.payload = (char*)payload; - pub.payloadlen = payloadlen; + pub.payload = (char*) payload; + pub.payloadlen = payloadlen; - MQTTGWPacket* publish = new MQTTGWPacket(); - publish->setPUBLISH(&pub); + MQTTGWPacket* publish = new MQTTGWPacket(); + publish->setPUBLISH(&pub); - if ( _gateway->getAdapterManager()->isAggregaterActive() && client->isAggregated() ) - { - return publish; - } - else - { - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, publish); - _gateway->getBrokerSendQue()->post(ev1); - return nullptr; - } + if (_gateway->getAdapterManager()->isAggregaterActive() && client->isAggregated()) + { + return publish; + } + else + { + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, publish); + _gateway->getBrokerSendQue()->post(ev1); + return nullptr; + } } void MQTTSNPublishHandler::handlePuback(Client* client, MQTTSNPacket* packet) { - uint16_t topicId; - uint16_t msgId; - uint8_t rc; - - if ( client->isActive() ) - { - if ( packet->getPUBACK(&topicId, &msgId, &rc) == 0 ) - { - return; - } - - if ( rc == MQTTSN_RC_ACCEPTED) - { - if ( !_gateway->getAdapterManager()->getAggregater()->isActive() ) - { - MQTTGWPacket* pubAck = new MQTTGWPacket(); - pubAck->setAck(PUBACK, msgId); - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, pubAck); - _gateway->getBrokerSendQue()->post(ev1); - } - } - else if ( rc == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID) - { - WRITELOG(" PUBACK %d : Invalid Topic ID\n", msgId); - } - } -} - -void MQTTSNPublishHandler::handleAck(Client* client, MQTTSNPacket* packet, uint8_t packetType) -{ - uint16_t msgId; - - if ( client->isActive() ) - { - if ( packet->getACK(&msgId) == 0 ) - { - return; - } - MQTTGWPacket* ackPacket = new MQTTGWPacket(); - ackPacket->setAck(packetType, msgId); - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, ackPacket); - _gateway->getBrokerSendQue()->post(ev1); - } -} - -void MQTTSNPublishHandler::handleRegister(Client* client, MQTTSNPacket* packet) -{ - uint16_t id; - uint16_t msgId; - MQTTSNString topicName = MQTTSNString_initializer;; - MQTTSN_topicid topicid; - - if ( client->isActive() || client->isAwake()) - { - if ( packet->getREGISTER(&id, &msgId, &topicName) == 0 ) - { - return; - } - - topicid.type = MQTTSN_TOPIC_TYPE_NORMAL; - topicid.data.long_.len = topicName.lenstring.len; - topicid.data.long_.name = topicName.lenstring.data; - - id = client->getTopics()->add(&topicid)->getTopicId(); - - MQTTSNPacket* regAck = new MQTTSNPacket(); - regAck->setREGACK(id, msgId, MQTTSN_RC_ACCEPTED); - Event* ev = new Event(); - ev->setClientSendEvent(client, regAck); - _gateway->getClientSendQue()->post(ev); - } -} - -void MQTTSNPublishHandler::handleRegAck( Client* client, MQTTSNPacket* packet) -{ - uint16_t id; + uint16_t topicId; uint16_t msgId; uint8_t rc; - if ( client->isActive() || client->isAwake()) + + if (client->isActive()) { - if ( packet->getREGACK(&id, &msgId, &rc) == 0 ) + if (packet->getPUBACK(&topicId, &msgId, &rc) == 0) { return; } + if (rc == MQTTSN_RC_ACCEPTED) + { + if (!_gateway->getAdapterManager()->getAggregater()->isActive()) + { + MQTTGWPacket* pubAck = new MQTTGWPacket(); + pubAck->setAck(PUBACK, msgId); + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, pubAck); + _gateway->getBrokerSendQue()->post(ev1); + } + } + else if (rc == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID) + { + WRITELOG(" PUBACK %d : Invalid Topic ID\n", msgId); + } + } +} + +void MQTTSNPublishHandler::handleAck(Client* client, MQTTSNPacket* packet, uint8_t packetType) +{ + uint16_t msgId; + + if (client->isActive()) + { + if (packet->getACK(&msgId) == 0) + { + return; + } + MQTTGWPacket* ackPacket = new MQTTGWPacket(); + ackPacket->setAck(packetType, msgId); + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, ackPacket); + _gateway->getBrokerSendQue()->post(ev1); + } +} + +void MQTTSNPublishHandler::handleRegister(Client* client, MQTTSNPacket* packet) +{ + uint16_t id; + uint16_t msgId; + MQTTSNString topicName = MQTTSNString_initializer; + ; + MQTTSN_topicid topicid; + + if (client->isActive() || client->isAwake()) + { + if (packet->getREGISTER(&id, &msgId, &topicName) == 0) + { + return; + } + + topicid.type = MQTTSN_TOPIC_TYPE_NORMAL; + topicid.data.long_.len = topicName.lenstring.len; + topicid.data.long_.name = topicName.lenstring.data; + + id = client->getTopics()->add(&topicid)->getTopicId(); + + MQTTSNPacket* regAck = new MQTTSNPacket(); + regAck->setREGACK(id, msgId, MQTTSN_RC_ACCEPTED); + Event* ev = new Event(); + ev->setClientSendEvent(client, regAck); + _gateway->getClientSendQue()->post(ev); + } +} + +void MQTTSNPublishHandler::handleRegAck(Client* client, MQTTSNPacket* packet) +{ + uint16_t id; + uint16_t msgId; + uint8_t rc; + if (client->isActive() || client->isAwake()) + { + if (packet->getREGACK(&id, &msgId, &rc) == 0) + { + return; + } + + /* get PUBLISH message */ MQTTSNPacket* regAck = client->getWaitREGACKPacketList()->getPacket(msgId); - if ( regAck != nullptr ) + if (regAck != nullptr) { client->getWaitREGACKPacketList()->erase(msgId); Event* ev = new Event(); ev->setClientSendEvent(client, regAck); _gateway->getClientSendQue()->post(ev); } - if (client->isHoldPingReqest() && client->getWaitREGACKPacketList()->getCount() == 0 ) + + if (client->isHoldPingReqest() && client->getWaitREGACKPacketList()->getCount() == 0) { /* send PINGREQ to the broker */ - client->resetPingRequest(); - MQTTGWPacket* pingreq = new MQTTGWPacket(); - pingreq->setHeader(PINGREQ); - Event* evt = new Event(); - evt->setBrokerSendEvent(client, pingreq); - _gateway->getBrokerSendQue()->post(evt); + client->resetPingRequest(); + MQTTGWPacket* pingreq = new MQTTGWPacket(); + pingreq->setHeader(PINGREQ); + Event* evt = new Event(); + evt->setBrokerSendEvent(client, pingreq); + _gateway->getBrokerSendQue()->post(evt); } } } - - - void MQTTSNPublishHandler::handleAggregatePublish(Client* client, MQTTSNPacket* packet) { - int msgId = 0; - MQTTGWPacket* publish = handlePublish(client, packet); - if ( publish != nullptr ) - { - if ( publish->getMsgId() > 0 ) - { - if ( packet->isDuplicate() ) - { - msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); - } - else - { - msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); - } - publish->setMsgId(msgId); - } - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, publish); - _gateway->getBrokerSendQue()->post(ev1); - } + int msgId = 0; + MQTTGWPacket* publish = handlePublish(client, packet); + if (publish != nullptr) + { + if (publish->getMsgId() > 0) + { + if (packet->isDuplicate()) + { + msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); + } + else + { + msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); + } + publish->setMsgId(msgId); + } + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, publish); + _gateway->getBrokerSendQue()->post(ev1); + } } void MQTTSNPublishHandler::handleAggregateAck(Client* client, MQTTSNPacket* packet, int type) { - if ( type == MQTTSN_PUBREC ) - { - uint16_t msgId; + if (type == MQTTSN_PUBREC) + { + uint16_t msgId; - if ( packet->getACK(&msgId) == 0 ) - { - return; - } - MQTTSNPacket* ackPacket = new MQTTSNPacket(); - ackPacket->setPUBREL(msgId); - Event* ev = new Event(); - ev->setClientSendEvent(client, ackPacket); - _gateway->getClientSendQue()->post(ev); - } + if (packet->getACK(&msgId) == 0) + { + return; + } + MQTTSNPacket* ackPacket = new MQTTSNPacket(); + ackPacket->setPUBREL(msgId); + Event* ev = new Event(); + ev->setClientSendEvent(client, ackPacket); + _gateway->getClientSendQue()->post(ev); + } } diff --git a/MQTTSNGateway/src/MQTTSNGWPublishHandler.h b/MQTTSNGateway/src/MQTTSNGWPublishHandler.h index 85efeb8..d34b333 100644 --- a/MQTTSNGateway/src/MQTTSNGWPublishHandler.h +++ b/MQTTSNGateway/src/MQTTSNGWPublishHandler.h @@ -25,19 +25,19 @@ namespace MQTTSNGW class MQTTSNPublishHandler { public: - MQTTSNPublishHandler(Gateway* gateway); - ~MQTTSNPublishHandler(); - MQTTGWPacket* handlePublish(Client* client, MQTTSNPacket* packet); - void handlePuback(Client* client, MQTTSNPacket* packet); - void handleAck(Client* client, MQTTSNPacket* packet, uint8_t packetType); - void handleRegister(Client* client, MQTTSNPacket* packet); - void handleRegAck( Client* client, MQTTSNPacket* packet); + MQTTSNPublishHandler(Gateway* gateway); + ~MQTTSNPublishHandler(); + MQTTGWPacket* handlePublish(Client* client, MQTTSNPacket* packet); + void handlePuback(Client* client, MQTTSNPacket* packet); + void handleAck(Client* client, MQTTSNPacket* packet, uint8_t packetType); + void handleRegister(Client* client, MQTTSNPacket* packet); + void handleRegAck(Client* client, MQTTSNPacket* packet); - void handleAggregatePublish(Client* client, MQTTSNPacket* packet); - void handleAggregateAck(Client* client, MQTTSNPacket* packet, int type); + void handleAggregatePublish(Client* client, MQTTSNPacket* packet); + void handleAggregateAck(Client* client, MQTTSNPacket* packet, int type); private: - Gateway* _gateway; + Gateway* _gateway; }; } diff --git a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp index 349996f..91b05f9 100644 --- a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp +++ b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.cpp @@ -21,13 +21,13 @@ #include #include - using namespace MQTTSNGW; /*===================================== - Class QoSm1Proxy + Class QoSm1Proxy =====================================*/ -QoSm1Proxy:: QoSm1Proxy(Gateway* gw) : Adapter(gw) +QoSm1Proxy::QoSm1Proxy(Gateway* gw) : + Adapter(gw) { _gateway = gw; } @@ -37,24 +37,22 @@ QoSm1Proxy::~QoSm1Proxy(void) } - void QoSm1Proxy::initialize(char* gwName) { - if ( _gateway->hasSecureConnection() ) + if (_gateway->hasSecureConnection()) { - _isSecure = true; + _isSecure = true; } - /* Create QoS-1 Clients from clients.conf */ - _gateway->getClientList()->setClientList(QOSM1PROXY_TYPE); + /* Create QoS-1 Clients from clients.conf */ + _gateway->getClientList()->setClientList(QOSM1PROXY_TYPE); - /* Create a client for QoS-1 proxy */ - string name = string(gwName) + string("_QoS-1"); - setup(name.c_str(), Atype_QoSm1Proxy); - _isActive = true; + /* Create a client for QoS-1 proxy */ + string name = string(gwName) + string("_QoS-1"); + setup(name.c_str(), Atype_QoSm1Proxy); + _isActive = true; } - bool QoSm1Proxy::isActive(void) { return _isActive; diff --git a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h index 82e5f2a..125b1b9 100644 --- a/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h +++ b/MQTTSNGateway/src/MQTTSNGWQoSm1Proxy.h @@ -27,12 +27,12 @@ class SensorNetAddress; class MQTTSNPacket; /*===================================== - Class QoSm1Proxy + Class QoSm1Proxy =====================================*/ -class QoSm1Proxy : public Adapter +class QoSm1Proxy: public Adapter { public: - QoSm1Proxy(Gateway* gw); + QoSm1Proxy(Gateway* gw); ~QoSm1Proxy(void); void initialize(char* GWnAME); @@ -41,13 +41,10 @@ public: private: Gateway* _gateway; - bool _isActive {false}; - bool _isSecure {false}; + bool _isActive { false }; + bool _isSecure { false }; }; - } - - #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWQOSM1PROXY_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.cpp b/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.cpp index a08bf49..797e36b 100644 --- a/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.cpp +++ b/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.cpp @@ -26,7 +26,7 @@ using namespace MQTTSNGW; MQTTSNSubscribeHandler::MQTTSNSubscribeHandler(Gateway* gateway) { - _gateway = gateway; + _gateway = gateway; } MQTTSNSubscribeHandler::~MQTTSNSubscribeHandler() @@ -36,63 +36,71 @@ MQTTSNSubscribeHandler::~MQTTSNSubscribeHandler() MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packet) { - uint8_t dup; - int qos; - uint16_t msgId; - MQTTSN_topicid topicFilter; - Topic* topic = nullptr; + uint8_t dup; + int qos; + uint16_t msgId; + MQTTSN_topicid topicFilter; + Topic* topic = nullptr; uint16_t topicId = 0; MQTTGWPacket* subscribe; Event* ev1; Event* evsuback; - if ( packet->getSUBSCRIBE(&dup, &qos, &msgId, &topicFilter) == 0 ) - { - return nullptr; - } + if (packet->getSUBSCRIBE(&dup, &qos, &msgId, &topicFilter) == 0) + { + return nullptr; + } - if ( msgId == 0 ) - { - return nullptr; - } + if (msgId == 0) + { + return nullptr; + } - if ( topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED ) + if (topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED) { topic = client->getTopics()->getTopicById(&topicFilter); - if ( !topic ) + if (!topic) { - topic = _gateway->getTopics()->getTopicById(&topicFilter); - if ( topic ) - { - topic = client->getTopics()->add(topic->getTopicName()->c_str(), topic->getTopicId()); - } - else - { - goto RespExit; - } + /* Search the topic in Client common topic table */ + topic = _gateway->getTopics()->getTopicById(&topicFilter); + if (topic) + { + topic = client->getTopics()->add(topic->getTopicName()->c_str(), topic->getTopicId()); + if (topic == nullptr) + { + WRITELOG("%s Client(%s) can't add the Topic.%s\n", + ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + goto RespExit; + } + } + else + { + goto RespExit; + } } topicId = topic->getTopicId(); subscribe = new MQTTGWPacket(); - subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId); + subscribe->setSUBSCRIBE((char*) topic->getTopicName()->c_str(), (uint8_t) qos, (uint16_t) msgId); } else if (topicFilter.type == MQTTSN_TOPIC_TYPE_NORMAL) { topic = client->getTopics()->getTopicByName(&topicFilter); - if ( topic == nullptr ) + if (topic == nullptr) { topic = client->getTopics()->add(&topicFilter); - if ( topic == nullptr ) + if (topic == nullptr) { - WRITELOG("%s Client(%s) can't add the Topic.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - return nullptr; + WRITELOG("%s Client(%s) can't add the Topic.%s\n", + ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + goto RespExit; } } topicId = topic->getTopicId(); subscribe = new MQTTGWPacket(); - subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId); + subscribe->setSUBSCRIBE((char*) topic->getTopicName()->c_str(), (uint8_t) qos, (uint16_t) msgId); } else //MQTTSN_TOPIC_TYPE_SHORT { @@ -103,73 +111,70 @@ MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPack topicId = topicFilter.data.short_name[0] << 8; topicId |= topicFilter.data.short_name[1]; subscribe = new MQTTGWPacket(); - subscribe->setSUBSCRIBE(topicstr, (uint8_t)qos, (uint16_t)msgId); + subscribe->setSUBSCRIBE(topicstr, (uint8_t) qos, (uint16_t) msgId); } - client->setWaitedSubTopicId(msgId, topicId, topicFilter.type); + client->setWaitedSubTopicId(msgId, topicId, &topicFilter); - if ( !client->isAggregated() ) + if (!client->isAggregated()) { - ev1 = new Event(); - ev1->setBrokerSendEvent(client, subscribe); - _gateway->getBrokerSendQue()->post(ev1); - return nullptr; + ev1 = new Event(); + ev1->setBrokerSendEvent(client, subscribe); + _gateway->getBrokerSendQue()->post(ev1); + return nullptr; } else { - return subscribe; + return subscribe; } - -RespExit: - MQTTSNPacket* sSuback = new MQTTSNPacket(); - sSuback->setSUBACK(qos, topicFilter.data.id, msgId, MQTTSN_RC_NOT_SUPPORTED); - evsuback = new Event(); - evsuback->setClientSendEvent(client, sSuback); - _gateway->getClientSendQue()->post(evsuback); - return nullptr; + RespExit: MQTTSNPacket* sSuback = new MQTTSNPacket(); + sSuback->setSUBACK(qos, topicFilter.data.id, msgId, MQTTSN_RC_REJECTED_INVALID_TOPIC_ID); + evsuback = new Event(); + evsuback->setClientSendEvent(client, sSuback); + _gateway->getClientSendQue()->post(evsuback); + return nullptr; } MQTTGWPacket* MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* packet) { - uint16_t msgId; - MQTTSN_topicid topicFilter; + uint16_t msgId; + MQTTSN_topicid topicFilter; MQTTGWPacket* unsubscribe = nullptr; - if ( packet->getUNSUBSCRIBE(&msgId, &topicFilter) == 0 ) - { - return nullptr; - } - - if ( msgId == 0 ) + if (packet->getUNSUBSCRIBE(&msgId, &topicFilter) == 0) { - return nullptr; + return nullptr; } + if (msgId == 0) + { + return nullptr; + } - if (topicFilter.type == MQTTSN_TOPIC_TYPE_SHORT) - { - char shortTopic[3]; + if (topicFilter.type == MQTTSN_TOPIC_TYPE_SHORT) + { + char shortTopic[3]; shortTopic[0] = topicFilter.data.short_name[0]; shortTopic[1] = topicFilter.data.short_name[1]; shortTopic[2] = 0; unsubscribe = new MQTTGWPacket(); unsubscribe->setUNSUBSCRIBE(shortTopic, msgId); - } - else - { - Topic* topic = nullptr; + } + else + { + Topic* topic = nullptr; - if (topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED) - { - topic = client->getTopics()->getTopicById(&topicFilter); - } - else - { - topic = client->getTopics()->getTopicByName(&topicFilter); - } + if (topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED) + { + topic = client->getTopics()->getTopicById(&topicFilter); + } + else + { + topic = client->getTopics()->getTopicByName(&topicFilter); + } - if ( topic == nullptr ) + if (topic == nullptr) { MQTTSNPacket* sUnsuback = new MQTTSNPacket(); sUnsuback->setUNSUBACK(msgId); @@ -183,85 +188,87 @@ MQTTGWPacket* MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPa unsubscribe = new MQTTGWPacket(); unsubscribe->setUNSUBSCRIBE(topic->getTopicName()->c_str(), msgId); } - } + } - if ( !client->isAggregated() ) + if (!client->isAggregated()) { - Event* ev1 = new Event(); - ev1->setBrokerSendEvent(client, unsubscribe); - _gateway->getBrokerSendQue()->post(ev1); - return nullptr; + Event* ev1 = new Event(); + ev1->setBrokerSendEvent(client, unsubscribe); + _gateway->getBrokerSendQue()->post(ev1); + return nullptr; } else { - return unsubscribe; + return unsubscribe; } } void MQTTSNSubscribeHandler::handleAggregateSubscribe(Client* client, MQTTSNPacket* packet) { - MQTTGWPacket* subscribe = handleSubscribe(client, packet); + MQTTGWPacket* subscribe = handleSubscribe(client, packet); - if ( subscribe != nullptr ) - { - int msgId = 0; - if ( packet->isDuplicate() ) - { - msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); - } - else - { - msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); - } + if (subscribe != nullptr) + { + int msgId = 0; + if (packet->isDuplicate()) + { + msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); + } + else + { + msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); + } - if ( msgId == 0 ) - { - WRITELOG("%s MQTTSNSubscribeHandler can't create MessageIdTableElement %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - return; - } + if (msgId == 0) + { + WRITELOG("%s MQTTSNSubscribeHandler can't create MessageIdTableElement %s%s\n", + ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + return; + } - UTF8String str = subscribe->getTopic(); - string* topicName = new string(str.data, str.len); // topicName is delete by topic - Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); + UTF8String str = subscribe->getTopic(); + string* topicName = new string(str.data, str.len); // topicName is delete by topic + Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); - _gateway->getAdapterManager()->getAggregater()->addAggregateTopic(&topic, client); + _gateway->getAdapterManager()->getAggregater()->addAggregateTopic(&topic, client); - subscribe->setMsgId(msgId); - Event* ev = new Event(); - ev->setBrokerSendEvent(client, subscribe); - _gateway->getBrokerSendQue()->post(ev); - } + subscribe->setMsgId(msgId); + Event* ev = new Event(); + ev->setBrokerSendEvent(client, subscribe); + _gateway->getBrokerSendQue()->post(ev); + } } void MQTTSNSubscribeHandler::handleAggregateUnsubscribe(Client* client, MQTTSNPacket* packet) { - MQTTGWPacket* unsubscribe = handleUnsubscribe(client, packet); - if ( unsubscribe != nullptr ) - { - int msgId = 0; - if ( packet->isDuplicate() ) - { - msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); - } - else - { - msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); - } + MQTTGWPacket* unsubscribe = handleUnsubscribe(client, packet); + if (unsubscribe != nullptr) + { + int msgId = 0; + if (packet->isDuplicate()) + { + msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); + } + else + { + msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); + } - if ( msgId == 0 ) - { - WRITELOG("%s MQTTSNUnsubscribeHandler can't create MessageIdTableElement %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); - return; - } + if (msgId == 0) + { + WRITELOG("%s MQTTSNUnsubscribeHandler can't create MessageIdTableElement %s%s\n", + ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); + return; + } - UTF8String str = unsubscribe->getTopic(); - string* topicName = new string(str.data, str.len); // topicName is delete by topic - Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); - _gateway->getAdapterManager()->getAggregater()->removeAggregateTopic(&topic, client); + UTF8String str = unsubscribe->getTopic(); + string* topicName = new string(str.data, str.len); // topicName is delete by topic + Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); + _gateway->getAdapterManager()->getAggregater()->removeAggregateTopic(&topic, client); - unsubscribe->setMsgId(msgId); - Event* ev = new Event(); - ev->setBrokerSendEvent(client, unsubscribe); - _gateway->getBrokerSendQue()->post(ev); - } + unsubscribe->setMsgId(msgId); + Event* ev = new Event(); + ev->setBrokerSendEvent(client, unsubscribe); + _gateway->getBrokerSendQue()->post(ev); + } } diff --git a/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h b/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h index 5b2202a..dd21e3e 100644 --- a/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h +++ b/MQTTSNGateway/src/MQTTSNGWSubscribeHandler.h @@ -24,23 +24,22 @@ namespace MQTTSNGW { /*===================================== - Class MQTTSNSubscribeHandler + Class MQTTSNSubscribeHandler =====================================*/ class MQTTSNSubscribeHandler { public: - MQTTSNSubscribeHandler(Gateway* gateway); - ~MQTTSNSubscribeHandler(); - MQTTGWPacket* handleSubscribe(Client* client, MQTTSNPacket* packet); - MQTTGWPacket* handleUnsubscribe(Client* client, MQTTSNPacket* packet); - void handleAggregateSubscribe(Client* client, MQTTSNPacket* packet); - void handleAggregateUnsubscribe(Client* client, MQTTSNPacket* packet); + MQTTSNSubscribeHandler(Gateway* gateway); + ~MQTTSNSubscribeHandler(); + MQTTGWPacket* handleSubscribe(Client* client, MQTTSNPacket* packet); + MQTTGWPacket* handleUnsubscribe(Client* client, MQTTSNPacket* packet); + void handleAggregateSubscribe(Client* client, MQTTSNPacket* packet); + void handleAggregateUnsubscribe(Client* client, MQTTSNPacket* packet); private: - Gateway* _gateway; + Gateway* _gateway; }; } - #endif /* MQTTSNGWSUBSCRIBEHANDLER_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWTopic.cpp b/MQTTSNGateway/src/MQTTSNGWTopic.cpp index 8f56a4c..68cf1fe 100644 --- a/MQTTSNGateway/src/MQTTSNGWTopic.cpp +++ b/MQTTSNGateway/src/MQTTSNGWTopic.cpp @@ -27,35 +27,35 @@ using namespace MQTTSNGW; Topic::Topic() { _type = MQTTSN_TOPIC_TYPE_NORMAL; - _topicName = nullptr; - _topicId = 0; - _next = nullptr; + _topicName = nullptr; + _topicId = 0; + _next = nullptr; } Topic::Topic(string* topic, MQTTSN_topicTypes type) { _type = type; - _topicName = topic; - _topicId = 0; - _next = nullptr; + _topicName = topic; + _topicId = 0; + _next = nullptr; } Topic::~Topic() { - if ( _topicName ) - { - delete _topicName; - } + if (_topicName) + { + delete _topicName; + } } string* Topic::getTopicName(void) { - return _topicName; + return _topicName; } uint16_t Topic::getTopicId(void) { - return _topicId; + return _topicId; } MQTTSN_topicTypes Topic::getType(void) @@ -65,103 +65,103 @@ MQTTSN_topicTypes Topic::getType(void) Topic* Topic::duplicate(void) { - Topic* newTopic = new Topic(); - newTopic->_type = _type; - newTopic->_topicId = _topicId; - newTopic->_topicName = new string(_topicName->c_str()); - return newTopic; + Topic* newTopic = new Topic(); + newTopic->_type = _type; + newTopic->_topicId = _topicId; + newTopic->_topicName = new string(_topicName->c_str()); + return newTopic; } bool Topic::isMatch(string* topicName) { - string::size_type tlen = _topicName->size(); + string::size_type tlen = _topicName->size(); - string::size_type tpos = 0; - string::size_type tloc = 0; - string::size_type pos = 0; - string::size_type loc = 0; - string wildcard = "#"; - string wildcards = "+"; + string::size_type tpos = 0; + string::size_type tloc = 0; + string::size_type pos = 0; + string::size_type loc = 0; + string wildcard = "#"; + string wildcards = "+"; - while(true) - { - loc = topicName->find('/', pos); - tloc = _topicName->find('/', tpos); + while (true) + { + loc = topicName->find('/', pos); + tloc = _topicName->find('/', tpos); - if ( loc != string::npos && tloc != string::npos ) - { - string subtopic = topicName->substr(pos, loc - pos); - string subtopict = _topicName->substr(tpos, tloc - tpos); - if (subtopict == wildcard) - { - return true; - } - else if (subtopict == wildcards) - { - if ( (tpos = tloc + 1 ) > tlen ) - { - pos = loc + 1; - loc = topicName->find('/', pos); - if ( loc == string::npos ) - { - return true; - } - else - { - return false; - } - } - pos = loc + 1; - } - else if ( subtopic != subtopict ) - { - return false; - } - else - { - if ( (tpos = tloc + 1) > tlen ) - { - return false; - } + if (loc != string::npos && tloc != string::npos) + { + string subtopic = topicName->substr(pos, loc - pos); + string subtopict = _topicName->substr(tpos, tloc - tpos); + if (subtopict == wildcard) + { + return true; + } + else if (subtopict == wildcards) + { + if ((tpos = tloc + 1) > tlen) + { + pos = loc + 1; + loc = topicName->find('/', pos); + if (loc == string::npos) + { + return true; + } + else + { + return false; + } + } + pos = loc + 1; + } + else if (subtopic != subtopict) + { + return false; + } + else + { + if ((tpos = tloc + 1) > tlen) + { + return false; + } - pos = loc + 1; - } - } - else if ( loc == string::npos && tloc == string::npos ) - { - string subtopic = topicName->substr(pos); - string subtopict = _topicName->substr(tpos); - if ( subtopict == wildcard || subtopict == wildcards) - { - return true; - } - else if ( subtopic == subtopict ) - { - return true; - } - else - { - return false; - } - } - else if ( loc == string::npos && tloc != string::npos ) - { - string subtopic = topicName->substr(pos); - string subtopict = _topicName->substr(tpos, tloc - tpos); - if ( subtopic != subtopict) - { - return false; - } + pos = loc + 1; + } + } + else if (loc == string::npos && tloc == string::npos) + { + string subtopic = topicName->substr(pos); + string subtopict = _topicName->substr(tpos); + if (subtopict == wildcard || subtopict == wildcards) + { + return true; + } + else if (subtopic == subtopict) + { + return true; + } + else + { + return false; + } + } + else if (loc == string::npos && tloc != string::npos) + { + string subtopic = topicName->substr(pos); + string subtopict = _topicName->substr(tpos, tloc - tpos); + if (subtopic != subtopict) + { + return false; + } - tpos = tloc + 1; + tpos = tloc + 1; - return _topicName->substr(tpos) == wildcard; - } - else if ( loc != string::npos && tloc == string::npos ) - { - return _topicName->substr(tpos) == wildcard; - } - } + return _topicName->substr(tpos) == wildcard; + } + else if (loc != string::npos && tloc == string::npos) + { + return _topicName->substr(tpos) == wildcard; + } + } } void Topic::print(void) @@ -198,11 +198,11 @@ Topic* Topics::getTopicByName(const MQTTSN_topicid* topicid) string sname = string(ch, ch + topicid->data.long_.len); while (p) { - if ( p->_topicName->compare(sname) == 0 ) - { - return p; - } - p = p->_next; + if (p->_topicName->compare(sname) == 0) + { + return p; + } + p = p->_next; } return 0; } @@ -213,7 +213,7 @@ Topic* Topics::getTopicById(const MQTTSN_topicid* topicid) while (p) { - if ( p->_type == topicid->type && p->_topicId == topicid->data.id ) + if (p->_type == topicid->type && p->_topicId == topicid->data.id) { return p; } @@ -225,14 +225,14 @@ Topic* Topics::getTopicById(const MQTTSN_topicid* topicid) // For MQTTSN_TOPIC_TYPE_NORMAL */ Topic* Topics::add(const MQTTSN_topicid* topicid) { - if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL ) + if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL) { return 0; } Topic* topic = getTopicByName(topicid); - if ( topic ) + if (topic) { return topic; } @@ -244,18 +244,17 @@ Topic* Topics::add(const char* topicName, uint16_t id) { MQTTSN_topicid topicId; - if ( _cnt >= MAX_TOPIC_PAR_CLIENT ) + if (_cnt >= MAX_TOPIC_PAR_CLIENT) { return 0; } - topicId.data.long_.name = (char*)const_cast(topicName); + topicId.data.long_.name = (char*) const_cast(topicName); topicId.data.long_.len = strlen(topicName); - Topic* topic = getTopicByName(&topicId); - if ( topic ) + if (topic) { return topic; } @@ -270,7 +269,7 @@ Topic* Topics::add(const char* topicName, uint16_t id) string* name = new string(topicName); topic->_topicName = name; - if ( id == 0 ) + if (id == 0) { topic->_type = MQTTSN_TOPIC_TYPE_NORMAL; topic->_topicId = getNextTopicId(); @@ -278,12 +277,12 @@ Topic* Topics::add(const char* topicName, uint16_t id) else { topic->_type = MQTTSN_TOPIC_TYPE_PREDEFINED; - topic->_topicId = id; + topic->_topicId = id; } _cnt++; - if ( _first == nullptr) + if (_first == nullptr) { _first = topic; } @@ -331,7 +330,6 @@ Topic* Topics::match(const MQTTSN_topicid* topicid) return 0; } - void Topics::eraseNormal(void) { Topic* topic = _first; @@ -340,14 +338,14 @@ void Topics::eraseNormal(void) while (topic) { - if ( topic->_type == MQTTSN_TOPIC_TYPE_NORMAL ) + if (topic->_type == MQTTSN_TOPIC_TYPE_NORMAL) { next = topic->_next; - if ( _first == topic ) + if (_first == topic) { _first = next; } - if ( prev ) + if (prev) { prev->_next = next; } @@ -365,18 +363,18 @@ void Topics::eraseNormal(void) Topic* Topics::getFirstTopic(void) { - return _first; + return _first; } Topic* Topics::getNextTopic(Topic* topic) { - return topic->_next; + return topic->_next; } void Topics::print(void) { Topic* topic = _first; - if (topic == nullptr ) + if (topic == nullptr) { WRITELOG("No Topic.\n"); } @@ -398,13 +396,22 @@ uint8_t Topics::getCount(void) /*===================================== Class TopicIdMap =====================================*/ -TopicIdMapElement::TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) +TopicIdMapElement::TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic) { _msgId = msgId; _topicId = topicId; - _type = type; + _type = topic->type; + _wildcard = 0; _next = nullptr; _prev = nullptr; + + if (_type == MQTTSN_TOPIC_TYPE_NORMAL) + { + if (strchr(topic->data.long_.name, '#') != 0 || strchr(topic->data.long_.name, '+') != 0) + { + _wildcard = 1; + } + } } TopicIdMapElement::~TopicIdMapElement() @@ -419,7 +426,14 @@ MQTTSN_topicTypes TopicIdMapElement::getTopicType(void) uint16_t TopicIdMapElement::getTopicId(void) { - return _topicId; + if (_wildcard > 0) + { + return 0; + } + else + { + return _topicId; + } } TopicIdMap::TopicIdMap() @@ -434,7 +448,7 @@ TopicIdMap::TopicIdMap() TopicIdMap::~TopicIdMap() { TopicIdMapElement* p = _first; - while ( p ) + while (p) { TopicIdMapElement* q = p->_next; delete p; @@ -445,9 +459,9 @@ TopicIdMap::~TopicIdMap() TopicIdMapElement* TopicIdMap::getElement(uint16_t msgId) { TopicIdMapElement* p = _first; - while ( p ) + while (p) { - if ( p->_msgId == msgId ) + if (p->_msgId == msgId) { return p; } @@ -456,23 +470,23 @@ TopicIdMapElement* TopicIdMap::getElement(uint16_t msgId) return 0; } -TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) +TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic) { - if ( _cnt > _maxInflight * 2 || ( topicId == 0 && type != MQTTSN_TOPIC_TYPE_SHORT ) ) + if (_cnt > _maxInflight * 2 || (topicId == 0 && topic->type != MQTTSN_TOPIC_TYPE_SHORT)) { return 0; } - if ( getElement(msgId) ) + if (getElement(msgId)) { erase(msgId); } - TopicIdMapElement* elm = new TopicIdMapElement(msgId, topicId, type); - if ( elm == 0 ) + TopicIdMapElement* elm = new TopicIdMapElement(msgId, topicId, topic); + if (elm == 0) { return 0; } - if ( _first == nullptr ) + if (_first == nullptr) { _first = elm; _end = elm; @@ -490,11 +504,11 @@ TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topi void TopicIdMap::erase(uint16_t msgId) { TopicIdMapElement* p = _first; - while ( p ) + while (p) { - if ( p->_msgId == msgId ) + if (p->_msgId == msgId) { - if ( p->_prev == nullptr ) + if (p->_prev == nullptr) { _first = p->_next; } @@ -503,7 +517,7 @@ void TopicIdMap::erase(uint16_t msgId) p->_prev->_next = p->_next; } - if ( p->_next == nullptr ) + if (p->_next == nullptr) { _end = p->_prev; } @@ -523,7 +537,7 @@ void TopicIdMap::erase(uint16_t msgId) void TopicIdMap::clear(void) { TopicIdMapElement* p = _first; - while ( p ) + while (p) { TopicIdMapElement* q = p->_next; delete p; @@ -534,5 +548,3 @@ void TopicIdMap::clear(void) _cnt = 0; } - - diff --git a/MQTTSNGateway/src/MQTTSNGWTopic.h b/MQTTSNGateway/src/MQTTSNGWTopic.h index 4d7b0c3..f796b8b 100644 --- a/MQTTSNGateway/src/MQTTSNGWTopic.h +++ b/MQTTSNGateway/src/MQTTSNGWTopic.h @@ -24,7 +24,6 @@ namespace MQTTSNGW { - /*===================================== Class Topic ======================================*/ @@ -46,7 +45,7 @@ public: private: MQTTSN_topicTypes _type; uint16_t _topicId; - string* _topicName; + string* _topicName; Topic* _next; }; @@ -72,7 +71,7 @@ public: private: uint16_t _nextTopicId; Topic* _first; - uint8_t _cnt; + uint8_t _cnt; }; /*===================================== @@ -82,7 +81,7 @@ class TopicIdMapElement { friend class TopicIdMap; public: - TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); + TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic); ~TopicIdMapElement(); MQTTSN_topicTypes getTopicType(void); uint16_t getTopicId(void); @@ -90,6 +89,7 @@ public: private: uint16_t _msgId; uint16_t _topicId; + uint8_t _wildcard; MQTTSN_topicTypes _type; TopicIdMapElement* _next; TopicIdMapElement* _prev; @@ -101,7 +101,7 @@ public: TopicIdMap(); ~TopicIdMap(); TopicIdMapElement* getElement(uint16_t msgId); - TopicIdMapElement* add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); + TopicIdMapElement* add(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic); void erase(uint16_t msgId); void clear(void); private: @@ -112,9 +112,6 @@ private: int _maxInflight; }; - } - - #endif /* MQTTSNGATEWAY_SRC_MQTTSNGWTOPIC_H_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWVersion.h b/MQTTSNGateway/src/MQTTSNGWVersion.h index 251e5af..275be35 100644 --- a/MQTTSNGateway/src/MQTTSNGWVersion.h +++ b/MQTTSNGateway/src/MQTTSNGWVersion.h @@ -17,6 +17,6 @@ #ifndef MQTTSNGWVERSION_H_IN_ #define MQTTSNGWVERSION_H_IN_ -#define PAHO_GATEWAY_VERSION "1.4.0" +#define PAHO_GATEWAY_VERSION "1.6.0" #endif /* MQTTSNGWVERSION_H_IN_ */ diff --git a/MQTTSNGateway/src/MQTTSNGWVersion.h.in b/MQTTSNGateway/src/MQTTSNGWVersion.h.in index 8dab1a0..f012fe7 100644 --- a/MQTTSNGateway/src/MQTTSNGWVersion.h.in +++ b/MQTTSNGateway/src/MQTTSNGWVersion.h.in @@ -17,6 +17,6 @@ #ifndef MQTTSNGWVERSION_H_IN_ #define MQTTSNGWVERSION_H_IN_ -#define PAHO_GATEWAY_VERSION "@GATEWAY_VERSION@" +#define PAHO_GATEWAY_VERSION "@GATEWAY_VERSION@" #endif /* MQTTSNGWVERSION_H_IN_ */ \ No newline at end of file diff --git a/MQTTSNGateway/src/MQTTSNGateway.cpp b/MQTTSNGateway/src/MQTTSNGateway.cpp index 6ed0c04..d672268 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.cpp +++ b/MQTTSNGateway/src/MQTTSNGateway.cpp @@ -32,10 +32,10 @@ MQTTSNGW::Gateway* theGateway = nullptr; Gateway::Gateway(void) { + theGateway = this; theMultiTaskProcess = this; theProcess = this; - _packetEventQue.setMaxSize(MAX_INFLIGHTMESSAGES * MAX_CLIENTS); - _clientList = new ClientList(); + _clientList = new ClientList(this); _adapterManager = new AdapterManager(this); _topics = new Topics(); _stopFlg = false; @@ -43,78 +43,87 @@ Gateway::Gateway(void) Gateway::~Gateway() { - if ( _params.loginId ) - { - free(_params.loginId); - } - if ( _params.password ) - { - free(_params.password); - } - if ( _params.gatewayName ) - { - free(_params.gatewayName); - } - if ( _params.brokerName ) - { - free(_params.brokerName); - } - if ( _params.port ) - { - free(_params.port); - } - if ( _params.portSecure ) - { - free(_params.portSecure); - } - if ( _params.certKey ) - { - free(_params.certKey); - } - if ( _params.privateKey ) - { - free(_params.privateKey); - } - if ( _params.rootCApath ) - { - free(_params.rootCApath); - } - if ( _params.rootCAfile ) - { - free(_params.rootCAfile); - } - if ( _params.clientListName ) - { - free(_params.clientListName); - } - if ( _params.predefinedTopicFileName ) - { - free( _params.predefinedTopicFileName); - } - if ( _params.configName ) - { - free(_params.configName); - } - - if ( _params.qosMinusClientListName ) + if (_params.loginId) + { + free(_params.loginId); + } + if (_params.password) + { + free(_params.password); + } + if (_params.gatewayName) + { + free(_params.gatewayName); + } + if (_params.brokerName) + { + free(_params.brokerName); + } + if (_params.port) + { + free(_params.port); + } + if (_params.portSecure) + { + free(_params.portSecure); + } + if (_params.certKey) + { + free(_params.certKey); + } + if (_params.privateKey) + { + free(_params.privateKey); + } + if (_params.rootCApath) + { + free(_params.rootCApath); + } + if (_params.rootCAfile) + { + free(_params.rootCAfile); + } + if (_params.clientListName) + { + free(_params.clientListName); + } + if (_params.predefinedTopicFileName) + { + free(_params.predefinedTopicFileName); + } + if (_params.configName) + { + free(_params.configName); + } + if (_params.qosMinusClientListName) { free(_params.qosMinusClientListName); } + if (_params.rfcommAddr) + { + free(_params.rfcommAddr); + } + if (_params.gwCertskey) + { + free(_params.gwCertskey); + } + if (_params.gwPrivatekey) + { + free(_params.gwPrivatekey); + } - if ( _adapterManager ) + if (_adapterManager) { delete _adapterManager; } - if ( _clientList ) + if (_clientList) { delete _clientList; } - - if ( _topics ) - { - delete _topics; - } -// WRITELOG("Gateway is deleted normally.\r\n"); + if (_topics) + { + delete _topics; + } } int Gateway::getParam(const char* parameter, char* value) @@ -124,256 +133,285 @@ int Gateway::getParam(const char* parameter, char* value) char* Gateway::getClientListFileName(void) { - return _params.clientListName; + return _params.clientListName; } char* Gateway::getPredefinedTopicFileName(void) { - return _params.predefinedTopicFileName; + return _params.predefinedTopicFileName; } void Gateway::initialize(int argc, char** argv) { - char param[MQTTSNGW_PARAM_MAX]; - string fileName; + char param[MQTTSNGW_PARAM_MAX]; + string fileName; theGateway = this; - MultiTaskProcess::initialize(argc, argv); - resetRingBuffer(); + MultiTaskProcess::initialize(argc, argv); + resetRingBuffer(); - _params.configDir = *getConfigDirName(); + _params.configDir = *getConfigDirName(); fileName = _params.configDir + *getConfigFileName(); _params.configName = strdup(fileName.c_str()); - if (getParam("BrokerName", param) == 0) - { - _params.brokerName = strdup(param); - } - if (getParam("BrokerPortNo", param) == 0) - { - _params.port = strdup(param); - } - if (getParam("BrokerSecurePortNo", param) == 0) - { - _params.portSecure = strdup(param); - } + if (getParam("BrokerName", param) == 0) + { + _params.brokerName = strdup(param); + } + if (getParam("BrokerPortNo", param) == 0) + { + _params.port = strdup(param); + } + if (getParam("BrokerSecurePortNo", param) == 0) + { + _params.portSecure = strdup(param); + } - if (getParam("CertKey", param) == 0) - { - _params.certKey = strdup(param); - } - if (getParam("PrivateKey", param) == 0) - { - _params.privateKey = strdup(param); - } - if (getParam("RootCApath", param) == 0) - { - _params.rootCApath = strdup(param); - } - if (getParam("RootCAfile", param) == 0) - { - _params.rootCAfile = strdup(param); - } + if (getParam("CertKey", param) == 0) + { + _params.certKey = strdup(param); + } + if (getParam("PrivateKey", param) == 0) + { + _params.privateKey = strdup(param); + } + if (getParam("RootCApath", param) == 0) + { + _params.rootCApath = strdup(param); + } + if (getParam("RootCAfile", param) == 0) + { + _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) - { - _params.gatewayId = atoi(param); - } + if (getParam("GatewayID", param) == 0) + { + _params.gatewayId = atoi(param); + } - if (_params.gatewayId == 0 || _params.gatewayId > 255) - { - throw Exception( "Gateway::initialize: invalid Gateway Id"); - } + if (_params.gatewayId == 0 || _params.gatewayId > 255) + { + throw Exception("Gateway::initialize: invalid Gateway Id", 0); + } - if (getParam("GatewayName", param) == 0) - { - _params.gatewayName = strdup(param); - } + if (getParam("GatewayName", param) == 0) + { + _params.gatewayName = strdup(param); + } - if (_params.gatewayName == 0 ) - { - throw Exception( "Gateway::initialize: Gateway Name is missing."); - } + if (_params.gatewayName == 0) + { + throw Exception("Gateway::initialize: Gateway Name is missing.", 0); + } - _params.mqttVersion = DEFAULT_MQTT_VERSION; - if (getParam("MQTTVersion", param) == 0) - { - _params.mqttVersion = atoi(param); - } + _params.mqttVersion = DEFAULT_MQTT_VERSION; + if (getParam("MQTTVersion", param) == 0) + { + _params.mqttVersion = atoi(param); + } - _params.maxInflightMsgs = DEFAULT_MQTT_VERSION; - if (getParam("MaxInflightMsgs", param) == 0) - { - _params.maxInflightMsgs = atoi(param); - } + _params.maxInflightMsgs = MAX_INFLIGHTMESSAGES; + if (getParam("MaxInflightMsgs", param) == 0) + { + _params.maxInflightMsgs = atoi(param); + } - _params.keepAlive = DEFAULT_KEEP_ALIVE_TIME; - if (getParam("KeepAlive", param) == 0) - { - _params.keepAlive = atoi(param); - } + _params.keepAlive = DEFAULT_KEEP_ALIVE_TIME; + if (getParam("KeepAlive", param) == 0) + { + _params.keepAlive = atoi(param); + } - if (getParam("LoginID", param) == 0) - { - _params.loginId = strdup(param); - } + if (getParam("LoginID", param) == 0) + { + _params.loginId = strdup(param); + } - if (getParam("Password", param) == 0) - { - _params.password = strdup(param); - } + if (getParam("Password", param) == 0) + { + _params.password = strdup(param); + } - if (getParam("ClientAuthentication", param) == 0) - { - if (!strcasecmp(param, "YES")) - { - _params.clientAuthentication = true; - } - } + if (getParam("ClientAuthentication", param) == 0) + { + if (!strcasecmp(param, "YES")) + { + _params.clientAuthentication = true; + } + } - if (getParam("ClientsList", param) == 0) - { - _params.clientListName = strdup(param); - } + if (getParam("ClientsList", param) == 0) + { + _params.clientListName = strdup(param); + } - if (getParam("PredefinedTopic", param) == 0) - { - if ( !strcasecmp(param, "YES") ) - { - _params.predefinedTopic = true; - if (getParam("PredefinedTopicList", param) == 0) - { - _params.predefinedTopicFileName = strdup(param); - } - } - } + if (getParam("PredefinedTopic", param) == 0) + { + if (!strcasecmp(param, "YES")) + { + _params.predefinedTopic = true; + if (getParam("PredefinedTopicList", param) == 0) + { + _params.predefinedTopicFileName = strdup(param); + } + } + } - if (getParam("AggregatingGateway", param) == 0) - { - if ( !strcasecmp(param, "YES") ) - { - _params.aggregatingGw = true; - } - } + if (getParam("AggregatingGateway", param) == 0) + { + if (!strcasecmp(param, "YES")) + { + _params.aggregatingGw = true; + } + } - if (getParam("Forwarder", param) == 0) - { - if ( !strcasecmp(param, "YES") ) - { - _params.forwarder = true; - } - } + if (getParam("Forwarder", param) == 0) + { + if (!strcasecmp(param, "YES")) + { + _params.forwarder = true; + } + } - if (getParam("QoS-1", param) == 0) - { - if ( !strcasecmp(param, "YES") ) - { - _params.qosMinus1 = true; - } - } + if (getParam("QoS-1", param) == 0) + { + if (!strcasecmp(param, "YES")) + { + _params.qosMinus1 = true; + } + } + _params.maxClients = MAX_CLIENTS; + if (getParam("MaxNumberOfClients", param) == 0) + { + _params.maxClients = atoi(param); + } - /* Initialize adapters */ - _adapterManager->initialize( _params.gatewayName, _params.aggregatingGw, _params.forwarder, _params.qosMinus1); + if (getParam("RFCOMMAddress", param) == 0) + { + _params.rfcommAddr = strdup(param); + } - /* Setup ClientList and Predefined topics */ - _clientList->initialize(_params.aggregatingGw); + /* Setup max PacketEventQue size */ + _packetEventQue.setMaxSize(_params.maxInflightMsgs * _params.maxClients); + + /* Initialize adapters */ + _adapterManager->initialize(_params.gatewayName, _params.aggregatingGw, _params.forwarder, _params.qosMinus1); + + /* Setup ClientList and Predefined topics */ + _clientList->initialize(_params.aggregatingGw); + + /* SensorNetwork initialize */ + _sensorNetwork.initialize(); } void Gateway::run(void) { /* write prompts */ - _lightIndicator.redLight(true); - WRITELOG("\n%s", PAHO_COPYRIGHT4); - WRITELOG("\n%s\n", PAHO_COPYRIGHT0); - WRITELOG("%s\n", PAHO_COPYRIGHT1); - WRITELOG("%s\n", PAHO_COPYRIGHT2); - WRITELOG(" *\n%s\n", PAHO_COPYRIGHT3); - WRITELOG(" * Version: %s\n", PAHO_GATEWAY_VERSION); - WRITELOG("%s\n", PAHO_COPYRIGHT4); - WRITELOG("\n%s %s has been started.\n\n", currentDateTime(), _params.gatewayName); - WRITELOG(" ConfigFile: %s\n", _params.configName); + _lightIndicator.redLight(true); + WRITELOG("\n%s", PAHO_COPYRIGHT4); + WRITELOG("\n%s\n", PAHO_COPYRIGHT0); + WRITELOG("%s\n", PAHO_COPYRIGHT1); + WRITELOG("%s\n", PAHO_COPYRIGHT2); + WRITELOG(" *\n%s\n", PAHO_COPYRIGHT3); + WRITELOG(" * Version: %s\n", PAHO_GATEWAY_VERSION); + WRITELOG("%s\n", PAHO_COPYRIGHT4); + WRITELOG(" ConfigFile : %s\n", _params.configName); - if ( _params.clientListName ) - { - WRITELOG(" ClientList: %s\n", _params.clientListName); - } - - if ( _params.predefinedTopicFileName ) + if (_params.clientListName) { - WRITELOG(" PreDefFile: %s\n", _params.predefinedTopicFileName); + WRITELOG(" ClientList : %s\n", _params.clientListName); } - WRITELOG(" SensorN/W: %s\n", _sensorNetwork.getDescription()); - WRITELOG(" Broker: %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); - WRITELOG(" RootCApath: %s\n", _params.rootCApath); - WRITELOG(" RootCAfile: %s\n", _params.rootCAfile); - WRITELOG(" CertKey: %s\n", _params.certKey); - WRITELOG(" PrivateKey: %s\n\n\n", _params.privateKey); + if (_params.predefinedTopicFileName) + { + WRITELOG(" PreDefFile : %s\n", _params.predefinedTopicFileName); + } - _stopFlg = false; + WRITELOG(" Broker : %s : %s, %s\n", _params.brokerName, _params.port, _params.portSecure); + WRITELOG(" RootCApath : %s\n", _params.rootCApath); + WRITELOG(" RootCAfile : %s\n", _params.rootCAfile); + WRITELOG(" CertKey : %s\n", _params.certKey); + WRITELOG(" PrivateKey : %s\n", _params.privateKey); + WRITELOG(" SensorN/W : %s\n", _sensorNetwork.getDescription()); +#ifdef DTLS + WRITELOG(" DtlsCertsKey: %s\n", _params.gwCertskey); + WRITELOG(" DtlsPrivKey : %s\n", _params.gwPrivatekey); +#endif + WRITELOG(" Max Clients : %d\n\n", _params.maxClients); + WRITELOG("%s %s starts running.\n\n", currentDateTime(), _params.gatewayName); - /* Run Tasks until CTRL+C entred */ - MultiTaskProcess::run(); + _stopFlg = false; - _stopFlg = true; + /* Run Tasks until CTRL+C entered or Exception occurred */ + MultiTaskProcess::run(); + WRITELOG("\n"); + _stopFlg = true; - /* stop Tasks */ - Event* ev = new Event(); - ev->setStop(); - _packetEventQue.post(ev); - ev = new Event(); - ev->setStop(); - _brokerSendQue.post(ev); - ev = new Event(); - ev->setStop(); - _clientSendQue.post(ev); + /* stop Tasks */ + Event* ev = new Event(); + ev->setStop(); + _packetEventQue.post(ev); + ev = new Event(); + ev->setStop(); + _brokerSendQue.post(ev); + ev = new Event(); + ev->setStop(); + _clientSendQue.post(ev); - /* wait until all Task stop */ - MultiTaskProcess::waitStop(); + /* wait until all Task stop */ + MultiTaskProcess::waitStop(); - WRITELOG("\n\n%s MQTT-SN Gateway stopped.\n\n", currentDateTime()); - _lightIndicator.allLightOff(); + WRITELOG("\n%s MQTT-SN Gateway stopped.\n\n", currentDateTime()); + _lightIndicator.allLightOff(); } bool Gateway::IsStopping(void) { - return _stopFlg; + return _stopFlg; } EventQue* Gateway::getPacketEventQue() { - return &_packetEventQue; + return &_packetEventQue; } EventQue* Gateway::getClientSendQue() { - return &_clientSendQue; + return &_clientSendQue; } EventQue* Gateway::getBrokerSendQue() { - return &_brokerSendQue; + return &_brokerSendQue; } ClientList* Gateway::getClientList() { - return _clientList; + return _clientList; } SensorNetwork* Gateway::getSensorNetwork() { - return &_sensorNetwork; + return &_sensorNetwork; } LightIndicator* Gateway::getLightIndicator() { - return &_lightIndicator; + return &_lightIndicator; } GatewayParams* Gateway::getGWParams(void) { - return &_params; + return &_params; } AdapterManager* Gateway::getAdapterManager(void) @@ -388,102 +426,98 @@ Topics* Gateway::getTopics(void) bool Gateway::hasSecureConnection(void) { - return ( _params.certKey - && _params.privateKey - && _params.rootCApath - && _params.rootCAfile ); + return (_params.certKey && _params.privateKey && _params.rootCApath && _params.rootCAfile); } + /*===================================== Class EventQue =====================================*/ EventQue::EventQue() { - } EventQue::~EventQue() { - _mutex.lock(); - while (_que.size() > 0) - { - delete _que.front(); - _que.pop(); - } - _mutex.unlock(); + _mutex.lock(); + while (_que.size() > 0) + { + delete _que.front(); + _que.pop(); + } + _mutex.unlock(); } -void EventQue::setMaxSize(uint16_t maxSize) +void EventQue::setMaxSize(uint16_t maxSize) { - _que.setMaxSize((int)maxSize); + _que.setMaxSize((int) maxSize); } Event* EventQue::wait(void) { - Event* ev = nullptr; + Event* ev = nullptr; - while(ev == nullptr) - { - if ( _que.size() == 0 ) - { - _sem.wait(); - } - _mutex.lock(); - ev = _que.front(); - _que.pop(); - _mutex.unlock(); - } - return ev; + while (ev == nullptr) + { + if (_que.size() == 0) + { + _sem.wait(); + } + _mutex.lock(); + ev = _que.front(); + _que.pop(); + _mutex.unlock(); + } + return ev; } Event* EventQue::timedwait(uint16_t millsec) { - Event* ev; - if ( _que.size() == 0 ) - { - _sem.timedwait(millsec); - } - _mutex.lock(); + Event* ev; + if (_que.size() == 0) + { + _sem.timedwait(millsec); + } + _mutex.lock(); - if (_que.size() == 0) - { - ev = new Event(); - ev->setTimeout(); - } - else - { - ev = _que.front(); - _que.pop(); - } - _mutex.unlock(); - return ev; + if (_que.size() == 0) + { + ev = new Event(); + ev->setTimeout(); + } + else + { + ev = _que.front(); + _que.pop(); + } + _mutex.unlock(); + return ev; } void EventQue::post(Event* ev) { - if ( ev ) - { - _mutex.lock(); - if ( _que.post(ev) ) - { - _sem.post(); - } - else - { - delete ev; - } - _mutex.unlock(); - } + if (ev) + { + _mutex.lock(); + if (_que.post(ev)) + { + _sem.post(); + } + else + { + delete ev; + } + _mutex.unlock(); + } } int EventQue::size() { - _mutex.lock(); - int sz = _que.size(); - _mutex.unlock(); - return sz; + _mutex.lock(); + int sz = _que.size(); + _mutex.unlock(); + return sz; } - /*===================================== Class Event =====================================*/ @@ -494,96 +528,95 @@ Event::Event() Event::~Event() { - if (_sensorNetAddr) - { - delete _sensorNetAddr; - } + if (_sensorNetAddr) + { + delete _sensorNetAddr; + } - if (_mqttSNPacket) - { - delete _mqttSNPacket; - } + if (_mqttSNPacket) + { + delete _mqttSNPacket; + } - if (_mqttGWPacket) - { - delete _mqttGWPacket; - } + if (_mqttGWPacket) + { + delete _mqttGWPacket; + } } EventType Event::getEventType() { - return _eventType; + return _eventType; } void Event::setClientSendEvent(Client* client, MQTTSNPacket* packet) { - _client = client; - _eventType = EtClientSend; - _mqttSNPacket = packet; + _client = client; + _eventType = EtClientSend; + _mqttSNPacket = packet; } void Event::setBrokerSendEvent(Client* client, MQTTGWPacket* packet) { - _client = client; - _eventType = EtBrokerSend; - _mqttGWPacket = packet; + _client = client; + _eventType = EtBrokerSend; + _mqttGWPacket = packet; } void Event::setClientRecvEvent(Client* client, MQTTSNPacket* packet) { - _client = client; - _eventType = EtClientRecv; - _mqttSNPacket = packet; + _client = client; + _eventType = EtClientRecv; + _mqttSNPacket = packet; } void Event::setBrokerRecvEvent(Client* client, MQTTGWPacket* packet) { - _client = client; - _eventType = EtBrokerRecv; - _mqttGWPacket = packet; + _client = client; + _eventType = EtBrokerRecv; + _mqttGWPacket = packet; } void Event::setTimeout(void) { - _eventType = EtTimeout; + _eventType = EtTimeout; } void Event::setStop(void) { - _eventType = EtStop; + _eventType = EtStop; } void Event::setBrodcastEvent(MQTTSNPacket* msg) { - _mqttSNPacket = msg; - _eventType = EtBroadcast; + _mqttSNPacket = msg; + _eventType = EtBroadcast; } void Event::setClientSendEvent(SensorNetAddress* addr, MQTTSNPacket* msg) { - _eventType = EtSensornetSend; - _sensorNetAddr = addr; - _mqttSNPacket = msg; + _eventType = EtSensornetSend; + _sensorNetAddr = addr; + _mqttSNPacket = msg; } Client* Event::getClient(void) { - return _client; + return _client; } SensorNetAddress* Event::getSensorNetAddress(void) { - return _sensorNetAddr; + return _sensorNetAddr; } MQTTSNPacket* Event::getMQTTSNPacket() { - return _mqttSNPacket; + return _mqttSNPacket; } MQTTGWPacket* Event::getMQTTGWPacket(void) { - return _mqttGWPacket; + return _mqttGWPacket; } - diff --git a/MQTTSNGateway/src/MQTTSNGateway.h b/MQTTSNGateway/src/MQTTSNGateway.h index 86c7952..d4836ae 100644 --- a/MQTTSNGateway/src/MQTTSNGateway.h +++ b/MQTTSNGateway/src/MQTTSNGateway.h @@ -20,6 +20,7 @@ #include "MQTTSNGWProcess.h" #include "MQTTSNPacket.h" #include "MQTTSNGWClient.h" +#include "MQTTSNGWProcess.h" namespace MQTTSNGW { @@ -28,7 +29,7 @@ namespace MQTTSNGW ==================================*/ #define PAHO_COPYRIGHT0 " * MQTT-SN Gateway" #define PAHO_COPYRIGHT1 " * Part of Project Paho in Eclipse" -#define PAHO_COPYRIGHT2 " * (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)" +#define PAHO_COPYRIGHT2 " * (https://github.com/eclipse/paho.mqtt-sn.embedded-c.git)" #define PAHO_COPYRIGHT3 " * Author : Tomoaki YAMAGUCHI" #define PAHO_COPYRIGHT4 " ***************************************************************************" /*========================================================== @@ -46,8 +47,8 @@ namespace MQTTSNGW #define LEFTARROW "<---" #define RIGHTARROW "--->" -#define LEFTARROWB "<===" -#define RIGHTARROWB "===>" +#define LEFTARROWB "<===" +#define RIGHTARROWB "===>" #define FORMAT_Y_G_G_NL "\n%s \033[0m\033[0;33m%-18s\033[0m\033[0;32m%-6s%-34.32s \033[0m\033[0;34m%s\033[0m\033[0;37m\n" #define FORMAT_Y_G_G "%s \033[0m\033[0;33m%-18s\033[0m\033[0;32m%-6s%-34.32s \033[0m\033[0;34m%s\033[0m\033[0;37m\n" @@ -68,152 +69,153 @@ namespace MQTTSNGW #define FORMAT_BL_NL "\n%s \033[0m\033[0;34m%-18s%-6s%-34.32s %s\033[0m\033[0;37m\n" #define FORMAT_W_NL "\n%s %-18s%-6s%-34.32s %s\n" -#define ERRMSG_HEADER "\033[0m\033[0;31mError:" -#define ERRMSG_FOOTER "\033[0m\033[0;37m" +#define ERRMSG_HEADER "\033[0m\033[0;31mError:" +#define ERRMSG_FOOTER "\033[0m\033[0;37m" /*===================================== - Class Event - ====================================*/ + Class Event + ====================================*/ class Client; -enum EventType{ - Et_NA = 0, - EtStop, - EtTimeout, - EtBrokerRecv, - EtBrokerSend, - EtClientRecv, - EtClientSend, - EtBroadcast, - EtSensornetSend +enum EventType +{ + Et_NA = 0, + EtStop, + EtTimeout, + EtBrokerRecv, + EtBrokerSend, + EtClientRecv, + EtClientSend, + EtBroadcast, + EtSensornetSend }; - -class Event{ +class Event +{ public: - Event(); - ~Event(); - EventType getEventType(void); - void setClientRecvEvent(Client*, MQTTSNPacket*); - void setClientSendEvent(Client*, MQTTSNPacket*); - void setBrokerRecvEvent(Client*, MQTTGWPacket*); - void setBrokerSendEvent(Client*, MQTTGWPacket*); - void setBrodcastEvent(MQTTSNPacket*); // ADVERTISE and GWINFO - void setTimeout(void); // Required by EventQue.timedwait() - void setStop(void); - void setClientSendEvent(SensorNetAddress*, MQTTSNPacket*); - Client* getClient(void); - SensorNetAddress* getSensorNetAddress(void); - MQTTSNPacket* getMQTTSNPacket(void); - MQTTGWPacket* getMQTTGWPacket(void); + Event(); + ~Event(); + EventType getEventType(void); + void setClientRecvEvent(Client*, MQTTSNPacket*); + void setClientSendEvent(Client*, MQTTSNPacket*); + void setBrokerRecvEvent(Client*, MQTTGWPacket*); + void setBrokerSendEvent(Client*, MQTTGWPacket*); + void setBrodcastEvent(MQTTSNPacket*); // ADVERTISE and GWINFO + void setTimeout(void); // Required by EventQue.timedwait() + void setStop(void); + void setClientSendEvent(SensorNetAddress*, MQTTSNPacket*); + Client* getClient(void); + SensorNetAddress* getSensorNetAddress(void); + MQTTSNPacket* getMQTTSNPacket(void); + MQTTGWPacket* getMQTTGWPacket(void); private: - EventType _eventType {Et_NA}; - Client* _client {nullptr}; - SensorNetAddress* _sensorNetAddr {nullptr}; - MQTTSNPacket* _mqttSNPacket {nullptr}; - MQTTGWPacket* _mqttGWPacket {nullptr}; + EventType _eventType { Et_NA }; + Client* _client { nullptr }; + SensorNetAddress* _sensorNetAddr { nullptr }; + MQTTSNPacket* _mqttSNPacket { nullptr }; + MQTTGWPacket* _mqttGWPacket { nullptr }; }; - /*===================================== Class EventQue ====================================*/ class EventQue { public: - EventQue(); - ~EventQue(); - Event* wait(void); - Event* timedwait(uint16_t millsec); - void setMaxSize(uint16_t maxSize); - void post(Event*); - int size(); + EventQue(); + ~EventQue(); + Event* wait(void); + Event* timedwait(uint16_t millsec); + void setMaxSize(uint16_t maxSize); + void post(Event*); + int size(); private: - Que _que; - Mutex _mutex; - Semaphore _sem; + Que _que; + Mutex _mutex; + Semaphore _sem; }; - - /*===================================== Class GatewayParams ====================================*/ class GatewayParams { public: - string configDir; - char* configName {nullptr}; - char* clientListName {nullptr}; - char* loginId {nullptr}; - char* password {nullptr}; - uint16_t keepAlive {0}; - uint8_t gatewayId {0}; - uint8_t mqttVersion {0}; - uint16_t maxInflightMsgs {0}; - char* gatewayName {nullptr}; - char* brokerName {nullptr}; - char* port {nullptr}; - char* portSecure {nullptr}; - char* rootCApath {nullptr}; - char* rootCAfile {nullptr}; - char* certKey {nullptr}; - char* predefinedTopicFileName {nullptr}; - char* privateKey {nullptr}; - char* qosMinusClientListName {nullptr}; - bool clientAuthentication {false}; - bool predefinedTopic {false}; - bool aggregatingGw {false}; - bool qosMinus1 {false}; - bool forwarder {false}; + string configDir; + char* configName { nullptr }; + char* clientListName { nullptr }; + char* loginId { nullptr }; + char* password { nullptr }; + uint16_t keepAlive { 0 }; + uint8_t gatewayId { 0 }; + uint8_t mqttVersion { 0 }; + uint16_t maxInflightMsgs { 0 }; + char* gatewayName { nullptr }; + char* brokerName { nullptr }; + char* port { nullptr }; + char* portSecure{ nullptr }; + char* rootCApath { nullptr }; + char* rootCAfile { nullptr }; + char* certKey { nullptr }; + char* predefinedTopicFileName { nullptr }; + char* privateKey { nullptr }; + char* qosMinusClientListName { nullptr }; + bool clientAuthentication { false }; + bool predefinedTopic { false }; + bool aggregatingGw { false }; + bool qosMinus1 { false }; + bool forwarder { false }; + int maxClients {0}; + char* rfcommAddr { nullptr }; + char* gwCertskey { nullptr }; + char* gwPrivatekey { nullptr }; }; - - /*===================================== - Class Gateway + Class Gateway =====================================*/ class AdapterManager; class ClientList; +class ClientsPool; -class Gateway: public MultiTaskProcess{ +class Gateway: public MultiTaskProcess +{ public: Gateway(void); - ~Gateway(); - virtual void initialize(int argc, char** argv); - void run(void); + ~Gateway(); + virtual void initialize(int argc, char** argv); + void run(void); - EventQue* getPacketEventQue(void); - EventQue* getClientSendQue(void); - EventQue* getBrokerSendQue(void); - ClientList* getClientList(void); - SensorNetwork* getSensorNetwork(void); - LightIndicator* getLightIndicator(void); - GatewayParams* getGWParams(void); - AdapterManager* getAdapterManager(void); - int getParam(const char* parameter, char* value); - char* getClientListFileName(void); - char* getPredefinedTopicFileName(void); - - bool hasSecureConnection(void); - Topics* getTopics(void); - bool IsStopping(void); + EventQue* getPacketEventQue(void); + EventQue* getClientSendQue(void); + EventQue* getBrokerSendQue(void); + ClientList* getClientList(void); + SensorNetwork* getSensorNetwork(void); + LightIndicator* getLightIndicator(void); + GatewayParams* getGWParams(void); + AdapterManager* getAdapterManager(void); + int getParam(const char* parameter, char* value); + char* getClientListFileName(void); + char* getPredefinedTopicFileName(void); + bool hasSecureConnection(void); + Topics* getTopics(void); + bool IsStopping(void); + void requestSensorNetSubTask(void); private: - GatewayParams _params; - ClientList* _clientList {nullptr}; - EventQue _packetEventQue; - EventQue _brokerSendQue; - EventQue _clientSendQue; - LightIndicator _lightIndicator; - SensorNetwork _sensorNetwork; - AdapterManager* _adapterManager {nullptr}; - Topics* _topics; - bool _stopFlg; + GatewayParams _params; + ClientList* _clientList; + EventQue _packetEventQue; + EventQue _brokerSendQue; + EventQue _clientSendQue; + LightIndicator _lightIndicator; + SensorNetwork _sensorNetwork; + AdapterManager* _adapterManager; + Topics* _topics; + bool _stopFlg; }; - } #endif /* MQTTSNGATEWAY_H_ */ diff --git a/MQTTSNGateway/src/linux/Network.cpp b/MQTTSNGateway/src/linux/Network.cpp index 842e121..bd5039a 100644 --- a/MQTTSNGateway/src/linux/Network.cpp +++ b/MQTTSNGateway/src/linux/Network.cpp @@ -279,6 +279,7 @@ bool Network::connect(const char* host, const char* port, const char* caPath, co char errmsg[256]; char peer_CN[256]; bool rc; + X509* peer = nullptr; _mutex.lock(); try @@ -385,7 +386,7 @@ bool Network::connect(const char* host, const char* port, const char* caPath, co throw false; } - X509* peer = SSL_get_peer_certificate(_ssl); + peer = SSL_get_peer_certificate(_ssl); X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, peer_CN, 256); char* pos = peer_CN; if ( *pos == '*') @@ -413,7 +414,12 @@ bool Network::connect(const char* host, const char* port, const char* caPath, co { rc = x; } + _mutex.unlock(); + if (peer != nullptr) + { + X509_free(peer); + } return rc; } @@ -650,3 +656,7 @@ bool Network::isSecure() return _secureFlg; } +void Network::setSecure(bool secureFlg) +{ + _secureFlg = secureFlg; +} diff --git a/MQTTSNGateway/src/linux/Network.h b/MQTTSNGateway/src/linux/Network.h index f5e15bd..57ed2ce 100644 --- a/MQTTSNGateway/src/linux/Network.h +++ b/MQTTSNGateway/src/linux/Network.h @@ -80,6 +80,7 @@ public: bool isValid(void); bool isSecure(void); int getSock(void); + void setSecure(bool secureFlg); private: static SSL_CTX* _ctx; diff --git a/MQTTSNGateway/src/linux/Threading.cpp b/MQTTSNGateway/src/linux/Threading.cpp index 7c452e7..db26fbc 100644 --- a/MQTTSNGateway/src/linux/Threading.cpp +++ b/MQTTSNGateway/src/linux/Threading.cpp @@ -79,23 +79,23 @@ Mutex::Mutex(const char* fileName) if ((_shmid = shmget(key, sizeof(pthread_mutex_t), IPC_CREAT | 0666)) < 0) { - throw Exception( -1, "Mutex can't create a shared memory."); + throw Exception("Mutex can't create a shared memory.", -1); } _pmutex = (pthread_mutex_t*) shmat(_shmid, NULL, 0); if (_pmutex == (void*) -1) { - throw Exception( -1, "Mutex can't attach shared memory."); + throw Exception("Mutex can't attach shared memory.", -1); } pthread_mutexattr_init(&attr); if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) != 0) { - throw Exception( -1, "Mutex can't set the process-shared flag"); + throw Exception("Mutex can't set the process-shared flag", -1); } if (pthread_mutex_init(_pmutex, &attr) != 0) { - throw Exception( -1, "Mutex can't initialize."); + throw Exception("Mutex can't initialize.", -1); } } @@ -121,44 +121,37 @@ Mutex::~Mutex(void) void Mutex::lock(void) { + int rc = 0; if (_pmutex) { - pthread_mutex_lock(_pmutex); + rc = pthread_mutex_lock(_pmutex); } else { - try - { - if (pthread_mutex_lock(&_mutex)) - { - throw; - } - } catch (char* errmsg) - { - throw Exception( -1, "The same thread can't aquire a mutex twice."); - } + rc = pthread_mutex_lock(&_mutex); + } + + if (rc) + { + throw Exception("Mutex lock error", errno); } } void Mutex::unlock(void) { - + int rc = 0; if (_pmutex) { - pthread_mutex_unlock(_pmutex); + rc = pthread_mutex_unlock(_pmutex); } else { - try - { - if (pthread_mutex_unlock(&_mutex)) - { - throw; - } - } catch (char* errmsg) - { - throw Exception( -1, "Mutex can't unlock."); - } + rc = pthread_mutex_unlock(&_mutex); + } + + if (rc) + { + throw Exception("Mutex lock error", errno); } } @@ -225,12 +218,12 @@ NamedSemaphore::NamedSemaphore(const char* name, unsigned int val) _psem = sem_open(name, O_CREAT, 0666, val); if (_psem == SEM_FAILED) { - throw Exception( -1, "Semaphore can't be created."); + throw Exception("Semaphore can't be created.", -1); } _name = strdup(name); if (_name == NULL) { - throw Exception( -1, "Semaphore can't allocate memories."); + throw Exception("Semaphore can't allocate memories.", -1); } } @@ -263,11 +256,6 @@ void NamedSemaphore::timedwait(uint16_t millsec) /*========================================= Class RingBuffer =========================================*/ -RingBuffer::RingBuffer() -{ - RingBuffer(MQTTSNGW_KEY_DIRECTORY); -} - RingBuffer::RingBuffer(const char* keyDirectory) { int fp = 0; @@ -303,7 +291,7 @@ RingBuffer::RingBuffer(const char* keyDirectory) } else { - throw Exception(-1, "RingBuffer can't attach shared memory."); + throw Exception("RingBuffer can't attach shared memory.", -1); } } else if ((_shmid = shmget(key, PROCESS_LOG_BUFFER_SIZE, IPC_CREAT | 0666)) != -1) @@ -318,12 +306,12 @@ RingBuffer::RingBuffer(const char* keyDirectory) } else { - throw Exception(-1, "RingBuffer can't create a shared memory."); + throw Exception("RingBuffer can't create a shared memory.", -1); } } else { - throw Exception(-1, "RingBuffer can't create a shared memory."); + throw Exception( "RingBuffer can't create a shared memory.", -1); } _pmx = new Mutex(MQTTSNGW_RB_MUTEX_KEY); @@ -495,7 +483,7 @@ void RingBuffer::reset() } else { - throw Exception(-1, "RingBuffer can't reset. need to clear shared memory."); + throw Exception("RingBuffer can't reset. need to clear shared memory.", -1); } _pmx->unlock(); } @@ -506,6 +494,7 @@ void RingBuffer::reset() Thread::Thread() { _threadID = 0; + _taskName = nullptr; } Thread::~Thread() @@ -535,15 +524,10 @@ bool Thread::equals(pthread_t *t1, pthread_t *t2) int Thread::start(void) { - Runnable* runnable = this; + Runnable* runnable = this; return pthread_create(&_threadID, 0, _run, runnable); } -void Thread::stopProcess(void) -{ - theMultiTaskProcess->threadStopped(); -} - void Thread::stop(void) { if ( _threadID ) @@ -552,3 +536,13 @@ void Thread::stop(void) _threadID = 0; } } + +void Thread::setTaskName(const char* name) +{ + _taskName = name; +} + +const char* Thread::getTaskName(void) +{ + return _taskName; +} diff --git a/MQTTSNGateway/src/linux/Threading.h b/MQTTSNGateway/src/linux/Threading.h index 795ee5a..677e7ee 100644 --- a/MQTTSNGateway/src/linux/Threading.h +++ b/MQTTSNGateway/src/linux/Threading.h @@ -31,6 +31,9 @@ namespace MQTTSNGW #define MQTTSNGW_RB_MUTEX_KEY "rbmutex.key" #define MQTTSNGW_RB_SEMAPHOR_NAME "/rbsemaphor" +#define RED_HDR "\033[0m\033[0;31m" +#define CLR_HDR "\033[0m\033[0;37m" + /*===================================== Class Mutex ====================================*/ @@ -92,8 +95,7 @@ private: class RingBuffer { public: - RingBuffer(); - RingBuffer(const char* keyDirctory); + RingBuffer(const char* keyDirectory = MQTTSNGW_KEY_DIRECTORY); ~RingBuffer(); void put(char* buffer); int get(char* buffer, int bufferLength); @@ -124,15 +126,17 @@ public: #define MAGIC_WORD_FOR_THREAD \ public: void EXECRUN() \ { \ - try \ - { \ - run(); \ - stopProcess(); \ - } \ - catch(...) \ - { \ - throw; \ - } \ + try \ + { \ + run(); \ + } \ + catch ( Exception &ex ) \ + { \ + ex.writeMessage(); \ + WRITELOG("%s%s caught an exception and stopped.%s\n", RED_HDR, getTaskName(), CLR_HDR); \ + theMultiTaskProcess->abort(); \ + } \ + theMultiTaskProcess->threadStopped(); \ } /*===================================== @@ -146,12 +150,15 @@ public: static pthread_t getID(); static bool equals(pthread_t*, pthread_t*); virtual void initialize(int argc, char** argv); - void stopProcess(void); void waitStop(void); void stop(void); + const char* getTaskName(void); + void setTaskName(const char* name); + void abort(int threadNo); private: static void* _run(void*); pthread_t _threadID; + const char* _taskName; }; } diff --git a/MQTTSNGateway/src/linux/dtls/SensorNetwork.cpp b/MQTTSNGateway/src/linux/dtls/SensorNetwork.cpp new file mode 100644 index 0000000..3f2dcf3 --- /dev/null +++ b/MQTTSNGateway/src/linux/dtls/SensorNetwork.cpp @@ -0,0 +1,1386 @@ +/************************************************************************************** + * 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 + **************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SensorNetwork.h" +#include "MQTTSNGWProcess.h" +#include "MQTTSNGateway.h" + +using namespace std; +using namespace MQTTSNGW; + +extern Gateway *theGateway; + +#define COOKIE_SECRET_LENGTH 16 +int cookie_initialized = 0; +unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; + +/*=========================================== + Class SensorNetAddreess + + These 4 methods are minimum requirements for the SensorNetAddress class. + isMatch(SensorNetAddress* ) + operator =(SensorNetAddress& ) + setAddress(string* ) + sprint(char* ) + + UDPPort class requires these 3 methods. + getIpAddress(void) + getPortNo(void) + setAddress(uint32_t IpAddr, uint16_t port) + + ============================================*/ +SensorNetAddress::SensorNetAddress() +{ + _portNo = 0; + _pfdsIndex = 0; + memset(&_ipAddr, 0, sizeof(_ipAddr)); +} + +SensorNetAddress::~SensorNetAddress() +{ +} + +void SensorNetAddress::setFamily(int type) +{ + _ipAddr.af = type; +} + +int SensorNetAddress::getFamily(void) +{ + return _ipAddr.af; +} + +ipAddr_t* SensorNetAddress::getIpAddress(void) +{ + return &_ipAddr; +} + +in_port_t SensorNetAddress::getPort(void) +{ + return _portNo; +} + +void SensorNetAddress::setAddress(ipAddr_t *IpAddr, uint16_t port) +{ + + _ipAddr.addr.ad6 = IpAddr->addr.ad6; + _portNo = htons(port); + + _ipAddr.af = IpAddr->af; +} + +void SensorNetAddress::setPort(uint16_t port) +{ + _portNo = htons(port); +} + +/** + * Set Address data to SensorNetAddress + * + * @param *ip_port is "IP_Address:PortNo" format string + * @return success = 0, Invalid format = -1 + * + * This function is used in ClientList::authorize(const char* fileName) + * e.g. + * Authorized clients are defined by fileName = "clients.conf" + * + * Client02,172.16.1.7:12002 + * Client03,172.16.1.8:13003 + * Client01,172.16.1.6:12001 + * or + * Client01,[xxxx::xxxx]:11001 + * Client02,[xxxx::xxxx]:12001 + * + * This definition is necessary when using TLS/DTLS connection. + * Gateway rejects clients are not in the list for security reasons. + * + */ +int SensorNetAddress::setAddress(string *ipAddrPort) +{ + string port(""); + string ip(""); + size_t pos; + int portNo = 0; + _portNo = 0; + memset(&_ipAddr.addr, 0, sizeof(_ipAddr.addr.ad6)); + + if (*ipAddrPort->c_str() == '[') + { + // AF_INET6 + pos = ipAddrPort->find_last_of("]:"); + if (pos != string::npos) + { + ip = ipAddrPort->substr(1, pos - 2); + port = ipAddrPort->substr(pos + 1); + } + } + else + { + // AF_INET + pos = ipAddrPort->find_last_of(':'); + if (pos != string::npos) + { + ip = ipAddrPort->substr(0, pos); + port = ipAddrPort->substr(pos + 1); + } + } + + if (port == "" || ip == "") + { + return -1; + } + + if (setIpAddress(&ip) == 0) + { + if ((portNo = atoi(port.c_str())) != 0) + { + _portNo = htons(portNo); + return 0; + } + } + return -1; +} + +int SensorNetAddress::setIpAddress(string *ipAddress) +{ + if (inet_pton(AF_INET, (const char*) ipAddress->c_str(), (void*) &_ipAddr.addr) == 1) + { + _ipAddr.af = AF_INET; + } + else if (inet_pton(AF_INET6, (const char*) ipAddress->c_str(), (void*) &_ipAddr.addr) == 1) + { + _ipAddr.af = AF_INET6; + } + else + { + _ipAddr.af = 0; + return -1; + } + return 0; +} + +bool SensorNetAddress::isMatch(SensorNetAddress *addr) +{ + if (this->_portNo != addr->_portNo || this->_ipAddr.af != addr->_ipAddr.af) + { + return false; + } + + if (this->_ipAddr.af == AF_INET + && memcmp((const void*) &this->_ipAddr.addr.ad4, (const void*) &addr->_ipAddr.addr.ad4, sizeof(struct in_addr)) + == 0) + { + return true; + } + + if (this->_ipAddr.af == AF_INET6 + && memcmp((const void*) &this->_ipAddr.addr.ad6, (const void*) &addr->_ipAddr.addr.ad6, sizeof(struct in6_addr)) + == 0) + { + return true; + } + return false; +} + +SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress &addr) +{ + this->_portNo = addr._portNo; + memcpy((void*) &this->_ipAddr, (const void*) &addr._ipAddr, sizeof(_ipAddr)); + this->_pfdsIndex = addr._pfdsIndex; + return *this; +} + +void SensorNetAddress::setSockaddr4(sockaddr_in *sockaddr) +{ + _ipAddr.af = sockaddr->sin_family; + _portNo = sockaddr->sin_port; + memcpy((void*) &_ipAddr.addr.ad4, (void*) &sockaddr->sin_addr, sizeof(_ipAddr.addr.ad4)); +} + +void SensorNetAddress::setSockaddr6(sockaddr_in6 *sockaddr) +{ + _ipAddr.af = sockaddr->sin6_family; + _portNo = sockaddr->sin6_port; + memcpy((void*) &_ipAddr.addr.ad6, (void*) &sockaddr->sin6_addr, sizeof(_ipAddr.addr.ad6)); +} + +void SensorNetAddress::cpyAddr4(sockaddr_in *sockaddr) +{ + sockaddr->sin_family = _ipAddr.af; + memcpy((void*) &sockaddr->sin_addr, (void*) &_ipAddr.addr.ad4, sizeof(_ipAddr.addr.ad4)); + sockaddr->sin_port = _portNo; +} + +void SensorNetAddress::cpyAddr6(sockaddr_in6 *sockaddr) +{ + sockaddr->sin6_family = _ipAddr.af; + sockaddr->sin6_port = _portNo; + memcpy((void*) &sockaddr->sin6_addr, (void*) &_ipAddr.addr.ad6, sizeof(_ipAddr.addr.ad6)); +} + +void SensorNetAddress::cpyAddr(SensorNetAddress *addr) +{ + addr->_portNo = _portNo; + memcpy((void*) &addr->_ipAddr, (const void*) &_ipAddr, sizeof(_ipAddr)); + addr->_pfdsIndex = _pfdsIndex; +} + +char* SensorNetAddress::sprint(char *buf) +{ + char senderstr[INET6_ADDRSTRLEN]; + char *ptr = senderstr; + + if (_ipAddr.af == AF_INET) + { + ptr = inet_ntoa(_ipAddr.addr.ad4); + sprintf(buf, "%s:", ptr); + } + else if (_ipAddr.af == AF_INET6) + { + inet_ntop(AF_INET6, (const void*) &_ipAddr.addr.ad6, ptr, INET6_ADDRSTRLEN); + sprintf(buf, "[%s]:", ptr); + } + else + { + *buf = 0; + return buf; + } + sprintf(buf + strlen(buf), "%d", ntohs(_portNo)); + sprintf(buf + strlen(buf), " index=%d", _pfdsIndex); + return buf; +} + +void SensorNetAddress::setIndex(int index) +{ + _pfdsIndex = index; +} +int SensorNetAddress::getIndex(void) +{ + return _pfdsIndex; +} + +void SensorNetAddress::clear(void) +{ + memset(&_ipAddr, 0, sizeof(_ipAddr)); + _portNo = 0; +} + +Connections::Connections() +{ + _pollfds = nullptr; + _ssls = nullptr; + _maxfds = 0; + _numfds = 2; +} + +Connections::~Connections() +{ + if (_ssls) + { + for (int i = 0; i < _numfds; i++) + { + if (_ssls[i] > 0) + { + SSL_shutdown(_ssls[i]); + SSL_free(_ssls[i]); + } + } + free(_ssls); + } + + if (_pollfds) + { + for (int i = 0; i < _numfds; i++) + { + if (_pollfds[i].fd > 0) + { + ::close(_pollfds[i].fd); + } + } + free(_pollfds); + } +} + +void Connections::initialize(int maxClient) +{ + _maxfds = maxClient + POLL_SSL; + if ((_pollfds = (pollfd*) calloc(_maxfds, sizeof(pollfd))) == NULL) + { + throw EXCEPTION("Can't allocate pollfd.", 0); + } + if ((_ssls = (SSL**) calloc(_maxfds, sizeof(SSL*))) == NULL) + { + throw EXCEPTION("Can't allocate ssls.", 0); + } +} + +void Connections::closeSSL(int index) +{ + index += POLL_SSL; + SSL_shutdown(_ssls[index]); + SSL_free(_ssls[index]); + _ssls[index] = (SSL*) -1; +} + +int Connections::getEventUnicast(void) +{ + return _pollfds[POLL_UCAST].revents; +} + +int Connections::getEventMulticast(void) +{ + return _pollfds[POLL_MCAST].revents; +} + +int Connections::getEventClient(int index) +{ + return _pollfds[index + POLL_SSL].revents; +} + +int Connections::getSockMulticast(void) +{ + return _pollfds[POLL_MCAST].fd; +} + +void Connections::setSockMulticast(int sock) +{ + _mutex.lock(); + _pollfds[POLL_MCAST].fd = sock; + _pollfds[POLL_MCAST].events = POLLIN; + _mutex.unlock(); +} + +void Connections::setSockUnicast(int sock) +{ + _mutex.lock(); + _pollfds[POLL_UCAST].fd = sock; + _pollfds[POLL_UCAST].events = POLLIN; + _mutex.unlock(); +} + +int Connections::getSockUnicast(void) +{ + return _pollfds[POLL_UCAST].fd; +} + +int Connections::getSockClient(int index) +{ + return _pollfds[index + POLL_SSL].fd; +} + +void Connections::close(int index) +{ + D_NWSTACK("Connection %d closed\n", index); + int idx = index + POLL_SSL; + _mutex.lock(); + int sock = _pollfds[idx].fd; + SSL *ssl = _ssls[idx]; + + for (; idx < _numfds; idx++) + { + _ssls[idx] = _ssls[idx + 1]; + _pollfds[idx] = _pollfds[idx + 1]; + + if (_ssls[idx + 1] == 0) + { + break; + } + } + + if (ssl > 0) + { + _numfds--; + SSL_shutdown(ssl); + SSL_free(ssl); + } + if (sock > 0) + { + ::close(sock); + } + _mutex.unlock(); +} + +int Connections::poll(int timeout) +{ + return ::poll(_pollfds, _numfds, timeout); +} + +int Connections::addClientSSL(SSL *ssl, int sock) +{ + _mutex.lock(); + _pollfds[_numfds].fd = sock; + _pollfds[_numfds].events = POLLIN; + _ssls[_numfds] = ssl; + int rc = _numfds - POLL_SSL; + _numfds++; + _mutex.unlock(); + D_NWSTACK("Add client connection index=%d, ssl=%ld, sock=%d\n", rc, (long int )ssl, sock); + return rc; +} + +int Connections::getNumOfConnections(void) +{ + return _numfds; +} + +int Connections::getNumOfClients(void) +{ + return _numfds - POLL_SSL > 0 ? _numfds - POLL_SSL : 0; +} + +SSL* Connections::getClientSSL(int index) +{ + return _ssls[index + POLL_SSL]; +} + +void Connections::print(void) +{ + for (int i = 0; i < _numfds; i++) + { + printf("index=%d fd=%d ssl=%ld \n", i, _pollfds[i].fd, (long int) _ssls[i]); + } +} + +/*================================================================ + Class SensorNetwork + + getDescpription( ) is used by Gateway::initialize( ) + initialize( ) is used by Gateway::initialize( ) + getSenderAddress( ) is used by ClientRecvTask::run( ) + broadcast( ) is used by MQTTSNPacket::broadcast( ) + unicast( ) is used by MQTTSNPacket::unicast( ) + read( ) is used by MQTTSNPacket::recv( ) + + ================================================================*/ +#define DTLS_CLIENTHELLO 22 +#define DTLS_APPL 23 +#define DTLS_OTHERS 100 + +#define DTLS_TIMEOUT 4 + +/* Certificate verification. Returns 1 if trusted, else 0 */ +int verify_cert(int ok, X509_STORE_CTX *ctx); + +/* Generate cookie. Returns 1 on success, 0 otherwise */ +int generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len); + +/* Verify cookie. Returns 1 on success, 0 otherwise */ +int verify_cookie(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len); + +SensorNetwork::SensorNetwork() +{ + _conns = new Connections(); + _dtlsctx = nullptr; + _af = 0; +} + +SensorNetwork::~SensorNetwork() +{ + if (_conns != nullptr) + { + delete _conns; + } +} + +int SensorNetwork::unicast(const uint8_t *payload, uint16_t payloadLength, SensorNetAddress *sendToAddr) +{ +#ifdef DEBUG_NW + char buf[256]; + _conns->print(); + sendToAddr->sprint(buf); + D_NWSTACK("sendto %s\n", buf); +#endif + + _mutex.lock(); + SSL *ssl = _conns->getClientSSL(sendToAddr->getIndex()); + int len = SSL_write(ssl, payload, payloadLength); + int rc = SSL_get_error(ssl, len); + if (rc < 0) + { + D_NWSTACK("error %d in SensorNetwork::unicast\n", rc); + len = -1; + } + _mutex.unlock(); + return len; +} + +int SensorNetwork::broadcast(const uint8_t *payload, uint16_t payloadLength) +{ + _mutex.lock(); + + int status; +#ifndef DTLS6 + sockaddr_in dest; + _multicastAddr.cpyAddr4(&dest); + + status = ::sendto(_conns->getSockUnicast(), payload, payloadLength, 0, (const sockaddr*) &dest, sizeof(dest)); + if (status < 0) + { + WRITELOG("AF_INET errno = %d in UDP4_6Port::sendto\n", errno); + } + + D_NWSTACK("sendto %s:%u length = %d\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), status); + +#else + sockaddr_in6 dest; + _multicastAddr.cpyAddr6(&dest); + + status = ::sendto(_conns->getSockUnicast(), payload, payloadLength, 0, (const sockaddr*) &dest, sizeof(dest)); + if (status < 0) + { + WRITELOG("AF_INET6 errno = %d in SensorNetwork::broadcast\n", errno); + } + +#ifdef DEBUG_NW + char buff[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &dest.sin6_addr, buff, INET6_ADDRSTRLEN); + D_NWSTACK("sendto [%s]:%u length = %d\n", buff, ntohs(dest.sin6_port), status); +#endif +#endif + _mutex.unlock(); + return status; +} + +int SensorNetwork::read(uint8_t *buf, uint16_t bufLen) +{ + int optval; + int clientIndex = -1; + int sockListen = 0; + char errmsg[256]; + union + { + struct sockaddr_in s4; + struct sockaddr_in6 s6; + } client_addr; + + SensorNetAddress client; + client.clear(); + client.setFamily(_af); + + // Check POLL_IN + int cnt = _conns->poll(6000); // Timeout 6secs + if (cnt == 0) + { + // Timeout + return cnt; + } + else if (cnt < 0) + { + return -1; + } + + _mutex.lock(); + + // Check Unicast Port + + if (_conns->getEventUnicast() & POLLIN) + { + D_NWSTACK("RECV Unicast SSL_connect\n"); + + // SSL connection request from a client +#ifdef DEBUG_NW + int dtls = getUnicastClient(&client); + D_NWSTACK("Packet type = %d\n", dtls); +#else + getUnicastClient(&client); +#endif + sockListen = _conns->getSockUnicast(); + + // Listen Connection + SSL *ssl = SSL_new(_dtlsctx); + BIO *bio = BIO_new_dgram(sockListen, BIO_NOCLOSE); + SSL_set_bio(ssl, bio, bio); + + SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); + + int rc = 0; + + // SSL Listen + D_NWSTACK("DTLSv1_listen\n"); + + rc = DTLSv1_listen(ssl, (BIO_ADDR*) &client_addr); + + if (rc <= 0) + { + ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); + WRITELOG("Listen rc=%d %s\n", rc, errmsg); + _mutex.unlock(); + return 0; + } + + // Handle client connection +#ifndef DTLS6 + // DTLS over IPv4 + int client_fd = socket(AF_INET, SOCK_DGRAM, 0); + optval = 1; + setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &optval, sizeof(optval)); + // Bind to Dtls PortNo + bind(client_fd, (sockaddr*) &_serverAddr4, sizeof(sockaddr_in)); + connect(client_fd, (sockaddr*) &client_addr, sizeof(sockaddr_in)); + client.setSockaddr4((sockaddr_in*) &client_addr.s4); +#else + // DTLS over IPv6 + int client_fd = socket(AF_INET6, SOCK_DGRAM, 0); + optval = 1; + setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &optval, sizeof(optval)); + // Bind to Dtls PortNo + bind(client_fd, (sockaddr*) &_serverAddr6, sizeof(sockaddr_in6)); + connect(client_fd, (sockaddr*) &client_addr, sizeof(sockaddr_in6)); + client.setSockaddr6((sockaddr_in6*) &client_addr.s6); +#endif + + BIO *cbio = SSL_get_rbio(ssl); + BIO_set_fd(cbio, client_fd, BIO_NOCLOSE); + BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &client_addr); + + // set timeout + timeval timeout; + timeout.tv_sec = DTLS_TIMEOUT; + timeout.tv_usec = 0; + BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); + + // Finish handshake + int ret = SSL_accept(ssl); + if (ret <= 0) + { + ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); + WRITELOG("SSL_accept %s\n", errmsg); + SSL_shutdown(ssl); + SSL_free(ssl); + ::close(client_fd); + } + else + { + // add ssl & socket to Connections instance + int index = _conns->addClientSSL(ssl, client_fd); + + // save SensorNetworkAddress of Client + client.setIndex(index); + client.cpyAddr(&_senderAddr); + +#ifdef DEBUG_NW + char clientaddrBuf[128]; + _senderAddr.sprint(clientaddrBuf); + D_NWSTACK("DTLS accepted client is %s index=%d client_fd=%d\n", clientaddrBuf, _senderAddr.getIndex(), + client_fd); +#endif + } + _mutex.unlock(); + } + + // check Multicast + else if (_conns->getEventMulticast() & POLLIN) + { + _mutex.unlock(); + return multicastRecv(buf, bufLen); + } + else + { + // Check SSL packet from clients + size_t recvlen = 0; + SSL *ssl = 0; + int numfds = _conns->getNumOfConnections(); + + for (int i = 0; i < numfds - POLL_SSL; i++) + { + if (_conns->getEventClient(i) == POLLIN) + { + D_NWSTACK("SSL Packet RECV\n"); + int dtls = getSendClient(i, &client); + + if (dtls > 0) + { + if (dtls == DTLS_CLIENTHELLO) + { + // Received packet is ClientHello +#ifdef DEBUG_NW + char clientaddrBuf[128]; + client.sprint(clientaddrBuf); + D_NWSTACK("Client %s A packet is ClientHello. Client reconnected. Close connection. SSL_connection will timeout.\n", clientaddrBuf); +#endif + clientIndex = i; + _mutex.unlock(); + _conns->close(clientIndex); + return 0; + } + + // The packet is a MQTT-SN message + ssl = _conns->getClientSSL(i); + int len = SSL_read_ex(ssl, (void*) buf, (size_t) bufLen, &recvlen); + if (SSL_get_error(ssl, len) < 0) + { + D_NWSTACK("SSL RECV Error\n"); + _conns->close(i); + recvlen = -1; + } + else + { + client.cpyAddr(&_senderAddr); + _senderAddr.setIndex(i); + +#ifdef DEBUG_NW + char clientaddrBuf[128]; + _senderAddr.sprint(clientaddrBuf); + D_NWSTACK("Client %s ssl=%ld Received. idx=%d\n", clientaddrBuf, (long int )ssl, i); +#endif + } + _mutex.unlock(); + return recvlen; + } + } + } + } + return 0; +} + +void SensorNetwork::initialize(void) +{ + char param[MQTTSNGW_PARAM_MAX]; + char errmsg[256]; + uint16_t multicastPortNo = 0; + uint16_t unicastPortNo = 0; + + SensorNetAddress add; + sockaddr_in6 soadd; + add.setSockaddr6(&soadd); + +#ifndef DTLS6 + string ip; + uint32_t ttl = 1; + + if (theProcess->getParam("MulticastIP", param) == 0) + { + ip = param; + _description += "IPv4 DTLS Multicast "; + _description += param; + } + if (theProcess->getParam("MulticastPortNo", param) == 0) + { + multicastPortNo = atoi(param); + _description += ":"; + _description += param; + } + if (theProcess->getParam("GatewayPortNo", param) == 0) + { + unicastPortNo = atoi(param); + _description += ", Gateway PortNo:"; + _description += param; + } + if (theProcess->getParam("MulticastTTL", param) == 0) + { + ttl = atoi(param); + _description += ", TTL:"; + _description += param; + } +#else + string ip6; + uint32_t hops = 1; + string interface; + + if (theProcess->getParam("MulticastIPv6", param) == 0) + { + ip6 = param; + _description += "IPv6 DTLS Multicast ["; + _description += param; + } + if (theProcess->getParam("MulticastIPv6PortNo", param) == 0) + { + multicastPortNo = atoi(param); + _description += "]:"; + _description += param; + } + if (theProcess->getParam("GatewayIPv6PortNo", param) == 0) + { + unicastPortNo = atoi(param); + _description += ", Gateway PortNo:"; + _description += param; + } + if (theProcess->getParam("MulticastIPv6If", param) == 0) + { + interface = param; + _description += ", Interface:"; + _description += param; + } + if (theProcess->getParam("MulticastHops", param) == 0) + { + hops = atoi(param); + _description += ", Hops:"; + _description += param; + } +#endif + + if (theGateway->getGWParams()->gwCertskey == nullptr) + { + throw EXCEPTION("DtlsCertsKey is required.", 0); + } + if (theGateway->getGWParams()->gwPrivatekey == nullptr) + { + throw EXCEPTION("DtlsPrivateKey is required.", 0); + } + + /* allocate Connections */ + _conns->initialize(theGateway->getGWParams()->maxClients); + + SSL_load_error_strings(); + SSL_library_init(); + + _dtlsctx = SSL_CTX_new(DTLS_server_method()); + if (_dtlsctx == 0) + { + ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); + D_NWSTACK("SSL_CTX_new() %s\n", errmsg); + throw EXCEPTION("SSL_CTX_new()", 0); + } + SSL_CTX_set_min_proto_version(_dtlsctx, DTLS1_VERSION); + + if (SSL_CTX_use_certificate_file(_dtlsctx, theGateway->getGWParams()->gwCertskey, SSL_FILETYPE_PEM) != 1) + { + ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); + D_NWSTACK("SSL_CTX_use_certificate_file() %s %s\n", theGateway->getGWParams()->gwCertskey, errmsg); + throw EXCEPTION("SSL_CTX_use_certificate_file()", 0); + } + if (SSL_CTX_use_PrivateKey_file(_dtlsctx, theGateway->getGWParams()->gwPrivatekey, SSL_FILETYPE_PEM) != 1) + { + ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); + D_NWSTACK("SSL_CTX_use_PrivateKey_file() %s %s\n", theGateway->getGWParams()->gwPrivatekey, errmsg); + throw EXCEPTION("SSL_CTX_use_PrivateKey_file()", 0); + } + + /* Client certification and cookie are not required */ + SSL_CTX_set_verify(_dtlsctx, SSL_VERIFY_NONE, NULL); + SSL_CTX_set_cookie_generate_cb(_dtlsctx, generate_cookie); + SSL_CTX_set_cookie_verify_cb(_dtlsctx, verify_cookie); + + /* Prepare UDP and UDP6 sockets for Multicasting and unicasting */ +#ifndef DTLS6 + if (openV4(&ip, multicastPortNo, unicastPortNo, ttl) < 0) + { + throw EXCEPTION("Can't open a UDP4", errno); + } +#else + if (openV6(&ip6, &interface, multicastPortNo, unicastPortNo, hops) < 0) + { + throw EXCEPTION("Can't open a UDP6", errno); + } +#endif +} + +const char* SensorNetwork::getDescription(void) +{ + return _description.c_str(); +} + +SensorNetAddress* SensorNetwork::getSenderAddress(void) +{ + return &_senderAddr; +} + +int SensorNetwork::openV4(string *ipAddress, uint16_t multiPortNo, uint16_t uniPortNo, uint32_t ttl) +{ + int optval = 0; + int rc = -1; + int sock = 0; + errno = 0; + _af = AF_INET; + + if (uniPortNo == 0 || multiPortNo == 0) + { + D_NWSTACK("error portNo undefined in UDP4_6Port::openV4\n"); + return rc; + } + + /*------ Create unicast socket --------*/ + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) + { + D_NWSTACK("can't create unicast socket in UDP4_6Port::openV4 error %d %s\n", errno, strerror(errno)); + return -1; + } + + optval = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + _serverAddr4.sin_family = AF_INET; + _serverAddr4.sin_port = htons(uniPortNo); + _serverAddr4.sin_addr.s_addr = INADDR_ANY; + + if (::bind(sock, (sockaddr*) &_serverAddr4, sizeof(_serverAddr4)) < 0) + { + D_NWSTACK("can't bind unicast socket in UDP4_6Port::openV4 error %d %s\n", errno, strerror(errno)); + return -1; + } + _conns->setSockUnicast(sock); + + /*------ Create Multicast socket --------*/ + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) + { + D_NWSTACK("can't create multicast socket in UDP4_6Port::openV4 error %d %s\n", errno, strerror(errno)); + return -1; + } + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + sockaddr_in addrm; + addrm.sin_family = AF_INET; + addrm.sin_port = htons(multiPortNo); + addrm.sin_addr.s_addr = INADDR_ANY; + + if (::bind(sock, (sockaddr*) &addrm, sizeof(addrm)) < 0) + { + D_NWSTACK("can't bind multicast socket in UDP4_6Port::openV4 error %d %s\n", errno, strerror(errno)); + return -1; + } + + ip_mreq mreq; + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_interface.s_addr = INADDR_ANY; + mreq.imr_multiaddr.s_addr = inet_addr(ipAddress->c_str()); + + if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + { + D_NWSTACK("Multicast IP_ADD_MEMBERSHIP in UDP4_6Port::openV4 error %d %s\n", errno, strerror(errno)); + return -1; + } + if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) + { + D_NWSTACK("Multicast IP_MULTICAST_TTL in UDP4_6Port::openV4 error %d %s\n", errno, strerror(errno)); + return -1; + } + +#ifdef DEBUG_NW + optval = 1; +#else + optval = 0; +#endif + + if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char*) &optval, sizeof(optval)) < 0) + { + D_NWSTACK("error %d IP_MULTICAST_LOOP in UDP4_6Port::openV4 %s\n", errno, strerror(errno)); + return -1; + } + _multicastAddr.setFamily(AF_INET); + _multicastAddr.setIpAddress(ipAddress); + _multicastAddr.setPort(multiPortNo); + _conns->setSockMulticast(sock); + return 0; +} + +int SensorNetwork::openV6(string *ipAddress, string *interface, uint16_t multiPortNo, uint16_t uniPortNo, uint32_t hops) +{ + int optval = 0; + int sock = 0; + uint32_t ifindex = 0; + + errno = 0; + + if (uniPortNo == 0 || multiPortNo == 0) + { + WRITELOG("error portNo undefined in SensorNetwork::openV6\n"); + return -1; + } + + _multicastAddr.setPort(multiPortNo); + _unicastAddr.setPort(uniPortNo); + + if (_multicastAddr.setIpAddress(ipAddress) < 0) + { + D_NWSTACK("Incorrect IPV6 address in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + + /*------ Create unicast socket --------*/ + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) + { + D_NWSTACK("can't create unicast socket in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + _conns->setSockUnicast(sock); + + optval = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + optval = 1; + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) < 0) + { + D_NWSTACK("IPV6_ONLY in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + + memset(&_serverAddr6, 0, sizeof(_serverAddr6)); + _serverAddr6.sin6_family = AF_INET6; + _serverAddr6.sin6_port = htons(uniPortNo); + _serverAddr6.sin6_addr = in6addr_any; + + if (::bind(sock, (sockaddr*) &_serverAddr6, sizeof(_serverAddr6)) < 0) + { + D_NWSTACK("can't bind unicast socket in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + + if (interface->size() > 0) + { + ifindex = if_nametoindex(interface->c_str()); +#ifdef __APPLE__ + setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &ifindex, interface->size()); +#else + setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, interface->c_str(), interface->size()); +#endif + } + + // Create Multicast socket + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) + { + D_NWSTACK("can't create multicast socket in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + + _conns->setSockMulticast(sock); + + optval = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) + { + D_NWSTACK("IPV6_MULTICAST_IF in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &optval, sizeof(optval)) < 0) + { + D_NWSTACK("IPV6_ONLY in SensorNetworkSensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + + sockaddr_in6 addrm; + addrm.sin6_family = AF_INET6; + addrm.sin6_port = htons(multiPortNo); + addrm.sin6_addr = in6addr_any; + + if (::bind(sock, (sockaddr*) &addrm, sizeof(addrm)) < 0) + { + D_NWSTACK("can't bind multicast socket in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + + struct ipv6_mreq mreq; + mreq.ipv6mr_multiaddr = _multicastAddr.getIpAddress()->addr.ad6; + mreq.ipv6mr_interface = ifindex; + + if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0) + { + D_NWSTACK("Multicast IPV6_JOIN_GROUP in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + +#ifdef DEBUG_NW + optval = 1; +#else + optval = 0; +#endif + + if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0) + { + D_NWSTACK("IPV6_MULTICAST_LOOP in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + + if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) + { + D_NWSTACK("Multicast IPV6_MULTICAST_HOPS in SensorNetwork::openV6 error %s\n", strerror(errno)); + return -1; + } + _multicastAddr.setFamily(AF_INET6); + _multicastAddr.setIpAddress(ipAddress); + _multicastAddr.setPort(multiPortNo); + return 0; +} + +int SensorNetwork::multicastRecv(uint8_t *buf, uint16_t len) +{ + int rc = -1; + +#ifndef DTLS6 + sockaddr_in sender; + socklen_t addrlen = sizeof(sender); + memset(&sender, 0, addrlen); + + rc = ::recvfrom(_conns->getSockMulticast(), buf, len, 0, (sockaddr*) &sender, &addrlen); + if (rc < 0 && errno != EAGAIN) + { + D_NWSTACK("errno %s IPv4 in SensorNetwork::multicastRecv\n", strerror(errno)); + return -1; + } + + D_NWSTACK("IPv4 multicast recved from %s:%d length = %d\n", inet_ntoa(sender.sin_addr), ntohs(sender.sin_port), rc); + +#else + sockaddr_in6 sender; + socklen_t addrlen = sizeof(sender); + memset(&sender, 0, addrlen); + + rc = ::recvfrom(_conns->getSockMulticast(), buf, len, 0, (sockaddr*) &sender, &addrlen); + if (rc < 0 && errno != EAGAIN) + { + D_NWSTACK("errno = %d IPv6 in SensorNetwork::multicastRecv\n", errno); + return -1; + } +#ifdef DEBUG_NW + char buff[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &sender.sin6_addr, buff, INET6_ADDRSTRLEN); + D_NWSTACK("IPv6 multicast recved from %s:%u length = %d\n", buff, ntohs(sender.sin6_port), rc); +#endif +#endif + + return rc; +} + +int SensorNetwork::getUnicastClient(SensorNetAddress *addr) +{ + return getSenderAddress(_conns->getSockUnicast(), addr); +} + +int SensorNetwork::getSendClient(int index, SensorNetAddress *addr) +{ + return getSenderAddress(_conns->getSockClient(index), addr); +} + +int SensorNetwork::getSenderAddress(int sock, SensorNetAddress *addr) +{ + int len = -1; + +#ifndef DTLS6 + // AF_INET + sockaddr_in sender4 = { 0 }; + socklen_t addrlen4 = sizeof(sender4); + char buf[16]; + int rc = DTLS_OTHERS; + + len = ::recvfrom(sock, buf, 15, MSG_PEEK, (sockaddr*) &sender4, &addrlen4); + + if (len < 0 && errno != EAGAIN) + { + D_NWSTACK("errno = %d in SensorNetwork::getSenderAddress\n", errno); + return -1; + } + + addr->setSockaddr4(&sender4); + + D_NWSTACK("SensorNetwork::getSenderAddress recved from %s:%d length = %d fd=%d\n", inet_ntoa(sender4.sin_addr), + ntohs(addr->getPort()), len, sock); + + if (len >= 13) + { + if (buf[0] == DTLS_CLIENTHELLO || buf[0] == DTLS_APPL) + { + rc = buf[0]; + } + } + return rc; + +#else + //AF_INET6 + sockaddr_in6 sender6 = { 0 }; + socklen_t addrlen6 = sizeof(sender6); + char buf[16]; + int rc = DTLS_OTHERS; + + len = ::recvfrom(sock, &buf, 15, MSG_PEEK, (sockaddr*) &sender6, &addrlen6); + + if (len < 0 && errno != EAGAIN) + { + D_NWSTACK("errno = %d in SensorNetwork::getSenderAddress\n", errno); + return -1; + } + + addr->setSockaddr6(&sender6); + +#ifdef DEBUG_NW + char senderstr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &sender6.sin6_addr,senderstr,INET6_ADDRSTRLEN); + D_NWSTACK("recved from %s:%d length = %d fd=%d\n",senderstr ,ntohs(addr->getPort()), len, sock); +#endif +#endif + + if (len >= 13) + { + if (buf[0] == DTLS_CLIENTHELLO || buf[0] == DTLS_APPL) + { + rc = buf[0]; + } + } + return rc; +} + +void SensorNetwork::clearRecvData(int sock) +{ + uint8_t buf[MQTTSNGW_MAX_PACKET_SIZE]; + ::recv(sock, buf, MQTTSNGW_MAX_PACKET_SIZE, 0); +} + +Connections* SensorNetwork::getConnections(void) +{ + return _conns; +} + + +int verify_cert(int ok, X509_STORE_CTX *ctx) +{ + return 1; +} + +int generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) +{ + unsigned char *buf; + unsigned char result[EVP_MAX_MD_SIZE]; + unsigned int len = 0; + unsigned int rsltlen; + union + { + struct sockaddr_storage ss; + struct sockaddr_in6 s6; + struct sockaddr_in s4; + } peer; + + if (!cookie_initialized) + { + if (!RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH)) + { + return 0; + } + cookie_initialized = 1; + } + + (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); + + len = 0; + switch (peer.ss.ss_family) + { + case AF_INET: + len += sizeof(struct in_addr); + break; + case AF_INET6: + len += sizeof(struct in6_addr); + break; + default: + OPENSSL_assert(0); + break; + } + len += sizeof(in_port_t); + buf = (unsigned char*) OPENSSL_malloc(len); + + switch (peer.ss.ss_family) + { + case AF_INET: + memcpy(buf, &peer.s4.sin_port, sizeof(in_port_t)); + memcpy(buf + sizeof(peer.s4.sin_port), &peer.s4.sin_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + memcpy(buf, &peer.s6.sin6_port, sizeof(in_port_t)); + memcpy(buf + sizeof(in_port_t), &peer.s6.sin6_addr, sizeof(struct in6_addr)); + break; + default: + OPENSSL_assert(0); + break; + } + + HMAC(EVP_sha1(), (const void*) cookie_secret, COOKIE_SECRET_LENGTH, (const unsigned char*) buf, len, result, &rsltlen); + OPENSSL_free(buf); + + memcpy(cookie, result, rsltlen); + *cookie_len = rsltlen; + + return 1; +} + +int verify_cookie(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len) +{ + unsigned char *buf; + unsigned char result[EVP_MAX_MD_SIZE]; + unsigned int len = 0; + unsigned int rsltlen; + union + { + struct sockaddr_storage ss; + struct sockaddr_in6 s6; + struct sockaddr_in s4; + } peer; + + if (!cookie_initialized) + { + return 0; + } + + (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); + + len = 0; + switch (peer.ss.ss_family) + { + case AF_INET: + len += sizeof(struct in_addr); + break; + case AF_INET6: + len += sizeof(struct in6_addr); + break; + default: + OPENSSL_assert(0); + break; + } + len += sizeof(in_port_t); + buf = (unsigned char*) OPENSSL_malloc(len); + + switch (peer.ss.ss_family) + { + case AF_INET: + memcpy(buf, &peer.s4.sin_port, sizeof(in_port_t)); + memcpy(buf + sizeof(in_port_t), &peer.s4.sin_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + memcpy(buf, &peer.s6.sin6_port, sizeof(in_port_t)); + memcpy(buf + sizeof(in_port_t), &peer.s6.sin6_addr, sizeof(struct in6_addr)); + break; + default: + OPENSSL_assert(0); + break; + } + + HMAC(EVP_sha1(), (const void*) cookie_secret, COOKIE_SECRET_LENGTH, (const unsigned char*) buf, len, result, &rsltlen); + OPENSSL_free(buf); + + if (cookie_len == rsltlen && memcmp(result, cookie, rsltlen) == 0) + { + return 1; + } + return 0; +} + diff --git a/MQTTSNGateway/src/linux/dtls/SensorNetwork.h b/MQTTSNGateway/src/linux/dtls/SensorNetwork.h new file mode 100644 index 0000000..0ef1753 --- /dev/null +++ b/MQTTSNGateway/src/linux/dtls/SensorNetwork.h @@ -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 +#include +#include +#include +#include + +using namespace std; + +namespace MQTTSNGW +{ +/*=========================================== + Class SensorNetAddreess + ============================================*/ +typedef struct +{ + int af; + union + { + struct in_addr ad4; + struct in6_addr ad6; + } addr; +} ipAddr_t; + +class SensorNetAddress +{ +public: + SensorNetAddress(); + ~SensorNetAddress(); + void setAddress(ipAddr_t *Address, uint16_t port); + int setAddress(string *ipAddrPort); + int setIpAddress(string *IpAddress); + void setFamily(int type); + int getFamily(void); + void setPort(in_port_t port); + void setSockaddr4(sockaddr_in *sockaddr); + void setSockaddr6(sockaddr_in6 *sockaddr); + void cpyAddr4(sockaddr_in *sockaddr); + void cpyAddr6(sockaddr_in6 *sockaddr); + void cpyAddr(SensorNetAddress *addr); + in_port_t getPort(void); + ipAddr_t* getIpAddress(void); + void setIndex(int index); + int getIndex(void); + + void clear(void); + + bool isMatch(SensorNetAddress *addr); + SensorNetAddress& operator =(SensorNetAddress &addr); + char* sprint(char *buf); +private: + int _pfdsIndex; + in_port_t _portNo; + ipAddr_t _ipAddr; +}; + +/*=========================================== + Class Connections + ============================================*/ +#define POLL_UCAST 0 +#define POLL_MCAST 1 +#define POLL_SSL 2 + +typedef struct +{ + int af; + SSL *ssl; +} afSSL_t; + +class Connections +{ +public: + Connections(); + ~Connections(); + void initialize(int maxClient); + void close(int index); + int poll(int timeout); + int addClientSock(int sock); + int addClientSSL(SSL *ssl, int sock); + void setSockMulticast(int sock); + void setSockUnicast(int sock); + int getNumOfConnections(void); + int getNumOfClients(void); + SSL* getClientSSL(int index); + int getEventClient(int index); + int getSockClient(int index); + int getSockMulticast(void); + int getSockUnicast(void); + int getEventMulticast(void); + int getEventUnicast(void); + int getEventListen(void); + void closeSSL(int index); + void print(void); +private: + pollfd *_pollfds; + SSL **_ssls; + int _maxfds; + int _numfds; + Mutex _mutex; +}; + +/*=========================================== + Class SensorNetwork + ============================================*/ +class SensorNetwork +{ + friend class SensorNetSubTask; +public: + SensorNetwork(); + ~SensorNetwork(); + + int unicast(const uint8_t *payload, uint16_t payloadLength, SensorNetAddress *sendto); + int broadcast(const uint8_t *payload, uint16_t payloadLength); + int read(uint8_t *buf, uint16_t bufLen); + void initialize(void); + const char* getDescription(void); + SensorNetAddress* getSenderAddress(void); + Connections* getConnections(void); + void close(); + +private: + int openV4(string *ipAddress, uint16_t multiPortNo, uint16_t uniPortNo, uint32_t ttl); + int openV6(string *ipAddress, string *interface, uint16_t multiPortNo, uint16_t uniPortNo, uint32_t hops); + int multicastRecv(uint8_t *buf, uint16_t len); + int getSendClient(int index, SensorNetAddress *addr); + int getSenderAddress(int sock, SensorNetAddress *addr); + int getUnicastClient(SensorNetAddress *addr); + void clearRecvData(int sock); + + Mutex _mutex; + SensorNetAddress _senderAddr; + SensorNetAddress _multicastAddr; + SensorNetAddress _unicastAddr; + string _description; + SSL_CTX *_dtlsctx; + Connections *_conns; + sockaddr_in _serverAddr4; + sockaddr_in6 _serverAddr6; + int _af; +}; + +} +#endif /* SENSORNETWORK_H_ */ diff --git a/MQTTSNGateway/src/linux/loralink/SensorNetwork.cpp b/MQTTSNGateway/src/linux/loralink/SensorNetwork.cpp index 854854c..9d755db 100644 --- a/MQTTSNGateway/src/linux/loralink/SensorNetwork.cpp +++ b/MQTTSNGateway/src/linux/loralink/SensorNetwork.cpp @@ -119,7 +119,7 @@ int SensorNetwork::read(uint8_t* buf, uint16_t bufLen) return LoRaLink::recv(buf, bufLen, &_clientAddr); } -int SensorNetwork::initialize(void) +void SensorNetwork::initialize(void) { char param[MQTTSNGW_PARAM_MAX]; uint32_t baudrate = 115200; @@ -135,15 +135,22 @@ int SensorNetwork::initialize(void) theProcess->getParam("DeviceRxLoRaLink", param); _description += ", SerialRx "; _description += param; + errno = 0; + if ( LoRaLink::open(LORALINK_MODEM_RX, param, baudrate) < 0 ) { - return -1; + throw EXCEPTION("Can't open a LoRaLink", errno); } theProcess->getParam("DeviceTxLoRaLink", param); _description += ", SerialTx "; _description += param; - return LoRaLink::open(LORALINK_MODEM_TX, param, baudrate); + errno = 0; + + if ( LoRaLink::open(LORALINK_MODEM_TX, param, baudrate) < 0 ) + { + throw EXCEPTION("Can't open a LoRaLink", errno); + } } const char* SensorNetwork::getDescription(void) @@ -376,7 +383,7 @@ bool LoRaLink::readApiFrame(LoRaLinkFrame_t* api, LoRaLinkReadParameters_t* para int LoRaLink::send(LoRaLinkPayloadType_t type, const uint8_t* payload, uint16_t pLen, SensorNetAddress* addr) { - D_NWSTACK("\r\n===> Send: "); + D_LRSTACK("\r\n===> Send: "); uint8_t buf[2] = { 0 }; uint8_t chks = 0; uint16_t len = pLen + 3; // 3 = DestAddr[1] + PayloadType[1] + Crc[1] @@ -397,7 +404,7 @@ int LoRaLink::send(LoRaLinkPayloadType_t type, const uint8_t* payload, uint16_t send(type); chks += type; - D_NWSTACK("\r\n Payload: "); + D_LRSTACK("\r\n Payload: "); for ( uint8_t i = 0; i < pLen; i++ ){ send(payload[i]); // Payload @@ -405,21 +412,21 @@ int LoRaLink::send(LoRaLinkPayloadType_t type, const uint8_t* payload, uint16_t } chks = 0xff - chks; - D_NWSTACK(" checksum "); + D_LRSTACK(" checksum "); send(chks); - D_NWSTACK("\r\n"); + D_LRSTACK("\r\n"); /* wait ACK */ _sem.timedwait(LORALINK_TIMEOUT_ACK); if ( _respCd == LORALINK_NO_FREE_CH ) { - D_NWSTACK(" Channel isn't free\r\n"); + D_LRSTACK(" Channel isn't free\r\n"); return -1; } else if ( _respCd != LORALINK_ACK ) { - D_NWSTACK(" Not Acknowleged\r\n"); + D_LRSTACK(" Not Acknowleged\r\n"); return -1; } return (int)pLen; @@ -472,7 +479,7 @@ int LoRaLink::recv(uint8_t* buf) /* if ( *buf == ESCAPE ) { - D_NWSTACK( " %02x",buf[0] ); + D_LRSTACK( " %02x",buf[0] ); if ( read(fd, buf, 1) == 1 ) { *buf = PAD ^ *buf; @@ -484,7 +491,7 @@ int LoRaLink::recv(uint8_t* buf) } */ - D_NWSTACK( " %02x",buf[0] ); + D_LRSTACK(" %02x", buf[0]); return 0; } } @@ -545,7 +552,7 @@ bool SerialPort::send(unsigned char b) } else { - D_NWSTACK( " %02x", b); + D_LRSTACK(" %02x", b); return true; } } diff --git a/MQTTSNGateway/src/linux/loralink/SensorNetwork.h b/MQTTSNGateway/src/linux/loralink/SensorNetwork.h index 0565ff1..212dc46 100644 --- a/MQTTSNGateway/src/linux/loralink/SensorNetwork.h +++ b/MQTTSNGateway/src/linux/loralink/SensorNetwork.h @@ -11,7 +11,7 @@ * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: - * Tomoaki Yamaguchi - initial API and implementation + * Tomoaki Yamaguchi - initial API and implementation **************************************************************************************/ #ifndef SENSORNETWORKX_H_ #define SENSORNETWORKX_H_ @@ -25,12 +25,11 @@ using namespace std; namespace MQTTSNGW { -//#define DEBUG_NWSTACK -#ifdef DEBUG_NWSTACK - #define D_NWSTACK(...) printf(__VA_ARGS__); fflush(stdout) +#ifdef DEBUG_NW +#define D_LRSTACK(...) printf(__VA_ARGS__); fflush(stdout) #else - #define D_NWSTACK(...) + #define D_LRSTACK(...) #endif @@ -173,7 +172,7 @@ public: int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto); int broadcast(const uint8_t* payload, uint16_t payloadLength); int read(uint8_t* buf, uint16_t bufLen); - int initialize(void); + void initialize(void); const char* getDescription(void); SensorNetAddress* getSenderAddress(void); diff --git a/MQTTSNGateway/src/linux/rfcomm/SensorNetwork.cpp b/MQTTSNGateway/src/linux/rfcomm/SensorNetwork.cpp new file mode 100644 index 0000000..e8d6bcd --- /dev/null +++ b/MQTTSNGateway/src/linux/rfcomm/SensorNetwork.cpp @@ -0,0 +1,422 @@ +/************************************************************************************** + * Copyright (c) 2016, Tomoaki Yamaguchi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation + **************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SensorNetwork.h" +#include "MQTTSNGWProcess.h" + +using namespace std; +using namespace MQTTSNGW; + +/*=========================================== + * Class SensorNetAddreess + + * These 4 methods are minimum requirements for the SensorNetAddress class. + * isMatch(SensorNetAddress* ) + * operator =(SensorNetAddress& ) + * setAddress(string* ) + * sprint(char* ) + + * BlePort class requires these 3 methods. + * getIpAddress(void) + * getPortNo(void) + * setAddress(uint32_t BtAddr, uint16_t channel) + + ============================================*/ +bdaddr_t NullAddr = { 0, 0, 0, 0, 0, 0 }; + +SensorNetAddress::SensorNetAddress() +{ + _channel = 0; + bacpy(&_bdAddr, &NullAddr); +} + +SensorNetAddress::~SensorNetAddress() +{ + +} + +bdaddr_t* SensorNetAddress::getAddress(void) +{ + return &_bdAddr; +} + +uint16_t SensorNetAddress::getPortNo(void) +{ + return _channel; +} + +void SensorNetAddress::setAddress(bdaddr_t BdAddr, uint16_t channel) +{ + bacpy(&_bdAddr, &BdAddr); + _channel = channel; +} + +/** + * Set Address data to SensorNetAddress + * + * @param *dev_channel is "Device_Address.Channel" format string + * @return success = 0, Invalid format = -1 + * + * Valid channels are 1 to 30. + * + * Client01,XX:XX:XX:XX:XX:XX.1 + * + */ +int SensorNetAddress::setAddress(string* dev_channel) +{ + int rc = -1; + size_t pos = dev_channel->find_first_of("."); + + if (pos == string::npos) + { + _channel = 0; + memset(&_bdAddr, 0, sizeof(bdaddr_t)); + return rc; + } + + string dvAddr = dev_channel->substr(0, pos); + string strchannel = dev_channel->substr(pos + 1); + if (strchannel == "*") + { + _channel = 0; + } + else + { + _channel = atoi(strchannel.c_str()); + } + str2ba(dvAddr.c_str(), &_bdAddr); + + if ((_channel < 0 && _channel > 30) || bacmp(&_bdAddr, &NullAddr) == 0) + { + return rc; + } + return 0; +} + +bool SensorNetAddress::isMatch(SensorNetAddress* addr) +{ + return ((this->_channel == addr->_channel) && bacmp(&this->_bdAddr, &addr->_bdAddr) == 0); +} + +SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress& addr) +{ + this->_channel = addr._channel; + this->_bdAddr = addr._bdAddr; + return *this; +} + +char* SensorNetAddress::sprint(char* buf) +{ + ba2str(const_cast(&_bdAddr), buf); + sprintf(buf + strlen(buf), ".%d", _channel); + return buf; +} + +/*================================================================ + Class SensorNetwork + + getDescpription( ) is used by Gateway::initialize( ) + initialize( ) is used by Gateway::initialize( ) + getSenderAddress( ) is used by ClientRecvTask::run( ) + broadcast( ) is used by MQTTSNPacket::broadcast( ) + unicast( ) is used by MQTTSNPacket::unicast( ) + read( ) is used by MQTTSNPacket::recv( ) + + ================================================================*/ + +SensorNetwork::SensorNetwork() +{ + +} + +SensorNetwork::~SensorNetwork() +{ +} + +int SensorNetwork::unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendToAddr) +{ + uint16_t ch = sendToAddr->getPortNo(); + RfcommPort* blep = &_rfPorts[ch - 1]; + int rc = 0; + errno = 0; + + if ((rc = blep->send(payload, (uint32_t) payloadLength)) < 0) + { + D_NWSTACK("errno == %d in BlePort::sendto %d\n", errno, ch); + } D_NWSTACK("sendto %u length = %d\n", ch, rc); + return rc; +} + +int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength) +{ + int rc = 0; + + for (int i = 0; i < MAX_RFCOMM_CH; i++) + { + errno = 0; + if (_rfPorts[i].getSock() > 0) + { + if ((rc = _rfPorts[i].send(payload, (uint32_t) payloadLength)) < 0) + { + D_NWSTACK("errno == %d in BlePort::sendto %d\n", errno, i + 1); + }D_NWSTACK("sendto %u length = %d\n", i + 1, rc); + } + } + return rc; +} + +int SensorNetwork::read(uint8_t* buf, uint16_t bufLen) +{ + struct timeval timeout; + fd_set recvfds; + int maxSock = 0; + + timeout.tv_sec = 1; + timeout.tv_usec = 0; // 1 sec + FD_ZERO(&recvfds); + + for (int i = 0; i < MAX_RFCOMM_CH; i++) + { + if (_rfPorts[i]._rfCommSock > 0) + { + if (maxSock < _rfPorts[i]._rfCommSock) + { + maxSock = _rfPorts[i]._rfCommSock; + } + FD_SET(_rfPorts[i]._rfCommSock, &recvfds); + } + else if (_rfPorts[i]._listenSock > 0) + { + if (maxSock < _rfPorts[i]._listenSock) + { + maxSock = _rfPorts[i]._listenSock; + } + FD_SET(_rfPorts[i]._listenSock, &recvfds); + } + } + + int rc = 0; + if (select(maxSock + 1, &recvfds, 0, 0, &timeout) > 0) + { + for (int i = 0; i < MAX_RFCOMM_CH; i++) + { + if (_rfPorts[i]._rfCommSock > 0) + { + if (FD_ISSET(_rfPorts[i]._rfCommSock, &recvfds)) + { + rc = _rfPorts[i].recv(buf, bufLen); + if (rc == -1) + { + _rfPorts[i].close(); + } + } + } + else if (_rfPorts[i]._listenSock > 0) + { + if (FD_ISSET(_rfPorts[i]._listenSock, &recvfds)) + { + int sock = _rfPorts[i].accept(&_senderAddr); + if (sock > 0) + { + _rfPorts[i]._rfCommSock = sock; + } + } + } + } + } + return rc; +} + +/** + * Prepare UDP sockets and description of SensorNetwork like + * "UDP Multicast 225.1.1.1:1883 Gateway Port 10000". + * The description is for a start up prompt. + */ +void SensorNetwork::initialize(void) +{ + char param[MQTTSNGW_PARAM_MAX]; + string devAddr; + SensorNetAddress sa; + + /* + * theProcess->getParam( ) copies + * a text specified by "Key" into param[] from the Gateway.conf + * + * in Gateway.conf e.g. + * + * # BLE + * RFCOMM=XX:XX:XX:XX:XX:XX.0 + * + */ + if (theProcess->getParam("RFCOMMAddress", param) == 0) + { + devAddr = param; + _description = "Bluetooth RFCOMM "; + _description += param; + } + + errno = 0; + if (sa.setAddress(&devAddr) == -1) + { + throw EXCEPTION("Invalid Bluetooth Address", errno); + } + + /* Prepare BLE sockets */ + WRITELOG("Initialize RFCOMM\n"); + int rc = MAX_RFCOMM_CH; + for (uint16_t i = 0; i < MAX_RFCOMM_CH; i++) + { + + rc += _rfPorts[i].open(sa.getAddress(), i + 1); + } + if (rc == 0) + { + throw EXCEPTION("Can't open Bluetooth RFComms", errno); + } +} + +const char* SensorNetwork::getDescription(void) +{ + return _description.c_str(); +} + +SensorNetAddress* SensorNetwork::getSenderAddress(void) +{ + return &_senderAddr; +} + +/*========================================= + Class BleStack + =========================================*/ + +RfcommPort::RfcommPort() +{ + _disconReq = false; + _rfCommSock = 0; + _listenSock = 0; + _channel = 0; +} + +RfcommPort::~RfcommPort() +{ + close(); + + if (_listenSock > 0) + { + ::close(_listenSock); + } +} + +void RfcommPort::close(void) +{ + if (_rfCommSock > 0) + { + ::close(_rfCommSock); + _rfCommSock = 0; + } +} + +int RfcommPort::open(bdaddr_t* devAddr, uint16_t channel) +{ + const int reuse = 1; + + if (channel < 1 || channel > 30) + { + D_NWSTACK("error Channel undefined in BlePort::open\n"); + return 0; + } + + + /*------ Create unicast socket --------*/ + _listenSock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (_listenSock < 0) + { + D_NWSTACK("error can't create Rfcomm socket in BlePort::open\n"); + return 0; + } + + sockaddr_rc addru; + addru.rc_family = AF_BLUETOOTH; + addru.rc_channel = channel; + bacpy(&addru.rc_bdaddr, devAddr); + + uint8_t buf[20]; + ba2str(devAddr, (char*) buf); + setsockopt(_listenSock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + errno = 0; + if (::bind(_listenSock, (sockaddr*) &addru, sizeof(addru)) < 0) + { + WRITELOG("\033[0m\033[0;31mCan't bind RFCOMM CH = %d %s\033[0m\033[0;37m\n", channel, strerror(errno)); + ::close(_listenSock); + return 0; + } + _channel = channel; + ::listen(_listenSock, 1); + WRITELOG("Listen RFCOMM CH = %d\n", channel); + return 1; +} + +int RfcommPort::send(const uint8_t* buf, uint32_t length) +{ + return ::send(_rfCommSock, buf, length, 0); +} + +int RfcommPort::recv(uint8_t* buf, uint16_t len) +{ + int rc = 0; + errno = 0; + + rc = ::read(_rfCommSock, buf, len); + if (rc < 0 && errno != EAGAIN) + { + D_NWSTACK("errno = %d in BlePort::recv\n", errno); + return -1; + } + return rc; +} + +int RfcommPort::accept(SensorNetAddress* addr) +{ + struct sockaddr_rc devAddr = { 0 }; + socklen_t opt = sizeof(devAddr); + + int sock = 0; + errno = 0; + + sock = ::accept(_listenSock, (sockaddr *) &devAddr, &opt); + if (sock < 0 && errno != EAGAIN) + { + D_NWSTACK("errno == %d in BlePort::recv\n", errno); + return -1; + } + bdaddr_t bdAddr = devAddr.rc_bdaddr; + addr->setAddress(bdAddr, _channel); + return sock; +} + +int RfcommPort::getSock(void) +{ + return _rfCommSock; +} diff --git a/MQTTSNGateway/src/linux/rfcomm/SensorNetwork.h b/MQTTSNGateway/src/linux/rfcomm/SensorNetwork.h new file mode 100644 index 0000000..2aef9f8 --- /dev/null +++ b/MQTTSNGateway/src/linux/rfcomm/SensorNetwork.h @@ -0,0 +1,98 @@ +/************************************************************************************** + * Copyright (c) 2016, Tomoaki Yamaguchi + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation + **************************************************************************************/ + +#ifndef SENSORNETWORK_H_ +#define SENSORNETWORK_H_ + +#include "MQTTSNGWDefines.h" +#include +#include + +using namespace std; + +namespace MQTTSNGW +{ + +#define MAX_RFCOMM_CH 30 + +/*=========================================== + Class SensorNetAddreess + ============================================*/ +class SensorNetAddress +{ +public: + SensorNetAddress(); + ~SensorNetAddress(); + void setAddress(bdaddr_t bdAddr, uint16_t channel); + int setAddress(string* data); + uint16_t getPortNo(void); + bdaddr_t* getAddress(void); + bool isMatch(SensorNetAddress* addr); + SensorNetAddress& operator =(SensorNetAddress& addr); + char* sprint(char* buf); +private: + uint16_t _channel; + bdaddr_t _bdAddr; +}; + +/*======================================== + Class RfcommPort + =======================================*/ +class RfcommPort +{ + friend class SensorNetwork; +public: + RfcommPort(); + virtual ~RfcommPort(); + + int open(bdaddr_t* devAddress, uint16_t channel); + void close(void); + int send(const uint8_t* buf, uint32_t length); + int recv(uint8_t* buf, uint16_t len); + int getSock(void); + int accept(SensorNetAddress* addr); +private: + int _rfCommSock; + int _listenSock; + uint16_t _channel; + bool _disconReq; +}; + +/*=========================================== + Class SensorNetwork + ============================================*/ +class SensorNetwork +{ +public: + SensorNetwork(); + ~SensorNetwork(); + + int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto); + int broadcast(const uint8_t* payload, uint16_t payloadLength); + int read(uint8_t* buf, uint16_t bufLen); + void initialize(void); + const char* getDescription(void); + SensorNetAddress* getSenderAddress(void); + +private: + // sockets for RFCOMM + RfcommPort _rfPorts[MAX_RFCOMM_CH]; + SensorNetAddress _senderAddr; + string _description; +}; + +} +#endif /* SENSORNETWORK_H_ */ diff --git a/MQTTSNGateway/src/linux/udp/SensorNetwork.cpp b/MQTTSNGateway/src/linux/udp/SensorNetwork.cpp index 1b57ff5..e855619 100644 --- a/MQTTSNGateway/src/linux/udp/SensorNetwork.cpp +++ b/MQTTSNGateway/src/linux/udp/SensorNetwork.cpp @@ -20,10 +20,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #include "SensorNetwork.h" #include "MQTTSNGWProcess.h" @@ -142,7 +145,7 @@ char* SensorNetAddress::sprint(char* buf) In Gateway version 1.0 getDescpription( ) is used by Gateway::initialize( ) - initialize( ) is used by ClientSendTask::initialize( ) + initialize( ) is used by Gateway::initialize( ) getSenderAddress( ) is used by ClientRecvTask::run( ) broadcast( ) is used by MQTTSNPacket::broadcast( ) unicast( ) is used by MQTTSNPacket::unicast( ) @@ -170,16 +173,15 @@ int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength) int SensorNetwork::read(uint8_t* buf, uint16_t bufLen) { - return UDPPort::recv(buf, bufLen, &_clientAddr); + return UDPPort::recv(buf, bufLen, &_senderAddr); } /** * Prepare UDP sockets and description of SensorNetwork like * "UDP Multicast 225.1.1.1:1883 Gateway Port 10000". * The description is for a start up prompt. - * @return success = 0, error = -1 */ -int SensorNetwork::initialize(void) +void SensorNetwork::initialize(void) { char param[MQTTSNGW_PARAM_MAX]; uint16_t multicastPortNo = 0; @@ -197,34 +199,38 @@ int SensorNetwork::initialize(void) * MulticastIP=225.1.1.1 * MulticastPortNo=1883 * - */ - if (theProcess->getParam("MulticastIP", param) == 0) - { - ip = param; - _description = "UDP Multicast "; - _description += param; - } - if (theProcess->getParam("MulticastPortNo", param) == 0) - { - multicastPortNo = atoi(param); - _description += ":"; - _description += param; - } - if (theProcess->getParam("GatewayPortNo", param) == 0) - { - unicastPortNo = atoi(param); - _description += " Gateway Port "; - _description += param; - } - if (theProcess->getParam("MulticastTTL", param) == 0) - { - ttl = atoi(param); - _description += " TTL: "; - _description += param; - } + */ + if (theProcess->getParam("MulticastIP", param) == 0) + { + ip = param; + _description = "UDP Multicast "; + _description += param; + } + if (theProcess->getParam("MulticastPortNo", param) == 0) + { + multicastPortNo = atoi(param); + _description += ":"; + _description += param; + } + if (theProcess->getParam("GatewayPortNo", param) == 0) + { + unicastPortNo = atoi(param); + _description += ", Gateway Port:"; + _description += param; + } + if (theProcess->getParam("MulticastTTL", param) == 0) + { + ttl = atoi(param); + _description += ", TTL:"; + _description += param; + } - /* Prepare UDP sockets */ - return UDPPort::open(ip.c_str(), multicastPortNo, unicastPortNo, ttl); + /* setup UDP sockets */ + errno = 0; + if ( UDPPort::open(ip.c_str(), multicastPortNo, unicastPortNo, ttl) < 0 ) + { + throw EXCEPTION("Can't open a UDP", errno); + } } const char* SensorNetwork::getDescription(void) @@ -234,7 +240,7 @@ const char* SensorNetwork::getDescription(void) SensorNetAddress* SensorNetwork::getSenderAddress(void) { - return &_clientAddr; + return &_senderAddr; } /*========================================= @@ -244,8 +250,7 @@ SensorNetAddress* SensorNetwork::getSenderAddress(void) UDPPort::UDPPort() { _disconReq = false; - _sockfdUnicast = -1; - _sockfdMulticast = -1; + memset(_pollFds, 0, sizeof(_pollFds)); } UDPPort::~UDPPort() @@ -255,188 +260,164 @@ UDPPort::~UDPPort() void UDPPort::close(void) { - if (_sockfdUnicast > 0) - { - ::close(_sockfdUnicast); - _sockfdUnicast = -1; - } - if (_sockfdMulticast > 0) - { - ::close(_sockfdMulticast); - _sockfdMulticast = -1; - } + for (int i = 0; i < 2; i++) + { + if (_pollFds[i].fd > 0) + { + ::close(_pollFds[i].fd); + _pollFds[i].fd = 0; + } + } } -int UDPPort::open(const char* ipAddress, uint16_t multiPortNo, uint16_t uniPortNo, unsigned int ttl) +int UDPPort::open(const char *multicastIP, uint16_t multiPortNo, uint16_t uniPortNo, unsigned int ttl) { - char loopch = 0; - const int reuse = 1; + int optval = 0; + int sock = 0; - if (uniPortNo == 0 || multiPortNo == 0) - { - D_NWSTACK("error portNo undefined in UDPPort::open\n"); - return -1; - } + if (uniPortNo == 0 || multiPortNo == 0) + { + D_NWSTACK("error portNo undefined in UDPPort::open\n"); + return -1; + } - uint32_t ip = inet_addr(ipAddress); - _grpAddr.setAddress(ip, htons(multiPortNo)); - _clientAddr.setAddress(ip, htons(uniPortNo)); - _ttl = ttl; + /*------ Create unicast socket --------*/ + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) + { + D_NWSTACK("error can't create unicast socket in UDPPort::open\n"); + return -1; + } - /*------ Create unicast socket --------*/ - _sockfdUnicast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (_sockfdUnicast < 0) - { - D_NWSTACK("error can't create unicast socket in UDPPort::open\n"); - return -1; - } + sockaddr_in addru; + addru.sin_family = AF_INET; + addru.sin_port = htons(uniPortNo); + addru.sin_addr.s_addr = INADDR_ANY; - setsockopt(_sockfdUnicast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); - - sockaddr_in addru; - addru.sin_family = AF_INET; - addru.sin_port = htons(uniPortNo); - addru.sin_addr.s_addr = INADDR_ANY; - - if (::bind(_sockfdUnicast, (sockaddr*) &addru, sizeof(addru)) < 0) + if (::bind(sock, (sockaddr*) &addru, sizeof(addru)) < 0) { D_NWSTACK("error can't bind unicast socket in UDPPort::open\n"); return -1; } - if (setsockopt(_sockfdUnicast, IPPROTO_IP, IP_MULTICAST_LOOP, (char*) &loopch, sizeof(loopch)) < 0) - { - D_NWSTACK("error IP_MULTICAST_LOOP in UDPPort::open\n"); - close(); - return -1; - } - /*------ Create Multicast socket --------*/ - _sockfdMulticast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (_sockfdMulticast < 0) + _pollFds[0].fd = sock; + _pollFds[0].events = POLLIN; + + /*------ 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"); close(); return -1; } - setsockopt(_sockfdMulticast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + optval = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - sockaddr_in addrm; - addrm.sin_family = AF_INET; - addrm.sin_port = _grpAddr.getPortNo(); - addrm.sin_addr.s_addr = INADDR_ANY; + sockaddr_in addrm; + addrm.sin_family = AF_INET; + addrm.sin_port = htons(multiPortNo); + addrm.sin_addr.s_addr = INADDR_ANY; - if (::bind(_sockfdMulticast, (sockaddr*) &addrm, sizeof(addrm)) < 0) - { - D_NWSTACK("error can't bind multicast socket in UDPPort::open\n"); - return -1; - } - if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_MULTICAST_LOOP, (char*) &loopch, sizeof(loopch)) < 0) - { - D_NWSTACK("error IP_MULTICAST_LOOP in UDPPort::open\n"); - close(); - return -1; - } + if (::bind(sock, (sockaddr*) &addrm, sizeof(addrm)) < 0) + { + D_NWSTACK("error can't bind multicast socket in UDPPort::open\n"); + return -1; + } - ip_mreq mreq; - mreq.imr_interface.s_addr = INADDR_ANY; - mreq.imr_multiaddr.s_addr = _grpAddr.getIpAddress(); + ip_mreq mreq; + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_interface.s_addr = INADDR_ANY; + mreq.imr_multiaddr.s_addr = inet_addr(multicastIP); - if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) - { - D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); - close(); - return -1; - } + if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + { + D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); + close(); + return -1; + } - if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,sizeof(ttl)) < 0) - { - D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); - close(); - return -1; - } + if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) + { + D_NWSTACK("error Multicast IP_MULTICAST_TTL in UDPPort::open\n"); + close(); + return -1; + } - if (setsockopt(_sockfdUnicast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) - { - D_NWSTACK("error Unicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); - close(); - return -1; - } - return 0; +#ifdef DEBUG_NW + optval = 1; +#else + optval = 0; +#endif + + if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0) + { + D_NWSTACK("error IP_MULTICAST_LOOP in UDPPort::open\n"); + close(); + return -1; + } + + _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) { - sockaddr_in dest; - dest.sin_family = AF_INET; - dest.sin_port = addr->getPortNo(); - dest.sin_addr.s_addr = addr->getIpAddress(); + sockaddr_in dest; + dest.sin_family = AF_INET; + dest.sin_port = addr->getPortNo(); + dest.sin_addr.s_addr = addr->getIpAddress(); - int status = ::sendto(_sockfdUnicast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest)); - if (status < 0) - { - D_NWSTACK("errno == %d in UDPPort::sendto\n", errno); - } - D_NWSTACK("sendto %s:%u length = %d\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), status); - return status; + int status = ::sendto(_pollFds[0].fd, buf, length, 0, (const sockaddr*) &dest, sizeof(dest)); + if (status < 0) + { + D_NWSTACK("errno == %d in UDPPort::sendto\n", errno); + } + + D_NWSTACK("sendto %s:%u length = %d\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), status); + return status; } int UDPPort::broadcast(const uint8_t* buf, uint32_t length) { - return unicast(buf, length, &_grpAddr); + return unicast(buf, length, &_multicastAddr); } int UDPPort::recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr) { - struct timeval timeout; - fd_set recvfds; - int maxSock = 0; + int rc = 0; + poll(_pollFds, 2, 2000); // Timeout 2 seconds - timeout.tv_sec = 1; - timeout.tv_usec = 0; // 1 sec - FD_ZERO(&recvfds); - FD_SET(_sockfdUnicast, &recvfds); - FD_SET(_sockfdMulticast, &recvfds); - - if (_sockfdMulticast > _sockfdUnicast) - { - maxSock = _sockfdMulticast; - } - else - { - maxSock = _sockfdUnicast; - } - - int rc = 0; - if ( select(maxSock + 1, &recvfds, 0, 0, &timeout) > 0 ) - { - if (FD_ISSET(_sockfdUnicast, &recvfds)) - { - rc = recvfrom(_sockfdUnicast, buf, len, 0, addr); - } - else if (FD_ISSET(_sockfdMulticast, &recvfds)) - { - rc = recvfrom(_sockfdMulticast, buf, len, 0, &_grpAddr); - } - } - return rc; + if (_pollFds[0].revents == POLLIN) + { + rc = recvfrom(_pollFds[0].fd, buf, len, 0, addr); + } + else if (_pollFds[1].revents == POLLIN) + { + rc = recvfrom(_pollFds[1].fd, buf, len, 0, addr); + } + return rc; } int UDPPort::recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr) { - sockaddr_in sender; - socklen_t addrlen = sizeof(sender); - memset(&sender, 0, addrlen); + sockaddr_in sender; + socklen_t addrlen = sizeof(sender); + 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) - { - D_NWSTACK("errno == %d in UDPPort::recvfrom\n", errno); - return -1; - } - 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); - return status; + if (status < 0 && errno != EAGAIN) + { + D_NWSTACK("errno == %d in UDPPort::recvfrom\n", errno); + return -1; + } + 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); + return status; } diff --git a/MQTTSNGateway/src/linux/udp/SensorNetwork.h b/MQTTSNGateway/src/linux/udp/SensorNetwork.h index 735a3c5..2a3870a 100644 --- a/MQTTSNGateway/src/linux/udp/SensorNetwork.h +++ b/MQTTSNGateway/src/linux/udp/SensorNetwork.h @@ -19,18 +19,13 @@ #include "MQTTSNGWDefines.h" #include +#include using namespace std; namespace MQTTSNGW { -#ifdef DEBUG_NWSTACK - #define D_NWSTACK(...) printf(__VA_ARGS__) -#else - #define D_NWSTACK(...) -#endif - /*=========================================== Class SensorNetAddreess ============================================*/ @@ -70,13 +65,9 @@ private: void setNonBlocking(const bool); int recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr); - int _sockfdUnicast; - int _sockfdMulticast; - - SensorNetAddress _grpAddr; - SensorNetAddress _clientAddr; + pollfd _pollFds[2]; bool _disconReq; - unsigned int _ttl; + SensorNetAddress _multicastAddr; }; /*=========================================== @@ -91,12 +82,12 @@ public: int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto); int broadcast(const uint8_t* payload, uint16_t payloadLength); int read(uint8_t* buf, uint16_t bufLen); - int initialize(void); + void initialize(void); const char* getDescription(void); SensorNetAddress* getSenderAddress(void); private: - SensorNetAddress _clientAddr; // Sender's address. not gateway's one. + SensorNetAddress _senderAddr; string _description; }; diff --git a/MQTTSNGateway/src/linux/udp6/SensorNetwork.cpp b/MQTTSNGateway/src/linux/udp6/SensorNetwork.cpp index 915aef8..193d1d7 100644 --- a/MQTTSNGateway/src/linux/udp6/SensorNetwork.cpp +++ b/MQTTSNGateway/src/linux/udp6/SensorNetwork.cpp @@ -1,6 +1,6 @@ /************************************************************************************** * 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 * are made available under the terms of the Eclipse Public License v1.0 @@ -20,8 +20,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -40,61 +42,57 @@ using namespace MQTTSNGW; ============================================*/ SensorNetAddress::SensorNetAddress() { - _portNo = 0; - memset((void *)&_IpAddr,0,sizeof(_IpAddr)); + memset((void*) &_IpAddr, 0, sizeof(_IpAddr)); } SensorNetAddress::~SensorNetAddress() { } -struct sockaddr_in6 *SensorNetAddress::getIpAddress(void) +sockaddr_in6* SensorNetAddress::getIpAddress(void) { - return &_IpAddr; + return &_IpAddr; } 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)); - _portNo = port; + memcpy((void*) &_IpAddr, IpAddr, sizeof(_IpAddr)); } /** * convert Text data to SensorNetAddress - * @param data is a IP_Address:PortNo format string + * @param data is a string [IPV6_Address]:PortNo * @return success = 0, Invalid format = -1 */ 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) - { - int portNo = 0; - string port = data->substr(pos + 1); + if ((portNo = atoi(port.c_str())) > 0) + { + _IpAddr.sin6_port = htons(portNo); + _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 ) - { - _portNo = htons(portNo); - - string ip = data->substr(1,pos - 1); - const char *cstr = ip.c_str(); - - if (inet_pton(AF_INET6, cstr, &(_IpAddr.sin6_addr)) == 1 ) - { - return 0; - } - } - } - _portNo = 0; - memset((void *)&_IpAddr,0,sizeof(_IpAddr)); - return -1; + if (inet_pton(AF_INET6, cstr, &(_IpAddr.sin6_addr)) == 1) + { + return 0; + } + } + } + memset((void*) &_IpAddr, 0, sizeof(_IpAddr)); + return -1; } /** @@ -104,43 +102,42 @@ int SensorNetAddress::setAddress(string* data) */ int SensorNetAddress::setAddress(const char* data) { - if ( inet_pton(AF_INET6, data, &(_IpAddr.sin6_addr)) == 1 ) - { - return 0; - } - else - { - return -1; - } + if (inet_pton(AF_INET6, data, &(_IpAddr.sin6_addr)) == 1) + { + _IpAddr.sin6_family = AF_INET6; + return 0; + } + else + { + return -1; + } } char* SensorNetAddress::getAddress(void) { - inet_ntop(AF_INET6, &(_IpAddr.sin6_addr), _addrString, INET6_ADDRSTRLEN); - return _addrString; + inet_ntop(AF_INET6, &(_IpAddr.sin6_addr), _addrString, INET6_ADDRSTRLEN); + return _addrString; } bool SensorNetAddress::isMatch(SensorNetAddress* addr) { - return (this->_portNo == addr->_portNo) && \ - (memcmp(this->_IpAddr.sin6_addr.s6_addr, addr->_IpAddr.sin6_addr.s6_addr, sizeof(this->_IpAddr.sin6_addr.s6_addr)) == 0); + 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); } SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress& addr) { - this->_portNo = addr._portNo; - memcpy(&this->_IpAddr.sin6_addr, &addr._IpAddr.sin6_addr, sizeof(this->_IpAddr.sin6_addr)); - return *this; + memcpy(&this->_IpAddr, &addr._IpAddr, sizeof(this->_IpAddr)); + return *this; } char* SensorNetAddress::sprint(char* buf) { - char ip[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(_IpAddr.sin6_addr), ip, INET6_ADDRSTRLEN); - sprintf( buf, "%s:", ip); - sprintf( buf + strlen(buf), "%d", ntohs(_portNo)); - return buf; + sprintf(buf, "[%s]:", getAddress()); + sprintf(buf + strlen(buf), "%d", ntohs(_IpAddr.sin6_port)); + return buf; } /*=========================================== @@ -156,70 +153,74 @@ SensorNetwork::~SensorNetwork() 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) { - return UDPPort6::broadcast(payload, payloadLength); + return UDPPort6::broadcast(payload, payloadLength); } int SensorNetwork::read(uint8_t* buf, uint16_t bufLen) { - return UDPPort6::recv(buf, bufLen, &_clientAddr); + return UDPPort6::recv(buf, bufLen, &_clientAddr); } -int SensorNetwork::initialize(void) +void SensorNetwork::initialize(void) { - char param[MQTTSNGW_PARAM_MAX]; - uint16_t unicastPortNo = 0; - string ip; - string broadcast; - string interface; - unsigned int hops = 1; + char param[MQTTSNGW_PARAM_MAX]; + uint16_t unicastPortNo = 0; + uint16_t multicastPortNo = 0; + string ip; + string multicast; + string interface; + uint32_t hops = 1; - if (theProcess->getParam("GatewayUDP6Bind", param) == 0) - { - ip = param; - _description = "GatewayUDP6Bind: "; - _description += param; - } - if (theProcess->getParam("GatewayUDP6Port", param) == 0) - { - unicastPortNo = atoi(param); - _description += " Gateway Port: "; - _description += param; - } - if (theProcess->getParam("GatewayUDP6Broadcast", param) == 0) - { - broadcast = param; - _description += " Broadcast Address: "; - _description += param; - } - if (theProcess->getParam("GatewayUDP6If", param) == 0) - { - interface = param; - _description += " Interface: "; - _description += param; - } - if (theProcess->getParam("GatewayUDP6Hops", param) == 0) - { - hops = atoi(param); - _description += " Hops: "; - _description += param; - } + if (theProcess->getParam("MulticastIPv6", param) == 0) + { + multicast = param; + _description += "Multicast Address: ["; + _description += param; + } + if (theProcess->getParam("MulticastIPv6PortNo", param) == 0) + { + multicastPortNo = atoi(param); + _description += "]:"; + _description += param; + } + if (theProcess->getParam("GatewayIPv6PortNo", param) == 0) + { + unicastPortNo = atoi(param); + _description += ", Gateway Port:"; + _description += param; + } + if (theProcess->getParam("MulticastIPv6If", param) == 0) + { + interface = param; + _description += ", Interface: "; + _description += param; + } + if (theProcess->getParam("MulticastHops", param) == 0) + { + hops = atoi(param); + _description += ", Hops:"; + _description += param; + } - return UDPPort6::open(ip.c_str(), unicastPortNo, broadcast.c_str(), interface.c_str(), hops); + if (UDPPort6::open(unicastPortNo, multicastPortNo, multicast.c_str(), interface.c_str(), hops) < 0) + { + throw EXCEPTION("Can't open a UDP6", errno); + } } const char* SensorNetwork::getDescription(void) { - return _description.c_str(); + return _description.c_str(); } SensorNetAddress* SensorNetwork::getSenderAddress(void) { - return &_clientAddr; + return &_clientAddr; } /*========================================= @@ -228,269 +229,241 @@ SensorNetAddress* SensorNetwork::getSenderAddress(void) UDPPort6::UDPPort6() { - _disconReq = false; - _sockfdUnicast = -1; - _sockfdMulticast = -1; + _disconReq = false; + _hops = 0; } UDPPort6::~UDPPort6() { - close(); + close(); } void UDPPort6::close(void) { - if (_sockfdUnicast > 0) - { - ::close(_sockfdUnicast); - _sockfdUnicast = -1; - } - if (_sockfdMulticast > 0) - { - ::close(_sockfdMulticast); - _sockfdMulticast = -1; - } + for (int i = 0; i < 2; i++) + { + if (_pollfds[i].fd > 0) + { + ::close(_pollfds[i].fd); + _pollfds[i].fd = 0; + } + } } -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 errnu; - const int reuse = 1; + int optval = 0; + int sock = 0; + sockaddr_in6 addr6; + uint32_t ifindex = 0; - if (uniPortNo == 0) - { - WRITELOG("error portNo undefined in UDPPort::open\n"); - return -1; - } + errno = 0; + if (uniPortNo == 0 || multiPortNo == 0) + { + D_NWSTACK("error portNo undefined in UDPPort6::open\n"); + return -1; + } - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_INET6; // use IPv6 - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE; //use local IF address + // Create a unicast socket + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) + { + 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); - if(_sockfdMulticast <0) - { - WRITELOG("UDP6::open - multicast: %s",strerror(_sockfdMulticast)); - return errno; - } + optval = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &optval, sizeof(optval)); - //select the interface - unsigned int ifindex; - ifindex = if_nametoindex(interfaceName); - errnu = setsockopt(_sockfdMulticast, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex,sizeof(ifindex)); - if(errnu <0) - { - WRITELOG("UDP6::open - limit IF: %s",strerror(errnu)); - return errnu; - } + optval = 1; + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &optval, sizeof(optval)) < 0) + { + D_NWSTACK("\033[0m\033[0;31m unicast socket error %s IPV6_V6ONLY\033[0m\033[0;37m\n", strerror(errno)); + close(); + return -1; + } - 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 - int on = 1; - errnu = setsockopt(_sockfdMulticast, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); - 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) - { + if (strlen(interfaceName) > 0) + { + ifindex = if_nametoindex(interfaceName); #ifdef __APPLE__ - int idx = if_nametoindex(interfaceName); - setsockopt(_sockfdUnicast, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)); -#else - //socket option: bind to a given interface name - setsockopt(_sockfdUnicast, SOL_SOCKET, SO_BINDTODEVICE, interfaceName, strlen(interfaceName)); + setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex)); +#else + setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, interfaceName, strlen(interfaceName)); #endif - } + } - //socket option: reuse address - setsockopt(_sockfdUnicast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(uniPortNo); + addr6.sin6_addr = in6addr_any; - //finally: bind... - errnu = ::bind(_sockfdUnicast, res->ai_addr, res->ai_addrlen); - if (errnu < 0) - { - WRITELOG("error can't bind unicast socket in UDPPort::open: %s\n",strerror(errnu)); - return -1; - } + if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0) + { + D_NWSTACK("error can't bind unicast socket in UDPPort6::open: %s\n", strerror(errno)); + close(); + return -1; + } - //if given, set a broadcast address; otherwise it will be :: - if(strlen(broadcastAddr) > 0) - { - _grpAddr.setAddress(broadcastAddr); - } else { - _grpAddr.setAddress("::"); - } - //everything went fine... - freeaddrinfo(res); - return 0; + + // create a MULTICAST socket + + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) + { + D_NWSTACK("UDP6::open - multicast: %s", strerror(errno)); + close(); + return -1; + } + _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_JOIN_GROUP, &addrm, sizeof(addrm)) < 0) + { + D_NWSTACK("\033[0m\033[0;31m error %d IPV6_JOIN_GROUP 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) { - char destStr[INET6_ADDRSTRLEN+10]; - struct addrinfo hints, *res; - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_INET6; // use IPv6 - hints.ai_socktype = SOCK_DGRAM; + sockaddr_in6 dest; + memset(&dest, 0, sizeof(dest)); + dest.sin6_family = AF_INET6; + dest.sin6_port = addr->getPortNo(); + memcpy(dest.sin6_addr.s6_addr, (const void*) &addr->getIpAddress()->sin6_addr, sizeof(in6_addr)); - int port = 0; - string portStr; - if(addr->getPortNo() != 0) - { - port = htons(addr->getPortNo()); - portStr = to_string(port); - } else { - port = _uniPortNo; - portStr = to_string(port); - } +#ifdef DEBUG_NW + char addrBuf[INET6_ADDRSTRLEN]; + addr->sprint(addrBuf); + D_NWSTACK("sendto %s\n", addrBuf); +#endif - if(strlen(_interfaceName) != 0) - { - strcpy(destStr, addr->getAddress()); - strcat(destStr,"%"); - strcat(destStr,_interfaceName); - if(IN6_IS_ADDR_LINKLOCAL(&addr->getIpAddress()->sin6_addr)) - { - getaddrinfo(destStr, portStr.c_str(), &hints, &res); - } - else - { - getaddrinfo(addr->getAddress(), portStr.c_str(), &hints, &res); - } - } else { - strcpy(destStr, addr->getAddress()); - getaddrinfo(addr->getAddress(), portStr.c_str(), &hints, &res); - } + int status = ::sendto(_pollfds[0].fd, buf, length, 0, (const sockaddr*) &dest, sizeof(dest)); - 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(status)); - } - - return status; + if (status < 0) + { + D_NWSTACK("%s in UDPPor6t::sendto\n", strerror(errno)); + } + return status; } int UDPPort6::broadcast(const uint8_t* buf, uint32_t length) { - struct addrinfo hint,*info; - int err; - memset( &hint, 0, sizeof( hint ) ); + int err = unicast(buf, length, &_grpAddr); - hint.ai_family = AF_INET6; - hint.ai_socktype = SOCK_DGRAM; - hint.ai_protocol = 0; + if (err < 0) + { + D_NWSTACK("UDP6::broadcast - sendto: %s", strerror(errno)); + return err; + } - - - 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(err)); - return err; - } - - err = sendto(_sockfdMulticast, buf, length, 0, info->ai_addr, info->ai_addrlen ); - - if(err < 0 ) { - WRITELOG("UDP6::broadcast - sendto: %s",strerror(err)); - return errno; - } - - return 0; + return 0; } int UDPPort6::recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr) { - struct timeval timeout; - fd_set recvfds; + int rc = poll(_pollfds, 2, 2000); // Timeout 2secs + if (rc == 0) + { + return rc; + } - timeout.tv_sec = 1; - timeout.tv_usec = 0; // 1 sec - FD_ZERO(&recvfds); - FD_SET(_sockfdUnicast, &recvfds); - - int rc = 0; - if ( select(_sockfdUnicast + 1, &recvfds, 0, 0, &timeout) > 0 ) - { - if (FD_ISSET(_sockfdUnicast, &recvfds)) - { - rc = recvfrom(_sockfdUnicast, buf, len, 0, addr); - } - } - return rc; + for (int i = 0; i < 2; i++) + { + if (_pollfds[i].revents & POLLIN) + { + return recvfrom(_pollfds[i].fd, buf, len, 0, addr); + } + } + return 0; } int UDPPort6::recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr) { - sockaddr_in6 sender; - socklen_t addrlen = sizeof(sender); - memset(&sender, 0, addrlen); + sockaddr_in6 sender; + socklen_t addrlen = sizeof(sender); + 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) - { - WRITELOG("errno == %d in UDPPort::recvfrom: %s\n",errno,strerror(errno)); - return -1; - } - addr->setAddress(&sender, (uint16_t)sender.sin6_port); - //D_NWSTACK("recved from %s:%d length = %d\n", inet_ntoa(sender.sin_addr),ntohs(sender.sin_port), status); - return status; + if (status < 0 && errno != EAGAIN) + { + D_NWSTACK("errno in UDPPort6::recvfrom: %s\n", strerror(errno)); + return -1; + } + addr->setAddress(&sender); + +#ifdef DEBUG_NW + char addrBuf[INET6_ADDRSTRLEN]; + addr->sprint(addrBuf); + D_NWSTACK("sendto %s length = %d\n", addrBuf, status); +#endif + return status; } diff --git a/MQTTSNGateway/src/linux/udp6/SensorNetwork.h b/MQTTSNGateway/src/linux/udp6/SensorNetwork.h index 0e3ab7e..68830b6 100644 --- a/MQTTSNGateway/src/linux/udp6/SensorNetwork.h +++ b/MQTTSNGateway/src/linux/udp6/SensorNetwork.h @@ -12,7 +12,7 @@ * http://www.eclipse.org/org/documents/edl-v10.php. * * 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 **************************************************************************************/ @@ -22,69 +22,59 @@ #include "MQTTSNGWDefines.h" #include #include +#include using namespace std; namespace MQTTSNGW { -#ifdef DEBUG_NWSTACK - #define D_NWSTACK(...) printf(__VA_ARGS__) -#else - #define D_NWSTACK(...) -#endif - /*=========================================== Class SensorNetAddreess ============================================*/ class SensorNetAddress { public: - SensorNetAddress(); - ~SensorNetAddress(); - void setAddress(struct sockaddr_in6 *IpAddr, uint16_t port); - int setAddress(string* data); - int setAddress(const char* data); - uint16_t getPortNo(void); - struct sockaddr_in6 *getIpAddress(void); - char* getAddress(void); - bool isMatch(SensorNetAddress* addr); - SensorNetAddress& operator =(SensorNetAddress& addr); - char* sprint(char* buf); + SensorNetAddress(); + ~SensorNetAddress(); + void setAddress(sockaddr_in6 *IpAddr); + int setAddress(string* data); + int setAddress(const char* data); + uint16_t getPortNo(void); + sockaddr_in6* getIpAddress(void); + char* getAddress(void); + bool isMatch(SensorNetAddress* addr); + SensorNetAddress& operator =(SensorNetAddress& addr); + char* sprint(char* buf); private: - uint16_t _portNo; - char _addrString[INET6_ADDRSTRLEN+1]; - struct sockaddr_in6 _IpAddr; + char _addrString[INET6_ADDRSTRLEN + 1]; + sockaddr_in6 _IpAddr; }; /*======================================== - Class UpdPort + Class UpdPort6 =======================================*/ class UDPPort6 { public: - UDPPort6(); - virtual ~UDPPort6(); + UDPPort6(); + virtual ~UDPPort6(); - int open(const char* ipAddress, uint16_t uniPortNo, const char* broadcastAddr, const char* interfaceName, unsigned int hops); - void close(void); - int unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* sendToAddr); - int broadcast(const uint8_t* buf, uint32_t length); - int recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr); + int open(uint16_t uniPortNo, uint16_t multiPortNo, const char *broadcastAddr, const char *interfaceName, uint32_t hops); + void close(void); + int unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* sendToAddr); + int broadcast(const uint8_t* buf, uint32_t length); + int recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr); private: - void setNonBlocking(const bool); - int recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr); + void setNonBlocking(const bool); + int recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr); - int _sockfdUnicast; - int _sockfdMulticast; - char _interfaceName[10]; - - SensorNetAddress _grpAddr; - SensorNetAddress _clientAddr; - uint16_t _uniPortNo; - bool _disconReq; - unsigned int _hops; + pollfd _pollfds[2]; + SensorNetAddress _grpAddr; + SensorNetAddress _clientAddr; + bool _disconReq; + uint32_t _hops; }; /*=========================================== @@ -93,19 +83,19 @@ private: class SensorNetwork: public UDPPort6 { public: - SensorNetwork(); - ~SensorNetwork(); + 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); - int initialize(void); - const char* getDescription(void); - SensorNetAddress* getSenderAddress(void); + int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto); + int broadcast(const uint8_t* payload, uint16_t payloadLength); + int read(uint8_t* buf, uint16_t bufLen); + void initialize(void); + const char* getDescription(void); + SensorNetAddress* getSenderAddress(void); private: - SensorNetAddress _clientAddr; // Sender's address. not gateway's one. - string _description; + SensorNetAddress _clientAddr; // Sender's address. not gateway's one. + string _description; }; } diff --git a/MQTTSNGateway/src/linux/xbee/SensorNetwork.cpp b/MQTTSNGateway/src/linux/xbee/SensorNetwork.cpp index 502a17d..4be4eae 100644 --- a/MQTTSNGateway/src/linux/xbee/SensorNetwork.cpp +++ b/MQTTSNGateway/src/linux/xbee/SensorNetwork.cpp @@ -11,7 +11,7 @@ * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: - * Tomoaki Yamaguchi - initial API and implementation + * Tomoaki Yamaguchi - initial API and implementation **************************************************************************************/ #include @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -118,7 +119,7 @@ int SensorNetwork::read(uint8_t* buf, uint16_t bufLen) return XBee::recv(buf, bufLen, &_clientAddr); } -int SensorNetwork::initialize(void) +void SensorNetwork::initialize(void) { char param[MQTTSNGW_PARAM_MAX]; uint32_t baudrate = 9600; @@ -145,7 +146,12 @@ int SensorNetwork::initialize(void) _description += ", SerialDevice "; _description += param; - return XBee::open(param, baudrate); + errno =0; + + if ( XBee::open(param, baudrate) < 0 ) + { + throw EXCEPTION("Can't open a XBee", errno); + } } const char* SensorNetwork::getDescription(void) diff --git a/MQTTSNGateway/src/linux/xbee/SensorNetwork.h b/MQTTSNGateway/src/linux/xbee/SensorNetwork.h index 24b8752..c21ce91 100644 --- a/MQTTSNGateway/src/linux/xbee/SensorNetwork.h +++ b/MQTTSNGateway/src/linux/xbee/SensorNetwork.h @@ -25,13 +25,6 @@ using namespace std; 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_RESPONSE 0x90 @@ -126,7 +119,7 @@ public: int unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendto); int broadcast(const uint8_t* payload, uint16_t payloadLength); int read(uint8_t* buf, uint16_t bufLen); - int initialize(void); + void initialize(void); const char* getDescription(void); SensorNetAddress* getSenderAddress(void); diff --git a/MQTTSNGateway/src/mainGateway.cpp b/MQTTSNGateway/src/mainGateway.cpp index 4c6657c..986cacc 100644 --- a/MQTTSNGateway/src/mainGateway.cpp +++ b/MQTTSNGateway/src/mainGateway.cpp @@ -21,30 +21,26 @@ #include "MQTTSNGWPacketHandleTask.h" using namespace MQTTSNGW; - /* * Gateway Application */ Gateway gateway; -PacketHandleTask task1(&gateway); -ClientRecvTask task2(&gateway); -ClientSendTask task3(&gateway); -BrokerRecvTask task4(&gateway); -BrokerSendTask task5(&gateway); +PacketHandleTask task1(&gateway); +ClientRecvTask task2(&gateway); +ClientSendTask task3(&gateway); +BrokerRecvTask task4(&gateway); +BrokerSendTask task5(&gateway); int main(int argc, char** argv) { - gateway.initialize(argc, argv); - gateway.run(); try { - gateway.initialize(argc, argv); - gateway.run(); - } - catch (const std::exception &ex) + gateway.initialize(argc, argv); + gateway.run(); + } + catch (Exception &ex) { - WRITELOG("\nEclipse Paho MQTT-SN Gateway exception: %s\n", ex.what()); - WRITELOG("MQTT-SNGateway [-f Config file name]\n"); - } - return 0; + ex.writeMessage(); + WRITELOG("ABORT Gateway!!!\n\n\n"); + } } diff --git a/MQTTSNGateway/src/mainLogmonitor.cpp b/MQTTSNGateway/src/mainLogmonitor.cpp index f73a2a9..da66757 100644 --- a/MQTTSNGateway/src/mainLogmonitor.cpp +++ b/MQTTSNGateway/src/mainLogmonitor.cpp @@ -19,15 +19,14 @@ using namespace MQTTSNGW; - /* * Logmonitor process */ int main(int argc, char** argv) { - Logmonitor monitor = Logmonitor(); - monitor.initialize(argc, argv); - monitor.run(); - return 0; + Logmonitor monitor = Logmonitor(); + monitor.initialize(argc, argv); + monitor.run(); + return 0; } diff --git a/MQTTSNGateway/src/tests/TestProcess.cpp b/MQTTSNGateway/src/tests/TestProcess.cpp index 56ba0b1..9f1a4ea 100644 --- a/MQTTSNGateway/src/tests/TestProcess.cpp +++ b/MQTTSNGateway/src/tests/TestProcess.cpp @@ -29,7 +29,6 @@ using namespace std; using namespace MQTTSNGW; -#define ARGV "./Build/testPFW" #define CONFDIR "./" #define CONF "gateway.conf" @@ -63,9 +62,8 @@ void TestProcess::run(void) /* Test command line parameter */ assert(1 == getArgc() || 3 == getArgc() ); - assert(0 == strcmp(ARGV, *getArgv())); getParam("BrokerName", value); - assert(0 == strcmp("mqtt.eclipse.org", value)); + assert(0 == strcmp("mqtt.eclipseprojects.io", value)); /* Test RingBuffer */ for ( i = 0; i < 1000; i++) diff --git a/MQTTSNGateway/src/tests/TestTopicIdMap.cpp b/MQTTSNGateway/src/tests/TestTopicIdMap.cpp index ce3ecb3..26b5312 100644 --- a/MQTTSNGateway/src/tests/TestTopicIdMap.cpp +++ b/MQTTSNGateway/src/tests/TestTopicIdMap.cpp @@ -32,13 +32,13 @@ TestTopicIdMap::~TestTopicIdMap() } -bool TestTopicIdMap::testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicTypes type) +bool TestTopicIdMap::testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicid* topic) { TopicIdMapElement* elm = _map->getElement((uint16_t)msgid ); if ( elm ) { //printf("msgid=%d id=%d type=%d\n", msgid, elm->getTopicId(), elm->getTopicType()); - return elm->getTopicId() == id && elm->getTopicType() == type; + return elm->getTopicId() == id && elm->getTopicType() == topic->type; } //printf("msgid=%d\n", msgid); return false; @@ -49,144 +49,161 @@ bool TestTopicIdMap::testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicTyp void TestTopicIdMap::test(void) { uint16_t id[MAXID]; + MQTTSN_topicid topicId; + topicId.data.long_.name = const_cast("topic/test"); + topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; for ( int i = 0; i < MAXID; i++ ) { id[i] = i + 1; - _map->add(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL); + + _map->add(id[i], id[i], &topicId); } for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL)); + assert(testGetElement(id[i], id[i], &topicId)); } for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL)); + assert(!testGetElement(id[i], id[i], &topicId)); } + topicId.type = MQTTSN_TOPIC_TYPE_PREDEFINED; for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED)); + assert(!testGetElement(id[i], id[i], &topicId)); } for ( int i = 0; i < 5; i++ ) { _map->erase(id[i]); } + + topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; for ( int i = 0; i < 5; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL)); + + assert(!testGetElement(id[i], id[i], &topicId)); } for ( int i = 5; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL)); + assert(testGetElement(id[i], id[i], &topicId)); } for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL)); + assert(!testGetElement(id[i], id[i], &topicId)); } _map->clear(); for ( int i = 0; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL)); + assert(!testGetElement(id[i], id[i], &topicId)); } + topicId.type = MQTTSN_TOPIC_TYPE_SHORT; + for ( int i = 0; i < MAXID; i++ ) { - _map->add(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT); + _map->add(id[i], id[i], &topicId); } for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT)); + assert(testGetElement(id[i], id[i], &topicId)); } for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT)); + assert(!testGetElement(id[i], id[i], &topicId)); } + topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_NORMAL)); + assert(!testGetElement(id[i], id[i], &topicId)); } for ( int i = 0; i < 5; i++ ) { _map->erase(id[i]); } + + topicId.type = MQTTSN_TOPIC_TYPE_SHORT; for ( int i = 0; i < 5; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT)); + assert(!testGetElement(id[i], id[i], &topicId)); } for ( int i = 5; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT)); + assert(testGetElement(id[i], id[i], &topicId)); } for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT)); + assert(!testGetElement(id[i], id[i], &topicId)); } _map->clear(); for ( int i = 0; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT)); + assert(!testGetElement(id[i], id[i], &topicId)); } + topicId.type = MQTTSN_TOPIC_TYPE_PREDEFINED; for ( int i = 0; i < MAXID; i++ ) { - _map->add(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED); + _map->add(id[i], id[i], &topicId); } for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED)); + assert(testGetElement(id[i], id[i], &topicId)); } for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED)); + assert(!testGetElement(id[i], id[i], &topicId)); } + topicId.type = MQTTSN_TOPIC_TYPE_SHORT; for ( int i = 0; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_SHORT)); + assert(!testGetElement(id[i], id[i], &topicId)); } for ( int i = 0; i < 5; i++ ) { _map->erase(id[i]); } + + topicId.type = MQTTSN_TOPIC_TYPE_PREDEFINED; for ( int i = 0; i < 5; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED)); + assert(!testGetElement(id[i], id[i], &topicId)); } for ( int i = 5; i < MAX_INFLIGHTMESSAGES * 2 + 1; i++ ) { - assert(testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED)); + assert(testGetElement(id[i], id[i], &topicId)); } for ( int i = MAX_INFLIGHTMESSAGES * 2 + 1; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED)); + assert(!testGetElement(id[i], id[i], &topicId)); } _map->clear(); for ( int i = 0; i < MAXID; i++ ) { - assert(!testGetElement(id[i], id[i], MQTTSN_TOPIC_TYPE_PREDEFINED)); + assert(!testGetElement(id[i], id[i], &topicId)); } printf("[ OK ]\n"); } diff --git a/MQTTSNGateway/src/tests/TestTopicIdMap.h b/MQTTSNGateway/src/tests/TestTopicIdMap.h index 3edceb1..29cd5bd 100644 --- a/MQTTSNGateway/src/tests/TestTopicIdMap.h +++ b/MQTTSNGateway/src/tests/TestTopicIdMap.h @@ -24,7 +24,7 @@ public: TestTopicIdMap(); ~TestTopicIdMap(); void test(void); - bool testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicTypes type); + bool testGetElement(uint16_t msgid, uint16_t id, MQTTSN_topicid* topic); private: TopicIdMap* _map; diff --git a/MQTTSNPacket/samples/CMakeLists.txt b/MQTTSNPacket/samples/CMakeLists.txt index 99300f9..c7fc47b 100644 --- a/MQTTSNPacket/samples/CMakeLists.txt +++ b/MQTTSNPacket/samples/CMakeLists.txt @@ -23,39 +23,39 @@ ADD_EXECUTABLE( qos0pub.c transport.c ) -TARGET_LINK_LIBRARIES(qos0pub MQTTSNPacketClient) +TARGET_LINK_LIBRARIES(qos0pub MQTTSNPacket) ADD_EXECUTABLE( qos0pub_register qos0pub_register.c transport.c ) -TARGET_LINK_LIBRARIES(qos0pub_register MQTTSNPacketClient) +TARGET_LINK_LIBRARIES(qos0pub_register MQTTSNPacket) ADD_EXECUTABLE( qos-1pub qos-1pub.c transport.c ) -TARGET_LINK_LIBRARIES(qos-1pub MQTTSNPacketClient) +TARGET_LINK_LIBRARIES(qos-1pub MQTTSNPacket) ADD_EXECUTABLE( qos-1pub_extended qos-1pub_extended.c transport.c ) -TARGET_LINK_LIBRARIES(qos-1pub_extended MQTTSNPacketClient) +TARGET_LINK_LIBRARIES(qos-1pub_extended MQTTSNPacket) ADD_EXECUTABLE( qos1pub qos1pub.c transport.c ) -TARGET_LINK_LIBRARIES(qos1pub MQTTSNPacketClient) +TARGET_LINK_LIBRARIES(qos1pub MQTTSNPacket) ADD_EXECUTABLE( pub0sub1 pub0sub1.c transport.c ) -TARGET_LINK_LIBRARIES(pub0sub1 MQTTSNPacketClient) +TARGET_LINK_LIBRARIES(pub0sub1 MQTTSNPacket) \ No newline at end of file diff --git a/MQTTSNPacket/samples/build b/MQTTSNPacket/samples/build deleted file mode 100755 index a6e4937..0000000 --- a/MQTTSNPacket/samples/build +++ /dev/null @@ -1,7 +0,0 @@ -gcc -Wall -c transport.c -Os -s -gcc -Wall qos0pub.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos0pub -Os -s -gcc -Wall qos0pub_register.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos0pub_register -Os -s -gcc -Wall qos-1pub.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c -o qos-1pub -Os -s -gcc -Wall qos-1pub_extended.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c -o qos-1pub_extended -Os -s -gcc -Wall qos1pub.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos1pub -Os -s -gcc -Wall pub0sub1.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c ../src/MQTTSNSubscribeClient.c -o pub0sub1 -Os -s diff --git a/MQTTSNPacket/samples/linux/rfcomm/build b/MQTTSNPacket/samples/linux/rfcomm/build new file mode 100644 index 0000000..5c3702f --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/build @@ -0,0 +1,14 @@ +rm -rf bin +mkdir bin +cd bin + +PKTSRC=../../../../src +SRC=.. +gcc -Wall -c $SRC/rfcomm.c -Os -s +gcc -Wall $SRC/qos0pub.c rfcomm.o -lbluetooth -I $PKTSRC $PKTSRC/MQTTSNSerializePublish.c $PKTSRC/MQTTSNPacket.c $PKTSRC/MQTTSNConnectClient.c -o qos0pub -Os -s +gcc -Wall $SRC/qos0pub_register.c rfcomm.o -lbluetooth -I $PKTSRC $PKTSRC/MQTTSNSerializePublish.c $PKTSRC/MQTTSNDeserializePublish.c $PKTSRC/MQTTSNPacket.c $PKTSRC/MQTTSNConnectClient.c -o qos0pub_register -Os -s +gcc -Wall $SRC/qos-1pub.c rfcomm.o -lbluetooth -I $PKTSRC $PKTSRC/MQTTSNSerializePublish.c $PKTSRC/MQTTSNPacket.c -o qos-1pub -Os -s +gcc -Wall $SRC/qos-1pub_extended.c rfcomm.o -lbluetooth -I $PKTSRC $PKTSRC/MQTTSNSerializePublish.c $PKTSRC/MQTTSNPacket.c -o qos-1pub_extended -Os -s +gcc -Wall $SRC/qos1pub.c rfcomm.o -lbluetooth -I $PKTSRC $PKTSRC/MQTTSNSerializePublish.c $PKTSRC/MQTTSNDeserializePublish.c $PKTSRC/MQTTSNPacket.c $PKTSRC/MQTTSNConnectClient.c -o qos1pub -Os -s +gcc -Wall $SRC/pub0sub1.c rfcomm.o -lbluetooth -I $PKTSRC $PKTSRC/MQTTSNSerializePublish.c $PKTSRC/MQTTSNDeserializePublish.c $PKTSRC/MQTTSNPacket.c $PKTSRC/MQTTSNConnectClient.c $PKTSRC/MQTTSNSubscribeClient.c -o pub0sub1 -Os -s +rm rfcomm.o diff --git a/MQTTSNPacket/samples/linux/rfcomm/pub0sub1.c b/MQTTSNPacket/samples/linux/rfcomm/pub0sub1.c new file mode 100644 index 0000000..b0ff3e2 --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/pub0sub1.c @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * 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: + * Ian Craggs - initial API and implementation and/or initial documentation + * Sergio R. Caprile - clarifications and/or documentation extension + * + * Description: + * Normal topic name is automatically registered at subscription, then + * a message is published and the node receives it itself + *******************************************************************************/ + +#include +#include +#include + +#include "MQTTSNPacket.h" +#include "rfcomm.h" + + +int main(int argc, char** argv) +{ + int rc = 0; + unsigned char buf[200]; + int buflen = sizeof(buf); + MQTTSN_topicid topic; + unsigned char* payload = (unsigned char*)"mypayload"; + int payloadlen = strlen((char*)payload); + int len = 0; + unsigned char dup = 0; + int qos = 1; + unsigned char retained = 0; + short packetid = 1; + char *topicname = "a long topic name"; + char *host = ""; + int channel = 1; + MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; + unsigned short topicid; + + if (argc > 1) + host = argv[1]; + + if (argc > 2) + channel = atoi(argv[2]); + + printf("Sending to address %s channel %d\n", host, channel); + if (rfcomm_open(host, channel) < 0) + { + goto exit; + } + + options.clientID.cstring = "pub0sub1 MQTT-SN"; + len = MQTTSNSerialize_connect(buf, buflen, &options); + rc = rfcomm_sendPacketBuffer(buf, len); + + /* wait for connack */ + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_CONNACK) + { + int connack_rc = -1; + + if (MQTTSNDeserialize_connack(&connack_rc, buf, buflen) != 1 || connack_rc != 0) + { + printf("Unable to connect, return code %d\n", connack_rc); + goto exit; + } + else + printf("connected rc %d\n", connack_rc); + } + else + goto exit; + + + /* subscribe */ + printf("Subscribing\n"); + topic.type = MQTTSN_TOPIC_TYPE_NORMAL; + topic.data.long_.name = topicname; + topic.data.long_.len = strlen(topic.data.long_.name); + len = MQTTSNSerialize_subscribe(buf, buflen, 0, 2, packetid, &topic); + rc = rfcomm_sendPacketBuffer(buf, len); + + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_SUBACK) /* wait for suback */ + { + unsigned short submsgid; + int granted_qos; + unsigned char returncode; + + rc = MQTTSNDeserialize_suback(&granted_qos, &topicid, &submsgid, &returncode, buf, buflen); + if (granted_qos != 2 || returncode != 0) + { + printf("granted qos != 2, %d return code %d\n", granted_qos, returncode); + goto exit; + } + else + printf("suback topic id %d\n", topicid); + } + else + goto exit; + + printf("Publishing\n"); + /* publish with short name */ + topic.type = MQTTSN_TOPIC_TYPE_NORMAL; + topic.data.id = topicid; + ++packetid; + len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid, + topic, payload, payloadlen); + rc = rfcomm_sendPacketBuffer(buf, len); + + /* wait for puback */ + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_PUBACK) + { + unsigned short packet_id, topic_id; + unsigned char returncode; + + if (MQTTSNDeserialize_puback(&topic_id, &packet_id, &returncode, buf, buflen) != 1 || returncode != MQTTSN_RC_ACCEPTED) + printf("Unable to publish, return code %d\n", returncode); + else + printf("puback received, msgid %d topic id %d\n", packet_id, topic_id); + } + else + goto exit; + + printf("Receive publish\n"); + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_PUBLISH) + { + unsigned short packet_id; + int qos, payloadlen; + unsigned char* payload; + unsigned char dup, retained; + MQTTSN_topicid pubtopic; + + if (MQTTSNDeserialize_publish(&dup, &qos, &retained, &packet_id, &pubtopic, + &payload, &payloadlen, buf, buflen) != 1) + printf("Error deserializing publish\n"); + else + printf("publish received, id %d qos %d\n", packet_id, qos); + + if (qos == 1) + { + len = MQTTSNSerialize_puback(buf, buflen, pubtopic.data.id, packet_id, MQTTSN_RC_ACCEPTED); + rc = rfcomm_sendPacketBuffer(buf, len); + if (rc == 0) + printf("puback sent\n"); + } + } + else + goto exit; + + len = MQTTSNSerialize_disconnect(buf, buflen, 0); + rc = rfcomm_sendPacketBuffer(buf, len); + +exit: + rfcomm_close(); + + return 0; +} diff --git a/MQTTSNPacket/samples/linux/rfcomm/qos-1pub.c b/MQTTSNPacket/samples/linux/rfcomm/qos-1pub.c new file mode 100644 index 0000000..3931870 --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/qos-1pub.c @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * 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: + * Ian Craggs - initial API and implementation and/or initial documentation + * Sergio R. Caprile - clarifications and/or documentation extension + * + * Description: + * A qos -1 message can be sent without connecting + * Short topic name used to avoid registration process + *******************************************************************************/ + +#include +#include +#include + +#include "MQTTSNPacket.h" +#include "rfcomm.h" + + +int main(int argc, char** argv) +{ + unsigned char buf[200]; + int buflen = sizeof(buf); + MQTTSN_topicid topic; + unsigned char* payload = (unsigned char*)"mypayload"; + int payloadlen = strlen((char*)payload); + int len = 0; + int dup = 0; + int qos = 3; + int retained = 0; + short packetid = 0; + char *host = ""; + int channel = 1; + + if (argc > 1) + host = argv[1]; + + if (argc > 2) + channel = atoi(argv[2]); + + printf("Sending to address %s channel %d\n", host, channel); + if (rfcomm_open(host, channel) < 0) + { + return -1; + } + + /* publish with short name */ + topic.type = MQTTSN_TOPIC_TYPE_SHORT; + memcpy(topic.data.short_name, "tt", 2); + len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid, + topic, payload, payloadlen); + + rfcomm_sendPacketBuffer(buf, len); + + rfcomm_close(); + + return 0; +} diff --git a/MQTTSNPacket/samples/linux/rfcomm/qos-1pub_extended.c b/MQTTSNPacket/samples/linux/rfcomm/qos-1pub_extended.c new file mode 100644 index 0000000..098de73 --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/qos-1pub_extended.c @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * 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: + * Ian Craggs - initial API and implementation and/or initial documentation + * Sergio R. Caprile - clarifications and/or documentation extension + * + * Description: + * Extension to the specs in which a node can send a normal (long) topic name inside the + * payload area to avoid the registration process and the usage of short/predefined types + *******************************************************************************/ + +#include +#include +#include + +#include "MQTTSNPacket.h" +#include "rfcomm.h" + + +int main(int argc, char** argv) +{ + unsigned char buf[200]; + int buflen = sizeof(buf); + MQTTSN_topicid topic; + unsigned char* payload = (unsigned char*)"mypayload"; + int payloadlen = strlen((char*)payload); + int len = 0; + int dup = 0; + int qos = 3; + int retained = 0; + short packetid = 0; + char *topicname = "a long topic name"; + char *host = ""; + int channel = 1; + + if (argc > 1) + host = argv[1]; + + if (argc > 2) + channel = atoi(argv[2]); + + printf("Sending to Address %s channel %d\n", host, channel); + if (rfcomm_open(host, channel) < 0) + { + return -1;; + } + + topic.type = MQTTSN_TOPIC_TYPE_NORMAL; + topic.data.long_.name = topicname; + topic.data.long_.len = strlen(topicname); + + len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid, + topic, payload, payloadlen); + + rfcomm_sendPacketBuffer(buf, len); + + rfcomm_close(); + + return 0; +} diff --git a/MQTTSNPacket/samples/linux/rfcomm/qos0pub.c b/MQTTSNPacket/samples/linux/rfcomm/qos0pub.c new file mode 100644 index 0000000..e2fa09b --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/qos0pub.c @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * 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: + * Ian Craggs - initial API and implementation and/or initial documentation + * Sergio R. Caprile - clarifications and/or documentation extension + * + * Description: + * Short topic name used to avoid registration process + *******************************************************************************/ + +#include +#include +#include + +#include "MQTTSNPacket.h" +#include "rfcomm.h" + + +int main(int argc, char** argv) +{ + int rc = 0; + unsigned char buf[200]; + int buflen = sizeof(buf); + MQTTSN_topicid topic; + unsigned char* payload = (unsigned char*)"mypayload"; + int payloadlen = strlen((char*)payload); + int len = 0; + int dup = 0; + int qos = 0; + int retained = 0; + short packetid = 0; +// char *topicname = "a long topic name"; + char *host = ""; + int channel = 1; + MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; + + if (argc > 1) + host = argv[1]; + + if (argc > 2) + channel = atoi(argv[2]); + + printf("Sending to address %s port %d\n", host, channel); + if (rfcomm_open(host, channel) < 0) + { + goto exit; + } + + options.clientID.cstring = "myclientid"; + len = MQTTSNSerialize_connect(buf, buflen, &options); + rc = rfcomm_sendPacketBuffer(buf, len); + + /* wait for connack */ + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_CONNACK) + { + int connack_rc = -1; + + if (MQTTSNDeserialize_connack(&connack_rc, buf, buflen) != 1 || connack_rc != 0) + { + printf("Unable to connect, return code %d\n", connack_rc); + goto exit; + } + else + printf("connected rc %d\n", connack_rc); + } + else + goto exit; + + + /* publish with short name */ + topic.type = MQTTSN_TOPIC_TYPE_SHORT; + memcpy(topic.data.short_name, "tt", 2); + len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid, + topic, payload, payloadlen); + rc = rfcomm_sendPacketBuffer(buf, len); + + printf("rc %d from send packet for publish length %d\n", rc, len); + +exit: + rfcomm_close(); + + return 0; +} diff --git a/MQTTSNPacket/samples/linux/rfcomm/qos0pub_register.c b/MQTTSNPacket/samples/linux/rfcomm/qos0pub_register.c new file mode 100644 index 0000000..1be0d50 --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/qos0pub_register.c @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * 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: + * Ian Craggs - initial API and implementation and/or initial documentation + * Sergio R. Caprile - clarifications and/or documentation extension + * + * Description: + * Normal topic name used to show registration process + *******************************************************************************/ + +#include +#include +#include + +#include "MQTTSNPacket.h" +#include "rfcomm.h" + + +int main(int argc, char** argv) +{ + int rc = 0; + unsigned char buf[200]; + int buflen = sizeof(buf); + MQTTSN_topicid topic; + MQTTSNString topicstr; + unsigned char* payload = (unsigned char*)"mypayload"; + int payloadlen = strlen((char*)payload); + int len = 0; + int dup = 0; + int qos = 0; + int retained = 0; + short packetid = 0; + char *topicname = "a long topic name"; + char *host = ""; + int channel = 1; + MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; + unsigned short topicid; + + if (argc > 1) + host = argv[1]; + + if (argc > 2) + channel = atoi(argv[2]); + + printf("Sending to address %s channel %d\n", host, channel); + if (rfcomm_open(host, (unsigned char) channel) < 0) + { + goto exit; + } + + options.clientID.cstring = "myclientid"; + len = MQTTSNSerialize_connect(buf, buflen, &options); + rc = rfcomm_sendPacketBuffer(buf, len); + + /* wait for connack */ + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_CONNACK) + { + int connack_rc = -1; + + if (MQTTSNDeserialize_connack(&connack_rc, buf, buflen) != 1 || connack_rc != 0) + { + printf("Unable to connect, return code %d\n", connack_rc); + goto exit; + } + else + printf("connected rc %d\n", connack_rc); + } + else + goto exit; + + /* register topic name */ + printf("Registering\n"); + topicstr.cstring = topicname; + topicstr.lenstring.len = strlen(topicname); + len = MQTTSNSerialize_register(buf, buflen, 0, packetid, &topicstr); + rc = rfcomm_sendPacketBuffer(buf, len); + + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_REGACK) /* wait for regack */ + { + unsigned short submsgid; + unsigned char returncode; + + rc = MQTTSNDeserialize_regack(&topicid, &submsgid, &returncode, buf, buflen); + if (returncode != 0) + { + printf("return code %d\n", returncode); + goto exit; + } + else + printf("regack topic id %d\n", topicid); + } + else + goto exit; + + /* publish with obtained id */ + printf("Publishing\n"); + topic.type = MQTTSN_TOPIC_TYPE_NORMAL; + topic.data.id = topicid; + ++packetid; + len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid, + topic, payload, payloadlen); + rc = rfcomm_sendPacketBuffer(buf, len); + + printf("rc %d from send packet for publish length %d\n", rc, len); + +exit: + rfcomm_close(); + + return 0; +} diff --git a/MQTTSNPacket/samples/linux/rfcomm/qos1pub.c b/MQTTSNPacket/samples/linux/rfcomm/qos1pub.c new file mode 100644 index 0000000..1ab61be --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/qos1pub.c @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * 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: + * Ian Craggs - initial API and implementation and/or initial documentation + * Sergio R. Caprile - clarifications and/or documentation extension + * + * Description: + * Short topic name used to avoid registration process + *******************************************************************************/ + +#include +#include +#include + +#include "MQTTSNPacket.h" +#include "rfcomm.h" + + +int main(int argc, char** argv) +{ + unsigned char buf[200]; + int buflen = sizeof(buf); + MQTTSN_topicid topic; + unsigned char* payload = (unsigned char*)"mypayload"; + int payloadlen = strlen((char*)payload); + int len = 0; + int dup = 0; + int qos = 1; + int retained = 0; + short packetid = 1; + char *host = ""; + int channel = 1; + MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; + + if (argc > 1) + host = argv[1]; + + if (argc > 2) + channel = atoi(argv[2]); + + printf("Sending to address %s channel %d\n", host, channel); + if (rfcomm_open(host, channel) < 0) + { + goto exit; + } + + options.clientID.cstring = "myclientid"; + len = MQTTSNSerialize_connect(buf, buflen, &options); + rfcomm_sendPacketBuffer(buf, len); + + /* wait for connack */ + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_CONNACK) + { + int connack_rc = -1; + + if (MQTTSNDeserialize_connack(&connack_rc, buf, buflen) != 1 || connack_rc != 0) + { + printf("Unable to connect, return code %d\n", connack_rc); + goto exit; + } + else + printf("connected rc %d\n", connack_rc); + } + else + goto exit; + + /* publish with short name */ + topic.type = MQTTSN_TOPIC_TYPE_SHORT; + memcpy(topic.data.short_name, "tt", 2); + len = MQTTSNSerialize_publish(buf, buflen - len, dup, qos, retained, packetid, + topic, payload, payloadlen); + rfcomm_sendPacketBuffer(buf, len); + + /* wait for puback */ + if (MQTTSNPacket_read(buf, buflen, rfcomm_getdata) == MQTTSN_PUBACK) + { + unsigned short packet_id, topic_id; + unsigned char returncode; + + if (MQTTSNDeserialize_puback(&topic_id, &packet_id, &returncode, buf, buflen) != 1 || returncode != MQTTSN_RC_ACCEPTED) + printf("Unable to publish, return code %d\n", returncode); + else + printf("puback received, id %d\n", packet_id); + } + else + goto exit; + + len = MQTTSNSerialize_disconnect(buf, buflen, 0); + rfcomm_sendPacketBuffer(buf, len); + +exit: + rfcomm_close(); + + return 0; +} diff --git a/MQTTSNPacket/samples/linux/rfcomm/rfcomm.c b/MQTTSNPacket/samples/linux/rfcomm/rfcomm.c new file mode 100644 index 0000000..8ade937 --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/rfcomm.c @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2021 tomoaki@tomy-tech.com + * + * 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 implementation + *******************************************************************************/ +#if defined(WIN32) || defined(__APP__) +#error "Only available on Linux." +#endif + + +#if !defined(SOCKET_ERROR) + /** error in socket operation */ + #define SOCKET_ERROR -1 +#endif + +#define INVALID_SOCKET SOCKET_ERROR +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rfcomm.h" + +static int mysock = INVALID_SOCKET; + +int Socket_error(char* aString, int sock) +{ + if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK) + { + if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET)) + { + int orig_errno = errno; + char* errmsg = strerror(errno); + + printf("Socket error %d (%s) in %s for socket %d\n", orig_errno, errmsg, aString, sock); + } + } + return -errno; +} + + +int rfcomm_sendPacketBuffer(unsigned char* buf, int buflen) +{ + int rc = 0; + + if ((rc = write(mysock, buf, buflen)) == SOCKET_ERROR) + { + Socket_error("sendto", mysock); + } + else + { + rc = 0; + } + return rc; +} + + +int rfcomm_getdata(unsigned char* buf, int count) +{ + int rc = recv(mysock, buf, count, 0); + printf("received %d bytes count %d\n", rc, (int) count); + return rc; +} + +/** +return >=0 for a socket descriptor, <0 for an error code +*/ +int rfcomm_open(char* addr, unsigned char channel) +{ + const int reuse = 1; + + mysock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (mysock == INVALID_SOCKET) + return Socket_error("socket", mysock); + + setsockopt(mysock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + + struct sockaddr_rc addru = { 0 }; + addru.rc_family = AF_BLUETOOTH; + addru.rc_channel = channel; + str2ba(addr, &addru.rc_bdaddr); + + // connect to server + errno = 0; + if (connect(mysock, (struct sockaddr *) &addru, sizeof(addru)) < 0) + { + rfcomm_close(); + return Socket_error("connect", mysock); + } + return mysock; +} + +int rfcomm_close() +{ + int rc; + + rc = shutdown(mysock, SHUT_WR); + rc = close(mysock); + mysock = INVALID_SOCKET; + return rc; +} diff --git a/MQTTSNPacket/samples/linux/rfcomm/rfcomm.h b/MQTTSNPacket/samples/linux/rfcomm/rfcomm.h new file mode 100644 index 0000000..1564d04 --- /dev/null +++ b/MQTTSNPacket/samples/linux/rfcomm/rfcomm.h @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * 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: + * Ian Craggs - initial API and implementation and/or initial documentation + * Sergio R. Caprile - "commonalization" from prior samples and/or documentation extension + *******************************************************************************/ + +int rfcom_sendPacketBuffer(unsigned char* buf, int buflen); +int rfcomm_getdata(unsigned char* buf, int count); +int rfcomm_open(char* address, unsigned char channel); +int rfcomm_close(void); diff --git a/MQTTSNPacket/src/CMakeLists.txt b/MQTTSNPacket/src/CMakeLists.txt index 3e53996..cab550f 100644 --- a/MQTTSNPacket/src/CMakeLists.txt +++ b/MQTTSNPacket/src/CMakeLists.txt @@ -17,8 +17,7 @@ PROJECT(mqtt-sn-packet C) -ADD_LIBRARY(MQTTSNPacketClient SHARED MQTTSNConnectClient.c MQTTSNPacket.c MQTTSNSearchClient.c MQTTSNSubscribeClient.c - MQTTSNUnsubscribeClient.c MQTTSNSerializePublish.c MQTTSNDeserializePublish.c) +ADD_LIBRARY(MQTTSNPacket SHARED MQTTSNConnectClient.c MQTTSNPacket.c MQTTSNSearchClient.c MQTTSNSubscribeClient.c + MQTTSNUnsubscribeClient.c MQTTSNSerializePublish.c MQTTSNDeserializePublish.c MQTTSNConnectServer.c MQTTSNPacket.c + MQTTSNSearchServer.c MQTTSNSubscribeServer.c MQTTSNUnsubscribeServer.c MQTTSNSerializePublish.c MQTTSNDeserializePublish.c) -ADD_LIBRARY(MQTTSNPacketServer SHARED MQTTSNConnectServer.c MQTTSNPacket.c MQTTSNSearchServer.c MQTTSNSubscribeServer.c - MQTTSNUnsubscribeServer.c MQTTSNSerializePublish.c MQTTSNDeserializePublish.c) diff --git a/MQTTSNPacket/src/MQTTSNSerializePublish.c b/MQTTSNPacket/src/MQTTSNSerializePublish.c index 256a8d3..2531ba7 100644 --- a/MQTTSNPacket/src/MQTTSNSerializePublish.c +++ b/MQTTSNPacket/src/MQTTSNSerializePublish.c @@ -232,7 +232,7 @@ int MQTTSNSerialize_register(unsigned char* buf, int buflen, unsigned short topi int topicnamelen = 0; FUNC_ENTRY; - topicnamelen = (topicname->cstring) ? strlen(topicname->cstring) : topicname->lenstring.len; + topicnamelen = (topicname->cstring) ? (int)strlen(topicname->cstring) : topicname->lenstring.len; if ((len = MQTTSNPacket_len(MQTTSNSerialize_registerLength(topicnamelen))) > buflen) { rc = MQTTSNPACKET_BUFFER_TOO_SHORT; diff --git a/MQTTSNPacket/test/CMakeLists.txt b/MQTTSNPacket/test/CMakeLists.txt index f6c98b2..4d563b3 100644 --- a/MQTTSNPacket/test/CMakeLists.txt +++ b/MQTTSNPacket/test/CMakeLists.txt @@ -23,7 +23,7 @@ ADD_EXECUTABLE( test1.c ) -TARGET_LINK_LIBRARIES(test1 MQTTSNPacketClient MQTTSNPacketServer) +TARGET_LINK_LIBRARIES(test1 MQTTSNPacket) ADD_TEST(NAME test1 COMMAND test1) @@ -32,4 +32,4 @@ ADD_EXECUTABLE( test2.c ) -TARGET_LINK_LIBRARIES(test2 MQTTSNPacketClient MQTTSNPacketServer) +TARGET_LINK_LIBRARIES(test2 MQTTSNPacket) \ No newline at end of file diff --git a/README.md b/README.md index 5a46018..db89200 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ MQTT project, but it's not yet complete. ## Build requirements / compilation -CMake builds for MQTTSNPacket with a Makefile for MQTTSNGateway have been introduced, along with Travis-CI configuration for automated build & testing. +CMake builds have been introduced, along with Travis-CI configuration for automated build & testing. The travis-build.sh file has the full build and test sequence for Linux. diff --git a/travis-build.sh b/travis-build.sh index 696aa53..1050f92 100755 --- a/travis-build.sh +++ b/travis-build.sh @@ -6,6 +6,24 @@ rm -rf build.paho mkdir build.paho cd build.paho echo "travis build dir $TRAVIS_BUILD_DIR pwd $PWD" -cmake .. +cmake .. -DSENSORNET=loralink make ctest -VV --timeout 600 +cmake .. -DSENSORNET=rfcomm +make MQTT-SNGateway +cmake .. -DSENSORNET=xbee +make MQTT-SNGateway +cmake .. -DSENSORNET=udp6 +make MQTT-SNGateway +cmake .. -DSENSORNET=dtls +make MQTT-SNGateway +cmake .. -DSENSORNET=udp +make MQTT-SNGateway +cd ../MQTTSNGateway/GatewayTester +make SENSORNET=UDP6 +make SENSORNET=DTLS +make SENSORNET=DTLS6 +make SENSORNET=RFCOMM +make SENSORNET=UDP + +