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