Add toolchain and mbtk source
Change-Id: Ie12546301367ea59240bf23d5e184ad7e36e40b3
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnect.h b/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnect.h
new file mode 100755
index 0000000..d77f18c
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnect.h
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * 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
+ * Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTCONNECT_H_
+#define MQTTCONNECT_H_
+
+#if !defined(DLLImport)
+ #define DLLImport
+#endif
+#if !defined(DLLExport)
+ #define DLLExport
+#endif
+
+
+typedef union
+{
+ unsigned char all; /**< all connect flags */
+#if defined(REVERSED)
+ struct
+ {
+ unsigned int username : 1; /**< 3.1 user name */
+ unsigned int password : 1; /**< 3.1 password */
+ unsigned int willRetain : 1; /**< will retain setting */
+ unsigned int willQoS : 2; /**< will QoS value */
+ unsigned int will : 1; /**< will flag */
+ unsigned int cleansession : 1; /**< clean session flag */
+ unsigned int : 1; /**< unused */
+ } bits;
+#else
+ struct
+ {
+ unsigned int : 1; /**< unused */
+ unsigned int cleansession : 1; /**< cleansession flag */
+ unsigned int will : 1; /**< will flag */
+ unsigned int willQoS : 2; /**< will QoS value */
+ unsigned int willRetain : 1; /**< will retain setting */
+ unsigned int password : 1; /**< 3.1 password */
+ unsigned int username : 1; /**< 3.1 user name */
+ } bits;
+#endif
+} MQTTConnectFlags; /**< connect flags byte */
+
+
+
+/**
+ * Defines the MQTT "Last Will and Testament" (LWT) settings for
+ * the connect packet.
+ */
+typedef struct
+{
+ /** The eyecatcher for this structure. must be MQTW. */
+ char struct_id[4];
+ /** The version number of this structure. Must be 0 */
+ int struct_version;
+ /** The LWT topic to which the LWT message will be published. */
+ MQTTString topicName;
+ /** The LWT payload. */
+ MQTTString message;
+ /**
+ * The retained flag for the LWT message (see MQTTAsync_message.retained).
+ */
+ unsigned char retained;
+ /**
+ * The quality of service setting for the LWT message (see
+ * MQTTAsync_message.qos and @ref qos).
+ */
+ char qos;
+} MQTTPacket_willOptions;
+
+
+#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
+
+
+typedef struct
+{
+ /** The eyecatcher for this structure. must be MQTC. */
+ char struct_id[4];
+ /** The version number of this structure. Must be 0 */
+ int struct_version;
+ /** Version of MQTT to be used. 3 = 3.1 4 = 3.1.1
+ */
+ unsigned char MQTTVersion;
+ MQTTString clientID;
+ unsigned short keepAliveInterval;
+ unsigned char cleansession;
+ unsigned char willFlag;
+ MQTTPacket_willOptions will;
+ MQTTString username;
+ MQTTString password;
+} MQTTPacket_connectData;
+
+typedef union
+{
+ unsigned char all; /**< all connack flags */
+#if defined(REVERSED)
+ struct
+ {
+ unsigned int sessionpresent : 1; /**< session present flag */
+ unsigned int : 7; /**< unused */
+ } bits;
+#else
+ struct
+ {
+ unsigned int : 7; /**< unused */
+ unsigned int sessionpresent : 1; /**< session present flag */
+ } bits;
+#endif
+} MQTTConnackFlags; /**< connack flags byte */
+
+#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
+ MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
+
+DLLExport int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options);
+DLLExport int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len);
+
+DLLExport int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent);
+DLLExport int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen);
+
+DLLExport int MQTTSerialize_disconnect(unsigned char* buf, int buflen);
+DLLExport int MQTTSerialize_pingreq(unsigned char* buf, int buflen);
+
+#endif /* MQTTCONNECT_H_ */
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnectClient.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnectClient.c
new file mode 100755
index 0000000..405c23e
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnectClient.c
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * 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 "MQTTPacket.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 MQTTSerialize_connectLength(MQTTPacket_connectData* options)
+{
+ int len = 0;
+
+ FUNC_ENTRY;
+
+ if (options->MQTTVersion == 3)
+ len = 12; /* variable depending on MQTT or MQIsdp */
+ else if (options->MQTTVersion == 4)
+ len = 10;
+
+ len += MQTTstrlen(options->clientID)+2;
+ if (options->willFlag)
+ len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2;
+ if (options->username.cstring || options->username.lenstring.data)
+ len += MQTTstrlen(options->username)+2;
+ if (options->password.cstring || options->password.lenstring.data)
+ len += MQTTstrlen(options->password)+2;
+
+ 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 MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options)
+{
+ unsigned char *ptr = buf;
+ MQTTHeader header = {0};
+ MQTTConnectFlags flags = {0};
+ int len = 0;
+ int rc = -1;
+
+ FUNC_ENTRY;
+ if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+
+ header.byte = 0;
+ header.bits.type = CONNECT;
+ writeChar(&ptr, header.byte); /* write header */
+ ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
+ if (options->MQTTVersion == 4)
+ {
+ writeCString(&ptr, "MQTT");
+ writeChar(&ptr, (char) 4);
+ }
+ else
+ {
+ writeCString(&ptr, "MQIsdp");
+ writeChar(&ptr, (char) 3);
+ }
+
+ flags.all = 0;
+ flags.bits.cleansession = options->cleansession;
+ flags.bits.will = (options->willFlag) ? 1 : 0;
+ if (flags.bits.will)
+ {
+ flags.bits.willQoS = options->will.qos;
+ flags.bits.willRetain = options->will.retained;
+ }
+
+ if (options->username.cstring || options->username.lenstring.data)
+ flags.bits.username = 1;
+ if (options->password.cstring || options->password.lenstring.data)
+ flags.bits.password = 1;
+ writeChar(&ptr, flags.all);
+ writeInt(&ptr, options->keepAliveInterval);
+ writeMQTTString(&ptr, options->clientID);
+ if (options->willFlag)
+ {
+ writeMQTTString(&ptr, options->will.topicName);
+ writeMQTTString(&ptr, options->will.message);
+ }
+ if (flags.bits.username)
+ writeMQTTString(&ptr, options->username);
+ if (flags.bits.password)
+ writeMQTTString(&ptr, options->password);
+
+ rc = ptr - buf;
+
+ exit: FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
+/**
+ * Deserializes the supplied (wire) buffer into connack data - return code
+ * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
+ * @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 MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char* curdata = buf;
+ unsigned char* enddata = NULL;
+ int rc = 0;
+ int mylen;
+ MQTTConnackFlags flags = {0};
+
+ FUNC_ENTRY;
+ header.byte = readChar(&curdata);
+ if (header.bits.type != CONNACK)
+ goto exit;
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+ if (enddata - curdata < 2)
+ goto exit;
+
+ flags.all = readChar(&curdata);
+ *sessionPresent = flags.bits.sessionpresent;
+ *connack_rc = readChar(&curdata);
+
+ rc = 1;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
+/**
+ * Serializes a 0-length 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 packettype the message type
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype)
+{
+ MQTTHeader header = {0};
+ int rc = -1;
+ unsigned char *ptr = buf;
+
+ FUNC_ENTRY;
+ if (buflen < 2)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+ header.byte = 0;
+ header.bits.type = packettype;
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
+ 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
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_disconnect(unsigned char* buf, int buflen)
+{
+ return MQTTSerialize_zero(buf, buflen, DISCONNECT);
+}
+
+
+/**
+ * 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
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_pingreq(unsigned char* buf, int buflen)
+{
+ return MQTTSerialize_zero(buf, buflen, PINGREQ);
+}
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnectServer.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnectServer.c
new file mode 100755
index 0000000..7c1fe50
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTConnectServer.c
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * 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 "MQTTPacket.h"
+#include <string.h>
+
+#define min(a, b) ((a < b) ? a : b)
+
+
+/**
+ * Validates MQTT protocol name and version combinations
+ * @param protocol the MQTT protocol name as an MQTTString
+ * @param version the MQTT protocol version number, as in the connect packet
+ * @return correct MQTT combination? 1 is true, 0 is false
+ */
+int MQTTPacket_checkVersion(MQTTString* protocol, int version)
+{
+ int rc = 0;
+
+ if (version == 3 && memcmp(protocol->lenstring.data, "MQIsdp",
+ min(6, protocol->lenstring.len)) == 0)
+ rc = 1;
+ else if (version == 4 && memcmp(protocol->lenstring.data, "MQTT",
+ min(4, protocol->lenstring.len)) == 0)
+ rc = 1;
+ return rc;
+}
+
+
+/**
+ * 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 MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len)
+{
+ MQTTHeader header = {0};
+ MQTTConnectFlags flags = {0};
+ unsigned char* curdata = buf;
+ unsigned char* enddata = &buf[len];
+ int rc = 0;
+ MQTTString Protocol;
+ int version;
+ int mylen = 0;
+
+ FUNC_ENTRY;
+ header.byte = readChar(&curdata);
+ if (header.bits.type != CONNECT)
+ goto exit;
+
+ curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */
+
+ if (!readMQTTLenString(&Protocol, &curdata, enddata) ||
+ enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */
+ goto exit;
+
+ version = (int)readChar(&curdata); /* Protocol version */
+ /* If we don't recognize the protocol version, we don't parse the connect packet on the
+ * basis that we don't know what the format will be.
+ */
+ if (MQTTPacket_checkVersion(&Protocol, version))
+ {
+ flags.all = readChar(&curdata);
+ data->cleansession = flags.bits.cleansession;
+ data->keepAliveInterval = readInt(&curdata);
+ if (!readMQTTLenString(&data->clientID, &curdata, enddata))
+ goto exit;
+ data->willFlag = flags.bits.will;
+ if (flags.bits.will)
+ {
+ data->will.qos = flags.bits.willQoS;
+ data->will.retained = flags.bits.willRetain;
+ if (!readMQTTLenString(&data->will.topicName, &curdata, enddata) ||
+ !readMQTTLenString(&data->will.message, &curdata, enddata))
+ goto exit;
+ }
+ if (flags.bits.username)
+ {
+ if (enddata - curdata < 3 || !readMQTTLenString(&data->username, &curdata, enddata))
+ goto exit; /* username flag set, but no username supplied - invalid */
+ if (flags.bits.password &&
+ (enddata - curdata < 3 || !readMQTTLenString(&data->password, &curdata, enddata)))
+ goto exit; /* password flag set, but no password supplied - invalid */
+ }
+ else if (flags.bits.password)
+ goto exit; /* password flag set without username - invalid */
+ 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
+ * @param sessionPresent the MQTT 3.1.1 sessionPresent flag
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent)
+{
+ MQTTHeader header = {0};
+ int rc = 0;
+ unsigned char *ptr = buf;
+ MQTTConnackFlags flags = {0};
+
+ FUNC_ENTRY;
+ if (buflen < 2)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+ header.byte = 0;
+ header.bits.type = CONNACK;
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+
+ flags.all = 0;
+ flags.bits.sessionpresent = sessionPresent;
+ writeChar(&ptr, flags.all);
+ writeChar(&ptr, connack_rc);
+
+ rc = ptr - buf;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTDeserializePublish.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTDeserializePublish.c
new file mode 100755
index 0000000..dbc9e5d
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTDeserializePublish.c
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * 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 "MQTTPacket.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 MQTTString - 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 MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+ unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char* curdata = buf;
+ unsigned char* enddata = NULL;
+ int rc = 0;
+ int mylen = 0;
+
+ FUNC_ENTRY;
+ header.byte = readChar(&curdata);
+ if (header.bits.type != PUBLISH)
+ goto exit;
+ *dup = header.bits.dup;
+ *qos = header.bits.qos;
+ *retained = header.bits.retain;
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+
+ if (!readMQTTLenString(topicName, &curdata, enddata) ||
+ enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */
+ goto exit;
+
+ if (*qos > 0)
+ *packetid = readInt(&curdata);
+
+ *payloadlen = enddata - curdata;
+ *payload = 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 dup returned integer - the MQTT dup flag
+ * @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 MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char* curdata = buf;
+ unsigned char* enddata = NULL;
+ int rc = 0;
+ int mylen;
+
+ FUNC_ENTRY;
+ header.byte = readChar(&curdata);
+ *dup = header.bits.dup;
+ *packettype = header.bits.type;
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+
+ if (enddata - curdata < 2)
+ goto exit;
+ *packetid = readInt(&curdata);
+
+ rc = 1;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTFormat.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTFormat.c
new file mode 100755
index 0000000..3015a0e
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTFormat.c
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * 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 "MQTTPacket.h"
+
+#include <string.h>
+
+
+const char* MQTTPacket_names[] =
+{
+ "RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL",
+ "PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK",
+ "PINGREQ", "PINGRESP", "DISCONNECT"
+};
+
+
+const char* MQTTPacket_getName(unsigned short packetid)
+{
+ return MQTTPacket_names[packetid];
+}
+
+
+int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data)
+{
+ int strindex = 0;
+
+ strindex = snprintf(strbuf, strbuflen,
+ "CONNECT MQTT version %d, client id %.*s, clean session %d, keep alive %d",
+ (int)data->MQTTVersion, data->clientID.lenstring.len, data->clientID.lenstring.data,
+ (int)data->cleansession, data->keepAliveInterval);
+ if (data->willFlag)
+ strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+ ", will QoS %d, will retain %d, will topic %.*s, will message %.*s",
+ data->will.qos, data->will.retained,
+ data->will.topicName.lenstring.len, data->will.topicName.lenstring.data,
+ data->will.message.lenstring.len, data->will.message.lenstring.data);
+ if (data->username.lenstring.data && data->username.lenstring.len > 0)
+ strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+ ", user name %.*s", data->username.lenstring.len, data->username.lenstring.data);
+ if (data->password.lenstring.data && data->password.lenstring.len > 0)
+ strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+ ", password %.*s", data->password.lenstring.len, data->password.lenstring.data);
+ return strindex;
+}
+
+
+int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent)
+{
+ int strindex = snprintf(strbuf, strbuflen, "CONNACK session present %d, rc %d", sessionPresent, connack_rc);
+ return strindex;
+}
+
+
+int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained,
+ unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen)
+{
+ int strindex = snprintf(strbuf, strbuflen,
+ "PUBLISH dup %d, QoS %d, retained %d, packet id %d, topic %.*s, payload length %d, payload %.*s",
+ dup, qos, retained, packetid,
+ (topicName.lenstring.len < 20) ? topicName.lenstring.len : 20, topicName.lenstring.data,
+ payloadlen, (payloadlen < 20) ? payloadlen : 20, payload);
+ return strindex;
+}
+
+
+int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid)
+{
+ int strindex = snprintf(strbuf, strbuflen, "%s, packet id %d", MQTTPacket_names[packettype], packetid);
+ if (dup)
+ strindex += snprintf(strbuf + strindex, strbuflen - strindex, ", dup %d", dup);
+ return strindex;
+}
+
+
+int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count,
+ MQTTString topicFilters[], int requestedQoSs[])
+{
+ return snprintf(strbuf, strbuflen,
+ "SUBSCRIBE dup %d, packet id %d count %d topic %.*s qos %d",
+ dup, packetid, count,
+ topicFilters[0].lenstring.len, topicFilters[0].lenstring.data,
+ requestedQoSs[0]);
+}
+
+
+int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs)
+{
+ return snprintf(strbuf, strbuflen,
+ "SUBACK packet id %d count %d granted qos %d", packetid, count, grantedQoSs[0]);
+}
+
+
+int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid,
+ int count, MQTTString topicFilters[])
+{
+ return snprintf(strbuf, strbuflen,
+ "UNSUBSCRIBE dup %d, packet id %d count %d topic %.*s",
+ dup, packetid, count,
+ topicFilters[0].lenstring.len, topicFilters[0].lenstring.data);
+}
+
+
+char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen)
+{
+ int index = 0;
+ int rem_length = 0;
+ MQTTHeader header = {0};
+ int strindex = 0;
+
+ header.byte = buf[index++];
+ index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
+
+ switch (header.bits.type)
+ {
+ case CONNACK:
+ {
+ unsigned char sessionPresent, connack_rc;
+ if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) == 1)
+ strindex = MQTTStringFormat_connack(strbuf, strbuflen, connack_rc, sessionPresent);
+ }
+ break;
+ case PUBLISH:
+ {
+ unsigned char dup, retained, *payload;
+ unsigned short packetid;
+ int qos, payloadlen;
+ MQTTString topicName = MQTTString_initializer;
+ if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
+ &payload, &payloadlen, buf, buflen) == 1)
+ strindex = MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, packetid,
+ topicName, payload, payloadlen);
+ }
+ break;
+ case PUBACK:
+ case PUBREC:
+ case PUBREL:
+ case PUBCOMP:
+ {
+ unsigned char packettype, dup;
+ unsigned short packetid;
+ if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
+ strindex = MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
+ }
+ break;
+ case SUBACK:
+ {
+ unsigned short packetid;
+ int maxcount = 1, count = 0;
+ int grantedQoSs[1];
+ if (MQTTDeserialize_suback(&packetid, maxcount, &count, grantedQoSs, buf, buflen) == 1)
+ strindex = MQTTStringFormat_suback(strbuf, strbuflen, packetid, count, grantedQoSs);
+ }
+ break;
+ case UNSUBACK:
+ {
+ unsigned short packetid;
+ if (MQTTDeserialize_unsuback(&packetid, buf, buflen) == 1)
+ strindex = MQTTStringFormat_ack(strbuf, strbuflen, UNSUBACK, 0, packetid);
+ }
+ break;
+ case PINGREQ:
+ case PINGRESP:
+ case DISCONNECT:
+ strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
+ break;
+ }
+ return strbuf;
+}
+
+
+char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen)
+{
+ int index = 0;
+ int rem_length = 0;
+ MQTTHeader header = {0};
+ int strindex = 0;
+
+ header.byte = buf[index++];
+ index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
+
+ switch (header.bits.type)
+ {
+ case CONNECT:
+ {
+ MQTTPacket_connectData data;
+ int rc;
+ if ((rc = MQTTDeserialize_connect(&data, buf, buflen)) == 1)
+ strindex = MQTTStringFormat_connect(strbuf, strbuflen, &data);
+ }
+ break;
+ case PUBLISH:
+ {
+ unsigned char dup, retained, *payload;
+ unsigned short packetid;
+ int qos, payloadlen;
+ MQTTString topicName = MQTTString_initializer;
+ if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
+ &payload, &payloadlen, buf, buflen) == 1)
+ strindex = MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, packetid,
+ topicName, payload, payloadlen);
+ }
+ break;
+ case PUBACK:
+ case PUBREC:
+ case PUBREL:
+ case PUBCOMP:
+ {
+ unsigned char packettype, dup;
+ unsigned short packetid;
+ if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
+ strindex = MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
+ }
+ break;
+ case SUBSCRIBE:
+ {
+ unsigned char dup;
+ unsigned short packetid;
+ int maxcount = 1, count = 0;
+ MQTTString topicFilters[1];
+ int requestedQoSs[1];
+ if (MQTTDeserialize_subscribe(&dup, &packetid, maxcount, &count,
+ topicFilters, requestedQoSs, buf, buflen) == 1)
+ strindex = MQTTStringFormat_subscribe(strbuf, strbuflen, dup, packetid, count, topicFilters, requestedQoSs);;
+ }
+ break;
+ case UNSUBSCRIBE:
+ {
+ unsigned char dup;
+ unsigned short packetid;
+ int maxcount = 1, count = 0;
+ MQTTString topicFilters[1];
+ if (MQTTDeserialize_unsubscribe(&dup, &packetid, maxcount, &count, topicFilters, buf, buflen) == 1)
+ strindex = MQTTStringFormat_unsubscribe(strbuf, strbuflen, dup, packetid, count, topicFilters);
+ }
+ break;
+ case PINGREQ:
+ case PINGRESP:
+ case DISCONNECT:
+ strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
+ break;
+ }
+ strbuf[strbuflen] = '\0';
+ return strbuf;
+}
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTFormat.h b/mbtk/mbtk_mqtt/MQTTPacket/MQTTFormat.h
new file mode 100755
index 0000000..f7bd0d1
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTFormat.h
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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(MQTTFORMAT_H)
+#define MQTTFORMAT_H
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+
+const char* MQTTPacket_getName(unsigned short packetid);
+int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data);
+int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent);
+int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained,
+ unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen);
+int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid);
+int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count,
+ MQTTString topicFilters[], int requestedQoSs[]);
+int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs);
+int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid,
+ int count, MQTTString topicFilters[]);
+char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen);
+char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen);
+
+#endif
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTPacket.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTPacket.c
new file mode 100755
index 0000000..c100f55
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTPacket.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * 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
+ * Sergio R. Caprile - non-blocking packet read functions for stream transport
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+
+#include <string.h>
+
+/**
+ * Encodes the message length according to the MQTT algorithm
+ * @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 buffer
+ */
+int MQTTPacket_encode(unsigned char* buf, int length)
+{
+ int rc = 0;
+
+ FUNC_ENTRY;
+ do
+ {
+ char d = length % 128;
+ length /= 128;
+ /* if there are more digits to encode, set the top bit of this digit */
+ if (length > 0)
+ d |= 0x80;
+ buf[rc++] = d;
+ } while (length > 0);
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
+/**
+ * Decodes the message length according to the MQTT algorithm
+ * @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 MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value)
+{
+ unsigned char c;
+ int multiplier = 1;
+ int len = 0;
+#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
+
+ FUNC_ENTRY;
+ *value = 0;
+ do
+ {
+ int rc = MQTTPACKET_READ_ERROR;
+
+ if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+ {
+ rc = MQTTPACKET_READ_ERROR; /* bad data */
+ goto exit;
+ }
+ rc = (*getcharfn)(&c, 1);
+ if (rc != 1)
+ goto exit;
+ *value += (c & 127) * multiplier;
+ multiplier *= 128;
+ } while ((c & 128) != 0);
+exit:
+ FUNC_EXIT_RC(len);
+ return len;
+}
+
+
+int MQTTPacket_len(int rem_len)
+{
+ rem_len += 1; /* header byte */
+
+ /* now remaining_length field */
+ if (rem_len < 128)
+ rem_len += 1;
+ else if (rem_len < 16384)
+ rem_len += 2;
+ else if (rem_len < 2097151)
+ rem_len += 3;
+ else
+ rem_len += 4;
+ return rem_len;
+}
+
+
+static unsigned char* bufptr;
+
+int bufchar(unsigned char* c, int count)
+{
+ int i;
+
+ for (i = 0; i < count; ++i)
+ *c = *bufptr++;
+ return count;
+}
+
+
+int MQTTPacket_decodeBuf(unsigned char* buf, int* value)
+{
+ bufptr = buf;
+ return MQTTPacket_decode(bufchar, value);
+}
+
+
+/**
+ * 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*(*ptr) + (*(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 = 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
+ */
+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, const char* string)
+{
+ int len = strlen(string);
+ writeInt(pptr, len);
+ memcpy(*pptr, string, len);
+ *pptr += len;
+}
+
+
+int getLenStringLen(char* ptr)
+{
+ int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
+ return len;
+}
+
+
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring)
+{
+ if (mqttstring.lenstring.len > 0)
+ {
+ writeInt(pptr, mqttstring.lenstring.len);
+ memcpy(*pptr, mqttstring.lenstring.data, mqttstring.lenstring.len);
+ *pptr += mqttstring.lenstring.len;
+ }
+ else if (mqttstring.cstring)
+ writeCString(pptr, mqttstring.cstring);
+ else
+ writeInt(pptr, 0);
+}
+
+
+/**
+ * @param mqttstring the MQTTString 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 readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata)
+{
+ int rc = 0;
+
+ FUNC_ENTRY;
+ /* the first two bytes are the length of the string */
+ if (enddata - (*pptr) > 1) /* enough length to read the integer? */
+ {
+ mqttstring->lenstring.len = readInt(pptr); /* increments pptr to point past length */
+ if (&(*pptr)[mqttstring->lenstring.len] <= enddata)
+ {
+ mqttstring->lenstring.data = (char*)*pptr;
+ *pptr += mqttstring->lenstring.len;
+ rc = 1;
+ }
+ }
+ mqttstring->cstring = NULL;
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
+/**
+ * Return the length of the MQTTstring - C string if there is one, otherwise the length delimited string
+ * @param mqttstring the string to return the length of
+ * @return the length of the string
+ */
+int MQTTstrlen(MQTTString mqttstring)
+{
+ int rc = 0;
+
+ if (mqttstring.cstring)
+ rc = strlen(mqttstring.cstring);
+ else
+ rc = mqttstring.lenstring.len;
+ return rc;
+}
+
+
+/**
+ * Compares an MQTTString to a C string
+ * @param a the MQTTString to compare
+ * @param bptr the C string to compare
+ * @return boolean - equal or not
+ */
+int MQTTPacket_equals(MQTTString* a, char* bptr)
+{
+ int alen = 0,
+ blen = 0;
+ char *aptr;
+
+ if (a->cstring)
+ {
+ aptr = a->cstring;
+ alen = strlen(a->cstring);
+ }
+ else
+ {
+ aptr = a->lenstring.data;
+ alen = a->lenstring.len;
+ }
+ blen = strlen(bptr);
+
+ return (alen == blen) && (strncmp(aptr, bptr, alen) == 0);
+}
+
+
+/**
+ * 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 -1 on error
+ * @note the whole message must fit into the caller's buffer
+ */
+int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int))
+{
+ int rc = -1;
+ MQTTHeader header = {0};
+ int len = 0;
+ int rem_len = 0;
+
+ /* 1. read the header byte. This has the packet type in it */
+ if ((*getfn)(buf, 1) != 1)
+ goto exit;
+
+ len = 1;
+ /* 2. read the remaining length. This is variable in itself */
+ MQTTPacket_decode(getfn, &rem_len);
+ len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */
+
+ /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+ if((rem_len + len) > buflen)
+ goto exit;
+ if ((*getfn)(buf + len, rem_len) != rem_len)
+ goto exit;
+
+ header.byte = buf[0];
+ rc = header.bits.type;
+exit:
+ return rc;
+}
+
+/**
+ * Decodes the message length according to the MQTT algorithm, non-blocking
+ * @param trp pointer to a transport structure holding what is needed to solve getting data from it
+ * @param value the decoded length returned
+ * @return integer the number of bytes read from the socket, 0 for call again, or -1 on error
+ */
+static int MQTTPacket_decodenb(MQTTTransport *trp)
+{
+ unsigned char c;
+ int rc = MQTTPACKET_READ_ERROR;
+
+ FUNC_ENTRY;
+ if(trp->len == 0){ /* initialize on first call */
+ trp->multiplier = 1;
+ trp->rem_len = 0;
+ }
+ do {
+ int frc;
+ if (++(trp->len) > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+ goto exit;
+ if ((frc=(*trp->getfn)(trp->sck, &c, 1)) == -1)
+ goto exit;
+ if (frc == 0){
+ rc = 0;
+ goto exit;
+ }
+ trp->rem_len += (c & 127) * trp->multiplier;
+ trp->multiplier *= 128;
+ } while ((c & 128) != 0);
+ rc = trp->len;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+/**
+ * Helper function to read packet data from some source into a buffer, non-blocking
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param trp pointer to a transport structure holding what is needed to solve getting data from it
+ * @return integer MQTT packet type, 0 for call again, or -1 on error
+ * @note the whole message must fit into the caller's buffer
+ */
+int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp)
+{
+ int rc = -1, frc;
+ MQTTHeader header = {0};
+
+ switch(trp->state){
+ default:
+ trp->state = 0;
+ /*FALLTHROUGH*/
+ case 0:
+ /* read the header byte. This has the packet type in it */
+ if ((frc=(*trp->getfn)(trp->sck, buf, 1)) == -1)
+ goto exit;
+ if (frc == 0)
+ return 0;
+ trp->len = 0;
+ ++trp->state;
+ /*FALLTHROUGH*/
+ /* read the remaining length. This is variable in itself */
+ case 1:
+ if((frc=MQTTPacket_decodenb(trp)) == MQTTPACKET_READ_ERROR)
+ goto exit;
+ if(frc == 0)
+ return 0;
+ trp->len = 1 + MQTTPacket_encode(buf + 1, trp->rem_len); /* put the original remaining length back into the buffer */
+ if((trp->rem_len + trp->len) > buflen)
+ goto exit;
+ ++trp->state;
+ /*FALLTHROUGH*/
+ case 2:
+ /* read the rest of the buffer using a callback to supply the rest of the data */
+ if ((frc=(*trp->getfn)(trp->sck, buf + trp->len, trp->rem_len)) == -1)
+ goto exit;
+ if (frc == 0)
+ return 0;
+ trp->rem_len -= frc;
+ trp->len += frc;
+ if(trp->rem_len)
+ return 0;
+
+ header.byte = buf[0];
+ rc = header.bits.type;
+ break;
+ }
+
+exit:
+ trp->state = 0;
+ return rc;
+}
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTPacket.h b/mbtk/mbtk_mqtt/MQTTPacket/MQTTPacket.h
new file mode 100755
index 0000000..f417929
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTPacket.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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
+ * Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTPACKET_H_
+#define MQTTPACKET_H_
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#if defined(WIN32_DLL) || defined(WIN64_DLL)
+ #define DLLImport __declspec(dllimport)
+ #define DLLExport __declspec(dllexport)
+#elif defined(LINUX_SO)
+ #define DLLImport extern
+ #define DLLExport __attribute__ ((visibility ("default")))
+#else
+ #define DLLImport
+ #define DLLExport
+#endif
+
+enum errors
+{
+ MQTTPACKET_BUFFER_TOO_SHORT = -2,
+ MQTTPACKET_READ_ERROR = -1,
+ MQTTPACKET_READ_COMPLETE
+};
+
+enum msgTypes
+{
+ CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
+ PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
+ PINGREQ, PINGRESP, DISCONNECT
+};
+
+/**
+ * Bitfields for the MQTT header byte.
+ */
+typedef union
+{
+ unsigned char byte; /**< the whole byte */
+#if defined(REVERSED)
+ struct
+ {
+ unsigned int type : 4; /**< message type nibble */
+ unsigned int dup : 1; /**< DUP flag bit */
+ unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
+ unsigned int retain : 1; /**< retained flag bit */
+ } bits;
+#else
+ struct
+ {
+ unsigned int retain : 1; /**< retained flag bit */
+ unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
+ unsigned int dup : 1; /**< DUP flag bit */
+ unsigned int type : 4; /**< message type nibble */
+ } bits;
+#endif
+} MQTTHeader;
+
+typedef struct
+{
+ int len;
+ char* data;
+} MQTTLenString;
+
+typedef struct
+{
+ char* cstring;
+ MQTTLenString lenstring;
+} MQTTString;
+
+#define MQTTString_initializer {NULL, {0, NULL}}
+
+int MQTTstrlen(MQTTString mqttstring);
+
+#include "MQTTConnect.h"
+#include "MQTTPublish.h"
+#include "MQTTSubscribe.h"
+#include "MQTTUnsubscribe.h"
+#include "MQTTFormat.h"
+
+int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid);
+int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen);
+
+int MQTTPacket_len(int rem_len);
+int MQTTPacket_equals(MQTTString* a, char* b);
+
+int MQTTPacket_encode(unsigned char* buf, int length);
+int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value);
+int MQTTPacket_decodeBuf(unsigned char* buf, 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 readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata);
+void writeCString(unsigned char** pptr, const char* string);
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring);
+
+DLLExport int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int));
+
+typedef struct {
+ int (*getfn)(void *, unsigned char*, int); /* must return -1 for error, 0 for call again, or the number of bytes read */
+ void *sck; /* pointer to whatever the system may use to identify the transport */
+ int multiplier;
+ int rem_len;
+ int len;
+ char state;
+}MQTTTransport;
+
+int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp);
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+
+#endif /* MQTTPACKET_H_ */
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTPublish.h b/mbtk/mbtk_mqtt/MQTTPacket/MQTTPublish.h
new file mode 100755
index 0000000..d62dddb
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTPublish.h
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTPUBLISH_H_
+#define MQTTPUBLISH_H_
+
+#if !defined(DLLImport)
+ #define DLLImport
+#endif
+#if !defined(DLLExport)
+ #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
+ MQTTString topicName, unsigned char* payload, int payloadlen);
+
+DLLExport int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+ unsigned char** payload, int* payloadlen, unsigned char* buf, int len);
+
+DLLExport int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid);
+DLLExport int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid);
+DLLExport int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid);
+
+#endif /* MQTTPUBLISH_H_ */
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTSerializePublish.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTSerializePublish.c
new file mode 100755
index 0000000..236791f
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTSerializePublish.c
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * 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
+ * Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144
+ *******************************************************************************/
+
+#include "MQTTPacket.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 MQTTSerialize_publishLength(int qos, MQTTString topicName, int payloadlen)
+{
+ int len = 0;
+
+ len += 2 + MQTTstrlen(topicName) + payloadlen;
+ if (qos > 0)
+ len += 2; /* packetid */
+ return 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 topicName MQTTString - 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 MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
+ MQTTString topicName, unsigned char* payload, int payloadlen)
+{
+ unsigned char *ptr = buf;
+ MQTTHeader header = {0};
+ int rem_len = 0;
+ int rc = 0;
+
+ FUNC_ENTRY;
+ if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+
+ header.bits.type = PUBLISH;
+ header.bits.dup = dup;
+ header.bits.qos = qos;
+ header.bits.retain = retained;
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+ writeMQTTString(&ptr, topicName);
+
+ if (qos > 0)
+ writeInt(&ptr, packetid);
+
+ memcpy(ptr, payload, payloadlen);
+ ptr += payloadlen;
+
+ 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 packet type
+ * @param dup the MQTT dup flag
+ * @param packetid the MQTT packet identifier
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char packettype, unsigned char dup, unsigned short packetid)
+{
+ MQTTHeader header = {0};
+ int rc = 0;
+ unsigned char *ptr = buf;
+
+ FUNC_ENTRY;
+ if (buflen < 4)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+ header.bits.type = packettype;
+ header.bits.dup = dup;
+ header.bits.qos = (packettype == PUBREL) ? 1 : 0;
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+ 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 MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid)
+{
+ return MQTTSerialize_ack(buf, buflen, PUBACK, 0, 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 MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid)
+{
+ return MQTTSerialize_ack(buf, buflen, PUBREL, dup, 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 MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid)
+{
+ return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid);
+}
+
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribe.h b/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribe.h
new file mode 100755
index 0000000..383ca0d
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribe.h
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ * Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTSUBSCRIBE_H_
+#define MQTTSUBSCRIBE_H_
+
+#if !defined(DLLImport)
+ #define DLLImport
+#endif
+#if !defined(DLLExport)
+ #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+ int count, MQTTString topicFilters[], int requestedQoSs[]);
+
+DLLExport int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid,
+ int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int len);
+
+DLLExport int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs);
+
+DLLExport int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int len);
+
+
+#endif /* MQTTSUBSCRIBE_H_ */
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribeClient.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribeClient.c
new file mode 100755
index 0000000..5b1ca28
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribeClient.c
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * 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 "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+ * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters
+ * @param count the number of topic filter strings in topicFilters
+ * @param topicFilters the array of topic filter strings to be used in the publish
+ * @return the length of buffer needed to contain the serialized version of the packet
+ */
+int MQTTSerialize_subscribeLength(int count, MQTTString topicFilters[])
+{
+ int i;
+ int len = 2; /* packetid */
+
+ for (i = 0; i < count; ++i)
+ len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */
+ 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 bufferr
+ * @param dup integer - the MQTT dup flag
+ * @param packetid integer - the MQTT packet identifier
+ * @param count - number of members in the topicFilters and reqQos arrays
+ * @param topicFilters - array of topic filter names
+ * @param requestedQoSs - array of requested QoS
+ * @return the length of the serialized data. <= 0 indicates error
+ */
+int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, int count,
+ MQTTString topicFilters[], int requestedQoSs[])
+{
+ unsigned char *ptr = buf;
+ MQTTHeader header = {0};
+ int rem_len = 0;
+ int rc = 0;
+ int i = 0;
+
+ FUNC_ENTRY;
+ if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+
+ header.byte = 0;
+ header.bits.type = SUBSCRIBE;
+ header.bits.dup = dup;
+ header.bits.qos = 1;
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+ writeInt(&ptr, packetid);
+
+ for (i = 0; i < count; ++i)
+ {
+ writeMQTTString(&ptr, topicFilters[i]);
+ writeChar(&ptr, requestedQoSs[i]);
+ }
+
+ rc = ptr - buf;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
+
+/**
+ * Deserializes the supplied (wire) buffer into suback data
+ * @param packetid returned integer - the MQTT packet identifier
+ * @param maxcount - the maximum number of members allowed in the grantedQoSs array
+ * @param count returned integer - number of members in the grantedQoSs array
+ * @param grantedQoSs returned array of integers - the granted qualities of service
+ * @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 MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char* curdata = buf;
+ unsigned char* enddata = NULL;
+ int rc = 0;
+ int mylen;
+
+ FUNC_ENTRY;
+ header.byte = readChar(&curdata);
+ if (header.bits.type != SUBACK)
+ goto exit;
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+ if (enddata - curdata < 2)
+ goto exit;
+
+ *packetid = readInt(&curdata);
+
+ *count = 0;
+ while (curdata < enddata)
+ {
+ if (*count > maxcount)
+ {
+ rc = -1;
+ goto exit;
+ }
+ grantedQoSs[(*count)++] = readChar(&curdata);
+ }
+
+ rc = 1;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribeServer.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribeServer.c
new file mode 100755
index 0000000..15bb15d
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTSubscribeServer.c
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * 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 "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+ * Deserializes the supplied (wire) buffer into subscribe data
+ * @param dup integer returned - the MQTT dup flag
+ * @param packetid integer returned - the MQTT packet identifier
+ * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
+ * @param count - number of members in the topicFilters and requestedQoSs arrays
+ * @param topicFilters - array of topic filter names
+ * @param requestedQoSs - array of requested QoS
+ * @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 the length of the serialized data. <= 0 indicates error
+ */
+int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
+ int requestedQoSs[], unsigned char* buf, int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char* curdata = buf;
+ unsigned char* enddata = NULL;
+ int rc = -1;
+ int mylen = 0;
+
+ FUNC_ENTRY;
+ header.byte = readChar(&curdata);
+ if (header.bits.type != SUBSCRIBE)
+ goto exit;
+ *dup = header.bits.dup;
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+
+ *packetid = readInt(&curdata);
+
+ *count = 0;
+ while (curdata < enddata)
+ {
+ if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
+ goto exit;
+ if (curdata >= enddata) /* do we have enough data to read the req_qos version byte? */
+ goto exit;
+ requestedQoSs[*count] = readChar(&curdata);
+ (*count)++;
+ }
+
+ 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 packetid integer - the MQTT packet identifier
+ * @param count - number of members in the grantedQoSs array
+ * @param grantedQoSs - array of granted QoS
+ * @return the length of the serialized data. <= 0 indicates error
+ */
+int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs)
+{
+ MQTTHeader header = {0};
+ int rc = -1;
+ unsigned char *ptr = buf;
+ int i;
+
+ FUNC_ENTRY;
+ if (buflen < 2 + count)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+ header.byte = 0;
+ header.bits.type = SUBACK;
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, 2 + count); /* write remaining length */
+
+ writeInt(&ptr, packetid);
+
+ for (i = 0; i < count; ++i)
+ writeChar(&ptr, grantedQoSs[i]);
+
+ rc = ptr - buf;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribe.h b/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribe.h
new file mode 100755
index 0000000..1644ae5
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribe.h
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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
+ * Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTUNSUBSCRIBE_H_
+#define MQTTUNSUBSCRIBE_H_
+
+#if !defined(DLLImport)
+ #define DLLImport
+#endif
+#if !defined(DLLExport)
+ #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+ int count, MQTTString topicFilters[]);
+
+DLLExport int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[],
+ unsigned char* buf, int len);
+
+DLLExport int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid);
+
+DLLExport int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int len);
+
+#endif /* MQTTUNSUBSCRIBE_H_ */
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribeClient.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribeClient.c
new file mode 100755
index 0000000..0f8db7b
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribeClient.c
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * 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 "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+ * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters
+ * @param count the number of topic filter strings in topicFilters
+ * @param topicFilters the array of topic filter strings to be used in the publish
+ * @return the length of buffer needed to contain the serialized version of the packet
+ */
+int MQTTSerialize_unsubscribeLength(int count, MQTTString topicFilters[])
+{
+ int i;
+ int len = 2; /* packetid */
+
+ for (i = 0; i < count; ++i)
+ len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/
+ return len;
+}
+
+
+/**
+ * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending
+ * @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
+ * @param dup integer - the MQTT dup flag
+ * @param packetid integer - the MQTT packet identifier
+ * @param count - number of members in the topicFilters array
+ * @param topicFilters - array of topic filter names
+ * @return the length of the serialized data. <= 0 indicates error
+ */
+int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+ int count, MQTTString topicFilters[])
+{
+ unsigned char *ptr = buf;
+ MQTTHeader header = {0};
+ int rem_len = 0;
+ int rc = -1;
+ int i = 0;
+
+ FUNC_ENTRY;
+ if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+
+ header.byte = 0;
+ header.bits.type = UNSUBSCRIBE;
+ header.bits.dup = dup;
+ header.bits.qos = 1;
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+ writeInt(&ptr, packetid);
+
+ for (i = 0; i < count; ++i)
+ writeMQTTString(&ptr, topicFilters[i]);
+
+ rc = ptr - buf;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
+/**
+ * Deserializes the supplied (wire) buffer into unsuback data
+ * @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 MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen)
+{
+ unsigned char type = 0;
+ unsigned char dup = 0;
+ int rc = 0;
+
+ FUNC_ENTRY;
+ rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen);
+ if (type == UNSUBACK)
+ rc = 1;
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribeServer.c b/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribeServer.c
new file mode 100755
index 0000000..b0e427d
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/MQTTUnsubscribeServer.c
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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 "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+ * Deserializes the supplied (wire) buffer into unsubscribe data
+ * @param dup integer returned - the MQTT dup flag
+ * @param packetid integer returned - the MQTT packet identifier
+ * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
+ * @param count - number of members in the topicFilters and requestedQoSs arrays
+ * @param topicFilters - array of topic filter names
+ * @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 the length of the serialized data. <= 0 indicates error
+ */
+int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
+ unsigned char* buf, int len)
+{
+ MQTTHeader header = {0};
+ unsigned char* curdata = buf;
+ unsigned char* enddata = NULL;
+ int rc = 0;
+ int mylen = 0;
+
+ FUNC_ENTRY;
+ header.byte = readChar(&curdata);
+ if (header.bits.type != UNSUBSCRIBE)
+ goto exit;
+ *dup = header.bits.dup;
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+
+ *packetid = readInt(&curdata);
+
+ *count = 0;
+ while (curdata < enddata)
+ {
+ if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
+ goto exit;
+ (*count)++;
+ }
+
+ rc = 1;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
+/**
+ * Serializes the supplied unsuback 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 packetid integer - the MQTT packet identifier
+ * @return the length of the serialized data. <= 0 indicates error
+ */
+int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid)
+{
+ MQTTHeader header = {0};
+ int rc = 0;
+ unsigned char *ptr = buf;
+
+ FUNC_ENTRY;
+ if (buflen < 2)
+ {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+ header.byte = 0;
+ header.bits.type = UNSUBACK;
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+
+ writeInt(&ptr, packetid);
+
+ rc = ptr - buf;
+exit:
+ FUNC_EXIT_RC(rc);
+ return rc;
+}
+
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/StackTrace.h b/mbtk/mbtk_mqtt/MQTTPacket/StackTrace.h
new file mode 100755
index 0000000..c65a2ef
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/StackTrace.h
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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
+ * Ian Craggs - fix for bug #434081
+ *******************************************************************************/
+
+#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)
+
+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
+
+#endif
+
+
+
+
+#endif /* STACKTRACE_H_ */
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/core_sha1.c b/mbtk/mbtk_mqtt/MQTTPacket/core_sha1.c
new file mode 100644
index 0000000..dfd3a3d
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/core_sha1.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+//#include "infra_config.h"
+
+//#ifdef INFRA_SHA1
+
+#include <stdlib.h>
+#include <string.h>
+#include "core_sha1.h"
+//#include "infra_sha1.h"
+
+#define SHA1_KEY_IOPAD_SIZE (64)
+#define SHA1_DIGEST_SIZE (20)
+
+
+/* Implementation that should never be optimized out by the compiler */
+static void core_sha1_zeroize( void *v, uint32_t n ) {
+ volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+void core_sha1_init(iot_sha1_context *ctx)
+{
+ memset(ctx, 0, sizeof(iot_sha1_context));
+}
+
+void core_sha1_free(iot_sha1_context *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+
+ core_sha1_zeroize(ctx, sizeof(iot_sha1_context));
+}
+
+void core_sha1_clone(iot_sha1_context *dst,
+ const iot_sha1_context *src)
+{
+ *dst = *src;
+}
+
+/*
+ * SHA-1 context setup
+ */
+void core_sha1_starts(iot_sha1_context *ctx)
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+}
+
+void core_sha1_process(iot_sha1_context *ctx, const unsigned char data[64])
+{
+ uint32_t temp, W[16], A, B, C, D, E;
+
+ GET_UINT32_BE( W[ 0], data, 0 );
+ GET_UINT32_BE( W[ 1], data, 4 );
+ GET_UINT32_BE( W[ 2], data, 8 );
+ GET_UINT32_BE( W[ 3], data, 12 );
+ GET_UINT32_BE( W[ 4], data, 16 );
+ GET_UINT32_BE( W[ 5], data, 20 );
+ GET_UINT32_BE( W[ 6], data, 24 );
+ GET_UINT32_BE( W[ 7], data, 28 );
+ GET_UINT32_BE( W[ 8], data, 32 );
+ GET_UINT32_BE( W[ 9], data, 36 );
+ GET_UINT32_BE( W[10], data, 40 );
+ GET_UINT32_BE( W[11], data, 44 );
+ GET_UINT32_BE( W[12], data, 48 );
+ GET_UINT32_BE( W[13], data, 52 );
+ GET_UINT32_BE( W[14], data, 56 );
+ GET_UINT32_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) \
+( \
+ temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
+ W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) \
+{ \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P( A, B, C, D, E, W[0] );
+ P( E, A, B, C, D, W[1] );
+ P( D, E, A, B, C, W[2] );
+ P( C, D, E, A, B, W[3] );
+ P( B, C, D, E, A, W[4] );
+ P( A, B, C, D, E, W[5] );
+ P( E, A, B, C, D, W[6] );
+ P( D, E, A, B, C, W[7] );
+ P( C, D, E, A, B, W[8] );
+ P( B, C, D, E, A, W[9] );
+ P( A, B, C, D, E, W[10] );
+ P( E, A, B, C, D, W[11] );
+ P( D, E, A, B, C, W[12] );
+ P( C, D, E, A, B, W[13] );
+ P( B, C, D, E, A, W[14] );
+ P( A, B, C, D, E, W[15] );
+ P( E, A, B, C, D, R(16) );
+ P( D, E, A, B, C, R(17) );
+ P( C, D, E, A, B, R(18) );
+ P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P( A, B, C, D, E, R(20) );
+ P( E, A, B, C, D, R(21) );
+ P( D, E, A, B, C, R(22) );
+ P( C, D, E, A, B, R(23) );
+ P( B, C, D, E, A, R(24) );
+ P( A, B, C, D, E, R(25) );
+ P( E, A, B, C, D, R(26) );
+ P( D, E, A, B, C, R(27) );
+ P( C, D, E, A, B, R(28) );
+ P( B, C, D, E, A, R(29) );
+ P( A, B, C, D, E, R(30) );
+ P( E, A, B, C, D, R(31) );
+ P( D, E, A, B, C, R(32) );
+ P( C, D, E, A, B, R(33) );
+ P( B, C, D, E, A, R(34) );
+ P( A, B, C, D, E, R(35) );
+ P( E, A, B, C, D, R(36) );
+ P( D, E, A, B, C, R(37) );
+ P( C, D, E, A, B, R(38) );
+ P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P( A, B, C, D, E, R(40) );
+ P( E, A, B, C, D, R(41) );
+ P( D, E, A, B, C, R(42) );
+ P( C, D, E, A, B, R(43) );
+ P( B, C, D, E, A, R(44) );
+ P( A, B, C, D, E, R(45) );
+ P( E, A, B, C, D, R(46) );
+ P( D, E, A, B, C, R(47) );
+ P( C, D, E, A, B, R(48) );
+ P( B, C, D, E, A, R(49) );
+ P( A, B, C, D, E, R(50) );
+ P( E, A, B, C, D, R(51) );
+ P( D, E, A, B, C, R(52) );
+ P( C, D, E, A, B, R(53) );
+ P( B, C, D, E, A, R(54) );
+ P( A, B, C, D, E, R(55) );
+ P( E, A, B, C, D, R(56) );
+ P( D, E, A, B, C, R(57) );
+ P( C, D, E, A, B, R(58) );
+ P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P( A, B, C, D, E, R(60) );
+ P( E, A, B, C, D, R(61) );
+ P( D, E, A, B, C, R(62) );
+ P( C, D, E, A, B, R(63) );
+ P( B, C, D, E, A, R(64) );
+ P( A, B, C, D, E, R(65) );
+ P( E, A, B, C, D, R(66) );
+ P( D, E, A, B, C, R(67) );
+ P( C, D, E, A, B, R(68) );
+ P( B, C, D, E, A, R(69) );
+ P( A, B, C, D, E, R(70) );
+ P( E, A, B, C, D, R(71) );
+ P( D, E, A, B, C, R(72) );
+ P( C, D, E, A, B, R(73) );
+ P( B, C, D, E, A, R(74) );
+ P( A, B, C, D, E, R(75) );
+ P( E, A, B, C, D, R(76) );
+ P( D, E, A, B, C, R(77) );
+ P( C, D, E, A, B, R(78) );
+ P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void core_sha1_update(iot_sha1_context *ctx, const unsigned char *input, uint32_t ilen)
+{
+ uint32_t fill;
+ uint32_t left;
+
+ if( ilen == 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+ core_sha1_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ core_sha1_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha1_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+void core_sha1_finish(iot_sha1_context *ctx, unsigned char output[20])
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_BE( high, msglen, 0 );
+ PUT_UINT32_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ core_sha1_update( ctx, sha1_padding, padn );
+ core_sha1_update( ctx, msglen, 8 );
+
+ PUT_UINT32_BE( ctx->state[0], output, 0 );
+ PUT_UINT32_BE( ctx->state[1], output, 4 );
+ PUT_UINT32_BE( ctx->state[2], output, 8 );
+ PUT_UINT32_BE( ctx->state[3], output, 12 );
+ PUT_UINT32_BE( ctx->state[4], output, 16 );
+}
+
+
+/*
+ * output = SHA-1( input buffer )
+ */
+void core_sha1(const unsigned char *input, uint32_t ilen, unsigned char output[20])
+{
+ iot_sha1_context ctx;
+
+ core_sha1_init(&ctx);
+ core_sha1_starts(&ctx);
+ core_sha1_update(&ctx, input, ilen);
+ core_sha1_finish(&ctx, output);
+ core_sha1_free(&ctx);
+}
+
+static int8_t core_hb2hex(uint8_t hb)
+{
+ hb = hb & 0xF;
+ return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a');
+}
+
+void core_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len)
+{
+ iot_sha1_context context;
+ unsigned char k_ipad[SHA1_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
+ unsigned char k_opad[SHA1_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
+ unsigned char out[SHA1_DIGEST_SIZE];
+ int i;
+
+ if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
+ return;
+ }
+
+ if (key_len > SHA1_KEY_IOPAD_SIZE) {
+ return;
+ }
+
+ /* start out by storing key in pads */
+ memset(k_ipad, 0, sizeof(k_ipad));
+ memset(k_opad, 0, sizeof(k_opad));
+ memcpy(k_ipad, key, key_len);
+ memcpy(k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < SHA1_KEY_IOPAD_SIZE; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner SHA */
+ core_sha1_init(&context); /* init context for 1st pass */
+ core_sha1_starts(&context); /* setup context for 1st pass */
+ core_sha1_update(&context, k_ipad, SHA1_KEY_IOPAD_SIZE); /* start with inner pad */
+ core_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
+ core_sha1_finish(&context, out); /* finish up 1st pass */
+
+ /* perform outer SHA */
+ core_sha1_init(&context); /* init context for 2nd pass */
+ core_sha1_starts(&context); /* setup context for 2nd pass */
+ core_sha1_update(&context, k_opad, SHA1_KEY_IOPAD_SIZE); /* start with outer pad */
+ core_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
+ core_sha1_finish(&context, out); /* finish up 2nd pass */
+
+ for (i = 0; i < SHA1_DIGEST_SIZE; ++i) {
+ digest[i * 2] = core_hb2hex(out[i] >> 4);
+ digest[i * 2 + 1] = core_hb2hex(out[i]);
+ }
+}
+
+void core_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len)
+{
+ iot_sha1_context context;
+ unsigned char k_ipad[SHA1_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
+ unsigned char k_opad[SHA1_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
+ unsigned char out[SHA1_DIGEST_SIZE];
+ int i;
+
+ if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
+ return;
+ }
+
+ if (key_len > SHA1_KEY_IOPAD_SIZE) {
+ return;
+ }
+
+ /* start out by storing key in pads */
+ memset(k_ipad, 0, sizeof(k_ipad));
+ memset(k_opad, 0, sizeof(k_opad));
+ memcpy(k_ipad, key, key_len);
+ memcpy(k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < SHA1_KEY_IOPAD_SIZE; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner SHA */
+ core_sha1_init(&context); /* init context for 1st pass */
+ core_sha1_starts(&context); /* setup context for 1st pass */
+ core_sha1_update(&context, k_ipad, SHA1_KEY_IOPAD_SIZE); /* start with inner pad */
+ core_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
+ core_sha1_finish(&context, out); /* finish up 1st pass */
+
+ /* perform outer SHA */
+ core_sha1_init(&context); /* init context for 2nd pass */
+ core_sha1_starts(&context); /* setup context for 2nd pass */
+ core_sha1_update(&context, k_opad, SHA1_KEY_IOPAD_SIZE); /* start with outer pad */
+ core_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
+ core_sha1_finish(&context, out); /* finish up 2nd pass */
+ memcpy(digest, out, SHA1_DIGEST_SIZE);
+}
+
+//#endif
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/core_sha1.h b/mbtk/mbtk_mqtt/MQTTPacket/core_sha1.h
new file mode 100644
index 0000000..0260002
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/core_sha1.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#ifndef _CORE_SHA1_H_
+#define _CORE_SHA1_H_
+
+//#include "infra_types.h"
+
+#define SHA1_DIGEST_SIZE (20)
+
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/**
+ * \brief SHA-1 context structure
+ */
+typedef struct {
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[5]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+} iot_sha1_context;
+
+/**
+ * \brief Initialize SHA-1 context
+ *
+ * \param ctx SHA-1 context to be initialized
+ */
+void core_sha1_init(iot_sha1_context *ctx);
+
+/**
+ * \brief Clear SHA-1 context
+ *
+ * \param ctx SHA-1 context to be cleared
+ */
+void core_sha1_free(iot_sha1_context *ctx);
+
+/**
+ * \brief Clone (the state of) a SHA-1 context
+ *
+ * \param dst The destination context
+ * \param src The context to be cloned
+ */
+void core_sha1_clone(iot_sha1_context *dst,
+ const iot_sha1_context *src);
+
+/**
+ * \brief SHA-1 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void core_sha1_starts(iot_sha1_context *ctx);
+
+/**
+ * \brief SHA-1 process buffer
+ *
+ * \param ctx SHA-1 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void core_sha1_update(iot_sha1_context *ctx, const unsigned char *input, uint32_t ilen);
+
+/**
+ * \brief SHA-1 final digest
+ *
+ * \param ctx SHA-1 context
+ * \param output SHA-1 checksum result
+ */
+void core_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]);
+
+/* Internal use */
+void core_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]);
+
+/**
+ * \brief Output = SHA-1( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-1 checksum result
+ */
+void core_sha1(const unsigned char *input, uint32_t ilen, unsigned char output[20]);
+void core_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len);
+void core_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len);
+
+#endif
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/core_sha256.c b/mbtk/mbtk_mqtt/MQTTPacket/core_sha256.c
new file mode 100755
index 0000000..d819047
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/core_sha256.c
@@ -0,0 +1,329 @@
+#include "core_sha256.h"
+
+#define MINI_SHA256_SMALLER
+#define SHA256_KEY_IOPAD_SIZE (64)
+#define SHA256_DIGEST_SIZE (32)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+ do { \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+ } while( 0 )
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+ do { \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+ } while( 0 )
+#endif
+
+
+static void utils_sha256_zeroize(void *v, uint32_t n)
+{
+ volatile unsigned char *p = v;
+ while (n--) {
+ *p++ = 0;
+ }
+}
+
+void core_sha256_init(core_sha256_context_t *ctx)
+{
+ memset(ctx, 0, sizeof(core_sha256_context_t));
+}
+
+void core_sha256_free(core_sha256_context_t *ctx)
+{
+ if (NULL == ctx) {
+ return;
+ }
+
+ utils_sha256_zeroize(ctx, sizeof(core_sha256_context_t));
+}
+
+void core_sha256_starts(core_sha256_context_t *ctx)
+{
+ uint8_t is224 = 0;
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if (is224 == 0) {
+ /* SHA-256 */
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+ }
+
+ ctx->is224 = is224;
+}
+
+static const uint32_t K[] = {
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+};
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+ ( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+ )
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+ { \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+ }
+
+void core_sha256_process(core_sha256_context_t *ctx, const unsigned char data[64])
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A[8];
+ unsigned int i;
+
+ for (i = 0; i < 8; i++) {
+ A[i] = ctx->state[i];
+ }
+
+#if defined(MINI_SHA256_SMALLER)
+ for (i = 0; i < 64; i++) {
+ if (i < 16) {
+ GET_UINT32_BE(W[i], data, 4 * i);
+ } else {
+ R(i);
+ }
+
+ P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i]);
+
+ temp1 = A[7];
+ A[7] = A[6];
+ A[6] = A[5];
+ A[5] = A[4];
+ A[4] = A[3];
+ A[3] = A[2];
+ A[2] = A[1];
+ A[1] = A[0];
+ A[0] = temp1;
+ }
+#else /* MINI_SHA256_SMALLER */
+ for (i = 0; i < 16; i++) {
+ GET_UINT32_BE(W[i], data, 4 * i);
+ }
+
+ for (i = 0; i < 16; i += 8) {
+ P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i + 0], K[i + 0]);
+ P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i + 1], K[i + 1]);
+ P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i + 2], K[i + 2]);
+ P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i + 3], K[i + 3]);
+ P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i + 4], K[i + 4]);
+ P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i + 5], K[i + 5]);
+ P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i + 6], K[i + 6]);
+ P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i + 7], K[i + 7]);
+ }
+
+ for (i = 16; i < 64; i += 8) {
+ P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i + 0), K[i + 0]);
+ P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i + 1), K[i + 1]);
+ P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i + 2), K[i + 2]);
+ P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i + 3), K[i + 3]);
+ P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i + 4), K[i + 4]);
+ P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i + 5), K[i + 5]);
+ P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i + 6), K[i + 6]);
+ P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i + 7), K[i + 7]);
+ }
+#endif /* MINI_SHA256_SMALLER */
+
+ for (i = 0; i < 8; i++) {
+ ctx->state[i] += A[i];
+ }
+}
+void core_sha256_update(core_sha256_context_t *ctx, const unsigned char *input, uint32_t ilen)
+{
+ size_t fill;
+ uint32_t left;
+
+ if (ilen == 0) {
+ return;
+ }
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if (ctx->total[0] < (uint32_t) ilen) {
+ ctx->total[1]++;
+ }
+
+ if (left && ilen >= fill) {
+ memcpy((void *)(ctx->buffer + left), input, fill);
+ core_sha256_process(ctx, ctx->buffer);
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while (ilen >= 64) {
+ core_sha256_process(ctx, input);
+ input += 64;
+ ilen -= 64;
+ }
+
+ if (ilen > 0) {
+ memcpy((void *)(ctx->buffer + left), input, ilen);
+ }
+}
+
+static const unsigned char sha256_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void core_sha256_finish(core_sha256_context_t *ctx, uint8_t output[32])
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = (ctx->total[0] >> 29)
+ | (ctx->total[1] << 3);
+ low = (ctx->total[0] << 3);
+
+ PUT_UINT32_BE(high, msglen, 0);
+ PUT_UINT32_BE(low, msglen, 4);
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ core_sha256_update(ctx, sha256_padding, padn);
+ core_sha256_update(ctx, msglen, 8);
+
+ PUT_UINT32_BE(ctx->state[0], output, 0);
+ PUT_UINT32_BE(ctx->state[1], output, 4);
+ PUT_UINT32_BE(ctx->state[2], output, 8);
+ PUT_UINT32_BE(ctx->state[3], output, 12);
+ PUT_UINT32_BE(ctx->state[4], output, 16);
+ PUT_UINT32_BE(ctx->state[5], output, 20);
+ PUT_UINT32_BE(ctx->state[6], output, 24);
+
+ if (ctx->is224 == 0) {
+ PUT_UINT32_BE(ctx->state[7], output, 28);
+ }
+}
+
+void core_sha256(const uint8_t *input, uint32_t ilen, uint8_t output[32])
+{
+ core_sha256_context_t ctx;
+
+ core_sha256_init(&ctx);
+ core_sha256_starts(&ctx);
+ core_sha256_update(&ctx, input, ilen);
+ core_sha256_finish(&ctx, output);
+ core_sha256_free(&ctx);
+}
+
+void core_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32])
+{
+ core_sha256_context_t context;
+ uint8_t k_ipad[SHA256_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
+ uint8_t k_opad[SHA256_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
+ int32_t i;
+
+ if ((NULL == msg) || (NULL == key) || (NULL == output)) {
+ return;
+ }
+
+ if (key_len > SHA256_KEY_IOPAD_SIZE) {
+ return;
+ }
+
+ /* start out by storing key in pads */
+ memset(k_ipad, 0, sizeof(k_ipad));
+ memset(k_opad, 0, sizeof(k_opad));
+ memcpy(k_ipad, key, key_len);
+ memcpy(k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < SHA256_KEY_IOPAD_SIZE; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner SHA */
+ core_sha256_init(&context); /* init context for 1st pass */
+ core_sha256_starts(&context); /* setup context for 1st pass */
+ core_sha256_update(&context, k_ipad, SHA256_KEY_IOPAD_SIZE); /* start with inner pad */
+ core_sha256_update(&context, msg, msg_len); /* then text of datagram */
+ core_sha256_finish(&context, output); /* finish up 1st pass */
+
+ /* perform outer SHA */
+ core_sha256_init(&context); /* init context for 2nd pass */
+ core_sha256_starts(&context); /* setup context for 2nd pass */
+ core_sha256_update(&context, k_opad, SHA256_KEY_IOPAD_SIZE); /* start with outer pad */
+ core_sha256_update(&context, output, SHA256_DIGEST_SIZE); /* then results of 1st hash */
+ core_sha256_finish(&context, output); /* finish up 2nd pass */
+}
+
+int32_t core_hex2str(uint8_t *input, uint32_t input_len, char *output, uint8_t lowercase)
+{
+ char *upper = "0123456789ABCDEF";
+ char *lower = "0123456789abcdef";
+ char *encode = upper;
+ int i = 0, j = 0;
+
+ if (lowercase) {
+ encode = lower;
+ }
+
+ for (i = 0; i < input_len; i++) {
+ output[j++] = encode[(input[i] >> 4) & 0xf];
+ output[j++] = encode[(input[i]) & 0xf];
+ }
+
+ return 0;
+}
+
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/core_sha256.h b/mbtk/mbtk_mqtt/MQTTPacket/core_sha256.h
new file mode 100755
index 0000000..2141941
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/core_sha256.h
@@ -0,0 +1,86 @@
+#ifndef _CORE_SHA256_H_
+#define _CORE_SHA256_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "core_stdinc.h"
+
+#define CORE_SHA256_DIGEST_LENGTH (32)
+#define CORE_SHA256_BLOCK_LENGTH (64)
+#define CORE_SHA256_SHORT_BLOCK_LENGTH (CORE_SHA256_BLOCK_LENGTH - 8)
+#define CORE_SHA256_DIGEST_STRING_LENGTH (CORE_SHA256_DIGEST_LENGTH * 2 + 1)
+
+/**
+ * \brief SHA-256 context structure
+ */
+typedef struct {
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[8]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+ uint8_t is224; /*!< 0 => SHA-256, else SHA-224 */
+} core_sha256_context_t;
+
+/**
+ * \brief Initialize SHA-256 context
+ *
+ * \param ctx SHA-256 context to be initialized
+ */
+void core_sha256_init(core_sha256_context_t *ctx);
+
+/**
+ * \brief Clear SHA-256 context
+ *
+ * \param ctx SHA-256 context to be cleared
+ */
+void core_sha256_free(core_sha256_context_t *ctx);
+
+
+/**
+ * \brief SHA-256 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void core_sha256_starts(core_sha256_context_t *ctx);
+
+/**
+ * \brief SHA-256 process buffer
+ *
+ * \param ctx SHA-256 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void core_sha256_update(core_sha256_context_t *ctx, const unsigned char *input, uint32_t ilen);
+
+/**
+ * \brief SHA-256 final digest
+ *
+ * \param ctx SHA-256 context
+ * \param output SHA-256 checksum result
+ */
+void core_sha256_finish(core_sha256_context_t *ctx, uint8_t output[32]);
+
+/* Internal use */
+void core_sha256_process(core_sha256_context_t *ctx, const unsigned char data[64]);
+
+/**
+ * \brief Output = SHA-256( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-256 checksum result
+ */
+void core_sha256(const uint8_t *input, uint32_t ilen, uint8_t output[32]);
+
+void core_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32]);
+
+int core_hex2str(uint8_t *input, uint32_t input_len, char *output, uint8_t lowercase);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/mbtk/mbtk_mqtt/MQTTPacket/core_stdinc.h b/mbtk/mbtk_mqtt/MQTTPacket/core_stdinc.h
new file mode 100755
index 0000000..d58acbc
--- /dev/null
+++ b/mbtk/mbtk_mqtt/MQTTPacket/core_stdinc.h
@@ -0,0 +1,16 @@
+#ifndef _CORE_STDINC_H_
+#define _CORE_STDINC_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+