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

Fork of Cayenne-MQTT-mbed by myDevicesIoT

Committer:
jburhenn
Date:
Fri Oct 07 17:21:45 2016 +0000
Revision:
0:09ef59d2d0f7
Child:
22:0dbabcc6e7b2
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jburhenn 0:09ef59d2d0f7 1 /*******************************************************************************
jburhenn 0:09ef59d2d0f7 2 * Copyright (c) 2014 IBM Corp.
jburhenn 0:09ef59d2d0f7 3 *
jburhenn 0:09ef59d2d0f7 4 * All rights reserved. This program and the accompanying materials
jburhenn 0:09ef59d2d0f7 5 * are made available under the terms of the Eclipse Public License v1.0
jburhenn 0:09ef59d2d0f7 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
jburhenn 0:09ef59d2d0f7 7 *
jburhenn 0:09ef59d2d0f7 8 * The Eclipse Public License is available at
jburhenn 0:09ef59d2d0f7 9 * http://www.eclipse.org/legal/epl-v10.html
jburhenn 0:09ef59d2d0f7 10 * and the Eclipse Distribution License is available at
jburhenn 0:09ef59d2d0f7 11 * http://www.eclipse.org/org/documents/edl-v10.php.
jburhenn 0:09ef59d2d0f7 12 *
jburhenn 0:09ef59d2d0f7 13 * Contributors:
jburhenn 0:09ef59d2d0f7 14 * Ian Craggs - initial API and implementation and/or initial documentation
jburhenn 0:09ef59d2d0f7 15 *******************************************************************************/
jburhenn 0:09ef59d2d0f7 16
jburhenn 0:09ef59d2d0f7 17 #include "MQTTPacket.h"
jburhenn 0:09ef59d2d0f7 18
jburhenn 0:09ef59d2d0f7 19 #include <string.h>
jburhenn 0:09ef59d2d0f7 20
jburhenn 0:09ef59d2d0f7 21 /**
jburhenn 0:09ef59d2d0f7 22 * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
jburhenn 0:09ef59d2d0f7 23 * @param options the options to be used to build the connect packet
jburhenn 0:09ef59d2d0f7 24 * @return the length of buffer needed to contain the serialized version of the packet
jburhenn 0:09ef59d2d0f7 25 */
jburhenn 0:09ef59d2d0f7 26 int MQTTSerialize_connectLength(MQTTPacket_connectData* options)
jburhenn 0:09ef59d2d0f7 27 {
jburhenn 0:09ef59d2d0f7 28 int len = 0;
jburhenn 0:09ef59d2d0f7 29
jburhenn 0:09ef59d2d0f7 30
jburhenn 0:09ef59d2d0f7 31 if (options->MQTTVersion == 3)
jburhenn 0:09ef59d2d0f7 32 len = 12; /* variable depending on MQTT or MQIsdp */
jburhenn 0:09ef59d2d0f7 33 else if (options->MQTTVersion == 4)
jburhenn 0:09ef59d2d0f7 34 len = 10;
jburhenn 0:09ef59d2d0f7 35
jburhenn 0:09ef59d2d0f7 36 len += MQTTstrlen(options->clientID)+2;
jburhenn 0:09ef59d2d0f7 37 if (options->willFlag)
jburhenn 0:09ef59d2d0f7 38 len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2;
jburhenn 0:09ef59d2d0f7 39 if (options->username.cstring || options->username.lenstring.data)
jburhenn 0:09ef59d2d0f7 40 len += MQTTstrlen(options->username)+2;
jburhenn 0:09ef59d2d0f7 41 if (options->password.cstring || options->password.lenstring.data)
jburhenn 0:09ef59d2d0f7 42 len += MQTTstrlen(options->password)+2;
jburhenn 0:09ef59d2d0f7 43
jburhenn 0:09ef59d2d0f7 44 return len;
jburhenn 0:09ef59d2d0f7 45 }
jburhenn 0:09ef59d2d0f7 46
jburhenn 0:09ef59d2d0f7 47
jburhenn 0:09ef59d2d0f7 48 /**
jburhenn 0:09ef59d2d0f7 49 * Serializes the connect options into the buffer.
jburhenn 0:09ef59d2d0f7 50 * @param buf the buffer into which the packet will be serialized
jburhenn 0:09ef59d2d0f7 51 * @param len the length in bytes of the supplied buffer
jburhenn 0:09ef59d2d0f7 52 * @param options the options to be used to build the connect packet
jburhenn 0:09ef59d2d0f7 53 * @return serialized length, or error if 0
jburhenn 0:09ef59d2d0f7 54 */
jburhenn 0:09ef59d2d0f7 55 int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options)
jburhenn 0:09ef59d2d0f7 56 {
jburhenn 0:09ef59d2d0f7 57 unsigned char *ptr = buf;
jburhenn 0:09ef59d2d0f7 58 MQTTHeader header = {0};
jburhenn 0:09ef59d2d0f7 59 MQTTConnectFlags flags = {0};
jburhenn 0:09ef59d2d0f7 60 int len = 0;
jburhenn 0:09ef59d2d0f7 61 int rc = -1;
jburhenn 0:09ef59d2d0f7 62
jburhenn 0:09ef59d2d0f7 63 if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
jburhenn 0:09ef59d2d0f7 64 {
jburhenn 0:09ef59d2d0f7 65 rc = MQTTPACKET_BUFFER_TOO_SHORT;
jburhenn 0:09ef59d2d0f7 66 goto exit;
jburhenn 0:09ef59d2d0f7 67 }
jburhenn 0:09ef59d2d0f7 68
jburhenn 0:09ef59d2d0f7 69 header.byte = 0;
jburhenn 0:09ef59d2d0f7 70 header.bits.type = CONNECT_MSG;
jburhenn 0:09ef59d2d0f7 71 writeChar(&ptr, header.byte); /* write header */
jburhenn 0:09ef59d2d0f7 72
jburhenn 0:09ef59d2d0f7 73 ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
jburhenn 0:09ef59d2d0f7 74
jburhenn 0:09ef59d2d0f7 75 if (options->MQTTVersion == 4)
jburhenn 0:09ef59d2d0f7 76 {
jburhenn 0:09ef59d2d0f7 77 writeCString(&ptr, "MQTT");
jburhenn 0:09ef59d2d0f7 78 writeChar(&ptr, (char) 4);
jburhenn 0:09ef59d2d0f7 79 }
jburhenn 0:09ef59d2d0f7 80 else
jburhenn 0:09ef59d2d0f7 81 {
jburhenn 0:09ef59d2d0f7 82 writeCString(&ptr, "MQIsdp");
jburhenn 0:09ef59d2d0f7 83 writeChar(&ptr, (char) 3);
jburhenn 0:09ef59d2d0f7 84 }
jburhenn 0:09ef59d2d0f7 85
jburhenn 0:09ef59d2d0f7 86 flags.all = 0;
jburhenn 0:09ef59d2d0f7 87 flags.bits.cleansession = options->cleansession;
jburhenn 0:09ef59d2d0f7 88 flags.bits.will = (options->willFlag) ? 1 : 0;
jburhenn 0:09ef59d2d0f7 89 if (flags.bits.will)
jburhenn 0:09ef59d2d0f7 90 {
jburhenn 0:09ef59d2d0f7 91 flags.bits.willQoS = options->will.qos;
jburhenn 0:09ef59d2d0f7 92 flags.bits.willRetain = options->will.retained;
jburhenn 0:09ef59d2d0f7 93 }
jburhenn 0:09ef59d2d0f7 94
jburhenn 0:09ef59d2d0f7 95 if (options->username.cstring || options->username.lenstring.data)
jburhenn 0:09ef59d2d0f7 96 flags.bits.username = 1;
jburhenn 0:09ef59d2d0f7 97 if (options->password.cstring || options->password.lenstring.data)
jburhenn 0:09ef59d2d0f7 98 flags.bits.password = 1;
jburhenn 0:09ef59d2d0f7 99
jburhenn 0:09ef59d2d0f7 100 writeChar(&ptr, flags.all);
jburhenn 0:09ef59d2d0f7 101 writeInt(&ptr, options->keepAliveInterval);
jburhenn 0:09ef59d2d0f7 102 writeMQTTString(&ptr, options->clientID);
jburhenn 0:09ef59d2d0f7 103 if (options->willFlag)
jburhenn 0:09ef59d2d0f7 104 {
jburhenn 0:09ef59d2d0f7 105 writeMQTTString(&ptr, options->will.topicName);
jburhenn 0:09ef59d2d0f7 106 writeMQTTString(&ptr, options->will.message);
jburhenn 0:09ef59d2d0f7 107 }
jburhenn 0:09ef59d2d0f7 108 if (flags.bits.username)
jburhenn 0:09ef59d2d0f7 109 writeMQTTString(&ptr, options->username);
jburhenn 0:09ef59d2d0f7 110 if (flags.bits.password)
jburhenn 0:09ef59d2d0f7 111 writeMQTTString(&ptr, options->password);
jburhenn 0:09ef59d2d0f7 112
jburhenn 0:09ef59d2d0f7 113 rc = ptr - buf;
jburhenn 0:09ef59d2d0f7 114
jburhenn 0:09ef59d2d0f7 115 exit:
jburhenn 0:09ef59d2d0f7 116 return rc;
jburhenn 0:09ef59d2d0f7 117 }
jburhenn 0:09ef59d2d0f7 118
jburhenn 0:09ef59d2d0f7 119
jburhenn 0:09ef59d2d0f7 120 /**
jburhenn 0:09ef59d2d0f7 121 * Deserializes the supplied (wire) buffer into connack data - return code
jburhenn 0:09ef59d2d0f7 122 * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
jburhenn 0:09ef59d2d0f7 123 * @param connack_rc returned integer value of the connack return code
jburhenn 0:09ef59d2d0f7 124 * @param buf the raw buffer data, of the correct length determined by the remaining length field
jburhenn 0:09ef59d2d0f7 125 * @param len the length in bytes of the data in the supplied buffer
jburhenn 0:09ef59d2d0f7 126 * @return error code. 1 is success, 0 is failure
jburhenn 0:09ef59d2d0f7 127 */
jburhenn 0:09ef59d2d0f7 128 int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen)
jburhenn 0:09ef59d2d0f7 129 {
jburhenn 0:09ef59d2d0f7 130 MQTTHeader header = {0};
jburhenn 0:09ef59d2d0f7 131 unsigned char* curdata = buf;
jburhenn 0:09ef59d2d0f7 132 unsigned char* enddata = NULL;
jburhenn 0:09ef59d2d0f7 133 int rc = 0;
jburhenn 0:09ef59d2d0f7 134 int mylen;
jburhenn 0:09ef59d2d0f7 135 MQTTConnackFlags flags = {0};
jburhenn 0:09ef59d2d0f7 136
jburhenn 0:09ef59d2d0f7 137 header.byte = readChar(&curdata);
jburhenn 0:09ef59d2d0f7 138 if (header.bits.type != CONNACK_MSG)
jburhenn 0:09ef59d2d0f7 139 goto exit;
jburhenn 0:09ef59d2d0f7 140
jburhenn 0:09ef59d2d0f7 141 curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
jburhenn 0:09ef59d2d0f7 142 enddata = curdata + mylen;
jburhenn 0:09ef59d2d0f7 143 if (enddata - curdata < 2)
jburhenn 0:09ef59d2d0f7 144 goto exit;
jburhenn 0:09ef59d2d0f7 145
jburhenn 0:09ef59d2d0f7 146 flags.all = readChar(&curdata);
jburhenn 0:09ef59d2d0f7 147 *sessionPresent = flags.bits.sessionpresent;
jburhenn 0:09ef59d2d0f7 148 *connack_rc = readChar(&curdata);
jburhenn 0:09ef59d2d0f7 149
jburhenn 0:09ef59d2d0f7 150 rc = 1;
jburhenn 0:09ef59d2d0f7 151 exit:
jburhenn 0:09ef59d2d0f7 152 return rc;
jburhenn 0:09ef59d2d0f7 153 }
jburhenn 0:09ef59d2d0f7 154
jburhenn 0:09ef59d2d0f7 155
jburhenn 0:09ef59d2d0f7 156 /**
jburhenn 0:09ef59d2d0f7 157 * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
jburhenn 0:09ef59d2d0f7 158 * @param buf the buffer into which the packet will be serialized
jburhenn 0:09ef59d2d0f7 159 * @param buflen the length in bytes of the supplied buffer, to avoid overruns
jburhenn 0:09ef59d2d0f7 160 * @param packettype the message type
jburhenn 0:09ef59d2d0f7 161 * @return serialized length, or error if 0
jburhenn 0:09ef59d2d0f7 162 */
jburhenn 0:09ef59d2d0f7 163 int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype)
jburhenn 0:09ef59d2d0f7 164 {
jburhenn 0:09ef59d2d0f7 165 MQTTHeader header = {0};
jburhenn 0:09ef59d2d0f7 166 int rc = -1;
jburhenn 0:09ef59d2d0f7 167 unsigned char *ptr = buf;
jburhenn 0:09ef59d2d0f7 168
jburhenn 0:09ef59d2d0f7 169 if (buflen < 2)
jburhenn 0:09ef59d2d0f7 170 {
jburhenn 0:09ef59d2d0f7 171 rc = MQTTPACKET_BUFFER_TOO_SHORT;
jburhenn 0:09ef59d2d0f7 172 goto exit;
jburhenn 0:09ef59d2d0f7 173 }
jburhenn 0:09ef59d2d0f7 174 header.byte = 0;
jburhenn 0:09ef59d2d0f7 175 header.bits.type = packettype;
jburhenn 0:09ef59d2d0f7 176 writeChar(&ptr, header.byte); /* write header */
jburhenn 0:09ef59d2d0f7 177
jburhenn 0:09ef59d2d0f7 178 ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
jburhenn 0:09ef59d2d0f7 179 rc = ptr - buf;
jburhenn 0:09ef59d2d0f7 180 exit:
jburhenn 0:09ef59d2d0f7 181 return rc;
jburhenn 0:09ef59d2d0f7 182 }
jburhenn 0:09ef59d2d0f7 183
jburhenn 0:09ef59d2d0f7 184
jburhenn 0:09ef59d2d0f7 185 /**
jburhenn 0:09ef59d2d0f7 186 * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
jburhenn 0:09ef59d2d0f7 187 * @param buf the buffer into which the packet will be serialized
jburhenn 0:09ef59d2d0f7 188 * @param buflen the length in bytes of the supplied buffer, to avoid overruns
jburhenn 0:09ef59d2d0f7 189 * @return serialized length, or error if 0
jburhenn 0:09ef59d2d0f7 190 */
jburhenn 0:09ef59d2d0f7 191 int MQTTSerialize_disconnect(unsigned char* buf, int buflen)
jburhenn 0:09ef59d2d0f7 192 {
jburhenn 0:09ef59d2d0f7 193 return MQTTSerialize_zero(buf, buflen, DISCONNECT_MSG);
jburhenn 0:09ef59d2d0f7 194 }
jburhenn 0:09ef59d2d0f7 195
jburhenn 0:09ef59d2d0f7 196
jburhenn 0:09ef59d2d0f7 197 /**
jburhenn 0:09ef59d2d0f7 198 * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
jburhenn 0:09ef59d2d0f7 199 * @param buf the buffer into which the packet will be serialized
jburhenn 0:09ef59d2d0f7 200 * @param buflen the length in bytes of the supplied buffer, to avoid overruns
jburhenn 0:09ef59d2d0f7 201 * @return serialized length, or error if 0
jburhenn 0:09ef59d2d0f7 202 */
jburhenn 0:09ef59d2d0f7 203 int MQTTSerialize_pingreq(unsigned char* buf, int buflen)
jburhenn 0:09ef59d2d0f7 204 {
jburhenn 0:09ef59d2d0f7 205 return MQTTSerialize_zero(buf, buflen, PINGREQ_MSG);
jburhenn 0:09ef59d2d0f7 206 }