mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-29 17:22:56 +08:00
compile mqtt module passed on linux
mqttclient compile pass, log and ssl config off
This commit is contained in:
parent
f506721544
commit
8c96721a55
148
package/mqtt/MQTTConnect.h
Normal file
148
package/mqtt/MQTTConnect.h
Normal file
@ -0,0 +1,148 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014, 2017 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 - add connack return code definitions
|
||||
* Xiang Rong - 442039 Add makefile to Embedded C client
|
||||
* Ian Craggs - fix for issue #64, bit order in connack response
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTCONNECT_H_
|
||||
#define MQTTCONNECT_H_
|
||||
|
||||
enum connack_return_codes
|
||||
{
|
||||
MQTT_CONNECTION_ACCEPTED = 0,
|
||||
MQTT_UNNACCEPTABLE_PROTOCOL = 1,
|
||||
MQTT_CLIENTID_REJECTED = 2,
|
||||
MQTT_SERVER_UNAVAILABLE = 3,
|
||||
MQTT_BAD_USERNAME_OR_PASSWORD = 4,
|
||||
MQTT_NOT_AUTHORIZED = 5,
|
||||
};
|
||||
|
||||
#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 reserved : 7; /**< unused */
|
||||
unsigned int sessionpresent : 1; /**< session present flag */
|
||||
} bits;
|
||||
#else
|
||||
struct
|
||||
{
|
||||
unsigned int sessionpresent : 1; /**< session present flag */
|
||||
unsigned int reserved: 7; /**< unused */
|
||||
} 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_ */
|
214
package/mqtt/MQTTConnectClient.c
Normal file
214
package/mqtt/MQTTConnectClient.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
}
|
148
package/mqtt/MQTTConnectServer.c
Normal file
148
package/mqtt/MQTTConnectServer.c
Normal file
@ -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;
|
||||
}
|
||||
|
107
package/mqtt/MQTTDeserializePublish.c
Normal file
107
package/mqtt/MQTTDeserializePublish.c
Normal file
@ -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;
|
||||
}
|
||||
|
262
package/mqtt/MQTTFormat.c
Normal file
262
package/mqtt/MQTTFormat.c
Normal file
@ -0,0 +1,262 @@
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
#if defined(MQTT_CLIENT)
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MQTT_SERVER)
|
||||
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;
|
||||
}
|
||||
#endif
|
37
package/mqtt/MQTTFormat.h
Normal file
37
package/mqtt/MQTTFormat.h
Normal file
@ -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
|
412
package/mqtt/MQTTPacket.c
Normal file
412
package/mqtt/MQTTPacket.c
Normal file
@ -0,0 +1,412 @@
|
||||
/*******************************************************************************
|
||||
* 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 (rem_len && ((*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->len);
|
||||
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:
|
||||
if(trp->rem_len){
|
||||
/* 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;
|
||||
}
|
||||
|
133
package/mqtt/MQTTPacket.h
Normal file
133
package/mqtt/MQTTPacket.h
Normal file
@ -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"
|
||||
|
||||
DLLExport int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid);
|
||||
DLLExport int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTPacket_len(int rem_len);
|
||||
DLLExport int MQTTPacket_equals(MQTTString* a, char* b);
|
||||
|
||||
DLLExport 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_ */
|
38
package/mqtt/MQTTPublish.h
Normal file
38
package/mqtt/MQTTPublish.h
Normal file
@ -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_ */
|
169
package/mqtt/MQTTSerializePublish.c
Normal file
169
package/mqtt/MQTTSerializePublish.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
46
package/mqtt/MQTTSubscribe.h
Normal file
46
package/mqtt/MQTTSubscribe.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-09 20:15:32
|
||||
* @LastEditTime: 2019-12-20 20:37:31
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
/*******************************************************************************
|
||||
* 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_ */
|
137
package/mqtt/MQTTSubscribeClient.c
Normal file
137
package/mqtt/MQTTSubscribeClient.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
112
package/mqtt/MQTTSubscribeServer.c
Normal file
112
package/mqtt/MQTTSubscribeServer.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
38
package/mqtt/MQTTUnsubscribe.h
Normal file
38
package/mqtt/MQTTUnsubscribe.h
Normal file
@ -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_ */
|
106
package/mqtt/MQTTUnsubscribeClient.c
Normal file
106
package/mqtt/MQTTUnsubscribeClient.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
102
package/mqtt/MQTTUnsubscribeServer.c
Normal file
102
package/mqtt/MQTTUnsubscribeServer.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
78
package/mqtt/StackTrace.h
Normal file
78
package/mqtt/StackTrace.h
Normal file
@ -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_ */
|
46
package/mqtt/mqtt_config.h
Normal file
46
package/mqtt/mqtt_config.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @LastEditTime: 2020-06-17 19:31:41
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTT_CONFIG_H_
|
||||
#define _MQTT_CONFIG_H_
|
||||
|
||||
// #define MQTT_LOG_IS_SALOF
|
||||
|
||||
#define MQTT_LOG_LEVEL MQTT_LOG_INFO_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
|
||||
|
||||
#ifdef MQTT_LOG_IS_SALOF
|
||||
#define SALOF_USING_LOG (1U)
|
||||
#define SALOF_USING_SALOF (1U)
|
||||
#define SALOF_LOG_LEVEL MQTT_LOG_LEVEL
|
||||
#define SALOF_OS SALOF_USING_LINUX
|
||||
#define SALOF_USING_IDLE_HOOK (0U)
|
||||
#define SALOF_LOG_COLOR (1U)
|
||||
#define SALOF_LOG_TS (0U)
|
||||
#define SALOF_LOG_TAR (0U)
|
||||
#define SALOF_BUFF_SIZE 512
|
||||
#define SALOF_FIFO_SIZE 4096
|
||||
#define SALOF_TASK_STACK_SIZE 1024
|
||||
#define SALOF_TASK_TICK 50
|
||||
#endif
|
||||
|
||||
#define MQTT_MAX_PACKET_ID (0xFFFF - 1)
|
||||
#define MQTT_TOPIC_LEN_MAX 64
|
||||
#define MQTT_ACK_HANDLER_NUM_MAX 64
|
||||
#define MQTT_DEFAULT_BUF_SIZE 1024
|
||||
#define MQTT_DEFAULT_CMD_TIMEOUT 5000
|
||||
#define MQTT_MAX_CMD_TIMEOUT 20000
|
||||
#define MQTT_MIN_CMD_TIMEOUT 1000
|
||||
#define MQTT_KEEP_ALIVE_INTERVAL 50 // unit: second
|
||||
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1
|
||||
#define MQTT_RECONNECT_DEFAULT_DURATION 1000
|
||||
#define MQTT_THREAD_STACK_SIZE 2048
|
||||
#define MQTT_THREAD_PRIO 5
|
||||
#define MQTT_THREAD_TICK 50
|
||||
|
||||
|
||||
#define MQTT_NETWORK_TYPE_NO_TLS
|
||||
|
||||
#endif /* _MQTT_CONFIG_H_ */
|
88
package/mqtt/mqtt_defconfig.h
Normal file
88
package/mqtt/mqtt_defconfig.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* @Author : jiejie
|
||||
* @GitHub : https://github.com/jiejieTop
|
||||
* @Date : 2021-02-26 12:00:24
|
||||
* @LastEditors : jiejie
|
||||
* @LastEditTime : 2022-06-15 23:22:10
|
||||
* @FilePath : /mqttclient/mqttclient/mqtt_defconfig.h
|
||||
* Copyright (c) 2022 jiejie, All Rights Reserved. Please keep the author information and source code according to the license.
|
||||
*/
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2020-02-25 03:36:09
|
||||
* @LastEditTime: 2020-06-17 19:59:41
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
#ifndef _DEFCONFIG_H_
|
||||
#define _DEFCONFIG_H_
|
||||
|
||||
#include "mqtt_config.h"
|
||||
|
||||
#ifndef MQTT_LOG_LEVEL
|
||||
#define MQTT_LOG_LEVEL MQTT_LOG_DEBUG_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
|
||||
#endif // !MQTT_LOG_LEVEL
|
||||
|
||||
#ifndef MQTT_MAX_PACKET_ID
|
||||
#define MQTT_MAX_PACKET_ID (0xFFFF - 1)
|
||||
#endif // !MQTT_MAX_PACKET_ID
|
||||
|
||||
#ifndef MQTT_TOPIC_LEN_MAX
|
||||
#define MQTT_TOPIC_LEN_MAX 64
|
||||
#endif // !MQTT_TOPIC_LEN_MAX
|
||||
|
||||
#ifndef MQTT_ACK_HANDLER_NUM_MAX
|
||||
#define MQTT_ACK_HANDLER_NUM_MAX 64
|
||||
#endif // !MQTT_ACK_HANDLER_NUM_MAX
|
||||
|
||||
#ifndef MQTT_DEFAULT_BUF_SIZE
|
||||
#define MQTT_DEFAULT_BUF_SIZE 1024
|
||||
#endif // !MQTT_DEFAULT_BUF_SIZE
|
||||
|
||||
#ifndef MQTT_DEFAULT_CMD_TIMEOUT
|
||||
#define MQTT_DEFAULT_CMD_TIMEOUT 4000
|
||||
#endif // !MQTT_DEFAULT_CMD_TIMEOUT
|
||||
|
||||
#ifndef MQTT_MAX_CMD_TIMEOUT
|
||||
#define MQTT_MAX_CMD_TIMEOUT 20000
|
||||
#endif // !MQTT_MAX_CMD_TIMEOUT
|
||||
|
||||
#ifndef MQTT_MIN_CMD_TIMEOUT
|
||||
#define MQTT_MIN_CMD_TIMEOUT 1000
|
||||
#endif // !MQTT_MIN_CMD_TIMEOUT
|
||||
|
||||
#ifndef MQTT_KEEP_ALIVE_INTERVAL
|
||||
#define MQTT_KEEP_ALIVE_INTERVAL 100 // unit: second
|
||||
#endif // !MQTT_KEEP_ALIVE_INTERVAL
|
||||
|
||||
#ifndef MQTT_VERSION
|
||||
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1
|
||||
#endif // !MQTT_VERSION
|
||||
|
||||
#ifndef MQTT_RECONNECT_DEFAULT_DURATION
|
||||
#define MQTT_RECONNECT_DEFAULT_DURATION 1000
|
||||
#endif // !MQTT_RECONNECT_DEFAULT_DURATION
|
||||
|
||||
#ifndef MQTT_THREAD_STACK_SIZE
|
||||
#define MQTT_THREAD_STACK_SIZE 4096
|
||||
#endif // !MQTT_THREAD_STACK_SIZE
|
||||
|
||||
#ifndef MQTT_THREAD_PRIO
|
||||
#define MQTT_THREAD_PRIO 5
|
||||
#endif // !MQTT_THREAD_PRIO
|
||||
|
||||
#ifndef MQTT_THREAD_TICK
|
||||
#define MQTT_THREAD_TICK 50
|
||||
#endif // !MQTT_THREAD_TICK
|
||||
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
|
||||
#ifndef MQTT_TLS_HANDSHAKE_TIMEOUT
|
||||
#define MQTT_TLS_HANDSHAKE_TIMEOUT (5 * 1000)
|
||||
#endif // !MQTT_TLS_HANDSHAKE_TIMEOUT
|
||||
|
||||
#endif /* MQTT_NETWORK_TYPE_NO_TLS */
|
||||
|
||||
#endif /* _DEFCONFIG_H_ */
|
53
package/mqtt/mqtt_error.h
Normal file
53
package/mqtt/mqtt_error.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 00:42:16
|
||||
* @LastEditTime: 2020-10-17 14:16:15
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTT_ERROR_H_
|
||||
#define _MQTT_ERROR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum mqtt_error {
|
||||
MQTT_SSL_CERT_ERROR = -0x001C, /* cetr parse failed */
|
||||
MQTT_SOCKET_FAILED_ERROR = -0x001B, /* socket fd failed */
|
||||
MQTT_SOCKET_UNKNOWN_HOST_ERROR = -0x001A, /* socket unknown host ip or domain */
|
||||
MQTT_SET_PUBLISH_DUP_FAILED_ERROR = -0x0019, /* mqtt publish packet set udp bit failed */
|
||||
MQTT_CLEAN_SESSION_ERROR = -0x0018, /* mqtt clean session error */
|
||||
MQTT_ACK_NODE_IS_EXIST_ERROR = -0x0017, /* mqtt ack list is exist ack node */
|
||||
MQTT_ACK_HANDLER_NUM_TOO_MUCH_ERROR = -0x0016, /* mqtt ack handler number is too much */
|
||||
MQTT_RESUBSCRIBE_ERROR = -0x0015, /* mqtt resubscribe error */
|
||||
MQTT_SUBSCRIBE_ERROR = -0x0014, /* mqtt subscribe error */
|
||||
MQTT_SEND_PACKET_ERROR = -0x0013, /* mqtt send a packet */
|
||||
MQTT_SERIALIZE_PUBLISH_ACK_PACKET_ERROR = -0x0012, /* mqtt serialize publish ack packet error */
|
||||
MQTT_PUBLISH_PACKET_ERROR = -0x0011, /* mqtt publish packet error */
|
||||
MQTT_RECONNECT_TIMEOUT_ERROR = -0x0010, /* mqtt try reconnect, but timeout */
|
||||
MQTT_SUBSCRIBE_NOT_ACK_ERROR = -0x000F, /* mqtt subscribe, but not ack */
|
||||
MQTT_NOT_CONNECT_ERROR = -0x000E, /* mqtt not connect */
|
||||
MQTT_SUBSCRIBE_ACK_PACKET_ERROR = -0x000D, /* mqtt subscribe, but ack packet error */
|
||||
MQTT_UNSUBSCRIBE_ACK_PACKET_ERROR = -0x000C, /* mqtt unsubscribe, but ack packet error */
|
||||
MQTT_PUBLISH_ACK_PACKET_ERROR = -0x000B, /* mqtt pubilsh ack packet error */
|
||||
MQTT_PUBLISH_ACK_TYPE_ERROR = -0x000A, /* mqtt pubilsh ack type error */
|
||||
MQTT_PUBREC_PACKET_ERROR = -0x0009, /* mqtt pubrec packet error */
|
||||
MQTT_BUFFER_TOO_SHORT_ERROR = -0x0008, /* mqtt buffer too short */
|
||||
MQTT_NOTHING_TO_READ_ERROR = -0x0007, /* mqtt nothing to read */
|
||||
MQTT_SUBSCRIBE_QOS_ERROR = -0x0006, /* mqtt subsrcibe qos error */
|
||||
MQTT_BUFFER_OVERFLOW_ERROR = -0x0005, /* mqtt buffer overflow */
|
||||
MQTT_CONNECT_FAILED_ERROR = -0x0004, /* mqtt connect failed */
|
||||
MQTT_MEM_NOT_ENOUGH_ERROR = -0x0003, /* mqtt memory not enough */
|
||||
MQTT_NULL_VALUE_ERROR = -0x0002, /* mqtt value is null */
|
||||
MQTT_FAILED_ERROR = -0x0001, /* failed */
|
||||
MQTT_SUCCESS_ERROR = 0x0000 /* success */
|
||||
} mqtt_error_t;
|
||||
|
||||
#define RETURN_ERROR(x) { return x; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
72
package/mqtt/mqtt_list.c
Normal file
72
package/mqtt/mqtt_list.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-11 22:46:33
|
||||
* @LastEditTime: 2020-04-27 23:28:12
|
||||
* @Description: the following code references TencentOS tiny, please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
# include "mqtt_list.h"
|
||||
|
||||
static void _mqtt_list_add(mqtt_list_t *node, mqtt_list_t *prev, mqtt_list_t *next)
|
||||
{
|
||||
next->prev = node;
|
||||
node->next = next;
|
||||
node->prev = prev;
|
||||
prev->next = node;
|
||||
}
|
||||
|
||||
static void _mqtt_list_del(mqtt_list_t *prev, mqtt_list_t *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
static void _mqtt_list_del_entry(mqtt_list_t *entry)
|
||||
{
|
||||
_mqtt_list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
void mqtt_list_init(mqtt_list_t *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
void mqtt_list_add(mqtt_list_t *node, mqtt_list_t *list)
|
||||
{
|
||||
_mqtt_list_add(node, list, list->next);
|
||||
}
|
||||
|
||||
void mqtt_list_add_tail(mqtt_list_t *node, mqtt_list_t *list)
|
||||
{
|
||||
_mqtt_list_add(node, list->prev, list);
|
||||
}
|
||||
|
||||
void mqtt_list_del(mqtt_list_t *entry)
|
||||
{
|
||||
_mqtt_list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
void mqtt_list_del_init(mqtt_list_t *entry)
|
||||
{
|
||||
_mqtt_list_del_entry(entry);
|
||||
mqtt_list_init(entry);
|
||||
}
|
||||
|
||||
void mqtt_list_move(mqtt_list_t *node, mqtt_list_t *list)
|
||||
{
|
||||
_mqtt_list_del_entry(node);
|
||||
mqtt_list_add(node, list);
|
||||
}
|
||||
|
||||
void mqtt_list_move_tail(mqtt_list_t *node, mqtt_list_t *list)
|
||||
{
|
||||
_mqtt_list_del_entry(node);
|
||||
mqtt_list_add_tail(node, list);
|
||||
}
|
||||
|
||||
int mqtt_list_is_empty(mqtt_list_t *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
70
package/mqtt/mqtt_list.h
Normal file
70
package/mqtt/mqtt_list.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-11 22:47:55
|
||||
* @LastEditTime: 2020-10-17 14:18:02
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTT_LIST_H_
|
||||
#define _MQTT_LIST_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct mqtt_list_node {
|
||||
struct mqtt_list_node *next;
|
||||
struct mqtt_list_node *prev;
|
||||
} mqtt_list_t;
|
||||
|
||||
#define OFFSET_OF_FIELD(type, field) \
|
||||
((size_t)&(((type *)0)->field))
|
||||
|
||||
#define CONTAINER_OF_FIELD(ptr, type, field) \
|
||||
((type *)((unsigned char *)(ptr) - OFFSET_OF_FIELD(type, field)))
|
||||
|
||||
#define LIST_NODE(node) \
|
||||
{ &(node), &(node) }
|
||||
|
||||
#define LIST_DEFINE(list) \
|
||||
mqtt_list_t list = { &(list), &(list) }
|
||||
|
||||
#define LIST_ENTRY(list, type, field) \
|
||||
CONTAINER_OF_FIELD(list, type, field)
|
||||
|
||||
#define LIST_FIRST_ENTRY(list, type, field) \
|
||||
LIST_ENTRY((list)->next, type, field)
|
||||
|
||||
#define LIST_FIRST_ENTRY_OR_NULL(list, type, field) \
|
||||
(mqtt_list_is_empty(list) ? NULL : LIST_FIRST_ENTRY(list, type, field))
|
||||
|
||||
#define LIST_FOR_EACH(curr, list) \
|
||||
for (curr = (list)->next; curr != (list); curr = curr->next)
|
||||
|
||||
#define LIST_FOR_EACH_PREV(curr, list) \
|
||||
for (curr = (list)->prev; curr != (list); curr = curr->prev)
|
||||
|
||||
#define LIST_FOR_EACH_SAFE(curr, next, list) \
|
||||
for (curr = (list)->next, next = curr->next; curr != (list); \
|
||||
curr = next, next = curr->next)
|
||||
|
||||
#define LIST_FOR_EACH_PREV_SAFE(curr, next, list) \
|
||||
for (curr = (list)->prev, next = curr->prev; \
|
||||
curr != (list); \
|
||||
curr = next, next = curr->prev)
|
||||
|
||||
void mqtt_list_init(mqtt_list_t *list);
|
||||
void mqtt_list_add(mqtt_list_t *node, mqtt_list_t *list);
|
||||
void mqtt_list_add_tail(mqtt_list_t *node, mqtt_list_t *list);
|
||||
void mqtt_list_del(mqtt_list_t *entry);
|
||||
void mqtt_list_del_init(mqtt_list_t *entry);
|
||||
void mqtt_list_move(mqtt_list_t *node, mqtt_list_t *list);
|
||||
void mqtt_list_move_tail(mqtt_list_t *node, mqtt_list_t *list);
|
||||
int mqtt_list_is_empty(mqtt_list_t *list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIST_H_ */
|
||||
|
71
package/mqtt/mqtt_log.h
Normal file
71
package/mqtt/mqtt_log.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-27 03:25:58
|
||||
* @LastEditTime: 2020-10-17 14:15:55
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTT_LOG_H_
|
||||
#define _MQTT_LOG_H_
|
||||
|
||||
#include "mqtt_defconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MQTT_LOG_BASE_LEVEL (0)
|
||||
#define MQTT_LOG_ERR_LEVEL (MQTT_LOG_BASE_LEVEL + 1)
|
||||
#define MQTT_LOG_WARN_LEVEL (MQTT_LOG_ERR_LEVEL + 1)
|
||||
#define MQTT_LOG_INFO_LEVEL (MQTT_LOG_WARN_LEVEL + 1)
|
||||
#define MQTT_LOG_DEBUG_LEVEL (MQTT_LOG_INFO_LEVEL + 1)
|
||||
|
||||
#ifdef MQTT_LOG_IS_SALOF
|
||||
#include "salof.h"
|
||||
|
||||
#define MQTT_LOG_D(fmt, ...) SALOF_LOG_DEBUG(fmt, ##__VA_ARGS__)
|
||||
#define MQTT_LOG_I(fmt, ...) SALOF_LOG_INFO(fmt, ##__VA_ARGS__)
|
||||
#define MQTT_LOG_W(fmt, ...) SALOF_LOG_WARN(fmt, ##__VA_ARGS__)
|
||||
#define MQTT_LOG_E(fmt, ...) SALOF_LOG_ERR(fmt, ##__VA_ARGS__)
|
||||
#define mqtt_log_init salof_init
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_DEBUG_LEVEL
|
||||
#define MQTT_LOG_D(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG_D(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_INFO_LEVEL
|
||||
#define MQTT_LOG_I(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG_I(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_WARN_LEVEL
|
||||
#define MQTT_LOG_W(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG_W(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_ERR_LEVEL
|
||||
#define MQTT_LOG_E(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG_E(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_BASE_LEVEL
|
||||
#define MQTT_LOG(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#define mqtt_log_init()
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LOG_H_ */
|
1500
package/mqtt/mqttclient.c
Normal file
1500
package/mqtt/mqttclient.c
Normal file
File diff suppressed because it is too large
Load Diff
180
package/mqtt/mqttclient.h
Normal file
180
package/mqtt/mqttclient.h
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-09 21:31:25
|
||||
* @LastEditTime : 2022-06-11 22:45:02
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTTCLIENT_H_
|
||||
#define _MQTTCLIENT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "MQTTPacket.h"
|
||||
#include "mqtt_list.h"
|
||||
#include "platform_timer.h"
|
||||
#include "platform_memory.h"
|
||||
#include "platform_mutex.h"
|
||||
#include "platform_thread.h"
|
||||
#include "mqtt_defconfig.h"
|
||||
#include "network.h"
|
||||
#include "random.h"
|
||||
#include "mqtt_error.h"
|
||||
#include "mqtt_log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum mqtt_qos {
|
||||
QOS0 = 0,
|
||||
QOS1 = 1,
|
||||
QOS2 = 2,
|
||||
SUBFAIL = 0x80
|
||||
} mqtt_qos_t;
|
||||
|
||||
typedef enum client_state {
|
||||
CLIENT_STATE_INVALID = -1,
|
||||
CLIENT_STATE_INITIALIZED = 0,
|
||||
CLIENT_STATE_CONNECTED = 1,
|
||||
CLIENT_STATE_DISCONNECTED = 2,
|
||||
CLIENT_STATE_CLEAN_SESSION = 3
|
||||
}client_state_t;
|
||||
|
||||
typedef struct mqtt_connack_data {
|
||||
uint8_t rc;
|
||||
uint8_t session_present;
|
||||
} mqtt_connack_data_t;
|
||||
|
||||
typedef struct mqtt_message {
|
||||
mqtt_qos_t qos;
|
||||
uint8_t retained;
|
||||
uint8_t dup;
|
||||
uint16_t id;
|
||||
size_t payloadlen;
|
||||
void *payload;
|
||||
} mqtt_message_t;
|
||||
|
||||
typedef struct message_data {
|
||||
char topic_name[MQTT_TOPIC_LEN_MAX];
|
||||
mqtt_message_t *message;
|
||||
} message_data_t;
|
||||
|
||||
typedef void (*interceptor_handler_t)(void* client, message_data_t* msg);
|
||||
typedef void (*message_handler_t)(void* client, message_data_t* msg);
|
||||
typedef void (*reconnect_handler_t)(void* client, void* reconnect_date);
|
||||
|
||||
typedef struct message_handlers {
|
||||
mqtt_list_t list;
|
||||
mqtt_qos_t qos;
|
||||
const char* topic_filter;
|
||||
message_handler_t handler;
|
||||
} message_handlers_t;
|
||||
|
||||
typedef struct ack_handlers {
|
||||
mqtt_list_t list;
|
||||
platform_timer_t timer;
|
||||
uint32_t type;
|
||||
uint16_t packet_id;
|
||||
message_handlers_t *handler;
|
||||
uint16_t payload_len;
|
||||
uint8_t *payload;
|
||||
} ack_handlers_t;
|
||||
|
||||
typedef struct mqtt_will_options {
|
||||
mqtt_qos_t will_qos;
|
||||
uint8_t will_retained;
|
||||
char *will_topic;
|
||||
char *will_message;
|
||||
} mqtt_will_options_t;
|
||||
|
||||
typedef struct mqtt_client {
|
||||
char *mqtt_client_id;
|
||||
char *mqtt_user_name;
|
||||
char *mqtt_password;
|
||||
char *mqtt_host;
|
||||
char *mqtt_port;
|
||||
char *mqtt_ca;
|
||||
void *mqtt_reconnect_data;
|
||||
uint8_t *mqtt_read_buf;
|
||||
uint8_t *mqtt_write_buf;
|
||||
uint16_t mqtt_keep_alive_interval;
|
||||
uint16_t mqtt_packet_id;
|
||||
uint32_t mqtt_will_flag : 1;
|
||||
uint32_t mqtt_clean_session : 1;
|
||||
uint32_t mqtt_ping_outstanding : 2;
|
||||
uint32_t mqtt_version : 4;
|
||||
uint32_t mqtt_ack_handler_number : 24;
|
||||
uint32_t mqtt_cmd_timeout;
|
||||
uint32_t mqtt_read_buf_size;
|
||||
uint32_t mqtt_write_buf_size;
|
||||
uint32_t mqtt_reconnect_try_duration;
|
||||
size_t mqtt_client_id_len;
|
||||
size_t mqtt_user_name_len;
|
||||
size_t mqtt_password_len;
|
||||
mqtt_will_options_t *mqtt_will_options;
|
||||
client_state_t mqtt_client_state;
|
||||
platform_mutex_t mqtt_write_lock;
|
||||
platform_mutex_t mqtt_global_lock;
|
||||
mqtt_list_t mqtt_msg_handler_list;
|
||||
mqtt_list_t mqtt_ack_handler_list;
|
||||
network_t *mqtt_network;
|
||||
platform_thread_t *mqtt_thread;
|
||||
platform_timer_t mqtt_last_sent;
|
||||
platform_timer_t mqtt_last_received;
|
||||
reconnect_handler_t mqtt_reconnect_handler;
|
||||
interceptor_handler_t mqtt_interceptor_handler;
|
||||
} mqtt_client_t;
|
||||
|
||||
|
||||
#define MQTT_ROBUSTNESS_CHECK(item, err) if (!(item)) { \
|
||||
MQTT_LOG_E("%s:%d %s()... check for error.", __FILE__, __LINE__, __FUNCTION__); \
|
||||
return err; }
|
||||
|
||||
#define MQTT_CLIENT_SET_DEFINE(name, type, res) \
|
||||
type mqtt_set_##name(mqtt_client_t *c, type t) { \
|
||||
MQTT_ROBUSTNESS_CHECK((c), res); \
|
||||
c->mqtt_##name = t; \
|
||||
return c->mqtt_##name; \
|
||||
}
|
||||
|
||||
#define MQTT_CLIENT_SET_STATEMENT(name, type) \
|
||||
type mqtt_set_##name(mqtt_client_t *, type);
|
||||
|
||||
MQTT_CLIENT_SET_STATEMENT(client_id, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(user_name, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(password, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(host, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(port, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(ca, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(reconnect_data, void*)
|
||||
MQTT_CLIENT_SET_STATEMENT(keep_alive_interval, uint16_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(will_flag, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(clean_session, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(version, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(cmd_timeout, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(read_buf_size, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(write_buf_size, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(reconnect_try_duration, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(reconnect_handler, reconnect_handler_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(interceptor_handler, interceptor_handler_t)
|
||||
|
||||
void mqtt_sleep_ms(int ms);
|
||||
mqtt_client_t *mqtt_lease(void);
|
||||
int mqtt_release(mqtt_client_t* c);
|
||||
int mqtt_connect(mqtt_client_t* c);
|
||||
int mqtt_disconnect(mqtt_client_t* c);
|
||||
int mqtt_keep_alive(mqtt_client_t* c);
|
||||
int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, message_handler_t msg_handler);
|
||||
int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter);
|
||||
int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg);
|
||||
int mqtt_list_subscribe_topic(mqtt_client_t* c);
|
||||
int mqtt_set_will_options(mqtt_client_t* c, char *topic, mqtt_qos_t qos, uint8_t retained, char *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MQTTCLIENT_H_ */
|
36
package/mqtt/nettype_tcp.c
Normal file
36
package/mqtt/nettype_tcp.c
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 13:38:52
|
||||
* @LastEditTime: 2020-05-25 10:13:41
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "nettype_tcp.h"
|
||||
#include "mqtt_log.h"
|
||||
#include "platform_net_socket.h"
|
||||
|
||||
int nettype_tcp_read(network_t *n, unsigned char *read_buf, int len, int timeout)
|
||||
{
|
||||
return platform_net_socket_recv_timeout(n->socket, read_buf, len, timeout);
|
||||
}
|
||||
|
||||
int nettype_tcp_write(network_t *n, unsigned char *write_buf, int len, int timeout)
|
||||
{
|
||||
return platform_net_socket_write_timeout(n->socket, write_buf, len, timeout);
|
||||
}
|
||||
|
||||
int nettype_tcp_connect(network_t* n)
|
||||
{
|
||||
n->socket = platform_net_socket_connect(n->host, n->port, PLATFORM_NET_PROTO_TCP);
|
||||
if (n->socket < 0)
|
||||
RETURN_ERROR(n->socket);
|
||||
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
||||
void nettype_tcp_disconnect(network_t* n)
|
||||
{
|
||||
if (NULL != n)
|
||||
platform_net_socket_close(n->socket);
|
||||
n->socket = -1;
|
||||
}
|
27
package/mqtt/nettype_tcp.h
Normal file
27
package/mqtt/nettype_tcp.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 13:39:00
|
||||
* @LastEditTime: 2020-10-17 14:17:10
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _NETTYPE_TCP_H_
|
||||
#define _NETTYPE_TCP_H_
|
||||
|
||||
#include "network.h"
|
||||
#include "mqtt_error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int nettype_tcp_read(network_t *n, unsigned char *buf, int len, int timeout);
|
||||
int nettype_tcp_write(network_t *n, unsigned char *buf, int len, int timeout);
|
||||
int nettype_tcp_connect(network_t* n);
|
||||
void nettype_tcp_disconnect(network_t* n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
253
package/mqtt/nettype_tls.c
Normal file
253
package/mqtt/nettype_tls.c
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2020-01-11 19:45:35
|
||||
* @LastEditTime: 2020-09-20 14:29:06
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "nettype_tls.h"
|
||||
#include "platform_net_socket.h"
|
||||
#include "platform_memory.h"
|
||||
#include "platform_timer.h"
|
||||
#include "random.h"
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/x509_crt.h"
|
||||
#include "mbedtls/pk.h"
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
static int server_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
|
||||
{
|
||||
if (0 != *flags)
|
||||
MQTT_LOG_E("%s:%d %s()... server_certificate_verify failed returned 0x%04x\n", __FILE__, __LINE__, __FUNCTION__, *flags);
|
||||
return *flags;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int nettype_tls_entropy_source(void *data, uint8_t *output, size_t len, size_t *out_len)
|
||||
{
|
||||
uint32_t seed;
|
||||
(void) data;
|
||||
seed = random_number();
|
||||
|
||||
if (len > sizeof(seed)) {
|
||||
len = sizeof(seed);
|
||||
}
|
||||
|
||||
memcpy(output, &seed, len);
|
||||
*out_len = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nettype_tls_init(network_t* n, nettype_tls_params_t* nettype_tls_params)
|
||||
{
|
||||
int rc = MQTT_SUCCESS_ERROR;
|
||||
|
||||
mbedtls_platform_set_calloc_free(platform_memory_calloc, platform_memory_free);
|
||||
|
||||
mbedtls_net_init(&(nettype_tls_params->socket_fd));
|
||||
mbedtls_ssl_init(&(nettype_tls_params->ssl));
|
||||
mbedtls_ssl_config_init(&(nettype_tls_params->ssl_conf));
|
||||
mbedtls_ctr_drbg_init(&(nettype_tls_params->ctr_drbg));
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
mbedtls_x509_crt_init(&(nettype_tls_params->ca_cert));
|
||||
mbedtls_x509_crt_init(&(nettype_tls_params->client_cert));
|
||||
mbedtls_pk_init(&(nettype_tls_params->private_key));
|
||||
#endif
|
||||
|
||||
mbedtls_entropy_init(&(nettype_tls_params->entropy));
|
||||
mbedtls_entropy_add_source(&(nettype_tls_params->entropy), nettype_tls_entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG);
|
||||
|
||||
if ((rc = mbedtls_ctr_drbg_seed(&(nettype_tls_params->ctr_drbg), mbedtls_entropy_func,
|
||||
&(nettype_tls_params->entropy), NULL, 0)) != 0) {
|
||||
MQTT_LOG_E("mbedtls_ctr_drbg_seed failed returned 0x%04x", (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
if ((rc = mbedtls_ssl_config_defaults(&(nettype_tls_params->ssl_conf), MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
MQTT_LOG_E("mbedtls_ssl_config_defaults failed returned 0x%04x", (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_rng(&(nettype_tls_params->ssl_conf), mbedtls_ctr_drbg_random, &(nettype_tls_params->ctr_drbg));
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if (NULL != n->ca_crt) {
|
||||
n->ca_crt_len = strlen(n->ca_crt);
|
||||
|
||||
if (0 != (rc = (mbedtls_x509_crt_parse(&(nettype_tls_params->ca_cert), (unsigned char *)n->ca_crt,
|
||||
(n->ca_crt_len + 1))))) {
|
||||
MQTT_LOG_E("%s:%d %s()... parse ca crt failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(&(nettype_tls_params->ssl_conf), &(nettype_tls_params->ca_cert), NULL);
|
||||
|
||||
if ((rc = mbedtls_ssl_conf_own_cert(&(nettype_tls_params->ssl_conf),
|
||||
&(nettype_tls_params->client_cert), &(nettype_tls_params->private_key))) != 0) {
|
||||
MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_conf_own_cert failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_verify(&(nettype_tls_params->ssl_conf), server_certificate_verify, (void *)n->host);
|
||||
|
||||
mbedtls_ssl_conf_authmode(&(nettype_tls_params->ssl_conf), MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
#endif
|
||||
|
||||
mbedtls_ssl_conf_read_timeout(&(nettype_tls_params->ssl_conf), n->timeout_ms);
|
||||
|
||||
if ((rc = mbedtls_ssl_setup(&(nettype_tls_params->ssl), &(nettype_tls_params->ssl_conf))) != 0) {
|
||||
MQTT_LOG_E("mbedtls_ssl_setup failed returned 0x%04x", (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if ((rc = mbedtls_ssl_set_hostname(&(nettype_tls_params->ssl), n->host)) != 0) {
|
||||
MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_set_hostname failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
mbedtls_ssl_set_bio(&(nettype_tls_params->ssl), &(nettype_tls_params->socket_fd), mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);
|
||||
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
||||
|
||||
int nettype_tls_connect(network_t* n)
|
||||
{
|
||||
int rc;
|
||||
if (NULL == n)
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) platform_memory_alloc(sizeof(nettype_tls_params_t));
|
||||
|
||||
if (NULL == nettype_tls_params)
|
||||
RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
|
||||
|
||||
|
||||
rc = nettype_tls_init(n, nettype_tls_params);
|
||||
if (MQTT_SUCCESS_ERROR != rc)
|
||||
goto exit;
|
||||
|
||||
if (0 != (rc = mbedtls_net_connect(&(nettype_tls_params->socket_fd), n->host, n->port, MBEDTLS_NET_PROTO_TCP)))
|
||||
goto exit;
|
||||
|
||||
while ((rc = mbedtls_ssl_handshake(&(nettype_tls_params->ssl))) != 0) {
|
||||
if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
MQTT_LOG_E("%s:%d %s()...mbedtls handshake failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
|
||||
MQTT_LOG_E("%s:%d %s()...unable to verify the server's certificate", __FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
#endif
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rc = mbedtls_ssl_get_verify_result(&(nettype_tls_params->ssl))) != 0) {
|
||||
MQTT_LOG_E("%s:%d %s()...mbedtls_ssl_get_verify_result returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
n->nettype_tls_params = nettype_tls_params;
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR)
|
||||
|
||||
exit:
|
||||
platform_memory_free(nettype_tls_params);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
|
||||
void nettype_tls_disconnect(network_t* n)
|
||||
{
|
||||
int rc = 0;
|
||||
if (NULL == n)
|
||||
return;
|
||||
|
||||
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
|
||||
|
||||
do {
|
||||
rc = mbedtls_ssl_close_notify(&(nettype_tls_params->ssl));
|
||||
} while (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
|
||||
mbedtls_net_free(&(nettype_tls_params->socket_fd));
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
mbedtls_x509_crt_free(&(nettype_tls_params->client_cert));
|
||||
mbedtls_x509_crt_free(&(nettype_tls_params->ca_cert));
|
||||
mbedtls_pk_free(&(nettype_tls_params->private_key));
|
||||
#endif
|
||||
mbedtls_ssl_free(&(nettype_tls_params->ssl));
|
||||
mbedtls_ssl_config_free(&(nettype_tls_params->ssl_conf));
|
||||
mbedtls_ctr_drbg_free(&(nettype_tls_params->ctr_drbg));
|
||||
mbedtls_entropy_free(&(nettype_tls_params->entropy));
|
||||
|
||||
platform_memory_free(nettype_tls_params);
|
||||
}
|
||||
|
||||
int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
int rc = 0;
|
||||
int write_len = 0;
|
||||
platform_timer_t timer;
|
||||
|
||||
if (NULL == n)
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
|
||||
|
||||
platform_timer_cutdown(&timer, timeout);
|
||||
|
||||
do {
|
||||
rc = mbedtls_ssl_write(&(nettype_tls_params->ssl), (unsigned char *)(buf + write_len), len - write_len);
|
||||
|
||||
if (rc > 0) {
|
||||
write_len += rc;
|
||||
} else if ((rc == 0) || ((rc != MBEDTLS_ERR_SSL_WANT_WRITE) && (rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_TIMEOUT))) {
|
||||
MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_write failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
break;
|
||||
}
|
||||
} while((!platform_timer_is_expired(&timer)) && (write_len < len));
|
||||
|
||||
return write_len;
|
||||
}
|
||||
|
||||
int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
int rc = 0;
|
||||
int read_len = 0;
|
||||
platform_timer_t timer;
|
||||
|
||||
if (NULL == n)
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
|
||||
|
||||
platform_timer_cutdown(&timer, timeout);
|
||||
|
||||
do {
|
||||
rc = mbedtls_ssl_read(&(nettype_tls_params->ssl), (unsigned char *)(buf + read_len), len - read_len);
|
||||
|
||||
if (rc > 0) {
|
||||
read_len += rc;
|
||||
} else if ((rc == 0) || ((rc != MBEDTLS_ERR_SSL_WANT_WRITE) && (rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_TIMEOUT))) {
|
||||
// MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_read failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
break;
|
||||
}
|
||||
} while((!platform_timer_is_expired(&timer)) && (read_len < len));
|
||||
|
||||
return read_len;
|
||||
}
|
||||
|
||||
#endif /* MQTT_NETWORK_TYPE_NO_TLS */
|
64
package/mqtt/nettype_tls.h
Normal file
64
package/mqtt/nettype_tls.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* @Author : jiejie
|
||||
* @GitHub : https://github.com/jiejieTop
|
||||
* @Date : 2021-02-26 12:00:24
|
||||
* @LastEditors : jiejie
|
||||
* @LastEditTime : 2022-06-15 19:48:43
|
||||
* @FilePath : /mqttclient/network/nettype_tls.h
|
||||
* Copyright (c) 2022 jiejie, All Rights Reserved. Please keep the author information and source code according to the license.
|
||||
*/
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2020-01-11 19:45:44
|
||||
* @LastEditTime: 2020-10-17 14:14:11
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
#ifndef _NETTYPE_TLS_H_
|
||||
#define _NETTYPE_TLS_H_
|
||||
|
||||
#include "mqtt_defconfig.h"
|
||||
#include "network.h"
|
||||
#include "mqtt_error.h"
|
||||
#include "mqtt_log.h"
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
|
||||
#include "mbedtls/config.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct nettype_tls_params {
|
||||
mbedtls_net_context socket_fd; /**< mbed TLS network context. */
|
||||
mbedtls_entropy_context entropy; /**< mbed TLS entropy. */
|
||||
mbedtls_ctr_drbg_context ctr_drbg; /**< mbed TLS ctr_drbg. */
|
||||
mbedtls_ssl_context ssl; /**< mbed TLS control context. */
|
||||
mbedtls_ssl_config ssl_conf; /**< mbed TLS configuration context. */
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
mbedtls_x509_crt ca_cert; /**< mbed TLS CA certification. */
|
||||
mbedtls_x509_crt client_cert; /**< mbed TLS Client certification. */
|
||||
#endif
|
||||
mbedtls_pk_context private_key; /**< mbed TLS Client key. */
|
||||
} nettype_tls_params_t;
|
||||
|
||||
int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout);
|
||||
int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout);
|
||||
int nettype_tls_connect(network_t* n);
|
||||
void nettype_tls_disconnect(network_t* n);
|
||||
|
||||
#endif /* MQTT_NETWORK_TYPE_NO_TLS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
113
package/mqtt/network.c
Normal file
113
package/mqtt/network.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-09 21:30:54
|
||||
* @LastEditTime: 2020-06-05 17:17:48
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "platform_timer.h"
|
||||
#include "platform_memory.h"
|
||||
#include "nettype_tcp.h"
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
#include "nettype_tls.h"
|
||||
#endif
|
||||
|
||||
int network_read(network_t *n, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if (n->channel)
|
||||
return nettype_tls_read(n, buf, len, timeout);
|
||||
#endif
|
||||
return nettype_tcp_read(n, buf, len, timeout);
|
||||
}
|
||||
|
||||
int network_write(network_t *n, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if (n->channel)
|
||||
return nettype_tls_write(n, buf, len, timeout);
|
||||
#endif
|
||||
return nettype_tcp_write(n, buf, len, timeout);
|
||||
}
|
||||
|
||||
int network_connect(network_t *n)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if (n->channel)
|
||||
return nettype_tls_connect(n);
|
||||
#endif
|
||||
return nettype_tcp_connect(n);
|
||||
|
||||
}
|
||||
|
||||
void network_disconnect(network_t *n)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if (n->channel)
|
||||
nettype_tls_disconnect(n);
|
||||
else
|
||||
#endif
|
||||
nettype_tcp_disconnect(n);
|
||||
}
|
||||
|
||||
int network_init(network_t *n, const char *host, const char *port, const char *ca)
|
||||
{
|
||||
if (NULL == n)
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
n->socket = -1;
|
||||
n->host = host;
|
||||
n->port = port;
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
n->channel = 0;
|
||||
|
||||
if (NULL != ca) {
|
||||
network_set_ca(n, ca);
|
||||
}
|
||||
#endif
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
||||
void network_release(network_t* n)
|
||||
{
|
||||
if (n->socket >= 0)
|
||||
network_disconnect(n);
|
||||
|
||||
memset(n, 0, sizeof(network_t));
|
||||
}
|
||||
|
||||
void network_set_channel(network_t *n, int channel)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
n->channel = channel;
|
||||
#endif
|
||||
}
|
||||
|
||||
int network_set_ca(network_t *n, const char *ca)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if ((NULL == n) || (NULL == ca))
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
n->ca_crt = ca;
|
||||
n->ca_crt_len = strlen(ca);
|
||||
n->channel = NETWORK_CHANNEL_TLS;
|
||||
n->timeout_ms = MQTT_TLS_HANDSHAKE_TIMEOUT;
|
||||
#endif
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
||||
int network_set_host_port(network_t* n, char *host, char *port)
|
||||
{
|
||||
if (!(n && host && port))
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
n->host = host;
|
||||
n->port = port;
|
||||
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
47
package/mqtt/network.h
Normal file
47
package/mqtt/network.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-09 21:31:02
|
||||
* @LastEditTime: 2020-10-17 14:14:41
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _NETWORK_H_
|
||||
#define _NETWORK_H_
|
||||
|
||||
#include "mqtt_defconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NETWORK_CHANNEL_TCP 0
|
||||
#define NETWORK_CHANNEL_TLS 1
|
||||
|
||||
typedef struct network {
|
||||
const char *host;
|
||||
const char *port;
|
||||
int socket;
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
int channel; /* tcp or tls */
|
||||
const char *ca_crt;
|
||||
unsigned int ca_crt_len;
|
||||
unsigned int timeout_ms; // SSL handshake timeout in millisecond
|
||||
void *nettype_tls_params;
|
||||
#endif
|
||||
} network_t;
|
||||
|
||||
int network_init(network_t *n, const char *host, const char *port, const char *ca);
|
||||
int network_set_ca(network_t *n, const char *ca);
|
||||
void network_set_channel(network_t *n, int channel);
|
||||
int network_set_host_port(network_t* n, char *host, char *port);
|
||||
int network_read(network_t* n, unsigned char* buf, int len, int timeout);
|
||||
int network_write(network_t* n, unsigned char* buf, int len, int timeout);
|
||||
int network_connect(network_t* n);
|
||||
void network_disconnect(network_t *n);
|
||||
void network_release(network_t* n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
26
package/mqtt/platform_memory.c
Normal file
26
package/mqtt/platform_memory.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-14 22:02:07
|
||||
* @LastEditTime: 2020-02-19 20:26:04
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "platform_memory.h"
|
||||
|
||||
void *platform_memory_alloc(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *platform_memory_calloc(size_t num, size_t size)
|
||||
{
|
||||
return calloc(num, size);
|
||||
}
|
||||
|
||||
void platform_memory_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
|
26
package/mqtt/platform_memory.h
Normal file
26
package/mqtt/platform_memory.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-14 22:06:35
|
||||
* @LastEditTime: 2020-10-17 14:17:24
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_MEMORY_H_
|
||||
#define _PLATFORM_MEMORY_H_
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *platform_memory_alloc(size_t size);
|
||||
void *platform_memory_calloc(size_t num, size_t size);
|
||||
void platform_memory_free(void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
33
package/mqtt/platform_mutex.c
Normal file
33
package/mqtt/platform_mutex.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 18:27:19
|
||||
* @LastEditTime: 2020-02-23 15:01:06
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "platform_mutex.h"
|
||||
|
||||
int platform_mutex_init(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_init(&(m->mutex), NULL);
|
||||
}
|
||||
|
||||
int platform_mutex_lock(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_lock(&(m->mutex));
|
||||
}
|
||||
|
||||
int platform_mutex_trylock(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_trylock(&(m->mutex));
|
||||
}
|
||||
|
||||
int platform_mutex_unlock(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_unlock(&(m->mutex));
|
||||
}
|
||||
|
||||
int platform_mutex_destroy(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_destroy(&(m->mutex));
|
||||
}
|
30
package/mqtt/platform_mutex.h
Normal file
30
package/mqtt/platform_mutex.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 18:31:33
|
||||
* @LastEditTime: 2020-10-17 14:17:31
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_MUTEX_H_
|
||||
#define _PLATFORM_MUTEX_H_
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct platform_mutex {
|
||||
pthread_mutex_t mutex;
|
||||
} platform_mutex_t;
|
||||
|
||||
int platform_mutex_init(platform_mutex_t* m);
|
||||
int platform_mutex_lock(platform_mutex_t* m);
|
||||
int platform_mutex_trylock(platform_mutex_t* m);
|
||||
int platform_mutex_unlock(platform_mutex_t* m);
|
||||
int platform_mutex_destroy(platform_mutex_t* m);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
125
package/mqtt/platform_net_socket.c
Normal file
125
package/mqtt/platform_net_socket.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2020-01-10 23:45:59
|
||||
* @LastEditTime: 2020-06-05 17:13:00
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "platform_net_socket.h"
|
||||
#include "mqtt_error.h"
|
||||
|
||||
int platform_net_socket_connect(const char *host, const char *port, int proto)
|
||||
{
|
||||
int fd, ret = MQTT_SOCKET_UNKNOWN_HOST_ERROR;
|
||||
struct addrinfo hints, *addr_list, *cur;
|
||||
|
||||
/* Do name resolution with both IPv6 and IPv4 */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = (proto == PLATFORM_NET_PROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
|
||||
hints.ai_protocol = (proto == PLATFORM_NET_PROTO_UDP) ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
|
||||
if (getaddrinfo(host, port, &hints, &addr_list) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
|
||||
fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
||||
if (fd < 0) {
|
||||
ret = MQTT_SOCKET_FAILED_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
|
||||
ret = fd;
|
||||
break;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
ret = MQTT_CONNECT_FAILED_ERROR;
|
||||
}
|
||||
|
||||
freeaddrinfo(addr_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int platform_net_socket_recv(int fd, void *buf, size_t len, int flags)
|
||||
{
|
||||
return recv(fd, buf, len, flags);
|
||||
}
|
||||
|
||||
int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
int nread;
|
||||
int nleft = len;
|
||||
unsigned char *ptr;
|
||||
ptr = buf;
|
||||
|
||||
struct timeval tv = {
|
||||
timeout / 1000,
|
||||
(timeout % 1000) * 1000
|
||||
};
|
||||
|
||||
if (tv.tv_sec < 0 || (tv.tv_sec == 0 && tv.tv_usec <= 0)) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100;
|
||||
}
|
||||
|
||||
platform_net_socket_setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
|
||||
|
||||
while (nleft > 0) {
|
||||
nread = platform_net_socket_recv(fd, ptr, nleft, 0);
|
||||
if (nread < 0) {
|
||||
return -1;
|
||||
} else if (nread == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
nleft -= nread;
|
||||
ptr += nread;
|
||||
}
|
||||
return len - nleft;
|
||||
}
|
||||
|
||||
int platform_net_socket_write(int fd, void *buf, size_t len)
|
||||
{
|
||||
return write(fd, buf, len);
|
||||
}
|
||||
|
||||
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
struct timeval tv = {
|
||||
timeout / 1000,
|
||||
(timeout % 1000) * 1000
|
||||
};
|
||||
|
||||
if (tv.tv_sec < 0 || (tv.tv_sec == 0 && tv.tv_usec <= 0)) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100;
|
||||
}
|
||||
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval));
|
||||
|
||||
return write(fd, buf, len);
|
||||
}
|
||||
|
||||
int platform_net_socket_close(int fd)
|
||||
{
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
int platform_net_socket_set_block(int fd)
|
||||
{
|
||||
return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, F_GETFL) & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
int platform_net_socket_set_nonblock(int fd)
|
||||
{
|
||||
return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, F_GETFL) | O_NONBLOCK);
|
||||
}
|
||||
|
||||
int platform_net_socket_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
return setsockopt(fd, level, optname, optval, optlen);
|
||||
}
|
||||
|
49
package/mqtt/platform_net_socket.h
Normal file
49
package/mqtt/platform_net_socket.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 13:39:00
|
||||
* @LastEditTime: 2020-10-17 14:17:45
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_NET_SOCKET_H_
|
||||
#define _PLATFORM_NET_SOCKET_H_
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PLATFORM_NET_PROTO_TCP 0 /**< The TCP transport protocol */
|
||||
#define PLATFORM_NET_PROTO_UDP 1 /**< The UDP transport protocol */
|
||||
|
||||
int platform_net_socket_connect(const char *host, const char *port, int proto);
|
||||
int platform_net_socket_recv(int fd, void *buf, size_t len, int flags);
|
||||
int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout);
|
||||
int platform_net_socket_write(int fd, void *buf, size_t len);
|
||||
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout);
|
||||
int platform_net_socket_close(int fd);
|
||||
int platform_net_socket_set_block(int fd);
|
||||
int platform_net_socket_set_nonblock(int fd);
|
||||
int platform_net_socket_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PLATFORM_NET_SOCKET_H_ */
|
61
package/mqtt/platform_thread.c
Normal file
61
package/mqtt/platform_thread.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-23 19:26:27
|
||||
* @LastEditTime: 2020-02-23 16:19:07
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "platform_thread.h"
|
||||
#include "platform_memory.h"
|
||||
|
||||
platform_thread_t *platform_thread_init( const char *name,
|
||||
void (*entry)(void *),
|
||||
void * const param,
|
||||
unsigned int stack_size,
|
||||
unsigned int priority,
|
||||
unsigned int tick)
|
||||
{
|
||||
int res;
|
||||
platform_thread_t *thread;
|
||||
void *(*thread_entry) (void *);
|
||||
|
||||
thread_entry = (void *(*)(void*))entry;
|
||||
thread = platform_memory_alloc(sizeof(platform_thread_t));
|
||||
|
||||
res = pthread_create(&thread->thread, NULL, thread_entry, param);
|
||||
if(res != 0) {
|
||||
platform_memory_free(thread);
|
||||
}
|
||||
|
||||
thread->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
|
||||
thread->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
void platform_thread_startup(platform_thread_t* thread)
|
||||
{
|
||||
(void) thread;
|
||||
}
|
||||
|
||||
void platform_thread_stop(platform_thread_t* thread)
|
||||
{
|
||||
pthread_mutex_lock(&(thread->mutex));
|
||||
pthread_cond_wait(&(thread->cond), &(thread->mutex));
|
||||
pthread_mutex_unlock(&(thread->mutex));
|
||||
}
|
||||
|
||||
void platform_thread_start(platform_thread_t* thread)
|
||||
{
|
||||
pthread_mutex_lock(&(thread->mutex));
|
||||
pthread_cond_signal(&(thread->cond));
|
||||
pthread_mutex_unlock(&(thread->mutex));
|
||||
}
|
||||
|
||||
void platform_thread_destroy(platform_thread_t* thread)
|
||||
{
|
||||
if (NULL != thread)
|
||||
pthread_detach(thread->thread);
|
||||
}
|
||||
|
||||
|
38
package/mqtt/platform_thread.h
Normal file
38
package/mqtt/platform_thread.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 18:31:44
|
||||
* @LastEditTime: 2020-10-17 14:15:21
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_THREAD_H_
|
||||
#define _PLATFORM_THREAD_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct platform_thread {
|
||||
pthread_t thread;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
} platform_thread_t;
|
||||
|
||||
platform_thread_t *platform_thread_init( const char *name,
|
||||
void (*entry)(void *),
|
||||
void * const param,
|
||||
unsigned int stack_size,
|
||||
unsigned int priority,
|
||||
unsigned int tick);
|
||||
void platform_thread_startup(platform_thread_t* thread);
|
||||
void platform_thread_stop(platform_thread_t* thread);
|
||||
void platform_thread_start(platform_thread_t* thread);
|
||||
void platform_thread_destroy(platform_thread_t* thread);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
48
package/mqtt/platform_timer.c
Normal file
48
package/mqtt/platform_timer.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-10 22:16:41
|
||||
* @LastEditTime: 2020-06-05 17:18:48
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
#include "platform_timer.h"
|
||||
|
||||
void platform_timer_init(platform_timer_t* timer)
|
||||
{
|
||||
timer->time = (struct timeval){0, 0};
|
||||
}
|
||||
|
||||
void platform_timer_cutdown(platform_timer_t* timer, unsigned int timeout)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000};
|
||||
timeradd(&now, &interval, &timer->time);
|
||||
}
|
||||
|
||||
char platform_timer_is_expired(platform_timer_t* timer)
|
||||
{
|
||||
struct timeval now, res;
|
||||
gettimeofday(&now, NULL);
|
||||
timersub(&timer->time, &now, &res);
|
||||
return ((res.tv_sec < 0) || (res.tv_sec == 0 && res.tv_usec <= 0));
|
||||
}
|
||||
|
||||
int platform_timer_remain(platform_timer_t* timer)
|
||||
{
|
||||
struct timeval now, res;
|
||||
gettimeofday(&now, NULL);
|
||||
timersub(&timer->time, &now, &res);
|
||||
return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;
|
||||
}
|
||||
|
||||
unsigned long platform_timer_now(void)
|
||||
{
|
||||
return (unsigned long) time(NULL);
|
||||
}
|
||||
|
||||
void platform_timer_usleep(unsigned long usec)
|
||||
{
|
||||
usleep(usec);
|
||||
}
|
35
package/mqtt/platform_timer.h
Normal file
35
package/mqtt/platform_timer.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-10 22:18:32
|
||||
* @LastEditTime: 2020-10-17 14:17:55
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_TIMER_H_
|
||||
#define _PLATFORM_TIMER_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct platform_timer {
|
||||
struct timeval time;
|
||||
} platform_timer_t;
|
||||
|
||||
void platform_timer_init(platform_timer_t* timer);
|
||||
void platform_timer_cutdown(platform_timer_t* timer, unsigned int timeout);
|
||||
char platform_timer_is_expired(platform_timer_t* timer);
|
||||
int platform_timer_remain(platform_timer_t* timer);
|
||||
unsigned long platform_timer_now(void);
|
||||
void platform_timer_usleep(unsigned long usec);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
77
package/mqtt/random.c
Normal file
77
package/mqtt/random.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* @Author : jiejie
|
||||
* @GitHub : https://github.com/jiejieTop
|
||||
* @Date : 2021-02-26 12:00:24
|
||||
* @LastEditors : jiejie
|
||||
* @LastEditTime : 2022-06-15 19:44:22
|
||||
* @FilePath : /mqttclient/common/random.c
|
||||
* Copyright (c) 2022 jiejie, All Rights Reserved. Please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "random.h"
|
||||
|
||||
extern int platform_timer_now();
|
||||
static unsigned int last_seed = 1;
|
||||
|
||||
|
||||
int __attribute__((weak)) platform_timer_now()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int do_random(unsigned int seed)
|
||||
{
|
||||
srand(seed);
|
||||
return rand();
|
||||
}
|
||||
|
||||
int random_number(void)
|
||||
{
|
||||
unsigned int seed = (unsigned int) platform_timer_now();
|
||||
last_seed += (seed >> ((seed ^ last_seed) % 3));
|
||||
return do_random(last_seed ^ seed);
|
||||
}
|
||||
|
||||
// random number range interval [min, max)
|
||||
int random_number_range(unsigned int min, unsigned int max)
|
||||
{
|
||||
return (random_number() % (max - min)) + min;
|
||||
}
|
||||
|
||||
int random_string(char *buffer, int len)
|
||||
{
|
||||
unsigned int i, flag, seed, random;
|
||||
|
||||
if (NULL == buffer)
|
||||
return 0;
|
||||
|
||||
seed = (unsigned int) random_number();
|
||||
seed += (unsigned int) ((size_t)buffer ^ seed);
|
||||
|
||||
random = (unsigned int)do_random(seed);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
random = do_random(seed ^ random);
|
||||
flag = (unsigned int)random % 3;
|
||||
switch (flag) {
|
||||
case 0:
|
||||
buffer[i] = 'A' + do_random(random ^ (i & flag)) % 26;
|
||||
break;
|
||||
case 1:
|
||||
buffer[i] = 'a' + do_random(random ^ (i & flag)) % 26;
|
||||
break;
|
||||
case 2:
|
||||
buffer[i] = '0' + do_random(random ^ (i & flag)) % 10;
|
||||
break;
|
||||
default:
|
||||
buffer[i] = 'x';
|
||||
break;
|
||||
}
|
||||
random += ((0xb433e5c6 ^ random) << (i & flag));
|
||||
}
|
||||
|
||||
buffer[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
29
package/mqtt/random.h
Normal file
29
package/mqtt/random.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* @Author : jiejie
|
||||
* @GitHub : https://github.com/jiejieTop
|
||||
* @Date : 2021-02-26 12:00:24
|
||||
* @LastEditors : jiejie
|
||||
* @LastEditTime : 2022-06-15 19:40:10
|
||||
* @FilePath : /mqttclient/common/random.h
|
||||
* Copyright (c) 2022 jiejie, All Rights Reserved. Please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _RANDOM_H_
|
||||
#define _RANDOM_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RANDOM_MAX 0x7FFFFFFF
|
||||
|
||||
int random_number(void);
|
||||
int random_number_range(unsigned int min, unsigned int max);
|
||||
int random_string(char *buffer, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _RANDOM_H_ */
|
4
port/linux/.vscode/settings.json
vendored
4
port/linux/.vscode/settings.json
vendored
@ -72,7 +72,9 @@
|
||||
"fcntl.h": "c",
|
||||
"pikastddata_bytearray.h": "c",
|
||||
"webclient.h": "c",
|
||||
"platform_socket.h": "c"
|
||||
"platform_socket.h": "c",
|
||||
"nettype_tcp.h": "c",
|
||||
"platform_memory.h": "c"
|
||||
},
|
||||
"python.formatting.provider": "autopep8",
|
||||
"C_Cpp.errorSquiggles": "Disabled"
|
||||
|
@ -1,6 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.0.0)
|
||||
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-sign-conversion -Wno-write-strings -Wno-implicit-fallthrough
|
||||
-Wno-unused-function)
|
||||
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-sign-conversion -Wno-write-strings -Wno-implicit-fallthrough -Wno-sign-compare -Wno-cast-function-type -Wno-unused-function)
|
||||
OPTION(PIKA_CONFIG_ENABLE "pika config enable" OFF)
|
||||
IF(PIKA_CONFIG_ENABLE)
|
||||
ADD_DEFINITIONS(-DPIKA_CONFIG_ENABLE)
|
||||
|
148
port/linux/package/pikascript/pikascript-lib/mqtt/MQTTConnect.h
Normal file
148
port/linux/package/pikascript/pikascript-lib/mqtt/MQTTConnect.h
Normal file
@ -0,0 +1,148 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014, 2017 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 - add connack return code definitions
|
||||
* Xiang Rong - 442039 Add makefile to Embedded C client
|
||||
* Ian Craggs - fix for issue #64, bit order in connack response
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTCONNECT_H_
|
||||
#define MQTTCONNECT_H_
|
||||
|
||||
enum connack_return_codes
|
||||
{
|
||||
MQTT_CONNECTION_ACCEPTED = 0,
|
||||
MQTT_UNNACCEPTABLE_PROTOCOL = 1,
|
||||
MQTT_CLIENTID_REJECTED = 2,
|
||||
MQTT_SERVER_UNAVAILABLE = 3,
|
||||
MQTT_BAD_USERNAME_OR_PASSWORD = 4,
|
||||
MQTT_NOT_AUTHORIZED = 5,
|
||||
};
|
||||
|
||||
#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 reserved : 7; /**< unused */
|
||||
unsigned int sessionpresent : 1; /**< session present flag */
|
||||
} bits;
|
||||
#else
|
||||
struct
|
||||
{
|
||||
unsigned int sessionpresent : 1; /**< session present flag */
|
||||
unsigned int reserved: 7; /**< unused */
|
||||
} 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_ */
|
@ -0,0 +1,214 @@
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
262
port/linux/package/pikascript/pikascript-lib/mqtt/MQTTFormat.c
Normal file
262
port/linux/package/pikascript/pikascript-lib/mqtt/MQTTFormat.c
Normal file
@ -0,0 +1,262 @@
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
#if defined(MQTT_CLIENT)
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MQTT_SERVER)
|
||||
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;
|
||||
}
|
||||
#endif
|
@ -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
|
412
port/linux/package/pikascript/pikascript-lib/mqtt/MQTTPacket.c
Normal file
412
port/linux/package/pikascript/pikascript-lib/mqtt/MQTTPacket.c
Normal file
@ -0,0 +1,412 @@
|
||||
/*******************************************************************************
|
||||
* 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 (rem_len && ((*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->len);
|
||||
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:
|
||||
if(trp->rem_len){
|
||||
/* 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;
|
||||
}
|
||||
|
133
port/linux/package/pikascript/pikascript-lib/mqtt/MQTTPacket.h
Normal file
133
port/linux/package/pikascript/pikascript-lib/mqtt/MQTTPacket.h
Normal file
@ -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"
|
||||
|
||||
DLLExport int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid);
|
||||
DLLExport int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTPacket_len(int rem_len);
|
||||
DLLExport int MQTTPacket_equals(MQTTString* a, char* b);
|
||||
|
||||
DLLExport 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_ */
|
@ -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_ */
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-09 20:15:32
|
||||
* @LastEditTime: 2019-12-20 20:37:31
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
/*******************************************************************************
|
||||
* 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_ */
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @LastEditTime: 2020-06-17 19:31:41
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTT_CONFIG_H_
|
||||
#define _MQTT_CONFIG_H_
|
||||
|
||||
// #define MQTT_LOG_IS_SALOF
|
||||
|
||||
#define MQTT_LOG_LEVEL MQTT_LOG_INFO_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
|
||||
|
||||
#ifdef MQTT_LOG_IS_SALOF
|
||||
#define SALOF_USING_LOG (1U)
|
||||
#define SALOF_USING_SALOF (1U)
|
||||
#define SALOF_LOG_LEVEL MQTT_LOG_LEVEL
|
||||
#define SALOF_OS SALOF_USING_LINUX
|
||||
#define SALOF_USING_IDLE_HOOK (0U)
|
||||
#define SALOF_LOG_COLOR (1U)
|
||||
#define SALOF_LOG_TS (0U)
|
||||
#define SALOF_LOG_TAR (0U)
|
||||
#define SALOF_BUFF_SIZE 512
|
||||
#define SALOF_FIFO_SIZE 4096
|
||||
#define SALOF_TASK_STACK_SIZE 1024
|
||||
#define SALOF_TASK_TICK 50
|
||||
#endif
|
||||
|
||||
#define MQTT_MAX_PACKET_ID (0xFFFF - 1)
|
||||
#define MQTT_TOPIC_LEN_MAX 64
|
||||
#define MQTT_ACK_HANDLER_NUM_MAX 64
|
||||
#define MQTT_DEFAULT_BUF_SIZE 1024
|
||||
#define MQTT_DEFAULT_CMD_TIMEOUT 5000
|
||||
#define MQTT_MAX_CMD_TIMEOUT 20000
|
||||
#define MQTT_MIN_CMD_TIMEOUT 1000
|
||||
#define MQTT_KEEP_ALIVE_INTERVAL 50 // unit: second
|
||||
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1
|
||||
#define MQTT_RECONNECT_DEFAULT_DURATION 1000
|
||||
#define MQTT_THREAD_STACK_SIZE 2048
|
||||
#define MQTT_THREAD_PRIO 5
|
||||
#define MQTT_THREAD_TICK 50
|
||||
|
||||
|
||||
#define MQTT_NETWORK_TYPE_NO_TLS
|
||||
|
||||
#endif /* _MQTT_CONFIG_H_ */
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* @Author : jiejie
|
||||
* @GitHub : https://github.com/jiejieTop
|
||||
* @Date : 2021-02-26 12:00:24
|
||||
* @LastEditors : jiejie
|
||||
* @LastEditTime : 2022-06-15 23:22:10
|
||||
* @FilePath : /mqttclient/mqttclient/mqtt_defconfig.h
|
||||
* Copyright (c) 2022 jiejie, All Rights Reserved. Please keep the author information and source code according to the license.
|
||||
*/
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2020-02-25 03:36:09
|
||||
* @LastEditTime: 2020-06-17 19:59:41
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
#ifndef _DEFCONFIG_H_
|
||||
#define _DEFCONFIG_H_
|
||||
|
||||
#include "mqtt_config.h"
|
||||
|
||||
#ifndef MQTT_LOG_LEVEL
|
||||
#define MQTT_LOG_LEVEL MQTT_LOG_DEBUG_LEVEL //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
|
||||
#endif // !MQTT_LOG_LEVEL
|
||||
|
||||
#ifndef MQTT_MAX_PACKET_ID
|
||||
#define MQTT_MAX_PACKET_ID (0xFFFF - 1)
|
||||
#endif // !MQTT_MAX_PACKET_ID
|
||||
|
||||
#ifndef MQTT_TOPIC_LEN_MAX
|
||||
#define MQTT_TOPIC_LEN_MAX 64
|
||||
#endif // !MQTT_TOPIC_LEN_MAX
|
||||
|
||||
#ifndef MQTT_ACK_HANDLER_NUM_MAX
|
||||
#define MQTT_ACK_HANDLER_NUM_MAX 64
|
||||
#endif // !MQTT_ACK_HANDLER_NUM_MAX
|
||||
|
||||
#ifndef MQTT_DEFAULT_BUF_SIZE
|
||||
#define MQTT_DEFAULT_BUF_SIZE 1024
|
||||
#endif // !MQTT_DEFAULT_BUF_SIZE
|
||||
|
||||
#ifndef MQTT_DEFAULT_CMD_TIMEOUT
|
||||
#define MQTT_DEFAULT_CMD_TIMEOUT 4000
|
||||
#endif // !MQTT_DEFAULT_CMD_TIMEOUT
|
||||
|
||||
#ifndef MQTT_MAX_CMD_TIMEOUT
|
||||
#define MQTT_MAX_CMD_TIMEOUT 20000
|
||||
#endif // !MQTT_MAX_CMD_TIMEOUT
|
||||
|
||||
#ifndef MQTT_MIN_CMD_TIMEOUT
|
||||
#define MQTT_MIN_CMD_TIMEOUT 1000
|
||||
#endif // !MQTT_MIN_CMD_TIMEOUT
|
||||
|
||||
#ifndef MQTT_KEEP_ALIVE_INTERVAL
|
||||
#define MQTT_KEEP_ALIVE_INTERVAL 100 // unit: second
|
||||
#endif // !MQTT_KEEP_ALIVE_INTERVAL
|
||||
|
||||
#ifndef MQTT_VERSION
|
||||
#define MQTT_VERSION 4 // 4 is mqtt 3.1.1
|
||||
#endif // !MQTT_VERSION
|
||||
|
||||
#ifndef MQTT_RECONNECT_DEFAULT_DURATION
|
||||
#define MQTT_RECONNECT_DEFAULT_DURATION 1000
|
||||
#endif // !MQTT_RECONNECT_DEFAULT_DURATION
|
||||
|
||||
#ifndef MQTT_THREAD_STACK_SIZE
|
||||
#define MQTT_THREAD_STACK_SIZE 4096
|
||||
#endif // !MQTT_THREAD_STACK_SIZE
|
||||
|
||||
#ifndef MQTT_THREAD_PRIO
|
||||
#define MQTT_THREAD_PRIO 5
|
||||
#endif // !MQTT_THREAD_PRIO
|
||||
|
||||
#ifndef MQTT_THREAD_TICK
|
||||
#define MQTT_THREAD_TICK 50
|
||||
#endif // !MQTT_THREAD_TICK
|
||||
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
|
||||
#ifndef MQTT_TLS_HANDSHAKE_TIMEOUT
|
||||
#define MQTT_TLS_HANDSHAKE_TIMEOUT (5 * 1000)
|
||||
#endif // !MQTT_TLS_HANDSHAKE_TIMEOUT
|
||||
|
||||
#endif /* MQTT_NETWORK_TYPE_NO_TLS */
|
||||
|
||||
#endif /* _DEFCONFIG_H_ */
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 00:42:16
|
||||
* @LastEditTime: 2020-10-17 14:16:15
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTT_ERROR_H_
|
||||
#define _MQTT_ERROR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum mqtt_error {
|
||||
MQTT_SSL_CERT_ERROR = -0x001C, /* cetr parse failed */
|
||||
MQTT_SOCKET_FAILED_ERROR = -0x001B, /* socket fd failed */
|
||||
MQTT_SOCKET_UNKNOWN_HOST_ERROR = -0x001A, /* socket unknown host ip or domain */
|
||||
MQTT_SET_PUBLISH_DUP_FAILED_ERROR = -0x0019, /* mqtt publish packet set udp bit failed */
|
||||
MQTT_CLEAN_SESSION_ERROR = -0x0018, /* mqtt clean session error */
|
||||
MQTT_ACK_NODE_IS_EXIST_ERROR = -0x0017, /* mqtt ack list is exist ack node */
|
||||
MQTT_ACK_HANDLER_NUM_TOO_MUCH_ERROR = -0x0016, /* mqtt ack handler number is too much */
|
||||
MQTT_RESUBSCRIBE_ERROR = -0x0015, /* mqtt resubscribe error */
|
||||
MQTT_SUBSCRIBE_ERROR = -0x0014, /* mqtt subscribe error */
|
||||
MQTT_SEND_PACKET_ERROR = -0x0013, /* mqtt send a packet */
|
||||
MQTT_SERIALIZE_PUBLISH_ACK_PACKET_ERROR = -0x0012, /* mqtt serialize publish ack packet error */
|
||||
MQTT_PUBLISH_PACKET_ERROR = -0x0011, /* mqtt publish packet error */
|
||||
MQTT_RECONNECT_TIMEOUT_ERROR = -0x0010, /* mqtt try reconnect, but timeout */
|
||||
MQTT_SUBSCRIBE_NOT_ACK_ERROR = -0x000F, /* mqtt subscribe, but not ack */
|
||||
MQTT_NOT_CONNECT_ERROR = -0x000E, /* mqtt not connect */
|
||||
MQTT_SUBSCRIBE_ACK_PACKET_ERROR = -0x000D, /* mqtt subscribe, but ack packet error */
|
||||
MQTT_UNSUBSCRIBE_ACK_PACKET_ERROR = -0x000C, /* mqtt unsubscribe, but ack packet error */
|
||||
MQTT_PUBLISH_ACK_PACKET_ERROR = -0x000B, /* mqtt pubilsh ack packet error */
|
||||
MQTT_PUBLISH_ACK_TYPE_ERROR = -0x000A, /* mqtt pubilsh ack type error */
|
||||
MQTT_PUBREC_PACKET_ERROR = -0x0009, /* mqtt pubrec packet error */
|
||||
MQTT_BUFFER_TOO_SHORT_ERROR = -0x0008, /* mqtt buffer too short */
|
||||
MQTT_NOTHING_TO_READ_ERROR = -0x0007, /* mqtt nothing to read */
|
||||
MQTT_SUBSCRIBE_QOS_ERROR = -0x0006, /* mqtt subsrcibe qos error */
|
||||
MQTT_BUFFER_OVERFLOW_ERROR = -0x0005, /* mqtt buffer overflow */
|
||||
MQTT_CONNECT_FAILED_ERROR = -0x0004, /* mqtt connect failed */
|
||||
MQTT_MEM_NOT_ENOUGH_ERROR = -0x0003, /* mqtt memory not enough */
|
||||
MQTT_NULL_VALUE_ERROR = -0x0002, /* mqtt value is null */
|
||||
MQTT_FAILED_ERROR = -0x0001, /* failed */
|
||||
MQTT_SUCCESS_ERROR = 0x0000 /* success */
|
||||
} mqtt_error_t;
|
||||
|
||||
#define RETURN_ERROR(x) { return x; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-11 22:46:33
|
||||
* @LastEditTime: 2020-04-27 23:28:12
|
||||
* @Description: the following code references TencentOS tiny, please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
# include "mqtt_list.h"
|
||||
|
||||
static void _mqtt_list_add(mqtt_list_t *node, mqtt_list_t *prev, mqtt_list_t *next)
|
||||
{
|
||||
next->prev = node;
|
||||
node->next = next;
|
||||
node->prev = prev;
|
||||
prev->next = node;
|
||||
}
|
||||
|
||||
static void _mqtt_list_del(mqtt_list_t *prev, mqtt_list_t *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
static void _mqtt_list_del_entry(mqtt_list_t *entry)
|
||||
{
|
||||
_mqtt_list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
void mqtt_list_init(mqtt_list_t *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
void mqtt_list_add(mqtt_list_t *node, mqtt_list_t *list)
|
||||
{
|
||||
_mqtt_list_add(node, list, list->next);
|
||||
}
|
||||
|
||||
void mqtt_list_add_tail(mqtt_list_t *node, mqtt_list_t *list)
|
||||
{
|
||||
_mqtt_list_add(node, list->prev, list);
|
||||
}
|
||||
|
||||
void mqtt_list_del(mqtt_list_t *entry)
|
||||
{
|
||||
_mqtt_list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
void mqtt_list_del_init(mqtt_list_t *entry)
|
||||
{
|
||||
_mqtt_list_del_entry(entry);
|
||||
mqtt_list_init(entry);
|
||||
}
|
||||
|
||||
void mqtt_list_move(mqtt_list_t *node, mqtt_list_t *list)
|
||||
{
|
||||
_mqtt_list_del_entry(node);
|
||||
mqtt_list_add(node, list);
|
||||
}
|
||||
|
||||
void mqtt_list_move_tail(mqtt_list_t *node, mqtt_list_t *list)
|
||||
{
|
||||
_mqtt_list_del_entry(node);
|
||||
mqtt_list_add_tail(node, list);
|
||||
}
|
||||
|
||||
int mqtt_list_is_empty(mqtt_list_t *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-11 22:47:55
|
||||
* @LastEditTime: 2020-10-17 14:18:02
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTT_LIST_H_
|
||||
#define _MQTT_LIST_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct mqtt_list_node {
|
||||
struct mqtt_list_node *next;
|
||||
struct mqtt_list_node *prev;
|
||||
} mqtt_list_t;
|
||||
|
||||
#define OFFSET_OF_FIELD(type, field) \
|
||||
((size_t)&(((type *)0)->field))
|
||||
|
||||
#define CONTAINER_OF_FIELD(ptr, type, field) \
|
||||
((type *)((unsigned char *)(ptr) - OFFSET_OF_FIELD(type, field)))
|
||||
|
||||
#define LIST_NODE(node) \
|
||||
{ &(node), &(node) }
|
||||
|
||||
#define LIST_DEFINE(list) \
|
||||
mqtt_list_t list = { &(list), &(list) }
|
||||
|
||||
#define LIST_ENTRY(list, type, field) \
|
||||
CONTAINER_OF_FIELD(list, type, field)
|
||||
|
||||
#define LIST_FIRST_ENTRY(list, type, field) \
|
||||
LIST_ENTRY((list)->next, type, field)
|
||||
|
||||
#define LIST_FIRST_ENTRY_OR_NULL(list, type, field) \
|
||||
(mqtt_list_is_empty(list) ? NULL : LIST_FIRST_ENTRY(list, type, field))
|
||||
|
||||
#define LIST_FOR_EACH(curr, list) \
|
||||
for (curr = (list)->next; curr != (list); curr = curr->next)
|
||||
|
||||
#define LIST_FOR_EACH_PREV(curr, list) \
|
||||
for (curr = (list)->prev; curr != (list); curr = curr->prev)
|
||||
|
||||
#define LIST_FOR_EACH_SAFE(curr, next, list) \
|
||||
for (curr = (list)->next, next = curr->next; curr != (list); \
|
||||
curr = next, next = curr->next)
|
||||
|
||||
#define LIST_FOR_EACH_PREV_SAFE(curr, next, list) \
|
||||
for (curr = (list)->prev, next = curr->prev; \
|
||||
curr != (list); \
|
||||
curr = next, next = curr->prev)
|
||||
|
||||
void mqtt_list_init(mqtt_list_t *list);
|
||||
void mqtt_list_add(mqtt_list_t *node, mqtt_list_t *list);
|
||||
void mqtt_list_add_tail(mqtt_list_t *node, mqtt_list_t *list);
|
||||
void mqtt_list_del(mqtt_list_t *entry);
|
||||
void mqtt_list_del_init(mqtt_list_t *entry);
|
||||
void mqtt_list_move(mqtt_list_t *node, mqtt_list_t *list);
|
||||
void mqtt_list_move_tail(mqtt_list_t *node, mqtt_list_t *list);
|
||||
int mqtt_list_is_empty(mqtt_list_t *list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIST_H_ */
|
||||
|
71
port/linux/package/pikascript/pikascript-lib/mqtt/mqtt_log.h
Normal file
71
port/linux/package/pikascript/pikascript-lib/mqtt/mqtt_log.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-27 03:25:58
|
||||
* @LastEditTime: 2020-10-17 14:15:55
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTT_LOG_H_
|
||||
#define _MQTT_LOG_H_
|
||||
|
||||
#include "mqtt_defconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MQTT_LOG_BASE_LEVEL (0)
|
||||
#define MQTT_LOG_ERR_LEVEL (MQTT_LOG_BASE_LEVEL + 1)
|
||||
#define MQTT_LOG_WARN_LEVEL (MQTT_LOG_ERR_LEVEL + 1)
|
||||
#define MQTT_LOG_INFO_LEVEL (MQTT_LOG_WARN_LEVEL + 1)
|
||||
#define MQTT_LOG_DEBUG_LEVEL (MQTT_LOG_INFO_LEVEL + 1)
|
||||
|
||||
#ifdef MQTT_LOG_IS_SALOF
|
||||
#include "salof.h"
|
||||
|
||||
#define MQTT_LOG_D(fmt, ...) SALOF_LOG_DEBUG(fmt, ##__VA_ARGS__)
|
||||
#define MQTT_LOG_I(fmt, ...) SALOF_LOG_INFO(fmt, ##__VA_ARGS__)
|
||||
#define MQTT_LOG_W(fmt, ...) SALOF_LOG_WARN(fmt, ##__VA_ARGS__)
|
||||
#define MQTT_LOG_E(fmt, ...) SALOF_LOG_ERR(fmt, ##__VA_ARGS__)
|
||||
#define mqtt_log_init salof_init
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_DEBUG_LEVEL
|
||||
#define MQTT_LOG_D(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG_D(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_INFO_LEVEL
|
||||
#define MQTT_LOG_I(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG_I(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_WARN_LEVEL
|
||||
#define MQTT_LOG_W(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG_W(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_ERR_LEVEL
|
||||
#define MQTT_LOG_E(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG_E(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#if MQTT_LOG_LEVEL < MQTT_LOG_BASE_LEVEL
|
||||
#define MQTT_LOG(fmt, ...)
|
||||
#else
|
||||
#define MQTT_LOG(fmt, ...) { printf(fmt, ##__VA_ARGS__); printf("\n");}
|
||||
#endif
|
||||
|
||||
#define mqtt_log_init()
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LOG_H_ */
|
1500
port/linux/package/pikascript/pikascript-lib/mqtt/mqttclient.c
Normal file
1500
port/linux/package/pikascript/pikascript-lib/mqtt/mqttclient.c
Normal file
File diff suppressed because it is too large
Load Diff
180
port/linux/package/pikascript/pikascript-lib/mqtt/mqttclient.h
Normal file
180
port/linux/package/pikascript/pikascript-lib/mqtt/mqttclient.h
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-09 21:31:25
|
||||
* @LastEditTime : 2022-06-11 22:45:02
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _MQTTCLIENT_H_
|
||||
#define _MQTTCLIENT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "MQTTPacket.h"
|
||||
#include "mqtt_list.h"
|
||||
#include "platform_timer.h"
|
||||
#include "platform_memory.h"
|
||||
#include "platform_mutex.h"
|
||||
#include "platform_thread.h"
|
||||
#include "mqtt_defconfig.h"
|
||||
#include "network.h"
|
||||
#include "random.h"
|
||||
#include "mqtt_error.h"
|
||||
#include "mqtt_log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum mqtt_qos {
|
||||
QOS0 = 0,
|
||||
QOS1 = 1,
|
||||
QOS2 = 2,
|
||||
SUBFAIL = 0x80
|
||||
} mqtt_qos_t;
|
||||
|
||||
typedef enum client_state {
|
||||
CLIENT_STATE_INVALID = -1,
|
||||
CLIENT_STATE_INITIALIZED = 0,
|
||||
CLIENT_STATE_CONNECTED = 1,
|
||||
CLIENT_STATE_DISCONNECTED = 2,
|
||||
CLIENT_STATE_CLEAN_SESSION = 3
|
||||
}client_state_t;
|
||||
|
||||
typedef struct mqtt_connack_data {
|
||||
uint8_t rc;
|
||||
uint8_t session_present;
|
||||
} mqtt_connack_data_t;
|
||||
|
||||
typedef struct mqtt_message {
|
||||
mqtt_qos_t qos;
|
||||
uint8_t retained;
|
||||
uint8_t dup;
|
||||
uint16_t id;
|
||||
size_t payloadlen;
|
||||
void *payload;
|
||||
} mqtt_message_t;
|
||||
|
||||
typedef struct message_data {
|
||||
char topic_name[MQTT_TOPIC_LEN_MAX];
|
||||
mqtt_message_t *message;
|
||||
} message_data_t;
|
||||
|
||||
typedef void (*interceptor_handler_t)(void* client, message_data_t* msg);
|
||||
typedef void (*message_handler_t)(void* client, message_data_t* msg);
|
||||
typedef void (*reconnect_handler_t)(void* client, void* reconnect_date);
|
||||
|
||||
typedef struct message_handlers {
|
||||
mqtt_list_t list;
|
||||
mqtt_qos_t qos;
|
||||
const char* topic_filter;
|
||||
message_handler_t handler;
|
||||
} message_handlers_t;
|
||||
|
||||
typedef struct ack_handlers {
|
||||
mqtt_list_t list;
|
||||
platform_timer_t timer;
|
||||
uint32_t type;
|
||||
uint16_t packet_id;
|
||||
message_handlers_t *handler;
|
||||
uint16_t payload_len;
|
||||
uint8_t *payload;
|
||||
} ack_handlers_t;
|
||||
|
||||
typedef struct mqtt_will_options {
|
||||
mqtt_qos_t will_qos;
|
||||
uint8_t will_retained;
|
||||
char *will_topic;
|
||||
char *will_message;
|
||||
} mqtt_will_options_t;
|
||||
|
||||
typedef struct mqtt_client {
|
||||
char *mqtt_client_id;
|
||||
char *mqtt_user_name;
|
||||
char *mqtt_password;
|
||||
char *mqtt_host;
|
||||
char *mqtt_port;
|
||||
char *mqtt_ca;
|
||||
void *mqtt_reconnect_data;
|
||||
uint8_t *mqtt_read_buf;
|
||||
uint8_t *mqtt_write_buf;
|
||||
uint16_t mqtt_keep_alive_interval;
|
||||
uint16_t mqtt_packet_id;
|
||||
uint32_t mqtt_will_flag : 1;
|
||||
uint32_t mqtt_clean_session : 1;
|
||||
uint32_t mqtt_ping_outstanding : 2;
|
||||
uint32_t mqtt_version : 4;
|
||||
uint32_t mqtt_ack_handler_number : 24;
|
||||
uint32_t mqtt_cmd_timeout;
|
||||
uint32_t mqtt_read_buf_size;
|
||||
uint32_t mqtt_write_buf_size;
|
||||
uint32_t mqtt_reconnect_try_duration;
|
||||
size_t mqtt_client_id_len;
|
||||
size_t mqtt_user_name_len;
|
||||
size_t mqtt_password_len;
|
||||
mqtt_will_options_t *mqtt_will_options;
|
||||
client_state_t mqtt_client_state;
|
||||
platform_mutex_t mqtt_write_lock;
|
||||
platform_mutex_t mqtt_global_lock;
|
||||
mqtt_list_t mqtt_msg_handler_list;
|
||||
mqtt_list_t mqtt_ack_handler_list;
|
||||
network_t *mqtt_network;
|
||||
platform_thread_t *mqtt_thread;
|
||||
platform_timer_t mqtt_last_sent;
|
||||
platform_timer_t mqtt_last_received;
|
||||
reconnect_handler_t mqtt_reconnect_handler;
|
||||
interceptor_handler_t mqtt_interceptor_handler;
|
||||
} mqtt_client_t;
|
||||
|
||||
|
||||
#define MQTT_ROBUSTNESS_CHECK(item, err) if (!(item)) { \
|
||||
MQTT_LOG_E("%s:%d %s()... check for error.", __FILE__, __LINE__, __FUNCTION__); \
|
||||
return err; }
|
||||
|
||||
#define MQTT_CLIENT_SET_DEFINE(name, type, res) \
|
||||
type mqtt_set_##name(mqtt_client_t *c, type t) { \
|
||||
MQTT_ROBUSTNESS_CHECK((c), res); \
|
||||
c->mqtt_##name = t; \
|
||||
return c->mqtt_##name; \
|
||||
}
|
||||
|
||||
#define MQTT_CLIENT_SET_STATEMENT(name, type) \
|
||||
type mqtt_set_##name(mqtt_client_t *, type);
|
||||
|
||||
MQTT_CLIENT_SET_STATEMENT(client_id, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(user_name, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(password, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(host, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(port, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(ca, char*)
|
||||
MQTT_CLIENT_SET_STATEMENT(reconnect_data, void*)
|
||||
MQTT_CLIENT_SET_STATEMENT(keep_alive_interval, uint16_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(will_flag, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(clean_session, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(version, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(cmd_timeout, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(read_buf_size, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(write_buf_size, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(reconnect_try_duration, uint32_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(reconnect_handler, reconnect_handler_t)
|
||||
MQTT_CLIENT_SET_STATEMENT(interceptor_handler, interceptor_handler_t)
|
||||
|
||||
void mqtt_sleep_ms(int ms);
|
||||
mqtt_client_t *mqtt_lease(void);
|
||||
int mqtt_release(mqtt_client_t* c);
|
||||
int mqtt_connect(mqtt_client_t* c);
|
||||
int mqtt_disconnect(mqtt_client_t* c);
|
||||
int mqtt_keep_alive(mqtt_client_t* c);
|
||||
int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, message_handler_t msg_handler);
|
||||
int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter);
|
||||
int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg);
|
||||
int mqtt_list_subscribe_topic(mqtt_client_t* c);
|
||||
int mqtt_set_will_options(mqtt_client_t* c, char *topic, mqtt_qos_t qos, uint8_t retained, char *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MQTTCLIENT_H_ */
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 13:38:52
|
||||
* @LastEditTime: 2020-05-25 10:13:41
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "nettype_tcp.h"
|
||||
#include "mqtt_log.h"
|
||||
#include "platform_net_socket.h"
|
||||
|
||||
int nettype_tcp_read(network_t *n, unsigned char *read_buf, int len, int timeout)
|
||||
{
|
||||
return platform_net_socket_recv_timeout(n->socket, read_buf, len, timeout);
|
||||
}
|
||||
|
||||
int nettype_tcp_write(network_t *n, unsigned char *write_buf, int len, int timeout)
|
||||
{
|
||||
return platform_net_socket_write_timeout(n->socket, write_buf, len, timeout);
|
||||
}
|
||||
|
||||
int nettype_tcp_connect(network_t* n)
|
||||
{
|
||||
n->socket = platform_net_socket_connect(n->host, n->port, PLATFORM_NET_PROTO_TCP);
|
||||
if (n->socket < 0)
|
||||
RETURN_ERROR(n->socket);
|
||||
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
||||
void nettype_tcp_disconnect(network_t* n)
|
||||
{
|
||||
if (NULL != n)
|
||||
platform_net_socket_close(n->socket);
|
||||
n->socket = -1;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 13:39:00
|
||||
* @LastEditTime: 2020-10-17 14:17:10
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _NETTYPE_TCP_H_
|
||||
#define _NETTYPE_TCP_H_
|
||||
|
||||
#include "network.h"
|
||||
#include "mqtt_error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int nettype_tcp_read(network_t *n, unsigned char *buf, int len, int timeout);
|
||||
int nettype_tcp_write(network_t *n, unsigned char *buf, int len, int timeout);
|
||||
int nettype_tcp_connect(network_t* n);
|
||||
void nettype_tcp_disconnect(network_t* n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
253
port/linux/package/pikascript/pikascript-lib/mqtt/nettype_tls.c
Normal file
253
port/linux/package/pikascript/pikascript-lib/mqtt/nettype_tls.c
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2020-01-11 19:45:35
|
||||
* @LastEditTime: 2020-09-20 14:29:06
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "nettype_tls.h"
|
||||
#include "platform_net_socket.h"
|
||||
#include "platform_memory.h"
|
||||
#include "platform_timer.h"
|
||||
#include "random.h"
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/x509_crt.h"
|
||||
#include "mbedtls/pk.h"
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
static int server_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
|
||||
{
|
||||
if (0 != *flags)
|
||||
MQTT_LOG_E("%s:%d %s()... server_certificate_verify failed returned 0x%04x\n", __FILE__, __LINE__, __FUNCTION__, *flags);
|
||||
return *flags;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int nettype_tls_entropy_source(void *data, uint8_t *output, size_t len, size_t *out_len)
|
||||
{
|
||||
uint32_t seed;
|
||||
(void) data;
|
||||
seed = random_number();
|
||||
|
||||
if (len > sizeof(seed)) {
|
||||
len = sizeof(seed);
|
||||
}
|
||||
|
||||
memcpy(output, &seed, len);
|
||||
*out_len = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nettype_tls_init(network_t* n, nettype_tls_params_t* nettype_tls_params)
|
||||
{
|
||||
int rc = MQTT_SUCCESS_ERROR;
|
||||
|
||||
mbedtls_platform_set_calloc_free(platform_memory_calloc, platform_memory_free);
|
||||
|
||||
mbedtls_net_init(&(nettype_tls_params->socket_fd));
|
||||
mbedtls_ssl_init(&(nettype_tls_params->ssl));
|
||||
mbedtls_ssl_config_init(&(nettype_tls_params->ssl_conf));
|
||||
mbedtls_ctr_drbg_init(&(nettype_tls_params->ctr_drbg));
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
mbedtls_x509_crt_init(&(nettype_tls_params->ca_cert));
|
||||
mbedtls_x509_crt_init(&(nettype_tls_params->client_cert));
|
||||
mbedtls_pk_init(&(nettype_tls_params->private_key));
|
||||
#endif
|
||||
|
||||
mbedtls_entropy_init(&(nettype_tls_params->entropy));
|
||||
mbedtls_entropy_add_source(&(nettype_tls_params->entropy), nettype_tls_entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG);
|
||||
|
||||
if ((rc = mbedtls_ctr_drbg_seed(&(nettype_tls_params->ctr_drbg), mbedtls_entropy_func,
|
||||
&(nettype_tls_params->entropy), NULL, 0)) != 0) {
|
||||
MQTT_LOG_E("mbedtls_ctr_drbg_seed failed returned 0x%04x", (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
if ((rc = mbedtls_ssl_config_defaults(&(nettype_tls_params->ssl_conf), MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
MQTT_LOG_E("mbedtls_ssl_config_defaults failed returned 0x%04x", (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_rng(&(nettype_tls_params->ssl_conf), mbedtls_ctr_drbg_random, &(nettype_tls_params->ctr_drbg));
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if (NULL != n->ca_crt) {
|
||||
n->ca_crt_len = strlen(n->ca_crt);
|
||||
|
||||
if (0 != (rc = (mbedtls_x509_crt_parse(&(nettype_tls_params->ca_cert), (unsigned char *)n->ca_crt,
|
||||
(n->ca_crt_len + 1))))) {
|
||||
MQTT_LOG_E("%s:%d %s()... parse ca crt failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(&(nettype_tls_params->ssl_conf), &(nettype_tls_params->ca_cert), NULL);
|
||||
|
||||
if ((rc = mbedtls_ssl_conf_own_cert(&(nettype_tls_params->ssl_conf),
|
||||
&(nettype_tls_params->client_cert), &(nettype_tls_params->private_key))) != 0) {
|
||||
MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_conf_own_cert failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_verify(&(nettype_tls_params->ssl_conf), server_certificate_verify, (void *)n->host);
|
||||
|
||||
mbedtls_ssl_conf_authmode(&(nettype_tls_params->ssl_conf), MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
#endif
|
||||
|
||||
mbedtls_ssl_conf_read_timeout(&(nettype_tls_params->ssl_conf), n->timeout_ms);
|
||||
|
||||
if ((rc = mbedtls_ssl_setup(&(nettype_tls_params->ssl), &(nettype_tls_params->ssl_conf))) != 0) {
|
||||
MQTT_LOG_E("mbedtls_ssl_setup failed returned 0x%04x", (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if ((rc = mbedtls_ssl_set_hostname(&(nettype_tls_params->ssl), n->host)) != 0) {
|
||||
MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_set_hostname failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
mbedtls_ssl_set_bio(&(nettype_tls_params->ssl), &(nettype_tls_params->socket_fd), mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);
|
||||
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
||||
|
||||
int nettype_tls_connect(network_t* n)
|
||||
{
|
||||
int rc;
|
||||
if (NULL == n)
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) platform_memory_alloc(sizeof(nettype_tls_params_t));
|
||||
|
||||
if (NULL == nettype_tls_params)
|
||||
RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
|
||||
|
||||
|
||||
rc = nettype_tls_init(n, nettype_tls_params);
|
||||
if (MQTT_SUCCESS_ERROR != rc)
|
||||
goto exit;
|
||||
|
||||
if (0 != (rc = mbedtls_net_connect(&(nettype_tls_params->socket_fd), n->host, n->port, MBEDTLS_NET_PROTO_TCP)))
|
||||
goto exit;
|
||||
|
||||
while ((rc = mbedtls_ssl_handshake(&(nettype_tls_params->ssl))) != 0) {
|
||||
if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
MQTT_LOG_E("%s:%d %s()...mbedtls handshake failed returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
|
||||
MQTT_LOG_E("%s:%d %s()...unable to verify the server's certificate", __FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
#endif
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rc = mbedtls_ssl_get_verify_result(&(nettype_tls_params->ssl))) != 0) {
|
||||
MQTT_LOG_E("%s:%d %s()...mbedtls_ssl_get_verify_result returned 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
n->nettype_tls_params = nettype_tls_params;
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR)
|
||||
|
||||
exit:
|
||||
platform_memory_free(nettype_tls_params);
|
||||
RETURN_ERROR(rc);
|
||||
}
|
||||
|
||||
|
||||
void nettype_tls_disconnect(network_t* n)
|
||||
{
|
||||
int rc = 0;
|
||||
if (NULL == n)
|
||||
return;
|
||||
|
||||
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
|
||||
|
||||
do {
|
||||
rc = mbedtls_ssl_close_notify(&(nettype_tls_params->ssl));
|
||||
} while (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
|
||||
mbedtls_net_free(&(nettype_tls_params->socket_fd));
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
mbedtls_x509_crt_free(&(nettype_tls_params->client_cert));
|
||||
mbedtls_x509_crt_free(&(nettype_tls_params->ca_cert));
|
||||
mbedtls_pk_free(&(nettype_tls_params->private_key));
|
||||
#endif
|
||||
mbedtls_ssl_free(&(nettype_tls_params->ssl));
|
||||
mbedtls_ssl_config_free(&(nettype_tls_params->ssl_conf));
|
||||
mbedtls_ctr_drbg_free(&(nettype_tls_params->ctr_drbg));
|
||||
mbedtls_entropy_free(&(nettype_tls_params->entropy));
|
||||
|
||||
platform_memory_free(nettype_tls_params);
|
||||
}
|
||||
|
||||
int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
int rc = 0;
|
||||
int write_len = 0;
|
||||
platform_timer_t timer;
|
||||
|
||||
if (NULL == n)
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
|
||||
|
||||
platform_timer_cutdown(&timer, timeout);
|
||||
|
||||
do {
|
||||
rc = mbedtls_ssl_write(&(nettype_tls_params->ssl), (unsigned char *)(buf + write_len), len - write_len);
|
||||
|
||||
if (rc > 0) {
|
||||
write_len += rc;
|
||||
} else if ((rc == 0) || ((rc != MBEDTLS_ERR_SSL_WANT_WRITE) && (rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_TIMEOUT))) {
|
||||
MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_write failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
break;
|
||||
}
|
||||
} while((!platform_timer_is_expired(&timer)) && (write_len < len));
|
||||
|
||||
return write_len;
|
||||
}
|
||||
|
||||
int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
int rc = 0;
|
||||
int read_len = 0;
|
||||
platform_timer_t timer;
|
||||
|
||||
if (NULL == n)
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
|
||||
|
||||
platform_timer_cutdown(&timer, timeout);
|
||||
|
||||
do {
|
||||
rc = mbedtls_ssl_read(&(nettype_tls_params->ssl), (unsigned char *)(buf + read_len), len - read_len);
|
||||
|
||||
if (rc > 0) {
|
||||
read_len += rc;
|
||||
} else if ((rc == 0) || ((rc != MBEDTLS_ERR_SSL_WANT_WRITE) && (rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_TIMEOUT))) {
|
||||
// MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_read failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
|
||||
break;
|
||||
}
|
||||
} while((!platform_timer_is_expired(&timer)) && (read_len < len));
|
||||
|
||||
return read_len;
|
||||
}
|
||||
|
||||
#endif /* MQTT_NETWORK_TYPE_NO_TLS */
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* @Author : jiejie
|
||||
* @GitHub : https://github.com/jiejieTop
|
||||
* @Date : 2021-02-26 12:00:24
|
||||
* @LastEditors : jiejie
|
||||
* @LastEditTime : 2022-06-15 19:48:43
|
||||
* @FilePath : /mqttclient/network/nettype_tls.h
|
||||
* Copyright (c) 2022 jiejie, All Rights Reserved. Please keep the author information and source code according to the license.
|
||||
*/
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2020-01-11 19:45:44
|
||||
* @LastEditTime: 2020-10-17 14:14:11
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
#ifndef _NETTYPE_TLS_H_
|
||||
#define _NETTYPE_TLS_H_
|
||||
|
||||
#include "mqtt_defconfig.h"
|
||||
#include "network.h"
|
||||
#include "mqtt_error.h"
|
||||
#include "mqtt_log.h"
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
|
||||
#include "mbedtls/config.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct nettype_tls_params {
|
||||
mbedtls_net_context socket_fd; /**< mbed TLS network context. */
|
||||
mbedtls_entropy_context entropy; /**< mbed TLS entropy. */
|
||||
mbedtls_ctr_drbg_context ctr_drbg; /**< mbed TLS ctr_drbg. */
|
||||
mbedtls_ssl_context ssl; /**< mbed TLS control context. */
|
||||
mbedtls_ssl_config ssl_conf; /**< mbed TLS configuration context. */
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
mbedtls_x509_crt ca_cert; /**< mbed TLS CA certification. */
|
||||
mbedtls_x509_crt client_cert; /**< mbed TLS Client certification. */
|
||||
#endif
|
||||
mbedtls_pk_context private_key; /**< mbed TLS Client key. */
|
||||
} nettype_tls_params_t;
|
||||
|
||||
int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout);
|
||||
int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout);
|
||||
int nettype_tls_connect(network_t* n);
|
||||
void nettype_tls_disconnect(network_t* n);
|
||||
|
||||
#endif /* MQTT_NETWORK_TYPE_NO_TLS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
113
port/linux/package/pikascript/pikascript-lib/mqtt/network.c
Normal file
113
port/linux/package/pikascript/pikascript-lib/mqtt/network.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-09 21:30:54
|
||||
* @LastEditTime: 2020-06-05 17:17:48
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "platform_timer.h"
|
||||
#include "platform_memory.h"
|
||||
#include "nettype_tcp.h"
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
#include "nettype_tls.h"
|
||||
#endif
|
||||
|
||||
int network_read(network_t *n, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if (n->channel)
|
||||
return nettype_tls_read(n, buf, len, timeout);
|
||||
#endif
|
||||
return nettype_tcp_read(n, buf, len, timeout);
|
||||
}
|
||||
|
||||
int network_write(network_t *n, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if (n->channel)
|
||||
return nettype_tls_write(n, buf, len, timeout);
|
||||
#endif
|
||||
return nettype_tcp_write(n, buf, len, timeout);
|
||||
}
|
||||
|
||||
int network_connect(network_t *n)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if (n->channel)
|
||||
return nettype_tls_connect(n);
|
||||
#endif
|
||||
return nettype_tcp_connect(n);
|
||||
|
||||
}
|
||||
|
||||
void network_disconnect(network_t *n)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if (n->channel)
|
||||
nettype_tls_disconnect(n);
|
||||
else
|
||||
#endif
|
||||
nettype_tcp_disconnect(n);
|
||||
}
|
||||
|
||||
int network_init(network_t *n, const char *host, const char *port, const char *ca)
|
||||
{
|
||||
if (NULL == n)
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
n->socket = -1;
|
||||
n->host = host;
|
||||
n->port = port;
|
||||
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
n->channel = 0;
|
||||
|
||||
if (NULL != ca) {
|
||||
network_set_ca(n, ca);
|
||||
}
|
||||
#endif
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
||||
void network_release(network_t* n)
|
||||
{
|
||||
if (n->socket >= 0)
|
||||
network_disconnect(n);
|
||||
|
||||
memset(n, 0, sizeof(network_t));
|
||||
}
|
||||
|
||||
void network_set_channel(network_t *n, int channel)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
n->channel = channel;
|
||||
#endif
|
||||
}
|
||||
|
||||
int network_set_ca(network_t *n, const char *ca)
|
||||
{
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
if ((NULL == n) || (NULL == ca))
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
n->ca_crt = ca;
|
||||
n->ca_crt_len = strlen(ca);
|
||||
n->channel = NETWORK_CHANNEL_TLS;
|
||||
n->timeout_ms = MQTT_TLS_HANDSHAKE_TIMEOUT;
|
||||
#endif
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
||||
int network_set_host_port(network_t* n, char *host, char *port)
|
||||
{
|
||||
if (!(n && host && port))
|
||||
RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
|
||||
|
||||
n->host = host;
|
||||
n->port = port;
|
||||
|
||||
RETURN_ERROR(MQTT_SUCCESS_ERROR);
|
||||
}
|
||||
|
47
port/linux/package/pikascript/pikascript-lib/mqtt/network.h
Normal file
47
port/linux/package/pikascript/pikascript-lib/mqtt/network.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-09 21:31:02
|
||||
* @LastEditTime: 2020-10-17 14:14:41
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _NETWORK_H_
|
||||
#define _NETWORK_H_
|
||||
|
||||
#include "mqtt_defconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NETWORK_CHANNEL_TCP 0
|
||||
#define NETWORK_CHANNEL_TLS 1
|
||||
|
||||
typedef struct network {
|
||||
const char *host;
|
||||
const char *port;
|
||||
int socket;
|
||||
#ifndef MQTT_NETWORK_TYPE_NO_TLS
|
||||
int channel; /* tcp or tls */
|
||||
const char *ca_crt;
|
||||
unsigned int ca_crt_len;
|
||||
unsigned int timeout_ms; // SSL handshake timeout in millisecond
|
||||
void *nettype_tls_params;
|
||||
#endif
|
||||
} network_t;
|
||||
|
||||
int network_init(network_t *n, const char *host, const char *port, const char *ca);
|
||||
int network_set_ca(network_t *n, const char *ca);
|
||||
void network_set_channel(network_t *n, int channel);
|
||||
int network_set_host_port(network_t* n, char *host, char *port);
|
||||
int network_read(network_t* n, unsigned char* buf, int len, int timeout);
|
||||
int network_write(network_t* n, unsigned char* buf, int len, int timeout);
|
||||
int network_connect(network_t* n);
|
||||
void network_disconnect(network_t *n);
|
||||
void network_release(network_t* n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-14 22:02:07
|
||||
* @LastEditTime: 2020-02-19 20:26:04
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "platform_memory.h"
|
||||
|
||||
void *platform_memory_alloc(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *platform_memory_calloc(size_t num, size_t size)
|
||||
{
|
||||
return calloc(num, size);
|
||||
}
|
||||
|
||||
void platform_memory_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-14 22:06:35
|
||||
* @LastEditTime: 2020-10-17 14:17:24
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_MEMORY_H_
|
||||
#define _PLATFORM_MEMORY_H_
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *platform_memory_alloc(size_t size);
|
||||
void *platform_memory_calloc(size_t num, size_t size);
|
||||
void platform_memory_free(void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 18:27:19
|
||||
* @LastEditTime: 2020-02-23 15:01:06
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "platform_mutex.h"
|
||||
|
||||
int platform_mutex_init(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_init(&(m->mutex), NULL);
|
||||
}
|
||||
|
||||
int platform_mutex_lock(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_lock(&(m->mutex));
|
||||
}
|
||||
|
||||
int platform_mutex_trylock(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_trylock(&(m->mutex));
|
||||
}
|
||||
|
||||
int platform_mutex_unlock(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_unlock(&(m->mutex));
|
||||
}
|
||||
|
||||
int platform_mutex_destroy(platform_mutex_t* m)
|
||||
{
|
||||
return pthread_mutex_destroy(&(m->mutex));
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 18:31:33
|
||||
* @LastEditTime: 2020-10-17 14:17:31
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_MUTEX_H_
|
||||
#define _PLATFORM_MUTEX_H_
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct platform_mutex {
|
||||
pthread_mutex_t mutex;
|
||||
} platform_mutex_t;
|
||||
|
||||
int platform_mutex_init(platform_mutex_t* m);
|
||||
int platform_mutex_lock(platform_mutex_t* m);
|
||||
int platform_mutex_trylock(platform_mutex_t* m);
|
||||
int platform_mutex_unlock(platform_mutex_t* m);
|
||||
int platform_mutex_destroy(platform_mutex_t* m);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2020-01-10 23:45:59
|
||||
* @LastEditTime: 2020-06-05 17:13:00
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "platform_net_socket.h"
|
||||
#include "mqtt_error.h"
|
||||
|
||||
int platform_net_socket_connect(const char *host, const char *port, int proto)
|
||||
{
|
||||
int fd, ret = MQTT_SOCKET_UNKNOWN_HOST_ERROR;
|
||||
struct addrinfo hints, *addr_list, *cur;
|
||||
|
||||
/* Do name resolution with both IPv6 and IPv4 */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = (proto == PLATFORM_NET_PROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
|
||||
hints.ai_protocol = (proto == PLATFORM_NET_PROTO_UDP) ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
|
||||
if (getaddrinfo(host, port, &hints, &addr_list) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
|
||||
fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
||||
if (fd < 0) {
|
||||
ret = MQTT_SOCKET_FAILED_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
|
||||
ret = fd;
|
||||
break;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
ret = MQTT_CONNECT_FAILED_ERROR;
|
||||
}
|
||||
|
||||
freeaddrinfo(addr_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int platform_net_socket_recv(int fd, void *buf, size_t len, int flags)
|
||||
{
|
||||
return recv(fd, buf, len, flags);
|
||||
}
|
||||
|
||||
int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
int nread;
|
||||
int nleft = len;
|
||||
unsigned char *ptr;
|
||||
ptr = buf;
|
||||
|
||||
struct timeval tv = {
|
||||
timeout / 1000,
|
||||
(timeout % 1000) * 1000
|
||||
};
|
||||
|
||||
if (tv.tv_sec < 0 || (tv.tv_sec == 0 && tv.tv_usec <= 0)) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100;
|
||||
}
|
||||
|
||||
platform_net_socket_setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
|
||||
|
||||
while (nleft > 0) {
|
||||
nread = platform_net_socket_recv(fd, ptr, nleft, 0);
|
||||
if (nread < 0) {
|
||||
return -1;
|
||||
} else if (nread == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
nleft -= nread;
|
||||
ptr += nread;
|
||||
}
|
||||
return len - nleft;
|
||||
}
|
||||
|
||||
int platform_net_socket_write(int fd, void *buf, size_t len)
|
||||
{
|
||||
return write(fd, buf, len);
|
||||
}
|
||||
|
||||
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
|
||||
{
|
||||
struct timeval tv = {
|
||||
timeout / 1000,
|
||||
(timeout % 1000) * 1000
|
||||
};
|
||||
|
||||
if (tv.tv_sec < 0 || (tv.tv_sec == 0 && tv.tv_usec <= 0)) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100;
|
||||
}
|
||||
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval));
|
||||
|
||||
return write(fd, buf, len);
|
||||
}
|
||||
|
||||
int platform_net_socket_close(int fd)
|
||||
{
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
int platform_net_socket_set_block(int fd)
|
||||
{
|
||||
return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, F_GETFL) & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
int platform_net_socket_set_nonblock(int fd)
|
||||
{
|
||||
return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, F_GETFL) | O_NONBLOCK);
|
||||
}
|
||||
|
||||
int platform_net_socket_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
return setsockopt(fd, level, optname, optval, optlen);
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 13:39:00
|
||||
* @LastEditTime: 2020-10-17 14:17:45
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_NET_SOCKET_H_
|
||||
#define _PLATFORM_NET_SOCKET_H_
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PLATFORM_NET_PROTO_TCP 0 /**< The TCP transport protocol */
|
||||
#define PLATFORM_NET_PROTO_UDP 1 /**< The UDP transport protocol */
|
||||
|
||||
int platform_net_socket_connect(const char *host, const char *port, int proto);
|
||||
int platform_net_socket_recv(int fd, void *buf, size_t len, int flags);
|
||||
int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout);
|
||||
int platform_net_socket_write(int fd, void *buf, size_t len);
|
||||
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout);
|
||||
int platform_net_socket_close(int fd);
|
||||
int platform_net_socket_set_block(int fd);
|
||||
int platform_net_socket_set_nonblock(int fd);
|
||||
int platform_net_socket_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PLATFORM_NET_SOCKET_H_ */
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-23 19:26:27
|
||||
* @LastEditTime: 2020-02-23 16:19:07
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#include "platform_thread.h"
|
||||
#include "platform_memory.h"
|
||||
|
||||
platform_thread_t *platform_thread_init( const char *name,
|
||||
void (*entry)(void *),
|
||||
void * const param,
|
||||
unsigned int stack_size,
|
||||
unsigned int priority,
|
||||
unsigned int tick)
|
||||
{
|
||||
int res;
|
||||
platform_thread_t *thread;
|
||||
void *(*thread_entry) (void *);
|
||||
|
||||
thread_entry = (void *(*)(void*))entry;
|
||||
thread = platform_memory_alloc(sizeof(platform_thread_t));
|
||||
|
||||
res = pthread_create(&thread->thread, NULL, thread_entry, param);
|
||||
if(res != 0) {
|
||||
platform_memory_free(thread);
|
||||
}
|
||||
|
||||
thread->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
|
||||
thread->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
void platform_thread_startup(platform_thread_t* thread)
|
||||
{
|
||||
(void) thread;
|
||||
}
|
||||
|
||||
void platform_thread_stop(platform_thread_t* thread)
|
||||
{
|
||||
pthread_mutex_lock(&(thread->mutex));
|
||||
pthread_cond_wait(&(thread->cond), &(thread->mutex));
|
||||
pthread_mutex_unlock(&(thread->mutex));
|
||||
}
|
||||
|
||||
void platform_thread_start(platform_thread_t* thread)
|
||||
{
|
||||
pthread_mutex_lock(&(thread->mutex));
|
||||
pthread_cond_signal(&(thread->cond));
|
||||
pthread_mutex_unlock(&(thread->mutex));
|
||||
}
|
||||
|
||||
void platform_thread_destroy(platform_thread_t* thread)
|
||||
{
|
||||
if (NULL != thread)
|
||||
pthread_detach(thread->thread);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-15 18:31:44
|
||||
* @LastEditTime: 2020-10-17 14:15:21
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_THREAD_H_
|
||||
#define _PLATFORM_THREAD_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct platform_thread {
|
||||
pthread_t thread;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
} platform_thread_t;
|
||||
|
||||
platform_thread_t *platform_thread_init( const char *name,
|
||||
void (*entry)(void *),
|
||||
void * const param,
|
||||
unsigned int stack_size,
|
||||
unsigned int priority,
|
||||
unsigned int tick);
|
||||
void platform_thread_startup(platform_thread_t* thread);
|
||||
void platform_thread_stop(platform_thread_t* thread);
|
||||
void platform_thread_start(platform_thread_t* thread);
|
||||
void platform_thread_destroy(platform_thread_t* thread);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-10 22:16:41
|
||||
* @LastEditTime: 2020-06-05 17:18:48
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
#include "platform_timer.h"
|
||||
|
||||
void platform_timer_init(platform_timer_t* timer)
|
||||
{
|
||||
timer->time = (struct timeval){0, 0};
|
||||
}
|
||||
|
||||
void platform_timer_cutdown(platform_timer_t* timer, unsigned int timeout)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000};
|
||||
timeradd(&now, &interval, &timer->time);
|
||||
}
|
||||
|
||||
char platform_timer_is_expired(platform_timer_t* timer)
|
||||
{
|
||||
struct timeval now, res;
|
||||
gettimeofday(&now, NULL);
|
||||
timersub(&timer->time, &now, &res);
|
||||
return ((res.tv_sec < 0) || (res.tv_sec == 0 && res.tv_usec <= 0));
|
||||
}
|
||||
|
||||
int platform_timer_remain(platform_timer_t* timer)
|
||||
{
|
||||
struct timeval now, res;
|
||||
gettimeofday(&now, NULL);
|
||||
timersub(&timer->time, &now, &res);
|
||||
return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;
|
||||
}
|
||||
|
||||
unsigned long platform_timer_now(void)
|
||||
{
|
||||
return (unsigned long) time(NULL);
|
||||
}
|
||||
|
||||
void platform_timer_usleep(unsigned long usec)
|
||||
{
|
||||
usleep(usec);
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* @Author: jiejie
|
||||
* @Github: https://github.com/jiejieTop
|
||||
* @Date: 2019-12-10 22:18:32
|
||||
* @LastEditTime: 2020-10-17 14:17:55
|
||||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||||
*/
|
||||
#ifndef _PLATFORM_TIMER_H_
|
||||
#define _PLATFORM_TIMER_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct platform_timer {
|
||||
struct timeval time;
|
||||
} platform_timer_t;
|
||||
|
||||
void platform_timer_init(platform_timer_t* timer);
|
||||
void platform_timer_cutdown(platform_timer_t* timer, unsigned int timeout);
|
||||
char platform_timer_is_expired(platform_timer_t* timer);
|
||||
int platform_timer_remain(platform_timer_t* timer);
|
||||
unsigned long platform_timer_now(void);
|
||||
void platform_timer_usleep(unsigned long usec);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
77
port/linux/package/pikascript/pikascript-lib/mqtt/random.c
Normal file
77
port/linux/package/pikascript/pikascript-lib/mqtt/random.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* @Author : jiejie
|
||||
* @GitHub : https://github.com/jiejieTop
|
||||
* @Date : 2021-02-26 12:00:24
|
||||
* @LastEditors : jiejie
|
||||
* @LastEditTime : 2022-06-15 19:44:22
|
||||
* @FilePath : /mqttclient/common/random.c
|
||||
* Copyright (c) 2022 jiejie, All Rights Reserved. Please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "random.h"
|
||||
|
||||
extern int platform_timer_now();
|
||||
static unsigned int last_seed = 1;
|
||||
|
||||
|
||||
int __attribute__((weak)) platform_timer_now()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int do_random(unsigned int seed)
|
||||
{
|
||||
srand(seed);
|
||||
return rand();
|
||||
}
|
||||
|
||||
int random_number(void)
|
||||
{
|
||||
unsigned int seed = (unsigned int) platform_timer_now();
|
||||
last_seed += (seed >> ((seed ^ last_seed) % 3));
|
||||
return do_random(last_seed ^ seed);
|
||||
}
|
||||
|
||||
// random number range interval [min, max)
|
||||
int random_number_range(unsigned int min, unsigned int max)
|
||||
{
|
||||
return (random_number() % (max - min)) + min;
|
||||
}
|
||||
|
||||
int random_string(char *buffer, int len)
|
||||
{
|
||||
unsigned int i, flag, seed, random;
|
||||
|
||||
if (NULL == buffer)
|
||||
return 0;
|
||||
|
||||
seed = (unsigned int) random_number();
|
||||
seed += (unsigned int) ((size_t)buffer ^ seed);
|
||||
|
||||
random = (unsigned int)do_random(seed);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
random = do_random(seed ^ random);
|
||||
flag = (unsigned int)random % 3;
|
||||
switch (flag) {
|
||||
case 0:
|
||||
buffer[i] = 'A' + do_random(random ^ (i & flag)) % 26;
|
||||
break;
|
||||
case 1:
|
||||
buffer[i] = 'a' + do_random(random ^ (i & flag)) % 26;
|
||||
break;
|
||||
case 2:
|
||||
buffer[i] = '0' + do_random(random ^ (i & flag)) % 10;
|
||||
break;
|
||||
default:
|
||||
buffer[i] = 'x';
|
||||
break;
|
||||
}
|
||||
random += ((0xb433e5c6 ^ random) << (i & flag));
|
||||
}
|
||||
|
||||
buffer[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
29
port/linux/package/pikascript/pikascript-lib/mqtt/random.h
Normal file
29
port/linux/package/pikascript/pikascript-lib/mqtt/random.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* @Author : jiejie
|
||||
* @GitHub : https://github.com/jiejieTop
|
||||
* @Date : 2021-02-26 12:00:24
|
||||
* @LastEditors : jiejie
|
||||
* @LastEditTime : 2022-06-15 19:40:10
|
||||
* @FilePath : /mqttclient/common/random.h
|
||||
* Copyright (c) 2022 jiejie, All Rights Reserved. Please keep the author information and source code according to the license.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _RANDOM_H_
|
||||
#define _RANDOM_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RANDOM_MAX 0x7FFFFFFF
|
||||
|
||||
int random_number(void);
|
||||
int random_number_range(unsigned int min, unsigned int max);
|
||||
int random_string(char *buffer, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _RANDOM_H_ */
|
Loading…
x
Reference in New Issue
Block a user