Basic C library for MQTT packet serialization and deserialization

Dependents:   MQTT MQTT MQTT MQTT ... more

Fork of MQTTPacket by MQTT

This library is part of the EclipseTM Paho project; specifically the embedded client.

A basic MQTT library in C for packet serialization and deserialization

Committer:
Ian Craggs
Date:
Mon Oct 30 12:47:11 2017 +0000
Revision:
25:aedcaf7984d5
Parent:
23:7a52009beba1
Merging mine and Jan's changes

Who changed what in which revision?

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