Version to make it easier to reuse without source modifications

Committer:
JMF
Date:
Tue Mar 27 17:26:35 2018 +0000
Revision:
0:5cd4781e0c88
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JMF 0:5cd4781e0c88 1 /*******************************************************************************
JMF 0:5cd4781e0c88 2 * Copyright (c) 2014 IBM Corp.
JMF 0:5cd4781e0c88 3 *
JMF 0:5cd4781e0c88 4 * All rights reserved. This program and the accompanying materials
JMF 0:5cd4781e0c88 5 * are made available under the terms of the Eclipse Public License v1.0
JMF 0:5cd4781e0c88 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
JMF 0:5cd4781e0c88 7 *
JMF 0:5cd4781e0c88 8 * The Eclipse Public License is available at
JMF 0:5cd4781e0c88 9 * http://www.eclipse.org/legal/epl-v10.html
JMF 0:5cd4781e0c88 10 * and the Eclipse Distribution License is available at
JMF 0:5cd4781e0c88 11 * http://www.eclipse.org/org/documents/edl-v10.php.
JMF 0:5cd4781e0c88 12 *
JMF 0:5cd4781e0c88 13 * Contributors:
JMF 0:5cd4781e0c88 14 * Ian Craggs - initial API and implementation and/or initial documentation
JMF 0:5cd4781e0c88 15 * Sergio R. Caprile - non-blocking packet read functions for stream transport
JMF 0:5cd4781e0c88 16 *******************************************************************************/
JMF 0:5cd4781e0c88 17
JMF 0:5cd4781e0c88 18 #include "StackTrace.h"
JMF 0:5cd4781e0c88 19 #include "MQTTPacket.h"
JMF 0:5cd4781e0c88 20
JMF 0:5cd4781e0c88 21 #include <string.h>
JMF 0:5cd4781e0c88 22
JMF 0:5cd4781e0c88 23 /**
JMF 0:5cd4781e0c88 24 * Encodes the message length according to the MQTT algorithm
JMF 0:5cd4781e0c88 25 * @param buf the buffer into which the encoded data is written
JMF 0:5cd4781e0c88 26 * @param length the length to be encoded
JMF 0:5cd4781e0c88 27 * @return the number of bytes written to buffer
JMF 0:5cd4781e0c88 28 */
JMF 0:5cd4781e0c88 29 int MQTTPacket_encode(unsigned char* buf, int length)
JMF 0:5cd4781e0c88 30 {
JMF 0:5cd4781e0c88 31 int rc = 0;
JMF 0:5cd4781e0c88 32
JMF 0:5cd4781e0c88 33 FUNC_ENTRY;
JMF 0:5cd4781e0c88 34 do
JMF 0:5cd4781e0c88 35 {
JMF 0:5cd4781e0c88 36 char d = length % 128;
JMF 0:5cd4781e0c88 37 length /= 128;
JMF 0:5cd4781e0c88 38 /* if there are more digits to encode, set the top bit of this digit */
JMF 0:5cd4781e0c88 39 if (length > 0)
JMF 0:5cd4781e0c88 40 d |= 0x80;
JMF 0:5cd4781e0c88 41 buf[rc++] = d;
JMF 0:5cd4781e0c88 42 } while (length > 0);
JMF 0:5cd4781e0c88 43 FUNC_EXIT_RC(rc);
JMF 0:5cd4781e0c88 44 return rc;
JMF 0:5cd4781e0c88 45 }
JMF 0:5cd4781e0c88 46
JMF 0:5cd4781e0c88 47
JMF 0:5cd4781e0c88 48 /**
JMF 0:5cd4781e0c88 49 * Decodes the message length according to the MQTT algorithm
JMF 0:5cd4781e0c88 50 * @param getcharfn pointer to function to read the next character from the data source
JMF 0:5cd4781e0c88 51 * @param value the decoded length returned
JMF 0:5cd4781e0c88 52 * @return the number of bytes read from the socket
JMF 0:5cd4781e0c88 53 */
JMF 0:5cd4781e0c88 54 int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value)
JMF 0:5cd4781e0c88 55 {
JMF 0:5cd4781e0c88 56 unsigned char c;
JMF 0:5cd4781e0c88 57 int multiplier = 1;
JMF 0:5cd4781e0c88 58 int len = 0;
JMF 0:5cd4781e0c88 59 #define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
JMF 0:5cd4781e0c88 60
JMF 0:5cd4781e0c88 61 FUNC_ENTRY;
JMF 0:5cd4781e0c88 62 *value = 0;
JMF 0:5cd4781e0c88 63 do
JMF 0:5cd4781e0c88 64 {
JMF 0:5cd4781e0c88 65 int rc = MQTTPACKET_READ_ERROR;
JMF 0:5cd4781e0c88 66
JMF 0:5cd4781e0c88 67 if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
JMF 0:5cd4781e0c88 68 {
JMF 0:5cd4781e0c88 69 rc = MQTTPACKET_READ_ERROR; /* bad data */
JMF 0:5cd4781e0c88 70 goto exit;
JMF 0:5cd4781e0c88 71 }
JMF 0:5cd4781e0c88 72 rc = (*getcharfn)(&c, 1);
JMF 0:5cd4781e0c88 73 if (rc != 1)
JMF 0:5cd4781e0c88 74 goto exit;
JMF 0:5cd4781e0c88 75 *value += (c & 127) * multiplier;
JMF 0:5cd4781e0c88 76 multiplier *= 128;
JMF 0:5cd4781e0c88 77 } while ((c & 128) != 0);
JMF 0:5cd4781e0c88 78 exit:
JMF 0:5cd4781e0c88 79 FUNC_EXIT_RC(len);
JMF 0:5cd4781e0c88 80 return len;
JMF 0:5cd4781e0c88 81 }
JMF 0:5cd4781e0c88 82
JMF 0:5cd4781e0c88 83
JMF 0:5cd4781e0c88 84 int MQTTPacket_len(int rem_len)
JMF 0:5cd4781e0c88 85 {
JMF 0:5cd4781e0c88 86 rem_len += 1; /* header byte */
JMF 0:5cd4781e0c88 87
JMF 0:5cd4781e0c88 88 /* now remaining_length field */
JMF 0:5cd4781e0c88 89 if (rem_len < 128)
JMF 0:5cd4781e0c88 90 rem_len += 1;
JMF 0:5cd4781e0c88 91 else if (rem_len < 16384)
JMF 0:5cd4781e0c88 92 rem_len += 2;
JMF 0:5cd4781e0c88 93 else if (rem_len < 2097151)
JMF 0:5cd4781e0c88 94 rem_len += 3;
JMF 0:5cd4781e0c88 95 else
JMF 0:5cd4781e0c88 96 rem_len += 4;
JMF 0:5cd4781e0c88 97 return rem_len;
JMF 0:5cd4781e0c88 98 }
JMF 0:5cd4781e0c88 99
JMF 0:5cd4781e0c88 100
JMF 0:5cd4781e0c88 101 static unsigned char* bufptr;
JMF 0:5cd4781e0c88 102
JMF 0:5cd4781e0c88 103 int bufchar(unsigned char* c, int count)
JMF 0:5cd4781e0c88 104 {
JMF 0:5cd4781e0c88 105 int i;
JMF 0:5cd4781e0c88 106
JMF 0:5cd4781e0c88 107 for (i = 0; i < count; ++i)
JMF 0:5cd4781e0c88 108 *c = *bufptr++;
JMF 0:5cd4781e0c88 109 return count;
JMF 0:5cd4781e0c88 110 }
JMF 0:5cd4781e0c88 111
JMF 0:5cd4781e0c88 112
JMF 0:5cd4781e0c88 113 int MQTTPacket_decodeBuf(unsigned char* buf, int* value)
JMF 0:5cd4781e0c88 114 {
JMF 0:5cd4781e0c88 115 bufptr = buf;
JMF 0:5cd4781e0c88 116 return MQTTPacket_decode(bufchar, value);
JMF 0:5cd4781e0c88 117 }
JMF 0:5cd4781e0c88 118
JMF 0:5cd4781e0c88 119
JMF 0:5cd4781e0c88 120 /**
JMF 0:5cd4781e0c88 121 * Calculates an integer from two bytes read from the input buffer
JMF 0:5cd4781e0c88 122 * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
JMF 0:5cd4781e0c88 123 * @return the integer value calculated
JMF 0:5cd4781e0c88 124 */
JMF 0:5cd4781e0c88 125 int readInt(unsigned char** pptr)
JMF 0:5cd4781e0c88 126 {
JMF 0:5cd4781e0c88 127 unsigned char* ptr = *pptr;
JMF 0:5cd4781e0c88 128 int len = 256*(*ptr) + (*(ptr+1));
JMF 0:5cd4781e0c88 129 *pptr += 2;
JMF 0:5cd4781e0c88 130 return len;
JMF 0:5cd4781e0c88 131 }
JMF 0:5cd4781e0c88 132
JMF 0:5cd4781e0c88 133
JMF 0:5cd4781e0c88 134 /**
JMF 0:5cd4781e0c88 135 * Reads one character from the input buffer.
JMF 0:5cd4781e0c88 136 * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
JMF 0:5cd4781e0c88 137 * @return the character read
JMF 0:5cd4781e0c88 138 */
JMF 0:5cd4781e0c88 139 char readChar(unsigned char** pptr)
JMF 0:5cd4781e0c88 140 {
JMF 0:5cd4781e0c88 141 char c = **pptr;
JMF 0:5cd4781e0c88 142 (*pptr)++;
JMF 0:5cd4781e0c88 143 return c;
JMF 0:5cd4781e0c88 144 }
JMF 0:5cd4781e0c88 145
JMF 0:5cd4781e0c88 146
JMF 0:5cd4781e0c88 147 /**
JMF 0:5cd4781e0c88 148 * Writes one character to an output buffer.
JMF 0:5cd4781e0c88 149 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
JMF 0:5cd4781e0c88 150 * @param c the character to write
JMF 0:5cd4781e0c88 151 */
JMF 0:5cd4781e0c88 152 void writeChar(unsigned char** pptr, char c)
JMF 0:5cd4781e0c88 153 {
JMF 0:5cd4781e0c88 154 **pptr = c;
JMF 0:5cd4781e0c88 155 (*pptr)++;
JMF 0:5cd4781e0c88 156 }
JMF 0:5cd4781e0c88 157
JMF 0:5cd4781e0c88 158
JMF 0:5cd4781e0c88 159 /**
JMF 0:5cd4781e0c88 160 * Writes an integer as 2 bytes to an output buffer.
JMF 0:5cd4781e0c88 161 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
JMF 0:5cd4781e0c88 162 * @param anInt the integer to write
JMF 0:5cd4781e0c88 163 */
JMF 0:5cd4781e0c88 164 void writeInt(unsigned char** pptr, int anInt)
JMF 0:5cd4781e0c88 165 {
JMF 0:5cd4781e0c88 166 **pptr = (unsigned char)(anInt / 256);
JMF 0:5cd4781e0c88 167 (*pptr)++;
JMF 0:5cd4781e0c88 168 **pptr = (unsigned char)(anInt % 256);
JMF 0:5cd4781e0c88 169 (*pptr)++;
JMF 0:5cd4781e0c88 170 }
JMF 0:5cd4781e0c88 171
JMF 0:5cd4781e0c88 172
JMF 0:5cd4781e0c88 173 /**
JMF 0:5cd4781e0c88 174 * Writes a "UTF" string to an output buffer. Converts C string to length-delimited.
JMF 0:5cd4781e0c88 175 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
JMF 0:5cd4781e0c88 176 * @param string the C string to write
JMF 0:5cd4781e0c88 177 */
JMF 0:5cd4781e0c88 178 void writeCString(unsigned char** pptr, const char* string)
JMF 0:5cd4781e0c88 179 {
JMF 0:5cd4781e0c88 180 int len = strlen(string);
JMF 0:5cd4781e0c88 181 writeInt(pptr, len);
JMF 0:5cd4781e0c88 182 memcpy(*pptr, string, len);
JMF 0:5cd4781e0c88 183 *pptr += len;
JMF 0:5cd4781e0c88 184 }
JMF 0:5cd4781e0c88 185
JMF 0:5cd4781e0c88 186
JMF 0:5cd4781e0c88 187 int getLenStringLen(char* ptr)
JMF 0:5cd4781e0c88 188 {
JMF 0:5cd4781e0c88 189 int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
JMF 0:5cd4781e0c88 190 return len;
JMF 0:5cd4781e0c88 191 }
JMF 0:5cd4781e0c88 192
JMF 0:5cd4781e0c88 193
JMF 0:5cd4781e0c88 194 void writeMQTTString(unsigned char** pptr, MQTTString mqttstring)
JMF 0:5cd4781e0c88 195 {
JMF 0:5cd4781e0c88 196 if (mqttstring.lenstring.len > 0)
JMF 0:5cd4781e0c88 197 {
JMF 0:5cd4781e0c88 198 writeInt(pptr, mqttstring.lenstring.len);
JMF 0:5cd4781e0c88 199 memcpy(*pptr, mqttstring.lenstring.data, mqttstring.lenstring.len);
JMF 0:5cd4781e0c88 200 *pptr += mqttstring.lenstring.len;
JMF 0:5cd4781e0c88 201 }
JMF 0:5cd4781e0c88 202 else if (mqttstring.cstring)
JMF 0:5cd4781e0c88 203 writeCString(pptr, mqttstring.cstring);
JMF 0:5cd4781e0c88 204 else
JMF 0:5cd4781e0c88 205 writeInt(pptr, 0);
JMF 0:5cd4781e0c88 206 }
JMF 0:5cd4781e0c88 207
JMF 0:5cd4781e0c88 208
JMF 0:5cd4781e0c88 209 /**
JMF 0:5cd4781e0c88 210 * @param mqttstring the MQTTString structure into which the data is to be read
JMF 0:5cd4781e0c88 211 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
JMF 0:5cd4781e0c88 212 * @param enddata pointer to the end of the data: do not read beyond
JMF 0:5cd4781e0c88 213 * @return 1 if successful, 0 if not
JMF 0:5cd4781e0c88 214 */
JMF 0:5cd4781e0c88 215 int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata)
JMF 0:5cd4781e0c88 216 {
JMF 0:5cd4781e0c88 217 int rc = 0;
JMF 0:5cd4781e0c88 218
JMF 0:5cd4781e0c88 219 FUNC_ENTRY;
JMF 0:5cd4781e0c88 220 /* the first two bytes are the length of the string */
JMF 0:5cd4781e0c88 221 if (enddata - (*pptr) > 1) /* enough length to read the integer? */
JMF 0:5cd4781e0c88 222 {
JMF 0:5cd4781e0c88 223 mqttstring->lenstring.len = readInt(pptr); /* increments pptr to point past length */
JMF 0:5cd4781e0c88 224 if (&(*pptr)[mqttstring->lenstring.len] <= enddata)
JMF 0:5cd4781e0c88 225 {
JMF 0:5cd4781e0c88 226 mqttstring->lenstring.data = (char*)*pptr;
JMF 0:5cd4781e0c88 227 *pptr += mqttstring->lenstring.len;
JMF 0:5cd4781e0c88 228 rc = 1;
JMF 0:5cd4781e0c88 229 }
JMF 0:5cd4781e0c88 230 }
JMF 0:5cd4781e0c88 231 mqttstring->cstring = NULL;
JMF 0:5cd4781e0c88 232 FUNC_EXIT_RC(rc);
JMF 0:5cd4781e0c88 233 return rc;
JMF 0:5cd4781e0c88 234 }
JMF 0:5cd4781e0c88 235
JMF 0:5cd4781e0c88 236
JMF 0:5cd4781e0c88 237 /**
JMF 0:5cd4781e0c88 238 * Return the length of the MQTTstring - C string if there is one, otherwise the length delimited string
JMF 0:5cd4781e0c88 239 * @param mqttstring the string to return the length of
JMF 0:5cd4781e0c88 240 * @return the length of the string
JMF 0:5cd4781e0c88 241 */
JMF 0:5cd4781e0c88 242 int MQTTstrlen(MQTTString mqttstring)
JMF 0:5cd4781e0c88 243 {
JMF 0:5cd4781e0c88 244 int rc = 0;
JMF 0:5cd4781e0c88 245
JMF 0:5cd4781e0c88 246 if (mqttstring.cstring)
JMF 0:5cd4781e0c88 247 rc = strlen(mqttstring.cstring);
JMF 0:5cd4781e0c88 248 else
JMF 0:5cd4781e0c88 249 rc = mqttstring.lenstring.len;
JMF 0:5cd4781e0c88 250 return rc;
JMF 0:5cd4781e0c88 251 }
JMF 0:5cd4781e0c88 252
JMF 0:5cd4781e0c88 253
JMF 0:5cd4781e0c88 254 /**
JMF 0:5cd4781e0c88 255 * Compares an MQTTString to a C string
JMF 0:5cd4781e0c88 256 * @param a the MQTTString to compare
JMF 0:5cd4781e0c88 257 * @param bptr the C string to compare
JMF 0:5cd4781e0c88 258 * @return boolean - equal or not
JMF 0:5cd4781e0c88 259 */
JMF 0:5cd4781e0c88 260 int MQTTPacket_equals(MQTTString* a, char* bptr)
JMF 0:5cd4781e0c88 261 {
JMF 0:5cd4781e0c88 262 int alen = 0,
JMF 0:5cd4781e0c88 263 blen = 0;
JMF 0:5cd4781e0c88 264 char *aptr;
JMF 0:5cd4781e0c88 265
JMF 0:5cd4781e0c88 266 if (a->cstring)
JMF 0:5cd4781e0c88 267 {
JMF 0:5cd4781e0c88 268 aptr = a->cstring;
JMF 0:5cd4781e0c88 269 alen = strlen(a->cstring);
JMF 0:5cd4781e0c88 270 }
JMF 0:5cd4781e0c88 271 else
JMF 0:5cd4781e0c88 272 {
JMF 0:5cd4781e0c88 273 aptr = a->lenstring.data;
JMF 0:5cd4781e0c88 274 alen = a->lenstring.len;
JMF 0:5cd4781e0c88 275 }
JMF 0:5cd4781e0c88 276 blen = strlen(bptr);
JMF 0:5cd4781e0c88 277
JMF 0:5cd4781e0c88 278 return (alen == blen) && (strncmp(aptr, bptr, alen) == 0);
JMF 0:5cd4781e0c88 279 }
JMF 0:5cd4781e0c88 280
JMF 0:5cd4781e0c88 281
JMF 0:5cd4781e0c88 282 /**
JMF 0:5cd4781e0c88 283 * Helper function to read packet data from some source into a buffer
JMF 0:5cd4781e0c88 284 * @param buf the buffer into which the packet will be serialized
JMF 0:5cd4781e0c88 285 * @param buflen the length in bytes of the supplied buffer
JMF 0:5cd4781e0c88 286 * @param getfn pointer to a function which will read any number of bytes from the needed source
JMF 0:5cd4781e0c88 287 * @return integer MQTT packet type, or -1 on error
JMF 0:5cd4781e0c88 288 * @note the whole message must fit into the caller's buffer
JMF 0:5cd4781e0c88 289 */
JMF 0:5cd4781e0c88 290 int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int))
JMF 0:5cd4781e0c88 291 {
JMF 0:5cd4781e0c88 292 int rc = -1;
JMF 0:5cd4781e0c88 293 MQTTHeader header = {0};
JMF 0:5cd4781e0c88 294 int len = 0;
JMF 0:5cd4781e0c88 295 int rem_len = 0;
JMF 0:5cd4781e0c88 296
JMF 0:5cd4781e0c88 297 /* 1. read the header byte. This has the packet type in it */
JMF 0:5cd4781e0c88 298 if ((*getfn)(buf, 1) != 1)
JMF 0:5cd4781e0c88 299 goto exit;
JMF 0:5cd4781e0c88 300
JMF 0:5cd4781e0c88 301 len = 1;
JMF 0:5cd4781e0c88 302 /* 2. read the remaining length. This is variable in itself */
JMF 0:5cd4781e0c88 303 MQTTPacket_decode(getfn, &rem_len);
JMF 0:5cd4781e0c88 304 len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */
JMF 0:5cd4781e0c88 305
JMF 0:5cd4781e0c88 306 /* 3. read the rest of the buffer using a callback to supply the rest of the data */
JMF 0:5cd4781e0c88 307 if((rem_len + len) > buflen)
JMF 0:5cd4781e0c88 308 goto exit;
JMF 0:5cd4781e0c88 309 if (rem_len && ((*getfn)(buf + len, rem_len) != rem_len))
JMF 0:5cd4781e0c88 310 goto exit;
JMF 0:5cd4781e0c88 311
JMF 0:5cd4781e0c88 312 header.byte = buf[0];
JMF 0:5cd4781e0c88 313 rc = header.bits.type;
JMF 0:5cd4781e0c88 314 exit:
JMF 0:5cd4781e0c88 315 return rc;
JMF 0:5cd4781e0c88 316 }
JMF 0:5cd4781e0c88 317
JMF 0:5cd4781e0c88 318 /**
JMF 0:5cd4781e0c88 319 * Decodes the message length according to the MQTT algorithm, non-blocking
JMF 0:5cd4781e0c88 320 * @param trp pointer to a transport structure holding what is needed to solve getting data from it
JMF 0:5cd4781e0c88 321 * @param value the decoded length returned
JMF 0:5cd4781e0c88 322 * @return integer the number of bytes read from the socket, 0 for call again, or -1 on error
JMF 0:5cd4781e0c88 323 */
JMF 0:5cd4781e0c88 324 static int MQTTPacket_decodenb(MQTTTransport *trp)
JMF 0:5cd4781e0c88 325 {
JMF 0:5cd4781e0c88 326 unsigned char c;
JMF 0:5cd4781e0c88 327 int rc = MQTTPACKET_READ_ERROR;
JMF 0:5cd4781e0c88 328
JMF 0:5cd4781e0c88 329 FUNC_ENTRY;
JMF 0:5cd4781e0c88 330 if(trp->len == 0){ /* initialize on first call */
JMF 0:5cd4781e0c88 331 trp->multiplier = 1;
JMF 0:5cd4781e0c88 332 trp->rem_len = 0;
JMF 0:5cd4781e0c88 333 }
JMF 0:5cd4781e0c88 334 do {
JMF 0:5cd4781e0c88 335 int frc;
JMF 0:5cd4781e0c88 336 if (trp->len >= MAX_NO_OF_REMAINING_LENGTH_BYTES)
JMF 0:5cd4781e0c88 337 goto exit;
JMF 0:5cd4781e0c88 338 if ((frc=(*trp->getfn)(trp->sck, &c, 1)) == -1)
JMF 0:5cd4781e0c88 339 goto exit;
JMF 0:5cd4781e0c88 340 if (frc == 0){
JMF 0:5cd4781e0c88 341 rc = 0;
JMF 0:5cd4781e0c88 342 goto exit;
JMF 0:5cd4781e0c88 343 }
JMF 0:5cd4781e0c88 344 ++(trp->len);
JMF 0:5cd4781e0c88 345 trp->rem_len += (c & 127) * trp->multiplier;
JMF 0:5cd4781e0c88 346 trp->multiplier *= 128;
JMF 0:5cd4781e0c88 347 } while ((c & 128) != 0);
JMF 0:5cd4781e0c88 348 rc = trp->len;
JMF 0:5cd4781e0c88 349 exit:
JMF 0:5cd4781e0c88 350 FUNC_EXIT_RC(rc);
JMF 0:5cd4781e0c88 351 return rc;
JMF 0:5cd4781e0c88 352 }
JMF 0:5cd4781e0c88 353
JMF 0:5cd4781e0c88 354 /**
JMF 0:5cd4781e0c88 355 * Helper function to read packet data from some source into a buffer, non-blocking
JMF 0:5cd4781e0c88 356 * @param buf the buffer into which the packet will be serialized
JMF 0:5cd4781e0c88 357 * @param buflen the length in bytes of the supplied buffer
JMF 0:5cd4781e0c88 358 * @param trp pointer to a transport structure holding what is needed to solve getting data from it
JMF 0:5cd4781e0c88 359 * @return integer MQTT packet type, 0 for call again, or -1 on error
JMF 0:5cd4781e0c88 360 * @note the whole message must fit into the caller's buffer
JMF 0:5cd4781e0c88 361 */
JMF 0:5cd4781e0c88 362 int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp)
JMF 0:5cd4781e0c88 363 {
JMF 0:5cd4781e0c88 364 int rc = -1, frc;
JMF 0:5cd4781e0c88 365 MQTTHeader header = {0};
JMF 0:5cd4781e0c88 366
JMF 0:5cd4781e0c88 367 switch(trp->state){
JMF 0:5cd4781e0c88 368 default:
JMF 0:5cd4781e0c88 369 trp->state = 0;
JMF 0:5cd4781e0c88 370 /*FALLTHROUGH*/
JMF 0:5cd4781e0c88 371 case 0:
JMF 0:5cd4781e0c88 372 /* read the header byte. This has the packet type in it */
JMF 0:5cd4781e0c88 373 if ((frc=(*trp->getfn)(trp->sck, buf, 1)) == -1)
JMF 0:5cd4781e0c88 374 goto exit;
JMF 0:5cd4781e0c88 375 if (frc == 0)
JMF 0:5cd4781e0c88 376 return 0;
JMF 0:5cd4781e0c88 377 trp->len = 0;
JMF 0:5cd4781e0c88 378 ++trp->state;
JMF 0:5cd4781e0c88 379 /*FALLTHROUGH*/
JMF 0:5cd4781e0c88 380 /* read the remaining length. This is variable in itself */
JMF 0:5cd4781e0c88 381 case 1:
JMF 0:5cd4781e0c88 382 if((frc=MQTTPacket_decodenb(trp)) == MQTTPACKET_READ_ERROR)
JMF 0:5cd4781e0c88 383 goto exit;
JMF 0:5cd4781e0c88 384 if(frc == 0)
JMF 0:5cd4781e0c88 385 return 0;
JMF 0:5cd4781e0c88 386 trp->len = 1 + MQTTPacket_encode(buf + 1, trp->rem_len); /* put the original remaining length back into the buffer */
JMF 0:5cd4781e0c88 387 if((trp->rem_len + trp->len) > buflen)
JMF 0:5cd4781e0c88 388 goto exit;
JMF 0:5cd4781e0c88 389 ++trp->state;
JMF 0:5cd4781e0c88 390 /*FALLTHROUGH*/
JMF 0:5cd4781e0c88 391 case 2:
JMF 0:5cd4781e0c88 392 if(trp->rem_len){
JMF 0:5cd4781e0c88 393 /* read the rest of the buffer using a callback to supply the rest of the data */
JMF 0:5cd4781e0c88 394 if ((frc=(*trp->getfn)(trp->sck, buf + trp->len, trp->rem_len)) == -1)
JMF 0:5cd4781e0c88 395 goto exit;
JMF 0:5cd4781e0c88 396 if (frc == 0)
JMF 0:5cd4781e0c88 397 return 0;
JMF 0:5cd4781e0c88 398 trp->rem_len -= frc;
JMF 0:5cd4781e0c88 399 trp->len += frc;
JMF 0:5cd4781e0c88 400 if(trp->rem_len)
JMF 0:5cd4781e0c88 401 return 0;
JMF 0:5cd4781e0c88 402 }
JMF 0:5cd4781e0c88 403 header.byte = buf[0];
JMF 0:5cd4781e0c88 404 rc = header.bits.type;
JMF 0:5cd4781e0c88 405 break;
JMF 0:5cd4781e0c88 406 }
JMF 0:5cd4781e0c88 407
JMF 0:5cd4781e0c88 408 exit:
JMF 0:5cd4781e0c88 409 trp->state = 0;
JMF 0:5cd4781e0c88 410 return rc;
JMF 0:5cd4781e0c88 411 }