V.06 11/3

Dependencies:   FT6206 SDFileSystem SPI_TFT_ILI9341 TFT_fonts

Fork of ATT_AWS_IoT_demo by attiot

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MQTTConnectClient.cpp Source File

MQTTConnectClient.cpp

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   * @param the length of buffer needed to contain the serialized version of the packet
00026   * @return MQTTReturnCode indicating function execution status
00027   */
00028 size_t MQTTSerialize_GetConnectLength(MQTTPacket_connectData *options) {
00029         size_t len = 0;
00030     FUNC_ENTRY;
00031 
00032     /* variable depending on MQTT or MQIsdp */
00033     if(3 == options->MQTTVersion) {
00034         len = 12;
00035     } else if(4 == options->MQTTVersion) {
00036         len = 10;
00037     }
00038 
00039     len += MQTTstrlen(options->clientID) + 2;
00040 
00041     if(options->willFlag) {
00042         len += MQTTstrlen(options->will.topicName) + 2 + MQTTstrlen(options->will.message) + 2;
00043     }
00044 
00045     if(options->username.cstring || options->username.lenstring.data) {
00046         len += MQTTstrlen(options->username) + 2;
00047     }
00048 
00049     if(options->password.cstring || options->password.lenstring.data) {
00050         len += MQTTstrlen(options->password) + 2;
00051     }
00052 
00053     FUNC_EXIT_RC(len);
00054     return len;
00055 }
00056 
00057 /**
00058   * Serializes the connect options into the buffer.
00059   * @param buf the buffer into which the packet will be serialized
00060   * @param len the length in bytes of the supplied buffer
00061   * @param options the options to be used to build the connect packet
00062   * @param serialized length
00063   * @return MQTTReturnCode indicating function execution status
00064   */
00065 MQTTReturnCode MQTTSerialize_connect(unsigned char *buf, size_t buflen,
00066                                      MQTTPacket_connectData *options,
00067                                      uint32_t *serialized_len) {
00068         unsigned char *ptr = buf;
00069         MQTTHeader header = {0};
00070         MQTTConnectFlags flags = {0};
00071         size_t len = 0;
00072         MQTTReturnCode rc = MQTTPacket_InitHeader(&header, CONNECT, QOS0, 0, 0);
00073 
00074     FUNC_ENTRY;
00075     if(NULL == buf || NULL == options || NULL == serialized_len) {
00076         FUNC_EXIT_RC(MQTT_NULL_VALUE_ERROR);
00077         return MQTT_NULL_VALUE_ERROR;
00078     }
00079 
00080     len = MQTTSerialize_GetConnectLength(options);
00081     if(MQTTPacket_len(len) > buflen) {
00082         FUNC_EXIT_RC(MQTTPACKET_BUFFER_TOO_SHORT);
00083         return MQTTPACKET_BUFFER_TOO_SHORT;
00084     }
00085 
00086     if(SUCCESS != rc) {
00087         FUNC_EXIT_RC(rc);
00088         return rc;
00089     }
00090 
00091     writeChar(&ptr, header.byte); /* write header */
00092 
00093     ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
00094 
00095     if(4 == options->MQTTVersion) {
00096         writeCString(&ptr, "MQTT");
00097         writeChar(&ptr, (char) 4);
00098     } else {
00099         writeCString(&ptr, "MQIsdp");
00100         writeChar(&ptr, (char) 3);
00101     }
00102 
00103     flags.all = 0;
00104     flags.bits.cleansession = (options->cleansession) ? 1 : 0;
00105     flags.bits.will = (options->willFlag) ? 1 : 0;
00106     if(flags.bits.will) {
00107         flags.bits.willQoS = options->will.qos;
00108         flags.bits.willRetain = (options->will.retained) ? 1 : 0;
00109     }
00110 
00111     if(options->username.cstring || options->username.lenstring.data) {
00112         flags.bits.username = 1;
00113     }
00114 
00115     if(options->password.cstring || options->password.lenstring.data) {
00116         flags.bits.password = 1;
00117     }
00118 
00119     writeChar(&ptr, flags.all);
00120     writeInt(&ptr, options->keepAliveInterval);
00121     writeMQTTString(&ptr, options->clientID);
00122     if(options->willFlag) {
00123         writeMQTTString(&ptr, options->will.topicName);
00124         writeMQTTString(&ptr, options->will.message);
00125     }
00126 
00127     if(flags.bits.username) {
00128         writeMQTTString(&ptr, options->username);
00129     }
00130 
00131     if(flags.bits.password) {
00132         writeMQTTString(&ptr, options->password);
00133     }
00134 
00135     *serialized_len = (uint32_t)(ptr - buf);
00136 
00137     FUNC_EXIT_RC(SUCCESS);
00138     return SUCCESS;
00139 }
00140 
00141 /**
00142   * Deserializes the supplied (wire) buffer into connack data - return code
00143   * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
00144   * @param connack_rc returned integer value of the connack return code
00145   * @param buf the raw buffer data, of the correct length determined by the remaining length field
00146   * @param buflen the length in bytes of the data in the supplied buffer
00147   * @return MQTTReturnCode indicating function execution status
00148   */
00149 MQTTReturnCode MQTTDeserialize_connack(unsigned char *sessionPresent,
00150                                        MQTTReturnCode *connack_rc,
00151                                        unsigned char *buf, size_t buflen) {
00152         MQTTHeader header = {0};
00153         unsigned char *curdata = buf;
00154         unsigned char *enddata = NULL;
00155         MQTTReturnCode rc = FAILURE;
00156         uint32_t decodedLen = 0;
00157         uint32_t readBytesLen = 0;
00158         MQTTConnackFlags flags = {0};
00159         unsigned char connack_rc_char;
00160     FUNC_ENTRY;
00161     if(NULL == sessionPresent || NULL == connack_rc || NULL == buf) {
00162         FUNC_EXIT_RC(MQTT_NULL_VALUE_ERROR);
00163         return MQTT_NULL_VALUE_ERROR;
00164     }
00165 
00166     /* CONNACK header size is fixed at two bytes for fixed and 2 bytes for variable,
00167      * using that as minimum size
00168      * MQTT v3.1.1 Specification 3.2.1 */
00169     if(4 > buflen) {
00170         FUNC_EXIT_RC(MQTTPACKET_BUFFER_TOO_SHORT);
00171         return MQTTPACKET_BUFFER_TOO_SHORT;
00172     }
00173 
00174     header.byte = readChar(&curdata);
00175     if(CONNACK != header.bits.type) {
00176         FUNC_EXIT_RC(FAILURE);
00177         return FAILURE;
00178     }
00179 
00180     /* read remaining length */
00181     rc = MQTTPacket_decodeBuf(curdata, &decodedLen, &readBytesLen);
00182     if(SUCCESS != rc) {
00183         FUNC_EXIT_RC(rc);
00184         return rc;
00185     }
00186 
00187     curdata += (readBytesLen);
00188     enddata = curdata + decodedLen;
00189     if(enddata - curdata < 2) {
00190         FUNC_EXIT_RC(FAILURE);
00191         return FAILURE;
00192     }
00193 
00194     flags.all = readChar(&curdata);
00195     *sessionPresent = flags.bits.sessionpresent;
00196     
00197     connack_rc_char = readChar(&curdata);
00198     switch(connack_rc_char) {
00199         case CONNACK_CONNECTION_ACCEPTED:
00200             *connack_rc = MQTT_CONNACK_CONNECTION_ACCEPTED;
00201             break;
00202         case CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR:
00203             *connack_rc = MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
00204             break;
00205         case CONNACK_IDENTIFIER_REJECTED_ERROR:
00206             *connack_rc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR;
00207             break;
00208         case CONNACK_SERVER_UNAVAILABLE_ERROR:
00209             *connack_rc = MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR;
00210             break;
00211         case CONNACK_BAD_USERDATA_ERROR:
00212             *connack_rc = MQTT_CONNACK_BAD_USERDATA_ERROR;
00213             break;
00214         case CONNACK_NOT_AUTHORIZED_ERROR:
00215             *connack_rc = MQTT_CONNACK_NOT_AUTHORIZED_ERROR;
00216             break;
00217         default:
00218             *connack_rc = MQTT_CONNACK_UNKNOWN_ERROR;
00219             break;
00220     }
00221 
00222     FUNC_EXIT_RC(SUCCESS);
00223     return SUCCESS;
00224 }
00225 
00226 /**
00227   * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
00228   * @param buf the buffer into which the packet will be serialized
00229   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00230   * @param packettype the message type
00231   * @param serialized length
00232   * @return MQTTReturnCode indicating function execution status
00233   */
00234 MQTTReturnCode MQTTSerialize_zero(unsigned char *buf, size_t buflen,
00235                                   unsigned char packetType,
00236                                   uint32_t *serialized_length) {
00237         MQTTHeader header = {0};
00238         unsigned char *ptr = buf;
00239         MQTTReturnCode rc = MQTTPacket_InitHeader(&header, (MessageTypes)packetType, QOS0, 0, 0);
00240 
00241     FUNC_ENTRY;
00242     if(NULL == buf || NULL == serialized_length) {
00243         FUNC_EXIT_RC(MQTT_NULL_VALUE_ERROR);
00244         return MQTT_NULL_VALUE_ERROR;
00245     }
00246 
00247     /* Buffer should have at least 2 bytes for the header */
00248     if(4 > buflen) {
00249         FUNC_EXIT_RC(MQTTPACKET_BUFFER_TOO_SHORT);
00250         return MQTTPACKET_BUFFER_TOO_SHORT;
00251     }
00252 
00253     if(SUCCESS != rc) {
00254         FUNC_EXIT_RC(rc);
00255         return rc;
00256     }
00257 
00258     /* write header */
00259     writeChar(&ptr, header.byte);
00260 
00261     /* write remaining length */
00262     ptr += MQTTPacket_encode(ptr, 0);
00263     *serialized_length = (uint32_t)(ptr - buf);
00264 
00265     FUNC_EXIT_RC(SUCCESS);
00266     return SUCCESS;
00267 }
00268 
00269 
00270 /**
00271   * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
00272   * @param buf the buffer into which the packet will be serialized
00273   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00274   * @param serialized length
00275   * @return MQTTReturnCode indicating function execution status
00276   */
00277 MQTTReturnCode MQTTSerialize_disconnect(unsigned char *buf, size_t buflen,
00278                                         uint32_t *serialized_length) {
00279     return MQTTSerialize_zero(buf, buflen, DISCONNECT, serialized_length);
00280 }
00281 
00282 
00283 /**
00284   * Serializes a pingreq packet into the supplied buffer, ready for writing to a socket
00285   * @param buf the buffer into which the packet will be serialized
00286   * @param buflen the length in bytes of the supplied buffer, to avoid overruns
00287   * @param serialized length
00288   * @return MQTTReturnCode indicating function execution status
00289   */
00290 MQTTReturnCode MQTTSerialize_pingreq(unsigned char *buf, size_t buflen,
00291                                      uint32_t *serialized_length) {
00292     return MQTTSerialize_zero(buf, buflen, PINGREQ, serialized_length);
00293 }
00294 
00295