refactor: Reorganize mqtt5 property management to mqtt5_msg library

This commit is contained in:
Euripedes Rocha
2026-10-01 06:53:56 +02:00
committed by Euripedes Rocha Filho
parent 69ca2fb79b
commit 5de986916c
11 changed files with 289 additions and 270 deletions
+1 -65
View File
@@ -8,6 +8,7 @@
#define _MQTT5_CLIENT_H_
#include "mqtt_client.h"
#include "mqtt_common.h"
#ifdef __cplusplus
extern "C" {
@@ -77,11 +78,6 @@ typedef enum mqtt5_reason_code_t {
*/
typedef __attribute__((deprecated)) esp_mqtt5_reason_code_t esp_mqtt5_error_reason_code_t;
/**
* MQTT5 user property handle
*/
typedef struct mqtt5_user_property_list_t *mqtt5_user_property_handle_t;
/**
* MQTT5 protocol connect properties and will properties configuration, more details refer to MQTT5 protocol document section 3.1.2.11 and 3.3.2.3
*/
@@ -106,58 +102,6 @@ typedef struct {
will_user_property; /*!< The handle for will message user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_connection_property_config_t;
/**
* MQTT5 protocol publish properties configuration, more details refer to MQTT5 protocol document section 3.3.2.3
*/
typedef struct {
bool payload_format_indicator; /*!< This value is to indicator publish message payload format */
uint32_t message_expiry_interval; /*!< The time interval that message expiry */
uint16_t topic_alias; /*!< An integer value to identify the topic instead of using topic name string */
const char *response_topic; /*!< Topic name for a response message */
const char *correlation_data; /*!< Binary data for receiver to match the response message */
uint16_t correlation_data_len; /*!< The length of correlation data */
const char
*content_type; /*!< This value is to indicator publish message content type, use a MIME content type string */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_publish_property_config_t;
/**
* MQTT5 protocol subscribe properties configuration, more details refer to MQTT5 protocol document section 3.8.2.1
*/
typedef struct {
uint16_t subscribe_id; /*!< A variable byte represents the identifier of the subscription */
bool no_local_flag; /*!< Subscription Option to allow that server publish message that client sent */
bool retain_as_published_flag; /*!< Subscription Option to keep the retain flag as published option */
uint8_t retain_handle; /*!< Subscription Option to handle retain option */
bool is_share_subscribe; /*!< Whether subscribe is a shared subscription */
const char
*share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_subscribe_property_config_t;
/**
* MQTT5 protocol unsubscribe properties configuration, more details refer to MQTT5 protocol document section 3.10.2.1
*/
typedef struct {
bool is_share_subscribe; /*!< Whether subscribe is a shared subscription */
const char
*share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_unsubscribe_property_config_t;
/**
* MQTT5 protocol disconnect properties configuration, more details refer to MQTT5 protocol document section 3.14.2.2
*/
typedef struct {
uint32_t session_expiry_interval; /*!< The interval time of session expiry */
uint8_t disconnect_reason; /*!< The reason that connection disconnect, refer to mqtt5_error_reason_code */
mqtt5_user_property_handle_t
user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_disconnect_property_config_t;
/**
* MQTT5 server response properties from CONNACK (section 3.2.2.3)
*
@@ -194,14 +138,6 @@ typedef struct {
esp_mqtt5_server_resp_property_t server; /*!< Server response properties from CONNACK (valid only in MQTT_EVENT_CONNECTED) */
} esp_mqtt5_event_property_t;
/**
* MQTT5 protocol for user property
*/
typedef struct {
const char *key; /*!< Item key name */
const char *value; /*!< Item value string */
} esp_mqtt5_user_property_item_t;
/**
* @brief Set MQTT5 client connect property configuration
*
+1 -23
View File
@@ -18,6 +18,7 @@
#include "esp_err.h"
#include "esp_event.h"
#include "esp_transport.h"
#include "mqtt_common.h"
#ifdef CONFIG_MQTT_PROTOCOL_5
#include "mqtt5_client.h"
#endif
@@ -28,11 +29,6 @@ extern "C" {
typedef struct esp_mqtt_client *esp_mqtt_client_handle_t;
#define MQTT_OVER_TCP_SCHEME "mqtt"
#define MQTT_OVER_SSL_SCHEME "mqtts"
#define MQTT_OVER_WS_SCHEME "ws"
#define MQTT_OVER_WSS_SCHEME "wss"
/**
* @brief *MQTT* event types.
*
@@ -152,16 +148,6 @@ typedef enum esp_mqtt_transport_t {
``wss`` */
} esp_mqtt_transport_t;
/**
* *MQTT* protocol version used for connection
*/
typedef enum esp_mqtt_protocol_ver_t {
MQTT_PROTOCOL_UNDEFINED = 0,
MQTT_PROTOCOL_V_3_1,
MQTT_PROTOCOL_V_3_1_1,
MQTT_PROTOCOL_V_5,
} esp_mqtt_protocol_ver_t;
/**
* States of MQTT client connection
*/
@@ -408,14 +394,6 @@ typedef struct esp_mqtt_client_config_t {
} outbox; /*!< Outbox configuration. */
} esp_mqtt_client_config_t;
/**
* Topic definition struct
*/
typedef struct topic_t {
const char *filter; /*!< Topic filter to subscribe */
int qos; /*!< Max QoS level of the subscription */
} esp_mqtt_topic_t;
/**
* @brief Creates *MQTT* client handle based on the configuration
*
+99
View File
@@ -0,0 +1,99 @@
/*
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MQTT_OVER_TCP_SCHEME "mqtt"
#define MQTT_OVER_SSL_SCHEME "mqtts"
#define MQTT_OVER_WS_SCHEME "ws"
#define MQTT_OVER_WSS_SCHEME "wss"
/**
* *MQTT* protocol version used for connection
*/
typedef enum esp_mqtt_protocol_ver_t {
MQTT_PROTOCOL_UNDEFINED = 0,
MQTT_PROTOCOL_V_3_1,
MQTT_PROTOCOL_V_3_1_1,
MQTT_PROTOCOL_V_5,
} esp_mqtt_protocol_ver_t;
/**
* Topic definition struct
*/
typedef struct topic_t {
const char *filter; /*!< Topic filter to subscribe */
int qos; /*!< Max QoS level of the subscription */
} esp_mqtt_topic_t;
/**
* MQTT5 user property handle
*/
typedef struct mqtt5_user_property_list_t *mqtt5_user_property_handle_t;
/**
* MQTT5 protocol for user property
*/
typedef struct {
const char *key; /*!< Item key name */
const char *value; /*!< Item value string */
} esp_mqtt5_user_property_item_t;
/**
* MQTT5 protocol publish properties configuration, more details refer to MQTT5 protocol document section 3.3.2.3
*/
typedef struct {
bool payload_format_indicator; /*!< This value is to indicator publish message payload format */
uint32_t message_expiry_interval; /*!< The time interval that message expiry */
uint16_t topic_alias; /*!< An integer value to identify the topic instead of using topic name string */
const char *response_topic; /*!< Topic name for a response message */
const char *correlation_data; /*!< Binary data for receiver to match the response message */
uint16_t correlation_data_len; /*!< The length of correlation data */
const char *content_type; /*!< This value is to indicator publish message content type, use a MIME content type string */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_publish_property_config_t;
/**
* MQTT5 protocol subscribe properties configuration, more details refer to MQTT5 protocol document section 3.8.2.1
*/
typedef struct {
uint16_t subscribe_id; /*!< A variable byte represents the identifier of the subscription */
bool no_local_flag; /*!< Subscription Option to allow that server publish message that client sent */
bool retain_as_published_flag; /*!< Subscription Option to keep the retain flag as published option */
uint8_t retain_handle; /*!< Subscription Option to handle retain option */
bool is_share_subscribe; /*!< Whether subscribe is a shared subscription */
const char *share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_subscribe_property_config_t;
/**
* MQTT5 protocol disconnect properties configuration, more details refer to MQTT5 protocol document section 3.14.2.2
*/
typedef struct {
uint32_t session_expiry_interval; /*!< The interval time of session expiry */
uint8_t disconnect_reason; /*!< The reason that connection disconnect, refer to mqtt5_error_reason_code */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_disconnect_property_config_t;
/**
* MQTT5 protocol unsubscribe properties configuration, more details refer to MQTT5 protocol document section 3.10.2.1
*/
typedef struct {
bool is_share_subscribe; /*!< Whether subscribe is a shared subscription */
const char *share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_unsubscribe_property_config_t;
#ifdef __cplusplus
}
#endif
-7
View File
@@ -16,13 +16,6 @@
extern "C" {
#endif
typedef struct mqtt5_topic_alias {
char *topic;
uint16_t topic_len;
uint16_t topic_alias;
STAILQ_ENTRY(mqtt5_topic_alias) next;
} mqtt5_topic_alias_t;
STAILQ_HEAD(mqtt5_topic_alias_list_t, mqtt5_topic_alias);
typedef struct mqtt5_topic_alias_list_t *mqtt5_topic_alias_handle_t;
typedef struct mqtt5_topic_alias *mqtt5_topic_alias_item_t;
+11 -9
View File
@@ -7,10 +7,8 @@
#define MQTT5_MSG_H
#include <stdint.h>
#include <stdbool.h>
#include "sys/queue.h"
#include "mqtt_config.h"
#include "mqtt_msg.h"
#include "mqtt_client.h"
#include "mqtt_common.h"
#ifdef __cplusplus
extern "C" {
#endif
@@ -45,12 +43,6 @@ enum mqtt_properties_type {
MQTT5_PROPERTY_SHARED_SUBSCR_AVAILABLE = 0x2A,
};
typedef struct mqtt5_user_property {
char *key;
char *value;
STAILQ_ENTRY(mqtt5_user_property) next;
} mqtt5_user_property_t;
STAILQ_HEAD(mqtt5_user_property_list_t, mqtt5_user_property);
typedef struct mqtt5_user_property *mqtt5_user_property_item_t;
typedef struct {
@@ -141,6 +133,16 @@ mqtt_message_t *mqtt5_msg_pubrel(mqtt_message_t *message, uint16_t message_id);
mqtt_message_t *mqtt5_msg_pubrec(mqtt_message_t *message, uint16_t message_id);
mqtt_message_t *mqtt5_msg_puback(mqtt_message_t *message, uint16_t message_id);
mqtt5_user_property_handle_t mqtt5_msg_create_user_property_list(void);
esp_err_t mqtt5_msg_set_user_property(mqtt5_user_property_handle_t *user_property_list, const char *key, size_t key_len,
const char *value, size_t value_len);
void mqtt5_msg_delete_user_property(mqtt5_user_property_handle_t user_property_list);
esp_err_t mqtt5_msg_get_user_property(mqtt5_user_property_handle_t user_property_list,
esp_mqtt5_user_property_item_t *item, uint8_t *item_num);
uint8_t mqtt5_msg_get_user_property_count(mqtt5_user_property_handle_t user_property_list);
esp_err_t mqtt5_msg_copy_user_property(mqtt5_user_property_handle_t user_property_new,
const struct mqtt5_user_property_list_t *user_property_old);
#ifdef __cplusplus
}
#endif
+1
View File
@@ -15,6 +15,7 @@
#include "platform.h"
#include "esp_event.h"
#include "mqtt_config.h"
#include "mqtt_client.h"
#include "mqtt_msg.h"
#ifdef MQTT_PROTOCOL_5
+3 -2
View File
@@ -8,9 +8,10 @@
#define MQTT_MSG_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "esp_err.h"
#include "mqtt_common.h"
#include "mqtt_config.h"
#include "mqtt_client.h"
#ifdef __cplusplus
extern "C" {
#endif
+137 -33
View File
@@ -5,11 +5,11 @@
*/
#include <string.h>
#include "mqtt5_msg.h"
#include "mqtt_client.h"
#include "mqtt_config.h"
#include "esp_err.h"
#include "mqtt_common.h"
#include "platform.h"
#include "esp_log.h"
#include "mqtt_client_priv.h"
#include "sys/queue.h"
#define MQTT5_MAX_FIXED_HEADER_SIZE 5
#define MQTT5_MAX_PROPERTY_STRING_LEN (16 * 1024)
@@ -32,6 +32,13 @@ static const char *TAG = "mqtt5_msg";
#define MQTT5_CONVERT_TWO_BYTE(i, a) i = (a >> 8) & 0xff; \
i = a & 0xff;
typedef struct mqtt5_user_property {
char *key;
char *value;
STAILQ_ENTRY(mqtt5_user_property) next;
} mqtt5_user_property_t;
STAILQ_HEAD(mqtt5_user_property_list_t, mqtt5_user_property);
enum mqtt5_connect_flag {
MQTT5_CONNECT_FLAG_USERNAME = 1 << 7,
MQTT5_CONNECT_FLAG_PASSWORD = 1 << 6,
@@ -234,13 +241,12 @@ static mqtt_message_t *fini_message(mqtt_message_t *message, int type, int dup,
return message;
}
static esp_err_t mqtt5_msg_set_user_property(mqtt5_user_property_handle_t *user_property, char *key, size_t key_len,
char *value, size_t value_len)
esp_err_t mqtt5_msg_set_user_property(mqtt5_user_property_handle_t *user_property_list, const char *key, size_t key_len,
const char *value, size_t value_len)
{
if (!*user_property) {
*user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, *user_property, return ESP_FAIL);
STAILQ_INIT(*user_property);
if (!*user_property_list) {
*user_property_list = mqtt5_msg_create_user_property_list();
ESP_MEM_CHECK(TAG, *user_property_list, return ESP_FAIL);
}
mqtt5_user_property_item_t user_property_item = calloc(1, sizeof(mqtt5_user_property_t));
@@ -260,13 +266,13 @@ static esp_err_t mqtt5_msg_set_user_property(mqtt5_user_property_handle_t *user_
});
memcpy(user_property_item->value, value, value_len);
user_property_item->value[value_len] = '\0';
STAILQ_INSERT_TAIL(*user_property, user_property_item, next);
STAILQ_INSERT_TAIL(*user_property_list, user_property_item, next);
return ESP_OK;
}
static mqtt5_user_property_handle_t mqtt5_msg_get_user_property(uint8_t *buffer, size_t buffer_length)
static mqtt5_user_property_handle_t mqtt5_msg_parse_user_property(uint8_t *buffer, size_t buffer_length)
{
mqtt5_user_property_handle_t user_porperty = NULL;
mqtt5_user_property_handle_t user_property = NULL;
uint8_t *property = buffer;
uint16_t property_offset = 0, len = 0;
@@ -327,8 +333,7 @@ static mqtt5_user_property_handle_t mqtt5_msg_get_user_property(uint8_t *buffer,
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
if (mqtt5_msg_set_user_property(&user_porperty, (char *)key, key_len, (char *)value, value_len) != ESP_OK) {
#pragma GCC diagnostic pop
if (mqtt5_msg_set_user_property(&user_property, (char *)key, key_len, (char *)value, value_len) != ESP_OK) {
ESP_LOGE(TAG, "mqtt5_msg_set_user_property fail");
goto err;
}
@@ -342,9 +347,9 @@ static mqtt5_user_property_handle_t mqtt5_msg_get_user_property(uint8_t *buffer,
}
}
return user_porperty;
return user_property;
err:
esp_mqtt5_client_delete_user_property(user_porperty);
mqtt5_msg_delete_user_property(user_property);
return NULL;
}
@@ -562,7 +567,7 @@ char *mqtt5_get_publish_property_payload(uint8_t *buffer, size_t buffer_length,
property_offset += len;
if (mqtt5_msg_set_user_property(user_property, (char *)key, key_len, (char *)value, value_len) != ESP_OK) {
esp_mqtt5_client_delete_user_property(*user_property);
mqtt5_msg_delete_user_property(*user_property);
*user_property = NULL;
ESP_LOGE(TAG, "mqtt5_msg_set_user_property fail");
return NULL;
@@ -613,7 +618,7 @@ char *mqtt5_get_suback_data(uint8_t *buffer, size_t *length, mqtt5_user_property
if (*user_property) {
ESP_LOGE(TAG, "user_property not freed before mqtt5_get_suback_data");
esp_mqtt5_client_delete_user_property(*user_property);
mqtt5_msg_delete_user_property(*user_property);
*user_property = NULL;
}
@@ -637,16 +642,11 @@ char *mqtt5_get_suback_data(uint8_t *buffer, size_t *length, mqtt5_user_property
return NULL;
}
/* False positive: the previous *user_property value is freed above if non-NULL.
* The analyzer cannot track the deallocation across the TU boundary. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
*user_property = mqtt5_msg_get_user_property(buffer + offset, property_len);
#pragma GCC diagnostic pop
*user_property = mqtt5_msg_parse_user_property(buffer + offset, property_len);
offset += property_len;
if (offset >= totlen) {
esp_mqtt5_client_delete_user_property(*user_property);
mqtt5_msg_delete_user_property(*user_property);
*user_property = NULL;
*length = 0;
return NULL;
@@ -667,7 +667,7 @@ char *mqtt5_get_puback_data(uint8_t *buffer, size_t *length, mqtt5_user_property
if (*user_property) {
ESP_LOGE(TAG, "user_property not freed before mqtt5_get_puback_data");
esp_mqtt5_client_delete_user_property(*user_property);
mqtt5_msg_delete_user_property(*user_property);
*user_property = NULL;
}
@@ -689,12 +689,7 @@ char *mqtt5_get_puback_data(uint8_t *buffer, size_t *length, mqtt5_user_property
return NULL;
}
/* False positive: the previous *user_property value is freed above if non-NULL.
* The analyzer cannot track the deallocation across the TU boundary. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
*user_property = mqtt5_msg_get_user_property(buffer + offset, property_len);
#pragma GCC diagnostic pop
*user_property = mqtt5_msg_parse_user_property(buffer + offset, property_len);
}
return data;
@@ -1006,7 +1001,7 @@ esp_err_t mqtt5_msg_parse_connack_property(uint8_t *buffer, size_t buffer_len, m
property_offset += len;
if (mqtt5_msg_set_user_property(user_property, (char *)key, key_len, (char *)value, value_len) != ESP_OK) {
esp_mqtt5_client_delete_user_property(*user_property);
mqtt5_msg_delete_user_property(*user_property);
*user_property = NULL;
ESP_LOGE(TAG, "mqtt5_msg_set_user_property fail");
return ESP_FAIL;
@@ -1543,3 +1538,112 @@ mqtt_message_t *mqtt5_msg_pubcomp(mqtt_message_t *message, uint16_t message_id)
properties_offset), fail_message(message));
return fini_message(message, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0);
}
void mqtt5_msg_delete_user_property(mqtt5_user_property_handle_t user_property_list)
{
if (user_property_list) {
mqtt5_user_property_item_t item;
mqtt5_user_property_item_t tmp;
STAILQ_FOREACH_SAFE(item, user_property_list, next, tmp) {
STAILQ_REMOVE(user_property_list, item, mqtt5_user_property, next);
free(item->key);
free(item->value);
free(item);
}
}
free(user_property_list);
}
mqtt5_user_property_handle_t mqtt5_msg_create_user_property_list(void)
{
mqtt5_user_property_handle_t user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, user_property, return NULL);
STAILQ_INIT(user_property);
return user_property;
}
uint8_t mqtt5_msg_get_user_property_count(mqtt5_user_property_handle_t user_property_list)
{
uint8_t count = 0;
mqtt5_user_property_item_t item;
STAILQ_FOREACH(item, user_property_list, next) {
count ++;
}
return count;
}
static void mqtt5_msg_free_user_property_result(esp_mqtt5_user_property_item_t *item)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
free((void *)item->key);
free((void *)item->value);
#pragma GCC diagnostic pop
item->key = NULL;
item->value = NULL;
}
esp_err_t mqtt5_msg_get_user_property(mqtt5_user_property_handle_t user_property_list,
esp_mqtt5_user_property_item_t *item, uint8_t *item_num)
{
int property_item_idx = 0;
int j = 0;
mqtt5_user_property_item_t user_property_item;
uint8_t num = *item_num;
STAILQ_FOREACH(user_property_item, user_property_list, next) {
if (property_item_idx < num) {
size_t item_key_len = strlen(user_property_item->key);
size_t item_value_len = strlen(user_property_item->value);
char *key = calloc(1, item_key_len + 1);
ESP_MEM_CHECK(TAG, key, goto err);
memcpy(key, user_property_item->key, item_key_len);
key[item_key_len] = '\0';
char *value = calloc(1, item_value_len + 1);
ESP_MEM_CHECK(TAG, value, {
free(key);
goto err;
});
memcpy(value, user_property_item->value, item_value_len);
value[item_value_len] = '\0';
item[property_item_idx].key = key;
item[property_item_idx].value = value;
property_item_idx ++;
} else {
break;
}
}
*item_num = property_item_idx;
return ESP_OK;
err:
for (j = 0; j < property_item_idx; j ++) {
mqtt5_msg_free_user_property_result(&item[j]);
}
return ESP_ERR_NO_MEM;
}
esp_err_t mqtt5_msg_copy_user_property(mqtt5_user_property_handle_t user_property_new,
const struct mqtt5_user_property_list_t *user_property_old)
{
mqtt5_user_property_item_t old_item;
mqtt5_user_property_item_t new_item;
STAILQ_FOREACH(old_item, user_property_old, next) {
new_item = calloc(1, sizeof(mqtt5_user_property_t));
ESP_MEM_CHECK(TAG, new_item, return ESP_FAIL);
new_item->key = strdup(old_item->key);
ESP_MEM_CHECK(TAG, new_item->key, {
free(new_item);
return ESP_FAIL;
});
new_item->value = strdup(old_item->value);
ESP_MEM_CHECK(TAG, new_item->value, {
free(new_item->key);
free(new_item);
return ESP_FAIL;
});
STAILQ_INSERT_TAIL(user_property_new, new_item, next);
}
return ESP_OK;
}
-1
View File
@@ -5,7 +5,6 @@
*/
#include <string.h>
#include "esp_heap_caps.h"
#include "mqtt_client.h"
#include "mqtt_msg.h"
#include "mqtt_config.h"
#include "platform.h"
+35 -130
View File
@@ -4,15 +4,29 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_err.h"
#include "mqtt_config.h"
#include "mqtt_client.h"
#include "mqtt_client_priv.h"
#include "mqtt5_client.h"
#include "mqtt5_msg.h"
#include "esp_log.h"
#include <string.h>
#include <sys/queue.h>
static const char *TAG = "mqtt5_client";
// Receive Maximum is optional in CONNACK; when absent the limit is 65535
#define MQTT5_DEFAULT_RECEIVE_MAXIMUM 65535
typedef struct mqtt5_topic_alias {
char *topic;
uint16_t topic_len;
uint16_t topic_alias;
STAILQ_ENTRY(mqtt5_topic_alias) next;
} mqtt5_topic_alias_t;
STAILQ_HEAD(mqtt5_topic_alias_list_t, mqtt5_topic_alias);
static void esp_mqtt5_print_error_code(esp_mqtt5_client_handle_t client, int code);
static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle,
uint16_t topic_alias, char *topic, size_t topic_len);
@@ -505,25 +519,7 @@ static esp_err_t esp_mqtt5_user_property_copy(mqtt5_user_property_handle_t user_
ESP_LOGE(TAG, "Input is NULL");
return ESP_FAIL;
}
mqtt5_user_property_item_t old_item, new_item;
STAILQ_FOREACH(old_item, user_property_old, next) {
new_item = calloc(1, sizeof(mqtt5_user_property_t));
ESP_MEM_CHECK(TAG, new_item, return ESP_FAIL);
new_item->key = strdup(old_item->key);
ESP_MEM_CHECK(TAG, new_item->key, {
free(new_item);
return ESP_FAIL;
});
new_item->value = strdup(old_item->value);
ESP_MEM_CHECK(TAG, new_item->value, {
free(new_item->key);
free(new_item);
return ESP_FAIL;
});
STAILQ_INSERT_TAIL(user_property_new, new_item, next);
}
return ESP_OK;
return mqtt5_msg_copy_user_property(user_property_new, user_property_old);
}
esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client,
@@ -688,17 +684,11 @@ esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t cli
if (property->user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->disconnect_property_info.user_property);
/* False positive: the allocation remains owned by disconnect_property_info
* until it is replaced or the MQTT 5 configuration is destroyed. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
client->mqtt5_config->disconnect_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
client->mqtt5_config->disconnect_property_info.user_property = mqtt5_msg_create_user_property_list();
ESP_MEM_CHECK(TAG, client->mqtt5_config->disconnect_property_info.user_property, {
MQTT_API_UNLOCK(client);
return ESP_ERR_NO_MEM;
});
#pragma GCC diagnostic pop
STAILQ_INIT(client->mqtt5_config->disconnect_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->disconnect_property_info.user_property,
property->user_property) != ESP_OK) {
@@ -772,9 +762,8 @@ esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client
if (connect_property->user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->connect_property_info.user_property);
client->mqtt5_config->connect_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
client->mqtt5_config->connect_property_info.user_property = mqtt5_msg_create_user_property_list();
ESP_MEM_CHECK(TAG, client->mqtt5_config->connect_property_info.user_property, goto _mqtt_set_config_failed);
STAILQ_INIT(client->mqtt5_config->connect_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->connect_property_info.user_property,
connect_property->user_property) != ESP_OK) {
@@ -817,14 +806,8 @@ esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client
if (connect_property->will_user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->will_property_info.user_property);
/* False positive: esp_mqtt_destroy_config() releases this allocation on failure,
* but the analyzer cannot follow that cleanup across the translation-unit boundary. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
client->mqtt5_config->will_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
client->mqtt5_config->will_property_info.user_property = mqtt5_msg_create_user_property_list();
ESP_MEM_CHECK(TAG, client->mqtt5_config->will_property_info.user_property, goto _mqtt_set_config_failed);
#pragma GCC diagnostic pop
STAILQ_INIT(client->mqtt5_config->will_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->will_property_info.user_property,
connect_property->will_user_property) != ESP_OK) {
@@ -842,7 +825,7 @@ _mqtt_set_config_failed:
return ESP_ERR_NO_MEM;
}
esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_property,
esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_property_list,
esp_mqtt5_user_property_item_t item[], uint8_t item_num)
{
if (!item_num || !item) {
@@ -850,124 +833,46 @@ esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_
return ESP_FAIL;
}
if (!*user_property) {
*user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, *user_property, return ESP_ERR_NO_MEM);
STAILQ_INIT(*user_property);
}
for (int i = 0; i < item_num; i ++) {
if (item[i].key && item[i].value) {
mqtt5_user_property_item_t user_property_item = calloc(1, sizeof(mqtt5_user_property_t));
ESP_MEM_CHECK(TAG, user_property_item, goto err);
size_t key_len = strlen(item[i].key);
size_t value_len = strlen(item[i].value);
user_property_item->key = calloc(1, key_len + 1);
ESP_MEM_CHECK(TAG, user_property_item->key, {
free(user_property_item);
goto err;
});
memcpy(user_property_item->key, item[i].key, key_len);
user_property_item->key[key_len] = '\0';
user_property_item->value = calloc(1, value_len + 1);
ESP_MEM_CHECK(TAG, user_property_item->value, {
free(user_property_item->key);
free(user_property_item);
goto err;
});
memcpy(user_property_item->value, item[i].value, value_len);
user_property_item->value[value_len] = '\0';
STAILQ_INSERT_TAIL(*user_property, user_property_item, next);
esp_err_t ret = mqtt5_msg_set_user_property(user_property_list, item[i].key, key_len, item[i].value,
value_len);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set user property");
esp_mqtt5_client_delete_user_property(*user_property_list);
*user_property_list = NULL;
return ret;
}
}
}
return ESP_OK;
err:
esp_mqtt5_client_delete_user_property(*user_property);
*user_property = NULL;
return ESP_ERR_NO_MEM;
}
esp_err_t esp_mqtt5_client_get_user_property(mqtt5_user_property_handle_t user_property,
esp_mqtt5_user_property_item_t *item, uint8_t *item_num)
{
int i = 0, j = 0;
if (user_property && item && *item_num) {
mqtt5_user_property_item_t user_property_item;
uint8_t num = *item_num;
STAILQ_FOREACH(user_property_item, user_property, next) {
if (i < num) {
size_t item_key_len = strlen(user_property_item->key);
size_t item_value_len = strlen(user_property_item->value);
char *key = calloc(1, item_key_len + 1);
ESP_MEM_CHECK(TAG, key, goto err);
memcpy(key, user_property_item->key, item_key_len);
key[item_key_len] = '\0';
char *value = calloc(1, item_value_len + 1);
ESP_MEM_CHECK(TAG, value, {
free(key);
goto err;
});
memcpy(value, user_property_item->value, item_value_len);
value[item_value_len] = '\0';
item[i].key = key;
item[i].value = value;
i ++;
} else {
break;
}
}
*item_num = i;
return ESP_OK;
} else {
if (!user_property || !item || !item_num || !*item_num) {
ESP_LOGE(TAG, "Input value is NULL or item_num is 0");
return ESP_FAIL;
}
err:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
for (j = 0; j < i; j ++) {
if (item[j].key) {
free((char *)item[j].key);
}
if (item[j].value) {
free((char *)item[j].value);
}
}
#pragma GCC diagnostic pop
return ESP_ERR_NO_MEM;
return mqtt5_msg_get_user_property(user_property, item, item_num);
}
uint8_t esp_mqtt5_client_get_user_property_count(mqtt5_user_property_handle_t user_property)
{
uint8_t count = 0;
if (user_property) {
mqtt5_user_property_item_t item;
STAILQ_FOREACH(item, user_property, next) {
count ++;
}
if (!user_property) {
return 0;
}
return count;
return mqtt5_msg_get_user_property_count(user_property);
}
void esp_mqtt5_client_delete_user_property(mqtt5_user_property_handle_t user_property)
void esp_mqtt5_client_delete_user_property(mqtt5_user_property_handle_t user_property_list)
{
if (user_property) {
mqtt5_user_property_item_t item, tmp;
STAILQ_FOREACH_SAFE(item, user_property, next, tmp) {
STAILQ_REMOVE(user_property, item, mqtt5_user_property, next);
free(item->key);
free(item->value);
free(item);
}
}
free(user_property);
mqtt5_msg_delete_user_property(user_property_list);
}
+1
View File
@@ -10,6 +10,7 @@
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "esp_transport.h"
#include "mqtt_config.h"
#include "mqtt_client.h"
#include "mqtt_client_priv.h"
#include "mqtt_msg.h"