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