Andrew Reed / Mbed OS CITY1082-i2c_master_wifi_mqtt
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MQTTSNPacket.c Source File

MQTTSNPacket.c

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 "StackTrace.h"
00018 #include "MQTTSNPacket.h"
00019 
00020 #include <string.h>
00021 
00022 static const char* packet_names[] =
00023 {
00024         "ADVERTISE", "SEARCHGW", "GWINFO", "RESERVED", "CONNECT", "CONNACK",
00025         "WILLTOPICREQ", "WILLTOPIC", "WILLMSGREQ", "WILLMSG", "REGISTER", "REGACK",
00026         "PUBLISH", "PUBACK", "PUBCOMP", "PUBREC", "PUBREL", "RESERVED",
00027         "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP",
00028         "DISCONNECT", "RESERVED", "WILLTOPICUPD", "WILLTOPICRESP", "WILLMSGUPD",
00029         "WILLMSGRESP"
00030 };
00031 
00032 static const char* encapsulation_packet_name = "ENCAPSULATED";
00033 
00034 /**
00035  * Returns a character string representing the packet name given a MsgType code
00036  * @param code MsgType code
00037  * @return the corresponding packet name
00038  */
00039 const char* MQTTSNPacket_name(int code)
00040 {
00041     if ( code == MQTTSN_ENCAPSULATED )
00042     {
00043         return encapsulation_packet_name;
00044     }
00045     return (code >= 0 && code <= MQTTSN_WILLMSGRESP) ? packet_names[code] : "UNKNOWN";
00046 }
00047 
00048 
00049 /**
00050  * Calculates the full packet length including length field
00051  * @param length the length of the MQTT-SN packet without the length field
00052  * @return the total length of the MQTT-SN packet including the length field
00053  */
00054 int MQTTSNPacket_len(int length)
00055 {
00056     return (length > 255) ? length + 3 : length + 1;
00057 }
00058 
00059 /**
00060  * Encodes the MQTT-SN message length
00061  * @param buf the buffer into which the encoded data is written
00062  * @param length the length to be encoded
00063  * @return the number of bytes written to the buffer
00064  */
00065 int MQTTSNPacket_encode(unsigned char* buf, int length)
00066 {
00067     int rc = 0;
00068 
00069     FUNC_ENTRY;
00070     if (length > 255)
00071     {
00072         writeChar(&buf, 0x01);
00073         writeInt(&buf, length);
00074         rc += 3;
00075     }
00076     else
00077         buf[rc++] = length;
00078 
00079     FUNC_EXIT_RC(rc);
00080     return rc;
00081 }
00082 
00083 
00084 /**
00085  * Obtains the MQTT-SN packet length from received data
00086  * @param getcharfn pointer to function to read the next character from the data source
00087  * @param value the decoded length returned
00088  * @return the number of bytes read from the socket
00089  */
00090 int MQTTSNPacket_decode(unsigned char* buf, int buflen, int* value)
00091 {
00092     int len = MQTTSNPACKET_READ_ERROR;
00093 #define MAX_NO_OF_LENGTH_BYTES 3
00094 
00095     FUNC_ENTRY;
00096     if (buflen <= 0)
00097         goto exit;
00098 
00099     if (buf[0] == 1)
00100     {
00101         unsigned char* bufptr = &buf[1];
00102         if (buflen < MAX_NO_OF_LENGTH_BYTES)
00103             goto exit;
00104         *value = readInt(&bufptr);
00105         len = 3;
00106     }
00107     else
00108     {
00109         *value = buf[0];
00110         len = 1;
00111     }
00112 exit:
00113     FUNC_EXIT_RC(len);
00114     return len;
00115 }
00116 
00117 /**
00118  * Check if two MQTT-SN topics are equal. Long names are not checked.
00119  * @param a pointer to first topic
00120  * @param b pointer to second topic
00121  * @return boolean true if topics are equal and flase otherwise
00122  */
00123 int MQTTSNTopic_equals(const MQTTSN_topicid* const a, const MQTTSN_topicid* const b)
00124 {
00125     if ((a->type == b->type)
00126             && (a->data.id == b->data.id)
00127             && (a->data.short_name[0] == b->data.short_name[0])
00128             && (a->data.short_name[1] == b->data.short_name[1])) {
00129         return 1;
00130     } else {
00131         return 0;
00132     }
00133 }
00134 
00135 #if 0 // Those are already defined in MQTTPacket.c
00136 /**
00137  * Calculates an integer from two bytes read from the input buffer
00138  * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
00139  * @return the integer value calculated
00140  */
00141 int readInt(unsigned char** pptr)
00142 {
00143     unsigned char* ptr = *pptr;
00144     int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
00145     *pptr += 2;
00146     return len;
00147 }
00148 
00149 
00150 /**
00151  * Reads one character from the input buffer.
00152  * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
00153  * @return the character read
00154  */
00155 char readChar(unsigned char** pptr)
00156 {
00157     char c = **pptr;
00158     (*pptr)++;
00159     return c;
00160 }
00161 
00162 
00163 /**
00164  * Writes one character to an output buffer.
00165  * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
00166  * @param c the character to write
00167  */
00168 void writeChar(unsigned char** pptr, char c)
00169 {
00170     **pptr = (unsigned char)c;
00171     (*pptr)++;
00172 }
00173 
00174 
00175 /**
00176  * Writes an integer as 2 bytes to an output buffer.
00177  * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
00178  * @param anInt the integer to write: 0 to 65535
00179  */
00180 void writeInt(unsigned char** pptr, int anInt)
00181 {
00182     **pptr = (unsigned char)(anInt / 256);
00183     (*pptr)++;
00184     **pptr = (unsigned char)(anInt % 256);
00185     (*pptr)++;
00186 }
00187 
00188 
00189 /**
00190  * Writes a "UTF" string to an output buffer.  Converts C string to length-delimited.
00191  * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
00192  * @param string the C string to write
00193  */
00194 void writeCString(unsigned char** pptr, char* string)
00195 {
00196     int len = strlen(string);
00197     memcpy(*pptr, string, len);
00198     *pptr += len;
00199 }
00200 
00201 
00202 int getLenStringLen(char* ptr)
00203 {
00204     int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
00205     return len;
00206 }
00207 #endif
00208 
00209 void writeMQTTSNString(unsigned char** pptr, MQTTSNString MQTTSNString)
00210 {
00211     if (MQTTSNString.lenstring.len > 0)
00212     {
00213         memcpy(*pptr, (const unsigned char*)MQTTSNString.lenstring.data, MQTTSNString.lenstring.len);
00214         *pptr += MQTTSNString.lenstring.len;
00215     }
00216     else if (MQTTSNString.cstring)
00217         writeCString(pptr, MQTTSNString.cstring);
00218 }
00219 
00220 
00221 /**
00222  * @param MQTTSNString the MQTTSNString structure into which the data is to be read
00223  * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
00224  * @param enddata pointer to the end of the data: do not read beyond
00225  * @return 1 if successful, 0 if not
00226  */
00227 int readMQTTSNString(MQTTSNString* MQTTSNString, unsigned char** pptr, unsigned char* enddata)
00228 {
00229     int rc = 0;
00230 
00231     FUNC_ENTRY;
00232     MQTTSNString->lenstring.len = enddata - *pptr;
00233     if (MQTTSNString->lenstring.len > 0)
00234     {
00235         MQTTSNString->lenstring.data = (char*)*pptr;
00236         *pptr += MQTTSNString->lenstring.len;
00237     }
00238     else
00239     {
00240         MQTTSNString->lenstring.data = NULL;
00241         MQTTSNString->cstring = NULL;
00242     }
00243     rc = 1;
00244     FUNC_EXIT_RC(rc);
00245     return rc;
00246 }
00247 
00248 
00249 /**
00250  * Return the length of the MQTTSNString - C string if there is one, otherwise the length delimited string
00251  * @param MQTTSNString the string to return the length of
00252  * @return the length of the string
00253  */
00254 int MQTTSNstrlen(MQTTSNString MQTTSNString)
00255 {
00256     int rc = 0;
00257 
00258     if (MQTTSNString.cstring)
00259         rc = strlen(MQTTSNString.cstring);
00260     else
00261         rc = MQTTSNString.lenstring.len;
00262     return rc;
00263 }
00264 
00265 
00266 /**
00267  * Helper function to read packet data from some source into a buffer
00268  * @param buf the buffer into which the packet will be serialized
00269  * @param buflen the length in bytes of the supplied buffer
00270  * @param getfn pointer to a function which will read any number of bytes from the needed source
00271  * @return integer MQTT packet type, or MQTTSNPACKET_READ_ERROR on error
00272  */
00273 int MQTTSNPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int))
00274 {
00275     int rc = MQTTSNPACKET_READ_ERROR;
00276     const int MQTTSN_MIN_PACKET_LENGTH = 2;
00277     int len = 0;  /* the length of the whole packet including length field */
00278     int lenlen = 0;
00279     int datalen = 0;
00280 
00281     /* 1. read a packet - UDP style */
00282     if ((len = (*getfn)(buf, buflen)) < MQTTSN_MIN_PACKET_LENGTH)
00283         goto exit;
00284 
00285     /* 2. read the length.  This is variable in itself */
00286     lenlen = MQTTSNPacket_decode(buf, len, &datalen);
00287     if (datalen != len)
00288         goto exit; /* there was an error */
00289 
00290     rc = buf[lenlen]; /* return the packet type */
00291 exit:
00292     return rc;
00293 }
00294 
00295 int MQTTSNPacket_read_nb(unsigned char* buf, int buflen)
00296 {
00297     int rc = MQTTSNPACKET_READ_ERROR;
00298     int len = buflen;  /* the length of the whole packet including length field */
00299     int lenlen = 0;
00300     int datalen = 0;
00301 
00302     /* 2. read the length.  This is variable in itself */
00303     lenlen = MQTTSNPacket_decode(buf, len, &datalen);
00304     if (datalen != len)
00305         goto exit; /* there was an error */
00306 
00307     rc = buf[lenlen]; /* return the packet type */
00308 exit:
00309     return rc;
00310 }
00311