1 /******************************************************************************* 2 * Copyright (c) 2014, 2017 IBM Corp. 3 * 4 * All rights reserved. This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License v1.0 6 * and Eclipse Distribution License v1.0 which accompany this distribution. 7 * 8 * The Eclipse Public License is available at 9 * http://www.eclipse.org/legal/epl-v10.html 10 * and the Eclipse Distribution License is available at 11 * http://www.eclipse.org/org/documents/edl-v10.php. 12 * 13 * Contributors: 14 * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation 15 * Ian Craggs - documentation and platform specific header 16 * Ian Craggs - add setMessageHandler function 17 *******************************************************************************/ 18 19 #if !defined(MQTT_CLIENT_H) 20 #define MQTT_CLIENT_H 21 22 #if defined(__cplusplus) 23 extern "C" { 24 #endif 25 26 #if defined(WIN32_DLL) || defined(WIN64_DLL) 27 #define DLLImport __declspec(dllimport) 28 #define DLLExport __declspec(dllexport) 29 #elif defined(LINUX_SO) 30 #define DLLImport extern 31 #define DLLExport __attribute__ ((visibility ("default"))) 32 #else 33 #define DLLImport 34 #define DLLExport 35 #endif 36 #include "MQTTLinux.h" 37 #include "MQTTPacket.h" 38 #if defined(MQTTCLIENT_PLATFORM_HEADER) 39 /* The following sequence of macros converts the MQTTCLIENT_PLATFORM_HEADER value 40 * into a string constant suitable for use with include. 41 */ 42 #define xstr(s) str(s) 43 #define str(s) #s 44 #include xstr(MQTTCLIENT_PLATFORM_HEADER) 45 #endif 46 47 #define MAX_PACKET_ID 65535 /* according to the MQTT specification - do not change! */ 48 49 #define MAX_MESSAGE_HANDLERS 50 /* redefinable - how many subscriptions do you want? */ 50 51 #if !defined(MAX_MESSAGE_HANDLERS) 52 #define MAX_MESSAGE_HANDLERS 5 /* redefinable - how many subscriptions do you want? */ 53 #endif 54 55 enum QoS { QOS0, QOS1, QOS2, SUBFAIL = 0x80 }; 56 57 /* all failure return codes must be negative */ 58 enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 }; 59 60 /* The Platform specific header must define the Network and Timer structures and functions 61 * which operate on them. 62 * 63 typedef struct Network 64 { 65 int (*mqttread)(Network*, unsigned char* read_buffer, int, int); 66 int (*mqttwrite)(Network*, unsigned char* send_buffer, int, int); 67 } Network;*/ 68 69 /* The Timer structure must be defined in the platform specific header, 70 * and have the following functions to operate on it. */ 71 extern void TimerInit(Timer*); 72 extern char TimerIsExpired(Timer*); 73 extern void TimerCountdownMS(Timer*, unsigned int); 74 extern void TimerCountdown(Timer*, unsigned int); 75 extern int TimerLeftMS(Timer*); 76 77 typedef struct MQTTMessage { 78 enum QoS qos; 79 unsigned char retained; 80 unsigned char dup; 81 unsigned short id; 82 void *payload; 83 size_t payloadlen; 84 } MQTTMessage; 85 86 typedef struct MessageData { 87 MQTTMessage* message; 88 MQTTString* topicName; 89 } MessageData; 90 91 typedef struct MQTTConnackData { 92 unsigned char rc; 93 unsigned char sessionPresent; 94 } MQTTConnackData; 95 96 typedef struct MQTTSubackData { 97 enum QoS grantedQoS; 98 } MQTTSubackData; 99 100 typedef void (*messageHandler)(MessageData*); 101 102 typedef struct MQTTClient { 103 unsigned int next_packetid, 104 command_timeout_ms; 105 size_t buf_size, 106 readbuf_size; 107 unsigned char *buf, 108 *readbuf; 109 unsigned int keepAliveInterval; 110 char ping_outstanding; 111 int isconnected; 112 int cleansession; 113 bool isAlreadyCloseConnect; 114 struct MessageHandlers 115 { 116 const char* topicFilter; 117 void (*fp) (MessageData*); 118 } messageHandlers[MAX_MESSAGE_HANDLERS]; /* Message handlers are indexed by subscription topic */ 119 120 void (*defaultMessageHandler) (MessageData*); 121 122 Network* ipstack; 123 Timer last_sent, last_received; 124 #if defined(MQTT_TASK) 125 Mutex mutex; 126 Thread thread; 127 #endif 128 } MQTTClient; 129 130 #define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0} 131 132 133 /** 134 * Create an MQTT client object 135 * @param client 136 * @param network 137 * @param command_timeout_ms 138 * @param 139 */ 140 DLLExport void MQTTClientInit(MQTTClient* client, Network* network, unsigned int command_timeout_ms, 141 unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size); 142 143 /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack 144 * The nework object must be connected to the network endpoint before calling this 145 * @param options - connect options 146 * @return success code 147 */ 148 DLLExport int MQTTConnectWithResults(MQTTClient* client, MQTTPacket_connectData* options, 149 MQTTConnackData* data); 150 151 /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack 152 * The nework object must be connected to the network endpoint before calling this 153 * @param options - connect options 154 * @return success code 155 */ 156 DLLExport int MQTTConnect(MQTTClient* client, MQTTPacket_connectData* options); 157 158 /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs 159 * @param client - the client object to use 160 * @param topic - the topic to publish to 161 * @param message - the message to send 162 * @return success code 163 */ 164 DLLExport int MQTTPublish(MQTTClient* client, const char*, MQTTMessage*); 165 int MQTTAsyncPublish(MQTTClient* c, const char* topicName, MQTTMessage* message); 166 167 /** MQTT SetMessageHandler - set or remove a per topic message handler 168 * @param client - the client object to use 169 * @param topicFilter - the topic filter set the message handler for 170 * @param messageHandler - pointer to the message handler function or NULL to remove 171 * @return success code 172 */ 173 DLLExport int MQTTSetMessageHandler(MQTTClient* c, const char* topicFilter, messageHandler messageHandler); 174 175 /** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning. 176 * @param client - the client object to use 177 * @param topicFilter - the topic filter to subscribe to 178 * @param message - the message to send 179 * @return success code 180 */ 181 DLLExport int MQTTSubscribe(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler); 182 DLLExport int MQTTAsyncSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos, messageHandler messageHandler, MQTTSubackData* data); 183 /** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning. 184 * @param client - the client object to use 185 * @param topicFilter - the topic filter to subscribe to 186 * @param message - the message to send 187 * @param data - suback granted QoS returned 188 * @return success code 189 */ 190 DLLExport int MQTTSubscribeWithResults(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler, MQTTSubackData* data); 191 192 /** MQTT Subscribe - send an MQTT unsubscribe packet and wait for unsuback before returning. 193 * @param client - the client object to use 194 * @param topicFilter - the topic filter to unsubscribe from 195 * @return success code 196 */ 197 DLLExport int MQTTUnsubscribe(MQTTClient* client, const char* topicFilter); 198 int MQTTAsyncUnsubscribe(MQTTClient* c, const char* topicFilter); 199 200 /** MQTT Disconnect - send an MQTT disconnect packet and close the connection 201 * @param client - the client object to use 202 * @return success code 203 */ 204 DLLExport int MQTTDisconnect(MQTTClient* client); 205 206 /** MQTT Yield - MQTT background 207 * @param client - the client object to use 208 * @param time - the time, in milliseconds, to yield for 209 * @return success code 210 */ 211 DLLExport int MQTTYield(MQTTClient* client, int time); 212 213 /** MQTT isConnected 214 * @param client - the client object to use 215 * @return truth value indicating whether the client is connected to the server 216 */ 217 DLLExport int MQTTIsConnected(MQTTClient* client); 218 219 #if defined(MQTT_TASK) 220 /** MQTT start background thread for a client. After this, MQTTYield should not be called. 221 * @param client - the client object to use 222 * @return success code 223 */ 224 DLLExport int MQTTStartTask(MQTTClient* client); 225 #endif 226 227 #if defined(__cplusplus) 228 } 229 #endif 230 231 #endif 232