mqtt_sn_client_message.c
Go to the documentation of this file.
1 /**
2  * @file mqtt_sn_client_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-2026 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.6.4
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"
41 #include "mqtt_sn/mqtt_sn_debug.h"
42 #include "debug.h"
43 
44 //Check TCP/IP stack configuration
45 #if (MQTT_SN_CLIENT_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Process incoming MQTT-SN message
50  * @param[in] context Pointer to the MQTT-SN client context
51  * @param[in] message Pointer to the received MQTT-SN message
52  * @param[in] ipAddr Source IP address
53  * @param[in] port Source port
54  * @return Error code
55  **/
56 
58  MqttSnMessage *message, const IpAddr *ipAddr, uint16_t port)
59 {
60  error_t error;
62 
63  //Parse MQTT-SN message header
64  error = mqttSnParseHeader(message, &type);
65 
66  //Check status code
67  if(!error)
68  {
69  //Debug message
70  TRACE_INFO("%s message received (%" PRIuSIZE " bytes)...\r\n",
72 
73  //Dump the contents of the message for debugging purpose
74  mqttSnDumpMessage(message->buffer, message->length);
75 
76  //Check message type
77  switch(type)
78  {
79  //GWINFO message received?
81  //Process incoming GWINFO message
82  error = mqttSnClientProcessGwInfo(context, message, ipAddr, port);
83  break;
84 
85  //CONNACK message received?
87  //Process incoming CONNACK message
88  error = mqttSnClientProcessConnAck(context, message);
89  break;
90 
91  //WILLTOPICREQ message received?
93  //Process incoming WILLTOPICREQ message
94  error = mqttSnClientProcessWillTopicReq(context, message);
95  break;
96 
97  //WILLMSGREQ message received?
99  //Process incoming WILLMSGREQ message
100  error = mqttSnClientProcessWillMsgReq(context, message);
101  break;
102 
103  //REGISTER message received?
105  //Process incoming REGISTER message
106  error = mqttSnClientProcessRegister(context, message);
107  break;
108 
109  //REGACK message received?
111  //Process incoming REGACK message
112  error = mqttSnClientProcessRegAck(context, message);
113  break;
114 
115  //PUBLISH message received?
117  //Process incoming PUBLISH message
118  error = mqttSnClientProcessPublish(context, message);
119  break;
120 
121  //PUBACK message received?
123  //Process incoming PUBACK message
124  error = mqttSnClientProcessPubAck(context, message);
125  break;
126  //PUBREC message received?
128  //Process incoming PUBREC message
129  error = mqttSnClientProcessPubRec(context, message);
130  break;
131 
132  //PUBREL message received?
134  //Process incoming PUBREL message
135  error = mqttSnClientProcessPubRel(context, message);
136  break;
137 
138  //PUBCOMP message received?
140  //Process incoming PUBCOMP message
141  error = mqttSnClientProcessPubComp(context, message);
142  break;
143 
144  //SUBACK message received?
146  //Process incoming SUBACK message
147  error = mqttSnClientProcessSubAck(context, message);
148  break;
149 
150  //UNSUBACK message received?
152  //Process incoming UNSUBACK message
153  error = mqttSnClientProcessUnsubAck(context, message);
154  break;
155 
156  //PINGREQ message received?
158  //Process incoming PINGREQ message
159  error = mqttSnClientProcessPingReq(context, message);
160  break;
161 
162  //PINGRESP message received?
164  //Process incoming PINGRESP message
165  error = mqttSnClientProcessPingResp(context, message);
166  break;
167 
168  //DISCONNECT message received?
170  //Process incoming DISCONNECT message
171  error = mqttSnClientProcessDisconnect(context, message);
172  break;
173 
174  //WILLTOPICRESP message received?
176  //Process incoming DISCONNECT message
177  error = mqttSnClientProcessWillTopicResp(context, message);
178  break;
179 
180  //WILLMSGRESP message received?
182  //Process incoming DISCONNECT message
183  error = mqttSnClientProcessWillMsgResp(context, message);
184  break;
185 
186  //Unknown message received?
187  default:
188  //Report an error
189  error = ERROR_INVALID_TYPE;
190  break;
191  }
192  }
193  else
194  {
195  //Debug message
196  TRACE_WARNING("Invalid message received (%" PRIuSIZE " bytes)...\r\n",
197  message->length);
198 
199  //Dump the contents of the message
200  TRACE_DEBUG_ARRAY(" ", message->buffer, message->length);
201  }
202 
203  //Return status code
204  return error;
205 }
206 
207 
208 /**
209  * @brief Process incoming GWINFO message
210  * @param[in] context Pointer to the MQTT-SN client context
211  * @param[in] message Pointer to the received MQTT-SN message
212  * @param[in] ipAddr Source IP address
213  * @param[in] port Source port
214  * @return Error code
215  **/
216 
218  const MqttSnMessage *message, const IpAddr *ipAddr, uint16_t port)
219 {
220  error_t error;
221  uint8_t gwId;
222  const uint8_t *gwAdd;
223  size_t gwAddLen;
224 
225  //Parse GWINFO message
226  error = mqttSnParseGwInfo(message, &gwId, &gwAdd, &gwAddLen);
227 
228  //Valid message received?
229  if(!error)
230  {
231  //Check current state
232  if(context->state == MQTT_SN_CLIENT_STATE_SEARCHING)
233  {
234  //Notify the application that a GWINFO message has been received
235  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
236  context->msgType = MQTT_SN_MSG_TYPE_GWINFO;
237  context->gwIpAddr = *ipAddr;
238  context->gwPort = port;
239  }
240  }
241 
242  //Return status code
243  return error;
244 }
245 
246 
247 /**
248  * @brief Process incoming CONNACK message
249  * @param[in] context Pointer to the MQTT-SN client context
250  * @param[in] message Pointer to the received MQTT-SN message
251  * @return Error code
252  **/
253 
255  const MqttSnMessage *message)
256 {
257  error_t error;
259 
260  //Parse CONNACK message
262 
263  //Valid message received?
264  if(!error)
265  {
266  //Check current state
267  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
268  context->msgType == MQTT_SN_MSG_TYPE_CONNECT)
269  {
270  //Notify the application that a CONNACK message has been received
271  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
272  context->msgType = MQTT_SN_MSG_TYPE_CONNACK;
273  context->returnCode = returnCode;
274 
275  //The MQTT-SN gateway is alive
276  context->keepAliveCounter = 0;
277  }
278  }
279 
280  //Return status code
281  return error;
282 }
283 
284 
285 /**
286  * @brief Process incoming WILLTOPICREQ message
287  * @param[in] context Pointer to the MQTT-SN client context
288  * @param[in] message Pointer to the received MQTT-SN message
289  * @return Error code
290  **/
291 
293  const MqttSnMessage *message)
294 {
295  error_t error;
296 
297  //Parse WILLTOPICREQ message
299 
300  //Valid message received?
301  if(!error)
302  {
303  //The WILLTOPIC message is sent by a client as response to the WILLTOPICREQ
304  //message for transferring its Will topic name to the GW
305  error = mqttSnClientSendWillTopic(context);
306  }
307 
308  //Return status code
309  return error;
310 }
311 
312 
313 /**
314  * @brief Process incoming WILLMSGREQ message
315  * @param[in] context Pointer to the MQTT-SN client context
316  * @param[in] message Pointer to the received MQTT-SN message
317  * @return Error code
318  **/
319 
321  const MqttSnMessage *message)
322 {
323  error_t error;
324 
325  //Parse WILLMSGREQ message
327 
328  //Valid message received?
329  if(!error)
330  {
331  //The WILLMSG message is sent by a client as response to a WILLMSGREQ
332  //for transferring its Will message to the GW
333  error = mqttSnClientSendWillMsg(context);
334  }
335 
336  //Return status code
337  return error;
338 }
339 
340 
341 /**
342  * @brief Process incoming REGISTER message
343  * @param[in] context Pointer to the MQTT-SN client context
344  * @param[in] message Pointer to the received MQTT-SN message
345  * @return Error code
346  **/
347 
349  const MqttSnMessage *message)
350 {
351  error_t error;
352  uint16_t msgId;
353  uint16_t topicId;
354  const char_t *topicName;
356 
357  //Parse REGISTER message
359 
360  //Valid message received?
361  if(!error)
362  {
363  //Save the topic ID assigned by the gateway
364  error = mqttSnClientAddTopic(context, topicName, topicId);
365 
366  //Check status code
367  if(!error)
368  {
370  }
371  else
372  {
374  }
375 
376  //The client sends a REGACK message to acknowledge the receipt and
377  //processing of a REGISTER message
378  error = mqttSnClientSendRegAck(context, msgId, topicId, returnCode);
379  }
380 
381  //Return status code
382  return error;
383 }
384 
385 
386 /**
387  * @brief Process incoming REGACK message
388  * @param[in] context Pointer to the MQTT-SN client context
389  * @param[in] message Pointer to the received MQTT-SN message
390  * @return Error code
391  **/
392 
394  const MqttSnMessage *message)
395 {
396  error_t error;
397  uint16_t msgId;
398  uint16_t topicId;
400 
401  //Parse REGACK message
403 
404  //Valid message received?
405  if(!error)
406  {
407  //Check current state
408  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
409  context->msgType == MQTT_SN_MSG_TYPE_REGISTER &&
410  context->msgId == msgId)
411  {
412  //Notify the application that a REGACK message has been received
413  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
414  context->msgType = MQTT_SN_MSG_TYPE_REGACK;
415  context->topicId = topicId;
416  context->returnCode = returnCode;
417 
418  //The MQTT-SN gateway is alive
419  context->keepAliveCounter = 0;
420  }
421  }
422 
423  //Return status code
424  return error;
425 }
426 
427 
428 /**
429  * @brief Process incoming PUBLISH message
430  * @param[in] context Pointer to the MQTT-SN client context
431  * @param[in] message Pointer to the received MQTT-SN message
432  * @return Error code
433  **/
434 
436  const MqttSnMessage *message)
437 {
438  error_t error;
439  bool_t duplicate;
440  uint16_t msgId;
441  uint16_t topicId;
442  const uint8_t *data;
443  size_t dataLen;
446 
447  //Parse PUBLISH message
449  &data, &dataLen);
450 
451  //Valid message received?
452  if(!error)
453  {
454  //Check QoS level
455  if(flags.qos == MQTT_SN_QOS_LEVEL_1)
456  {
457  //Deliver the message to the application
459  data, dataLen);
460 
461  //A PUBACK packet is the response to a PUBLISH packet with QoS level 1
462  error = mqttSnClientSendPubAck(context, msgId, topicId, returnCode);
463  }
464  else if(flags.qos == MQTT_SN_QOS_LEVEL_2)
465  {
466  //Check whether the ownership of the QoS 2 message has already been
467  //transferred to the client
468  duplicate = mqttSnClientIsDuplicateMessageId(context, msgId);
469 
470  //Duplicate message?
471  if(duplicate)
472  {
473  //In QoS 2, the receiver must not cause duplicate messages to be
474  //delivered to any onward recipients
475  error = mqttSnClientSendPubRec(context, msgId);
476  }
477  else
478  {
479  //Accept the ownership of the QoS 2 message
480  error = mqttSnClientStoreMessageId(context, msgId);
481 
482  //Check status code
483  if(!error)
484  {
485  //Initiate onward delivery of the application message
487  data, dataLen);
488  }
489  else
490  {
491  //The message identifier cannot be saved
493  }
494 
495  //Check whether the PUBLISH message has been accepted
497  {
498  //A PUBREC packet is the response to a PUBLISH packet with QoS 2.
499  //It is the second packet of the QoS 2 protocol exchange
500  error = mqttSnClientSendPubRec(context, msgId);
501  }
502  else
503  {
504  //Discard message identifier
506 
507  //Reject the PUBLISH message
508  error = mqttSnClientSendPubAck(context, msgId, topicId,
509  returnCode);
510  }
511  }
512  }
513  else
514  {
515  //Deliver the message to the application
517  data, dataLen);
518 
519  //In QoS 0, the receiver always accepts the message
520  error = NO_ERROR;
521  }
522  }
523 
524  //Return status code
525  return error;
526 }
527 
528 
529 /**
530  * @brief Process incoming PUBACK message
531  * @param[in] context Pointer to the MQTT-SN client context
532  * @param[in] message Pointer to the received MQTT-SN message
533  * @return Error code
534  **/
535 
537  const MqttSnMessage *message)
538 {
539  error_t error;
540  uint16_t msgId;
541  uint16_t topicId;
543 
544  //Parse PUBACK message
546 
547  //Valid message received?
548  if(!error)
549  {
550  //Check current state
551  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
552  context->msgType == MQTT_SN_MSG_TYPE_PUBLISH &&
553  context->msgId == msgId)
554  {
555  //Notify the application that a PUBACK message has been received
556  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
557  context->msgType = MQTT_SN_MSG_TYPE_PUBACK;
558  context->returnCode = returnCode;
559 
560  //The MQTT-SN gateway is alive
561  context->keepAliveCounter = 0;
562  }
563  }
564 
565  //Return status code
566  return error;
567 }
568 
569 
570 /**
571  * @brief Process incoming PUBREC message
572  * @param[in] context Pointer to the MQTT-SN client context
573  * @param[in] message Pointer to the received MQTT-SN message
574  * @return Error code
575  **/
576 
578  const MqttSnMessage *message)
579 {
580  error_t error;
581  uint16_t msgId;
582 
583  //Parse PUBREC message
584  error = mqttSnParsePubRec(message, &msgId);
585 
586  //Valid message received?
587  if(!error)
588  {
589  //Check current state
590  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
591  context->msgType == MQTT_SN_MSG_TYPE_PUBLISH &&
592  context->msgId == msgId)
593  {
594  //Notify the application that a PUBREC message has been received
595  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
596  context->msgType = MQTT_SN_MSG_TYPE_PUBREC;
597 
598  //The MQTT-SN gateway is alive
599  context->keepAliveCounter = 0;
600  }
601  }
602 
603  //Return status code
604  return error;
605 }
606 
607 
608 /**
609  * @brief Process incoming PUBREL message
610  * @param[in] context Pointer to the MQTT-SN client context
611  * @param[in] message Pointer to the received MQTT-SN message
612  * @return Error code
613  **/
614 
616  const MqttSnMessage *message)
617 {
618  error_t error;
619  uint16_t msgId;
620 
621  //Parse PUBREL message
622  error = mqttSnParsePubRel(message, &msgId);
623 
624  //Valid message received?
625  if(!error)
626  {
627  //Discard message identifier
629 
630  //A PUBCOMP message is the response to a PUBREL packet. It is the fourth
631  //and final message of the QoS 2 protocol exchange
632  error = mqttSnClientSendPubComp(context, msgId);
633  }
634 
635  //Return status code
636  return error;
637 }
638 
639 
640 /**
641  * @brief Process incoming PUBCOMP message
642  * @param[in] context Pointer to the MQTT-SN client context
643  * @param[in] message Pointer to the received MQTT-SN message
644  * @return Error code
645  **/
646 
648  const MqttSnMessage *message)
649 {
650  error_t error;
651  uint16_t msgId;
652 
653  //Parse PUBCOMP message
654  error = mqttSnParsePubComp(message, &msgId);
655 
656  //Valid message received?
657  if(!error)
658  {
659  //Check current state
660  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
661  context->msgType == MQTT_SN_MSG_TYPE_PUBREL &&
662  context->msgId == msgId)
663  {
664  //Notify the application that a PUBCOMP message has been received
665  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
666  context->msgType = MQTT_SN_MSG_TYPE_PUBCOMP;
667 
668  //The MQTT-SN gateway is alive
669  context->keepAliveCounter = 0;
670  }
671  }
672 
673  //Return status code
674  return error;
675 }
676 
677 
678 /**
679  * @brief Process incoming SUBACK message
680  * @param[in] context Pointer to the MQTT-SN client context
681  * @param[in] message Pointer to the received MQTT-SN message
682  * @return Error code
683  **/
684 
686  const MqttSnMessage *message)
687 {
688  error_t error;
689  uint16_t msgId;
690  uint16_t topicId;
693 
694  //Parse SUBACK message
696 
697  //Valid message received?
698  if(!error)
699  {
700  //Check current state
701  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
702  context->msgType == MQTT_SN_MSG_TYPE_SUBSCRIBE &&
703  context->msgId == msgId)
704  {
705  //Notify the application that a SUBACK message has been received
706  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
707  context->msgType = MQTT_SN_MSG_TYPE_SUBACK;
708  context->topicId = topicId;
709  context->returnCode = returnCode;
710 
711  //The MQTT-SN gateway is alive
712  context->keepAliveCounter = 0;
713  }
714  }
715 
716  //Return status code
717  return error;
718 }
719 
720 
721 /**
722  * @brief Process incoming UNSUBACK message
723  * @param[in] context Pointer to the MQTT-SN client context
724  * @param[in] message Pointer to the received MQTT-SN message
725  * @return Error code
726  **/
727 
729  const MqttSnMessage *message)
730 {
731  error_t error;
732  uint16_t msgId;
733 
734  //Parse UNSUBACK message
735  error = mqttSnParseUnsubAck(message, &msgId);
736 
737  //Valid message received?
738  if(!error)
739  {
740  //Check current state
741  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
742  context->msgType == MQTT_SN_MSG_TYPE_UNSUBSCRIBE &&
743  context->msgId == msgId)
744  {
745  //Notify the application that a UNSUBACK message has been received
746  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
747  context->msgType = MQTT_SN_MSG_TYPE_UNSUBACK;
748 
749  //The MQTT-SN gateway is alive
750  context->keepAliveCounter = 0;
751  }
752  }
753 
754  //Return status code
755  return error;
756 }
757 
758 
759 /**
760  * @brief Process incoming PINGREQ message
761  * @param[in] context Pointer to the MQTT-SN client context
762  * @param[in] message Pointer to the received MQTT-SN message
763  * @return Error code
764  **/
765 
767  const MqttSnMessage *message)
768 {
769  error_t error;
770  const char_t *clientId;
771 
772  //Parse PINGREQ message
774 
775  //Valid message received?
776  if(!error)
777  {
778  //A client shall answer with a PINGRESP message when it receives a
779  //PINGREQ message from the GW to which it is connected
780  error = mqttSnClientSendPingResp(context);
781  }
782 
783  //Return status code
784  return error;
785 }
786 
787 
788 /**
789  * @brief Process incoming PINGRESP message
790  * @param[in] context Pointer to the MQTT-SN client context
791  * @param[in] message Pointer to the received MQTT-SN message
792  * @return Error code
793  **/
794 
796  const MqttSnMessage *message)
797 {
798  error_t error;
799 
800  //Parse PINGRESP message
801  error = mqttSnParsePingResp(message);
802 
803  //Valid message received?
804  if(!error)
805  {
806  //Check current state
807  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
808  context->msgType == MQTT_SN_MSG_TYPE_PINGREQ)
809  {
810  //Notify the application that a PINGRESP message has been received
811  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
812  context->msgType = MQTT_SN_MSG_TYPE_PINGRESP;
813  }
814 
815  //The MQTT-SN gateway is alive
816  context->keepAliveCounter = 0;
817  }
818 
819  //Return status code
820  return error;
821 }
822 
823 
824 /**
825  * @brief Process incoming DISCONNECT message
826  * @param[in] context Pointer to the MQTT-SN client context
827  * @param[in] message Pointer to the received MQTT-SN message
828  * @return Error code
829  **/
830 
832  const MqttSnMessage *message)
833 {
834  error_t error;
835  uint16_t duration;
836 
837  //Parse DISCONNECT message
839 
840  //Valid message received?
841  if(!error)
842  {
843  //The gateway indicates that it wants to close the connection
844  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
845  }
846 
847  //Return status code
848  return error;
849 }
850 
851 
852 /**
853  * @brief Process incoming WILLTOPICRESP message
854  * @param[in] context Pointer to the MQTT-SN client context
855  * @param[in] message Pointer to the received MQTT-SN message
856  * @return Error code
857  **/
858 
860  const MqttSnMessage *message)
861 {
862  error_t error;
864 
865  //Parse WILLTOPICRESP message
867 
868  //Valid message received?
869  if(!error)
870  {
871  //Check current state
872  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
873  context->msgType == MQTT_SN_MSG_TYPE_WILLTOPICUPD)
874  {
875  //Notify the application that a WILLTOPICRESP message has been received
876  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
877  context->msgType = MQTT_SN_MSG_TYPE_WILLTOPICRESP;
878  context->returnCode = returnCode;
879 
880  //The MQTT-SN gateway is alive
881  context->keepAliveCounter = 0;
882  }
883  }
884 
885  //Return status code
886  return error;
887 }
888 
889 
890 /**
891  * @brief Process incoming WILLMSGRESP message
892  * @param[in] context Pointer to the MQTT-SN client context
893  * @param[in] message Pointer to the received MQTT-SN message
894  * @return Error code
895  **/
896 
898  const MqttSnMessage *message)
899 {
900  error_t error;
902 
903  //Parse WILLMSGRESP message
905 
906  //Valid message received?
907  if(!error)
908  {
909  //Check current state
910  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
911  context->msgType == MQTT_SN_MSG_TYPE_WILLMSGUPD)
912  {
913  //Notify the application that a WILLMSGRESP message has been received
914  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
915  context->msgType = MQTT_SN_MSG_TYPE_WILLMSGRESP;
916  context->returnCode = returnCode;
917 
918  //The MQTT-SN gateway is alive
919  context->keepAliveCounter = 0;
920  }
921  }
922 
923  //Return status code
924  return error;
925 }
926 
927 
928 /**
929  * @brief Send SEARCHGW message
930  * @param[in] context Pointer to the MQTT-SN client context
931  * @param[in] radius Broadcast radius of SEARCHGW message
932  * @param[in] destIpAddr Destination IP address
933  * @param[in] destPort Destination port number
934  * @return Error code
935  **/
936 
938  const IpAddr *destIpAddr, uint16_t destPort)
939 {
940  error_t error;
941 
942  //Format SEARCHGW message
943  error = mqttSnFormatSearchGw(&context->message, radius);
944 
945  //Check status code
946  if(!error)
947  {
948  //Debug message
949  TRACE_INFO("Sending SEARCHGW message (%" PRIuSIZE " bytes)...\r\n",
950  context->message.length);
951 
952  //Dump the contents of the message for debugging purpose
953  mqttSnDumpMessage(context->message.buffer, context->message.length);
954 
955  //Send MQTT-SN message
957  context->message.buffer, context->message.length);
958 
959  //Save the time at which the message was sent
960  context->retransmitStartTime = osGetSystemTime();
961  }
962 
963  //Return status code
964  return error;
965 }
966 
967 
968 /**
969  * @brief Send CONNECT message
970  * @param[in] context Pointer to the MQTT-SN client context
971  * @param[in] cleanSession If this flag is set, then the client and server
972  * must discard any previous session and start a new one
973  * @return Error code
974  **/
975 
977  bool_t cleanSession)
978 {
979  error_t error;
980  systime_t time;
982 
983  //The flags contains a number of parameters specifying the behavior of
984  //the MQTT-SN connection
985  flags.all = 0;
986 
987  //If CleanSession is set to 1, the client and server must discard any
988  //previous session and start a new one
989  if(cleanSession)
990  flags.cleanSession = TRUE;
991 
992  //If the client supplies a zero-byte Client Identifier, the client must
993  //also set CleanSession to 1
994  if(context->clientId[0] == '\0')
995  flags.cleanSession = TRUE;
996 
997  //Check whether a valid Will message has been specified
998  if(context->willMessage.topic[0] != '\0')
999  flags.will = TRUE;
1000 
1001  //Format CONNECT message
1002  error = mqttSnFormatConnect(&context->message, flags,
1003  context->keepAlive / 1000, context->clientId);
1004 
1005  //Check status code
1006  if(!error)
1007  {
1008  //Debug message
1009  TRACE_INFO("Sending CONNECT message (%" PRIuSIZE " bytes)...\r\n",
1010  context->message.length);
1011 
1012  //Dump the contents of the message for debugging purpose
1013  mqttSnDumpMessage(context->message.buffer, context->message.length);
1014 
1015  //Send MQTT-SN message
1016  error = mqttSnClientSendDatagram(context, context->message.buffer,
1017  context->message.length);
1018 
1019  //Get current time
1020  time = osGetSystemTime();
1021 
1022  //Save the time at which the message was sent
1023  context->retransmitStartTime = time;
1024  context->keepAliveTimestamp = time;
1025 
1026  //Update MQTT-SN client state
1027  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1028  context->msgType = MQTT_SN_MSG_TYPE_CONNECT;
1029  }
1030 
1031  //Return status code
1032  return error;
1033 }
1034 
1035 
1036 /**
1037  * @brief Send WILLTOPIC message
1038  * @param[in] context Pointer to the MQTT-SN client context
1039  * @return Error code
1040  **/
1041 
1043 {
1044  error_t error;
1045 
1046  //Format WILLTOPIC message
1047  error = mqttSnFormatWillTopic(&context->message,
1048  context->willMessage.flags, context->willMessage.topic);
1049 
1050  //Check status code
1051  if(!error)
1052  {
1053  //Debug message
1054  TRACE_INFO("Sending WILLTOPIC message (%" PRIuSIZE " bytes)...\r\n",
1055  context->message.length);
1056 
1057  //Dump the contents of the message for debugging purpose
1058  mqttSnDumpMessage(context->message.buffer, context->message.length);
1059 
1060  //Send MQTT-SN message
1061  error = mqttSnClientSendDatagram(context, context->message.buffer,
1062  context->message.length);
1063  }
1064 
1065  //Return status code
1066  return error;
1067 }
1068 
1069 
1070 /**
1071  * @brief Send WILLMSG message
1072  * @param[in] context Pointer to the MQTT-SN client context
1073  * @return Error code
1074  **/
1075 
1077 {
1078  error_t error;
1079 
1080  //Format WILLMSG message
1081  error = mqttSnFormatWillMsg(&context->message,
1082  context->willMessage.payload, context->willMessage.length);
1083 
1084  //Check status code
1085  if(!error)
1086  {
1087  //Debug message
1088  TRACE_INFO("Sending WILLMSG message (%" PRIuSIZE " bytes)...\r\n",
1089  context->message.length);
1090 
1091  //Dump the contents of the message for debugging purpose
1092  mqttSnDumpMessage(context->message.buffer, context->message.length);
1093 
1094  //Send MQTT-SN message
1095  error = mqttSnClientSendDatagram(context, context->message.buffer,
1096  context->message.length);
1097  }
1098 
1099  //Return status code
1100  return error;
1101 }
1102 
1103 
1104 /**
1105  * @brief Send REGISTER message
1106  * @param[in] context Pointer to the MQTT-SN client context
1107  * @param[in] topicName Topic name
1108  * @return Error code
1109  **/
1110 
1112  const char_t *topicName)
1113 {
1114  error_t error;
1115  systime_t time;
1116 
1117  //Format REGISTER message
1118  error = mqttSnFormatRegister(&context->message, context->msgId, 0,
1119  topicName);
1120 
1121  //Check status code
1122  if(!error)
1123  {
1124  //Debug message
1125  TRACE_INFO("Sending REGISTER message (%" PRIuSIZE " bytes)...\r\n",
1126  context->message.length);
1127 
1128  //Dump the contents of the message for debugging purpose
1129  mqttSnDumpMessage(context->message.buffer, context->message.length);
1130 
1131  //Send MQTT-SN message
1132  error = mqttSnClientSendDatagram(context, context->message.buffer,
1133  context->message.length);
1134 
1135  //Get current time
1136  time = osGetSystemTime();
1137 
1138  //Save the time at which the message was sent
1139  context->retransmitStartTime = time;
1140  context->keepAliveTimestamp = time;
1141 
1142  //Update MQTT-SN client state
1143  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1144  context->msgType = MQTT_SN_MSG_TYPE_REGISTER;
1145  }
1146 
1147  //Return status code
1148  return error;
1149 }
1150 
1151 
1152 /**
1153  * @brief Send REGACK message
1154  * @param[in] context Pointer to the MQTT-SN client context
1155  * @param[in] msgId Message identifier
1156  * @param[in] topicId Topic identifier
1157  * @param[in] returnCode Return code
1158  * @return Error code
1159  **/
1160 
1163 {
1164  error_t error;
1165 
1166  //Format REGACK message
1167  error = mqttSnFormatRegAck(&context->message, msgId, topicId, returnCode);
1168 
1169  //Check status code
1170  if(!error)
1171  {
1172  //Debug message
1173  TRACE_INFO("Sending REGACK message (%" PRIuSIZE " bytes)...\r\n",
1174  context->message.length);
1175 
1176  //Dump the contents of the message for debugging purpose
1177  mqttSnDumpMessage(context->message.buffer, context->message.length);
1178 
1179  //Send MQTT-SN message
1180  error = mqttSnClientSendDatagram(context, context->message.buffer,
1181  context->message.length);
1182  }
1183 
1184  //Return status code
1185  return error;
1186 }
1187 
1188 
1189 /**
1190  * @brief Send PUBLISH message
1191  * @param[in] context Pointer to the MQTT-SN client context
1192  * @param[in] msgId Message identifier
1193  * @param[in] topicName Short topic name
1194  * @param[in] data Message payload
1195  * @param[in] length Length of the message payload
1196  * @param[in] qos QoS level to be used when publishing the message
1197  * @param[in] retain This flag specifies if the message is to be retained
1198  * @param[in] dup This flag specifies if the message is sent for the first
1199  * time or if the message is retransmitted
1200  * @return Error code
1201  **/
1202 
1204  uint16_t msgId, const char_t *topicName, const uint8_t *data,
1205  size_t length, MqttSnQosLevel qos, bool_t retain, bool_t dup)
1206 {
1207  error_t error;
1208  systime_t time;
1209  uint16_t topicId;
1211 
1212  //Initialize status code
1213  error = NO_ERROR;
1214 
1215  //Reset unused flags
1216  flags.all = 0;
1217  //Set QoS level
1218  flags.qos = qos;
1219  //Set RETAIN flag
1220  flags.retain = retain;
1221  //set DUP flag
1222  flags.dup = dup;
1223 
1224  //Short topic name?
1226  {
1227  //The PUBLISH message contains a short topic name
1228  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1229  //The value of the topic ID is not relevant
1230  topicId = 0;
1231  }
1232  else
1233  {
1234  //Check whether a predefined topic ID has been registered
1236 
1237  //Predefined topic ID found?
1239  {
1240  //The PUBLISH message contains a predefined topic ID
1241  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1242  }
1243  else
1244  {
1245  //Check whether the topic name has been registered
1247 
1248  //Topic ID found?
1250  {
1251  //The PUBLISH message contains a normal topic ID
1252  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_ID;
1253  }
1254  else
1255  {
1256  //The topic name has not been registered
1257  error = ERROR_NOT_FOUND;
1258  }
1259  }
1260  }
1261 
1262  //Check status code
1263  if(!error)
1264  {
1265  //Format PUBLISH message
1266  error = mqttSnFormatPublish(&context->message, flags, msgId,
1268  }
1269 
1270  //Check status code
1271  if(!error)
1272  {
1273  //Debug message
1274  TRACE_INFO("Sending PUBLISH message (%" PRIuSIZE " bytes)...\r\n",
1275  context->message.length);
1276 
1277  //Dump the contents of the message for debugging purpose
1278  mqttSnDumpMessage(context->message.buffer, context->message.length);
1279 
1280  //Send MQTT-SN message
1281  error = mqttSnClientSendDatagram(context, context->message.buffer,
1282  context->message.length);
1283 
1284  //Get current time
1285  time = osGetSystemTime();
1286 
1287  //Check QoS level
1289  {
1290  //Save the time at which the message was sent
1291  context->retransmitStartTime = time;
1292  context->keepAliveTimestamp = time;
1293 
1294  //Update MQTT-SN client state
1295  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1296  context->msgType = MQTT_SN_MSG_TYPE_PUBLISH;
1297  }
1298  else
1299  {
1300  //In the QoS 0, no response is sent by the receiver and no retry
1301  //is performed by the sender
1302  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1303  }
1304  }
1305 
1306  //Return status code
1307  return error;
1308 }
1309 
1310 
1311 /**
1312  * @brief Send PUBACK message
1313  * @param[in] context Pointer to the MQTT-SN client context
1314  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1315  * @param[in] topicId Topic identifier
1316  * @param[in] returnCode Return code
1317  * @return Error code
1318  **/
1319 
1322 {
1323  error_t error;
1324 
1325  //Format PUBACK message
1326  error = mqttSnFormatPubAck(&context->message, msgId, topicId, returnCode);
1327 
1328  //Check status code
1329  if(!error)
1330  {
1331  //Debug message
1332  TRACE_INFO("Sending PUBACK message (%" PRIuSIZE " bytes)...\r\n",
1333  context->message.length);
1334 
1335  //Dump the contents of the message for debugging purpose
1336  mqttSnDumpMessage(context->message.buffer, context->message.length);
1337 
1338  //Send MQTT-SN message
1339  error = mqttSnClientSendDatagram(context, context->message.buffer,
1340  context->message.length);
1341  }
1342 
1343  //Return status code
1344  return error;
1345 }
1346 
1347 
1348 /**
1349  * @brief Send PUBREC message
1350  * @param[in] context Pointer to the MQTT-SN client context
1351  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1352  * @return Error code
1353  **/
1354 
1356 {
1357  error_t error;
1358 
1359  //Format PUBREC message
1360  error = mqttSnFormatPubRec(&context->message, msgId);
1361 
1362  //Check status code
1363  if(!error)
1364  {
1365  //Debug message
1366  TRACE_INFO("Sending PUBREC message (%" PRIuSIZE " bytes)...\r\n",
1367  context->message.length);
1368 
1369  //Dump the contents of the message for debugging purpose
1370  mqttSnDumpMessage(context->message.buffer, context->message.length);
1371 
1372  //Send MQTT-SN message
1373  error = mqttSnClientSendDatagram(context, context->message.buffer,
1374  context->message.length);
1375  }
1376 
1377  //Return status code
1378  return error;
1379 }
1380 
1381 
1382 /**
1383  * @brief Send PUBREL message
1384  * @param[in] context Pointer to the MQTT-SN client context
1385  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1386  * @return Error code
1387  **/
1388 
1390 {
1391  error_t error;
1392  systime_t time;
1393 
1394  //Format PUBREL message
1395  error = mqttSnFormatPubRel(&context->message, msgId);
1396 
1397  //Check status code
1398  if(!error)
1399  {
1400  //Debug message
1401  TRACE_INFO("Sending PUBREL message (%" PRIuSIZE " bytes)...\r\n",
1402  context->message.length);
1403 
1404  //Dump the contents of the message for debugging purpose
1405  mqttSnDumpMessage(context->message.buffer, context->message.length);
1406 
1407  //Send MQTT-SN message
1408  error = mqttSnClientSendDatagram(context, context->message.buffer,
1409  context->message.length);
1410 
1411  //Get current time
1412  time = osGetSystemTime();
1413 
1414  //Save the time at which the message was sent
1415  context->retransmitStartTime = time;
1416  context->keepAliveTimestamp = time;
1417 
1418  //Update MQTT-SN client state
1419  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1420  context->msgType = MQTT_SN_MSG_TYPE_PUBREL;
1421  }
1422 
1423  //Return status code
1424  return error;
1425 }
1426 
1427 
1428 /**
1429  * @brief Send PUBCOMP message
1430  * @param[in] context Pointer to the MQTT-SN client context
1431  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1432  * @return Error code
1433  **/
1434 
1436 {
1437  error_t error;
1438 
1439  //Format PUBCOMP message
1440  error = mqttSnFormatPubComp(&context->message, msgId);
1441 
1442  //Check status code
1443  if(!error)
1444  {
1445  //Debug message
1446  TRACE_INFO("Sending PUBCOMP message (%" PRIuSIZE " bytes)...\r\n",
1447  context->message.length);
1448 
1449  //Dump the contents of the message for debugging purpose
1450  mqttSnDumpMessage(context->message.buffer, context->message.length);
1451 
1452  //Send MQTT-SN message
1453  error = mqttSnClientSendDatagram(context, context->message.buffer,
1454  context->message.length);
1455  }
1456 
1457  //Return status code
1458  return error;
1459 }
1460 
1461 
1462 /**
1463  * @brief Send SUBSCRIBE message
1464  * @param[in] context Pointer to the MQTT-SN client context
1465  * @param[in] topicName Topic filter
1466  * @param[in] qos Maximum QoS level at which the server can send application
1467  * messages to the client
1468  * @return Error code
1469  **/
1470 
1473 {
1474  error_t error;
1475  systime_t time;
1476  uint16_t topicId;
1478 
1479  //Initialize status code
1480  error = NO_ERROR;
1481 
1482  //Reset unused flags
1483  flags.all = 0;
1484  //Set QoS level
1485  flags.qos = qos;
1486 
1487  //Check whether a predefined topic ID has been registered
1489 
1490  //Predefined topic ID found?
1492  {
1493  //The SUBSCRIBE message contains a predefined topic ID
1494  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1495  }
1496  else
1497  {
1498  //Short topic name?
1500  {
1501  //The SUBSCRIBE message contains a short topic name
1502  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1503  }
1504  else
1505  {
1506  //The SUBSCRIBE message contains a normal topic name
1507  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_NAME;
1508  }
1509 
1510  //Format SUBSCRIBE message
1511  error = mqttSnFormatSubscribe(&context->message, flags,
1512  context->msgId, topicId, topicName);
1513  }
1514 
1515  //Check status code
1516  if(!error)
1517  {
1518  //Debug message
1519  TRACE_INFO("Sending SUBSCRIBE message (%" PRIuSIZE " bytes)...\r\n",
1520  context->message.length);
1521 
1522  //Dump the contents of the message for debugging purpose
1523  mqttSnDumpMessage(context->message.buffer, context->message.length);
1524 
1525  //Send MQTT-SN message
1526  error = mqttSnClientSendDatagram(context, context->message.buffer,
1527  context->message.length);
1528 
1529  //Get current time
1530  time = osGetSystemTime();
1531 
1532  //Save the time at which the message was sent
1533  context->retransmitStartTime = time;
1534  context->keepAliveTimestamp = time;
1535 
1536  //Update MQTT-SN client state
1537  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1538  context->msgType = MQTT_SN_MSG_TYPE_SUBSCRIBE;
1539  }
1540 
1541  //Return status code
1542  return error;
1543 }
1544 
1545 
1546 /**
1547  * @brief Send UNSUBSCRIBE message
1548  * @param[in] context Pointer to the MQTT-SN client context
1549  * @param[in] topicName Topic filter
1550  * @return Error code
1551  **/
1552 
1554  const char_t *topicName)
1555 {
1556  error_t error;
1557  systime_t time;
1558  uint16_t topicId;
1560 
1561  //Initialize status code
1562  error = NO_ERROR;
1563 
1564  //Reset unused flags
1565  flags.all = 0;
1566 
1567  //Check whether a predefined topic ID has been registered
1569 
1570  //Predefined topic ID found?
1572  {
1573  //The UNSUBSCRIBE message contains a predefined topic ID
1574  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1575  }
1576  else
1577  {
1578  //Short topic name?
1579  if(osStrlen(topicName) == 2 && osStrchr(topicName, '#') == NULL &&
1580  osStrchr(topicName, '+') == NULL)
1581  {
1582  //The UNSUBSCRIBE message contains a short topic name
1583  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1584  }
1585  else
1586  {
1587  //The UNSUBSCRIBE message contains a normal topic name
1588  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_NAME;
1589  }
1590 
1591  //Format UNSUBSCRIBE message
1592  error = mqttSnFormatUnsubscribe(&context->message, flags,
1593  context->msgId, topicId, topicName);
1594  }
1595 
1596  //Check status code
1597  if(!error)
1598  {
1599  //Debug message
1600  TRACE_INFO("Sending UNSUBSCRIBE message (%" PRIuSIZE " bytes)...\r\n",
1601  context->message.length);
1602 
1603  //Dump the contents of the message for debugging purpose
1604  mqttSnDumpMessage(context->message.buffer, context->message.length);
1605 
1606  //Send MQTT-SN message
1607  error = mqttSnClientSendDatagram(context, context->message.buffer,
1608  context->message.length);
1609 
1610  //Get current time
1611  time = osGetSystemTime();
1612 
1613  //Save the time at which the message was sent
1614  context->retransmitStartTime = time;
1615  context->keepAliveTimestamp = time;
1616 
1617  //Update MQTT-SN client state
1618  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1619  context->msgType = MQTT_SN_MSG_TYPE_UNSUBSCRIBE;
1620  }
1621 
1622  //Return status code
1623  return error;
1624 }
1625 
1626 
1627 /**
1628  * @brief Send PINGREQ message
1629  * @param[in] context Pointer to the MQTT-SN client context
1630  * @return Error code
1631  **/
1632 
1634 {
1635  error_t error;
1636 
1637  //Format PINGREQ message
1638  error = mqttSnFormatPingReq(&context->message, context->clientId);
1639 
1640  //Check status code
1641  if(!error)
1642  {
1643  //Debug message
1644  TRACE_INFO("Sending PINGREQ message (%" PRIuSIZE " bytes)...\r\n",
1645  context->message.length);
1646 
1647  //Dump the contents of the message for debugging purpose
1648  mqttSnDumpMessage(context->message.buffer, context->message.length);
1649 
1650  //Send MQTT-SN message
1651  error = mqttSnClientSendDatagram(context, context->message.buffer,
1652  context->message.length);
1653 
1654  //Save the time at which the message was sent
1655  context->keepAliveTimestamp = osGetSystemTime();
1656  }
1657 
1658  //Return status code
1659  return error;
1660 }
1661 
1662 
1663 /**
1664  * @brief Send PINGRESP message
1665  * @param[in] context Pointer to the MQTT-SN client context
1666  * @return Error code
1667  **/
1668 
1670 {
1671  error_t error;
1672 
1673  //Format PINGRESP message
1674  error = mqttSnFormatPingResp(&context->message);
1675 
1676  //Check status code
1677  if(!error)
1678  {
1679  //Debug message
1680  TRACE_INFO("Sending PINGRESP message (%" PRIuSIZE " bytes)...\r\n",
1681  context->message.length);
1682 
1683  //Dump the contents of the message for debugging purpose
1684  mqttSnDumpMessage(context->message.buffer, context->message.length);
1685 
1686  //Send MQTT-SN message
1687  error = mqttSnClientSendDatagram(context, context->message.buffer,
1688  context->message.length);
1689  }
1690 
1691  //Return status code
1692  return error;
1693 }
1694 
1695 
1696 /**
1697  * @brief Send DISCONNECT message
1698  * @param[in] context Pointer to the MQTT-SN client context
1699  * @param[in] duration Value of the sleep timer
1700  * @return Error code
1701  **/
1702 
1704  uint16_t duration)
1705 {
1706  error_t error;
1707 
1708  //Format DISCONNECT message
1709  error = mqttSnFormatDisconnect(&context->message, duration);
1710 
1711  //Check status code
1712  if(!error)
1713  {
1714  //Debug message
1715  TRACE_INFO("Sending DISCONNECT message (%" PRIuSIZE " bytes)...\r\n",
1716  context->message.length);
1717 
1718  //Dump the contents of the message for debugging purpose
1719  mqttSnDumpMessage(context->message.buffer, context->message.length);
1720 
1721  //Send MQTT-SN message
1722  error = mqttSnClientSendDatagram(context, context->message.buffer,
1723  context->message.length);
1724 
1725  //Save the time at which the message was sent
1726  context->retransmitStartTime = osGetSystemTime();
1727 
1728  //Update MQTT-SN client state
1729  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1730  context->msgType = MQTT_SN_MSG_TYPE_DISCONNECT;
1731  }
1732 
1733  //Return status code
1734  return error;
1735 }
1736 
1737 
1738 /**
1739  * @brief Send WILLTOPICUPD message
1740  * @param[in] context Pointer to the MQTT-SN client context
1741  * @return Error code
1742  **/
1743 
1745 {
1746  error_t error;
1747  systime_t time;
1748 
1749  //Format WILLTOPICUPD message
1750  error = mqttSnFormatWillTopicUpd(&context->message,
1751  context->willMessage.flags, context->willMessage.topic);
1752 
1753  //Check status code
1754  if(!error)
1755  {
1756  //Debug message
1757  TRACE_INFO("Sending WILLTOPICUPD message (%" PRIuSIZE " bytes)...\r\n",
1758  context->message.length);
1759 
1760  //Dump the contents of the message for debugging purpose
1761  mqttSnDumpMessage(context->message.buffer, context->message.length);
1762 
1763  //Send MQTT-SN message
1764  error = mqttSnClientSendDatagram(context, context->message.buffer,
1765  context->message.length);
1766 
1767  //Get current time
1768  time = osGetSystemTime();
1769 
1770  //Save the time at which the message was sent
1771  context->retransmitStartTime = time;
1772  context->keepAliveTimestamp = time;
1773 
1774  //Update MQTT-SN client state
1775  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1776  context->msgType = MQTT_SN_MSG_TYPE_WILLTOPICUPD;
1777  }
1778 
1779  //Return status code
1780  return error;
1781 }
1782 
1783 
1784 /**
1785  * @brief Send WILLMSGUPD message
1786  * @param[in] context Pointer to the MQTT-SN client context
1787  * @return Error code
1788  **/
1789 
1791 {
1792  error_t error;
1793  systime_t time;
1794 
1795  //Format WILLMSGUPD message
1796  error = mqttSnFormatWillMsgUpd(&context->message,
1797  context->willMessage.payload, context->willMessage.length);
1798 
1799  //Check status code
1800  if(!error)
1801  {
1802  //Debug message
1803  TRACE_INFO("Sending WILLMSGUPD message (%" PRIuSIZE " bytes)...\r\n",
1804  context->message.length);
1805 
1806  //Dump the contents of the message for debugging purpose
1807  mqttSnDumpMessage(context->message.buffer, context->message.length);
1808 
1809  //Send MQTT-SN message
1810  error = mqttSnClientSendDatagram(context, context->message.buffer,
1811  context->message.length);
1812 
1813  //Get current time
1814  time = osGetSystemTime();
1815 
1816  //Save the time at which the message was sent
1817  context->retransmitStartTime = time;
1818  context->keepAliveTimestamp = time;
1819 
1820  //Update MQTT-SN client state
1821  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1822  context->msgType = MQTT_SN_MSG_TYPE_WILLMSGUPD;
1823  }
1824 
1825  //Return status code
1826  return error;
1827 }
1828 
1829 #endif
error_t mqttSnClientProcessWillMsgReq(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLMSGREQ message.
#define osStrchr(s, c)
Definition: os_port.h:201
error_t mqttSnFormatSearchGw(MqttSnMessage *message, uint8_t radius)
Format SEARCHGW message.
error_t mqttSnClientSendPubRel(MqttSnClientContext *context, uint16_t msgId)
Send PUBREL message.
error_t mqttSnParseRegister(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, const char_t **topicName)
Parse REGISTER 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 mqttSnFormatPubRel(MqttSnMessage *message, uint16_t msgId)
Format PUBREL message.
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
error_t mqttSnFormatPingResp(MqttSnMessage *message)
Format PINGRESP message.
@ MQTT_SN_MSG_TYPE_PINGRESP
error_t mqttSnFormatPingReq(MqttSnMessage *message, const char_t *clientId)
Format PINGREQ message.
error_t mqttSnParseWillTopicReq(const MqttSnMessage *message)
Parse WILLTOPICREQ message.
error_t mqttSnFormatUnsubscribe(MqttSnMessage *message, MqttSnFlags flags, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format UNSUBSCRIBE message.
@ MQTT_SN_MSG_TYPE_REGISTER
@ MQTT_SN_SHORT_TOPIC_NAME
Short topic name.
IP network address.
Definition: ip.h:90
@ MQTT_SN_MSG_TYPE_PINGREQ
error_t mqttSnFormatWillMsg(MqttSnMessage *message, const void *data, size_t dataLen)
Format WILLMSG message.
error_t mqttSnFormatConnect(MqttSnMessage *message, MqttSnFlags flags, uint16_t duration, const char_t *clientId)
Format CONNECT message.
error_t mqttSnClientProcessConnAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming CONNACK message.
error_t mqttSnClientSendDisconnect(MqttSnClientContext *context, uint16_t duration)
Send DISCONNECT message.
@ MQTT_SN_MSG_TYPE_CONNECT
error_t mqttSnParseWillMsgResp(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse WILLMSGRESP message.
uint8_t message[]
Definition: chap.h:154
error_t mqttSnClientSendRegister(MqttSnClientContext *context, const char_t *topicName)
Send REGISTER message.
#define MqttSnClientContext
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
@ MQTT_SN_QOS_LEVEL_1
At least once delivery.
error_t mqttSnClientSendPubAck(MqttSnClientContext *context, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Send PUBACK message.
MqttSnReturnCode
MQTT-SN return codes.
error_t mqttSnClientSendSubscribe(MqttSnClientContext *context, const char_t *topicName, MqttSnQosLevel qos)
Send SUBSCRIBE message.
@ MQTT_SN_PREDEFINED_TOPIC_ID
Predefined topic ID.
error_t mqttSnParsePublish(const MqttSnMessage *message, MqttSnFlags *flags, uint16_t *msgId, uint16_t *topicId, const uint8_t **data, size_t *dataLen)
Parse PUBLISH message.
MqttSnQosLevel
Quality of service level.
error_t mqttSnFormatWillTopic(MqttSnMessage *message, MqttSnFlags flags, const char_t *topicName)
Format WILLTOPIC message.
@ MQTT_SN_NORMAL_TOPIC_NAME
Normal topic name.
error_t mqttSnParseRegAck(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse REGACK message.
error_t mqttSnClientProcessMessage(MqttSnClientContext *context, MqttSnMessage *message, const IpAddr *ipAddr, uint16_t port)
Process incoming MQTT-SN message.
error_t mqttSnClientProcessGwInfo(MqttSnClientContext *context, const MqttSnMessage *message, const IpAddr *ipAddr, uint16_t port)
Process incoming GWINFO message.
uint8_t type
Definition: coap_common.h:176
error_t mqttSnClientSendSearchGw(MqttSnClientContext *context, uint8_t radius, const IpAddr *destIpAddr, uint16_t destPort)
Send SEARCHGW message.
@ MQTT_SN_MSG_TYPE_GWINFO
error_t mqttSnClientSendUnsubscribe(MqttSnClientContext *context, const char_t *topicName)
Send UNSUBSCRIBE message.
uint16_t msgId
@ MQTT_SN_RETURN_CODE_REJECTED_CONGESTION
@ MQTT_SN_MSG_TYPE_WILLTOPICRESP
uint16_t destPort
Definition: tcp.h:347
uint8_t qos
Definition: mqtt_common.h:181
#define osStrlen(s)
Definition: os_port.h:171
MQTT-SN message formatting and parsing.
uint16_t topicId
@ MQTT_SN_MSG_TYPE_PUBREL
error_t mqttSnParseWillTopicResp(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse WILLTOPICRESP message.
error_t mqttSnClientSendRegAck(MqttSnClientContext *context, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Send REGACK message.
error_t mqttSnParseDisconnect(const MqttSnMessage *message, uint16_t *duration)
Parse DISCONNECT message.
uint8_t returnCode
error_t mqttSnFormatWillTopicUpd(MqttSnMessage *message, MqttSnFlags flags, const char_t *topicName)
Format WILLTOPICUPD message.
@ MQTT_SN_CLIENT_STATE_SENDING_REQ
uint8_t gwAdd[]
@ MQTT_SN_MSG_TYPE_WILLTOPICREQ
error_t mqttSnClientSendPingReq(MqttSnClientContext *context)
Send PINGREQ message.
@ MQTT_SN_MSG_TYPE_WILLMSGREQ
uint16_t mqttSnClientFindTopicName(MqttSnClientContext *context, const char_t *topicName)
Retrieve the topic ID associated with a given topic name.
@ MQTT_SN_CLIENT_STATE_SEARCHING
error_t mqttSnFormatPubAck(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Format PUBACK message.
error_t mqttSnFormatDisconnect(MqttSnMessage *message, uint16_t duration)
Format DISCONNECT message.
bool_t mqttSnClientIsDuplicateMessageId(MqttSnClientContext *context, uint16_t msgId)
Check whether the message ID is a duplicate (QoS 2 message processing)
error_t mqttSnClientSendPingResp(MqttSnClientContext *context)
Send PINGRESP message.
error_t mqttSnClientProcessSubAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming SUBACK message.
@ MQTT_SN_NORMAL_TOPIC_ID
Normal topic ID.
error_t mqttSnClientAddTopic(MqttSnClientContext *context, const char_t *topicName, uint16_t topicId)
Add a new entry to the topic table.
error_t mqttSnParseWillMsgReq(const MqttSnMessage *message)
Parse WILLMSGREQ message.
error_t mqttSnClientProcessPublish(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBLISH message.
error_t mqttSnFormatPubComp(MqttSnMessage *message, uint16_t msgId)
Format PUBCOMP message.
error_t mqttSnFormatSubscribe(MqttSnMessage *message, MqttSnFlags flags, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format SUBSCRIBE message.
error_t mqttSnParseHeader(MqttSnMessage *message, MqttSnMsgType *type)
Format MQTT-SN message header.
error_t mqttSnParseConnAck(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse CONNACK message.
error_t mqttSnParseUnsubAck(const MqttSnMessage *message, uint16_t *msgId)
Parse UNSUBACK message.
error_t
Error codes.
Definition: error.h:43
@ MQTT_SN_MSG_TYPE_PUBREC
error_t mqttSnClientSendPubComp(MqttSnClientContext *context, uint16_t msgId)
Send PUBCOMP message.
error_t mqttSnClientProcessPingReq(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PINGREQ message.
@ MQTT_SN_MSG_TYPE_WILLTOPICUPD
error_t mqttSnParseGwInfo(const MqttSnMessage *message, uint8_t *gwId, const uint8_t **gwAdd, size_t *gwAddLen)
Parse GWINFO message.
error_t mqttSnClientSendDatagram(MqttSnClientContext *context, const void *data, size_t length)
Send a datagram.
@ MQTT_SN_MSG_TYPE_SUBSCRIBE
error_t mqttSnClientSendWillMsgUpd(MqttSnClientContext *context)
Send WILLMSGUPD message.
@ MQTT_SN_MSG_TYPE_PUBLISH
@ MQTT_SN_MSG_TYPE_WILLMSGRESP
bool_t mqttSnClientIsShortTopicName(const char_t *topicName)
Check whether a topic name is a short topic name.
error_t mqttSnFormatRegAck(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Format REGACK message.
error_t mqttSnClientProcessUnsubAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming UNSUBACK message.
@ MQTT_SN_MSG_TYPE_PUBCOMP
error_t mqttSnClientProcessRegister(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming REGISTER message.
@ MQTT_SN_MSG_TYPE_DISCONNECT
error_t mqttSnClientProcessPubAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBACK message.
error_t mqttSnClientProcessPubRel(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBREL message.
MqttSnReturnCode mqttSnDeliverPublishMessage(MqttSnClientContext *context, MqttSnFlags flags, uint16_t topicId, const uint8_t *data, size_t dataLen)
Deliver a PUBLISH message to the application.
error_t mqttSnClientSendPublish(MqttSnClientContext *context, uint16_t msgId, const char_t *topicName, const uint8_t *data, size_t length, MqttSnQosLevel qos, bool_t retain, bool_t dup)
Send PUBLISH message.
@ ERROR_INVALID_TYPE
Definition: error.h:115
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
@ MQTT_SN_CLIENT_STATE_RESP_RECEIVED
@ MQTT_SN_CLIENT_STATE_DISCONNECTING
error_t mqttSnParsePingResp(const MqttSnMessage *message)
Parse PINGRESP message.
uint32_t dataLen
Definition: sftp_common.h:229
error_t mqttSnClientProcessRegAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming REGACK message.
error_t mqttSnParseSubAck(const MqttSnMessage *message, MqttSnFlags *flags, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse SUBACK message.
error_t mqttSnClientProcessPubComp(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBCOMP message.
Helper functions for MQTT-SN client.
@ MQTT_SN_MSG_TYPE_REGACK
error_t mqttSnFormatPubRec(MqttSnMessage *message, uint16_t msgId)
Format PUBREC message.
uint32_t systime_t
System time.
uint16_t port
Definition: dns_common.h:270
uint16_t duration
#define TRACE_WARNING(...)
Definition: debug.h:93
const char_t * mqttSnGetMessageName(uint16_t msgType)
Get the name of the specified MQTT-SN message.
char char_t
Definition: compiler_port.h:55
MqttSnMsgType
MQTT-SN message types.
error_t mqttSnClientProcessPingResp(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PINGRESP message.
uint32_t time
Transport protocol abstraction layer.
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
error_t mqttSnClientProcessWillTopicReq(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLTOPICREQ message.
@ MQTT_SN_MSG_TYPE_WILLMSGUPD
error_t mqttSnClientProcessDisconnect(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming DISCONNECT message.
error_t mqttSnDumpMessage(const uint8_t *message, size_t length)
Dump MQTT-SN message for debugging purpose.
Definition: mqtt_sn_debug.c:95
uint16_t mqttSnClientFindPredefTopicName(MqttSnClientContext *context, const char_t *topicName)
Retrieve the topic ID associated with a predefined topic name.
error_t mqttSnParsePubRel(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBREL message.
char_t topicName[]
@ MQTT_SN_RETURN_CODE_ACCEPTED
MQTT-SN message.
error_t mqttSnClientSendPubRec(MqttSnClientContext *context, uint16_t msgId)
Send PUBREC message.
error_t mqttSnFormatRegister(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format REGISTER message.
error_t mqttSnClientStoreMessageId(MqttSnClientContext *context, uint16_t msgId)
Store message ID (QoS 2 message processing)
@ MQTT_SN_MSG_TYPE_UNSUBACK
uint8_t dup
Definition: mqtt_common.h:182
@ MQTT_SN_CLIENT_STATE_ACTIVE
error_t mqttSnClientSendWillMsg(MqttSnClientContext *context)
Send WILLMSG message.
error_t mqttSnClientBroadcastDatagram(MqttSnClientContext *context, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length)
Broadcast a datagram.
error_t mqttSnClientProcessWillTopicResp(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLTOPICRESP message.
Ipv4Addr ipAddr
Definition: ipcp.h:105
MQTT-SN message formatting and parsing.
MQTT-SN client.
char_t clientId[]
error_t mqttSnClientSendWillTopicUpd(MqttSnClientContext *context)
Send WILLTOPICUPD message.
error_t mqttSnFormatWillMsgUpd(MqttSnMessage *message, const void *data, size_t dataLen)
Format WILLMSGUPD message.
error_t mqttSnParsePubRec(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBREC message.
uint8_t flags
Definition: tcp.h:358
error_t mqttSnParsePubAck(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse PUBACK message.
error_t mqttSnParsePingReq(const MqttSnMessage *message, const char_t **clientId)
Parse PINGREQ message.
#define PRIuSIZE
TCP/IP stack core.
@ MQTT_SN_MSG_TYPE_UNSUBSCRIBE
error_t mqttSnClientProcessPubRec(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBREC message.
MqttSnFlags
Data logging functions for debugging purpose (MQTT-SN)
error_t mqttSnParsePubComp(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBCOMP message.
error_t mqttSnClientProcessWillMsgResp(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLMSGRESP message.
@ MQTT_SN_MSG_TYPE_CONNACK
@ MQTT_SN_QOS_LEVEL_2
Exactly once delivery.
error_t mqttSnClientDiscardMessageId(MqttSnClientContext *context, uint16_t msgId)
Discard message ID (QoS 2 message processing)
#define MQTT_SN_INVALID_TOPIC_ID
@ NO_ERROR
Success.
Definition: error.h:44
@ MQTT_SN_MSG_TYPE_PUBACK
Debugging facilities.
@ MQTT_SN_MSG_TYPE_SUBACK
error_t mqttSnClientSendWillTopic(MqttSnClientContext *context)
Send WILLTOPIC message.
error_t mqttSnClientSendConnect(MqttSnClientContext *context, bool_t cleanSession)
Send CONNECT message.
systime_t osGetSystemTime(void)
Retrieve system time.
Ipv4Addr destIpAddr
Definition: ipcp.h:80