Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mqtt_client_packet.c Source File

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