• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2009, 2022 IBM Corp., Ian Craggs and others
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v2.0
6  * and Eclipse Distribution License v1.0 which accompany this distribution.
7  *
8  * The Eclipse Public License is available at
9  *    https://www.eclipse.org/legal/epl-2.0/
10  * and the Eclipse Distribution License is available at
11  *   http://www.eclipse.org/org/documents/edl-v10.php.
12  *
13  * Contributors:
14  *    Ian Craggs - initial API and implementation and/or initial documentation
15  *    Ian Craggs, Allan Stockdill-Mander - SSL updates
16  *    Ian Craggs - multiple server connection support
17  *    Ian Craggs - MQTT 3.1.1 support
18  *    Ian Craggs - remove const from eyecatchers #168
19  *******************************************************************************/
20 
21 /**
22  * @cond MQTTClient_internal
23  * @mainpage MQTT Client Library Internals
24  * In the beginning there was one MQTT C client library, MQTTClient, as implemented in MQTTClient.c
25  * This library was designed to be easy to use for applications which didn't mind if some of the calls
26  * blocked for a while.  For instance, the MQTTClient_connect call will block until a successful
27  * connection has completed, or a connection has failed, which could be as long as the "connection
28  * timeout" interval, whose default is 30 seconds.
29  *
30  * However in mobile devices and other windowing environments, blocking on the GUI thread is a bad
31  * thing as it causes the user interface to freeze.  Hence a new API, MQTTAsync, implemented
32  * in MQTTAsync.c, was devised.  There are no blocking calls in this library, so it is well suited
33  * to GUI and mobile environments, at the expense of some extra complexity.
34  *
35  * Both libraries are designed to be sparing in the use of threads.  So multiple client objects are
36  * handled by one or two threads, with a select call in Socket_getReadySocket(), used to determine
37  * when a socket has incoming data.  This API is thread safe: functions may be called by multiple application
38  * threads, with the exception of ::MQTTClient_yield and ::MQTTClient_receive, which are intended
39  * for single threaded environments only.
40  *
41  * @endcond
42  * @cond MQTTClient_main
43  * @mainpage MQTT Client library for C (MQTTClient)
44  * © Copyright 2009, 2022 IBM Corp., Ian Craggs and others
45  *
46  * @brief An MQTT client library in C.
47  *
48  * These pages describe the original more synchronous API which might be
49  * considered easier to use.  Some of the calls will block.  For the new
50  * totally asynchronous API where no calls block, which is especially suitable
51  * for use in windowed environments, see the
52  * <a href="../../MQTTAsync/html/index.html">MQTT C Client Asynchronous API Documentation</a>.
53  * The MQTTClient API is not thread safe, whereas the MQTTAsync API is.
54  *
55  * An MQTT client application connects to MQTT-capable servers.
56  * A typical client is responsible for collecting information from a telemetry
57  * device and publishing the information to the server. It can also subscribe
58  * to topics, receive messages, and use this information to control the
59  * telemetry device.
60  *
61  * MQTT clients implement the published MQTT v3 protocol. You can write your own
62  * API to the MQTT protocol using the programming language and platform of your
63  * choice. This can be time-consuming and error-prone.
64  *
65  * To simplify writing MQTT client applications, this library encapsulates
66  * the MQTT v3 protocol for you. Using this library enables a fully functional
67  * MQTT client application to be written in a few lines of code.
68  * The information presented here documents the API provided
69  * by the MQTT Client library for C.
70  *
71  * <b>Using the client</b><br>
72  * Applications that use the client library typically use a similar structure:
73  * <ul>
74  * <li>Create a client object</li>
75  * <li>Set the options to connect to an MQTT server</li>
76  * <li>Set up callback functions if multi-threaded (asynchronous mode)
77  * operation is being used (see @ref async).</li>
78  * <li>Subscribe to any topics the client needs to receive</li>
79  * <li>Repeat until finished:</li>
80  *     <ul>
81  *     <li>Publish any messages the client needs to</li>
82  *     <li>Handle any incoming messages</li>
83  *     </ul>
84  * <li>Disconnect the client</li>
85  * <li>Free any memory being used by the client</li>
86  * </ul>
87  * Some simple examples are shown here:
88  * <ul>
89  * <li>@ref pubsync</li>
90  * <li>@ref pubasync</li>
91  * <li>@ref subasync</li>
92  * </ul>
93  * Additional information about important concepts is provided here:
94  * <ul>
95  * <li>@ref async</li>
96  * <li>@ref callbacks</li>
97  * <li>@ref wildcard</li>
98  * <li>@ref qos</li>
99  * <li>@ref tracing</li>
100  * </ul>
101  * @endcond
102  */
103 
104 /*
105 /// @cond EXCLUDE
106 */
107 #if !defined(MQTTCLIENT_H)
108 #define MQTTCLIENT_H
109 
110 #if defined(__cplusplus)
111  extern "C" {
112 #endif
113 
114 #include <stdio.h>
115 /*
116 /// @endcond
117 */
118 
119 #include "MQTTExportDeclarations.h"
120 
121 #include "MQTTProperties.h"
122 #include "MQTTReasonCodes.h"
123 #include "MQTTSubscribeOpts.h"
124 #if !defined(NO_PERSISTENCE)
125 #include "MQTTClientPersistence.h"
126 #endif
127 
128 /**
129  * Return code: No error. Indicates successful completion of an MQTT client
130  * operation.
131  */
132 #define MQTTCLIENT_SUCCESS 0
133 /**
134  * Return code: A generic error code indicating the failure of an MQTT client
135  * operation.
136  */
137 #define MQTTCLIENT_FAILURE -1
138 
139 /* error code -2 is MQTTCLIENT_PERSISTENCE_ERROR */
140 
141 /**
142  * Return code: The client is disconnected.
143  */
144 #define MQTTCLIENT_DISCONNECTED -3
145 /**
146  * Return code: The maximum number of messages allowed to be simultaneously
147  * in-flight has been reached.
148  */
149 #define MQTTCLIENT_MAX_MESSAGES_INFLIGHT -4
150 /**
151  * Return code: An invalid UTF-8 string has been detected.
152  */
153 #define MQTTCLIENT_BAD_UTF8_STRING -5
154 /**
155  * Return code: A NULL parameter has been supplied when this is invalid.
156  */
157 #define MQTTCLIENT_NULL_PARAMETER -6
158 /**
159  * Return code: The topic has been truncated (the topic string includes
160  * embedded NULL characters). String functions will not access the full topic.
161  * Use the topic length value to access the full topic.
162  */
163 #define MQTTCLIENT_TOPICNAME_TRUNCATED -7
164 /**
165  * Return code: A structure parameter does not have the correct eyecatcher
166  * and version number.
167  */
168 #define MQTTCLIENT_BAD_STRUCTURE -8
169 /**
170  * Return code: A QoS value that falls outside of the acceptable range (0,1,2)
171  */
172 #define MQTTCLIENT_BAD_QOS -9
173 /**
174  * Return code: Attempting SSL connection using non-SSL version of library
175  */
176 #define MQTTCLIENT_SSL_NOT_SUPPORTED -10
177  /**
178   * Return code: unrecognized MQTT version
179   */
180  #define MQTTCLIENT_BAD_MQTT_VERSION -11
181 /**
182  * Return code: protocol prefix in serverURI should be:
183  * @li @em tcp:// or @em mqtt:// - Insecure TCP
184  * @li @em ssl:// or @em mqtts:// - Encrypted SSL/TLS
185  * @li @em ws:// - Insecure websockets
186  * @li @em wss:// - Secure web sockets
187  * The TLS enabled prefixes (ssl, mqtts, wss) are only valid if a TLS
188  * version of the library is linked with.
189  */
190 #define MQTTCLIENT_BAD_PROTOCOL -14
191  /**
192   * Return code: option not applicable to the requested version of MQTT
193   */
194  #define MQTTCLIENT_BAD_MQTT_OPTION -15
195  /**
196   * Return code: call not applicable to the requested version of MQTT
197   */
198  #define MQTTCLIENT_WRONG_MQTT_VERSION -16
199  /**
200   * Return code: 0 length will topic on connect
201   */
202  #define MQTTCLIENT_0_LEN_WILL_TOPIC -17
203 
204 
205 /**
206  * Default MQTT version to connect with.  Use 3.1.1 then fall back to 3.1
207  */
208 #define MQTTVERSION_DEFAULT 0
209 /**
210  * MQTT version to connect with: 3.1
211  */
212 #define MQTTVERSION_3_1 3
213 /**
214  * MQTT version to connect with: 3.1.1
215  */
216 #define MQTTVERSION_3_1_1 4
217  /**
218   * MQTT version to connect with: 5
219   */
220  #define MQTTVERSION_5 5
221 /**
222  * Bad return code from subscribe, as defined in the 3.1.1 specification
223  */
224 #define MQTT_BAD_SUBSCRIBE 0x80
225 
226 /**
227  *  Initialization options
228  */
229 typedef struct
230 {
231 	/** The eyecatcher for this structure.  Must be MQTG. */
232 	char struct_id[4];
233 	/** The version number of this structure.  Must be 0 */
234 	int struct_version;
235 	/** 1 = we do openssl init, 0 = leave it to the application */
236 	int do_openssl_init;
237 } MQTTClient_init_options;
238 
239 #define MQTTClient_init_options_initializer { {'M', 'Q', 'T', 'G'}, 0, 0 }
240 
241 /**
242  * Global init of mqtt library. Call once on program start to set global behaviour.
243  * do_openssl_init - if mqtt library should initialize OpenSSL (1) or rely on the caller to do it before using the library (0)
244  */
245 LIBMQTT_API void MQTTClient_global_init(MQTTClient_init_options* inits);
246 
247 /**
248  * A handle representing an MQTT client. A valid client handle is available
249  * following a successful call to MQTTClient_create().
250  */
251 typedef void* MQTTClient;
252 /**
253  * A value representing an MQTT message. A delivery token is returned to the
254  * client application when a message is published. The token can then be used to
255  * check that the message was successfully delivered to its destination (see
256  * MQTTClient_publish(),
257  * MQTTClient_publishMessage(),
258  * MQTTClient_deliveryComplete(),
259  * MQTTClient_waitForCompletion() and
260  * MQTTClient_getPendingDeliveryTokens()).
261  */
262 typedef int MQTTClient_deliveryToken;
263 typedef int MQTTClient_token;
264 
265 /**
266  * A structure representing the payload and attributes of an MQTT message. The
267  * message topic is not part of this structure (see MQTTClient_publishMessage(),
268  * MQTTClient_publish(), MQTTClient_receive(), MQTTClient_freeMessage()
269  * and MQTTClient_messageArrived()).
270  */
271 typedef struct
272 {
273 	/** The eyecatcher for this structure.  must be MQTM. */
274 	char struct_id[4];
275 	/** The version number of this structure.  Must be 0 or 1
276 	 *  0 indicates no message properties */
277 	int struct_version;
278 	/** The length of the MQTT message payload in bytes. */
279 	int payloadlen;
280 	/** A pointer to the payload of the MQTT message. */
281 	void* payload;
282 	/**
283      * The quality of service (QoS) assigned to the message.
284      * There are three levels of QoS:
285      * <DL>
286      * <DT><B>QoS0</B></DT>
287      * <DD>Fire and forget - the message may not be delivered</DD>
288      * <DT><B>QoS1</B></DT>
289      * <DD>At least once - the message will be delivered, but may be
290      * delivered more than once in some circumstances.</DD>
291      * <DT><B>QoS2</B></DT>
292      * <DD>Once and one only - the message will be delivered exactly once.</DD>
293      * </DL>
294      */
295 	int qos;
296 	/**
297      * The retained flag serves two purposes depending on whether the message
298      * it is associated with is being published or received.
299      *
300      * <b>retained = true</b><br>
301      * For messages being published, a true setting indicates that the MQTT
302      * server should retain a copy of the message. The message will then be
303      * transmitted to new subscribers to a topic that matches the message topic.
304      * For subscribers registering a new subscription, the flag being true
305      * indicates that the received message is not a new one, but one that has
306      * been retained by the MQTT server.
307      *
308      * <b>retained = false</b> <br>
309      * For publishers, this indicates that this message should not be retained
310      * by the MQTT server. For subscribers, a false setting indicates this is
311      * a normal message, received as a result of it being published to the
312      * server.
313      */
314 	int retained;
315 	/**
316       * The dup flag indicates whether or not this message is a duplicate.
317       * It is only meaningful when receiving QoS1 messages. When true, the
318       * client application should take appropriate action to deal with the
319       * duplicate message.
320       */
321 	int dup;
322 	/** The message identifier is normally reserved for internal use by the
323       * MQTT client and server.
324       */
325 	int msgid;
326 	/**
327 	 * The MQTT V5 properties associated with the message.
328 	 */
329 	MQTTProperties properties;
330 } MQTTClient_message;
331 
332 #define MQTTClient_message_initializer { {'M', 'Q', 'T', 'M'}, 1, 0, NULL, 0, 0, 0, 0, MQTTProperties_initializer }
333 
334 /**
335  * This is a callback function. The client application
336  * must provide an implementation of this function to enable asynchronous
337  * receipt of messages. The function is registered with the client library by
338  * passing it as an argument to MQTTClient_setCallbacks(). It is
339  * called by the client library when a new message that matches a client
340  * subscription has been received from the server. This function is executed on
341  * a separate thread to the one on which the client application is running.
342  * @param context A pointer to the <i>context</i> value originally passed to
343  * MQTTClient_setCallbacks(), which contains any application-specific context.
344  * @param topicName The topic associated with the received message.
345  * @param topicLen The length of the topic if there are one
346  * more NULL characters embedded in <i>topicName</i>, otherwise <i>topicLen</i>
347  * is 0. If <i>topicLen</i> is 0, the value returned by <i>strlen(topicName)</i>
348  * can be trusted. If <i>topicLen</i> is greater than 0, the full topic name
349  * can be retrieved by accessing <i>topicName</i> as a byte array of length
350  * <i>topicLen</i>.
351  * @param message The MQTTClient_message structure for the received message.
352  * This structure contains the message payload and attributes.
353  * @return This function must return 0 or 1 indicating whether or not
354  * the message has been safely received by the client application. <br>
355  * Returning 1 indicates that the message has been successfully handled.
356  * To free the message storage, ::MQTTClient_freeMessage must be called.
357  * To free the topic name storage, ::MQTTClient_free must be called.<br>
358  * Returning 0 indicates that there was a problem. In this
359  * case, the client library will reinvoke MQTTClient_messageArrived() to
360  * attempt to deliver the message to the application again.
361  * Do not free the message and topic storage when returning 0, otherwise
362  * the redelivery will fail.
363  */
364 typedef int MQTTClient_messageArrived(void* context, char* topicName, int topicLen, MQTTClient_message* message);
365 
366 /**
367  * This is a callback function. The client application
368  * must provide an implementation of this function to enable asynchronous
369  * notification of delivery of messages. The function is registered with the
370  * client library by passing it as an argument to MQTTClient_setCallbacks().
371  * It is called by the client library after the client application has
372  * published a message to the server. It indicates that the necessary
373  * handshaking and acknowledgements for the requested quality of service (see
374  * MQTTClient_message.qos) have been completed. This function is executed on a
375  * separate thread to the one on which the client application is running.
376  * <b>Note:</b>MQTTClient_deliveryComplete() is not called when messages are
377  * published at QoS0.
378  * @param context A pointer to the <i>context</i> value originally passed to
379  * MQTTClient_setCallbacks(), which contains any application-specific context.
380  * @param dt The ::MQTTClient_deliveryToken associated with
381  * the published message. Applications can check that all messages have been
382  * correctly published by matching the delivery tokens returned from calls to
383  * MQTTClient_publish() and MQTTClient_publishMessage() with the tokens passed
384  * to this callback.
385  */
386 typedef void MQTTClient_deliveryComplete(void* context, MQTTClient_deliveryToken dt);
387 
388 /**
389  * This is a callback function. The client application
390  * must provide an implementation of this function to enable asynchronous
391  * notification of the loss of connection to the server. The function is
392  * registered with the client library by passing it as an argument to
393  * MQTTClient_setCallbacks(). It is called by the client library if the client
394  * loses its connection to the server. The client application must take
395  * appropriate action, such as trying to reconnect or reporting the problem.
396  * This function is executed on a separate thread to the one on which the
397  * client application is running.
398  * @param context A pointer to the <i>context</i> value originally passed to
399  * MQTTClient_setCallbacks(), which contains any application-specific context.
400  * @param cause The reason for the disconnection.
401  * Currently, <i>cause</i> is always set to NULL.
402  */
403 typedef void MQTTClient_connectionLost(void* context, char* cause);
404 
405 /**
406  * This function sets the callback functions for a specific client.
407  * If your client application doesn't use a particular callback, set the
408  * relevant parameter to NULL. Calling MQTTClient_setCallbacks() puts the
409  * client into multi-threaded mode. Any necessary message acknowledgements and
410  * status communications are handled in the background without any intervention
411  * from the client application. See @ref async for more information.
412  *
413  * <b>Note:</b> The MQTT client must be disconnected when this function is
414  * called.
415  * @param handle A valid client handle from a successful call to
416  * MQTTClient_create().
417  * @param context A pointer to any application-specific context. The
418  * the <i>context</i> pointer is passed to each of the callback functions to
419  * provide access to the context information in the callback.
420  * @param cl A pointer to an MQTTClient_connectionLost() callback
421  * function. You can set this to NULL if your application doesn't handle
422  * disconnections.
423  * @param ma A pointer to an MQTTClient_messageArrived() callback
424  * function. This callback function must be set when you call
425  * MQTTClient_setCallbacks(), as otherwise there would be nowhere to deliver
426  * any incoming messages.
427  * @param dc A pointer to an MQTTClient_deliveryComplete() callback
428  * function. You can set this to NULL if your application publishes
429  * synchronously or if you do not want to check for successful delivery.
430  * @return ::MQTTCLIENT_SUCCESS if the callbacks were correctly set,
431  * ::MQTTCLIENT_FAILURE if an error occurred.
432  */
433 LIBMQTT_API int MQTTClient_setCallbacks(MQTTClient handle, void* context, MQTTClient_connectionLost* cl,
434 									MQTTClient_messageArrived* ma, MQTTClient_deliveryComplete* dc);
435 
436 
437 /**
438  * This is a callback function, which will be called when the a disconnect
439  * packet is received from the server.  This applies to MQTT V5 and above only.
440  * @param context A pointer to the <i>context</i> value originally passed to
441  * ::MQTTClient_setDisconnected(), which contains any application-specific context.
442  * @param properties The MQTT V5 properties received with the disconnect, if any.
443  * @param reasonCode The MQTT V5 reason code received with the disconnect.
444  * Currently, <i>cause</i> is always set to NULL.
445  */
446 typedef void MQTTClient_disconnected(void* context, MQTTProperties* properties,
447 		enum MQTTReasonCodes reasonCode);
448 
449 /**
450  * Sets the MQTTClient_disconnected() callback function for a client.  This will be called
451  * if a disconnect packet is received from the server.  Only valid for MQTT V5 and above.
452  * @param handle A valid client handle from a successful call to
453  * MQTTClient_create().
454  * @param context A pointer to any application-specific context. The
455  * the <i>context</i> pointer is passed to each of the callback functions to
456  * provide access to the context information in the callback.
457  * @param co A pointer to an MQTTClient_disconnected() callback
458  * function.  NULL removes the callback setting.
459  * @return ::MQTTCLIENT_SUCCESS if the callbacks were correctly set,
460  * ::MQTTCLIENT_FAILURE if an error occurred.
461  */
462 LIBMQTT_API int MQTTClient_setDisconnected(MQTTClient handle, void* context, MQTTClient_disconnected* co);
463 
464 /**
465  * This is a callback function, the MQTT V5 version of MQTTClient_deliveryComplete().
466  * The client application
467  * must provide an implementation of this function to enable asynchronous
468  * notification of the completed delivery of messages.
469  * It is called by the client library after the client application has
470  * published a message to the server. It indicates that the necessary
471  * handshaking and acknowledgements for the requested quality of service (see
472  * MQTTClient_message.qos) have been completed. This function is executed on a
473  * separate thread to the one on which the client application is running.
474  * <b>Note:</b> It is not called when messages are published at QoS0.
475  * @param context A pointer to the <i>context</i> value originally passed to
476  * MQTTClient_setCallbacks(), which contains any application-specific context.
477  * @param dt The ::MQTTClient_deliveryToken associated with
478  * the published message. Applications can check that all messages have been
479  * correctly published by matching the delivery tokens returned from calls to
480  * MQTTClient_publish() and MQTTClient_publishMessage() with the tokens passed
481  * to this callback.
482  * @param packet_type the last received packet type for this completion. For QoS 1
483  * always PUBACK.  For QoS 2 could be PUBREC or PUBCOMP.
484  * @param properties the MQTT V5 properties returned with the last packet from the server
485  * @param reasonCode the reason code returned from the server
486  */
487 typedef void MQTTClient_published(void* context, int dt, int packet_type, MQTTProperties* properties,
488 		enum MQTTReasonCodes reasonCode);
489 
490 LIBMQTT_API int MQTTClient_setPublished(MQTTClient handle, void* context, MQTTClient_published* co);
491 
492 /**
493  * This function creates an MQTT client ready for connection to the
494  * specified server and using the specified persistent storage (see
495  * MQTTClient_persistence). See also MQTTClient_destroy().
496  * @param handle A pointer to an ::MQTTClient handle. The handle is
497  * populated with a valid client reference following a successful return from
498  * this function.
499  * @param serverURI A null-terminated string specifying the server to
500  * which the client will connect. It takes the form <i>protocol://host:port</i>.
501  * Currently, <i>protocol</i> must be:
502  * <br>
503  * @em tcp:// or @em mqtt:// - Insecure TCP
504  * <br>
505  * @em ssl:// or @em mqtts:// - Encrypted SSL/TLS
506  * <br>
507  * @em ws:// - Insecure websockets
508  * <br>
509  * @em wss:// - Secure web sockets
510  * <br>
511  * The TLS enabled prefixes (ssl, mqtts, wss) are only valid if a TLS
512  * version of the library is linked with.
513  * For <i>host</i>, you can specify either an IP address or a host name. For
514  * instance, to connect to a server running on the local machines with the
515  * default MQTT port, specify <i>tcp://localhost:1883</i>.
516  * @param clientId The client identifier passed to the server when the
517  * client connects to it. It is a null-terminated UTF-8 encoded string.
518  * @param persistence_type The type of persistence to be used by the client:
519  * <br>
520  * ::MQTTCLIENT_PERSISTENCE_NONE: Use in-memory persistence. If the device or
521  * system on which the client is running fails or is switched off, the current
522  * state of any in-flight messages is lost and some messages may not be
523  * delivered even at QoS1 and QoS2.
524  * <br>
525  * ::MQTTCLIENT_PERSISTENCE_DEFAULT: Use the default (file system-based)
526  * persistence mechanism. Status about in-flight messages is held in persistent
527  * storage and provides some protection against message loss in the case of
528  * unexpected failure.
529  * <br>
530  * ::MQTTCLIENT_PERSISTENCE_USER: Use an application-specific persistence
531  * implementation. Using this type of persistence gives control of the
532  * persistence mechanism to the application. The application has to implement
533  * the MQTTClient_persistence interface.
534  * @param persistence_context If the application uses
535  * ::MQTTCLIENT_PERSISTENCE_NONE persistence, this argument is unused and should
536  * be set to NULL. For ::MQTTCLIENT_PERSISTENCE_DEFAULT persistence, it
537  * should be set to the location of the persistence directory (if set
538  * to NULL, the persistence directory used is the working directory).
539  * Applications that use ::MQTTCLIENT_PERSISTENCE_USER persistence set this
540  * argument to point to a valid MQTTClient_persistence structure.
541  * @return ::MQTTCLIENT_SUCCESS if the client is successfully created, otherwise
542  * an error code is returned.
543  */
544 LIBMQTT_API int MQTTClient_create(MQTTClient* handle, const char* serverURI, const char* clientId,
545 		int persistence_type, void* persistence_context);
546 
547 /** Options for the ::MQTTClient_createWithOptions call */
548 typedef struct
549 {
550 	/** The eyecatcher for this structure.  must be MQCO. */
551 	char struct_id[4];
552 	/** The version number of this structure.  Must be 0 */
553 	int struct_version;
554 	/** Whether the MQTT version is 3.1, 3.1.1, or 5.  To use V5, this must be set.
555 	 *  MQTT V5 has to be chosen here, because during the create call the message persistence
556 	 *  is initialized, and we want to know whether the format of any persisted messages
557 	 *  is appropriate for the MQTT version we are going to connect with.  Selecting 3.1 or
558 	 *  3.1.1 and attempting to read 5.0 persisted messages will result in an error on create.  */
559 	int MQTTVersion;
560 } MQTTClient_createOptions;
561 
562 #define MQTTClient_createOptions_initializer { {'M', 'Q', 'C', 'O'}, 0, MQTTVERSION_DEFAULT }
563 
564 /**
565  * A version of :MQTTClient_create() with additional options.
566  * This function creates an MQTT client ready for connection to the
567  * specified server and using the specified persistent storage (see
568  * MQTTClient_persistence). See also MQTTClient_destroy().
569  * @param handle A pointer to an ::MQTTClient handle. The handle is
570  * populated with a valid client reference following a successful return from
571  * this function.
572  * @param serverURI A null-terminated string specifying the server to
573  * which the client will connect. It takes the form <i>protocol://host:port</i>.
574  * Currently, <i>protocol</i> must be <i>tcp</i> or <i>ssl</i>.
575  * For <i>host</i>, you can
576  * specify either an IP address or a host name. For instance, to connect to
577  * a server running on the local machines with the default MQTT port, specify
578  * <i>tcp://localhost:1883</i>.
579  * @param clientId The client identifier passed to the server when the
580  * client connects to it. It is a null-terminated UTF-8 encoded string.
581  * @param persistence_type The type of persistence to be used by the client:
582  * <br>
583  * ::MQTTCLIENT_PERSISTENCE_NONE: Use in-memory persistence. If the device or
584  * system on which the client is running fails or is switched off, the current
585  * state of any in-flight messages is lost and some messages may not be
586  * delivered even at QoS1 and QoS2.
587  * <br>
588  * ::MQTTCLIENT_PERSISTENCE_DEFAULT: Use the default (file system-based)
589  * persistence mechanism. Status about in-flight messages is held in persistent
590  * storage and provides some protection against message loss in the case of
591  * unexpected failure.
592  * <br>
593  * ::MQTTCLIENT_PERSISTENCE_USER: Use an application-specific persistence
594  * implementation. Using this type of persistence gives control of the
595  * persistence mechanism to the application. The application has to implement
596  * the MQTTClient_persistence interface.
597  * @param persistence_context If the application uses
598  * ::MQTTCLIENT_PERSISTENCE_NONE persistence, this argument is unused and should
599  * be set to NULL. For ::MQTTCLIENT_PERSISTENCE_DEFAULT persistence, it
600  * should be set to the location of the persistence directory (if set
601  * to NULL, the persistence directory used is the working directory).
602  * Applications that use ::MQTTCLIENT_PERSISTENCE_USER persistence set this
603  * argument to point to a valid MQTTClient_persistence structure.
604  * @param options additional options for the create.
605  * @return ::MQTTCLIENT_SUCCESS if the client is successfully created, otherwise
606  * an error code is returned.
607  */
608 LIBMQTT_API int MQTTClient_createWithOptions(MQTTClient* handle, const char* serverURI, const char* clientId,
609 		int persistence_type, void* persistence_context, MQTTClient_createOptions* options);
610 
611 /**
612  * MQTTClient_willOptions defines the MQTT "Last Will and Testament" (LWT) settings for
613  * the client. In the event that a client unexpectedly loses its connection to
614  * the server, the server publishes the LWT message to the LWT topic on
615  * behalf of the client. This allows other clients (subscribed to the LWT topic)
616  * to be made aware that the client has disconnected. To enable the LWT
617  * function for a specific client, a valid pointer to an MQTTClient_willOptions
618  * structure is passed in the MQTTClient_connectOptions structure used in the
619  * MQTTClient_connect() call that connects the client to the server. The pointer
620  * to MQTTClient_willOptions can be set to NULL if the LWT function is not
621  * required.
622  */
623 typedef struct
624 {
625 	/** The eyecatcher for this structure.  must be MQTW. */
626 	char struct_id[4];
627 	/** The version number of this structure.  Must be 0 or 1
628 		   0 means there is no binary payload option
629 	 */
630 	int struct_version;
631 	/** The LWT topic to which the LWT message will be published. */
632 	const char* topicName;
633 	/** The LWT payload in string form. */
634 	const char* message;
635 	/**
636 	 * The retained flag for the LWT message (see MQTTClient_message.retained).
637 	 */
638 	int retained;
639 	/**
640 	 * The quality of service setting for the LWT message (see
641 	 * MQTTClient_message.qos and @ref qos).
642 	 */
643 	int qos;
644   /** The LWT payload in binary form. This is only checked and used if the message option is NULL */
645 	struct
646 	{
647 		int len;            /**< binary payload length */
648 		const void* data;  /**< binary payload data */
649 	} payload;
650 } MQTTClient_willOptions;
651 
652 #define MQTTClient_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, {0, NULL} }
653 
654 #define MQTT_SSL_VERSION_DEFAULT 0
655 #define MQTT_SSL_VERSION_TLS_1_0 1
656 #define MQTT_SSL_VERSION_TLS_1_1 2
657 #define MQTT_SSL_VERSION_TLS_1_2 3
658 
659 #if defined(IOT_CONNECT) || defined(IOT_LITEOS_ADAPT)
660 typedef struct
661 {
662 	const unsigned char* body;            /**< string of cert in PEM format */
663 	size_t size;  /**< binary payload data */
664 } cert_string;
665 
666 typedef struct
667 {
668 	const unsigned char* body;            /**< string of key in KEY forma */
669 	size_t size;  /**< binary payload data */
670 } key_string;
671 #endif
672 
673 /**
674 * MQTTClient_sslProperties defines the settings to establish an SSL/TLS connection using the
675 * OpenSSL library. It covers the following scenarios:
676 * - Server authentication: The client needs the digital certificate of the server. It is included
677 *   in a store containting trusted material (also known as "trust store").
678 * - Mutual authentication: Both client and server are authenticated during the SSL handshake. In
679 *   addition to the digital certificate of the server in a trust store, the client will need its own
680 *   digital certificate and the private key used to sign its digital certificate stored in a "key store".
681 * - Anonymous connection: Both client and server do not get authenticated and no credentials are needed
682 *   to establish an SSL connection. Note that this scenario is not fully secure since it is subject to
683 *   man-in-the-middle attacks.
684 */
685 typedef struct
686 {
687 	/** The eyecatcher for this structure.  Must be MQTS */
688 	char struct_id[4];
689 
690 	/** The version number of this structure. Must be 0, 1, 2, 3, 4 or 5.
691 	 * 0 means no sslVersion
692 	 * 1 means no verify, CApath
693 	 * 2 means no ssl_error_context, ssl_error_cb
694 	 * 3 means no ssl_psk_cb, ssl_psk_context, disableDefaultTrustStore
695 	 * 4 means no protos, protos_len
696 	 */
697 	int struct_version;
698 
699 	/** The file in PEM format containing the public digital certificates trusted by the client. */
700 	const char* trustStore;
701 
702 	/** The file in PEM format containing the public certificate chain of the client. It may also include
703 	* the client's private key.
704 	*/
705 	const char* keyStore;
706 
707 	/** If not included in the sslKeyStore, this setting points to the file in PEM format containing
708 	* the client's private key.
709 	*/
710 	const char* privateKey;
711 
712 	/** The password to load the client's privateKey if encrypted. */
713 	const char* privateKeyPassword;
714 
715 	/**
716 	* The list of cipher suites that the client will present to the server during the SSL handshake. For a
717 	* full explanation of the cipher list format, please see the OpenSSL on-line documentation:
718 	* http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT
719 	* If this setting is ommitted, its default value will be "ALL", that is, all the cipher suites -excluding
720 	* those offering no encryption- will be considered.
721 	* This setting can be used to set an SSL anonymous connection ("aNULL" string value, for instance).
722 	*/
723 	const char* enabledCipherSuites;
724 
725     /** True/False option to enable verification of the server certificate **/
726     int enableServerCertAuth;
727 
728     /** The SSL/TLS version to use. Specify one of MQTT_SSL_VERSION_DEFAULT (0),
729     * MQTT_SSL_VERSION_TLS_1_0 (1), MQTT_SSL_VERSION_TLS_1_1 (2) or MQTT_SSL_VERSION_TLS_1_2 (3).
730     * Only used if struct_version is >= 1.
731     */
732     int sslVersion;
733 
734     /**
735      * Whether to carry out post-connect checks, including that a certificate
736      * matches the given host name.
737      * Exists only if struct_version >= 2
738      */
739     int verify;
740 
741     /**
742      * From the OpenSSL documentation:
743      * If CApath is not NULL, it points to a directory containing CA certificates in PEM format.
744      * Exists only if struct_version >= 2
745 	 */
746 	const char* CApath;
747 
748     /**
749      * Callback function for OpenSSL error handler ERR_print_errors_cb
750      * Exists only if struct_version >= 3
751      */
752     int (*ssl_error_cb) (const char *str, size_t len, void *u);
753 
754     /**
755      * Application-specific contex for OpenSSL error handler ERR_print_errors_cb
756      * Exists only if struct_version >= 3
757      */
758     void* ssl_error_context;
759 
760 	/**
761 	 * Callback function for setting TLS-PSK options. Parameters correspond to that of
762 	 * SSL_CTX_set_psk_client_callback, except for u which is the pointer ssl_psk_context.
763 	 * Exists only if struct_version >= 4
764 	 */
765 	unsigned int (*ssl_psk_cb) (const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len, void *u);
766 
767 	/**
768 	 * Application-specific contex for ssl_psk_cb
769 	 * Exists only if struct_version >= 4
770 	 */
771 	void* ssl_psk_context;
772 
773 	/**
774 	 * Don't load default SSL CA. Should be used together with PSK to make sure
775 	 * regular servers with certificate in place is not accepted.
776 	 * Exists only if struct_version >= 4
777 	 */
778 	int disableDefaultTrustStore;
779 
780 	/**
781 	 * The protocol-lists must be in wire-format, which is defined as a vector of non-empty, 8-bit length-prefixed, byte strings.
782 	 * The length-prefix byte is not included in the length. Each string is limited to 255 bytes. A byte-string length of 0 is invalid.
783 	 * A truncated byte-string is invalid.
784 	 * Check documentation for SSL_CTX_set_alpn_protos
785 	 * Exists only if struct_version >= 5
786 	 */
787 	const unsigned char *protos;
788 
789 	/**
790 	 * The length of the vector protos vector
791 	 * Exists only if struct_version >= 5
792 	 */
793 	unsigned int protos_len;
794 
795 #if defined(IOT_CONNECT) || defined(IOT_LITEOS_ADAPT)
796 	/** CA Certification */
797 	const cert_string* los_trustStore;
798 	/** client Certification */
799 	const cert_string* los_keyStore;
800 	/** client private key */
801 	const key_string* los_privateKey;
802 
803 	const unsigned char* psk;
804 	unsigned int psk_len;
805 	const unsigned char* psk_id;
806 	unsigned int psk_id_len;
807 #endif
808 } MQTTClient_SSLOptions;
809 
810 #if defined(IOT_CONNECT) || defined(IOT_LITEOS_ADAPT)
811 #define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 5, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL, 0 }
812 #else
813 #define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 5, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }
814 #endif
815 
816 /**
817   * MQTTClient_libraryInfo is used to store details relating to the currently used
818   * library such as the version in use, the time it was built and relevant openSSL
819   * options.
820   * There is one static instance of this struct in MQTTClient.c
821   */
822 
823 typedef struct
824 {
825 	const char* name;
826 	const char* value;
827 } MQTTClient_nameValue;
828 
829 /**
830   * This function returns version information about the library.
831   * no trace information will be returned.
832   * @return an array of strings describing the library.  The last entry is a NULL pointer.
833   */
834 LIBMQTT_API MQTTClient_nameValue* MQTTClient_getVersionInfo(void);
835 
836 /**
837  * MQTTClient_connectOptions defines several settings that control the way the
838  * client connects to an MQTT server.
839  *
840  * <b>Note:</b> Default values are not defined for members of
841  * MQTTClient_connectOptions so it is good practice to specify all settings.
842  * If the MQTTClient_connectOptions structure is defined as an automatic
843  * variable, all members are set to random values and thus must be set by the
844  * client application. If the MQTTClient_connectOptions structure is defined
845  * as a static variable, initialization (in compliant compilers) sets all
846  * values to 0 (NULL for pointers). A #keepAliveInterval setting of 0 prevents
847  * correct operation of the client and so you <b>must</b> at least set a value
848  * for #keepAliveInterval.
849  *
850  * Suitable default values are set in the following initializers:
851  * - MQTTClient_connectOptions_initializer: for MQTT 3.1.1 non-WebSockets
852  * - MQTTClient_connectOptions_initializer5: for MQTT 5.0 non-WebSockets
853  * - MQTTClient_connectOptions_initializer_ws: for MQTT 3.1.1 WebSockets
854  * - MQTTClient_connectOptions_initializer5_ws: for MQTT 5.0 WebSockets
855  */
856 typedef struct
857 {
858 	/** The eyecatcher for this structure.  must be MQTC. */
859 	char struct_id[4];
860 	/** The version number of this structure.  Must be 0, 1, 2, 3, 4, 5, 6, 7 or 8.
861 	 * 0 signifies no SSL options and no serverURIs
862 	 * 1 signifies no serverURIs
863 	 * 2 signifies no MQTTVersion
864 	 * 3 signifies no returned values
865 	 * 4 signifies no binary password option
866 	 * 5 signifies no maxInflightMessages and cleanstart
867 	 * 6 signifies no HTTP headers option
868 	 * 7 signifies no HTTP proxy and HTTPS proxy options
869 	 */
870 	int struct_version;
871 	/** The "keep alive" interval, measured in seconds, defines the maximum time
872    * that should pass without communication between the client and the server
873    * The client will ensure that at least one message travels across the
874    * network within each keep alive period.  In the absence of a data-related
875 	 * message during the time period, the client sends a very small MQTT
876    * "ping" message, which the server will acknowledge. The keep alive
877    * interval enables the client to detect when the server is no longer
878 	 * available without having to wait for the long TCP/IP timeout.
879 	 */
880 	int keepAliveInterval;
881 	/**
882    * This is a boolean value. The cleansession setting controls the behaviour
883    * of both the client and the server at connection and disconnection time.
884    * The client and server both maintain session state information. This
885    * information is used to ensure "at least once" and "exactly once"
886    * delivery, and "exactly once" receipt of messages. Session state also
887    * includes subscriptions created by an MQTT client. You can choose to
888    * maintain or discard state information between sessions.
889    *
890    * When cleansession is true, the state information is discarded at
891    * connect and disconnect. Setting cleansession to false keeps the state
892    * information. When you connect an MQTT client application with
893    * MQTTClient_connect(), the client identifies the connection using the
894    * client identifier and the address of the server. The server checks
895    * whether session information for this client
896    * has been saved from a previous connection to the server. If a previous
897    * session still exists, and cleansession=true, then the previous session
898    * information at the client and server is cleared. If cleansession=false,
899    * the previous session is resumed. If no previous session exists, a new
900    * session is started.
901 	 */
902 	int cleansession;
903 	/**
904    * This is a boolean value that controls how many messages can be in-flight
905    * simultaneously. Setting <i>reliable</i> to true means that a published
906    * message must be completed (acknowledgements received) before another
907    * can be sent. Attempts to publish additional messages receive an
908    * ::MQTTCLIENT_MAX_MESSAGES_INFLIGHT return code. Setting this flag to
909    * false allows up to 10 messages to be in-flight. This can increase
910    * overall throughput in some circumstances.
911 	 */
912 	int reliable;
913 	/**
914    * This is a pointer to an MQTTClient_willOptions structure. If your
915    * application does not make use of the Last Will and Testament feature,
916    * set this pointer to NULL.
917    */
918 	MQTTClient_willOptions* will;
919 	/**
920    * MQTT servers that support the MQTT v3.1.1 protocol provide authentication
921    * and authorisation by user name and password. This is the user name
922    * parameter.
923    */
924 	const char* username;
925 	/**
926    * MQTT servers that support the MQTT v3.1.1 protocol provide authentication
927    * and authorisation by user name and password. This is the password
928    * parameter.
929    */
930 	const char* password;
931 	/**
932    * The time interval in seconds to allow a connect to complete.
933    */
934 	int connectTimeout;
935 	/**
936 	 * The time interval in seconds after which unacknowledged publish requests are
937 	 * retried during a TCP session.  With MQTT 3.1.1 and later, retries are
938 	 * not required except on reconnect.  0 turns off in-session retries, and is the
939 	 * recommended setting.  Adding retries to an already overloaded network only
940 	 * exacerbates the problem.
941 	 */
942 	int retryInterval;
943 	/**
944    * This is a pointer to an MQTTClient_SSLOptions structure. If your
945    * application does not make use of SSL, set this pointer to NULL.
946    */
947 	MQTTClient_SSLOptions* ssl;
948 	/**
949 	 * The number of entries in the optional serverURIs array. Defaults to 0.
950 	 */
951 	int serverURIcount;
952 	/**
953    * An optional array of null-terminated strings specifying the servers to
954    * which the client will connect. Each string takes the form <i>protocol://host:port</i>.
955    * <i>protocol</i> must be <i>tcp</i>, <i>ssl</i>, <i>ws</i> or <i>wss</i>.
956    * The TLS enabled prefixes (ssl, wss) are only valid if a TLS version of the library
957    * is linked with.
958    * For <i>host</i>, you can
959    * specify either an IP address or a host name. For instance, to connect to
960    * a server running on the local machines with the default MQTT port, specify
961    * <i>tcp://localhost:1883</i>.
962    * If this list is empty (the default), the server URI specified on MQTTClient_create()
963    * is used.
964    */
965 	char* const* serverURIs;
966 	/**
967 	 * Sets the version of MQTT to be used on the connect.
968 	 * MQTTVERSION_DEFAULT (0) = default: start with 3.1.1, and if that fails, fall back to 3.1
969 	 * MQTTVERSION_3_1 (3) = only try version 3.1
970 	 * MQTTVERSION_3_1_1 (4) = only try version 3.1.1
971 	 * MQTTVERSION_5 (5) = only try version 5.0
972 	 */
973 	int MQTTVersion;
974 	/**
975 	 * Returned from the connect when the MQTT version used to connect is 3.1.1
976 	 */
977 	struct
978 	{
979 		const char* serverURI;     /**< the serverURI connected to */
980 		int MQTTVersion;     /**< the MQTT version used to connect with */
981 		int sessionPresent;  /**< if the MQTT version is 3.1.1, the value of sessionPresent returned in the connack */
982 	} returned;
983 	/**
984    * Optional binary password.  Only checked and used if the password option is NULL
985    */
986 	struct
987 	{
988 		int len;           /**< binary password length */
989 		const void* data;  /**< binary password data */
990 	} binarypwd;
991 	/**
992 	 * The maximum number of messages in flight
993 	 */
994 	int maxInflightMessages;
995 	/*
996 	 * MQTT V5 clean start flag.  Only clears state at the beginning of the session.
997 	 */
998 	int cleanstart;
999 	/**
1000 	 * HTTP headers for websockets
1001 	 */
1002 	const MQTTClient_nameValue* httpHeaders;
1003 	/**
1004 	 * HTTP proxy
1005 	 */
1006 	const char* httpProxy;
1007 	/**
1008 	 * HTTPS proxy
1009 	 */
1010 	const char* httpsProxy;
1011 } MQTTClient_connectOptions;
1012 
1013 #if defined(IOT_CONNECT) || defined(IOT_LITEOS_ADAPT)
1014 /** Initializer for connect options for MQTT 3.1.1 non-WebSocket connections */
1015 #define MQTTClient_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 8, 60, 1, 0, NULL, NULL, NULL, 30, 0, NULL,\
1016 0, NULL, MQTTVERSION_DEFAULT, {NULL, 0, 0}, {0, NULL}, -1, 0, NULL, NULL, NULL}
1017 #else
1018 #define MQTTClient_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 8, 60, 1, 1, NULL, NULL, NULL, 30, 0, NULL,\
1019 0, NULL, MQTTVERSION_DEFAULT, {NULL, 0, 0}, {0, NULL}, -1, 0, NULL, NULL, NULL}
1020 #endif
1021 /** Initializer for connect options for MQTT 5.0 non-WebSocket connections */
1022 #define MQTTClient_connectOptions_initializer5 { {'M', 'Q', 'T', 'C'}, 8, 60, 0, 1, NULL, NULL, NULL, 30, 0, NULL,\
1023 0, NULL, MQTTVERSION_5, {NULL, 0, 0}, {0, NULL}, -1, 1, NULL, NULL, NULL}
1024 
1025 /** Initializer for connect options for MQTT 3.1.1 WebSockets connections.
1026   * The keepalive interval is set to 45 seconds to avoid webserver 60 second inactivity timeouts.
1027   */
1028 #define MQTTClient_connectOptions_initializer_ws { {'M', 'Q', 'T', 'C'}, 8, 45, 1, 1, NULL, NULL, NULL, 30, 0, NULL,\
1029 0, NULL, MQTTVERSION_DEFAULT, {NULL, 0, 0}, {0, NULL}, -1, 0, NULL, NULL, NULL}
1030 
1031 /** Initializer for connect options for MQTT 5.0 WebSockets connections.
1032   * The keepalive interval is set to 45 seconds to avoid webserver 60 second inactivity timeouts.
1033   */
1034 #define MQTTClient_connectOptions_initializer5_ws { {'M', 'Q', 'T', 'C'}, 8, 45, 0, 1, NULL, NULL, NULL, 30, 0, NULL,\
1035 0, NULL, MQTTVERSION_5, {NULL, 0, 0}, {0, NULL}, -1, 1, NULL, NULL, NULL}
1036 
1037 /**
1038   * This function attempts to connect a previously-created client (see
1039   * MQTTClient_create()) to an MQTT server using the specified options. If you
1040   * want to enable asynchronous message and status notifications, you must call
1041   * MQTTClient_setCallbacks() prior to MQTTClient_connect().
1042   * @param handle A valid client handle from a successful call to
1043   * MQTTClient_create().
1044   * @param options A pointer to a valid MQTTClient_connectOptions
1045   * structure.
1046   * @return ::MQTTCLIENT_SUCCESS if the client successfully connects to the
1047   * server. An error code is returned if the client was unable to connect to
1048   * the server.
1049   * Error codes greater than 0 are returned by the MQTT protocol:<br><br>
1050   * <b>1</b>: Connection refused: Unacceptable protocol version<br>
1051   * <b>2</b>: Connection refused: Identifier rejected<br>
1052   * <b>3</b>: Connection refused: Server unavailable<br>
1053   * <b>4</b>: Connection refused: Bad user name or password<br>
1054   * <b>5</b>: Connection refused: Not authorized<br>
1055   * <b>6-255</b>: Reserved for future use<br>
1056   */
1057 LIBMQTT_API int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options);
1058 
1059 /** MQTT version 5.0 response information */
1060 typedef struct MQTTResponse
1061 {
1062 	int version;                        /* the version number of this structure */
1063 	enum MQTTReasonCodes reasonCode;    /* the MQTT 5.0 reason code returned */
1064 	int reasonCodeCount;	            /* the number of reason codes.  Used for subscribeMany5 and unsubscribeMany5 */
1065 	enum MQTTReasonCodes* reasonCodes;  /* a list of reason codes.  Used for subscribeMany5 and unsubscribeMany5 */
1066 	MQTTProperties* properties;         /* optionally, the MQTT 5.0 properties returned */
1067 } MQTTResponse;
1068 
1069 #define MQTTResponse_initializer {1, MQTTREASONCODE_SUCCESS, 0, NULL, NULL}
1070 
1071 /**
1072  * Frees the storage associated with the MQTT response.
1073  * @param response the response structure to be freed
1074  */
1075 LIBMQTT_API void MQTTResponse_free(MQTTResponse response);
1076 
1077 /**
1078   * Attempts to connect a previously-created client (see
1079   * MQTTClient_create()) to an MQTT server using MQTT version 5.0 and the specified options. If you
1080   * want to enable asynchronous message and status notifications, you must call
1081   * MQTTClient_setCallbacks() prior to MQTTClient_connect().
1082   * @param handle A valid client handle from a successful call to
1083   * MQTTClient_create().
1084   * @param options A pointer to a valid MQTTClient_connectOptions
1085   * structure.
1086   * @param connectProperties the MQTT 5.0 connect properties to use
1087   * @param willProperties the MQTT 5.0 properties to set on the will message
1088   * @return the MQTT 5.0 response information: error codes and properties.
1089   */
1090 LIBMQTT_API MQTTResponse MQTTClient_connect5(MQTTClient handle, MQTTClient_connectOptions* options,
1091 		MQTTProperties* connectProperties, MQTTProperties* willProperties);
1092 
1093 /**
1094   * This function attempts to disconnect the client from the MQTT
1095   * server. In order to allow the client time to complete handling of messages
1096   * that are in-flight when this function is called, a timeout period is
1097   * specified. When the timeout period has expired, the client disconnects even
1098   * if there are still outstanding message acknowledgements.
1099   * The next time the client connects to the same server, any QoS 1 or 2
1100   * messages which have not completed will be retried depending on the
1101   * cleansession settings for both the previous and the new connection (see
1102   * MQTTClient_connectOptions.cleansession and MQTTClient_connect()).
1103   * @param handle A valid client handle from a successful call to
1104   * MQTTClient_create().
1105   * @param timeout The client delays disconnection for up to this time (in
1106   * milliseconds) in order to allow in-flight message transfers to complete.
1107   * @return ::MQTTCLIENT_SUCCESS if the client successfully disconnects from
1108   * the server. An error code is returned if the client was unable to disconnect
1109   * from the server
1110   */
1111 LIBMQTT_API int MQTTClient_disconnect(MQTTClient handle, int timeout);
1112 
1113 LIBMQTT_API int MQTTClient_disconnect5(MQTTClient handle, int timeout, enum MQTTReasonCodes reason, MQTTProperties* props);
1114 
1115 /**
1116   * This function allows the client application to test whether or not a
1117   * client is currently connected to the MQTT server.
1118   * @param handle A valid client handle from a successful call to
1119   * MQTTClient_create().
1120   * @return Boolean true if the client is connected, otherwise false.
1121   */
1122 LIBMQTT_API int MQTTClient_isConnected(MQTTClient handle);
1123 
1124 #if defined(IOT_CONNECT) || defined(IOT_LITEOS_ADAPT)
1125 LIBMQTT_API int MQTTClient_getConnectState(MQTTClient handle);
1126 #endif
1127 /* Subscribe is synchronous.  QoS list parameter is changed on return to granted QoSs.
1128    Returns return code, MQTTCLIENT_SUCCESS == success, non-zero some sort of error (TBD) */
1129 
1130 /**
1131   * This function attempts to subscribe a client to a single topic, which may
1132   * contain wildcards (see @ref wildcard). This call also specifies the
1133   * @ref qos requested for the subscription
1134   * (see also MQTTClient_subscribeMany()).
1135   * @param handle A valid client handle from a successful call to
1136   * MQTTClient_create().
1137   * @param topic The subscription topic, which may include wildcards.
1138   * @param qos The requested quality of service for the subscription.
1139   * @return ::MQTTCLIENT_SUCCESS if the subscription request is successful.
1140   * An error code is returned if there was a problem registering the
1141   * subscription.
1142   */
1143 LIBMQTT_API int MQTTClient_subscribe(MQTTClient handle, const char* topic, int qos);
1144 
1145 /**
1146   * This function attempts to subscribe an MQTT version 5.0 client to a single topic, which may
1147   * contain wildcards (see @ref wildcard). This call also specifies the
1148   * @ref qos requested for the subscription
1149   * (see also MQTTClient_subscribeMany()).
1150   * @param handle A valid client handle from a successful call to
1151   * MQTTClient_create().
1152   * @param topic The subscription topic, which may include wildcards.
1153   * @param qos The requested quality of service for the subscription.
1154   * @param opts the MQTT 5.0 subscribe options to be used
1155   * @param props the MQTT 5.0 properties to be used
1156   * @return the MQTT 5.0 response information: error codes and properties.
1157   */
1158 LIBMQTT_API MQTTResponse MQTTClient_subscribe5(MQTTClient handle, const char* topic, int qos,
1159 		MQTTSubscribe_options* opts, MQTTProperties* props);
1160 
1161 /**
1162   * This function attempts to subscribe a client to a list of topics, which may
1163   * contain wildcards (see @ref wildcard). This call also specifies the
1164   * @ref qos requested for each topic (see also MQTTClient_subscribe()).
1165   * @param handle A valid client handle from a successful call to
1166   * MQTTClient_create().
1167   * @param count The number of topics for which the client is requesting
1168   * subscriptions.
1169   * @param topic An array (of length <i>count</i>) of pointers to
1170   * topics, each of which may include wildcards.
1171   * @param qos An array (of length <i>count</i>) of @ref qos
1172   * values. qos[n] is the requested QoS for topic[n].
1173   * @return ::MQTTCLIENT_SUCCESS if the subscription request is successful.
1174   * An error code is returned if there was a problem registering the
1175   * subscriptions.
1176   */
1177 LIBMQTT_API int MQTTClient_subscribeMany(MQTTClient handle, int count, char* const* topic, int* qos);
1178 
1179 /**
1180   * This function attempts to subscribe an MQTT version 5.0 client to a list of topics, which may
1181   * contain wildcards (see @ref wildcard). This call also specifies the
1182   * @ref qos requested for each topic (see also MQTTClient_subscribe()).
1183   * @param handle A valid client handle from a successful call to
1184   * MQTTClient_create().
1185   * @param count The number of topics for which the client is requesting
1186   * subscriptions.
1187   * @param topic An array (of length <i>count</i>) of pointers to
1188   * topics, each of which may include wildcards.
1189   * @param qos An array (of length <i>count</i>) of @ref qos
1190   * values. qos[n] is the requested QoS for topic[n].
1191   * @param opts the MQTT 5.0 subscribe options to be used
1192   * @param props the MQTT 5.0 properties to be used
1193   * @return the MQTT 5.0 response information: error codes and properties.
1194   */
1195 LIBMQTT_API MQTTResponse MQTTClient_subscribeMany5(MQTTClient handle, int count, char* const* topic,
1196 		int* qos, MQTTSubscribe_options* opts, MQTTProperties* props);
1197 
1198 /**
1199   * This function attempts to remove an existing subscription made by the
1200   * specified client.
1201   * @param handle A valid client handle from a successful call to
1202   * MQTTClient_create().
1203   * @param topic The topic for the subscription to be removed, which may
1204   * include wildcards (see @ref wildcard).
1205   * @return ::MQTTCLIENT_SUCCESS if the subscription is removed.
1206   * An error code is returned if there was a problem removing the
1207   * subscription.
1208   */
1209 LIBMQTT_API int MQTTClient_unsubscribe(MQTTClient handle, const char* topic);
1210 
1211 /**
1212   * This function attempts to remove an existing subscription made by the
1213   * specified client using MQTT 5.0.
1214   * @param handle A valid client handle from a successful call to
1215   * MQTTClient_create().
1216   * @param topic The topic for the subscription to be removed, which may
1217   * include wildcards (see @ref wildcard).
1218   * @param props the MQTT 5.0 properties to be used
1219   * @return the MQTT 5.0 response information: error codes and properties.
1220   */
1221 LIBMQTT_API MQTTResponse MQTTClient_unsubscribe5(MQTTClient handle, const char* topic, MQTTProperties* props);
1222 
1223 /**
1224   * This function attempts to remove existing subscriptions to a list of topics
1225   * made by the specified client.
1226   * @param handle A valid client handle from a successful call to
1227   * MQTTClient_create().
1228   * @param count The number subscriptions to be removed.
1229   * @param topic An array (of length <i>count</i>) of pointers to the topics of
1230   * the subscriptions to be removed, each of which may include wildcards.
1231   * @return ::MQTTCLIENT_SUCCESS if the subscriptions are removed.
1232   * An error code is returned if there was a problem removing the subscriptions.
1233   */
1234 LIBMQTT_API int MQTTClient_unsubscribeMany(MQTTClient handle, int count, char* const* topic);
1235 
1236 /**
1237   * This function attempts to remove existing subscriptions to a list of topics
1238   * made by the specified client using MQTT version 5.0.
1239   * @param handle A valid client handle from a successful call to
1240   * MQTTClient_create().
1241   * @param count The number subscriptions to be removed.
1242   * @param topic An array (of length <i>count</i>) of pointers to the topics of
1243   * the subscriptions to be removed, each of which may include wildcards.
1244   * @param props the MQTT 5.0 properties to be used
1245   * @return the MQTT 5.0 response information: error codes and properties.
1246   */
1247 LIBMQTT_API MQTTResponse MQTTClient_unsubscribeMany5(MQTTClient handle, int count, char* const* topic, MQTTProperties* props);
1248 
1249 /**
1250   * This function attempts to publish a message to a given topic (see also
1251   * MQTTClient_publishMessage()). An ::MQTTClient_deliveryToken is issued when
1252   * this function returns successfully. If the client application needs to
1253   * test for succesful delivery of QoS1 and QoS2 messages, this can be done
1254   * either asynchronously or synchronously (see @ref async,
1255   * ::MQTTClient_waitForCompletion and MQTTClient_deliveryComplete()).
1256   * @param handle A valid client handle from a successful call to
1257   * MQTTClient_create().
1258   * @param topicName The topic associated with this message.
1259   * @param payloadlen The length of the payload in bytes.
1260   * @param payload A pointer to the byte array payload of the message.
1261   * @param qos The @ref qos of the message.
1262   * @param retained The retained flag for the message.
1263   * @param dt A pointer to an ::MQTTClient_deliveryToken. This is populated
1264   * with a token representing the message when the function returns
1265   * successfully. If your application does not use delivery tokens, set this
1266   * argument to NULL.
1267   * @return ::MQTTCLIENT_SUCCESS if the message is accepted for publication.
1268   * An error code is returned if there was a problem accepting the message.
1269   */
1270 LIBMQTT_API int MQTTClient_publish(MQTTClient handle, const char* topicName, int payloadlen, const void* payload, int qos, int retained,
1271 		MQTTClient_deliveryToken* dt);
1272 
1273 /**
1274   * Attempts to publish a message to a given topic using MQTT version 5.0 (see also
1275   * MQTTClient_publishMessage5()). An ::MQTTClient_deliveryToken is issued when
1276   * this function returns successfully. If the client application needs to
1277   * test for succesful delivery of QoS1 and QoS2 messages, this can be done
1278   * either asynchronously or synchronously (see @ref async,
1279   * ::MQTTClient_waitForCompletion and MQTTClient_deliveryComplete()).
1280   * @param handle A valid client handle from a successful call to
1281   * MQTTClient_create().
1282   * @param topicName The topic associated with this message.
1283   * @param payloadlen The length of the payload in bytes.
1284   * @param payload A pointer to the byte array payload of the message.
1285   * @param qos The @ref qos of the message.
1286   * @param retained The retained flag for the message.
1287   * @param properties the MQTT 5.0 properties to be used
1288   * @param dt A pointer to an ::MQTTClient_deliveryToken. This is populated
1289   * with a token representing the message when the function returns
1290   * successfully. If your application does not use delivery tokens, set this
1291   * argument to NULL.
1292   * @return the MQTT 5.0 response information: error codes and properties.
1293   */
1294 LIBMQTT_API MQTTResponse MQTTClient_publish5(MQTTClient handle, const char* topicName, int payloadlen, const void* payload,
1295 		int qos, int retained, MQTTProperties* properties, MQTTClient_deliveryToken* dt);
1296 /**
1297   * This function attempts to publish a message to a given topic (see also
1298   * MQTTClient_publish()). An ::MQTTClient_deliveryToken is issued when
1299   * this function returns successfully. If the client application needs to
1300   * test for succesful delivery of QoS1 and QoS2 messages, this can be done
1301   * either asynchronously or synchronously (see @ref async,
1302   * ::MQTTClient_waitForCompletion and MQTTClient_deliveryComplete()).
1303   * @param handle A valid client handle from a successful call to
1304   * MQTTClient_create().
1305   * @param topicName The topic associated with this message.
1306   * @param msg A pointer to a valid MQTTClient_message structure containing
1307   * the payload and attributes of the message to be published.
1308   * @param dt A pointer to an ::MQTTClient_deliveryToken. This is populated
1309   * with a token representing the message when the function returns
1310   * successfully. If your application does not use delivery tokens, set this
1311   * argument to NULL.
1312   * @return ::MQTTCLIENT_SUCCESS if the message is accepted for publication.
1313   * An error code is returned if there was a problem accepting the message.
1314   */
1315 LIBMQTT_API int MQTTClient_publishMessage(MQTTClient handle, const char* topicName, MQTTClient_message* msg, MQTTClient_deliveryToken* dt);
1316 
1317 
1318 /**
1319   * Attempts to publish a message to the given topic using MQTT version 5.0
1320   * (see also
1321   * MQTTClient_publish5()). An ::MQTTClient_deliveryToken is issued when
1322   * this function returns successfully. If the client application needs to
1323   * test for succesful delivery of QoS1 and QoS2 messages, this can be done
1324   * either asynchronously or synchronously (see @ref async,
1325   * ::MQTTClient_waitForCompletion and MQTTClient_deliveryComplete()).
1326   * @param handle A valid client handle from a successful call to
1327   * MQTTClient_create().
1328   * @param topicName The topic associated with this message.
1329   * @param msg A pointer to a valid MQTTClient_message structure containing
1330   * the payload and attributes of the message to be published.
1331   * @param dt A pointer to an ::MQTTClient_deliveryToken. This is populated
1332   * with a token representing the message when the function returns
1333   * successfully. If your application does not use delivery tokens, set this
1334   * argument to NULL.
1335   * @return the MQTT 5.0 response information: error codes and properties.
1336   */
1337 LIBMQTT_API MQTTResponse MQTTClient_publishMessage5(MQTTClient handle, const char* topicName, MQTTClient_message* msg,
1338 		MQTTClient_deliveryToken* dt);
1339 
1340 /**
1341   * This function is called by the client application to synchronize execution
1342   * of the main thread with completed publication of a message. When called,
1343   * MQTTClient_waitForCompletion() blocks execution until the message has been
1344   * successful delivered or the specified timeout has expired. See @ref async.
1345   * @param handle A valid client handle from a successful call to
1346   * MQTTClient_create().
1347   * @param dt The ::MQTTClient_deliveryToken that represents the message being
1348   * tested for successful delivery. Delivery tokens are issued by the
1349   * publishing functions MQTTClient_publish() and MQTTClient_publishMessage().
1350   * @param timeout The maximum time to wait in milliseconds.
1351   * @return ::MQTTCLIENT_SUCCESS if the message was successfully delivered.
1352   * An error code is returned if the timeout expires or there was a problem
1353   * checking the token.
1354   */
1355 LIBMQTT_API int MQTTClient_waitForCompletion(MQTTClient handle, MQTTClient_deliveryToken dt, unsigned long timeout);
1356 
1357 
1358 /**
1359   * This function sets a pointer to an array of delivery tokens for
1360   * messages that are currently in-flight (pending completion).
1361   *
1362   * <b>Important note:</b> The memory used to hold the array of tokens is
1363   * malloc()'d in this function. The client application is responsible for
1364   * freeing this memory when it is no longer required.
1365   * @param handle A valid client handle from a successful call to
1366   * MQTTClient_create().
1367   * @param tokens The address of a pointer to an ::MQTTClient_deliveryToken.
1368   * When the function returns successfully, the pointer is set to point to an
1369   * array of tokens representing messages pending completion. The last member of
1370   * the array is set to -1 to indicate there are no more tokens. If no tokens
1371   * are pending, the pointer is set to NULL.
1372   * @return ::MQTTCLIENT_SUCCESS if the function returns successfully.
1373   * An error code is returned if there was a problem obtaining the list of
1374   * pending tokens.
1375   */
1376 LIBMQTT_API int MQTTClient_getPendingDeliveryTokens(MQTTClient handle, MQTTClient_deliveryToken **tokens);
1377 
1378 /**
1379   * When implementing a single-threaded client, call this function periodically
1380   * to allow processing of message retries and to send MQTT keepalive pings.
1381   * If the application is calling MQTTClient_receive() regularly, then it is
1382   * not necessary to call this function.
1383   */
1384 LIBMQTT_API void MQTTClient_yield(void);
1385 
1386 /**
1387   * This function performs a synchronous receive of incoming messages. It should
1388   * be used only when the client application has not set callback methods to
1389   * support asynchronous receipt of messages (see @ref async and
1390   * MQTTClient_setCallbacks()). Using this function allows a single-threaded
1391   * client subscriber application to be written. When called, this function
1392   * blocks until the next message arrives or the specified timeout expires
1393   *(see also MQTTClient_yield()).
1394   *
1395   * <b>Important note:</b> The application must free() the memory allocated
1396   * to the topic and the message when processing is complete (see
1397   * MQTTClient_freeMessage()).
1398   * @param handle A valid client handle from a successful call to
1399   * MQTTClient_create().
1400   * @param topicName The address of a pointer to a topic. This function
1401   * allocates the memory for the topic and returns it to the application
1402   * by setting <i>topicName</i> to point to the topic.
1403   * @param topicLen The length of the topic. If the return code from this
1404   * function is ::MQTTCLIENT_TOPICNAME_TRUNCATED, the topic contains embedded
1405   * NULL characters and the full topic should be retrieved by using
1406   * <i>topicLen</i>.
1407   * @param message The address of a pointer to the received message. This
1408   * function allocates the memory for the message and returns it to the
1409   * application by setting <i>message</i> to point to the received message.
1410   * The pointer is set to NULL if the timeout expires.
1411   * @param timeout The length of time to wait for a message in milliseconds.
1412   * @return ::MQTTCLIENT_SUCCESS or ::MQTTCLIENT_TOPICNAME_TRUNCATED if a
1413   * message is received. ::MQTTCLIENT_SUCCESS can also indicate that the
1414   * timeout expired, in which case <i>message</i> is NULL. An error code is
1415   * returned if there was a problem trying to receive a message.
1416   */
1417 LIBMQTT_API int MQTTClient_receive(MQTTClient handle, char** topicName, int* topicLen, MQTTClient_message** message,
1418 		unsigned long timeout);
1419 
1420 /**
1421   * This function frees memory allocated to an MQTT message, including the
1422   * additional memory allocated to the message payload. The client application
1423   * calls this function when the message has been fully processed. <b>Important
1424   * note:</b> This function does not free the memory allocated to a message
1425   * topic string. It is the responsibility of the client application to free
1426   * this memory using the MQTTClient_free() library function.
1427   * @param msg The address of a pointer to the ::MQTTClient_message structure
1428   * to be freed.
1429   */
1430 LIBMQTT_API void MQTTClient_freeMessage(MQTTClient_message** msg);
1431 
1432 /**
1433   * This function frees memory allocated by the MQTT C client library, especially the
1434   * topic name. This is needed on Windows when the client libary and application
1435   * program have been compiled with different versions of the C compiler.  It is
1436   * thus good policy to always use this function when freeing any MQTT C client-
1437   * allocated memory.
1438   * @param ptr The pointer to the client library storage to be freed.
1439   */
1440 LIBMQTT_API void MQTTClient_free(void* ptr);
1441 
1442 /**
1443   * This function frees the memory allocated to an MQTT client (see
1444   * MQTTClient_create()). It should be called when the client is no longer
1445   * required.
1446   * @param handle A pointer to the handle referring to the ::MQTTClient
1447   * structure to be freed.
1448   */
1449 LIBMQTT_API void MQTTClient_destroy(MQTTClient* handle);
1450 
1451 
1452 enum MQTTCLIENT_TRACE_LEVELS
1453 {
1454 	MQTTCLIENT_TRACE_MAXIMUM = 1,
1455 	MQTTCLIENT_TRACE_MEDIUM,
1456 	MQTTCLIENT_TRACE_MINIMUM,
1457 	MQTTCLIENT_TRACE_PROTOCOL,
1458 	MQTTCLIENT_TRACE_ERROR,
1459 	MQTTCLIENT_TRACE_SEVERE,
1460 	MQTTCLIENT_TRACE_FATAL,
1461 };
1462 
1463 
1464 /**
1465   * This function sets the level of trace information which will be
1466   * returned in the trace callback.
1467   * @param level the trace level required
1468   */
1469 LIBMQTT_API void MQTTClient_setTraceLevel(enum MQTTCLIENT_TRACE_LEVELS level);
1470 
1471 
1472 /**
1473   * This is a callback function prototype which must be implemented if you want
1474   * to receive trace information. Do not invoke any other Paho API calls in this
1475   * callback function - unpredictable behavior may result.
1476   * @param level the trace level of the message returned
1477   * @param message the trace message.  This is a pointer to a static buffer which
1478   * will be overwritten on each call.  You must copy the data if you want to keep
1479   * it for later.
1480   */
1481 typedef void MQTTClient_traceCallback(enum MQTTCLIENT_TRACE_LEVELS level, char* message);
1482 
1483 /**
1484   * This function sets the trace callback if needed.  If set to NULL,
1485   * no trace information will be returned.  The default trace level is
1486   * MQTTASYNC_TRACE_MINIMUM.
1487   * @param callback a pointer to the function which will handle the trace information
1488   */
1489 LIBMQTT_API void MQTTClient_setTraceCallback(MQTTClient_traceCallback* callback);
1490 
1491 /**
1492   * Sets the timeout value for un/subscribe commands when waiting for the un/suback response from
1493   * the server.  Values less than 5000 are not allowed.
1494   * @param handle A valid client handle from a successful call to MQTTClient_create().
1495   * @param milliSeconds the maximum number of milliseconds to wait
1496   * @return MQTTCLIENT_SUCCESS or MQTTCLIENT_FAILURE
1497   */
1498 LIBMQTT_API int MQTTClient_setCommandTimeout(MQTTClient handle, unsigned long milliSeconds);
1499 
1500 /**
1501  * Returns a pointer to the string representation of the error or NULL.
1502  *
1503  * Do not free after use. Returns NULL if the error code is unknown.
1504  */
1505 LIBMQTT_API const char* MQTTClient_strerror(int code);
1506 
1507 #if defined(__cplusplus)
1508      }
1509 #endif
1510 
1511 #endif
1512 
1513 /*!
1514   * @cond MQTTClient_main
1515   * @page async Asynchronous vs synchronous client applications
1516   * This client library supports two modes of operation. These are referred to
1517   * as <b>synchronous</b> and <b>asynchronous</b> modes. If your application
1518   * calls MQTTClient_setCallbacks(), this puts the client into asynchronous
1519   * mode, otherwise it operates in synchronous mode.
1520   *
1521   * In synchronous mode, the client application runs on a single thread.
1522   * Messages are published using the MQTTClient_publish() and
1523   * MQTTClient_publishMessage() functions. To determine that a QoS1 or QoS2
1524   * (see @ref qos) message has been successfully delivered, the application
1525   * must call the MQTTClient_waitForCompletion() function. An example showing
1526   * synchronous publication is shown in @ref pubsync. Receiving messages in
1527   * synchronous mode uses the MQTTClient_receive() function. Client applications
1528   * must call either MQTTClient_receive() or MQTTClient_yield() relatively
1529   * frequently in order to allow processing of acknowledgements and the MQTT
1530   * "pings" that keep the network connection to the server alive.
1531   *
1532   * In asynchronous mode, the client application runs on several threads. The
1533   * main program calls functions in the client library to publish and subscribe,
1534   * just as for the synchronous mode. Processing of handshaking and maintaining
1535   * the network connection is performed in the background, however.
1536   * Notifications of status and message reception are provided to the client
1537   * application using callbacks registered with the library by the call to
1538   * MQTTClient_setCallbacks() (see MQTTClient_messageArrived(),
1539   * MQTTClient_connectionLost() and MQTTClient_deliveryComplete()).
1540   * This API is not thread safe however - it is not possible to call it from multiple
1541   * threads without synchronization.  You can use the MQTTAsync API for that.
1542   *
1543   * @page callbacks Callbacks
1544   * You must not call a function from this API from within a callback otherwise
1545   * a deadlock might result.  The only exception to this is the ability to call
1546   * connect within the connection lost callback, to allow a reconnect.
1547   *
1548   * When using MQTT 5.0, you can also call connect from within the disconnected
1549   * callback, which is invoked when the MQTT server sends a disconnect packet.
1550   * This server behaviour is allowed in MQTT 5.0, but not in MQTT 3.1.1, so the
1551   * disconnected callback will never be invoked if you use MQTT 3.1.1.
1552   *
1553   * In particular, you must make a publish call within the message arrived callback.
1554   * These restrictions are all lifted in the
1555   * <a href="../../MQTTAsync/html/index.html">MQTTAsync API</a>.
1556   *
1557   * If no callbacks are assigned, this will include the message arrived callback.
1558   * This could be done if the application is a pure publisher, and does
1559   * not subscribe to any topics.  If however messages are received, and no message
1560   * arrived callback is set, or receive not called, then those messages will accumulate
1561   * and take up memory, as there is no place for them to be delivered.
1562   * It is up to the application to protect against this situation.
1563   *
1564   * @page wildcard Subscription wildcards
1565   * Every MQTT message includes a topic that classifies it. MQTT servers use
1566   * topics to determine which subscribers should receive messages published to
1567   * the server.
1568   *
1569   * Consider the server receiving messages from several environmental sensors.
1570   * Each sensor publishes its measurement data as a message with an associated
1571   * topic. Subscribing applications need to know which sensor originally
1572   * published each received message. A unique topic is thus used to identify
1573   * each sensor and measurement type. Topics such as SENSOR1TEMP,
1574   * SENSOR1HUMIDITY, SENSOR2TEMP and so on achieve this but are not very
1575   * flexible. If additional sensors are added to the system at a later date,
1576   * subscribing applications must be modified to receive them.
1577   *
1578   * To provide more flexibility, MQTT supports a hierarchical topic namespace.
1579   * This allows application designers to organize topics to simplify their
1580   * management. Levels in the hierarchy are delimited by the '/' character,
1581   * such as SENSOR/1/HUMIDITY. Publishers and subscribers use these
1582   * hierarchical topics as already described.
1583   *
1584   * For subscriptions, two wildcard characters are supported:
1585   * <ul>
1586   * <li>A '#' character represents a complete sub-tree of the hierarchy and
1587   * thus must be the last character in a subscription topic string, such as
1588   * SENSOR/#. This will match any topic starting with SENSOR/, such as
1589   * SENSOR/1/TEMP and SENSOR/2/HUMIDITY.</li>
1590   * <li> A '+' character represents a single level of the hierarchy and is
1591   * used between delimiters. For example, SENSOR/+/TEMP will match
1592   * SENSOR/1/TEMP and SENSOR/2/TEMP.</li>
1593   * </ul>
1594   * Publishers are not allowed to use the wildcard characters in their topic
1595   * names.
1596   *
1597   * Deciding on your topic hierarchy is an important step in your system design.
1598   *
1599   * @page qos Quality of service
1600   * The MQTT protocol provides three qualities of service for delivering
1601   * messages between clients and servers: "at most once", "at least once" and
1602   * "exactly once".
1603   *
1604   * Quality of service (QoS) is an attribute of an individual message being
1605   * published. An application sets the QoS for a specific message by setting the
1606   * MQTTClient_message.qos field to the required value.
1607   *
1608   * A subscribing client can set the maximum quality of service a server uses
1609   * to send messages that match the client subscriptions. The
1610   * MQTTClient_subscribe() and MQTTClient_subscribeMany() functions set this
1611   * maximum. The QoS of a message forwarded to a subscriber thus might be
1612   * different to the QoS given to the message by the original publisher.
1613   * The lower of the two values is used to forward a message.
1614   *
1615   * The three levels are:
1616   *
1617   * <b>QoS0, At most once:</b> The message is delivered at most once, or it
1618   * may not be delivered at all. Its delivery across the network is not
1619   * acknowledged. The message is not stored. The message could be lost if the
1620   * client is disconnected, or if the server fails. QoS0 is the fastest mode of
1621   * transfer. It is sometimes called "fire and forget".
1622   *
1623   * The MQTT protocol does not require servers to forward publications at QoS0
1624   * to a client. If the client is disconnected at the time the server receives
1625   * the publication, the publication might be discarded, depending on the
1626   * server implementation.
1627   *
1628   * <b>QoS1, At least once:</b> The message is always delivered at least once.
1629   * It might be delivered multiple times if there is a failure before an
1630   * acknowledgment is received by the sender. The message must be stored
1631   * locally at the sender, until the sender receives confirmation that the
1632   * message has been published by the receiver. The message is stored in case
1633   * the message must be sent again.
1634   *
1635   * <b>QoS2, Exactly once:</b> The message is always delivered exactly once.
1636   * The message must be stored locally at the sender, until the sender receives
1637   * confirmation that the message has been published by the receiver. The
1638   * message is stored in case the message must be sent again. QoS2 is the
1639   * safest, but slowest mode of transfer. A more sophisticated handshaking
1640   * and acknowledgement sequence is used than for QoS1 to ensure no duplication
1641   * of messages occurs.
1642   * @page pubsync Synchronous publication example
1643 @code
1644 #include <stdio.h>
1645 #include <stdlib.h>
1646 #include <string.h>
1647 #include "MQTTClient.h"
1648 
1649 #define ADDRESS     "tcp://mqtt.eclipseprojects.io:1883"
1650 #define CLIENTID    "ExampleClientPub"
1651 #define TOPIC       "MQTT Examples"
1652 #define PAYLOAD     "Hello World!"
1653 #define QOS         1
1654 #define TIMEOUT     10000L
1655 
1656 int main(int argc, char* argv[])
1657 {
1658     MQTTClient client;
1659     MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
1660     MQTTClient_message pubmsg = MQTTClient_message_initializer;
1661     MQTTClient_deliveryToken token;
1662     int rc;
1663 
1664     if ((rc = MQTTClient_create(&client, ADDRESS, CLIENTID,
1665         MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
1666     {
1667          printf("Failed to create client, return code %d\n", rc);
1668          exit(EXIT_FAILURE);
1669     }
1670 
1671     conn_opts.keepAliveInterval = 20;
1672     conn_opts.cleansession = 1;
1673     if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
1674     {
1675         printf("Failed to connect, return code %d\n", rc);
1676         exit(EXIT_FAILURE);
1677     }
1678 
1679     pubmsg.payload = PAYLOAD;
1680     pubmsg.payloadlen = (int)strlen(PAYLOAD);
1681     pubmsg.qos = QOS;
1682     pubmsg.retained = 0;
1683     if ((rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
1684     {
1685          printf("Failed to publish message, return code %d\n", rc);
1686          exit(EXIT_FAILURE);
1687     }
1688 
1689     printf("Waiting for up to %d seconds for publication of %s\n"
1690             "on topic %s for client with ClientID: %s\n",
1691             (int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
1692     rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
1693     printf("Message with delivery token %d delivered\n", token);
1694 
1695     if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
1696     	printf("Failed to disconnect, return code %d\n", rc);
1697     MQTTClient_destroy(&client);
1698     return rc;
1699 }
1700 
1701   * @endcode
1702   *
1703   * @page pubasync Asynchronous publication example
1704 @code{.c}
1705 #include <stdio.h>
1706 #include <stdlib.h>
1707 #include <string.h>
1708 #include "MQTTClient.h"
1709 
1710 #if !defined(_WIN32)
1711 #include <unistd.h>
1712 #else
1713 #include <windows.h>
1714 #endif
1715 
1716 #define ADDRESS     "tcp://mqtt.eclipseprojects.io:1883"
1717 #define CLIENTID    "ExampleClientPub"
1718 #define TOPIC       "MQTT Examples"
1719 #define PAYLOAD     "Hello World!"
1720 #define QOS         1
1721 #define TIMEOUT     10000L
1722 
1723 MQTTClient_deliveryToken deliveredtoken;
1724 
1725 void delivered(void *context, MQTTClient_deliveryToken dt)
1726 {
1727     printf("Message with token value %d delivery confirmed\n", dt);
1728     deliveredtoken = dt;
1729 }
1730 
1731 int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
1732 {
1733     printf("Message arrived\n");
1734     printf("     topic: %s\n", topicName);
1735     printf("   message: %.*s\n", message->payloadlen, (char*)message->payload);
1736     MQTTClient_freeMessage(&message);
1737     MQTTClient_free(topicName);
1738     return 1;
1739 }
1740 
1741 void connlost(void *context, char *cause)
1742 {
1743     printf("\nConnection lost\n");
1744     printf("     cause: %s\n", cause);
1745 }
1746 
1747 int main(int argc, char* argv[])
1748 {
1749     MQTTClient client;
1750     MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
1751     MQTTClient_message pubmsg = MQTTClient_message_initializer;
1752     MQTTClient_deliveryToken token;
1753     int rc;
1754 
1755     if ((rc = MQTTClient_create(&client, ADDRESS, CLIENTID,
1756         MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
1757     {
1758         printf("Failed to create client, return code %d\n", rc);
1759         rc = EXIT_FAILURE;
1760         goto exit;
1761     }
1762 
1763     if ((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
1764     {
1765         printf("Failed to set callbacks, return code %d\n", rc);
1766         rc = EXIT_FAILURE;
1767         goto destroy_exit;
1768     }
1769 
1770     conn_opts.keepAliveInterval = 20;
1771     conn_opts.cleansession = 1;
1772     if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
1773     {
1774         printf("Failed to connect, return code %d\n", rc);
1775         rc = EXIT_FAILURE;
1776         goto destroy_exit;
1777     }
1778 
1779     pubmsg.payload = PAYLOAD;
1780     pubmsg.payloadlen = (int)strlen(PAYLOAD);
1781     pubmsg.qos = QOS;
1782     pubmsg.retained = 0;
1783     deliveredtoken = 0;
1784     if ((rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
1785     {
1786     	printf("Failed to publish message, return code %d\n", rc);
1787     	rc = EXIT_FAILURE;
1788     }
1789     else
1790     {
1791     	printf("Waiting for publication of %s\n"
1792             "on topic %s for client with ClientID: %s\n",
1793             PAYLOAD, TOPIC, CLIENTID);
1794     	while (deliveredtoken != token)
1795     	{
1796 			#if defined(_WIN32)
1797 				Sleep(100);
1798 			#else
1799 				usleep(10000L);
1800 			#endif
1801     	}
1802     }
1803 
1804     if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
1805     {
1806     	printf("Failed to disconnect, return code %d\n", rc);
1807     	rc = EXIT_FAILURE;
1808     }
1809 
1810 destroy_exit:
1811     MQTTClient_destroy(&client);
1812 
1813 exit:
1814     return rc;
1815 }
1816 
1817   * @endcode
1818   * @page subasync Asynchronous subscription example
1819 @code
1820 #include <stdio.h>
1821 #include <stdlib.h>
1822 #include <string.h>
1823 #include "MQTTClient.h"
1824 
1825 #define ADDRESS     "tcp://mqtt.eclipseprojects.io:1883"
1826 #define CLIENTID    "ExampleClientSub"
1827 #define TOPIC       "MQTT Examples"
1828 #define PAYLOAD     "Hello World!"
1829 #define QOS         1
1830 #define TIMEOUT     10000L
1831 
1832 volatile MQTTClient_deliveryToken deliveredtoken;
1833 
1834 void delivered(void *context, MQTTClient_deliveryToken dt)
1835 {
1836     printf("Message with token value %d delivery confirmed\n", dt);
1837     deliveredtoken = dt;
1838 }
1839 
1840 int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
1841 {
1842     printf("Message arrived\n");
1843     printf("     topic: %s\n", topicName);
1844     printf("   message: %.*s\n", message->payloadlen, (char*)message->payload);
1845     MQTTClient_freeMessage(&message);
1846     MQTTClient_free(topicName);
1847     return 1;
1848 }
1849 
1850 void connlost(void *context, char *cause)
1851 {
1852     printf("\nConnection lost\n");
1853     printf("     cause: %s\n", cause);
1854 }
1855 
1856 int main(int argc, char* argv[])
1857 {
1858     MQTTClient client;
1859     MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
1860     int rc;
1861 
1862     if ((rc = MQTTClient_create(&client, ADDRESS, CLIENTID,
1863         MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
1864     {
1865         printf("Failed to create client, return code %d\n", rc);
1866         rc = EXIT_FAILURE;
1867         goto exit;
1868     }
1869 
1870     if ((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
1871     {
1872         printf("Failed to set callbacks, return code %d\n", rc);
1873         rc = EXIT_FAILURE;
1874         goto destroy_exit;
1875     }
1876 
1877     conn_opts.keepAliveInterval = 20;
1878     conn_opts.cleansession = 1;
1879     if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
1880     {
1881         printf("Failed to connect, return code %d\n", rc);
1882         rc = EXIT_FAILURE;
1883         goto destroy_exit;
1884     }
1885 
1886     printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
1887            "Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
1888     if ((rc = MQTTClient_subscribe(client, TOPIC, QOS)) != MQTTCLIENT_SUCCESS)
1889     {
1890     	printf("Failed to subscribe, return code %d\n", rc);
1891     	rc = EXIT_FAILURE;
1892     }
1893     else
1894     {
1895     	int ch;
1896     	do
1897     	{
1898         	ch = getchar();
1899     	} while (ch!='Q' && ch != 'q');
1900 
1901         if ((rc = MQTTClient_unsubscribe(client, TOPIC)) != MQTTCLIENT_SUCCESS)
1902         {
1903         	printf("Failed to unsubscribe, return code %d\n", rc);
1904         	rc = EXIT_FAILURE;
1905         }
1906     }
1907 
1908     if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
1909     {
1910     	printf("Failed to disconnect, return code %d\n", rc);
1911     	rc = EXIT_FAILURE;
1912     }
1913 destroy_exit:
1914     MQTTClient_destroy(&client);
1915 exit:
1916     return rc;
1917 }
1918 
1919   * @endcode
1920   * @page tracing Tracing
1921   *
1922   * Runtime tracing is controlled by environment variables.
1923   *
1924   * Tracing is switched on by setting MQTT_C_CLIENT_TRACE.  A value of ON, or stdout, prints to
1925   * stdout, any other value is interpreted as a file name to use.
1926   *
1927   * The amount of trace detail is controlled with the MQTT_C_CLIENT_TRACE_LEVEL environment
1928   * variable - valid values are ERROR, PROTOCOL, MINIMUM, MEDIUM and MAXIMUM
1929   * (from least to most verbose).
1930   *
1931   * The variable MQTT_C_CLIENT_TRACE_MAX_LINES limits the number of lines of trace that are output
1932   * to a file.  Two files are used at most, when they are full, the last one is overwritten with the
1933   * new trace entries.  The default size is 1000 lines.
1934   *
1935   * ### MQTT Packet Tracing
1936   *
1937   * A feature that can be very useful is printing the MQTT packets that are sent and received.  To
1938   * achieve this, use the following environment variable settings:
1939   * @code
1940     MQTT_C_CLIENT_TRACE=ON
1941     MQTT_C_CLIENT_TRACE_LEVEL=PROTOCOL
1942   * @endcode
1943   * The output you should see looks like this:
1944   * @code
1945     20130528 155936.813 3 stdout-subscriber -> CONNECT cleansession: 1 (0)
1946     20130528 155936.813 3 stdout-subscriber <- CONNACK rc: 0
1947     20130528 155936.813 3 stdout-subscriber -> SUBSCRIBE msgid: 1 (0)
1948     20130528 155936.813 3 stdout-subscriber <- SUBACK msgid: 1
1949     20130528 155941.818 3 stdout-subscriber -> DISCONNECT (0)
1950   * @endcode
1951   * where the fields are:
1952   * 1. date
1953   * 2. time
1954   * 3. socket number
1955   * 4. client id
1956   * 5. direction (-> from client to server, <- from server to client)
1957   * 6. packet details
1958   *
1959   * ### Default Level Tracing
1960   *
1961   * This is an extract of a default level trace of a call to connect:
1962   * @code
1963     19700101 010000.000 (1152206656) (0)> MQTTClient_connect:893
1964     19700101 010000.000 (1152206656)  (1)> MQTTClient_connectURI:716
1965     20130528 160447.479 Connecting to serverURI localhost:1883
1966     20130528 160447.479 (1152206656)   (2)> MQTTProtocol_connect:98
1967     20130528 160447.479 (1152206656)    (3)> MQTTProtocol_addressPort:48
1968     20130528 160447.479 (1152206656)    (3)< MQTTProtocol_addressPort:73
1969     20130528 160447.479 (1152206656)    (3)> Socket_new:599
1970     20130528 160447.479 New socket 4 for localhost, port 1883
1971     20130528 160447.479 (1152206656)     (4)> Socket_addSocket:163
1972     20130528 160447.479 (1152206656)      (5)> Socket_setnonblocking:73
1973     20130528 160447.479 (1152206656)      (5)< Socket_setnonblocking:78 (0)
1974     20130528 160447.479 (1152206656)     (4)< Socket_addSocket:176 (0)
1975     20130528 160447.479 (1152206656)     (4)> Socket_error:95
1976     20130528 160447.479 (1152206656)     (4)< Socket_error:104 (115)
1977     20130528 160447.479 Connect pending
1978     20130528 160447.479 (1152206656)    (3)< Socket_new:683 (115)
1979     20130528 160447.479 (1152206656)   (2)< MQTTProtocol_connect:131 (115)
1980   * @endcode
1981   * where the fields are:
1982   * 1. date
1983   * 2. time
1984   * 3. thread id
1985   * 4. function nesting level
1986   * 5. function entry (>) or exit (<)
1987   * 6. function name : line of source code file
1988   * 7. return value (if there is one)
1989   *
1990   * ### Memory Allocation Tracing
1991   *
1992   * Setting the trace level to maximum causes memory allocations and frees to be traced along with
1993   * the default trace entries, with messages like the following:
1994   * @code
1995     20130528 161819.657 Allocating 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 177 ptr 0x179f930
1996 
1997     20130528 161819.657 Freeing 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 201, heap use now 896 bytes
1998   * @endcode
1999   * When the last MQTT client object is destroyed, if the trace is being recorded
2000   * and all memory allocated by the client library has not been freed, an error message will be
2001   * written to the trace.  This can help with fixing memory leaks.  The message will look like this:
2002   * @code
2003     20130528 163909.208 Some memory not freed at shutdown, possible memory leak
2004     20130528 163909.208 Heap scan start, total 880 bytes
2005     20130528 163909.208 Heap element size 32, line 354, file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c, ptr 0x260cb00
2006     20130528 163909.208   Content
2007     20130528 163909.209 Heap scan end
2008   * @endcode
2009   * @endcond
2010   */
2011