Embed:
(wiki syntax)
Show/hide line numbers
mqtt_client_packet.c
Go to the documentation of this file.
00001 /** 00002 * @file mqtt_client_packet.c 00003 * @brief MQTT packet parsing and formatting 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL MQTT_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "mqtt/mqtt_client.h" 00035 #include "mqtt/mqtt_client_packet.h" 00036 #include "mqtt/mqtt_client_transport.h" 00037 #include "mqtt/mqtt_client_misc.h" 00038 #include "debug.h" 00039 00040 //Check TCP/IP stack configuration 00041 #if (MQTT_CLIENT_SUPPORT == ENABLED) 00042 00043 //MQTT control packets 00044 static const char_t *packetLabel[16] = 00045 { 00046 "Reserved", //0 00047 "CONNECT", //1 00048 "CONNACK", //2 00049 "PUBLISH", //3 00050 "PUBACK", //4 00051 "PUBREC", //5 00052 "PUBREL", //6 00053 "PUBCOMP", //7 00054 "SUBSCRIBE", //8 00055 "SUBACK", //9 00056 "UNSUBSCRIBE", //10 00057 "UNSUBACK", //11 00058 "PINGREQ", //12 00059 "PINGRESP", //13 00060 "DISCONNECT", //14 00061 "Reserved" //15 00062 }; 00063 00064 00065 /** 00066 * @brief Receive MQTT packet 00067 * @param[in] context Pointer to the MQTT client context 00068 * @return Error code 00069 **/ 00070 00071 error_t mqttClientReceivePacket(MqttClientContext *context) 00072 { 00073 error_t error; 00074 size_t n; 00075 uint8_t value; 00076 00077 //Initialize status code 00078 error = NO_ERROR; 00079 00080 //Receive incoming packet 00081 while(1) 00082 { 00083 //Packet header is being received? 00084 if(context->packetLen == 0) 00085 { 00086 //Read a single byte 00087 error = mqttClientReceiveData(context, &value, sizeof(uint8_t), &n, 0); 00088 00089 //Any data received? 00090 if(!error) 00091 { 00092 //Save the current byte 00093 context->packet[context->packetPos] = value; 00094 00095 //The Remaining Length is encoded using a variable length encoding scheme 00096 if(context->packetPos > 0) 00097 { 00098 //The most significant bit is used to indicate that there are 00099 //following bytes in the representation 00100 if(value & 0x80) 00101 { 00102 //Applications can send control packets of size up to 256 MB 00103 if(context->packetPos < 4) 00104 { 00105 //The least significant seven bits of each byte encode the data 00106 context->remainingLen |= (value & 0x7F) << (7 * (context->packetPos - 1)); 00107 } 00108 else 00109 { 00110 //Report an error 00111 error = ERROR_INVALID_SYNTAX; 00112 } 00113 } 00114 else 00115 { 00116 //The least significant seven bits of each byte encode the data 00117 context->remainingLen |= value << (7 * (context->packetPos - 1)); 00118 //Calculate the length of the control packet 00119 context->packetLen = context->packetPos + 1 + context->remainingLen; 00120 00121 //Sanity check 00122 if(context->packetLen > MQTT_CLIENT_BUFFER_SIZE) 00123 error = ERROR_INVALID_LENGTH; 00124 } 00125 } 00126 00127 //Advance data pointer 00128 context->packetPos++; 00129 } 00130 } 00131 //Variable header or payload is being received? 00132 else 00133 { 00134 //Any remaining data? 00135 if(context->packetPos < context->packetLen) 00136 { 00137 //Read more data 00138 error = mqttClientReceiveData(context, context->packet + context->packetPos, 00139 context->packetLen - context->packetPos, &n, 0); 00140 00141 //Advance data pointer 00142 context->packetPos += n; 00143 } 00144 else 00145 { 00146 //The packet has been successfully received 00147 break; 00148 } 00149 } 00150 00151 //Any error to report? 00152 if(error) 00153 break; 00154 } 00155 00156 //Return status code 00157 return error; 00158 } 00159 00160 00161 /** 00162 * @brief Process incoming MQTT packet 00163 * @param[in] context Pointer to the MQTT client context 00164 * @return Error code 00165 **/ 00166 00167 error_t mqttClientProcessPacket(MqttClientContext *context) 00168 { 00169 error_t error; 00170 bool_t dup; 00171 bool_t retain; 00172 size_t remainingLen; 00173 MqttQosLevel qos; 00174 MqttPacketType type; 00175 00176 //Point to the first byte of the packet 00177 context->packetPos = 0; 00178 00179 //Read the fixed header from the input buffer 00180 error = mqttDeserializeHeader(context->packet, context->packetLen, 00181 &context->packetPos, &type, &dup, &qos, &retain, &remainingLen); 00182 00183 //Failed to deserialize fixed header? 00184 if(error) 00185 return error; 00186 00187 //Debug message 00188 TRACE_INFO("MQTT: %s packet received (%" PRIuSIZE " bytes)...\r\n", 00189 packetLabel[type], context->packetLen); 00190 00191 //Dump the contents of the packet 00192 TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen); 00193 00194 //Check MQTT control packet type 00195 switch(type) 00196 { 00197 //CONNACK packet received? 00198 case MQTT_PACKET_TYPE_CONNACK: 00199 //Process incoming CONNACK packet 00200 error = mqttClientProcessConnAck(context, dup, qos, retain, remainingLen); 00201 break; 00202 //PUBLISH packet received? 00203 case MQTT_PACKET_TYPE_PUBLISH: 00204 //Process incoming PUBLISH packet 00205 error = mqttClientProcessPublish(context, dup, qos, retain, remainingLen); 00206 break; 00207 //PUBACK packet received? 00208 case MQTT_PACKET_TYPE_PUBACK: 00209 //Process incoming PUBACK packet 00210 error = mqttClientProcessPubAck(context, dup, qos, retain, remainingLen); 00211 break; 00212 //PUBREC packet received? 00213 case MQTT_PACKET_TYPE_PUBREC: 00214 //Process incoming PUBREC packet 00215 error = mqttClientProcessPubRec(context, dup, qos, retain, remainingLen); 00216 break; 00217 //PUBREL packet received? 00218 case MQTT_PACKET_TYPE_PUBREL: 00219 //Process incoming PUBREL packet 00220 error = mqttClientProcessPubRel(context, dup, qos, retain, remainingLen); 00221 break; 00222 //PUBCOMP packet received? 00223 case MQTT_PACKET_TYPE_PUBCOMP: 00224 //Process incoming PUBCOMP packet 00225 error = mqttClientProcessPubComp(context, dup, qos, retain, remainingLen); 00226 break; 00227 //SUBACK packet received? 00228 case MQTT_PACKET_TYPE_SUBACK: 00229 //Process incoming SUBACK packet 00230 error = mqttClientProcessSubAck(context, dup, qos, retain, remainingLen); 00231 break; 00232 //UNSUBACK packet received? 00233 case MQTT_PACKET_TYPE_UNSUBACK: 00234 //Process incoming UNSUBACK packet 00235 error = mqttClientProcessUnsubAck(context, dup, qos, retain, remainingLen); 00236 break; 00237 //PINGRESP packet received? 00238 case MQTT_PACKET_TYPE_PINGRESP: 00239 //Process incoming PINGRESP packet 00240 error = mqttClientProcessPingResp(context, dup, qos, retain, remainingLen); 00241 break; 00242 //Unknown packet received? 00243 default: 00244 //Report an error 00245 error = ERROR_INVALID_PACKET; 00246 } 00247 00248 //Return status code 00249 return error; 00250 } 00251 00252 00253 /** 00254 * @brief Process incoming CONNACK packet 00255 * @param[in] context Pointer to the MQTT client context 00256 * @param[in] dup DUP flag from the fixed header 00257 * @param[in] qos QoS field from the fixed header 00258 * @param[in] retain RETAIN flag from the fixed header 00259 * @param[in] remainingLen Length of the variable header and the payload 00260 **/ 00261 00262 error_t mqttClientProcessConnAck(MqttClientContext *context, 00263 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00264 { 00265 error_t error; 00266 uint8_t connectAckFlags; 00267 uint8_t connectReturnCode; 00268 00269 //If invalid flags are received, the receiver must close the network connection 00270 if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE) 00271 return ERROR_INVALID_PACKET; 00272 00273 //The first byte of the variable header is the Connect Acknowledge Flags 00274 error = mqttDeserializeByte(context->packet, context->packetLen, 00275 &context->packetPos, &connectAckFlags); 00276 00277 //Failed to deserialize the Connect Acknowledge Flags? 00278 if(error) 00279 return error; 00280 00281 //The second byte of the variable header is the Connect Return Code 00282 error = mqttDeserializeByte(context->packet, context->packetLen, 00283 &context->packetPos, &connectReturnCode); 00284 00285 //Failed to deserialize the Connect Return Code? 00286 if(error) 00287 return error; 00288 00289 //Any registered callback? 00290 if(context->callbacks.connAckCallback != NULL) 00291 { 00292 //Invoke user callback function 00293 context->callbacks.connAckCallback(context, 00294 connectAckFlags, connectReturnCode); 00295 } 00296 00297 //Make sure the connection is accepted 00298 if(connectReturnCode != MQTT_CONNECT_RET_CODE_ACCEPTED) 00299 return ERROR_CONNECTION_REFUSED; 00300 00301 //Notify the application that a CONNACK packet has been received 00302 if(context->packetType == MQTT_PACKET_TYPE_CONNECT) 00303 context->state = MQTT_CLIENT_STATE_PACKET_RECEIVED; 00304 00305 //Successful processing 00306 return NO_ERROR; 00307 } 00308 00309 00310 /** 00311 * @brief Process incoming PUBLISH packet 00312 * @param[in] context Pointer to the MQTT client context 00313 * @param[in] dup DUP flag from the fixed header 00314 * @param[in] qos QoS field from the fixed header 00315 * @param[in] retain RETAIN flag from the fixed header 00316 * @param[in] remainingLen Length of the variable header and the payload 00317 **/ 00318 00319 error_t mqttClientProcessPublish(MqttClientContext *context, 00320 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00321 { 00322 error_t error; 00323 uint16_t packetId; 00324 char_t *topic; 00325 size_t topicLen; 00326 uint8_t *message; 00327 size_t messageLen; 00328 00329 //The Topic Name must be present as the first field in the PUBLISH 00330 //packet variable header 00331 error = mqttDeserializeString(context->packet, context->packetLen, 00332 &context->packetPos, &topic, &topicLen); 00333 00334 //Failed to deserialize Topic Name? 00335 if(error) 00336 return error; 00337 00338 //Check QoS level 00339 if(qos != MQTT_QOS_LEVEL_0) 00340 { 00341 //The Packet Identifier field is only present in PUBLISH packets 00342 //where the QoS level is 1 or 2 00343 error = mqttDeserializeShort(context->packet, context->packetLen, 00344 &context->packetPos, &packetId); 00345 00346 //Failed to deserialize Packet Identifier field? 00347 if(error) 00348 return error; 00349 } 00350 else 00351 { 00352 //No packet identifier 00353 packetId = 0; 00354 } 00355 00356 //The payload contains the Application Message that is being published 00357 message = context->packet + context->packetPos; 00358 00359 //The length of the payload can be calculated by subtracting the length of the 00360 //variable header from the Remaining Length field that is in the fixed header 00361 messageLen = context->packetLen - context->packetPos; 00362 00363 //Make room for the NULL character at the end of the Topic Name 00364 memmove(topic - 1, topic, topicLen); 00365 //Properly terminate the string with a NULL character 00366 topic[topicLen - 1] = '\0'; 00367 //Point to the first character of the Topic Name 00368 topic--; 00369 00370 //Any registered callback? 00371 if(context->callbacks.publishCallback != NULL) 00372 { 00373 //Invoke user callback function 00374 context->callbacks.publishCallback(context, topic, 00375 message, messageLen, dup, qos, retain, packetId); 00376 } 00377 00378 //Check QoS level 00379 if(qos == MQTT_QOS_LEVEL_1) 00380 { 00381 //A PUBACK packet is the response to a PUBLISH packet with QoS level 1 00382 error = mqttClientFormatPubAck(context, packetId); 00383 00384 //Check status code 00385 if(!error) 00386 { 00387 //Debug message 00388 TRACE_INFO("MQTT: Sending PUBACK packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen); 00389 TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen); 00390 00391 //Point to the beginning of the packet 00392 context->packetPos = 0; 00393 00394 //Send PUBACK packet 00395 mqttClientChangeState(context, MQTT_CLIENT_STATE_SENDING_PACKET); 00396 } 00397 } 00398 else if(qos == MQTT_QOS_LEVEL_2) 00399 { 00400 //A PUBREC packet is the response to a PUBLISH packet with QoS 2. It is 00401 //the second packet of the QoS 2 protocol exchange 00402 error = mqttClientFormatPubRec(context, packetId); 00403 00404 //Check status code 00405 if(!error) 00406 { 00407 //Debug message 00408 TRACE_INFO("MQTT: Sending PUBREC packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen); 00409 TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen); 00410 00411 //Point to the beginning of the packet 00412 context->packetPos = 0; 00413 00414 //Send PUBREC packet 00415 mqttClientChangeState(context, MQTT_CLIENT_STATE_SENDING_PACKET); 00416 } 00417 } 00418 00419 //Return status code 00420 return error; 00421 } 00422 00423 00424 /** 00425 * @brief Process incoming PUBACK packet 00426 * @param[in] context Pointer to the MQTT client context 00427 * @param[in] dup DUP flag from the fixed header 00428 * @param[in] qos QoS field from the fixed header 00429 * @param[in] retain RETAIN flag from the fixed header 00430 * @param[in] remainingLen Length of the variable header and the payload 00431 **/ 00432 00433 error_t mqttClientProcessPubAck(MqttClientContext *context, 00434 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00435 { 00436 error_t error; 00437 uint16_t packetId; 00438 00439 //If invalid flags are received, the receiver must close the network connection 00440 if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE) 00441 return ERROR_INVALID_PACKET; 00442 00443 //The variable header contains the Packet Identifier from the PUBLISH 00444 //packet that is being acknowledged 00445 error = mqttDeserializeShort(context->packet, context->packetLen, 00446 &context->packetPos, &packetId); 00447 00448 //Failed to deserialize Packet Identifier field? 00449 if(error) 00450 return error; 00451 00452 //Any registered callback? 00453 if(context->callbacks.pubAckCallback != NULL) 00454 { 00455 //Invoke user callback function 00456 context->callbacks.pubAckCallback(context, packetId); 00457 } 00458 00459 //Notify the application that a PUBACK packet has been received 00460 if(context->packetType == MQTT_PACKET_TYPE_PUBLISH && context->packetId == packetId) 00461 context->state = MQTT_CLIENT_STATE_PACKET_RECEIVED; 00462 00463 //Return status code 00464 return error; 00465 } 00466 00467 00468 /** 00469 * @brief Process incoming PUBREC packet 00470 * @param[in] context Pointer to the MQTT client context 00471 * @param[in] dup DUP flag from the fixed header 00472 * @param[in] qos QoS field from the fixed header 00473 * @param[in] retain RETAIN flag from the fixed header 00474 * @param[in] remainingLen Length of the variable header and the payload 00475 **/ 00476 00477 error_t mqttClientProcessPubRec(MqttClientContext *context, 00478 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00479 { 00480 error_t error; 00481 uint16_t packetId; 00482 00483 //If invalid flags are received, the receiver must close the network connection 00484 if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE) 00485 return ERROR_INVALID_PACKET; 00486 00487 //The variable header contains the Packet Identifier from the PUBLISH 00488 //packet that is being acknowledged 00489 error = mqttDeserializeShort(context->packet, context->packetLen, 00490 &context->packetPos, &packetId); 00491 00492 //Failed to deserialize Packet Identifier field? 00493 if(error) 00494 return error; 00495 00496 //Any registered callback? 00497 if(context->callbacks.pubRecCallback != NULL) 00498 { 00499 //Invoke user callback function 00500 context->callbacks.pubRecCallback(context, packetId); 00501 } 00502 00503 //A PUBREL packet is the response to a PUBREC packet. It is the third 00504 //packet of the QoS 2 protocol exchange 00505 error = mqttClientFormatPubRel(context, packetId); 00506 00507 //Check status code 00508 if(!error) 00509 { 00510 //Debug message 00511 TRACE_INFO("MQTT: Sending PUBREL packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen); 00512 TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen); 00513 00514 //Point to the beginning of the packet 00515 context->packetPos = 0; 00516 00517 //Send PUBREL packet 00518 mqttClientChangeState(context, MQTT_CLIENT_STATE_SENDING_PACKET); 00519 } 00520 00521 //Return status code 00522 return error; 00523 } 00524 00525 00526 /** 00527 * @brief Process incoming PUBREL packet 00528 * @param[in] context Pointer to the MQTT client context 00529 * @param[in] dup DUP flag from the fixed header 00530 * @param[in] qos QoS field from the fixed header 00531 * @param[in] retain RETAIN flag from the fixed header 00532 * @param[in] remainingLen Length of the variable header and the payload 00533 **/ 00534 00535 error_t mqttClientProcessPubRel(MqttClientContext *context, 00536 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00537 { 00538 error_t error; 00539 uint16_t packetId; 00540 00541 //If invalid flags are received, the receiver must close the network connection 00542 if(dup != FALSE && qos != MQTT_QOS_LEVEL_1 && retain != FALSE) 00543 return ERROR_INVALID_PACKET; 00544 00545 //The variable header contains the same Packet Identifier as the PUBREC 00546 //packet that is being acknowledged 00547 error = mqttDeserializeShort(context->packet, context->packetLen, 00548 &context->packetPos, &packetId); 00549 00550 //Failed to deserialize Packet Identifier field? 00551 if(error) 00552 return error; 00553 00554 //Any registered callback? 00555 if(context->callbacks.pubRelCallback != NULL) 00556 { 00557 //Invoke user callback function 00558 context->callbacks.pubRelCallback(context, packetId); 00559 } 00560 00561 //A PUBCOMP packet is the response to a PUBREL packet. It is the fourth and 00562 //final packet of the QoS 2 protocol exchange 00563 error = mqttClientFormatPubComp(context, packetId); 00564 00565 //Check status code 00566 if(!error) 00567 { 00568 //Debug message 00569 TRACE_INFO("MQTT: Sending PUBCOMP packet (%" PRIuSIZE " bytes)...\r\n", context->packetLen); 00570 TRACE_DEBUG_ARRAY(" ", context->packet, context->packetLen); 00571 00572 //Point to the beginning of the packet 00573 context->packetPos = 0; 00574 00575 //Send PUBCOMP packet 00576 mqttClientChangeState(context, MQTT_CLIENT_STATE_SENDING_PACKET); 00577 } 00578 00579 //Return status code 00580 return error; 00581 } 00582 00583 00584 /** 00585 * @brief Process incoming PUBCOMP packet 00586 * @param[in] context Pointer to the MQTT client context 00587 * @param[in] dup DUP flag from the fixed header 00588 * @param[in] qos QoS field from the fixed header 00589 * @param[in] retain RETAIN flag from the fixed header 00590 * @param[in] remainingLen Length of the variable header and the payload 00591 **/ 00592 00593 error_t mqttClientProcessPubComp(MqttClientContext *context, 00594 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00595 { 00596 error_t error; 00597 uint16_t packetId; 00598 00599 //If invalid flags are received, the receiver must close the network connection 00600 if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE) 00601 return ERROR_INVALID_PACKET; 00602 00603 //The variable header contains the same Packet Identifier as the PUBREL 00604 //packet that is being acknowledged 00605 error = mqttDeserializeShort(context->packet, context->packetLen, 00606 &context->packetPos, &packetId); 00607 00608 //Failed to deserialize Packet Identifier field? 00609 if(error) 00610 return error; 00611 00612 //Any registered callback? 00613 if(context->callbacks.pubCompCallback != NULL) 00614 { 00615 //Invoke user callback function 00616 context->callbacks.pubCompCallback(context, packetId); 00617 } 00618 00619 //Notify the application that a PUBCOMP packet has been received 00620 if(context->packetType == MQTT_PACKET_TYPE_PUBLISH && context->packetId == packetId) 00621 context->state = MQTT_CLIENT_STATE_PACKET_RECEIVED; 00622 00623 //Successful processing 00624 return NO_ERROR; 00625 } 00626 00627 00628 /** 00629 * @brief Process incoming SUBACK packet 00630 * @param[in] context Pointer to the MQTT client context 00631 * @param[in] dup DUP flag from the fixed header 00632 * @param[in] qos QoS field from the fixed header 00633 * @param[in] retain RETAIN flag from the fixed header 00634 * @param[in] remainingLen Length of the variable header and the payload 00635 **/ 00636 00637 error_t mqttClientProcessSubAck(MqttClientContext *context, 00638 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00639 { 00640 error_t error; 00641 uint16_t packetId; 00642 00643 //If invalid flags are received, the receiver must close the network connection 00644 if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE) 00645 return ERROR_INVALID_PACKET; 00646 00647 //The variable header contains the Packet Identifier from the SUBSCRIBE 00648 //packet that is being acknowledged 00649 error = mqttDeserializeShort(context->packet, context->packetLen, 00650 &context->packetPos, &packetId); 00651 00652 //Failed to deserialize Packet Identifier field? 00653 if(error) 00654 return error; 00655 00656 //Any registered callback? 00657 if(context->callbacks.subAckCallback != NULL) 00658 { 00659 //Invoke user callback function 00660 context->callbacks.subAckCallback(context, packetId); 00661 } 00662 00663 //Notify the application that a SUBACK packet has been received 00664 if(context->packetType == MQTT_PACKET_TYPE_SUBSCRIBE && context->packetId == packetId) 00665 context->state = MQTT_CLIENT_STATE_PACKET_RECEIVED; 00666 00667 //Successful processing 00668 return NO_ERROR; 00669 } 00670 00671 00672 /** 00673 * @brief Process incoming UNSUBACK packet 00674 * @param[in] context Pointer to the MQTT client context 00675 * @param[in] dup DUP flag from the fixed header 00676 * @param[in] qos QoS field from the fixed header 00677 * @param[in] retain RETAIN flag from the fixed header 00678 * @param[in] remainingLen Length of the variable header and the payload 00679 **/ 00680 00681 error_t mqttClientProcessUnsubAck(MqttClientContext *context, 00682 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00683 { 00684 error_t error; 00685 uint16_t packetId; 00686 00687 //If invalid flags are received, the receiver must close the network connection 00688 if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE) 00689 return ERROR_INVALID_PACKET; 00690 00691 //The variable header contains the Packet Identifier from the UNSUBSCRIBE 00692 //packet that is being acknowledged 00693 error = mqttDeserializeShort(context->packet, context->packetLen, 00694 &context->packetPos, &packetId); 00695 00696 //Failed to deserialize Packet Identifier field? 00697 if(error) 00698 return error; 00699 00700 //Any registered callback? 00701 if(context->callbacks.unsubAckCallback != NULL) 00702 { 00703 //Invoke user callback function 00704 context->callbacks.unsubAckCallback(context, packetId); 00705 } 00706 00707 //Notify the application that an UNSUBACK packet has been received 00708 if(context->packetType == MQTT_PACKET_TYPE_UNSUBSCRIBE && context->packetId == packetId) 00709 context->state = MQTT_CLIENT_STATE_PACKET_RECEIVED; 00710 00711 //Successful processing 00712 return NO_ERROR; 00713 } 00714 00715 00716 /** 00717 * @brief Process incoming PINGRESP packet 00718 * @param[in] context Pointer to the MQTT client context 00719 * @param[in] dup DUP flag from the fixed header 00720 * @param[in] qos QoS field from the fixed header 00721 * @param[in] retain RETAIN flag from the fixed header 00722 * @param[in] remainingLen Length of the variable header and the payload 00723 **/ 00724 00725 error_t mqttClientProcessPingResp(MqttClientContext *context, 00726 bool_t dup, MqttQosLevel qos, bool_t retain, size_t remainingLen) 00727 { 00728 //If invalid flags are received, the receiver must close the network connection 00729 if(dup != FALSE && qos != MQTT_QOS_LEVEL_0 && retain != FALSE) 00730 return ERROR_INVALID_PACKET; 00731 00732 //Any registered callback? 00733 if(context->callbacks.pingRespCallback != NULL) 00734 { 00735 //Invoke user callback function 00736 context->callbacks.pingRespCallback(context); 00737 } 00738 00739 //Notify the application that an PINGRESP packet has been received 00740 if(context->packetType == MQTT_PACKET_TYPE_PINGREQ) 00741 context->state = MQTT_CLIENT_STATE_PACKET_RECEIVED; 00742 00743 //Successful processing 00744 return NO_ERROR; 00745 } 00746 00747 00748 /** 00749 * @brief Format CONNECT packet 00750 * @param[in] context Pointer to the MQTT client context 00751 * @param[in] cleanSession If this flag is set, then the client and server 00752 * must discard any previous session and start a new one 00753 * @return Error code 00754 **/ 00755 00756 error_t mqttClientFormatConnect(MqttClientContext *context, 00757 bool_t cleanSession) 00758 { 00759 error_t error; 00760 size_t n; 00761 uint8_t connectFlags; 00762 MqttClientWillMessage *willMessage; 00763 00764 //Make room for the fixed header 00765 n = MQTT_MAX_HEADER_SIZE; 00766 00767 //Check protocol version 00768 if(context->settings.protocolLevel == MQTT_PROTOCOL_LEVEL_3_1) 00769 { 00770 //The Protocol Name is a UTF-8 encoded string that represents the 00771 //protocol name "MQIsdp" 00772 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00773 &n, MQTT_PROTOCOL_NAME_3_1, strlen(MQTT_PROTOCOL_NAME_3_1)); 00774 } 00775 else if(context->settings.protocolLevel == MQTT_PROTOCOL_LEVEL_3_1_1) 00776 { 00777 //The Protocol Name is a UTF-8 encoded string that represents the 00778 //protocol name "MQTT" 00779 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00780 &n, MQTT_PROTOCOL_NAME_3_1_1, strlen(MQTT_PROTOCOL_NAME_3_1_1)); 00781 } 00782 else 00783 { 00784 //Invalid protocol level 00785 error = ERROR_INVALID_VERSION; 00786 } 00787 00788 //Any error to report? 00789 if(error) 00790 return error; 00791 00792 //The Protocol Level represents the revision level of the protocol 00793 //used by the client 00794 error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00795 &n, context->settings.protocolLevel); 00796 00797 //Failed to serialize data? 00798 if(error) 00799 return error; 00800 00801 //The Connect Flags byte contains a number of parameters specifying 00802 //the behavior of the MQTT connection 00803 connectFlags = 0; 00804 00805 //If CleanSession is set to 1, the client and server must discard any 00806 //previous session and start a new one 00807 if(cleanSession) 00808 connectFlags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; 00809 00810 //If the client supplies a zero-byte Client Identifier, the client must 00811 //also set CleanSession to 1 00812 if(context->settings.clientId[0] == '\0') 00813 connectFlags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; 00814 00815 //Point to the Will message 00816 willMessage = &context->settings.willMessage; 00817 00818 //Check whether a valid Will message has been specified 00819 if(willMessage->topic[0] != '\0') 00820 { 00821 //Set the Will flag 00822 connectFlags |= MQTT_CONNECT_FLAG_WILL; 00823 00824 //Check the Will QoS level 00825 if(willMessage->qos == MQTT_QOS_LEVEL_1) 00826 connectFlags |= MQTT_CONNECT_FLAG_WILL_QOS_1; 00827 else if(willMessage->qos == MQTT_QOS_LEVEL_2) 00828 connectFlags |= MQTT_CONNECT_FLAG_WILL_QOS_2; 00829 00830 //The Will Retain flag specifies if the Will Message is to be 00831 //retained when it is published 00832 if(willMessage->retain) 00833 connectFlags |= MQTT_CONNECT_FLAG_WILL_RETAIN; 00834 } 00835 00836 //Check whether a valid user name has been specified 00837 if(context->settings.username[0] != '\0') 00838 connectFlags |= MQTT_CONNECT_FLAG_USERNAME; 00839 00840 //Check whether a valid password has been specified 00841 if(context->settings.password[0] != '\0') 00842 connectFlags |= MQTT_CONNECT_FLAG_PASSWORD; 00843 00844 //Write the Connect Flags to the output buffer 00845 error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00846 &n, connectFlags); 00847 00848 //Failed to serialize data? 00849 if(error) 00850 return error; 00851 00852 //The Keep Alive is a time interval measured in seconds. It is the maximum 00853 //time interval that is permitted to elapse between the point at which the 00854 //client finishes transmitting one control packet and the point it starts 00855 //sending the next 00856 error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00857 &n, context->settings.keepAlive); 00858 00859 //Failed to serialize data? 00860 if(error) 00861 return error; 00862 00863 //The Client Identifier identifies the client to the server. The Client 00864 //Identifier must be present and must be the first field in the CONNECT 00865 //packet payload 00866 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00867 &n, context->settings.clientId, strlen(context->settings.clientId)); 00868 00869 //Failed to serialize data? 00870 if(error) 00871 return error; 00872 00873 //If the Will Flag is set to 1, the Will Topic is the next field in 00874 //the payload 00875 if(willMessage->topic[0] != '\0') 00876 { 00877 //Write the Will Topic to the output buffer 00878 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00879 &n, willMessage->topic, strlen(willMessage->topic)); 00880 00881 //Failed to serialize data? 00882 if(error) 00883 return error; 00884 00885 //Write the Will message to the output buffer 00886 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00887 &n, willMessage->payload, willMessage->length); 00888 00889 //Failed to serialize data? 00890 if(error) 00891 return error; 00892 } 00893 00894 //If the User Name Flag is set to 1, this is the next field in the payload 00895 if(context->settings.username[0] != '\0') 00896 { 00897 //Write the User Name to the output buffer 00898 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00899 &n, context->settings.username, strlen(context->settings.username)); 00900 00901 //Failed to serialize data? 00902 if(error) 00903 return error; 00904 } 00905 00906 //If the Password Flag is set to 1, this is the next field in the payload 00907 if(context->settings.password[0] != '\0') 00908 { 00909 //Write the Password to the output buffer 00910 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00911 &n, context->settings.password, strlen(context->settings.password)); 00912 00913 //Failed to serialize data? 00914 if(error) 00915 return error; 00916 } 00917 00918 //Calculate the length of the variable header and the payload 00919 context->packetLen = n - MQTT_MAX_HEADER_SIZE; 00920 00921 //The fixed header will be encoded in reverse order 00922 n = MQTT_MAX_HEADER_SIZE; 00923 00924 //Prepend the variable header and the payload with the fixed header 00925 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_CONNECT, 00926 FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen); 00927 00928 //Failed to serialize fixed header? 00929 if(error) 00930 return error; 00931 00932 //Point to the first byte of the MQTT packet 00933 context->packet = context->buffer + n; 00934 //Calculate the length of the MQTT packet 00935 context->packetLen += MQTT_MAX_HEADER_SIZE - n; 00936 00937 //Successful processing 00938 return NO_ERROR; 00939 } 00940 00941 00942 /** 00943 * @brief Format PUBLISH packet 00944 * @param[in] context Pointer to the MQTT client context 00945 * @param[in] topic Topic name 00946 * @param[in] message Message payload 00947 * @param[in] length Length of the message payload 00948 * @param[in] qos QoS level to be used when publishing the message 00949 * @param[in] retain This flag specifies if the message is to be retained 00950 * @return Error code 00951 **/ 00952 00953 error_t mqttClientFormatPublish(MqttClientContext *context, const char_t *topic, 00954 const void *message, size_t length, MqttQosLevel qos, bool_t retain) 00955 { 00956 error_t error; 00957 size_t n; 00958 00959 //Make room for the fixed header 00960 n = MQTT_MAX_HEADER_SIZE; 00961 00962 //The Topic Name must be present as the first field in the PUBLISH 00963 //packet variable header 00964 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00965 &n, topic, strlen(topic)); 00966 00967 //Failed to serialize Topic Name? 00968 if(error) 00969 return error; 00970 00971 //Check QoS level 00972 if(qos != MQTT_QOS_LEVEL_0) 00973 { 00974 //Each time a client sends a new PUBLISH packet it must assign it 00975 //a currently unused packet identifier 00976 context->packetId++; 00977 00978 //The Packet Identifier field is only present in PUBLISH packets 00979 //where the QoS level is 1 or 2 00980 error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00981 &n, context->packetId); 00982 00983 //Failed to serialize Packet Identifier field? 00984 if(error) 00985 return error; 00986 } 00987 00988 //The payload contains the Application Message that is being published 00989 error = mqttSerializeData(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 00990 &n, message, length); 00991 00992 //Failed to serialize Application Message? 00993 if(error) 00994 return error; 00995 00996 //Calculate the length of the variable header and the payload 00997 context->packetLen = n - MQTT_MAX_HEADER_SIZE; 00998 00999 //The fixed header will be encoded in reverse order 01000 n = MQTT_MAX_HEADER_SIZE; 01001 01002 //Prepend the variable header and the payload with the fixed header 01003 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBLISH, 01004 FALSE, qos, retain, context->packetLen); 01005 01006 //Failed to serialize fixed header? 01007 if(error) 01008 return error; 01009 01010 //Point to the first byte of the MQTT packet 01011 context->packet = context->buffer + n; 01012 //Calculate the length of the MQTT packet 01013 context->packetLen += MQTT_MAX_HEADER_SIZE - n; 01014 01015 //Successful processing 01016 return NO_ERROR; 01017 } 01018 01019 01020 /** 01021 * @brief Format PUBACK packet 01022 * @param[in] context Pointer to the MQTT client context 01023 * @param[in] packetId Packet identifier 01024 * @return Error code 01025 **/ 01026 01027 error_t mqttClientFormatPubAck(MqttClientContext *context, uint16_t packetId) 01028 { 01029 error_t error; 01030 size_t n; 01031 01032 //Make room for the fixed header 01033 n = MQTT_MAX_HEADER_SIZE; 01034 01035 //The variable header contains the Packet Identifier from the PUBLISH 01036 //packet that is being acknowledged 01037 error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01038 &n, packetId); 01039 01040 //Failed to serialize Packet Identifier field? 01041 if(error) 01042 return error; 01043 01044 //Calculate the length of the variable header and the payload 01045 context->packetLen = n - MQTT_MAX_HEADER_SIZE; 01046 01047 //The fixed header will be encoded in reverse order 01048 n = MQTT_MAX_HEADER_SIZE; 01049 01050 //Prepend the variable header and the payload with the fixed header 01051 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBACK, 01052 FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen); 01053 01054 //Failed to serialize fixed header? 01055 if(error) 01056 return error; 01057 01058 //Point to the first byte of the MQTT packet 01059 context->packet = context->buffer + n; 01060 //Calculate the length of the MQTT packet 01061 context->packetLen += MQTT_MAX_HEADER_SIZE - n; 01062 01063 //Successful processing 01064 return NO_ERROR; 01065 } 01066 01067 01068 /** 01069 * @brief Format PUBREC packet 01070 * @param[in] context Pointer to the MQTT client context 01071 * @param[in] packetId Packet identifier 01072 * @return Error code 01073 **/ 01074 01075 error_t mqttClientFormatPubRec(MqttClientContext *context, uint16_t packetId) 01076 { 01077 error_t error; 01078 size_t n; 01079 01080 //Make room for the fixed header 01081 n = MQTT_MAX_HEADER_SIZE; 01082 01083 //The variable header contains the Packet Identifier from the PUBLISH 01084 //packet that is being acknowledged 01085 error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01086 &n, packetId); 01087 01088 //Failed to serialize Packet Identifier field? 01089 if(error) 01090 return error; 01091 01092 //Calculate the length of the variable header and the payload 01093 context->packetLen = n - MQTT_MAX_HEADER_SIZE; 01094 01095 //The fixed header will be encoded in reverse order 01096 n = MQTT_MAX_HEADER_SIZE; 01097 01098 //Prepend the variable header and the payload with the fixed header 01099 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBREC, 01100 FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen); 01101 01102 //Failed to serialize fixed header? 01103 if(error) 01104 return error; 01105 01106 //Point to the first byte of the MQTT packet 01107 context->packet = context->buffer + n; 01108 //Calculate the length of the MQTT packet 01109 context->packetLen += MQTT_MAX_HEADER_SIZE - n; 01110 01111 //Successful processing 01112 return NO_ERROR; 01113 } 01114 01115 01116 /** 01117 * @brief Format PUBREL packet 01118 * @param[in] context Pointer to the MQTT client context 01119 * @param[in] packetId Packet identifier 01120 * @return Error code 01121 **/ 01122 01123 error_t mqttClientFormatPubRel(MqttClientContext *context, uint16_t packetId) 01124 { 01125 error_t error; 01126 size_t n; 01127 01128 //Make room for the fixed header 01129 n = MQTT_MAX_HEADER_SIZE; 01130 01131 //The variable header contains the same Packet Identifier as the PUBREC 01132 //packet that is being acknowledged 01133 error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01134 &n, packetId); 01135 01136 //Failed to serialize Packet Identifier field? 01137 if(error) 01138 return error; 01139 01140 //Calculate the length of the variable header and the payload 01141 context->packetLen = n - MQTT_MAX_HEADER_SIZE; 01142 01143 //The fixed header will be encoded in reverse order 01144 n = MQTT_MAX_HEADER_SIZE; 01145 01146 //Prepend the variable header and the payload with the fixed header 01147 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBREL, 01148 FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen); 01149 01150 //Failed to serialize fixed header? 01151 if(error) 01152 return error; 01153 01154 //Point to the first byte of the MQTT packet 01155 context->packet = context->buffer + n; 01156 //Calculate the length of the MQTT packet 01157 context->packetLen += MQTT_MAX_HEADER_SIZE - n; 01158 01159 //Successful processing 01160 return NO_ERROR; 01161 } 01162 01163 01164 /** 01165 * @brief Format PUBCOMP packet 01166 * @param[in] context Pointer to the MQTT client context 01167 * @param[in] packetId Packet identifier 01168 * @return Error code 01169 **/ 01170 01171 error_t mqttClientFormatPubComp(MqttClientContext *context, uint16_t packetId) 01172 { 01173 error_t error; 01174 size_t n; 01175 01176 //Make room for the fixed header 01177 n = MQTT_MAX_HEADER_SIZE; 01178 01179 //The variable header contains the same Packet Identifier as the PUBREL 01180 //packet that is being acknowledged 01181 error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01182 &n, packetId); 01183 01184 //Failed to serialize Packet Identifier field? 01185 if(error) 01186 return error; 01187 01188 //Calculate the length of the variable header and the payload 01189 context->packetLen = n - MQTT_MAX_HEADER_SIZE; 01190 01191 //The fixed header will be encoded in reverse order 01192 n = MQTT_MAX_HEADER_SIZE; 01193 01194 //Prepend the variable header and the payload with the fixed header 01195 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PUBCOMP, 01196 FALSE, MQTT_QOS_LEVEL_0, FALSE, context->packetLen); 01197 01198 //Failed to serialize fixed header? 01199 if(error) 01200 return error; 01201 01202 //Point to the first byte of the MQTT packet 01203 context->packet = context->buffer + n; 01204 //Calculate the length of the MQTT packet 01205 context->packetLen += MQTT_MAX_HEADER_SIZE - n; 01206 01207 //Successful processing 01208 return NO_ERROR; 01209 } 01210 01211 01212 /** 01213 * @brief Format SUBSCRIBE packet 01214 * @param[in] context Pointer to the MQTT client context 01215 * @param[in] topic Topic filter 01216 * @param[in] qos Maximum QoS level at which the server can send application 01217 * messages to the client 01218 * @return Error code 01219 **/ 01220 01221 error_t mqttClientFormatSubscribe(MqttClientContext *context, 01222 const char_t *topic, MqttQosLevel qos) 01223 { 01224 error_t error; 01225 size_t n; 01226 01227 //Make room for the fixed header 01228 n = MQTT_MAX_HEADER_SIZE; 01229 01230 //Each time a client sends a new SUBSCRIBE packet it must assign it 01231 //a currently unused packet identifier 01232 context->packetId++; 01233 01234 //Write Packet Identifier to the output buffer 01235 error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01236 &n, context->packetId); 01237 01238 //Failed to serialize data? 01239 if(error) 01240 return error; 01241 01242 //Write the Topic Filter to the output buffer 01243 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01244 &n, topic, strlen(topic)); 01245 01246 //Failed to serialize data? 01247 if(error) 01248 return error; 01249 01250 //Write the Requested QoS to the output buffer 01251 error = mqttSerializeByte(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01252 &n, qos); 01253 01254 //Failed to serialize data? 01255 if(error) 01256 return error; 01257 01258 //Calculate the length of the variable header and the payload 01259 context->packetLen = n - MQTT_MAX_HEADER_SIZE; 01260 01261 //The fixed header will be encoded in reverse order 01262 n = MQTT_MAX_HEADER_SIZE; 01263 01264 //Prepend the variable header and the payload with the fixed header 01265 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_SUBSCRIBE, 01266 FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen); 01267 01268 //Failed to serialize fixed header? 01269 if(error) 01270 return error; 01271 01272 //Point to the first byte of the MQTT packet 01273 context->packet = context->buffer + n; 01274 //Calculate the length of the MQTT packet 01275 context->packetLen += MQTT_MAX_HEADER_SIZE - n; 01276 01277 //Successful processing 01278 return NO_ERROR; 01279 } 01280 01281 01282 /** 01283 * @brief Format UNSUBSCRIBE packet 01284 * @param[in] context Pointer to the MQTT client context 01285 * @param[in] topic Topic filter 01286 * @return Error code 01287 **/ 01288 01289 error_t mqttClientFormatUnsubscribe(MqttClientContext *context, 01290 const char_t *topic) 01291 { 01292 error_t error; 01293 size_t n; 01294 01295 //Make room for the fixed header 01296 n = MQTT_MAX_HEADER_SIZE; 01297 01298 //Each time a client sends a new UNSUBSCRIBE packet it must assign it 01299 //a currently unused packet identifier 01300 context->packetId++; 01301 01302 //Write Packet Identifier to the output buffer 01303 error = mqttSerializeShort(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01304 &n, context->packetId); 01305 01306 //Failed to serialize data? 01307 if(error) 01308 return error; 01309 01310 //Write the Topic Filter to the output buffer 01311 error = mqttSerializeString(context->buffer, MQTT_CLIENT_BUFFER_SIZE, 01312 &n, topic, strlen(topic)); 01313 01314 //Failed to serialize data? 01315 if(error) 01316 return error; 01317 01318 //Calculate the length of the variable header and the payload 01319 context->packetLen = n - MQTT_MAX_HEADER_SIZE; 01320 01321 //The fixed header will be encoded in reverse order 01322 n = MQTT_MAX_HEADER_SIZE; 01323 01324 //Prepend the variable header and the payload with the fixed header 01325 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_UNSUBSCRIBE, 01326 FALSE, MQTT_QOS_LEVEL_1, FALSE, context->packetLen); 01327 01328 //Failed to serialize fixed header? 01329 if(error) 01330 return error; 01331 01332 //Point to the first byte of the MQTT packet 01333 context->packet = context->buffer + n; 01334 //Calculate the length of the MQTT packet 01335 context->packetLen += MQTT_MAX_HEADER_SIZE - n; 01336 01337 //Successful processing 01338 return NO_ERROR; 01339 } 01340 01341 01342 /** 01343 * @brief Format PINGREQ packet 01344 * @param[in] context Pointer to the MQTT client context 01345 * @return Error code 01346 **/ 01347 01348 error_t mqttClientFormatPingReq(MqttClientContext *context) 01349 { 01350 error_t error; 01351 size_t n; 01352 01353 //The fixed header will be encoded in reverse order 01354 n = MQTT_MAX_HEADER_SIZE; 01355 01356 //The PINGREQ packet does not contain any variable header nor payload 01357 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_PINGREQ, 01358 FALSE, MQTT_QOS_LEVEL_0, FALSE, 0); 01359 01360 //Failed to serialize fixed header? 01361 if(error) 01362 return error; 01363 01364 //Point to the first byte of the MQTT packet 01365 context->packet = context->buffer + n; 01366 //Calculate the length of the MQTT packet 01367 context->packetLen = MQTT_MAX_HEADER_SIZE - n; 01368 01369 //Successful processing 01370 return NO_ERROR; 01371 } 01372 01373 01374 /** 01375 * @brief Format DISCONNECT packet 01376 * @param[in] context Pointer to the MQTT client context 01377 * @return Error code 01378 **/ 01379 01380 error_t mqttClientFormatDisconnect(MqttClientContext *context) 01381 { 01382 error_t error; 01383 size_t n; 01384 01385 //The fixed header will be encoded in reverse order 01386 n = MQTT_MAX_HEADER_SIZE; 01387 01388 //The DISCONNECT packet does not contain any variable header nor payload 01389 error = mqttSerializeHeader(context->buffer, &n, MQTT_PACKET_TYPE_DISCONNECT, 01390 FALSE, MQTT_QOS_LEVEL_0, FALSE, 0); 01391 01392 //Failed to serialize fixed header? 01393 if(error) 01394 return error; 01395 01396 //Point to the first byte of the MQTT packet 01397 context->packet = context->buffer + n; 01398 //Calculate the length of the MQTT packet 01399 context->packetLen = MQTT_MAX_HEADER_SIZE - n; 01400 01401 //Successful processing 01402 return NO_ERROR; 01403 } 01404 01405 #endif 01406
Generated on Tue Jul 12 2022 17:10:15 by
