From 9fbfba080a29421c79d81ee4758aea907486f690 Mon Sep 17 00:00:00 2001 From: CIPop Date: Mon, 14 Aug 2023 22:07:29 +0000 Subject: [PATCH] WIP: Separating V3 and V5 client public API. --- MQTTClient-C/src/CMakeLists.txt | 18 +- MQTTClient-C/src/MQTTClient.c | 2 +- MQTTClient-C/src/MQTTClient.h | 2 +- MQTTClient-C/src/MQTTClientCommon.h | 271 +++++++++++++++++++++++ MQTTClient-C/src/{V5 => }/MQTTV5Client.h | 2 +- 5 files changed, 282 insertions(+), 13 deletions(-) create mode 100755 MQTTClient-C/src/MQTTClientCommon.h rename MQTTClient-C/src/{V5 => }/MQTTV5Client.h (99%) diff --git a/MQTTClient-C/src/CMakeLists.txt b/MQTTClient-C/src/CMakeLists.txt index 331196a1..aa09d4aa 100644 --- a/MQTTClient-C/src/CMakeLists.txt +++ b/MQTTClient-C/src/CMakeLists.txt @@ -17,7 +17,7 @@ # MQTTClient Library - C -file(GLOB SOURCES "*.c" "linux/*.c") +file(GLOB SOURCES "*.c" "V3/*.c" "linux/*.c") add_library(paho-embed-mqtt3cc SHARED ${SOURCES}) install(TARGETS paho-embed-mqtt3cc DESTINATION /usr/lib) @@ -26,12 +26,10 @@ target_link_libraries(paho-embed-mqtt3cc paho-embed-mqtt3c) target_compile_definitions(paho-embed-mqtt3cc PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h MQTTCLIENT_QOS2=1) -# TODO: Temporarily disable MQTT v5 -# -# file(GLOB SOURCES "*.c" "V5/*.c" "linux/*.c") -# add_library(paho-embed-mqtt5cc SHARED ${SOURCES}) -# install(TARGETS paho-embed-mqtt5cc DESTINATION /usr/lib) -# target_include_directories(paho-embed-mqtt5cc PRIVATE "linux") -# target_link_libraries(paho-embed-mqtt5cc paho-embed-mqtt5c) -# target_compile_definitions(paho-embed-mqtt5cc PRIVATE -# MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h MQTTCLIENT_QOS2=1 MQTTV5) +file(GLOB SOURCES "*.c" "V5/*.c" "linux/*.c") +add_library(paho-embed-mqtt5cc SHARED ${SOURCES}) +install(TARGETS paho-embed-mqtt5cc DESTINATION /usr/lib) +target_include_directories(paho-embed-mqtt5cc PRIVATE "linux") +target_link_libraries(paho-embed-mqtt5cc paho-embed-mqtt5c) +target_compile_definitions(paho-embed-mqtt5cc PRIVATE + MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h MQTTCLIENT_QOS2=1 MQTTV5) diff --git a/MQTTClient-C/src/MQTTClient.c b/MQTTClient-C/src/MQTTClient.c index 37d70654..9e9e9344 100755 --- a/MQTTClient-C/src/MQTTClient.c +++ b/MQTTClient-C/src/MQTTClient.c @@ -16,7 +16,7 @@ * Ian Craggs - add ability to set message handler separately #6 *******************************************************************************/ #if defined(MQTTV5) -#include "V5/MQTTV5Client.h" +#include "MQTTV5Client.h" #else #include "MQTTClient.h" #endif diff --git a/MQTTClient-C/src/MQTTClient.h b/MQTTClient-C/src/MQTTClient.h index 47328878..3c1ba9c6 100755 --- a/MQTTClient-C/src/MQTTClient.h +++ b/MQTTClient-C/src/MQTTClient.h @@ -232,7 +232,7 @@ typedef struct MQTTClient void (*defaultMessageHandler) (MessageData*); Network* ipstack; - Timer last_sent, last_received, pingresp_timer; + Timer last_sent, last_received, pingresp_timer; #if defined(MQTT_TASK) Mutex mutex; Thread thread; diff --git a/MQTTClient-C/src/MQTTClientCommon.h b/MQTTClient-C/src/MQTTClientCommon.h new file mode 100755 index 00000000..4f31f414 --- /dev/null +++ b/MQTTClient-C/src/MQTTClientCommon.h @@ -0,0 +1,271 @@ +/******************************************************************************* + * Copyright (c) 2023 Microsoft Corporation. All rights reserved. + * + * 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. + * + *******************************************************************************/ + +#if !defined(MQTT_CLIENT_COMMON_H_) +#define MQTT_CLIENT_COMMON_H_ + +#if defined(__cplusplus) + extern "C" { +#endif + +#if defined(WIN32_DLL) || defined(WIN64_DLL) + #define DLLImport __declspec(dllimport) + #define DLLExport __declspec(dllexport) +#elif defined(LINUX_SO) + #define DLLImport extern + #define DLLExport __attribute__ ((visibility ("default"))) +#else + #define DLLImport + #define DLLExport +#endif + +#if defined(MQTTV5) +#include "MQTTV5Packet.h" +#else +#include "MQTTPacket.h" +#endif /* MQTTV5 */ + +#if defined(MQTTCLIENT_PLATFORM_HEADER) +/* The following sequence of macros converts the MQTTCLIENT_PLATFORM_HEADER value + * into a string constant suitable for use with include. + */ +#define xstr(s) str(s) +#define str(s) #s +#include xstr(MQTTCLIENT_PLATFORM_HEADER) +#endif + +#define MAX_PACKET_ID 65535 /* according to the MQTT specification - do not change! */ + +#if !defined(MAX_MESSAGE_HANDLERS) +/** + * @brief The maximum number of message handlers. This can be redefined by the user and applies to all client objects. + * + */ +#define MAX_MESSAGE_HANDLERS 5 /* redefinable - how many subscriptions do you want? */ +#endif + +/// @brief MQTT Quality of Service levels. +enum MQTTQoS { + /// @brief QoS 0: At most once delivery + MQTTQOS_0, + /// @brief QoS 1: At least once delivery + MQTTQOS_1, + /// @brief QoS 2: Exactly once delivery + MQTTQOS_2, + /// @brief SUBACK MQTTv3 failure return code + MQTTQOS_SUBFAIL=0x80 }; + +/* all failure return codes must be negative */ +enum MQTTClientReturnCode { + MQTTCLIENT_BUFFER_OVERFLOW = -2, + MQTTCLIENT_FAILURE = -1, + MQTTCLIENT_SUCCESS = 0 }; + +/* The Platform specific header must define the Network and Timer structures and functions + * which operate on them. + * +typedef struct Network +{ + int (*mqttread)(Network*, unsigned char* read_buffer, int, int); + int (*mqttwrite)(Network*, unsigned char* send_buffer, int, int); +} Network;*/ + +/* The Timer structure must be defined in the platform specific header, + * and have the following functions to operate on it. */ +extern void TimerInit(Timer*); +extern char TimerIsExpired(Timer*); +extern void TimerCountdownMS(Timer*, unsigned int); +extern void TimerCountdown(Timer*, unsigned int); +extern int TimerLeftMS(Timer*); + +/** + * @brief Data structure for holding information about a message. + * + */ +#if defined(MQTTV5) +typedef struct MQTTV5Message +#else +typedef struct MQTTMessage +#endif +{ +#if defined(MQTTV5) + /// @brief The MQTTv5 message properties. + MQTTProperties* properties; +#endif /* MQTTV5 */ + /// @brief The MQTT message QoS. + enum MQTTQoS qos; + /// @brief The MQTT message retained flag. + unsigned char retained; + /// @brief The MQTT message dup flag. + unsigned char dup; + /// @brief The MQTT message identifier. + unsigned short id; + /// @brief The MQTT message payload. + void *payload; + /// @brief The MQTT message `payload` length. + size_t payloadlen; +#if defined(MQTTV5) +} MQTTV5Message; +#else +} MQTTMessage; +#endif + +/** + * @brief Data structure for holding information about a received message. + * + */ +#if defined(MQTTV5) +typedef struct MessageV5Data +{ + /// @brief The MQTT message. + MQTTV5Message* message; + /// @brief The topic to which the message was published. + MQTTString* topicName; +} MessageData; +#else +typedef struct MessageData +{ + /// @brief The MQTT message. + MQTTMessage* message; + /// @brief The topic to which the message was published. + MQTTString* topicName; +} MessageData; +#endif + +/** + * @brief Data structure containing CONNACK information. + * + */ +typedef struct MQTTConnackData +{ +#if defined(MQTTV5) + /// @brief The MQTTv5 message properties. + MQTTProperties* properties; + /// @brief The MQTTv5 reason code. + enum MQTTReasonCodes reasonCode; +#else + /// @brief The MQTTv3 reason code. + unsigned char rc; +#endif /* MQTTV5 */ + /// @brief The MQTT session present flag. + unsigned char sessionPresent; +} MQTTConnackData; + +/** + * @brief Data structure containing SUBACK information. + * + */ +typedef struct MQTTSubackData +{ +#if defined(MQTTV5) + /// @brief The MQTTv5 message properties. + MQTTProperties* properties; + /// @brief The MQTT reason code. + enum MQTTReasonCodes reasonCode; +#else + /// @brief The MQTT granted QoS or `MQTTQOS_SUBFAIL` on failure. + enum MQTTQoS grantedQoS; +#endif /* MQTTV5 */ +} MQTTSubackData; + +/** + * @brief Data structure containing information about a published message. + * @remark This structure is used for both QoS1 (PUBACK) and QoS2 (PUBCOMP) messages. + * @remark The `id` field is omitted as it is already present in the `MQTTMessage` structure. + */ +typedef struct MQTTPubDoneData +{ +#if defined(MQTTV5) + /// @brief The MQTTv5 message properties. + MQTTProperties* properties; + /// @brief The MQTTv5 reason code. + enum MQTTReasonCodes reasonCode; +#endif /* MQTTV5 */ + /// @brief The MQTT message dup flag. + unsigned char dup; +} MQTTPubDoneData; + +/** + * @brief Callback type for handling incoming messages. + * @remark Separate callbacks can be used for each subscription filter. + * + * @param received The received message. + */ +typedef void (*messageHandler)(MessageData* received); + +#if defined(MQTTV5) +/** + * @brief Callback type used for asynchronous MQTTv5 DISCONNECT and AUTH. + * @remark Separate callbacks should be used for each control message type. + * + * @param properties The MQTTv5 message properties. + * @param reasonCode The MQTTv5 reason code. + * @param id The MQTT message identifier. + * + */ +typedef void (*controlHandler)(MQTTProperties* properties, enum MQTTReasonCodes reasonCode, unsigned short id); +#endif /* MQTTV5 */ + +/** + * @brief The MQTTClient handle. + * @note This structure should be treated as opaque by the user. + * + */ +typedef struct MQTTClient +{ + unsigned int next_packetid, + command_timeout_ms; + size_t buf_size, + readbuf_size; + unsigned char *buf, + *readbuf; + unsigned int keepAliveInterval; + char ping_outstanding; + int isconnected; + +#if defined(MQTTV5) + int cleanstart; + MQTTProperties* recvProperties; +#else + int cleansession; +#endif /* MQTTV5 */ + + struct MessageHandlers + { + const char* topicFilter; + void (*fp) (MessageData*); + } messageHandlers[MAX_MESSAGE_HANDLERS]; /* Message handlers are indexed by subscription topic */ + + void (*defaultMessageHandler) (MessageData*); + + Network* ipstack; + Timer last_sent, last_received, pingresp_timer; +#if defined(MQTT_TASK) + Mutex mutex; + Thread thread; +#endif +} MQTTClient; // TODO Rename to MQTTV5Client for V5. + +/** + * @brief Default initializer for an MQTTClient structure. + * + */ +#define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0} + + +#if defined(__cplusplus) + } +#endif + +#endif /* MQTT_CLIENT_COMMON_H_ */ diff --git a/MQTTClient-C/src/V5/MQTTV5Client.h b/MQTTClient-C/src/MQTTV5Client.h similarity index 99% rename from MQTTClient-C/src/V5/MQTTV5Client.h rename to MQTTClient-C/src/MQTTV5Client.h index a32259d5..02306c17 100755 --- a/MQTTClient-C/src/V5/MQTTV5Client.h +++ b/MQTTClient-C/src/MQTTV5Client.h @@ -20,7 +20,7 @@ #endif #include -#include "../MQTTClient.h" +#include "MQTTClientCommon.h" #include "MQTTV5Packet.h"