tos_kernel_sig_init

tos_kernel_sig_init
This commit is contained in:
Supowang
2022-06-28 13:02:03 +08:00
parent c18f082949
commit 2be1169b0b
8376 changed files with 0 additions and 7963023 deletions

View File

@@ -1,10 +0,0 @@
file(GLOB src ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)
set(inc ${CMAKE_CURRENT_SOURCE_DIR}/inc/)
set(src_common ${src_common} ${src} PARENT_SCOPE)
set(inc_common ${inc_common} ${inc} PARENT_SCOPE)
if( ${CONFIG_IOT_TEST} STREQUAL "ON")
file(GLOB src_unit_test ${CMAKE_CURRENT_SOURCE_DIR}/test/*.cc)
set(src_test ${src_test} ${src_unit_test} PARENT_SCOPE)
endif()

View File

@@ -1,335 +0,0 @@
/**
* @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:
* <table>
* <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2021-05-24 <td>1.0 <td>fancyxu <td>first commit
* </table>
*/
#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 <stdint.h>
#include <string.h>
/**
* @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_

View File

@@ -1,364 +0,0 @@
/**
* @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_deserialize.c
* @brief implements mqtt packet deserialize. Reference paho.mqtt.embedded-c &
* http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.pdf
* @author fancyxu (fancyxu@tencent.com)
* @version 1.0
* @date 2021-05-21
*
* @par Change Log:
* <table>
* <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2021-05-21 <td>1.0 <td>fancyxu <td>first commit
* </table>
*/
#include "mqtt_packet.h"
/**
* @brief Reads one character from the input buffer. See 1.5.1.
*
* @param[in,out] pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return the character read
*/
static inline char _read_char(uint8_t** pptr)
{
char c = **pptr;
(*pptr)++;
return c;
}
/**
* @brief Calculates an integer from two bytes read from the input buffer. See 1.5.2.
*
* @param[in,out] pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return the integer value calculated
*/
static inline uint16_t _read_int(uint8_t** pptr)
{
uint8_t* ptr = *pptr;
int len = 256 * (*ptr) + (*(ptr + 1));
*pptr += 2;
return (uint16_t)len;
}
/**
* @brief Read a UTF-8 encoded string pointer from the input buffer. See 1.5.3.
*
* @param[out] pstring the pointer of the C string to read.
* @param[in,out] pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return the length of string
*/
static inline int _read_string(char** pstring, uint8_t** pptr)
{
int str_len = _read_int(pptr);
if (str_len > 0) {
*pstring = (char*)*pptr;
*pptr += str_len;
}
return str_len;
}
/**
* @brief Check the mqtt type and get publish flags. See 2.2.
*
* @param[in] packet_type type of mqtt control packet, See 2.2.1
* @param[in] pflags pointer to the flags of mqtt control packet fixed header. See 2.2.2
* @param[in,out] pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return @see MQTTPacketErrCode
*/
static int _mqtt_packet_type_check(MQTTPacketType packet_type, MQTTPublishFlags* pflags, uint8_t** pptr)
{
MQTTHeader header = {0};
header.byte = _read_char(pptr);
switch (header.bits.type) {
case PUBLISH:
pflags->dup = header.bits.dup;
pflags->qos = header.bits.qos;
pflags->retain = header.bits.retain;
break;
case SUBSCRIBE:
case UNSUBSCRIBE:
if ((header.byte & 0xf0) != 0x10) {
return MQTT_ERR_INVALID_PACKET_TYPE;
}
break;
default:
break;
}
return packet_type != header.bits.type ? MQTT_ERR_INVALID_PACKET_TYPE : MQTT_RET_PACKET_OK;
}
/**
* @brief Deserialize remaining length. See 2.2.3.
*
* @param[in] buf_len the length in bytes of the supplied buffer
* @param[in] plen the pointer to the remaining length
* @param[in,out] pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return @see MQTTPacketErrCode
*/
static int _mqtt_remaining_length_deserialize(int buf_len, int* plen, uint8_t** pptr)
{
uint8_t* buf = *pptr;
uint8_t c = 0;
uint32_t multiplier = 1;
uint32_t count = 0;
uint32_t len = 0;
do {
if (++count > MAX_NO_OF_REMAINING_LENGTH_BYTES) {
return MQTT_ERR_INVALID_PACKET_TYPE;
}
c = *buf++;
len += (c & 127) * multiplier;
multiplier *= 128;
SHORT_BUFFER_CHECK(buf_len, count + 1 + len);
} while (c & 128);
if (plen) {
*plen = len;
}
*pptr += count;
return MQTT_RET_PACKET_OK;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
uint8_t* ptr = buf;
int rc = 0;
MQTTConnackFlags flags = {0};
rc = _mqtt_packet_type_check(CONNACK, NULL, &ptr);
if (rc) {
goto exit;
}
rc = _mqtt_remaining_length_deserialize(buf_len, NULL, &ptr);
if (rc < 0) {
goto exit;
}
flags.all = _read_char(&ptr);
*session_present = flags.bits.sessionpresent;
*connack_rc = _read_char(&ptr);
exit:
return 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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
uint8_t* ptr = buf;
int rc = 0;
rc = _mqtt_packet_type_check(PINGRESP, NULL, &ptr);
if (rc) {
goto exit;
}
rc = _mqtt_remaining_length_deserialize(buf_len, NULL, &ptr);
if (rc < 0) {
goto exit;
}
exit:
return rc;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
uint8_t* ptr = buf;
uint8_t* ptr_remain = NULL;
int rc = 0;
int len = 0;
rc = _mqtt_packet_type_check(PUBLISH, flags, &ptr);
if (rc) {
goto exit;
}
rc = _mqtt_remaining_length_deserialize(buf_len, &len, &ptr);
if (rc) {
goto exit;
}
ptr_remain = ptr;
rc = _read_string(topic_name, &ptr);
if (rc <= 0) {
rc = MQTT_ERR_INVALID_PACKET_TYPE;
goto exit;
}
*topic_len = rc;
if (flags->qos > 0) {
*packet_id = _read_int(&ptr);
}
*payload_len = len - (ptr - ptr_remain);
*payload = ptr;
rc = MQTT_RET_PACKET_OK;
exit:
return rc;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
uint8_t* ptr = buf;
int rc = 0;
rc = _mqtt_packet_type_check(PUBACK, 0, &ptr);
if (rc) {
goto exit;
}
rc = _mqtt_remaining_length_deserialize(buf_len, NULL, &ptr);
if (rc) {
goto exit;
}
*packet_id = _read_int(&ptr);
exit:
return rc;
}
/**
* @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[])
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
uint8_t* ptr = buf;
int rc = 0;
int len = 0;
rc = _mqtt_packet_type_check(SUBACK, NULL, &ptr);
if (rc) {
goto exit;
}
rc = _mqtt_remaining_length_deserialize(buf_len, &len, &ptr);
if (rc) {
goto exit;
}
*packet_id = _read_int(&ptr);
len -= 2;
*count = 0;
while (len--) {
if (*count > maxcount) {
rc = MQTT_ERR_SUB_COUNT_EXCEED;
goto exit;
}
granted_qos[(*count)++] = _read_char(&ptr);
}
exit:
return rc;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
uint8_t* ptr = buf;
int rc = 0;
rc = _mqtt_packet_type_check(UNSUBACK, NULL, &ptr);
if (rc) {
goto exit;
}
rc = _mqtt_remaining_length_deserialize(buf_len, NULL, &ptr);
if (rc) {
goto exit;
}
*packet_id = _read_int(&ptr);
exit:
return rc;
}

View File

@@ -1,458 +0,0 @@
/**
* @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_serialize.c
* @brief implements mqtt packet serialize. Reference paho.mqtt.embedded-c &
* http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.pdf
* @author fancyxu (fancyxu@tencent.com)
* @version 1.0
* @date 2021-05-21
*
* @par Change Log:
* <table>
* <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2021-05-21 <td>1.0 <td>fancyxu <td>first commit
* </table>
*/
#include "mqtt_packet.h"
/**
* @brief Writes one character to an output buffer. See 1.5.1.
*
* @param[in] c the character to write
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned
*/
static inline void _write_char(char c, uint8_t** pptr)
{
**pptr = c;
(*pptr)++;
}
/**
* @brief Writes an integer as 2 bytes to an output buffer. See 1.5.2.
*
* @param[in] value the integer to write.
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned.
*/
static inline void _write_int(int value, uint8_t** pptr)
{
**pptr = (uint8_t)(value / 256);
(*pptr)++;
**pptr = (uint8_t)(value % 256);
(*pptr)++;
}
/**
* @brief Writes a UTF-8 encoded string to an output buffer. Converts C string to
* length-delimited. See 1.5.3.
*
* @param[in] string the C string to write
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned
*/
static inline void _write_string(const char* string, uint8_t** pptr)
{
int len = strlen(string);
_write_int(len, pptr);
memcpy(*pptr, string, len);
*pptr += len;
}
/**
* @brief Serialize mqtt fixed header except remaining length. See 2.2.
*
* @param[in] packet_type type of mqtt control packet, See 2.2.1 MQTT Control Packet type
* @param[in] pflags pointer to the flags of mqtt control packet fixed header. See 2.2.2 Flags
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned
*/
static void _mqtt_header_serialize(MQTTPacketType packet_type, const MQTTPublishFlags* pflags, uint8_t** pptr)
{
MQTTHeader header = {0};
switch (packet_type) {
case PUBLISH:
header.bits.dup = pflags->dup;
header.bits.qos = pflags->qos;
header.bits.retain = pflags->retain;
break;
case SUBSCRIBE:
case UNSUBSCRIBE:
header.byte = 0x02;
break;
default:
break;
}
header.bits.type |= packet_type;
_write_char(header.byte, pptr); /* write header */
}
/**
* @brief Serialize remaining length. See 2.2.3.
*
* @param[in] length the length to be encoded to remaining length
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned
*/
static void _mqtt_remaining_length_serialize(int length, uint8_t** pptr)
{
char d;
do {
d = length % 128;
length /= 128;
// if there are more digits to encode, set the top bit of this digit
if (length > 0) {
d |= 0x80;
}
_write_char(d, pptr);
} while (length > 0);
}
/**
* @brief Serialize the remaining length of the MQTT connect packet that would be produced using the
* supplied connect options. See 3.1.1.
*
* @param[in] options the options to be used to build the connect packet
* @param[in] buf_len the length in bytes of the supplied buffer
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned
*/
static int _mqtt_connect_remaining_length_serialize(const MQTTPacketConnectOption* options, int buf_len, uint8_t** pptr)
{
if (options->mqtt_version != 3 && options->mqtt_version != 4) {
return MQTT_ERR_VERSION_UNSUPPORTED;
}
int len = 0;
len = options->mqtt_version == 3 ? 12 : 10;
len += strlen(options->client_id) + 2;
if (options->will_flag) {
len += strlen(options->will.topic_name) + 2 + strlen(options->will.message) + 2;
}
if (options->username) {
len += strlen(options->username) + 2;
}
if (options->password) {
len += strlen(options->password) + 2;
}
SHORT_BUFFER_CHECK(buf_len, len);
_mqtt_remaining_length_serialize(len, pptr);
return MQTT_RET_PACKET_OK;
}
/**
* @brief Serialize the mqtt connect packet variable header. See 3.1.2.
*
* @param[in] options the options to be used to build the connect packet
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned
*/
static int _mqtt_connect_variable_header_serialize(const MQTTPacketConnectOption* options, uint8_t** pptr)
{
if (options->password && !options->username) {
return MQTT_ERR_INVALID_PACKET_TYPE;
}
// 3.1.2.1 protocol name & 3.1.2.2 protocol level
switch (options->mqtt_version) {
case 3:
_write_string("MQIsdp", pptr);
_write_char((char)3, pptr);
break;
case 4:
_write_string("MQTT", pptr);
_write_char((char)4, pptr);
break;
}
// 3.1.2.3 Connect Flags
MQTTConnectFlags flags = {
.bits.clean_session = options->clean_session,
.bits.will = options->will_flag,
.bits.will_qos = options->will_flag ? options->will.qos : 0,
.bits.will_retain = options->will_flag ? options->will.retained : 0,
.bits.username = options->username ? 1 : 0,
.bits.password = options->password ? 1 : 0,
};
_write_char(flags.all, pptr);
return MQTT_RET_PACKET_OK;
}
/**
* @brief Serialize the remaining length of the MQTT publish packet that would be produced using the supplied
* parameters. See 3.3.2 & 3.3.3.
*
* @param[in] qos the MQTT QoS of the publish (packet id is omitted for QoS 0)
* @param[in] topic_name the topic name to be used in the publish
* @param[in] payload_len the length of the payload to be sent
* @param[in] buf_len the length in bytes of the supplied buffer
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned
*/
static int _mqtt_publish_remaining_length_serialize(uint8_t qos, const char* topic_name, int payload_len, int buf_len,
uint8_t** pptr)
{
int len = 0;
len += 2 + strlen(topic_name) + payload_len;
if (qos > 0) {
len += 2; /* packet id */
}
SHORT_BUFFER_CHECK(buf_len, len + MAX_MQTT_FIXED_HEADER_LEN);
_mqtt_remaining_length_serialize(len, pptr);
return MQTT_RET_PACKET_OK;
}
/**
* @brief Serialize the length of the MQTT subscribe/unsubscribe packet that would be produced using the
* supplied parameters. See 3.8.1 & 3.10.1.
*
* @param[in] count the number of topic filter strings in topicFilters
* @param[in] topic_filters the array of topic filter strings to be used in the publish
* @param[in] buf_len the length in bytes of the supplied buffer
* @param[out] pptr pointer to the output buffer - incremented by the number of bytes used & returned
*/
static int _mqtt_sub_unsub_remaining_length_serialize(uint32_t count, char* topic_filters[], int buf_len,
uint8_t** pptr, uint8_t is_sub)
{
int i = 0;
int len = 2; /* packet id */
for (i = 0; i < count; ++i) {
len += 2 + strlen(topic_filters[i]) + is_sub; /* length + topic */
}
SHORT_BUFFER_CHECK(buf_len, len + MAX_MQTT_FIXED_HEADER_LEN);
_mqtt_remaining_length_serialize(len, pptr);
return MQTT_RET_PACKET_OK;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
int rc;
uint8_t* ptr = buf;
// 3.1.1 Fixed header
_mqtt_header_serialize(CONNECT, NULL, &ptr);
rc = _mqtt_connect_remaining_length_serialize(options, buf_len, &ptr);
if (rc) {
return rc;
}
// 3.1.2 Variable header
rc = _mqtt_connect_variable_header_serialize(options, &ptr);
if (rc) {
return rc;
}
// 3.1.3 Payload
_write_int(options->keep_alive_interval, &ptr);
_write_string(options->client_id, &ptr);
if (options->will_flag) {
_write_string(options->will.topic_name, &ptr);
_write_string(options->will.message, &ptr);
}
if (options->username) {
_write_string(options->username, &ptr);
}
if (options->password) {
_write_string(options->password, &ptr);
}
return ptr - buf;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
uint8_t* ptr = buf;
_mqtt_header_serialize(DISCONNECT, 0, &ptr);
_mqtt_remaining_length_serialize(0, &ptr);
return ptr - buf;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
uint8_t* ptr = buf;
_mqtt_header_serialize(PINGREQ, 0, &ptr);
_mqtt_remaining_length_serialize(0, &ptr);
return ptr - buf;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
int rc;
uint8_t* ptr = buf;
_mqtt_header_serialize(PUBLISH, flags, &ptr);
rc = _mqtt_publish_remaining_length_serialize(flags->qos, topic_name, payload_len, buf_len, &ptr);
if (rc) {
return rc;
}
_write_string(topic_name, &ptr);
if (flags->qos > 0) {
_write_int(packet_id, &ptr);
}
memcpy(ptr, payload, payload_len);
ptr += payload_len;
return ptr - buf;
}
/**
* @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)
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN + 2);
uint8_t* ptr = buf;
_mqtt_header_serialize(PUBACK, 0, &ptr);
_mqtt_remaining_length_serialize(2, &ptr);
_write_int(packet_id, &ptr);
return ptr - buf;
}
/**
* @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[])
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
int rc, i = 0;
uint8_t* ptr = buf;
_mqtt_header_serialize(SUBSCRIBE, 0, &ptr);
rc = _mqtt_sub_unsub_remaining_length_serialize(count, topic_filters, buf_len, &ptr, 1);
if (rc) {
return rc;
}
_write_int(packet_id, &ptr);
for (i = 0; i < count; ++i) {
_write_string(topic_filters[i], &ptr);
_write_char(requested_qos[i], &ptr);
}
return ptr - buf;
}
/**
* @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[])
{
SHORT_BUFFER_CHECK(buf_len, MIN_MQTT_FIXED_HEADER_LEN);
int rc, i = 0;
uint8_t* ptr = buf;
_mqtt_header_serialize(UNSUBSCRIBE, 0, &ptr);
rc = _mqtt_sub_unsub_remaining_length_serialize(count, topic_filters, buf_len, &ptr, 0);
if (rc) {
return rc;
}
_write_int(packet_id, &ptr);
for (i = 0; i < count; ++i) {
_write_string(topic_filters[i], &ptr);
}
return ptr - buf;
}

View File

@@ -1,8 +0,0 @@
Language: Cpp
BasedOnStyle: Google
ColumnLimit: 120
DerivePointerAlignment: true
PointerAlignment: Left
SortIncludes: true
IncludeBlocks: Preserve
IndentPPDirectives: AfterHash

View File

@@ -1,307 +0,0 @@
/**
* @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 test_mqtt_packet.cc
* @brief unit test for mqtt packet
* @author fancyxu (fancyxu@tencent.com)
* @version 1.0
* @date 2021-06-01
*
* @par Change Log:
* <table>
* <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2021-06-01 <td>1.0 <td>fancyxu <td>first commit
* </table>
*/
#include <iostream>
#include <string>
#include "gtest/gtest.h"
#include "mqtt_packet.h"
namespace mqtt_packet_unittest {
/**
* @brief Test connect packet.
*
*/
TEST(MQTTPacketTest, CONNECT) {
uint8_t test_packet[] = {
0x10, 0x77, 0x00, 0x04, 0x4d, 0x51, 0x54, 0x54, 0x04, 0xc2, 0x00, 0xf0, 0x00, 0x0e, 0x4a, 0x4e, 0x4c, 0x52,
0x57, 0x4f, 0x33, 0x54, 0x35, 0x39, 0x74, 0x65, 0x73, 0x74, 0x00, 0x28, 0x4a, 0x4e, 0x4c, 0x52, 0x57, 0x4f,
0x33, 0x54, 0x35, 0x39, 0x74, 0x65, 0x73, 0x74, 0x3b, 0x32, 0x31, 0x30, 0x31, 0x30, 0x34, 0x30, 0x36, 0x3b,
0x49, 0x41, 0x5a, 0x5a, 0x4a, 0x3b, 0x32, 0x31, 0x34, 0x37, 0x34, 0x38, 0x33, 0x36, 0x34, 0x37, 0x00, 0x31,
0x66, 0x62, 0x63, 0x39, 0x65, 0x34, 0x36, 0x33, 0x61, 0x32, 0x30, 0x64, 0x66, 0x30, 0x34, 0x35, 0x65, 0x62,
0x66, 0x34, 0x38, 0x34, 0x35, 0x61, 0x35, 0x39, 0x62, 0x32, 0x61, 0x38, 0x35, 0x66, 0x65, 0x62, 0x34, 0x31,
0x34, 0x31, 0x30, 0x30, 0x3b, 0x68, 0x6d, 0x61, 0x63, 0x73, 0x68, 0x61, 0x31,
};
uint8_t packet_buf[2048];
std::string user_name = "JNLRWO3T59test;21010406;IAZZJ;2147483647";
std::string password = "fbc9e463a20df045ebf4845a59b2a85feb414100;hmacsha1";
MQTTPacketConnectOption options = {
.mqtt_version = 4,
.client_id = "JNLRWO3T59test",
.keep_alive_interval = 240,
.clean_session = 1,
.will_flag = 0,
.will = {0},
.username = reinterpret_cast<char *>(const_cast<char *>(user_name.c_str())),
.password = reinterpret_cast<char *>(const_cast<char *>(password.c_str())),
};
ASSERT_EQ(mqtt_connect_packet_serialize(packet_buf, sizeof(packet_buf), &options), sizeof(test_packet));
ASSERT_EQ(memcmp(packet_buf, test_packet, sizeof(test_packet)), 0);
ASSERT_EQ(mqtt_connect_packet_serialize(packet_buf, 1, &options), MQTT_ERR_SHORT_BUFFER);
options.username = NULL;
ASSERT_EQ(mqtt_connect_packet_serialize(packet_buf, sizeof(packet_buf), &options), MQTT_ERR_INVALID_PACKET_TYPE);
options.password = NULL;
ASSERT_EQ(mqtt_connect_packet_serialize(packet_buf, sizeof(packet_buf), &options),
sizeof(test_packet) - user_name.length() - password.length() - 4);
options.mqtt_version = 5;
ASSERT_EQ(mqtt_connect_packet_serialize(packet_buf, sizeof(packet_buf), &options), MQTT_ERR_VERSION_UNSUPPORTED);
}
/**
* @brief Test connack packet.
*
*/
TEST(MQTTPacketTest, CONNACK) {
uint8_t test_packet[] = {0x20, 0x02, 0x00, 0x00};
uint8_t session_present, connack_rc;
for (uint8_t i = CONNACK_CONNECTION_ACCEPTED; i <= CONNACK_NOT_AUTHORIZED_ERROR; i++) {
test_packet[3] = i;
ASSERT_EQ(mqtt_connack_packet_deserialize(test_packet, sizeof(test_packet), &session_present, &connack_rc),
MQTT_RET_PACKET_OK);
ASSERT_EQ(connack_rc, i);
}
ASSERT_EQ(mqtt_connack_packet_deserialize(test_packet, 2, &session_present, &connack_rc), MQTT_ERR_SHORT_BUFFER);
test_packet[0] = SUBACK;
ASSERT_EQ(mqtt_connack_packet_deserialize(test_packet, sizeof(test_packet), &session_present, &connack_rc),
MQTT_ERR_INVALID_PACKET_TYPE);
}
/**
* @brief Test publish packet.
*
*/
TEST(MQTTPacketTest, PUBLISH) {
uint8_t test_packet[] = {
0x32, 0x40, 0x00, 0x14, 0x4a, 0x4e, 0x4c, 0x52, 0x57, 0x4f, 0x33, 0x54, 0x35, 0x39, 0x2f, 0x74, 0x65,
0x73, 0x74, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x70, 0xaf, 0x7b, 0x22, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x3a, 0x20, 0x22, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x22,
0x2c, 0x20, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x30, 0x22, 0x7d,
};
uint8_t packet_buf[128];
/**
* @brief QoS1
*
*/
char serialize_topic_name[] = "JNLRWO3T59/test/data";
int serialize_topic_len = strlen(serialize_topic_name);
uint16_t serialize_packet_id = 28847;
uint8_t serialize_payload[] = "{\"action\": \"publish_test\", \"count\": \"0\"}";
int serialize_payload_len = strlen((const char *)serialize_payload);
MQTTPublishFlags serialize_flags = {0, 1, 0};
ASSERT_EQ(mqtt_publish_packet_serialize(packet_buf, sizeof(packet_buf), &serialize_flags, serialize_packet_id,
serialize_topic_name, serialize_payload, serialize_payload_len),
sizeof(test_packet));
ASSERT_EQ(memcmp(packet_buf, test_packet, sizeof(test_packet)), 0);
char *deserialize_topic_name;
int deserialize_topic_len;
uint16_t deserialize_packet_id = 0;
uint8_t *deserialize_payload;
int deserialize_payload_len;
MQTTPublishFlags deserialize_flags;
ASSERT_EQ(mqtt_publish_packet_deserialize(test_packet, sizeof(test_packet), &deserialize_flags,
&deserialize_packet_id, &deserialize_topic_name, &deserialize_topic_len,
&deserialize_payload, &deserialize_payload_len),
0);
ASSERT_EQ(deserialize_packet_id, serialize_packet_id);
ASSERT_EQ(deserialize_topic_len, serialize_topic_len);
ASSERT_EQ(deserialize_payload_len, serialize_payload_len);
ASSERT_EQ(memcmp(&deserialize_flags, &serialize_flags, sizeof(deserialize_flags)), 0);
ASSERT_EQ(memcmp(deserialize_topic_name, serialize_topic_name, deserialize_topic_len), 0);
ASSERT_EQ(memcmp(deserialize_payload, serialize_payload, deserialize_payload_len), 0);
/**
* @brief QoS0
*
*/
serialize_flags.qos = 0;
deserialize_packet_id = 0;
ASSERT_EQ(
mqtt_publish_packet_serialize(packet_buf, sizeof(packet_buf), &serialize_flags, serialize_packet_id,
serialize_topic_name, serialize_payload, strlen((const char *)serialize_payload)),
sizeof(test_packet) - 2);
ASSERT_EQ(mqtt_publish_packet_deserialize(packet_buf, sizeof(packet_buf), &deserialize_flags, &deserialize_packet_id,
&deserialize_topic_name, &deserialize_topic_len, &deserialize_payload,
&deserialize_payload_len),
MQTT_RET_PACKET_OK);
ASSERT_NE(deserialize_packet_id, serialize_packet_id);
/**
* @brief bad packet
*
*/
packet_buf[0] = PUBACK;
ASSERT_EQ(mqtt_publish_packet_deserialize(packet_buf, sizeof(packet_buf), &deserialize_flags, &deserialize_packet_id,
&deserialize_topic_name, &deserialize_topic_len, &deserialize_payload,
&deserialize_payload_len),
MQTT_ERR_INVALID_PACKET_TYPE);
}
/**
* @brief Test puback packet.
*
*/
TEST(MQTTPacketTest, PUBACK) {
uint8_t test_packet[] = {0x40, 0x02, 0x70, 0xaf};
uint8_t packet_buf[128];
uint16_t serialize_packet_id = 28847;
ASSERT_EQ(mqtt_puback_packet_serialize(packet_buf, sizeof(packet_buf), serialize_packet_id), 4);
ASSERT_EQ(memcmp(packet_buf, test_packet, sizeof(test_packet)), 0);
uint16_t deserialize_packet_id;
ASSERT_EQ(mqtt_puback_packet_deserialize(test_packet, sizeof(test_packet), &deserialize_packet_id),
MQTT_RET_PACKET_OK);
ASSERT_EQ(deserialize_packet_id, serialize_packet_id);
}
/**
* @brief Test subscribe packet.
*
*/
TEST(MQTTPacketTest, SUBSCRIBE) {
uint8_t test_packet[] = {
0x82, 0x19, 0x70, 0xae, 0x00, 0x14, 0x4a, 0x4e, 0x4c, 0x52, 0x57, 0x4f, 0x33, 0x54,
0x35, 0x39, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x00,
};
uint8_t packet_buf[128];
std::string topic = "JNLRWO3T59/test/data";
uint16_t serialize_packet_id = 28846;
char *serialize_topic_name = reinterpret_cast<char *>(const_cast<char *>(topic.c_str()));
int serialize_qos = 0;
ASSERT_EQ(mqtt_subscribe_packet_serialize(packet_buf, sizeof(packet_buf), serialize_packet_id, 1,
&serialize_topic_name, &serialize_qos),
sizeof(test_packet));
ASSERT_EQ(memcmp(packet_buf, test_packet, sizeof(test_packet)), 0);
}
/**
* @brief Test suback packet.
*
*/
TEST(MQTTPacketTest, SUBACK) {
uint8_t test_packet[] = {0x90, 0x03, 0x70, 0xae, 0x00};
int sub_count = 0;
uint16_t packet_id;
int granted_qos[1];
ASSERT_EQ(mqtt_suback_packet_deserialize(test_packet, sizeof(test_packet), 1, &sub_count, &packet_id, granted_qos),
MQTT_RET_PACKET_OK);
ASSERT_EQ(sub_count, 1);
ASSERT_EQ(packet_id, 28846);
ASSERT_EQ(granted_qos[0], 0);
}
/**
* @brief Test unsubscribe packet.
*
*/
TEST(MQTTPacketTest, UNSUBSCRIBE) {
uint8_t test_packet[] = {
0xa2, 0x18, 0x35, 0x74, 0x00, 0x14, 0x4a, 0x4e, 0x4c, 0x52, 0x57, 0x4f, 0x33,
0x54, 0x35, 0x39, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x64, 0x61, 0x74, 0x61,
};
uint8_t packet_buf[128];
uint16_t packet_id = 13684;
std::string topic = "JNLRWO3T59/test/data";
char *topic_name = reinterpret_cast<char *>(const_cast<char *>(topic.c_str()));
ASSERT_EQ(mqtt_unsubscribe_packet_serialize(packet_buf, sizeof(packet_buf), packet_id, 1, &topic_name),
sizeof(test_packet));
ASSERT_EQ(memcmp(packet_buf, test_packet, sizeof(test_packet)), 0);
}
/**
* @brief Test connack packet.
*
*/
TEST(MQTTPacketTest, UNSUBACK) {
uint8_t test_packet[] = {0xb0, 0x02, 0x92, 0x6b};
uint16_t packet_id;
ASSERT_EQ(mqtt_unsuback_packet_deserialize(test_packet, sizeof(test_packet), &packet_id), MQTT_RET_PACKET_OK);
ASSERT_EQ(packet_id, 37483);
}
/**
* @brief Test pingreq packet.
*
*/
TEST(MQTTPacketTest, PINGREQ) {
uint8_t test_packet[] = {0xc0, 0x00};
uint8_t packet_buf[128];
ASSERT_EQ(mqtt_pingreq_packet_serialize(packet_buf, sizeof(packet_buf)), sizeof(test_packet));
ASSERT_EQ(memcmp(packet_buf, test_packet, sizeof(test_packet)), 0);
}
/**
* @brief Test pingresp packet.
*
*/
TEST(MQTTPacketTest, PINGRESP) {
uint8_t test_packet[] = {0xd0, 0x00};
ASSERT_EQ(mqtt_pingresp_packet_deserialize(test_packet, sizeof(test_packet)), MQTT_RET_PACKET_OK);
}
/**
* @brief Test disconnect packet.
*
*/
TEST(MQTTPacketTest, DISCONNECT) {
uint8_t test_packet[] = {0xe0, 0x00};
uint8_t packet_buf[128];
ASSERT_EQ(mqtt_disconnect_packet_serialize(packet_buf, sizeof(packet_buf)), sizeof(test_packet));
ASSERT_EQ(memcmp(packet_buf, test_packet, sizeof(test_packet)), 0);
}
} // namespace mqtt_packet_unittest