Basic C library for MQTT packet serialization and deserialization

Dependents:   MQTT MQTT MQTT MQTT ... more

Fork of MQTTPacket by MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MQTTConnectClient.c Source File

MQTTConnectClient.c

00001 /*******************************************************************************
00002  * Copyright (c) 2014 IBM Corp.
00003  *
00004  * All rights reserved. This program and the accompanying materials
00005  * are made available under the terms of the Eclipse Public License v1.0
00006  * and Eclipse Distribution License v1.0 which accompany this distribution.
00007  *
00008  * The Eclipse Public License is available at
00009  *    http://www.eclipse.org/legal/epl-v10.html
00010  * and the Eclipse Distribution License is available at
00011  *   http://www.eclipse.org/org/documents/edl-v10.php.
00012  *
00013  * Contributors:
00014  *    Ian Craggs - initial API and implementation and/or initial documentation
00015  *******************************************************************************/
00016 
00017 #include "MQTTPacket.h"
00018 #include "StackTrace.h"
00019 
00020 #include <string.h>
00021 
00022 /**
00023   * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
00024   * @param options the options to be used to build the connect packet
00025   * @return the length of buffer needed to contain the serialized version of the packet
00026   */
00027 int MQTTSerialize_connectLength(MQTTPacket_connectData* options)
00028 {
00029     int len = 0;
00030 
00031     FUNC_ENTRY;
00032 
00033     if (options->MQTTVersion == 3)
00034         len = 12; /* variable depending on MQTT or MQIsdp */
00035     else if (options->MQTTVersion == 4)
00036         len = 10;
00037 
00038     len += MQTTstrlen(options->clientID)+2;
00039     if (options->willFlag)
00040         len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2;
00041     if (options->username.cstring || options->username.lenstring.data)
00042         len += MQTTstrlen(options->username)+2;
00043     if (options->password.cstring || options->password.lenstring.data)
00044         len += MQTTstrlen(options->password)+2;
00045 
00046     FUNC_EXIT_RC(len);
00047     return len;
00048 }
00049 
00050 
00051 /**
00052   * Serializes the connect options into the buffer.
00053   * @param buf the buffer into which the packet will be serialized
00054   * @param len the length in bytes of the supplied buffer
00055   * @param options the options to be used to build the connect packet
00056   * @return serialized length, or error if 0
00057   */
00058 int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options)
00059 {
00060     unsigned char *ptr = buf;
00061     MQTTHeader header = {0};
00062     MQTTConnectFlags flags = {0};
00063     int len = 0;
00064     int rc = -1;
00065 
00066     FUNC_ENTRY;
00067     if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
00068     {
00069         rc = MQTTPACKET_BUFFER_TOO_SHORT;
00070         goto exit;
00071     }
00072 
00073     header.byte = 0;
00074     header.bits.type = CONNECT;
00075     writeChar(&ptr, header.byte); /* write header */
00076 
00077     ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
00078 
00079     if (options->MQTTVersion == 4)
00080     {
00081         writeCString(&ptr, "MQTT");
00082         writeChar(&ptr, (char) 4);
00083     }
00084     else
00085     {
00086         writeCString(&ptr, "MQIsdp");
00087         writeChar(&ptr, (char) 3);
00088     }
00089 
00090     flags.all = 0;
00091     flags.bits.cleansession = options->cleansession;
00092     flags.bits.will = (options->willFlag) ? 1 : 0;
00093     if (flags.bits.will)
00094     {
00095         flags.bits.willQoS = options->will.qos;
00096         flags.bits.willRetain = options->will.retained;
00097     }
00098 
00099     if (options->username.cstring || options->username.lenstring.data)
00100         flags.bits.username = 1;
00101     if (options->password.cstring || options->password.lenstring.data)
00102         flags.bits.password = 1;
00103 
00104     writeChar(&ptr, flags.all);
00105     writeInt(&ptr, options->keepAliveInterval);
00106     writeMQTTString(&ptr, options->clientID);
00107     if (options->willFlag)
00108     {
00109         writeMQTTString(&ptr, options->will.topicName);
00110         writeMQTTString(&ptr, options->will.message);
00111     }
00112     if (flags.bits.username)
00113         writeMQTTString(&ptr, options->username);
00114     if (flags.bits.password)
00115         writeMQTTString(&ptr, options->password);
00116 
00117     rc = ptr - buf;
00118 
00119     exit: FUNC_EXIT_RC(rc);
00120     return rc;
00121 }
00122 
00123 
00124 /**
00125   * Deserializes the supplied (wire) buffer into connack data - return code
00126   * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
00127   * @param connack_rc returned integer value of the connack return code
00128   * @param buf the raw buffer data, of the correct length determined by the remaining length field
00129   * @param len the length in bytes of the data in the supplied buffer
00130   * @return error code.  1 is success, 0 is failure
00131   */
00132 int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen)
00133 {
00134     MQTTHeader header = {0};
00135     unsigned char* curdata = buf;
00136     unsigned char* enddata = NULL;
00137     int rc = 0;
00138     int mylen;
00139     MQTTConnackFlags flags = {0};
00140 
00141     FUNC_ENTRY;
00142     header.byte = readChar(&curdata);
00143     if (header.bits.type != CONNACK)
00144         goto exit;
00145 
00146     curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
00147     enddata = curdata + mylen;
00148     if (enddata - curdata < 2)
00149         goto exit;
00150 
00151     flags.all = readChar(&curdata);
00152     *sessionPresent = flags.bits.sessionpresent;
00153     *connack_rc = readChar(&curdata);
00154 
00155     rc = 1;
00156 exit:
00157     FUNC_EXIT_RC(rc);
00158     return rc;
00159 }
00160 
00161 
00162 
00163 /**
00164   * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
00165   * @param buf the buffer into which the packet will be serialized
00166   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00167   * @param packettype the message type
00168   * @return serialized length, or error if 0
00169   */
00170 int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype)
00171 {
00172     MQTTHeader header = {0};
00173     int rc = -1;
00174     unsigned char *ptr = buf;
00175 
00176     FUNC_ENTRY;
00177     if (buflen < 2)
00178     {
00179         rc = MQTTPACKET_BUFFER_TOO_SHORT;
00180         goto exit;
00181     }
00182     header.byte = 0;
00183     header.bits.type = packettype;
00184     writeChar(&ptr, header.byte); /* write header */
00185 
00186     ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
00187     rc = ptr - buf;
00188 exit:
00189     FUNC_EXIT_RC(rc);
00190     return rc;
00191 }
00192 
00193 
00194 /**
00195   * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
00196   * @param buf the buffer into which the packet will be serialized
00197   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00198   * @return serialized length, or error if 0
00199   */
00200 int MQTTSerialize_disconnect(unsigned char* buf, int buflen)
00201 {
00202     return MQTTSerialize_zero(buf, buflen, DISCONNECT);
00203 }
00204 
00205 
00206 /**
00207   * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
00208   * @param buf the buffer into which the packet will be serialized
00209   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00210   * @return serialized length, or error if 0
00211   */
00212 int MQTTSerialize_pingreq(unsigned char* buf, int buflen)
00213 {
00214     return MQTTSerialize_zero(buf, buflen, PINGREQ);
00215 }