source/interface/azure_iot_mqtt.h (125 lines of code) (raw):

/* Copyright (c) Microsoft Corporation. * Licensed under the MIT License. */ /** * @file azure_iot_mqtt.h * * @brief Azure IoT MQTT is the MQTT interface that AzureIoT middleware depends upon. * * @note This interface is private and subjected to change. Currently, there is only * one implementation for this interface, which uses coreMQTT as underlying MQTT stack. */ #ifndef AZURE_IOT_MQTT_H #define AZURE_IOT_MQTT_H #include <stdint.h> #include <stddef.h> #include <stdbool.h> #include "azure_iot_mqtt_port.h" #include "azure_iot_transport_interface.h" #define azureiotmqttPACKET_TYPE_CONNECT ( ( uint8_t ) 0x10U ) /**< @brief CONNECT (client-to-server). */ #define azureiotmqttPACKET_TYPE_CONNACK ( ( uint8_t ) 0x20U ) /**< @brief CONNACK (server-to-client). */ #define azureiotmqttPACKET_TYPE_PUBLISH ( ( uint8_t ) 0x30U ) /**< @brief PUBLISH (bidirectional). */ #define azureiotmqttPACKET_TYPE_PUBACK ( ( uint8_t ) 0x40U ) /**< @brief PUBACK (bidirectional). */ #define azureiotmqttPACKET_TYPE_PUBREC ( ( uint8_t ) 0x50U ) /**< @brief PUBREC (bidirectional). */ #define azureiotmqttPACKET_TYPE_PUBREL ( ( uint8_t ) 0x62U ) /**< @brief PUBREL (bidirectional). */ #define azureiotmqttPACKET_TYPE_PUBCOMP ( ( uint8_t ) 0x70U ) /**< @brief PUBCOMP (bidirectional). */ #define azureiotmqttPACKET_TYPE_SUBSCRIBE ( ( uint8_t ) 0x82U ) /**< @brief SUBSCRIBE (client-to-server). */ #define azureiotmqttPACKET_TYPE_SUBACK ( ( uint8_t ) 0x90U ) /**< @brief SUBACK (server-to-client). */ #define azureiotmqttPACKET_TYPE_UNSUBSCRIBE ( ( uint8_t ) 0xA2U ) /**< @brief UNSUBSCRIBE (client-to-server). */ #define azureiotmqttPACKET_TYPE_UNSUBACK ( ( uint8_t ) 0xB0U ) /**< @brief UNSUBACK (server-to-client). */ #define azureiotmqttPACKET_TYPE_PINGREQ ( ( uint8_t ) 0xC0U ) /**< @brief PINGREQ (client-to-server). */ #define azureiotmqttPACKET_TYPE_PINGRESP ( ( uint8_t ) 0xD0U ) /**< @brief PINGRESP (server-to-client). */ #define azureiotmqttPACKET_TYPE_DISCONNECT ( ( uint8_t ) 0xE0U ) /**< @brief DISCONNECT (client-to-server). */ #define azureiotmqttGET_PACKET_TYPE( ucType ) ( ( ucType ) & 0xF0U ) /**< @brief Get the packet type according to the MQTT spec */ /** * @brief Quality of service values. */ typedef enum AzureIoTMQTTQoS { eAzureIoTMQTTQoS0 = 0, /** Delivery at most once. */ eAzureIoTMQTTQoS1 = 1, /** Delivery at least once. */ eAzureIoTMQTTQoS2 = 2 /** Delivery exactly once. */ } AzureIoTMQTTQoS_t; /** * @brief MQTT suback ack status states. */ typedef enum AzureIoTMQTTSubAckStatus { eMQTTSubAckSuccessQos0 = 0x00, /** Success with a maximum delivery at QoS 0. */ eMQTTSubAckSuccessQos1 = 0x01, /** Success with a maximum delivery at QoS 1. */ eMQTTSubAckSuccessQos2 = 0x02, /** Success with a maximum delivery at QoS 2. */ eMQTTSubAckFailure = 0x80 /** Failure. */ } AzureIoTMQTTSubAckStatus_t; /** * @brief Result values used for Azure IoT MQTT functions. */ typedef enum AzureIoTMQTTResult { eAzureIoTMQTTSuccess = 0, /** Function completed successfully. */ eAzureIoTMQTTBadParameter, /** At least one parameter was invalid. */ eAzureIoTMQTTNoMemory, /** A provided buffer was too small. */ eAzureIoTMQTTSendFailed, /** The transport send function failed. */ eAzureIoTMQTTRecvFailed, /** The transport receive function failed. */ eAzureIoTMQTTBadResponse, /** An invalid packet was received from the server. */ eAzureIoTMQTTServerRefused, /** The server refused a CONNECT or SUBSCRIBE. */ eAzureIoTMQTTNoDataAvailable, /** No data available from the transport interface. */ eAzureIoTMQTTIllegalState, /** An illegal state in the state record. */ eAzureIoTMQTTStateCollision, /** A collision with an existing state record entry. */ eAzureIoTMQTTKeepAliveTimeout, /** Timeout while waiting for PINGRESP. */ eAzureIoTMQTTFailed /** Function failed with Unknown Error. */ } AzureIoTMQTTResult_t; /** * @brief Connection info for the MQTT client. */ typedef struct AzureIoTMQTTConnectInfo { /** * @brief Whether to establish a new, clean session or resume a previous session. */ bool xCleanSession; /** * @brief MQTT keep alive period, in seconds. */ uint16_t usKeepAliveSeconds; /** * @brief MQTT client identifier. Must be unique per client. */ const uint8_t * pcClientIdentifier; /** * @brief Length of the client identifier. */ uint16_t usClientIdentifierLength; /** * @brief MQTT user name. Set to NULL if not used. */ const uint8_t * pcUserName; /** * @brief Length of MQTT user name. Set to 0 if not used. * or set pcUserName to NULL. */ uint16_t usUserNameLength; /** * @brief MQTT password. Set to NULL if not used. */ const uint8_t * pcPassword; /** * @brief Length of MQTT password. Set to 0 if not used * or set pcPassword to NULL. */ uint16_t usPasswordLength; } AzureIoTMQTTConnectInfo_t; /** * @brief Subscription info for the MQTT client. */ typedef struct AzureIoTMQTTSubscribeInfo { /** * @brief Quality of Service for subscription. */ AzureIoTMQTTQoS_t xQoS; /** * @brief Topic filter to subscribe to. */ const uint8_t * pcTopicFilter; /** * @brief Length of subscription topic filter. */ uint16_t usTopicFilterLength; } AzureIoTMQTTSubscribeInfo_t; /** * @brief Publish info for the MQTT client. */ typedef struct AzureIoTMQTTPublishInfo { /** * @brief Quality of Service for message. */ AzureIoTMQTTQoS_t xQOS; /** * @brief Whether this is a retained message. */ bool xRetain; /** * @brief Whether this is a duplicate publish message. */ bool xDup; /** * @brief Topic name on which the message is published. */ const uint8_t * pcTopicName; /** * @brief Length of topic name. */ uint16_t usTopicNameLength; /** * @brief Message payload. */ const void * pvPayload; /** * @brief Message payload length. */ size_t xPayloadLength; } AzureIoTMQTTPublishInfo_t; /** * @brief MQTT packet deserialized info for the MQTT client. */ typedef struct AzureIoTMQTTDeserializedInfo { uint16_t usPacketIdentifier; /**< @brief Packet ID of deserialized packet. */ AzureIoTMQTTPublishInfo_t * pxPublishInfo; /**< @brief Pointer to deserialized publish info. */ AzureIoTMQTTResult_t xDeserializationResult; /**< @brief Return code of deserialization. */ } AzureIoTMQTTDeserializedInfo_t; /** * @brief MQTT packet info for the MQTT client. */ typedef struct AzureIoTMQTTPacketInfo { /** * @brief Type of incoming MQTT packet. */ uint8_t ucType; /** * @brief Remaining serialized data in the MQTT packet. */ uint8_t * pucRemainingData; /** * @brief Length of remaining serialized data. */ size_t xRemainingLength; } AzureIoTMQTTPacketInfo_t; /** * @brief Typedef of the MQTT client which is defined by the MQTT port. */ typedef AzureIoTMQTT_t * AzureIoTMQTTHandle_t; /** * @brief The time function to be used for MQTT functionality. * * @note Must return the time since Unix epoch. */ typedef uint32_t ( * AzureIoTMQTTGetCurrentTimeFunc_t )( void ); /** * @brief The callback function which will be invoked on receipt of an MQTT message. */ typedef void ( * AzureIoTMQTTEventCallback_t )( AzureIoTMQTTHandle_t pContext, struct AzureIoTMQTTPacketInfo * pxPacketInfo, struct AzureIoTMQTTDeserializedInfo * pxDeserializedInfo ); /** * @brief Initialize an AzureIoTMQTT context. * * @note This function is for integration of the Azure IoT middleware and * the underlying MQTT stack and should in general not be invoked by * applications directly. * * @param[in] xContext The AzureIoTMQTT context to initialize. * @param[in] pxTransportInterface The transport interface to use with the context. * @param[in] xGetTimeFunction The time utility function to use with the context. * @param[in] xUserCallback The user callback to use with the context to * notify about incoming packet events. * @param[in] pucNetworkBuffer Network buffer provided for the context. * @param[in] xNetworkBufferLength Length of network buffer. * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_Init( AzureIoTMQTTHandle_t xContext, const AzureIoTTransportInterface_t * pxTransportInterface, AzureIoTMQTTGetCurrentTimeFunc_t xGetTimeFunction, AzureIoTMQTTEventCallback_t xUserCallback, uint8_t * pucNetworkBuffer, size_t xNetworkBufferLength ); /** * @brief Establish an MQTT session. * * @note Last Will and Testament is not used with Azure IoT Hub. * * This function will send MQTT CONNECT packet and receive a CONNACK packet. The * send and receive from the network is done through the transport interface. * * @param[in] xContext Initialized AzureIoTMQTT context. * @param[in] pxConnectInfo MQTT CONNECT packet information. * @param[in] pxWillInfo Last Will and Testament. Pass NULL if Last Will and Testament is not used. * @param[in] ulMilliseconds Maximum time in milliseconds to wait for a CONNACK packet. * @param[out] pxSessionPresent Whether a previous session was present. * Only relevant if not establishing a clean session. * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_Connect( AzureIoTMQTTHandle_t xContext, const AzureIoTMQTTConnectInfo_t * pxConnectInfo, const AzureIoTMQTTPublishInfo_t * pxWillInfo, uint32_t ulMilliseconds, bool * pxSessionPresent ); /** * @brief Sends MQTT SUBSCRIBE for the given list of topic filters to * the broker. * * @param[in] xContext Initialized AzureIoTMQTT context. * @param[in] pxSubscriptionList List of MQTT subscription infos. * @param[in] xSubscriptionCount The number of elements in pxSubscriptionList. * @param[in] usPacketId Packet ID ( generated by #AzureIoTMQTT_GetPacketId ). * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_Subscribe( AzureIoTMQTTHandle_t xContext, const AzureIoTMQTTSubscribeInfo_t * pxSubscriptionList, size_t xSubscriptionCount, uint16_t usPacketId ); /** * @brief Publishes a message to the given topic name. * * @param[in] xContext Initialized AzureIoTMQTT context. * @param[in] pxPublishInfo MQTT PUBLISH packet parameters. * @param[in] usPacketId packet ID ( generated by #AzureIoTMQTT_GetPacketId ). * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_Publish( AzureIoTMQTTHandle_t xContext, const AzureIoTMQTTPublishInfo_t * pxPublishInfo, uint16_t usPacketId ); /** * @brief Sends a MQTT PINGREQ to broker. * * @param[in] xContext Initialized AzureIoTMQTT context. * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_Ping( AzureIoTMQTTHandle_t xContext ); /** * @brief Sends MQTT UNSUBSCRIBE for the given list of topic filters to * the broker. * * @param[in] xContext Initialized AzureIoTMQTT context. * @param[in] pxSubscriptionList List of MQTT subscription infos. * @param[in] xSubscriptionCount The number of elements in pxSubscriptionList. * @param[in] usPacketId packet ID ( generated by #AzureIoTMQTT_GetPacketId ). * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_Unsubscribe( AzureIoTMQTTHandle_t xContext, const AzureIoTMQTTSubscribeInfo_t * pxSubscriptionList, size_t xSubscriptionCount, uint16_t usPacketId ); /** * @brief Disconnect a MQTT session. * * @param[in] xContext Initialized AzureIoTMQTT context. * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_Disconnect( AzureIoTMQTTHandle_t xContext ); /** * @brief Loop to receive packets from the transport interface. Handles keep * alive. * * @param[in] xContext Initialized AzureIoTMQTT context. * @param[in] ulMilliseconds Minimum time in milliseconds that the process loop will * run, unless an error occurs. * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_ProcessLoop( AzureIoTMQTTHandle_t xContext, uint32_t ulMilliseconds ); /** * @brief Get a packet ID. * * @param[in] xContext Initialized AzureIoTMQTT context. * * @return A non-zero number. */ uint16_t AzureIoTMQTT_GetPacketId( AzureIoTMQTTHandle_t xContext ); /** * @brief Parses the payload of a MQTT SUBACK packet that contains status codes * corresponding to topic filter subscription requests from the original * subscribe packet. * * Each return code in the SUBACK packet corresponds to a topic filter in the * SUBSCRIBE Packet being acknowledged. * The status codes can be one of the following: * - 0x00 - Success - Maximum QoS 0 * - 0x01 - Success - Maximum QoS 1 * - 0x02 - Success - Maximum QoS 2 * - 0x80 - Failure * Refer to #AzureIoTMQTTSubAckStatus_t for the status codes. * * @param[in] pxSubackPacket The SUBACK packet whose payload is to be parsed. * @param[out] ppucPayloadStart This is populated with the starting address * of the payload (or return codes for topic filters) in the SUBACK packet. * @param[out] pxPayloadSize This is populated with the size of the payload * in the SUBACK packet. It represents the number of topic filters whose * SUBACK status is present in the packet. * * @return An #AzureIoTMQTTResult_t with the result of the operation. */ AzureIoTMQTTResult_t AzureIoTMQTT_GetSubAckStatusCodes( const AzureIoTMQTTPacketInfo_t * pxSubackPacket, uint8_t ** ppucPayloadStart, size_t * pxPayloadSize ); #endif /* AZURE_IOT_MQTT_H */