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-2025 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.5.4
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] dup DUP flag
955  * @param[in] qos QoS level to be used when publishing the message
956  * @param[in] retain This flag specifies if the message is to be retained
957  * @return Error code
958  **/
959 
961  const void *message, size_t length, bool_t dup, MqttQosLevel qos,
962  bool_t retain)
963 {
964  error_t error;
965  size_t n;
966 
967  //Make room for the fixed header
969 
970  //The Topic Name must be present as the first field in the PUBLISH
971  //packet variable header
972  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
973  &n, topic, osStrlen(topic));
974 
975  //Failed to serialize Topic Name?
976  if(error)
977  return error;
978 
979  //Check QoS level
980  if(qos != MQTT_QOS_LEVEL_0)
981  {
982  //Each time a client sends a new PUBLISH packet it must assign it
983  //a currently unused packet identifier
984  if(context->packetId < UINT16_MAX)
985  {
986  context->packetId++;
987  }
988  else
989  {
990  context->packetId = 1;
991  }
992 
993  //The Packet Identifier field is only present in PUBLISH packets
994  //where the QoS level is 1 or 2
995  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
996  &n, context->packetId);
997 
998  //Failed to serialize Packet Identifier field?
999  if(error)
1000  return error;
1001  }
1002 
1003  //The payload contains the Application Message that is being published
1004  error = mqttSerializeData(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1005  &n, message, length);
1006 
1007  //Failed to serialize Application Message?
1008  if(error)
1009  return error;
1010 
1011  //Calculate the length of the variable header and the payload
1012  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1013 
1014  //The fixed header will be encoded in reverse order
1016 
1017  //Prepend the variable header and the payload with the fixed header
1018  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBLISH,
1019  dup, qos, retain, context->packetLen);
1020 
1021  //Failed to serialize fixed header?
1022  if(error)
1023  return error;
1024 
1025  //Point to the first byte of the MQTT packet
1026  context->packet = context->buffer + n;
1027  //Calculate the length of the MQTT packet
1028  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1029 
1030  //Successful processing
1031  return NO_ERROR;
1032 }
1033 
1034 
1035 /**
1036  * @brief Format PUBACK packet
1037  * @param[in] context Pointer to the MQTT client context
1038  * @param[in] packetId Packet identifier
1039  * @return Error code
1040  **/
1041 
1043 {
1044  error_t error;
1045  size_t n;
1046 
1047  //Make room for the fixed header
1049 
1050  //The variable header contains the Packet Identifier from the PUBLISH
1051  //packet that is being acknowledged
1052  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1053  &n, packetId);
1054 
1055  //Failed to serialize Packet Identifier field?
1056  if(error)
1057  return error;
1058 
1059  //Calculate the length of the variable header and the payload
1060  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1061 
1062  //The fixed header will be encoded in reverse order
1064 
1065  //Prepend the variable header and the payload with the fixed header
1066  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBACK,
1067  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1068 
1069  //Failed to serialize fixed header?
1070  if(error)
1071  return error;
1072 
1073  //Point to the first byte of the MQTT packet
1074  context->packet = context->buffer + n;
1075  //Calculate the length of the MQTT packet
1076  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1077 
1078  //Successful processing
1079  return NO_ERROR;
1080 }
1081 
1082 
1083 /**
1084  * @brief Format PUBREC packet
1085  * @param[in] context Pointer to the MQTT client context
1086  * @param[in] packetId Packet identifier
1087  * @return Error code
1088  **/
1089 
1091 {
1092  error_t error;
1093  size_t n;
1094 
1095  //Make room for the fixed header
1097 
1098  //The variable header contains the Packet Identifier from the PUBLISH
1099  //packet that is being acknowledged
1100  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1101  &n, packetId);
1102 
1103  //Failed to serialize Packet Identifier field?
1104  if(error)
1105  return error;
1106 
1107  //Calculate the length of the variable header and the payload
1108  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1109 
1110  //The fixed header will be encoded in reverse order
1112 
1113  //Prepend the variable header and the payload with the fixed header
1114  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBREC,
1115  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1116 
1117  //Failed to serialize fixed header?
1118  if(error)
1119  return error;
1120 
1121  //Point to the first byte of the MQTT packet
1122  context->packet = context->buffer + n;
1123  //Calculate the length of the MQTT packet
1124  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1125 
1126  //Successful processing
1127  return NO_ERROR;
1128 }
1129 
1130 
1131 /**
1132  * @brief Format PUBREL packet
1133  * @param[in] context Pointer to the MQTT client context
1134  * @param[in] packetId Packet identifier
1135  * @return Error code
1136  **/
1137 
1139 {
1140  error_t error;
1141  size_t n;
1142 
1143  //Make room for the fixed header
1145 
1146  //The variable header contains the same Packet Identifier as the PUBREC
1147  //packet that is being acknowledged
1148  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1149  &n, packetId);
1150 
1151  //Failed to serialize Packet Identifier field?
1152  if(error)
1153  return error;
1154 
1155  //Calculate the length of the variable header and the payload
1156  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1157 
1158  //The fixed header will be encoded in reverse order
1160 
1161  //Prepend the variable header and the payload with the fixed header
1162  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBREL,
1163  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1164 
1165  //Failed to serialize fixed header?
1166  if(error)
1167  return error;
1168 
1169  //Point to the first byte of the MQTT packet
1170  context->packet = context->buffer + n;
1171  //Calculate the length of the MQTT packet
1172  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1173 
1174  //Successful processing
1175  return NO_ERROR;
1176 }
1177 
1178 
1179 /**
1180  * @brief Format PUBCOMP packet
1181  * @param[in] context Pointer to the MQTT client context
1182  * @param[in] packetId Packet identifier
1183  * @return Error code
1184  **/
1185 
1187 {
1188  error_t error;
1189  size_t n;
1190 
1191  //Make room for the fixed header
1193 
1194  //The variable header contains the same Packet Identifier as the PUBREL
1195  //packet that is being acknowledged
1196  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1197  &n, packetId);
1198 
1199  //Failed to serialize Packet Identifier field?
1200  if(error)
1201  return error;
1202 
1203  //Calculate the length of the variable header and the payload
1204  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1205 
1206  //The fixed header will be encoded in reverse order
1208 
1209  //Prepend the variable header and the payload with the fixed header
1210  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBCOMP,
1211  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1212 
1213  //Failed to serialize fixed header?
1214  if(error)
1215  return error;
1216 
1217  //Point to the first byte of the MQTT packet
1218  context->packet = context->buffer + n;
1219  //Calculate the length of the MQTT packet
1220  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1221 
1222  //Successful processing
1223  return NO_ERROR;
1224 }
1225 
1226 
1227 /**
1228  * @brief Format SUBSCRIBE packet
1229  * @param[in] context Pointer to the MQTT client context
1230  * @param[in] topic Topic filter
1231  * @param[in] qos Maximum QoS level at which the server can send application
1232  * messages to the client
1233  * @return Error code
1234  **/
1235 
1237  const char_t *topic, MqttQosLevel qos)
1238 {
1239  error_t error;
1240  size_t n;
1241 
1242  //Make room for the fixed header
1244 
1245  //Each time a client sends a new SUBSCRIBE packet it must assign it
1246  //a currently unused packet identifier
1247  if(context->packetId < UINT16_MAX)
1248  {
1249  context->packetId++;
1250  }
1251  else
1252  {
1253  context->packetId = 1;
1254  }
1255 
1256  //Write Packet Identifier to the output buffer
1257  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1258  &n, context->packetId);
1259 
1260  //Failed to serialize data?
1261  if(error)
1262  return error;
1263 
1264  //Write the Topic Filter to the output buffer
1265  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1266  &n, topic, osStrlen(topic));
1267 
1268  //Failed to serialize data?
1269  if(error)
1270  return error;
1271 
1272  //Write the Requested QoS to the output buffer
1273  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1274  &n, qos);
1275 
1276  //Failed to serialize data?
1277  if(error)
1278  return error;
1279 
1280  //Calculate the length of the variable header and the payload
1281  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1282 
1283  //The fixed header will be encoded in reverse order
1285 
1286  //Prepend the variable header and the payload with the fixed header
1287  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_SUBSCRIBE,
1288  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1289 
1290  //Failed to serialize fixed header?
1291  if(error)
1292  return error;
1293 
1294  //Point to the first byte of the MQTT packet
1295  context->packet = context->buffer + n;
1296  //Calculate the length of the MQTT packet
1297  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1298 
1299  //Successful processing
1300  return NO_ERROR;
1301 }
1302 
1303 
1304 /**
1305  * @brief Format UNSUBSCRIBE packet
1306  * @param[in] context Pointer to the MQTT client context
1307  * @param[in] topic Topic filter
1308  * @return Error code
1309  **/
1310 
1312  const char_t *topic)
1313 {
1314  error_t error;
1315  size_t n;
1316 
1317  //Make room for the fixed header
1319 
1320  //Each time a client sends a new UNSUBSCRIBE packet it must assign it
1321  //a currently unused packet identifier
1322  if(context->packetId < UINT16_MAX)
1323  {
1324  context->packetId++;
1325  }
1326  else
1327  {
1328  context->packetId = 1;
1329  }
1330 
1331  //Write Packet Identifier to the output buffer
1332  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1333  &n, context->packetId);
1334 
1335  //Failed to serialize data?
1336  if(error)
1337  return error;
1338 
1339  //Write the Topic Filter to the output buffer
1340  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1341  &n, topic, osStrlen(topic));
1342 
1343  //Failed to serialize data?
1344  if(error)
1345  return error;
1346 
1347  //Calculate the length of the variable header and the payload
1348  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1349 
1350  //The fixed header will be encoded in reverse order
1352 
1353  //Prepend the variable header and the payload with the fixed header
1354  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_UNSUBSCRIBE,
1355  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1356 
1357  //Failed to serialize fixed header?
1358  if(error)
1359  return error;
1360 
1361  //Point to the first byte of the MQTT packet
1362  context->packet = context->buffer + n;
1363  //Calculate the length of the MQTT packet
1364  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1365 
1366  //Successful processing
1367  return NO_ERROR;
1368 }
1369 
1370 
1371 /**
1372  * @brief Format PINGREQ packet
1373  * @param[in] context Pointer to the MQTT client context
1374  * @return Error code
1375  **/
1376 
1378 {
1379  error_t error;
1380  size_t n;
1381 
1382  //The fixed header will be encoded in reverse order
1384 
1385  //The PINGREQ packet does not contain any variable header nor payload
1386  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PINGREQ,
1388 
1389  //Failed to serialize fixed header?
1390  if(error)
1391  return error;
1392 
1393  //Point to the first byte of the MQTT packet
1394  context->packet = context->buffer + n;
1395  //Calculate the length of the MQTT packet
1396  context->packetLen = MQTT_MAX_HEADER_SIZE - n;
1397 
1398  //Successful processing
1399  return NO_ERROR;
1400 }
1401 
1402 
1403 /**
1404  * @brief Format DISCONNECT packet
1405  * @param[in] context Pointer to the MQTT client context
1406  * @return Error code
1407  **/
1408 
1410 {
1411  error_t error;
1412  size_t n;
1413 
1414  //The fixed header will be encoded in reverse order
1416 
1417  //The DISCONNECT packet does not contain any variable header nor payload
1418  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_DISCONNECT,
1420 
1421  //Failed to serialize fixed header?
1422  if(error)
1423  return error;
1424 
1425  //Point to the first byte of the MQTT packet
1426  context->packet = context->buffer + n;
1427  //Calculate the length of the MQTT packet
1428  context->packetLen = MQTT_MAX_HEADER_SIZE - n;
1429 
1430  //Successful processing
1431  return NO_ERROR;
1432 }
1433 
1434 #endif
error_t mqttSerializeData(uint8_t *buffer, size_t bufferLen, size_t *pos, const void *data, size_t dataLen)
Serialize raw data.
error_t mqttClientProcessPubAck(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBACK packet.
@ MQTT_CONNECT_FLAG_USERNAME
Definition: mqtt_common.h:131
error_t mqttClientProcessPingResp(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PINGRESP packet.
int bool_t
Definition: compiler_port.h:61
@ MQTT_PACKET_TYPE_DISCONNECT
Client is disconnecting.
Definition: mqtt_common.h:114
error_t mqttClientFormatPubAck(MqttClientContext *context, uint16_t packetId)
Format PUBACK packet.
error_t mqttClientFormatPingReq(MqttClientContext *context)
Format PINGREQ packet.
@ MQTT_QOS_LEVEL_2
Exactly once delivery.
Definition: mqtt_common.h:90
@ MQTT_CONNECT_RET_CODE_ACCEPTED
Definition: mqtt_common.h:151
uint8_t message[]
Definition: chap.h:154
error_t mqttClientProcessPubComp(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBCOMP packet.
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.
@ MQTT_CONNECT_FLAG_WILL_QOS_1
Definition: mqtt_common.h:127
@ MQTT_PACKET_TYPE_PUBLISH
Publish message.
Definition: mqtt_common.h:103
@ MQTT_PACKET_TYPE_PUBREC
Publish received (assured delivery part 1)
Definition: mqtt_common.h:105
error_t mqttClientReceivePacket(MqttClientContext *context)
Receive MQTT packet.
error_t mqttClientFormatPublish(MqttClientContext *context, const char_t *topic, const void *message, size_t length, bool_t dup, MqttQosLevel qos, bool_t retain)
Format PUBLISH packet.
uint8_t type
Definition: coap_common.h:176
error_t mqttDeserializeString(uint8_t *buffer, size_t bufferLen, size_t *pos, char_t **string, size_t *stringLen)
Deserialize string.
uint8_t qos
Definition: mqtt_common.h:181
@ ERROR_CONNECTION_REFUSED
Definition: error.h:77
#define osStrlen(s)
Definition: os_port.h:168
error_t mqttClientProcessPubRec(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBREC packet.
uint8_t payload[MQTT_CLIENT_MAX_WILL_PAYLOAD_LEN]
Will message payload.
Definition: mqtt_client.h:266
@ ERROR_INVALID_VERSION
Definition: error.h:118
error_t mqttDeserializeByte(uint8_t *buffer, size_t bufferLen, size_t *pos, uint8_t *value)
Read a 8-bit integer from the input buffer.
@ MQTT_CLIENT_STATE_SENDING_PACKET
Definition: mqtt_client.h:165
@ MQTT_PACKET_TYPE_CONNACK
Connect acknowledgment.
Definition: mqtt_common.h:102
error_t mqttClientFormatConnect(MqttClientContext *context, bool_t cleanSession)
Format CONNECT packet.
@ MQTT_CLIENT_STATE_PACKET_RECEIVED
Definition: mqtt_client.h:169
error_t mqttClientProcessSubAck(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming SUBACK packet.
error_t mqttClientFormatPubRel(MqttClientContext *context, uint16_t packetId)
Format PUBREL packet.
@ MQTT_CONNECT_FLAG_WILL_RETAIN
Definition: mqtt_common.h:129
error_t mqttClientProcessUnsubAck(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming UNSUBACK packet.
#define FALSE
Definition: os_port.h:46
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.
Helper functions for MQTT client.
void mqttClientChangeState(MqttClientContext *context, MqttClientState newState)
Update MQTT client state.
error_t
Error codes.
Definition: error.h:43
Transport protocol abstraction layer.
@ MQTT_PACKET_TYPE_PINGRESP
Ping response.
Definition: mqtt_common.h:113
@ MQTT_QOS_LEVEL_0
At most once delivery.
Definition: mqtt_common.h:88
error_t mqttSerializeByte(uint8_t *buffer, size_t bufferLen, size_t *pos, uint8_t value)
Write a 8-bit integer to the output buffer.
@ MQTT_PACKET_TYPE_PUBACK
Publish acknowledgment.
Definition: mqtt_common.h:104
MqttQosLevel
Quality of service level.
Definition: mqtt_common.h:87
@ MQTT_PACKET_TYPE_PINGREQ
Ping request.
Definition: mqtt_common.h:112
@ MQTT_PACKET_TYPE_SUBACK
Subscribe acknowledgment.
Definition: mqtt_common.h:109
error_t mqttClientProcessConnAck(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming CONNACK packet.
@ ERROR_INVALID_PACKET
Definition: error.h:141
@ ERROR_INVALID_LENGTH
Definition: error.h:111
error_t mqttClientFormatUnsubscribe(MqttClientContext *context, const char_t *topic)
Format UNSUBSCRIBE packet.
@ MQTT_PACKET_TYPE_CONNECT
Client request to connect to server.
Definition: mqtt_common.h:101
@ MQTT_PACKET_TYPE_SUBSCRIBE
Client subscribe request.
Definition: mqtt_common.h:108
MQTT packet parsing and formatting.
@ MQTT_PACKET_TYPE_UNSUBACK
Unsubscribe acknowledgment.
Definition: mqtt_common.h:111
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
error_t mqttClientProcessPubRel(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBREL packet.
error_t mqttClientProcessPacket(MqttClientContext *context)
Process incoming MQTT packet.
bool_t retain
Specifies if the Will message is to be retained.
Definition: mqtt_client.h:269
error_t mqttClientFormatPubRec(MqttClientContext *context, uint16_t packetId)
Format PUBREC packet.
@ MQTT_PACKET_TYPE_UNSUBSCRIBE
Unsubscribe request.
Definition: mqtt_common.h:110
error_t mqttClientFormatDisconnect(MqttClientContext *context)
Format DISCONNECT packet.
#define MQTT_PROTOCOL_NAME_3_1
Definition: mqtt_common.h:43
size_t length
Length of the Will message payload.
Definition: mqtt_client.h:267
error_t mqttClientReceiveData(MqttClientContext *context, void *data, size_t size, size_t *received, uint_t flags)
Receive data using the relevant transport protocol.
@ MQTT_CONNECT_FLAG_WILL_QOS_2
Definition: mqtt_common.h:128
char char_t
Definition: compiler_port.h:55
#define MQTT_MAX_HEADER_SIZE
Definition: mqtt_common.h:50
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
uint8_t n
@ MQTT_CONNECT_FLAG_PASSWORD
Definition: mqtt_common.h:130
@ MQTT_PACKET_TYPE_PUBCOMP
Publish complete (assured delivery part 3)
Definition: mqtt_common.h:107
uint8_t value[]
Definition: tcp.h:376
error_t mqttClientFormatPubComp(MqttClientContext *context, uint16_t packetId)
Format PUBCOMP packet.
error_t mqttClientProcessPublish(MqttClientContext *context, bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
Process incoming PUBLISH packet.
error_t mqttClientFormatSubscribe(MqttClientContext *context, const char_t *topic, MqttQosLevel qos)
Format SUBSCRIBE packet.
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
uint8_t dup
Definition: mqtt_common.h:182
@ MQTT_CONNECT_FLAG_CLEAN_SESSION
Definition: mqtt_common.h:124
@ MQTT_PACKET_TYPE_PUBREL
Publish release (assured delivery part 2)
Definition: mqtt_common.h:106
@ MQTT_VERSION_3_1_1
MQTT version 3.1.1.
Definition: mqtt_common.h:65
#define MqttClientContext
Definition: mqtt_client.h:147
MqttQosLevel qos
QoS level to be used when publishing the Will message.
Definition: mqtt_client.h:268
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 mqttSerializeShort(uint8_t *buffer, size_t bufferLen, size_t *pos, uint16_t value)
Write a 16-bit integer to the output buffer.
@ MQTT_QOS_LEVEL_1
At least once delivery.
Definition: mqtt_common.h:89
#define PRIuSIZE
TCP/IP stack core.
#define MQTT_CLIENT_BUFFER_SIZE
Definition: mqtt_client.h:124
@ MQTT_VERSION_3_1
MQTT version 3.1.
Definition: mqtt_common.h:64
error_t mqttSerializeString(uint8_t *buffer, size_t bufferLen, size_t *pos, const void *string, size_t stringLen)
Serialize string.
const char_t *const mqttPacketLabel[16]
char_t topic[MQTT_CLIENT_MAX_WILL_TOPIC_LEN+1]
Will topic name.
Definition: mqtt_client.h:265
@ NO_ERROR
Success.
Definition: error.h:44
MqttPacketType
MQTT control packet type.
Definition: mqtt_common.h:99
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:150
#define MQTT_PROTOCOL_NAME_3_1_1
Definition: mqtt_common.h:45
@ MQTT_CONNECT_FLAG_WILL
Definition: mqtt_common.h:125
MQTT client.