Skip to content

Commit 0276e28

Browse files
committed
[nrf fromtree] net: mqtt: Add MQTT 5.0 support for PUBLISH ACKs
Add support for PUBACK, PUBREC, PUBREL and PUBCOMP specified in MQTT 5.0. As all of these acknowledgment packets have similar format, introduced a common encoder/decoder to handle ACK packets. Signed-off-by: Robert Lubos <[email protected]> (cherry picked from commit c21e642)
1 parent 00d256e commit 0276e28

File tree

7 files changed

+357
-74
lines changed

7 files changed

+357
-74
lines changed

include/zephyr/net/mqtt.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,28 +334,77 @@ struct mqtt_connack_param {
334334
#endif /* CONFIG_MQTT_VERSION_5_0 */
335335
};
336336

337+
/** @brief Common MQTT 5.0 properties shared across all ack-type messages. */
338+
struct mqtt_common_ack_properties {
339+
/** MQTT 5.0, chapter 3.4.2.2.3 User Property. */
340+
struct mqtt_utf8_pair user_prop[CONFIG_MQTT_USER_PROPERTIES_MAX];
341+
342+
/** MQTT 5.0, chapter 3.4.2.2.2 Reason String. */
343+
struct mqtt_utf8 reason_string;
344+
345+
/** Flags indicating whether given property was present in received packet. */
346+
struct {
347+
/** Reason String property was present. */
348+
bool has_reason_string;
349+
/** User Property property was present. */
350+
bool has_user_prop;
351+
} rx;
352+
};
353+
337354
/** @brief Parameters for MQTT publish acknowledgment (PUBACK). */
338355
struct mqtt_puback_param {
339356
/** Message id of the PUBLISH message being acknowledged */
340357
uint16_t message_id;
358+
359+
#if defined(CONFIG_MQTT_VERSION_5_0)
360+
/** MQTT 5.0 reason code. */
361+
uint8_t reason_code;
362+
363+
/** MQTT 5.0 properties. */
364+
struct mqtt_common_ack_properties prop;
365+
#endif /* CONFIG_MQTT_VERSION_5_0 */
341366
};
342367

343368
/** @brief Parameters for MQTT publish receive (PUBREC). */
344369
struct mqtt_pubrec_param {
345370
/** Message id of the PUBLISH message being acknowledged */
346371
uint16_t message_id;
372+
373+
#if defined(CONFIG_MQTT_VERSION_5_0)
374+
/** MQTT 5.0 reason code. */
375+
uint8_t reason_code;
376+
377+
/** MQTT 5.0 properties. */
378+
struct mqtt_common_ack_properties prop;
379+
#endif /* CONFIG_MQTT_VERSION_5_0 */
347380
};
348381

349382
/** @brief Parameters for MQTT publish release (PUBREL). */
350383
struct mqtt_pubrel_param {
351384
/** Message id of the PUBREC message being acknowledged */
352385
uint16_t message_id;
386+
387+
#if defined(CONFIG_MQTT_VERSION_5_0)
388+
/** MQTT 5.0 reason code. */
389+
uint8_t reason_code;
390+
391+
/** MQTT 5.0 properties. */
392+
struct mqtt_common_ack_properties prop;
393+
#endif /* CONFIG_MQTT_VERSION_5_0 */
353394
};
354395

355396
/** @brief Parameters for MQTT publish complete (PUBCOMP). */
356397
struct mqtt_pubcomp_param {
357398
/** Message id of the PUBREL message being acknowledged */
358399
uint16_t message_id;
400+
401+
#if defined(CONFIG_MQTT_VERSION_5_0)
402+
/** MQTT 5.0 reason code. */
403+
uint8_t reason_code;
404+
405+
/** MQTT 5.0 properties. */
406+
struct mqtt_common_ack_properties prop;
407+
#endif /* CONFIG_MQTT_VERSION_5_0 */
359408
};
360409

361410
/** @brief Parameters for MQTT subscription acknowledgment (SUBACK). */

subsys/net/lib/mqtt/mqtt.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ int mqtt_publish_qos1_ack(struct mqtt_client *client,
309309
goto error;
310310
}
311311

312-
err_code = publish_ack_encode(param, &packet);
312+
err_code = publish_ack_encode(client, param, &packet);
313313
if (err_code < 0) {
314314
goto error;
315315
}
@@ -346,7 +346,7 @@ int mqtt_publish_qos2_receive(struct mqtt_client *client,
346346
goto error;
347347
}
348348

349-
err_code = publish_receive_encode(param, &packet);
349+
err_code = publish_receive_encode(client, param, &packet);
350350
if (err_code < 0) {
351351
goto error;
352352
}
@@ -383,7 +383,7 @@ int mqtt_publish_qos2_release(struct mqtt_client *client,
383383
goto error;
384384
}
385385

386-
err_code = publish_release_encode(param, &packet);
386+
err_code = publish_release_encode(client, param, &packet);
387387
if (err_code < 0) {
388388
goto error;
389389
}
@@ -420,7 +420,7 @@ int mqtt_publish_qos2_complete(struct mqtt_client *client,
420420
goto error;
421421
}
422422

423-
err_code = publish_complete_encode(param, &packet);
423+
err_code = publish_complete_encode(client, param, &packet);
424424
if (err_code < 0) {
425425
goto error;
426426
}

subsys/net/lib/mqtt/mqtt_decoder.c

Lines changed: 115 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -810,25 +810,132 @@ int publish_decode(const struct mqtt_client *client, uint8_t flags,
810810
return 0;
811811
}
812812

813-
int publish_ack_decode(struct buf_ctx *buf, struct mqtt_puback_param *param)
813+
#if defined(CONFIG_MQTT_VERSION_5_0)
814+
static int common_ack_properties_decode(struct buf_ctx *buf,
815+
struct mqtt_common_ack_properties *prop)
814816
{
815-
return unpack_uint16(buf, &param->message_id);
817+
struct property_decoder prop_dec[] = {
818+
{
819+
&prop->reason_string,
820+
&prop->rx.has_reason_string,
821+
MQTT_PROP_REASON_STRING
822+
},
823+
{
824+
&prop->user_prop,
825+
&prop->rx.has_user_prop,
826+
MQTT_PROP_USER_PROPERTY
827+
}
828+
};
829+
830+
return properties_decode(prop_dec, ARRAY_SIZE(prop_dec), buf);
831+
}
832+
#else
833+
static int common_ack_properties_decode(struct buf_ctx *buf,
834+
struct mqtt_common_ack_properties *prop)
835+
{
836+
ARG_UNUSED(prop);
837+
ARG_UNUSED(buf);
838+
839+
return -ENOTSUP;
816840
}
841+
#endif /* CONFIG_MQTT_VERSION_5_0 */
817842

818-
int publish_receive_decode(struct buf_ctx *buf, struct mqtt_pubrec_param *param)
843+
static int common_pub_ack_decode(struct buf_ctx *buf, uint16_t *message_id,
844+
uint8_t *reason_code,
845+
struct mqtt_common_ack_properties *prop)
819846
{
820-
return unpack_uint16(buf, &param->message_id);
847+
size_t remaining_len;
848+
int err;
849+
850+
err = unpack_uint16(buf, message_id);
851+
if (err < 0) {
852+
return err;
853+
}
854+
855+
remaining_len = buf->end - buf->cur;
856+
857+
/* For MQTT < 5.0 properties are NULL. */
858+
if (prop != NULL && reason_code != NULL) {
859+
if (remaining_len > 0) {
860+
err = unpack_uint8(buf, reason_code);
861+
if (err < 0) {
862+
return err;
863+
}
864+
}
865+
866+
if (remaining_len > 1) {
867+
err = common_ack_properties_decode(buf, prop);
868+
if (err < 0) {
869+
return err;
870+
}
871+
}
872+
}
873+
874+
return 0;
821875
}
822876

823-
int publish_release_decode(struct buf_ctx *buf, struct mqtt_pubrel_param *param)
877+
int publish_ack_decode(const struct mqtt_client *client, struct buf_ctx *buf,
878+
struct mqtt_puback_param *param)
824879
{
825-
return unpack_uint16(buf, &param->message_id);
880+
struct mqtt_common_ack_properties *prop = NULL;
881+
uint8_t *reason_code = NULL;
882+
883+
#if defined(CONFIG_MQTT_VERSION_5_0)
884+
if (mqtt_is_version_5_0(client)) {
885+
prop = &param->prop;
886+
reason_code = &param->reason_code;
887+
}
888+
#endif
889+
890+
return common_pub_ack_decode(buf, &param->message_id, reason_code, prop);
891+
}
892+
893+
int publish_receive_decode(const struct mqtt_client *client, struct buf_ctx *buf,
894+
struct mqtt_pubrec_param *param)
895+
{
896+
struct mqtt_common_ack_properties *prop = NULL;
897+
uint8_t *reason_code = NULL;
898+
899+
#if defined(CONFIG_MQTT_VERSION_5_0)
900+
if (mqtt_is_version_5_0(client)) {
901+
prop = &param->prop;
902+
reason_code = &param->reason_code;
903+
}
904+
#endif
905+
906+
return common_pub_ack_decode(buf, &param->message_id, reason_code, prop);
826907
}
827908

828-
int publish_complete_decode(struct buf_ctx *buf,
909+
int publish_release_decode(const struct mqtt_client *client, struct buf_ctx *buf,
910+
struct mqtt_pubrel_param *param)
911+
{
912+
struct mqtt_common_ack_properties *prop = NULL;
913+
uint8_t *reason_code = NULL;
914+
915+
#if defined(CONFIG_MQTT_VERSION_5_0)
916+
if (mqtt_is_version_5_0(client)) {
917+
prop = &param->prop;
918+
reason_code = &param->reason_code;
919+
}
920+
#endif
921+
922+
return common_pub_ack_decode(buf, &param->message_id, reason_code, prop);
923+
}
924+
925+
int publish_complete_decode(const struct mqtt_client *client, struct buf_ctx *buf,
829926
struct mqtt_pubcomp_param *param)
830927
{
831-
return unpack_uint16(buf, &param->message_id);
928+
struct mqtt_common_ack_properties *prop = NULL;
929+
uint8_t *reason_code = NULL;
930+
931+
#if defined(CONFIG_MQTT_VERSION_5_0)
932+
if (mqtt_is_version_5_0(client)) {
933+
prop = &param->prop;
934+
reason_code = &param->reason_code;
935+
}
936+
#endif
937+
938+
return common_ack_decode(buf, &param->message_id, reason_code, prop);
832939
}
833940

834941
int subscribe_ack_decode(struct buf_ctx *buf, struct mqtt_suback_param *param)

0 commit comments

Comments
 (0)