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_searchgw(struct net_buf_simple * buf,struct mqtt_sn_param_searchgw * params)114 static int decode_msg_searchgw(struct net_buf_simple *buf, struct mqtt_sn_param_searchgw *params)
115 {
116 	if (buf->len != 1) {
117 		return -EPROTO;
118 	}
119 
120 	params->radius = net_buf_simple_pull_u8(buf);
121 
122 	return 0;
123 }
124 
decode_msg_gwinfo(struct net_buf_simple * buf,struct mqtt_sn_param_gwinfo * params)125 static int decode_msg_gwinfo(struct net_buf_simple *buf, struct mqtt_sn_param_gwinfo *params)
126 {
127 	if (buf->len < 1) {
128 		return -EPROTO;
129 	}
130 
131 	params->gw_id = net_buf_simple_pull_u8(buf);
132 
133 	if (buf->len) {
134 		decode_data(buf, &params->gw_add);
135 	} else {
136 		params->gw_add.size = 0;
137 	}
138 
139 	return 0;
140 }
141 
decode_msg_connack(struct net_buf_simple * buf,struct mqtt_sn_param_connack * params)142 static int decode_msg_connack(struct net_buf_simple *buf, struct mqtt_sn_param_connack *params)
143 {
144 	if (buf->len != 1) {
145 		return -EPROTO;
146 	}
147 
148 	params->ret_code = net_buf_simple_pull_u8(buf);
149 
150 	return 0;
151 }
152 
decode_msg_willtopicreq(struct net_buf_simple * buf)153 static int decode_msg_willtopicreq(struct net_buf_simple *buf)
154 {
155 	return decode_empty_message(buf);
156 }
157 
decode_msg_willmsgreq(struct net_buf_simple * buf)158 static int decode_msg_willmsgreq(struct net_buf_simple *buf)
159 {
160 	return decode_empty_message(buf);
161 }
162 
decode_msg_register(struct net_buf_simple * buf,struct mqtt_sn_param_register * params)163 static int decode_msg_register(struct net_buf_simple *buf, struct mqtt_sn_param_register *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 	decode_data(buf, &params->topic);
172 
173 	return 0;
174 }
175 
decode_msg_regack(struct net_buf_simple * buf,struct mqtt_sn_param_regack * params)176 static int decode_msg_regack(struct net_buf_simple *buf, struct mqtt_sn_param_regack *params)
177 {
178 	if (buf->len != 5) {
179 		return -EPROTO;
180 	}
181 
182 	params->topic_id = net_buf_simple_pull_be16(buf);
183 	params->msg_id = net_buf_simple_pull_be16(buf);
184 	params->ret_code = net_buf_simple_pull_u8(buf);
185 
186 	return 0;
187 }
188 
decode_msg_publish(struct net_buf_simple * buf,struct mqtt_sn_param_publish * params)189 static int decode_msg_publish(struct net_buf_simple *buf, struct mqtt_sn_param_publish *params)
190 {
191 	struct mqtt_sn_flags flags;
192 
193 	if (buf->len < 6) {
194 		return -EPROTO;
195 	}
196 
197 	decode_flags(buf, &flags);
198 	params->dup = flags.dup;
199 	params->qos = flags.qos;
200 	params->retain = flags.retain;
201 	params->topic_type = flags.topic_type;
202 	params->topic_id = net_buf_simple_pull_be16(buf);
203 	params->msg_id = net_buf_simple_pull_be16(buf);
204 	decode_data(buf, &params->data);
205 
206 	return 0;
207 }
208 
decode_msg_puback(struct net_buf_simple * buf,struct mqtt_sn_param_puback * params)209 static int decode_msg_puback(struct net_buf_simple *buf, struct mqtt_sn_param_puback *params)
210 {
211 	if (buf->len != 5) {
212 		return -EPROTO;
213 	}
214 
215 	params->topic_id = net_buf_simple_pull_be16(buf);
216 	params->msg_id = net_buf_simple_pull_be16(buf);
217 	params->ret_code = net_buf_simple_pull_u8(buf);
218 
219 	return 0;
220 }
221 
decode_msg_pubrec(struct net_buf_simple * buf,struct mqtt_sn_param_pubrec * params)222 static int decode_msg_pubrec(struct net_buf_simple *buf, struct mqtt_sn_param_pubrec *params)
223 {
224 	if (buf->len != 2) {
225 		return -EPROTO;
226 	}
227 
228 	params->msg_id = net_buf_simple_pull_be16(buf);
229 
230 	return 0;
231 }
232 
decode_msg_pubrel(struct net_buf_simple * buf,struct mqtt_sn_param_pubrel * params)233 static int decode_msg_pubrel(struct net_buf_simple *buf, struct mqtt_sn_param_pubrel *params)
234 {
235 	if (buf->len != 2) {
236 		return -EPROTO;
237 	}
238 
239 	params->msg_id = net_buf_simple_pull_be16(buf);
240 
241 	return 0;
242 }
243 
decode_msg_pubcomp(struct net_buf_simple * buf,struct mqtt_sn_param_pubcomp * params)244 static int decode_msg_pubcomp(struct net_buf_simple *buf, struct mqtt_sn_param_pubcomp *params)
245 {
246 	if (buf->len != 2) {
247 		return -EPROTO;
248 	}
249 
250 	params->msg_id = net_buf_simple_pull_be16(buf);
251 
252 	return 0;
253 }
254 
decode_msg_suback(struct net_buf_simple * buf,struct mqtt_sn_param_suback * params)255 static int decode_msg_suback(struct net_buf_simple *buf, struct mqtt_sn_param_suback *params)
256 {
257 	struct mqtt_sn_flags flags;
258 
259 	if (buf->len != 6) {
260 		return -EPROTO;
261 	}
262 
263 	decode_flags(buf, &flags);
264 
265 	params->qos = flags.qos;
266 
267 	params->topic_id = net_buf_simple_pull_be16(buf);
268 	params->msg_id = net_buf_simple_pull_be16(buf);
269 	params->ret_code = net_buf_simple_pull_u8(buf);
270 
271 	return 0;
272 }
273 
decode_msg_unsuback(struct net_buf_simple * buf,struct mqtt_sn_param_unsuback * params)274 static int decode_msg_unsuback(struct net_buf_simple *buf, struct mqtt_sn_param_unsuback *params)
275 {
276 	if (buf->len != 2) {
277 		return -EPROTO;
278 	}
279 
280 	params->msg_id = net_buf_simple_pull_be16(buf);
281 
282 	return 0;
283 }
284 
decode_msg_pingreq(struct net_buf_simple * buf)285 static int decode_msg_pingreq(struct net_buf_simple *buf)
286 {
287 	/* The client_id field is only set if the message was sent by a client. */
288 	return decode_empty_message(buf);
289 }
290 
decode_msg_pingresp(struct net_buf_simple * buf)291 static int decode_msg_pingresp(struct net_buf_simple *buf)
292 {
293 	return decode_empty_message(buf);
294 }
295 
decode_msg_disconnect(struct net_buf_simple * buf,struct mqtt_sn_param_disconnect * params)296 static int decode_msg_disconnect(struct net_buf_simple *buf,
297 				 struct mqtt_sn_param_disconnect *params)
298 {
299 	/* The duration field is only set if the message was sent by a client. */
300 	return decode_empty_message(buf);
301 }
302 
decode_msg_willtopicresp(struct net_buf_simple * buf,struct mqtt_sn_param_willtopicresp * params)303 static int decode_msg_willtopicresp(struct net_buf_simple *buf,
304 				    struct mqtt_sn_param_willtopicresp *params)
305 {
306 	if (buf->len != 1) {
307 		return -EPROTO;
308 	}
309 
310 	params->ret_code = net_buf_simple_pull_u8(buf);
311 
312 	return 0;
313 }
314 
decode_msg_willmsgresp(struct net_buf_simple * buf,struct mqtt_sn_param_willmsgresp * params)315 static int decode_msg_willmsgresp(struct net_buf_simple *buf,
316 				  struct mqtt_sn_param_willmsgresp *params)
317 {
318 	if (buf->len != 1) {
319 		return -EPROTO;
320 	}
321 
322 	params->ret_code = net_buf_simple_pull_u8(buf);
323 
324 	return 0;
325 }
326 
mqtt_sn_decode_msg(struct net_buf_simple * buf,struct mqtt_sn_param * params)327 int mqtt_sn_decode_msg(struct net_buf_simple *buf, struct mqtt_sn_param *params)
328 {
329 	ssize_t len;
330 
331 	if (!buf || !buf->len) {
332 		return -EINVAL;
333 	}
334 
335 	len = decode_payload_length(buf);
336 	if (len < 0) {
337 		LOG_ERR("Could not decode message: %d", (int)len);
338 		return (int)len;
339 	}
340 
341 	params->type = (enum mqtt_sn_msg_type)net_buf_simple_pull_u8(buf);
342 
343 	LOG_INF("Decoding message type: %d", params->type);
344 
345 	switch (params->type) {
346 	case MQTT_SN_MSG_TYPE_ADVERTISE:
347 		return decode_msg_advertise(buf, &params->params.advertise);
348 	case MQTT_SN_MSG_TYPE_SEARCHGW:
349 		return decode_msg_searchgw(buf, &params->params.searchgw);
350 	case MQTT_SN_MSG_TYPE_GWINFO:
351 		return decode_msg_gwinfo(buf, &params->params.gwinfo);
352 	case MQTT_SN_MSG_TYPE_CONNACK:
353 		return decode_msg_connack(buf, &params->params.connack);
354 	case MQTT_SN_MSG_TYPE_WILLTOPICREQ:
355 		return decode_msg_willtopicreq(buf);
356 	case MQTT_SN_MSG_TYPE_WILLMSGREQ:
357 		return decode_msg_willmsgreq(buf);
358 	case MQTT_SN_MSG_TYPE_REGISTER:
359 		return decode_msg_register(buf, &params->params.reg);
360 	case MQTT_SN_MSG_TYPE_REGACK:
361 		return decode_msg_regack(buf, &params->params.regack);
362 	case MQTT_SN_MSG_TYPE_PUBLISH:
363 		return decode_msg_publish(buf, &params->params.publish);
364 	case MQTT_SN_MSG_TYPE_PUBACK:
365 		return decode_msg_puback(buf, &params->params.puback);
366 	case MQTT_SN_MSG_TYPE_PUBREC:
367 		return decode_msg_pubrec(buf, &params->params.pubrec);
368 	case MQTT_SN_MSG_TYPE_PUBREL:
369 		return decode_msg_pubrel(buf, &params->params.pubrel);
370 	case MQTT_SN_MSG_TYPE_PUBCOMP:
371 		return decode_msg_pubcomp(buf, &params->params.pubcomp);
372 	case MQTT_SN_MSG_TYPE_SUBACK:
373 		return decode_msg_suback(buf, &params->params.suback);
374 	case MQTT_SN_MSG_TYPE_UNSUBACK:
375 		return decode_msg_unsuback(buf, &params->params.unsuback);
376 	case MQTT_SN_MSG_TYPE_PINGREQ:
377 		return decode_msg_pingreq(buf);
378 	case MQTT_SN_MSG_TYPE_PINGRESP:
379 		return decode_msg_pingresp(buf);
380 	case MQTT_SN_MSG_TYPE_DISCONNECT:
381 		return decode_msg_disconnect(buf, &params->params.disconnect);
382 	case MQTT_SN_MSG_TYPE_WILLTOPICRESP:
383 		return decode_msg_willtopicresp(buf, &params->params.willtopicresp);
384 	case MQTT_SN_MSG_TYPE_WILLMSGRESP:
385 		return decode_msg_willmsgresp(buf, &params->params.willmsgresp);
386 	default:
387 		LOG_ERR("Got unexpected message type %d", params->type);
388 		return -EINVAL;
389 	}
390 }
391