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