mqtt_client_packet.c
Go to the documentation of this file.
1 /**
2  * @file mqtt_client_packet.c
3  * @brief MQTT packet parsing and formatting
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL MQTT_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "mqtt/mqtt_client.h"
39 #include "mqtt/mqtt_client_misc.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (MQTT_CLIENT_SUPPORT == ENABLED)
44 
45 //MQTT control packets
46 const char_t *const mqttPacketLabel[16] =
47 {
48  "Reserved", //0
49  "CONNECT", //1
50  "CONNACK", //2
51  "PUBLISH", //3
52  "PUBACK", //4
53  "PUBREC", //5
54  "PUBREL", //6
55  "PUBCOMP", //7
56  "SUBSCRIBE", //8
57  "SUBACK", //9
58  "UNSUBSCRIBE", //10
59  "UNSUBACK", //11
60  "PINGREQ", //12
61  "PINGRESP", //13
62  "DISCONNECT", //14
63  "Reserved" //15
64 };
65 
66 
67 /**
68  * @brief Receive MQTT packet
69  * @param[in] context Pointer to the MQTT client context
70  * @return Error code
71  **/
72 
74 {
75  error_t error;
76  size_t n;
77  uint8_t value;
78 
79  //Initialize status code
80  error = NO_ERROR;
81 
82  //Receive incoming packet
83  while(1)
84  {
85  //Packet header is being received?
86  if(context->packetLen == 0)
87  {
88  //Read a single byte
89  error = mqttClientReceiveData(context, &value, sizeof(uint8_t), &n, 0);
90 
91  //Any data received?
92  if(!error)
93  {
94  //Save the current byte
95  context->packet[context->packetPos] = value;
96 
97  //The Remaining Length is encoded using a variable length encoding scheme
98  if(context->packetPos > 0)
99  {
100  //The most significant bit is used to indicate that there are
101  //following bytes in the representation
102  if(value & 0x80)
103  {
104  //Applications can send control packets of size up to 256 MB
105  if(context->packetPos < 4)
106  {
107  //The least significant seven bits of each byte encode the data
108  context->remainingLen |= (value & 0x7F) << (7 * (context->packetPos - 1));
109  }
110  else
111  {
112  //Report an error
113  error = ERROR_INVALID_SYNTAX;
114  }
115  }
116  else
117  {
118  //The least significant seven bits of each byte encode the data
119  context->remainingLen |= value << (7 * (context->packetPos - 1));
120  //Calculate the length of the control packet
121  context->packetLen = context->packetPos + 1 + context->remainingLen;
122 
123  //Sanity check
124  if(context->packetLen > MQTT_CLIENT_BUFFER_SIZE)
125  error = ERROR_INVALID_LENGTH;
126  }
127  }
128 
129  //Advance data pointer
130  context->packetPos++;
131  }
132  }
133  //Variable header or payload is being received?
134  else
135  {
136  //Any remaining data?
137  if(context->packetPos < context->packetLen)
138  {
139  //Read more data
140  error = mqttClientReceiveData(context, context->packet + context->packetPos,
141  context->packetLen - context->packetPos, &n, 0);
142 
143  //Advance data pointer
144  context->packetPos += n;
145  }
146  else
147  {
148  //The packet has been successfully received
149  break;
150  }
151  }
152 
153  //Any error to report?
154  if(error)
155  break;
156  }
157 
158  //Return status code
159  return error;
160 }
161 
162 
163 /**
164  * @brief Process incoming MQTT packet
165  * @param[in] context Pointer to the MQTT client context
166  * @return Error code
167  **/
168 
170 {
171  error_t error;
172  bool_t dup;
173  bool_t retain;
174  size_t remainingLen;
177 
178  //Point to the first byte of the packet
179  context->packetPos = 0;
180 
181  //Read the fixed header from the input buffer
182  error = mqttDeserializeHeader(context->packet, context->packetLen,
183  &context->packetPos, &type, &dup, &qos, &retain, &remainingLen);
184 
185  //Failed to deserialize fixed header?
186  if(error)
187  return error;
188 
189  //Debug message
190  TRACE_INFO("MQTT: %s packet received (%" PRIuSIZE " bytes)...\r\n",
191  mqttPacketLabel[type], context->packetLen);
192 
193  //Dump the contents of the packet
194  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
195 
196  //Check MQTT control packet type
197  switch(type)
198  {
199  //CONNACK packet received?
201  //Process incoming CONNACK packet
202  error = mqttClientProcessConnAck(context, dup, qos, retain, remainingLen);
203  break;
204  //PUBLISH packet received?
206  //Process incoming PUBLISH packet
207  error = mqttClientProcessPublish(context, dup, qos, retain, remainingLen);
208  break;
209  //PUBACK packet received?
211  //Process incoming PUBACK packet
212  error = mqttClientProcessPubAck(context, dup, qos, retain, remainingLen);
213  break;
214  //PUBREC packet received?
216  //Process incoming PUBREC packet
217  error = mqttClientProcessPubRec(context, dup, qos, retain, remainingLen);
218  break;
219  //PUBREL packet received?
221  //Process incoming PUBREL packet
222  error = mqttClientProcessPubRel(context, dup, qos, retain, remainingLen);
223  break;
224  //PUBCOMP packet received?
226  //Process incoming PUBCOMP packet
227  error = mqttClientProcessPubComp(context, dup, qos, retain, remainingLen);
228  break;
229  //SUBACK packet received?
231  //Process incoming SUBACK packet
232  error = mqttClientProcessSubAck(context, dup, qos, retain, remainingLen);
233  break;
234  //UNSUBACK packet received?
236  //Process incoming UNSUBACK packet
237  error = mqttClientProcessUnsubAck(context, dup, qos, retain, remainingLen);
238  break;
239  //PINGRESP packet received?
241  //Process incoming PINGRESP packet
242  error = mqttClientProcessPingResp(context, dup, qos, retain, remainingLen);
243  break;
244  //Unknown packet received?
245  default:
246  //Report an error
247  error = ERROR_INVALID_PACKET;
248  }
249 
250  //Return status code
251  return error;
252 }
253 
254 
255 /**
256  * @brief Process incoming CONNACK packet
257  * @param[in] context Pointer to the MQTT client context
258  * @param[in] dup DUP flag from the fixed header
259  * @param[in] qos QoS field from the fixed header
260  * @param[in] retain RETAIN flag from the fixed header
261  * @param[in] remainingLen Length of the variable header and the payload
262  **/
263 
265  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
266 {
267  error_t error;
268  uint8_t connectAckFlags;
269  uint8_t connectReturnCode;
270 
271  //If invalid flags are received, the receiver must close the network connection
272  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
273  return ERROR_INVALID_PACKET;
274 
275  //The first byte of the variable header is the Connect Acknowledge Flags
276  error = mqttDeserializeByte(context->packet, context->packetLen,
277  &context->packetPos, &connectAckFlags);
278 
279  //Failed to deserialize the Connect Acknowledge Flags?
280  if(error)
281  return error;
282 
283  //The second byte of the variable header is the Connect Return Code
284  error = mqttDeserializeByte(context->packet, context->packetLen,
285  &context->packetPos, &connectReturnCode);
286 
287  //Failed to deserialize the Connect Return Code?
288  if(error)
289  return error;
290 
291  //Any registered callback?
292  if(context->callbacks.connAckCallback != NULL)
293  {
294  //Invoke user callback function
295  context->callbacks.connAckCallback(context,
296  connectAckFlags, connectReturnCode);
297  }
298 
299  //Make sure the connection is accepted
300  if(connectReturnCode != MQTT_CONNECT_RET_CODE_ACCEPTED)
302 
303  //Notify the application that a CONNACK packet has been received
304  if(context->packetType == MQTT_PACKET_TYPE_CONNECT)
306 
307  //Successful processing
308  return NO_ERROR;
309 }
310 
311 
312 /**
313  * @brief Process incoming PUBLISH packet
314  * @param[in] context Pointer to the MQTT client context
315  * @param[in] dup DUP flag from the fixed header
316  * @param[in] qos QoS field from the fixed header
317  * @param[in] retain RETAIN flag from the fixed header
318  * @param[in] remainingLen Length of the variable header and the payload
319  **/
320 
322  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
323 {
324  error_t error;
325  uint16_t packetId;
326  char_t *topic;
327  size_t topicLen;
328  uint8_t *message;
329  size_t messageLen;
330 
331  //The Topic Name must be present as the first field in the PUBLISH
332  //packet variable header
333  error = mqttDeserializeString(context->packet, context->packetLen,
334  &context->packetPos, &topic, &topicLen);
335 
336  //Failed to deserialize Topic Name?
337  if(error)
338  return error;
339 
340  //Check QoS level
341  if(qos != MQTT_QOS_LEVEL_0)
342  {
343  //The Packet Identifier field is only present in PUBLISH packets
344  //where the QoS level is 1 or 2
345  error = mqttDeserializeShort(context->packet, context->packetLen,
346  &context->packetPos, &packetId);
347 
348  //Failed to deserialize Packet Identifier field?
349  if(error)
350  return error;
351  }
352  else
353  {
354  //No packet identifier
355  packetId = 0;
356  }
357 
358  //The payload contains the Application Message that is being published
359  message = context->packet + context->packetPos;
360 
361  //The length of the payload can be calculated by subtracting the length of the
362  //variable header from the Remaining Length field that is in the fixed header
363  messageLen = context->packetLen - context->packetPos;
364 
365  //Make room for the NULL character at the end of the Topic Name
366  osMemmove(topic - 1, topic, topicLen);
367  //Properly terminate the string with a NULL character
368  topic[topicLen - 1] = '\0';
369  //Point to the first character of the Topic Name
370  topic--;
371 
372  //Any registered callback?
373  if(context->callbacks.publishCallback != NULL)
374  {
375  //Invoke user callback function
376  context->callbacks.publishCallback(context, topic,
377  message, messageLen, dup, qos, retain, packetId);
378  }
379 
380  //Check QoS level
381  if(qos == MQTT_QOS_LEVEL_1)
382  {
383  //A PUBACK packet is the response to a PUBLISH packet with QoS level 1
384  error = mqttClientFormatPubAck(context, packetId);
385 
386  //Check status code
387  if(!error)
388  {
389  //Debug message
390  TRACE_INFO("MQTT: Sending PUBACK packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
391  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
392 
393  //Point to the beginning of the packet
394  context->packetPos = 0;
395 
396  //Send PUBACK packet
398  }
399  }
400  else if(qos == MQTT_QOS_LEVEL_2)
401  {
402  //A PUBREC packet is the response to a PUBLISH packet with QoS 2. It is
403  //the second packet of the QoS 2 protocol exchange
404  error = mqttClientFormatPubRec(context, packetId);
405 
406  //Check status code
407  if(!error)
408  {
409  //Debug message
410  TRACE_INFO("MQTT: Sending PUBREC packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
411  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
412 
413  //Point to the beginning of the packet
414  context->packetPos = 0;
415 
416  //Send PUBREC packet
418  }
419  }
420 
421  //Return status code
422  return error;
423 }
424 
425 
426 /**
427  * @brief Process incoming PUBACK packet
428  * @param[in] context Pointer to the MQTT client context
429  * @param[in] dup DUP flag from the fixed header
430  * @param[in] qos QoS field from the fixed header
431  * @param[in] retain RETAIN flag from the fixed header
432  * @param[in] remainingLen Length of the variable header and the payload
433  **/
434 
436  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
437 {
438  error_t error;
439  uint16_t packetId;
440 
441  //If invalid flags are received, the receiver must close the network connection
442  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
443  return ERROR_INVALID_PACKET;
444 
445  //The variable header contains the Packet Identifier from the PUBLISH
446  //packet that is being acknowledged
447  error = mqttDeserializeShort(context->packet, context->packetLen,
448  &context->packetPos, &packetId);
449 
450  //Failed to deserialize Packet Identifier field?
451  if(error)
452  return error;
453 
454  //Any registered callback?
455  if(context->callbacks.pubAckCallback != NULL)
456  {
457  //Invoke user callback function
458  context->callbacks.pubAckCallback(context, packetId);
459  }
460 
461  //Notify the application that a PUBACK packet has been received
462  if(context->packetType == MQTT_PACKET_TYPE_PUBLISH && context->packetId == packetId)
464 
465  //Return status code
466  return error;
467 }
468 
469 
470 /**
471  * @brief Process incoming PUBREC packet
472  * @param[in] context Pointer to the MQTT client context
473  * @param[in] dup DUP flag from the fixed header
474  * @param[in] qos QoS field from the fixed header
475  * @param[in] retain RETAIN flag from the fixed header
476  * @param[in] remainingLen Length of the variable header and the payload
477  **/
478 
480  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
481 {
482  error_t error;
483  uint16_t packetId;
484 
485  //If invalid flags are received, the receiver must close the network connection
486  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
487  return ERROR_INVALID_PACKET;
488 
489  //The variable header contains the Packet Identifier from the PUBLISH
490  //packet that is being acknowledged
491  error = mqttDeserializeShort(context->packet, context->packetLen,
492  &context->packetPos, &packetId);
493 
494  //Failed to deserialize Packet Identifier field?
495  if(error)
496  return error;
497 
498  //Any registered callback?
499  if(context->callbacks.pubRecCallback != NULL)
500  {
501  //Invoke user callback function
502  context->callbacks.pubRecCallback(context, packetId);
503  }
504 
505  //A PUBREL packet is the response to a PUBREC packet. It is the third
506  //packet of the QoS 2 protocol exchange
507  error = mqttClientFormatPubRel(context, packetId);
508 
509  //Check status code
510  if(!error)
511  {
512  //Debug message
513  TRACE_INFO("MQTT: Sending PUBREL packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
514  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
515 
516  //Point to the beginning of the packet
517  context->packetPos = 0;
518 
519  //Send PUBREL packet
521  }
522 
523  //Return status code
524  return error;
525 }
526 
527 
528 /**
529  * @brief Process incoming PUBREL packet
530  * @param[in] context Pointer to the MQTT client context
531  * @param[in] dup DUP flag from the fixed header
532  * @param[in] qos QoS field from the fixed header
533  * @param[in] retain RETAIN flag from the fixed header
534  * @param[in] remainingLen Length of the variable header and the payload
535  **/
536 
538  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
539 {
540  error_t error;
541  uint16_t packetId;
542 
543  //If invalid flags are received, the receiver must close the network connection
544  if(dup != FALSE && qos != MQTT_QOS_LEVEL_1 && retain != FALSE)
545  return ERROR_INVALID_PACKET;
546 
547  //The variable header contains the same Packet Identifier as the PUBREC
548  //packet that is being acknowledged
549  error = mqttDeserializeShort(context->packet, context->packetLen,
550  &context->packetPos, &packetId);
551 
552  //Failed to deserialize Packet Identifier field?
553  if(error)
554  return error;
555 
556  //Any registered callback?
557  if(context->callbacks.pubRelCallback != NULL)
558  {
559  //Invoke user callback function
560  context->callbacks.pubRelCallback(context, packetId);
561  }
562 
563  //A PUBCOMP packet is the response to a PUBREL packet. It is the fourth and
564  //final packet of the QoS 2 protocol exchange
565  error = mqttClientFormatPubComp(context, packetId);
566 
567  //Check status code
568  if(!error)
569  {
570  //Debug message
571  TRACE_INFO("MQTT: Sending PUBCOMP packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
572  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
573 
574  //Point to the beginning of the packet
575  context->packetPos = 0;
576 
577  //Send PUBCOMP packet
579  }
580 
581  //Return status code
582  return error;
583 }
584 
585 
586 /**
587  * @brief Process incoming PUBCOMP packet
588  * @param[in] context Pointer to the MQTT client context
589  * @param[in] dup DUP flag from the fixed header
590  * @param[in] qos QoS field from the fixed header
591  * @param[in] retain RETAIN flag from the fixed header
592  * @param[in] remainingLen Length of the variable header and the payload
593  **/
594 
596  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
597 {
598  error_t error;
599  uint16_t packetId;
600 
601  //If invalid flags are received, the receiver must close the network connection
602  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
603  return ERROR_INVALID_PACKET;
604 
605  //The variable header contains the same Packet Identifier as the PUBREL
606  //packet that is being acknowledged
607  error = mqttDeserializeShort(context->packet, context->packetLen,
608  &context->packetPos, &packetId);
609 
610  //Failed to deserialize Packet Identifier field?
611  if(error)
612  return error;
613 
614  //Any registered callback?
615  if(context->callbacks.pubCompCallback != NULL)
616  {
617  //Invoke user callback function
618  context->callbacks.pubCompCallback(context, packetId);
619  }
620 
621  //Notify the application that a PUBCOMP packet has been received
622  if(context->packetType == MQTT_PACKET_TYPE_PUBLISH && context->packetId == packetId)
624 
625  //Successful processing
626  return NO_ERROR;
627 }
628 
629 
630 /**
631  * @brief Process incoming SUBACK packet
632  * @param[in] context Pointer to the MQTT client context
633  * @param[in] dup DUP flag from the fixed header
634  * @param[in] qos QoS field from the fixed header
635  * @param[in] retain RETAIN flag from the fixed header
636  * @param[in] remainingLen Length of the variable header and the payload
637  **/
638 
640  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
641 {
642  error_t error;
643  uint16_t packetId;
644 
645  //If invalid flags are received, the receiver must close the network connection
646  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
647  return ERROR_INVALID_PACKET;
648 
649  //The variable header contains the Packet Identifier from the SUBSCRIBE
650  //packet that is being acknowledged
651  error = mqttDeserializeShort(context->packet, context->packetLen,
652  &context->packetPos, &packetId);
653 
654  //Failed to deserialize Packet Identifier field?
655  if(error)
656  return error;
657 
658  //Any registered callback?
659  if(context->callbacks.subAckCallback != NULL)
660  {
661  //Invoke user callback function
662  context->callbacks.subAckCallback(context, packetId);
663  }
664 
665  //Notify the application that a SUBACK packet has been received
666  if(context->packetType == MQTT_PACKET_TYPE_SUBSCRIBE && context->packetId == packetId)
668 
669  //Successful processing
670  return NO_ERROR;
671 }
672 
673 
674 /**
675  * @brief Process incoming UNSUBACK packet
676  * @param[in] context Pointer to the MQTT client context
677  * @param[in] dup DUP flag from the fixed header
678  * @param[in] qos QoS field from the fixed header
679  * @param[in] retain RETAIN flag from the fixed header
680  * @param[in] remainingLen Length of the variable header and the payload
681  **/
682 
684  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
685 {
686  error_t error;
687  uint16_t packetId;
688 
689  //If invalid flags are received, the receiver must close the network connection
690  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
691  return ERROR_INVALID_PACKET;
692 
693  //The variable header contains the Packet Identifier from the UNSUBSCRIBE
694  //packet that is being acknowledged
695  error = mqttDeserializeShort(context->packet, context->packetLen,
696  &context->packetPos, &packetId);
697 
698  //Failed to deserialize Packet Identifier field?
699  if(error)
700  return error;
701 
702  //Any registered callback?
703  if(context->callbacks.unsubAckCallback != NULL)
704  {
705  //Invoke user callback function
706  context->callbacks.unsubAckCallback(context, packetId);
707  }
708 
709  //Notify the application that an UNSUBACK packet has been received
710  if(context->packetType == MQTT_PACKET_TYPE_UNSUBSCRIBE && context->packetId == packetId)
712 
713  //Successful processing
714  return NO_ERROR;
715 }
716 
717 
718 /**
719  * @brief Process incoming PINGRESP packet
720  * @param[in] context Pointer to the MQTT client context
721  * @param[in] dup DUP flag from the fixed header
722  * @param[in] qos QoS field from the fixed header
723  * @param[in] retain RETAIN flag from the fixed header
724  * @param[in] remainingLen Length of the variable header and the payload
725  **/
726 
728  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
729 {
730  //If invalid flags are received, the receiver must close the network connection
731  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
732  return ERROR_INVALID_PACKET;
733 
734  //Any registered callback?
735  if(context->callbacks.pingRespCallback != NULL)
736  {
737  //Invoke user callback function
738  context->callbacks.pingRespCallback(context);
739  }
740 
741  //Notify the application that an PINGRESP packet has been received
742  if(context->packetType == MQTT_PACKET_TYPE_PINGREQ)
744 
745  //Successful processing
746  return NO_ERROR;
747 }
748 
749 
750 /**
751  * @brief Format CONNECT packet
752  * @param[in] context Pointer to the MQTT client context
753  * @param[in] cleanSession If this flag is set, then the client and server
754  * must discard any previous session and start a new one
755  * @return Error code
756  **/
757 
759  bool_t cleanSession)
760 {
761  error_t error;
762  size_t n;
763  uint8_t connectFlags;
764  MqttClientWillMessage *willMessage;
765 
766  //Make room for the fixed header
768 
769  //Check protocol version
770  if(context->settings.version == MQTT_VERSION_3_1)
771  {
772  //The Protocol Name is a UTF-8 encoded string that represents the
773  //protocol name "MQIsdp"
774  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
776  }
777  else if(context->settings.version == MQTT_VERSION_3_1_1)
778  {
779  //The Protocol Name is a UTF-8 encoded string that represents the
780  //protocol name "MQTT"
781  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
783  }
784  else
785  {
786  //Invalid protocol level
787  error = ERROR_INVALID_VERSION;
788  }
789 
790  //Any error to report?
791  if(error)
792  return error;
793 
794  //The Protocol Level represents the revision level of the protocol
795  //used by the client
796  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
797  &n, context->settings.version);
798 
799  //Failed to serialize data?
800  if(error)
801  return error;
802 
803  //The Connect Flags byte contains a number of parameters specifying
804  //the behavior of the MQTT connection
805  connectFlags = 0;
806 
807  //If CleanSession is set to 1, the client and server must discard any
808  //previous session and start a new one
809  if(cleanSession)
810  connectFlags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
811 
812  //If the client supplies a zero-byte Client Identifier, the client must
813  //also set CleanSession to 1
814  if(context->settings.clientId[0] == '\0')
815  connectFlags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
816 
817  //Point to the Will message
818  willMessage = &context->settings.willMessage;
819 
820  //Check whether a valid Will message has been specified
821  if(willMessage->topic[0] != '\0')
822  {
823  //Set the Will flag
824  connectFlags |= MQTT_CONNECT_FLAG_WILL;
825 
826  //Check the Will QoS level
827  if(willMessage->qos == MQTT_QOS_LEVEL_1)
828  {
829  connectFlags |= MQTT_CONNECT_FLAG_WILL_QOS_1;
830  }
831  else if(willMessage->qos == MQTT_QOS_LEVEL_2)
832  {
833  connectFlags |= MQTT_CONNECT_FLAG_WILL_QOS_2;
834  }
835 
836  //The Will Retain flag specifies if the Will Message is to be
837  //retained when it is published
838  if(willMessage->retain)
839  connectFlags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
840  }
841 
842  //Check whether a valid user name has been specified
843  if(context->settings.username[0] != '\0')
844  connectFlags |= MQTT_CONNECT_FLAG_USERNAME;
845 
846  //Check whether a valid password has been specified
847  if(context->settings.password[0] != '\0')
848  connectFlags |= MQTT_CONNECT_FLAG_PASSWORD;
849 
850  //Write the Connect Flags to the output buffer
851  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
852  &n, connectFlags);
853 
854  //Failed to serialize data?
855  if(error)
856  return error;
857 
858  //The Keep Alive is a time interval measured in seconds. It is the maximum
859  //time interval that is permitted to elapse between the point at which the
860  //client finishes transmitting one control packet and the point it starts
861  //sending the next
862  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
863  &n, context->settings.keepAlive);
864 
865  //Failed to serialize data?
866  if(error)
867  return error;
868 
869  //The Client Identifier identifies the client to the server. The Client
870  //Identifier must be present and must be the first field in the CONNECT
871  //packet payload
872  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
873  &n, context->settings.clientId, osStrlen(context->settings.clientId));
874 
875  //Failed to serialize data?
876  if(error)
877  return error;
878 
879  //If the Will Flag is set to 1, the Will Topic is the next field in
880  //the payload
881  if(willMessage->topic[0] != '\0')
882  {
883  //Write the Will Topic to the output buffer
884  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
885  &n, willMessage->topic, osStrlen(willMessage->topic));
886 
887  //Failed to serialize data?
888  if(error)
889  return error;
890 
891  //Write the Will message to the output buffer
892  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
893  &n, willMessage->payload, willMessage->length);
894 
895  //Failed to serialize data?
896  if(error)
897  return error;
898  }
899 
900  //If the User Name Flag is set to 1, this is the next field in the payload
901  if(context->settings.username[0] != '\0')
902  {
903  //Write the User Name to the output buffer
904  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
905  &n, context->settings.username, osStrlen(context->settings.username));
906 
907  //Failed to serialize data?
908  if(error)
909  return error;
910  }
911 
912  //If the Password Flag is set to 1, this is the next field in the payload
913  if(context->settings.password[0] != '\0')
914  {
915  //Write the Password to the output buffer
916  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
917  &n, context->settings.password, osStrlen(context->settings.password));
918 
919  //Failed to serialize data?
920  if(error)
921  return error;
922  }
923 
924  //Calculate the length of the variable header and the payload
925  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
926 
927  //The fixed header will be encoded in reverse order
929 
930  //Prepend the variable header and the payload with the fixed header
931  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_CONNECT,
932  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
933 
934  //Failed to serialize fixed header?
935  if(error)
936  return error;
937 
938  //Point to the first byte of the MQTT packet
939  context->packet = context->buffer + n;
940  //Calculate the length of the MQTT packet
941  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
942 
943  //Successful processing
944  return NO_ERROR;
945 }
946 
947 
948 /**
949  * @brief Format PUBLISH packet
950  * @param[in] context Pointer to the MQTT client context
951  * @param[in] topic Topic name
952  * @param[in] message Message payload
953  * @param[in] length Length of the message payload
954  * @param[in] qos QoS level to be used when publishing the message
955  * @param[in] retain This flag specifies if the message is to be retained
956  * @return Error code
957  **/
958 
960  const void *message, size_t length, MqttQosLevel qos, bool_t retain)
961 {
962  error_t error;
963  size_t n;
964 
965  //Make room for the fixed header
967 
968  //The Topic Name must be present as the first field in the PUBLISH
969  //packet variable header
970  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
971  &n, topic, osStrlen(topic));
972 
973  //Failed to serialize Topic Name?
974  if(error)
975  return error;
976 
977  //Check QoS level
978  if(qos != MQTT_QOS_LEVEL_0)
979  {
980  //Each time a client sends a new PUBLISH packet it must assign it
981  //a currently unused packet identifier
982  context->packetId++;
983 
984  //The Packet Identifier field is only present in PUBLISH packets
985  //where the QoS level is 1 or 2
986  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
987  &n, context->packetId);
988 
989  //Failed to serialize Packet Identifier field?
990  if(error)
991  return error;
992  }
993 
994  //The payload contains the Application Message that is being published
995  error = mqttSerializeData(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
996  &n, message, length);
997 
998  //Failed to serialize Application Message?
999  if(error)
1000  return error;
1001 
1002  //Calculate the length of the variable header and the payload
1003  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1004 
1005  //The fixed header will be encoded in reverse order
1007 
1008  //Prepend the variable header and the payload with the fixed header
1009  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBLISH,
1010  FALSE, qos, retain, context->packetLen);
1011 
1012  //Failed to serialize fixed header?
1013  if(error)
1014  return error;
1015 
1016  //Point to the first byte of the MQTT packet
1017  context->packet = context->buffer + n;
1018  //Calculate the length of the MQTT packet
1019  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1020 
1021  //Successful processing
1022  return NO_ERROR;
1023 }
1024 
1025 
1026 /**
1027  * @brief Format PUBACK packet
1028  * @param[in] context Pointer to the MQTT client context
1029  * @param[in] packetId Packet identifier
1030  * @return Error code
1031  **/
1032 
1034 {
1035  error_t error;
1036  size_t n;
1037 
1038  //Make room for the fixed header
1040 
1041  //The variable header contains the Packet Identifier from the PUBLISH
1042  //packet that is being acknowledged
1043  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1044  &n, packetId);
1045 
1046  //Failed to serialize Packet Identifier field?
1047  if(error)
1048  return error;
1049 
1050  //Calculate the length of the variable header and the payload
1051  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1052 
1053  //The fixed header will be encoded in reverse order
1055 
1056  //Prepend the variable header and the payload with the fixed header
1057  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBACK,
1058  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1059 
1060  //Failed to serialize fixed header?
1061  if(error)
1062  return error;
1063 
1064  //Point to the first byte of the MQTT packet
1065  context->packet = context->buffer + n;
1066  //Calculate the length of the MQTT packet
1067  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1068 
1069  //Successful processing
1070  return NO_ERROR;
1071 }
1072 
1073 
1074 /**
1075  * @brief Format PUBREC packet
1076  * @param[in] context Pointer to the MQTT client context
1077  * @param[in] packetId Packet identifier
1078  * @return Error code
1079  **/
1080 
1082 {
1083  error_t error;
1084  size_t n;
1085 
1086  //Make room for the fixed header
1088 
1089  //The variable header contains the Packet Identifier from the PUBLISH
1090  //packet that is being acknowledged
1091  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1092  &n, packetId);
1093 
1094  //Failed to serialize Packet Identifier field?
1095  if(error)
1096  return error;
1097 
1098  //Calculate the length of the variable header and the payload
1099  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1100 
1101  //The fixed header will be encoded in reverse order
1103 
1104  //Prepend the variable header and the payload with the fixed header
1105  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBREC,
1106  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1107 
1108  //Failed to serialize fixed header?
1109  if(error)
1110  return error;
1111 
1112  //Point to the first byte of the MQTT packet
1113  context->packet = context->buffer + n;
1114  //Calculate the length of the MQTT packet
1115  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1116 
1117  //Successful processing
1118  return NO_ERROR;
1119 }
1120 
1121 
1122 /**
1123  * @brief Format PUBREL packet
1124  * @param[in] context Pointer to the MQTT client context
1125  * @param[in] packetId Packet identifier
1126  * @return Error code
1127  **/
1128 
1130 {
1131  error_t error;
1132  size_t n;
1133 
1134  //Make room for the fixed header
1136 
1137  //The variable header contains the same Packet Identifier as the PUBREC
1138  //packet that is being acknowledged
1139  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1140  &n, packetId);
1141 
1142  //Failed to serialize Packet Identifier field?
1143  if(error)
1144  return error;
1145 
1146  //Calculate the length of the variable header and the payload
1147  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1148 
1149  //The fixed header will be encoded in reverse order
1151 
1152  //Prepend the variable header and the payload with the fixed header
1153  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBREL,
1154  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1155 
1156  //Failed to serialize fixed header?
1157  if(error)
1158  return error;
1159 
1160  //Point to the first byte of the MQTT packet
1161  context->packet = context->buffer + n;
1162  //Calculate the length of the MQTT packet
1163  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1164 
1165  //Successful processing
1166  return NO_ERROR;
1167 }
1168 
1169 
1170 /**
1171  * @brief Format PUBCOMP packet
1172  * @param[in] context Pointer to the MQTT client context
1173  * @param[in] packetId Packet identifier
1174  * @return Error code
1175  **/
1176 
1178 {
1179  error_t error;
1180  size_t n;
1181 
1182  //Make room for the fixed header
1184 
1185  //The variable header contains the same Packet Identifier as the PUBREL
1186  //packet that is being acknowledged
1187  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1188  &n, packetId);
1189 
1190  //Failed to serialize Packet Identifier field?
1191  if(error)
1192  return error;
1193 
1194  //Calculate the length of the variable header and the payload
1195  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1196 
1197  //The fixed header will be encoded in reverse order
1199 
1200  //Prepend the variable header and the payload with the fixed header
1201  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBCOMP,
1202  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1203 
1204  //Failed to serialize fixed header?
1205  if(error)
1206  return error;
1207 
1208  //Point to the first byte of the MQTT packet
1209  context->packet = context->buffer + n;
1210  //Calculate the length of the MQTT packet
1211  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1212 
1213  //Successful processing
1214  return NO_ERROR;
1215 }
1216 
1217 
1218 /**
1219  * @brief Format SUBSCRIBE packet
1220  * @param[in] context Pointer to the MQTT client context
1221  * @param[in] topic Topic filter
1222  * @param[in] qos Maximum QoS level at which the server can send application
1223  * messages to the client
1224  * @return Error code
1225  **/
1226 
1228  const char_t *topic, MqttQosLevel qos)
1229 {
1230  error_t error;
1231  size_t n;
1232 
1233  //Make room for the fixed header
1235 
1236  //Each time a client sends a new SUBSCRIBE packet it must assign it
1237  //a currently unused packet identifier
1238  context->packetId++;
1239 
1240  //Write Packet Identifier to the output buffer
1241  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1242  &n, context->packetId);
1243 
1244  //Failed to serialize data?
1245  if(error)
1246  return error;
1247 
1248  //Write the Topic Filter to the output buffer
1249  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1250  &n, topic, osStrlen(topic));
1251 
1252  //Failed to serialize data?
1253  if(error)
1254  return error;
1255 
1256  //Write the Requested QoS to the output buffer
1257  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1258  &n, qos);
1259 
1260  //Failed to serialize data?
1261  if(error)
1262  return error;
1263 
1264  //Calculate the length of the variable header and the payload
1265  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1266 
1267  //The fixed header will be encoded in reverse order
1269 
1270  //Prepend the variable header and the payload with the fixed header
1271  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_SUBSCRIBE,
1272  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1273 
1274  //Failed to serialize fixed header?
1275  if(error)
1276  return error;
1277 
1278  //Point to the first byte of the MQTT packet
1279  context->packet = context->buffer + n;
1280  //Calculate the length of the MQTT packet
1281  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1282 
1283  //Successful processing
1284  return NO_ERROR;
1285 }
1286 
1287 
1288 /**
1289  * @brief Format UNSUBSCRIBE packet
1290  * @param[in] context Pointer to the MQTT client context
1291  * @param[in] topic Topic filter
1292  * @return Error code
1293  **/
1294 
1296  const char_t *topic)
1297 {
1298  error_t error;
1299  size_t n;
1300 
1301  //Make room for the fixed header
1303 
1304  //Each time a client sends a new UNSUBSCRIBE packet it must assign it
1305  //a currently unused packet identifier
1306  context->packetId++;
1307 
1308  //Write Packet Identifier to the output buffer
1309  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1310  &n, context->packetId);
1311 
1312  //Failed to serialize data?
1313  if(error)
1314  return error;
1315 
1316  //Write the Topic Filter to the output buffer
1317  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1318  &n, topic, osStrlen(topic));
1319 
1320  //Failed to serialize data?
1321  if(error)
1322  return error;
1323 
1324  //Calculate the length of the variable header and the payload
1325  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1326 
1327  //The fixed header will be encoded in reverse order
1329 
1330  //Prepend the variable header and the payload with the fixed header
1331  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_UNSUBSCRIBE,
1332  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1333 
1334  //Failed to serialize fixed header?
1335  if(error)
1336  return error;
1337 
1338  //Point to the first byte of the MQTT packet
1339  context->packet = context->buffer + n;
1340  //Calculate the length of the MQTT packet
1341  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1342 
1343  //Successful processing
1344  return NO_ERROR;
1345 }
1346 
1347 
1348 /**
1349  * @brief Format PINGREQ packet
1350  * @param[in] context Pointer to the MQTT client context
1351  * @return Error code
1352  **/
1353 
1355 {
1356  error_t error;
1357  size_t n;
1358 
1359  //The fixed header will be encoded in reverse order
1361 
1362  //The PINGREQ packet does not contain any variable header nor payload
1363  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PINGREQ,
1365 
1366  //Failed to serialize fixed header?
1367  if(error)
1368  return error;
1369 
1370  //Point to the first byte of the MQTT packet
1371  context->packet = context->buffer + n;
1372  //Calculate the length of the MQTT packet
1373  context->packetLen = MQTT_MAX_HEADER_SIZE - n;
1374 
1375  //Successful processing
1376  return NO_ERROR;
1377 }
1378 
1379 
1380 /**
1381  * @brief Format DISCONNECT packet
1382  * @param[in] context Pointer to the MQTT client context
1383  * @return Error code
1384  **/
1385 
1387 {
1388  error_t error;
1389  size_t n;
1390 
1391  //The fixed header will be encoded in reverse order
1393 
1394  //The DISCONNECT packet does not contain any variable header nor payload
1395  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_DISCONNECT,
1397 
1398  //Failed to serialize fixed header?
1399  if(error)
1400  return error;
1401 
1402  //Point to the first byte of the MQTT packet
1403  context->packet = context->buffer + n;
1404  //Calculate the length of the MQTT packet
1405  context->packetLen = MQTT_MAX_HEADER_SIZE - n;
1406 
1407  //Successful processing
1408  return NO_ERROR;
1409 }
1410 
1411 #endif
uint8_t message[]
Definition: chap.h:154
uint8_t type
Definition: coap_common.h:176
#define PRIuSIZE
char char_t
Definition: compiler_port.h:48
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:108
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_CONNECTION_REFUSED
Definition: error.h:77
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PACKET
Definition: error.h:140
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_VERSION
Definition: error.h:118
MQTT client.
#define MQTT_CLIENT_BUFFER_SIZE
Definition: mqtt_client.h:124
@ MQTT_CLIENT_STATE_PACKET_RECEIVED
Definition: mqtt_client.h:169
@ MQTT_CLIENT_STATE_SENDING_PACKET
Definition: mqtt_client.h:165
#define MqttClientContext
Definition: mqtt_client.h:147
error_t mqttDeserializeHeader(uint8_t *buffer, size_t bufferLen, size_t *pos, MqttPacketType *type, bool_t *dup, MqttQosLevel *qos, bool_t *retain, size_t *remainingLen)
Deserialize fixed header.
error_t mqttDeserializeByte(uint8_t *buffer, size_t bufferLen, size_t *pos, uint8_t *value)
Read a 8-bit integer from the input buffer.
error_t mqttSerializeData(uint8_t *buffer, size_t bufferLen, size_t *pos, const void *data, size_t dataLen)
Serialize raw data.
error_t mqttSerializeString(uint8_t *buffer, size_t bufferLen, size_t *pos, const void *string, size_t stringLen)
Serialize string.
error_t mqttDeserializeShort(uint8_t *buffer, size_t bufferLen, size_t *pos, uint16_t *value)
Read a 16-bit integer from the input buffer.
error_t mqttSerializeHeader(uint8_t *buffer, size_t *pos, MqttPacketType type, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Serialize fixed header.
error_t mqttSerializeShort(uint8_t *buffer, size_t bufferLen, size_t *pos, uint16_t value)
Write a 16-bit integer to the output buffer.
error_t mqttDeserializeString(uint8_t *buffer, size_t bufferLen, size_t *pos, char_t **string, size_t *stringLen)
Deserialize string.
error_t mqttSerializeByte(uint8_t *buffer, size_t bufferLen, size_t *pos, uint8_t value)
Write a 8-bit integer to the output buffer.
void mqttClientChangeState(MqttClientContext *context, MqttClientState newState)
Update MQTT client state.
Helper functions for MQTT client.
error_t mqttClientFormatPublish(MqttClientContext *context, const char_t *topic, const void *message, size_t length, MqttQosLevel qos, bool_t retain)
Format PUBLISH packet.
error_t mqttClientFormatUnsubscribe(MqttClientContext *context, const char_t *topic)
Format UNSUBSCRIBE packet.
error_t mqttClientFormatSubscribe(MqttClientContext *context, const char_t *topic, MqttQosLevel qos)
Format SUBSCRIBE packet.
error_t mqttClientProcessPubComp(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBCOMP packet.
error_t mqttClientProcessSubAck(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming SUBACK packet.
error_t mqttClientFormatConnect(MqttClientContext *context, bool_t cleanSession)
Format CONNECT packet.
error_t mqttClientFormatPubRel(MqttClientContext *context, uint16_t packetId)
Format PUBREL packet.
error_t mqttClientProcessConnAck(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming CONNACK packet.
error_t mqttClientProcessPubRec(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBREC packet.
error_t mqttClientFormatPingReq(MqttClientContext *context)
Format PINGREQ packet.
error_t mqttClientProcessPacket(MqttClientContext *context)
Process incoming MQTT packet.
error_t mqttClientProcessUnsubAck(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming UNSUBACK packet.
error_t mqttClientProcessPubAck(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBACK packet.
error_t mqttClientFormatDisconnect(MqttClientContext *context)
Format DISCONNECT packet.
error_t mqttClientFormatPubAck(MqttClientContext *context, uint16_t packetId)
Format PUBACK packet.
error_t mqttClientFormatPubRec(MqttClientContext *context, uint16_t packetId)
Format PUBREC packet.
error_t mqttClientProcessPingResp(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PINGRESP packet.
const char_t *const mqttPacketLabel[16]
error_t mqttClientFormatPubComp(MqttClientContext *context, uint16_t packetId)
Format PUBCOMP packet.
error_t mqttClientReceivePacket(MqttClientContext *context)
Receive MQTT packet.
error_t mqttClientProcessPubRel(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBREL packet.
error_t mqttClientProcessPublish(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBLISH packet.
MQTT packet parsing and formatting.
error_t mqttClientReceiveData(MqttClientContext *context, void *data, size_t size, size_t *received, uint_t flags)
Receive data using the relevant transport protocol.
Transport protocol abstraction layer.
#define MQTT_PROTOCOL_NAME_3_1_1
Definition: mqtt_common.h:45
#define MQTT_PROTOCOL_NAME_3_1
Definition: mqtt_common.h:43
@ MQTT_CONNECT_FLAG_PASSWORD
Definition: mqtt_common.h:130
@ MQTT_CONNECT_FLAG_WILL_RETAIN
Definition: mqtt_common.h:129
@ MQTT_CONNECT_FLAG_WILL
Definition: mqtt_common.h:125
@ MQTT_CONNECT_FLAG_CLEAN_SESSION
Definition: mqtt_common.h:124
@ MQTT_CONNECT_FLAG_USERNAME
Definition: mqtt_common.h:131
@ MQTT_CONNECT_FLAG_WILL_QOS_1
Definition: mqtt_common.h:127
@ MQTT_CONNECT_FLAG_WILL_QOS_2
Definition: mqtt_common.h:128
uint8_t dup
Definition: mqtt_common.h:182
uint8_t qos
Definition: mqtt_common.h:181
MqttQosLevel
Quality of service level.
Definition: mqtt_common.h:87
@ MQTT_QOS_LEVEL_2
Exactly once delivery.
Definition: mqtt_common.h:90
@ MQTT_QOS_LEVEL_1
At least once delivery.
Definition: mqtt_common.h:89
@ MQTT_QOS_LEVEL_0
At most once delivery.
Definition: mqtt_common.h:88
#define MQTT_MAX_HEADER_SIZE
Definition: mqtt_common.h:50
@ MQTT_VERSION_3_1
MQTT version 3.1.
Definition: mqtt_common.h:64
@ MQTT_VERSION_3_1_1
MQTT version 3.1.1.
Definition: mqtt_common.h:65
@ MQTT_CONNECT_RET_CODE_ACCEPTED
Definition: mqtt_common.h:151
MqttPacketType
MQTT control packet type.
Definition: mqtt_common.h:99
@ MQTT_PACKET_TYPE_DISCONNECT
Client is disconnecting.
Definition: mqtt_common.h:114
@ MQTT_PACKET_TYPE_SUBACK
Subscribe acknowledgment.
Definition: mqtt_common.h:109
@ MQTT_PACKET_TYPE_PUBACK
Publish acknowledgment.
Definition: mqtt_common.h:104
@ MQTT_PACKET_TYPE_SUBSCRIBE
Client subscribe request.
Definition: mqtt_common.h:108
@ MQTT_PACKET_TYPE_UNSUBSCRIBE
Unsubscribe request.
Definition: mqtt_common.h:110
@ MQTT_PACKET_TYPE_CONNACK
Connect acknowledgment.
Definition: mqtt_common.h:102
@ MQTT_PACKET_TYPE_PINGRESP
Ping response.
Definition: mqtt_common.h:113
@ MQTT_PACKET_TYPE_PUBCOMP
Publish complete (assured delivery part 3)
Definition: mqtt_common.h:107
@ MQTT_PACKET_TYPE_PUBREC
Publish received (assured delivery part 1)
Definition: mqtt_common.h:105
@ MQTT_PACKET_TYPE_PINGREQ
Ping request.
Definition: mqtt_common.h:112
@ MQTT_PACKET_TYPE_CONNECT
Client request to connect to server.
Definition: mqtt_common.h:101
@ MQTT_PACKET_TYPE_PUBLISH
Publish message.
Definition: mqtt_common.h:103
@ MQTT_PACKET_TYPE_UNSUBACK
Unsubscribe acknowledgment.
Definition: mqtt_common.h:111
@ MQTT_PACKET_TYPE_PUBREL
Publish release (assured delivery part 2)
Definition: mqtt_common.h:106
TCP/IP stack core.
#define osMemmove(dest, src, length)
Definition: os_port.h:147
#define osStrlen(s)
Definition: os_port.h:165
#define FALSE
Definition: os_port.h:46
uint8_t payload[MQTT_CLIENT_MAX_WILL_PAYLOAD_LEN]
Will message payload.
Definition: mqtt_client.h:266
char_t topic[MQTT_CLIENT_MAX_WILL_TOPIC_LEN+1]
Will topic name.
Definition: mqtt_client.h:265
size_t length
Length of the Will message payload.
Definition: mqtt_client.h:267
MqttQosLevel qos
QoS level to be used when publishing the Will message.
Definition: mqtt_client.h:268
bool_t retain
Specifies if the Will message is to be retained.
Definition: mqtt_client.h:269
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369