From 5e0b638be5a3ac37db91f96fc337bbb9ec9d200d Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Fri, 25 Aug 2023 08:37:22 -0500 Subject: [PATCH] Add DTLS support to MQTT-SN client --- README.md | 21 +------- examples/include.am | 1 + examples/mqttexample.c | 97 ++++++++++++++++++++++++++++------ examples/mqttexample.h | 5 ++ examples/mqttnet.c | 32 +++-------- examples/mqttnet.h | 21 ++++++++ examples/sn-client/README.md | 82 ++++++++++++++++++++++++++++ examples/sn-client/sn-client.c | 16 +++++- src/mqtt_client.c | 10 ++++ src/mqtt_packet.c | 54 ++++++++++++++----- src/mqtt_socket.c | 27 ++++++---- wolfmqtt/mqtt_client.h | 15 ++++-- wolfmqtt/mqtt_socket.h | 2 +- 13 files changed, 293 insertions(+), 90 deletions(-) create mode 100644 examples/sn-client/README.md diff --git a/README.md b/README.md index 961e7de7a..4399b231d 100644 --- a/README.md +++ b/README.md @@ -189,26 +189,7 @@ This example enables the wolfMQTT client to connect to the IBM Watson Internet o ### MQTT-SN Example The Sensor Network client implements the MQTT-SN protocol for low-bandwidth networks. There are several differences from MQTT, including the ability to use a two byte Topic ID instead the full topic during subscribe and publish. The SN client requires an MQTT-SN gateway. The gateway acts as an intermediary between the SN clients and the broker. This client was tested with the Eclipse Paho MQTT-SN Gateway, which connects by default to the public Eclipse broker, much like our wolfMQTT Client example. The address of the gateway must be configured as the host. The example is located in `/examples/sn-client/`. -A special feature of MQTT-SN is the ability to use QoS level -1 (negative one) to publish to a predefined topic without first connecting to the gateway. There is no feedback in the application if there was an error, so confirmation of the test would involve running the `sn-client` first and watching for the publish from the `sn-client_qos-1`. There is an example provided in `/examples/sn-client/sn-client_qos-1`. It requires some configuration changes of the gateway. - -* Enable the the QoS-1 feature, predefined topics, and change the gateway name in `gateway.conf`: - -``` -QoS-1=YES -PredefinedTopic=YES -PredefinedTopicList=./predefinedTopic.conf -. -. -. -#GatewayName=PahoGateway-01 -GatewayName=WolfGateway -``` - -* Comment out all entries and add a new topic in `predefinedTopic.conf`: - -``` -WolfGatewayQoS-1,wolfMQTT/example/testTopic, 1 -``` +More about MQTT-SN examples in [examples/sn-client/README.md](examples/sn-client/README.md) ### Multithread Example This example exercises the multithreading capabilities of the client library. The client implements two tasks: one that publishes to the broker; and another that waits for messages from the broker. The publish thread is created `NUM_PUB_TASKS` times (10 by default) and sends unique messages to the broker. This feature is enabled using the `--enable-mt` configuration option. The example is located in `/examples/multithread/`. diff --git a/examples/include.am b/examples/include.am index bc64ffee7..b6b44c967 100644 --- a/examples/include.am +++ b/examples/include.am @@ -168,4 +168,5 @@ EXTRA_DIST+= examples/mqttuart.c \ examples/aws/awsiot.vcxproj \ examples/wiot/wiot.vcxproj \ examples/sn-client/sn-client.vcxproj \ + examples/sn-client/README.md \ examples/multithread/multithread.vcxproj diff --git a/examples/mqttexample.c b/examples/mqttexample.c index 9a3a495bb..8e41e80c8 100644 --- a/examples/mqttexample.c +++ b/examples/mqttexample.c @@ -198,8 +198,6 @@ void mqtt_show_usage(MQTTCtx* mqttCtx) PRINTF("-? Help, print this usage"); PRINTF("-h Host to connect to, default: %s", mqttCtx->host); - /* Remove TLS and SNI args for sn-client */ - if(XSTRNCMP(mqttCtx->app_name, "sn-client", 10)){ #ifdef ENABLE_MQTT_TLS PRINTF("-p Port to connect on, default: Normal %d, TLS %d", MQTT_DEFAULT_PORT, MQTT_SECURE_PORT); @@ -207,22 +205,19 @@ void mqtt_show_usage(MQTTCtx* mqttCtx) PRINTF("-A Load CA (validate peer)"); PRINTF("-K Use private key (for TLS mutual auth)"); PRINTF("-c Use certificate (for TLS mutual auth)"); -#ifdef HAVE_SNI - PRINTF("-S Use Host Name Indication, blank defaults to host"); -#endif -#ifdef HAVE_PQC + #ifdef HAVE_SNI + /* Remove SNI args for sn-client */ + if(XSTRNCMP(mqttCtx->app_name, "sn-client", 10)){ + PRINTF("-S Use Host Name Indication, blank defaults to host"); + } + #endif + #ifdef HAVE_PQC PRINTF("-Q Use Key Share with post-quantum algorithm"); -#endif + #endif #else PRINTF("-p Port to connect on, default: %d", MQTT_DEFAULT_PORT); #endif - } - - else{ - PRINTF("-p Port to connect on, default: %d", - MQTT_DEFAULT_PORT); - } PRINTF("-q Qos Level 0-2, default: %d", mqttCtx->qos); PRINTF("-s Disable clean session connect flag"); @@ -401,10 +396,9 @@ int mqtt_parse_args(MQTTCtx* mqttCtx, int argc, char** argv) mqtt_show_usage(mqttCtx); return MY_EX_USAGE; } - - /* Remove TLS and SNI functionality for sn-client */ + + /* Remove SNI functionality for sn-client */ if(!XSTRNCMP(mqttCtx->app_name, "sn-client", 10)){ - mqttCtx->use_tls = 0; #ifdef HAVE_SNI useSNI=0; #endif @@ -646,7 +640,8 @@ int mqtt_tls_cb(MqttClient* client) return rc; } } - #elif defined(WOLFMQTT_ZEPHYR) + #else + /* Note: Zephyr example uses NO_FILESYSTEM */ #ifdef WOLFSSL_ENCRYPTED_KEYS /* Setup password callback for pkcs8 key */ wolfSSL_CTX_set_default_passwd_cb(client->tls.ctx, @@ -714,12 +709,80 @@ int mqtt_tls_cb(MqttClient* client) return rc; } + +#ifdef WOLFMQTT_SN +int mqtt_dtls_cb(MqttClient* client) { +#ifdef WOLFSSL_DTLS + int rc = WOLFSSL_FAILURE; + + client->tls.ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); + if (client->tls.ctx) { + wolfSSL_CTX_set_verify(client->tls.ctx, WOLFSSL_VERIFY_PEER, + mqtt_tls_verify_cb); + + /* default to success */ + rc = WOLFSSL_SUCCESS; + +#if !defined(NO_CERT) && !defined(NO_FILESYSTEM) + if (mTlsCaFile) { + /* Load CA certificate file */ + rc = wolfSSL_CTX_load_verify_locations(client->tls.ctx, + mTlsCaFile, NULL); + if (rc != WOLFSSL_SUCCESS) { + PRINTF("Error loading CA %s: %d (%s)", mTlsCaFile, + rc, wolfSSL_ERR_reason_error_string(rc)); + return rc; + } + } + if (mTlsCertFile && mTlsKeyFile) { + /* Load If using a mutual authentication */ + rc = wolfSSL_CTX_use_certificate_file(client->tls.ctx, + mTlsCertFile, WOLFSSL_FILETYPE_PEM); + if (rc != WOLFSSL_SUCCESS) { + PRINTF("Error loading certificate %s: %d (%s)", mTlsCertFile, + rc, wolfSSL_ERR_reason_error_string(rc)); + return rc; + } + + rc = wolfSSL_CTX_use_PrivateKey_file(client->tls.ctx, + mTlsKeyFile, WOLFSSL_FILETYPE_PEM); + if (rc != WOLFSSL_SUCCESS) { + PRINTF("Error loading key %s: %d (%s)", mTlsKeyFile, + rc, wolfSSL_ERR_reason_error_string(rc)); + return rc; + } + } +#endif + + client->tls.ssl = wolfSSL_new(client->tls.ctx); + if (client->tls.ssl == NULL) { + rc = WOLFSSL_FAILURE; + return rc; + } + } + + PRINTF("MQTT DTLS Setup (%d)", rc); +#else /* WOLFSSL_DTLS */ + (void)client; + int rc = 0; + PRINTF("MQTT DTLS Setup - Must enable DTLS in wolfSSL!"); +#endif + return rc; +} +#endif /* WOLFMQTT_SN */ #else int mqtt_tls_cb(MqttClient* client) { (void)client; return 0; } +#ifdef WOLFMQTT_SN +int mqtt_dtls_cb(MqttClient* client) +{ + (void)client; + return 0; +} +#endif #endif /* ENABLE_MQTT_TLS */ int mqtt_file_load(const char* filePath, byte** fileBuf, int *fileLen) diff --git a/examples/mqttexample.h b/examples/mqttexample.h index 8e4b09e6a..b668ae7f5 100644 --- a/examples/mqttexample.h +++ b/examples/mqttexample.h @@ -188,6 +188,11 @@ int mqtt_parse_args(MQTTCtx* mqttCtx, int argc, char** argv); int err_sys(const char* msg); int mqtt_tls_cb(MqttClient* client); + +#ifdef WOLFMQTT_SN +int mqtt_dtls_cb(MqttClient* client); +#endif + word16 mqtt_get_packetid(void); #ifdef WOLFMQTT_NONBLOCK diff --git a/examples/mqttnet.c b/examples/mqttnet.c index 13be7a525..4339fce57 100644 --- a/examples/mqttnet.c +++ b/examples/mqttnet.c @@ -24,16 +24,7 @@ #include #endif -#include "wolfmqtt/mqtt_client.h" #include "examples/mqttnet.h" -#include "examples/mqttexample.h" -#include "examples/mqttport.h" - -/* Local context for Net callbacks */ -typedef enum { - SOCK_BEGIN = 0, - SOCK_CONN -} NB_Stat; #if 0 /* TODO: add multicast support */ typedef struct MulticastCtx { @@ -41,21 +32,6 @@ typedef struct MulticastCtx { } MulticastCtx; #endif - -typedef struct _SocketContext { - SOCKET_T fd; - NB_Stat stat; - SOCK_ADDR_IN addr; -#ifdef MICROCHIP_MPLAB_HARMONY - word32 bytes; -#endif -#if defined(WOLFMQTT_MULTITHREAD) && defined(WOLFMQTT_ENABLE_STDIN_CAP) - /* "self pipe" -> signal wake sleep() */ - SOCKET_T pfd[2]; -#endif - MQTTCtx* mqttCtx; -} SocketContext; - /* Private functions */ /* -------------------------------------------------------------------------- */ @@ -578,7 +554,7 @@ static int SN_NetConnect(void *context, const char* host, word16 port, struct addrinfo hints; MQTTCtx* mqttCtx = sock->mqttCtx; - PRINTF("NetConnect: Host %s, Port %u, Timeout %d ms, Use TLS %d", + PRINTF("NetConnect: Host %s, Port %u, Timeout %d ms, Use DTLS %d", host, port, timeout_ms, mqttCtx->use_tls); /* Get address information for host and locate IPv4 */ @@ -830,6 +806,12 @@ static int NetRead_ex(void *context, byte* buf, int buf_len, } else { bytes += rc; /* Data */ + #ifdef ENABLE_MQTT_TLS + if (MqttClient_SetFlags(&mqttCtx->client, 0, 0) + & MQTT_CLIENT_FLAG_IS_TLS) { + break; + } + #endif } } diff --git a/examples/mqttnet.h b/examples/mqttnet.h index 877c5e0ee..56ad8c780 100644 --- a/examples/mqttnet.h +++ b/examples/mqttnet.h @@ -27,6 +27,27 @@ #endif #include "examples/mqttexample.h" +#include "examples/mqttport.h" + +/* Local context for Net callbacks */ +typedef enum { + SOCK_BEGIN = 0, + SOCK_CONN +} NB_Stat; + +typedef struct _SocketContext { + SOCKET_T fd; + NB_Stat stat; + SOCK_ADDR_IN addr; +#ifdef MICROCHIP_MPLAB_HARMONY + word32 bytes; +#endif +#if defined(WOLFMQTT_MULTITHREAD) && defined(WOLFMQTT_ENABLE_STDIN_CAP) + /* "self pipe" -> signal wake sleep() */ + SOCKET_T pfd[2]; +#endif + MQTTCtx* mqttCtx; +} SocketContext; /* Functions used to handle the MqttNet structure creation / destruction */ int MqttClientNet_Init(MqttNet* net, MQTTCtx* mqttCtx); diff --git a/examples/sn-client/README.md b/examples/sn-client/README.md new file mode 100644 index 000000000..051b28ba0 --- /dev/null +++ b/examples/sn-client/README.md @@ -0,0 +1,82 @@ +# MQTT-SN Example +The Sensor Network client implements the MQTT-SN protocol for low-bandwidth networks. There are several differences from MQTT, including the ability to use a two byte Topic ID instead the full topic during subscribe and publish. The SN client requires an MQTT-SN gateway. The gateway acts as an intermediary between the SN clients and the broker. This client was tested with the Eclipse Paho MQTT-SN Gateway, which connects by default to the public Eclipse broker, much like our wolfMQTT Client example. The address of the gateway must be configured as the host. The example is located in `/examples/sn-client/`. + +To enable Sensor Network protocol support, configure wolfMQTT using: +`./configure --enable-sn` + +## QoS-1 +A special feature of MQTT-SN is the ability to use QoS level -1 (negative one) to publish to a predefined topic without first connecting to the gateway. There is no feedback in the application if there was an error, so confirmation of the test would involve running the `sn-client` first and watching for the publish from the `sn-client_qos-1`. There is an example provided in `/examples/sn-client/sn-client_qos-1`. It requires some configuration changes of the gateway. + +* Enable the the QoS-1 feature, predefined topics, and change the gateway name in `gateway.conf`: + +``` +QoS-1=YES +PredefinedTopic=YES +PredefinedTopicList=./predefinedTopic.conf +. +. +. +#GatewayName=PahoGateway-01 +GatewayName=WolfGateway +``` + +* Comment out all entries and add a new topic in `predefinedTopic.conf`: + +``` +WolfGatewayQoS-1,wolfMQTT/example/testTopic, 1 +``` + +## MQTT-SN with DTLS +MQTT-SN can be secured using DTLS. This enables encryption of sensor data to the gateway. The Eclipse Paho MQTT-SN Gateway supports DTLS clients. + +To build the Eclipse Paho MQTT-SN Gateway with DTLS: +`/MQTTSNGateway$ ./build.sh dtls` + +To build wolfSSL with DTLS support: +`./configure --enable-dtls && make && sudo make install` + +To run the wolfMQTT sn-client example with DTLS: +`./examples/sn-client/sn-client -t` + +### Notes for Gateway configuration +* To use with local mosquitto broker, edit MQTTSNGateway/gateway.conf. Also set paths to DTLS cert / key. + +``` +-BrokerName=mqtt.eclipseprojects.io ++BrokerName=localhost + +... + +-DtlsCertsKey=/etc/ssl/certs/gateway.pem +-DtlsPrivKey=/etc/ssl/private/privkey.pem ++#DtlsCertsKey=/etc/ssl/certs/gateway.pem ++DtlsCertsKey=//wolfssl/certs/server-cert.pem ++#DtlsPrivKey=/etc/ssl/private/privkey.pem ++DtlsPrivKey=//wolfssl/certs/server-key.pem +``` +* I had to fix a bug in the gateway (could be related to the openssl or compiler version): + +``` +diff --git a/MQTTSNGateway/src/linux/dtls/SensorNetwork.cpp b/MQTTSNGateway/src/linux/dtls/SensorNetwork.cpp +index 3f2dcf3..363d0ba 100644 +--- a/MQTTSNGateway/src/linux/dtls/SensorNetwork.cpp ++++ b/MQTTSNGateway/src/linux/dtls/SensorNetwork.cpp +@@ -308,7 +308,7 @@ Connections::~Connections() + { + for (int i = 0; i < _numfds; i++) + { +- if (_ssls[i] > 0) ++ if (_ssls[i] > (SSL *)0) + { + SSL_shutdown(_ssls[i]); + SSL_free(_ssls[i]); +@@ -416,7 +416,7 @@ void Connections::close(int index) + } + } + +- if (ssl > 0) ++ if (ssl > (SSL *)0) + { + _numfds--; + SSL_shutdown(ssl); +``` diff --git a/examples/sn-client/sn-client.c b/examples/sn-client/sn-client.c index eb5ffcf52..a4fbbfb6a 100644 --- a/examples/sn-client/sn-client.c +++ b/examples/sn-client/sn-client.c @@ -139,9 +139,21 @@ int sn_test(MQTTCtx *mqttCtx) goto exit; } - /* Setup socket direct to gateway (UDP network, so no TLS) */ + /* The client.ctx will be stored in the cert callback ctx during + MqttSocket_Connect for use by mqtt_tls_verify_cb */ + mqttCtx->client.ctx = mqttCtx; + +#if defined(ENABLE_MQTT_TLS) && defined(WOLFSSL_DTLS) + if (mqttCtx->use_tls) { + /* Set the DTLS flag in the client structure to indicate DTLS usage */ + MqttClient_SetFlags(&mqttCtx->client, 0, MQTT_CLIENT_FLAG_IS_DTLS); + } +#endif + + /* Setup socket direct to gateway */ rc = MqttClient_NetConnect(&mqttCtx->client, mqttCtx->host, - mqttCtx->port, DEFAULT_CON_TIMEOUT_MS, 0, NULL); + mqttCtx->port, DEFAULT_CON_TIMEOUT_MS, + mqttCtx->use_tls, NULL /*mqtt_dtls_cb*/); PRINTF("MQTT-SN Socket Connect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); diff --git a/src/mqtt_client.c b/src/mqtt_client.c index c37a443ff..aaa2724d3 100644 --- a/src/mqtt_client.c +++ b/src/mqtt_client.c @@ -2780,6 +2780,16 @@ const char* MqttClient_ReturnCodeToString(int return_code) } #endif /* !WOLFMQTT_NO_ERROR_STRINGS */ +word32 MqttClient_SetFlags(MqttClient *client, word32 mask, word32 flags) +{ + if (client != NULL) { + client->flags &= ~mask; + client->flags |= flags; + return client->flags; + } + return 0; +} + #ifdef WOLFMQTT_SN /* Private functions */ diff --git a/src/mqtt_packet.c b/src/mqtt_packet.c index 63f1d8f56..43ba6e64b 100644 --- a/src/mqtt_packet.c +++ b/src/mqtt_packet.c @@ -3524,14 +3524,18 @@ int SN_Packet_Read(MqttClient *client, byte* rx_buf, int rx_buf_len, int timeout_ms) { int rc, len = 0, remain_read = 0; - word16 total_len = 0; + word16 total_len = 0, idx = 0; switch (client->packet.stat) { case MQTT_PK_BEGIN: { - /* Read first 2 bytes using MSG_PEEK */ - rc = MqttSocket_Peek(client, rx_buf, 2, timeout_ms); + /* Read first 2 bytes */ + if (client->flags & MQTT_CLIENT_FLAG_IS_DTLS) { + rc = MqttSocket_Read(client, rx_buf, 2, timeout_ms); + } else { + rc = MqttSocket_Peek(client, rx_buf, 2, timeout_ms); + } if (rc < 0) { return MqttPacket_HandleNetError(client, rc); } @@ -3544,16 +3548,29 @@ int SN_Packet_Read(MqttClient *client, byte* rx_buf, int rx_buf_len, if (rx_buf[0] == SN_PACKET_LEN_IND){ /* Read length stored in first three bytes, type in fourth */ - rc = MqttSocket_Peek(client, rx_buf, 4, timeout_ms); - if (rc < 0) { - return MqttPacket_HandleNetError(client, rc); + if (client->flags & MQTT_CLIENT_FLAG_IS_DTLS) { + rc = MqttSocket_Read(client, rx_buf+len, 2, timeout_ms); + if (rc < 0) { + return MqttPacket_HandleNetError(client, rc); + } + else if (rc != 2) { + return MqttPacket_HandleNetError(client, + MQTT_TRACE_ERROR(MQTT_CODE_ERROR_NETWORK)); + } + rc += len; } - else if (rc != 4) { - return MqttPacket_HandleNetError(client, - MQTT_TRACE_ERROR(MQTT_CODE_ERROR_NETWORK)); + else { + rc = MqttSocket_Peek(client, rx_buf, 4, timeout_ms); + if (rc < 0) { + return MqttPacket_HandleNetError(client, rc); + } + else if (rc != 4) { + return MqttPacket_HandleNetError(client, + MQTT_TRACE_ERROR(MQTT_CODE_ERROR_NETWORK)); + } + len = rc; } - len = rc; (void)MqttDecode_Num(&rx_buf[1], &total_len); client->packet.header_len = len; } @@ -3580,7 +3597,12 @@ int SN_Packet_Read(MqttClient *client, byte* rx_buf, int rx_buf_len, } else if ((total_len == 2) || (total_len == 4)) { /* Handle peek */ - client->packet.remain_len = total_len; + if (client->flags & MQTT_CLIENT_FLAG_IS_DTLS) { + client->packet.remain_len = total_len - len; + } + else { + client->packet.remain_len = total_len; + } } else { client->packet.remain_len = 0; @@ -3592,16 +3614,22 @@ int SN_Packet_Read(MqttClient *client, byte* rx_buf, int rx_buf_len, client->packet.remain_len = rx_buf_len - client->packet.header_len; } - + if (client->flags & MQTT_CLIENT_FLAG_IS_DTLS) { + total_len -= client->packet.header_len; + idx = client->packet.header_len; + } /* Read whole message */ if (client->packet.remain_len > 0) { - rc = MqttSocket_Read(client, &rx_buf[0], + rc = MqttSocket_Read(client, &rx_buf[idx], total_len, timeout_ms); if (rc <= 0) { return MqttPacket_HandleNetError(client, rc); } remain_read = rc; } + if (client->flags & MQTT_CLIENT_FLAG_IS_DTLS) { + remain_read += client->packet.header_len; + } break; } diff --git a/src/mqtt_socket.c b/src/mqtt_socket.c index 33fe61c50..92344423c 100644 --- a/src/mqtt_socket.c +++ b/src/mqtt_socket.c @@ -124,7 +124,7 @@ static int MqttSocket_WriteDo(MqttClient *client, const byte* buf, int buf_len, int rc; #ifdef ENABLE_MQTT_TLS - if (client->flags & MQTT_CLIENT_FLAG_IS_TLS) { + if (MqttClient_SetFlags(client,0,0) & MQTT_CLIENT_FLAG_IS_TLS) { client->tls.timeout_ms = timeout_ms; client->tls.sockRcWrite = 0; /* init value */ rc = wolfSSL_write(client->tls.ssl, (char*)buf, buf_len); @@ -230,7 +230,7 @@ static int MqttSocket_ReadDo(MqttClient *client, byte* buf, int buf_len, #endif #ifdef ENABLE_MQTT_TLS - if (client->flags & MQTT_CLIENT_FLAG_IS_TLS) { + if (MqttClient_SetFlags(client,0,0) & MQTT_CLIENT_FLAG_IS_TLS) { client->tls.timeout_ms = timeout_ms; client->tls.sockRcRead = 0; /* init value */ rc = wolfSSL_read(client->tls.ssl, (char*)buf, buf_len); @@ -359,7 +359,7 @@ int MqttSocket_Peek(MqttClient *client, byte* buf, int buf_len, int timeout_ms) return rc; } -#endif +#endif /* WOLFMQTT_SN */ int MqttSocket_Connect(MqttClient *client, const char* host, word16 port, int timeout_ms, int use_tls, MqttTlsCb cb) @@ -417,10 +417,17 @@ int MqttSocket_Connect(MqttClient *client, const char* host, word16 port, /* Create and initialize the WOLFSSL_CTX structure */ if (client->tls.ctx == NULL) { /* Use defaults */ - /* Use highest available and allow downgrade. If wolfSSL is built with - * old TLS support, it is possible for a server to force a downgrade to - * an insecure version. */ - client->tls.ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + /* Use highest available and allow downgrade. If wolfSSL is built + * with old TLS support, it is possible for a server to force a + * downgrade to an insecure version. */ + if (!(client->flags & MQTT_CLIENT_FLAG_IS_DTLS)) { + client->tls.ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + } + #ifdef WOLFSSL_DTLS + else { + client->tls.ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); + } + #endif if (client->tls.ctx == NULL) { rc = MQTT_CODE_ERROR_TLS_CONNECT; goto exit; @@ -458,13 +465,14 @@ int MqttSocket_Connect(MqttClient *client, const char* host, word16 port, wolfSSL_SetCertCbCtx(client->tls.ssl, client->ctx); } + MqttClient_SetFlags(client, 0, MQTT_CLIENT_FLAG_IS_TLS); rc = wolfSSL_connect(client->tls.ssl); if (rc != WOLFSSL_SUCCESS) { rc = MQTT_CODE_ERROR_TLS_CONNECT; + MqttClient_SetFlags(client, MQTT_CLIENT_FLAG_IS_TLS, 0); goto exit; } - client->flags |= MQTT_CLIENT_FLAG_IS_TLS; rc = MQTT_CODE_SUCCESS; } @@ -521,7 +529,8 @@ int MqttSocket_Disconnect(MqttClient *client) client->tls.ctx = NULL; } wolfSSL_Cleanup(); - client->flags &= ~MQTT_CLIENT_FLAG_IS_TLS; + MqttClient_SetFlags(client, + (MQTT_CLIENT_FLAG_IS_TLS | MQTT_CLIENT_FLAG_IS_DTLS), 0); #endif /* Make sure socket is closed */ diff --git a/wolfmqtt/mqtt_client.h b/wolfmqtt/mqtt_client.h index ac996767d..61085b293 100644 --- a/wolfmqtt/mqtt_client.h +++ b/wolfmqtt/mqtt_client.h @@ -96,9 +96,18 @@ typedef int (*MqttPublishCb)(MqttPublish* publish); /* Client flags */ enum MqttClientFlags { - MQTT_CLIENT_FLAG_IS_CONNECTED = 0x01, - MQTT_CLIENT_FLAG_IS_TLS = 0x02 + MQTT_CLIENT_FLAG_IS_CONNECTED = 0x01 << 0, + MQTT_CLIENT_FLAG_IS_TLS = 0x01 << 1, + MQTT_CLIENT_FLAG_IS_DTLS = 0x01 << 2 }; +/*! \brief Sets flags in the MqttClient structure. To be used from + the application before calling MqttClient_NetConnect. + * \param client Pointer to MqttClient structure + * \param mask Flags to clear + * \param flags Flags to set + * \return Value of flags in the MqttClient structure + */ +WOLFMQTT_API word32 MqttClient_SetFlags(struct _MqttClient *client, word32 mask, word32 flags); typedef enum _MqttPkStat { MQTT_PK_BEGIN, @@ -510,11 +519,11 @@ WOLFMQTT_API int MqttClient_IsMessageActive( * \param client Pointer to MqttClient structure * \param host Address of the broker server * \param port Optional custom port. If zero will use defaults + * \param timeout_ms Milliseconds until read timeout * \param use_tls If non-zero value will connect with and use TLS for encryption of data * \param cb A function callback for configuration of the SSL context certificate checking - * \param timeout_ms Milliseconds until read timeout * \return MQTT_CODE_SUCCESS or MQTT_CODE_ERROR_* (see enum MqttPacketResponseCodes) */ diff --git a/wolfmqtt/mqtt_socket.h b/wolfmqtt/mqtt_socket.h index 27f68d775..cedc2ed6c 100644 --- a/wolfmqtt/mqtt_socket.h +++ b/wolfmqtt/mqtt_socket.h @@ -98,7 +98,7 @@ WOLFMQTT_LOCAL int MqttSocket_Read(struct _MqttClient *client, byte* buf, #ifdef WOLFMQTT_SN WOLFMQTT_LOCAL int MqttSocket_Peek(struct _MqttClient *client, byte* buf, int buf_len, int timeout_ms); -#endif +#endif /* WOLFMQTT_SN */ WOLFMQTT_LOCAL int MqttSocket_Connect(struct _MqttClient *client, const char* host, word16 port, int timeout_ms, int use_tls, MqttTlsCb cb);