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.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL MQTT_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "mqtt/mqtt_client.h"
39 #include "mqtt/mqtt_client_misc.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (MQTT_CLIENT_SUPPORT == ENABLED)
44 
45 //MQTT control packets
46 const char_t *const mqttPacketLabel[16] =
47 {
48  "Reserved", //0
49  "CONNECT", //1
50  "CONNACK", //2
51  "PUBLISH", //3
52  "PUBACK", //4
53  "PUBREC", //5
54  "PUBREL", //6
55  "PUBCOMP", //7
56  "SUBSCRIBE", //8
57  "SUBACK", //9
58  "UNSUBSCRIBE", //10
59  "UNSUBACK", //11
60  "PINGREQ", //12
61  "PINGRESP", //13
62  "DISCONNECT", //14
63  "Reserved" //15
64 };
65 
66 
67 /**
68  * @brief Receive MQTT packet
69  * @param[in] context Pointer to the MQTT client context
70  * @return Error code
71  **/
72 
74 {
75  error_t error;
76  size_t n;
77  uint8_t value;
78 
79  //Initialize status code
80  error = NO_ERROR;
81 
82  //Receive incoming packet
83  while(1)
84  {
85  //Packet header is being received?
86  if(context->packetLen == 0)
87  {
88  //Read a single byte
89  error = mqttClientReceiveData(context, &value, sizeof(uint8_t), &n, 0);
90 
91  //Any data received?
92  if(!error)
93  {
94  //Save the current byte
95  context->packet[context->packetPos] = value;
96 
97  //The Remaining Length is encoded using a variable length encoding scheme
98  if(context->packetPos > 0)
99  {
100  //The most significant bit is used to indicate that there are
101  //following bytes in the representation
102  if(value & 0x80)
103  {
104  //Applications can send control packets of size up to 256 MB
105  if(context->packetPos < 4)
106  {
107  //The least significant seven bits of each byte encode the data
108  context->remainingLen |= (value & 0x7F) << (7 * (context->packetPos - 1));
109  }
110  else
111  {
112  //Report an error
113  error = ERROR_INVALID_SYNTAX;
114  }
115  }
116  else
117  {
118  //The least significant seven bits of each byte encode the data
119  context->remainingLen |= value << (7 * (context->packetPos - 1));
120  //Calculate the length of the control packet
121  context->packetLen = context->packetPos + 1 + context->remainingLen;
122 
123  //Sanity check
124  if(context->packetLen > MQTT_CLIENT_BUFFER_SIZE)
125  error = ERROR_INVALID_LENGTH;
126  }
127  }
128 
129  //Advance data pointer
130  context->packetPos++;
131  }
132  }
133  //Variable header or payload is being received?
134  else
135  {
136  //Any remaining data?
137  if(context->packetPos < context->packetLen)
138  {
139  //Read more data
140  error = mqttClientReceiveData(context, context->packet + context->packetPos,
141  context->packetLen - context->packetPos, &n, 0);
142 
143  //Advance data pointer
144  context->packetPos += n;
145  }
146  else
147  {
148  //The packet has been successfully received
149  break;
150  }
151  }
152 
153  //Any error to report?
154  if(error)
155  break;
156  }
157 
158  //Return status code
159  return error;
160 }
161 
162 
163 /**
164  * @brief Process incoming MQTT packet
165  * @param[in] context Pointer to the MQTT client context
166  * @return Error code
167  **/
168 
170 {
171  error_t error;
172  bool_t dup;
173  bool_t retain;
174  size_t remainingLen;
177 
178  //Point to the first byte of the packet
179  context->packetPos = 0;
180 
181  //Read the fixed header from the input buffer
182  error = mqttDeserializeHeader(context->packet, context->packetLen,
183  &context->packetPos, &type, &dup, &qos, &retain, &remainingLen);
184 
185  //Failed to deserialize fixed header?
186  if(error)
187  return error;
188 
189  //Debug message
190  TRACE_INFO("MQTT: %s packet received (%" PRIuSIZE " bytes)...\r\n",
191  mqttPacketLabel[type], context->packetLen);
192 
193  //Dump the contents of the packet
194  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
195 
196  //Check MQTT control packet type
197  switch(type)
198  {
199  //CONNACK packet received?
201  //Process incoming CONNACK packet
202  error = mqttClientProcessConnAck(context, dup, qos, retain, remainingLen);
203  break;
204 
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)
315 
316  //Successful processing
317  return NO_ERROR;
318 }
319 
320 
321 /**
322  * @brief Process incoming PUBLISH packet
323  * @param[in] context Pointer to the MQTT client context
324  * @param[in] dup DUP flag from the fixed header
325  * @param[in] qos QoS field from the fixed header
326  * @param[in] retain RETAIN flag from the fixed header
327  * @param[in] remainingLen Length of the variable header and the payload
328  **/
329 
331  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
332 {
333  error_t error;
334  uint16_t packetId;
335  char_t *topic;
336  size_t topicLen;
337  uint8_t *message;
338  size_t messageLen;
339 
340  //The Topic Name must be present as the first field in the PUBLISH
341  //packet variable header
342  error = mqttDeserializeString(context->packet, context->packetLen,
343  &context->packetPos, &topic, &topicLen);
344 
345  //Failed to deserialize Topic Name?
346  if(error)
347  return error;
348 
349  //Check QoS level
350  if(qos != MQTT_QOS_LEVEL_0)
351  {
352  //The Packet Identifier field is only present in PUBLISH packets
353  //where the QoS level is 1 or 2
354  error = mqttDeserializeShort(context->packet, context->packetLen,
355  &context->packetPos, &packetId);
356 
357  //Failed to deserialize Packet Identifier field?
358  if(error)
359  return error;
360  }
361  else
362  {
363  //No packet identifier
364  packetId = 0;
365  }
366 
367  //The payload contains the Application Message that is being published
368  message = context->packet + context->packetPos;
369 
370  //The length of the payload can be calculated by subtracting the length of the
371  //variable header from the Remaining Length field that is in the fixed header
372  messageLen = context->packetLen - context->packetPos;
373 
374  //Make room for the NULL character at the end of the Topic Name
375  osMemmove(topic - 1, topic, topicLen);
376  //Properly terminate the string with a NULL character
377  topic[topicLen - 1] = '\0';
378  //Point to the first character of the Topic Name
379  topic--;
380 
381  //Any registered callback?
382  if(context->callbacks.publishCallback != NULL)
383  {
384  //Invoke user callback function
385  context->callbacks.publishCallback(context, topic,
386  message, messageLen, dup, qos, retain, packetId);
387  }
388 
389  //Check QoS level
390  if(qos == MQTT_QOS_LEVEL_1)
391  {
392  //A PUBACK packet is the response to a PUBLISH packet with QoS level 1
393  error = mqttClientFormatPubAck(context, packetId);
394 
395  //Check status code
396  if(!error)
397  {
398  //Debug message
399  TRACE_INFO("MQTT: Sending PUBACK packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
400  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
401 
402  //Point to the beginning of the packet
403  context->packetPos = 0;
404 
405  //Send PUBACK packet
407  }
408  }
409  else if(qos == MQTT_QOS_LEVEL_2)
410  {
411  //A PUBREC packet is the response to a PUBLISH packet with QoS 2. It is
412  //the second packet of the QoS 2 protocol exchange
413  error = mqttClientFormatPubRec(context, packetId);
414 
415  //Check status code
416  if(!error)
417  {
418  //Debug message
419  TRACE_INFO("MQTT: Sending PUBREC packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
420  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
421 
422  //Point to the beginning of the packet
423  context->packetPos = 0;
424 
425  //Send PUBREC packet
427  }
428  }
429 
430  //Return status code
431  return error;
432 }
433 
434 
435 /**
436  * @brief Process incoming PUBACK packet
437  * @param[in] context Pointer to the MQTT client context
438  * @param[in] dup DUP flag from the fixed header
439  * @param[in] qos QoS field from the fixed header
440  * @param[in] retain RETAIN flag from the fixed header
441  * @param[in] remainingLen Length of the variable header and the payload
442  **/
443 
445  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
446 {
447  error_t error;
448  uint16_t packetId;
449 
450  //If invalid flags are received, the receiver must close the network connection
451  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
452  return ERROR_INVALID_PACKET;
453 
454  //The variable header contains the Packet Identifier from the PUBLISH
455  //packet that is being acknowledged
456  error = mqttDeserializeShort(context->packet, context->packetLen,
457  &context->packetPos, &packetId);
458 
459  //Failed to deserialize Packet Identifier field?
460  if(error)
461  return error;
462 
463  //Any registered callback?
464  if(context->callbacks.pubAckCallback != NULL)
465  {
466  //Invoke user callback function
467  context->callbacks.pubAckCallback(context, packetId);
468  }
469 
470  //Notify the application that a PUBACK packet has been received
471  if(context->packetType == MQTT_PACKET_TYPE_PUBLISH && context->packetId == packetId)
473 
474  //Return status code
475  return error;
476 }
477 
478 
479 /**
480  * @brief Process incoming PUBREC packet
481  * @param[in] context Pointer to the MQTT client context
482  * @param[in] dup DUP flag from the fixed header
483  * @param[in] qos QoS field from the fixed header
484  * @param[in] retain RETAIN flag from the fixed header
485  * @param[in] remainingLen Length of the variable header and the payload
486  **/
487 
489  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
490 {
491  error_t error;
492  uint16_t packetId;
493 
494  //If invalid flags are received, the receiver must close the network connection
495  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
496  return ERROR_INVALID_PACKET;
497 
498  //The variable header contains the Packet Identifier from the PUBLISH
499  //packet that is being acknowledged
500  error = mqttDeserializeShort(context->packet, context->packetLen,
501  &context->packetPos, &packetId);
502 
503  //Failed to deserialize Packet Identifier field?
504  if(error)
505  return error;
506 
507  //Any registered callback?
508  if(context->callbacks.pubRecCallback != NULL)
509  {
510  //Invoke user callback function
511  context->callbacks.pubRecCallback(context, packetId);
512  }
513 
514  //A PUBREL packet is the response to a PUBREC packet. It is the third
515  //packet of the QoS 2 protocol exchange
516  error = mqttClientFormatPubRel(context, packetId);
517 
518  //Check status code
519  if(!error)
520  {
521  //Debug message
522  TRACE_INFO("MQTT: Sending PUBREL packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
523  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
524 
525  //Point to the beginning of the packet
526  context->packetPos = 0;
527 
528  //Send PUBREL packet
530  }
531 
532  //Return status code
533  return error;
534 }
535 
536 
537 /**
538  * @brief Process incoming PUBREL packet
539  * @param[in] context Pointer to the MQTT client context
540  * @param[in] dup DUP flag from the fixed header
541  * @param[in] qos QoS field from the fixed header
542  * @param[in] retain RETAIN flag from the fixed header
543  * @param[in] remainingLen Length of the variable header and the payload
544  **/
545 
547  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
548 {
549  error_t error;
550  uint16_t packetId;
551 
552  //If invalid flags are received, the receiver must close the network connection
553  if(dup != FALSE && qos != MQTT_QOS_LEVEL_1 && retain != FALSE)
554  return ERROR_INVALID_PACKET;
555 
556  //The variable header contains the same Packet Identifier as the PUBREC
557  //packet that is being acknowledged
558  error = mqttDeserializeShort(context->packet, context->packetLen,
559  &context->packetPos, &packetId);
560 
561  //Failed to deserialize Packet Identifier field?
562  if(error)
563  return error;
564 
565  //Any registered callback?
566  if(context->callbacks.pubRelCallback != NULL)
567  {
568  //Invoke user callback function
569  context->callbacks.pubRelCallback(context, packetId);
570  }
571 
572  //A PUBCOMP packet is the response to a PUBREL packet. It is the fourth and
573  //final packet of the QoS 2 protocol exchange
574  error = mqttClientFormatPubComp(context, packetId);
575 
576  //Check status code
577  if(!error)
578  {
579  //Debug message
580  TRACE_INFO("MQTT: Sending PUBCOMP packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen);
581  TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen);
582 
583  //Point to the beginning of the packet
584  context->packetPos = 0;
585 
586  //Send PUBCOMP packet
588  }
589 
590  //Return status code
591  return error;
592 }
593 
594 
595 /**
596  * @brief Process incoming PUBCOMP packet
597  * @param[in] context Pointer to the MQTT client context
598  * @param[in] dup DUP flag from the fixed header
599  * @param[in] qos QoS field from the fixed header
600  * @param[in] retain RETAIN flag from the fixed header
601  * @param[in] remainingLen Length of the variable header and the payload
602  **/
603 
605  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
606 {
607  error_t error;
608  uint16_t packetId;
609 
610  //If invalid flags are received, the receiver must close the network connection
611  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
612  return ERROR_INVALID_PACKET;
613 
614  //The variable header contains the same Packet Identifier as the PUBREL
615  //packet that is being acknowledged
616  error = mqttDeserializeShort(context->packet, context->packetLen,
617  &context->packetPos, &packetId);
618 
619  //Failed to deserialize Packet Identifier field?
620  if(error)
621  return error;
622 
623  //Any registered callback?
624  if(context->callbacks.pubCompCallback != NULL)
625  {
626  //Invoke user callback function
627  context->callbacks.pubCompCallback(context, packetId);
628  }
629 
630  //Notify the application that a PUBCOMP packet has been received
631  if(context->packetType == MQTT_PACKET_TYPE_PUBLISH && context->packetId == packetId)
633 
634  //Successful processing
635  return NO_ERROR;
636 }
637 
638 
639 /**
640  * @brief Process incoming SUBACK packet
641  * @param[in] context Pointer to the MQTT client context
642  * @param[in] dup DUP flag from the fixed header
643  * @param[in] qos QoS field from the fixed header
644  * @param[in] retain RETAIN flag from the fixed header
645  * @param[in] remainingLen Length of the variable header and the payload
646  **/
647 
649  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
650 {
651  error_t error;
652  uint16_t packetId;
653 
654  //If invalid flags are received, the receiver must close the network connection
655  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
656  return ERROR_INVALID_PACKET;
657 
658  //The variable header contains the Packet Identifier from the SUBSCRIBE
659  //packet that is being acknowledged
660  error = mqttDeserializeShort(context->packet, context->packetLen,
661  &context->packetPos, &packetId);
662 
663  //Failed to deserialize Packet Identifier field?
664  if(error)
665  return error;
666 
667  //Any registered callback?
668  if(context->callbacks.subAckCallback != NULL)
669  {
670  //Invoke user callback function
671  context->callbacks.subAckCallback(context, packetId);
672  }
673 
674  //Notify the application that a SUBACK packet has been received
675  if(context->packetType == MQTT_PACKET_TYPE_SUBSCRIBE && context->packetId == packetId)
677 
678  //Successful processing
679  return NO_ERROR;
680 }
681 
682 
683 /**
684  * @brief Process incoming UNSUBACK packet
685  * @param[in] context Pointer to the MQTT client context
686  * @param[in] dup DUP flag from the fixed header
687  * @param[in] qos QoS field from the fixed header
688  * @param[in] retain RETAIN flag from the fixed header
689  * @param[in] remainingLen Length of the variable header and the payload
690  **/
691 
693  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
694 {
695  error_t error;
696  uint16_t packetId;
697 
698  //If invalid flags are received, the receiver must close the network connection
699  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
700  return ERROR_INVALID_PACKET;
701 
702  //The variable header contains the Packet Identifier from the UNSUBSCRIBE
703  //packet that is being acknowledged
704  error = mqttDeserializeShort(context->packet, context->packetLen,
705  &context->packetPos, &packetId);
706 
707  //Failed to deserialize Packet Identifier field?
708  if(error)
709  return error;
710 
711  //Any registered callback?
712  if(context->callbacks.unsubAckCallback != NULL)
713  {
714  //Invoke user callback function
715  context->callbacks.unsubAckCallback(context, packetId);
716  }
717 
718  //Notify the application that an UNSUBACK packet has been received
719  if(context->packetType == MQTT_PACKET_TYPE_UNSUBSCRIBE && context->packetId == packetId)
721 
722  //Successful processing
723  return NO_ERROR;
724 }
725 
726 
727 /**
728  * @brief Process incoming PINGRESP packet
729  * @param[in] context Pointer to the MQTT client context
730  * @param[in] dup DUP flag from the fixed header
731  * @param[in] qos QoS field from the fixed header
732  * @param[in] retain RETAIN flag from the fixed header
733  * @param[in] remainingLen Length of the variable header and the payload
734  **/
735 
737  bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen)
738 {
739  //If invalid flags are received, the receiver must close the network connection
740  if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE)
741  return ERROR_INVALID_PACKET;
742 
743  //Any registered callback?
744  if(context->callbacks.pingRespCallback != NULL)
745  {
746  //Invoke user callback function
747  context->callbacks.pingRespCallback(context);
748  }
749 
750  //Notify the application that an PINGRESP packet has been received
751  if(context->packetType == MQTT_PACKET_TYPE_PINGREQ)
753 
754  //Successful processing
755  return NO_ERROR;
756 }
757 
758 
759 /**
760  * @brief Format CONNECT packet
761  * @param[in] context Pointer to the MQTT client context
762  * @param[in] cleanSession If this flag is set, then the client and server
763  * must discard any previous session and start a new one
764  * @return Error code
765  **/
766 
768  bool_t cleanSession)
769 {
770  error_t error;
771  size_t n;
772  uint8_t connectFlags;
773  MqttClientWillMessage *willMessage;
774 
775  //Make room for the fixed header
777 
778  //Check protocol version
779  if(context->settings.version == MQTT_VERSION_3_1)
780  {
781  //The Protocol Name is a UTF-8 encoded string that represents the
782  //protocol name "MQIsdp"
783  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
785  }
786  else if(context->settings.version == MQTT_VERSION_3_1_1)
787  {
788  //The Protocol Name is a UTF-8 encoded string that represents the
789  //protocol name "MQTT"
790  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
792  }
793  else
794  {
795  //Invalid protocol level
796  error = ERROR_INVALID_VERSION;
797  }
798 
799  //Any error to report?
800  if(error)
801  return error;
802 
803  //The Protocol Level represents the revision level of the protocol
804  //used by the client
805  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
806  &n, context->settings.version);
807 
808  //Failed to serialize data?
809  if(error)
810  return error;
811 
812  //The Connect Flags byte contains a number of parameters specifying
813  //the behavior of the MQTT connection
814  connectFlags = 0;
815 
816  //If CleanSession is set to 1, the client and server must discard any
817  //previous session and start a new one
818  if(cleanSession)
819  connectFlags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
820 
821  //If the client supplies a zero-byte Client Identifier, the client must
822  //also set CleanSession to 1
823  if(context->settings.clientId[0] == '\0')
824  connectFlags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
825 
826  //Point to the Will message
827  willMessage = &context->settings.willMessage;
828 
829  //Check whether a valid Will message has been specified
830  if(willMessage->topic[0] != '\0')
831  {
832  //Set the Will flag
833  connectFlags |= MQTT_CONNECT_FLAG_WILL;
834 
835  //Check the Will QoS level
836  if(willMessage->qos == MQTT_QOS_LEVEL_1)
837  {
838  connectFlags |= MQTT_CONNECT_FLAG_WILL_QOS_1;
839  }
840  else if(willMessage->qos == MQTT_QOS_LEVEL_2)
841  {
842  connectFlags |= MQTT_CONNECT_FLAG_WILL_QOS_2;
843  }
844 
845  //The Will Retain flag specifies if the Will Message is to be
846  //retained when it is published
847  if(willMessage->retain)
848  connectFlags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
849  }
850 
851  //Check whether a valid user name has been specified
852  if(context->settings.username[0] != '\0')
853  connectFlags |= MQTT_CONNECT_FLAG_USERNAME;
854 
855  //Check whether a valid password has been specified
856  if(context->settings.password[0] != '\0')
857  connectFlags |= MQTT_CONNECT_FLAG_PASSWORD;
858 
859  //Write the Connect Flags to the output buffer
860  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
861  &n, connectFlags);
862 
863  //Failed to serialize data?
864  if(error)
865  return error;
866 
867  //The Keep Alive is a time interval measured in seconds. It is the maximum
868  //time interval that is permitted to elapse between the point at which the
869  //client finishes transmitting one control packet and the point it starts
870  //sending the next
871  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
872  &n, context->settings.keepAlive);
873 
874  //Failed to serialize data?
875  if(error)
876  return error;
877 
878  //The Client Identifier identifies the client to the server. The Client
879  //Identifier must be present and must be the first field in the CONNECT
880  //packet payload
881  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
882  &n, context->settings.clientId, osStrlen(context->settings.clientId));
883 
884  //Failed to serialize data?
885  if(error)
886  return error;
887 
888  //If the Will Flag is set to 1, the Will Topic is the next field in
889  //the payload
890  if(willMessage->topic[0] != '\0')
891  {
892  //Write the Will Topic to the output buffer
893  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
894  &n, willMessage->topic, osStrlen(willMessage->topic));
895 
896  //Failed to serialize data?
897  if(error)
898  return error;
899 
900  //Write the Will message to the output buffer
901  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
902  &n, willMessage->payload, willMessage->length);
903 
904  //Failed to serialize data?
905  if(error)
906  return error;
907  }
908 
909  //If the User Name Flag is set to 1, this is the next field in the payload
910  if(context->settings.username[0] != '\0')
911  {
912  //Write the User Name to the output buffer
913  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
914  &n, context->settings.username, osStrlen(context->settings.username));
915 
916  //Failed to serialize data?
917  if(error)
918  return error;
919  }
920 
921  //If the Password Flag is set to 1, this is the next field in the payload
922  if(context->settings.password[0] != '\0')
923  {
924  //Write the Password to the output buffer
925  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
926  &n, context->settings.password, osStrlen(context->settings.password));
927 
928  //Failed to serialize data?
929  if(error)
930  return error;
931  }
932 
933  //Calculate the length of the variable header and the payload
934  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
935 
936  //The fixed header will be encoded in reverse order
938 
939  //Prepend the variable header and the payload with the fixed header
940  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_CONNECT,
941  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
942 
943  //Failed to serialize fixed header?
944  if(error)
945  return error;
946 
947  //Point to the first byte of the MQTT packet
948  context->packet = context->buffer + n;
949  //Calculate the length of the MQTT packet
950  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
951 
952  //Successful processing
953  return NO_ERROR;
954 }
955 
956 
957 /**
958  * @brief Format PUBLISH packet
959  * @param[in] context Pointer to the MQTT client context
960  * @param[in] publishInfo PUBLISH packet parameters
961  * @return Error code
962  **/
963 
965  MqttPublishInfo *publishInfo)
966 {
967  error_t error;
968  size_t n;
969 
970  //Make room for the fixed header
972 
973  //The Topic Name must be present as the first field in the PUBLISH
974  //packet variable header
975  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
976  &n, publishInfo->topicName, osStrlen(publishInfo->topicName));
977 
978  //Failed to serialize Topic Name?
979  if(error)
980  return error;
981 
982  //Check QoS level
983  if(publishInfo->qos != MQTT_QOS_LEVEL_0)
984  {
985  //Each time a client sends a new PUBLISH packet it must assign it
986  //a currently unused packet identifier
987  if(context->packetId < UINT16_MAX)
988  {
989  context->packetId++;
990  }
991  else
992  {
993  context->packetId = 1;
994  }
995 
996  //The Packet Identifier field is only present in PUBLISH packets
997  //where the QoS level is 1 or 2
998  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
999  &n, context->packetId);
1000 
1001  //Failed to serialize Packet Identifier field?
1002  if(error)
1003  return error;
1004  }
1005 
1006  //Check if the payload fits in the buffer
1007  if(publishInfo->fragLen == 0 &&
1008  publishInfo->payloadLen <= (MQTT_CLIENT_BUFFER_SIZE - n))
1009  {
1010  //The payload contains the Application Message that is being published
1011  error = mqttSerializeData(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1012  &n, publishInfo->payload, publishInfo->payloadLen);
1013 
1014  //Failed to serialize Application Message?
1015  if(error)
1016  return error;
1017 
1018  //Calculate the length of the variable header and the payload
1019  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1020 
1021  //The fixed header will be encoded in reverse order
1023 
1024  //Prepend the variable header and the payload with the fixed header
1025  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBLISH,
1026  publishInfo->dup, publishInfo->qos, publishInfo->retain,
1027  context->packetLen);
1028 
1029  //Failed to serialize fixed header?
1030  if(error)
1031  return error;
1032 
1033  //The buffer contains both the header and the payload
1034  context->payloadPos = publishInfo->payloadLen;
1035  context->fragPos = 0;
1036  }
1037  else
1038  {
1039  //Calculate the length of the variable header
1040  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1041 
1042  //The fixed header will be encoded in reverse order
1044 
1045  //Prepend the variable header and the payload with the fixed header
1046  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBLISH,
1047  publishInfo->dup, publishInfo->qos, publishInfo->retain,
1048  context->packetLen + publishInfo->payloadLen);
1049 
1050  //Failed to serialize fixed header?
1051  if(error)
1052  return error;
1053 
1054  //The payload will be sent separately
1055  context->payloadPos = 0;
1056  context->fragPos = 0;
1057  }
1058 
1059  //Point to the first byte of the MQTT packet
1060  context->packet = context->buffer + n;
1061  //Calculate the length of the MQTT packet
1062  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1063 
1064  //Successful processing
1065  return NO_ERROR;
1066 }
1067 
1068 
1069 /**
1070  * @brief Format PUBACK packet
1071  * @param[in] context Pointer to the MQTT client context
1072  * @param[in] packetId Packet identifier
1073  * @return Error code
1074  **/
1075 
1077 {
1078  error_t error;
1079  size_t n;
1080 
1081  //Make room for the fixed header
1083 
1084  //The variable header contains the Packet Identifier from the PUBLISH
1085  //packet that is being acknowledged
1086  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1087  &n, packetId);
1088 
1089  //Failed to serialize Packet Identifier field?
1090  if(error)
1091  return error;
1092 
1093  //Calculate the length of the variable header and the payload
1094  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1095 
1096  //The fixed header will be encoded in reverse order
1098 
1099  //Prepend the variable header and the payload with the fixed header
1100  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBACK,
1101  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1102 
1103  //Failed to serialize fixed header?
1104  if(error)
1105  return error;
1106 
1107  //Point to the first byte of the MQTT packet
1108  context->packet = context->buffer + n;
1109  //Calculate the length of the MQTT packet
1110  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1111 
1112  //Successful processing
1113  return NO_ERROR;
1114 }
1115 
1116 
1117 /**
1118  * @brief Format PUBREC packet
1119  * @param[in] context Pointer to the MQTT client context
1120  * @param[in] packetId Packet identifier
1121  * @return Error code
1122  **/
1123 
1125 {
1126  error_t error;
1127  size_t n;
1128 
1129  //Make room for the fixed header
1131 
1132  //The variable header contains the Packet Identifier from the PUBLISH
1133  //packet that is being acknowledged
1134  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1135  &n, packetId);
1136 
1137  //Failed to serialize Packet Identifier field?
1138  if(error)
1139  return error;
1140 
1141  //Calculate the length of the variable header and the payload
1142  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1143 
1144  //The fixed header will be encoded in reverse order
1146 
1147  //Prepend the variable header and the payload with the fixed header
1148  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBREC,
1149  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1150 
1151  //Failed to serialize fixed header?
1152  if(error)
1153  return error;
1154 
1155  //Point to the first byte of the MQTT packet
1156  context->packet = context->buffer + n;
1157  //Calculate the length of the MQTT packet
1158  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1159 
1160  //Successful processing
1161  return NO_ERROR;
1162 }
1163 
1164 
1165 /**
1166  * @brief Format PUBREL packet
1167  * @param[in] context Pointer to the MQTT client context
1168  * @param[in] packetId Packet identifier
1169  * @return Error code
1170  **/
1171 
1173 {
1174  error_t error;
1175  size_t n;
1176 
1177  //Make room for the fixed header
1179 
1180  //The variable header contains the same Packet Identifier as the PUBREC
1181  //packet that is being acknowledged
1182  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1183  &n, packetId);
1184 
1185  //Failed to serialize Packet Identifier field?
1186  if(error)
1187  return error;
1188 
1189  //Calculate the length of the variable header and the payload
1190  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1191 
1192  //The fixed header will be encoded in reverse order
1194 
1195  //Prepend the variable header and the payload with the fixed header
1196  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBREL,
1197  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1198 
1199  //Failed to serialize fixed header?
1200  if(error)
1201  return error;
1202 
1203  //Point to the first byte of the MQTT packet
1204  context->packet = context->buffer + n;
1205  //Calculate the length of the MQTT packet
1206  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1207 
1208  //Successful processing
1209  return NO_ERROR;
1210 }
1211 
1212 
1213 /**
1214  * @brief Format PUBCOMP packet
1215  * @param[in] context Pointer to the MQTT client context
1216  * @param[in] packetId Packet identifier
1217  * @return Error code
1218  **/
1219 
1221 {
1222  error_t error;
1223  size_t n;
1224 
1225  //Make room for the fixed header
1227 
1228  //The variable header contains the same Packet Identifier as the PUBREL
1229  //packet that is being acknowledged
1230  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1231  &n, packetId);
1232 
1233  //Failed to serialize Packet Identifier field?
1234  if(error)
1235  return error;
1236 
1237  //Calculate the length of the variable header and the payload
1238  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1239 
1240  //The fixed header will be encoded in reverse order
1242 
1243  //Prepend the variable header and the payload with the fixed header
1244  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBCOMP,
1245  FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen);
1246 
1247  //Failed to serialize fixed header?
1248  if(error)
1249  return error;
1250 
1251  //Point to the first byte of the MQTT packet
1252  context->packet = context->buffer + n;
1253  //Calculate the length of the MQTT packet
1254  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1255 
1256  //Successful processing
1257  return NO_ERROR;
1258 }
1259 
1260 
1261 /**
1262  * @brief Format SUBSCRIBE packet
1263  * @param[in] context Pointer to the MQTT client context
1264  * @param[in] topic Topic filter
1265  * @param[in] qos Maximum QoS level at which the server can send application
1266  * messages to the client
1267  * @return Error code
1268  **/
1269 
1271  const char_t *topic, MqttQosLevel qos)
1272 {
1273  error_t error;
1274  size_t n;
1275 
1276  //Make room for the fixed header
1278 
1279  //Each time a client sends a new SUBSCRIBE packet it must assign it
1280  //a currently unused packet identifier
1281  if(context->packetId < UINT16_MAX)
1282  {
1283  context->packetId++;
1284  }
1285  else
1286  {
1287  context->packetId = 1;
1288  }
1289 
1290  //Write Packet Identifier to the output buffer
1291  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1292  &n, context->packetId);
1293 
1294  //Failed to serialize data?
1295  if(error)
1296  return error;
1297 
1298  //Write the Topic Filter to the output buffer
1299  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1300  &n, topic, osStrlen(topic));
1301 
1302  //Failed to serialize data?
1303  if(error)
1304  return error;
1305 
1306  //Write the Requested QoS to the output buffer
1307  error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1308  &n, qos);
1309 
1310  //Failed to serialize data?
1311  if(error)
1312  return error;
1313 
1314  //Calculate the length of the variable header and the payload
1315  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1316 
1317  //The fixed header will be encoded in reverse order
1319 
1320  //Prepend the variable header and the payload with the fixed header
1321  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_SUBSCRIBE,
1322  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1323 
1324  //Failed to serialize fixed header?
1325  if(error)
1326  return error;
1327 
1328  //Point to the first byte of the MQTT packet
1329  context->packet = context->buffer + n;
1330  //Calculate the length of the MQTT packet
1331  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1332 
1333  //Successful processing
1334  return NO_ERROR;
1335 }
1336 
1337 
1338 /**
1339  * @brief Format UNSUBSCRIBE packet
1340  * @param[in] context Pointer to the MQTT client context
1341  * @param[in] topic Topic filter
1342  * @return Error code
1343  **/
1344 
1346  const char_t *topic)
1347 {
1348  error_t error;
1349  size_t n;
1350 
1351  //Make room for the fixed header
1353 
1354  //Each time a client sends a new UNSUBSCRIBE packet it must assign it
1355  //a currently unused packet identifier
1356  if(context->packetId < UINT16_MAX)
1357  {
1358  context->packetId++;
1359  }
1360  else
1361  {
1362  context->packetId = 1;
1363  }
1364 
1365  //Write Packet Identifier to the output buffer
1366  error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1367  &n, context->packetId);
1368 
1369  //Failed to serialize data?
1370  if(error)
1371  return error;
1372 
1373  //Write the Topic Filter to the output buffer
1374  error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE,
1375  &n, topic, osStrlen(topic));
1376 
1377  //Failed to serialize data?
1378  if(error)
1379  return error;
1380 
1381  //Calculate the length of the variable header and the payload
1382  context->packetLen = n - MQTT_MAX_HEADER_SIZE;
1383 
1384  //The fixed header will be encoded in reverse order
1386 
1387  //Prepend the variable header and the payload with the fixed header
1388  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_UNSUBSCRIBE,
1389  FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen);
1390 
1391  //Failed to serialize fixed header?
1392  if(error)
1393  return error;
1394 
1395  //Point to the first byte of the MQTT packet
1396  context->packet = context->buffer + n;
1397  //Calculate the length of the MQTT packet
1398  context->packetLen += MQTT_MAX_HEADER_SIZE - n;
1399 
1400  //Successful processing
1401  return NO_ERROR;
1402 }
1403 
1404 
1405 /**
1406  * @brief Format PINGREQ packet
1407  * @param[in] context Pointer to the MQTT client context
1408  * @return Error code
1409  **/
1410 
1412 {
1413  error_t error;
1414  size_t n;
1415 
1416  //The fixed header will be encoded in reverse order
1418 
1419  //The PINGREQ packet does not contain any variable header nor payload
1420  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PINGREQ,
1422 
1423  //Failed to serialize fixed header?
1424  if(error)
1425  return error;
1426 
1427  //Point to the first byte of the MQTT packet
1428  context->packet = context->buffer + n;
1429  //Calculate the length of the MQTT packet
1430  context->packetLen = MQTT_MAX_HEADER_SIZE - n;
1431 
1432  //Successful processing
1433  return NO_ERROR;
1434 }
1435 
1436 
1437 /**
1438  * @brief Format DISCONNECT packet
1439  * @param[in] context Pointer to the MQTT client context
1440  * @return Error code
1441  **/
1442 
1444 {
1445  error_t error;
1446  size_t n;
1447 
1448  //The fixed header will be encoded in reverse order
1450 
1451  //The DISCONNECT packet does not contain any variable header nor payload
1452  error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_DISCONNECT,
1454 
1455  //Failed to serialize fixed header?
1456  if(error)
1457  return error;
1458 
1459  //Point to the first byte of the MQTT packet
1460  context->packet = context->buffer + n;
1461  //Calculate the length of the MQTT packet
1462  context->packetLen = MQTT_MAX_HEADER_SIZE - n;
1463 
1464  //Successful processing
1465  return NO_ERROR;
1466 }
1467 
1468 #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.