GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/mqttprotocols.c
Date: 2025-09-22 22:57:09
Exec Total Coverage
Lines: 0 530 0.0%
Functions: 0 28 0.0%
Branches: 0 304 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/net/mqttprotocols.h"
30 #include "gate/libraries.h"
31 #include "gate/streams.h"
32 #include "gate/results.h"
33 #include "gate/serializers.h"
34 #include "gate/debugging.h"
35
36
37 /* #include <mosquitto.h> */
38
39
40 ✗ gate_result_t gate_mqtt_write_byte(gate_stream_t* stream, gate_uint8_t value)
41 {
42 ✗ return gate_stream_write(stream, (char const*)&value, 1, NULL);
43 }
44
45 ✗ gate_result_t gate_mqtt_write_word(gate_stream_t* stream, gate_uint16_t value)
46 {
47 char buff[4];
48 ✗ gate_size_t len = gate_serialize_uint16_b(buff, sizeof(buff), &value);
49 ✗ return gate_stream_write_block(stream, buff, len, NULL);
50 }
51
52 ✗ gate_result_t gate_mqtt_write_length(gate_stream_t* stream, gate_size_t value)
53 {
54 ✗ gate_result_t ret = GATE_RESULT_OK;
55 unsigned char encoded_char;
56
57 ✗ while (GATE_SUCCEEDED(ret))
58 {
59 ✗ encoded_char = value % 128;
60 ✗ value /= 128;
61 ✗ if (value > 0)
62 {
63 ✗ encoded_char |= 128;
64 }
65 ✗ ret = gate_stream_write(stream, (char const*)&encoded_char, 1, NULL);
66 ✗ if (value == 0)
67 {
68 /* all bits are encoded, we are done */
69 ✗ break;
70 }
71 }
72 ✗ return ret;
73 }
74
75 ✗ gate_result_t gate_mqtt_write_string(gate_stream_t* stream, char const* str, gate_size_t length)
76 {
77 ✗ gate_uint16_t const len = (gate_uint16_t)length;
78 ✗ gate_result_t ret = gate_mqtt_write_word(stream, len);
79 ✗ if (GATE_SUCCEEDED(ret))
80 {
81 ✗ ret = gate_stream_write(stream, str, length, NULL);
82 }
83 ✗ return ret;
84 }
85
86 ✗ gate_result_t gate_mqtt_read_byte(gate_stream_t* stream, gate_uint8_t* value)
87 {
88 ✗ char chr = 0;
89 ✗ gate_size_t received = 0;
90 ✗ gate_result_t ret = gate_stream_read(stream, &chr, 1, &received);
91 ✗ if (GATE_SUCCEEDED(ret))
92 {
93 ✗ if (received != 1)
94 {
95 ✗ ret = GATE_RESULT_ENDOFSTREAM;
96 }
97 else
98 {
99 ✗ *value = (gate_uint8_t)chr;
100 }
101 }
102 ✗ return ret;
103 }
104
105 ✗ gate_result_t gate_mqtt_read_word(gate_stream_t* stream, gate_uint16_t* value)
106 {
107 char buff[2];
108 ✗ gate_size_t received = 0;
109 ✗ gate_result_t ret = gate_stream_read_block(stream, &buff[0], 2, &received);
110 ✗ if (GATE_SUCCEEDED(ret))
111 {
112 ✗ if (received != 2)
113 {
114 ✗ ret = GATE_RESULT_ENDOFSTREAM;
115 }
116 else
117 {
118 ✗ gate_deserialize_uint16_b(buff, 2, value);
119 }
120 }
121 ✗ return ret;
122 }
123 ✗ gate_result_t gate_mqtt_read_length(gate_stream_t* stream, gate_size_t* ptr_value)
124 {
125 ✗ gate_result_t ret = GATE_RESULT_FAILED;
126 ✗ gate_size_t value = 0;
127 unsigned char b;
128 ✗ gate_size_t len_received = 0;
129 ✗ gate_size_t multiplier = 1;
130
131 do
132 {
133 ✗ ret = gate_stream_read(stream, (char*)&b, 1, &len_received);
134 ✗ GATE_BREAK_IF_FAILED(ret);
135 ✗ if (len_received == 0)
136 {
137 ✗ ret = GATE_RESULT_ENDOFSTREAM;
138 ✗ break;
139 }
140 ✗ value += (b & 127) * multiplier;
141 ✗ multiplier *= 128;
142 ✗ if (multiplier > 128 * 128 * 128)
143 {
144 ✗ ret = GATE_RESULT_INVALIDCONTENT;
145 ✗ break;
146 }
147 ✗ } while ((b & 128) != 0);
148
149 ✗ if (ptr_value)
150 {
151 ✗ *ptr_value = value;
152 }
153 ✗ return ret;
154 }
155 ✗ gate_result_t gate_mqtt_read_string(gate_stream_t* stream, gate_strbuilder_t* builder)
156 {
157 char buffer[4096];
158 ✗ gate_size_t transferred = 0;
159 ✗ gate_size_t received = 0;
160 ✗ gate_uint16_t str_length = 0;
161 ✗ gate_result_t ret = gate_mqtt_read_word(stream, &str_length);
162 ✗ if (GATE_SUCCEEDED(ret))
163 {
164 ✗ while (transferred < str_length)
165 {
166 ✗ gate_size_t required = str_length - transferred;
167 ✗ if (required > sizeof(buffer))
168 {
169 ✗ required = sizeof(buffer);
170 }
171 ✗ ret = gate_stream_read_block(stream, buffer, required, &received);
172 ✗ GATE_BREAK_IF_FAILED(ret);
173 ✗ gate_strbuilder_append_text(builder, buffer, received);
174 ✗ if (received < required)
175 {
176 ✗ ret = GATE_RESULT_INVALIDCONTENT;
177 ✗ break;
178 }
179 ✗ transferred += received;
180 }
181 }
182 ✗ return ret;
183 }
184
185 ✗ gate_result_t gate_mqtt_read_string_length_skip_data(gate_stream_t* stream, gate_uint16_t* ptr_length)
186 {
187 char buffer[4096];
188 ✗ gate_size_t transferred = 0;
189 ✗ gate_size_t received = 0;
190 ✗ gate_uint16_t str_length = 0;
191 ✗ gate_result_t ret = gate_mqtt_read_word(stream, &str_length);
192 ✗ if (GATE_SUCCEEDED(ret))
193 {
194 ✗ if (ptr_length)
195 {
196 ✗ *ptr_length = str_length;
197 }
198 ✗ while (transferred < str_length)
199 {
200 ✗ gate_size_t required = str_length - transferred;
201 ✗ if (required > sizeof(buffer))
202 {
203 ✗ required = sizeof(buffer);
204 }
205 ✗ ret = gate_stream_read_block(stream, buffer, required, &received);
206 ✗ GATE_BREAK_IF_FAILED(ret);
207 ✗ if (received < required)
208 {
209 ✗ ret = GATE_RESULT_INVALIDCONTENT;
210 ✗ break;
211 }
212 ✗ transferred += received;
213 }
214 }
215 ✗ return ret;
216 }
217
218
219 ✗ static gate_result_t serialize_memstream_packet(
220 gate_stream_t* output_stream,
221 gate_mqtt_packet_type_t packet_type,
222 unsigned char packet_flags,
223 gate_memstream_t* memstream)
224 {
225 ✗ gate_uint8_t const fixed_header_byte = (((gate_uint8_t)packet_type & 0x0f) << 4) | (packet_flags & 0x0f);
226 ✗ char const* const ptr_content = gate_memstream_get_data(memstream);
227 ✗ gate_size_t const content_size = gate_memstream_size(memstream);
228 gate_result_t ret;
229
230 do
231 {
232 ✗ ret = gate_mqtt_write_byte(output_stream, fixed_header_byte);
233 ✗ GATE_BREAK_IF_FAILED(ret);
234 ✗ ret = gate_mqtt_write_length(output_stream, content_size);
235 ✗ GATE_BREAK_IF_FAILED(ret);
236 ✗ ret = gate_stream_write_block(output_stream, ptr_content, content_size, NULL);
237 ✗ GATE_BREAK_IF_FAILED(ret);
238 } while (0);
239 ✗ return ret;
240 }
241
242 ✗ static gate_result_t serialize_connect_message(gate_stream_t* output_stream, gate_mqtt_message_t const* msg)
243 {
244 ✗ gate_result_t ret = GATE_RESULT_OK;
245 gate_memstream_impl_t data_memstream_impl;
246 char data_memstream_buffer[4096];
247
248 ✗ gate_memstream_t* const data_memstream = gate_memstream_create_static_unmanaged(&data_memstream_impl, data_memstream_buffer, sizeof(data_memstream_buffer), 0);
249 ✗ gate_stream_t* const data_stream = (gate_stream_t*)data_memstream;
250
251 do
252 {
253 /* var header */
254 ✗ ret = gate_mqtt_write_string(data_stream, "MQTT", 4);
255 ✗ GATE_BREAK_IF_FAILED(ret);
256 ✗ ret = gate_mqtt_write_byte(data_stream, msg->content.connect.level);
257 ✗ GATE_BREAK_IF_FAILED(ret);
258 ✗ ret = gate_mqtt_write_byte(data_stream, msg->content.connect.flags);
259 ✗ GATE_BREAK_IF_FAILED(ret);
260 ✗ ret = gate_mqtt_write_word(data_stream, msg->content.connect.keep_alive);
261 ✗ GATE_BREAK_IF_FAILED(ret);
262
263 /* payload */
264 ✗ ret = gate_mqtt_write_string(data_stream, msg->content.connect.client_id, msg->content.connect.client_id_len);
265 ✗ GATE_BREAK_IF_FAILED(ret);
266 ✗ if (GATE_FLAG_ENABLED(msg->content.connect.flags, GATE_MQTT_CONNECT_FLAG_WILLFLAG))
267 {
268 ✗ ret = gate_mqtt_write_string(data_stream, msg->content.connect.will_topic, msg->content.connect.will_topic_len);
269 ✗ GATE_BREAK_IF_FAILED(ret);
270 ✗ ret = gate_mqtt_write_string(data_stream, msg->content.connect.will_message, msg->content.connect.will_message_len);
271 ✗ GATE_BREAK_IF_FAILED(ret);
272 }
273 ✗ if (GATE_FLAG_ENABLED(msg->content.connect.flags, GATE_MQTT_CONNECT_FLAG_USER))
274 {
275 ✗ ret = gate_mqtt_write_string(data_stream, msg->content.connect.user, msg->content.connect.user_len);
276 ✗ GATE_BREAK_IF_FAILED(ret);
277 }
278 ✗ if (GATE_FLAG_ENABLED(msg->content.connect.flags, GATE_MQTT_CONNECT_FLAG_PASSWORD))
279 {
280 ✗ ret = gate_mqtt_write_string(data_stream, msg->content.connect.password, msg->content.connect.password_len);
281 ✗ GATE_BREAK_IF_FAILED(ret);
282 }
283
284 /* build full packet */
285 ✗ ret = serialize_memstream_packet(output_stream, gate_mqtt_packet_connect, msg->packet_flags, data_memstream);
286 } while (0);
287 ✗ return ret;
288 }
289
290 ✗ static gate_result_t serialize_connect_ack_message(gate_stream_t* output_stream, gate_mqtt_message_t const* msg)
291 {
292 ✗ gate_result_t ret = GATE_RESULT_OK;
293 gate_memstream_impl_t data_memstream_impl;
294 char data_memstream_buffer[64];
295
296 ✗ gate_memstream_t* const data_memstream = gate_memstream_create_static_unmanaged(&data_memstream_impl, data_memstream_buffer, sizeof(data_memstream_buffer), 0);
297 ✗ gate_stream_t* const data_stream = (gate_stream_t*)data_memstream;
298
299 do
300 {
301 /* var header */
302 ✗ ret = gate_mqtt_write_byte(data_stream, msg->content.connect_ack.flags);
303 ✗ GATE_BREAK_IF_FAILED(ret);
304 ✗ ret = gate_mqtt_write_byte(data_stream, msg->content.connect_ack.return_code);
305 ✗ GATE_BREAK_IF_FAILED(ret);
306
307 /* build full packet */
308 ✗ ret = serialize_memstream_packet(output_stream, gate_mqtt_packet_connect_ack, msg->packet_flags, data_memstream);
309 ✗ GATE_BREAK_IF_FAILED(ret);
310
311 /* succeeded */
312 } while (0);
313 ✗ return ret;
314 }
315
316 ✗ static gate_result_t serialize_pubish_message(gate_stream_t* output_stream, gate_mqtt_message_t const* msg)
317 {
318 gate_result_t ret;
319 ✗ gate_size_t written = 0;
320 ✗ gate_memstream_t* data_memstream = NULL;
321 gate_stream_t* data_stream;
322
323 do
324 {
325 ✗ const gate_size_t content_len = msg->content.publish.data_len + msg->content.publish.topic_len + 5;
326 ✗ data_memstream = gate_memstream_create(content_len);
327 ✗ if (NULL == data_memstream)
328 {
329 ✗ ret = GATE_RESULT_OUTOFMEMORY;
330 ✗ break;
331 }
332 ✗ data_stream = (gate_stream_t*)data_memstream;
333
334
335 /* var header */
336 ✗ ret = gate_mqtt_write_string(data_stream, msg->content.publish.topic, msg->content.publish.topic_len);
337 ✗ GATE_BREAK_IF_FAILED(ret);
338
339 ✗ if (GATE_FLAG_ENABLED(msg->packet_flags, GATE_MQTT_FLAG_QOS1) || GATE_FLAG_ENABLED(msg->packet_flags, GATE_MQTT_FLAG_QOS2))
340 {
341 ✗ ret = gate_mqtt_write_word(data_stream, msg->content.publish.packet_identifier);
342 ✗ GATE_BREAK_IF_FAILED(ret);
343 }
344
345 /* payload */
346 ✗ ret = gate_stream_write_block(data_stream, msg->content.publish.data, msg->content.publish.data_len, &written);
347 ✗ GATE_BREAK_IF_FAILED(ret);
348
349 /* build full packet */
350 ✗ ret = serialize_memstream_packet(output_stream, gate_mqtt_packet_publish, msg->packet_flags, data_memstream);
351 ✗ GATE_BREAK_IF_FAILED(ret);
352
353 /* success case reached */
354 } while (0);
355
356 ✗ if (data_memstream != NULL)
357 {
358 ✗ gate_object_release(data_memstream);
359 }
360
361 ✗ return ret;
362 }
363
364
365 ✗ static gate_result_t serialize_nocontent_message(gate_stream_t* output_stream, gate_mqtt_message_t const* msg)
366 {
367 gate_memstream_impl_t data_memstream_impl;
368 ✗ gate_memstream_t* data_memstream = gate_memstream_create_static_unmanaged(&data_memstream_impl, NULL, 0, 0);
369 ✗ return serialize_memstream_packet(output_stream, msg->packet_type, msg->packet_flags, data_memstream);
370 }
371
372 ✗ static gate_result_t serialize_packet_identifier_only_message(gate_stream_t* output_stream, gate_mqtt_message_t const* msg, gate_uint16_t id)
373 {
374 char buffer[16];
375 gate_memstream_impl_t data_memstream_impl;
376 ✗ gate_memstream_t* data_memstream = gate_memstream_create_static_unmanaged(&data_memstream_impl, buffer, sizeof(buffer), 0);
377
378 ✗ gate_result_t result = gate_mqtt_write_word((gate_stream_t*)data_memstream, id);
379
380 ✗ if (GATE_SUCCEEDED(result))
381 {
382 ✗ result = serialize_memstream_packet(output_stream, msg->packet_type, msg->packet_flags, data_memstream);
383 }
384 ✗ return result;
385 }
386
387 ✗ static gate_result_t serialize_subscribe_message(gate_stream_t* output_stream, gate_mqtt_message_t const* msg)
388 {
389 gate_result_t ret;
390 ✗ gate_memstream_t* data_memstream = NULL;
391 gate_stream_t* data_stream;
392 gate_mqtt_subscription_t const* subscr;
393 gate_uint16_t subscr_count;
394
395 do
396 {
397 ✗ data_memstream = gate_memstream_create(128);
398 ✗ if (NULL == data_memstream)
399 {
400 ✗ ret = GATE_RESULT_OUTOFMEMORY;
401 ✗ break;
402 }
403 ✗ data_stream = (gate_stream_t*)data_memstream;
404
405
406 /* var header */
407 ✗ ret = gate_mqtt_write_word(data_stream, msg->content.subscribe.packet_identifier);
408 ✗ GATE_BREAK_IF_FAILED(ret);
409
410 /* payload */
411 ✗ subscr_count = msg->content.subscribe.topics_count;
412 ✗ subscr = msg->content.subscribe.topics;
413 ✗ for (; subscr_count > 0; --subscr_count, ++subscr)
414 {
415 ✗ ret = gate_mqtt_write_string(data_stream, subscr->topic, subscr->topic_len);
416 ✗ GATE_BREAK_IF_FAILED(ret);
417
418 ✗ ret = gate_mqtt_write_byte(data_stream, subscr->qos);
419 ✗ GATE_BREAK_IF_FAILED(ret);
420 }
421
422 ✗ GATE_BREAK_IF_FAILED(ret);
423
424 /* build full packet */
425 ✗ ret = serialize_memstream_packet(output_stream, gate_mqtt_packet_subscribe, 0x02, data_memstream);
426 ✗ GATE_BREAK_IF_FAILED(ret);
427
428 /* success case reached */
429 } while (0);
430
431 ✗ if (data_memstream != NULL)
432 {
433 ✗ gate_object_release(data_memstream);
434 }
435
436 ✗ return ret;
437 }
438
439 ✗ static gate_result_t serialize_subscribe_ack_message(gate_stream_t* output_stream, gate_mqtt_message_t const* msg)
440 {
441 gate_result_t ret;
442 ✗ gate_memstream_t* data_memstream = NULL;
443 gate_stream_t* data_stream;
444 gate_uint8_t const* ret_codes;
445 gate_uint16_t ret_codes_count;
446
447 do
448 {
449 ✗ data_memstream = gate_memstream_create(128);
450 ✗ if (NULL == data_memstream)
451 {
452 ✗ ret = GATE_RESULT_OUTOFMEMORY;
453 ✗ break;
454 }
455 ✗ data_stream = (gate_stream_t*)data_memstream;
456
457
458 /* var header */
459 ✗ ret = gate_mqtt_write_word(data_stream, msg->content.subscribe_ack.packet_identifier);
460 ✗ GATE_BREAK_IF_FAILED(ret);
461
462 /* payload */
463 ✗ ret_codes_count = msg->content.subscribe_ack.ret_codes_count;
464 ✗ ret_codes = msg->content.subscribe_ack.ret_codes;
465 ✗ for (; ret_codes_count > 0; --ret_codes_count, ++ret_codes)
466 {
467 ✗ ret = gate_mqtt_write_byte(data_stream, *ret_codes);
468 ✗ GATE_BREAK_IF_FAILED(ret);
469 }
470
471 ✗ GATE_BREAK_IF_FAILED(ret);
472
473 /* build full packet */
474 ✗ ret = serialize_memstream_packet(output_stream, gate_mqtt_packet_subscribe_ack, msg->packet_flags, data_memstream);
475 ✗ GATE_BREAK_IF_FAILED(ret);
476
477 /* success case reached */
478 } while (0);
479
480 ✗ if (data_memstream != NULL)
481 {
482 ✗ gate_object_release(data_memstream);
483 }
484
485 ✗ return ret;
486 }
487
488 ✗ static gate_result_t serialize_unsubscribe_message(gate_stream_t* output_stream, gate_mqtt_message_t const* msg)
489 {
490 gate_result_t ret;
491 ✗ gate_memstream_t* data_memstream = NULL;
492 gate_stream_t* data_stream;
493 gate_mqtt_subscription_t const* subscr;
494 gate_uint16_t subscr_count;
495
496 do
497 {
498 ✗ data_memstream = gate_memstream_create(128);
499 ✗ if (NULL == data_memstream)
500 {
501 ✗ ret = GATE_RESULT_OUTOFMEMORY;
502 ✗ break;
503 }
504 ✗ data_stream = (gate_stream_t*)data_memstream;
505
506
507 /* var header */
508 ✗ ret = gate_mqtt_write_word(data_stream, msg->content.subscribe.packet_identifier);
509 ✗ GATE_BREAK_IF_FAILED(ret);
510
511 /* payload */
512 ✗ subscr_count = msg->content.unsubscribe.topics_count;
513 ✗ subscr = msg->content.unsubscribe.topics;
514 ✗ for (; subscr_count > 0; --subscr_count, ++subscr)
515 {
516 ✗ ret = gate_mqtt_write_string(data_stream, subscr->topic, subscr->topic_len);
517 ✗ GATE_BREAK_IF_FAILED(ret);
518 }
519
520 ✗ GATE_BREAK_IF_FAILED(ret);
521
522 /* build full packet */
523 ✗ ret = serialize_memstream_packet(output_stream, gate_mqtt_packet_subscribe, msg->packet_flags, data_memstream);
524 ✗ GATE_BREAK_IF_FAILED(ret);
525
526 /* success case reached */
527 } while (0);
528
529 ✗ if (data_memstream != NULL)
530 {
531 ✗ gate_object_release(data_memstream);
532 }
533
534 ✗ return ret;
535 }
536
537
538 ✗ gate_result_t gate_mqtt_send_message(gate_stream_t* mqtt_stream, gate_mqtt_message_t const* msg)
539 {
540 ✗ if (!mqtt_stream || !msg)
541 {
542 ✗ return GATE_RESULT_INVALIDARG;
543 }
544
545 ✗ switch (msg->packet_type)
546 {
547 ✗ case gate_mqtt_packet_connect: return serialize_connect_message(mqtt_stream, msg);
548 ✗ case gate_mqtt_packet_connect_ack: return serialize_connect_ack_message(mqtt_stream, msg);
549 ✗ case gate_mqtt_packet_publish: return serialize_pubish_message(mqtt_stream, msg);
550 ✗ case gate_mqtt_packet_publish_ack: return serialize_packet_identifier_only_message(mqtt_stream, msg, msg->content.publish_ack.packet_identifier);
551 ✗ case gate_mqtt_packet_publish_receive: return serialize_packet_identifier_only_message(mqtt_stream, msg, msg->content.publish_received.packet_identifier);
552 ✗ case gate_mqtt_packet_publish_release: return serialize_packet_identifier_only_message(mqtt_stream, msg, msg->content.publish_release.packet_identifier);
553 ✗ case gate_mqtt_packet_publish_complete: return serialize_packet_identifier_only_message(mqtt_stream, msg, msg->content.publish_complete.packet_identifier);
554 ✗ case gate_mqtt_packet_subscribe: return serialize_subscribe_message(mqtt_stream, msg);
555 ✗ case gate_mqtt_packet_subscribe_ack: return serialize_subscribe_ack_message(mqtt_stream, msg);
556 ✗ case gate_mqtt_packet_unsubscribe: return serialize_unsubscribe_message(mqtt_stream, msg);
557 ✗ case gate_mqtt_packet_unsubscribe_ack: return serialize_packet_identifier_only_message(mqtt_stream, msg, msg->content.unsubscribe_ack.packet_identifier);
558 ✗ case gate_mqtt_packet_ping_request: return serialize_nocontent_message(mqtt_stream, msg);
559 ✗ case gate_mqtt_packet_ping_response: return serialize_nocontent_message(mqtt_stream, msg);
560 ✗ case gate_mqtt_packet_disconnect: return serialize_nocontent_message(mqtt_stream, msg);
561 ✗ default: return GATE_RESULT_NOTSUPPORTED;
562 }
563 }
564
565 ✗ static gate_result_t deserialize_connect(gate_memoryblock_t* block, gate_mqtt_message_t* msg)
566 {
567 ✗ gate_result_t ret = GATE_RESULT_FAILED;
568
569 do
570 {
571 gate_size_t offset;
572 ✗ gate_strbuilder_t builder = GATE_INIT_EMPTY;
573 char buffer[4096];
574 gate_memstream_impl_t block_stream;
575 ✗ char const* const ptr_block_content = (char const*)gate_memoryblock_get_content(block);
576 ✗ gate_size_t const block_content_len = gate_memoryblock_get_size(block);
577
578 ✗ gate_stream_t* const strm = (gate_stream_t*)gate_memstream_create_static_unmanaged_readonly(
579 &block_stream, ptr_block_content, block_content_len, block_content_len);
580
581 ✗ if (strm == NULL)
582 {
583 ✗ ret = GATE_RESULT_OUTOFMEMORY;
584 ✗ break;
585 }
586
587 ✗ gate_strbuilder_create_static(&builder, buffer, sizeof(buffer), 0);
588
589 ✗ ret = gate_mqtt_read_string(strm, &builder);
590 ✗ GATE_BREAK_IF_FAILED(ret);
591
592 ✗ if (gate_str_compare(gate_strbuilder_ptr(&builder, 0), gate_strbuilder_length(&builder), "MQTT", 4) != 0)
593 {
594 /* Not a valid MQTT connect message */
595 ✗ ret = GATE_RESULT_INVALIDHEADER;
596 ✗ break;
597 }
598
599 ✗ ret = gate_mqtt_read_byte(strm, &msg->content.connect.level);
600 ✗ GATE_BREAK_IF_FAILED(ret);
601
602 ✗ ret = gate_mqtt_read_byte(strm, &msg->content.connect.flags);
603 ✗ GATE_BREAK_IF_FAILED(ret);
604
605 ✗ ret = gate_mqtt_read_word(strm, &msg->content.connect.keep_alive);
606 ✗ GATE_BREAK_IF_FAILED(ret);
607
608 ✗ offset = 10; /* payload starts at block offset 10: */
609
610 /* read client id */
611 ✗ gate_mqtt_read_string_length_skip_data(strm, &msg->content.connect.client_id_len);
612 ✗ offset += 2;
613 ✗ msg->content.connect.client_id = &ptr_block_content[offset];
614 ✗ offset += msg->content.connect.client_id_len;
615
616 ✗ if (GATE_FLAG_ENABLED(msg->content.connect.flags, GATE_MQTT_CONNECT_FLAG_WILLFLAG))
617 {
618 /* read optional will topic+content */
619 ✗ gate_mqtt_read_string_length_skip_data(strm, &msg->content.connect.will_topic_len);
620 ✗ offset += 2;
621 ✗ msg->content.connect.will_topic = &ptr_block_content[offset];
622 ✗ offset += msg->content.connect.will_topic_len;
623
624 ✗ gate_mqtt_read_string_length_skip_data(strm, &msg->content.connect.will_message_len);
625 ✗ offset += 2;
626 ✗ msg->content.connect.will_message = &ptr_block_content[offset];
627 ✗ offset += msg->content.connect.will_message_len;
628 }
629
630 ✗ if (GATE_FLAG_ENABLED(msg->content.connect.flags, GATE_MQTT_CONNECT_FLAG_USER))
631 {
632 /* read optional user string */
633 ✗ gate_mqtt_read_string_length_skip_data(strm, &msg->content.connect.user_len);
634 ✗ offset += 2;
635 ✗ msg->content.connect.user = &ptr_block_content[offset];
636 ✗ offset += msg->content.connect.user_len;
637 }
638
639 ✗ if (GATE_FLAG_ENABLED(msg->content.connect.flags, GATE_MQTT_CONNECT_FLAG_PASSWORD))
640 {
641 /* read optional will topic+content */
642 ✗ gate_mqtt_read_string_length_skip_data(strm, &msg->content.connect.password_len);
643 ✗ offset += 2;
644 ✗ msg->content.connect.password = &ptr_block_content[offset];
645 ✗ offset += msg->content.connect.password_len;
646 }
647 } while (0);
648
649 ✗ return ret;
650 }
651
652
653 ✗ static gate_result_t deserialize_connect_ack(gate_memoryblock_t* block, gate_mqtt_message_t* msg)
654 {
655 ✗ gate_result_t ret = GATE_RESULT_FAILED;
656 ✗ gate_uint8_t ack_flags = 0;
657 ✗ gate_uint8_t ret_code = 0;
658
659 do
660 {
661 gate_memstream_impl_t block_stream;
662 ✗ char const* const ptr_block_content = (char const*)gate_memoryblock_get_content(block);
663 ✗ gate_size_t const block_content_len = gate_memoryblock_get_size(block);
664
665 ✗ gate_stream_t* const strm = (gate_stream_t*)gate_memstream_create_static_unmanaged_readonly(
666 &block_stream, ptr_block_content, block_content_len, block_content_len);
667
668 ✗ if (strm == NULL)
669 {
670 ✗ ret = GATE_RESULT_OUTOFMEMORY;
671 ✗ break;
672 }
673
674
675 ✗ if (block_content_len != 2)
676 {
677 ✗ ret = GATE_RESULT_INVALIDHEADER;
678 ✗ break;
679 }
680
681 ✗ ret = gate_mqtt_read_byte(strm, &ack_flags);
682 ✗ GATE_BREAK_IF_FAILED(ret);
683 ✗ ret = gate_mqtt_read_byte(strm, &ret_code);
684 ✗ GATE_BREAK_IF_FAILED(ret);
685
686 ✗ msg->content.connect_ack.flags = ack_flags;
687 ✗ msg->content.connect_ack.return_code = ret_code;
688 } while (0);
689
690 ✗ return ret;
691 }
692
693 ✗ static gate_result_t deserialize_package_identifier_only_message(gate_memoryblock_t* block, gate_uint16_t* ptr_packet_id)
694 {
695 gate_result_t ret;
696 ✗ void const* const ptr_block_data = gate_memoryblock_get_content(block);
697 ✗ gate_size_t const block_len = gate_memoryblock_get_size(block);
698
699 do
700 {
701 gate_memstream_impl_t data_strm;
702 ✗ gate_stream_t* input_strm = (gate_stream_t*)gate_memstream_create_static_unmanaged_readonly(
703 &data_strm, ptr_block_data, block_len, block_len);
704 ✗ if (input_strm == NULL)
705 {
706 ✗ ret = GATE_RESULT_OUTOFMEMORY;
707 ✗ break;
708 }
709
710 ✗ ret = gate_mqtt_read_word(input_strm, ptr_packet_id);
711 ✗ GATE_BREAK_IF_FAILED(ret);
712
713 /* success case reached */
714 } while (0);
715
716 ✗ return ret;
717
718 }
719
720 ✗ static gate_result_t deserialize_publish(gate_memoryblock_t* block, gate_mqtt_message_t* msg)
721 {
722 ✗ gate_result_t ret = GATE_RESULT_FAILED;
723
724 do
725 {
726 gate_size_t offset;
727 gate_memstream_impl_t block_stream;
728 ✗ char const* const ptr_block_content = (char const*)gate_memoryblock_get_content(block);
729 ✗ gate_size_t const block_content_len = gate_memoryblock_get_size(block);
730
731 ✗ gate_stream_t* const strm = (gate_stream_t*)gate_memstream_create_static_unmanaged_readonly(
732 &block_stream, ptr_block_content, block_content_len, block_content_len);
733
734 ✗ if (strm == NULL)
735 {
736 ✗ ret = GATE_RESULT_OUTOFMEMORY;
737 ✗ break;
738 }
739
740 ✗ ret = gate_mqtt_read_string_length_skip_data(strm, &msg->content.publish.topic_len);
741 ✗ GATE_BREAK_IF_FAILED(ret);
742 ✗ offset = 2;
743 ✗ msg->content.publish.topic = &ptr_block_content[offset];
744 ✗ offset += msg->content.publish.topic_len;
745
746 ✗ if (GATE_FLAG_ENABLED(msg->packet_flags, GATE_MQTT_FLAG_QOS1) || GATE_FLAG_ENABLED(msg->packet_flags, GATE_MQTT_FLAG_QOS2))
747 {
748 ✗ ret = gate_mqtt_read_word(strm, &msg->content.publish.packet_identifier);
749 ✗ GATE_BREAK_IF_FAILED(ret);
750 ✗ offset += 2;
751 }
752 else
753 {
754 ✗ msg->content.publish.packet_identifier = 0;
755 }
756
757 ✗ msg->content.publish.data_len = (gate_uint32_t)(block_content_len - offset);
758 ✗ msg->content.publish.data = &ptr_block_content[offset];
759
760 /* success case reached */
761 } while (0);
762
763 ✗ return ret;
764 }
765
766 ✗ static gate_result_t deserialize_subscribe(gate_memoryblock_t* block, gate_mqtt_message_t* msg)
767 {
768 ✗ gate_result_t ret = GATE_RESULT_FAILED;
769
770 do
771 {
772 gate_size_t offset;
773 gate_memstream_impl_t block_stream;
774 ✗ char const* const ptr_block_content = (char const*)gate_memoryblock_get_content(block);
775 ✗ gate_size_t const block_content_len = gate_memoryblock_get_size(block);
776
777 ✗ gate_stream_t* const strm = (gate_stream_t*)gate_memstream_create_static_unmanaged_readonly(
778 &block_stream, ptr_block_content, block_content_len, block_content_len);
779
780 ✗ if (strm == NULL)
781 {
782 ✗ ret = GATE_RESULT_OUTOFMEMORY;
783 ✗ break;
784 }
785
786 ✗ ret = gate_mqtt_read_word(strm, &msg->content.subscribe.packet_identifier);
787 ✗ GATE_BREAK_IF_FAILED(ret);
788
789 ✗ offset = 2;
790 ✗ msg->content.subscribe.topics_count = 0;
791 ✗ while ((gate_memstream_size(&block_stream) >= 4) && (msg->content.subscribe.topics_count < GATE_MQTT_ARRAY_MAX))
792 {
793 ✗ gate_mqtt_subscription_t* ptr_sub = &msg->content.subscribe.topics[msg->content.subscribe.topics_count];
794
795 ✗ ret = gate_mqtt_read_string_length_skip_data(strm, &ptr_sub->topic_len);
796 ✗ GATE_BREAK_IF_FAILED(ret);
797 ✗ offset += 2;
798 ✗ ptr_sub->topic = &ptr_block_content[offset];
799 ✗ offset += ptr_sub->topic_len;
800
801 ✗ ret = gate_mqtt_read_byte(strm, &ptr_sub->qos);
802 ✗ GATE_BREAK_IF_FAILED(ret);
803 ✗ offset += 1;
804
805 ✗ ++msg->content.subscribe.topics_count;
806 }
807 ✗ GATE_BREAK_IF_FAILED(ret);
808
809 /* success case reached */
810 } while (0);
811
812 ✗ return ret;
813 }
814
815 ✗ static gate_result_t deserialize_subscribe_ack(gate_memoryblock_t* block, gate_mqtt_message_t* msg)
816 {
817 ✗ gate_result_t ret = GATE_RESULT_FAILED;
818
819 do
820 {
821 gate_size_t offset;
822 gate_memstream_impl_t block_stream;
823 ✗ char const* const ptr_block_content = (char const*)gate_memoryblock_get_content(block);
824 ✗ gate_size_t const block_content_len = gate_memoryblock_get_size(block);
825
826 ✗ gate_stream_t* const strm = (gate_stream_t*)gate_memstream_create_static_unmanaged_readonly(
827 &block_stream, ptr_block_content, block_content_len, block_content_len);
828
829 ✗ if (strm == NULL)
830 {
831 ✗ ret = GATE_RESULT_OUTOFMEMORY;
832 ✗ break;
833 }
834
835 ✗ ret = gate_mqtt_read_word(strm, &msg->content.subscribe_ack.packet_identifier);
836 ✗ GATE_BREAK_IF_FAILED(ret);
837
838 ✗ offset = 2;
839 ✗ msg->content.subscribe_ack.ret_codes_count = 0;
840 ✗ while ((gate_memstream_size(&block_stream) > 0) && (msg->content.subscribe_ack.ret_codes_count < GATE_MQTT_ARRAY_MAX))
841 {
842 ✗ ret = gate_mqtt_read_byte(strm, &msg->content.subscribe_ack.ret_codes[msg->content.subscribe_ack.ret_codes_count]);
843 ✗ GATE_BREAK_IF_FAILED(ret);
844
845 ✗ ++msg->content.subscribe_ack.ret_codes_count;
846 }
847 ✗ GATE_BREAK_IF_FAILED(ret);
848
849 /* success case reached */
850 } while (0);
851
852 ✗ return ret;
853 }
854
855 ✗ static gate_result_t deserialize_unsubscribe(gate_memoryblock_t* block, gate_mqtt_message_t* msg)
856 {
857 ✗ gate_result_t ret = GATE_RESULT_FAILED;
858
859 do
860 {
861 gate_size_t offset;
862 gate_memstream_impl_t block_stream;
863 ✗ char const* const ptr_block_content = (char const*)gate_memoryblock_get_content(block);
864 ✗ gate_size_t const block_content_len = gate_memoryblock_get_size(block);
865
866 ✗ gate_stream_t* const strm = (gate_stream_t*)gate_memstream_create_static_unmanaged_readonly(
867 &block_stream, ptr_block_content, block_content_len, block_content_len);
868
869 ✗ if (strm == NULL)
870 {
871 ✗ ret = GATE_RESULT_OUTOFMEMORY;
872 ✗ break;
873 }
874
875 ✗ ret = gate_mqtt_read_word(strm, &msg->content.unsubscribe.packet_identifier);
876 ✗ GATE_BREAK_IF_FAILED(ret);
877
878 ✗ offset = 2;
879 ✗ msg->content.unsubscribe.topics_count = 0;
880 ✗ while ((gate_memstream_size(&block_stream) >= 3) && (msg->content.unsubscribe.topics_count < GATE_MQTT_ARRAY_MAX))
881 {
882 ✗ gate_mqtt_subscription_t* ptr_sub = &msg->content.unsubscribe.topics[msg->content.unsubscribe.topics_count];
883
884 ✗ ret = gate_mqtt_read_string_length_skip_data(strm, &ptr_sub->topic_len);
885 ✗ GATE_BREAK_IF_FAILED(ret);
886 ✗ offset += 2;
887 ✗ ptr_sub->topic = &ptr_block_content[offset];
888 ✗ offset += ptr_sub->topic_len;
889
890 ✗ ptr_sub->qos = 0;
891
892 ✗ ++msg->content.unsubscribe.topics_count;
893 }
894 ✗ GATE_BREAK_IF_FAILED(ret);
895
896 /* success case reached */
897 } while (0);
898
899 ✗ return ret;
900 }
901
902
903 ✗ gate_result_t gate_mqtt_has_queued_message(gate_stream_t* mqtt_stream)
904 {
905 ✗ gate_result_t ret = GATE_RESULT_FAILED;
906 char buffer[1024];
907 ✗ char* ptr_buffer = &buffer[0];
908 ✗ gate_size_t buffer_capacity = sizeof(buffer);
909 gate_size_t returned;
910 gate_memstream_impl_t memstrm;
911 ✗ gate_stream_t* strm = NULL;
912
913 do
914 {
915 ✗ gate_uint8_t fixed_header_byte = 0;
916 ✗ gate_size_t fixed_header_contentlen = 0;
917 gate_size_t remaining_bytes;
918 gate_size_t fixed_header_length;
919 gate_size_t total_packet_length;
920
921 ✗ ret = gate_stream_peek(mqtt_stream, ptr_buffer, buffer_capacity, &returned);
922 ✗ GATE_BREAK_IF_FAILED(ret);
923
924 ✗ if (returned < 2)
925 {
926 ✗ ret = GATE_RESULT_ENDOFSTREAM;
927 ✗ break;
928 }
929
930 ✗ strm = (gate_stream_t*)gate_memstream_create_static_unmanaged_readonly(&memstrm, ptr_buffer, returned, returned);
931 ✗ if (!strm)
932 {
933 ✗ ret = GATE_RESULT_OUTOFMEMORY;
934 ✗ break;
935 }
936
937 ✗ ret = gate_mqtt_read_byte(strm, &fixed_header_byte);
938 ✗ GATE_BREAK_IF_FAILED(ret);
939
940 ✗ ret = gate_mqtt_read_length(strm, &fixed_header_contentlen);
941 ✗ GATE_BREAK_IF_FAILED(ret);
942
943 ✗ remaining_bytes = gate_memstream_size(&memstrm);
944 ✗ GATE_DEBUG_ASSERT(returned >= remaining_bytes);
945 ✗ fixed_header_length = returned - remaining_bytes;
946 ✗ total_packet_length = fixed_header_length + fixed_header_contentlen;
947
948 ✗ if (total_packet_length > buffer_capacity)
949 {
950 ✗ ptr_buffer = (char*)gate_mem_alloc(total_packet_length);
951 ✗ if (ptr_buffer == NULL)
952 {
953 ✗ ret = GATE_RESULT_OUTOFMEMORY;
954 ✗ break;
955 }
956 }
957
958 ✗ ret = gate_stream_peek(mqtt_stream, ptr_buffer, total_packet_length, &returned);
959 ✗ GATE_BREAK_IF_FAILED(ret);
960
961 ✗ if (returned < total_packet_length)
962 {
963 /* not enough bytes in stream to decode a full package */
964 ✗ ret = GATE_RESULT_ENDOFSTREAM;
965 ✗ break;
966 }
967
968 /* success case, we have a full packet in the stream */
969 ✗ ret = GATE_RESULT_OK;
970 } while (0);
971
972 ✗ if ((ptr_buffer != NULL) && (ptr_buffer != &buffer[0]))
973 {
974 ✗ gate_mem_dealloc(ptr_buffer);
975 }
976
977 ✗ return ret;
978 }
979
980
981 ✗ gate_result_t gate_mqtt_receive_message(gate_stream_t* mqtt_stream, gate_mqtt_message_t* msg, gate_memoryblock_t** ptr_new_memblock)
982 {
983 gate_result_t ret;
984 ✗ gate_memoryblock_t* mem_block = NULL;
985
986 do
987 {
988 ✗ gate_uint8_t fixed_header_byte = 0;
989 ✗ gate_size_t fixed_header_len = 0;
990 ✗ gate_uint64_t content_transferred = 0;
991
992 ✗ if (!mqtt_stream || !msg || !ptr_new_memblock)
993 {
994 ✗ ret = GATE_RESULT_INVALIDARG;
995 ✗ break;
996 }
997
998 ✗ ret = gate_mqtt_read_byte(mqtt_stream, &fixed_header_byte);
999 ✗ GATE_BREAK_IF_FAILED(ret);
1000
1001 ✗ ret = gate_mqtt_read_length(mqtt_stream, &fixed_header_len);
1002 ✗ GATE_BREAK_IF_FAILED(ret);
1003
1004 ✗ msg->packet_type = (gate_mqtt_packet_type_t)((fixed_header_byte & 0xf0) >> 4);
1005 ✗ msg->packet_flags = fixed_header_byte & 0x0f;
1006
1007 ✗ if (fixed_header_len > 0)
1008 {
1009 gate_memstream_impl_t memstream;
1010
1011 ✗ mem_block = gate_memoryblock_create(fixed_header_len);
1012 ✗ if (NULL == mem_block)
1013 {
1014 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1015 ✗ break;
1016 }
1017
1018 ✗ if (NULL == gate_memstream_create_static_unmanaged(&memstream, gate_memoryblock_get_content(mem_block), gate_memoryblock_get_size(mem_block), 0))
1019 {
1020 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1021 ✗ break;
1022 }
1023
1024 ✗ ret = gate_stream_transfer_limit(mqtt_stream, fixed_header_len, (gate_stream_t*)&memstream, &content_transferred);
1025 ✗ GATE_BREAK_IF_FAILED(ret);
1026 ✗ if (content_transferred < fixed_header_len)
1027 {
1028 ✗ ret = GATE_RESULT_ENDOFSTREAM;
1029 ✗ break;
1030 }
1031 }
1032
1033 ✗ switch (msg->packet_type)
1034 {
1035 ✗ case gate_mqtt_packet_connect:
1036 ✗ ret = deserialize_connect(mem_block, msg);
1037 ✗ break;
1038 ✗ case gate_mqtt_packet_connect_ack:
1039 ✗ ret = deserialize_connect_ack(mem_block, msg);
1040 ✗ break;
1041 ✗ case gate_mqtt_packet_publish:
1042 ✗ ret = deserialize_publish(mem_block, msg);
1043 ✗ break;
1044 ✗ case gate_mqtt_packet_publish_ack:
1045 ✗ ret = deserialize_package_identifier_only_message(mem_block, &msg->content.publish_ack.packet_identifier);
1046 ✗ break;
1047 ✗ case gate_mqtt_packet_publish_receive:
1048 ✗ ret = deserialize_package_identifier_only_message(mem_block, &msg->content.publish_received.packet_identifier);
1049 ✗ break;
1050 ✗ case gate_mqtt_packet_publish_release:
1051 ✗ ret = deserialize_package_identifier_only_message(mem_block, &msg->content.publish_release.packet_identifier);
1052 ✗ break;
1053 ✗ case gate_mqtt_packet_publish_complete:
1054 ✗ ret = deserialize_package_identifier_only_message(mem_block, &msg->content.publish_complete.packet_identifier);
1055 ✗ break;
1056 ✗ case gate_mqtt_packet_subscribe:
1057 ✗ ret = deserialize_subscribe(mem_block, msg);
1058 ✗ break;
1059 ✗ case gate_mqtt_packet_subscribe_ack:
1060 ✗ ret = deserialize_subscribe_ack(mem_block, msg);
1061 ✗ break;
1062 ✗ case gate_mqtt_packet_unsubscribe:
1063 ✗ ret = deserialize_unsubscribe(mem_block, msg);
1064 ✗ break;
1065 ✗ case gate_mqtt_packet_unsubscribe_ack:
1066 ✗ ret = deserialize_package_identifier_only_message(mem_block, &msg->content.unsubscribe_ack.packet_identifier);
1067 ✗ break;
1068
1069 ✗ case gate_mqtt_packet_ping_request:
1070 case gate_mqtt_packet_ping_response:
1071 case gate_mqtt_packet_disconnect:
1072 /* no content to deserialize */
1073 ✗ break;
1074 ✗ default:
1075 ✗ ret = GATE_RESULT_NOTSUPPORTED;
1076 ✗ break;
1077 }
1078 ✗ GATE_BREAK_IF_FAILED(ret);
1079
1080 ✗ if (ptr_new_memblock != NULL)
1081 {
1082 ✗ *ptr_new_memblock = mem_block;
1083 ✗ mem_block = NULL;
1084 }
1085 } while (0);
1086
1087 ✗ if (mem_block)
1088 {
1089 ✗ gate_object_release(mem_block);
1090 ✗ mem_block = NULL;
1091 }
1092
1093 ✗ return ret;
1094 }
1095