net: mqtt: Add MQTT 5.0 support for SUBSCRIBE/UNSUBSCRIBE
Add support for SUBSCRIBE/UNSUBSCRIBE messages specified in MQTT 5.0. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
c21e64251b
commit
efd795b066
5 changed files with 149 additions and 8 deletions
|
@ -493,7 +493,7 @@ struct mqtt_publish_param {
|
||||||
#endif /* CONFIG_MQTT_VERSION_5_0 */
|
#endif /* CONFIG_MQTT_VERSION_5_0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief List of topics in a subscription request. */
|
/** @brief Parameters for subscribe/unsubscribe message. */
|
||||||
struct mqtt_subscription_list {
|
struct mqtt_subscription_list {
|
||||||
/** Array containing topics along with QoS for each. */
|
/** Array containing topics along with QoS for each. */
|
||||||
struct mqtt_topic *list;
|
struct mqtt_topic *list;
|
||||||
|
@ -503,6 +503,19 @@ struct mqtt_subscription_list {
|
||||||
|
|
||||||
/** Message id used to identify subscription request. */
|
/** Message id used to identify subscription request. */
|
||||||
uint16_t message_id;
|
uint16_t message_id;
|
||||||
|
|
||||||
|
#if defined(CONFIG_MQTT_VERSION_5_0)
|
||||||
|
/** MQTT 5.0 properties. */
|
||||||
|
struct {
|
||||||
|
/** MQTT 5.0, chapter 3.8.2.1.3 / 3.10.2.1.2 User Property. */
|
||||||
|
struct mqtt_utf8_pair user_prop[CONFIG_MQTT_USER_PROPERTIES_MAX];
|
||||||
|
|
||||||
|
/** MQTT 5.0, chapter 3.8.2.1.2 Subscription Identifier.
|
||||||
|
* Ignored for UNSUBSCRIBE requests.
|
||||||
|
*/
|
||||||
|
uint32_t subscription_identifier;
|
||||||
|
} prop;
|
||||||
|
#endif /* CONFIG_MQTT_VERSION_5_0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -495,7 +495,7 @@ int mqtt_subscribe(struct mqtt_client *client,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code = subscribe_encode(param, &packet);
|
err_code = subscribe_encode(client, param, &packet);
|
||||||
if (err_code < 0) {
|
if (err_code < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -529,7 +529,7 @@ int mqtt_unsubscribe(struct mqtt_client *client,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code = unsubscribe_encode(param, &packet);
|
err_code = unsubscribe_encode(client, param, &packet);
|
||||||
if (err_code < 0) {
|
if (err_code < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -383,6 +383,32 @@ static int encode_uint32_property(uint8_t prop, uint32_t value,
|
||||||
return pack_uint32(value, buf);
|
return pack_uint32(value, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t var_int_property_length(uint32_t value)
|
||||||
|
{
|
||||||
|
if (value == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sizeof(uint8_t) + (size_t)pack_variable_int(value, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int encode_var_int_property(uint8_t prop, uint32_t value,
|
||||||
|
struct buf_ctx *buf)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (value == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pack_uint8(prop, buf);
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pack_variable_int(value, buf);
|
||||||
|
}
|
||||||
|
|
||||||
static size_t string_property_length(const struct mqtt_utf8 *str)
|
static size_t string_property_length(const struct mqtt_utf8 *str)
|
||||||
{
|
{
|
||||||
if (str->size == 0) {
|
if (str->size == 0) {
|
||||||
|
@ -1164,7 +1190,54 @@ int disconnect_encode(struct buf_ctx *buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int subscribe_encode(const struct mqtt_subscription_list *param,
|
#if defined(CONFIG_MQTT_VERSION_5_0)
|
||||||
|
static uint32_t subscribe_properties_length(
|
||||||
|
const struct mqtt_subscription_list *param)
|
||||||
|
{
|
||||||
|
return var_int_property_length(param->prop.subscription_identifier) +
|
||||||
|
user_properties_length(param->prop.user_prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int subscribe_properties_encode(const struct mqtt_subscription_list *param,
|
||||||
|
struct buf_ctx *buf)
|
||||||
|
{
|
||||||
|
uint32_t properties_len;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Precalculate total properties length */
|
||||||
|
properties_len = subscribe_properties_length(param);
|
||||||
|
err = pack_variable_int(properties_len, buf);
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = encode_var_int_property(MQTT_PROP_SUBSCRIPTION_IDENTIFIER,
|
||||||
|
param->prop.subscription_identifier,
|
||||||
|
buf);
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = encode_user_properties(param->prop.user_prop, buf);
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int subscribe_properties_encode(const struct mqtt_subscription_list *param,
|
||||||
|
struct buf_ctx *buf)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(param);
|
||||||
|
ARG_UNUSED(buf);
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MQTT_VERSION_5_0 */
|
||||||
|
|
||||||
|
int subscribe_encode(const struct mqtt_client *client,
|
||||||
|
const struct mqtt_subscription_list *param,
|
||||||
struct buf_ctx *buf)
|
struct buf_ctx *buf)
|
||||||
{
|
{
|
||||||
const uint8_t message_type = MQTT_MESSAGES_OPTIONS(
|
const uint8_t message_type = MQTT_MESSAGES_OPTIONS(
|
||||||
|
@ -1186,6 +1259,13 @@ int subscribe_encode(const struct mqtt_subscription_list *param,
|
||||||
return err_code;
|
return err_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mqtt_is_version_5_0(client)) {
|
||||||
|
err_code = subscribe_properties_encode(param, buf);
|
||||||
|
if (err_code != 0) {
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < param->list_count; i++) {
|
for (i = 0; i < param->list_count; i++) {
|
||||||
err_code = pack_utf8_str(¶m->list[i].topic, buf);
|
err_code = pack_utf8_str(¶m->list[i].topic, buf);
|
||||||
if (err_code != 0) {
|
if (err_code != 0) {
|
||||||
|
@ -1201,7 +1281,46 @@ int subscribe_encode(const struct mqtt_subscription_list *param,
|
||||||
return mqtt_encode_fixed_header(message_type, start, buf);
|
return mqtt_encode_fixed_header(message_type, start, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int unsubscribe_encode(const struct mqtt_subscription_list *param,
|
#if defined(CONFIG_MQTT_VERSION_5_0)
|
||||||
|
static uint32_t unsubscribe_properties_length(
|
||||||
|
const struct mqtt_subscription_list *param)
|
||||||
|
{
|
||||||
|
return user_properties_length(param->prop.user_prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int unsubscribe_properties_encode(
|
||||||
|
const struct mqtt_subscription_list *param, struct buf_ctx *buf)
|
||||||
|
{
|
||||||
|
uint32_t properties_len;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Precalculate total properties length */
|
||||||
|
properties_len = unsubscribe_properties_length(param);
|
||||||
|
err = pack_variable_int(properties_len, buf);
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = encode_user_properties(param->prop.user_prop, buf);
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int unsubscribe_properties_encode(
|
||||||
|
const struct mqtt_subscription_list *param, struct buf_ctx *buf)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(param);
|
||||||
|
ARG_UNUSED(buf);
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MQTT_VERSION_5_0 */
|
||||||
|
|
||||||
|
int unsubscribe_encode(const struct mqtt_client *client,
|
||||||
|
const struct mqtt_subscription_list *param,
|
||||||
struct buf_ctx *buf)
|
struct buf_ctx *buf)
|
||||||
{
|
{
|
||||||
const uint8_t message_type = MQTT_MESSAGES_OPTIONS(
|
const uint8_t message_type = MQTT_MESSAGES_OPTIONS(
|
||||||
|
@ -1218,6 +1337,13 @@ int unsubscribe_encode(const struct mqtt_subscription_list *param,
|
||||||
return err_code;
|
return err_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mqtt_is_version_5_0(client)) {
|
||||||
|
err_code = unsubscribe_properties_encode(param, buf);
|
||||||
|
if (err_code != 0) {
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < param->list_count; i++) {
|
for (i = 0; i < param->list_count; i++) {
|
||||||
err_code = pack_utf8_str(¶m->list[i].topic, buf);
|
err_code = pack_utf8_str(¶m->list[i].topic, buf);
|
||||||
if (err_code != 0) {
|
if (err_code != 0) {
|
||||||
|
|
|
@ -305,7 +305,8 @@ int disconnect_encode(struct buf_ctx *buf);
|
||||||
*
|
*
|
||||||
* @return 0 if the procedure is successful, an error code otherwise.
|
* @return 0 if the procedure is successful, an error code otherwise.
|
||||||
*/
|
*/
|
||||||
int subscribe_encode(const struct mqtt_subscription_list *param,
|
int subscribe_encode(const struct mqtt_client *client,
|
||||||
|
const struct mqtt_subscription_list *param,
|
||||||
struct buf_ctx *buf);
|
struct buf_ctx *buf);
|
||||||
|
|
||||||
/**@brief Constructs/encodes Unsubscribe packet.
|
/**@brief Constructs/encodes Unsubscribe packet.
|
||||||
|
@ -318,7 +319,8 @@ int subscribe_encode(const struct mqtt_subscription_list *param,
|
||||||
*
|
*
|
||||||
* @return 0 if the procedure is successful, an error code otherwise.
|
* @return 0 if the procedure is successful, an error code otherwise.
|
||||||
*/
|
*/
|
||||||
int unsubscribe_encode(const struct mqtt_subscription_list *param,
|
int unsubscribe_encode(const struct mqtt_client *client,
|
||||||
|
const struct mqtt_subscription_list *param,
|
||||||
struct buf_ctx *buf);
|
struct buf_ctx *buf);
|
||||||
|
|
||||||
/**@brief Constructs/encodes Ping Request packet.
|
/**@brief Constructs/encodes Ping Request packet.
|
||||||
|
|
|
@ -846,7 +846,7 @@ static int eval_msg_subscribe(struct mqtt_test *mqtt_test)
|
||||||
buf.cur = client.tx_buf;
|
buf.cur = client.tx_buf;
|
||||||
buf.end = client.tx_buf + client.tx_buf_size;
|
buf.end = client.tx_buf + client.tx_buf_size;
|
||||||
|
|
||||||
rc = subscribe_encode(param, &buf);
|
rc = subscribe_encode(&client, param, &buf);
|
||||||
|
|
||||||
/**TESTPOINT: Check subscribe_encode function*/
|
/**TESTPOINT: Check subscribe_encode function*/
|
||||||
zassert_false(rc, "subscribe_encode failed");
|
zassert_false(rc, "subscribe_encode failed");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue