mirror of
https://github.com/eclipse/paho.mqtt-sn.embedded-c.git
synced 2025-12-15 16:36:52 +01:00
The purpose of this branch is to share work in process. Change sellect() of UDP to poll() Rewrite UDP6 for DTLS6 Known bug: can't reconnect DTLS Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
This commit is contained in:
@@ -20,7 +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 \
|
||||
@@ -38,11 +41,13 @@ CXX := g++
|
||||
CPPFLAGS +=
|
||||
|
||||
INCLUDES += -I$(SUBDIR)
|
||||
DEFS :=
|
||||
LIBS +=
|
||||
DEF1 :=
|
||||
DEF2 :=
|
||||
DEFS := -D$(SN) $(DEF1) $(DEF2)
|
||||
LIBS += -L/usr/local/lib -L/usr/local/opt/openssl
|
||||
LDFLAGS :=
|
||||
CXXFLAGS := -Wall -O3 -std=c++11
|
||||
LDADD := -lbluetooth
|
||||
LDADD := -lbluetooth -lssl -lcrypto
|
||||
OUTDIR := Build
|
||||
|
||||
PROG := $(OUTDIR)/$(PROGTEST)
|
||||
@@ -76,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)
|
||||
|
||||
@@ -2,27 +2,6 @@
|
||||
**sample/mainTest.cpp** is a Test sample coading.
|
||||
Each test is described as one function. test1(), test2()...
|
||||
```
|
||||
/*------------------------------------------------------
|
||||
* Test functions
|
||||
*
|
||||
* you can use 4 commands in Test functions
|
||||
*
|
||||
* 1) PUBLISH(const char* topicName,
|
||||
* uint8_t* payload,
|
||||
* uint16_t len,
|
||||
* uint8_t qos,
|
||||
* bool retain = false);
|
||||
*
|
||||
* 2) SUBSCRIBE(const char* topicName,
|
||||
* TopicCallback onPublish,
|
||||
* uint8_t qos);
|
||||
*
|
||||
* 3) UNSUBSCRIBE(const char* topicName);
|
||||
*
|
||||
* 4) DISCONNECT(uint16_t sleepInSecs);
|
||||
*
|
||||
*------------------------------------------------------*/
|
||||
|
||||
void test1(void)
|
||||
{
|
||||
char payload[300];
|
||||
@@ -36,8 +15,34 @@ void test2(void)
|
||||
uint8_t qos = 1;
|
||||
SUBSCRIBE(topic2, on_publish02, qos);
|
||||
}
|
||||
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* MQTT-SN GATEWAY TEST CLIENT
|
||||
*
|
||||
* Supported functions.
|
||||
*
|
||||
* void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
|
||||
*
|
||||
* void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
|
||||
*
|
||||
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
|
||||
*
|
||||
* void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
|
||||
*
|
||||
* void UNSUBSCRIBE ( const char* topicName );
|
||||
*
|
||||
* void UNSUBSCRIBE ( uint16_t topicId );
|
||||
*
|
||||
* void DISCONNECT ( uint16_t sleepInSecs );
|
||||
*
|
||||
* void CONNECT ( void );
|
||||
*
|
||||
* void DISPLAY( format, .....); <== instead of printf()
|
||||
*--------------------------------------------------------------------------
|
||||
|
||||
```
|
||||
**TEST_LIST** is a test senario. Test functions are executed one by one.
|
||||
**TEST_LIST** is a test senario. Test functions are executed interactively.
|
||||
```
|
||||
/*------------------------------------------------------
|
||||
* A List of Test Tasks
|
||||
@@ -54,80 +59,59 @@ TEST_LIST = {// e.g. TEST( Label, Test),
|
||||
};
|
||||
|
||||
```
|
||||
## step1. Define a sensor network
|
||||
|
||||
**UDP** or **Bluetooth** is available as a sensor network.
|
||||
Uncomment a line \#define UDP or RFCOMM in LMqttsnClientApp.h file.
|
||||
**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
|
||||
};
|
||||
```
|
||||
|
||||
/*======================================
|
||||
* Program mode Flag
|
||||
======================================*/
|
||||
//#define CLIENT_MODE
|
||||
#define UDP
|
||||
//#define RFCOMM
|
||||
```
|
||||
|
||||
## step2. Build
|
||||
## How to Build
|
||||
```
|
||||
$ git clone https://github.com/eclipse/paho.mqtt-sn.embedded-c
|
||||
copy codes from the github.
|
||||
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester
|
||||
$ make
|
||||
$ make install
|
||||
$ make clean
|
||||
$ ./build.sh [udp | udp6 | dtls | dtls6 | rfcomm]
|
||||
```
|
||||
MQTT-SNGatewayTester program is copied into ../../../ directory.
|
||||
|
||||
|
||||
## **step3. Execute Gateway Tester.**
|
||||
|
||||
## Execute Gateway Tester
|
||||
```
|
||||
$ cd ../../..
|
||||
$ ./MQTT-SNGatewayTester
|
||||
$ ./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.....
|
||||
|
||||
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 ) :
|
||||
Execute "Step0:Connect" ? ( y/n ) :
|
||||
|
||||
```
|
||||
|
||||
22
MQTTSNGateway/GatewayTester/build.sh
Executable file
22
MQTTSNGateway/GatewayTester/build.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
DEF1="DEF1=${2}"
|
||||
DEF2="DEF2=${3}"
|
||||
|
||||
if [ $1 == "udp" ] ; then
|
||||
make SN=UDP $DEF1 $DEF2
|
||||
elif [ $1 == "udp6" ] ; then
|
||||
make SN=UDP6 $DEF1 $DEF2
|
||||
elif [ $1 == "rfcomm" ] ; then
|
||||
make SN=RFCOMM $DEF1 $DEF2
|
||||
elif [ $1 == "dtls" ] ; then
|
||||
make SN=DTLS $DEF1 $DEF2
|
||||
elif [ $1 == "dtls6" ] ; then
|
||||
make SN=DTLS6 $DEF1 $DEF2
|
||||
elif [ $1 == "clean" ] ; then
|
||||
make clean
|
||||
else
|
||||
echo "Usage: build.sh [ udp | udp6 | rfcomm | dtls | dtls6] | clean"
|
||||
fi
|
||||
|
||||
|
||||
@@ -51,17 +51,26 @@ 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 = { "GatewayTestClient", // ClientId
|
||||
RFCOMMCONF = { "ClientPUB", // ClientId
|
||||
"60:57:18:06:8B:72", // GW Address
|
||||
1, // Rfcomm channel
|
||||
};
|
||||
|
||||
@@ -51,17 +51,26 @@ 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 = { "GatewayTestClient", // ClientId
|
||||
RFCOMMCONF = { "QoS-1_Client01", // ClientId
|
||||
"60:57:18:06:8B:72", // GW Address
|
||||
1, // Rfcomm channel
|
||||
};
|
||||
|
||||
@@ -51,17 +51,26 @@ 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 = { "GatewayTestClient", // ClientId
|
||||
RFCOMMCONF = { "ClientSUB", // ClientId
|
||||
"60:57:18:06:8B:72", // GW Address
|
||||
1, // Rfcomm channel
|
||||
};
|
||||
|
||||
@@ -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,7 +49,7 @@ extern LMqttsnClient* theClient;
|
||||
extern LScreen* theScreen;
|
||||
|
||||
/*------------------------------------------------------
|
||||
* UDP Configuration (theNetcon)
|
||||
* UDP,DTLS Configuration (theNetcon)
|
||||
*------------------------------------------------------*/
|
||||
UDPCONF = { "GatewayTestClient", // ClientId
|
||||
{ 225, 1, 1, 1 }, // Multicast group IP
|
||||
@@ -57,6 +57,16 @@ UDPCONF = { "GatewayTestClient", // ClientId
|
||||
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)
|
||||
*------------------------------------------------------*/
|
||||
|
||||
@@ -200,6 +200,15 @@ int LGwProxy::getConnectResponce(void)
|
||||
{
|
||||
_network.setGwAddress();
|
||||
_gwId = _mqttsnMsg[1];
|
||||
|
||||
#if defined(DTLS) || defined(DTLS6)
|
||||
if (_network.sslConnect() < 0)
|
||||
{
|
||||
DISPLAY(
|
||||
"\033[0m\033[0;32m\n\nLGwProxy::getConnectResponce Can't connect the Gateway via SSL.\033[0m\033[0;37m\n\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
_status = GW_CONNECTING;
|
||||
}
|
||||
else if (_mqttsnMsg[0] == MQTTSN_TYPE_WILLTOPICREQ && _status == GW_WAIT_WILLTOPICREQ)
|
||||
|
||||
@@ -23,7 +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"
|
||||
@@ -43,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
|
||||
|
||||
|
||||
@@ -53,8 +53,14 @@ int main(int argc, char** argv)
|
||||
printf("\n%s", PAHO_COPYRIGHT0);
|
||||
#if defined(UDP)
|
||||
printf(" UDP\n");
|
||||
#elif defined(UDP6)
|
||||
printf(" UDP6\n");
|
||||
#elif defined(RFCOMM)
|
||||
printf(" RFCOMM\n");
|
||||
#elif defined(DTLS)
|
||||
printf(" DTLS\n");
|
||||
#elif defined(DTLS6)
|
||||
printf(" DTLS6\n");
|
||||
#else
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
@@ -17,17 +17,16 @@
|
||||
#ifndef MQTTSNCLIENTAPP_H_
|
||||
#define MQTTSNCLIENTAPP_H_
|
||||
|
||||
/*======================================
|
||||
* Debug Flag
|
||||
======================================*/
|
||||
//#define DEBUG_NW
|
||||
//#define DEBUG_MQTTSN
|
||||
|
||||
/*======================================
|
||||
* Program mode Flag
|
||||
======================================*/
|
||||
//#define CLIENT_MODE
|
||||
#define UDP
|
||||
//#define RFCOMM
|
||||
/*======================================
|
||||
* Debug Flag
|
||||
======================================*/
|
||||
#define DEBUG_NW
|
||||
//#define DEBUG_MQTTSN
|
||||
|
||||
/****************************************
|
||||
MQTT-SN Parameters
|
||||
@@ -75,6 +74,15 @@ struct LUdpConfig
|
||||
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;
|
||||
@@ -97,20 +105,40 @@ typedef enum
|
||||
#define MQTTSN_CONFIG MqttsnConfig theMqttsnConfig
|
||||
#define MQTTSNCONF LMqttsnConfig theMqcon
|
||||
|
||||
#ifdef UDP
|
||||
#define NETWORK_CONFIG UdpConfig theNetworkConfig
|
||||
#if defined(UDP)
|
||||
#define UDPCONF LUdpConfig theNetcon
|
||||
#define RFCOMMCONF LRfcommConfig theConf
|
||||
#define UDP6CONF LUdp6Config theU6Conf
|
||||
#define RFCOMMCONF LRfcommConfig theRfConf
|
||||
#define SENSORNET_CONFIG_t LUdpConfig
|
||||
#else
|
||||
#ifdef RFCOMM
|
||||
#define NETWORK_CONFIG BleConfig theNetworkConfig
|
||||
|
||||
#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 theConf
|
||||
#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
|
||||
#error "UDP and RFCOMM are not defined in LMqttsnClientApp.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define CONNECT(...) theClient->getGwProxy()->connect(__VA_ARGS__)
|
||||
#define PUBLISH(...) theClient->publish(__VA_ARGS__)
|
||||
|
||||
537
MQTTSNGateway/GatewayTester/src/LNetworkDtls.cpp
Normal file
537
MQTTSNGateway/GatewayTester/src/LNetworkDtls.cpp
Normal file
@@ -0,0 +1,537 @@
|
||||
/**************************************************************************************
|
||||
* Copyright (c) 2016, Tomoaki Yamaguchi
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
|
||||
**************************************************************************************/
|
||||
#ifdef DTLS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "LMqttsnClientApp.h"
|
||||
#include "LNetworkDtls.h"
|
||||
#include "LTimer.h"
|
||||
#include "LScreen.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace linuxAsyncClient;
|
||||
|
||||
extern uint16_t getUint16(const uint8_t* pos);
|
||||
extern uint32_t getUint32(const uint8_t* pos);
|
||||
extern LScreen* theScreen;
|
||||
extern bool theClientMode;
|
||||
|
||||
/* Certificate verification. Returns 1 if trusted, else 0 */
|
||||
int verify_cert(int ok, X509_STORE_CTX *ctx);
|
||||
|
||||
/*=========================================
|
||||
Class LNetwork
|
||||
=========================================*/
|
||||
LNetwork::LNetwork()
|
||||
{
|
||||
_sleepflg = false;
|
||||
resetGwAddress();
|
||||
}
|
||||
|
||||
LNetwork::~LNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
|
||||
{
|
||||
return LDtlsPort::multicast(xmitData, (uint32_t) dataLen);
|
||||
}
|
||||
|
||||
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
|
||||
{
|
||||
return LDtlsPort::unicast(xmitData, dataLen);
|
||||
}
|
||||
|
||||
|
||||
uint8_t* LNetwork::getMessage(int *len)
|
||||
{
|
||||
*len = 0;
|
||||
uint16_t recvLen = 0;
|
||||
if (checkRecvBuf())
|
||||
{
|
||||
recvLen = LDtlsPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
|
||||
if (_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (recvLen < 0)
|
||||
{
|
||||
*len = recvLen;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rxDataBuf[0] == 0x01)
|
||||
{
|
||||
*len = getUint16(_rxDataBuf + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*len = _rxDataBuf[0];
|
||||
}
|
||||
return _rxDataBuf;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LNetwork::setGwAddress(void)
|
||||
{
|
||||
_gwPortNo = _portNo;
|
||||
_gwIpAddress = _ipAddress;
|
||||
}
|
||||
|
||||
void LNetwork::resetGwAddress(void)
|
||||
{
|
||||
_gwIpAddress = 0;
|
||||
_gwPortNo = 0;
|
||||
}
|
||||
|
||||
|
||||
bool LNetwork::initialize(LUdpConfig *config)
|
||||
{
|
||||
return LDtlsPort::open(config);
|
||||
}
|
||||
|
||||
void LNetwork::setSleep()
|
||||
{
|
||||
_sleepflg = true;
|
||||
}
|
||||
|
||||
bool LNetwork::isBroadcastable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int LNetwork::sslConnect(void)
|
||||
{
|
||||
return LDtlsPort::sslConnect(_gwIpAddress, _gwPortNo);
|
||||
}
|
||||
|
||||
/*=========================================
|
||||
Class DtlsPort
|
||||
=========================================*/
|
||||
LDtlsPort::LDtlsPort()
|
||||
{
|
||||
_disconReq = false;
|
||||
_sockfdMcast = 0;
|
||||
_sockfdSsl = 0;
|
||||
_castStat = 0;
|
||||
}
|
||||
|
||||
LDtlsPort::~LDtlsPort()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
void LDtlsPort::close()
|
||||
{
|
||||
if (_sockfdMcast > 0)
|
||||
{
|
||||
::close(_sockfdMcast);
|
||||
_sockfdMcast = 0;
|
||||
if (_sockfdSsl > 0)
|
||||
{
|
||||
::close(_sockfdSsl);
|
||||
_sockfdSsl = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LDtlsPort::open(LUdpConfig *config)
|
||||
{
|
||||
char errmsg[256];
|
||||
int optval = 0;
|
||||
|
||||
uint8_t sav = config->ipAddress[3];
|
||||
config->ipAddress[3] = config->ipAddress[0];
|
||||
config->ipAddress[0] = sav;
|
||||
sav = config->ipAddress[2];
|
||||
config->ipAddress[2] = config->ipAddress[1];
|
||||
config->ipAddress[1] = sav;
|
||||
|
||||
_gIpAddr = getUint32((const uint8_t*) config->ipAddress);
|
||||
_gPortNo = htons(config->gPortNo);
|
||||
_uPortNo = htons(config->uPortNo);
|
||||
|
||||
if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
_ctx = SSL_CTX_new(DTLS_client_method());
|
||||
|
||||
if (_ctx == 0)
|
||||
{
|
||||
ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg));
|
||||
DISPLAY("SSL_CTX_new() %s\n", errmsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Client certification and cookie are not required */
|
||||
SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_cert);
|
||||
|
||||
/* setup Multicast socket */
|
||||
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (_sockfdMcast < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in addrm;
|
||||
addrm.sin_family = AF_INET;
|
||||
addrm.sin_port = _gPortNo;
|
||||
addrm.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
optval = 1;
|
||||
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
|
||||
if (::bind(_sockfdMcast, (struct sockaddr*) &addrm, sizeof(addrm)) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
optval = 1;
|
||||
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in LDtlsPort::open\033[0m\033[0;37m\n");
|
||||
DISPLAY("\033[0m\033[0;31m\nerror IP_MULTICAST_LOOP in LDtlsPort::open\033[0m\033[0;37m\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
ip_mreq mreq;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
mreq.imr_multiaddr.s_addr = _gIpAddr;
|
||||
|
||||
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in LDtlsPort::open\033[0m\033[0;37m\n");
|
||||
DISPLAY("\033[0m\033[0;31m\nerror IP_ADD_MEMBERSHIP in LDtlsPort::open\033[0m\033[0;37m\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LDtlsPort::isUnicast()
|
||||
{
|
||||
return (_castStat == STAT_UNICAST);
|
||||
}
|
||||
|
||||
|
||||
int LDtlsPort::unicast(const uint8_t *buf, uint32_t length)
|
||||
{
|
||||
int status = SSL_write(_ssl, buf, length);
|
||||
if (status <= 0)
|
||||
{
|
||||
int rc = 0;
|
||||
SSL_get_error(_ssl, rc);
|
||||
D_NWLOG("errno == %d in LDtlsPort::unicast\n", rc);
|
||||
DISPLAY("errno == %d in LDtlsPort::unicast\n", rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
D_NWLOG("sendto gateway via DTLS ");
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
}
|
||||
D_NWLOG("\n");
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34msendto the gateway via SSL ");
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int LDtlsPort::multicast(const uint8_t *buf, uint32_t length)
|
||||
{
|
||||
struct sockaddr_in dest;
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = _gPortNo;
|
||||
dest.sin_addr.s_addr = _gIpAddr;
|
||||
|
||||
int status = ::sendto(_sockfdMcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
|
||||
if (status < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtlsPort::multicast\033[0m\033[0;37m\n", errno);
|
||||
DISPLAY("\033[0m\033[0;31merrno == %d in LDtlsPort::multicast\033[0m\033[0;37m\n", errno);
|
||||
return errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
D_NWLOG("sendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo));
|
||||
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
DISPLAY(" %02x", *(buf + i));
|
||||
}
|
||||
D_NWLOG("\n");
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo));
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool LDtlsPort::checkRecvBuf()
|
||||
{
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 50000; // 50 msec
|
||||
|
||||
uint8_t buf[2];
|
||||
fd_set recvfds;
|
||||
int maxSock = 0;
|
||||
|
||||
FD_ZERO(&recvfds);
|
||||
if (_sockfdMcast)
|
||||
{
|
||||
FD_SET(_sockfdMcast, &recvfds);
|
||||
}
|
||||
if (_sockfdSsl)
|
||||
{
|
||||
FD_SET(_sockfdSsl, &recvfds);
|
||||
}
|
||||
|
||||
if (_sockfdMcast > _sockfdSsl)
|
||||
{
|
||||
maxSock = _sockfdMcast;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxSock = _sockfdSsl;
|
||||
}
|
||||
|
||||
select(maxSock + 1, &recvfds, 0, 0, &timeout);
|
||||
|
||||
if (FD_ISSET(_sockfdMcast, &recvfds))
|
||||
{
|
||||
if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
|
||||
{
|
||||
_castStat = STAT_MULTICAST;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (FD_ISSET(_sockfdSsl, &recvfds))
|
||||
{
|
||||
if (::recv(_sockfdSsl, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
|
||||
{
|
||||
_castStat = STAT_SSL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_castStat = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int LDtlsPort::recv(uint8_t *buf, uint16_t len, bool flg, uint32_t *ipAddressPtr, in_port_t *portPtr)
|
||||
{
|
||||
int flags = flg ? MSG_DONTWAIT : 0;
|
||||
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
|
||||
}
|
||||
|
||||
int LDtlsPort::recvfrom(uint8_t *buf, uint16_t length, int flags, uint32_t *ipAddressPtr, in_port_t *portPtr)
|
||||
{
|
||||
struct sockaddr_in sender;
|
||||
int status = 0;
|
||||
socklen_t addrlen = sizeof(sender);
|
||||
memset(&sender, 0, addrlen);
|
||||
|
||||
if (_castStat == STAT_SSL)
|
||||
{
|
||||
D_NWLOG("Ucast ");
|
||||
if (SSL_read(_ssl, buf, length) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (_castStat == STAT_MULTICAST)
|
||||
{
|
||||
D_NWLOG("Mcast ");
|
||||
status = ::recvfrom(_sockfdMcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (status < 0 && errno != EAGAIN)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtlsPort::recvfrom \033[0m\033[0;37m\n", errno);
|
||||
DISPLAY("\033[0m\033[0;31merrno == %d in LDtlsPort::recvfrom \033[0m\033[0;37m\n", errno);
|
||||
}
|
||||
else if (status > 0)
|
||||
{
|
||||
*ipAddressPtr = sender.sin_addr.s_addr;
|
||||
*portPtr = sender.sin_port;
|
||||
|
||||
D_NWLOG("recved %-15s:%-6u", inet_ntoa(sender.sin_addr), ntohs(*portPtr));
|
||||
|
||||
for (uint16_t i = 0; i < status; i++)
|
||||
{
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
}
|
||||
D_NWLOG("\n");
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", inet_ntoa(sender.sin_addr), ntohs(*portPtr));
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < status; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int LDtlsPort::sslConnect(uint32_t ipAddress, in_port_t portNo)
|
||||
{
|
||||
int reuse = 1;
|
||||
if (_ssl != 0)
|
||||
{
|
||||
SSL_shutdown(_ssl);
|
||||
SSL_free(_ssl);
|
||||
_sockfdSsl = 0;
|
||||
_ssl = 0;
|
||||
}
|
||||
|
||||
if (_sockfdSsl > 0)
|
||||
{
|
||||
D_NWLOG("LDtlsPort::sslConnect socket exists.\n");
|
||||
::close(_sockfdSsl);
|
||||
}
|
||||
|
||||
_sockfdSsl = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (_sockfdSsl < 0)
|
||||
{
|
||||
D_NWLOG("LDtlsPort::sslConnect Can't create a socket\n");
|
||||
return -1;
|
||||
}
|
||||
setsockopt(_sockfdSsl, SOL_SOCKET, SO_REUSEADDR || SO_REUSEPORT, &reuse, sizeof(reuse));
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = _uPortNo;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if (::bind(_sockfdSsl, (struct sockaddr*) &addr, sizeof(addr)) < 0)
|
||||
{
|
||||
D_NWLOG("LDtlsPort::sslConnect Can't bind a socket\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in dest;
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = portNo;
|
||||
dest.sin_addr.s_addr = ipAddress;
|
||||
int rc = 0;
|
||||
errno = 0;
|
||||
BIO *cbio = BIO_new_dgram(_sockfdSsl, BIO_NOCLOSE);
|
||||
connect(_sockfdSsl, (sockaddr*) &dest, sizeof(sockaddr_in));
|
||||
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest);
|
||||
_ssl = SSL_new(_ctx);
|
||||
SSL_set_bio(_ssl, cbio, cbio);
|
||||
|
||||
D_NWLOG("LDtlsPort::sslConnect connect to %-15s:%-6u\n", inet_ntoa(dest.sin_addr), htons(dest.sin_port));
|
||||
int stat = SSL_connect(_ssl);
|
||||
if (stat != 1)
|
||||
{
|
||||
rc = -1;
|
||||
D_NWLOG("SSL fail to connect\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
D_NWLOG("SSL connected\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int verify_cert(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
117
MQTTSNGateway/GatewayTester/src/LNetworkDtls.h
Normal file
117
MQTTSNGateway/GatewayTester/src/LNetworkDtls.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/**************************************************************************************
|
||||
* Copyright (c) 2016, Tomoaki Yamaguchi
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
|
||||
**************************************************************************************/
|
||||
|
||||
#ifndef NETWORKDTLS_H_
|
||||
#define NETWORKDTLS_H_
|
||||
|
||||
#ifdef DTLS
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <arpa/inet.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#define SOCKET_MAXHOSTNAME 200
|
||||
#define SOCKET_MAXCONNECTIONS 5
|
||||
#define SOCKET_MAXRECV 500
|
||||
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
|
||||
|
||||
#define STAT_UNICAST 1
|
||||
#define STAT_MULTICAST 2
|
||||
#define STAT_SSL 3
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace linuxAsyncClient {
|
||||
/*========================================
|
||||
Class LDtlsPort
|
||||
=======================================*/
|
||||
class LDtlsPort
|
||||
{
|
||||
friend class LNetwork;
|
||||
public:
|
||||
LDtlsPort();
|
||||
virtual ~LDtlsPort();
|
||||
|
||||
bool open(LUdpConfig* config);
|
||||
|
||||
int unicast(const uint8_t *buf, uint32_t length);
|
||||
int multicast( const uint8_t* buf, uint32_t length );
|
||||
int recv(uint8_t* buf, uint16_t len, bool nonblock, uint32_t* ipaddress, in_port_t* port );
|
||||
int recv(uint8_t* buf, int flags);
|
||||
bool checkRecvBuf();
|
||||
bool isUnicast();
|
||||
SSL* getSSL(void);
|
||||
int sslConnect(uint32_t ipAddress, in_port_t port);
|
||||
private:
|
||||
void close();
|
||||
int recvfrom ( uint8_t* buf, uint16_t len, int flags, uint32_t* ipaddress, in_port_t* port );
|
||||
|
||||
int _sockfdMcast;
|
||||
int _sockfdSsl;
|
||||
SSL_CTX *_ctx;
|
||||
SSL *_ssl;
|
||||
in_port_t _gPortNo;
|
||||
in_port_t _uPortNo;
|
||||
uint32_t _gIpAddr;
|
||||
uint8_t _castStat;
|
||||
bool _disconReq;
|
||||
|
||||
};
|
||||
|
||||
#define NO_ERROR 0
|
||||
#define PACKET_EXCEEDS_LENGTH 1
|
||||
/*===========================================
|
||||
Class Network
|
||||
============================================*/
|
||||
class LNetwork: public LDtlsPort
|
||||
{
|
||||
public:
|
||||
LNetwork();
|
||||
~LNetwork();
|
||||
|
||||
int broadcast(const uint8_t* payload, uint16_t payloadLen);
|
||||
int unicast(const uint8_t* payload, uint16_t payloadLen);
|
||||
void setGwAddress(void);
|
||||
void resetGwAddress(void);
|
||||
bool initialize(LUdpConfig* config);
|
||||
uint8_t* getMessage(int* len);
|
||||
bool isBroadcastable();
|
||||
int sslConnect(void);
|
||||
private:
|
||||
void setSleep();
|
||||
int readApiFrame(void);
|
||||
|
||||
uint32_t _gwIpAddress;
|
||||
uint32_t _ipAddress;
|
||||
in_port_t _gwPortNo;
|
||||
in_port_t _portNo;
|
||||
int _returnCode;
|
||||
bool _sleepflg;
|
||||
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
|
||||
|
||||
};
|
||||
|
||||
} /* end of namespace */
|
||||
#endif /* DTLS */
|
||||
#endif /* NETWORKDTLS_H_ */
|
||||
533
MQTTSNGateway/GatewayTester/src/LNetworkDtls6.cpp
Normal file
533
MQTTSNGateway/GatewayTester/src/LNetworkDtls6.cpp
Normal file
@@ -0,0 +1,533 @@
|
||||
/**************************************************************************************
|
||||
* Copyright (c) 2021, Tomoaki Yamaguchi
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
|
||||
**************************************************************************************/
|
||||
#ifdef DTLS6
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <net/if.h>
|
||||
#include <termios.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <poll.h>
|
||||
#include "LMqttsnClientApp.h"
|
||||
#include "LNetworkDtls6.h"
|
||||
#include "LTimer.h"
|
||||
#include "LScreen.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace linuxAsyncClient;
|
||||
|
||||
extern uint16_t getUint16(const uint8_t *pos);
|
||||
extern uint32_t getUint32(const uint8_t *pos);
|
||||
extern LScreen *theScreen;
|
||||
extern bool theClientMode;
|
||||
|
||||
/* Certificate verification. Returns 1 if trusted, else 0 */
|
||||
int verify_cert(int ok, X509_STORE_CTX *ctx);
|
||||
|
||||
/*=========================================
|
||||
Class LNetwork
|
||||
=========================================*/
|
||||
LNetwork::LNetwork()
|
||||
{
|
||||
_sleepflg = false;
|
||||
resetGwAddress();
|
||||
}
|
||||
|
||||
LNetwork::~LNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
|
||||
{
|
||||
return LDtls6Port::multicast(xmitData, (uint32_t) dataLen);
|
||||
}
|
||||
|
||||
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
|
||||
{
|
||||
return LDtls6Port::unicast(xmitData, dataLen);
|
||||
}
|
||||
|
||||
uint8_t* LNetwork::getMessage(int *len)
|
||||
{
|
||||
*len = 0;
|
||||
if (checkRecvBuf())
|
||||
{
|
||||
uint16_t recvLen = LDtls6Port::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
|
||||
int diffAddr = memcmp(_ipAddress.s6_addr, _gwIpAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
|
||||
if (isUnicast() && diffAddr && (_portNo != _gwPortNo))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (recvLen < 0)
|
||||
{
|
||||
*len = recvLen;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rxDataBuf[0] == 0x01)
|
||||
{
|
||||
*len = getUint16(_rxDataBuf + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*len = _rxDataBuf[0];
|
||||
}
|
||||
return _rxDataBuf;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LNetwork::setGwAddress(void)
|
||||
{
|
||||
_gwPortNo = _portNo;
|
||||
memcpy(&_gwIpAddress.s6_addr, &_ipAddress.s6_addr, sizeof(_ipAddress.s6_addr));
|
||||
|
||||
}
|
||||
|
||||
void LNetwork::resetGwAddress(void)
|
||||
{
|
||||
memset(&_gwIpAddress, 0, sizeof(_gwIpAddress));
|
||||
_gwPortNo = 0;
|
||||
}
|
||||
|
||||
bool LNetwork::initialize(LUdp6Config *config)
|
||||
{
|
||||
return LDtls6Port::open(config);
|
||||
}
|
||||
|
||||
void LNetwork::setSleep()
|
||||
{
|
||||
_sleepflg = true;
|
||||
}
|
||||
|
||||
bool LNetwork::isBroadcastable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int LNetwork::sslConnect(void)
|
||||
{
|
||||
return LDtls6Port::sslConnect(_gwIpAddress, _gwPortNo);
|
||||
}
|
||||
|
||||
/*=========================================
|
||||
Class Dtls6Port
|
||||
=========================================*/
|
||||
LDtls6Port::LDtls6Port()
|
||||
{
|
||||
_disconReq = false;
|
||||
memset(_pollfds, 0, sizeof(_pollfds));
|
||||
_sock = 0;
|
||||
_castStat = 0;
|
||||
_ifIndex = 0;
|
||||
_gIpAddrStr = NULL;
|
||||
}
|
||||
|
||||
LDtls6Port::~LDtls6Port()
|
||||
{
|
||||
close();
|
||||
if (_gIpAddrStr)
|
||||
{
|
||||
free(_gIpAddrStr);
|
||||
}
|
||||
}
|
||||
|
||||
void LDtls6Port::close()
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_pollfds[i].fd > 0)
|
||||
{
|
||||
::close(_pollfds[i].fd);
|
||||
_pollfds[i].fd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LDtls6Port::open(LUdp6Config *config)
|
||||
{
|
||||
int optval = 1;
|
||||
int sock = 0;
|
||||
sockaddr_in6 addr6;
|
||||
char errmsg[256];
|
||||
|
||||
_gPortNo = htons(config->gPortNo);
|
||||
_uPortNo = htons(config->uPortNo);
|
||||
|
||||
if (_gPortNo == 0 || _uPortNo == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
_ctx = SSL_CTX_new(DTLS_client_method());
|
||||
|
||||
if (_ctx == 0)
|
||||
{
|
||||
ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg));
|
||||
DISPLAY("SSL_CTX_new() %s\n", errmsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Client certification and cookie are not required */
|
||||
SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_cert);
|
||||
|
||||
if (strlen(config->interface) > 0)
|
||||
{
|
||||
_ifIndex = if_nametoindex(config->interface);
|
||||
_interfaceName = config->interface;
|
||||
}
|
||||
|
||||
/* create a multicast socket */
|
||||
sock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
optval = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
|
||||
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_port = _gPortNo;
|
||||
addr6.sin6_addr = in6addr_any;
|
||||
|
||||
if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror %s ::bind() in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
ipv6_mreq addrm;
|
||||
addrm.ipv6mr_interface = _ifIndex;
|
||||
inet_pton(AF_INET6, config->ipAddress, &addrm.ipv6mr_multiaddr);
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror %s IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
optval = 0;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror %s IPV6_MULTICAST_LOOP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
_pollfds[1].fd = sock;
|
||||
_pollfds[1].events = POLLIN;
|
||||
_gIpAddr.sin6_family = AF_INET6;
|
||||
_gIpAddr.sin6_port = _gPortNo;
|
||||
memcpy(&_gIpAddr.sin6_addr, (const void*) &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr));
|
||||
_gIpAddrStr = strdup(config->ipAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LDtls6Port::isUnicast()
|
||||
{
|
||||
return (_sock == _pollfds[0].fd && _sock > 0);
|
||||
}
|
||||
|
||||
int LDtls6Port::unicast(const uint8_t *buf, uint32_t length)
|
||||
{
|
||||
int status = SSL_write(_ssl, buf, length);
|
||||
if (status <= 0)
|
||||
{
|
||||
int rc = 0;
|
||||
SSL_get_error(_ssl, rc);
|
||||
DISPLAY("errno == %d in LDtls6Port::unicast\n", rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
D_NWLOG("sendto gateway via DTLS ");
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
}D_NWLOG("\n");
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34msendto the gateway via SSL ");
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int LDtls6Port::multicast(const uint8_t *buf, uint32_t length)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
char portStr[8];
|
||||
sprintf(portStr, "%d", ntohs(_gPortNo));
|
||||
|
||||
int status = ::sendto(_pollfds[1].fd, buf, length, 0, (sockaddr*) &_gIpAddr, sizeof(_gIpAddr));
|
||||
if (status < 0)
|
||||
{
|
||||
D_NWLOG("multicast to [%s]:%-6s ", _gIpAddrStr, portStr);D_NWLOG("\033[0m\033[0;31merrno = %d %s in Udp6Port::multicast\033[0m\033[0;37m\n", errno, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
D_NWLOG("multicast to [%s]:%-6s", _gIpAddrStr, portStr);
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
}D_NWLOG("\n");
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
memset(sbuf, 0, SCREEN_BUFF_SIZE);
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34mmulticast to [%s]:%-6s", _gIpAddrStr, portStr);
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
bool LDtls6Port::checkRecvBuf()
|
||||
{
|
||||
uint8_t buf[2];
|
||||
|
||||
int cnt = poll(_pollfds, 2, 2000); // Timeout 2secs
|
||||
if (cnt == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_pollfds[0].revents & POLLIN)
|
||||
{
|
||||
if (::recv(_pollfds[0].fd, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
|
||||
{
|
||||
_castStat = STAT_SSL;
|
||||
_sock = _pollfds[0].fd;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (_pollfds[1].revents & POLLIN)
|
||||
{
|
||||
if (::recv(_pollfds[1].fd, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
|
||||
{
|
||||
_castStat = STAT_MULTICAST;
|
||||
_sock = _pollfds[1].fd;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int LDtls6Port::recv(uint8_t *buf, uint16_t len, bool flg, in6_addr *ipAddressPtr, in_port_t *portPtr)
|
||||
{
|
||||
int flags = flg ? MSG_DONTWAIT : 0;
|
||||
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
|
||||
}
|
||||
|
||||
int LDtls6Port::recvfrom(uint8_t *buf, uint16_t length, int flags, in6_addr *ipAddressPtr, in_port_t *portPtr)
|
||||
{
|
||||
sockaddr_in6 sender;
|
||||
int status = 0;
|
||||
socklen_t addrlen = sizeof(sender);
|
||||
memset(&sender, 0, addrlen);
|
||||
char addrBuf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (_castStat == STAT_SSL)
|
||||
{
|
||||
D_NWLOG("Ucast ");
|
||||
if (SSL_read(_ssl, buf, length) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (_castStat == STAT_MULTICAST)
|
||||
{
|
||||
D_NWLOG("Mcast ");
|
||||
status = ::recvfrom(_sock, buf, length, flags, (sockaddr*) &sender, &addrlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (status < 0 && errno != EAGAIN)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtls6Port::recvfrom \033[0m\033[0;37m\n", errno);
|
||||
DISPLAY("\033[0m\033[0;31merrno == %d in LDtls6Port::recvfrom \033[0m\033[0;37m\n", errno);
|
||||
}
|
||||
else if (status > 0)
|
||||
{
|
||||
inet_ntop(AF_INET6, &sender.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
|
||||
memcpy(ipAddressPtr->s6_addr, (const void*) sender.sin6_addr.s6_addr, sizeof(sender.sin6_addr.s6_addr));
|
||||
*portPtr = sender.sin6_port;
|
||||
|
||||
D_NWLOG("recved %-15s:%-6u", addrBuf, htons(*portPtr));
|
||||
|
||||
for (uint16_t i = 0; i < status; i++)
|
||||
{
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
}D_NWLOG("\n");
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", addrBuf, htons(*portPtr));
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < status; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int LDtls6Port::sslConnect(in6_addr ipAddress, uint16_t portNo)
|
||||
{
|
||||
int optval = 1;
|
||||
int sock = _pollfds[0].fd;
|
||||
|
||||
if (_ssl != 0)
|
||||
{
|
||||
SSL_free(_ssl);
|
||||
}
|
||||
|
||||
if (sock > 0)
|
||||
{
|
||||
::close(sock);
|
||||
}
|
||||
|
||||
sock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (sock <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
optval = 1;
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR || SO_REUSEPORT, &optval, sizeof(optval));
|
||||
|
||||
if (_ifIndex > 0)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &_ifIndex, sizeof(_ifIndex));
|
||||
#else
|
||||
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, _interfaceName.c_str(), _interfaceName.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
struct sockaddr_in6 addr;
|
||||
addr.sin6_family = AF_INET6;
|
||||
addr.sin6_port = _uPortNo;
|
||||
addr.sin6_addr = in6addr_any;
|
||||
|
||||
if (::bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
_pollfds[0].fd = sock;
|
||||
_pollfds[0].events = POLLIN;
|
||||
|
||||
uint16_t listenPort = htons(portNo);
|
||||
struct sockaddr_in6 dest;
|
||||
dest.sin6_family = AF_INET6;
|
||||
dest.sin6_port = htons(listenPort);
|
||||
memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr));
|
||||
|
||||
int rc = 0;
|
||||
|
||||
BIO *cbio = BIO_new_dgram(sock, BIO_NOCLOSE);
|
||||
connect(sock, (sockaddr*) &dest, sizeof(sockaddr_in6));
|
||||
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest);
|
||||
_ssl = SSL_new(_ctx);
|
||||
SSL_set_bio(_ssl, cbio, cbio);
|
||||
|
||||
#ifdef DEBUG_NW
|
||||
char addrBuf[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &dest.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
|
||||
D_NWLOG("connect to %-15s:%-6u\n", addrBuf, ntohs(dest.sin6_port));
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
int stat = SSL_connect(_ssl);
|
||||
if (stat != 1)
|
||||
{
|
||||
rc = -1;
|
||||
D_NWLOG("SSL fail to connect %s\n",strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
D_NWLOG("SSL connected\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int verify_cert(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
121
MQTTSNGateway/GatewayTester/src/LNetworkDtls6.h
Normal file
121
MQTTSNGateway/GatewayTester/src/LNetworkDtls6.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/**************************************************************************************
|
||||
* Copyright (c) 2021, Tomoaki Yamaguchi
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
|
||||
**************************************************************************************/
|
||||
|
||||
#ifndef NETWORKDTLS6_H_
|
||||
#define NETWORKDTLS6_H_
|
||||
|
||||
#ifdef DTLS6
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <arpa/inet.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <poll.h>
|
||||
|
||||
#define SOCKET_MAXHOSTNAME 200
|
||||
#define SOCKET_MAXCONNECTIONS 5
|
||||
#define SOCKET_MAXRECV 500
|
||||
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
|
||||
|
||||
#define STAT_UNICAST 1
|
||||
#define STAT_MULTICAST 2
|
||||
#define STAT_SSL 3
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace linuxAsyncClient {
|
||||
/*========================================
|
||||
Class LDtls6Port
|
||||
=======================================*/
|
||||
class LDtls6Port
|
||||
{
|
||||
friend class LNetwork;
|
||||
public:
|
||||
LDtls6Port();
|
||||
virtual ~LDtls6Port();
|
||||
|
||||
bool open(LUdp6Config* config);
|
||||
|
||||
int unicast(const uint8_t *buf, uint32_t length);
|
||||
int multicast( const uint8_t* buf, uint32_t length );
|
||||
int recv(uint8_t* buf, uint16_t len, bool nonblock, in6_addr* ipaddress, in_port_t* port );
|
||||
int recv(uint8_t* buf, int flags);
|
||||
bool checkRecvBuf();
|
||||
bool isUnicast();
|
||||
SSL* getSSL(void);
|
||||
int sslConnect(in6_addr ipAddress, uint16_t port);
|
||||
private:
|
||||
void close();
|
||||
int recvfrom ( uint8_t* buf, uint16_t len, int flags, in6_addr* ipaddress, in_port_t* port );
|
||||
|
||||
SSL_CTX *_ctx;
|
||||
SSL *_ssl;
|
||||
pollfd _pollfds[2];
|
||||
in_port_t _gPortNo;
|
||||
in_port_t _uPortNo;
|
||||
sockaddr_in6 _gIpAddr;
|
||||
char *_gIpAddrStr;
|
||||
uint32_t _ifIndex;
|
||||
string _interfaceName;
|
||||
uint8_t _castStat;
|
||||
int _sock;
|
||||
bool _disconReq;
|
||||
|
||||
};
|
||||
|
||||
#define NO_ERROR 0
|
||||
#define PACKET_EXCEEDS_LENGTH 1
|
||||
/*===========================================
|
||||
Class Network
|
||||
============================================*/
|
||||
class LNetwork: public LDtls6Port
|
||||
{
|
||||
public:
|
||||
LNetwork();
|
||||
~LNetwork();
|
||||
|
||||
int broadcast(const uint8_t* payload, uint16_t payloadLen);
|
||||
int unicast(const uint8_t* payload, uint16_t payloadLen);
|
||||
void setGwAddress(void);
|
||||
void resetGwAddress(void);
|
||||
bool initialize(LUdp6Config* config);
|
||||
uint8_t* getMessage(int* len);
|
||||
bool isBroadcastable();
|
||||
int sslConnect(void);
|
||||
private:
|
||||
void setSleep();
|
||||
int readApiFrame(void);
|
||||
|
||||
in6_addr _gwIpAddress;
|
||||
in6_addr _ipAddress;
|
||||
in_port_t _gwPortNo;
|
||||
in_port_t _portNo;
|
||||
int _returnCode;
|
||||
bool _sleepflg;
|
||||
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
|
||||
|
||||
};
|
||||
|
||||
} /* end of namespace */
|
||||
#endif /* DTLS6 */
|
||||
#endif /* NETWORKDTLS6_H_ */
|
||||
@@ -13,7 +13,6 @@
|
||||
* Contributors:
|
||||
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
|
||||
**************************************************************************************/
|
||||
#include "LMqttsnClientApp.h"
|
||||
#ifdef RFCOMM
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -29,6 +28,7 @@
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/rfcomm.h>
|
||||
|
||||
#include "LMqttsnClientApp.h"
|
||||
#include "LNetworkRfcomm.h"
|
||||
#include "LTimer.h"
|
||||
#include "LScreen.h"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#ifndef NETWORKRFCOMM_H_
|
||||
#define NETWORKRFCOMM_H_
|
||||
|
||||
#include "LMqttsnClientApp.h"
|
||||
#ifdef RFCOMM
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* Contributors:
|
||||
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
|
||||
**************************************************************************************/
|
||||
#include "LMqttsnClientApp.h"
|
||||
#ifdef UDP
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -27,89 +26,105 @@
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "LMqttsnClientApp.h"
|
||||
#include "LNetworkUdp.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 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()
|
||||
@@ -117,7 +132,7 @@ bool LNetwork::isBroadcastable()
|
||||
return true;
|
||||
}
|
||||
/*=========================================
|
||||
Class udpStack
|
||||
Class udpStack
|
||||
=========================================*/
|
||||
LUdpPort::LUdpPort()
|
||||
{
|
||||
@@ -132,267 +147,302 @@ LUdpPort::~LUdpPort()
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
void LUdpPort::close(){
|
||||
if(_sockfdMcast > 0)
|
||||
{
|
||||
::close( _sockfdMcast);
|
||||
_sockfdMcast = -1;
|
||||
if(_sockfdUcast > 0)
|
||||
{
|
||||
::close( _sockfdUcast);
|
||||
_sockfdUcast = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LUdpPort::open(LUdpConfig* config)
|
||||
void LUdpPort::close()
|
||||
{
|
||||
const int reuse = 1;
|
||||
char loopch = 1;
|
||||
|
||||
uint8_t sav = config->ipAddress[3];
|
||||
config->ipAddress[3] = config->ipAddress[0];
|
||||
config->ipAddress[0] = sav;
|
||||
sav = config->ipAddress[2];
|
||||
config->ipAddress[2] = config->ipAddress[1];
|
||||
config->ipAddress[1] = sav;
|
||||
|
||||
_gPortNo = htons(config->gPortNo);
|
||||
_gIpAddr = getUint32((const uint8_t*)config->ipAddress);
|
||||
_uPortNo = htons(config->uPortNo);
|
||||
|
||||
if( _gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
_sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (_sockfdUcast < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = _uPortNo;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if( ::bind ( _sockfdUcast, (struct sockaddr*)&addr, sizeof(addr)) <0){
|
||||
return false;
|
||||
}
|
||||
|
||||
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (_sockfdMcast < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in addrm;
|
||||
addrm.sin_family = AF_INET;
|
||||
addrm.sin_port = _gPortNo;
|
||||
addrm.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
|
||||
|
||||
if( ::bind ( _sockfdMcast, (struct sockaddr*)&addrm, sizeof(addrm)) <0){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP,(char*)&loopch, sizeof(loopch)) <0 ){
|
||||
D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n");
|
||||
DISPLAY("\033[0m\033[0;31m\nerror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
ip_mreq mreq;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
mreq.imr_multiaddr.s_addr = _gIpAddr;
|
||||
|
||||
if( setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq) )< 0){
|
||||
D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in UdpPort::open\033[0m\033[0;37m\n");
|
||||
DISPLAY("\033[0m\033[0;31m\nerror IP_ADD_MEMBERSHIP in UdpPort::open\033[0m\033[0;37m\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (_sockfdMcast > 0)
|
||||
{
|
||||
::close(_sockfdMcast);
|
||||
_sockfdMcast = -1;
|
||||
if (_sockfdUcast > 0)
|
||||
{
|
||||
::close(_sockfdUcast);
|
||||
_sockfdUcast = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LUdpPort::isUnicast(){
|
||||
return ( _castStat == STAT_UNICAST);
|
||||
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;
|
||||
|
||||
_gPortNo = htons(config->gPortNo);
|
||||
_gIpAddr = getUint32((const uint8_t*) config->ipAddress);
|
||||
_uPortNo = htons(config->uPortNo);
|
||||
|
||||
if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (_sockfdUcast < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
optval = 1;
|
||||
setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = _uPortNo;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (::bind(_sockfdUcast, (struct sockaddr*) &addr, sizeof(addr)) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (_sockfdMcast < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr_in addrm;
|
||||
addrm.sin_family = AF_INET;
|
||||
addrm.sin_port = _gPortNo;
|
||||
addrm.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
optval = 1;
|
||||
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
|
||||
if (::bind(_sockfdMcast, (struct sockaddr*) &addrm, sizeof(addrm)) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ip_mreq mreq;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
mreq.imr_multiaddr.s_addr = _gIpAddr;
|
||||
|
||||
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in UdpPort::open\033[0m\033[0;37m\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
optval= 1;
|
||||
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
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;
|
||||
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::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(_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( _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));
|
||||
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;
|
||||
}
|
||||
|
||||
for(uint16_t i = 0; i < length ; i++){
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
DISPLAY(" %02x", *(buf + i));
|
||||
}
|
||||
D_NWLOG("\n");
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
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));
|
||||
|
||||
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(_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
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#ifndef NETWORKUDP_H_
|
||||
#define NETWORKUDP_H_
|
||||
|
||||
#include "LMqttsnClientApp.h"
|
||||
#ifdef UDP
|
||||
|
||||
#include <sys/time.h>
|
||||
@@ -30,7 +29,6 @@
|
||||
#include <string>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
#define SOCKET_MAXHOSTNAME 200
|
||||
#define SOCKET_MAXCONNECTIONS 5
|
||||
#define SOCKET_MAXRECV 500
|
||||
|
||||
433
MQTTSNGateway/GatewayTester/src/LNetworkUdp6.cpp
Normal file
433
MQTTSNGateway/GatewayTester/src/LNetworkUdp6.cpp
Normal file
@@ -0,0 +1,433 @@
|
||||
/**************************************************************************************
|
||||
* Copyright (c) 2021, Tomoaki Yamaguchi
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
|
||||
**************************************************************************************/
|
||||
#ifdef UDP6
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include "LMqttsnClientApp.h"
|
||||
#include "LNetworkUdp6.h"
|
||||
#include "LTimer.h"
|
||||
#include "LScreen.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace linuxAsyncClient;
|
||||
|
||||
extern uint16_t getUint16(const uint8_t *pos);
|
||||
extern uint32_t getUint32(const uint8_t *pos);
|
||||
extern LScreen *theScreen;
|
||||
extern bool theClientMode;
|
||||
/*=========================================
|
||||
Class LNetwork
|
||||
=========================================*/
|
||||
LNetwork::LNetwork()
|
||||
{
|
||||
_sleepflg = false;
|
||||
resetGwAddress();
|
||||
}
|
||||
|
||||
LNetwork::~LNetwork()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
|
||||
{
|
||||
return LUdp6Port::multicast(xmitData, (uint32_t) dataLen);
|
||||
}
|
||||
|
||||
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
|
||||
{
|
||||
return LUdp6Port::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo);
|
||||
}
|
||||
|
||||
uint8_t* LNetwork::getMessage(int *len)
|
||||
{
|
||||
*len = 0;
|
||||
if (checkRecvBuf())
|
||||
{
|
||||
uint16_t recvLen = LUdp6Port::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
|
||||
int diffAddr = memcmp(_ipAddress.s6_addr, _gwIpAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
|
||||
if (isUnicast() && diffAddr && (_portNo != _gwPortNo))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (recvLen < 0)
|
||||
{
|
||||
*len = recvLen;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rxDataBuf[0] == 0x01)
|
||||
{
|
||||
*len = getUint16(_rxDataBuf + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*len = _rxDataBuf[0];
|
||||
}
|
||||
return _rxDataBuf;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LNetwork::setGwAddress(void)
|
||||
{
|
||||
memcpy(_gwIpAddress.s6_addr, _ipAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
|
||||
_gwPortNo = _portNo;
|
||||
}
|
||||
|
||||
void LNetwork::resetGwAddress(void)
|
||||
{
|
||||
memset(_gwIpAddress.s6_addr, 0, sizeof(_gwIpAddress.s6_addr));
|
||||
_gwPortNo = 0;
|
||||
}
|
||||
|
||||
bool LNetwork::initialize(LUdp6Config *config)
|
||||
{
|
||||
return LUdp6Port::open(config);
|
||||
}
|
||||
|
||||
void LNetwork::setSleep()
|
||||
{
|
||||
_sleepflg = true;
|
||||
}
|
||||
|
||||
bool LNetwork::isBroadcastable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/*=========================================
|
||||
Class udp6Stack
|
||||
=========================================*/
|
||||
LUdp6Port::LUdp6Port()
|
||||
{
|
||||
_disconReq = false;
|
||||
memset(_pollfds, 0, sizeof(_pollfds));
|
||||
_sock = 0;
|
||||
_interface = NULL;
|
||||
_gIpAddrStr = NULL;
|
||||
}
|
||||
|
||||
LUdp6Port::~LUdp6Port()
|
||||
{
|
||||
close();
|
||||
if (_gIpAddrStr)
|
||||
{
|
||||
free(_gIpAddrStr);
|
||||
}
|
||||
if (_interface)
|
||||
{
|
||||
free(_interface);
|
||||
}
|
||||
}
|
||||
|
||||
void LUdp6Port::close()
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_pollfds[i].fd > 0)
|
||||
{
|
||||
::close(_pollfds[i].fd);
|
||||
_pollfds[i].fd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LUdp6Port::open(LUdp6Config *config)
|
||||
{
|
||||
int optval = 1;
|
||||
int sock = 0;
|
||||
uint32_t ifindex = 0;
|
||||
sockaddr_in6 addr6;
|
||||
|
||||
_gPortNo = htons(config->gPortNo);
|
||||
_uPortNo = htons(config->uPortNo);
|
||||
|
||||
if (_gPortNo == 0 || _uPortNo == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* create a unicast socket */
|
||||
sock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
optval = 1;
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
|
||||
if (strlen(config->interface) > 0)
|
||||
{
|
||||
ifindex = if_nametoindex(config->interface);
|
||||
#ifdef __APPLE__
|
||||
setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
|
||||
#else
|
||||
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, config->interface, strlen(config->interface));
|
||||
#endif
|
||||
}
|
||||
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_port = _uPortNo;
|
||||
addr6.sin6_addr = in6addr_any;
|
||||
|
||||
if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror %s ::bind() to unicast address\033[0m\033[0;37m\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
_pollfds[0].fd = sock;
|
||||
_pollfds[0].events = POLLIN;
|
||||
|
||||
/* create a multicast socket */
|
||||
sock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
optval = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
|
||||
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_port = _gPortNo;
|
||||
addr6.sin6_addr = in6addr_any;
|
||||
|
||||
if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror %s ::bind() in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ipv6_mreq addrm;
|
||||
addrm.ipv6mr_interface = ifindex;
|
||||
inet_pton(AF_INET6, config->ipAddress, &addrm.ipv6mr_multiaddr);
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror %s IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
optval = 1;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merror %s IPV6_MULTICAST_LOOP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
_pollfds[1].fd = sock;
|
||||
_pollfds[1].events = POLLIN;
|
||||
_gIpAddr.sin6_family = AF_INET6;
|
||||
_gIpAddr.sin6_port = _gPortNo;
|
||||
memcpy(&_gIpAddr.sin6_addr, (const void*) &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr));
|
||||
_gIpAddrStr = strdup(config->ipAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
int LUdp6Port::unicast(const uint8_t *buf, uint32_t length, in6_addr ipAddress, uint16_t port)
|
||||
{
|
||||
struct sockaddr_in6 dest;
|
||||
dest.sin6_family = AF_INET6;
|
||||
dest.sin6_port = port;
|
||||
memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr));
|
||||
|
||||
char addrBuf[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &dest.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
|
||||
D_NWLOG("unicast to [%s]:%-6u", addrBuf, htons(port));
|
||||
|
||||
int status = ::sendto(_pollfds[0].fd, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
|
||||
if (status < 0)
|
||||
{
|
||||
D_NWLOG(" errno = %d %s in Udp6Port::unicast\n", errno, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
}
|
||||
D_NWLOG("\n");
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34municast to [%s[:%-6u", addrBuf, htons(port));
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int LUdp6Port::multicast(const uint8_t *buf, uint32_t length)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
char portStr[8];
|
||||
sprintf(portStr, "%d", ntohs(_gPortNo));
|
||||
|
||||
int status = ::sendto(_pollfds[1].fd, buf, length, 0, (sockaddr*) &_gIpAddr, sizeof(_gIpAddr));
|
||||
if (status < 0)
|
||||
{
|
||||
D_NWLOG("multicast to [%s]:%-6s ", _gIpAddrStr, portStr);
|
||||
D_NWLOG("\033[0m\033[0;31merrno = %d %s in Udp6Port::multicast\033[0m\033[0;37m\n", errno, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
D_NWLOG("multicast to [%s]:%-6s", _gIpAddrStr, portStr);
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
D_NWLOG(" %02x", *(buf + i));
|
||||
}
|
||||
D_NWLOG("\n");
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
memset(sbuf, 0, SCREEN_BUFF_SIZE);
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34mmulticast to [%s]:%-6s", _gIpAddrStr, portStr);
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
bool LUdp6Port::checkRecvBuf()
|
||||
{
|
||||
uint8_t buf[2];
|
||||
|
||||
int cnt = poll(_pollfds, 2, 2000); // Timeout 2secs
|
||||
if (cnt == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_pollfds[i].revents & POLLIN)
|
||||
{
|
||||
if (::recv(_pollfds[i].fd, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
|
||||
{
|
||||
_sock = _pollfds[i].fd;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
int LUdp6Port::recv(uint8_t *buf, uint16_t len, bool flg, in6_addr *ipAddressPtr, uint16_t *portPtr)
|
||||
{
|
||||
int flags = flg ? MSG_DONTWAIT : 0;
|
||||
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
|
||||
}
|
||||
|
||||
int LUdp6Port::recvfrom(uint8_t *buf, uint16_t length, int flags, in6_addr *ipAddressPtr, uint16_t *portPtr)
|
||||
{
|
||||
struct sockaddr_in6 sender;
|
||||
int status;
|
||||
socklen_t addrlen = sizeof(sender);
|
||||
memset(&sender, 0, addrlen);
|
||||
char addrBuf[INET6_ADDRSTRLEN];
|
||||
|
||||
status = ::recvfrom(_sock, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
|
||||
|
||||
if (status < 0 && errno != EAGAIN)
|
||||
{
|
||||
D_NWLOG("\033[0m\033[0;31merrno == %d in Udp6Port::recvfrom \033[0m\033[0;37m\n", errno);
|
||||
}
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
inet_ntop(AF_INET6, &sender.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
|
||||
memcpy(ipAddressPtr->s6_addr, (const void*) sender.sin6_addr.s6_addr, sizeof(sender.sin6_addr.s6_addr));
|
||||
*portPtr = sender.sin6_port;
|
||||
|
||||
if (!theClientMode)
|
||||
{
|
||||
char sbuf[SCREEN_BUFF_SIZE];
|
||||
int pos = 0;
|
||||
sprintf(sbuf, "\033[0;34mrecv from [%s]:%-6u", addrBuf, htons(*portPtr));
|
||||
pos = strlen(sbuf);
|
||||
for (uint16_t i = 0; i < status; i++)
|
||||
{
|
||||
sprintf(sbuf + pos, " %02x", *(buf + i));
|
||||
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
|
||||
theScreen->display(sbuf);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool LUdp6Port::isUnicast(void)
|
||||
{
|
||||
return (_sock == _pollfds[0].fd && _sock > 0);
|
||||
}
|
||||
#endif /* UDP6 */
|
||||
|
||||
113
MQTTSNGateway/GatewayTester/src/LNetworkUdp6.h
Normal file
113
MQTTSNGateway/GatewayTester/src/LNetworkUdp6.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/**************************************************************************************
|
||||
* Copyright (c) 2021, Tomoaki Yamaguchi
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
|
||||
**************************************************************************************/
|
||||
|
||||
#ifndef NETWORKUDP6_H_
|
||||
#define NETWORKUDP6_H_
|
||||
|
||||
#ifdef UDP6
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <arpa/inet.h>
|
||||
#include <poll.h>
|
||||
|
||||
|
||||
#define SOCKET_MAXHOSTNAME 200
|
||||
#define SOCKET_MAXCONNECTIONS 5
|
||||
#define SOCKET_MAXRECV 500
|
||||
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
|
||||
|
||||
#define STAT_UNICAST 1
|
||||
#define STAT_MULTICAST 2
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace linuxAsyncClient {
|
||||
/*========================================
|
||||
Class LUpd6Port
|
||||
=======================================*/
|
||||
class LUdp6Port
|
||||
{
|
||||
friend class LNetwork;
|
||||
public:
|
||||
LUdp6Port();
|
||||
virtual ~LUdp6Port();
|
||||
|
||||
bool open(LUdp6Config *config);
|
||||
|
||||
int unicast(const uint8_t *buf, uint32_t length, in6_addr ipaddress, uint16_t port);
|
||||
int multicast( const uint8_t* buf, uint32_t length );
|
||||
int recv(uint8_t *buf, uint16_t len, bool nonblock, in6_addr *ipaddress, uint16_t *port);
|
||||
int recv(uint8_t* buf, int flags);
|
||||
bool checkRecvBuf();
|
||||
bool isUnicast();
|
||||
|
||||
private:
|
||||
void close();
|
||||
int recvfrom(uint8_t *buf, uint16_t len, int flags, in6_addr *ipaddress, uint16_t *port);
|
||||
|
||||
pollfd _pollfds[2];
|
||||
uint16_t _gPortNo;
|
||||
uint16_t _uPortNo;
|
||||
sockaddr_in6 _gIpAddr;
|
||||
char *_gIpAddrStr;
|
||||
char* _interface;
|
||||
int _sock;
|
||||
bool _disconReq;
|
||||
|
||||
};
|
||||
|
||||
#define NO_ERROR 0
|
||||
#define PACKET_EXCEEDS_LENGTH 1
|
||||
/*===========================================
|
||||
Class Network
|
||||
============================================*/
|
||||
class LNetwork: public LUdp6Port
|
||||
{
|
||||
public:
|
||||
LNetwork();
|
||||
~LNetwork();
|
||||
|
||||
int broadcast(const uint8_t* payload, uint16_t payloadLen);
|
||||
int unicast(const uint8_t* payload, uint16_t payloadLen);
|
||||
void setGwAddress(void);
|
||||
void resetGwAddress(void);
|
||||
bool initialize(LUdp6Config *config);
|
||||
uint8_t* getMessage(int* len);
|
||||
bool isBroadcastable();
|
||||
private:
|
||||
void setSleep();
|
||||
int readApiFrame(void);
|
||||
|
||||
in6_addr _gwIpAddress;
|
||||
in6_addr _ipAddress;
|
||||
uint16_t _gwPortNo;
|
||||
uint16_t _portNo;
|
||||
int _returnCode;
|
||||
bool _sleepflg;
|
||||
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
|
||||
|
||||
};
|
||||
|
||||
} /* end of namespace */
|
||||
#endif /* UDP6 */
|
||||
#endif /* NETWORKUDP_H_ */
|
||||
Reference in New Issue
Block a user