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-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.6
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 
205  //PUBLISH packet received?
207  //Process incoming PUBLISH packet
208  error = mqttClientProcessPublish(context, dup, qos, retain, remainingLen);
209  break;
210 
211  //PUBACK packet received?
213  //Process incoming PUBACK packet
214  error = mqttClientProcessPubAck(context, dup, qos, retain, remainingLen);
215  break;
216 
217  //PUBREC packet received?
219  //Process incoming PUBREC packet
220  error = mqttClientProcessPubRec(context, dup, qos, retain, remainingLen);
221  break;
222 
223  //PUBREL packet received?
225  //Process incoming PUBREL packet
226  error = mqttClientProcessPubRel(context, dup, qos, retain, remainingLen);
227  break;
228 
229  //PUBCOMP packet received?
231  //Process incoming PUBCOMP packet
232  error = mqttClientProcessPubComp(context, dup, qos, retain, remainingLen);
233  break;
234 
235  //SUBACK packet received?
237  //Process incoming SUBACK packet
238  error = mqttClientProcessSubAck(context, dup, qos, retain, remainingLen);
239  break;
240 
241  //UNSUBACK packet received?
243  //Process incoming UNSUBACK packet
244  error = mqttClientProcessUnsubAck(context, dup, qos, retain, remainingLen);
245  break;
246 
247  //PINGRESP packet received?
249  //Process incoming PINGRESP packet
250  error = mqttClientProcessPingResp(context, dup, qos, retain, remainingLen);
251  break;
252 
253  //Unknown packet received?
254  default:
255  //Report an error
256  error = ERROR_INVALID_PACKET;
257  }
258 
259  //Return status code
260  return error;
261 }
262 
263 
264 /**
265  * @brief Process incoming CONNACK packet
266  * @param[in] context Pointer to the MQTT client context
267  * @param[in] dup DUP flag from the fixed header
268  * @param[in] qos QoS field from the fixed header
269  * @param[in] retain RETAIN flag from the fixed header
270  * @param[in] remainingLen Length of the variable header and the payload
271  **/
272 
274  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
275 {
276  error_t error;
277  uint8_t connectAckFlags;
278  uint8_t connectReturnCode;
279 
280  //If invalid flags are received, the receiver must close the network connection
281  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
282  return ERROR_INVALID_PACKET;
283 
284  //The first byte of the variable header is the Connect Acknowledge Flags
285  error = mqttDeserializeByte(context->packet, context->packetLen,
286  &context->packetPos, &connectAckFlags);
287 
288  //Failed to deserialize the Connect Acknowledge Flags?
289  if(error)
290  return error;
291 
292  //The second byte of the variable header is the Connect Return Code
293  error = mqttDeserializeByte(context->packet, context->packetLen,
294  &context->packetPos, &connectReturnCode);
295 
296  //Failed to deserialize the Connect Return Code?
297  if(error)
298  return error;
299 
300  //Any registered callback?
301  if(context->callbacks.connAckCallback != NULL)
302  {
303  //Invoke user callback function
304  context->callbacks.connAckCallback(context,
305  connectAckFlags, connectReturnCode);
306  }
307 
308  //Make sure the connection is accepted
309  if(connectReturnCode != MQTT_CONNECT_RET_CODE_ACCEPTED)
311 
312  //Notify the application that a CONNACK packet has been received
313  if(context->packetType == MQTT_PACKET_TYPE_CONNECT)
314  {
316  }
317 
318  //Successful processing
319  return NO_ERROR;
320 }
321 
322 
323 /**
324  * @brief Process incoming PUBLISH packet
325  * @param[in] context Pointer to the MQTT client context
326  * @param[in] dup DUP flag from the fixed header
327  * @param[in] qos QoS field from the fixed header
328  * @param[in] retain RETAIN flag from the fixed header
329  * @param[in] remainingLen Length of the variable header and the payload
330  **/
331 
333  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
334 {
335  error_t error;
336  uint16_t packetId;
337  char_t *topic;
338  size_t topicLen;
339  uint8_t *message;
340  size_t messageLen;
341 
342  //The Topic Name must be present as the first field in the PUBLISH
343  //packet variable header
344  error = mqttDeserializeString(context->packet, context->packetLen,
345  &context->packetPos, &topic, &topicLen);
346 
347  //Failed to deserialize Topic Name?
348  if(error)
349  return error;
350 
351  //Check QoS level
352  if(qos != MQTT_QOS_LEVEL_0)
353  {
354  //The Packet Identifier field is only present in PUBLISH packets
355  //where the QoS level is 1 or 2
356  error = mqttDeserializeShort(context->packet, context->packetLen,
357  &context->packetPos, &packetId);
358 
359  //Failed to deserialize Packet Identifier field?
360  if(error)
361  return error;
362  }
363  else
364  {
365  //No packet identifier
366  packetId = 0;
367  }
368 
369  //The payload contains the Application Message that is being published
370  message = context->packet + context->packetPos;
371 
372  //The length of the payload can be calculated by subtracting the length of the
373  //variable header from the Remaining Length field that is in the fixed header
374  messageLen = context->packetLen - context->packetPos;
375 
376  //Make room for the NULL character at the end of the Topic Name
377  osMemmove(topic - 1, topic, topicLen);
378  //Properly terminate the string with a NULL character
379  topic[topicLen - 1] = '\0';
380  //Point to the first character of the Topic Name
381  topic--;
382 
383  //Any registered callback?
384  if(context->callbacks.publishCallback != NULL)
385  {
386  //Invoke user callback function
387  context->callbacks.publishCallback(context, topic,
388  message, messageLen, dup, qos, retain, packetId);
389  }
390 
391  //Check QoS level
392  if(qos == MQTT_QOS_LEVEL_1)
393  {
394  //A PUBACK packet is the response to a PUBLISH packet with QoS level 1
395  error = mqttClientFormatPubAck(context, packetId);
396 
397  //Check status code
398  if(!error)
399  {
400  //Debug message
401  TRACE_INFO("MQTT: Sending PUBACK packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
402  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
403 
404  //Point to the beginning of the packet
405  context->packetPos = 0;
406 
407  //Send PUBACK packet
409  }
410  }
411  else if(qos == MQTT_QOS_LEVEL_2)
412  {
413  //A PUBREC packet is the response to a PUBLISH packet with QoS 2. It is
414  //the second packet of the QoS 2 protocol exchange
415  error = mqttClientFormatPubRec(context, packetId);
416 
417  //Check status code
418  if(!error)
419  {
420  //Debug message
421  TRACE_INFO("MQTT: Sending PUBREC packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
422  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
423 
424  //Point to the beginning of the packet
425  context->packetPos = 0;
426 
427  //Send PUBREC packet
429  }
430  }
431 
432  //Return status code
433  return error;
434 }
435 
436 
437 /**
438  * @brief Process incoming PUBACK packet
439  * @param[in] context Pointer to the MQTT client context
440  * @param[in] dup DUP flag from the fixed header
441  * @param[in] qos QoS field from the fixed header
442  * @param[in] retain RETAIN flag from the fixed header
443  * @param[in] remainingLen Length of the variable header and the payload
444  **/
445 
447  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
448 {
449  error_t error;
450  uint16_t packetId;
451 
452  //If invalid flags are received, the receiver must close the network connection
453  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
454  return ERROR_INVALID_PACKET;
455 
456  //The variable header contains the Packet Identifier from the PUBLISH
457  //packet that is being acknowledged
458  error = mqttDeserializeShort(context->packet, context->packetLen,
459  &context->packetPos, &packetId);
460 
461  //Failed to deserialize Packet Identifier field?
462  if(error)
463  return error;
464 
465  //Any registered callback?
466  if(context->callbacks.pubAckCallback != NULL)
467  {
468  //Invoke user callback function
469  context->callbacks.pubAckCallback(context, packetId);
470  }
471 
472  //Notify the application that a PUBACK packet has been received
473  if(context->packetType == MQTT_PACKET_TYPE_PUBLISH && context->packetId == packetId)
474  {
476  }
477 
478  //Return status code
479  return error;
480 }
481 
482 
483 /**
484  * @brief Process incoming PUBREC packet
485  * @param[in] context Pointer to the MQTT client context
486  * @param[in] dup DUP flag from the fixed header
487  * @param[in] qos QoS field from the fixed header
488  * @param[in] retain RETAIN flag from the fixed header
489  * @param[in] remainingLen Length of the variable header and the payload
490  **/
491 
493  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
494 {
495  error_t error;
496  uint16_t packetId;
497 
498  //If invalid flags are received, the receiver must close the network connection
499  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
500  return ERROR_INVALID_PACKET;
501 
502  //The variable header contains the Packet Identifier from the PUBLISH
503  //packet that is being acknowledged
504  error = mqttDeserializeShort(context->packet, context->packetLen,
505  &context->packetPos, &packetId);
506 
507  //Failed to deserialize Packet Identifier field?
508  if(error)
509  return error;
510 
511  //Any registered callback?
512  if(context->callbacks.pubRecCallback != NULL)
513  {
514  //Invoke user callback function
515  context->callbacks.pubRecCallback(context, packetId);
516  }
517 
518  //A PUBREL packet is the response to a PUBREC packet. It is the third
519  //packet of the QoS 2 protocol exchange
520  error = mqttClientFormatPubRel(context, packetId);
521 
522  //Check status code
523  if(!error)
524  {
525  //Debug message
526  TRACE_INFO("MQTT: Sending PUBREL packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
527  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
528 
529  //Save the type of the MQTT packet to be sent
530  context->packetType = MQTT_PACKET_TYPE_PUBREL;
531  //Point to the beginning of the packet
532  context->packetPos = 0;
533 
534  //Send PUBREL packet
536  }
537 
538  //Return status code
539  return error;
540 }
541 
542 
543 /**
544  * @brief Process incoming PUBREL packet
545  * @param[in] context Pointer to the MQTT client context
546  * @param[in] dup DUP flag from the fixed header
547  * @param[in] qos QoS field from the fixed header
548  * @param[in] retain RETAIN flag from the fixed header
549  * @param[in] remainingLen Length of the variable header and the payload
550  **/
551 
553  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
554 {
555  error_t error;
556  uint16_t packetId;
557 
558  //If invalid flags are received, the receiver must close the network connection
559  if(dup != FALSE && qos != MQTT_QOS_LEVEL_1 && retain != FALSE)
560  return ERROR_INVALID_PACKET;
561 
562  //The variable header contains the same Packet Identifier as the PUBREC
563  //packet that is being acknowledged
564  error = mqttDeserializeShort(context->packet, context->packetLen,
565  &context->packetPos, &packetId);
566 
567  //Failed to deserialize Packet Identifier field?
568  if(error)
569  return error;
570 
571  //Any registered callback?
572  if(context->callbacks.pubRelCallback != NULL)
573  {
574  //Invoke user callback function
575  context->callbacks.pubRelCallback(context, packetId);
576  }
577 
578  //A PUBCOMP packet is the response to a PUBREL packet. It is the fourth and
579  //final packet of the QoS 2 protocol exchange
580  error = mqttClientFormatPubComp(context, packetId);
581 
582  //Check status code
583  if(!error)
584  {
585  //Debug message
586  TRACE_INFO("MQTT: Sending PUBCOMP packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
587  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
588 
589  //Point to the beginning of the packet
590  context->packetPos = 0;
591 
592  //Send PUBCOMP packet
594  }
595 
596  //Return status code
597  return error;
598 }
599 
600 
601 /**
602  * @brief Process incoming PUBCOMP packet
603  * @param[in] context Pointer to the MQTT client context
604  * @param[in] dup DUP flag from the fixed header
605  * @param[in] qos QoS field from the fixed header
606  * @param[in] retain RETAIN flag from the fixed header
607  * @param[in] remainingLen Length of the variable header and the payload
608  **/
609 
611  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
612 {
613  error_t error;
614  uint16_t packetId;
615 
616  //If invalid flags are received, the receiver must close the network connection
617  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
618  return ERROR_INVALID_PACKET;
619 
620  //The variable header contains the same Packet Identifier as the PUBREL
621  //packet that is being acknowledged
622  error = mqttDeserializeShort(context->packet, context->packetLen,
623  &context->packetPos, &packetId);
624 
625  //Failed to deserialize Packet Identifier field?
626  if(error)
627  return error;
628 
629  //Any registered callback?
630  if(context->callbacks.pubCompCallback != NULL)
631  {
632  //Invoke user callback function
633  context->callbacks.pubCompCallback(context, packetId);
634  }
635 
636  //Notify the application that a PUBCOMP packet has been received
637  if(context->packetType == MQTT_PACKET_TYPE_PUBREL && context->packetId == packetId)
638  {
640  }
641 
642  //Successful processing
643  return NO_ERROR;
644 }
645 
646 
647 /**
648  * @brief Process incoming SUBACK packet
649  * @param[in] context Pointer to the MQTT client context
650  * @param[in] dup DUP flag from the fixed header
651  * @param[in] qos QoS field from the fixed header
652  * @param[in] retain RETAIN flag from the fixed header
653  * @param[in] remainingLen Length of the variable header and the payload
654  **/
655 
657  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
658 {
659  error_t error;
660  uint16_t packetId;
661 
662  //If invalid flags are received, the receiver must close the network connection
663  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
664  return ERROR_INVALID_PACKET;
665 
666  //The variable header contains the Packet Identifier from the SUBSCRIBE
667  //packet that is being acknowledged
668  error = mqttDeserializeShort(context->packet, context->packetLen,
669  &context->packetPos, &packetId);
670 
671  //Failed to deserialize Packet Identifier field?
672  if(error)
673  return error;
674 
675  //Any registered callback?
676  if(context->callbacks.subAckCallback != NULL)
677  {
678  //Invoke user callback function
679  context->callbacks.subAckCallback(context, packetId);
680  }
681 
682  //Notify the application that a SUBACK packet has been received
683  if(context->packetType == MQTT_PACKET_TYPE_SUBSCRIBE && context->packetId == packetId)
684  {
686  }
687 
688  //Successful processing
689  return NO_ERROR;
690 }
691 
692 
693 /**
694  * @brief Process incoming UNSUBACK packet
695  * @param[in] context Pointer to the MQTT client context
696  * @param[in] dup DUP flag from the fixed header
697  * @param[in] qos QoS field from the fixed header
698  * @param[in] retain RETAIN flag from the fixed header
699  * @param[in] remainingLen Length of the variable header and the payload
700  **/
701 
703  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
704 {
705  error_t error;
706  uint16_t packetId;
707 
708  //If invalid flags are received, the receiver must close the network connection
709  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
710  return ERROR_INVALID_PACKET;
711 
712  //The variable header contains the Packet Identifier from the UNSUBSCRIBE
713  //packet that is being acknowledged
714  error = mqttDeserializeShort(context->packet, context->packetLen,
715  &context->packetPos, &packetId);
716 
717  //Failed to deserialize Packet Identifier field?
718  if(error)
719  return error;
720 
721  //Any registered callback?
722  if(context->callbacks.unsubAckCallback != NULL)
723  {
724  //Invoke user callback function
725  context->callbacks.unsubAckCallback(context, packetId);
726  }
727 
728  //Notify the application that an UNSUBACK packet has been received
729  if(context->packetType == MQTT_PACKET_TYPE_UNSUBSCRIBE && context->packetId == packetId)
730  {
732  }
733 
734  //Successful processing
735  return NO_ERROR;
736 }
737 
738 
739 /**
740  * @brief Process incoming PINGRESP packet
741  * @param[in] context Pointer to the MQTT client context
742  * @param[in] dup DUP flag from the fixed header
743  * @param[in] qos QoS field from the fixed header
744  * @param[in] retain RETAIN flag from the fixed header
745  * @param[in] remainingLen Length of the variable header and the payload
746  **/
747 
749  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
750 {
751  //If invalid flags are received, the receiver must close the network connection
752  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
753  return ERROR_INVALID_PACKET;
754 
755  //Any registered callback?
756  if(context->callbacks.pingRespCallback != NULL)
757  {
758  //Invoke user callback function
759  context->callbacks.pingRespCallback(context);
760  }
761 
762  //Notify the application that an PINGRESP packet has been received
763  if(context->packetType == MQTT_PACKET_TYPE_PINGREQ)
764  {
766  }
767 
768  //Successful processing
769  return NO_ERROR;
770 }
771 
772 
773 /**
774  * @brief Format CONNECT packet
775  * @param[in] context Pointer to the MQTT client context
776  * @param[in] cleanSession If this flag is set, then the client and server
777  * must discard any previous session and start a new one
778  * @return Error code
779  **/
780 
782  bool_t cleanSession)
783 {
784  error_t error;
785  size_t n;
786  uint8_t connectFlags;
787  MqttClientWillMessage *willMessage;
788 
789  //Make room for the fixed header
791 
792  //Check protocol version
793  if(context->settings.version == MQTT_VERSION_3_1)
794  {
795  //The Protocol Name is a UTF-8 encoded string that represents the
796  //protocol name "MQIsdp"
797  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
799  }
800  else if(context->settings.version == MQTT_VERSION_3_1_1)
801  {
802  //The Protocol Name is a UTF-8 encoded string that represents the
803  //protocol name "MQTT"
804  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
806  }
807  else
808  {
809  //Invalid protocol level
810  error = ERROR_INVALID_VERSION;
811  }
812 
813  //Any error to report?
814  if(error)
815  return error;
816 
817  //The Protocol Level represents the revision level of the protocol
818  //used by the client
819  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
820  &n, context->settings.version);
821 
822  //Failed to serialize data?
823  if(error)
824  return error;
825 
826  //The Connect Flags byte contains a number of parameters specifying
827  //the behavior of the MQTT connection
828  connectFlags = 0;
829 
830  //If CleanSession is set to 1, the client and server must discard any
831  //previous session and start a new one
832  if(cleanSession)
833  connectFlags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
834 
835  //If the client supplies a zero-byte Client Identifier, the client must
836  //also set CleanSession to 1
837  if(context->settings.clientId[0] == '\0')
838  connectFlags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
839 
840  //Point to the Will message
841  willMessage = &context->settings.willMessage;
842 
843  //Check whether a valid Will message has been specified
844  if(willMessage->topic[0] != '\0')
845  {
846  //Set the Will flag
847  connectFlags |= MQTT_CONNECT_FLAG_WILL;
848 
849  //Check the Will QoS level
850  if(willMessage->qos == MQTT_QOS_LEVEL_1)
851  {
852  connectFlags |= MQTT_CONNECT_FLAG_WILL_QOS_1;
853  }
854  else if(willMessage->qos == MQTT_QOS_LEVEL_2)
855  {
856  connectFlags |= MQTT_CONNECT_FLAG_WILL_QOS_2;
857  }
858 
859  //The Will Retain flag specifies if the Will Message is to be
860  //retained when it is published
861  if(willMessage->retain)
862  connectFlags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
863  }
864 
865  //Check whether a valid user name has been specified
866  if(context->settings.username[0] != '\0')
867  connectFlags |= MQTT_CONNECT_FLAG_USERNAME;
868 
869  //Check whether a valid password has been specified
870  if(context->settings.password[0] != '\0')
871  connectFlags |= MQTT_CONNECT_FLAG_PASSWORD;
872 
873  //Write the Connect Flags to the output buffer
874  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
875  &n, connectFlags);
876 
877  //Failed to serialize data?
878  if(error)
879  return error;
880 
881  //The Keep Alive is a time interval measured in seconds. It is the maximum
882  //time interval that is permitted to elapse between the point at which the
883  //client finishes transmitting one control packet and the point it starts
884  //sending the next
885  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
886  &n, context->settings.keepAlive);
887 
888  //Failed to serialize data?
889  if(error)
890  return error;
891 
892  //The Client Identifier identifies the client to the server. The Client
893  //Identifier must be present and must be the first field in the CONNECT
894  //packet payload
895  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
896  &n, context->settings.clientId, osStrlen(context->settings.clientId));
897 
898  //Failed to serialize data?
899  if(error)
900  return error;
901 
902  //If the Will Flag is set to 1, the Will Topic is the next field in
903  //the payload
904  if(willMessage->topic[0] != '\0')
905  {
906  //Write the Will Topic to the output buffer
907  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
908  &n, willMessage->topic, osStrlen(willMessage->topic));
909 
910  //Failed to serialize data?
911  if(error)
912  return error;
913 
914  //Write the Will message to the output buffer
915  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
916  &n, willMessage->payload, willMessage->length);
917 
918  //Failed to serialize data?
919  if(error)
920  return error;
921  }
922 
923  //If the User Name Flag is set to 1, this is the next field in the payload
924  if(context->settings.username[0] != '\0')
925  {
926  //Write the User Name to the output buffer
927  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
928  &n, context->settings.username, osStrlen(context->settings.username));
929 
930  //Failed to serialize data?
931  if(error)
932  return error;
933  }
934 
935  //If the Password Flag is set to 1, this is the next field in the payload
936  if(context->settings.password[0] != '\0')
937  {
938  //Write the Password to the output buffer
939  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
940  &n, context->settings.password, osStrlen(context->settings.password));
941 
942  //Failed to serialize data?
943  if(error)
944  return error;
945  }
946 
947  //Calculate the length of the variable header and the payload
948  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
949 
950  //The fixed header will be encoded in reverse order
952 
953  //Prepend the variable header and the payload with the fixed header
954  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_CONNECT,
955  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
956 
957  //Failed to serialize fixed header?
958  if(error)
959  return error;
960 
961  //Point to the first byte of the MQTT packet
962  context->packet = context->buffer + n;
963  //Calculate the length of the MQTT packet
964  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
965 
966  //Successful processing
967  return NO_ERROR;
968 }
969 
970 
971 /**
972  * @brief Format PUBLISH packet
973  * @param[in] context Pointer to the MQTT client context
974  * @param[in] publishInfo PUBLISH packet parameters
975  * @return Error code
976  **/
977 
979  MqttPublishInfo *publishInfo)
980 {
981  error_t error;
982  size_t n;
983 
984  //Make room for the fixed header
986 
987  //The Topic Name must be present as the first field in the PUBLISH
988  //packet variable header
989  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
990  &n, publishInfo->topicName, osStrlen(publishInfo->topicName));
991 
992  //Failed to serialize Topic Name?
993  if(error)
994  return error;
995 
996  //Check QoS level
997  if(publishInfo->qos != MQTT_QOS_LEVEL_0)
998  {
999  //Each time a client sends a new PUBLISH packet it must assign it
1000  //a currently unused packet identifier
1001  if(context->packetId < UINT16_MAX)
1002  {
1003  context->packetId++;
1004  }
1005  else
1006  {
1007  context->packetId = 1;
1008  }
1009 
1010  //The Packet Identifier field is only present in PUBLISH packets
1011  //where the QoS level is 1 or 2
1012  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1013  &n, context->packetId);
1014 
1015  //Failed to serialize Packet Identifier field?
1016  if(error)
1017  return error;
1018  }
1019 
1020  //Check if the payload fits in the buffer
1021  if(publishInfo->fragLen == 0 &&
1022  publishInfo->payloadLen <= (MQTT_CLIENT_BUFFER_SIZE - n))
1023  {
1024  //The payload contains the Application Message that is being published
1025  error = mqttSerializeData(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1026  &n, publishInfo->payload, publishInfo->payloadLen);
1027 
1028  //Failed to serialize Application Message?
1029  if(error)
1030  return error;
1031 
1032  //Calculate the length of the variable header and the payload
1033  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1034 
1035  //The fixed header will be encoded in reverse order
1037 
1038  //Prepend the variable header and the payload with the fixed header
1039  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBLISH,
1040  publishInfo->dup, publishInfo->qos, publishInfo->retain,
1041  context->packetLen);
1042 
1043  //Failed to serialize fixed header?
1044  if(error)
1045  return error;
1046 
1047  //The buffer contains both the header and the payload
1048  context->payloadPos = publishInfo->payloadLen;
1049  context->fragPos = 0;
1050  }
1051  else
1052  {
1053  //Calculate the length of the variable header
1054  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1055 
1056  //The fixed header will be encoded in reverse order
1058 
1059  //Prepend the variable header and the payload with the fixed header
1060  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBLISH,
1061  publishInfo->dup, publishInfo->qos, publishInfo->retain,
1062  context->packetLen + publishInfo->payloadLen);
1063 
1064  //Failed to serialize fixed header?
1065  if(error)
1066  return error;
1067 
1068  //The payload will be sent separately
1069  context->payloadPos = 0;
1070  context->fragPos = 0;
1071  }
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 PUBACK 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_PUBACK,
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 PUBREC 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 Packet Identifier from the PUBLISH
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_PUBREC,
1163  FALSE, MQTT_QOS_LEVEL_0, 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 PUBREL 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 PUBREC
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_PUBREL,
1211  FALSE, MQTT_QOS_LEVEL_1, 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 PUBCOMP packet
1229  * @param[in] context Pointer to the MQTT client context
1230  * @param[in] packetId Packet identifier
1231  * @return Error code
1232  **/
1233 
1235 {
1236  error_t error;
1237  size_t n;
1238 
1239  //Make room for the fixed header
1241 
1242  //The variable header contains the same Packet Identifier as the PUBREL
1243  //packet that is being acknowledged
1244  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1245  &n, packetId);
1246 
1247  //Failed to serialize Packet Identifier field?
1248  if(error)
1249  return error;
1250 
1251  //Calculate the length of the variable header and the payload
1252  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1253 
1254  //The fixed header will be encoded in reverse order
1256 
1257  //Prepend the variable header and the payload with the fixed header
1258  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBCOMP,
1259  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1260 
1261  //Failed to serialize fixed header?
1262  if(error)
1263  return error;
1264 
1265  //Point to the first byte of the MQTT packet
1266  context->packet = context->buffer + n;
1267  //Calculate the length of the MQTT packet
1268  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1269 
1270  //Successful processing
1271  return NO_ERROR;
1272 }
1273 
1274 
1275 /**
1276  * @brief Format SUBSCRIBE packet
1277  * @param[in] context Pointer to the MQTT client context
1278  * @param[in] topic Topic filter
1279  * @param[in] qos Maximum QoS level at which the server can send application
1280  * messages to the client
1281  * @return Error code
1282  **/
1283 
1285  const char_t *topic, MqttQosLevel qos)
1286 {
1287  error_t error;
1288  size_t n;
1289 
1290  //Make room for the fixed header
1292 
1293  //Each time a client sends a new SUBSCRIBE packet it must assign it
1294  //a currently unused packet identifier
1295  if(context->packetId < UINT16_MAX)
1296  {
1297  context->packetId++;
1298  }
1299  else
1300  {
1301  context->packetId = 1;
1302  }
1303 
1304  //Write Packet Identifier to the output buffer
1305  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1306  &n, context->packetId);
1307 
1308  //Failed to serialize data?
1309  if(error)
1310  return error;
1311 
1312  //Write the Topic Filter to the output buffer
1313  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1314  &n, topic, osStrlen(topic));
1315 
1316  //Failed to serialize data?
1317  if(error)
1318  return error;
1319 
1320  //Write the Requested QoS to the output buffer
1321  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1322  &n, qos);
1323 
1324  //Failed to serialize data?
1325  if(error)
1326  return error;
1327 
1328  //Calculate the length of the variable header and the payload
1329  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1330 
1331  //The fixed header will be encoded in reverse order
1333 
1334  //Prepend the variable header and the payload with the fixed header
1335  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_SUBSCRIBE,
1336  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1337 
1338  //Failed to serialize fixed header?
1339  if(error)
1340  return error;
1341 
1342  //Point to the first byte of the MQTT packet
1343  context->packet = context->buffer + n;
1344  //Calculate the length of the MQTT packet
1345  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1346 
1347  //Successful processing
1348  return NO_ERROR;
1349 }
1350 
1351 
1352 /**
1353  * @brief Format UNSUBSCRIBE packet
1354  * @param[in] context Pointer to the MQTT client context
1355  * @param[in] topic Topic filter
1356  * @return Error code
1357  **/
1358 
1360  const char_t *topic)
1361 {
1362  error_t error;
1363  size_t n;
1364 
1365  //Make room for the fixed header
1367 
1368  //Each time a client sends a new UNSUBSCRIBE packet it must assign it
1369  //a currently unused packet identifier
1370  if(context->packetId < UINT16_MAX)
1371  {
1372  context->packetId++;
1373  }
1374  else
1375  {
1376  context->packetId = 1;
1377  }
1378 
1379  //Write Packet Identifier to the output buffer
1380  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1381  &n, context->packetId);
1382 
1383  //Failed to serialize data?
1384  if(error)
1385  return error;
1386 
1387  //Write the Topic Filter to the output buffer
1388  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1389  &n, topic, osStrlen(topic));
1390 
1391  //Failed to serialize data?
1392  if(error)
1393  return error;
1394 
1395  //Calculate the length of the variable header and the payload
1396  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1397 
1398  //The fixed header will be encoded in reverse order
1400 
1401  //Prepend the variable header and the payload with the fixed header
1402  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_UNSUBSCRIBE,
1403  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1404 
1405  //Failed to serialize fixed header?
1406  if(error)
1407  return error;
1408 
1409  //Point to the first byte of the MQTT packet
1410  context->packet = context->buffer + n;
1411  //Calculate the length of the MQTT packet
1412  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1413 
1414  //Successful processing
1415  return NO_ERROR;
1416 }
1417 
1418 
1419 /**
1420  * @brief Format PINGREQ packet
1421  * @param[in] context Pointer to the MQTT client context
1422  * @return Error code
1423  **/
1424 
1426 {
1427  error_t error;
1428  size_t n;
1429 
1430  //The fixed header will be encoded in reverse order
1432 
1433  //The PINGREQ packet does not contain any variable header nor payload
1434  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PINGREQ,
1436 
1437  //Failed to serialize fixed header?
1438  if(error)
1439  return error;
1440 
1441  //Point to the first byte of the MQTT packet
1442  context->packet = context->buffer + n;
1443  //Calculate the length of the MQTT packet
1444  context->packetLen = MQTT_MAX_HEADER_SIZE - n;
1445 
1446  //Successful processing
1447  return NO_ERROR;
1448 }
1449 
1450 
1451 /**
1452  * @brief Format DISCONNECT packet
1453  * @param[in] context Pointer to the MQTT client context
1454  * @return Error code
1455  **/
1456 
1458 {
1459  error_t error;
1460  size_t n;
1461 
1462  //The fixed header will be encoded in reverse order
1464 
1465  //The DISCONNECT packet does not contain any variable header nor payload
1466  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_DISCONNECT,
1468 
1469  //Failed to serialize fixed header?
1470  if(error)
1471  return error;
1472 
1473  //Point to the first byte of the MQTT packet
1474  context->packet = context->buffer + n;
1475  //Calculate the length of the MQTT packet
1476  context->packetLen = MQTT_MAX_HEADER_SIZE - n;
1477 
1478  //Successful processing
1479  return NO_ERROR;
1480 }
1481 
1482 #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.
const void * payload
Definition: mqtt_client.h:359
int bool_t
Definition: compiler_port.h:63
@ 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.
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:171
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:267
@ 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:170
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
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:270
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:268
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
PUBLISH packet parameters.
Definition: mqtt_client.h:354
#define MqttClientContext
Definition: mqtt_client.h:147
error_t mqttClientFormatPublish(MqttClientContext *context, MqttPublishInfo *publishInfo)
Format PUBLISH packet.
MqttQosLevel qos
QoS level to be used when publishing the Will message.
Definition: mqtt_client.h:269
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
MqttQosLevel qos
Definition: mqtt_client.h:356
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:266
@ NO_ERROR
Success.
Definition: error.h:44
const char_t * topicName
Definition: mqtt_client.h:358
MqttPacketType
MQTT control packet type.
Definition: mqtt_common.h:99
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:153
#define MQTT_PROTOCOL_NAME_3_1_1
Definition: mqtt_common.h:45
@ MQTT_CONNECT_FLAG_WILL
Definition: mqtt_common.h:125
MQTT client.