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