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