1205 lines
36 KiB
C
1205 lines
36 KiB
C
/* mqtt_packet.h
|
|
*
|
|
* Copyright (C) 2006-2020 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfMQTT.
|
|
*
|
|
* wolfMQTT is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfMQTT is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
/* Implementation by: David Garske
|
|
* Based on specification for MQTT v3.1.1 and v5.0
|
|
* See http://mqtt.org/documentation for additional MQTT documentation.
|
|
*/
|
|
|
|
#ifndef WOLFMQTT_PACKET_H
|
|
#define WOLFMQTT_PACKET_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include "wolfmqtt/mqtt_types.h"
|
|
|
|
|
|
|
|
/* Size of a data length elements in protocol */
|
|
#define MQTT_DATA_LEN_SIZE 2
|
|
#define MQTT_DATA_INT_SIZE 4
|
|
|
|
#ifndef MAX_PACKET_ID
|
|
#define MAX_PACKET_ID ((1 << 16) - 1)
|
|
#endif
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
|
|
#define MQTT_PACKET_SZ_MAX 0xA0000005
|
|
|
|
/* DATA TYPES */
|
|
typedef enum MqttDataType {
|
|
MQTT_DATA_TYPE_NONE = 0,
|
|
MQTT_DATA_TYPE_BYTE,
|
|
MQTT_DATA_TYPE_SHORT,
|
|
MQTT_DATA_TYPE_INT,
|
|
MQTT_DATA_TYPE_STRING,
|
|
MQTT_DATA_TYPE_VAR_INT,
|
|
MQTT_DATA_TYPE_BINARY,
|
|
MQTT_DATA_TYPE_STRING_PAIR,
|
|
} MqttDataType;
|
|
|
|
/* PROPERTIES */
|
|
typedef enum MqttPropertyType {
|
|
MQTT_PROP_NONE = 0,
|
|
MQTT_PROP_PAYLOAD_FORMAT_IND = 1,
|
|
MQTT_PROP_MSG_EXPIRY_INTERVAL = 2,
|
|
MQTT_PROP_CONTENT_TYPE = 3,
|
|
MQTT_PROP_RESP_TOPIC = 8,
|
|
MQTT_PROP_CORRELATION_DATA = 9,
|
|
MQTT_PROP_SUBSCRIPTION_ID = 11,
|
|
MQTT_PROP_SESSION_EXPIRY_INTERVAL = 17,
|
|
MQTT_PROP_ASSIGNED_CLIENT_ID = 18,
|
|
MQTT_PROP_SERVER_KEEP_ALIVE = 19,
|
|
MQTT_PROP_AUTH_METHOD = 21,
|
|
MQTT_PROP_AUTH_DATA = 22,
|
|
MQTT_PROP_REQ_PROB_INFO = 23,
|
|
MQTT_PROP_WILL_DELAY_INTERVAL = 24,
|
|
MQTT_PROP_REQ_RESP_INFO = 25,
|
|
MQTT_PROP_RESP_INFO = 26,
|
|
MQTT_PROP_SERVER_REF = 28,
|
|
MQTT_PROP_REASON_STR = 31,
|
|
MQTT_PROP_RECEIVE_MAX = 33,
|
|
MQTT_PROP_TOPIC_ALIAS_MAX = 34,
|
|
MQTT_PROP_TOPIC_ALIAS = 35,
|
|
MQTT_PROP_MAX_QOS = 36,
|
|
MQTT_PROP_RETAIN_AVAIL = 37,
|
|
MQTT_PROP_USER_PROP = 38,
|
|
MQTT_PROP_MAX_PACKET_SZ = 39,
|
|
MQTT_PROP_WILDCARD_SUB_AVAIL = 40,
|
|
MQTT_PROP_SUBSCRIPTION_ID_AVAIL = 41,
|
|
MQTT_PROP_SHARED_SUBSCRIPTION_AVAIL = 42,
|
|
MQTT_PROP_TYPE_MAX = 0xFF
|
|
} MqttPropertyType;
|
|
|
|
/* backwards compatibility for anyone using the typo name */
|
|
#define MQTT_PROP_PLAYLOAD_FORMAT_IND MQTT_PROP_PAYLOAD_FORMAT_IND
|
|
|
|
struct _MqttProp_Str {
|
|
word16 len;
|
|
char *str;
|
|
};
|
|
|
|
struct _MqttProp_Bin {
|
|
word16 len;
|
|
byte *data;
|
|
};
|
|
|
|
/* Property list */
|
|
typedef struct _MqttProp {
|
|
struct _MqttProp *next;
|
|
MqttPropertyType type;
|
|
byte data_byte;
|
|
word16 data_short;
|
|
word32 data_int;
|
|
struct _MqttProp_Str data_str;
|
|
struct _MqttProp_Bin data_bin;
|
|
struct _MqttProp_Str data_str2;
|
|
} MqttProp;
|
|
|
|
/* REASON CODES */
|
|
enum MqttReasonCodes {
|
|
MQTT_REASON_SUCCESS = 0x00,
|
|
MQTT_REASON_NORMAL_DISCONNECTION = 0x00,
|
|
MQTT_REASON_GRANTED_QOS_0 = 0x00,
|
|
MQTT_REASON_GRANTED_QOS_1 = 0x01,
|
|
MQTT_REASON_GRANTED_QOS_2 = 0x02,
|
|
MQTT_REASON_DISCONNECT_W_WILL_MSG = 0x04,
|
|
MQTT_REASON_NO_MATCH_SUB = 0x10,
|
|
MQTT_REASON_NO_SUB_EXIST = 0x11,
|
|
MQTT_REASON_CONT_AUTH = 0x18,
|
|
MQTT_REASON_REAUTH = 0x19,
|
|
|
|
/* begin error codes */
|
|
MQTT_REASON_UNSPECIFIED_ERR = 0x80,
|
|
MQTT_REASON_MALFORMED_PACKET = 0x81,
|
|
MQTT_REASON_PROTOCOL_ERR = 0x82,
|
|
MQTT_REASON_IMPL_SPECIFIC_ERR = 0x83,
|
|
MQTT_REASON_UNSUP_PROTO_VER = 0x84,
|
|
MQTT_REASON_CLIENT_ID_NOT_VALID = 0x85,
|
|
MQTT_REASON_BAD_USER_OR_PASS = 0x86,
|
|
MQTT_REASON_NOT_AUTHORIZED = 0x87,
|
|
MQTT_REASON_SERVER_UNAVAILABLE = 0x88,
|
|
MQTT_REASON_SERVER_BUSY = 0x89,
|
|
MQTT_REASON_BANNED = 0x8A,
|
|
MQTT_REASON_SERVER_SHUTTING_DOWN = 0x8B,
|
|
MQTT_REASON_BAD_AUTH_METHOD = 0x8C,
|
|
MQTT_REASON_KEEP_ALIVE_TIMEOUT = 0x8D,
|
|
MQTT_REASON_SESSION_TAKEN_OVER = 0x8E,
|
|
MQTT_REASON_TOPIC_FILTER_INVALID = 0x8F,
|
|
MQTT_REASON_TOPIC_NAME_INVALID = 0x90,
|
|
MQTT_REASON_PACKET_ID_IN_USE = 0x91,
|
|
MQTT_REASON_PACKET_ID_NOT_FOUND = 0x92,
|
|
MQTT_REASON_RX_MAX_EXCEEDED = 0x93,
|
|
MQTT_REASON_TOPIC_ALIAS_INVALID = 0x94,
|
|
MQTT_REASON_PACKET_TOO_LARGE = 0x95,
|
|
MQTT_REASON_MSG_RATE_TOO_HIGH = 0x96,
|
|
MQTT_REASON_QUOTA_EXCEEDED = 0x97,
|
|
MQTT_REASON_ADMIN_ACTION = 0x98,
|
|
MQTT_REASON_PAYLOAD_FORMAT_INVALID = 0x99,
|
|
MQTT_REASON_RETAIN_NOT_SUPPORTED = 0x9A,
|
|
MQTT_REASON_QOS_NOT_SUPPORTED = 0x9B,
|
|
MQTT_REASON_USE_ANOTHER_SERVER = 0x9C,
|
|
MQTT_REASON_SERVER_MOVED = 0x9D,
|
|
MQTT_REASON_SS_NOT_SUPPORTED = 0x9E,
|
|
MQTT_REASON_CON_RATE_EXCEED = 0x9F,
|
|
MQTT_REASON_MAX_CON_TIME = 0xA0,
|
|
MQTT_REASON_SUB_ID_NOT_SUP = 0xA1,
|
|
MQTT_REASON_WILDCARD_SUB_NOT_SUP = 0xA2,
|
|
};
|
|
#endif /* WOLFMQTT_V5 */
|
|
|
|
|
|
|
|
/* QoS */
|
|
//enum QoS { QOS0, QOS1, QOS2 };
|
|
|
|
typedef enum _MqttQoS {
|
|
MQTT_QOS_0 = 0, /* At most once delivery */
|
|
QOS0 = 0,
|
|
|
|
MQTT_QOS_1 = 1, /* At least once delivery */
|
|
QOS1 = 1,
|
|
|
|
MQTT_QOS_2 = 2, /* Exactly once delivery */
|
|
QOS2 = 2,
|
|
|
|
MQTT_QOS_3 = 3, /* Reserved - must not be used */
|
|
} MqttQoS;
|
|
|
|
|
|
/* Topic */
|
|
typedef struct _MqttTopic {
|
|
const char *topic_filter;
|
|
|
|
/* These are only on subscribe */
|
|
MqttQoS qos; /* Bits 0-1 = MqttQoS */
|
|
byte return_code; /* MqttSubscribeAckReturnCodes */
|
|
#ifdef WOLFMQTT_V5
|
|
byte sub_id;
|
|
word16 alias;
|
|
#endif
|
|
} MqttTopic;
|
|
|
|
/* Topic naming */
|
|
/* Be specific, use readable characters only.
|
|
* Use forward slashes to denote levels.
|
|
* Do not start name with forward slash (/) or $ (reserved for broker)
|
|
* Example: "main/sub/detail/unique" */
|
|
|
|
/* The forward slash is used to define levels of topic matching */
|
|
#define TOPIC_LEVEL_SEPERATOR '/'
|
|
|
|
/* These are available for Topic Filters on Subscribe only */
|
|
/* The plus is used to match on a single level */
|
|
/* Example: "user/home/+/light" */
|
|
#define TOPIC_LEVEL_SINGLE '+'
|
|
|
|
/* The hash is used to match on a multiple levels */
|
|
/* Example: "user/home/#" */
|
|
#define TOPIC_LEVEL_MULTI '#'
|
|
|
|
|
|
/* PACKET HEADER */
|
|
/* Packet types: Located in first byte of packet in bits 4-7 */
|
|
#define MQTT_PACKET_TYPE_GET(x) (((x) >> 4) & 0xF)
|
|
#define MQTT_PACKET_TYPE_SET(x) (((x) & 0xF) << 4)
|
|
typedef enum _MqttPacketType {
|
|
MQTT_PACKET_TYPE_RESERVED = 0,
|
|
MQTT_PACKET_TYPE_CONNECT = 1,
|
|
MQTT_PACKET_TYPE_CONNECT_ACK = 2, /* Acknowledgment */
|
|
MQTT_PACKET_TYPE_PUBLISH = 3,
|
|
MQTT_PACKET_TYPE_PUBLISH_ACK = 4, /* Acknowledgment */
|
|
MQTT_PACKET_TYPE_PUBLISH_REC = 5, /* Received */
|
|
MQTT_PACKET_TYPE_PUBLISH_REL = 6, /* Release */
|
|
MQTT_PACKET_TYPE_PUBLISH_COMP = 7, /* Complete */
|
|
MQTT_PACKET_TYPE_SUBSCRIBE = 8,
|
|
MQTT_PACKET_TYPE_SUBSCRIBE_ACK = 9, /* Acknowledgment */
|
|
MQTT_PACKET_TYPE_UNSUBSCRIBE = 10,
|
|
MQTT_PACKET_TYPE_UNSUBSCRIBE_ACK = 11, /* Acknowledgment */
|
|
MQTT_PACKET_TYPE_PING_REQ = 12, /* Request */
|
|
MQTT_PACKET_TYPE_PING_RESP = 13, /* Response */
|
|
MQTT_PACKET_TYPE_DISCONNECT = 14,
|
|
MQTT_PACKET_TYPE_AUTH = 15, /* Authentication (MQTT 5) */
|
|
MQTT_PACKET_TYPE_ANY = 16,
|
|
} MqttPacketType;
|
|
|
|
/* Packet flag bit-mask: Located in first byte of packet in bits 0-3 */
|
|
#define MQTT_PACKET_FLAGS_GET(x) ((x) & 0xF)
|
|
#define MQTT_PACKET_FLAGS_SET(x) (x)
|
|
#define MQTT_PACKET_FLAGS_GET_QOS(type_flags) \
|
|
((MQTT_PACKET_FLAGS_GET((type_flags)) & \
|
|
MQTT_PACKET_FLAG_QOS_MASK) >> MQTT_PACKET_FLAG_QOS_SHIFT)
|
|
#define MQTT_PACKET_FLAGS_SET_QOS(qos) \
|
|
(MQTT_PACKET_FLAGS_SET(((qos) << MQTT_PACKET_FLAG_QOS_SHIFT) & \
|
|
MQTT_PACKET_FLAG_QOS_MASK))
|
|
enum MqttPacketFlags {
|
|
MQTT_PACKET_FLAG_RETAIN = 0x1,
|
|
MQTT_PACKET_FLAG_QOS_SHIFT = 0x1,
|
|
MQTT_PACKET_FLAG_QOS_MASK = 0x6,
|
|
MQTT_PACKET_FLAG_DUPLICATE = 0x8,
|
|
};
|
|
|
|
/* Packet Header: Size is variable 2 - 5 bytes */
|
|
#define MQTT_PACKET_MAX_LEN_BYTES 4
|
|
#define MQTT_PACKET_LEN_ENCODE_MASK 0x80
|
|
typedef struct _MqttPacket {
|
|
/* Type = bits 4-7, Flags = 0-3 are flags */
|
|
byte type_flags; /* MqttPacketType and MqttPacketFlags */
|
|
|
|
/* Remaining Length: variable 1-4 bytes, encoded using scheme
|
|
where bit 7 = continuation bit */
|
|
byte len[MQTT_PACKET_MAX_LEN_BYTES];
|
|
|
|
/* Then packet_id if type is PUBLISH through UNSUBSCRIBE_ACK */
|
|
/* Packet Id: Included for types PUBLISH_ACK through UNSUBSCRIBE_ACK */
|
|
/* Note: Also included in PUBLISH after topic field (see MqttPublish) */
|
|
/* Must be non-zero value */
|
|
} WOLFMQTT_PACK MqttPacket;
|
|
#define MQTT_PACKET_HEADER_MIN_SIZE (2)
|
|
|
|
|
|
/* Generic Message */
|
|
typedef enum _MqttMsgStat {
|
|
MQTT_MSG_BEGIN = 0, /* must be zero, so memset will setup state */
|
|
#ifdef WOLFMQTT_V5
|
|
MQTT_MSG_AUTH,
|
|
#endif
|
|
MQTT_MSG_WAIT,
|
|
MQTT_MSG_WRITE,
|
|
MQTT_MSG_WRITE_PAYLOAD,
|
|
MQTT_MSG_READ,
|
|
MQTT_MSG_READ_PAYLOAD,
|
|
} MqttMsgStat;
|
|
|
|
#ifdef WOLFMQTT_MULTITHREAD
|
|
/* Pending Response Structure */
|
|
typedef struct _MqttPendResp {
|
|
word16 packet_id;
|
|
MqttPacketType packet_type;
|
|
int packet_ret;
|
|
void *packet_obj;
|
|
|
|
/* bits */
|
|
word16 packetDone: 1; /* task completed it */
|
|
word16 packetProcessing: 1; /* task processing it */
|
|
|
|
/* double linked list */
|
|
struct _MqttPendResp *next;
|
|
struct _MqttPendResp *prev;
|
|
} MqttPendResp;
|
|
#endif /* WOLFMQTT_MULTITHREAD */
|
|
|
|
|
|
/* CONNECT PACKET */
|
|
/* Connect flag bit-mask: Located in byte 8 of the MqttConnect packet */
|
|
#define MQTT_CONNECT_FLAG_GET_QOS(flags) \
|
|
(((flags) MQTT_CONNECT_FLAG_WILL_QOS_MASK) >> \
|
|
MQTT_CONNECT_FLAG_WILL_QOS_SHIFT)
|
|
#define MQTT_CONNECT_FLAG_SET_QOS(qos) \
|
|
(((qos) << MQTT_CONNECT_FLAG_WILL_QOS_SHIFT) & \
|
|
MQTT_CONNECT_FLAG_WILL_QOS_MASK)
|
|
enum MqttConnectFlags {
|
|
MQTT_CONNECT_FLAG_RESERVED = 0x01,
|
|
MQTT_CONNECT_FLAG_CLEAN_SESSION = 0x02, /* Old v3.1.1 name */
|
|
MQTT_CONNECT_FLAG_CLEAN_START = 0x02,
|
|
MQTT_CONNECT_FLAG_WILL_FLAG = 0x04,
|
|
MQTT_CONNECT_FLAG_WILL_QOS_SHIFT = 3,
|
|
MQTT_CONNECT_FLAG_WILL_QOS_MASK = 0x18,
|
|
MQTT_CONNECT_FLAG_WILL_RETAIN = 0x20,
|
|
MQTT_CONNECT_FLAG_PASSWORD = 0x40,
|
|
MQTT_CONNECT_FLAG_USERNAME = 0x80,
|
|
};
|
|
|
|
/* Connect Protocol */
|
|
/* Constant values for the protocol name and level */
|
|
#define MQTT_CONNECT_PROTOCOL_NAME_LEN 4
|
|
#define MQTT_CONNECT_PROTOCOL_NAME "MQTT"
|
|
#define MQTT_CONNECT_PROTOCOL_LEVEL_4 4 /* v3.1.1 */
|
|
#define MQTT_CONNECT_PROTOCOL_LEVEL_5 5 /* v5.0 */
|
|
#ifdef WOLFMQTT_V5
|
|
#define MQTT_CONNECT_PROTOCOL_LEVEL MQTT_CONNECT_PROTOCOL_LEVEL_5
|
|
#else
|
|
#define MQTT_CONNECT_PROTOCOL_LEVEL MQTT_CONNECT_PROTOCOL_LEVEL_4
|
|
#endif
|
|
/* Initializer */
|
|
#define MQTT_CONNECT_INIT \
|
|
{{0, MQTT_CONNECT_PROTOCOL_NAME_LEN}, {'M', 'Q', 'T', 'T'}, \
|
|
MQTT_CONNECT_PROTOCOL_LEVEL, 0, 0}
|
|
|
|
/* Connect packet structure */
|
|
typedef struct _MqttConnectPacket {
|
|
byte protocol_len[MQTT_DATA_LEN_SIZE];
|
|
char protocol_name[MQTT_CONNECT_PROTOCOL_NAME_LEN];
|
|
byte protocol_level;
|
|
byte flags; /* MqttConnectFlags */
|
|
word16 keep_alive; /* Seconds */
|
|
} WOLFMQTT_PACK MqttConnectPacket;
|
|
|
|
|
|
/* CONNECT ACKNOWLEDGE */
|
|
/* Connect Ack flags */
|
|
enum MqttConnectAckFlags {
|
|
MQTT_CONNECT_ACK_FLAG_SESSION_PRESENT = 0x01,
|
|
};
|
|
|
|
/* Connect Ack return codes */
|
|
enum MqttConnectAckReturnCodes {
|
|
/* Connection accepted */
|
|
MQTT_CONNECT_ACK_CODE_ACCEPTED = 0,
|
|
|
|
/* The Server does not support the level of the MQTT protocol requested
|
|
by the Client */
|
|
MQTT_CONNECT_ACK_CODE_REFUSED_PROTO = 1,
|
|
|
|
/* The Client identifier is correct UTF-8 but not allowed by the Server */
|
|
MQTT_CONNECT_ACK_CODE_REFUSED_ID = 2,
|
|
|
|
/* The Network Connection has been made but the MQTT service is
|
|
unavailable */
|
|
MQTT_CONNECT_ACK_CODE_REFUSED_UNAVAIL = 3,
|
|
|
|
/* The data in the user name or password is malformed */
|
|
MQTT_CONNECT_ACK_CODE_REFUSED_BAD_USER_PWD = 4,
|
|
|
|
/* The Client is not authorized to connect */
|
|
MQTT_CONNECT_ACK_CODE_REFUSED_NOT_AUTH = 5,
|
|
};
|
|
|
|
/* Connect Ack packet structure */
|
|
typedef struct _MqttConnectAck {
|
|
MqttMsgStat stat; /* must be first member at top */
|
|
|
|
byte flags; /* MqttConnectAckFlags */
|
|
byte return_code; /* MqttConnectAckCodes */
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
MqttProp *props;
|
|
byte protocol_level;
|
|
#endif
|
|
} MqttConnectAck;
|
|
/* Connect Ack has no payload */
|
|
|
|
/* CONNECT */
|
|
/* Connect structure */
|
|
/************添加结构体START*************/
|
|
|
|
typedef struct {
|
|
int len;
|
|
char *data;
|
|
} MQTTLenString;
|
|
|
|
typedef struct {
|
|
char *cstring;
|
|
MQTTLenString lenstring;
|
|
} MQTTString;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
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;
|
|
|
|
#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
|
|
|
|
#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}} }
|
|
|
|
|
|
/************添加结构体END*************/
|
|
struct _MqttMessage;
|
|
typedef struct _MqttConnect {
|
|
/* stat and pendResp must be first members at top */
|
|
MqttMsgStat stat;
|
|
#ifdef WOLFMQTT_MULTITHREAD
|
|
MqttPendResp pendResp;
|
|
#endif
|
|
|
|
word16 keep_alive_sec;
|
|
byte clean_session;
|
|
const char *client_id;
|
|
|
|
/* Protocol version: 4=v3.1.1 (default), 5=v5.0 */
|
|
byte protocol_level;
|
|
|
|
/* Optional Last will and testament */
|
|
byte enable_lwt;
|
|
struct _MqttMessage *lwt_msg;
|
|
|
|
/* Optional login */
|
|
const char *username;
|
|
const char *password;
|
|
|
|
/* Ack data */
|
|
MqttConnectAck ack;
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
MqttProp *props;
|
|
#endif
|
|
} MqttConnect;
|
|
|
|
|
|
/* PUBLISH RESPONSE */
|
|
/* This is the response struct for PUBLISH_ACK, PUBLISH_REC and PUBLISH_COMP */
|
|
/* If QoS = 0: No response */
|
|
/* If QoS = 1: Expect response packet with type =
|
|
MQTT_PACKET_TYPE_PUBLISH_ACK */
|
|
/* If QoS = 2: Expect response packet with type =
|
|
MQTT_PACKET_TYPE_PUBLISH_REC */
|
|
/* Packet Id required if QoS is 1 or 2 */
|
|
/* If Qos = 2: Send MQTT_PACKET_TYPE_PUBLISH_REL with PacketId to complete
|
|
QoS2 protocol exchange */
|
|
/* Expect response packet with type = MQTT_PACKET_TYPE_PUBLISH_COMP */
|
|
typedef struct _MqttPublishResp {
|
|
/* stat and pendResp must be first members at top */
|
|
MqttMsgStat stat;
|
|
#ifdef WOLFMQTT_MULTITHREAD
|
|
MqttPendResp pendResp;
|
|
#endif
|
|
|
|
word16 packet_id;
|
|
#ifdef WOLFMQTT_V5
|
|
byte reason_code;
|
|
MqttProp *props;
|
|
byte protocol_level;
|
|
#endif
|
|
} MqttPublishResp;
|
|
|
|
/* PUBLISH */
|
|
/* PacketId sent only if QoS > 0 */
|
|
typedef struct _MqttMessage {
|
|
/* stat and pendResp must be first members at top */
|
|
MqttMsgStat stat;
|
|
#ifdef WOLFMQTT_MULTITHREAD
|
|
MqttPendResp pendResp;
|
|
#endif
|
|
word16 packet_id;
|
|
byte type;
|
|
MqttQoS qos;
|
|
byte retain;
|
|
byte duplicate;
|
|
#ifdef WOLFMQTT_SN
|
|
byte topic_type;
|
|
byte return_code;
|
|
#endif
|
|
|
|
const char *topic_name; /* Pointer is valid only when
|
|
msg_new set in callback */
|
|
word16 topic_name_len;
|
|
word32 total_len; /* Payload total length */
|
|
byte *buffer; /* Payload buffer */
|
|
word32 buffer_len; /* Payload buffer length */
|
|
word32 buffer_pos; /* Payload buffer position */
|
|
|
|
/* Used internally for TX/RX buffers */
|
|
byte buffer_new; /* flag to indicate new message */
|
|
word32 intBuf_len; /* Buffer length */
|
|
word32 intBuf_pos; /* Buffer position */
|
|
|
|
void *ctx; /* user supplied context for publish callbacks */
|
|
|
|
MqttPublishResp resp;
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
MqttProp *props;
|
|
byte protocol_level;
|
|
#endif
|
|
} MqttMessage;
|
|
typedef MqttMessage MqttPublish; /* Publish is message */
|
|
|
|
/****************************************/
|
|
|
|
typedef struct MQTTMessage {
|
|
MqttQoS qos;
|
|
char retained;
|
|
char dup;
|
|
unsigned short id;
|
|
void *payload;
|
|
size_t payloadlen;
|
|
} MQTTMessage;
|
|
|
|
struct MessageData {
|
|
MQTTMessage *message;
|
|
MQTTString *topicName;
|
|
};
|
|
|
|
typedef struct MessageData MessageData;
|
|
|
|
|
|
/****************************************/
|
|
|
|
/* SUBSCRIBE ACK */
|
|
/* Packet Id followed by list of return codes corresponding to subscription
|
|
topic list sent. */
|
|
enum MqttSubscribeAckReturnCodes {
|
|
MQTT_SUBSCRIBE_ACK_CODE_SUCCESS_MAX_QOS0 = 0,
|
|
MQTT_SUBSCRIBE_ACK_CODE_SUCCESS_MAX_QOS1 = 1,
|
|
MQTT_SUBSCRIBE_ACK_CODE_SUCCESS_MAX_QOS2 = 2,
|
|
MQTT_SUBSCRIBE_ACK_CODE_FAILURE = 0x80,
|
|
};
|
|
typedef struct _MqttSubscribeAck {
|
|
MqttMsgStat stat; /* must be first member at top */
|
|
|
|
word16 packet_id;
|
|
byte *return_codes; /* MqttSubscribeAckReturnCodes */
|
|
#ifdef WOLFMQTT_V5
|
|
MqttProp *props;
|
|
byte protocol_level;
|
|
#endif
|
|
} MqttSubscribeAck;
|
|
|
|
/* SUBSCRIBE */
|
|
/* Packet Id followed by contiguous list of topics w/Qos to subscribe to. */
|
|
typedef struct _MqttSubscribe {
|
|
/* stat and pendResp must be first members at top */
|
|
MqttMsgStat stat;
|
|
#ifdef WOLFMQTT_MULTITHREAD
|
|
MqttPendResp pendResp;
|
|
#endif
|
|
|
|
word16 packet_id;
|
|
int topic_count;
|
|
MqttTopic *topics;
|
|
|
|
MqttSubscribeAck ack;
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
MqttProp *props;
|
|
byte protocol_level;
|
|
#endif
|
|
} MqttSubscribe;
|
|
|
|
|
|
/* UNSUBSCRIBE RESPONSE ACK */
|
|
/* No response payload (besides packet Id) */
|
|
typedef struct _MqttUnsubscribeAck {
|
|
MqttMsgStat stat; /* must be first member at top */
|
|
|
|
word16 packet_id;
|
|
#ifdef WOLFMQTT_V5
|
|
MqttProp *props;
|
|
byte *reason_codes;
|
|
byte protocol_level;
|
|
#endif
|
|
} MqttUnsubscribeAck;
|
|
|
|
/* UNSUBSCRIBE */
|
|
/* Packet Id followed by contiguous list of topics to unsubscribe from. */
|
|
typedef struct _MqttUnsubscribe {
|
|
/* stat and pendResp must be first members at top */
|
|
MqttMsgStat stat;
|
|
#ifdef WOLFMQTT_MULTITHREAD
|
|
MqttPendResp pendResp;
|
|
#endif
|
|
|
|
word16 packet_id;
|
|
int topic_count;
|
|
MqttTopic *topics;
|
|
|
|
MqttUnsubscribeAck ack;
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
MqttProp *props;
|
|
byte protocol_level;
|
|
#endif
|
|
} MqttUnsubscribe;
|
|
|
|
|
|
/* PING / PING RESPONSE */
|
|
/* Fixed header "MqttPacket" only. No variable header or payload */
|
|
typedef struct _MqttPing {
|
|
/* stat and pendResp must be first members at top */
|
|
MqttMsgStat stat;
|
|
#ifdef WOLFMQTT_MULTITHREAD
|
|
MqttPendResp pendResp;
|
|
#endif
|
|
} MqttPing;
|
|
|
|
|
|
/* DISCONNECT */
|
|
typedef struct _MqttDisconnect {
|
|
MqttMsgStat stat; /* must be first member at top */
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
byte reason_code;
|
|
MqttProp *props;
|
|
byte protocol_level;
|
|
#endif
|
|
} MqttDisconnect;
|
|
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
/* AUTH */
|
|
typedef struct _MqttAuth {
|
|
/* stat and pendResp must be first members at top */
|
|
MqttMsgStat stat;
|
|
#ifdef WOLFMQTT_MULTITHREAD
|
|
MqttPendResp pendResp;
|
|
#endif
|
|
|
|
byte reason_code;
|
|
MqttProp *props;
|
|
} MqttAuth;
|
|
#endif
|
|
|
|
/* Generic MQTT struct for packet types */
|
|
typedef union _MqttObject {
|
|
MqttConnect connect;
|
|
MqttConnectAck connect_ack;
|
|
MqttPublish publish;
|
|
MqttPublishResp publish_resp;
|
|
MqttSubscribe subscribe;
|
|
MqttSubscribeAck subscribe_ack;
|
|
MqttUnsubscribe unsubscribe;
|
|
MqttUnsubscribeAck unsubscribe_ack;
|
|
MqttPing ping;
|
|
MqttDisconnect disconnect;
|
|
#ifdef WOLFMQTT_V5
|
|
MqttAuth auth;
|
|
#endif
|
|
} MqttObject;
|
|
|
|
|
|
|
|
/* MQTT PACKET APPLICATION INTERFACE */
|
|
struct _MqttClient;
|
|
/* Packet Read/Write */
|
|
WOLFMQTT_LOCAL int MqttPacket_Write(struct _MqttClient *client, byte *tx_buf,
|
|
int tx_buf_len);
|
|
WOLFMQTT_LOCAL int MqttPacket_Read(struct _MqttClient *client, byte *rx_buf,
|
|
int rx_buf_len, int timeout_ms);
|
|
|
|
/* Packet Element Encoders/Decoders */
|
|
WOLFMQTT_LOCAL int MqttDecode_Num(byte *buf, word16 *len);
|
|
WOLFMQTT_LOCAL int MqttEncode_Num(byte *buf, word16 len);
|
|
|
|
WOLFMQTT_LOCAL int MqttDecode_Int(byte *buf, word32 *len);
|
|
WOLFMQTT_LOCAL int MqttEncode_Int(byte *buf, word32 len);
|
|
|
|
WOLFMQTT_LOCAL int MqttDecode_String(byte *buf, const char **pstr,
|
|
word16 *pstr_len);
|
|
WOLFMQTT_LOCAL int MqttEncode_String(byte *buf, const char *str);
|
|
|
|
WOLFMQTT_LOCAL int MqttEncode_Data(byte *buf, const byte *data,
|
|
word16 data_len);
|
|
|
|
WOLFMQTT_LOCAL int MqttDecode_Vbi(byte *buf, word32 *value);
|
|
WOLFMQTT_LOCAL int MqttEncode_Vbi(byte *buf, word32 x);
|
|
|
|
/* Packet Encoders/Decoders */
|
|
WOLFMQTT_LOCAL int MqttEncode_Connect(byte *tx_buf, int tx_buf_len,
|
|
MqttConnect *connect);
|
|
WOLFMQTT_LOCAL int MqttDecode_ConnectAck(byte *rx_buf, int rx_buf_len,
|
|
MqttConnectAck *connect_ack);
|
|
WOLFMQTT_LOCAL int MqttEncode_Publish(byte *tx_buf, int tx_buf_len,
|
|
MqttPublish *publish, byte use_cb);
|
|
WOLFMQTT_LOCAL int MqttDecode_Publish(byte *rx_buf, int rx_buf_len,
|
|
MqttPublish *publish);
|
|
WOLFMQTT_LOCAL int MqttEncode_PublishResp(byte *tx_buf, int tx_buf_len,
|
|
byte type, MqttPublishResp *publish_resp);
|
|
WOLFMQTT_LOCAL int MqttDecode_PublishResp(byte *rx_buf, int rx_buf_len,
|
|
byte type, MqttPublishResp *publish_resp);
|
|
WOLFMQTT_LOCAL int MqttEncode_Subscribe(byte *tx_buf, int tx_buf_len,
|
|
MqttSubscribe *subscribe);
|
|
WOLFMQTT_LOCAL int MqttDecode_SubscribeAck(byte *rx_buf, int rx_buf_len,
|
|
MqttSubscribeAck *subscribe_ack);
|
|
WOLFMQTT_LOCAL int MqttEncode_Unsubscribe(byte *tx_buf, int tx_buf_len,
|
|
MqttUnsubscribe *unsubscribe);
|
|
WOLFMQTT_LOCAL int MqttDecode_UnsubscribeAck(byte *rx_buf, int rx_buf_len,
|
|
MqttUnsubscribeAck *unsubscribe_ack);
|
|
WOLFMQTT_LOCAL int MqttEncode_Ping(byte *tx_buf, int tx_buf_len, MqttPing *ping);
|
|
WOLFMQTT_LOCAL int MqttDecode_Ping(byte *rx_buf, int rx_buf_len, MqttPing *ping);
|
|
WOLFMQTT_LOCAL int MqttEncode_Disconnect(byte *tx_buf, int tx_buf_len,
|
|
MqttDisconnect *disc);
|
|
|
|
#ifdef WOLFMQTT_V5
|
|
WOLFMQTT_LOCAL int MqttDecode_Disconnect(byte *rx_buf, int rx_buf_len,
|
|
MqttDisconnect *disc);
|
|
WOLFMQTT_LOCAL int MqttDecode_Auth(byte *rx_buf, int rx_buf_len,
|
|
MqttAuth *auth);
|
|
WOLFMQTT_LOCAL int MqttEncode_Auth(byte *tx_buf, int tx_buf_len,
|
|
MqttAuth *auth);
|
|
WOLFMQTT_LOCAL int MqttEncode_Props(MqttPacketType packet, MqttProp *props,
|
|
byte *buf);
|
|
WOLFMQTT_LOCAL int MqttDecode_Props(MqttPacketType packet, MqttProp **props,
|
|
byte *buf, word32 prop_len);
|
|
WOLFMQTT_LOCAL MqttProp *MqttProps_Add(MqttProp **head);
|
|
WOLFMQTT_LOCAL void MqttProps_Free(MqttProp *head);
|
|
WOLFMQTT_LOCAL MqttProp *MqttProps_FindType(MqttProp *head,
|
|
MqttPropertyType type);
|
|
#endif
|
|
|
|
#ifndef WOLFMQTT_NO_ERROR_STRINGS
|
|
WOLFMQTT_LOCAL const char *MqttPacket_TypeDesc(MqttPacketType packet_type);
|
|
#else
|
|
#define MqttPacket_TypeDesc(x) "not compiled in"
|
|
#endif
|
|
|
|
|
|
#ifdef WOLFMQTT_SN
|
|
|
|
/* Note that because MQTT-SN does not support message fragmentation and
|
|
reassembly, the maximum message length that could be used in a network is
|
|
governed by the maximum packet size that is supported by that network,
|
|
and not by the maximum length that could be encoded by MQTT-SN. */
|
|
#ifndef WOLFMQTT_SN_MAXPACKET_SIZE
|
|
#define WOLFMQTT_SN_MAXPACKET_SIZE 1024
|
|
#endif
|
|
|
|
/* The SN_GwAddr field has a variable length and contains the address of a GW.
|
|
Its depends on the network over which MQTT-SN operates and is indicated in
|
|
the first octet of this field. For example, in a ZigBee network the network
|
|
address is 2-octet long. */
|
|
typedef word16 SN_GwAddr ;
|
|
|
|
/* RETURN CODE values */
|
|
enum SN_ReturnCodes {
|
|
SN_RC_ACCEPTED = 0x00,
|
|
SN_RC_CONGESTION = 0x01,
|
|
SN_RC_INVTOPICNAME = 0x02,
|
|
SN_RC_NOTSUPPORTED = 0x03
|
|
/* 0x04 - 0xFF reserved */
|
|
};
|
|
|
|
/* MESSAGE HEADER */
|
|
/* Message types: Located in last byte of header */
|
|
typedef enum _SN_MsgType {
|
|
SN_MSG_TYPE_ADVERTISE = 0x00,
|
|
SN_MSG_TYPE_SEARCHGW = 0x01,
|
|
SN_MSG_TYPE_GWINFO = 0x02,
|
|
/* 0x03 reserved */
|
|
SN_MSG_TYPE_CONNECT = 0x04,
|
|
SN_MSG_TYPE_CONNACK = 0x05,
|
|
SN_MSG_TYPE_WILLTOPICREQ = 0x06,
|
|
SN_MSG_TYPE_WILLTOPIC = 0x07,
|
|
SN_MSG_TYPE_WILLMSGREQ = 0x08,
|
|
SN_MSG_TYPE_WILLMSG = 0x09,
|
|
SN_MSG_TYPE_REGISTER = 0x0A,
|
|
SN_MSG_TYPE_REGACK = 0x0B,
|
|
SN_MSG_TYPE_PUBLISH = 0x0C,
|
|
SN_MSG_TYPE_PUBACK = 0x0D,
|
|
SN_MSG_TYPE_PUBCOMP = 0x0E,
|
|
SN_MSG_TYPE_PUBREC = 0x0F,
|
|
SN_MSG_TYPE_PUBREL = 0x10,
|
|
/* 0x11 reserved */
|
|
SN_MSG_TYPE_SUBSCRIBE = 0x12,
|
|
SN_MSG_TYPE_SUBACK = 0x13,
|
|
SN_MSG_TYPE_UNSUBSCRIBE = 0x14,
|
|
SN_MSG_TYPE_UNSUBACK = 0x15,
|
|
SN_MSG_TYPE_PING_REQ = 0x16,
|
|
SN_MSG_TYPE_PING_RESP = 0x17,
|
|
SN_MSG_TYPE_DISCONNECT = 0x18,
|
|
/* 0x19 reserved */
|
|
SN_MSG_TYPE_WILLTOPICUPD = 0x1A,
|
|
SN_MSG_TYPE_WILLTOPICRESP = 0x1B,
|
|
SN_MSG_TYPE_WILLMSGUPD = 0x1C,
|
|
SN_MSG_TYPE_WILLMSGRESP = 0x1D,
|
|
/* 0x1E - 0xFD reserved */
|
|
SN_MSG_TYPE_ENCAPMSG = 0xFE, /* Encapsulated message */
|
|
/* 0xFF reserved */
|
|
SN_MSG_TYPE_RESERVED = 0xFF
|
|
} SN_MsgType;
|
|
|
|
/* Topic ID types */
|
|
enum SN_TopicId_Types {
|
|
SN_TOPIC_ID_TYPE_NORMAL = 0x0,
|
|
SN_TOPIC_ID_TYPE_PREDEF = 0x1,
|
|
SN_TOPIC_ID_TYPE_SHORT = 0x2
|
|
};
|
|
|
|
enum SN_PacketFlags {
|
|
SN_PACKET_FLAG_TOPICIDTYPE_MASK = 0x3,
|
|
SN_PACKET_FLAG_CLEANSESSION = 0x4,
|
|
SN_PACKET_FLAG_WILL = 0x8,
|
|
SN_PACKET_FLAG_RETAIN = 0x10,
|
|
SN_PACKET_FLAG_QOS_MASK = 0x60,
|
|
SN_PACKET_FLAG_QOS_SHIFT = 0x5,
|
|
SN_PACKET_FLAG_DUPLICATE = 0x80
|
|
};
|
|
|
|
/* Message Header: Size is variable 2 - 4 bytes */
|
|
|
|
/* If the first byte of the packet len is 0x01, then the packet size is
|
|
greater than 0xFF and is stored in the next two bytes */
|
|
#define SN_PACKET_LEN_IND 0x01
|
|
|
|
#define SN_PACKET_MAX_SMALL_SIZE 0xFF
|
|
|
|
/* Gateway (GW) messages */
|
|
/* Advertise message */
|
|
typedef struct _SN_AdvertiseMsg {
|
|
MqttMsgStat stat;
|
|
|
|
byte gwId; /* ID of the gateway that sent this message */
|
|
word16 duration; /* Seconds until next Advertise
|
|
is broadcast by this gateway */
|
|
} SN_Advertise;
|
|
|
|
typedef struct _SN_GwInfo {
|
|
MqttMsgStat stat;
|
|
|
|
byte gwId; /* ID of the gateway that sent this message */
|
|
SN_GwAddr *gwAddr; /* Address of the indicated gateway */
|
|
} SN_GwInfo;
|
|
|
|
typedef struct _SN_SearchGw {
|
|
MqttMsgStat stat;
|
|
|
|
byte radius; /* Broadcast radius (in hops) */
|
|
SN_GwInfo gwInfo;
|
|
} SN_SearchGw;
|
|
|
|
/* Connect Protocol */
|
|
#define SN_PROTOCOL_ID_1 0x01
|
|
#define SN_PROTOCOL_ID SN_PROTOCOL_ID_1
|
|
|
|
#define SN_CLIENTID_MAX_LEN 23
|
|
|
|
/* Connect Ack message structure */
|
|
typedef struct _SN_ConnectAck {
|
|
MqttMsgStat stat;
|
|
|
|
byte return_code;
|
|
} SN_ConnectAck;
|
|
|
|
/* WILL TOPIC */
|
|
typedef struct _SN_WillTopicUpd {
|
|
MqttMsgStat stat;
|
|
|
|
byte flags;
|
|
char *willTopic; /* contains the Will topic name */
|
|
} SN_WillTopicUpd;
|
|
|
|
typedef struct _SN_WillMsgUpd {
|
|
MqttMsgStat stat;
|
|
|
|
char *willMsg;
|
|
} SN_WillMsgUpd;
|
|
|
|
typedef struct _SN_WillTopicResp {
|
|
MqttMsgStat stat;
|
|
|
|
byte return_code;
|
|
} SN_WillTopicResp;
|
|
|
|
typedef SN_WillTopicResp SN_WillMsgResp;
|
|
|
|
typedef struct _SN_Will {
|
|
MqttMsgStat stat;
|
|
|
|
byte qos;
|
|
byte retain;
|
|
const char *willTopic;
|
|
byte *willMsg;
|
|
word16 willMsgLen;
|
|
|
|
union {
|
|
SN_WillMsgResp msgResp;
|
|
SN_WillMsgUpd msgUpd;
|
|
SN_WillTopicResp topicResp;
|
|
SN_WillTopicUpd topicUpd;
|
|
};
|
|
} SN_Will;
|
|
|
|
/* Connect */
|
|
typedef struct _SN_Connect {
|
|
MqttMsgStat stat;
|
|
|
|
word16 keep_alive_sec;
|
|
byte clean_session;
|
|
const char *client_id;
|
|
|
|
/* Protocol version: 1=v1.2 (default) */
|
|
byte protocol_level;
|
|
|
|
/* Optional Last will and testament */
|
|
byte enable_lwt;
|
|
SN_Will will;
|
|
|
|
/* Ack data */
|
|
SN_ConnectAck ack;
|
|
} SN_Connect;
|
|
|
|
/* REGISTER protocol */
|
|
typedef struct _SN_RegAck {
|
|
MqttMsgStat stat;
|
|
|
|
word16 topicId;
|
|
word16 packet_id;
|
|
byte return_code;
|
|
} SN_RegAck;
|
|
|
|
typedef struct _SN_Register {
|
|
MqttMsgStat stat;
|
|
|
|
word16 topicId;
|
|
word16 packet_id;
|
|
const char *topicName;
|
|
SN_RegAck regack;
|
|
} SN_Register;
|
|
|
|
/* PUBLISH RESPONSE */
|
|
/* This is the response struct for PUBREC, PUBREL, and PUBCOMP */
|
|
/* If QoS = 0: No response */
|
|
/* If QoS = 1: Expect response packet with type = SN_MSG_TYPE_PUBACK */
|
|
/* If QoS = 2: Expect response packet with type = SN_MSG_TYPE_PUBREC */
|
|
/* Message ID required if QoS is 1 or 2 */
|
|
/* If QoS = 2: Send SN_MSG_TYPE_PUBREL with msgId to complete
|
|
QoS2 protocol exchange */
|
|
/* Expect response packet with type = SN_MSG_TYPE_PUBCOMP */
|
|
typedef struct _SN_PublishResp {
|
|
MqttMsgStat stat;
|
|
|
|
word16 packet_id;
|
|
word16 topicId; /* PUBACK Only */
|
|
byte return_code; /* PUBACK Only */
|
|
} SN_PublishResp;
|
|
|
|
/* PUBLISH protocol */
|
|
typedef struct _SN_Publish {
|
|
MqttMsgStat stat; /* must be first member at top */
|
|
|
|
/* BEGIN: THIS SECTION NEEDS TO MATCH MqttMessage */
|
|
word16 packet_id;
|
|
byte type;
|
|
MqttQoS qos;
|
|
byte retain;
|
|
byte duplicate;
|
|
byte topic_type;
|
|
byte return_code;
|
|
|
|
const char *topic_name; /* Pointer is valid only when
|
|
msg_new set in callback */
|
|
word16 topic_name_len;
|
|
word32 total_len; /* Payload total length */
|
|
byte *buffer; /* Payload buffer */
|
|
word32 buffer_len; /* Payload buffer length */
|
|
word32 buffer_pos; /* Payload buffer position */
|
|
|
|
/* Used internally for TX/RX buffers */
|
|
byte buffer_new; /* flag to indicate new message */
|
|
word32 intBuf_len; /* Buffer length */
|
|
word32 intBuf_pos; /* Buffer position */
|
|
|
|
void *ctx; /* user supplied context for publish callbacks */
|
|
/* END: THIS SECTION NEEDS TO MATCH MqttMessage */
|
|
|
|
SN_PublishResp resp;
|
|
} SN_Publish;
|
|
|
|
/* SUBSCRIBE ACK */
|
|
typedef struct _SN_SubAck {
|
|
MqttMsgStat stat;
|
|
|
|
byte flags;
|
|
word16 topicId;
|
|
word16 packet_id;
|
|
byte return_code;
|
|
} SN_SubAck;
|
|
|
|
/* SUBSCRIBE */
|
|
typedef struct _SN_Subscribe {
|
|
MqttMsgStat stat;
|
|
|
|
byte duplicate;
|
|
byte qos;
|
|
word16 packet_id;
|
|
byte topic_type;
|
|
/* 5.3.12 TopicName
|
|
The TopicName field has a variable length and contains an UTF8-encoded
|
|
string that specifies the topic name.*/
|
|
const char *topicNameId; /* Contains topic name, ID,
|
|
or short name as indicated in topic type */
|
|
SN_SubAck subAck;
|
|
} SN_Subscribe;
|
|
|
|
/* UNSUBSCRIBE RESPONSE ACK */
|
|
typedef struct _SN_UnsubscribeAck {
|
|
MqttMsgStat stat; /* must be first member at top */
|
|
|
|
word16 packet_id;
|
|
} SN_UnsubscribeAck;
|
|
|
|
/* UNSUBSCRIBE */
|
|
typedef struct _SN_Unsubscribe {
|
|
MqttMsgStat stat;
|
|
|
|
byte duplicate;
|
|
byte qos;
|
|
word16 packet_id;
|
|
byte topic_type;
|
|
/* 5.3.12 TopicName
|
|
The TopicName field has a variable length and contains an UTF8-encoded
|
|
string that specifies the topic name.*/
|
|
const char *topicNameId; /* Contains topic name, ID,
|
|
or short name as indicated in topic type */
|
|
SN_UnsubscribeAck ack;
|
|
} SN_Unsubscribe;
|
|
|
|
/* PING / PING RESPONSE */
|
|
typedef struct _SN_PingReq {
|
|
MqttMsgStat stat;
|
|
|
|
/* clientId is optional and is included by a “sleeping” client when it
|
|
goes to the “awake” state and is waiting for messages sent by the
|
|
server/gateway. */
|
|
char *clientId;
|
|
} SN_PingReq;
|
|
|
|
/* DISCONNECT */
|
|
typedef struct _SN_Disconnect {
|
|
MqttMsgStat stat;
|
|
|
|
/* sleepTmr is optional and is included by a “sleeping” client
|
|
that wants to go the “asleep” state. */
|
|
word16 sleepTmr;
|
|
} SN_Disconnect;
|
|
|
|
typedef union _SN_Object {
|
|
SN_Advertise advertise;
|
|
SN_GwInfo gwInfo;
|
|
SN_SearchGw searchGw;
|
|
|
|
SN_Will will;
|
|
SN_Connect connect;
|
|
SN_ConnectAck connectAck;
|
|
|
|
SN_Register reg;
|
|
SN_RegAck regAck;
|
|
|
|
SN_Publish publish;
|
|
SN_PublishResp publishResp;
|
|
|
|
SN_Subscribe sub;
|
|
SN_SubAck subAck;
|
|
SN_Unsubscribe unSub;
|
|
SN_UnsubscribeAck unSubAck;
|
|
|
|
SN_PingReq pingReq;
|
|
SN_Disconnect disconnect;
|
|
|
|
SN_WillMsgUpd willMsgUpd;
|
|
SN_WillMsgResp willMsgResp;
|
|
|
|
SN_WillTopicUpd willTopicUpd;
|
|
SN_WillTopicResp willTopicResp;
|
|
} SN_Object;
|
|
|
|
|
|
/* Forward Encapsulation */
|
|
// TODO
|
|
|
|
WOLFMQTT_LOCAL int SN_Decode_Header(byte *rx_buf, int rx_buf_len,
|
|
SN_MsgType *p_packet_type);
|
|
WOLFMQTT_LOCAL int SN_Decode_Advertise(byte *rx_buf, int rx_buf_len,
|
|
SN_Advertise *gw_info);
|
|
WOLFMQTT_LOCAL int SN_Encode_SearchGW(byte *tx_buf, int tx_buf_len, byte hops);
|
|
WOLFMQTT_LOCAL int SN_Decode_GWInfo(byte *rx_buf, int rx_buf_len,
|
|
SN_GwInfo *gw_info);
|
|
WOLFMQTT_LOCAL int SN_Encode_Connect(byte *tx_buf, int tx_buf_len,
|
|
SN_Connect *connect);
|
|
WOLFMQTT_LOCAL int SN_Decode_ConnectAck(byte *rx_buf, int rx_buf_len,
|
|
SN_ConnectAck *connect_ack);
|
|
WOLFMQTT_LOCAL int SN_Decode_WillTopicReq(byte *rx_buf, int rx_buf_len);
|
|
WOLFMQTT_LOCAL int SN_Encode_WillTopic(byte *tx_buf, int tx_buf_len,
|
|
SN_Will *willTopic);
|
|
WOLFMQTT_LOCAL int SN_Decode_WillMsgReq(byte *rx_buf, int rx_buf_len);
|
|
WOLFMQTT_LOCAL int SN_Encode_WillMsg(byte *tx_buf, int tx_buf_len,
|
|
SN_Will *willMsg);
|
|
WOLFMQTT_LOCAL int SN_Encode_WillTopicUpdate(byte *tx_buf, int tx_buf_len,
|
|
SN_Will *willTopic);
|
|
WOLFMQTT_LOCAL int SN_Decode_WillTopicResponse(byte *rx_buf, int rx_buf_len);
|
|
WOLFMQTT_LOCAL int SN_Encode_WillMsgUpdate(byte *tx_buf, int tx_buf_len,
|
|
SN_Will *willMsg);
|
|
WOLFMQTT_LOCAL int SN_Decode_WillMsgResponse(byte *rx_buf, int rx_buf_len);
|
|
WOLFMQTT_LOCAL int SN_Encode_Register(byte *tx_buf, int tx_buf_len,
|
|
SN_Register *regist);
|
|
WOLFMQTT_LOCAL int SN_Decode_RegAck(byte *rx_buf, int rx_buf_len,
|
|
SN_RegAck *regack);
|
|
WOLFMQTT_LOCAL int SN_Encode_Subscribe(byte *tx_buf, int tx_buf_len,
|
|
SN_Subscribe *subscribe);
|
|
WOLFMQTT_LOCAL int SN_Decode_SubscribeAck(byte *rx_buf, int rx_buf_len,
|
|
SN_SubAck *subscribe_ack);
|
|
WOLFMQTT_LOCAL int SN_Encode_Publish(byte *tx_buf, int tx_buf_len,
|
|
SN_Publish *publish);
|
|
WOLFMQTT_LOCAL int SN_Decode_Publish(byte *rx_buf, int rx_buf_len,
|
|
SN_Publish *publish);
|
|
WOLFMQTT_LOCAL int SN_Encode_PublishResp(byte *tx_buf, int tx_buf_len,
|
|
byte type, SN_PublishResp *publish_resp);
|
|
WOLFMQTT_LOCAL int SN_Decode_PublishResp(byte *rx_buf, int rx_buf_len,
|
|
byte type, SN_PublishResp *publish_resp);
|
|
WOLFMQTT_LOCAL int SN_Encode_Unsubscribe(byte *tx_buf, int tx_buf_len,
|
|
SN_Unsubscribe *unsubscribe);
|
|
WOLFMQTT_LOCAL int SN_Decode_UnsubscribeAck(byte *rx_buf, int rx_buf_len,
|
|
SN_UnsubscribeAck *unsubscribe_ack);
|
|
WOLFMQTT_LOCAL int SN_Encode_Disconnect(byte *tx_buf, int tx_buf_len,
|
|
SN_Disconnect *disconnect);
|
|
WOLFMQTT_LOCAL int SN_Encode_Ping(byte *tx_buf, int tx_buf_len,
|
|
SN_PingReq *ping);
|
|
WOLFMQTT_LOCAL int SN_Decode_Ping(byte *rx_buf, int rx_buf_len);
|
|
WOLFMQTT_LOCAL int SN_Packet_Read(struct _MqttClient *client, byte *rx_buf,
|
|
int rx_buf_len, int timeout_ms);
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
|
|
#endif /* WOLFMQTT_PACKET_H */
|
|
|