• 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
15  *    Ian Craggs, Allan Stockdill-Mander - SSL connections
16  *    Ian Craggs - multiple server connection support
17  *    Ian Craggs - MQTT 3.1.1 support
18  *    Ian Craggs - fix for bug 444103 - success/failure callbacks not invoked
19  *    Ian Craggs - automatic reconnect and offline buffering (send while disconnected)
20  *    Ian Craggs - binary will message
21  *    Ian Craggs - binary password
22  *    Ian Craggs - remove const on eyecatchers #168
23  *    Ian Craggs - MQTT 5.0
24  *******************************************************************************/
25 
26 /********************************************************************/
27 
28 /**
29  * @cond MQTTAsync_main
30  * @mainpage Asynchronous MQTT client library for C (MQTTAsync)
31  *
32  * © Copyright 2009, 2022 IBM Corp., Ian Craggs and others
33  *
34  * @brief An Asynchronous MQTT client library for C.
35  *
36  * An MQTT client application connects to MQTT-capable servers.
37  * A typical client is responsible for collecting information from a telemetry
38  * device and publishing the information to the server. It can also subscribe
39  * to topics, receive messages, and use this information to control the
40  * telemetry device.
41  *
42  * MQTT clients implement the published MQTT v3 protocol. You can write your own
43  * API to the MQTT protocol using the programming language and platform of your
44  * choice. This can be time-consuming and error-prone.
45  *
46  * To simplify writing MQTT client applications, this library encapsulates
47  * the MQTT v3 protocol for you. Using this library enables a fully functional
48  * MQTT client application to be written in a few lines of code.
49  * The information presented here documents the API provided
50  * by the Asynchronous MQTT Client library for C.
51  *
52  * <b>Using the client</b><br>
53  * Applications that use the client library typically use a similar structure:
54  * <ul>
55  * <li>Create a client object</li>
56  * <li>Set the options to connect to an MQTT server</li>
57  * <li>Set up callback functions</li>
58  * <li>Connect the client to an MQTT server</li>
59  * <li>Subscribe to any topics the client needs to receive</li>
60  * <li>Repeat until finished:</li>
61  *     <ul>
62  *     <li>Publish any messages the client needs to</li>
63  *     <li>Handle any incoming messages</li>
64  *     </ul>
65  * <li>Disconnect the client</li>
66  * <li>Free any memory being used by the client</li>
67  * </ul>
68  * Some simple examples are shown here:
69  * <ul>
70  * <li>@ref publish</li>
71  * <li>@ref subscribe</li>
72  * </ul>
73  * Additional information about important concepts is provided here:
74  * <ul>
75  * <li>@ref async</li>
76  * <li>@ref wildcard</li>
77  * <li>@ref qos</li>
78  * <li>@ref tracing</li>
79  * <li>@ref auto_reconnect</li>
80  * <li>@ref offline_publish</li>
81  * </ul>
82  * @endcond
83  */
84 
85 /*
86 /// @cond EXCLUDE
87 */
88 #if !defined(MQTTASYNC_H)
89 #define MQTTASYNC_H
90 
91 #if defined(__cplusplus)
92  extern "C" {
93 #endif
94 
95 #include <stdio.h>
96 /*
97 /// @endcond
98 */
99 
100 #include "MQTTExportDeclarations.h"
101 
102 #include "MQTTProperties.h"
103 #include "MQTTReasonCodes.h"
104 #include "MQTTSubscribeOpts.h"
105 #if !defined(NO_PERSISTENCE)
106 #include "MQTTClientPersistence.h"
107 #endif
108 
109 /**
110  * Return code: No error. Indicates successful completion of an MQTT client
111  * operation.
112  */
113 #define MQTTASYNC_SUCCESS 0
114 /**
115  * Return code: A generic error code indicating the failure of an MQTT client
116  * operation.
117  */
118 #define MQTTASYNC_FAILURE -1
119 
120 /* error code -2 is MQTTAsync_PERSISTENCE_ERROR */
121 
122 #define MQTTASYNC_PERSISTENCE_ERROR -2
123 
124 /**
125  * Return code: The client is disconnected.
126  */
127 #define MQTTASYNC_DISCONNECTED -3
128 /**
129  * Return code: The maximum number of messages allowed to be simultaneously
130  * in-flight has been reached.
131  */
132 #define MQTTASYNC_MAX_MESSAGES_INFLIGHT -4
133 /**
134  * Return code: An invalid UTF-8 string has been detected.
135  */
136 #define MQTTASYNC_BAD_UTF8_STRING -5
137 /**
138  * Return code: A NULL parameter has been supplied when this is invalid.
139  */
140 #define MQTTASYNC_NULL_PARAMETER -6
141 /**
142  * Return code: The topic has been truncated (the topic string includes
143  * embedded NULL characters). String functions will not access the full topic.
144  * Use the topic length value to access the full topic.
145  */
146 #define MQTTASYNC_TOPICNAME_TRUNCATED -7
147 /**
148  * Return code: A structure parameter does not have the correct eyecatcher
149  * and version number.
150  */
151 #define MQTTASYNC_BAD_STRUCTURE -8
152 /**
153  * Return code: A qos parameter is not 0, 1 or 2
154  */
155 #define MQTTASYNC_BAD_QOS -9
156 /**
157  * Return code: All 65535 MQTT msgids are being used
158  */
159 #define MQTTASYNC_NO_MORE_MSGIDS -10
160 /**
161  * Return code: the request is being discarded when not complete
162  */
163 #define MQTTASYNC_OPERATION_INCOMPLETE -11
164 /**
165  * Return code: no more messages can be buffered
166  */
167 #define MQTTASYNC_MAX_BUFFERED_MESSAGES -12
168 /**
169  * Return code: Attempting SSL connection using non-SSL version of library
170  */
171 #define MQTTASYNC_SSL_NOT_SUPPORTED -13
172 /**
173  * Return code: protocol prefix in serverURI should be:
174  * @li @em tcp:// or @em mqtt:// - Insecure TCP
175  * @li @em ssl:// or @em mqtts:// - Encrypted SSL/TLS
176  * @li @em ws:// - Insecure websockets
177  * @li @em wss:// - Secure web sockets
178  *
179  * The TLS enabled prefixes (ssl, mqtts, wss) are only valid if the TLS
180  * version of the library is linked with.
181  */
182 #define MQTTASYNC_BAD_PROTOCOL -14
183 /**
184  * Return code: don't use options for another version of MQTT
185  */
186 #define MQTTASYNC_BAD_MQTT_OPTION -15
187 /**
188  * Return code: call not applicable to the client's version of MQTT
189  */
190 #define MQTTASYNC_WRONG_MQTT_VERSION -16
191 /**
192  *  Return code: 0 length will topic
193  */
194 #define MQTTASYNC_0_LEN_WILL_TOPIC -17
195 /*
196  * Return code: connect or disconnect command ignored because there is already a connect or disconnect
197  * command at the head of the list waiting to be processed. Use the onSuccess/onFailure callbacks to wait
198  * for the previous connect or disconnect command to be complete.
199  */
200 #define MQTTASYNC_COMMAND_IGNORED -18
201  /*
202   * Return code: maxBufferedMessages in the connect options must be >= 0
203   */
204  #define MQTTASYNC_MAX_BUFFERED -19
205 
206 /**
207  * Default MQTT version to connect with.  Use 3.1.1 then fall back to 3.1
208  */
209 #define MQTTVERSION_DEFAULT 0
210 /**
211  * MQTT version to connect with: 3.1
212  */
213 #define MQTTVERSION_3_1 3
214 /**
215  * MQTT version to connect with: 3.1.1
216  */
217 #define MQTTVERSION_3_1_1 4
218 /**
219  * MQTT version to connect with: 5
220  */
221 #define MQTTVERSION_5 5
222 /**
223  * Bad return code from subscribe, as defined in the 3.1.1 specification
224  */
225 #define MQTT_BAD_SUBSCRIBE 0x80
226 
227 
228 /**
229  *  Initialization options
230  */
231 typedef struct
232 {
233 	/** The eyecatcher for this structure.  Must be MQTG. */
234 	char struct_id[4];
235 	/** The version number of this structure.  Must be 0 */
236 	int struct_version;
237 	/** 1 = we do openssl init, 0 = leave it to the application */
238 	int do_openssl_init;
239 } MQTTAsync_init_options;
240 
241 #define MQTTAsync_init_options_initializer { {'M', 'Q', 'T', 'G'}, 0, 0 }
242 
243 /**
244  * Global init of mqtt library. Call once on program start to set global behaviour.
245  * handle_openssl_init - if mqtt library should handle openssl init (1) or rely on the caller to init it before using mqtt (0)
246  */
247 LIBMQTT_API void MQTTAsync_global_init(MQTTAsync_init_options* inits);
248 
249 /**
250  * A handle representing an MQTT client. A valid client handle is available
251  * following a successful call to MQTTAsync_create().
252  */
253 typedef void* MQTTAsync;
254 /**
255  * A value representing an MQTT message. A token is returned to the
256  * client application when a message is published. The token can then be used to
257  * check that the message was successfully delivered to its destination (see
258  * MQTTAsync_publish(),
259  * MQTTAsync_publishMessage(),
260  * MQTTAsync_deliveryComplete(), and
261  * MQTTAsync_getPendingTokens()).
262  */
263 typedef int MQTTAsync_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 MQTTAsync_publishMessage(),
268  * MQTTAsync_publish(), MQTTAsync_receive(), MQTTAsync_freeMessage()
269  * and MQTTAsync_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.  This is an output parameter only.
320       */
321 	int dup;
322 	/** The message identifier is reserved for internal use by the
323       * MQTT client and server.  It is an output parameter only - writing
324       * to it will serve no purpose.  It contains the MQTT message id of
325       * an incoming publish message.
326       */
327 	int msgid;
328 	/**
329 	 * The MQTT V5 properties associated with the message.
330 	 */
331 	MQTTProperties properties;
332 } MQTTAsync_message;
333 
334 #define MQTTAsync_message_initializer { {'M', 'Q', 'T', 'M'}, 1, 0, NULL, 0, 0, 0, 0, MQTTProperties_initializer }
335 
336 /**
337  * This is a callback function. The client application
338  * must provide an implementation of this function to enable asynchronous
339  * receipt of messages. The function is registered with the client library by
340  * passing it as an argument to MQTTAsync_setCallbacks(). It is
341  * called by the client library when a new message that matches a client
342  * subscription has been received from the server. This function is executed on
343  * a separate thread to the one on which the client application is running.
344  *
345  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
346  * called within this callback.
347  * @param context A pointer to the <i>context</i> value originally passed to
348  * MQTTAsync_setCallbacks(), which contains any application-specific context.
349  * @param topicName The topic associated with the received message.
350  * @param topicLen The length of the topic if there are one
351  * more NULL characters embedded in <i>topicName</i>, otherwise <i>topicLen</i>
352  * is 0. If <i>topicLen</i> is 0, the value returned by <i>strlen(topicName)</i>
353  * can be trusted. If <i>topicLen</i> is greater than 0, the full topic name
354  * can be retrieved by accessing <i>topicName</i> as a byte array of length
355  * <i>topicLen</i>.
356  * @param message The MQTTAsync_message structure for the received message.
357  * This structure contains the message payload and attributes.
358  * @return This function must return 0 or 1 indicating whether or not
359  * the message has been safely received by the client application. <br>
360  * Returning 1 indicates that the message has been successfully handled.
361  * To free the message storage, ::MQTTAsync_freeMessage must be called.
362  * To free the topic name storage, ::MQTTAsync_free must be called.<br>
363  * Returning 0 indicates that there was a problem. In this
364  * case, the client library will reinvoke MQTTAsync_messageArrived() to
365  * attempt to deliver the message to the application again.
366  * Do not free the message and topic storage when returning 0, otherwise
367  * the redelivery will fail.
368  */
369 typedef int MQTTAsync_messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message);
370 
371 /**
372  * This is a callback function. The client application
373  * must provide an implementation of this function to enable asynchronous
374  * notification of delivery of messages to the server. The function is
375  * registered with the client library by passing it as an argument to MQTTAsync_setCallbacks().
376  * It is called by the client library after the client application has
377  * published a message to the server. It indicates that the necessary
378  * handshaking and acknowledgements for the requested quality of service (see
379  * MQTTAsync_message.qos) have been completed. This function is executed on a
380  * separate thread to the one on which the client application is running.
381  *
382  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
383  * called within this callback.
384  * @param context A pointer to the <i>context</i> value originally passed to
385  * MQTTAsync_setCallbacks(), which contains any application-specific context.
386  * @param token The ::MQTTAsync_token associated with
387  * the published message. Applications can check that all messages have been
388  * correctly published by matching the tokens returned from calls to
389  * MQTTAsync_send() and MQTTAsync_sendMessage() with the tokens passed
390  * to this callback.
391  */
392 typedef void MQTTAsync_deliveryComplete(void* context, MQTTAsync_token token);
393 
394 /**
395  * This is a callback function. The client application
396  * must provide an implementation of this function to enable asynchronous
397  * notification of the loss of connection to the server. The function is
398  * registered with the client library by passing it as an argument to
399  * MQTTAsync_setCallbacks(). It is called by the client library if the client
400  * loses its connection to the server. The client application must take
401  * appropriate action, such as trying to reconnect or reporting the problem.
402  * This function is executed on a separate thread to the one on which the
403  * client application is running.
404  *
405  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
406  * called within this callback.
407  * @param context A pointer to the <i>context</i> value originally passed to
408  * MQTTAsync_setCallbacks(), which contains any application-specific context.
409  * @param cause The reason for the disconnection.
410  * Currently, <i>cause</i> is always set to NULL.
411  */
412 typedef void MQTTAsync_connectionLost(void* context, char* cause);
413 
414 
415 /**
416  * This is a callback function, which will be called when the client
417  * library successfully connects.  This is superfluous when the connection
418  * is made in response to a MQTTAsync_connect call, because the onSuccess
419  * callback can be used.  It is intended for use when automatic reconnect
420  * is enabled, so that when a reconnection attempt succeeds in the background,
421  * the application is notified and can take any required actions.
422  *
423  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
424  * called within this callback.
425  * @param context A pointer to the <i>context</i> value originally passed to
426  * MQTTAsync_setCallbacks(), which contains any application-specific context.
427  * @param cause The reason for the disconnection.
428  * Currently, <i>cause</i> is always set to NULL.
429  */
430 typedef void MQTTAsync_connected(void* context, char* cause);
431 
432 /**
433  * This is a callback function, which will be called when the client
434  * library receives a disconnect packet from the server. This applies to MQTT V5 and above only.
435  *
436  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
437  * called within this callback.
438  * @param context A pointer to the <i>context</i> value originally passed to
439  * MQTTAsync_setCallbacks(), which contains any application-specific context.
440  * @param properties the properties in the disconnect packet.
441  * @param properties the reason code from the disconnect packet
442  * Currently, <i>cause</i> is always set to NULL.
443  */
444 typedef void MQTTAsync_disconnected(void* context, MQTTProperties* properties,
445 		enum MQTTReasonCodes reasonCode);
446 
447 /**
448  * Sets the MQTTAsync_disconnected() callback function for a client.
449  * @param handle A valid client handle from a successful call to
450  * MQTTAsync_create().
451  *
452  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
453  * called within this callback.
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 MQTTAsync_connected() callback
458  * function.  NULL removes the callback setting.
459  * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set,
460  * ::MQTTASYNC_FAILURE if an error occurred.
461  */
462 LIBMQTT_API int MQTTAsync_setDisconnected(MQTTAsync handle, void* context, MQTTAsync_disconnected* co);
463 
464 /** The connect options that can be updated before an automatic reconnect. */
465 typedef struct
466 {
467 	/** The eyecatcher for this structure.  Will be MQCD. */
468 	char struct_id[4];
469 	/** The version number of this structure.  Will be 0 */
470 	int struct_version;
471 	/**
472 	 * MQTT servers that support the MQTT v3.1 protocol provide authentication
473 	 * and authorisation by user name and password. This is the user name parameter.
474 	 * Set data to NULL to remove.  To change, allocate new
475 	 * storage with ::MQTTAsync_allocate - this will then be free later by the library.
476 	 */
477 	const char* username;
478 	/**
479 	 * The password parameter of the MQTT authentication.
480 	 * Set data to NULL to remove.  To change, allocate new
481 	 * storage with ::MQTTAsync_allocate - this will then be free later by the library.
482 	 */
483 	struct {
484 		int len;           /**< binary password length */
485 		const void* data;  /**< binary password data */
486 	} binarypwd;
487 } MQTTAsync_connectData;
488 
489 #define MQTTAsync_connectData_initializer {{'M', 'Q', 'C', 'D'}, 0, NULL, {0, NULL}}
490 
491 /**
492  * This is a callback function which will allow the client application to update the
493  * connection data.
494  * @param data The connection data which can be modified by the application.
495  * @return Return a non-zero value to update the connect data, zero to keep the same data.
496  */
497 typedef int MQTTAsync_updateConnectOptions(void* context, MQTTAsync_connectData* data);
498 
499 /**
500  * Sets the MQTTAsync_updateConnectOptions() callback function for a client.
501  * @param handle A valid client handle from a successful call to MQTTAsync_create().
502  * @param context A pointer to any application-specific context. The
503  * the <i>context</i> pointer is passed to each of the callback functions to
504  * provide access to the context information in the callback.
505  * @param co A pointer to an MQTTAsync_updateConnectOptions() callback
506  * function.  NULL removes the callback setting.
507  */
508 LIBMQTT_API int MQTTAsync_setUpdateConnectOptions(MQTTAsync handle, void* context, MQTTAsync_updateConnectOptions* co);
509 
510 /**
511  * Sets the MQTTPersistence_beforeWrite() callback function for a client.
512  * @param handle A valid client handle from a successful call to MQTTAsync_create().
513  * @param context A pointer to any application-specific context. The
514  * the <i>context</i> pointer is passed to the callback function to
515  * provide access to the context information in the callback.
516  * @param co A pointer to an MQTTPersistence_beforeWrite() callback
517  * function.  NULL removes the callback setting.
518  */
519 LIBMQTT_API int MQTTAsync_setBeforePersistenceWrite(MQTTAsync handle, void* context, MQTTPersistence_beforeWrite* co);
520 
521 
522 /**
523  * Sets the MQTTPersistence_afterRead() callback function for a client.
524  * @param handle A valid client handle from a successful call to MQTTAsync_create().
525  * @param context A pointer to any application-specific context. The
526  * the <i>context</i> pointer is passed to the callback function to
527  * provide access to the context information in the callback.
528  * @param co A pointer to an MQTTPersistence_beforeWrite() callback
529  * function.  NULL removes the callback setting.
530  */
531 LIBMQTT_API int MQTTAsync_setAfterPersistenceRead(MQTTAsync handle, void* context, MQTTPersistence_afterRead* co);
532 
533 
534 /** The data returned on completion of an unsuccessful API call in the response callback onFailure. */
535 typedef struct
536 {
537 	/** A token identifying the failed request. */
538 	MQTTAsync_token token;
539 	/** A numeric code identifying the error. */
540 	int code;
541 	/** Optional text explaining the error. Can be NULL. */
542 	const char *message;
543 } MQTTAsync_failureData;
544 
545 
546 /** The data returned on completion of an unsuccessful API call in the response callback onFailure. */
547 typedef struct
548 {
549 	/** The eyecatcher for this structure.  Will be MQFD. */
550 	char struct_id[4];
551 	/** The version number of this structure.  Will be 0 */
552 	int struct_version;
553 	/** A token identifying the failed request. */
554 	MQTTAsync_token token;
555 	/** The MQTT reason code returned. */
556 	enum MQTTReasonCodes reasonCode;
557 	/** The MQTT properties on the ack, if any. */
558 	MQTTProperties properties;
559 	/** A numeric code identifying the MQTT client library error. */
560 	int code;
561 	/** Optional further text explaining the error. Can be NULL. */
562 	const char *message;
563 	/** Packet type on which the failure occurred - used for publish QoS 1/2 exchanges*/
564 	int packet_type;
565 } MQTTAsync_failureData5;
566 
567 #define MQTTAsync_failureData5_initializer {{'M', 'Q', 'F', 'D'}, 0, 0, MQTTREASONCODE_SUCCESS, MQTTProperties_initializer, 0, NULL, 0}
568 
569 /** The data returned on completion of a successful API call in the response callback onSuccess. */
570 typedef struct
571 {
572 	/** A token identifying the successful request. Can be used to refer to the request later. */
573 	MQTTAsync_token token;
574 	/** A union of the different values that can be returned for subscribe, unsubscribe and publish. */
575 	union
576 	{
577 		/** For subscribe, the granted QoS of the subscription returned by the server.
578 		 * Also for subscribeMany, if only 1 subscription was requested. */
579 		int qos;
580 		/** For subscribeMany, if more than one subscription was requested,
581 		 * the list of granted QoSs of the subscriptions returned by the server. */
582 		int* qosList;
583 		/** For publish, the message being sent to the server. */
584 		struct
585 		{
586 			MQTTAsync_message message; /**< the message being sent to the server */
587 			char* destinationName;     /**< the topic destination for the message */
588 		} pub;
589 		/* For connect, the server connected to, MQTT version used, and sessionPresent flag */
590 		struct
591 		{
592 			char* serverURI; /**< the connection string of the server */
593 			int MQTTVersion; /**< the version of MQTT being used */
594 			int sessionPresent; /**< the session present flag returned from the server */
595 		} connect;
596 	} alt;
597 } MQTTAsync_successData;
598 
599 
600 /** The data returned on completion of a successful API call in the response callback onSuccess. */
601 typedef struct
602 {
603 	char struct_id[4];    	/**< The eyecatcher for this structure.  Will be MQSD. */
604 	int struct_version;  	/**< The version number of this structure.  Will be 0 */
605 	/** A token identifying the successful request. Can be used to refer to the request later. */
606 	MQTTAsync_token token;
607 	enum MQTTReasonCodes reasonCode;  	/**< MQTT V5 reason code returned */
608 	MQTTProperties properties;  	        /**< MQTT V5 properties returned, if any */
609 	/** A union of the different values that can be returned for subscribe, unsubscribe and publish. */
610 	union
611 	{
612 		/** For subscribeMany, the list of reasonCodes returned by the server. */
613 		struct
614 		{
615 			int reasonCodeCount; /**< the number of reason codes in the reasonCodes array */
616 			enum MQTTReasonCodes* reasonCodes; /**< an array of reasonCodes */
617 		} sub;
618 		/** For publish, the message being sent to the server. */
619 		struct
620 		{
621 			MQTTAsync_message message; /**< the message being sent to the server */
622 			char* destinationName;     /**< the topic destination for the message */
623 		} pub;
624 		/* For connect, the server connected to, MQTT version used, and sessionPresent flag */
625 		struct
626 		{
627 			char* serverURI;  /**< the connection string of the server */
628 			int MQTTVersion;  /**< the version of MQTT being used */
629 			int sessionPresent;  /**< the session present flag returned from the server */
630 		} connect;
631 		/** For unsubscribeMany, the list of reasonCodes returned by the server. */
632 		struct
633 		{
634 			int reasonCodeCount; /**< the number of reason codes in the reasonCodes array */
635 			enum MQTTReasonCodes* reasonCodes; /**< an array of reasonCodes */
636 		} unsub;
637 	} alt;
638 } MQTTAsync_successData5;
639 
640 #define MQTTAsync_successData5_initializer {{'M', 'Q', 'S', 'D'}, 0, 0, MQTTREASONCODE_SUCCESS, MQTTProperties_initializer, {.sub={0,0}}}
641 
642 /**
643  * This is a callback function. The client application
644  * must provide an implementation of this function to enable asynchronous
645  * notification of the successful completion of an API call. The function is
646  * registered with the client library by passing it as an argument in
647  * ::MQTTAsync_responseOptions.
648  *
649  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
650  * called within this callback.
651  * @param context A pointer to the <i>context</i> value originally passed to
652  * ::MQTTAsync_responseOptions, which contains any application-specific context.
653  * @param response Any success data associated with the API completion.
654  */
655 typedef void MQTTAsync_onSuccess(void* context, MQTTAsync_successData* response);
656 
657 /**
658  * This is a callback function, the MQTT V5 version of ::MQTTAsync_onSuccess.
659  * The client application
660  * must provide an implementation of this function to enable asynchronous
661  * notification of the successful completion of an API call. The function is
662  * registered with the client library by passing it as an argument in
663  * ::MQTTAsync_responseOptions.
664  *
665  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
666  * called within this callback.
667  * @param context A pointer to the <i>context</i> value originally passed to
668  * ::MQTTAsync_responseOptions, which contains any application-specific context.
669  * @param response Any success data associated with the API completion.
670  */
671 typedef void MQTTAsync_onSuccess5(void* context, MQTTAsync_successData5* response);
672 
673 /**
674  * This is a callback function. The client application
675  * must provide an implementation of this function to enable asynchronous
676  * notification of the unsuccessful completion of an API call. The function is
677  * registered with the client library by passing it as an argument in
678  * ::MQTTAsync_responseOptions.
679  *
680  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
681  * called within this callback.
682  * @param context A pointer to the <i>context</i> value originally passed to
683  * ::MQTTAsync_responseOptions, which contains any application-specific context.
684  * @param response Failure data associated with the API completion.
685  */
686 typedef void MQTTAsync_onFailure(void* context,  MQTTAsync_failureData* response);
687 
688 /**
689  * This is a callback function, the MQTT V5 version of ::MQTTAsync_onFailure.
690  * The application must provide an implementation of this function to enable asynchronous
691  * notification of the unsuccessful completion of an API call. The function is
692  * registered with the client library by passing it as an argument in
693  * ::MQTTAsync_responseOptions.
694  *
695  * <b>Note:</b> Neither MQTTAsync_create() nor MQTTAsync_destroy() should be
696  * called within this callback.
697  * @param context A pointer to the <i>context</i> value originally passed to
698  * ::MQTTAsync_responseOptions, which contains any application-specific context.
699  * @param response Failure data associated with the API completion.
700  */
701 typedef void MQTTAsync_onFailure5(void* context,  MQTTAsync_failureData5* response);
702 
703 /** Structure to define call options.  For MQTT 5.0 there is input data as well as that
704  * describing the response method.  So there is now also a synonym ::MQTTAsync_callOptions
705  * to better reflect the use.  This responseOptions name is kept for backward
706  * compatibility.
707  */
708 typedef struct MQTTAsync_responseOptions
709 {
710 	/** The eyecatcher for this structure.  Must be MQTR */
711 	char struct_id[4];
712 	/** The version number of this structure.  Must be 0 or 1
713 	 *   if 0, no MQTTV5 options */
714 	int struct_version;
715 	/**
716     * A pointer to a callback function to be called if the API call successfully
717     * completes.  Can be set to NULL, in which case no indication of successful
718     * completion will be received.
719     */
720 	MQTTAsync_onSuccess* onSuccess;
721 	/**
722     * A pointer to a callback function to be called if the API call fails.
723     * Can be set to NULL, in which case no indication of unsuccessful
724     * completion will be received.
725     */
726 	MQTTAsync_onFailure* onFailure;
727 	/**
728     * A pointer to any application-specific context. The
729     * the <i>context</i> pointer is passed to success or failure callback functions to
730     * provide access to the context information in the callback.
731     */
732 	void* context;
733 	/**
734     * A token is returned from the call.  It can be used to track
735     * the state of this request, both in the callbacks and in future calls
736     * such as ::MQTTAsync_waitForCompletion. This is output only - any
737     * change by the application will be ignored.
738     */
739 	MQTTAsync_token token;
740 	/**
741     * A pointer to a callback function to be called if the API call successfully
742     * completes.  Can be set to NULL, in which case no indication of successful
743     * completion will be received.
744     */
745 	MQTTAsync_onSuccess5* onSuccess5;
746 	/**
747     * A pointer to a callback function to be called if the API call successfully
748     * completes.  Can be set to NULL, in which case no indication of successful
749     * completion will be received.
750     */
751 	MQTTAsync_onFailure5* onFailure5;
752 	/**
753 	 * MQTT V5 input properties
754 	 */
755 	MQTTProperties properties;
756 	/*
757 	 * MQTT V5 subscribe options, when used with subscribe only.
758 	 */
759 	MQTTSubscribe_options subscribeOptions;
760 	/*
761 	 * MQTT V5 subscribe option count, when used with subscribeMany only.
762 	 * The number of entries in the subscribe_options_list array.
763 	 */
764 	int subscribeOptionsCount;
765 	/*
766 	 * MQTT V5 subscribe option array, when used with subscribeMany only.
767 	 */
768 	MQTTSubscribe_options* subscribeOptionsList;
769 } MQTTAsync_responseOptions;
770 
771 #define MQTTAsync_responseOptions_initializer { {'M', 'Q', 'T', 'R'}, 1, NULL, NULL, 0, 0, NULL, NULL, MQTTProperties_initializer, MQTTSubscribe_options_initializer, 0, NULL}
772 
773 /** A synonym for responseOptions to better reflect its usage since MQTT 5.0 */
774 typedef struct MQTTAsync_responseOptions MQTTAsync_callOptions;
775 #define MQTTAsync_callOptions_initializer MQTTAsync_responseOptions_initializer
776 
777 /**
778  * This function sets the global callback functions for a specific client.
779  * If your client application doesn't use a particular callback, set the
780  * relevant parameter to NULL. Any necessary message acknowledgements and
781  * status communications are handled in the background without any intervention
782  * from the client application.  If you do not set a messageArrived callback
783  * function, you will not be notified of the receipt of any messages as a
784  * result of a subscription.
785  *
786  * <b>Note:</b> The MQTT client must be disconnected when this function is
787  * called.
788  * @param handle A valid client handle from a successful call to
789  * MQTTAsync_create().
790  * @param context A pointer to any application-specific context. The
791  * the <i>context</i> pointer is passed to each of the callback functions to
792  * provide access to the context information in the callback.
793  * @param cl A pointer to an MQTTAsync_connectionLost() callback
794  * function. You can set this to NULL if your application doesn't handle
795  * disconnections.
796  * @param ma A pointer to an MQTTAsync_messageArrived() callback
797  * function.  If this callback is not set, an error will be returned.
798  * You must set this callback because otherwise there would be
799  * no way to deliver any incoming messages.
800  * @param dc A pointer to an MQTTAsync_deliveryComplete() callback
801  * function. You can set this to NULL if you do not want to check
802  * for successful delivery.
803  * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set,
804  * ::MQTTASYNC_FAILURE if an error occurred.
805  */
806 LIBMQTT_API int MQTTAsync_setCallbacks(MQTTAsync handle, void* context, MQTTAsync_connectionLost* cl,
807 									 MQTTAsync_messageArrived* ma, MQTTAsync_deliveryComplete* dc);
808 
809 /**
810  * This function sets the callback function for a connection lost event for
811  * a specific client. Any necessary message acknowledgements and status
812  * communications are handled in the background without any intervention
813  * from the client application.
814  *
815  * <b>Note:</b> The MQTT client must be disconnected when this function is
816  * called.
817  * @param handle A valid client handle from a successful call to
818  * MQTTAsync_create().
819  * @param context A pointer to any application-specific context. The
820  * the <i>context</i> pointer is passed the callback functions to provide
821  * access to the context information in the callback.
822  * @param cl A pointer to an MQTTAsync_connectionLost() callback
823  * function. You can set this to NULL if your application doesn't handle
824  * disconnections.
825  * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set,
826  * ::MQTTASYNC_FAILURE if an error occurred.
827  */
828 
829 LIBMQTT_API int MQTTAsync_setConnectionLostCallback(MQTTAsync handle, void* context,
830 												  MQTTAsync_connectionLost* cl);
831 
832 /**
833  * This function sets the callback function for a message arrived event for
834  * a specific client. Any necessary message acknowledgements and status
835  * communications are handled in the background without any intervention
836  * from the client application.  If you do not set a messageArrived callback
837  * function, you will not be notified of the receipt of any messages as a
838  * result of a subscription.
839  *
840  * <b>Note:</b> The MQTT client must be disconnected when this function is
841  * called.
842  * @param handle A valid client handle from a successful call to
843  * MQTTAsync_create().
844  * @param context A pointer to any application-specific context. The
845  * the <i>context</i> pointer is passed to the callback functions to provide
846  * access to the context information in the callback.
847  * @param ma A pointer to an MQTTAsync_messageArrived() callback
848  * function.  You can set this to NULL if your application doesn't handle
849  * receipt of messages.
850  * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set,
851  * ::MQTTASYNC_FAILURE if an error occurred.
852  */
853 LIBMQTT_API int MQTTAsync_setMessageArrivedCallback(MQTTAsync handle, void* context,
854 												  MQTTAsync_messageArrived* ma);
855 
856 /**
857  * This function sets the callback function for a delivery complete event
858  * for a specific client. Any necessary message acknowledgements and status
859  * communications are handled in the background without any intervention
860  * from the client application.
861  *
862  * <b>Note:</b> The MQTT client must be disconnected when this function is
863  * called.
864  * @param handle A valid client handle from a successful call to
865  * MQTTAsync_create().
866  * @param context A pointer to any application-specific context. The
867  * the <i>context</i> pointer is passed to the callback functions to provide
868  * access to the context information in the callback.
869  * @param dc A pointer to an MQTTAsync_deliveryComplete() callback
870  * function. You can set this to NULL if you do not want to check
871  * for successful delivery.
872  * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set,
873  * ::MQTTASYNC_FAILURE if an error occurred.
874  */
875 LIBMQTT_API int MQTTAsync_setDeliveryCompleteCallback(MQTTAsync handle, void* context,
876 													MQTTAsync_deliveryComplete* dc);
877 
878 /**
879  * Sets the MQTTAsync_connected() callback function for a client.
880  * @param handle A valid client handle from a successful call to
881  * MQTTAsync_create().
882  * @param context A pointer to any application-specific context. The
883  * the <i>context</i> pointer is passed to each of the callback functions to
884  * provide access to the context information in the callback.
885  * @param co A pointer to an MQTTAsync_connected() callback
886  * function.  NULL removes the callback setting.
887  * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set,
888  * ::MQTTASYNC_FAILURE if an error occurred.
889  */
890 LIBMQTT_API int MQTTAsync_setConnected(MQTTAsync handle, void* context, MQTTAsync_connected* co);
891 
892 
893 /**
894  * Reconnects a client with the previously used connect options.  Connect
895  * must have previously been called for this to work.
896  * @param handle A valid client handle from a successful call to
897  * MQTTAsync_create().
898  * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set,
899  * ::MQTTASYNC_FAILURE if an error occurred.
900  */
901 LIBMQTT_API int MQTTAsync_reconnect(MQTTAsync handle);
902 
903 
904 /**
905  * This function creates an MQTT client ready for connection to the
906  * specified server and using the specified persistent storage (see
907  * MQTTAsync_persistence). See also MQTTAsync_destroy().
908  * @param handle A pointer to an ::MQTTAsync handle. The handle is
909  * populated with a valid client reference following a successful return from
910  * this function.
911  * @param serverURI A null-terminated string specifying the server to
912  * which the client will connect. It takes the form
913  * <i>protocol://host:port</i> where <i>protocol</i> must be:
914  * <br>
915  * @em tcp:// or @em mqtt:// - Insecure TCP
916  * <br>
917  * @em ssl:// or @em mqtts:// - Encrypted SSL/TLS
918  * <br>
919  * @em ws:// - Insecure websockets
920  * <br>
921  * @em wss:// - Secure web sockets
922  * <br>
923  * The TLS enabled prefixes (ssl, mqtts, wss) are only valid if a TLS
924  * version of the library is linked with.
925  * For <i>host</i>, you can specify either an IP address or a host name. For
926  * instance, to connect to a server running on the local machines with the
927  * default MQTT port, specify <i>tcp://localhost:1883</i>.
928  * @param clientId The client identifier passed to the server when the
929  * client connects to it. It is a null-terminated UTF-8 encoded string.
930  * @param persistence_type The type of persistence to be used by the client:
931  * <br>
932  * ::MQTTCLIENT_PERSISTENCE_NONE: Use in-memory persistence. If the device or
933  * system on which the client is running fails or is switched off, the current
934  * state of any in-flight messages is lost and some messages may not be
935  * delivered even at QoS1 and QoS2.
936  * <br>
937  * ::MQTTCLIENT_PERSISTENCE_DEFAULT: Use the default (file system-based)
938  * persistence mechanism. Status about in-flight messages is held in persistent
939  * storage and provides some protection against message loss in the case of
940  * unexpected failure.
941  * <br>
942  * ::MQTTCLIENT_PERSISTENCE_USER: Use an application-specific persistence
943  * implementation. Using this type of persistence gives control of the
944  * persistence mechanism to the application. The application has to implement
945  * the MQTTClient_persistence interface.
946  * @param persistence_context If the application uses
947  * ::MQTTCLIENT_PERSISTENCE_NONE persistence, this argument is unused and should
948  * be set to NULL. For ::MQTTCLIENT_PERSISTENCE_DEFAULT persistence, it
949  * should be set to the location of the persistence directory (if set
950  * to NULL, the persistence directory used is the working directory).
951  * Applications that use ::MQTTCLIENT_PERSISTENCE_USER persistence set this
952  * argument to point to a valid MQTTClient_persistence structure.
953  * @return ::MQTTASYNC_SUCCESS if the client is successfully created, otherwise
954  * an error code is returned.
955  */
956 LIBMQTT_API int MQTTAsync_create(MQTTAsync* handle, const char* serverURI, const char* clientId,
957 		int persistence_type, void* persistence_context);
958 
959 /** Options for the ::MQTTAsync_createWithOptions call */
960 typedef struct
961 {
962 	/** The eyecatcher for this structure.  must be MQCO. */
963 	char struct_id[4];
964 	/** The version number of this structure.  Must be 0, 1, 2 or 3
965 	 * 0 means no MQTTVersion
966 	 * 1 means no allowDisconnectedSendAtAnyTime, deleteOldestMessages, restoreMessages
967 	 * 2 means no persistQoS0
968 	 */
969 	int struct_version;
970 	/** Whether to allow messages to be sent when the client library is not connected. */
971 	int sendWhileDisconnected;
972 	/** The maximum number of messages allowed to be buffered. This is intended to be used to
973 	 * limit the number of messages queued while the client is not connected. It also applies
974 	 * when the client is connected, however, so has to be greater than 0. */
975 	int maxBufferedMessages;
976 	/** Whether the MQTT version is 3.1, 3.1.1, or 5.  To use V5, this must be set.
977 	 *  MQTT V5 has to be chosen here, because during the create call the message persistence
978 	 *  is initialized, and we want to know whether the format of any persisted messages
979 	 *  is appropriate for the MQTT version we are going to connect with.  Selecting 3.1 or
980 	 *  3.1.1 and attempting to read 5.0 persisted messages will result in an error on create.  */
981 	int MQTTVersion;
982 	/**
983 	 * Allow sending of messages while disconnected before a first successful connect.
984 	 */
985 	int allowDisconnectedSendAtAnyTime;
986 	/*
987 	 * When the maximum number of buffered messages is reached, delete the oldest rather than the newest.
988 	 */
989 	int deleteOldestMessages;
990 	/*
991 	 * Restore messages from persistence on create - or clear it.
992 	 */
993 	int restoreMessages;
994 	/*
995 	 * Persist QoS0 publish commands - an option to not persist them.
996 	 */
997 	int persistQoS0;
998 } MQTTAsync_createOptions;
999 
1000 #define MQTTAsync_createOptions_initializer  { {'M', 'Q', 'C', 'O'}, 2, 0, 100, MQTTVERSION_DEFAULT, 0, 0, 1, 1}
1001 
1002 #define MQTTAsync_createOptions_initializer5 { {'M', 'Q', 'C', 'O'}, 2, 0, 100, MQTTVERSION_5, 0, 0, 1, 1}
1003 
1004 
1005 LIBMQTT_API int MQTTAsync_createWithOptions(MQTTAsync* handle, const char* serverURI, const char* clientId,
1006 		int persistence_type, void* persistence_context, MQTTAsync_createOptions* options);
1007 
1008 /**
1009  * MQTTAsync_willOptions defines the MQTT "Last Will and Testament" (LWT) settings for
1010  * the client. In the event that a client unexpectedly loses its connection to
1011  * the server, the server publishes the LWT message to the LWT topic on
1012  * behalf of the client. This allows other clients (subscribed to the LWT topic)
1013  * to be made aware that the client has disconnected. To enable the LWT
1014  * function for a specific client, a valid pointer to an MQTTAsync_willOptions
1015  * structure is passed in the MQTTAsync_connectOptions structure used in the
1016  * MQTTAsync_connect() call that connects the client to the server. The pointer
1017  * to MQTTAsync_willOptions can be set to NULL if the LWT function is not
1018  * required.
1019  */
1020 typedef struct
1021 {
1022 	/** The eyecatcher for this structure.  must be MQTW. */
1023 	char struct_id[4];
1024 	/** The version number of this structure.  Must be 0 or 1
1025 	    0 indicates no binary will message support
1026 	 */
1027 	int struct_version;
1028 	/** The LWT topic to which the LWT message will be published. */
1029 	const char* topicName;
1030 	/** The LWT payload. */
1031 	const char* message;
1032 	/**
1033       * The retained flag for the LWT message (see MQTTAsync_message.retained).
1034       */
1035 	int retained;
1036 	/**
1037       * The quality of service setting for the LWT message (see
1038       * MQTTAsync_message.qos and @ref qos).
1039       */
1040 	int qos;
1041 	/** The LWT payload in binary form. This is only checked and used if the message option is NULL */
1042 	struct
1043 	{
1044   	int len;            /**< binary payload length */
1045 		const void* data;  /**< binary payload data */
1046 	} payload;
1047 } MQTTAsync_willOptions;
1048 
1049 #define MQTTAsync_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, { 0, NULL } }
1050 
1051 #define MQTT_SSL_VERSION_DEFAULT 0
1052 #define MQTT_SSL_VERSION_TLS_1_0 1
1053 #define MQTT_SSL_VERSION_TLS_1_1 2
1054 #define MQTT_SSL_VERSION_TLS_1_2 3
1055 
1056 /**
1057 * MQTTAsync_sslProperties defines the settings to establish an SSL/TLS connection using the
1058 * OpenSSL library. It covers the following scenarios:
1059 * - Server authentication: The client needs the digital certificate of the server. It is included
1060 *   in a store containting trusted material (also known as "trust store").
1061 * - Mutual authentication: Both client and server are authenticated during the SSL handshake. In
1062 *   addition to the digital certificate of the server in a trust store, the client will need its own
1063 *   digital certificate and the private key used to sign its digital certificate stored in a "key store".
1064 * - Anonymous connection: Both client and server do not get authenticated and no credentials are needed
1065 *   to establish an SSL connection. Note that this scenario is not fully secure since it is subject to
1066 *   man-in-the-middle attacks.
1067 */
1068 typedef struct
1069 {
1070 	/** The eyecatcher for this structure.  Must be MQTS */
1071 	char struct_id[4];
1072 
1073 	/** The version number of this structure. Must be 0, 1, 2, 3, 4 or 5.
1074 	 * 0 means no sslVersion
1075 	 * 1 means no verify, CApath
1076 	 * 2 means no ssl_error_context, ssl_error_cb
1077 	 * 3 means no ssl_psk_cb, ssl_psk_context, disableDefaultTrustStore
1078 	 * 4 means no protos, protos_len
1079 	 */
1080 	int struct_version;
1081 
1082 	/** The file in PEM format containing the public digital certificates trusted by the client. */
1083 	const char* trustStore;
1084 
1085 	/** The file in PEM format containing the public certificate chain of the client. It may also include
1086 	* the client's private key.
1087 	*/
1088 	const char* keyStore;
1089 
1090 	/** If not included in the sslKeyStore, this setting points to the file in PEM format containing
1091 	* the client's private key.
1092 	*/
1093 	const char* privateKey;
1094 
1095 	/** The password to load the client's privateKey if encrypted. */
1096 	const char* privateKeyPassword;
1097 
1098 	/**
1099 	* The list of cipher suites that the client will present to the server during the SSL handshake. For a
1100 	* full explanation of the cipher list format, please see the OpenSSL on-line documentation:
1101 	* http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT
1102 	* If this setting is ommitted, its default value will be "ALL", that is, all the cipher suites -excluding
1103 	* those offering no encryption- will be considered.
1104 	* This setting can be used to set an SSL anonymous connection ("aNULL" string value, for instance).
1105 	*/
1106 	const char* enabledCipherSuites;
1107 
1108     /** True/False option to enable verification of the server certificate **/
1109     int enableServerCertAuth;
1110 
1111     /** The SSL/TLS version to use. Specify one of MQTT_SSL_VERSION_DEFAULT (0),
1112     * MQTT_SSL_VERSION_TLS_1_0 (1), MQTT_SSL_VERSION_TLS_1_1 (2) or MQTT_SSL_VERSION_TLS_1_2 (3).
1113     * Only used if struct_version is >= 1.
1114     */
1115     int sslVersion;
1116 
1117     /**
1118      * Whether to carry out post-connect checks, including that a certificate
1119      * matches the given host name.
1120      * Exists only if struct_version >= 2
1121      */
1122     int verify;
1123 
1124     /**
1125      * From the OpenSSL documentation:
1126      * If CApath is not NULL, it points to a directory containing CA certificates in PEM format.
1127      * Exists only if struct_version >= 2
1128 	 */
1129 	const char* CApath;
1130 
1131     /**
1132      * Callback function for OpenSSL error handler ERR_print_errors_cb
1133      * Exists only if struct_version >= 3
1134      */
1135     int (*ssl_error_cb) (const char *str, size_t len, void *u);
1136 
1137     /**
1138      * Application-specific contex for OpenSSL error handler ERR_print_errors_cb
1139      * Exists only if struct_version >= 3
1140      */
1141     void* ssl_error_context;
1142 
1143 	/**
1144 	 * Callback function for setting TLS-PSK options. Parameters correspond to that of
1145 	 * SSL_CTX_set_psk_client_callback, except for u which is the pointer ssl_psk_context.
1146 	 * Exists only if struct_version >= 4
1147 	 */
1148 	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);
1149 
1150 	/**
1151 	 * Application-specific contex for ssl_psk_cb
1152 	 * Exists only if struct_version >= 4
1153 	 */
1154 	void* ssl_psk_context;
1155 
1156 	/**
1157 	 * Don't load default SSL CA. Should be used together with PSK to make sure
1158 	 * regular servers with certificate in place is not accepted.
1159 	 * Exists only if struct_version >= 4
1160 	 */
1161 	int disableDefaultTrustStore;
1162 
1163 	/**
1164 	 * The protocol-lists must be in wire-format, which is defined as a vector of non-empty, 8-bit length-prefixed, byte strings.
1165 	 * 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.
1166 	 * A truncated byte-string is invalid.
1167 	 * Check documentation for SSL_CTX_set_alpn_protos
1168 	 * Exists only if struct_version >= 5
1169 	 */
1170 	const unsigned char *protos;
1171 
1172 	/**
1173 	 * The length of the vector protos vector
1174 	 * Exists only if struct_version >= 5
1175 	 */
1176 	unsigned int protos_len;
1177 } MQTTAsync_SSLOptions;
1178 
1179 #define MQTTAsync_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 }
1180 
1181 /** Utility structure where name/value pairs are needed */
1182 typedef struct
1183 {
1184 	const char* name; /**< name string */
1185 	const char* value; /**< value string */
1186 } MQTTAsync_nameValue;
1187 
1188 /**
1189  * MQTTAsync_connectOptions defines several settings that control the way the
1190  * client connects to an MQTT server.
1191  *
1192  * Suitable default values are set in the following initializers:
1193  * - MQTTAsync_connectOptions_initializer: for MQTT 3.1.1 non-WebSockets
1194  * - MQTTAsync_connectOptions_initializer5: for MQTT 5.0 non-WebSockets
1195  * - MQTTAsync_connectOptions_initializer_ws: for MQTT 3.1.1 WebSockets
1196  * - MQTTAsync_connectOptions_initializer5_ws: for MQTT 5.0 WebSockets
1197  */
1198 typedef struct
1199 {
1200 	/** The eyecatcher for this structure.  must be MQTC. */
1201 	char struct_id[4];
1202 	/** The version number of this structure.  Must be 0, 1, 2, 3 4 5 6, 7 or 8.
1203 	  * 0 signifies no SSL options and no serverURIs
1204 	  * 1 signifies no serverURIs
1205       * 2 signifies no MQTTVersion
1206       * 3 signifies no automatic reconnect options
1207       * 4 signifies no binary password option (just string)
1208       * 5 signifies no MQTTV5 properties
1209       * 6 signifies no HTTP headers option
1210       * 7 signifies no HTTP proxy and HTTPS proxy options
1211 	  */
1212 	int struct_version;
1213 	/** The "keep alive" interval, measured in seconds, defines the maximum time
1214       * that should pass without communication between the client and the server
1215       * The client will ensure that at least one message travels across the
1216       * network within each keep alive period.  In the absence of a data-related
1217 	  * message during the time period, the client sends a very small MQTT
1218       * "ping" message, which the server will acknowledge. The keep alive
1219       * interval enables the client to detect when the server is no longer
1220 	  * available without having to wait for the long TCP/IP timeout.
1221 	  * Set to 0 if you do not want any keep alive processing.
1222 	  */
1223 	int keepAliveInterval;
1224 	/**
1225       * This is a boolean value. The cleansession setting controls the behaviour
1226       * of both the client and the server at connection and disconnection time.
1227       * The client and server both maintain session state information. This
1228       * information is used to ensure "at least once" and "exactly once"
1229       * delivery, and "exactly once" receipt of messages. Session state also
1230       * includes subscriptions created by an MQTT client. You can choose to
1231       * maintain or discard state information between sessions.
1232       *
1233       * When cleansession is true, the state information is discarded at
1234       * connect and disconnect. Setting cleansession to false keeps the state
1235       * information. When you connect an MQTT client application with
1236       * MQTTAsync_connect(), the client identifies the connection using the
1237       * client identifier and the address of the server. The server checks
1238       * whether session information for this client
1239       * has been saved from a previous connection to the server. If a previous
1240       * session still exists, and cleansession=true, then the previous session
1241       * information at the client and server is cleared. If cleansession=false,
1242       * the previous session is resumed. If no previous session exists, a new
1243       * session is started.
1244 	  */
1245 	int cleansession;
1246 	/**
1247       * This controls how many messages can be in-flight simultaneously.
1248 	  */
1249 	int maxInflight;
1250 	/**
1251       * This is a pointer to an MQTTAsync_willOptions structure. If your
1252       * application does not make use of the Last Will and Testament feature,
1253       * set this pointer to NULL.
1254       */
1255 	MQTTAsync_willOptions* will;
1256 	/**
1257       * MQTT servers that support the MQTT v3.1 protocol provide authentication
1258       * and authorisation by user name and password. This is the user name
1259       * parameter.
1260       */
1261 	const char* username;
1262 	/**
1263       * MQTT servers that support the MQTT v3.1 protocol provide authentication
1264       * and authorisation by user name and password. This is the password
1265       * parameter.
1266       */
1267 	const char* password;
1268 	/**
1269       * The time interval in seconds to allow a connect to complete.
1270       */
1271 	int connectTimeout;
1272 	/**
1273 	 * The time interval in seconds after which unacknowledged publish requests are
1274 	 * retried during a TCP session.  With MQTT 3.1.1 and later, retries are
1275 	 * not required except on reconnect.  0 turns off in-session retries, and is the
1276 	 * recommended setting.  Adding retries to an already overloaded network only
1277 	 * exacerbates the problem.
1278 	 */
1279 	int retryInterval;
1280 	/**
1281       * This is a pointer to an MQTTAsync_SSLOptions structure. If your
1282       * application does not make use of SSL, set this pointer to NULL.
1283       */
1284 	MQTTAsync_SSLOptions* ssl;
1285 	/**
1286       * A pointer to a callback function to be called if the connect successfully
1287       * completes.  Can be set to NULL, in which case no indication of successful
1288       * completion will be received.
1289       */
1290 	MQTTAsync_onSuccess* onSuccess;
1291 	/**
1292       * A pointer to a callback function to be called if the connect fails.
1293       * Can be set to NULL, in which case no indication of unsuccessful
1294       * completion will be received.
1295       */
1296 	MQTTAsync_onFailure* onFailure;
1297 	/**
1298 	  * A pointer to any application-specific context. The
1299       * the <i>context</i> pointer is passed to success or failure callback functions to
1300       * provide access to the context information in the callback.
1301       */
1302 	void* context;
1303 	/**
1304 	  * The number of entries in the serverURIs array.
1305 	  */
1306 	int serverURIcount;
1307 	/**
1308 	  * An array of null-terminated strings specifying the servers to
1309       * which the client will connect. Each string takes the form <i>protocol://host:port</i>.
1310       * <i>protocol</i> must be <i>tcp</i>, <i>ssl</i>, <i>ws</i> or <i>wss</i>.
1311       * The TLS enabled prefixes (ssl, wss) are only valid if a TLS version of the library
1312       * is linked with.
1313       * For <i>host</i>, you can
1314       * specify either an IP address or a domain name. For instance, to connect to
1315       * a server running on the local machines with the default MQTT port, specify
1316       * <i>tcp://localhost:1883</i>.
1317       */
1318 	char* const* serverURIs;
1319 	/**
1320       * Sets the version of MQTT to be used on the connect.
1321       * MQTTVERSION_DEFAULT (0) = default: start with 3.1.1, and if that fails, fall back to 3.1
1322       * MQTTVERSION_3_1 (3) = only try version 3.1
1323       * MQTTVERSION_3_1_1 (4) = only try version 3.1.1
1324 	  */
1325 	int MQTTVersion;
1326 	/**
1327 	  * Reconnect automatically in the case of a connection being lost. 0=false, 1=true
1328 	  */
1329 	int automaticReconnect;
1330 	/**
1331 	  * The minimum automatic reconnect retry interval in seconds. Doubled on each failed retry.
1332 	  */
1333 	int minRetryInterval;
1334 	/**
1335 	  * The maximum automatic reconnect retry interval in seconds. The doubling stops here on failed retries.
1336 	  */
1337 	int maxRetryInterval;
1338 	/**
1339 	 * Optional binary password.  Only checked and used if the password option is NULL
1340 	 */
1341 	struct {
1342 		int len;            /**< binary password length */
1343 		const void* data;  /**< binary password data */
1344 	} binarypwd;
1345 	/*
1346 	 * MQTT V5 clean start flag.  Only clears state at the beginning of the session.
1347 	 */
1348 	int cleanstart;
1349 	/**
1350 	 * MQTT V5 properties for connect
1351 	 */
1352 	MQTTProperties *connectProperties;
1353 	/**
1354 	 * MQTT V5 properties for the will message in the connect
1355 	 */
1356 	MQTTProperties *willProperties;
1357 	/**
1358       * A pointer to a callback function to be called if the connect successfully
1359       * completes.  Can be set to NULL, in which case no indication of successful
1360       * completion will be received.
1361       */
1362 	MQTTAsync_onSuccess5* onSuccess5;
1363 	/**
1364       * A pointer to a callback function to be called if the connect fails.
1365       * Can be set to NULL, in which case no indication of unsuccessful
1366       * completion will be received.
1367       */
1368 	MQTTAsync_onFailure5* onFailure5;
1369 	/**
1370 	 * HTTP headers for websockets
1371 	 */
1372 	const MQTTAsync_nameValue* httpHeaders;
1373 	/**
1374 	 * HTTP proxy
1375 	 */
1376 	const char* httpProxy;
1377 	/**
1378 	 * HTTPS proxy
1379 	 */
1380 	const char* httpsProxy;
1381 } MQTTAsync_connectOptions;
1382 
1383 /** Initializer for connect options for MQTT 3.1.1 non-WebSocket connections */
1384 #define MQTTAsync_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 8, 60, 1, 65535, NULL, NULL, NULL, 30, 0,\
1385 NULL, NULL, NULL, NULL, 0, NULL, MQTTVERSION_DEFAULT, 0, 1, 60, {0, NULL}, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
1386 
1387 /** Initializer for connect options for MQTT 5.0 non-WebSocket connections */
1388 #define MQTTAsync_connectOptions_initializer5 { {'M', 'Q', 'T', 'C'}, 8, 60, 0, 65535, NULL, NULL, NULL, 30, 0,\
1389 NULL, NULL, NULL, NULL, 0, NULL, MQTTVERSION_5, 0, 1, 60, {0, NULL}, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
1390 
1391 /** Initializer for connect options for MQTT 3.1.1 WebSockets connections.
1392   * The keepalive interval is set to 45 seconds to avoid webserver 60 second inactivity timeouts.
1393   */
1394 #define MQTTAsync_connectOptions_initializer_ws { {'M', 'Q', 'T', 'C'}, 8, 45, 1, 65535, NULL, NULL, NULL, 30, 0,\
1395 NULL, NULL, NULL, NULL, 0, NULL, MQTTVERSION_DEFAULT, 0, 1, 60, {0, NULL}, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
1396 
1397 /** Initializer for connect options for MQTT 5.0 WebSockets connections.
1398   * The keepalive interval is set to 45 seconds to avoid webserver 60 second inactivity timeouts.
1399   */
1400 #define MQTTAsync_connectOptions_initializer5_ws { {'M', 'Q', 'T', 'C'}, 8, 45, 0, 65535, NULL, NULL, NULL, 30, 0,\
1401 NULL, NULL, NULL, NULL, 0, NULL, MQTTVERSION_5, 0, 1, 60, {0, NULL}, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
1402 
1403 
1404 /**
1405   * This function attempts to connect a previously-created client (see
1406   * MQTTAsync_create()) to an MQTT server using the specified options. If you
1407   * want to enable asynchronous message and status notifications, you must call
1408   * MQTTAsync_setCallbacks() prior to MQTTAsync_connect().
1409   * @param handle A valid client handle from a successful call to
1410   * MQTTAsync_create().
1411   * @param options A pointer to a valid MQTTAsync_connectOptions
1412   * structure.
1413   * @return ::MQTTASYNC_SUCCESS if the client connect request was accepted.
1414   * If the client was unable to connect to the server, an error code is
1415   * returned via the onFailure callback, if set.
1416   * Error codes greater than 0 are returned by the MQTT protocol:<br><br>
1417   * <b>1</b>: Connection refused: Unacceptable protocol version<br>
1418   * <b>2</b>: Connection refused: Identifier rejected<br>
1419   * <b>3</b>: Connection refused: Server unavailable<br>
1420   * <b>4</b>: Connection refused: Bad user name or password<br>
1421   * <b>5</b>: Connection refused: Not authorized<br>
1422   * <b>6-255</b>: Reserved for future use<br>
1423   */
1424 LIBMQTT_API int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options);
1425 
1426 /** Options for the ::MQTTAsync_disconnect call */
1427 typedef struct
1428 {
1429 	/** The eyecatcher for this structure. Must be MQTD. */
1430 	char struct_id[4];
1431 	/** The version number of this structure.  Must be 0 or 1.  0 signifies no V5 properties */
1432 	int struct_version;
1433 	/**
1434       * The client delays disconnection for up to this time (in
1435       * milliseconds) in order to allow in-flight message transfers to complete.
1436       */
1437 	int timeout;
1438 	/**
1439     * A pointer to a callback function to be called if the disconnect successfully
1440     * completes.  Can be set to NULL, in which case no indication of successful
1441     * completion will be received.
1442     */
1443 	MQTTAsync_onSuccess* onSuccess;
1444 	/**
1445     * A pointer to a callback function to be called if the disconnect fails.
1446     * Can be set to NULL, in which case no indication of unsuccessful
1447     * completion will be received.
1448     */
1449 	MQTTAsync_onFailure* onFailure;
1450 	/**
1451 	* A pointer to any application-specific context. The
1452     * the <i>context</i> pointer is passed to success or failure callback functions to
1453     * provide access to the context information in the callback.
1454     */
1455 	void* context;
1456 	/**
1457 	 * MQTT V5 input properties
1458 	 */
1459 	MQTTProperties properties;
1460 	/**
1461 	 * Reason code for MQTTV5 disconnect
1462 	 */
1463 	enum MQTTReasonCodes reasonCode;
1464 	/**
1465     * A pointer to a callback function to be called if the disconnect successfully
1466     * completes.  Can be set to NULL, in which case no indication of successful
1467     * completion will be received.
1468     */
1469 	MQTTAsync_onSuccess5* onSuccess5;
1470 	/**
1471     * A pointer to a callback function to be called if the disconnect fails.
1472     * Can be set to NULL, in which case no indication of unsuccessful
1473     * completion will be received.
1474     */
1475 	MQTTAsync_onFailure5* onFailure5;
1476 } MQTTAsync_disconnectOptions;
1477 
1478 #define MQTTAsync_disconnectOptions_initializer { {'M', 'Q', 'T', 'D'}, 0, 0, NULL, NULL, NULL,\
1479 	MQTTProperties_initializer, MQTTREASONCODE_SUCCESS, NULL, NULL }
1480 
1481 #define MQTTAsync_disconnectOptions_initializer5 { {'M', 'Q', 'T', 'D'}, 1, 0, NULL, NULL, NULL,\
1482 	MQTTProperties_initializer, MQTTREASONCODE_SUCCESS, NULL, NULL }
1483 
1484 /**
1485   * This function attempts to disconnect the client from the MQTT
1486   * server. In order to allow the client time to complete handling of messages
1487   * that are in-flight when this function is called, a timeout period is
1488   * specified. When the timeout period has expired, the client disconnects even
1489   * if there are still outstanding message acknowledgements.
1490   * The next time the client connects to the same server, any QoS 1 or 2
1491   * messages which have not completed will be retried depending on the
1492   * cleansession settings for both the previous and the new connection (see
1493   * MQTTAsync_connectOptions.cleansession and MQTTAsync_connect()).
1494   * @param handle A valid client handle from a successful call to
1495   * MQTTAsync_create().
1496   * @param options The client delays disconnection for up to this time (in
1497   * milliseconds) in order to allow in-flight message transfers to complete.
1498   * @return ::MQTTASYNC_SUCCESS if the client successfully disconnects from
1499   * the server. An error code is returned if the client was unable to disconnect
1500   * from the server
1501   */
1502 LIBMQTT_API int MQTTAsync_disconnect(MQTTAsync handle, const MQTTAsync_disconnectOptions* options);
1503 
1504 
1505 /**
1506   * This function allows the client application to test whether or not a
1507   * client is currently connected to the MQTT server.
1508   * @param handle A valid client handle from a successful call to
1509   * MQTTAsync_create().
1510   * @return Boolean true if the client is connected, otherwise false.
1511   */
1512 LIBMQTT_API int MQTTAsync_isConnected(MQTTAsync handle);
1513 
1514 
1515 /**
1516   * This function attempts to subscribe a client to a single topic, which may
1517   * contain wildcards (see @ref wildcard). This call also specifies the
1518   * @ref qos requested for the subscription
1519   * (see also MQTTAsync_subscribeMany()).
1520   * @param handle A valid client handle from a successful call to
1521   * MQTTAsync_create().
1522   * @param topic The subscription topic, which may include wildcards.
1523   * @param qos The requested quality of service for the subscription.
1524   * @param response A pointer to a response options structure. Used to set callback functions.
1525   * @return ::MQTTASYNC_SUCCESS if the subscription request is successful.
1526   * An error code is returned if there was a problem registering the
1527   * subscription.
1528   */
1529 LIBMQTT_API int MQTTAsync_subscribe(MQTTAsync handle, const char* topic, int qos, MQTTAsync_responseOptions* response);
1530 
1531 
1532 /**
1533   * This function attempts to subscribe a client to a list of topics, which may
1534   * contain wildcards (see @ref wildcard). This call also specifies the
1535   * @ref qos requested for each topic (see also MQTTAsync_subscribe()).
1536   * @param handle A valid client handle from a successful call to
1537   * MQTTAsync_create().
1538   * @param count The number of topics for which the client is requesting
1539   * subscriptions.
1540   * @param topic An array (of length <i>count</i>) of pointers to
1541   * topics, each of which may include wildcards.
1542   * @param qos An array (of length <i>count</i>) of @ref qos
1543   * values. qos[n] is the requested QoS for topic[n].
1544   * @param response A pointer to a response options structure. Used to set callback functions.
1545   * @return ::MQTTASYNC_SUCCESS if the subscription request is successful.
1546   * An error code is returned if there was a problem registering the
1547   * subscriptions.
1548   */
1549 LIBMQTT_API int MQTTAsync_subscribeMany(MQTTAsync handle, int count, char* const* topic, const int* qos, MQTTAsync_responseOptions* response);
1550 
1551 /**
1552   * This function attempts to remove an existing subscription made by the
1553   * specified client.
1554   * @param handle A valid client handle from a successful call to
1555   * MQTTAsync_create().
1556   * @param topic The topic for the subscription to be removed, which may
1557   * include wildcards (see @ref wildcard).
1558   * @param response A pointer to a response options structure. Used to set callback functions.
1559   * @return ::MQTTASYNC_SUCCESS if the subscription is removed.
1560   * An error code is returned if there was a problem removing the
1561   * subscription.
1562   */
1563 LIBMQTT_API int MQTTAsync_unsubscribe(MQTTAsync handle, const char* topic, MQTTAsync_responseOptions* response);
1564 
1565 /**
1566   * This function attempts to remove existing subscriptions to a list of topics
1567   * made by the specified client.
1568   * @param handle A valid client handle from a successful call to
1569   * MQTTAsync_create().
1570   * @param count The number subscriptions to be removed.
1571   * @param topic An array (of length <i>count</i>) of pointers to the topics of
1572   * the subscriptions to be removed, each of which may include wildcards.
1573   * @param response A pointer to a response options structure. Used to set callback functions.
1574   * @return ::MQTTASYNC_SUCCESS if the subscriptions are removed.
1575   * An error code is returned if there was a problem removing the subscriptions.
1576   */
1577 LIBMQTT_API int MQTTAsync_unsubscribeMany(MQTTAsync handle, int count, char* const* topic, MQTTAsync_responseOptions* response);
1578 
1579 
1580 /**
1581   * This function attempts to publish a message to a given topic (see also
1582   * ::MQTTAsync_sendMessage()). An ::MQTTAsync_token is issued when
1583   * this function returns successfully if the QoS is greater than 0.
1584   * If the client application needs to
1585   * test for successful delivery of messages, a callback should be set
1586   * (see ::MQTTAsync_onSuccess() and ::MQTTAsync_deliveryComplete()).
1587   * @param handle A valid client handle from a successful call to
1588   * MQTTAsync_create().
1589   * @param destinationName The topic associated with this message.
1590   * @param payloadlen The length of the payload in bytes.
1591   * @param payload A pointer to the byte array payload of the message.
1592   * @param qos The @ref qos of the message.
1593   * @param retained The retained flag for the message.
1594   * @param response A pointer to an ::MQTTAsync_responseOptions structure. Used to set callback functions.
1595   * This is optional and can be set to NULL.
1596   * @return ::MQTTASYNC_SUCCESS if the message is accepted for publication.
1597   * An error code is returned if there was a problem accepting the message.
1598   */
1599 LIBMQTT_API int MQTTAsync_send(MQTTAsync handle, const char* destinationName, int payloadlen, const void* payload, int qos,
1600 		int retained, MQTTAsync_responseOptions* response);
1601 
1602 /**
1603   * This function attempts to publish a message to a given topic (see also
1604   * MQTTAsync_publish()). An ::MQTTAsync_token is issued when
1605   * this function returns successfully if the QoS is greater than 0.
1606   * If the client application needs to
1607   * test for successful delivery of messages, a callback should be set
1608   * (see ::MQTTAsync_onSuccess() and ::MQTTAsync_deliveryComplete()).
1609   * @param handle A valid client handle from a successful call to
1610   * MQTTAsync_create().
1611   * @param destinationName The topic associated with this message.
1612   * @param msg A pointer to a valid MQTTAsync_message structure containing
1613   * the payload and attributes of the message to be published.
1614   * @param response A pointer to an ::MQTTAsync_responseOptions structure. Used to set callback functions.
1615   * @return ::MQTTASYNC_SUCCESS if the message is accepted for publication.
1616   * An error code is returned if there was a problem accepting the message.
1617   */
1618 LIBMQTT_API int MQTTAsync_sendMessage(MQTTAsync handle, const char* destinationName, const MQTTAsync_message* msg, MQTTAsync_responseOptions* response);
1619 
1620 
1621 /**
1622   * This function sets a pointer to an array of tokens for
1623   * messages that are currently in-flight (pending completion).
1624   *
1625   * <b>Important note:</b> The memory used to hold the array of tokens is
1626   * malloc()'d in this function. The client application is responsible for
1627   * freeing this memory when it is no longer required.
1628   * @param handle A valid client handle from a successful call to
1629   * MQTTAsync_create().
1630   * @param tokens The address of a pointer to an ::MQTTAsync_token.
1631   * When the function returns successfully, the pointer is set to point to an
1632   * array of tokens representing messages pending completion. The last member of
1633   * the array is set to -1 to indicate there are no more tokens. If no tokens
1634   * are pending, the pointer is set to NULL.
1635   * @return ::MQTTASYNC_SUCCESS if the function returns successfully.
1636   * An error code is returned if there was a problem obtaining the list of
1637   * pending tokens.
1638   */
1639 LIBMQTT_API int MQTTAsync_getPendingTokens(MQTTAsync handle, MQTTAsync_token **tokens);
1640 
1641 /**
1642  * Tests whether a request corresponding to a token is complete.
1643  *
1644  * @param handle A valid client handle from a successful call to
1645  * MQTTAsync_create().
1646  * @param token An ::MQTTAsync_token associated with a request.
1647  * @return 1 if the request has been completed, 0 if not.
1648  */
1649 #define MQTTASYNC_TRUE 1
1650 LIBMQTT_API int MQTTAsync_isComplete(MQTTAsync handle, MQTTAsync_token token);
1651 
1652 
1653 /**
1654  * Waits for a request corresponding to a token to complete.  This only works for
1655  * messages with QoS greater than 0.  A QoS 0 message has no MQTT token.
1656  * This function will always return ::MQTTASYNC_SUCCESS for a QoS 0 message.
1657  *
1658  * @param handle A valid client handle from a successful call to
1659  * MQTTAsync_create().
1660  * @param token An ::MQTTAsync_token associated with a request.
1661  * @param timeout the maximum time to wait for completion, in milliseconds
1662  * @return ::MQTTASYNC_SUCCESS if the request has been completed in the time allocated,
1663  *  ::MQTTASYNC_FAILURE or ::MQTTASYNC_DISCONNECTED if not.
1664  */
1665 LIBMQTT_API int MQTTAsync_waitForCompletion(MQTTAsync handle, MQTTAsync_token token, unsigned long timeout);
1666 
1667 
1668 /**
1669   * This function frees memory allocated to an MQTT message, including the
1670   * additional memory allocated to the message payload. The client application
1671   * calls this function when the message has been fully processed. <b>Important
1672   * note:</b> This function does not free the memory allocated to a message
1673   * topic string. It is the responsibility of the client application to free
1674   * this memory using the MQTTAsync_free() library function.
1675   * @param msg The address of a pointer to the ::MQTTAsync_message structure
1676   * to be freed.
1677   */
1678 LIBMQTT_API void MQTTAsync_freeMessage(MQTTAsync_message** msg);
1679 
1680 /**
1681   * This function frees memory allocated by the MQTT C client library, especially the
1682   * topic name. This is needed on Windows when the client library and application
1683   * program have been compiled with different versions of the C compiler.  It is
1684   * thus good policy to always use this function when freeing any MQTT C client-
1685   * allocated memory.
1686   * @param ptr The pointer to the client library storage to be freed.
1687   */
1688 LIBMQTT_API void MQTTAsync_free(void* ptr);
1689 
1690 /**
1691   * This function is used to allocate memory to be used or freed by the MQTT C client library,
1692   * especially the data in the ::MQTTPersistence_afterRead and ::MQTTPersistence_beforeWrite
1693   * callbacks. This is needed on Windows when the client library and application
1694   * program have been compiled with different versions of the C compiler.
1695   * @param size The size of the memory to be allocated.
1696   */
1697 LIBMQTT_API void* MQTTAsync_malloc(size_t size);
1698 
1699 /**
1700   * This function frees the memory allocated to an MQTT client (see
1701   * MQTTAsync_create()). It should be called when the client is no longer
1702   * required.
1703   * @param handle A pointer to the handle referring to the ::MQTTAsync
1704   * structure to be freed.
1705   */
1706 LIBMQTT_API void MQTTAsync_destroy(MQTTAsync* handle);
1707 
1708 
1709 
1710 enum MQTTASYNC_TRACE_LEVELS
1711 {
1712 	MQTTASYNC_TRACE_MAXIMUM = 1,
1713 	MQTTASYNC_TRACE_MEDIUM,
1714 	MQTTASYNC_TRACE_MINIMUM,
1715 	MQTTASYNC_TRACE_PROTOCOL,
1716 	MQTTASYNC_TRACE_ERROR,
1717 	MQTTASYNC_TRACE_SEVERE,
1718 	MQTTASYNC_TRACE_FATAL,
1719 };
1720 
1721 
1722 /**
1723   * This function sets the level of trace information which will be
1724   * returned in the trace callback.
1725   * @param level the trace level required
1726   */
1727 LIBMQTT_API void MQTTAsync_setTraceLevel(enum MQTTASYNC_TRACE_LEVELS level);
1728 
1729 
1730 /**
1731   * This is a callback function prototype which must be implemented if you want
1732   * to receive trace information. Do not invoke any other Paho API calls in this
1733   * callback function - unpredictable behavior may result.
1734   * @param level the trace level of the message returned
1735   * @param message the trace message.  This is a pointer to a static buffer which
1736   * will be overwritten on each call.  You must copy the data if you want to keep
1737   * it for later.
1738   */
1739 typedef void MQTTAsync_traceCallback(enum MQTTASYNC_TRACE_LEVELS level, char* message);
1740 
1741 /**
1742   * This function sets the trace callback if needed.  If set to NULL,
1743   * no trace information will be returned.  The default trace level is
1744   * MQTTASYNC_TRACE_MINIMUM.
1745   * @param callback a pointer to the function which will handle the trace information
1746   */
1747 LIBMQTT_API void MQTTAsync_setTraceCallback(MQTTAsync_traceCallback* callback);
1748 
1749 /**
1750   * This function returns version information about the library.
1751   * no trace information will be returned.  The default trace level is
1752   * MQTTASYNC_TRACE_MINIMUM
1753   * @return an array of strings describing the library.  The last entry is a NULL pointer.
1754   */
1755 LIBMQTT_API MQTTAsync_nameValue* MQTTAsync_getVersionInfo(void);
1756 
1757 /**
1758  * Returns a pointer to a string representation of the error code, or NULL.
1759  * Do not free after use. Returns NULL if the error code is unknown.
1760  * @param code the MQTTASYNC_ return code.
1761  * @return a static string representation of the error code.
1762  */
1763 LIBMQTT_API const char* MQTTAsync_strerror(int code);
1764 
1765 
1766 /*!
1767   * @cond MQTTAsync_main
1768   * @page async Threading
1769   * The client application runs on several threads.
1770   * Processing of handshaking and maintaining
1771   * the network connection is performed in the background.
1772   * This API is thread safe: functions may be called by multiple application
1773   * threads.
1774   * Notifications of status and message reception are provided to the client
1775   * application using callbacks registered with the library by the call to
1776   * MQTTAsync_setCallbacks() (see MQTTAsync_messageArrived(),
1777   * MQTTAsync_connectionLost() and MQTTAsync_deliveryComplete()).
1778   * In addition, some functions allow success and failure callbacks to be set
1779   * for individual requests, in the ::MQTTAsync_responseOptions structure.  Applications
1780   * can be written as a chain of callback functions.
1781   *
1782   * @page callbacks Callbacks
1783   * Any function from this API may be used within a callback.  It is not advisable to
1784   * use ::MQTTAsync_waitForCompletion within a callback, however, as it is the only
1785   * API call that may take some time to complete, which may cause unpredictable
1786   * behaviour.  All the other API calls are intended to complete quickly, starting
1787   * a request in the background, with success or failure notified by other callbacks.
1788   *
1789   * If no callbacks are assigned, this will include the message arrived callback.
1790   * This could be done if the application is a pure publisher, and does
1791   * not subscribe to any topics.  If however messages are received, and no message
1792   * arrived callback is set, then those messages will accumulate
1793   * and take up memory, as there is no place for them to be delivered.
1794   * A log message will be written to highlight the issue, but it is up
1795   * to the application to protect against this situation.
1796   *
1797   * @page auto_reconnect Automatic Reconnect
1798   * The ability for the client library to reconnect automatically in the event
1799   * of a connection failure was added in 1.1.  The connection lost callback
1800   * allows a flexible response to the loss of a connection, so almost any
1801   * behaviour can be implemented in that way.  Automatic reconnect does have the
1802   * advantage of being a little simpler to use.
1803   *
1804   * To switch on automatic reconnect, the connect options field
1805   * automaticReconnect should be set to non-zero.  The minimum and maximum times
1806   * before the next connection attempt can also be set, the defaults being 1 and
1807   * 60 seconds.  At each failure to reconnect, the retry interval is doubled until
1808   * the maximum value is reached, and there it stays until the connection is
1809   * successfully re-established whereupon it is reset.
1810   *
1811   * When a reconnection attempt is successful, the ::MQTTAsync_connected callback
1812   * function is invoked, if set by calling ::MQTTAsync_setConnected.  This allows
1813   * the application to take any actions needed, such as amending subscriptions.
1814   *
1815   * @page offline_publish Publish While Disconnected
1816   * This feature was not originally available because with persistence enabled,
1817   * messages could be stored locally without ever knowing if they could be sent.
1818   * The client application could have created the client with an erroneous broker
1819   * address or port for instance.
1820   *
1821   * To enable messages to be published when the application is disconnected
1822   * ::MQTTAsync_createWithOptions must be used instead of ::MQTTAsync_create to
1823   * create the client object.  The ::MQTTAsync_createOptions field sendWhileDisconnected
1824   * must be set to non-zero, and the maxBufferedMessages field set as required -
1825   * the default being 100.
1826   *
1827   * ::MQTTAsync_getPendingTokens can be called to return the ids of the messages
1828   * waiting to be sent, or for which the sending process has not completed.
1829   *
1830   * @page wildcard Subscription wildcards
1831   * Every MQTT message includes a topic that classifies it. MQTT servers use
1832   * topics to determine which subscribers should receive messages published to
1833   * the server.
1834   *
1835   * Consider the server receiving messages from several environmental sensors.
1836   * Each sensor publishes its measurement data as a message with an associated
1837   * topic. Subscribing applications need to know which sensor originally
1838   * published each received message. A unique topic is thus used to identify
1839   * each sensor and measurement type. Topics such as SENSOR1TEMP,
1840   * SENSOR1HUMIDITY, SENSOR2TEMP and so on achieve this but are not very
1841   * flexible. If additional sensors are added to the system at a later date,
1842   * subscribing applications must be modified to receive them.
1843   *
1844   * To provide more flexibility, MQTT supports a hierarchical topic namespace.
1845   * This allows application designers to organize topics to simplify their
1846   * management. Levels in the hierarchy are delimited by the '/' character,
1847   * such as SENSOR/1/HUMIDITY. Publishers and subscribers use these
1848   * hierarchical topics as already described.
1849   *
1850   * For subscriptions, two wildcard characters are supported:
1851   * <ul>
1852   * <li>A '#' character represents a complete sub-tree of the hierarchy and
1853   * thus must be the last character in a subscription topic string, such as
1854   * SENSOR/#. This will match any topic starting with SENSOR/, such as
1855   * SENSOR/1/TEMP and SENSOR/2/HUMIDITY.</li>
1856   * <li> A '+' character represents a single level of the hierarchy and is
1857   * used between delimiters. For example, SENSOR/+/TEMP will match
1858   * SENSOR/1/TEMP and SENSOR/2/TEMP.</li>
1859   * </ul>
1860   * Publishers are not allowed to use the wildcard characters in their topic
1861   * names.
1862   *
1863   * Deciding on your topic hierarchy is an important step in your system design.
1864   *
1865   * @page qos Quality of service
1866   * The MQTT protocol provides three qualities of service for delivering
1867   * messages between clients and servers: "at most once", "at least once" and
1868   * "exactly once".
1869   *
1870   * Quality of service (QoS) is an attribute of an individual message being
1871   * published. An application sets the QoS for a specific message by setting the
1872   * MQTTAsync_message.qos field to the required value.
1873   *
1874   * A subscribing client can set the maximum quality of service a server uses
1875   * to send messages that match the client subscriptions. The
1876   * MQTTAsync_subscribe() and MQTTAsync_subscribeMany() functions set this
1877   * maximum. The QoS of a message forwarded to a subscriber thus might be
1878   * different to the QoS given to the message by the original publisher.
1879   * The lower of the two values is used to forward a message.
1880   *
1881   * The three levels are:
1882   *
1883   * <b>QoS0, At most once:</b> The message is delivered at most once, or it
1884   * may not be delivered at all. Its delivery across the network is not
1885   * acknowledged. The message is not stored. The message could be lost if the
1886   * client is disconnected, or if the server fails. QoS0 is the fastest mode of
1887   * transfer. It is sometimes called "fire and forget".
1888   *
1889   * The MQTT protocol does not require servers to forward publications at QoS0
1890   * to a client. If the client is disconnected at the time the server receives
1891   * the publication, the publication might be discarded, depending on the
1892   * server implementation.
1893   *
1894   * <b>QoS1, At least once:</b> The message is always delivered at least once.
1895   * It might be delivered multiple times if there is a failure before an
1896   * acknowledgment is received by the sender. The message must be stored
1897   * locally at the sender, until the sender receives confirmation that the
1898   * message has been published by the receiver. The message is stored in case
1899   * the message must be sent again.
1900   *
1901   * <b>QoS2, Exactly once:</b> The message is always delivered exactly once.
1902   * The message must be stored locally at the sender, until the sender receives
1903   * confirmation that the message has been published by the receiver. The
1904   * message is stored in case the message must be sent again. QoS2 is the
1905   * safest, but slowest mode of transfer. A more sophisticated handshaking
1906   * and acknowledgement sequence is used than for QoS1 to ensure no duplication
1907   * of messages occurs.
1908   * @page publish Publication example
1909 @code
1910 #include <stdio.h>
1911 #include <stdlib.h>
1912 #include <string.h>
1913 #include "MQTTAsync.h"
1914 
1915 #if !defined(_WIN32)
1916 #include <unistd.h>
1917 #else
1918 #include <windows.h>
1919 #endif
1920 
1921 #if defined(_WRS_KERNEL)
1922 #include <OsWrapper.h>
1923 #endif
1924 
1925 #define ADDRESS     "tcp://mqtt.eclipseprojects.io:1883"
1926 #define CLIENTID    "ExampleClientPub"
1927 #define TOPIC       "MQTT Examples"
1928 #define PAYLOAD     "Hello World!"
1929 #define QOS         1
1930 #define TIMEOUT     10000L
1931 
1932 int finished = 0;
1933 
1934 void connlost(void *context, char *cause)
1935 {
1936 	MQTTAsync client = (MQTTAsync)context;
1937 	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
1938 	int rc;
1939 
1940 	printf("\nConnection lost\n");
1941 	printf("     cause: %s\n", cause);
1942 
1943 	printf("Reconnecting\n");
1944 	conn_opts.keepAliveInterval = 20;
1945 	conn_opts.cleansession = 1;
1946 	if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
1947 	{
1948 		printf("Failed to start connect, return code %d\n", rc);
1949  		finished = 1;
1950 	}
1951 }
1952 
1953 void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
1954 {
1955 	printf("Disconnect failed\n");
1956 	finished = 1;
1957 }
1958 
1959 void onDisconnect(void* context, MQTTAsync_successData* response)
1960 {
1961 	printf("Successful disconnection\n");
1962 	finished = 1;
1963 }
1964 
1965 void onSendFailure(void* context, MQTTAsync_failureData* response)
1966 {
1967 	MQTTAsync client = (MQTTAsync)context;
1968 	MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
1969 	int rc;
1970 
1971 	printf("Message send failed token %d error code %d\n", response->token, response->code);
1972 	opts.onSuccess = onDisconnect;
1973 	opts.onFailure = onDisconnectFailure;
1974 	opts.context = client;
1975 	if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
1976 	{
1977 		printf("Failed to start disconnect, return code %d\n", rc);
1978 		exit(EXIT_FAILURE);
1979 	}
1980 }
1981 
1982 void onSend(void* context, MQTTAsync_successData* response)
1983 {
1984 	MQTTAsync client = (MQTTAsync)context;
1985 	MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
1986 	int rc;
1987 
1988 	printf("Message with token value %d delivery confirmed\n", response->token);
1989 	opts.onSuccess = onDisconnect;
1990 	opts.onFailure = onDisconnectFailure;
1991 	opts.context = client;
1992 	if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
1993 	{
1994 		printf("Failed to start disconnect, return code %d\n", rc);
1995 		exit(EXIT_FAILURE);
1996 	}
1997 }
1998 
1999 
2000 void onConnectFailure(void* context, MQTTAsync_failureData* response)
2001 {
2002 	printf("Connect failed, rc %d\n", response ? response->code : 0);
2003 	finished = 1;
2004 }
2005 
2006 
2007 void onConnect(void* context, MQTTAsync_successData* response)
2008 {
2009 	MQTTAsync client = (MQTTAsync)context;
2010 	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
2011 	MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
2012 	int rc;
2013 
2014 	printf("Successful connection\n");
2015 	opts.onSuccess = onSend;
2016 	opts.onFailure = onSendFailure;
2017 	opts.context = client;
2018 	pubmsg.payload = PAYLOAD;
2019 	pubmsg.payloadlen = (int)strlen(PAYLOAD);
2020 	pubmsg.qos = QOS;
2021 	pubmsg.retained = 0;
2022 	if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
2023 	{
2024 		printf("Failed to start sendMessage, return code %d\n", rc);
2025 		exit(EXIT_FAILURE);
2026 	}
2027 }
2028 
2029 int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* m)
2030 {
2031 	// not expecting any messages
2032 	return 1;
2033 }
2034 
2035 int main(int argc, char* argv[])
2036 {
2037 	MQTTAsync client;
2038 	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
2039 	int rc;
2040 
2041 	if ((rc = MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTASYNC_SUCCESS)
2042 	{
2043 		printf("Failed to create client object, return code %d\n", rc);
2044 		exit(EXIT_FAILURE);
2045 	}
2046 
2047 	if ((rc = MQTTAsync_setCallbacks(client, NULL, connlost, messageArrived, NULL)) != MQTTASYNC_SUCCESS)
2048 	{
2049 		printf("Failed to set callback, return code %d\n", rc);
2050 		exit(EXIT_FAILURE);
2051 	}
2052 
2053 	conn_opts.keepAliveInterval = 20;
2054 	conn_opts.cleansession = 1;
2055 	conn_opts.onSuccess = onConnect;
2056 	conn_opts.onFailure = onConnectFailure;
2057 	conn_opts.context = client;
2058 	if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
2059 	{
2060 		printf("Failed to start connect, return code %d\n", rc);
2061 		exit(EXIT_FAILURE);
2062 	}
2063 
2064 	printf("Waiting for publication of %s\n"
2065          "on topic %s for client with ClientID: %s\n",
2066          PAYLOAD, TOPIC, CLIENTID);
2067 	while (!finished)
2068 		#if defined(_WIN32)
2069 			Sleep(100);
2070 		#else
2071 			usleep(10000L);
2072 		#endif
2073 
2074 	MQTTAsync_destroy(&client);
2075  	return rc;
2076 }
2077 
2078   * @endcode
2079   * @page subscribe Subscription example
2080 @code
2081 #include <stdio.h>
2082 #include <stdlib.h>
2083 #include <string.h>
2084 #include "MQTTAsync.h"
2085 
2086 #if !defined(_WIN32)
2087 #include <unistd.h>
2088 #else
2089 #include <windows.h>
2090 #endif
2091 
2092 #if defined(_WRS_KERNEL)
2093 #include <OsWrapper.h>
2094 #endif
2095 
2096 #define ADDRESS     "tcp://mqtt.eclipseprojects.io:1883"
2097 #define CLIENTID    "ExampleClientSub"
2098 #define TOPIC       "MQTT Examples"
2099 #define PAYLOAD     "Hello World!"
2100 #define QOS         1
2101 #define TIMEOUT     10000L
2102 
2103 int disc_finished = 0;
2104 int subscribed = 0;
2105 int finished = 0;
2106 
2107 void connlost(void *context, char *cause)
2108 {
2109 	MQTTAsync client = (MQTTAsync)context;
2110 	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
2111 	int rc;
2112 
2113 	printf("\nConnection lost\n");
2114 	if (cause)
2115 		printf("     cause: %s\n", cause);
2116 
2117 	printf("Reconnecting\n");
2118 	conn_opts.keepAliveInterval = 20;
2119 	conn_opts.cleansession = 1;
2120 	if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
2121 	{
2122 		printf("Failed to start connect, return code %d\n", rc);
2123 		finished = 1;
2124 	}
2125 }
2126 
2127 
2128 int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
2129 {
2130     printf("Message arrived\n");
2131     printf("     topic: %s\n", topicName);
2132     printf("   message: %.*s\n", message->payloadlen, (char*)message->payload);
2133     MQTTAsync_freeMessage(&message);
2134     MQTTAsync_free(topicName);
2135     return 1;
2136 }
2137 
2138 void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
2139 {
2140 	printf("Disconnect failed, rc %d\n", response->code);
2141 	disc_finished = 1;
2142 }
2143 
2144 void onDisconnect(void* context, MQTTAsync_successData* response)
2145 {
2146 	printf("Successful disconnection\n");
2147 	disc_finished = 1;
2148 }
2149 
2150 void onSubscribe(void* context, MQTTAsync_successData* response)
2151 {
2152 	printf("Subscribe succeeded\n");
2153 	subscribed = 1;
2154 }
2155 
2156 void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
2157 {
2158 	printf("Subscribe failed, rc %d\n", response->code);
2159 	finished = 1;
2160 }
2161 
2162 
2163 void onConnectFailure(void* context, MQTTAsync_failureData* response)
2164 {
2165 	printf("Connect failed, rc %d\n", response->code);
2166 	finished = 1;
2167 }
2168 
2169 
2170 void onConnect(void* context, MQTTAsync_successData* response)
2171 {
2172 	MQTTAsync client = (MQTTAsync)context;
2173 	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
2174 	int rc;
2175 
2176 	printf("Successful connection\n");
2177 
2178 	printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
2179            "Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
2180 	opts.onSuccess = onSubscribe;
2181 	opts.onFailure = onSubscribeFailure;
2182 	opts.context = client;
2183 	if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS)
2184 	{
2185 		printf("Failed to start subscribe, return code %d\n", rc);
2186 		finished = 1;
2187 	}
2188 }
2189 
2190 
2191 int main(int argc, char* argv[])
2192 {
2193 	MQTTAsync client;
2194 	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
2195 	MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
2196 	int rc;
2197 	int ch;
2198 
2199 	if ((rc = MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL))
2200 			!= MQTTASYNC_SUCCESS)
2201 	{
2202 		printf("Failed to create client, return code %d\n", rc);
2203 		rc = EXIT_FAILURE;
2204 		goto exit;
2205 	}
2206 
2207 	if ((rc = MQTTAsync_setCallbacks(client, client, connlost, msgarrvd, NULL)) != MQTTASYNC_SUCCESS)
2208 	{
2209 		printf("Failed to set callbacks, return code %d\n", rc);
2210 		rc = EXIT_FAILURE;
2211 		goto destroy_exit;
2212 	}
2213 
2214 	conn_opts.keepAliveInterval = 20;
2215 	conn_opts.cleansession = 1;
2216 	conn_opts.onSuccess = onConnect;
2217 	conn_opts.onFailure = onConnectFailure;
2218 	conn_opts.context = client;
2219 	if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
2220 	{
2221 		printf("Failed to start connect, return code %d\n", rc);
2222 		rc = EXIT_FAILURE;
2223 		goto destroy_exit;
2224 	}
2225 
2226 	while (!subscribed && !finished)
2227 		#if defined(_WIN32)
2228 			Sleep(100);
2229 		#else
2230 			usleep(10000L);
2231 		#endif
2232 
2233 	if (finished)
2234 		goto exit;
2235 
2236 	do
2237 	{
2238 		ch = getchar();
2239 	} while (ch!='Q' && ch != 'q');
2240 
2241 	disc_opts.onSuccess = onDisconnect;
2242 	disc_opts.onFailure = onDisconnectFailure;
2243 	if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
2244 	{
2245 		printf("Failed to start disconnect, return code %d\n", rc);
2246 		rc = EXIT_FAILURE;
2247 		goto destroy_exit;
2248 	}
2249  	while (!disc_finished)
2250  	{
2251 		#if defined(_WIN32)
2252 			Sleep(100);
2253 		#else
2254 			usleep(10000L);
2255 		#endif
2256  	}
2257 
2258 destroy_exit:
2259 	MQTTAsync_destroy(&client);
2260 exit:
2261  	return rc;
2262 }
2263 
2264   * @endcode
2265 * @page tracing Tracing
2266   *
2267   * Runtime tracing can be controlled by environment variables or API calls.
2268   *
2269   * #### Environment variables
2270   *
2271   * Tracing is switched on by setting the MQTT_C_CLIENT_TRACE environment variable.
2272   * A value of ON, or stdout, prints to stdout, any other value is interpreted as a file name to use.
2273   *
2274   * The amount of trace detail is controlled with the MQTT_C_CLIENT_TRACE_LEVEL environment
2275   * variable - valid values are ERROR, PROTOCOL, MINIMUM, MEDIUM and MAXIMUM
2276   * (from least to most verbose).
2277   *
2278   * The variable MQTT_C_CLIENT_TRACE_MAX_LINES limits the number of lines of trace that are output
2279   * to a file.  Two files are used at most, when they are full, the last one is overwritten with the
2280   * new trace entries.  The default size is 1000 lines.
2281   *
2282   * #### Trace API calls
2283   *
2284   * MQTTAsync_traceCallback() is used to set a callback function which is called whenever trace
2285   * information is available.  This will be the same information as that printed if the
2286   * environment variables were used to control the trace.
2287   *
2288   * The MQTTAsync_setTraceLevel() calls is used to set the maximum level of trace entries that will be
2289   * passed to the callback function.  The levels are:
2290   * 1. ::MQTTASYNC_TRACE_MAXIMUM
2291   * 2. ::MQTTASYNC_TRACE_MEDIUM
2292   * 3. ::MQTTASYNC_TRACE_MINIMUM
2293   * 4. ::MQTTASYNC_TRACE_PROTOCOL
2294   * 5. ::MQTTASYNC_TRACE_ERROR
2295   * 6. ::MQTTASYNC_TRACE_SEVERE
2296   * 7. ::MQTTASYNC_TRACE_FATAL
2297   *
2298   * Selecting ::MQTTASYNC_TRACE_MAXIMUM will cause all trace entries at all levels to be returned.
2299   * Choosing ::MQTTASYNC_TRACE_ERROR will cause ERROR, SEVERE and FATAL trace entries to be returned
2300   * to the callback function.
2301   *
2302   * ### MQTT Packet Tracing
2303   *
2304   * A feature that can be very useful is printing the MQTT packets that are sent and received.  To
2305   * achieve this, use the following environment variable settings:
2306   * @code
2307     MQTT_C_CLIENT_TRACE=ON
2308     MQTT_C_CLIENT_TRACE_LEVEL=PROTOCOL
2309   * @endcode
2310   * The output you should see looks like this:
2311   * @code
2312     20130528 155936.813 3 stdout-subscriber -> CONNECT cleansession: 1 (0)
2313     20130528 155936.813 3 stdout-subscriber <- CONNACK rc: 0
2314     20130528 155936.813 3 stdout-subscriber -> SUBSCRIBE msgid: 1 (0)
2315     20130528 155936.813 3 stdout-subscriber <- SUBACK msgid: 1
2316     20130528 155941.818 3 stdout-subscriber -> DISCONNECT (0)
2317   * @endcode
2318   * where the fields are:
2319   * 1. date
2320   * 2. time
2321   * 3. socket number
2322   * 4. client id
2323   * 5. direction (-> from client to server, <- from server to client)
2324   * 6. packet details
2325   *
2326   * ### Default Level Tracing
2327   *
2328   * This is an extract of a default level trace of a call to connect:
2329   * @code
2330     19700101 010000.000 (1152206656) (0)> MQTTClient_connect:893
2331     19700101 010000.000 (1152206656)  (1)> MQTTClient_connectURI:716
2332     20130528 160447.479 Connecting to serverURI localhost:1883
2333     20130528 160447.479 (1152206656)   (2)> MQTTProtocol_connect:98
2334     20130528 160447.479 (1152206656)    (3)> MQTTProtocol_addressPort:48
2335     20130528 160447.479 (1152206656)    (3)< MQTTProtocol_addressPort:73
2336     20130528 160447.479 (1152206656)    (3)> Socket_new:599
2337     20130528 160447.479 New socket 4 for localhost, port 1883
2338     20130528 160447.479 (1152206656)     (4)> Socket_addSocket:163
2339     20130528 160447.479 (1152206656)      (5)> Socket_setnonblocking:73
2340     20130528 160447.479 (1152206656)      (5)< Socket_setnonblocking:78 (0)
2341     20130528 160447.479 (1152206656)     (4)< Socket_addSocket:176 (0)
2342     20130528 160447.479 (1152206656)     (4)> Socket_error:95
2343     20130528 160447.479 (1152206656)     (4)< Socket_error:104 (115)
2344     20130528 160447.479 Connect pending
2345     20130528 160447.479 (1152206656)    (3)< Socket_new:683 (115)
2346     20130528 160447.479 (1152206656)   (2)< MQTTProtocol_connect:131 (115)
2347   * @endcode
2348   * where the fields are:
2349   * 1. date
2350   * 2. time
2351   * 3. thread id
2352   * 4. function nesting level
2353   * 5. function entry (>) or exit (<)
2354   * 6. function name : line of source code file
2355   * 7. return value (if there is one)
2356   *
2357   * ### Memory Allocation Tracing
2358   *
2359   * Setting the trace level to maximum causes memory allocations and frees to be traced along with
2360   * the default trace entries, with messages like the following:
2361   * @code
2362     20130528 161819.657 Allocating 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 177 ptr 0x179f930
2363 
2364     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
2365   * @endcode
2366   * When the last MQTT client object is destroyed, if the trace is being recorded
2367   * and all memory allocated by the client library has not been freed, an error message will be
2368   * written to the trace.  This can help with fixing memory leaks.  The message will look like this:
2369   * @code
2370     20130528 163909.208 Some memory not freed at shutdown, possible memory leak
2371     20130528 163909.208 Heap scan start, total 880 bytes
2372     20130528 163909.208 Heap element size 32, line 354, file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c, ptr 0x260cb00
2373     20130528 163909.208   Content
2374     20130528 163909.209 Heap scan end
2375   * @endcode
2376   * @endcond
2377   */
2378 
2379 #if defined(__cplusplus)
2380      }
2381 #endif
2382 
2383 #endif
2384