Skip to content

Commit 9f6b55f

Browse files
committed
[nrf fromtree] net: mqtt: Add MQTT 5.0 support for DISCONNECT
Add support for DICONNECT message specified in MQTT 5.0. As with MQTT 5.0, the disconnect can now also be initiated by the broker, it was needed to add decoder support for the message. Signed-off-by: Robert Lubos <[email protected]> (cherry picked from commit 55e1c10)
1 parent 6427aca commit 9f6b55f

File tree

12 files changed

+320
-24
lines changed

12 files changed

+320
-24
lines changed

include/zephyr/net/mqtt.h

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,39 @@ enum mqtt_suback_return_code {
175175
MQTT_SUBACK_FAILURE = 0x80
176176
};
177177

178+
/** @brief MQTT Disconnect reason codes (MQTT 5.0, chapter 3.14.2.1). */
179+
enum mqtt_disconnect_reason_code {
180+
MQTT_DISCONNECT_NORMAL = 0,
181+
MQTT_DISCONNECT_WITH_WILL_MSG = 4,
182+
MQTT_DISCONNECT_UNSPECIFIED_ERROR = 128,
183+
MQTT_DISCONNECT_MALFORMED_PACKET = 129,
184+
MQTT_DISCONNECT_PROTOCOL_ERROR = 130,
185+
MQTT_DISCONNECT_IMPL_SPECIFIC_ERROR = 131,
186+
MQTT_DISCONNECT_NOT_AUTHORIZED = 135,
187+
MQTT_DISCONNECT_SERVER_BUSY = 137,
188+
MQTT_DISCONNECT_SERVER_SHUTTING_DOWN = 139,
189+
MQTT_DISCONNECT_KEEP_ALIVE_TIMEOUT = 141,
190+
MQTT_DISCONNECT_SESSION_TAKE_OVER = 142,
191+
MQTT_DISCONNECT_TOPIC_FILTER_INVALID = 143,
192+
MQTT_DISCONNECT_TOPIC_NAME_INVALID = 144,
193+
MQTT_DISCONNECT_RECV_MAX_EXCEEDED = 147,
194+
MQTT_DISCONNECT_TOPIC_ALIAS_INVALID = 148,
195+
MQTT_DISCONNECT_PACKET_TOO_LARGE = 149,
196+
MQTT_DISCONNECT_MESSAGE_RATE_TOO_HIGH = 150,
197+
MQTT_DISCONNECT_QUOTA_EXCEEDED = 151,
198+
MQTT_DISCONNECT_ADMIN_ACTION = 152,
199+
MQTT_DISCONNECT_PAYLOAD_FORMAT_INVALID = 153,
200+
MQTT_DISCONNECT_RETAIN_NOT_SUPPORTED = 154,
201+
MQTT_DISCONNECT_QOS_NOT_SUPPORTED = 155,
202+
MQTT_DISCONNECT_USE_ANOTHER_SERVER = 156,
203+
MQTT_DISCONNECT_SERVER_MOVED = 157,
204+
MQTT_DISCONNECT_SHARED_SUB_NOT_SUPPORTED = 158,
205+
MQTT_DISCONNECT_CONNECTION_RATE_EXCEEDED = 159,
206+
MQTT_DISCONNECT_MAX_CONNECT_TIME = 160,
207+
MQTT_DISCONNECT_SUB_ID_NOT_SUPPORTED = 161,
208+
MQTT_DISCONNECT_WILDCARD_SUB_NOT_SUPPORTED = 162,
209+
};
210+
178211
/** @brief Abstracts UTF-8 encoded strings. */
179212
struct mqtt_utf8 {
180213
const uint8_t *utf8; /**< Pointer to UTF-8 string. */
@@ -534,6 +567,41 @@ struct mqtt_subscription_list {
534567
#endif /* CONFIG_MQTT_VERSION_5_0 */
535568
};
536569

570+
/** @brief Parameters for disconnect message. */
571+
struct mqtt_disconnect_param {
572+
#if defined(CONFIG_MQTT_VERSION_5_0)
573+
/* MQTT 5.0 Disconnect reason code. */
574+
enum mqtt_disconnect_reason_code reason_code;
575+
576+
/** MQTT 5.0 properties. */
577+
struct {
578+
/** MQTT 5.0, chapter 3.14.2.2.4 User Property. */
579+
struct mqtt_utf8_pair user_prop[CONFIG_MQTT_USER_PROPERTIES_MAX];
580+
581+
/** MQTT 5.0, chapter 3.14.2.2.3 Reason String. */
582+
struct mqtt_utf8 reason_string;
583+
584+
/** MQTT 5.0, chapter 3.14.2.2.5 Server Reference. */
585+
struct mqtt_utf8 server_reference;
586+
587+
/** MQTT 5.0, chapter 3.14.2.2.2 Session Expiry Interval. */
588+
uint32_t session_expiry_interval;
589+
590+
/** Flags indicating whether given property was present in received packet. */
591+
struct {
592+
/** Session Expiry Interval property was present. */
593+
bool has_session_expiry_interval;
594+
/** Reason String property was present. */
595+
bool has_reason_string;
596+
/** User Property property was present. */
597+
bool has_user_prop;
598+
/** Server Reference property was present. */
599+
bool has_server_reference;
600+
} rx;
601+
} prop;
602+
#endif /* CONFIG_MQTT_VERSION_5_0 */
603+
};
604+
537605
/**
538606
* @brief Defines event parameters notified along with asynchronous events
539607
* to the application.
@@ -567,6 +635,11 @@ union mqtt_evt_param {
567635

568636
/** Parameters accompanying MQTT_EVT_UNSUBACK event. */
569637
struct mqtt_unsuback_param unsuback;
638+
639+
#if defined(CONFIG_MQTT_VERSION_5_0)
640+
/** Parameters accompanying MQTT_EVT_DISCONNECT event. */
641+
struct mqtt_disconnect_param disconnect;
642+
#endif /* CONFIG_MQTT_VERSION_5_0 */
570643
};
571644

572645
/** @brief Defines MQTT asynchronous event notified to the application. */
@@ -1042,10 +1115,13 @@ int mqtt_ping(struct mqtt_client *client);
10421115
*
10431116
* @param[in] client Identifies client instance for which procedure is
10441117
* requested.
1118+
* @param[in] param Optional Disconnect parameters. May be NULL.
1119+
* Ignored if MQTT 3.1.1 is used.
10451120
*
10461121
* @return 0 or a negative error code (errno.h) indicating reason of failure.
10471122
*/
1048-
int mqtt_disconnect(struct mqtt_client *client);
1123+
int mqtt_disconnect(struct mqtt_client *client,
1124+
const struct mqtt_disconnect_param *param);
10491125

10501126
/**
10511127
* @brief API to abort MQTT connection. This will close the corresponding

samples/net/cloud/aws_iot_mqtt/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ void aws_client_loop(void)
413413
}
414414

415415
cleanup:
416-
mqtt_disconnect(&client_ctx);
416+
mqtt_disconnect(&client_ctx, NULL);
417417

418418
close(fds.fd);
419419
fds.fd = -1;

samples/net/mqtt_publisher/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ static int publisher(void)
475475
r = 0;
476476
}
477477

478-
rc = mqtt_disconnect(&client_ctx);
478+
rc = mqtt_disconnect(&client_ctx, NULL);
479479
PRINT_RESULT("mqtt_disconnect", rc);
480480

481481
LOG_INF("Bye!");

samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ void app_mqtt_run(struct mqtt_client *client)
402402
}
403403
}
404404
/* Gracefully close connection */
405-
mqtt_disconnect(client);
405+
mqtt_disconnect(client, NULL);
406406
}
407407

408408
void app_mqtt_connect(struct mqtt_client *client)

subsys/net/lib/mqtt/mqtt.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ void event_notify(struct mqtt_client *client, const struct mqtt_evt *evt)
4646
}
4747
}
4848

49-
static void client_disconnect(struct mqtt_client *client, int result,
50-
bool notify)
49+
void mqtt_client_disconnect(struct mqtt_client *client, int result, bool notify)
5150
{
5251
int err_code;
5352

@@ -105,7 +104,7 @@ static int client_connect(struct mqtt_client *client)
105104
return 0;
106105

107106
error:
108-
client_disconnect(client, err_code, false);
107+
mqtt_client_disconnect(client, err_code, false);
109108
return err_code;
110109
}
111110

@@ -119,7 +118,7 @@ static int client_read(struct mqtt_client *client)
119118

120119
err_code = mqtt_handle_rx(client);
121120
if (err_code < 0) {
122-
client_disconnect(client, err_code, true);
121+
mqtt_client_disconnect(client, err_code, true);
123122
}
124123

125124
return err_code;
@@ -136,7 +135,7 @@ static int client_write(struct mqtt_client *client, const uint8_t *data,
136135
if (err_code < 0) {
137136
NET_ERR("Transport write failed, err_code = %d, "
138137
"closing connection", err_code);
139-
client_disconnect(client, err_code, true);
138+
mqtt_client_disconnect(client, err_code, true);
140139
return err_code;
141140
}
142141

@@ -157,7 +156,7 @@ static int client_write_msg(struct mqtt_client *client,
157156
if (err_code < 0) {
158157
NET_ERR("Transport write failed, err_code = %d, "
159158
"closing connection", err_code);
160-
client_disconnect(client, err_code, true);
159+
mqtt_client_disconnect(client, err_code, true);
161160
return err_code;
162161
}
163162

@@ -439,7 +438,8 @@ int mqtt_publish_qos2_complete(struct mqtt_client *client,
439438
return err_code;
440439
}
441440

442-
int mqtt_disconnect(struct mqtt_client *client)
441+
int mqtt_disconnect(struct mqtt_client *client,
442+
const struct mqtt_disconnect_param *param)
443443
{
444444
int err_code;
445445
struct buf_ctx packet;
@@ -455,7 +455,7 @@ int mqtt_disconnect(struct mqtt_client *client)
455455
goto error;
456456
}
457457

458-
err_code = disconnect_encode(&packet);
458+
err_code = disconnect_encode(client, param, &packet);
459459
if (err_code < 0) {
460460
goto error;
461461
}
@@ -465,7 +465,7 @@ int mqtt_disconnect(struct mqtt_client *client)
465465
goto error;
466466
}
467467

468-
client_disconnect(client, 0, true);
468+
mqtt_client_disconnect(client, 0, true);
469469

470470
error:
471471
mqtt_mutex_unlock(client);
@@ -584,7 +584,7 @@ int mqtt_abort(struct mqtt_client *client)
584584
mqtt_mutex_lock(client);
585585

586586
if (client->internal.state != MQTT_STATE_IDLE) {
587-
client_disconnect(client, -ECONNABORTED, true);
587+
mqtt_client_disconnect(client, -ECONNABORTED, true);
588588
}
589589

590590
mqtt_mutex_unlock(client);
@@ -686,7 +686,7 @@ static int read_publish_payload(struct mqtt_client *client, void *buffer,
686686
ret = -ENOTCONN;
687687
}
688688

689-
client_disconnect(client, ret, true);
689+
mqtt_client_disconnect(client, ret, true);
690690
goto exit;
691691
}
692692

subsys/net/lib/mqtt/mqtt_decoder.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,3 +1015,67 @@ int unsubscribe_ack_decode(const struct mqtt_client *client, struct buf_ctx *buf
10151015

10161016
return 0;
10171017
}
1018+
1019+
#if defined(CONFIG_MQTT_VERSION_5_0)
1020+
static int disconnect_properties_decode(struct buf_ctx *buf,
1021+
struct mqtt_disconnect_param *param)
1022+
{
1023+
struct property_decoder prop[] = {
1024+
{
1025+
&param->prop.session_expiry_interval,
1026+
&param->prop.rx.has_session_expiry_interval,
1027+
MQTT_PROP_SESSION_EXPIRY_INTERVAL
1028+
},
1029+
{
1030+
&param->prop.reason_string,
1031+
&param->prop.rx.has_reason_string,
1032+
MQTT_PROP_REASON_STRING
1033+
},
1034+
{
1035+
&param->prop.user_prop,
1036+
&param->prop.rx.has_user_prop,
1037+
MQTT_PROP_USER_PROPERTY
1038+
},
1039+
{
1040+
&param->prop.server_reference,
1041+
&param->prop.rx.has_server_reference,
1042+
MQTT_PROP_SERVER_REFERENCE
1043+
}
1044+
};
1045+
1046+
return properties_decode(prop, ARRAY_SIZE(prop), buf);
1047+
}
1048+
1049+
int disconnect_decode(const struct mqtt_client *client, struct buf_ctx *buf,
1050+
struct mqtt_disconnect_param *param)
1051+
{
1052+
1053+
size_t remaining_len;
1054+
uint8_t reason_code;
1055+
int err;
1056+
1057+
if (!mqtt_is_version_5_0(client)) {
1058+
return -ENOTSUP;
1059+
}
1060+
1061+
remaining_len = buf->end - buf->cur;
1062+
1063+
if (remaining_len > 0) {
1064+
err = unpack_uint8(buf, &reason_code);
1065+
if (err < 0) {
1066+
return err;
1067+
}
1068+
1069+
param->reason_code = reason_code;
1070+
}
1071+
1072+
if (remaining_len > 1) {
1073+
err = disconnect_properties_decode(buf, param);
1074+
if (err < 0) {
1075+
return err;
1076+
}
1077+
}
1078+
1079+
return 0;
1080+
}
1081+
#endif /* CONFIG_MQTT_VERSION_5_0 */

0 commit comments

Comments
 (0)