2 * Amazon FreeRTOS MQTT V2.0.0
\r
3 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
27 * @file iot_mqtt_internal.h
\r
28 * @brief Internal header of MQTT library. This header should not be included in
\r
29 * typical application code.
\r
32 #ifndef IOT_MQTT_INTERNAL_H_
\r
33 #define IOT_MQTT_INTERNAL_H_
\r
35 /* The config header is always included first. */
\r
36 #include "iot_config.h"
\r
38 /* Linear containers (lists and queues) include. */
\r
39 #include "iot_linear_containers.h"
\r
42 #include "iot_mqtt.h"
\r
44 /* Task pool include. */
\r
45 #include "iot_taskpool.h"
\r
48 * @def IotMqtt_Assert( expression )
\r
49 * @brief Assertion macro for the MQTT library.
\r
51 * Set @ref IOT_MQTT_ENABLE_ASSERTS to `1` to enable assertions in the MQTT
\r
54 * @param[in] expression Expression to be evaluated.
\r
56 #if IOT_MQTT_ENABLE_ASSERTS == 1
\r
57 #ifndef IotMqtt_Assert
\r
59 #define IotMqtt_Assert( expression ) assert( expression )
\r
62 #define IotMqtt_Assert( expression )
\r
65 /* Configure logs for MQTT functions. */
\r
66 #ifdef IOT_LOG_LEVEL_MQTT
\r
67 #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_MQTT
\r
69 #ifdef IOT_LOG_LEVEL_GLOBAL
\r
70 #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
\r
72 #define LIBRARY_LOG_LEVEL IOT_LOG_NONE
\r
76 #define LIBRARY_LOG_NAME ( "MQTT" )
\r
77 #include "iot_logging_setup.h"
\r
80 * Provide default values for undefined memory allocation functions based on
\r
81 * the usage of dynamic memory allocation.
\r
83 #if IOT_STATIC_MEMORY_ONLY == 1
\r
84 #include "private/iot_static_memory.h"
\r
87 * @brief Allocate an #_mqttConnection_t. This function should have the same
\r
88 * signature as [malloc]
\r
89 * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html).
\r
91 void * IotMqtt_MallocConnection( size_t size );
\r
94 * @brief Free an #_mqttConnection_t. This function should have the same
\r
95 * signature as [free]
\r
96 * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html).
\r
98 void IotMqtt_FreeConnection( void * ptr );
\r
101 * @brief Allocate memory for an MQTT packet. This function should have the
\r
102 * same signature as [malloc]
\r
103 * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html).
\r
105 #define IotMqtt_MallocMessage Iot_MallocMessageBuffer
\r
108 * @brief Free an MQTT packet. This function should have the same signature
\r
110 * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html).
\r
112 #define IotMqtt_FreeMessage Iot_FreeMessageBuffer
\r
115 * @brief Allocate an #_mqttOperation_t. This function should have the same
\r
116 * signature as [malloc]
\r
117 * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html).
\r
119 void * IotMqtt_MallocOperation( size_t size );
\r
122 * @brief Free an #_mqttOperation_t. This function should have the same
\r
123 * signature as [free]
\r
124 * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html).
\r
126 void IotMqtt_FreeOperation( void * ptr );
\r
129 * @brief Allocate an #_mqttSubscription_t. This function should have the
\r
130 * same signature as [malloc]
\r
131 * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html).
\r
133 void * IotMqtt_MallocSubscription( size_t size );
\r
136 * @brief Free an #_mqttSubscription_t. This function should have the same
\r
137 * signature as [free]
\r
138 * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html).
\r
140 void IotMqtt_FreeSubscription( void * ptr );
\r
141 #else /* if IOT_STATIC_MEMORY_ONLY == 1 */
\r
142 #include <stdlib.h>
\r
144 #ifndef IotMqtt_MallocConnection
\r
145 #define IotMqtt_MallocConnection malloc
\r
148 #ifndef IotMqtt_FreeConnection
\r
149 #define IotMqtt_FreeConnection free
\r
152 #ifndef IotMqtt_MallocMessage
\r
153 #define IotMqtt_MallocMessage malloc
\r
156 #ifndef IotMqtt_FreeMessage
\r
157 #define IotMqtt_FreeMessage free
\r
160 #ifndef IotMqtt_MallocOperation
\r
161 #define IotMqtt_MallocOperation malloc
\r
164 #ifndef IotMqtt_FreeOperation
\r
165 #define IotMqtt_FreeOperation free
\r
168 #ifndef IotMqtt_MallocSubscription
\r
169 #define IotMqtt_MallocSubscription malloc
\r
172 #ifndef IotMqtt_FreeSubscription
\r
173 #define IotMqtt_FreeSubscription free
\r
175 #endif /* if IOT_STATIC_MEMORY_ONLY == 1 */
\r
178 * @cond DOXYGEN_IGNORE
\r
179 * Doxygen should ignore this section.
\r
181 * Provide default values for undefined configuration constants.
\r
183 #ifndef AWS_IOT_MQTT_ENABLE_METRICS
\r
184 #define AWS_IOT_MQTT_ENABLE_METRICS ( 1 )
\r
186 #ifndef IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES
\r
187 #define IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES ( 0 )
\r
189 #ifndef IOT_MQTT_RESPONSE_WAIT_MS
\r
190 #define IOT_MQTT_RESPONSE_WAIT_MS ( 1000 )
\r
192 #ifndef IOT_MQTT_RETRY_MS_CEILING
\r
193 #define IOT_MQTT_RETRY_MS_CEILING ( 60000 )
\r
198 * @brief Marks the empty statement of an `else` branch.
\r
200 * Does nothing, but allows test coverage to detect branches not taken. By default,
\r
201 * this is defined to nothing. When running code coverage testing, this is defined
\r
202 * to an assembly NOP.
\r
204 #ifndef EMPTY_ELSE_MARKER
\r
205 #define EMPTY_ELSE_MARKER
\r
209 * Constants related to limits defined in AWS Service Limits.
\r
212 * https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html
\r
214 * Used to validate parameters if when connecting to an AWS IoT MQTT server.
\r
216 #define AWS_IOT_MQTT_SERVER_MIN_KEEPALIVE ( 30 ) /**< @brief Minumum keep-alive interval accepted by AWS IoT. */
\r
217 #define AWS_IOT_MQTT_SERVER_MAX_KEEPALIVE ( 1200 ) /**< @brief Maximum keep-alive interval accepted by AWS IoT. */
\r
218 #define AWS_IOT_MQTT_SERVER_MAX_CLIENTID ( 128 ) /**< @brief Maximum length of client identifier accepted by AWS IoT. */
\r
219 #define AWS_IOT_MQTT_SERVER_MAX_TOPIC_LENGTH ( 256 ) /**< @brief Maximum length of topic names or filters accepted by AWS IoT. */
\r
220 #define AWS_IOT_MQTT_SERVER_MAX_TOPIC_FILTERS_PER_SUBSCRIBE ( 8 ) /**< @brief Maximum number of topic filters in a single SUBSCRIBE packet. */
\r
223 * MQTT control packet type and flags. Always the first byte of an MQTT
\r
227 * http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/csprd02/mqtt-v3.1.1-csprd02.html#_Toc385349757
\r
229 #define MQTT_PACKET_TYPE_CONNECT ( ( uint8_t ) 0x10U ) /**< @brief CONNECT (client-to-server). */
\r
230 #define MQTT_PACKET_TYPE_CONNACK ( ( uint8_t ) 0x20U ) /**< @brief CONNACK (server-to-client). */
\r
231 #define MQTT_PACKET_TYPE_PUBLISH ( ( uint8_t ) 0x30U ) /**< @brief PUBLISH (bi-directional). */
\r
232 #define MQTT_PACKET_TYPE_PUBACK ( ( uint8_t ) 0x40U ) /**< @brief PUBACK (server-to-client). */
\r
233 #define MQTT_PACKET_TYPE_SUBSCRIBE ( ( uint8_t ) 0x82U ) /**< @brief SUBSCRIBE (client-to-server). */
\r
234 #define MQTT_PACKET_TYPE_SUBACK ( ( uint8_t ) 0x90U ) /**< @brief SUBACK (server-to-client). */
\r
235 #define MQTT_PACKET_TYPE_UNSUBSCRIBE ( ( uint8_t ) 0xa2U ) /**< @brief UNSUBSCRIBE (client-to-server). */
\r
236 #define MQTT_PACKET_TYPE_UNSUBACK ( ( uint8_t ) 0xb0U ) /**< @brief UNSUBACK (server-to-client). */
\r
237 #define MQTT_PACKET_TYPE_PINGREQ ( ( uint8_t ) 0xc0U ) /**< @brief PINGREQ (client-to-server). */
\r
238 #define MQTT_PACKET_TYPE_PINGRESP ( ( uint8_t ) 0xd0U ) /**< @brief PINGRESP (server-to-client). */
\r
239 #define MQTT_PACKET_TYPE_DISCONNECT ( ( uint8_t ) 0xe0U ) /**< @brief DISCONNECT (client-to-server). */
\r
242 * @brief A value that represents an invalid remaining length.
\r
244 * This value is greater than what is allowed by the MQTT specification.
\r
246 #define MQTT_REMAINING_LENGTH_INVALID ( ( size_t ) 268435456 )
\r
248 /*---------------------- MQTT internal data structures ----------------------*/
\r
251 * @brief Represents an MQTT connection.
\r
253 typedef struct _mqttConnection
\r
255 bool awsIotMqttMode; /**< @brief Specifies if this connection is to an AWS IoT MQTT server. */
\r
256 bool ownNetworkConnection; /**< @brief Whether this MQTT connection owns its network connection. */
\r
257 void * pNetworkConnection; /**< @brief References the transport-layer network connection. */
\r
258 const IotNetworkInterface_t * pNetworkInterface; /**< @brief Network interface provided to @ref mqtt_function_connect. */
\r
259 IotMqttCallbackInfo_t disconnectCallback; /**< @brief A function to invoke when this connection is disconnected. */
\r
261 #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1
\r
262 const IotMqttSerializer_t * pSerializer; /**< @brief MQTT packet serializer overrides. */
\r
265 bool disconnected; /**< @brief Tracks if this connection has been disconnected. */
\r
266 IotMutex_t referencesMutex; /**< @brief Recursive mutex. Grants access to connection state and operation lists. */
\r
267 int32_t references; /**< @brief Counts callbacks and operations using this connection. */
\r
268 IotListDouble_t pendingProcessing; /**< @brief List of operations waiting to be processed by a task pool routine. */
\r
269 IotListDouble_t pendingResponse; /**< @brief List of processed operations awaiting a server response. */
\r
271 IotListDouble_t subscriptionList; /**< @brief Holds subscriptions associated with this connection. */
\r
272 IotMutex_t subscriptionMutex; /**< @brief Grants exclusive access to the subscription list. */
\r
274 bool keepAliveFailure; /**< @brief Failure flag for keep-alive operation. */
\r
275 uint32_t keepAliveMs; /**< @brief Keep-alive interval in milliseconds. Its max value (per spec) is 65,535,000. */
\r
276 uint32_t nextKeepAliveMs; /**< @brief Relative delay for next keep-alive job. */
\r
277 IotTaskPoolJobStorage_t keepAliveJobStorage; /**< @brief Task pool job for processing this connection's keep-alive. */
\r
278 IotTaskPoolJob_t keepAliveJob; /**< @brief Task pool job for processing this connection's keep-alive. */
\r
279 uint8_t * pPingreqPacket; /**< @brief An MQTT PINGREQ packet, allocated if keep-alive is active. */
\r
280 size_t pingreqPacketSize; /**< @brief The size of an allocated PINGREQ packet. */
\r
281 } _mqttConnection_t;
\r
284 * @brief Represents a subscription stored in an MQTT connection.
\r
286 typedef struct _mqttSubscription
\r
288 IotLink_t link; /**< @brief List link member. */
\r
290 int32_t references; /**< @brief How many subscription callbacks are using this subscription. */
\r
293 * @brief Tracks whether @ref mqtt_function_unsubscribe has been called for
\r
294 * this subscription.
\r
296 * If there are active subscription callbacks, @ref mqtt_function_unsubscribe
\r
297 * cannot remove this subscription. Instead, it will set this flag, which
\r
298 * schedules the removal of this subscription once all subscription callbacks
\r
305 uint16_t identifier; /**< @brief Packet identifier. */
\r
306 size_t order; /**< @brief Order in the packet's list of subscriptions. */
\r
307 } packetInfo; /**< @brief Information about the SUBSCRIBE packet that registered this subscription. */
\r
309 IotMqttCallbackInfo_t callback; /**< @brief Callback information for this subscription. */
\r
311 uint16_t topicFilterLength; /**< @brief Length of #_mqttSubscription_t.pTopicFilter. */
\r
312 char pTopicFilter[]; /**< @brief The subscription topic filter. */
\r
313 } _mqttSubscription_t;
\r
316 * @brief Internal structure representing a single MQTT operation, such as
\r
317 * CONNECT, SUBSCRIBE, PUBLISH, etc.
\r
319 * Queues of these structures keeps track of all in-progress MQTT operations.
\r
321 typedef struct _mqttOperation
\r
323 /* Pointers to neighboring queue elements. */
\r
324 IotLink_t link; /**< @brief List link member. */
\r
326 bool incomingPublish; /**< @brief Set to true if this operation an incoming PUBLISH. */
\r
327 _mqttConnection_t * pMqttConnection; /**< @brief MQTT connection associated with this operation. */
\r
329 IotTaskPoolJobStorage_t jobStorage; /**< @brief Task pool job storage associated with this operation. */
\r
330 IotTaskPoolJob_t job; /**< @brief Task pool job associated with this operation. */
\r
334 /* If incomingPublish is false, this struct is valid. */
\r
337 /* Basic operation information. */
\r
338 int32_t jobReference; /**< @brief Tracks if a job is using this operation. Must always be 0, 1, or 2. */
\r
339 IotMqttOperationType_t type; /**< @brief What operation this structure represents. */
\r
340 uint32_t flags; /**< @brief Flags passed to the function that created this operation. */
\r
341 uint16_t packetIdentifier; /**< @brief The packet identifier used with this operation. */
\r
343 /* Serialized packet and size. */
\r
344 uint8_t * pMqttPacket; /**< @brief The MQTT packet to send over the network. */
\r
345 uint8_t * pPacketIdentifierHigh; /**< @brief The location of the high byte of the packet identifier in the MQTT packet. */
\r
346 size_t packetSize; /**< @brief Size of `pMqttPacket`. */
\r
348 /* How to notify of an operation's completion. */
\r
351 IotSemaphore_t waitSemaphore; /**< @brief Semaphore to be used with @ref mqtt_function_wait. */
\r
352 IotMqttCallbackInfo_t callback; /**< @brief User-provided callback function and parameter. */
\r
353 } notify; /**< @brief How to notify of this operation's completion. */
\r
354 IotMqttError_t status; /**< @brief Result of this operation. This is reported once a response is received. */
\r
360 uint32_t nextPeriod;
\r
364 /* If incomingPublish is true, this struct is valid. */
\r
367 IotMqttPublishInfo_t publishInfo; /**< @brief Deserialized PUBLISH. */
\r
368 const void * pReceivedData; /**< @brief Any buffer associated with this PUBLISH that should be freed. */
\r
370 } u; /**< @brief Valid member depends on _mqttOperation_t.incomingPublish. */
\r
371 } _mqttOperation_t;
\r
374 * @brief Represents an MQTT packet received from the network.
\r
376 * This struct is used to hold parameters for the deserializers so that all
\r
377 * deserializers have the same function signature.
\r
379 typedef struct _mqttPacket
\r
384 * @brief (Input) MQTT connection associated with this packet. Only used
\r
385 * when deserializing SUBACKs.
\r
387 _mqttConnection_t * pMqttConnection;
\r
390 * @brief (Output) Operation representing an incoming PUBLISH. Only used
\r
391 * when deserializing PUBLISHes.
\r
393 _mqttOperation_t * pIncomingPublish;
\r
394 } u; /**< @brief Valid member depends on packet being decoded. */
\r
396 uint8_t * pRemainingData; /**< @brief (Input) The remaining data in MQTT packet. */
\r
397 size_t remainingLength; /**< @brief (Input) Length of the remaining data in the MQTT packet. */
\r
398 uint16_t packetIdentifier; /**< @brief (Output) MQTT packet identifier. */
\r
399 uint8_t type; /**< @brief (Input) A value identifying the packet type. */
\r
402 /*-------------------- MQTT struct validation functions ---------------------*/
\r
405 * @brief Check that an #IotMqttConnectInfo_t is valid.
\r
407 * @param[in] pConnectInfo The #IotMqttConnectInfo_t to validate.
\r
409 * @return `true` if `pConnectInfo` is valid; `false` otherwise.
\r
411 bool _IotMqtt_ValidateConnect( const IotMqttConnectInfo_t * pConnectInfo );
\r
414 * @brief Check that an #IotMqttPublishInfo_t is valid.
\r
416 * @param[in] awsIotMqttMode Specifies if this PUBLISH packet is being sent to
\r
417 * an AWS IoT MQTT server.
\r
418 * @param[in] pPublishInfo The #IotMqttPublishInfo_t to validate.
\r
420 * @return `true` if `pPublishInfo` is valid; `false` otherwise.
\r
422 bool _IotMqtt_ValidatePublish( bool awsIotMqttMode,
\r
423 const IotMqttPublishInfo_t * pPublishInfo );
\r
426 * @brief Check that an #IotMqttOperation_t is valid and waitable.
\r
428 * @param[in] operation The #IotMqttOperation_t to validate.
\r
430 * @return `true` if `operation` is valid; `false` otherwise.
\r
432 bool _IotMqtt_ValidateOperation( IotMqttOperation_t operation );
\r
435 * @brief Check that a list of #IotMqttSubscription_t is valid.
\r
437 * @param[in] operation Either #IOT_MQTT_SUBSCRIBE or #IOT_MQTT_UNSUBSCRIBE.
\r
438 * Some parameters are not validated for #IOT_MQTT_UNSUBSCRIBE.
\r
439 * @param[in] awsIotMqttMode Specifies if this SUBSCRIBE packet is being sent to
\r
440 * an AWS IoT MQTT server.
\r
441 * @param[in] pListStart First element of the list to validate.
\r
442 * @param[in] listSize Number of elements in the subscription list.
\r
444 * @return `true` if every element in the list is valid; `false` otherwise.
\r
446 bool _IotMqtt_ValidateSubscriptionList( IotMqttOperationType_t operation,
\r
447 bool awsIotMqttMode,
\r
448 const IotMqttSubscription_t * pListStart,
\r
451 /*-------------------- MQTT packet serializer functions ---------------------*/
\r
454 * @brief Get the MQTT packet type from a stream of bytes off the network.
\r
456 * @param[in] pNetworkConnection Reference to the network connection.
\r
457 * @param[in] pNetworkInterface Function pointers used to interact with the
\r
460 * @return One of the server-to-client MQTT packet types.
\r
462 * @note This function is only used for incoming packets, and may not work
\r
463 * correctly for outgoing packets.
\r
465 uint8_t _IotMqtt_GetPacketType( void * pNetworkConnection,
\r
466 const IotNetworkInterface_t * pNetworkInterface );
\r
469 * @brief Get the remaining length from a stream of bytes off the network.
\r
471 * @param[in] pNetworkConnection Reference to the network connection.
\r
472 * @param[in] pNetworkInterface Function pointers used to interact with the
\r
475 * @return The remaining length; #MQTT_REMAINING_LENGTH_INVALID on error.
\r
477 size_t _IotMqtt_GetRemainingLength( void * pNetworkConnection,
\r
478 const IotNetworkInterface_t * pNetworkInterface );
\r
481 * @brief Generate a CONNECT packet from the given parameters.
\r
483 * @param[in] pConnectInfo User-provided CONNECT information.
\r
484 * @param[out] pConnectPacket Where the CONNECT packet is written.
\r
485 * @param[out] pPacketSize Size of the packet written to `pConnectPacket`.
\r
487 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
\r
489 IotMqttError_t _IotMqtt_SerializeConnect( const IotMqttConnectInfo_t * pConnectInfo,
\r
490 uint8_t ** pConnectPacket,
\r
491 size_t * pPacketSize );
\r
494 * @brief Deserialize a CONNACK packet.
\r
496 * Converts the packet from a stream of bytes to an #IotMqttError_t. Also
\r
497 * prints out debug log messages about the packet.
\r
499 * @param[in,out] pConnack Pointer to an MQTT packet struct representing a CONNACK.
\r
501 * @return #IOT_MQTT_SUCCESS if CONNACK specifies that CONNECT was accepted;
\r
502 * #IOT_MQTT_SERVER_REFUSED if CONNACK specifies that CONNECT was rejected;
\r
503 * #IOT_MQTT_BAD_RESPONSE if the CONNACK packet doesn't follow MQTT spec.
\r
505 IotMqttError_t _IotMqtt_DeserializeConnack( _mqttPacket_t * pConnack );
\r
508 * @brief Generate a PUBLISH packet from the given parameters.
\r
510 * @param[in] pPublishInfo User-provided PUBLISH information.
\r
511 * @param[out] pPublishPacket Where the PUBLISH packet is written.
\r
512 * @param[out] pPacketSize Size of the packet written to `pPublishPacket`.
\r
513 * @param[out] pPacketIdentifier The packet identifier generated for this PUBLISH.
\r
514 * @param[out] pPacketIdentifierHigh Where the high byte of the packet identifier
\r
517 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
\r
519 IotMqttError_t _IotMqtt_SerializePublish( const IotMqttPublishInfo_t * pPublishInfo,
\r
520 uint8_t ** pPublishPacket,
\r
521 size_t * pPacketSize,
\r
522 uint16_t * pPacketIdentifier,
\r
523 uint8_t ** pPacketIdentifierHigh );
\r
526 * @brief Set the DUP bit in a QoS 1 PUBLISH packet.
\r
528 * @param[in] pPublishPacket Pointer to the PUBLISH packet to modify.
\r
529 * @param[in] pPacketIdentifierHigh The high byte of any packet identifier to modify.
\r
530 * @param[out] pNewPacketIdentifier Since AWS IoT does not support the DUP flag,
\r
531 * a new packet identifier is generated and should be written here. This parameter
\r
532 * is only used when connected to an AWS IoT MQTT server.
\r
534 * @note See #IotMqttPublishInfo_t for caveats with retransmission to the
\r
535 * AWS IoT MQTT server.
\r
537 void _IotMqtt_PublishSetDup( uint8_t * pPublishPacket,
\r
538 uint8_t * pPacketIdentifierHigh,
\r
539 uint16_t * pNewPacketIdentifier );
\r
542 * @brief Deserialize a PUBLISH packet received from the server.
\r
544 * Converts the packet from a stream of bytes to an #IotMqttPublishInfo_t and
\r
545 * extracts the packet identifier. Also prints out debug log messages about the
\r
548 * @param[in,out] pPublish Pointer to an MQTT packet struct representing a PUBLISH.
\r
550 * @return #IOT_MQTT_SUCCESS if PUBLISH is valid; #IOT_MQTT_BAD_RESPONSE
\r
551 * if the PUBLISH packet doesn't follow MQTT spec.
\r
553 IotMqttError_t _IotMqtt_DeserializePublish( _mqttPacket_t * pPublish );
\r
556 * @brief Generate a PUBACK packet for the given packet identifier.
\r
558 * @param[in] packetIdentifier The packet identifier to place in PUBACK.
\r
559 * @param[out] pPubackPacket Where the PUBACK packet is written.
\r
560 * @param[out] pPacketSize Size of the packet written to `pPubackPacket`.
\r
562 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
\r
564 IotMqttError_t _IotMqtt_SerializePuback( uint16_t packetIdentifier,
\r
565 uint8_t ** pPubackPacket,
\r
566 size_t * pPacketSize );
\r
569 * @brief Deserialize a PUBACK packet.
\r
571 * Converts the packet from a stream of bytes to an #IotMqttError_t and extracts
\r
572 * the packet identifier. Also prints out debug log messages about the packet.
\r
574 * @param[in,out] pPuback Pointer to an MQTT packet struct representing a PUBACK.
\r
576 * @return #IOT_MQTT_SUCCESS if PUBACK is valid; #IOT_MQTT_BAD_RESPONSE
\r
577 * if the PUBACK packet doesn't follow MQTT spec.
\r
579 IotMqttError_t _IotMqtt_DeserializePuback( _mqttPacket_t * pPuback );
\r
582 * @brief Generate a SUBSCRIBE packet from the given parameters.
\r
584 * @param[in] pSubscriptionList User-provided array of subscriptions.
\r
585 * @param[in] subscriptionCount Size of `pSubscriptionList`.
\r
586 * @param[out] pSubscribePacket Where the SUBSCRIBE packet is written.
\r
587 * @param[out] pPacketSize Size of the packet written to `pSubscribePacket`.
\r
588 * @param[out] pPacketIdentifier The packet identifier generated for this SUBSCRIBE.
\r
590 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
\r
592 IotMqttError_t _IotMqtt_SerializeSubscribe( const IotMqttSubscription_t * pSubscriptionList,
\r
593 size_t subscriptionCount,
\r
594 uint8_t ** pSubscribePacket,
\r
595 size_t * pPacketSize,
\r
596 uint16_t * pPacketIdentifier );
\r
599 * @brief Deserialize a SUBACK packet.
\r
601 * Converts the packet from a stream of bytes to an #IotMqttError_t and extracts
\r
602 * the packet identifier. Also prints out debug log messages about the packet.
\r
604 * @param[in,out] pSuback Pointer to an MQTT packet struct representing a SUBACK.
\r
606 * @return #IOT_MQTT_SUCCESS if SUBACK is valid; #IOT_MQTT_BAD_RESPONSE
\r
607 * if the SUBACK packet doesn't follow MQTT spec.
\r
609 IotMqttError_t _IotMqtt_DeserializeSuback( _mqttPacket_t * pSuback );
\r
612 * @brief Generate an UNSUBSCRIBE packet from the given parameters.
\r
614 * @param[in] pSubscriptionList User-provided array of subscriptions to remove.
\r
615 * @param[in] subscriptionCount Size of `pSubscriptionList`.
\r
616 * @param[out] pUnsubscribePacket Where the UNSUBSCRIBE packet is written.
\r
617 * @param[out] pPacketSize Size of the packet written to `pUnsubscribePacket`.
\r
618 * @param[out] pPacketIdentifier The packet identifier generated for this UNSUBSCRIBE.
\r
620 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
\r
622 IotMqttError_t _IotMqtt_SerializeUnsubscribe( const IotMqttSubscription_t * pSubscriptionList,
\r
623 size_t subscriptionCount,
\r
624 uint8_t ** pUnsubscribePacket,
\r
625 size_t * pPacketSize,
\r
626 uint16_t * pPacketIdentifier );
\r
629 * @brief Deserialize a UNSUBACK packet.
\r
631 * Converts the packet from a stream of bytes to an #IotMqttError_t and extracts
\r
632 * the packet identifier. Also prints out debug log messages about the packet.
\r
634 * @param[in,out] pUnsuback Pointer to an MQTT packet struct representing an UNSUBACK.
\r
636 * @return #IOT_MQTT_SUCCESS if UNSUBACK is valid; #IOT_MQTT_BAD_RESPONSE
\r
637 * if the UNSUBACK packet doesn't follow MQTT spec.
\r
639 IotMqttError_t _IotMqtt_DeserializeUnsuback( _mqttPacket_t * pUnsuback );
\r
642 * @brief Generate a PINGREQ packet.
\r
644 * @param[out] pPingreqPacket Where the PINGREQ packet is written.
\r
645 * @param[out] pPacketSize Size of the packet written to `pPingreqPacket`.
\r
647 * @return Always returns #IOT_MQTT_SUCCESS.
\r
649 IotMqttError_t _IotMqtt_SerializePingreq( uint8_t ** pPingreqPacket,
\r
650 size_t * pPacketSize );
\r
653 * @brief Deserialize a PINGRESP packet.
\r
655 * Converts the packet from a stream of bytes to an #IotMqttError_t. Also
\r
656 * prints out debug log messages about the packet.
\r
658 * @param[in,out] pPingresp Pointer to an MQTT packet struct representing a PINGRESP.
\r
660 * @return #IOT_MQTT_SUCCESS if PINGRESP is valid; #IOT_MQTT_BAD_RESPONSE
\r
661 * if the PINGRESP packet doesn't follow MQTT spec.
\r
663 IotMqttError_t _IotMqtt_DeserializePingresp( _mqttPacket_t * pPingresp );
\r
666 * @brief Generate a DISCONNECT packet.
\r
668 * @param[out] pDisconnectPacket Where the DISCONNECT packet is written.
\r
669 * @param[out] pPacketSize Size of the packet written to `pDisconnectPacket`.
\r
671 * @return Always returns #IOT_MQTT_SUCCESS.
\r
673 IotMqttError_t _IotMqtt_SerializeDisconnect( uint8_t ** pDisconnectPacket,
\r
674 size_t * pPacketSize );
\r
677 * @brief Free a packet generated by the serializer.
\r
679 * @param[in] pPacket The packet to free.
\r
681 void _IotMqtt_FreePacket( uint8_t * pPacket );
\r
683 /*-------------------- MQTT operation record functions ----------------------*/
\r
686 * @brief Create a record for a new in-progress MQTT operation.
\r
688 * @param[in] pMqttConnection The MQTT connection to associate with the operation.
\r
689 * @param[in] flags Flags variable passed to a user-facing MQTT function.
\r
690 * @param[in] pCallbackInfo User-provided callback function and parameter.
\r
691 * @param[out] pNewOperation Set to point to the new operation on success.
\r
693 * @return #IOT_MQTT_SUCCESS, #IOT_MQTT_BAD_PARAMETER, or #IOT_MQTT_NO_MEMORY.
\r
695 IotMqttError_t _IotMqtt_CreateOperation( _mqttConnection_t * pMqttConnection,
\r
697 const IotMqttCallbackInfo_t * pCallbackInfo,
\r
698 _mqttOperation_t ** pNewOperation );
\r
701 * @brief Decrement the job reference count of an MQTT operation and optionally
\r
704 * Checks if the operation may be destroyed afterwards.
\r
706 * @param[in] pOperation The MQTT operation with the job to cancel.
\r
707 * @param[in] cancelJob Whether to attempt cancellation of the operation's job.
\r
709 * @return `true` if the the operation may be safely destroyed; `false` otherwise.
\r
711 bool _IotMqtt_DecrementOperationReferences( _mqttOperation_t * pOperation,
\r
715 * @brief Free resources used to record an MQTT operation. This is called when
\r
716 * the operation completes.
\r
718 * @param[in] pOperation The operation which completed.
\r
720 void _IotMqtt_DestroyOperation( _mqttOperation_t * pOperation );
\r
723 * @brief Task pool routine for processing an MQTT connection's keep-alive.
\r
725 * @param[in] pTaskPool Pointer to the system task pool.
\r
726 * @param[in] pKeepAliveJob Pointer the an MQTT connection's keep-alive job.
\r
727 * @param[in] pContext Pointer to an MQTT connection, passed as an opaque context.
\r
729 void _IotMqtt_ProcessKeepAlive( IotTaskPool_t pTaskPool,
\r
730 IotTaskPoolJob_t pKeepAliveJob,
\r
734 * @brief Task pool routine for processing an incoming PUBLISH message.
\r
736 * @param[in] pTaskPool Pointer to the system task pool.
\r
737 * @param[in] pPublishJob Pointer to the incoming PUBLISH operation's job.
\r
738 * @param[in] pContext Pointer to the incoming PUBLISH operation, passed as an
\r
741 void _IotMqtt_ProcessIncomingPublish( IotTaskPool_t pTaskPool,
\r
742 IotTaskPoolJob_t pPublishJob,
\r
746 * @brief Task pool routine for processing an MQTT operation to send.
\r
748 * @param[in] pTaskPool Pointer to the system task pool.
\r
749 * @param[in] pSendJob Pointer to an operation's job.
\r
750 * @param[in] pContext Pointer to the operation to send, passed as an opaque
\r
753 void _IotMqtt_ProcessSend( IotTaskPool_t pTaskPool,
\r
754 IotTaskPoolJob_t pSendJob,
\r
758 * @brief Task pool routine for processing a completed MQTT operation.
\r
760 * @param[in] pTaskPool Pointer to the system task pool.
\r
761 * @param[in] pOperationJob Pointer to the completed operation's job.
\r
762 * @param[in] pContext Pointer to the completed operation, passed as an opaque
\r
765 void _IotMqtt_ProcessCompletedOperation( IotTaskPool_t pTaskPool,
\r
766 IotTaskPoolJob_t pOperationJob,
\r
770 * @brief Schedule an operation for immediate processing.
\r
772 * @param[in] pOperation The operation to schedule.
\r
773 * @param[in] jobRoutine The routine to run for the job. Must be either
\r
774 * #_IotMqtt_ProcessSend, #_IotMqtt_ProcessCompletedOperation, or
\r
775 * #_IotMqtt_ProcessIncomingPublish.
\r
776 * @param[in] delay A delay before the operation job should be executed. Pass
\r
777 * `0` to execute ASAP.
\r
779 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_SCHEDULING_ERROR.
\r
781 IotMqttError_t _IotMqtt_ScheduleOperation( _mqttOperation_t * pOperation,
\r
782 IotTaskPoolRoutine_t jobRoutine,
\r
786 * @brief Search a list of MQTT operations pending responses using an operation
\r
787 * name and packet identifier. Removes a matching operation from the list if found.
\r
789 * @param[in] pMqttConnection The connection associated with the operation.
\r
790 * @param[in] type The operation type to look for.
\r
791 * @param[in] pPacketIdentifier A packet identifier to match. Pass `NULL` to ignore.
\r
793 * @return Pointer to any matching operation; `NULL` if no match was found.
\r
795 _mqttOperation_t * _IotMqtt_FindOperation( _mqttConnection_t * pMqttConnection,
\r
796 IotMqttOperationType_t type,
\r
797 const uint16_t * pPacketIdentifier );
\r
800 * @brief Notify of a completed MQTT operation.
\r
802 * @param[in] pOperation The MQTT operation which completed.
\r
804 * Depending on the parameters passed to a user-facing MQTT function, the
\r
805 * notification will cause @ref mqtt_function_wait to return or invoke a
\r
806 * user-provided callback.
\r
808 void _IotMqtt_Notify( _mqttOperation_t * pOperation );
\r
810 /*----------------- MQTT subscription management functions ------------------*/
\r
813 * @brief Add an array of subscriptions to the subscription manager.
\r
815 * @param[in] pMqttConnection The MQTT connection associated with the subscriptions.
\r
816 * @param[in] subscribePacketIdentifier Packet identifier for the subscriptions'
\r
817 * SUBSCRIBE packet.
\r
818 * @param[in] pSubscriptionList The first element in the array.
\r
819 * @param[in] subscriptionCount Number of elements in `pSubscriptionList`.
\r
821 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
\r
823 IotMqttError_t _IotMqtt_AddSubscriptions( _mqttConnection_t * pMqttConnection,
\r
824 uint16_t subscribePacketIdentifier,
\r
825 const IotMqttSubscription_t * pSubscriptionList,
\r
826 size_t subscriptionCount );
\r
829 * @brief Process a received PUBLISH from the server, invoking any subscription
\r
830 * callbacks that have a matching topic filter.
\r
832 * @param[in] pMqttConnection The MQTT connection associated with the received
\r
834 * @param[in] pCallbackParam The parameter to pass to a PUBLISH callback.
\r
836 void _IotMqtt_InvokeSubscriptionCallback( _mqttConnection_t * pMqttConnection,
\r
837 IotMqttCallbackParam_t * pCallbackParam );
\r
840 * @brief Remove a single subscription from the subscription manager by
\r
841 * packetIdentifier and order.
\r
843 * @param[in] pMqttConnection The MQTT connection associated with the subscriptions.
\r
844 * @param[in] packetIdentifier The packet identifier associated with the subscription's
\r
845 * SUBSCRIBE packet.
\r
846 * @param[in] order The order of the subscription in the SUBSCRIBE packet.
\r
847 * Pass `-1` to ignore order and remove all subscriptions for `packetIdentifier`.
\r
849 void _IotMqtt_RemoveSubscriptionByPacket( _mqttConnection_t * pMqttConnection,
\r
850 uint16_t packetIdentifier,
\r
854 * @brief Remove an array of subscriptions from the subscription manager by
\r
857 * @param[in] pMqttConnection The MQTT connection associated with the subscriptions.
\r
858 * @param[in] pSubscriptionList The first element in the array.
\r
859 * @param[in] subscriptionCount Number of elements in `pSubscriptionList`.
\r
861 void _IotMqtt_RemoveSubscriptionByTopicFilter( _mqttConnection_t * pMqttConnection,
\r
862 const IotMqttSubscription_t * pSubscriptionList,
\r
863 size_t subscriptionCount );
\r
865 /*------------------ MQTT connection management functions -------------------*/
\r
868 * @brief Attempt to increment the reference count of an MQTT connection.
\r
870 * @param[in] pMqttConnection The referenced MQTT connection.
\r
872 * @return `true` if the reference count was incremented; `false` otherwise. The
\r
873 * reference count will not be incremented for a disconnected connection.
\r
875 bool _IotMqtt_IncrementConnectionReferences( _mqttConnection_t * pMqttConnection );
\r
878 * @brief Decrement the reference count of an MQTT connection.
\r
880 * Also destroys an unreferenced MQTT connection.
\r
882 * @param[in] pMqttConnection The referenced MQTT connection.
\r
884 void _IotMqtt_DecrementConnectionReferences( _mqttConnection_t * pMqttConnection );
\r
887 * @brief Read the next available byte on a network connection.
\r
889 * @param[in] pNetworkConnection Reference to the network connection.
\r
890 * @param[in] pNetworkInterface Function pointers used to interact with the
\r
892 * @param[out] pIncomingByte The byte read from the network.
\r
894 * @return `true` if a byte was successfully received from the network; `false`
\r
897 bool _IotMqtt_GetNextByte( void * pNetworkConnection,
\r
898 const IotNetworkInterface_t * pNetworkInterface,
\r
899 uint8_t * pIncomingByte );
\r
902 * @brief Closes the network connection associated with an MQTT connection.
\r
904 * A network disconnect function must be set in the network interface for the
\r
905 * network connection to be closed.
\r
907 * @param[in] disconnectReason A reason to pass to the connection's disconnect
\r
909 * @param[in] pMqttConnection The MQTT connection with the network connection
\r
912 void _IotMqtt_CloseNetworkConnection( IotMqttDisconnectReason_t disconnectReason,
\r
913 _mqttConnection_t * pMqttConnection );
\r
915 #endif /* ifndef IOT_MQTT_INTERNAL_H_ */
\r