/** * @copyright * * Tencent is pleased to support the open source community by making IoT Hub available. * Copyright(C) 2018 - 2021 THL A29 Limited, a Tencent company.All rights reserved. * * Licensed under the MIT License(the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://opensource.org/licenses/MIT * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language governing permissions and * limitations under the License. * * @file mqtt_packet.h * @brief header file for mqtt packet * @author fancyxu (fancyxu@tencent.com) * @version 1.0 * @date 2021-05-24 * * @par Change Log: * *
Date Version Author Description *
2021-05-24 1.0 fancyxu first commit *
*/ #ifndef IOT_HUB_DEVICE_C_SDK_COMMON_MQTT_PACKET_INC_MQTT_PACKET_H_ #define IOT_HUB_DEVICE_C_SDK_COMMON_MQTT_PACKET_INC_MQTT_PACKET_H_ #ifdef __cplusplus extern "C" { #endif #include #include /** * @brief header 1 byte + remaining length 1~4 byte(s). * */ #define MAX_NO_OF_REMAINING_LENGTH_BYTES 4 #define MAX_MQTT_FIXED_HEADER_LEN (1 + MAX_NO_OF_REMAINING_LENGTH_BYTES) #define MIN_MQTT_FIXED_HEADER_LEN (1 + 1) /** * @brief Check if short buffer. * */ #define SHORT_BUFFER_CHECK(buf_len, len) \ if (buf_len < len) { \ return MQTT_ERR_SHORT_BUFFER; \ } /** * @brief Error code for mqtt packet。 * */ typedef enum { MQTT_RET_PACKET_OK = 0, MQTT_ERR_INVALID_PACKET_TYPE = -1, MQTT_ERR_SHORT_BUFFER = -2, MQTT_ERR_VERSION_UNSUPPORTED = -3, MQTT_ERR_SUB_COUNT_EXCEED = -4, } MQTTPacketErrCode; /** * @brief MQTT packet type. * */ typedef enum { CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, PINGREQ, PINGRESP, DISCONNECT } MQTTPacketType; /** * @brief Defines the MQTT "Last Will and Testament" (LWT) settings for the connect packet. * */ typedef struct { const char* topic_name; /**< The LWT topic to which the LWT message will be published */ const char* message; /**< The LWT payload */ uint8_t retained; /**< The retained flag for the LWT message */ uint8_t qos; /**< The quality of service setting for the LWT message */ } MQTTPacketWillOptions; /** * @brief MQTT packet connect option. * */ typedef struct { uint8_t mqtt_version; /**< Version of MQTT to be used. 3 = 3.1 4 = 3.1.1 */ const char* client_id; uint16_t keep_alive_interval; uint8_t clean_session; uint8_t will_flag; MQTTPacketWillOptions will; char* username; char* password; } MQTTPacketConnectOption; /** * @brief Bitfields for the MQTT header byte. * */ typedef union { uint8_t byte; /**< the whole byte */ struct { uint8_t retain : 1; /**< retained flag bit */ uint8_t qos : 2; /**< QoS value, 0, 1 or 2 */ uint8_t dup : 1; /**< DUP flag bit */ uint8_t type : 4; /**< message type nibble */ } bits; } MQTTHeader; /** * @brief Connect flags byte. * */ typedef union { uint8_t all; /**< all connect flags */ struct { uint8_t : 1; /**< unused */ uint8_t clean_session : 1; /**< cleansession flag */ uint8_t will : 1; /**< will flag */ uint8_t will_qos : 2; /**< will QoS value */ uint8_t will_retain : 1; /**< will retain setting */ uint8_t password : 1; /**< 3.1 password */ uint8_t username : 1; /**< 3.1 user name */ } bits; } MQTTConnectFlags; /** * @brief connack flags byte. * */ typedef union { unsigned char all; /**< all connack flags */ struct { unsigned int sessionpresent : 1; /**< session present flag */ unsigned int reserved : 7; /**< unused */ } bits; } MQTTConnackFlags; /** * @brief Flags for publish. * */ typedef struct { uint8_t dup; uint8_t qos; uint8_t retain; } MQTTPublishFlags; /** * @brief Connect return code. * */ typedef enum { CONNACK_CONNECTION_ACCEPTED = 0, /**< connection accepted */ CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1, /**< connection refused: unaccepted protocol version */ CONNACK_IDENTIFIER_REJECTED_ERROR = 2, /**< connection refused: identifier rejected */ CONNACK_SERVER_UNAVAILABLE_ERROR = 3, /**< connection refused: server unavailable */ CONNACK_BAD_USERDATA_ERROR = 4, /**< connection refused: bad user name or password */ CONNACK_NOT_AUTHORIZED_ERROR = 5 /**< connection refused: not authorized */ } MQTTConnackReturnCodes; /** * @brief Serialize the connect options into the buffer. See 3.1. * * @param[out] buf the buffer into which the packet will be serialized * @param[in] buf_len the length in bytes of the supplied buffer * @param[in] options the options to be used to build the connect packet * @return serialized length, or error if <= 0 */ int mqtt_connect_packet_serialize(uint8_t* buf, int buf_len, const MQTTPacketConnectOption* options); /** * @brief Serialize a disconnect packet into the supplied buffer, ready for writing to a socket. See 3.14. * * @param[out] buf the buffer into which the packet will be serialized * @param[in] buf_len the length in bytes of the supplied buffer, to avoid overruns * @return serialized length, or error if <= 0 */ int mqtt_disconnect_packet_serialize(uint8_t* buf, int buf_len); /** * @brief Serialize a disconnect packet into the supplied buffer, ready for writing to a socket. See 3.12. * * @param[out] buf the buffer into which the packet will be serialized * @param[in] buf_len the length in bytes of the supplied buffer, to avoid overruns * @return serialized length, or error if <= 0 */ int mqtt_pingreq_packet_serialize(uint8_t* buf, int buf_len); /** * @brief Serialize the supplied publish data into the supplied buffer, ready for sending. See 3.3. * * @param[out] buf the buffer into which the packet will be serialized * @param[in] buf_len the length in bytes of the supplied buffer * @param[in] flags the MQTT dup, qos, retained flag * @param[in] packet_id integer - the MQTT packet identifier * @param[in] topic_name char * - the MQTT topic in the publish * @param[in] payload byte buffer - the MQTT publish payload * @param[in] payload_len integer - the length of the MQTT payload * @return serialized length, or error if <= 0 */ int mqtt_publish_packet_serialize(uint8_t* buf, int buf_len, const MQTTPublishFlags* flags, uint16_t packet_id, const char* topic_name, const uint8_t* payload, int payload_len); /** * @brief Serialize a puback packet into the supplied buffer. See 3.4. * * @param[out] buf the buffer into which the packet will be serialized * @param[in] buf_len the length in bytes of the supplied buffer * @param[in] packet_id integer - the MQTT packet identifier * @return serialized length, or error if <= 0 */ int mqtt_puback_packet_serialize(uint8_t* buf, int buf_len, uint16_t packet_id); /** * @brief Serialize the supplied subscribe data into the supplied buffer, ready for sending. See 3.8. * * @param[out] buf the buffer into which the packet will be serialized * @param[in] buf_len the length in bytes of the supplied bufferr * @param[in] packet_id integer - the MQTT packet identifier * @param[in] count - number of members in the topicFilters and reqQos arrays * @param[in] topic_filters - array of topic filter names * @param[in] requested_qos - array of requested QoS * @return serialized length, or error if <= 0 */ int mqtt_subscribe_packet_serialize(uint8_t* buf, int buf_len, uint16_t packet_id, uint32_t count, char* topic_filters[], const int requested_qos[]); /** * @brief Serialize the supplied unsubscribe data into the supplied buffer, ready for sending. See 3.10. * * @param[out] buf the raw buffer data, of the correct length determined by the remaining length field * @param[in] buf_len the length in bytes of the data in the supplied buffer * @param[in] packet_id integer - the MQTT packet identifier * @param[in] count - number of members in the topicFilters array * @param[in] topic_filters - array of topic filter names * @return serialized length, or error if <= 0 */ int mqtt_unsubscribe_packet_serialize(uint8_t* buf, int buf_len, uint16_t packet_id, int count, char* topic_filters[]); /** * @brief Deserialize the supplied (wire) buffer into connack data. See 3.2. * * @param[in] buf the raw buffer data, of the correct length determined by the remaining length field * @param[in] buf_len the length in bytes of the data in the supplied buffer * @param[out] session_present the session present flag returned (only for MQTT 3.1.1) * @param[out] connack_rc returned integer value of the connack return code * @return @see MQTTPacketErrCode */ int mqtt_connack_packet_deserialize(uint8_t* buf, int buf_len, uint8_t* session_present, uint8_t* connack_rc); /** * @brief Deserialize the supplied (wire) buffer into pingresp data. See 3.13. * * @param[in] buf the raw buffer data, of the correct length determined by the remaining length field * @param[in] buf_len the length in bytes of the data in the supplied buffer * @return @see MQTTPacketErrCode */ int mqtt_pingresp_packet_deserialize(uint8_t* buf, int buf_len); /** * @brief Deserialize the supplied (wire) buffer into publish data. See 3.3. * * @param[in] buf the raw buffer data, of the correct length determined by the remaining length field * @param[in] buf_len the length in bytes of the data in the supplied buffer * @param[out] flags the MQTT dup, qos, retained flag * @param[out] packet_id returned integer - the MQTT packet identifier * @param[out] topic_name returned string - the MQTT topic in the publish * @param[out] topic_len returned integer - the length of the MQTT topic * @param[out] payload returned byte buffer - the MQTT publish payload * @param[out] payload_len returned integer - the length of the MQTT payload * @return @see MQTTPacketErrCode */ int mqtt_publish_packet_deserialize(uint8_t* buf, int buf_len, MQTTPublishFlags* flags, uint16_t* packet_id, char** topic_name, int* topic_len, uint8_t** payload, int* payload_len); /** * @brief Deserialize the supplied (wire) buffer into an ack. See 3.4. * * @param[in] buf the raw buffer data, of the correct length determined by the remaining length field * @param[in] buf_len the length in bytes of the data in the supplied buffer * @param[out] packet_id returned integer - the MQTT packet identifier * @return @see MQTTPacketErrCode */ int mqtt_puback_packet_deserialize(uint8_t* buf, int buf_len, uint16_t* packet_id); /** * @brief Deserialize the supplied (wire) buffer into suback data. See 3.9. * * @param[in] buf the raw buffer data, of the correct length determined by the remaining length field * @param[in] buf_len the length in bytes of the data in the supplied buffer * @param[in] maxcount - the maximum number of members allowed in the grantedQoSs array * @param[out] count returned integer - number of members in the grantedQoSs array * @param[out] packet_id returned integer - the MQTT packet identifier * @param[out] granted_qos returned array of integers - the granted qualities of service * @return @see MQTTPacketErrCode */ int mqtt_suback_packet_deserialize(uint8_t* buf, int buf_len, int maxcount, int* count, uint16_t* packet_id, int granted_qos[]); /** * @brief Deserialize the supplied (wire) buffer into unsuback data. See 3.11. * * @param[in] buf the raw buffer data, of the correct length determined by the remaining length field * @param[in] buf_len the length in bytes of the data in the supplied buffer * @param[out] packet_id returned integer - the MQTT packet identifier * @return @see MQTTPacketErrCode */ int mqtt_unsuback_packet_deserialize(uint8_t* buf, int buf_len, uint16_t* packet_id); #ifdef __cplusplus } #endif #endif // IOT_HUB_DEVICE_C_SDK_COMMON_MQTT_PACKET_INC_MQTT_PACKET_H_