The Cayenne MQTT mbed Library provides functions to easily connect to the Cayenne IoT project builder.

Dependents:   Cayenne-ESP8266Interface Cayenne-WIZnet_Library Cayenne-WIZnetInterface Cayenne-X-NUCLEO-IDW01M1 ... more

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 
00019 #include <string.h>
00020 
00021 /**
00022   * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
00023   * @param options the options to be used to build the connect packet
00024   * @return the length of buffer needed to contain the serialized version of the packet
00025   */
00026 size_t MQTTSerialize_connectLength(MQTTPacket_connectData* options)
00027 {
00028     size_t len = 0;
00029 
00030 
00031     if (options->MQTTVersion == 3)
00032         len = 12; /* variable depending on MQTT or MQIsdp */
00033     else if (options->MQTTVersion == 4)
00034         len = 10;
00035 
00036     len += MQTTstrlen(options->clientID)+2;
00037     if (options->willFlag)
00038         len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2;
00039     if (options->username.cstring || options->username.lenstring.data)
00040         len += MQTTstrlen(options->username)+2;
00041     if (options->password.cstring || options->password.lenstring.data)
00042         len += MQTTstrlen(options->password)+2;
00043 
00044     return len;
00045 }
00046 
00047 
00048 /**
00049   * Serializes the connect options into the buffer.
00050   * @param buf the buffer into which the packet will be serialized
00051   * @param len the length in bytes of the supplied buffer
00052   * @param options the options to be used to build the connect packet
00053   * @return serialized length, or error if 0
00054   */
00055 int MQTTSerialize_connect(unsigned char* buf, size_t buflen, MQTTPacket_connectData* options)
00056 {
00057     unsigned char *ptr = buf;
00058     MQTTHeader header = {0};
00059     MQTTConnectFlags flags = {0};
00060     size_t len = 0;
00061     int rc = -1;
00062 
00063     if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
00064     {
00065         rc = MQTTPACKET_BUFFER_TOO_SHORT;
00066         goto exit;
00067     }
00068 
00069     header.byte = 0;
00070     header.bits.type = CONNECT_MSG;
00071     writeChar(&ptr, header.byte); /* write header */
00072 
00073     ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
00074 
00075     if (options->MQTTVersion == 4)
00076     {
00077         writeCString(&ptr, "MQTT");
00078         writeChar(&ptr, (char) 4);
00079     }
00080     else
00081     {
00082         writeCString(&ptr, "MQIsdp");
00083         writeChar(&ptr, (char) 3);
00084     }
00085 
00086     flags.all = 0;
00087     flags.bits.cleansession = options->cleansession;
00088     flags.bits.will = (options->willFlag) ? 1 : 0;
00089     if (flags.bits.will)
00090     {
00091         flags.bits.willQoS = options->will.qos;
00092         flags.bits.willRetain = options->will.retained;
00093     }
00094 
00095     if (options->username.cstring || options->username.lenstring.data)
00096         flags.bits.username = 1;
00097     if (options->password.cstring || options->password.lenstring.data)
00098         flags.bits.password = 1;
00099 
00100     writeChar(&ptr, flags.all);
00101     writeInt(&ptr, options->keepAliveInterval);
00102     writeMQTTString(&ptr, options->clientID);
00103     if (options->willFlag)
00104     {
00105         writeMQTTString(&ptr, options->will.topicName);
00106         writeMQTTString(&ptr, options->will.message);
00107     }
00108     if (flags.bits.username)
00109         writeMQTTString(&ptr, options->username);
00110     if (flags.bits.password)
00111         writeMQTTString(&ptr, options->password);
00112 
00113     rc = (int)(ptr - buf);
00114 
00115     exit:
00116     return rc;
00117 }
00118 
00119 
00120 /**
00121   * Deserializes the supplied (wire) buffer into connack data - return code
00122   * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
00123   * @param connack_rc returned integer value of the connack return code
00124   * @param buf the raw buffer data, of the correct length determined by the remaining length field
00125   * @param len the length in bytes of the data in the supplied buffer
00126   * @return error code.  1 is success, 0 is failure
00127   */
00128 int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, size_t buflen)
00129 {
00130     MQTTHeader header = {0};
00131     unsigned char* curdata = buf;
00132     unsigned char* enddata = NULL;
00133     int rc = 0;
00134     int mylen;
00135     MQTTConnackFlags flags = {0};
00136 
00137     header.byte = readChar(&curdata);
00138     if (header.bits.type != CONNACK_MSG)
00139         goto exit;
00140 
00141     curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
00142     enddata = curdata + mylen;
00143     if (enddata - curdata < 2)
00144         goto exit;
00145 
00146     flags.all = readChar(&curdata);
00147     *sessionPresent = flags.bits.sessionpresent;
00148     *connack_rc = readChar(&curdata);
00149 
00150     rc = 1;
00151 exit:
00152     return rc;
00153 }
00154 
00155 
00156 /**
00157   * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
00158   * @param buf the buffer into which the packet will be serialized
00159   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00160   * @param packettype the message type
00161   * @return serialized length, or error if 0
00162   */
00163 int MQTTSerialize_zero(unsigned char* buf, size_t buflen, unsigned char packettype)
00164 {
00165     MQTTHeader header = {0};
00166     int rc = -1;
00167     unsigned char *ptr = buf;
00168 
00169     if (buflen < 2)
00170     {
00171         rc = MQTTPACKET_BUFFER_TOO_SHORT;
00172         goto exit;
00173     }
00174     header.byte = 0;
00175     header.bits.type = packettype;
00176     writeChar(&ptr, header.byte); /* write header */
00177 
00178     ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
00179     rc = (int)(ptr - buf);
00180 exit:
00181     return rc;
00182 }
00183 
00184 
00185 /**
00186   * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
00187   * @param buf the buffer into which the packet will be serialized
00188   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00189   * @return serialized length, or error if 0
00190   */
00191 int MQTTSerialize_disconnect(unsigned char* buf, size_t buflen)
00192 {
00193     return MQTTSerialize_zero(buf, buflen, DISCONNECT_MSG);
00194 }
00195 
00196 
00197 /**
00198   * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
00199   * @param buf the buffer into which the packet will be serialized
00200   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00201   * @return serialized length, or error if 0
00202   */
00203 int MQTTSerialize_pingreq(unsigned char* buf, size_t buflen)
00204 {
00205     return MQTTSerialize_zero(buf, buflen, PINGREQ_MSG);
00206 }