cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

lws-mqtt.h (14168B)


      1/*
      2 * libwebsockets - protocol - mqtt
      3 *
      4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to
      8 * deal in the Software without restriction, including without limitation the
      9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     10 * sell copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     22 * IN THE SOFTWARE.
     23 *
     24 * included from libwebsockets.h
     25 */
     26
     27#ifndef _LWS_MQTT_H
     28#define _LWS_MQTT_H 1
     29
     30struct _lws_mqtt_related;
     31typedef struct _lws_mqtt_related lws_mqtt_related_t;
     32struct lws_mqtt_str_st;
     33typedef struct lws_mqtt_str_st lws_mqtt_str_t;
     34
     35#define MQTT_VER_3_1_1 4
     36
     37#define LWS_MQTT_FINAL_PART 1
     38
     39#define LWS_MQTT_MAX_AWSIOT_TOPICLEN  256
     40#define LWS_MQTT_MAX_TOPICLEN  65535
     41#define LWS_MQTT_MAX_CIDLEN    128
     42#define LWS_MQTT_RANDOM_CIDLEN 23 /* 3.1.3.1-5: Server MUST... between
     43				     1 and 23 chars... */
     44
     45#define LWS_MQTT_SHADOW_MAX_THING_LEN 128
     46#define LWS_MQTT_SHADOW_MAX_SHADOW_LEN 64
     47#define LWS_MQTT_SHADOW_UPDATE_STR "/update"
     48#define LWS_MQTT_SHADOW_DELETE_STR "/delete"
     49#define LWS_MQTT_SHADOW_GET_STR "/get"
     50#define LWS_MQTT_SHADOW_RESP_ACCEPTED_STR  "/accepted"
     51#define LWS_MQTT_SHADOW_RESP_REJECTED_STR "/rejected"
     52#define LWS_MQTT_SHADOW_RESP_DELTA_STR "/delta"
     53#define LWS_MQTT_SHADOW_RESP_DOCUMENT_STR "/documents"
     54#define LWS_MQTT_SHADOW_UPDATE_ACCEPTED_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR
     55#define LWS_MQTT_SHADOW_UPDATE_REJECTED_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR
     56#define LWS_MQTT_SHADOW_UPDATE_DELTA_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_DELTA_STR
     57#define LWS_MQTT_SHADOW_UPDATE_DOCUMENT_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_DOCUMENT_STR
     58#define LWS_MQTT_SHADOW_DELETE_ACCEPTED_STR LWS_MQTT_SHADOW_DELETE_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR
     59#define LWS_MQTT_SHADOW_DELETE_REJECTED_STR LWS_MQTT_SHADOW_DELETE_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR
     60#define LWS_MQTT_SHADOW_GET_ACCEPTED_STR LWS_MQTT_SHADOW_GET_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR
     61#define LWS_MQTT_SHADOW_GET_REJECTED_STR LWS_MQTT_SHADOW_GET_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR
     62#define LWS_MQTT_SHADOW_PREFIX_FORMAT "$aws/things/%s"
     63#define LWS_MQTT_SHADOW_NAMED_SHADOW_TOPIC_FORMAT LWS_MQTT_SHADOW_PREFIX_FORMAT "/shadow/name/%s%s"
     64#define LWS_MQTT_SHADOW_UNNAMED_SHADOW_TOPIC_FORMAT  LWS_MQTT_SHADOW_PREFIX_FORMAT "/shadow%s"
     65#define LWS_MQTT_SHADOW_UNNAMED_TOPIC_MATCH	"$aws/things/+/shadow/+"
     66#define LWS_MQTT_SHADOW_NAMED_TOPIC_MATCH	"$aws/things/+/shadow/name/+/+"
     67
     68typedef enum {
     69	QOS0,
     70	QOS1,
     71	QOS2,				/* not supported */
     72	RESERVED_QOS_LEVEL,
     73	FAILURE_QOS_LEVEL = 0x80
     74} lws_mqtt_qos_levels_t;
     75
     76typedef union {
     77	struct {
     78		uint8_t		retain:1;
     79		uint8_t 	qos:2;
     80		uint8_t 	dup:1;
     81		uint8_t 	ctrl_pkt_type:4;
     82	} flags;
     83	uint8_t 		bits;
     84} lws_mqtt_fixed_hdr_t;
     85
     86/*
     87 * MQTT connection parameters, passed into struct
     88 * lws_client_connect_info to establish a connection using
     89 * lws_client_connect_via_info().
     90*/
     91typedef struct lws_mqtt_client_connect_param_s {
     92	const char 			*client_id;	/* Client ID */
     93	uint16_t 			keep_alive;	/* MQTT keep alive
     94							   interval in
     95							   seconds */
     96	uint8_t 			clean_start:1;	/* MQTT clean
     97							   session */
     98	uint8_t				client_id_nofree:1;
     99	/**< do not free the client id */
    100	uint8_t				username_nofree:1;
    101	/**< do not free the username */
    102	uint8_t				password_nofree:1;
    103	/**< do not free the password */
    104	struct {
    105		const char 		*topic;
    106		const char 		*message;
    107		lws_mqtt_qos_levels_t	qos;
    108		uint8_t 		retain;
    109	} will_param;				/* MQTT LWT
    110						   parameters */
    111	struct {
    112		const char 		*topic;
    113		const char 		*message;
    114		lws_mqtt_qos_levels_t	qos;
    115		uint8_t 		retain;
    116	} birth_param;				/* MQTT Birth
    117						   parameters */
    118	const char 			*username;
    119	const char 			*password;
    120	uint8_t				aws_iot;
    121} lws_mqtt_client_connect_param_t;
    122
    123/*
    124 * MQTT publish parameters
    125*/
    126typedef struct lws_mqtt_publish_param_s {
    127	char			*topic;		/* Topic Name */
    128	uint16_t 		topic_len;
    129	const void 		*payload;	/* Publish Payload */
    130	uint32_t 		payload_len;	/* Size of the
    131						   complete payload */
    132	uint32_t		payload_pos;	/* where we are in payload */
    133	lws_mqtt_qos_levels_t 	qos;
    134
    135	/*--v-Following will be used by LWS-v--*/
    136	uint16_t 		packet_id;	/* Packet ID for QoS >
    137						   0 */
    138	uint8_t 		dup:1;		/* Retried PUBLISH,
    139						   for QoS > 0 */
    140	uint8_t			retain:1;	/* Retained message */
    141} lws_mqtt_publish_param_t;
    142
    143typedef struct topic_elem {
    144	const char		*name;		/* Topic Name */
    145	lws_mqtt_qos_levels_t 	qos;		/* Requested QoS */
    146
    147	/*--v-Following will be used by LWS-v--*/
    148	uint8_t 		acked;
    149} lws_mqtt_topic_elem_t;
    150
    151/*
    152 * MQTT publish parameters
    153*/
    154typedef struct lws_mqtt_subscribe_param_s {
    155	uint32_t		num_topics;	/* Number of topics */
    156	lws_mqtt_topic_elem_t	*topic;		/* Array of topic elements */
    157
    158	/*--v-Following will be used by LWS-v--*/
    159	uint16_t		packet_id;
    160} lws_mqtt_subscribe_param_t;
    161
    162typedef enum {
    163	LMQCP_RESERVED,
    164	LMQCP_CTOS_CONNECT,	/* Connection request */
    165	LMQCP_STOC_CONNACK,	/* Connection acknowledgment */
    166	LMQCP_PUBLISH,		/* Publish Message */
    167	LMQCP_PUBACK,		/* QoS 1:   Publish acknowledgment */
    168	LMQCP_PUBREC,		/* QoS 2.1: Publish received */
    169	LMQCP_PUBREL,		/* QoS 2.2: Publish release */
    170	LMQCP_PUBCOMP,		/* QoS 2.3: Publish complete */
    171	LMQCP_CTOS_SUBSCRIBE,	/* Subscribe request */
    172	LMQCP_STOC_SUBACK,	/* Subscribe acknowledgment */
    173	LMQCP_CTOS_UNSUBSCRIBE, /* Unsubscribe request */
    174	LMQCP_STOC_UNSUBACK,	/* Unsubscribe acknowledgment */
    175	LMQCP_CTOS_PINGREQ,	/* PING request */
    176	LMQCP_STOC_PINGRESP,	/* PONG response */
    177	LMQCP_DISCONNECT,	/* Disconnect notification */
    178	LMQCP_AUTH		/* Authentication exchange */
    179} lws_mqtt_control_packet_t;
    180
    181/* flags from byte 8 of C_TO_S CONNECT */
    182typedef enum {
    183	LMQCFT_USERNAME_NOFREE					= (1 << 10),
    184	LMQCFT_PASSWORD_NOFREE					= (1 << 9),
    185	LMQCFT_CLIENT_ID_NOFREE					= (1 << 8),
    186	/* only the low 8 are standardized and go out in the protocol */
    187	LMQCFT_USERNAME						= (1 << 7),
    188	LMQCFT_PASSWORD						= (1 << 6),
    189	LMQCFT_WILL_RETAIN					= (1 << 5),
    190	LMQCFT_WILL_QOS						= (1 << 3),
    191	LMQCFT_WILL_FLAG					= (1 << 2),
    192	LMQCFT_CLEAN_START					= (1 << 1),
    193	LMQCFT_RESERVED						= (1 << 0),
    194
    195	LMQCFT_WILL_QOS_MASK					= (3 << 3),
    196} lws_mqtt_connect_flags_t;
    197
    198/* flags for S_TO_C CONNACK */
    199typedef enum {
    200	LMQCFT_SESSION_PRESENT					= (1 << 0),
    201} lws_mqtt_connack_flags_t;
    202
    203typedef enum {
    204	LMQCP_REASON_SUCCESS					= 0x00,
    205	LMQCP_REASON_NORMAL_DISCONNECTION			= 0x00,
    206	LMQCP_REASON_GRANTED_QOS0				= 0x00,
    207	LMQCP_REASON_GRANTED_QOS1				= 0x01,
    208	LMQCP_REASON_GRANTED_QOS2				= 0x02,
    209	LMQCP_REASON_DISCONNECT_WILL				= 0x04,
    210	LMQCP_REASON_NO_MATCHING_SUBSCRIBER			= 0x10,
    211	LMQCP_REASON_NO_SUBSCRIPTION_EXISTED			= 0x11,
    212	LMQCP_REASON_CONTINUE_AUTHENTICATION			= 0x18,
    213	LMQCP_REASON_RE_AUTHENTICATE				= 0x19,
    214
    215	LMQCP_REASON_UNSPECIFIED_ERROR				= 0x80,
    216	LMQCP_REASON_MALFORMED_PACKET				= 0x81,
    217	LMQCP_REASON_PROTOCOL_ERROR				= 0x82,
    218	LMQCP_REASON_IMPLEMENTATION_SPECIFIC_ERROR		= 0x83,
    219
    220	/* Begin - Error codes for CONNACK */
    221	LMQCP_REASON_UNSUPPORTED_PROTOCOL			= 0x84,
    222	LMQCP_REASON_CLIENT_ID_INVALID				= 0x85,
    223	LMQCP_REASON_BAD_CREDENTIALS				= 0x86,
    224	LMQCP_REASON_NOT_AUTHORIZED				= 0x87,
    225	/* End - Error codes for CONNACK */
    226
    227	LMQCP_REASON_SERVER_UNAVAILABLE				= 0x88,
    228	LMQCP_REASON_SERVER_BUSY				= 0x89,
    229	LMQCP_REASON_BANNED					= 0x8a,
    230	LMQCP_REASON_SERVER_SHUTTING_DOWN			= 0x8b,
    231	LMQCP_REASON_BAD_AUTHENTICATION_METHOD			= 0x8c,
    232	LMQCP_REASON_KEEPALIVE_TIMEOUT				= 0x8d,
    233	LMQCP_REASON_SESSION_TAKEN_OVER				= 0x8e,
    234	LMQCP_REASON_TOPIC_FILTER_INVALID			= 0x8f,
    235	LMQCP_REASON_TOPIC_NAME_INVALID				= 0x90,
    236	LMQCP_REASON_PACKET_ID_IN_USE				= 0x91,
    237	LMQCP_REASON_PACKET_ID_NOT_FOUND			= 0x92,
    238	LMQCP_REASON_MAX_RX_EXCEEDED				= 0x93,
    239	LMQCP_REASON_TOPIC_ALIAS_INVALID			= 0x94,
    240	LMQCP_REASON_PACKET_TOO_LARGE				= 0x95,
    241	LMQCP_REASON_RATELIMIT					= 0x96,
    242	LMQCP_REASON_QUOTA_EXCEEDED				= 0x97,
    243	LMQCP_REASON_ADMINISTRATIVE_ACTION			= 0x98,
    244	LMQCP_REASON_PAYLOAD_FORMAT_INVALID			= 0x99,
    245	LMQCP_REASON_RETAIN_NOT_SUPPORTED			= 0x9a,
    246	LMQCP_REASON_QOS_NOT_SUPPORTED				= 0x9b,
    247	LMQCP_REASON_USE_ANOTHER_SERVER				= 0x9c,
    248	LMQCP_REASON_SERVER_MOVED				= 0x9d,
    249	LMQCP_REASON_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED		= 0x9e,
    250	LMQCP_REASON_CONNECTION_RATE_EXCEEDED			= 0x9f,
    251	LMQCP_REASON_MAXIMUM_CONNECT_TIME			= 0xa0,
    252	LMQCP_REASON_SUBSCRIPTION_IDS_NOT_SUPPORTED		= 0xa1,
    253	LMQCP_REASON_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED	= 0xa2,
    254} lws_mqtt_reason_t;
    255
    256typedef enum {
    257	LMQPROP_INVALID,
    258	LMQPROP_PAYLOAD_FORMAT_INDICATOR			= 0x01,
    259	LMQPROP_MESSAGE_EXPIRY_INTERVAL				= 0x02,
    260	LMQPROP_CONTENT_TYPE					= 0x03,
    261	LMQPROP_RESPONSE_TOPIC					= 0x08,
    262	LMQPROP_CORRELATION_DATA				= 0x09,
    263	LMQPROP_SUBSCRIPTION_IDENTIFIER				= 0x0b,
    264	LMQPROP_SESSION_EXPIRY_INTERVAL				= 0x11,
    265	LMQPROP_ASSIGNED_CLIENT_IDENTIFIER			= 0x12,
    266	LMQPROP_SERVER_KEEP_ALIVE				= 0x13,
    267	LMQPROP_AUTHENTICATION_METHOD				= 0x15,
    268	LMQPROP_AUTHENTICATION_DATA				= 0x16,
    269	LMQPROP_REQUEST_PROBLEM_INFORMATION			= 0x17,
    270	LMQPROP_WILL_DELAY_INTERVAL				= 0x18,
    271	LMQPROP_REQUEST_RESPONSE_INFORMATION			= 0x19,
    272	LMQPROP_RESPONSE_INFORMATION				= 0x1a,
    273	LMQPROP_SERVER_REFERENCE				= 0x1c,
    274	LMQPROP_REASON_STRING					= 0x1f,
    275	LMQPROP_RECEIVE_MAXIMUM					= 0x21,
    276	LMQPROP_TOPIC_ALIAS_MAXIMUM				= 0x22,
    277	LMQPROP_TOPIC_ALIAS					= 0x23,
    278	LMQPROP_MAXIMUM_QOS					= 0x24,
    279	LMQPROP_RETAIN_AVAILABLE				= 0x25,
    280	LMQPROP_USER_PROPERTY					= 0x26,
    281	LMQPROP_MAXIMUM_PACKET_SIZE				= 0x27,
    282	LMQPROP_WILDCARD_SUBSCRIPTION_AVAIL			= 0x28,
    283	LMQPROP_SUBSCRIPTION_IDENTIFIER_AVAIL			= 0x29,
    284	LMQPROP_SHARED_SUBSCRIPTION_AVAIL			= 0x2a
    285} lws_mqtt_property;
    286
    287int
    288lws_read_mqtt(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
    289
    290/* returns 0 if bd1 and bd2 are "the same", that includes empty, else nonzero */
    291LWS_VISIBLE LWS_EXTERN int
    292lws_mqtt_bindata_cmp(const lws_mqtt_str_t *bd1, const lws_mqtt_str_t *bd2);
    293
    294LWS_VISIBLE LWS_EXTERN void
    295lws_mqtt_str_init(lws_mqtt_str_t *s, uint8_t *buf, uint16_t lim, char nf);
    296
    297LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t *
    298lws_mqtt_str_create(uint16_t lim);
    299
    300LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t *
    301lws_mqtt_str_create_init(uint8_t *buf, uint16_t len, uint16_t lim);
    302
    303LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t *
    304lws_mqtt_str_create_cstr_dup(const char *buf, uint16_t lim);
    305
    306LWS_VISIBLE LWS_EXTERN uint8_t *
    307lws_mqtt_str_next(lws_mqtt_str_t *s, uint16_t *budget);
    308
    309LWS_VISIBLE LWS_EXTERN int
    310lws_mqtt_str_advance(lws_mqtt_str_t *s, int n);
    311
    312LWS_VISIBLE LWS_EXTERN void
    313lws_mqtt_str_free(lws_mqtt_str_t **s);
    314
    315
    316/**
    317 * lws_mqtt_client_send_publish() - lws_write a publish packet
    318 *
    319 * \param wsi: the mqtt child wsi
    320 * \param pub: additional information on what we're publishing
    321 * \param buf: payload to send
    322 * \param len: length of data in buf
    323 * \param final: flag indicating this is the last part
    324 *
    325 * Issues part of, or the whole of, a PUBLISH frame.  The first part of the
    326 * frame contains the header, and uses the .qos and .payload_len parts of \p pub
    327 * since MQTT requires the frame to specify the PUBLISH message length at the
    328 * start.  The \p len paramter may be less than \p pub.payload_len, in which
    329 * case subsequent calls with more payload are needed to complete the frame.
    330 *
    331 * Although the connection is stuck waiting for the remainder, in that it can't
    332 * issue any other frames until the current one is completed, lws returns to the
    333 * event loop normally and can continue the calls with additional payload even
    334 * for huge frames as the data becomes available, consistent with timeout needs
    335 * and latency to start any new frame (even, eg, related to ping / pong).
    336 *
    337 * If you're sending large frames, the OS will typically not allow the data to
    338 * be sent all at once to kernel side.  So you should ideally cut the payload
    339 * up into 1 or 2- mtu sized chunks and send that.
    340 *
    341 * Final should be set when you're calling with the last part of the payload.
    342 */
    343LWS_VISIBLE LWS_EXTERN int
    344lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub,
    345			     const void *buf, uint32_t len, int final);
    346
    347/**
    348 * lws_mqtt_client_send_subcribe() - lws_write a subscribe packet
    349 *
    350 * \param wsi: the mqtt child wsi
    351 * \param sub: which topic(s) we want to subscribe to
    352 *
    353 * For topics other child streams have not already subscribed to, send a packet
    354 * to the server asking to subscribe to them.  If all topics listed are already
    355 * subscribed to be the shared network connection, just trigger the
    356 * LWS_CALLBACK_MQTT_SUBSCRIBED callback as if a SUBACK had come.
    357 *
    358 * \p sub doesn't need to exist after the return from this function.
    359 */
    360LWS_VISIBLE LWS_EXTERN int
    361lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub);
    362
    363/**
    364 * lws_mqtt_client_send_unsubcribe() - lws_write a unsubscribe packet
    365 *
    366 * \param wsi: the mqtt child wsi
    367 * \param sub: which topic(s) we want to unsubscribe from
    368 *
    369 * For topics other child streams are not subscribed to, send a packet
    370 * to the server asking to unsubscribe from them.  If all topics
    371 * listed are already subscribed by other child streams on the shared
    372 * network connection, just trigger the LWS_CALLBACK_MQTT_UNSUBSCRIBED
    373 * callback as if a UNSUBACK had come.
    374 *
    375 * \p unsub doesn't need to exist after the return from this function.
    376 */
    377LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
    378lws_mqtt_client_send_unsubcribe(struct lws *wsi,
    379				const lws_mqtt_subscribe_param_t *unsub);
    380
    381#endif /* _LWS_MQTT_H */