Part of TI's mqtt
Dependents: mqtt_V1 cc3100_Test_mqtt_CM3
Diff: mqtt_client.h
- Revision:
- 0:087b5655778d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mqtt_client.h Sat Jun 06 13:28:41 2015 +0000 @@ -0,0 +1,945 @@ + +/****************************************************************************** +* +* Copyright (C) 2014 Texas Instruments Incorporated +* +* All rights reserved. Property of Texas Instruments Incorporated. +* Restricted rights to use, duplicate or disclose this code are +* granted through contract. +* +* The program may not be used without the written permission of +* Texas Instruments Incorporated or against the terms and conditions +* stipulated in the agreement under which this program has been supplied, +* and under no circumstances can it be used with non-TI connectivity device. +* +******************************************************************************/ + +/* + mqtt_client.h + + This module enumerates the public interfaces / API of the MQTT Client + Library. +*/ + + +#ifndef __MQTT_CLIENT_H__ +#define __MQTT_CLIENT_H__ + +/**@file mqtt_client.h + This C library provisions the interface / API(s) for the MQTT Client. + + This is a light-weight library to enable the services of the MQTT protocol + for one or more client applications (that would typically run on a resource + constrained system). The key consideration in the design of small footprint + library has been the abstraction of the low level details of the message + transactions with the server and yet, provide rudimentary API(s), such that, + the capabilities and features of the protocol are availalbe to be utilized + by existing and new applications in an un-restrictive manner. + + The library is targeted to conform to MQTT 3.1.1 specification. + + The MQTT Client library is a highly portable software and implies a very + limited set of dependencies on a platform. Importantly, these limited + dependencies are the commonly used features used in the embedded and the + networking world, and can be easily adapted to the target platforms. + + The services of the library are multi-task safe. Platform specific atomicity + constructs are used, through abstractions, by the library to maintain data + coherency and synchronization. In addition, the library can be configured to + support several in-flight messages. + + The client library supports multiple and simultaneous MQTT connections to one + or more servers. In this client LIB, the reference to an individual connection + in conjunction with the associated configuration parameters has been termed as + a 'context'. Therefore, the client library supports multiple 'contexts'. An + application that intends to make use of the client library must set-up or + create a 'context' prior to establishing a connection with the server. The + application can choose to destroy the 'context' after the connection with the + server has been terminated. The client LIB can only support a finite set of + 'contexts' and the number can be configured by using a compiler line option / + flag <b> -DCFG_CL_MQTT_CTXS </b>. + + Once, the 'context' is set-up, the application can send and receive the MQTT + packets to / from the server. Among several features supported by the client + LIB, the 'context' manages the keep-alive mechanism by automatically sending + PING request to the server, if there has been no other packet send to the + server with the keep-alive duration. + + @note Any future extensions & development must follow the following guidelines. + A new API or an extension to the existing API + a) must be rudimentary + b) must not imply a rule or policy (including a state machine) + b) must ensure simple design and implementation + +*/ + +#include "mqtt_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +namespace mbed_mqtt { + +/*------------------------------------------------------------------------------ + * MQTT Client Messaging Routines / Services + *------------------------------------------------------------------------------ + */ + +/** @defgroup client_api The Client Library API(s) + @{ +*/ + +#define MQTT_CLIENT_VERSTR "1.0.3" /**< Version of Client LIB */ + +void createMutex(void); + +static int32_t grp_net_setup_create(void); + +/** Provides a new MSG Identifier for a packet dispatch to server + + @return MSG / PKT Transaction identifier +*/ +uint16_t mqtt_client_new_msg_id(void); + +/** Ascertain whether connection / session with the server is active or not. + Prior to sending out any information any message to server, the application + can use this routine to check the status of the connection. If connection + does not exist, then client should first CONNECT to the broker. + + A connection to server could have been closed unsolicitedly either due to + keep alive time-out or due to error in RX / TX transactions. + + @note this API does not refer to network layer connection + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + + @return true if connection is active otherwise false. +*/ +bool mqtt_client_is_connected(void *ctx); + +/** Send the CONNECT message to the server (and don't wait for CONNACK). + This routine accomplishes multiple sequences. As a first step, it tries + to establish a network connection with the server. Then, it populates + an internaly allocated packet buffer with all the previously provided + payload data information, prepares the requisite headers and finally, + dispatches the constructed message to the server. + + Prior to invoking this service, the client application should provision the + intended payload contents of the CONNECT message by using the API(s) @ref + mqtt_client_ctx_info_register and @ref mqtt_client_ctx_will_register. And + information about the server of interest must be provided in the client LIB + 'context' creation (@ref mqtt_client_ctx_create). + + The client application must invoke an appropriate receive routine to know + about the corresponding response CONNACK from the server. The client LIB will + close the network connection to the server, if the server happens to refuse + the CONNECT request. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] clean_session asserted to delete references to previous session + at both server and client + @param[in] ka_secs Keep Alive Time + @return number of bytes sent or LIB defined errors (@ref lib_err_group) +*/ +int32_t mqtt_connect_msg_send(void *ctx, bool clean_session, uint16_t ka_secs); + +/** Send a PUBLISH message to the server (don't wait for PUBACK / PUBREC). + This routine creates a PUBLISH message in an internally allocated packet + buffer by embedding the 'topic' and 'data' contents, then prepares the + packet header and finally, dispatches the message to the server. + + After the packet has been sent to the server, if the associated QoS of the + dispatched packet is ether level 1 or 2, the client LIB 'context' will then + store the packet until the time, a corresponding PUB-ACK (for QoS1) or + PUB-REC (QoS2) message is received from the server. + + If the client LIB 'context' has been configured to assert 'clean session', + then the references to all the stored and unacknowledged PUBLISH messages + are dropped at the time of MQTT disconnection (or network disconnection). + Otherwise, these unacknowledged packets continue to be availalbe for the + next iteration of the MQTT connection. However, if the client application + asserts the 'clean session' parameter in the next iteration of the CONNECT + operation, then references to all the stored PUBLISH messages, if any, are + dropped. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] topic UTF8 based Topic Name for which data is being published. + @param[in] data_buf The binary data that is being published for the topic. + @param[in] data_len The length of the binary data. + @param[in] qos quality of service of the message + @param[in] retain should the server retain the message. + @return on success, a transaction message id otherwise, LIB defined errors + (@ref lib_err_group) +*/ +int32_t mqtt_client_pub_msg_send(void *ctx, + const struct utf8_string *topic, + const uint8_t *data_buf, uint32_t data_len, + enum mqtt_qos qos, bool retain); + +/** Dispatch application constructed PUBLISH message to the server. + Prior to sending the message to the server, this routine will prepare a fixed + header to account for the size of the contents and the flags that have been + indicated by the caller. + + After the packet has been sent to the server, if the associated QoS of the + dispatched packet is ether level 1 or 2, the client LIB 'context' will then + store the packet until the time, a corresponding PUB-ACK (for QoS1) or + PUB-REC (QoS2) message is received from the server. + + If the client LIB 'context' has been configured to assert 'clean session', + then the references to all the stored and unacknowledged PUBLISH messages + are dropped at the time of MQTT disconnection (or network disconnection). + Otherwise, these unacknowledged packets continue to be availalbe for the + next iteration of the MQTT connection. However, if the client application + asserts the 'clean session' parameter in the next iteration of the CONNECT + operation, then references to all the stored PUBLISH messages, if any, are + dropped. + + The caller must populate the payload information with topic and data before + invoking this service. + + This service facilitates direct writing of topic and (real-time) payload data + into the buffer, thereby, avoiding power consuming and wasteful intermediate + data copies. + + In case, the routine returns an error, the caller is responsbile for freeing + up or re-using the packet buffer. For all other cases, the client library + will manage the return of the packet buffer to the pool. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] mqp app created PUBLISH message without the fixed header + @param[in] qos QoS with which the message needs to send to server + @param[in] retain Asserted if the message is to be retained by server. + @return on success, the transaction Message ID, otherwise LIB defined errors + (@ref lib_err_group) +*/ +int32_t mqtt_client_pub_dispatch(void *ctx, struct mqtt_packet *mqp, + enum mqtt_qos qos, bool retain); + +/** Send a SUBSCRIBE message to the server (and don't wait for SUBACK). + This routine creates a SUBSCRIBE message in an internally allocated packet + buffer by embedding the 'qos_topics', then prepares the message header and + finally, dispatches the packet to the server. + + After the packet has been dispatched to the server, the library will store + the packet until the time, a corresponding SUB-ACK has been received from + the server. This mechanism enables the client LIB 'context' to trace the + sequence of the message-ID and / or resend the SUB packets to the server. + + The client LIB 'context', if configured to operate in the MQTT 3.1.1 mode + will drop or remove the un-acknowledged SUB messages at the time of the + termination of the network connection. + + In the MQTT 3.1 mode, the client LIB 'context' will remove the unacknowledged + SUB messages at the time of the termination of the network connection, if the + 'clean session' has been asserted. In case, the 'clean session' has not been + asserted, the stored SUB messages will continue to be available for the next + iteration of the MQTT connection. However, if the client application asserts + the 'clean session' parameter in the next iteration of the CONNECT operation, + then references to all the stored SUBSCRIBE messages, if any, are dropped. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] qos_topics an array of topic along-with its qos + @param[in] count the number of elements in the array + @return on success, the transaction Message ID, otherwise Lib defined errors + (@ref lib_err_group) +*/ +int32_t mqtt_sub_msg_send(void *ctx, const struct utf8_strqos *qos_topics, uint32_t count); + +/** Dispatch application constructed SUSBSCRIBE message to the server. + Prior to sending the message to the server, this routine will prepare a fixed + header to account for the size of the size of the contents. + + After the packet has been dispatched to the server, the library will store + the packet until the time, a corresponding SUB-ACK has been received from + the server. This mechanism enables the client LIB 'context' to trace the + sequence of the message-ID and / or resend the SUB packets to the server. + + The client LIB 'context', if configured to operate in the MQTT 3.1.1 mode + will drop or remove the un-acknowledged SUB messages at the time of the + termination of the network connection. + + In the MQTT 3.1 mode, the client LIB 'context' will remove the unacknowledged + SUB messages at the time of the termination of the network connection, if the + 'clean session' has been asserted. In case, the 'clean session' has not been + asserted, the stored SUB messages will continue to be available for the next + iteration of the MQTT connection. However, if the client application asserts + the 'clean session' parameter in the next iteration of the CONNECT operation, + then references to all the stored SUBSCRIBE messages, if any, are dropped. + + The caller must populate the payload information of topic along with qos + before invoking this service. + + This service facilitates direct writing of topic and (real-time) payload data + into the buffer, thereby, avoiding power consuming and wasteful intermediate + data copies. + + In case, the routine returns an error, the caller is responsbile for freeing + up or re-using the packet buffer. For all other cases, the client library + will manage the return of the packet buffer to the pool. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] mqp app created SUBSCRIBE message without the fixed header. + @return on success, the transaction Message ID, otherwise Lib defined errors + (@ref lib_err_group) +*/ +int32_t mqtt_sub_dispatch(void *ctx, struct mqtt_packet *mqp); + +/** Send an UNSUBSCRIBE message to the server (and don't wait for UNSUBACK). + This routine creates an UNSUBSCRIBE message in an internally allocated packet + buffer by embedding the 'topics', then prepares the message header and + finally, dispatches the packet to the server. + + After the packet has been dispatched to the server, the library will store + the packet until the time, a corresponding UNSUB-ACK has been received from + the server. This mechanism enables the client LIB 'context' to trace the + sequence of the message-ID and / or resend the UNSUB packets to the server. + + The client LIB 'context', if configured to operate in the MQTT 3.1.1 mode + will drop or remove the un-acknowledged SUB messages at the time of the + termination of the network connection. + + In the MQTT 3.1 mode, the client LIB 'context' will remove the unacknowledged + UNSUB messages at the time of the termination of the network connection, if + the 'clean session' has been asserted. In case, the 'clean session' has not + been asserted, the stored UNSUB messages will continue to be available for + the next iteration of the MQTT connection. However, if the client application + asserts the 'clean session' parameter in the next iteration of the CONNECT + operation, then references to all the stored UNSUBSCRIBE messages, if any, + are dropped. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] topics an array of topic to unsubscribe + @param[in] count the number of elements in the array + @return on success, the transaction Message ID, otherwise Lib defined errors + (@ref lib_err_group) +*/ +int32_t mqtt_unsub_msg_send(void *ctx, const struct utf8_string *topics, uint32_t count); + +/** Dispatch application constructed UNSUSBSCRIBE message to the server. + Prior to sending the message to the server, this routine will prepare a fixed + header to account for the size of the size of the contents. + + After the packet has been dispatched to the server, the library will store + the packet until the time, a corresponding UNSUB-ACK has been received from + the server. This mechanism enables the client LIB 'context' to trace the + sequence of the message-ID and / or resend the UNSUB packets to the server. + + The client LIB 'context', if configured to operate in the MQTT 3.1.1 mode + will drop or remove the un-acknowledged SUB messages at the time of the + termination of the network connection. + + In the MQTT 3.1 mode, the client LIB 'context' will remove the unacknowledged + UNSUB messages at the time of the termination of the network connection, if + the 'clean session' has been asserted. In case, the 'clean session' has not + been asserted, the stored UNSUB messages will continue to be available for + the next iteration of the MQTT connection. However, if the client application + asserts the 'clean session' parameter in the next iteration of the CONNECT + operation, then references to all the stored UNSUBSCRIBE messages, if any, + are dropped. + + The caller must populate the payload information of topics before invoking + this service. + + This service facilitates direct writing of topic and (real-time) payload data + into the buffer, thereby, avoiding power consuming and wasteful intermediate + data copies. + + In case, the routine returns an error, the caller is responsbile for freeing + up or re-using the packet buffer. For all other cases, the client library + will manage the return of the packet buffer to the pool. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] Packet Buffer that holds UNSUBSCRIBE message without a fixed header + @return on success, the transaction Message ID, otherwise LIB defined errors + (@ref lib_err_group) +*/ +int32_t mqtt_unsub_dispatch(void *ctx, struct mqtt_packet *mqp); + +/** Send a PINGREQ message to the server (and don't wait for PINGRSP). + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @return number of bytes sent or Lib define errors (@ref lib_err_group) +*/ + +int32_t mqtt_pingreq_send(void *ctx); + +/** Send a DISCONNECT message to the server. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @return number of bytes sent or Lib define errors (@ref lib_err_group) +*/ +int32_t mqtt_disconn_send(void *ctx); + + +/** Send remaining data or contents of the scheduled message to the server. + This routine tries to send the remaining data in an active transfer of a + message to the server. This service is valid, only if the network layer of + the platform is not able to send out the entire message in one TCP packet + and has to "back-off" or "give up the control" before it can schedule or + dispatch the next packet. In such a scenario, the network layer sends the + first part (segment) of the scheduled message in the mqtt_xxx_send() API and + the subsequent parts or the segments are sent using this routine. + + This routine is not applicable to the platforms or the scenarios, where the + implementation of the platform can segment the MQTT message in a manner to + schedule consercutive or back-to-back blocking socket transactions. + Specifically, this API must be used by an application, only if the network + layer can indicate in an asynchronous manner, its readiness to send the next + packet to the server. And the mechanism to indicate readiness of the network + layer for the next send transaction is out of band and out of scope for the + Client LIB and depends on the platform. + + A platform that resorts to partial send of a message and has to back-off from + transmission implies the following the considerations on to the application. + (a) The next segment / part of the currently active MQTT packet can be sent + or scheduled only after receiving the indication, to do so, from the network + layer. + (b) The next or new MQTT message (or its first segment) can be scheduled for + transmission only after receiving the indication for completion of handling + of the last segment of currently active message. + + @note The application developer should refer to the platform specific network + implementation for details. + + The routine returns the number of remaining bytes in the message to be sent. + However, as described earlier, the application is expected to wait for an + indication about the readiness of the network layer prior to sending or + scheduling another segment, if so available, to the server. Now, the new + segment can be a next part of the currently active message or it can be the + first segment of a new message. A return value of zero means that there is + no more data left in the scheduled message to be sent to the server and the + application should wait for an appropriate event to indicate the transmission + of the last segment. + + In case of an error, the transfer of the remaining segments or parts of the + scheduled message is aborted. Depending on the configuration of the 'clean + session' in-conjunction with the revision of the MQTT protocol, the active + message would be stored for re-transmission, MQTT connection is established + again. To store a message for re-transmission, at least one segment of the + message must have been successfully sent to the server. + + @note This API must be used by the application only if the platform has the + capability to indicate the completion of the sending of an active segment. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @return the number of bytes remaining to be sent in the message. Otherwise, + LIB defined errors (@ref lib_err_group) +*/ +int32_t mqtt_client_send_progress(void *ctx); + +/** Block on the 'context' to receive a message type with-in specified wait time. + This service is valid only for the configuration, where the application has + not provided the callbacks to the client LIB 'context'. The caller must + provide a packet buffer of adequate size to hold the expected message from + the server. + + The wait time implies the maximum intermediate duration between the reception + of two successive messages from the server. If no message is received before + the expiry of the wait time, the routine returns. However, the routine would + continue to block, in case, messages are being received within the successive + period of wait time and these messages are not the one that client is waiting + for. + + For platforms that can receive a MQTT message over multiple TCP packets or in + segments, it is neccessary for the application to provide the same packet + packet buffer 'mqp' across all iterations of this routine that returns with a + value of MQP_ERR_TIMEOUT. Such an arrangement enables the implementation to + iteratively build from consecutive multiple RX network packets / segements, a + MQTT message into the packet buffer 'mqp. The application can always choose + to assign a new 'mqp' once, a complete MQTT message has been received. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] msg_type message type to receive. A value of 0 would imply that + caller is ready to receive the next message, whatsoever, from the server. + @param[out] mqp packet buffer to hold the message received from the server. + @param[in] wait_secs maximum Time to wait for a message from the server. + @return On success, the number of bytes received for 'msg_type' from server, + otherwise LIB defined error values (@ref lib_err_group) +*/ +int32_t mqtt_client_ctx_await_msg(void *ctx, uint8_t msg_type, struct mqtt_packet *mqp, + uint32_t wait_secs); + +/** Helper function to receive any message from the server. + Refer to mqtt_client_ctx_await_msg for the details. + @see mqtt_client_ctx_await_msg +*/ +static inline +int32_t mqtt_client_ctx_recv(void *ctx, struct mqtt_packet *mqp, uint32_t wait_secs) +{ + /* Receive next and any MQTT Message from the broker */ + return mqtt_client_ctx_await_msg(ctx, 0x00, mqp, wait_secs); +} + +/** Run the context for the specificed wait time. + This service is valid only for the configuration, where the application has + populated the callbacks that can be invoked by the client LIB 'context'. + + This routine yields the control back to the application after the duration + of the wait time. Such an arrangement enable the application to make overall + progress to meet its intended functionality. + + The wait time implies the maximum intermediate duration between the reception + of two successive messages from the server. If no message is received before + the expiry of the wait time, the routine returns. However, the routine would + continue to block, in case, messages are being received within the successive + period of the wait time. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] wait_secs maximum time to wait for a message from the server + + @return MQP_ERR_NOTCONN if MQTT connection is closed by the application, + MQP_ERR_TIMEOUT if there was no MQTT transaction in the interval of wait time + and other values (@ref lib_err_group) +*/ +int32_t mqtt_client_ctx_run(void *ctx, uint32_t wait_secs); + +/** Block to receive any message for the grouped contexts within specified time. + This service is valid only for the set-up, where the applicatiion has not + configured the grouped contexts in the callback mode. The caller must provide + a packet buffer of adequate size to hold the expected message from the server. + + The wait time implies the maximum intermediate duration between the reception + of two successive messages from the server. If no message is received before + the expiry of the wait time, the routine returns. However, the routine would + continue to block, in case, messages are being received within the successive + period of wait time. + + In this revision of the LIB, the underlying implementation will be provide a + valid value in the 'app' field for the all returned values, including errors, + other than the cases of 'MQP_ERR_TIMEOUT' and 'MQP_ERR_LIBQUIT'. The value in + 'app', when valid refers to a previously configured handle to an application + and idenitifies the 'context' for which the routine has been returned. + + @param[out] mqp packet buffer to hold the message received from the server. + @param[in] wait_secs Maximum Time to wait for a message from the server. + @param[out] app place holder to indicate application handle for the packet. + @return On success, the number of bytes received for 'msg_type' from server, + otherwise LIB defined error values (@ref lib_err_group) + + @note if the value of MQP_ERR_LIBQUIT is returned, then system must be + restarted. +*/ +int32_t mqtt_client_await_msg(struct mqtt_packet *mqp, uint32_t wait_secs, void **app); + +/** Run the LIB for the specified wait time. + This service is valid only for the set-up of grouped contexts, where the + application has populated the callbacks that can be invoked by the LIB. + + This routine yields the control back to the application after the specified + duration of wait time. Such an arrangement enable the application to + make overall progress to meet it intended functionality. + + The wait time implies the maximum intermediate duration between the reception + of two successive messages from the server. If no message is received before + the expiry of the wait time, the routine returns. However, the routine would + continue to block, in case, messages are being received within the successive + period of wait time. + + @param[in] wait_secs maximum time to wait for a message from the server + + @return on connection close by client app, number of bytes received for the + last msg from broker, otherwise LIB defined error values. + + @note if the value of MQP_ERR_LIBQUIT is returned, then system must be + restarted. +*/ +int32_t mqtt_client_run(uint32_t wait_secs); + +/*------------------------------------------------------------------------------ + * MQTT Client Library: Packet Buffer Pool and its management + *------------------------------------------------------------------------------ + */ + +/** Allocates a free MQTT Packet Buffer. + The pool that will be used by the library to allocate a free MQP buffer + must be configured (i.e. registered) a-priori by the app. + + The parameter 'offset' is used to specify the number of bytes that are + reserved for the header in the buffer + + @param[in] msg_type Message Type for which MQP buffer is being assigned. + @param[in] offset Number of bytes to be reserved for MQTT headers. + @return A NULL on error, otherwise a reference to a valid packet holder. + + @see mqtt_client_register_buffers +*/ +struct mqtt_packet *mqp_client_alloc(uint8_t msg_type, uint8_t offset); + +/** Helper function to allocate a MQTT Packet Buffer for a message to be + dispatched to server. + + @see to mqp_client_alloc( ) for details. +*/ +static inline struct mqtt_packet *mqp_client_send_alloc(uint8_t msg_type) +{ + return mqp_client_alloc(msg_type, MAX_FH_LEN); +} + +/** Helper function to allocate a MQTT Packet Buffer for a message to be + received from the server. + + @see to mqp_client_alloc( ) for details. +*/ +static inline struct mqtt_packet *mqp_client_recv_alloc(uint8_t msg_type) +{ + return mqp_client_alloc(msg_type, 0); +} + +/** Create a pool of MQTT Packet Buffers for the client library. + This routine creates a pool of free MQTT Packet Buffers by attaching a buffer + (buf) to a packet holder (mqp). The count of mqp elements and buf elements in + the routine are same. And the size of the buffer in constant across all the + elements. + + The MQTT Packet Buffer pool should support (a) certain number of in-flight and + stored packets that await ACK(s) from the server (b) certain number of packets + from server whose processing would be deferred by the client app (to another + context) (c) a packet to create a CONNECT message to re-establish transaction + with the server. + + A meaningful size of the pool is very much application specific and depends + on the target functionality. For example, an application that intends to have + only one in-flight message to the server would need atmost three MQP buffers + (1 for TX (for Qos1 or 2 store), 1 for RX and 1 for CONNECT message). If the + application sends only QoS0 messages to the server, then the number of MQP + buffers would reduce to two (i.e. 1 Tx to support CONNECT / PUB out and 1 RX) + + @param[in] num_mqp Number or count of elements in mqp_vec and buf_vec. + @param[in] mqp_vec An array of MQTT Packet Holder without a buffer. + @param[in] buf_len The size or length of the buffer element in the 'buf_vec' + @param[in] buf_vec An array of buffers. + @retun 0 on success otherwise -1 on error. + + @note The parameters mqp_vec and buf_vec should be peristent entities. + + @see mqtt_client_await_msg + @see mqtt_client_run +*/ +int32_t mqtt_client_buffers_register(uint32_t num_mqp, struct mqtt_packet *mqp_vec, + uint32_t buf_len, uint8_t *buf_vec); + +/*------------------------------------------------------------------------------ + * MQTT Client Library: Register application, platform information and services. + *------------------------------------------------------------------------------ + */ + +/** Register application info and its credentials with the client library. + This routine registers information for all the specificed parameters, + therefore, an upate to single element would imply re-specification of + the other paramters, as well. + + @note Contents embedded in the parameters is not copied by the routine, + and instead a reference to the listed constructs is retained. Therefore, + the app must enable the parameter contents for persistency. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] client_id MQTT UTF8 identifier of the client. If set to NULL, + then the client will be treated as zero length entity. + @param[in] user_name MQTT UTF8 user name for the client. If not used, + set it to NULL. If used, then it can't be of zero length. + @param[in] pass_word MQTT UTF8 pass word for the client. If not used, set + it to NULL, If used, then it can't be of zero length. + @return 0 on success otherwise -1 + + User name without a pass word is a valid configuration. A pass word won't + be processed if it is not associated with a valid user name. +*/ +int32_t mqtt_client_ctx_info_register(void *ctx, + const struct utf8_string *client_id, + const struct utf8_string *user_name, + const struct utf8_string *pass_word); + +/** Register WILL information of the client application. + This routine registers information for all the specificed parameters, + therefore, an update to single element would imply re-specification + of the other paramters, as well. + + @note Contents embedded in the parameters is not copied by the routine, + and instead a reference to the listed constructs is retained. Therefore, + the app must enable the parameter contents for persistency. + + @param[in] ctx handle to the underlying network context in the LIB + @see mqtt_client_ctx_create + @param[in] will_top UTF8 WILL Topic on which WILL message is to be published. + @param[in] will_msg UTF8 WILL message. + @param[in] will_qos QOS for the WILL message + @param[in] retain asserted to indicate that published WILL must be retained + @return 0 on success otherwise -1. + + Both will_top and will_msg should be either present or should be NULL. + will_qos and retain are relevant only for a valid Topic and Message combo. +*/ +int32_t mqtt_client_ctx_will_register(void *ctx, + const struct utf8_string *will_top, + const struct utf8_string *will_msg, + enum mqtt_qos will_qos, bool retain); + +/** Abstraction for the device specific network services. + Network services for communication with the server + + @param[in] net refers to network services supported by the platform + @return on success, 0, otherwise -1 + + @ref net_ops_group + @note all entries in net must be supported by the platform. +*/ +int32_t mqtt_client_net_svc_register(const struct device_net_services *net); + +/** Helper functions & macros to derive 16 bit CONNACK Return Code from broker. + */ +#define VHB_CONNACK_RC(vh_buf) (vh_buf[1]) /**< CONNACK VH:: Return Code */ +#define MQP_CONNACK_RC(mqp) (mqp->buffer[3])/**< CONNACK MQP:: Return Code */ + +#define VHB_CONNACK_SP(vh_buf) (vh_buf[0] & 0x1)/**< CONNACK VH:: Session Bit */ +#define MQP_CONNACK_SP(mqp) (mqp->buffer[2] & 0x1) /**< CONNACK MQP:: \ + Session Bit */ + +#define VHB_CONNACK_VH16(vh_buf)((vh_buf[0] << 8) | vh_buf[1]) +#define MQP_CONNACK_VH16(mqp) ((mqp->buffer[2] << 8) | mqp->buffer[3]) + +/** Callbacks to be invoked by MQTT Client library onto Client application */ +struct mqtt_client_ctx_cbs { + + /** Provides a PUBLISH message from server to the client application. + The application can utilize the associated set of helper macros to + get references to the topic and the data information contained in + the message. @ref rxpub_help_group + + Depending upon the QoS level of the message, the MQTT client library + shall dispatch the correponding acknowlegement (PUBACK or PUBREC) to + the server, thereby, relieving application of this support. + + If the application completes the processing of the packet within the + implementation of this callback routine, then a value of 'true' must + be returned to the client LIB 'context'. The library, in this case, + does not handover the packet to application and instead, frees it up + on return from this routine. + + If the application intends to defer the processing of the PUBLISH + message to a different execution task, then it must takeover the + owernship of the packet by returning a value of 'false' to the client + LIB 'context. In this arrangement, the client LIB 'context' hands + over the packet to the application. The responsibility of storing, + managing and eventually freeing up the packet back to the pool, now, + lies with the app. + + @param[in] app application to which this PUBLISH message is targeted + @see mqtt_client_ctx_create + @param[in] dup asserted to indicate a DUPLICATE PUBLISH + @param[in] qos quality of Service of the PUBLISH message + @param[in] retain Asserted to indicate message at new subscription + @param[in] mqp Packet Buffer that holds the PUBLISH message + + @return true to indicate that processing of the packet has been + completed and it can freed-up and returned back to the pool by + the library. Otherwise, false. + */ + bool (*publish_rx)(void *app, + bool dup, enum mqtt_qos qos, bool retain, + struct mqtt_packet *mqp); + + /** Notifies the client application about an ACK or a response from the + server. Following are the messages that are notified by the client + LIB to the application. + + CONNACK, PINGRSP, PUBACK, PUBCOMP, SUBACK, UNSUBACK + + @param[in] app application to which this ACK message is targeted + @see mqtt_client_ctx_create + @param[in] msg_type Type of the MQTT messsage + @param[in] msg_id transaction identity of the message + @param[in] buf refers to contents of message and depends on msg_type + @param[in] len length of the buf + @return none + + @note The size of the buf parameter i.e len is non-zero for the + SUBACK and CONNACK messages. For SUBACK the buf carries an array of + QOS responses provided by the server. For CONNACK, the buf carries + variable header contents. Helper macro VHB_CONNACK_RC( ) and + VHB_CONNACK_SP( ) can be used to access contents provided by the + server. For all other messages, the value of len parameter is zero. + + @note The parameter msg_id is not relevant for the messages CONNACK + and PINGRSP and is set to zero. + */ + void (*ack_notify)(void *app, uint8_t msg_type, uint16_t msg_id, uint8_t *buf, uint32_t len); + + /** Notifies the client application about the termination of connection + with the server. After servicing this callback, the application can + destroy associated context if it no longer required + + @param[in] app application whose connection got terminated + @see mqtt_client_ctx_create + @param[in] cause reason that created disconnection + (@ref lib_err_group) + */ + void (*disconn_cb)(void *app, int32_t cause); +}; + +struct mqtt_client_ctx_cfg { + + /** @defgroup mqtt_ctx_cfg_opt_grp Options for application to config CTX + @{ + */ +#define MQTT_CFG_PROTOCOL_V31 0x0001 /**< Assert for ver3.1, default is 3.1.1 */ +#define MQTT_CFG_APP_HAS_RTSK 0x0002 /**< Assert if APP has dedicated RX Task */ +#define MQTT_CFG_MK_GROUP_CTX 0x0004 /**< Assert if task manages > 1 contexts */ + /** @} */ + + uint16_t config_opts; /**< Context config Opt, @ref mqtt_ctx_cfg_opt_grp */ + + /** @defgroup mqtt_netconn_opt_grp Options for App to configure network + @{ + */ +#define MQTT_NETCONN_OPT_IP6 DEV_NETCONN_OPT_IP6 /**<@ref dev_netconn_opt_grp */ +#define MQTT_NETCONN_OPT_URL DEV_NETCONN_OPT_URL /**<@ref dev_netconn_opt_grp */ +#define MQTT_NETCONN_OPT_SEC DEV_NETCONN_OPT_SEC /**<@ref dev_netconn_opt_grp */ + /** @} */ + + uint32_t nwconn_opts; /**< Network Options, @ref mqtt_netconn_opt_grp */ + + char *server_addr; /**< Reference to '\0' terminated address string */ + uint16_t port_number; /**< Network Listening Port number of the server */ + struct secure_conn *nw_security; /**< Refer to @ref mqtt_netsec_grp */ +}; + +/** Create a Network Connection Context. + This routine sets-up the parameters that are required to operate and manage + the network connection with a MQTT server / broker. As part of the creation + of a context, the implementation also records the handle, if provided, by + the application. In addition, the invoker of the routine must facilitate a + place holder to enable the client LIB to provision the reference to the + 'context', so created. + + Specifically, this routine associates or ties-up, in an one-to-one manner, + the caller provided handle 'app' and the client LIB provisioned handle 'ctx'. + The parameter 'app' is returned by the client LIB in certain other routines + to indicate the underlying 'context' with which network transaction or event + is associated. Similarly, the caller must specify the context handle 'ctx' + for which the services are being invoked. + + A user or a task prior to utilizing the services of the library to schedule + MQTT transactions must create a 'context'. A client LIB 'context' can be + operated in two modes: (a) sync-wait or explicit receive mode and (b) the + callback mode. Provisioning or absence of the callback parameter in this + routine defines the mode of operation of the 'context'. + + Explicit receive mode is analogous to the paradigm of the socket programming + in which an application utilize the recv() function call. It is anticipated + that applications which would make use of limited set of MQTT messages may + find this mode of operation useful. Applications which intend to operate the + 'context' in this mode must not provision any callbacks. + + On the other hand, certain applications, may prefer an asynchronous mode of + operation and would want the client LIB 'context' to raise callbacks into + the application, as and when, packets arrive from the server. And such + applications must provide the callback routines. + + @param[in] ctx_cfg configuration information for the Network Context. + @param[in] ctx_cbs callback routines. Must be set to NULL, if the application + intends to operate the context in the sync-wait / explicit receive mode. + @param[in] app handle to application. Returned by LIB in other routines + to refer to the underlying context. + @param[out] ctx reference to the context created and is provisioned by the + implementation. (Valid only if routine returns a success) + + @return 0 on success otherwise -1. +*/ +int32_t mqtt_client_ctx_create(const struct mqtt_client_ctx_cfg *ctx_cfg, + const struct mqtt_client_ctx_cbs *ctx_cbs, + void *app, void **ctx); + +/** Delete a Network Connection Context. + This routines destroys the previously created network 'context' and releases + resources that would be assigned for maintaining the information about the + 'context'. + + A user or a task prior to deleting the 'context' must ensure that there is no + active MQTT connection on this context. + + @param[in] ctx handle to network context to be deleted. The context must + have been previously created. + + @return 0 on success otherwise -1 +*/ + +int32_t mqtt_client_ctx_delete(void *ctx); + +/** Contruct / Data to initialize MQTT Client Library */ +struct mqtt_client_lib_cfg { + + /** If an application has more than one contexts (i.e. grouped contexts) + to manage in a single task, then a non-zero value must be provided. + Otherwise, this parameter must be set to zero. + */ + uint16_t loopback_port; + bool grp_uses_cbfn; /**< Assert if grouped contexts use call-backs */ + + /** For a multi-task environment, provide a handle to platform mutex */ + void *mutex; + void (*mutex_lockin)(void *mutex); /**< Take platform mutex function */ + void (*mutex_unlock)(void *mutex); /**< Give platform mutex function */ + + int32_t (*debug_printf)(const char *format, ...); /**< Debug, mandatory */ + bool aux_debug_en; /**< Assert to indicate additional debug info */ +}; + +/** Initialize the MQTT client library. + This routine initializes all the common constructs that are required to + manage the multiple network connetions. The client LIB must be initialized + prior to invoking of any other routine or service. + + @note This routine must be invoked only once in an run of the system. + + Depending upon the deployment needs, this routine can be invoked either as + part of the platform initialization sequence or as part of the application. + Deployments that have more than one application utilizing the services of + the client LIB should try to invoke the routine from the initialization + sequence of the platform. + + In addition, if an application has to manage more than one network + connections (i.e. in other words, if the application has to handle + a group of connections), then certain configuration must be set in + the LIB @see struct mqtt_client_lib_cfg + + @note There must be only one group of network connetions in the system. + + @param[in] cfg Configuration information for the MQTT client Library. + + @return 0 on success otherwise -1. +*/ + +int32_t mqtt_client_lib_init(const struct mqtt_client_lib_cfg *cfg); + +/** Exit the MQTT client library. + @return 0 on success otherwise -1. +*/ +int32_t mqtt_client_lib_exit(void); + +/** @} */ /* End group client_api */ + +}//namespace mbed_mqtt + +#ifdef __cplusplus +} +#endif + +#endif +