1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /** @file mqtt.h
8  *
9  * @defgroup mqtt_socket MQTT Client library
10  * @ingroup networking
11  * @{
12  * @brief MQTT Client Implementation
13  *
14  * @note The implementation assumes TCP module is enabled.
15  *
16  * @note By default the implementation uses MQTT version 3.1.1.
17  */
18 
19 #ifndef ZEPHYR_INCLUDE_NET_MQTT_H_
20 #define ZEPHYR_INCLUDE_NET_MQTT_H_
21 
22 #include <stddef.h>
23 
24 #include <zephyr/kernel.h>
25 #include <zephyr/types.h>
26 #include <zephyr/net/tls_credentials.h>
27 #include <zephyr/net/net_ip.h>
28 #include <zephyr/sys/mutex.h>
29 #include <zephyr/net/websocket.h>
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /**
36  * @brief MQTT Asynchronous Events notified to the application from the module
37  *        through the callback registered by the application.
38  */
39 enum mqtt_evt_type {
40 	/** Acknowledgment of connection request. Event result accompanying
41 	 *  the event indicates whether the connection failed or succeeded.
42 	 */
43 	MQTT_EVT_CONNACK,
44 
45 	/** Disconnection Event. MQTT Client Reference is no longer valid once
46 	 *  this event is received for the client.
47 	 */
48 	MQTT_EVT_DISCONNECT,
49 
50 	/** Publish event received when message is published on a topic client
51 	 *  is subscribed to.
52 	 *
53 	 * @note PUBLISH event structure only contains payload size, the payload
54 	 *       data parameter should be ignored. Payload content has to be
55 	 *       read manually with @ref mqtt_read_publish_payload function.
56 	 */
57 	MQTT_EVT_PUBLISH,
58 
59 	/** Acknowledgment for published message with QoS 1. */
60 	MQTT_EVT_PUBACK,
61 
62 	/** Reception confirmation for published message with QoS 2. */
63 	MQTT_EVT_PUBREC,
64 
65 	/** Release of published message with QoS 2. */
66 	MQTT_EVT_PUBREL,
67 
68 	/** Confirmation to a publish release message with QoS 2. */
69 	MQTT_EVT_PUBCOMP,
70 
71 	/** Acknowledgment to a subscribe request. */
72 	MQTT_EVT_SUBACK,
73 
74 	/** Acknowledgment to a unsubscribe request. */
75 	MQTT_EVT_UNSUBACK,
76 
77 	/** Ping Response from server. */
78 	MQTT_EVT_PINGRESP,
79 };
80 
81 /** @brief MQTT version protocol level. */
82 enum mqtt_version {
83 	MQTT_VERSION_3_1_0 = 3, /**< Protocol level for 3.1.0. */
84 	MQTT_VERSION_3_1_1 = 4  /**< Protocol level for 3.1.1. */
85 };
86 
87 /** @brief MQTT Quality of Service types. */
88 enum mqtt_qos {
89 	/** Lowest Quality of Service, no acknowledgment needed for published
90 	 *  message.
91 	 */
92 	MQTT_QOS_0_AT_MOST_ONCE = 0x00,
93 
94 	/** Medium Quality of Service, if acknowledgment expected for published
95 	 *  message, duplicate messages permitted.
96 	 */
97 	MQTT_QOS_1_AT_LEAST_ONCE = 0x01,
98 
99 	/** Highest Quality of Service, acknowledgment expected and message
100 	 *  shall be published only once. Message not published to interested
101 	 *  parties unless client issues a PUBREL.
102 	 */
103 	MQTT_QOS_2_EXACTLY_ONCE  = 0x02
104 };
105 
106 /** @brief MQTT CONNACK return codes. */
107 enum mqtt_conn_return_code {
108 	/** Connection accepted. */
109 	MQTT_CONNECTION_ACCEPTED                = 0x00,
110 
111 	/** The Server does not support the level of the MQTT protocol
112 	 * requested by the Client.
113 	 */
114 	MQTT_UNACCEPTABLE_PROTOCOL_VERSION      = 0x01,
115 
116 	/** The Client identifier is correct UTF-8 but not allowed by the
117 	 *  Server.
118 	 */
119 	MQTT_IDENTIFIER_REJECTED                = 0x02,
120 
121 	/** The Network Connection has been made but the MQTT service is
122 	 *  unavailable.
123 	 */
124 	MQTT_SERVER_UNAVAILABLE                 = 0x03,
125 
126 	/** The data in the user name or password is malformed. */
127 	MQTT_BAD_USER_NAME_OR_PASSWORD          = 0x04,
128 
129 	/** The Client is not authorized to connect. */
130 	MQTT_NOT_AUTHORIZED                     = 0x05
131 };
132 
133 /** @brief MQTT SUBACK return codes. */
134 enum mqtt_suback_return_code {
135 	/** Subscription with QoS 0 succeeded. */
136 	MQTT_SUBACK_SUCCESS_QoS_0 = 0x00,
137 
138 	/** Subscription with QoS 1 succeeded. */
139 	MQTT_SUBACK_SUCCESS_QoS_1 = 0x01,
140 
141 	/** Subscription with QoS 2 succeeded. */
142 	MQTT_SUBACK_SUCCESS_QoS_2 = 0x02,
143 
144 	/** Subscription for a topic failed. */
145 	MQTT_SUBACK_FAILURE = 0x80
146 };
147 
148 /** @brief Abstracts UTF-8 encoded strings. */
149 struct mqtt_utf8 {
150 	const uint8_t *utf8;       /**< Pointer to UTF-8 string. */
151 	uint32_t size;             /**< Size of UTF string, in bytes. */
152 };
153 
154 /**
155  * @brief Initialize UTF-8 encoded string from C literal string.
156  *
157  * Use it as follows:
158  *
159  * struct mqtt_utf8 password = MQTT_UTF8_LITERAL("my_pass");
160  *
161  * @param[in] literal Literal string from which to generate mqtt_utf8 object.
162  */
163 #define MQTT_UTF8_LITERAL(literal)				\
164 	((struct mqtt_utf8) {literal, sizeof(literal) - 1})
165 
166 /** @brief Abstracts binary strings. */
167 struct mqtt_binstr {
168 	uint8_t *data;             /**< Pointer to binary stream. */
169 	uint32_t len;              /**< Length of binary stream. */
170 };
171 
172 /** @brief Abstracts MQTT UTF-8 encoded topic that can be subscribed
173  *         to or published.
174  */
175 struct mqtt_topic {
176 	/** Topic on to be published or subscribed to. */
177 	struct mqtt_utf8 topic;
178 
179 	/** Quality of service requested for the subscription.
180 	 *  @ref mqtt_qos for details.
181 	 */
182 	uint8_t qos;
183 };
184 
185 /** @brief Parameters for a publish message. */
186 struct mqtt_publish_message {
187 	struct mqtt_topic topic;     /**< Topic on which data was published. */
188 	struct mqtt_binstr payload; /**< Payload on the topic published. */
189 };
190 
191 /** @brief Parameters for a connection acknowledgment (CONNACK). */
192 struct mqtt_connack_param {
193 	/** The Session Present flag enables a Client to establish whether
194 	 *  the Client and Server have a consistent view about whether there
195 	 *  is already stored Session state.
196 	 */
197 	uint8_t session_present_flag;
198 
199 	/** The appropriate non-zero Connect return code indicates if the Server
200 	 *  is unable to process a connection request for some reason.
201 	 */
202 	enum mqtt_conn_return_code return_code;
203 };
204 
205 /** @brief Parameters for MQTT publish acknowledgment (PUBACK). */
206 struct mqtt_puback_param {
207 	/** Message id of the PUBLISH message being acknowledged */
208 	uint16_t message_id;
209 };
210 
211 /** @brief Parameters for MQTT publish receive (PUBREC). */
212 struct mqtt_pubrec_param {
213 	/** Message id of the PUBLISH message being acknowledged */
214 	uint16_t message_id;
215 };
216 
217 /** @brief Parameters for MQTT publish release (PUBREL). */
218 struct mqtt_pubrel_param {
219 	/** Message id of the PUBREC message being acknowledged */
220 	uint16_t message_id;
221 };
222 
223 /** @brief Parameters for MQTT publish complete (PUBCOMP). */
224 struct mqtt_pubcomp_param {
225 	/** Message id of the PUBREL message being acknowledged */
226 	uint16_t message_id;
227 };
228 
229 /** @brief Parameters for MQTT subscription acknowledgment (SUBACK). */
230 struct mqtt_suback_param {
231 	/** Message id of the SUBSCRIBE message being acknowledged */
232 	uint16_t message_id;
233 	/** Return codes indicating maximum QoS level granted for each topic
234 	 *  in the subscription list.
235 	 */
236 	struct mqtt_binstr return_codes;
237 };
238 
239 /** @brief Parameters for MQTT unsubscribe acknowledgment (UNSUBACK). */
240 struct mqtt_unsuback_param {
241 	/** Message id of the UNSUBSCRIBE message being acknowledged */
242 	uint16_t message_id;
243 };
244 
245 /** @brief Parameters for a publish message (PUBLISH). */
246 struct mqtt_publish_param {
247 	/** Messages including topic, QoS and its payload (if any)
248 	 *  to be published.
249 	 */
250 	struct mqtt_publish_message message;
251 
252 	/** Message id used for the publish message. Redundant for QoS 0. */
253 	uint16_t message_id;
254 
255 	/** Duplicate flag. If 1, it indicates the message is being
256 	 *  retransmitted. Has no meaning with QoS 0.
257 	 */
258 	uint8_t dup_flag : 1;
259 
260 	/** Retain flag. If 1, the message shall be stored persistently
261 	 *  by the broker.
262 	 */
263 	uint8_t retain_flag : 1;
264 };
265 
266 /** @brief List of topics in a subscription request. */
267 struct mqtt_subscription_list {
268 	/** Array containing topics along with QoS for each. */
269 	struct mqtt_topic *list;
270 
271 	/** Number of topics in the subscription list */
272 	uint16_t list_count;
273 
274 	/** Message id used to identify subscription request. */
275 	uint16_t message_id;
276 };
277 
278 /**
279  * @brief Defines event parameters notified along with asynchronous events
280  *        to the application.
281  */
282 union mqtt_evt_param {
283 	/** Parameters accompanying MQTT_EVT_CONNACK event. */
284 	struct mqtt_connack_param connack;
285 
286 	/** Parameters accompanying MQTT_EVT_PUBLISH event.
287 	 *
288 	 * @note PUBLISH event structure only contains payload size, the payload
289 	 *       data parameter should be ignored. Payload content has to be
290 	 *       read manually with @ref mqtt_read_publish_payload function.
291 	 */
292 	struct mqtt_publish_param publish;
293 
294 	/** Parameters accompanying MQTT_EVT_PUBACK event. */
295 	struct mqtt_puback_param puback;
296 
297 	/** Parameters accompanying MQTT_EVT_PUBREC event. */
298 	struct mqtt_pubrec_param pubrec;
299 
300 	/** Parameters accompanying MQTT_EVT_PUBREL event. */
301 	struct mqtt_pubrel_param pubrel;
302 
303 	/** Parameters accompanying MQTT_EVT_PUBCOMP event. */
304 	struct mqtt_pubcomp_param pubcomp;
305 
306 	/** Parameters accompanying MQTT_EVT_SUBACK event. */
307 	struct mqtt_suback_param suback;
308 
309 	/** Parameters accompanying MQTT_EVT_UNSUBACK event. */
310 	struct mqtt_unsuback_param unsuback;
311 };
312 
313 /** @brief Defines MQTT asynchronous event notified to the application. */
314 struct mqtt_evt {
315 	/** Identifies the event. */
316 	enum mqtt_evt_type type;
317 
318 	/** Contains parameters (if any) accompanying the event. */
319 	union mqtt_evt_param param;
320 
321 	/** Event result. 0 or a negative error code (errno.h) indicating
322 	 *  reason of failure.
323 	 */
324 	int result;
325 };
326 
327 struct mqtt_client;
328 
329 /**
330  * @brief Asynchronous event notification callback registered by the
331  *        application.
332  *
333  * @param[in] client Identifies the client for which the event is notified.
334  * @param[in] evt Event description along with result and associated
335  *                parameters (if any).
336  */
337 typedef void (*mqtt_evt_cb_t)(struct mqtt_client *client,
338 			      const struct mqtt_evt *evt);
339 
340 /** @brief TLS configuration for secure MQTT transports. */
341 struct mqtt_sec_config {
342 	/** Indicates the preference for peer verification. */
343 	int peer_verify;
344 
345 	/** Indicates the number of entries in the cipher list. */
346 	uint32_t cipher_count;
347 
348 	/** Indicates the list of ciphers to be used for the session.
349 	 *  May be NULL to use the default ciphers.
350 	 */
351 	const int *cipher_list;
352 
353 	/** Indicates the number of entries in the sec tag list. */
354 	uint32_t sec_tag_count;
355 
356 	/** Indicates the list of security tags to be used for the session. */
357 	const sec_tag_t *sec_tag_list;
358 
359 	/** Peer hostname for ceritificate verification.
360 	 *  May be NULL to skip hostname verification.
361 	 */
362 	const char *hostname;
363 
364 	/** Indicates the preference for copying certificates to the heap. */
365 	int cert_nocopy;
366 };
367 
368 /** @brief MQTT transport type. */
369 enum mqtt_transport_type {
370 	/** Use non secure TCP transport for MQTT connection. */
371 	MQTT_TRANSPORT_NON_SECURE,
372 
373 #if defined(CONFIG_MQTT_LIB_TLS)
374 	/** Use secure TCP transport (TLS) for MQTT connection. */
375 	MQTT_TRANSPORT_SECURE,
376 #endif /* CONFIG_MQTT_LIB_TLS */
377 
378 #if defined(CONFIG_MQTT_LIB_WEBSOCKET)
379 	/** Use non secure Websocket transport for MQTT connection. */
380 	MQTT_TRANSPORT_NON_SECURE_WEBSOCKET,
381 #if defined(CONFIG_MQTT_LIB_TLS)
382 	/** Use secure Websocket transport (TLS) for MQTT connection. */
383 	MQTT_TRANSPORT_SECURE_WEBSOCKET,
384 #endif
385 #endif /* CONFIG_MQTT_LIB_WEBSOCKET */
386 #if defined(CONFIG_MQTT_LIB_CUSTOM_TRANSPORT)
387 	/** Use custom transport for MQTT connection. */
388 	MQTT_TRANSPORT_CUSTOM,
389 #endif /* CONFIG_MQTT_LIB_CUSTOM_TRANSPORT */
390 
391 	/** Shall not be used as a transport type.
392 	 *  Indicator of maximum transport types possible.
393 	 */
394 	MQTT_TRANSPORT_NUM
395 };
396 
397 /** @brief MQTT transport specific data. */
398 struct mqtt_transport {
399 	/** Transport type selection for client instance.
400 	 *  @ref mqtt_transport_type for possible values. MQTT_TRANSPORT_MAX
401 	 *  is not a valid type.
402 	 */
403 	enum mqtt_transport_type type;
404 
405 	union {
406 		/* TCP socket transport for MQTT */
407 		struct {
408 			/** Socket descriptor. */
409 			int sock;
410 		} tcp;
411 
412 #if defined(CONFIG_MQTT_LIB_TLS)
413 		/* TLS socket transport for MQTT */
414 		struct {
415 			/** Socket descriptor. */
416 			int sock;
417 
418 			/** TLS configuration. See @ref mqtt_sec_config for
419 			 *  details.
420 			 */
421 			struct mqtt_sec_config config;
422 		} tls;
423 #endif /* CONFIG_MQTT_LIB_TLS */
424 	};
425 
426 #if defined(CONFIG_MQTT_LIB_WEBSOCKET)
427 	/** Websocket transport for MQTT */
428 	struct {
429 		/** Websocket configuration. */
430 		struct websocket_request config;
431 
432 		/** Socket descriptor */
433 		int sock;
434 
435 		/** Websocket timeout, in milliseconds. */
436 		int32_t timeout;
437 	} websocket;
438 #endif
439 
440 #if defined(CONFIG_MQTT_LIB_CUSTOM_TRANSPORT)
441 	/** User defined data for custom transport for MQTT. */
442 	void *custom_transport_data;
443 #endif /* CONFIG_MQTT_LIB_CUSTOM_TRANSPORT */
444 
445 #if defined(CONFIG_SOCKS)
446 	struct {
447 		struct sockaddr addr;
448 		socklen_t addrlen;
449 	} proxy;
450 #endif
451 };
452 
453 /** @brief MQTT internal state. */
454 struct mqtt_internal {
455 	/** Internal. Mutex to protect access to the client instance. */
456 	struct sys_mutex mutex;
457 
458 	/** Internal. Wall clock value (in milliseconds) of the last activity
459 	 *  that occurred. Needed for periodic PING.
460 	 */
461 	uint32_t last_activity;
462 
463 	/** Internal. Client's state in the connection. */
464 	uint32_t state;
465 
466 	/** Internal.  Packet length read so far. */
467 	uint32_t rx_buf_datalen;
468 
469 	/** Internal. Remaining payload length to read. */
470 	uint32_t remaining_payload;
471 };
472 
473 /**
474  * @brief MQTT Client definition to maintain information relevant to the
475  *        client.
476  */
477 struct mqtt_client {
478 	/** MQTT client internal state. */
479 	struct mqtt_internal internal;
480 
481 	/** MQTT transport configuration and data. */
482 	struct mqtt_transport transport;
483 
484 	/** Unique client identification to be used for the connection. */
485 	struct mqtt_utf8 client_id;
486 
487 	/** Broker details, for example, address, port. Address type should
488 	 *  be compatible with transport used.
489 	 */
490 	const void *broker;
491 
492 	/** User name (if any) to be used for the connection. NULL indicates
493 	 *  no user name.
494 	 */
495 	struct mqtt_utf8 *user_name;
496 
497 	/** Password (if any) to be used for the connection. Note that if
498 	 *  password is provided, user name shall also be provided. NULL
499 	 *  indicates no password.
500 	 */
501 	struct mqtt_utf8 *password;
502 
503 	/** Will topic and QoS. Can be NULL. */
504 	struct mqtt_topic *will_topic;
505 
506 	/** Will message. Can be NULL. Non NULL value valid only if will topic
507 	 *  is not NULL.
508 	 */
509 	struct mqtt_utf8 *will_message;
510 
511 	/** Application callback registered with the module to get MQTT events.
512 	 */
513 	mqtt_evt_cb_t evt_cb;
514 
515 	/** Receive buffer used for MQTT packet reception in RX path. */
516 	uint8_t *rx_buf;
517 
518 	/** Size of receive buffer. */
519 	uint32_t rx_buf_size;
520 
521 	/** Transmit buffer used for creating MQTT packet in TX path. */
522 	uint8_t *tx_buf;
523 
524 	/** Size of transmit buffer. */
525 	uint32_t tx_buf_size;
526 
527 	/** Keepalive interval for this client in seconds.
528 	 *  Default is CONFIG_MQTT_KEEPALIVE.
529 	 */
530 	uint16_t keepalive;
531 
532 	/** MQTT protocol version. */
533 	uint8_t protocol_version;
534 
535 	/** Unanswered PINGREQ count on this connection. */
536 	int8_t unacked_ping;
537 
538 	/** Will retain flag, 1 if will message shall be retained persistently.
539 	 */
540 	uint8_t will_retain : 1;
541 
542 	/** Clean session flag indicating a fresh (1) or a retained session (0).
543 	 *  Default is CONFIG_MQTT_CLEAN_SESSION.
544 	 */
545 	uint8_t clean_session : 1;
546 };
547 
548 /**
549  * @brief Initializes the client instance.
550  *
551  * @param[in] client Client instance for which the procedure is requested.
552  *                   Shall not be NULL.
553  *
554  * @note Shall be called to initialize client structure, before setting any
555  *       client parameters and before connecting to broker.
556  */
557 void mqtt_client_init(struct mqtt_client *client);
558 
559 #if defined(CONFIG_SOCKS)
560 /*
561  * @brief Set proxy server details
562  *
563  * @param[in] client Client instance for which the procedure is requested,
564  *                   Shall not be NULL.
565  * @param[in] proxy_addr Proxy server address.
566  * @param[in] addrlen Proxy server address length.
567  *
568  * @return 0 or a negative error code (errno.h) indicating reason of failure.
569  *
570  * @note Must be called before calling mqtt_connect().
571  */
572 int mqtt_client_set_proxy(struct mqtt_client *client,
573 			  struct sockaddr *proxy_addr,
574 			  socklen_t addrlen);
575 #endif
576 
577 /**
578  * @brief API to request new MQTT client connection.
579  *
580  * @param[in] client Client instance for which the procedure is requested.
581  *                   Shall not be NULL.
582  *
583  * @note This memory is assumed to be resident until mqtt_disconnect is called.
584  * @note Any subsequent changes to parameters like broker address, user name,
585  *       device id, etc. have no effect once MQTT connection is established.
586  *
587  * @return 0 or a negative error code (errno.h) indicating reason of failure.
588  *
589  * @note Default protocol revision used for connection request is 3.1.1. Please
590  *       set client.protocol_version = MQTT_VERSION_3_1_0 to use protocol 3.1.0.
591  * @note
592  *       Please modify @kconfig{CONFIG_MQTT_KEEPALIVE} time to override default
593  *       of 1 minute.
594  */
595 int mqtt_connect(struct mqtt_client *client);
596 
597 /**
598  * @brief API to publish messages on topics.
599  *
600  * @param[in] client Client instance for which the procedure is requested.
601  *                   Shall not be NULL.
602  * @param[in] param Parameters to be used for the publish message.
603  *                  Shall not be NULL.
604  *
605  * @return 0 or a negative error code (errno.h) indicating reason of failure.
606  */
607 int mqtt_publish(struct mqtt_client *client,
608 		 const struct mqtt_publish_param *param);
609 
610 /**
611  * @brief API used by client to send acknowledgment on receiving QoS1 publish
612  *        message. Should be called on reception of @ref MQTT_EVT_PUBLISH with
613  *        QoS level @ref MQTT_QOS_1_AT_LEAST_ONCE.
614  *
615  * @param[in] client Client instance for which the procedure is requested.
616  *                   Shall not be NULL.
617  * @param[in] param Identifies message being acknowledged.
618  *
619  * @return 0 or a negative error code (errno.h) indicating reason of failure.
620  */
621 int mqtt_publish_qos1_ack(struct mqtt_client *client,
622 			  const struct mqtt_puback_param *param);
623 
624 /**
625  * @brief API used by client to send acknowledgment on receiving QoS2 publish
626  *        message. Should be called on reception of @ref MQTT_EVT_PUBLISH with
627  *        QoS level @ref MQTT_QOS_2_EXACTLY_ONCE.
628  *
629  * @param[in] client Identifies client instance for which the procedure is
630  *                   requested. Shall not be NULL.
631  * @param[in] param Identifies message being acknowledged.
632  *
633  * @return 0 or a negative error code (errno.h) indicating reason of failure.
634  */
635 int mqtt_publish_qos2_receive(struct mqtt_client *client,
636 			      const struct mqtt_pubrec_param *param);
637 
638 /**
639  * @brief API used by client to request release of QoS2 publish message.
640  *        Should be called on reception of @ref MQTT_EVT_PUBREC.
641  *
642  * @param[in] client Client instance for which the procedure is requested.
643  *                   Shall not be NULL.
644  * @param[in] param Identifies message being released.
645  *
646  * @return 0 or a negative error code (errno.h) indicating reason of failure.
647  */
648 int mqtt_publish_qos2_release(struct mqtt_client *client,
649 			      const struct mqtt_pubrel_param *param);
650 
651 /**
652  * @brief API used by client to send acknowledgment on receiving QoS2 publish
653  *        release message. Should be called on reception of
654  *        @ref MQTT_EVT_PUBREL.
655  *
656  * @param[in] client Identifies client instance for which the procedure is
657  *                   requested. Shall not be NULL.
658  * @param[in] param Identifies message being completed.
659  *
660  * @return 0 or a negative error code (errno.h) indicating reason of failure.
661  */
662 int mqtt_publish_qos2_complete(struct mqtt_client *client,
663 			       const struct mqtt_pubcomp_param *param);
664 
665 /**
666  * @brief API to request subscription of one or more topics on the connection.
667  *
668  * @param[in] client Identifies client instance for which the procedure
669  *                   is requested. Shall not be NULL.
670  * @param[in] param Subscription parameters. Shall not be NULL.
671  *
672  * @return 0 or a negative error code (errno.h) indicating reason of failure.
673  */
674 int mqtt_subscribe(struct mqtt_client *client,
675 		   const struct mqtt_subscription_list *param);
676 
677 /**
678  * @brief API to request unsubscription of one or more topics on the connection.
679  *
680  * @param[in] client Identifies client instance for which the procedure is
681  *                   requested. Shall not be NULL.
682  * @param[in] param Parameters describing topics being unsubscribed from.
683  *                  Shall not be NULL.
684  *
685  * @note QoS included in topic description is unused in this API.
686  *
687  * @return 0 or a negative error code (errno.h) indicating reason of failure.
688  */
689 int mqtt_unsubscribe(struct mqtt_client *client,
690 		     const struct mqtt_subscription_list *param);
691 
692 /**
693  * @brief API to send MQTT ping. The use of this API is optional, as the library
694  *        handles the connection keep-alive on it's own, see @ref mqtt_live.
695  *
696  * @param[in] client Identifies client instance for which procedure is
697  *                   requested.
698  *
699  * @return 0 or a negative error code (errno.h) indicating reason of failure.
700  */
701 int mqtt_ping(struct mqtt_client *client);
702 
703 /**
704  * @brief API to disconnect MQTT connection.
705  *
706  * @param[in] client Identifies client instance for which procedure is
707  *                   requested.
708  *
709  * @return 0 or a negative error code (errno.h) indicating reason of failure.
710  */
711 int mqtt_disconnect(struct mqtt_client *client);
712 
713 /**
714  * @brief API to abort MQTT connection. This will close the corresponding
715  *        transport without closing the connection gracefully at the MQTT level
716  *        (with disconnect message).
717  *
718  * @param[in] client Identifies client instance for which procedure is
719  *                   requested.
720  *
721  * @return 0 or a negative error code (errno.h) indicating reason of failure.
722  */
723 int mqtt_abort(struct mqtt_client *client);
724 
725 /**
726  * @brief This API should be called periodically for the client to be able
727  *        to keep the connection alive by sending Ping Requests if need be.
728  *
729  * @param[in] client Client instance for which the procedure is requested.
730  *                   Shall not be NULL.
731  *
732  * @note  Application shall ensure that the periodicity of calling this function
733  *        makes it possible to respect the Keep Alive time agreed with the
734  *        broker on connection. @ref mqtt_connect for details on Keep Alive
735  *        time.
736  *
737  * @return 0 or a negative error code (errno.h) indicating reason of failure.
738  */
739 int mqtt_live(struct mqtt_client *client);
740 
741 /**
742  * @brief Helper function to determine when next keep alive message should be
743  *        sent. Can be used for instance as a source for `poll` timeout.
744  *
745  * @param[in] client Client instance for which the procedure is requested.
746  *
747  * @return Time in milliseconds until next keep alive message is expected to
748  *         be sent. Function will return -1 if keep alive messages are
749  *         not enabled.
750  */
751 int mqtt_keepalive_time_left(const struct mqtt_client *client);
752 
753 /**
754  * @brief Receive an incoming MQTT packet. The registered callback will be
755  *        called with the packet content.
756  *
757  * @note In case of PUBLISH message, the payload has to be read separately with
758  *       @ref mqtt_read_publish_payload function. The size of the payload to
759  *       read is provided in the publish event structure.
760  *
761  * @note This is a non-blocking call.
762  *
763  * @param[in] client Client instance for which the procedure is requested.
764  *                   Shall not be NULL.
765  *
766  * @return 0 or a negative error code (errno.h) indicating reason of failure.
767  */
768 int mqtt_input(struct mqtt_client *client);
769 
770 /**
771  * @brief Read the payload of the received PUBLISH message. This function should
772  *        be called within the MQTT event handler, when MQTT PUBLISH message is
773  *        notified.
774  *
775  * @note This is a non-blocking call.
776  *
777  * @param[in] client Client instance for which the procedure is requested.
778  *                   Shall not be NULL.
779  * @param[out] buffer Buffer where payload should be stored.
780  * @param[in] length Length of the buffer, in bytes.
781  *
782  * @return Number of bytes read or a negative error code (errno.h) indicating
783  *         reason of failure.
784  */
785 int mqtt_read_publish_payload(struct mqtt_client *client, void *buffer,
786 			      size_t length);
787 
788 /**
789  * @brief Blocking version of @ref mqtt_read_publish_payload function.
790  *
791  * @param[in] client Client instance for which the procedure is requested.
792  *                   Shall not be NULL.
793  * @param[out] buffer Buffer where payload should be stored.
794  * @param[in] length Length of the buffer, in bytes.
795  *
796  * @return Number of bytes read or a negative error code (errno.h) indicating
797  *         reason of failure.
798  */
799 int mqtt_read_publish_payload_blocking(struct mqtt_client *client, void *buffer,
800 				       size_t length);
801 
802 /**
803  * @brief Blocking version of @ref mqtt_read_publish_payload function which
804  *        runs until the required number of bytes are read.
805  *
806  * @param[in] client Client instance for which the procedure is requested.
807  *                   Shall not be NULL.
808  * @param[out] buffer Buffer where payload should be stored.
809  * @param[in] length Number of bytes to read.
810  *
811  * @return 0 if success, otherwise a negative error code (errno.h) indicating
812  *         reason of failure.
813  */
814 int mqtt_readall_publish_payload(struct mqtt_client *client, uint8_t *buffer,
815 				 size_t length);
816 
817 #ifdef __cplusplus
818 }
819 #endif
820 
821 #endif /* ZEPHYR_INCLUDE_NET_MQTT_H_ */
822 
823 /**@}  */
824