mqtt_sn_message.c
Go to the documentation of this file.
1 /**
2  * @file mqtt_sn_message.c
3  * @brief MQTT-SN message formatting and parsing
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL MQTT_SN_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "mqtt_sn/mqtt_sn_client.h"
38 #include "debug.h"
39 
40 //Check TCP/IP stack configuration
41 #if (MQTT_SN_CLIENT_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Format MQTT-SN message header
46  * @param[in] message Pointer to the MQTT-SN message
47  * @param[in] type Message type
48  * @param[in] length Length of the message, in bytes
49  * @return Error code
50  **/
51 
53  size_t length)
54 {
55  //Check the length of the message
56  if((length + sizeof(MqttSnHeader)) < UINT8_MAX)
57  {
58  MqttSnHeader *header;
59 
60  //Make room for the message header (2 bytes)
61  osMemmove(message->buffer + sizeof(MqttSnHeader), message->buffer,
62  length);
63 
64  //The Length field specifies the total number of octets contained in
65  //the message, including the Length field itself
66  length += sizeof(MqttSnHeader);
67 
68  //Point to the buffer where to format the message header
69  header = (MqttSnHeader *) message->buffer;
70 
71  //The Length field is 1-octet long
72  header->length = (uint8_t) length;
73  //The MsgType specifies the message type
74  header->msgType = type;
75  }
76  else
77  {
78  MqttSnExtHeader *header;
79 
80  //Make room for the message header (4 bytes)
81  osMemmove(message->buffer + sizeof(MqttSnExtHeader), message->buffer,
82  length);
83 
84  //The Length field specifies the total number of octets contained in
85  //the message, including the Length field itself
86  length += sizeof(MqttSnExtHeader);
87 
88  //Point to the buffer where to format the message header
89  header = (MqttSnExtHeader *) message->buffer;
90 
91  //The Length field is 3-octet long
92  header->prefix = 0x01;
93  header->length = htons(length);
94  //The MsgType specifies the message type
95  header->msgType = type;
96  }
97 
98  //Terminate the payload with a NULL character
99  message->buffer[length] = '\0';
100 
101  //Save the length of the message
102  message->length = length;
103 
104  //Successful processing
105  return NO_ERROR;
106 }
107 
108 
109 /**
110  * @brief Format SEARCHGW message
111  * @param[in] message Pointer to the MQTT-SN message
112  * @param[in] radius Broadcast radius of SEARCHGW message
113  * @return Error code
114  **/
115 
117  uint8_t radius)
118 {
119  size_t length;
120  MqttSnSearchGw *searchGw;
121 
122  //Point to the buffer where to format the message
123  searchGw = (MqttSnSearchGw *) message->buffer;
124 
125  //Format SEARCHGW message
126  searchGw->radius = 0;
127 
128  //Compute the length of the message
129  length = sizeof(MqttSnSearchGw);
130 
131  //Format MQTT-SN message header
133 }
134 
135 
136 /**
137  * @brief Format CONNECT message
138  * @param[in] message Pointer to the MQTT-SN message
139  * @param[in] flags Flags
140  * @param[in] duration Value of the keep-alive timer
141  * @param[in] clientId Client identifier
142  * @return Error code
143  **/
144 
146  uint16_t duration, const char_t *clientId)
147 {
148  size_t length;
150 
151  //Point to the buffer where to format the message
152  connect = (MqttSnConnect *) message->buffer;
153 
154  //Format CONNECT message
155  connect->flags = flags;
156  connect->protocolId = MQTT_SN_PROTOCOL_ID;
157  connect->duration = htons(duration);
158 
159  //Copy client identifier
160  osStrcpy(connect->clientId, clientId);
161 
162  //Compute the length of the message
163  length = sizeof(MqttSnConnect) + osStrlen(clientId);
164 
165  //Format MQTT-SN message header
167 }
168 
169 
170 /**
171  * @brief Format WILLTOPIC message
172  * @param[in] message Pointer to the MQTT-SN message
173  * @param[in] flags Flags
174  * @param[in] topicName Topic name
175  * @return Error code
176  **/
177 
179  const char_t *topicName)
180 {
181  size_t length;
183 
184  //Point to the buffer where to format the message
185  willTopic = (MqttSnWillTopic *) message->buffer;
186 
187  //Valid Will topic?
188  if(topicName[0] != '\0')
189  {
190  //Format WILLTOPICUPD message
191  willTopic->flags = flags;
192  osStrcpy(willTopic->willTopic, topicName);
193 
194  //Compute the length of the message
196  }
197  else
198  {
199  //An empty WILLTOPIC message (without Flags and WillTopic field) is
200  //used by a client to delete the Will topic and the Will message stored
201  //in the server
202  length = 0;
203  }
204 
205  //Format MQTT-SN message header
207 }
208 
209 
210 /**
211  * @brief Format WILLMSG message
212  * @param[in] message Pointer to the MQTT-SN message
213  * @param[in] data Will message
214  * @param[in] dataLen Length of the Will message
215  * @return Error code
216  **/
217 
219  size_t dataLen)
220 {
221  MqttSnWillMsg *willMsg;
222 
223  //Point to the buffer where to format the message
224  willMsg = (MqttSnWillMsg *) message->buffer;
225 
226  //Copy Will message
227  osMemcpy(willMsg, data, dataLen);
228 
229  //Format MQTT-SN message header
231 }
232 
233 
234 /**
235  * @brief Format REGISTER message
236  * @param[in] message Pointer to the MQTT-SN message
237  * @param[in] msgId Message identifier
238  * @param[in] topicId Topic identifier
239  * @param[in] topicName Topic name
240  * @return Error code
241  **/
242 
244  uint16_t msgId, uint16_t topicId, const char_t *topicName)
245 {
246  size_t length;
247  MqttSnRegister *reg;
248 
249  //Point to the buffer where to format the message
250  reg = (MqttSnRegister *) message->buffer;
251 
252  //Format REGISTER message
253  reg->topicId = htons(topicId);
254  reg->msgId = htons(msgId);
255 
256  //Copy topic name
257  osStrcpy(reg->topicName, topicName);
258 
259  //Compute the length of the message
261 
262  //Format MQTT-SN message header
264 }
265 
266 
267 /**
268  * @brief Format REGACK message
269  * @param[in] message Pointer to the MQTT-SN message
270  * @param[in] msgId Message identifier
271  * @param[in] topicId Topic identifier
272  * @param[in] returnCode Return code
273  * @return Error code
274  **/
275 
278 {
279  size_t length;
280  MqttSnRegAck *regAck;
281 
282  //Point to the buffer where to format the message
283  regAck = (MqttSnRegAck *) message->buffer;
284 
285  //Format REGACK message
286  regAck->topicId = htons(topicId);
287  regAck->msgId = htons(msgId);
288  regAck->returnCode = returnCode;
289 
290  //Compute the length of the message
291  length = sizeof(MqttSnRegAck);
292 
293  //Format MQTT-SN message header
295 }
296 
297 
298 /**
299  * @brief Format PUBLISH message
300  * @param[in] message Pointer to the MQTT-SN message
301  * @param[in] flags Flags
302  * @param[in] msgId Message identifier
303  * @param[in] topicId Topic identifier
304  * @param[in] topicName Short topic name
305  * @param[in] data Message payload
306  * @param[in] dataLen Length of the message payload
307  * @return Error code
308  **/
309 
311  uint16_t msgId, uint16_t topicId, const char_t *topicName,
312  const uint8_t *data, size_t dataLen)
313 {
314  error_t error;
315  size_t length;
316  MqttSnPublish *publish;
317 
318  //Initialize status code
319  error = NO_ERROR;
320 
321  //Point to the buffer where to format the message
322  publish = (MqttSnPublish *) message->buffer;
323 
324  //Format PUBLISH message
325  publish->flags = flags;
326  publish->msgId = htons(msgId);
327 
328  //Check the type of topic identifier
329  if(flags.topicIdType == MQTT_SN_NORMAL_TOPIC_ID ||
330  flags.topicIdType == MQTT_SN_PREDEFINED_TOPIC_ID)
331  {
332  //Copy normal or predefined topic ID
333  publish->topicId = htons(topicId);
334  }
335  else if(flags.topicIdType == MQTT_SN_SHORT_TOPIC_NAME)
336  {
337  //Make sure the short topic name is valid
338  if(topicName != NULL && osStrlen(topicName) == 2)
339  {
340  //Short topic names are topic names that have a fixed length of two
341  //octets. They are short enough for being carried together with the
342  //data within PUBLISH messages
343  publish->topicId = htons((topicName[0] << 8) | topicName[1]);
344  }
345  else
346  {
347  //Report an error
348  error = ERROR_INVALID_PARAMETER;
349  }
350  }
351  else
352  {
353  //Report an error
354  error = ERROR_INVALID_PARAMETER;
355  }
356 
357  //Check status code
358  if(!error)
359  {
360  //Copy message payload
361  osMemcpy(publish->data, data, dataLen);
362 
363  //Compute the length of the message
364  length = sizeof(MqttSnPublish) + dataLen;
365 
366  //Format MQTT-SN message header
368  }
369 
370  //Return status code
371  return error;
372 }
373 
374 
375 /**
376  * @brief Format PUBACK message
377  * @param[in] message Pointer to the MQTT-SN message
378  * @param[in] msgId Message identifier of the corresponding PUBLISH message
379  * @param[in] topicId Topic identifier
380  * @param[in] returnCode Return code
381  * @return Error code
382  **/
383 
386 {
387  size_t length;
388  MqttSnPubAck *pubAck;
389 
390  //Point to the buffer where to format the message
391  pubAck = (MqttSnPubAck *) message->buffer;
392 
393  //Format PUBACK message
394  pubAck->topicId = htons(topicId);
395  pubAck->msgId = htons(msgId);
396  pubAck->returnCode = returnCode;
397 
398  //Compute the length of the message
399  length = sizeof(MqttSnPubAck);
400 
401  //Format MQTT-SN message header
403 }
404 
405 
406 /**
407  * @brief Format PUBREC message
408  * @param[in] message Pointer to the MQTT-SN message
409  * @param[in] msgId Message identifier of the corresponding PUBLISH message
410  * @return Error code
411  **/
412 
414 {
415  size_t length;
416  MqttSnPubRec *pubRec;
417 
418  //Point to the buffer where to format the message
419  pubRec = (MqttSnPubRec *) message->buffer;
420 
421  //Format PUBREC message
422  pubRec->msgId = htons(msgId);
423 
424  //Compute the length of the message
425  length = sizeof(MqttSnPubRec);
426 
427  //Format MQTT-SN message header
429 }
430 
431 
432 /**
433  * @brief Format PUBREL message
434  * @param[in] message Pointer to the MQTT-SN message
435  * @param[in] msgId Message identifier of the corresponding PUBLISH message
436  * @return Error code
437  **/
438 
440 {
441  size_t length;
442  MqttSnPubRel *pubRel;
443 
444  //Point to the buffer where to format the message
445  pubRel = (MqttSnPubRel *) message->buffer;
446 
447  //Format PUBREL message
448  pubRel->msgId = htons(msgId);
449 
450  //Compute the length of the message
451  length = sizeof(MqttSnPubRel);
452 
453  //Format MQTT-SN message header
455 }
456 
457 
458 /**
459  * @brief Format PUBCOMP message
460  * @param[in] message Pointer to the MQTT-SN message
461  * @param[in] msgId Message identifier of the corresponding PUBLISH message
462  * @return Error code
463  **/
464 
466 {
467  size_t length;
468  MqttSnPubComp *pubComp;
469 
470  //Point to the buffer where to format the message
471  pubComp = (MqttSnPubComp *) message->buffer;
472 
473  //Format PUBCOMP message
474  pubComp->msgId = htons(msgId);
475 
476  //Compute the length of the message
477  length = sizeof(MqttSnPubComp);
478 
479  //Format MQTT-SN message header
481 }
482 
483 
484 /**
485  * @brief Format SUBSCRIBE message
486  * @param[in] message Pointer to the MQTT-SN message
487  * @param[in] flags Flags
488  * @param[in] msgId Message identifier
489  * @param[in] topicId Topic identifier
490  * @param[in] topicName Topic name
491  * @return Error code
492  **/
493 
495  uint16_t msgId, uint16_t topicId, const char_t *topicName)
496 {
497  error_t error;
498  size_t length;
499  MqttSnSubscribe *subscribe;
500 
501  //Initialize status code
502  error = NO_ERROR;
503 
504  //Point to the buffer where to format the message
505  subscribe = (MqttSnSubscribe *) message->buffer;
506 
507  //Format SUBSCRIBE message
508  subscribe->flags = flags;
509  subscribe->msgId = htons(msgId);
510 
511  //Check the type of topic identifier
512  if(flags.topicIdType == MQTT_SN_NORMAL_TOPIC_NAME)
513  {
514  //Make sure the topic name is valid
515  if(topicName != NULL)
516  {
517  //Copy topic name
518  osStrcpy(subscribe->topicName, topicName);
519  //Compute the length of the message
521  }
522  else
523  {
524  //Report an error
525  error = ERROR_INVALID_PARAMETER;
526  }
527  }
528  else if(flags.topicIdType == MQTT_SN_SHORT_TOPIC_NAME)
529  {
530  //Make sure the short topic name is valid
531  if(topicName != NULL && osStrlen(topicName) == 2)
532  {
533  //Copy topic name
534  osStrcpy(subscribe->topicName, topicName);
535  //Compute the length of the message
537  }
538  else
539  {
540  //Report an error
541  error = ERROR_INVALID_PARAMETER;
542  }
543  }
544  else if(flags.topicIdType == MQTT_SN_PREDEFINED_TOPIC_ID)
545  {
546  //Copy predefined topic ID
547  STORE16BE(topicId, subscribe->topicName);
548  //Compute the length of the message
549  length = sizeof(MqttSnSubscribe) + sizeof(uint16_t);
550  }
551  else
552  {
553  //Report an error
554  error = ERROR_INVALID_PARAMETER;
555  }
556 
557  //Check status code
558  if(!error)
559  {
560  //Format MQTT-SN message header
562  }
563 
564  //Return status code
565  return error;
566 }
567 
568 
569 /**
570  * @brief Format UNSUBSCRIBE message
571  * @param[in] message Pointer to the MQTT-SN message
572  * @param[in] flags Flags
573  * @param[in] msgId Message identifier
574  * @param[in] topicId Topic identifier
575  * @param[in] topicName Topic name
576  * @return Error code
577  **/
578 
580  uint16_t msgId, uint16_t topicId, const char_t *topicName)
581 {
582  error_t error;
583  size_t length;
584  MqttSnUnsubscribe *unsubscribe;
585 
586  //Initialize status code
587  error = NO_ERROR;
588 
589  //Point to the buffer where to format the message
590  unsubscribe = (MqttSnUnsubscribe *) message->buffer;
591 
592  //Format UNSUBSCRIBE message
593  unsubscribe->flags = flags;
594  unsubscribe->msgId = htons(msgId);
595 
596  //Check the type of topic identifier
597  if(flags.topicIdType == MQTT_SN_NORMAL_TOPIC_NAME)
598  {
599  //Make sure the topic name is valid
600  if(topicName != NULL)
601  {
602  //Copy topic name
603  osStrcpy(unsubscribe->topicName, topicName);
604  //Compute the length of the message
606  }
607  else
608  {
609  //Report an error
610  error = ERROR_INVALID_PARAMETER;
611  }
612  }
613  else if(flags.topicIdType == MQTT_SN_SHORT_TOPIC_NAME)
614  {
615  //Make sure the short topic name is valid
616  if(topicName != NULL && osStrlen(topicName) == 2)
617  {
618  //Copy topic name
619  osStrcpy(unsubscribe->topicName, topicName);
620  //Compute the length of the message
622  }
623  else
624  {
625  //Report an error
626  error = ERROR_INVALID_PARAMETER;
627  }
628  }
629  else if(flags.topicIdType == MQTT_SN_PREDEFINED_TOPIC_ID)
630  {
631  //Copy predefined topic ID
632  STORE16BE(topicId, unsubscribe->topicName);
633  //Compute the length of the message
634  length = sizeof(MqttSnSubscribe) + sizeof(uint16_t);
635  }
636  else
637  {
638  //Report an error
639  error = ERROR_INVALID_PARAMETER;
640  }
641 
642  //Check status code
643  if(!error)
644  {
645  //Format MQTT-SN message header
647  }
648 
649  //Return status code
650  return error;
651 }
652 
653 
654 /**
655  * @brief Format PINGREQ message
656  * @param[in] message Pointer to the MQTT-SN message
657  * @param[in] clientId Client identifier
658  * @return Error code
659  **/
660 
662 {
663  size_t length;
664  MqttSnPingReq *pingReq;
665 
666  //Point to the buffer where to format the message
667  pingReq = (MqttSnPingReq *) message->buffer;
668 
669  //Copy client identifier
670  osStrcpy(pingReq, clientId);
671 
672  //Compute the length of the message
674 
675  //Format MQTT-SN message header
677 }
678 
679 
680 /**
681  * @brief Format PINGRESP message
682  * @param[in] message Pointer to the MQTT-SN message
683  * @return Error code
684  **/
685 
687 {
688  size_t length;
689 
690  //The PINGRESP message has only a header and no variable part
691  length = 0;
692 
693  //Format MQTT-SN message header
695 }
696 
697 
698 /**
699  * @brief Format DISCONNECT message
700  * @param[in] message Pointer to the MQTT-SN message
701  * @param[in] duration Value of the sleep timer
702  * @return Error code
703  **/
704 
706  uint16_t duration)
707 {
708  size_t length;
709  MqttSnDisconnect *disconnect;
710 
711  //Point to the buffer where to format the message
712  disconnect = (MqttSnDisconnect *) message->buffer;
713 
714  //Check the value of the sleep timer
715  if(duration != 0)
716  {
717  //A DISCONNECT message with a Duration field is sent by a client when
718  //it wants to go to the "asleep" state
719  disconnect->duration = htons(duration);
720 
721  //Compute the length of the message
722  length = sizeof(MqttSnDisconnect);
723  }
724  else
725  {
726  //A DISCONNECT message without a Duration field is sent by a client when
727  //it wants to go to the "disconnected" state
728  length = 0;
729  }
730 
731  //Format MQTT-SN message header
733 }
734 
735 
736 /**
737  * @brief Format WILLTOPICUPD message
738  * @param[in] message Pointer to the MQTT-SN message
739  * @param[in] flags Flags
740  * @param[in] topicName Topic name
741  * @return Error code
742  **/
743 
745  const char_t *topicName)
746 {
747  size_t length;
748  MqttSnWillTopicUpd *willTopicUpd;
749 
750  //Point to the buffer where to format the message
751  willTopicUpd = (MqttSnWillTopicUpd *) message->buffer;
752 
753  //Valid Will topic?
754  if(topicName[0] != '\0')
755  {
756  //Format WILLTOPICUPD message
757  willTopicUpd->flags = flags;
758  osStrcpy(willTopicUpd->willTopic, topicName);
759 
760  //Compute the length of the message
762  }
763  else
764  {
765  //An empty WILLTOPICUPD message (without Flags and WillTopic field) is
766  //used by a client to delete the Will topic and the Will message stored
767  //in the server
768  length = 0;
769  }
770 
771  //Format MQTT-SN message header
773 }
774 
775 
776 /**
777  * @brief Format WILLMSGUPD message
778  * @param[in] message Pointer to the MQTT-SN message
779  * @param[in] data Will message
780  * @param[in] dataLen Length of the Will message
781  * @return Error code
782  **/
783 
785  size_t dataLen)
786 {
787  MqttSnWillMsgUpd *willMsgUpd;
788 
789  //Point to the buffer where to format the message
790  willMsgUpd = (MqttSnWillMsgUpd *) message->buffer;
791 
792  //Copy Will message
793  osMemcpy(willMsgUpd, data, dataLen);
794 
795  //Format MQTT-SN message header
797 }
798 
799 
800 /**
801  * @brief Format MQTT-SN message header
802  * @param[in] message Pointer to the MQTT-SN message
803  * @param[out] type Message type
804  * @return Error code
805  **/
806 
808 {
809  //Malformed MQTT-SN message?
810  if(message->length == 0)
811  return ERROR_INVALID_LENGTH;
812 
813  //Check whether the first octet is 0x01
814  if(message->buffer[0] == 0x01)
815  {
816  const MqttSnExtHeader *header;
817 
818  //Point to message header
819  header = (MqttSnExtHeader *) message->buffer;
820 
821  //Malformed message?
822  if(message->length < sizeof(MqttSnExtHeader))
823  return ERROR_INVALID_LENGTH;
824  if(message->length < ntohs(header->length))
825  return ERROR_INVALID_LENGTH;
826 
827  //The Length field is 3-octet long
828  message->length = ntohs(header->length);
829  //Point to the variable part of the message
830  message->pos = sizeof(MqttSnExtHeader);
831 
832  //Retrieve message type
833  *type = (MqttSnMsgType) header->msgType;
834  }
835  else
836  {
837  const MqttSnHeader *header;
838 
839  //Point to message header
840  header = (MqttSnHeader *) message->buffer;
841 
842  //Malformed message?
843  if(message->length < sizeof(MqttSnHeader))
844  return ERROR_INVALID_LENGTH;
845  if(message->length < header->length)
846  return ERROR_INVALID_LENGTH;
847 
848  //The Length field is 1-octet long
849  message->length = header->length;
850  //Point to the variable part of the message
851  message->pos = sizeof(MqttSnHeader);
852 
853  //Retrieve message type
854  *type = (MqttSnMsgType) header->msgType;
855  }
856 
857  //Successful processing
858  return NO_ERROR;
859 }
860 
861 
862 /**
863  * @brief Parse GWINFO message
864  * @param[in] message Pointer to the MQTT-SN message
865  * @param[out] gwId Gateway identifier
866  * @param[out] gwAdd Gateway address
867  * @param[out] gwAddLen Length of the gateway address
868  * @return Error code
869  **/
870 
872  const uint8_t **gwAdd, size_t *gwAddLen)
873 {
874  size_t n;
875  const MqttSnGwInfo *gwInfo;
876 
877  //Point to the GWINFO message
878  gwInfo = (MqttSnGwInfo *) (message->buffer + message->pos);
879  //Calculate the length of the message
880  n = message->length - message->pos;
881 
882  //Check the length of the message
883  if(n < sizeof(MqttSnGwInfo))
884  return ERROR_INVALID_LENGTH;
885 
886  //Get gateway identifier
887  *gwId = gwInfo->gwId;
888  //Get gateway address
889  *gwAdd = gwInfo->gwAdd;
890 
891  //Calculate the length of the gateway address
892  *gwAddLen = n - sizeof(MqttSnGwInfo);
893 
894  //Successful processing
895  return NO_ERROR;
896 }
897 
898 
899 /**
900  * @brief Parse CONNACK message
901  * @param[in] message Pointer to the MQTT-SN message
902  * @param[out] returnCode Return code
903  * @return Error code
904  **/
905 
908 {
909  size_t n;
910  const MqttSnConnAck *connAck;
911 
912  //Point to the CONNACK message
913  connAck = (MqttSnConnAck *) (message->buffer + message->pos);
914  //Calculate the length of the message
915  n = message->length - message->pos;
916 
917  //Check the length of the message
918  if(n < sizeof(MqttSnConnAck))
919  return ERROR_INVALID_LENGTH;
920 
921  //Get return code
922  *returnCode = (MqttSnReturnCode) connAck->returnCode;
923 
924  //Successful processing
925  return NO_ERROR;
926 }
927 
928 
929 /**
930  * @brief Parse WILLTOPICREQ message
931  * @param[in] message Pointer to the MQTT-SN message
932  * @return Error code
933  **/
934 
936 {
937  //The WILLTOPICREQ message has only a header and no variable part
938  return NO_ERROR;
939 }
940 
941 
942 /**
943  * @brief Parse WILLMSGREQ message
944  * @param[in] message Pointer to the MQTT-SN message
945  * @return Error code
946  **/
947 
949 {
950  //The WILLMSGREQ message has only a header and no variable part
951  return NO_ERROR;
952 }
953 
954 
955 /**
956  * @brief Parse REGISTER message
957  * @param[in] message Pointer to the MQTT-SN message
958  * @param[out] msgId Message identifier
959  * @param[out] topicId Topic identifier
960  * @param[out] topicName Topic name
961  * @return Error code
962  **/
963 
965  uint16_t *topicId, const char_t **topicName)
966 {
967  size_t n;
968  const MqttSnRegister *reg;
969 
970  //Point to the REGISTER message
971  reg = (MqttSnRegister *) (message->buffer + message->pos);
972  //Calculate the length of the message
973  n = message->length - message->pos;
974 
975  //Check the length of the message
976  if(n < sizeof(MqttSnRegister))
977  return ERROR_INVALID_LENGTH;
978 
979  //Get message identifier
980  *msgId = ntohs(reg->msgId);
981  //Get topic identifier
982  *topicId = ntohs(reg->topicId);
983  //Get topic name
984  *topicName = reg->topicName;
985 
986  //Successful processing
987  return NO_ERROR;
988 }
989 
990 
991 /**
992  * @brief Parse REGACK message
993  * @param[in] message Pointer to the MQTT-SN message
994  * @param[out] msgId Message identifier
995  * @param[out] topicId Topic identifier
996  * @param[out] returnCode Return code
997  * @return Error code
998  **/
999 
1001  uint16_t *topicId, MqttSnReturnCode *returnCode)
1002 {
1003  size_t n;
1004  const MqttSnRegAck *regAck;
1005 
1006  //Point to the REGACK message
1007  regAck = (MqttSnRegAck *) (message->buffer + message->pos);
1008  //Calculate the length of the message
1009  n = message->length - message->pos;
1010 
1011  //Check the length of the message
1012  if(n < sizeof(MqttSnRegAck))
1013  return ERROR_INVALID_LENGTH;
1014 
1015  //Get return code
1016  *msgId = ntohs(regAck->msgId);
1017  //Get return code
1018  *topicId = ntohs(regAck->topicId);
1019  //Get return code
1020  *returnCode = (MqttSnReturnCode) regAck->returnCode;
1021 
1022  //Successful processing
1023  return NO_ERROR;
1024 }
1025 
1026 
1027 /**
1028  * @brief Parse PUBLISH message
1029  * @param[in] message Pointer to the MQTT-SN message
1030  * @param[out] flags Flags
1031  * @param[out] msgId Message identifier
1032  * @param[out] topicId Topic identifier
1033  * @param[out] data Pointer to the published data
1034  * @param[out] dataLen Length of the published data
1035  * @return Error code
1036  **/
1037 
1039  uint16_t *msgId, uint16_t *topicId, const uint8_t **data, size_t *dataLen)
1040 {
1041  size_t length;
1042  const MqttSnPublish *publish;
1043 
1044  //Point to the PUBLISH message
1045  publish = (MqttSnPublish *) (message->buffer + message->pos);
1046  //Calculate the length of the message
1047  length = message->length - message->pos;
1048 
1049  //Check the length of the message
1050  if(length < sizeof(MqttSnPublish))
1051  return ERROR_INVALID_LENGTH;
1052 
1053  //Get flags
1054  *flags = publish->flags;
1055  //Get message identifier
1056  *msgId = ntohs(publish->msgId);
1057  //Get topic identifier
1058  *topicId = ntohs(publish->topicId);
1059  //Get published data
1060  *data = publish->data;
1061 
1062  //Calculate the length of the published data
1063  *dataLen = length - sizeof(MqttSnPublish);
1064 
1065  //Successful processing
1066  return NO_ERROR;
1067 }
1068 
1069 
1070 /**
1071  * @brief Parse PUBACK message
1072  * @param[in] message Pointer to the MQTT-SN message
1073  * @param[out] msgId Message identifier
1074  * @param[out] topicId Topic identifier
1075  * @param[out] returnCode Return code
1076  * @return Error code
1077  **/
1078 
1080  uint16_t *topicId, MqttSnReturnCode *returnCode)
1081 {
1082  size_t length;
1083  const MqttSnPubAck *pubAck;
1084 
1085  //Point to the PUBACK message
1086  pubAck = (MqttSnPubAck *) (message->buffer + message->pos);
1087  //Calculate the length of the message
1088  length = message->length - message->pos;
1089 
1090  //Check the length of the message
1091  if(length < sizeof(MqttSnPubAck))
1092  return ERROR_INVALID_LENGTH;
1093 
1094  //Get message identifier
1095  *msgId = ntohs(pubAck->msgId);
1096  //Get topic identifier
1097  *topicId = ntohs(pubAck->topicId);
1098  //Get return code
1099  *returnCode = (MqttSnReturnCode) pubAck->returnCode;
1100 
1101  //Successful processing
1102  return NO_ERROR;
1103 }
1104 
1105 
1106 /**
1107  * @brief Parse PUBREC message
1108  * @param[in] message Pointer to the MQTT-SN message
1109  * @param[out] msgId Message identifier
1110  * @return Error code
1111  **/
1112 
1114 {
1115  size_t length;
1116  const MqttSnPubRec *pubRec;
1117 
1118  //Point to the PUBREC message
1119  pubRec = (MqttSnPubRec *) (message->buffer + message->pos);
1120  //Calculate the length of the message
1121  length = message->length - message->pos;
1122 
1123  //Check the length of the message
1124  if(length < sizeof(MqttSnPubRec))
1125  return ERROR_INVALID_LENGTH;
1126 
1127  //Get message identifier
1128  *msgId = ntohs(pubRec->msgId);
1129 
1130  //Successful processing
1131  return NO_ERROR;
1132 }
1133 
1134 
1135 /**
1136  * @brief Parse PUBREL message
1137  * @param[in] message Pointer to the MQTT-SN message
1138  * @param[out] msgId Message identifier
1139  * @return Error code
1140  **/
1141 
1143 {
1144  size_t length;
1145  const MqttSnPubRel *pubRel;
1146 
1147  //Point to the PUBREL message
1148  pubRel = (MqttSnPubRel *) (message->buffer + message->pos);
1149  //Calculate the length of the message
1150  length = message->length - message->pos;
1151 
1152  //Check the length of the message
1153  if(length < sizeof(MqttSnPubRel))
1154  return ERROR_INVALID_LENGTH;
1155 
1156  //Get message identifier
1157  *msgId = ntohs(pubRel->msgId);
1158 
1159  //Successful processing
1160  return NO_ERROR;
1161 }
1162 
1163 
1164 /**
1165  * @brief Parse PUBCOMP message
1166  * @param[in] message Pointer to the MQTT-SN message
1167  * @param[out] msgId Message identifier
1168  * @return Error code
1169  **/
1170 
1172 {
1173  size_t length;
1174  const MqttSnPubComp *pubComp;
1175 
1176  //Point to the PUBCOMP message
1177  pubComp = (MqttSnPubComp *) (message->buffer + message->pos);
1178  //Calculate the length of the message
1179  length = message->length - message->pos;
1180 
1181  //Check the length of the message
1182  if(length < sizeof(MqttSnPubComp))
1183  return ERROR_INVALID_LENGTH;
1184 
1185  //Get message identifier
1186  *msgId = ntohs(pubComp->msgId);
1187 
1188  //Successful processing
1189  return NO_ERROR;
1190 }
1191 
1192 
1193 /**
1194  * @brief Parse SUBACK message
1195  * @param[in] message Pointer to the MQTT-SN message
1196  * @param[out] flags Flags
1197  * @param[out] msgId Message identifier
1198  * @param[out] topicId Topic identifier
1199  * @param[out] returnCode Return code
1200  * @return Error code
1201  **/
1202 
1204  uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
1205 {
1206  size_t length;
1207  const MqttSnSubAck *subAck;
1208 
1209  //Point to the SUBACK message
1210  subAck = (MqttSnSubAck *) (message->buffer + message->pos);
1211  //Calculate the length of the message
1212  length = message->length - message->pos;
1213 
1214  //Check the length of the message
1215  if(length < sizeof(MqttSnSubAck))
1216  return ERROR_INVALID_LENGTH;
1217 
1218  //Get flags
1219  *flags = subAck->flags;
1220  //Get message identifier
1221  *msgId = ntohs(subAck->msgId);
1222  //Get topic identifier
1223  *topicId = ntohs(subAck->topicId);
1224  //Get return code
1225  *returnCode = (MqttSnReturnCode) subAck->returnCode;
1226 
1227  //Successful processing
1228  return NO_ERROR;
1229 }
1230 
1231 
1232 /**
1233  * @brief Parse UNSUBACK message
1234  * @param[in] message Pointer to the MQTT-SN message
1235  * @param[out] msgId Message identifier
1236  * @return Error code
1237  **/
1238 
1240 {
1241  size_t length;
1242  const MqttSnUnsubAck *unsubAck;
1243 
1244  //Point to the UNSUBACK message
1245  unsubAck = (MqttSnUnsubAck *) (message->buffer + message->pos);
1246  //Calculate the length of the message
1247  length = message->length - message->pos;
1248 
1249  //Check the length of the message
1250  if(length < sizeof(MqttSnUnsubAck))
1251  return ERROR_INVALID_LENGTH;
1252 
1253  //Get message identifier
1254  *msgId = ntohs(unsubAck->msgId);
1255 
1256  //Successful processing
1257  return NO_ERROR;
1258 }
1259 
1260 
1261 /**
1262  * @brief Parse PINGREQ message
1263  * @param[in] message Pointer to the MQTT-SN message
1264  * @param[out] clientId Client identifier
1265  * @return Error code
1266  **/
1267 
1269  const char_t **clientId)
1270 {
1271  const MqttSnPingReq *pingReq;
1272 
1273  //Point to the PINGREQ message
1274  pingReq = (MqttSnPingReq *) (message->buffer + message->pos);
1275 
1276  //Get client identifier
1277  *clientId = pingReq;
1278 
1279  //Successful processing
1280  return NO_ERROR;
1281 }
1282 
1283 
1284 /**
1285  * @brief Parse PINGRESP message
1286  * @param[in] message Pointer to the MQTT-SN message
1287  * @return Error code
1288  **/
1289 
1291 {
1292  //The PINGRESP message has only a header and no variable part
1293  return NO_ERROR;
1294 }
1295 
1296 
1297 /**
1298  * @brief Parse DISCONNECT message
1299  * @param[in] message Pointer to the MQTT-SN message
1300  * @param[out] duration Value of the sleep timer
1301  * @return Error code
1302  **/
1303 
1305  uint16_t *duration)
1306 {
1307  size_t length;
1308  const MqttSnDisconnect *disconnect;
1309 
1310  //Point to the DISCONNECT message
1311  disconnect = (MqttSnDisconnect *) (message->buffer + message->pos);
1312  //Calculate the length of the message
1313  length = message->length - message->pos;
1314 
1315  //The Duration parameter is optional
1316  if(length == 0)
1317  {
1318  //The field is not present
1319  *duration = 0;
1320  }
1321  else
1322  {
1323  //Check the length of the message
1324  if(length < sizeof(MqttSnDisconnect))
1325  return ERROR_INVALID_LENGTH;
1326 
1327  //Get topic identifier
1328  *duration = ntohs(disconnect->duration);
1329  }
1330 
1331  //Successful processing
1332  return NO_ERROR;
1333 }
1334 
1335 
1336 /**
1337  * @brief Parse WILLTOPICRESP message
1338  * @param[in] message Pointer to the MQTT-SN message
1339  * @param[out] returnCode Return code
1340  * @return Error code
1341  **/
1342 
1345 {
1346  size_t length;
1347  const MqttSnWillTopicResp *willTopicResp;
1348 
1349  //Point to the WILLTOPICRESP message
1350  willTopicResp = (MqttSnWillTopicResp *) (message->buffer + message->pos);
1351  //Calculate the length of the message
1352  length = message->length - message->pos;
1353 
1354  //Check the length of the message
1355  if(length < sizeof(MqttSnWillTopicResp))
1356  return ERROR_INVALID_LENGTH;
1357 
1358  //Get return code
1359  *returnCode = (MqttSnReturnCode) willTopicResp->returnCode;
1360 
1361  //Successful processing
1362  return NO_ERROR;
1363 }
1364 
1365 
1366 /**
1367  * @brief Parse WILLMSGRESP message
1368  * @param[in] message Pointer to the MQTT-SN message
1369  * @param[out] returnCode Return code
1370  * @return Error code
1371  **/
1372 
1375 {
1376  size_t length;
1377  const MqttSnWillMsgResp *willMsgResp;
1378 
1379  //Point to the WILLMSGRESP message
1380  willMsgResp = (MqttSnWillMsgResp *) (message->buffer + message->pos);
1381  //Calculate the length of the message
1382  length = message->length - message->pos;
1383 
1384  //Check the length of the message
1385  if(length < sizeof(MqttSnWillMsgResp))
1386  return ERROR_INVALID_LENGTH;
1387 
1388  //Get return code
1389  *returnCode = (MqttSnReturnCode) willMsgResp->returnCode;
1390 
1391  //Successful processing
1392  return NO_ERROR;
1393 }
1394 
1395 #endif
int_t connect(int_t s, const struct sockaddr *addr, socklen_t addrlen)
Establish a connection to a specified socket.
Definition: bsd_socket.c:204
uint8_t message[]
Definition: chap.h:154
uint8_t type
Definition: coap_common.h:176
char char_t
Definition: compiler_port.h:48
#define htons(value)
Definition: cpu_endian.h:413
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
#define ntohs(value)
Definition: cpu_endian.h:421
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t data[]
Definition: ethernet.h:222
MQTT-SN client.
#define MQTT_SN_PROTOCOL_ID
MqttSnMsgType
MQTT-SN message types.
@ MQTT_SN_MSG_TYPE_PINGREQ
@ MQTT_SN_MSG_TYPE_DISCONNECT
@ MQTT_SN_MSG_TYPE_UNSUBSCRIBE
@ MQTT_SN_MSG_TYPE_PUBLISH
@ MQTT_SN_MSG_TYPE_WILLTOPICUPD
@ MQTT_SN_MSG_TYPE_CONNECT
@ MQTT_SN_MSG_TYPE_SUBSCRIBE
@ MQTT_SN_MSG_TYPE_PUBACK
@ MQTT_SN_MSG_TYPE_REGISTER
@ MQTT_SN_MSG_TYPE_PINGRESP
@ MQTT_SN_MSG_TYPE_WILLTOPIC
@ MQTT_SN_MSG_TYPE_WILLMSGUPD
@ MQTT_SN_MSG_TYPE_PUBREC
@ MQTT_SN_MSG_TYPE_PUBCOMP
@ MQTT_SN_MSG_TYPE_PUBREL
@ MQTT_SN_MSG_TYPE_REGACK
@ MQTT_SN_MSG_TYPE_SEARCHGW
@ MQTT_SN_MSG_TYPE_WILLMSG
MqttSnPubRel
MqttSnSubAck
MqttSnPubComp
MqttSnSubscribe
char_t willTopic[]
MqttSnFlags
uint16_t msgId
MqttSnUnsubscribe
MqttSnWillTopicResp
MqttSnPubRec
MqttSnWillMsgResp
MqttSnPublish
MqttSnGwInfo
MqttSnHeader
uint16_t duration
MqttSnPubAck
MqttSnExtHeader
MqttSnWillTopicUpd
@ MQTT_SN_NORMAL_TOPIC_ID
Normal topic ID.
@ MQTT_SN_SHORT_TOPIC_NAME
Short topic name.
@ MQTT_SN_PREDEFINED_TOPIC_ID
Predefined topic ID.
@ MQTT_SN_NORMAL_TOPIC_NAME
Normal topic name.
MqttSnDisconnect
MqttSnRegAck
MqttSnSearchGw
void MqttSnWillMsgUpd
WILLMSGUPD message.
char_t topicName[]
void MqttSnWillMsg
WILLMSG message.
uint16_t topicId
uint8_t returnCode
uint8_t gwAdd[]
MqttSnReturnCode
MQTT-SN return codes.
char_t clientId[]
MqttSnRegister
MqttSnConnAck
MqttSnConnect
MqttSnUnsubAck
MqttSnWillTopic
void MqttSnPingReq
PINGREQ message.
error_t mqttSnFormatWillMsgUpd(MqttSnMessage *message, const void *data, size_t dataLen)
Format WILLMSGUPD message.
error_t mqttSnFormatRegAck(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Format REGACK message.
error_t mqttSnParseDisconnect(const MqttSnMessage *message, uint16_t *duration)
Parse DISCONNECT message.
error_t mqttSnFormatPublish(MqttSnMessage *message, MqttSnFlags flags, uint16_t msgId, uint16_t topicId, const char_t *topicName, const uint8_t *data, size_t dataLen)
Format PUBLISH message.
error_t mqttSnParseConnAck(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse CONNACK message.
error_t mqttSnParseWillMsgResp(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse WILLMSGRESP message.
error_t mqttSnParseWillTopicReq(const MqttSnMessage *message)
Parse WILLTOPICREQ message.
error_t mqttSnFormatPubAck(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Format PUBACK message.
error_t mqttSnParseHeader(MqttSnMessage *message, MqttSnMsgType *type)
Format MQTT-SN message header.
error_t mqttSnFormatPubRec(MqttSnMessage *message, uint16_t msgId)
Format PUBREC message.
error_t mqttSnParseSubAck(const MqttSnMessage *message, MqttSnFlags *flags, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse SUBACK message.
error_t mqttSnParsePubRel(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBREL message.
error_t mqttSnParseGwInfo(const MqttSnMessage *message, uint8_t *gwId, const uint8_t **gwAdd, size_t *gwAddLen)
Parse GWINFO message.
error_t mqttSnFormatDisconnect(MqttSnMessage *message, uint16_t duration)
Format DISCONNECT message.
error_t mqttSnParseWillMsgReq(const MqttSnMessage *message)
Parse WILLMSGREQ message.
error_t mqttSnParsePubAck(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse PUBACK message.
error_t mqttSnFormatSearchGw(MqttSnMessage *message, uint8_t radius)
Format SEARCHGW message.
error_t mqttSnFormatPingReq(MqttSnMessage *message, const char_t *clientId)
Format PINGREQ message.
error_t mqttSnFormatPingResp(MqttSnMessage *message)
Format PINGRESP message.
error_t mqttSnFormatUnsubscribe(MqttSnMessage *message, MqttSnFlags flags, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format UNSUBSCRIBE message.
error_t mqttSnParseWillTopicResp(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse WILLTOPICRESP message.
error_t mqttSnFormatPubRel(MqttSnMessage *message, uint16_t msgId)
Format PUBREL message.
error_t mqttSnFormatWillTopic(MqttSnMessage *message, MqttSnFlags flags, const char_t *topicName)
Format WILLTOPIC message.
error_t mqttSnFormatRegister(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format REGISTER message.
error_t mqttSnParsePubComp(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBCOMP message.
error_t mqttSnParsePublish(const MqttSnMessage *message, MqttSnFlags *flags, uint16_t *msgId, uint16_t *topicId, const uint8_t **data, size_t *dataLen)
Parse PUBLISH message.
error_t mqttSnParsePingReq(const MqttSnMessage *message, const char_t **clientId)
Parse PINGREQ message.
error_t mqttSnFormatWillTopicUpd(MqttSnMessage *message, MqttSnFlags flags, const char_t *topicName)
Format WILLTOPICUPD message.
error_t mqttSnParseUnsubAck(const MqttSnMessage *message, uint16_t *msgId)
Parse UNSUBACK message.
error_t mqttSnParseRegAck(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse REGACK message.
error_t mqttSnFormatConnect(MqttSnMessage *message, MqttSnFlags flags, uint16_t duration, const char_t *clientId)
Format CONNECT message.
error_t mqttSnParsePingResp(const MqttSnMessage *message)
Parse PINGRESP message.
error_t mqttSnFormatSubscribe(MqttSnMessage *message, MqttSnFlags flags, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format SUBSCRIBE message.
error_t mqttSnParseRegister(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, const char_t **topicName)
Parse REGISTER message.
error_t mqttSnFormatWillMsg(MqttSnMessage *message, const void *data, size_t dataLen)
Format WILLMSG message.
error_t mqttSnFormatPubComp(MqttSnMessage *message, uint16_t msgId)
Format PUBCOMP message.
error_t mqttSnParsePubRec(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBREC message.
error_t mqttSnFormatHeader(MqttSnMessage *message, MqttSnMsgType type, size_t length)
Format MQTT-SN message header.
MQTT-SN message formatting and parsing.
TCP/IP stack core.
#define osMemmove(dest, src, length)
Definition: os_port.h:147
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define osStrlen(s)
Definition: os_port.h:165
#define osStrcpy(s1, s2)
Definition: os_port.h:207
uint32_t dataLen
Definition: sftp_common.h:229
MQTT-SN message.
uint8_t length
Definition: tcp.h:368
uint8_t flags
Definition: tcp.h:351