1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /** @file mqtt_internal.h
8  *
9  * @brief Function and data structures internal to MQTT module.
10  */
11 
12 #ifndef MQTT_INTERNAL_H_
13 #define MQTT_INTERNAL_H_
14 
15 #include <stdint.h>
16 #include <string.h>
17 
18 #include <zephyr/net/mqtt.h>
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /**@brief Keep alive time for MQTT (in seconds). Sending of Ping Requests to
25  *        keep the connection alive are governed by this value.
26  */
27 #define MQTT_KEEPALIVE CONFIG_MQTT_KEEPALIVE
28 
29 /**@brief Clean session on every connect (1) or keep subscriptions and messages
30  *        between connects (0)
31  */
32 #define MQTT_CLEAN_SESSION (IS_ENABLED(CONFIG_MQTT_CLEAN_SESSION) ? 1U : 0U)
33 
34 /**@brief Minimum mandatory size of fixed header. */
35 #define MQTT_FIXED_HEADER_MIN_SIZE 2
36 
37 /**@brief Maximum size of the fixed header. Remaining length size is 4 in this
38  *        case.
39  */
40 #define MQTT_FIXED_HEADER_MAX_SIZE 5
41 
42 /**@brief MQTT Control Packet Types. */
43 #define MQTT_PKT_TYPE_CONNECT     0x10
44 #define MQTT_PKT_TYPE_CONNACK     0x20
45 #define MQTT_PKT_TYPE_PUBLISH     0x30
46 #define MQTT_PKT_TYPE_PUBACK      0x40
47 #define MQTT_PKT_TYPE_PUBREC      0x50
48 #define MQTT_PKT_TYPE_PUBREL      0x60
49 #define MQTT_PKT_TYPE_PUBCOMP     0x70
50 #define MQTT_PKT_TYPE_SUBSCRIBE   0x80
51 #define MQTT_PKT_TYPE_SUBACK      0x90
52 #define MQTT_PKT_TYPE_UNSUBSCRIBE 0xA0
53 #define MQTT_PKT_TYPE_UNSUBACK    0xB0
54 #define MQTT_PKT_TYPE_PINGREQ     0xC0
55 #define MQTT_PKT_TYPE_PINGRSP     0xD0
56 #define MQTT_PKT_TYPE_DISCONNECT  0xE0
57 
58 /**@brief Masks for MQTT header flags. */
59 #define MQTT_HEADER_DUP_MASK     0x08
60 #define MQTT_HEADER_QOS_MASK     0x06
61 #define MQTT_HEADER_RETAIN_MASK  0x01
62 
63 /**@brief Masks for MQTT header flags. */
64 #define MQTT_CONNECT_FLAG_CLEAN_SESSION   0x02
65 #define MQTT_CONNECT_FLAG_WILL_TOPIC      0x04
66 #define MQTT_CONNECT_FLAG_WILL_RETAIN     0x20
67 #define MQTT_CONNECT_FLAG_PASSWORD        0x40
68 #define MQTT_CONNECT_FLAG_USERNAME        0x80
69 
70 #define MQTT_CONNACK_FLAG_SESSION_PRESENT 0x01
71 
72 /**@brief Maximum payload size of MQTT packet. */
73 #define MQTT_MAX_PAYLOAD_SIZE 0x0FFFFFFF
74 
75 /**@brief Computes total size needed to pack a UTF8 string. */
76 #define GET_UT8STR_BUFFER_SIZE(STR) (sizeof(uint16_t) + (STR)->size)
77 
78 /**@brief Computes total size needed to pack a binary stream. */
79 #define GET_BINSTR_BUFFER_SIZE(STR) ((STR)->len)
80 
81 /**@brief Sets MQTT Client's state with one indicated in 'STATE'. */
82 #define MQTT_SET_STATE(CLIENT, STATE) ((CLIENT)->internal.state |= (STATE))
83 
84 /**@brief Sets MQTT Client's state exclusive to 'STATE'. */
85 #define MQTT_SET_STATE_EXCLUSIVE(CLIENT, STATE) \
86 					((CLIENT)->internal.state = (STATE))
87 
88 /**@brief Verifies if MQTT Client's state is set with one indicated in 'STATE'.
89  */
90 #define MQTT_HAS_STATE(CLIENT, STATE) ((CLIENT)->internal.state & (STATE))
91 
92 /**@brief Reset 'STATE' in MQTT Client's state. */
93 #define MQTT_RESET_STATE(CLIENT, STATE) ((CLIENT)->internal.state &= ~(STATE))
94 
95 /**@brief Initialize MQTT Client's state. */
96 #define MQTT_STATE_INIT(CLIENT) ((CLIENT)->internal.state = MQTT_STATE_IDLE)
97 
98 /**@brief Computes the first byte of MQTT message header based on message type,
99  *        duplication flag, QoS and  the retain flag.
100  */
101 #define MQTT_MESSAGES_OPTIONS(TYPE, DUP, QOS, RETAIN) \
102 	(((TYPE)      & 0xF0)  | \
103 	 (((DUP) << 3) & 0x08) | \
104 	 (((QOS) << 1) & 0x06) | \
105 	 ((RETAIN) & 0x01))
106 
107 #define MQTT_MAX_LENGTH_BYTES 4
108 #define MQTT_LENGTH_VALUE_MASK 0x7F
109 #define MQTT_LENGTH_CONTINUATION_BIT 0x80
110 #define MQTT_LENGTH_SHIFT 7
111 
112 /**@brief Check if the input pointer is NULL, if so it returns -EINVAL. */
113 #define NULL_PARAM_CHECK(param) \
114 	do { \
115 		if ((param) == NULL) { \
116 			return -EINVAL; \
117 		} \
118 	} while (false)
119 
120 #define NULL_PARAM_CHECK_VOID(param) \
121 	do { \
122 		if ((param) == NULL) { \
123 			return; \
124 		} \
125 	} while (false)
126 
127 /** Buffer context to iterate over buffer. */
128 struct buf_ctx {
129 	uint8_t *cur;
130 	uint8_t *end;
131 };
132 
133 /**@brief MQTT States. */
134 enum mqtt_state {
135 	/** Idle state, implying the client entry in the table is unused/free.
136 	 */
137 	MQTT_STATE_IDLE                 = 0x00000000,
138 
139 	/** TCP Connection has been requested, awaiting result of the request.
140 	 */
141 	MQTT_STATE_TCP_CONNECTING       = 0x00000001,
142 
143 	/** TCP Connection successfully established. */
144 	MQTT_STATE_TCP_CONNECTED        = 0x00000002,
145 
146 	/** MQTT Connection successful. */
147 	MQTT_STATE_CONNECTED            = 0x00000004,
148 };
149 
150 /**@brief Notify application about MQTT event.
151  *
152  * @param[in] client Identifies the client for which event occurred.
153  * @param[in] evt MQTT event.
154  */
155 void event_notify(struct mqtt_client *client, const struct mqtt_evt *evt);
156 
157 /**@brief Handles MQTT messages received from the peer.
158  *
159  * @param[in] client Identifies the client for which the data was received.
160 
161  * @return 0 if the procedure is successful, an error code otherwise.
162  */
163 int mqtt_handle_rx(struct mqtt_client *client);
164 
165 /**@brief Constructs/encodes Connect packet.
166  *
167  * @param[in] client Identifies the client for which the procedure is requested.
168  *                   All information required for creating the packet like
169  *                   client id, clean session flag, retain session flag etc are
170  *                   assumed to be populated for the client instance when this
171  *                   procedure is requested.
172  * @param[inout] buf_ctx Pointer to the buffer context structure,
173  *                       containing buffer for the encoded message.
174  *                       As output points to the beginning and end of
175  *                       the frame.
176  *
177  * @return 0 if the procedure is successful, an error code otherwise.
178  */
179 int connect_request_encode(const struct mqtt_client *client,
180 			   struct buf_ctx *buf);
181 
182 /**@brief Constructs/encodes Publish packet.
183  *
184  * @param[in] param Publish message parameters.
185  * @param[inout] buf_ctx Pointer to the buffer context structure,
186  *                       containing buffer for the encoded message.
187  *                       As output points to the beginning and end of
188  *                       the frame.
189  *
190  * @return 0 if the procedure is successful, an error code otherwise.
191  */
192 int publish_encode(const struct mqtt_publish_param *param, struct buf_ctx *buf);
193 
194 /**@brief Constructs/encodes Publish Ack packet.
195  *
196  * @param[in] param Publish Ack message parameters.
197  * @param[inout] buf_ctx Pointer to the buffer context structure,
198  *                       containing buffer for the encoded message.
199  *                       As output points to the beginning and end of
200  *                       the frame.
201  *
202  * @return 0 if the procedure is successful, an error code otherwise.
203  */
204 int publish_ack_encode(const struct mqtt_puback_param *param,
205 		       struct buf_ctx *buf);
206 
207 /**@brief Constructs/encodes Publish Receive packet.
208  *
209  * @param[in] param Publish Receive message parameters.
210  * @param[inout] buf_ctx Pointer to the buffer context structure,
211  *                       containing buffer for the encoded message.
212  *                       As output points to the beginning and end of
213  *                       the frame.
214  *
215  * @return 0 if the procedure is successful, an error code otherwise.
216  */
217 int publish_receive_encode(const struct mqtt_pubrec_param *param,
218 			   struct buf_ctx *buf);
219 
220 /**@brief Constructs/encodes Publish Release packet.
221  *
222  * @param[in] param Publish Release message parameters.
223  * @param[inout] buf_ctx Pointer to the buffer context structure,
224  *                       containing buffer for the encoded message.
225  *                       As output points to the beginning and end of
226  *                       the frame.
227  *
228  * @return 0 if the procedure is successful, an error code otherwise.
229  */
230 int publish_release_encode(const struct mqtt_pubrel_param *param,
231 			   struct buf_ctx *buf);
232 
233 /**@brief Constructs/encodes Publish Complete packet.
234  *
235  * @param[in] param Publish Complete message parameters.
236  * @param[inout] buf_ctx Pointer to the buffer context structure,
237  *                       containing buffer for the encoded message.
238  *                       As output points to the beginning and end of
239  *                       the frame.
240  *
241  * @return 0 if the procedure is successful, an error code otherwise.
242  */
243 int publish_complete_encode(const struct mqtt_pubcomp_param *param,
244 			    struct buf_ctx *buf);
245 
246 /**@brief Constructs/encodes Disconnect packet.
247  *
248  * @param[inout] buf_ctx Pointer to the buffer context structure,
249  *                       containing buffer for the encoded message.
250  *                       As output points to the beginning and end of
251  *                       the frame.
252  *
253  * @return 0 if the procedure is successful, an error code otherwise.
254  */
255 int disconnect_encode(struct buf_ctx *buf);
256 
257 /**@brief Constructs/encodes Subscribe packet.
258  *
259  * @param[in] param Subscribe message parameters.
260  * @param[inout] buf_ctx Pointer to the buffer context structure,
261  *                       containing buffer for the encoded message.
262  *                       As output points to the beginning and end of
263  *                       the frame.
264  *
265  * @return 0 if the procedure is successful, an error code otherwise.
266  */
267 int subscribe_encode(const struct mqtt_subscription_list *param,
268 		     struct buf_ctx *buf);
269 
270 /**@brief Constructs/encodes Unsubscribe packet.
271  *
272  * @param[in] param Unsubscribe message parameters.
273  * @param[inout] buf_ctx Pointer to the buffer context structure,
274  *                       containing buffer for the encoded message.
275  *                       As output points to the beginning and end of
276  *                       the frame.
277  *
278  * @return 0 if the procedure is successful, an error code otherwise.
279  */
280 int unsubscribe_encode(const struct mqtt_subscription_list *param,
281 		       struct buf_ctx *buf);
282 
283 /**@brief Constructs/encodes Ping Request packet.
284  *
285  * @param[inout] buf_ctx Pointer to the buffer context structure,
286  *                       containing buffer for the encoded message.
287  *                       As output points to the beginning and end of
288  *                       the frame.
289  *
290  * @return 0 if the procedure is successful, an error code otherwise.
291  */
292 int ping_request_encode(struct buf_ctx *buf);
293 
294 /**@brief Decode MQTT Packet Type and Length in the MQTT fixed header.
295  *
296  * @param[inout] buf A pointer to the buf_ctx structure containing current
297  *                   buffer position.
298  * @param[out] type_and_flags Message type and flags.
299  * @param[out] length Length of variable header and payload in the MQTT message.
300  *
301  * @return 0 if the procedure is successful, an error code otherwise.
302  */
303 int fixed_header_decode(struct buf_ctx *buf, uint8_t *type_and_flags,
304 			uint32_t *length);
305 
306 /**@brief Decode MQTT Connect Ack packet.
307  *
308  * @param[in] client MQTT client for which packet is decoded.
309  * @param[inout] buf A pointer to the buf_ctx structure containing current
310  *                   buffer position.
311  * @param[out] param Pointer to buffer for decoded Connect Ack parameters.
312  *
313  * @return 0 if the procedure is successful, an error code otherwise.
314  */
315 int connect_ack_decode(const struct mqtt_client *client, struct buf_ctx *buf,
316 		       struct mqtt_connack_param *param);
317 
318 /**@brief Decode MQTT Publish packet.
319  *
320  * @param[in] flags Byte containing message type and flags.
321  * @param[in] var_length Length of the variable part of the message.
322  * @param[inout] buf A pointer to the buf_ctx structure containing current
323  *                   buffer position.
324  * @param[out] param Pointer to buffer for decoded Publish parameters.
325  *
326  * @return 0 if the procedure is successful, an error code otherwise.
327  */
328 int publish_decode(uint8_t flags, uint32_t var_length, struct buf_ctx *buf,
329 		   struct mqtt_publish_param *param);
330 
331 /**@brief Decode MQTT Publish Ack packet.
332  *
333  * @param[inout] buf A pointer to the buf_ctx structure containing current
334  *                   buffer position.
335  * @param[out] param Pointer to buffer for decoded Publish Ack parameters.
336  *
337  * @return 0 if the procedure is successful, an error code otherwise.
338  */
339 int publish_ack_decode(struct buf_ctx *buf, struct mqtt_puback_param *param);
340 
341 /**@brief Decode MQTT Publish Receive packet.
342  *
343  * @param[inout] buf A pointer to the buf_ctx structure containing current
344  *                   buffer position.
345  * @param[out] param Pointer to buffer for decoded Publish Receive parameters.
346  *
347  * @return 0 if the procedure is successful, an error code otherwise.
348  */
349 int publish_receive_decode(struct buf_ctx *buf,
350 			   struct mqtt_pubrec_param *param);
351 
352 /**@brief Decode MQTT Publish Release packet.
353  *
354  * @param[inout] buf A pointer to the buf_ctx structure containing current
355  *                   buffer position.
356  * @param[out] param Pointer to buffer for decoded Publish Release parameters.
357  *
358  * @return 0 if the procedure is successful, an error code otherwise.
359  */
360 int publish_release_decode(struct buf_ctx *buf,
361 			   struct mqtt_pubrel_param *param);
362 
363 /**@brief Decode MQTT Publish Complete packet.
364  *
365  * @param[inout] buf A pointer to the buf_ctx structure containing current
366  *                   buffer position.
367  * @param[out] param Pointer to buffer for decoded Publish Complete parameters.
368  *
369  * @return 0 if the procedure is successful, an error code otherwise.
370  */
371 int publish_complete_decode(struct buf_ctx *buf,
372 			    struct mqtt_pubcomp_param *param);
373 
374 /**@brief Decode MQTT Subscribe packet.
375  *
376  * @param[inout] buf A pointer to the buf_ctx structure containing current
377  *                   buffer position.
378  * @param[out] param Pointer to buffer for decoded Subscribe parameters.
379  *
380  * @return 0 if the procedure is successful, an error code otherwise.
381  */
382 int subscribe_ack_decode(struct buf_ctx *buf,
383 			 struct mqtt_suback_param *param);
384 
385 /**@brief Decode MQTT Unsubscribe packet.
386  *
387  * @param[inout] buf A pointer to the buf_ctx structure containing current
388  *                   buffer position.
389  * @param[out] param Pointer to buffer for decoded Unsubscribe parameters.
390  *
391  * @return 0 if the procedure is successful, an error code otherwise.
392  */
393 int unsubscribe_ack_decode(struct buf_ctx *buf,
394 			   struct mqtt_unsuback_param *param);
395 
396 #ifdef __cplusplus
397 }
398 #endif
399 
400 #endif /* MQTT_INTERNAL_H_ */
401