1 /*
2 * Copyright (c) 2022 René Beckmann
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /** @file mqtt_sn_decoder.c
8 *
9 * @brief MQTT-SN message decoder.
10 */
11
12 #include "mqtt_sn_msg.h"
13
14 #include <zephyr/net/mqtt_sn.h>
15
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_DECLARE(net_mqtt_sn, CONFIG_MQTT_SN_LOG_LEVEL);
18
19 /**
20 * @brief Decode the length of a message payload.
21 *
22 * From the specification:
23 *
24 * The Length field is either 1- or 3-octet long and specifies the total number of octets
25 * contained in the message (including the Length field itself).
26 * If the first octet of the Length field is coded “0x01” then the Length field is 3-octet long;
27 * in this case, the two following octets specify the total number of octets of the message
28 * (most-significant octet first). Otherwise, the Length field is only 1-octet long and specifies
29 * itself the total number of octets contained in the message. The 3-octet format allows the
30 * encoding of message lengths up to 65535 octets. Messages with lengths smaller than 256 octets
31 * may use the shorter 1-octet format.
32 *
33 * @param buf
34 * @return Size of the message not including the length field or negative error code
35 */
decode_payload_length(struct net_buf_simple * buf)36 static ssize_t decode_payload_length(struct net_buf_simple *buf)
37 {
38 size_t length;
39 size_t length_field_s = 1;
40 size_t buflen = buf->len;
41
42 /*
43 * Size must not be larger than an uint16_t can fit,
44 * minus 3 bytes for the length field itself
45 */
46 if (buflen > UINT16_MAX) {
47 LOG_ERR("Message too large");
48 return -EFBIG;
49 }
50
51 length = net_buf_simple_pull_u8(buf);
52 if (length == MQTT_SN_LENGTH_FIELD_EXTENDED_PREFIX) {
53 length = net_buf_simple_pull_be16(buf);
54 length_field_s = 3;
55 }
56
57 if (length != buflen) {
58 LOG_ERR("Message length %zu != buffer size %zu", length, buflen);
59 return -EPROTO;
60 }
61
62 if (length <= length_field_s) {
63 LOG_ERR("Message length %zu - contains no data?", length);
64 return -ENODATA;
65 }
66
67 /* subtract the size of the length field to get message length */
68 return length - length_field_s;
69 }
70
decode_flags(struct net_buf_simple * buf,struct mqtt_sn_flags * flags)71 static void decode_flags(struct net_buf_simple *buf, struct mqtt_sn_flags *flags)
72 {
73 uint8_t b = net_buf_simple_pull_u8(buf);
74
75 flags->dup = (bool)(b & MQTT_SN_FLAGS_DUP);
76 flags->retain = (bool)(b & MQTT_SN_FLAGS_RETAIN);
77 flags->will = (bool)(b & MQTT_SN_FLAGS_WILL);
78 flags->clean_session = (bool)(b & MQTT_SN_FLAGS_CLEANSESSION);
79
80 flags->qos = (enum mqtt_sn_qos)((b & MQTT_SN_FLAGS_MASK_QOS) >> MQTT_SN_FLAGS_SHIFT_QOS);
81
82 flags->topic_type = (enum mqtt_sn_topic_type)((b & MQTT_SN_FLAGS_MASK_TOPICID_TYPE) >>
83 MQTT_SN_FLAGS_SHIFT_TOPICID_TYPE);
84 }
85
decode_data(struct net_buf_simple * buf,struct mqtt_sn_data * dest)86 static void decode_data(struct net_buf_simple *buf, struct mqtt_sn_data *dest)
87 {
88 dest->size = buf->len;
89 dest->data = net_buf_simple_pull_mem(buf, buf->len);
90 }
91
decode_empty_message(struct net_buf_simple * buf)92 static int decode_empty_message(struct net_buf_simple *buf)
93 {
94 if (buf->len) {
95 LOG_ERR("Message not empty");
96 return -EPROTO;
97 }
98
99 return 0;
100 }
101
decode_msg_advertise(struct net_buf_simple * buf,struct mqtt_sn_param_advertise * params)102 static int decode_msg_advertise(struct net_buf_simple *buf, struct mqtt_sn_param_advertise *params)
103 {
104 if (buf->len != 3) {
105 return -EPROTO;
106 }
107
108 params->gw_id = net_buf_simple_pull_u8(buf);
109 params->duration = net_buf_simple_pull_be16(buf);
110
111 return 0;
112 }
113
decode_msg_gwinfo(struct net_buf_simple * buf,struct mqtt_sn_param_gwinfo * params)114 static int decode_msg_gwinfo(struct net_buf_simple *buf, struct mqtt_sn_param_gwinfo *params)
115 {
116 if (buf->len < 1) {
117 return -EPROTO;
118 }
119
120 params->gw_id = net_buf_simple_pull_u8(buf);
121
122 if (buf->len) {
123 decode_data(buf, ¶ms->gw_add);
124 }
125
126 return 0;
127 }
128
decode_msg_connack(struct net_buf_simple * buf,struct mqtt_sn_param_connack * params)129 static int decode_msg_connack(struct net_buf_simple *buf, struct mqtt_sn_param_connack *params)
130 {
131 if (buf->len != 1) {
132 return -EPROTO;
133 }
134
135 params->ret_code = net_buf_simple_pull_u8(buf);
136
137 return 0;
138 }
139
decode_msg_willtopicreq(struct net_buf_simple * buf)140 static int decode_msg_willtopicreq(struct net_buf_simple *buf)
141 {
142 return decode_empty_message(buf);
143 }
144
decode_msg_willmsgreq(struct net_buf_simple * buf)145 static int decode_msg_willmsgreq(struct net_buf_simple *buf)
146 {
147 return decode_empty_message(buf);
148 }
149
decode_msg_register(struct net_buf_simple * buf,struct mqtt_sn_param_register * params)150 static int decode_msg_register(struct net_buf_simple *buf, struct mqtt_sn_param_register *params)
151 {
152 if (buf->len < 5) {
153 return -EPROTO;
154 }
155
156 params->topic_id = net_buf_simple_pull_be16(buf);
157 params->msg_id = net_buf_simple_pull_be16(buf);
158 decode_data(buf, ¶ms->topic);
159
160 return 0;
161 }
162
decode_msg_regack(struct net_buf_simple * buf,struct mqtt_sn_param_regack * params)163 static int decode_msg_regack(struct net_buf_simple *buf, struct mqtt_sn_param_regack *params)
164 {
165 if (buf->len != 5) {
166 return -EPROTO;
167 }
168
169 params->topic_id = net_buf_simple_pull_be16(buf);
170 params->msg_id = net_buf_simple_pull_be16(buf);
171 params->ret_code = net_buf_simple_pull_u8(buf);
172
173 return 0;
174 }
175
decode_msg_publish(struct net_buf_simple * buf,struct mqtt_sn_param_publish * params)176 static int decode_msg_publish(struct net_buf_simple *buf, struct mqtt_sn_param_publish *params)
177 {
178 struct mqtt_sn_flags flags;
179
180 if (buf->len < 6) {
181 return -EPROTO;
182 }
183
184 decode_flags(buf, &flags);
185 params->dup = flags.dup;
186 params->qos = flags.qos;
187 params->retain = flags.retain;
188 params->topic_type = flags.topic_type;
189 params->topic_id = net_buf_simple_pull_be16(buf);
190 params->msg_id = net_buf_simple_pull_be16(buf);
191 decode_data(buf, ¶ms->data);
192
193 return 0;
194 }
195
decode_msg_puback(struct net_buf_simple * buf,struct mqtt_sn_param_puback * params)196 static int decode_msg_puback(struct net_buf_simple *buf, struct mqtt_sn_param_puback *params)
197 {
198 if (buf->len != 5) {
199 return -EPROTO;
200 }
201
202 params->topic_id = net_buf_simple_pull_be16(buf);
203 params->msg_id = net_buf_simple_pull_be16(buf);
204 params->ret_code = net_buf_simple_pull_u8(buf);
205
206 return 0;
207 }
208
decode_msg_pubrec(struct net_buf_simple * buf,struct mqtt_sn_param_pubrec * params)209 static int decode_msg_pubrec(struct net_buf_simple *buf, struct mqtt_sn_param_pubrec *params)
210 {
211 if (buf->len != 2) {
212 return -EPROTO;
213 }
214
215 params->msg_id = net_buf_simple_pull_be16(buf);
216
217 return 0;
218 }
219
decode_msg_pubrel(struct net_buf_simple * buf,struct mqtt_sn_param_pubrel * params)220 static int decode_msg_pubrel(struct net_buf_simple *buf, struct mqtt_sn_param_pubrel *params)
221 {
222 if (buf->len != 2) {
223 return -EPROTO;
224 }
225
226 params->msg_id = net_buf_simple_pull_be16(buf);
227
228 return 0;
229 }
230
decode_msg_pubcomp(struct net_buf_simple * buf,struct mqtt_sn_param_pubcomp * params)231 static int decode_msg_pubcomp(struct net_buf_simple *buf, struct mqtt_sn_param_pubcomp *params)
232 {
233 if (buf->len != 2) {
234 return -EPROTO;
235 }
236
237 params->msg_id = net_buf_simple_pull_be16(buf);
238
239 return 0;
240 }
241
decode_msg_suback(struct net_buf_simple * buf,struct mqtt_sn_param_suback * params)242 static int decode_msg_suback(struct net_buf_simple *buf, struct mqtt_sn_param_suback *params)
243 {
244 struct mqtt_sn_flags flags;
245
246 if (buf->len != 6) {
247 return -EPROTO;
248 }
249
250 decode_flags(buf, &flags);
251
252 params->qos = flags.qos;
253
254 params->topic_id = net_buf_simple_pull_be16(buf);
255 params->msg_id = net_buf_simple_pull_be16(buf);
256 params->ret_code = net_buf_simple_pull_u8(buf);
257
258 return 0;
259 }
260
decode_msg_unsuback(struct net_buf_simple * buf,struct mqtt_sn_param_unsuback * params)261 static int decode_msg_unsuback(struct net_buf_simple *buf, struct mqtt_sn_param_unsuback *params)
262 {
263 if (buf->len != 2) {
264 return -EPROTO;
265 }
266
267 params->msg_id = net_buf_simple_pull_be16(buf);
268
269 return 0;
270 }
271
decode_msg_pingreq(struct net_buf_simple * buf)272 static int decode_msg_pingreq(struct net_buf_simple *buf)
273 {
274 /* The client_id field is only set if the message was sent by a client. */
275 return decode_empty_message(buf);
276 }
277
decode_msg_pingresp(struct net_buf_simple * buf)278 static int decode_msg_pingresp(struct net_buf_simple *buf)
279 {
280 return decode_empty_message(buf);
281 }
282
decode_msg_disconnect(struct net_buf_simple * buf,struct mqtt_sn_param_disconnect * params)283 static int decode_msg_disconnect(struct net_buf_simple *buf,
284 struct mqtt_sn_param_disconnect *params)
285 {
286 /* The duration field is only set if the message was sent by a client. */
287 return decode_empty_message(buf);
288 }
289
decode_msg_willtopicresp(struct net_buf_simple * buf,struct mqtt_sn_param_willtopicresp * params)290 static int decode_msg_willtopicresp(struct net_buf_simple *buf,
291 struct mqtt_sn_param_willtopicresp *params)
292 {
293 if (buf->len != 1) {
294 return -EPROTO;
295 }
296
297 params->ret_code = net_buf_simple_pull_u8(buf);
298
299 return 0;
300 }
301
decode_msg_willmsgresp(struct net_buf_simple * buf,struct mqtt_sn_param_willmsgresp * params)302 static int decode_msg_willmsgresp(struct net_buf_simple *buf,
303 struct mqtt_sn_param_willmsgresp *params)
304 {
305 if (buf->len != 1) {
306 return -EPROTO;
307 }
308
309 params->ret_code = net_buf_simple_pull_u8(buf);
310
311 return 0;
312 }
313
mqtt_sn_decode_msg(struct net_buf_simple * buf,struct mqtt_sn_param * params)314 int mqtt_sn_decode_msg(struct net_buf_simple *buf, struct mqtt_sn_param *params)
315 {
316 ssize_t len;
317
318 if (!buf || !buf->len) {
319 return -EINVAL;
320 }
321
322 len = decode_payload_length(buf);
323 if (len < 0) {
324 LOG_ERR("Could not decode message: %d", (int)len);
325 return (int)len;
326 }
327
328 params->type = (enum mqtt_sn_msg_type)net_buf_simple_pull_u8(buf);
329
330 LOG_INF("Decoding message type: %d", params->type);
331
332 switch (params->type) {
333 case MQTT_SN_MSG_TYPE_ADVERTISE:
334 return decode_msg_advertise(buf, ¶ms->params.advertise);
335 case MQTT_SN_MSG_TYPE_GWINFO:
336 return decode_msg_gwinfo(buf, ¶ms->params.gwinfo);
337 case MQTT_SN_MSG_TYPE_CONNACK:
338 return decode_msg_connack(buf, ¶ms->params.connack);
339 case MQTT_SN_MSG_TYPE_WILLTOPICREQ:
340 return decode_msg_willtopicreq(buf);
341 case MQTT_SN_MSG_TYPE_WILLMSGREQ:
342 return decode_msg_willmsgreq(buf);
343 case MQTT_SN_MSG_TYPE_REGISTER:
344 return decode_msg_register(buf, ¶ms->params.reg);
345 case MQTT_SN_MSG_TYPE_REGACK:
346 return decode_msg_regack(buf, ¶ms->params.regack);
347 case MQTT_SN_MSG_TYPE_PUBLISH:
348 return decode_msg_publish(buf, ¶ms->params.publish);
349 case MQTT_SN_MSG_TYPE_PUBACK:
350 return decode_msg_puback(buf, ¶ms->params.puback);
351 case MQTT_SN_MSG_TYPE_PUBREC:
352 return decode_msg_pubrec(buf, ¶ms->params.pubrec);
353 case MQTT_SN_MSG_TYPE_PUBREL:
354 return decode_msg_pubrel(buf, ¶ms->params.pubrel);
355 case MQTT_SN_MSG_TYPE_PUBCOMP:
356 return decode_msg_pubcomp(buf, ¶ms->params.pubcomp);
357 case MQTT_SN_MSG_TYPE_SUBACK:
358 return decode_msg_suback(buf, ¶ms->params.suback);
359 case MQTT_SN_MSG_TYPE_UNSUBACK:
360 return decode_msg_unsuback(buf, ¶ms->params.unsuback);
361 case MQTT_SN_MSG_TYPE_PINGREQ:
362 return decode_msg_pingreq(buf);
363 case MQTT_SN_MSG_TYPE_PINGRESP:
364 return decode_msg_pingresp(buf);
365 case MQTT_SN_MSG_TYPE_DISCONNECT:
366 return decode_msg_disconnect(buf, ¶ms->params.disconnect);
367 case MQTT_SN_MSG_TYPE_WILLTOPICRESP:
368 return decode_msg_willtopicresp(buf, ¶ms->params.willtopicresp);
369 case MQTT_SN_MSG_TYPE_WILLMSGRESP:
370 return decode_msg_willmsgresp(buf, ¶ms->params.willmsgresp);
371 default:
372 LOG_ERR("Got unexpected message type %d", params->type);
373 return -EINVAL;
374 }
375 }
376