Move MQTTSNPacket into subdirectory

This commit is contained in:
Ian Craggs
2015-04-09 16:40:04 +01:00
parent b73a6712c1
commit 44dc71a2b1
41 changed files with 1015 additions and 19 deletions

View File

@@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#ifndef MQTTSNCONNECT_H_
#define MQTTSNCONNECT_H_
typedef struct
{
/** The eyecatcher for this structure. must be MQSC. */
char struct_id[4];
/** The version number of this structure. Must be 0.
*/
int struct_version;
MQTTSNString clientID;
unsigned short duration;
unsigned char cleansession;
unsigned char willFlag;
} MQTTSNPacket_connectData;
#define MQTTSNPacket_connectData_initializer { {'M', 'Q', 'S', 'C'}, 0, {NULL, {0, NULL}}, 10, 1, 0 }
int MQTTSNSerialize_connect(unsigned char* buf, int buflen, MQTTSNPacket_connectData* options);
int MQTTSNDeserialize_connect(MQTTSNPacket_connectData* data, unsigned char* buf, int len);
int MQTTSNSerialize_connack(unsigned char* buf, int buflen, int connack_rc);
int MQTTSNDeserialize_connack(int* connack_rc, unsigned char* buf, int buflen);
int MQTTSNSerialize_disconnect(unsigned char* buf, int buflen, int duration);
int MQTTSNDeserialize_disconnect(int* duration, unsigned char* buf, int buflen);
int MQTTSNSerialize_pingreq(unsigned char* buf, int buflen, MQTTSNString clientid);
int MQTTSNDeserialize_pingreq(MQTTSNString* clientID, unsigned char* buf, int len);
int MQTTSNSerialize_pingresp(unsigned char* buf, int buflen);
int MQTTSNDeserialize_pingresp(unsigned char* buf, int buflen);
int MQTTSNSerialize_willmsg(unsigned char* buf, int buflen, MQTTSNString willMsg);
int MQTTSNDeserialize_willmsg(MQTTSNString* willMsg, unsigned char* buf, int buflen);
int MQTTSNSerialize_willmsgreq(unsigned char* buf, int buflen);
int MQTTSNDeserialize_willmsgreq(unsigned char* buf, int buflen);
int MQTTSNSerialize_willmsgupd(unsigned char* buf, int buflen, MQTTSNString willMsg);
int MQTTSNDeserialize_willmsgupd(MQTTSNString* willMsg, unsigned char* buf, int buflen);
int MQTTSNSerialize_willmsgresp(unsigned char* buf, int buflen, int resp_rc);
int MQTTSNDeserialize_willmsgresp(int* resp_rc, unsigned char* buf, int buflen);
int MQTTSNSerialize_willtopic(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic);
int MQTTSNDeserialize_willtopic(int* willQoS, unsigned char* willRetain, MQTTSNString* willTopic, unsigned char* buf, int buflen);
int MQTTSNSerialize_willtopicreq(unsigned char* buf, int buflen);
int MQTTSNDeserialize_willtopicreq(unsigned char* buf, int buflen);
int MQTTSNSerialize_willtopicupd(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic);
int MQTTSNDeserialize_willtopicupd(int *willQoS, unsigned char *willRetain, MQTTSNString* willTopic, unsigned char* buf, int buflen);
int MQTTSNSerialize_willtopicresp(unsigned char* buf, int buflen, int resp_rc);
int MQTTSNDeserialize_willtopicresp(int* resp_rc, unsigned char* buf, int buflen);
#endif /* MQTTSNCONNECT_H_ */

View File

@@ -0,0 +1,478 @@
/*******************************************************************************
* Copyright (c) 2014, 2015 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Nicholas Humfrey - Reformatting to make more consistent; bug 453862
*******************************************************************************/
#include "MQTTSNPacket.h"
#include "StackTrace.h"
#include <string.h>
/**
* Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
* @param options the options to be used to build the connect packet
* @return the length of buffer needed to contain the serialized version of the packet
*/
int MQTTSNSerialize_connectLength(MQTTSNPacket_connectData* options)
{
int len = 0;
FUNC_ENTRY;
len = 5 + MQTTSNstrlen(options->clientID);
FUNC_EXIT_RC(len);
return len;
}
/**
* Serializes the connect options into the buffer.
* @param buf the buffer into which the packet will be serialized
* @param len the length in bytes of the supplied buffer
* @param options the options to be used to build the connect packet
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_connect(unsigned char* buf, int buflen, MQTTSNPacket_connectData* options)
{
unsigned char *ptr = buf;
MQTTSNFlags flags;
int len = 0;
int rc = -1;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(MQTTSNSerialize_connectLength(options))) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_CONNECT); /* write message type */
flags.all = 0;
flags.bits.cleanSession = options->cleansession;
flags.bits.will = options->willFlag;
writeChar(&ptr, flags.all);
writeChar(&ptr, 0x01); /* protocol ID */
writeInt(&ptr, options->duration);
writeMQTTSNString(&ptr, options->clientID);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into connack data - return code
* @param connack_rc returned integer value of the connack return code
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_connack(int* connack_rc, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - buf < 3)
goto exit;
if (readChar(&curdata) != MQTTSN_CONNACK)
goto exit;
*connack_rc = readChar(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Determines the length of the MQTT disconnect packet (without length field)
* @param duration the parameter used for the disconnect
* @return the length of buffer needed to contain the serialized version of the packet
*/
int MQTTSNSerialize_disconnectLength(int duration)
{
int len = 0;
FUNC_ENTRY;
len = (duration >= 0) ? 3 : 1;
FUNC_EXIT_RC(len);
return len;
}
/**
* Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer, to avoid overruns
* @param duration optional duration, not added to packet if < 0
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_disconnect(unsigned char* buf, int buflen, int duration)
{
int rc = -1;
unsigned char *ptr = buf;
int len = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(MQTTSNSerialize_disconnectLength(duration))) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_DISCONNECT); /* write message type */
if (duration >= 0)
writeInt(&ptr, duration);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer, to avoid overruns
* @param clientid optional string, not added to packet string == NULL
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_pingreq(unsigned char* buf, int buflen, MQTTSNString clientid)
{
int rc = -1;
unsigned char *ptr = buf;
int len = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(MQTTSNstrlen(clientid) + 1)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_PINGREQ); /* write message type */
writeMQTTSNString(&ptr, clientid);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_pingresp(unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata < 2)
goto exit;
if (readChar(&curdata) != MQTTSN_PINGRESP)
goto exit;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes a willtopic or willtopicupd packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param len the length in bytes of the supplied buffer
* @param willQoS the qos of the will message
* @param willRetain the retained flag of the will message
* @param willTopic the topic of the will message
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willtopic1(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic,
enum MQTTSN_msgTypes packet_type)
{
unsigned char *ptr = buf;
MQTTSNFlags flags;
int len = 0;
int rc = -1;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(MQTTSNstrlen(willTopic) + 2)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, packet_type); /* write message type */
flags.all = 0;
flags.bits.QoS = willQoS;
flags.bits.retain = willRetain;
writeChar(&ptr, flags.all);
writeMQTTSNString(&ptr, willTopic);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes a willtopicupd packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param len the length in bytes of the supplied buffer
* @param willQoS the qos of the will message
* @param willRetain the retained flag of the will message
* @param willTopic the topic of the will message
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willtopicupd(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic)
{
return MQTTSNSerialize_willtopic1(buf, buflen, willQoS, willRetain, willTopic, MQTTSN_WILLTOPICUPD);
}
/**
* Serializes a willtopic packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param len the length in bytes of the supplied buffer
* @param willQoS the qos of the will message
* @param willRetain the retained flag of the will message
* @param willTopic the topic of the will message
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willtopic(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic)
{
return MQTTSNSerialize_willtopic1(buf, buflen, willQoS, willRetain, willTopic, MQTTSN_WILLTOPIC);
}
/**
* Serializes a willmsg or willmsgupd packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param willMsg the will message
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willmsg1(unsigned char* buf, int buflen, MQTTSNString willMsg, enum MQTTSN_msgTypes packet_type)
{
unsigned char *ptr = buf;
int len = 0;
int rc = -1;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(MQTTSNstrlen(willMsg) + 1)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, packet_type); /* write message type */
writeMQTTSNString(&ptr, willMsg);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes a willmsg packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param len the length in bytes of the supplied buffersage
* @param willMsg the will message
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willmsg(unsigned char* buf, int buflen, MQTTSNString willMsg)
{
return MQTTSNSerialize_willmsg1(buf, buflen, willMsg, MQTTSN_WILLMSG);
}
/**
* Serializes a willmsgupd packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param len the length in bytes of the supplied buffersage
* @param willMsg the will message
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willmsgupd(unsigned char* buf, int buflen, MQTTSNString willMsg)
{
return MQTTSNSerialize_willmsg1(buf, buflen, willMsg, MQTTSN_WILLMSGUPD);
}
/**
* Deserializes the supplied (wire) buffer
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willtopicreq(unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = -1;
int mylen;
FUNC_ENTRY;
if (MQTTSNPacket_decode(curdata++, buflen, &mylen) != 1) /* read length */
goto exit;
if (mylen > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
enddata = buf + mylen;
if (enddata - curdata < 1)
goto exit;
if (readChar(&curdata) != MQTTSN_WILLTOPICREQ)
goto exit;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willmsgreq(unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = -1;
int mylen;
FUNC_ENTRY;
if (MQTTSNPacket_decode(curdata++, buflen, &mylen) != 1) /* read length */
goto exit;
if (mylen > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
enddata = buf + mylen;
if (enddata - curdata < 1)
goto exit;
if (readChar(&curdata) != MQTTSN_WILLMSGREQ)
goto exit;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into willtopicresp data - return code
* @param connack_rc returned integer value of the return code
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willtopicresp(int* resp_rc, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - buf < 3)
goto exit;
if (readChar(&curdata) != MQTTSN_WILLTOPICRESP)
goto exit;
*resp_rc = readChar(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into willmsgresp data - return code
* @param connack_rc returned integer value of the return code
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willmsgresp(int* resp_rc, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - buf < 3)
goto exit;
if (readChar(&curdata) != MQTTSN_WILLMSGRESP)
goto exit;
*resp_rc = readChar(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,430 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "StackTrace.h"
#include "MQTTSNPacket.h"
#include <string.h>
#define min(a, b) ((a < b) ? 1 : 0)
/**
* Deserializes the supplied (wire) buffer into connect data structure
* @param data the connect data structure to be filled out
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_connect(MQTTSNPacket_connectData* data, unsigned char* buf, int len)
{
MQTTSNFlags flags;
unsigned char* curdata = buf;
unsigned char* enddata = &buf[len];
int rc = 0;
int version;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata < 2)
goto exit;
if (readChar(&curdata) != MQTTSN_CONNECT)
goto exit;
flags.all = readChar(&curdata);
data->cleansession = flags.bits.cleanSession;
data->willFlag = flags.bits.will;
if ((version = (int)readChar(&curdata)) != 1) /* Protocol version */
goto exit;
data->duration = readInt(&curdata);
if (!readMQTTSNString(&data->clientID, &curdata, enddata))
goto exit;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes the connack packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param connack_rc the integer connack return code to be used
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_connack(unsigned char* buf, int buflen, int connack_rc)
{
int rc = 0;
unsigned char *ptr = buf;
FUNC_ENTRY;
if (buflen < 3)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, 3); /* write length */
writeChar(&ptr, MQTTSN_CONNACK);
writeChar(&ptr, connack_rc);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into disconnect data - optional duration
* @param duration returned integer value of the duration field, -1 if no duration was specified
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_disconnect(int* duration, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = -1;
int mylen;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata < 1)
goto exit;
if (readChar(&curdata) != MQTTSN_DISCONNECT)
goto exit;
if (enddata - curdata == 2)
*duration = readInt(&curdata);
else if (enddata != curdata)
goto exit;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes a willtopicreq packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willtopicreq(unsigned char* buf, int buflen)
{
int rc = 0;
unsigned char *ptr = buf;
FUNC_ENTRY;
if (buflen < 2)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, 2); /* write length */
writeChar(&ptr, MQTTSN_WILLTOPICREQ);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes a willmsgreq packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willmsgreq(unsigned char* buf, int buflen)
{
int rc = 0;
unsigned char *ptr = buf;
FUNC_ENTRY;
if (buflen < 2)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, 2); /* write length */
writeChar(&ptr, MQTTSN_WILLMSGREQ);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into pingreq data
* @param clientID the connect data structure to be filled out
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_pingreq(MQTTSNString* clientID, unsigned char* buf, int len)
{
unsigned char* curdata = buf;
unsigned char* enddata = &buf[len];
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata < 1)
goto exit;
if (readChar(&curdata) != MQTTSN_PINGREQ)
goto exit;
if (!readMQTTSNString(clientID, &curdata, enddata))
goto exit;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes a pingresp packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_pingresp(unsigned char* buf, int buflen)
{
int rc = 0;
unsigned char *ptr = buf;
FUNC_ENTRY;
if (buflen < 2)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, 2); /* write length */
writeChar(&ptr, MQTTSN_PINGRESP);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into willtopic or willtopicupd data structure
* @param data the connect data structure to be filled out
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willtopic1(int *willQoS, unsigned char *willRetain, MQTTSNString* willTopic, unsigned char* buf, int len,
enum MQTTSN_msgTypes packet_type)
{
MQTTSNFlags flags;
unsigned char* curdata = buf;
unsigned char* enddata = &buf[len];
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata > buf + len)
goto exit;
if (readChar(&curdata) != packet_type)
goto exit;
flags.all = readChar(&curdata);
*willQoS = flags.bits.QoS;
*willRetain = flags.bits.retain;
if (!readMQTTSNString(willTopic, &curdata, enddata))
goto exit;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into willtopic data structure
* @param data the connect data structure to be filled out
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willtopic(int *willQoS, unsigned char *willRetain, MQTTSNString* willTopic, unsigned char* buf, int len)
{
return MQTTSNDeserialize_willtopic1(willQoS, willRetain, willTopic, buf, len, MQTTSN_WILLTOPIC);
}
/**
* Deserializes the supplied (wire) buffer into willtopic data structure
* @param data the connect data structure to be filled out
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willtopicupd(int *willQoS, unsigned char *willRetain, MQTTSNString* willTopic, unsigned char* buf, int len)
{
return MQTTSNDeserialize_willtopic1(willQoS, willRetain, willTopic, buf, len, MQTTSN_WILLTOPICUPD);
}
/**
* Deserializes the supplied (wire) buffer into willmsg or willmsgupd data
* @param willMsg the will message to be retrieved
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willmsg1(MQTTSNString* willMsg, unsigned char* buf, int len, enum MQTTSN_msgTypes packet_type)
{
unsigned char* curdata = buf;
unsigned char* enddata = &buf[len];
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata > buf + len)
goto exit;
if (readChar(&curdata) != packet_type)
goto exit;
if (!readMQTTSNString(willMsg, &curdata, enddata))
goto exit;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into willmsg data
* @param willMsg the will message to be retrieved
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willmsg(MQTTSNString* willMsg, unsigned char* buf, int len)
{
return MQTTSNDeserialize_willmsg1(willMsg, buf, len, MQTTSN_WILLMSG);
}
/**
* Deserializes the supplied (wire) buffer into willmsgupd data
* @param willMsg the will message to be retrieved
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param len the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_willmsgupd(MQTTSNString* willMsg, unsigned char* buf, int len)
{
return MQTTSNDeserialize_willmsg1(willMsg, buf, len, MQTTSN_WILLMSGUPD);
}
/**
* Serializes the willtopicresp packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param rc the integer return code to be used
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willtopicresp(unsigned char* buf, int buflen, int resp_rc)
{
int rc = 0;
unsigned char *ptr = buf;
FUNC_ENTRY;
if (buflen < 3)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, 3); /* write length */
writeChar(&ptr, MQTTSN_WILLTOPICRESP);
writeChar(&ptr, resp_rc);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes the willmsgresp packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param rc the integer return code to be used
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_willmsgresp(unsigned char* buf, int buflen, int resp_rc)
{
int rc = 0;
unsigned char *ptr = buf;
FUNC_ENTRY;
if (buflen < 3)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, 3); /* write length */
writeChar(&ptr, MQTTSN_WILLMSGRESP);
writeChar(&ptr, resp_rc);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,225 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "StackTrace.h"
#include "MQTTSNPacket.h"
#include <string.h>
#define min(a, b) ((a < b) ? 1 : 0)
/**
* Deserializes the supplied (wire) buffer into publish data
* @param dup returned integer - the MQTT dup flag
* @param qos returned integer - the MQTT QoS value
* @param retained returned integer - the MQTT retained flag
* @param packetid returned integer - the MQTT packet identifier
* @param topicName returned MQTTSNString - the MQTT topic in the publish
* @param payload returned byte buffer - the MQTT publish payload
* @param payloadlen returned integer - the length of the MQTT payload
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTSN_topicid* topic,
unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen)
{
MQTTSNFlags flags;
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_PUBLISH)
goto exit;
flags.all = readChar(&curdata);
*dup = flags.bits.dup;
*qos = flags.bits.QoS;
*retained = flags.bits.retain;
topic->type = flags.bits.topicIdType;
if (topic->type == MQTTSN_TOPIC_TYPE_NORMAL && *qos == 3)
{
/* special arrangement for long topic names in QoS -1 publishes. The length of the topic is in the topicid field */
topic->data.long_.len = readInt(&curdata);
}
else if (topic->type == MQTTSN_TOPIC_TYPE_NORMAL || topic->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
topic->data.id = readInt(&curdata);
else
{
topic->data.short_name[0] = readChar(&curdata);
topic->data.short_name[1] = readChar(&curdata);
}
*packetid = readInt(&curdata);
if (topic->type == MQTTSN_TOPIC_TYPE_NORMAL && *qos == 3)
{
topic->data.long_.name = (char*)curdata;
curdata += topic->data.long_.len;
}
*payloadlen = enddata - curdata;
*payload = curdata;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
int MQTTSNDeserialize_puback(unsigned short* topicid, unsigned short* packetid,
unsigned char* returncode, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_PUBACK)
goto exit;
*topicid = readInt(&curdata);
*packetid = readInt(&curdata);
*returncode = readChar(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into an ack
* @param packettype returned integer - the MQTT packet type
* @param packetid returned integer - the MQTT packet identifier
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success, 0 is failure
*/
int MQTTSNDeserialize_ack(unsigned char* type, unsigned short* packetid, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
*type = readChar(&curdata);
if (*type != MQTTSN_PUBREL && *type != MQTTSN_PUBREC && *type != MQTTSN_PUBCOMP)
goto exit;
*packetid = readInt(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into register data
* @param topicid returned topic id
* @param packetid returned integer - the MQTT packet identifier
* @param topicName returned MQTTSNString - the MQTT topic in the register
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_register(unsigned short* topicid, unsigned short* packetid, MQTTSNString* topicname,
unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_REGISTER)
goto exit;
*topicid = readInt(&curdata);
*packetid = readInt(&curdata);
topicname->lenstring.data = (char*)curdata;
topicname->lenstring.len = enddata - curdata;
topicname->cstring = NULL;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into register data
* @param topicid returned topic id
* @param packetid returned integer - the MQTT packet identifier
* @param return_code returned integer return code
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_regack(unsigned short* topicid, unsigned short* packetid, unsigned char* return_code,
unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_REGACK)
goto exit;
*topicid = readInt(&curdata);
*packetid = readInt(&curdata);
*return_code = readChar(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,271 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "StackTrace.h"
#include "MQTTSNPacket.h"
#include <string.h>
static char* packet_names[] =
{
"ADVERTISE", "SEARCHGW", "GWINFO", "RESERVED", "CONNECT", "CONNACK",
"WILLTOPICREQ", "WILLTOPIC", "WILLMSGREQ", "WILLMSG", "REGISTER", "REGACK",
"PUBLISH", "PUBACK", "PUBCOMP", "PUBREC", "PUBREL", "RESERVED",
"SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP",
"DISCONNECT", "RESERVED", "WILLTOPICUPD", "WILLTOPICRESP", "WILLMSGUPD",
"WILLMSGRESP"
};
/**
* Returns a character string representing the packet name given a MsgType code
* @param code MsgType code
* @return the corresponding packet name
*/
char* MQTTSNPacket_name(int code)
{
return (code >= 0 && code <= MQTTSN_WILLMSGRESP) ? packet_names[code] : "UNKNOWN";
}
/**
* Calculates the full packet length including length field
* @param length the length of the MQTT-SN packet without the length field
* @return the total length of the MQTT-SN packet including the length field
*/
int MQTTSNPacket_len(int length)
{
return (length > 255) ? length + 3 : length + 1;
}
/**
* Encodes the MQTT-SN message length
* @param buf the buffer into which the encoded data is written
* @param length the length to be encoded
* @return the number of bytes written to the buffer
*/
int MQTTSNPacket_encode(unsigned char* buf, int length)
{
int rc = 0;
FUNC_ENTRY;
if (length > 255)
{
buf[rc++] = 0x01;
writeInt(&buf, length);
rc += 2;
}
else
buf[rc++] = length;
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Obtains the MQTT-SN packet length from received data
* @param getcharfn pointer to function to read the next character from the data source
* @param value the decoded length returned
* @return the number of bytes read from the socket
*/
int MQTTSNPacket_decode(unsigned char* buf, int buflen, int* value)
{
int len = MQTTSNPACKET_READ_ERROR;
#define MAX_NO_OF_LENGTH_BYTES 3
FUNC_ENTRY;
if (buflen <= 0)
goto exit;
if (buf[0] == 1)
{
unsigned char* bufptr = &buf[1];
if (buflen < 3)
goto exit;
*value = readInt(&bufptr);
len = 3;
}
else
{
*value = buf[0];
len = 1;
}
exit:
FUNC_EXIT_RC(len);
return len;
}
/**
* Calculates an integer from two bytes read from the input buffer
* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return the integer value calculated
*/
int readInt(unsigned char** pptr)
{
unsigned char* ptr = *pptr;
int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
*pptr += 2;
return len;
}
/**
* Reads one character from the input buffer.
* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
* @return the character read
*/
char readChar(unsigned char** pptr)
{
char c = **pptr;
(*pptr)++;
return c;
}
/**
* Writes one character to an output buffer.
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param c the character to write
*/
void writeChar(unsigned char** pptr, char c)
{
**pptr = (unsigned char)c;
(*pptr)++;
}
/**
* Writes an integer as 2 bytes to an output buffer.
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param anInt the integer to write: 0 to 65535
*/
void writeInt(unsigned char** pptr, int anInt)
{
**pptr = (unsigned char)(anInt / 256);
(*pptr)++;
**pptr = (unsigned char)(anInt % 256);
(*pptr)++;
}
/**
* Writes a "UTF" string to an output buffer. Converts C string to length-delimited.
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param string the C string to write
*/
void writeCString(unsigned char** pptr, char* string)
{
int len = strlen(string);
memcpy(*pptr, string, len);
*pptr += len;
}
int getLenStringLen(char* ptr)
{
int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
return len;
}
void writeMQTTSNString(unsigned char** pptr, MQTTSNString MQTTSNString)
{
if (MQTTSNString.lenstring.len > 0)
{
memcpy(*pptr, MQTTSNString.lenstring.data, MQTTSNString.lenstring.len);
*pptr += MQTTSNString.lenstring.len;
}
else if (MQTTSNString.cstring)
writeCString(pptr, MQTTSNString.cstring);
}
/**
* @param MQTTSNString the MQTTSNString structure into which the data is to be read
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param enddata pointer to the end of the data: do not read beyond
* @return 1 if successful, 0 if not
*/
int readMQTTSNString(MQTTSNString* MQTTSNString, unsigned char** pptr, unsigned char* enddata)
{
int rc = 0;
FUNC_ENTRY;
MQTTSNString->lenstring.len = enddata - *pptr;
if (MQTTSNString->lenstring.len > 0)
{
MQTTSNString->lenstring.data = (char*)*pptr;
*pptr += MQTTSNString->lenstring.len;
}
else
MQTTSNString->lenstring.data = NULL;
MQTTSNString->cstring = NULL;
rc = 1;
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Return the length of the MQTTSNString - C string if there is one, otherwise the length delimited string
* @param MQTTSNString the string to return the length of
* @return the length of the string
*/
int MQTTSNstrlen(MQTTSNString MQTTSNString)
{
int rc = 0;
if (MQTTSNString.cstring)
rc = strlen(MQTTSNString.cstring);
else
rc = MQTTSNString.lenstring.len;
return rc;
}
/**
* Helper function to read packet data from some source into a buffer
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param getfn pointer to a function which will read any number of bytes from the needed source
* @return integer MQTT packet type, or MQTTSNPACKET_READ_ERROR on error
*/
int MQTTSNPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int))
{
int rc = MQTTSNPACKET_READ_ERROR;
const int MQTTSN_MIN_PACKET_LENGTH = 3;
int len = 0; /* the length of the whole packet including length field */
int lenlen = 0;
int datalen = 0;
/* 1. read a packet - UDP style */
if ((len = (*getfn)(buf, buflen)) < MQTTSN_MIN_PACKET_LENGTH)
goto exit;
/* 2. read the length. This is variable in itself */
lenlen = MQTTSNPacket_decode(buf, len, &datalen);
if (datalen != len)
goto exit; /* there was an error */
rc = buf[lenlen]; /* return the packet type */
exit:
return rc;
}

View File

@@ -0,0 +1,150 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#ifndef MQTTSNPACKET_H_
#define MQTTSNPACKET_H_
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
enum errors
{
MQTTSNPACKET_BUFFER_TOO_SHORT = -2,
MQTTSNPACKET_READ_ERROR = -1,
MQTTSNPACKET_READ_COMPLETE,
};
#define MQTTSN_PROTOCOL_VERSION 0x01
enum MQTTSN_connackCodes
{
MQTTSN_RC_ACCEPTED,
MQTTSN_RC_REJECTED_CONGESTED,
MQTTSN_RC_REJECTED_INVALID_TOPIC_ID,
};
enum MQTTSN_topicTypes
{
MQTTSN_TOPIC_TYPE_NORMAL, /* topic id in publish, topic name in subscribe */
MQTTSN_TOPIC_TYPE_PREDEFINED,
MQTTSN_TOPIC_TYPE_SHORT,
};
enum MQTTSN_msgTypes
{
MQTTSN_ADVERTISE, MQTTSN_SEARCHGW, MQTTSN_GWINFO, MQTTSN_RESERVED1,
MQTTSN_CONNECT, MQTTSN_CONNACK,
MQTTSN_WILLTOPICREQ, MQTTSN_WILLTOPIC, MQTTSN_WILLMSGREQ, MQTTSN_WILLMSG,
MQTTSN_REGISTER, MQTTSN_REGACK,
MQTTSN_PUBLISH, MQTTSN_PUBACK, MQTTSN_PUBCOMP, MQTTSN_PUBREC, MQTTSN_PUBREL, MQTTSN_RESERVED2,
MQTTSN_SUBSCRIBE, MQTTSN_SUBACK, MQTTSN_UNSUBSCRIBE, MQTTSN_UNSUBACK,
MQTTSN_PINGREQ, MQTTSN_PINGRESP,
MQTTSN_DISCONNECT, MQTTSN_RESERVED3,
MQTTSN_WILLTOPICUPD, MQTTSN_WILLTOPICRESP, MQTTSN_WILLMSGUPD, MQTTSN_WILLMSGRESP,
};
typedef struct
{
enum MQTTSN_topicTypes type;
union
{
unsigned short id;
char short_name[2];
struct
{
char* name;
int len;
} long_;
} data;
} MQTTSN_topicid;
/**
* Bitfields for the MQTT-SN flags byte.
*/
typedef union
{
unsigned char all;
#if defined(REVERSED)
struct
{
int dup: 1;
unsigned int QoS : 2;
unsigned int retain : 1;
unsigned int will : 1;
unsigned int cleanSession : 1;
unsigned int topicIdType : 2;
} bits;
#else
struct
{
unsigned int topicIdType : 2;
unsigned int cleanSession : 1;
unsigned int will : 1;
unsigned int retain : 1;
unsigned int QoS : 2;
int dup: 1;
} bits;
#endif
} MQTTSNFlags;
typedef struct
{
int len;
char* data;
} MQTTSNLenString;
typedef struct
{
char* cstring;
MQTTSNLenString lenstring;
} MQTTSNString;
#define MQTTSNString_initializer {NULL, {0, NULL}}
int MQTTSNstrlen(MQTTSNString mqttsnstring);
#include "MQTTSNConnect.h"
#include "MQTTSNPublish.h"
#include "MQTTSNSubscribe.h"
#include "MQTTSNUnsubscribe.h"
#include "MQTTSNSearch.h"
char* MQTTSNPacket_name(int ptype);
int MQTTSNPacket_len(int length);
int MQTTSNPacket_encode(unsigned char* buf, int length);
int MQTTSNPacket_decode(unsigned char* buf, int buflen, int* value);
int readInt(unsigned char** pptr);
char readChar(unsigned char** pptr);
void writeChar(unsigned char** pptr, char c);
void writeInt(unsigned char** pptr, int anInt);
int readMQTTSNString(MQTTSNString* mqttstring, unsigned char** pptr, unsigned char* enddata);
void writeCString(unsigned char** pptr, char* string);
void writeMQTTSNString(unsigned char** pptr, MQTTSNString mqttstring);
int MQTTSNPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int));
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
}
#endif
#endif /* MQTTSNPACKET_H_ */

View File

@@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(MQTTSNPUBLISH_H_)
#define MQTTSNPUBLISH_H_
int MQTTSNSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
MQTTSN_topicid topic, unsigned char* payload, int payloadlen);
int MQTTSNDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid,
MQTTSN_topicid* topic, unsigned char** payload, int* payloadlen, unsigned char* buf, int len);
int MQTTSNSerialize_puback(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
unsigned char returncode);
int MQTTSNDeserialize_puback(unsigned short* topicid, unsigned short* packetid,
unsigned char* returncode, unsigned char* buf, int buflen);
int MQTTSNSerialize_pubrec(unsigned char* buf, int buflen, unsigned short packetid);
int MQTTSNSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid);
int MQTTSNDeserialize_ack(unsigned char* packettype, unsigned short* packetid, unsigned char* buf, int buflen);
int MQTTSNSerialize_register(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
MQTTSNString* topicname);
int MQTTSNDeserialize_register(unsigned short* topicid, unsigned short* packetid, MQTTSNString* topicname,
unsigned char* buf, int buflen);
int MQTTSNSerialize_regack(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
unsigned char return_code);
int MQTTSNDeserialize_regack(unsigned short* topicid, unsigned short* packetid, unsigned char* return_code,
unsigned char* buf, int buflen);
#endif /* MQTTSNPUBLISH_H_ */

View File

@@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(MQTTSNSEARCH_H_)
#define MQTTSNSEARCH_H_
int MQTTSNSerialize_advertise(unsigned char* buf, int buflen, unsigned char gatewayid, unsigned short duration);
int MQTTSNDeserialize_advertise(unsigned char* gatewayid, unsigned short* duration, unsigned char* buf, int buflen);
int MQTTSNSerialize_searchgw(unsigned char* buf, int buflen, unsigned char radius);
int MQTTSNDeserialize_searchgw(unsigned char* radius, unsigned char* buf, int buflen);
int MQTTSNSerialize_gwinfo(unsigned char* buf, int buflen, unsigned char gatewayid, unsigned short gatewayaddress_len,
unsigned char* gatewayaddress);
int MQTTSNDeserialize_gwinfo(unsigned char* gatewayid, unsigned short* gatewayaddress_len, unsigned char** gatewayaddress,
unsigned char* buf, int buflen);
#endif /* MQTTSNSEARCH_H_ */

View File

@@ -0,0 +1,126 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "MQTTSNPacket.h"
#include "StackTrace.h"
#include <string.h>
/**
* Deserializes the supplied (wire) buffer into advertise data
* @param gatewayid the returned gateway id
* @param duration the returned duration - the time interval until the next advertise will be sent
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_advertise(unsigned char* gatewayid, unsigned short* duration, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_ADVERTISE)
goto exit;
*gatewayid = readChar(&curdata);
*duration = readInt(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes the supplied searchgw data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param radius the broadcast radius of this message
* @return the length of the serialized data. <= 0 indicates error
*/
int MQTTSNSerialize_searchgw(unsigned char* buf, int buflen, unsigned char radius)
{
unsigned char *ptr = buf;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(2)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_SEARCHGW); /* write message type */
writeChar(&ptr, radius);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into gwinfo data
* @param gatewayid the returned gateway id
* @param gatewayaddress_len the optional returned length of the gateway address (0 if none)
* @param gatewayaddress the optional returned gateway address (set to NULL if none)
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_gwinfo(unsigned char* gatewayid, unsigned short* gatewayaddress_len,
unsigned char** gatewayaddress, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_GWINFO)
goto exit;
*gatewayid = readChar(&curdata);
*gatewayaddress_len = enddata - curdata;
*gatewayaddress = (gatewayaddress_len > 0) ? curdata : NULL;
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,128 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "MQTTSNPacket.h"
#include "StackTrace.h"
#include <string.h>
/**
* Serializes the supplied advertise data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param radius the broadcast radius of this message
* @param duration - the time interval until the next advertise will be sent
* @return the length of the serialized data. <= 0 indicates error
*/
int MQTTSNSerialize_advertise(unsigned char* buf, int buflen, unsigned char gatewayid, unsigned short duration)
{
unsigned char *ptr = buf;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(4)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_ADVERTISE); /* write message type */
writeChar(&ptr, gatewayid);
writeInt(&ptr, duration);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into searchgw data
* @param radius the returned broadcast radius of this message
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_searchgw(unsigned char* radius, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_SEARCHGW)
goto exit;
*radius = readChar(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes the supplied gwinfo data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param gatewayid the gateway id
* @param gatewayaddress_len the optional length of the gateway address (0 if none)
* @param gatewayaddress the optional gateway address (NULL if none)
* @return the length of the serialized data. <= 0 indicates error
*/
int MQTTSNSerialize_gwinfo(unsigned char* buf, int buflen, unsigned char gatewayid, unsigned short gatewayaddress_len,
unsigned char* gatewayaddress)
{
unsigned char *ptr = buf;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(2 + gatewayaddress_len)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_GWINFO); /* write message type */
writeChar(&ptr, gatewayid);
if (gatewayaddress_len > 0 && gatewayaddress != NULL)
{
memcpy(ptr, gatewayaddress, gatewayaddress_len);
ptr += gatewayaddress_len;
}
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,290 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "MQTTSNPacket.h"
#include "StackTrace.h"
#include <string.h>
/**
* Determines the length of the MQTT publish packet that would be produced using the supplied parameters
* @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
* @param topicName the topic name to be used in the publish
* @param payloadlen the length of the payload to be sent
* @return the length of buffer needed to contain the serialized version of the packet
*/
int MQTTSNSerialize_publishLength(int payloadlen, MQTTSN_topicid topic, int qos)
{
int len = 6;
if (topic.type == MQTTSN_TOPIC_TYPE_NORMAL && qos == 3)
len += topic.data.long_.len;
return payloadlen + len;
}
/**
* Serializes the supplied publish data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param dup integer - the MQTT dup flag
* @param qos integer - the MQTT QoS value
* @param retained integer - the MQTT retained flag
* @param packetid integer - the MQTT packet identifier
* @param topic MQTTSN_topicid - the MQTT topic in the publish
* @param payload byte buffer - the MQTT publish payload
* @param payloadlen integer - the length of the MQTT payload
* @return the length of the serialized data. <= 0 indicates error
*/
int MQTTSNSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
MQTTSN_topicid topic, unsigned char* payload, int payloadlen)
{
unsigned char *ptr = buf;
MQTTSNFlags flags;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(MQTTSNSerialize_publishLength(payloadlen, topic, qos))) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_PUBLISH); /* write message type */
flags.all = 0;
flags.bits.dup = dup;
flags.bits.QoS = qos;
flags.bits.retain = retained;
flags.bits.topicIdType = topic.type;
writeChar(&ptr, flags.all);
if (topic.type == MQTTSN_TOPIC_TYPE_NORMAL && qos == 3)
{
/* special arrangement for long topic names in QoS -1 publishes. The length of the topic is in the topicid field */
writeInt(&ptr, topic.data.long_.len); /* topic length */
}
else if (topic.type == MQTTSN_TOPIC_TYPE_NORMAL || topic.type == MQTTSN_TOPIC_TYPE_PREDEFINED)
writeInt(&ptr, topic.data.id);
else
{
writeChar(&ptr, topic.data.short_name[0]);
writeChar(&ptr, topic.data.short_name[1]);
}
writeInt(&ptr, packetid);
if (topic.type == MQTTSN_TOPIC_TYPE_NORMAL && qos == 3)
{
memcpy(ptr, topic.data.long_.name, topic.data.long_.len);
ptr += topic.data.long_.len;
}
memcpy(ptr, payload, payloadlen);
ptr += payloadlen;
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
int MQTTSNSerialize_puback(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
unsigned char returncode)
{
unsigned char *ptr = buf;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(6)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_PUBACK); /* write message type */
writeInt(&ptr, topicid);
writeInt(&ptr, packetid);
writeChar(&ptr, returncode);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes the ack packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param type the MQTT-SN packet type
* @param packetid the MQTT-SN packet identifier
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_ack(unsigned char* buf, int buflen, unsigned short packet_type, unsigned short packetid)
{
int rc = 0;
unsigned char *ptr = buf;
int len = 4; /* ack packet length */
FUNC_ENTRY;
if (len > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, packet_type); /* write packet type */
writeInt(&ptr, packetid);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes a puback packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param packetid integer - the MQTT packet identifier
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_pubrec(unsigned char* buf, int buflen, unsigned short packetid)
{
return MQTTSNSerialize_ack(buf, buflen, MQTTSN_PUBREC, packetid);
}
/**
* Serializes a pubrel packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param dup integer - the MQTT dup flag
* @param packetid integer - the MQTT packet identifier
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_pubrel(unsigned char* buf, int buflen, unsigned short packetid)
{
return MQTTSNSerialize_ack(buf, buflen, MQTTSN_PUBREL, packetid);
}
/**
* Serializes a pubrel packet into the supplied buffer.
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param packetid integer - the MQTT packet identifier
* @return serialized length, or error if 0
*/
int MQTTSNSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid)
{
return MQTTSNSerialize_ack(buf, buflen, MQTTSN_PUBCOMP, packetid);
}
/**
* Determines the length of the MQTT register packet that would be produced using the supplied parameters
* @param topicnamelen the length of the topic name to be used in the register
* @return the length of buffer needed to contain the serialized version of the packet
*/
int MQTTSNSerialize_registerLength(int topicnamelen)
{
return topicnamelen + 5;
}
/**
* Serializes the supplied register data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param topicid if sent by a gateway, contains the id for the topicname, otherwise 0
* @param packetid integer - the MQTT packet identifier
* @param topicname null-terminated topic name string
* @return the length of the serialized data. <= 0 indicates error
*/
int MQTTSNSerialize_register(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
MQTTSNString* topicname)
{
unsigned char *ptr = buf;
int len = 0;
int rc = 0;
int topicnamelen = 0;
FUNC_ENTRY;
topicnamelen = (topicname->cstring) ? strlen(topicname->cstring) : topicname->lenstring.len;
if ((len = MQTTSNPacket_len(MQTTSNSerialize_registerLength(topicnamelen))) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_REGISTER); /* write message type */
writeInt(&ptr, topicid);
writeInt(&ptr, packetid);
memcpy(ptr, (topicname->cstring) ? topicname->cstring : topicname->lenstring.data, topicnamelen);
ptr += topicnamelen;
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes the supplied register data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param topicid if sent by a gateway, contains the id for the topicname, otherwise 0
* @param packetid integer - the MQTT packet identifier
* @param return_code integer return code
* @return the length of the serialized data. <= 0 indicates error
*/
int MQTTSNSerialize_regack(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
unsigned char return_code)
{
unsigned char *ptr = buf;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(6)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_REGACK); /* write message type */
writeInt(&ptr, topicid);
writeInt(&ptr, packetid);
writeChar(&ptr, return_code);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(MQTTSNSUBSCRIBE_H_)
#define MQTTSNSUBSCRIBE_H_
int MQTTSNSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned short packetid,
MQTTSN_topicid* topicFilter);
int MQTTSNDeserialize_subscribe(unsigned char* dup, int* qos, unsigned short* packetid,
MQTTSN_topicid* topicFilter, unsigned char* buf, int buflen);
int MQTTSNSerialize_suback(unsigned char* buf, int buflen, int qos, unsigned short topicid, unsigned short packetid,
unsigned char returncode);
int MQTTSNDeserialize_suback(int* qos, unsigned short* topicid, unsigned short* packetid,
unsigned char* returncode, unsigned char* buf, int buflen);
#endif /* MQTTSNSUBSCRIBE_H_ */

View File

@@ -0,0 +1,140 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "MQTTSNPacket.h"
#include "StackTrace.h"
#include <string.h>
/**
* Determines the length of the MQTTSN subscribe packet that would be produced using the supplied parameters,
* excluding length
* @param topicName the topic name to be used in the publish
* @return the length of buffer needed to contain the serialized version of the packet
*/
int MQTTSNSerialize_subscribeLength(MQTTSN_topicid* topicFilter)
{
int len = 4;
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL)
len += topicFilter->data.long_.len;
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT || topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
len += 2;
return len;
}
/**
* Serializes the supplied subscribe data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param dup integer - the MQTT-SN dup flag
* @param qos integer - the MQTT-SN QoS value
* @param packetid integer - the MQTT-SN packet identifier
* @param topic MQTTSN_topicid - the MQTT-SN topic in the subscribe
* @return the length of the serialized data. <= 0 indicates error
*/
int MQTTSNSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned short packetid,
MQTTSN_topicid* topicFilter)
{
unsigned char *ptr = buf;
MQTTSNFlags flags;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(MQTTSNSerialize_subscribeLength(topicFilter))) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_SUBSCRIBE); /* write message type */
flags.all = 0;
flags.bits.dup = dup;
flags.bits.QoS = qos;
flags.bits.topicIdType = topicFilter->type;
writeChar(&ptr, flags.all);
writeInt(&ptr, packetid);
/* now the topic id or name */
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL) /* means long topic name */
{
memcpy(ptr, topicFilter->data.long_.name, topicFilter->data.long_.len);
ptr += topicFilter->data.long_.len;
}
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
writeInt(&ptr, topicFilter->data.id);
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT)
{
writeChar(&ptr, topicFilter->data.short_name[0]);
writeChar(&ptr, topicFilter->data.short_name[1]);
}
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into suback data
* @param qos the returned qos
* @param topicid returned if "accepted" the value which will be used by the gateway in subsequent PUBLISH packets
* @param packetid returned - the same value as the one contained in the corresponding SUBSCRIBE
* @param returncode returned - "accepted" or rejection reason
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_suback(int* qos, unsigned short* topicid, unsigned short* packetid,
unsigned char* returncode, unsigned char* buf, int buflen)
{
MQTTSNFlags flags;
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_SUBACK)
goto exit;
flags.all = readChar(&curdata);
*qos = flags.bits.QoS;
*topicid = readInt(&curdata);
*packetid = readInt(&curdata);
*returncode = readChar(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,119 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "StackTrace.h"
#include "MQTTSNPacket.h"
#include <string.h>
/**
* Deserializes the supplied (wire) buffer into subscribe data
* @param dup the returned MQTT-SN dup flag
* @param qos the returned qos
* @param packetid returned - the same value as the one contained in the corresponding SUBSCRIBE
* @param topicFilter returned - the topic filter - normal, predefined or short
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_subscribe(unsigned char* dup, int* qos, unsigned short* packetid,
MQTTSN_topicid* topicFilter, unsigned char* buf, int buflen)
{
MQTTSNFlags flags;
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_SUBSCRIBE)
goto exit;
flags.all = readChar(&curdata);
*dup = flags.bits.dup;
*qos = flags.bits.QoS;
*packetid = readInt(&curdata);
topicFilter->type = flags.bits.topicIdType;
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL)
{
topicFilter->data.long_.len = enddata - curdata;
topicFilter->data.long_.name = (char*)curdata;
}
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
topicFilter->data.id = readInt(&curdata);
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT)
{
topicFilter->data.short_name[0] = readChar(&curdata);
topicFilter->data.short_name[1] = readChar(&curdata);
}
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Serializes the supplied suback data into the supplied buffer, ready for sending
* @param buf the buffer into which the packet will be serialized
* @param buflen the length in bytes of the supplied buffer
* @param qos integer - the MQTT-SN QoS value
* @param topicid if "accepted" the value which will be used by the gateway in subsequent PUBLISH packets
* @param packetid integer - the MQTT-SN packet identifier
* @param returncode returned - "accepted" or rejection reason
* @return the length of the serialized data. <= 0 indicates error
*/
int MQTTSNSerialize_suback(unsigned char* buf, int buflen, int qos, unsigned short topicid, unsigned short packetid,
unsigned char returncode)
{
MQTTSNFlags flags;
unsigned char *ptr = buf;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(7)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_SUBACK); /* write message type */
flags.all = 0;
flags.bits.QoS = qos;
writeChar(&ptr, flags.all);
writeInt(&ptr, topicid);
writeInt(&ptr, packetid);
writeChar(&ptr, returncode);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(MQTTSNUNSUBSCRIBE_H_)
#define MQTTSNUNSUBSCRIBE_H_
int MQTTSNSerialize_unsubscribe(unsigned char* buf, int buflen,
unsigned short packetid, MQTTSN_topicid* topicFilter);
int MQTTSNDeserialize_unsubscribe(unsigned short* packetid, MQTTSN_topicid* topicFilter,
unsigned char* buf, int buflen);
int MQTTSNSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid);
int MQTTSNDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen);
#endif /* MQTTSNUNSUBSCRIBE_H_ */

View File

@@ -0,0 +1,117 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "MQTTSNPacket.h"
#include "StackTrace.h"
#include <string.h>
/**
* Determines the length of the MQTTSN subscribe packet that would be produced using the supplied parameters,
* excluding length
* @param topicName the topic name to be used in the publish
* @return the length of buffer needed to contain the serialized version of the packet
*/
int MQTTSNSerialize_unsubscribeLength(MQTTSN_topicid* topicFilter)
{
int len = 4;
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL)
len += topicFilter->data.long_.len;
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT || topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
len += 2;
return len;
}
int MQTTSNSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned short packetid, MQTTSN_topicid* topicFilter)
{
unsigned char *ptr = buf;
MQTTSNFlags flags;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(MQTTSNSerialize_unsubscribeLength(topicFilter))) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_UNSUBSCRIBE); /* write message type */
flags.all = 0;
flags.bits.topicIdType = topicFilter->type;
writeChar(&ptr, flags.all);
writeInt(&ptr, packetid);
/* now the topic id or name */
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL) /* means long topic name */
{
memcpy(ptr, topicFilter->data.long_.name, topicFilter->data.long_.len);
ptr += topicFilter->data.long_.len;
}
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
writeInt(&ptr, topicFilter->data.id);
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT)
{
writeChar(&ptr, topicFilter->data.short_name[0]);
writeChar(&ptr, topicFilter->data.short_name[1]);
}
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
/**
* Deserializes the supplied (wire) buffer into unsuback data
* @param packetid returned - the same value as the one contained in the corresponding SUBSCRIBE
* @param buf the raw buffer data, of the correct length determined by the remaining length field
* @param buflen the length in bytes of the data in the supplied buffer
* @return error code. 1 is success
*/
int MQTTSNDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen)
{
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_UNSUBACK)
goto exit;
*packetid = readInt(&curdata);
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "StackTrace.h"
#include "MQTTSNPacket.h"
int MQTTSNDeserialize_unsubscribe(unsigned short* packetid, MQTTSN_topicid* topicFilter,
unsigned char* buf, int buflen)
{
MQTTSNFlags flags;
unsigned char* curdata = buf;
unsigned char* enddata = NULL;
int rc = 0;
int mylen = 0;
FUNC_ENTRY;
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
enddata = buf + mylen;
if (enddata - curdata > buflen)
goto exit;
if (readChar(&curdata) != MQTTSN_UNSUBSCRIBE)
goto exit;
flags.all = readChar(&curdata);
*packetid = readInt(&curdata);
topicFilter->type = flags.bits.topicIdType;
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL)
{
topicFilter->data.long_.len = enddata - curdata;
topicFilter->data.long_.name = (char*)curdata;
}
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
topicFilter->data.id = readInt(&curdata);
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT)
{
topicFilter->data.short_name[0] = readChar(&curdata);
topicFilter->data.short_name[1] = readChar(&curdata);
}
rc = 1;
exit:
FUNC_EXIT_RC(rc);
return rc;
}
int MQTTSNSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid)
{
unsigned char *ptr = buf;
int len = 0;
int rc = 0;
FUNC_ENTRY;
if ((len = MQTTSNPacket_len(7)) > buflen)
{
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
goto exit;
}
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
writeChar(&ptr, MQTTSN_UNSUBACK); /* write message type */
writeInt(&ptr, packetid);
rc = ptr - buf;
exit:
FUNC_EXIT_RC(rc);
return rc;
}

View File

@@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#ifndef STACKTRACE_H_
#define STACKTRACE_H_
#include <stdio.h>
#define NOSTACKTRACE 1
#if defined(NOSTACKTRACE)
#define FUNC_ENTRY
#define FUNC_ENTRY_NOLOG
#define FUNC_ENTRY_MED
#define FUNC_ENTRY_MAX
#define FUNC_EXIT
#define FUNC_EXIT_NOLOG
#define FUNC_EXIT_MED
#define FUNC_EXIT_MAX
#define FUNC_EXIT_RC(x)
#define FUNC_EXIT_MED_RC(x)
#define FUNC_EXIT_MAX_RC(x)
#else
#if defined(WIN32)
#define inline __inline
#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
#else
#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
#endif
#endif
void StackTrace_entry(const char* name, int line, int trace);
void StackTrace_exit(const char* name, int line, void* return_value, int trace);
void StackTrace_printStack(FILE* dest);
char* StackTrace_get(unsigned long);
#endif /* STACKTRACE_H_ */