doubao_chat/include_lib/net/wolfmqtt/mqtt_packet.h

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 */