]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/mqtt/src/private/iot_mqtt_internal.h
Add missing files so base MQTT project builds.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-IoT-SDK / c_sdk / standard / mqtt / src / private / iot_mqtt_internal.h
1 /*\r
2  * Amazon FreeRTOS MQTT V2.0.0\r
3  * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\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
11  *\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
14  *\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
21  *\r
22  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 /**\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
30  */\r
31 \r
32 #ifndef IOT_MQTT_INTERNAL_H_\r
33 #define IOT_MQTT_INTERNAL_H_\r
34 \r
35 /* The config header is always included first. */\r
36 #include "iot_config.h"\r
37 \r
38 /* Linear containers (lists and queues) include. */\r
39 #include "iot_linear_containers.h"\r
40 \r
41 /* MQTT include. */\r
42 #include "iot_mqtt.h"\r
43 \r
44 /* Task pool include. */\r
45 #include "iot_taskpool.h"\r
46 \r
47 /**\r
48  * @def IotMqtt_Assert( expression )\r
49  * @brief Assertion macro for the MQTT library.\r
50  *\r
51  * Set @ref IOT_MQTT_ENABLE_ASSERTS to `1` to enable assertions in the MQTT\r
52  * library.\r
53  *\r
54  * @param[in] expression Expression to be evaluated.\r
55  */\r
56 #if IOT_MQTT_ENABLE_ASSERTS == 1\r
57     #ifndef IotMqtt_Assert\r
58         #include <assert.h>\r
59         #define IotMqtt_Assert( expression )    assert( expression )\r
60     #endif\r
61 #else\r
62     #define IotMqtt_Assert( expression )\r
63 #endif\r
64 \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
68 #else\r
69     #ifdef IOT_LOG_LEVEL_GLOBAL\r
70         #define LIBRARY_LOG_LEVEL    IOT_LOG_LEVEL_GLOBAL\r
71     #else\r
72         #define LIBRARY_LOG_LEVEL    IOT_LOG_NONE\r
73     #endif\r
74 #endif\r
75 \r
76 #define LIBRARY_LOG_NAME    ( "MQTT" )\r
77 #include "iot_logging_setup.h"\r
78 \r
79 /*\r
80  * Provide default values for undefined memory allocation functions based on\r
81  * the usage of dynamic memory allocation.\r
82  */\r
83 #if IOT_STATIC_MEMORY_ONLY == 1\r
84     #include "private/iot_static_memory.h"\r
85 \r
86 /**\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
90  */\r
91     void * IotMqtt_MallocConnection( size_t size );\r
92 \r
93 /**\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
97  */\r
98     void IotMqtt_FreeConnection( void * ptr );\r
99 \r
100 /**\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
104  */\r
105     #define IotMqtt_MallocMessage    Iot_MallocMessageBuffer\r
106 \r
107 /**\r
108  * @brief Free an MQTT packet. This function should have the same signature\r
109  * as [free]\r
110  * (http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html).\r
111  */\r
112     #define IotMqtt_FreeMessage      Iot_FreeMessageBuffer\r
113 \r
114 /**\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
118  */\r
119     void * IotMqtt_MallocOperation( size_t size );\r
120 \r
121 /**\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
125  */\r
126     void IotMqtt_FreeOperation( void * ptr );\r
127 \r
128 /**\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
132  */\r
133     void * IotMqtt_MallocSubscription( size_t size );\r
134 \r
135 /**\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
139  */\r
140     void IotMqtt_FreeSubscription( void * ptr );\r
141 #else /* if IOT_STATIC_MEMORY_ONLY == 1 */\r
142     #include <stdlib.h>\r
143 \r
144     #ifndef IotMqtt_MallocConnection\r
145         #define IotMqtt_MallocConnection    malloc\r
146     #endif\r
147 \r
148     #ifndef IotMqtt_FreeConnection\r
149         #define IotMqtt_FreeConnection    free\r
150     #endif\r
151 \r
152     #ifndef IotMqtt_MallocMessage\r
153         #define IotMqtt_MallocMessage    malloc\r
154     #endif\r
155 \r
156     #ifndef IotMqtt_FreeMessage\r
157         #define IotMqtt_FreeMessage    free\r
158     #endif\r
159 \r
160     #ifndef IotMqtt_MallocOperation\r
161         #define IotMqtt_MallocOperation    malloc\r
162     #endif\r
163 \r
164     #ifndef IotMqtt_FreeOperation\r
165         #define IotMqtt_FreeOperation    free\r
166     #endif\r
167 \r
168     #ifndef IotMqtt_MallocSubscription\r
169         #define IotMqtt_MallocSubscription    malloc\r
170     #endif\r
171 \r
172     #ifndef IotMqtt_FreeSubscription\r
173         #define IotMqtt_FreeSubscription    free\r
174     #endif\r
175 #endif /* if IOT_STATIC_MEMORY_ONLY == 1 */\r
176 \r
177 /**\r
178  * @cond DOXYGEN_IGNORE\r
179  * Doxygen should ignore this section.\r
180  *\r
181  * Provide default values for undefined configuration constants.\r
182  */\r
183 #ifndef AWS_IOT_MQTT_ENABLE_METRICS\r
184     #define AWS_IOT_MQTT_ENABLE_METRICS             ( 1 )\r
185 #endif\r
186 #ifndef IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES\r
187     #define IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES    ( 0 )\r
188 #endif\r
189 #ifndef IOT_MQTT_RESPONSE_WAIT_MS\r
190     #define IOT_MQTT_RESPONSE_WAIT_MS               ( 1000 )\r
191 #endif\r
192 #ifndef IOT_MQTT_RETRY_MS_CEILING\r
193     #define IOT_MQTT_RETRY_MS_CEILING               ( 60000 )\r
194 #endif\r
195 /** @endcond */\r
196 \r
197 /**\r
198  * @brief Marks the empty statement of an `else` branch.\r
199  *\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
203  */\r
204 #ifndef EMPTY_ELSE_MARKER\r
205     #define EMPTY_ELSE_MARKER\r
206 #endif\r
207 \r
208 /*\r
209  * Constants related to limits defined in AWS Service Limits.\r
210  *\r
211  * For details, see\r
212  * https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html\r
213  *\r
214  * Used to validate parameters if when connecting to an AWS IoT MQTT server.\r
215  */\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
221 \r
222 /*\r
223  * MQTT control packet type and flags. Always the first byte of an MQTT\r
224  * packet.\r
225  *\r
226  * For details, see\r
227  * http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/csprd02/mqtt-v3.1.1-csprd02.html#_Toc385349757\r
228  */\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
240 \r
241 /**\r
242  * @brief A value that represents an invalid remaining length.\r
243  *\r
244  * This value is greater than what is allowed by the MQTT specification.\r
245  */\r
246 #define MQTT_REMAINING_LENGTH_INVALID                          ( ( size_t ) 268435456 )\r
247 \r
248 /*---------------------- MQTT internal data structures ----------------------*/\r
249 \r
250 /**\r
251  * @brief Represents an MQTT connection.\r
252  */\r
253 typedef struct _mqttConnection\r
254 {\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
260 \r
261     #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1\r
262         const IotMqttSerializer_t * pSerializer; /**< @brief MQTT packet serializer overrides. */\r
263     #endif\r
264 \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
270 \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
273 \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
282 \r
283 /**\r
284  * @brief Represents a subscription stored in an MQTT connection.\r
285  */\r
286 typedef struct _mqttSubscription\r
287 {\r
288     IotLink_t link;     /**< @brief List link member. */\r
289 \r
290     int32_t references; /**< @brief How many subscription callbacks are using this subscription. */\r
291 \r
292     /**\r
293      * @brief Tracks whether @ref mqtt_function_unsubscribe has been called for\r
294      * this subscription.\r
295      *\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
299      * terminate.\r
300      */\r
301     bool unsubscribed;\r
302 \r
303     struct\r
304     {\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
308 \r
309     IotMqttCallbackInfo_t callback; /**< @brief Callback information for this subscription. */\r
310 \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
314 \r
315 /**\r
316  * @brief Internal structure representing a single MQTT operation, such as\r
317  * CONNECT, SUBSCRIBE, PUBLISH, etc.\r
318  *\r
319  * Queues of these structures keeps track of all in-progress MQTT operations.\r
320  */\r
321 typedef struct _mqttOperation\r
322 {\r
323     /* Pointers to neighboring queue elements. */\r
324     IotLink_t link;                      /**< @brief List link member. */\r
325 \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
328 \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
331 \r
332     union\r
333     {\r
334         /* If incomingPublish is false, this struct is valid. */\r
335         struct\r
336         {\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
342 \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
347 \r
348             /* How to notify of an operation's completion. */\r
349             union\r
350             {\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
355 \r
356             struct\r
357             {\r
358                 uint32_t count;\r
359                 uint32_t limit;\r
360                 uint32_t nextPeriod;\r
361             } retry;\r
362         } operation;\r
363 \r
364         /* If incomingPublish is true, this struct is valid. */\r
365         struct\r
366         {\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
369         } publish;\r
370     } u;                                      /**< @brief Valid member depends on _mqttOperation_t.incomingPublish. */\r
371 } _mqttOperation_t;\r
372 \r
373 /**\r
374  * @brief Represents an MQTT packet received from the network.\r
375  *\r
376  * This struct is used to hold parameters for the deserializers so that all\r
377  * deserializers have the same function signature.\r
378  */\r
379 typedef struct _mqttPacket\r
380 {\r
381     union\r
382     {\r
383         /**\r
384          * @brief (Input) MQTT connection associated with this packet. Only used\r
385          * when deserializing SUBACKs.\r
386          */\r
387         _mqttConnection_t * pMqttConnection;\r
388 \r
389         /**\r
390          * @brief (Output) Operation representing an incoming PUBLISH. Only used\r
391          * when deserializing PUBLISHes.\r
392          */\r
393         _mqttOperation_t * pIncomingPublish;\r
394     } u;                       /**< @brief Valid member depends on packet being decoded. */\r
395 \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
400 } _mqttPacket_t;\r
401 \r
402 /*-------------------- MQTT struct validation functions ---------------------*/\r
403 \r
404 /**\r
405  * @brief Check that an #IotMqttConnectInfo_t is valid.\r
406  *\r
407  * @param[in] pConnectInfo The #IotMqttConnectInfo_t to validate.\r
408  *\r
409  * @return `true` if `pConnectInfo` is valid; `false` otherwise.\r
410  */\r
411 bool _IotMqtt_ValidateConnect( const IotMqttConnectInfo_t * pConnectInfo );\r
412 \r
413 /**\r
414  * @brief Check that an #IotMqttPublishInfo_t is valid.\r
415  *\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
419  *\r
420  * @return `true` if `pPublishInfo` is valid; `false` otherwise.\r
421  */\r
422 bool _IotMqtt_ValidatePublish( bool awsIotMqttMode,\r
423                                const IotMqttPublishInfo_t * pPublishInfo );\r
424 \r
425 /**\r
426  * @brief Check that an #IotMqttOperation_t is valid and waitable.\r
427  *\r
428  * @param[in] operation The #IotMqttOperation_t to validate.\r
429  *\r
430  * @return `true` if `operation` is valid; `false` otherwise.\r
431  */\r
432 bool _IotMqtt_ValidateOperation( IotMqttOperation_t operation );\r
433 \r
434 /**\r
435  * @brief Check that a list of #IotMqttSubscription_t is valid.\r
436  *\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
443  *\r
444  * @return `true` if every element in the list is valid; `false` otherwise.\r
445  */\r
446 bool _IotMqtt_ValidateSubscriptionList( IotMqttOperationType_t operation,\r
447                                         bool awsIotMqttMode,\r
448                                         const IotMqttSubscription_t * pListStart,\r
449                                         size_t listSize );\r
450 \r
451 /*-------------------- MQTT packet serializer functions ---------------------*/\r
452 \r
453 /**\r
454  * @brief Get the MQTT packet type from a stream of bytes off the network.\r
455  *\r
456  * @param[in] pNetworkConnection Reference to the network connection.\r
457  * @param[in] pNetworkInterface Function pointers used to interact with the\r
458  * network.\r
459  *\r
460  * @return One of the server-to-client MQTT packet types.\r
461  *\r
462  * @note This function is only used for incoming packets, and may not work\r
463  * correctly for outgoing packets.\r
464  */\r
465 uint8_t _IotMqtt_GetPacketType( void * pNetworkConnection,\r
466                                 const IotNetworkInterface_t * pNetworkInterface );\r
467 \r
468 /**\r
469  * @brief Get the remaining length from a stream of bytes off the network.\r
470  *\r
471  * @param[in] pNetworkConnection Reference to the network connection.\r
472  * @param[in] pNetworkInterface Function pointers used to interact with the\r
473  * network.\r
474  *\r
475  * @return The remaining length; #MQTT_REMAINING_LENGTH_INVALID on error.\r
476  */\r
477 size_t _IotMqtt_GetRemainingLength( void * pNetworkConnection,\r
478                                     const IotNetworkInterface_t * pNetworkInterface );\r
479 \r
480 /**\r
481  * @brief Generate a CONNECT packet from the given parameters.\r
482  *\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
486  *\r
487  * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.\r
488  */\r
489 IotMqttError_t _IotMqtt_SerializeConnect( const IotMqttConnectInfo_t * pConnectInfo,\r
490                                           uint8_t ** pConnectPacket,\r
491                                           size_t * pPacketSize );\r
492 \r
493 /**\r
494  * @brief Deserialize a CONNACK packet.\r
495  *\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
498  *\r
499  * @param[in,out] pConnack Pointer to an MQTT packet struct representing a CONNACK.\r
500  *\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
504  */\r
505 IotMqttError_t _IotMqtt_DeserializeConnack( _mqttPacket_t * pConnack );\r
506 \r
507 /**\r
508  * @brief Generate a PUBLISH packet from the given parameters.\r
509  *\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
515  * is written.\r
516  *\r
517  * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.\r
518  */\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
524 \r
525 /**\r
526  * @brief Set the DUP bit in a QoS 1 PUBLISH packet.\r
527  *\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
533  *\r
534  * @note See #IotMqttPublishInfo_t for caveats with retransmission to the\r
535  * AWS IoT MQTT server.\r
536  */\r
537 void _IotMqtt_PublishSetDup( uint8_t * pPublishPacket,\r
538                              uint8_t * pPacketIdentifierHigh,\r
539                              uint16_t * pNewPacketIdentifier );\r
540 \r
541 /**\r
542  * @brief Deserialize a PUBLISH packet received from the server.\r
543  *\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
546  * packet.\r
547  *\r
548  * @param[in,out] pPublish Pointer to an MQTT packet struct representing a PUBLISH.\r
549  *\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
552  */\r
553 IotMqttError_t _IotMqtt_DeserializePublish( _mqttPacket_t * pPublish );\r
554 \r
555 /**\r
556  * @brief Generate a PUBACK packet for the given packet identifier.\r
557  *\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
561  *\r
562  * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.\r
563  */\r
564 IotMqttError_t _IotMqtt_SerializePuback( uint16_t packetIdentifier,\r
565                                          uint8_t ** pPubackPacket,\r
566                                          size_t * pPacketSize );\r
567 \r
568 /**\r
569  * @brief Deserialize a PUBACK packet.\r
570  *\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
573  *\r
574  * @param[in,out] pPuback Pointer to an MQTT packet struct representing a PUBACK.\r
575  *\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
578  */\r
579 IotMqttError_t _IotMqtt_DeserializePuback( _mqttPacket_t * pPuback );\r
580 \r
581 /**\r
582  * @brief Generate a SUBSCRIBE packet from the given parameters.\r
583  *\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
589  *\r
590  * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.\r
591  */\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
597 \r
598 /**\r
599  * @brief Deserialize a SUBACK packet.\r
600  *\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
603  *\r
604  * @param[in,out] pSuback Pointer to an MQTT packet struct representing a SUBACK.\r
605  *\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
608  */\r
609 IotMqttError_t _IotMqtt_DeserializeSuback( _mqttPacket_t * pSuback );\r
610 \r
611 /**\r
612  * @brief Generate an UNSUBSCRIBE packet from the given parameters.\r
613  *\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
619  *\r
620  * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.\r
621  */\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
627 \r
628 /**\r
629  * @brief Deserialize a UNSUBACK packet.\r
630  *\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
633  *\r
634  * @param[in,out] pUnsuback Pointer to an MQTT packet struct representing an UNSUBACK.\r
635  *\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
638  */\r
639 IotMqttError_t _IotMqtt_DeserializeUnsuback( _mqttPacket_t * pUnsuback );\r
640 \r
641 /**\r
642  * @brief Generate a PINGREQ packet.\r
643  *\r
644  * @param[out] pPingreqPacket Where the PINGREQ packet is written.\r
645  * @param[out] pPacketSize Size of the packet written to `pPingreqPacket`.\r
646  *\r
647  * @return Always returns #IOT_MQTT_SUCCESS.\r
648  */\r
649 IotMqttError_t _IotMqtt_SerializePingreq( uint8_t ** pPingreqPacket,\r
650                                           size_t * pPacketSize );\r
651 \r
652 /**\r
653  * @brief Deserialize a PINGRESP packet.\r
654  *\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
657  *\r
658  * @param[in,out] pPingresp Pointer to an MQTT packet struct representing a PINGRESP.\r
659  *\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
662  */\r
663 IotMqttError_t _IotMqtt_DeserializePingresp( _mqttPacket_t * pPingresp );\r
664 \r
665 /**\r
666  * @brief Generate a DISCONNECT packet.\r
667  *\r
668  * @param[out] pDisconnectPacket Where the DISCONNECT packet is written.\r
669  * @param[out] pPacketSize Size of the packet written to `pDisconnectPacket`.\r
670  *\r
671  * @return Always returns #IOT_MQTT_SUCCESS.\r
672  */\r
673 IotMqttError_t _IotMqtt_SerializeDisconnect( uint8_t ** pDisconnectPacket,\r
674                                              size_t * pPacketSize );\r
675 \r
676 /**\r
677  * @brief Free a packet generated by the serializer.\r
678  *\r
679  * @param[in] pPacket The packet to free.\r
680  */\r
681 void _IotMqtt_FreePacket( uint8_t * pPacket );\r
682 \r
683 /*-------------------- MQTT operation record functions ----------------------*/\r
684 \r
685 /**\r
686  * @brief Create a record for a new in-progress MQTT operation.\r
687  *\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
692  *\r
693  * @return #IOT_MQTT_SUCCESS, #IOT_MQTT_BAD_PARAMETER, or #IOT_MQTT_NO_MEMORY.\r
694  */\r
695 IotMqttError_t _IotMqtt_CreateOperation( _mqttConnection_t * pMqttConnection,\r
696                                          uint32_t flags,\r
697                                          const IotMqttCallbackInfo_t * pCallbackInfo,\r
698                                          _mqttOperation_t ** pNewOperation );\r
699 \r
700 /**\r
701  * @brief Decrement the job reference count of an MQTT operation and optionally\r
702  * cancel its job.\r
703  *\r
704  * Checks if the operation may be destroyed afterwards.\r
705  *\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
708  *\r
709  * @return `true` if the the operation may be safely destroyed; `false` otherwise.\r
710  */\r
711 bool _IotMqtt_DecrementOperationReferences( _mqttOperation_t * pOperation,\r
712                                             bool cancelJob );\r
713 \r
714 /**\r
715  * @brief Free resources used to record an MQTT operation. This is called when\r
716  * the operation completes.\r
717  *\r
718  * @param[in] pOperation The operation which completed.\r
719  */\r
720 void _IotMqtt_DestroyOperation( _mqttOperation_t * pOperation );\r
721 \r
722 /**\r
723  * @brief Task pool routine for processing an MQTT connection's keep-alive.\r
724  *\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
728  */\r
729 void _IotMqtt_ProcessKeepAlive( IotTaskPool_t pTaskPool,\r
730                                 IotTaskPoolJob_t pKeepAliveJob,\r
731                                 void * pContext );\r
732 \r
733 /**\r
734  * @brief Task pool routine for processing an incoming PUBLISH message.\r
735  *\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
739  * opaque context.\r
740  */\r
741 void _IotMqtt_ProcessIncomingPublish( IotTaskPool_t pTaskPool,\r
742                                       IotTaskPoolJob_t pPublishJob,\r
743                                       void * pContext );\r
744 \r
745 /**\r
746  * @brief Task pool routine for processing an MQTT operation to send.\r
747  *\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
751  * context.\r
752  */\r
753 void _IotMqtt_ProcessSend( IotTaskPool_t pTaskPool,\r
754                            IotTaskPoolJob_t pSendJob,\r
755                            void * pContext );\r
756 \r
757 /**\r
758  * @brief Task pool routine for processing a completed MQTT operation.\r
759  *\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
763  * context.\r
764  */\r
765 void _IotMqtt_ProcessCompletedOperation( IotTaskPool_t pTaskPool,\r
766                                          IotTaskPoolJob_t pOperationJob,\r
767                                          void * pContext );\r
768 \r
769 /**\r
770  * @brief Schedule an operation for immediate processing.\r
771  *\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
778  *\r
779  * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_SCHEDULING_ERROR.\r
780  */\r
781 IotMqttError_t _IotMqtt_ScheduleOperation( _mqttOperation_t * pOperation,\r
782                                            IotTaskPoolRoutine_t jobRoutine,\r
783                                            uint32_t delay );\r
784 \r
785 /**\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
788  *\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
792  *\r
793  * @return Pointer to any matching operation; `NULL` if no match was found.\r
794  */\r
795 _mqttOperation_t * _IotMqtt_FindOperation( _mqttConnection_t * pMqttConnection,\r
796                                            IotMqttOperationType_t type,\r
797                                            const uint16_t * pPacketIdentifier );\r
798 \r
799 /**\r
800  * @brief Notify of a completed MQTT operation.\r
801  *\r
802  * @param[in] pOperation The MQTT operation which completed.\r
803  *\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
807  */\r
808 void _IotMqtt_Notify( _mqttOperation_t * pOperation );\r
809 \r
810 /*----------------- MQTT subscription management functions ------------------*/\r
811 \r
812 /**\r
813  * @brief Add an array of subscriptions to the subscription manager.\r
814  *\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
820  *\r
821  * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.\r
822  */\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
827 \r
828 /**\r
829  * @brief Process a received PUBLISH from the server, invoking any subscription\r
830  * callbacks that have a matching topic filter.\r
831  *\r
832  * @param[in] pMqttConnection The MQTT connection associated with the received\r
833  * PUBLISH.\r
834  * @param[in] pCallbackParam The parameter to pass to a PUBLISH callback.\r
835  */\r
836 void _IotMqtt_InvokeSubscriptionCallback( _mqttConnection_t * pMqttConnection,\r
837                                           IotMqttCallbackParam_t * pCallbackParam );\r
838 \r
839 /**\r
840  * @brief Remove a single subscription from the subscription manager by\r
841  * packetIdentifier and order.\r
842  *\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
848  */\r
849 void _IotMqtt_RemoveSubscriptionByPacket( _mqttConnection_t * pMqttConnection,\r
850                                           uint16_t packetIdentifier,\r
851                                           int32_t order );\r
852 \r
853 /**\r
854  * @brief Remove an array of subscriptions from the subscription manager by\r
855  * topic filter.\r
856  *\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
860  */\r
861 void _IotMqtt_RemoveSubscriptionByTopicFilter( _mqttConnection_t * pMqttConnection,\r
862                                                const IotMqttSubscription_t * pSubscriptionList,\r
863                                                size_t subscriptionCount );\r
864 \r
865 /*------------------ MQTT connection management functions -------------------*/\r
866 \r
867 /**\r
868  * @brief Attempt to increment the reference count of an MQTT connection.\r
869  *\r
870  * @param[in] pMqttConnection The referenced MQTT connection.\r
871  *\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
874  */\r
875 bool _IotMqtt_IncrementConnectionReferences( _mqttConnection_t * pMqttConnection );\r
876 \r
877 /**\r
878  * @brief Decrement the reference count of an MQTT connection.\r
879  *\r
880  * Also destroys an unreferenced MQTT connection.\r
881  *\r
882  * @param[in] pMqttConnection The referenced MQTT connection.\r
883  */\r
884 void _IotMqtt_DecrementConnectionReferences( _mqttConnection_t * pMqttConnection );\r
885 \r
886 /**\r
887  * @brief Read the next available byte on a network connection.\r
888  *\r
889  * @param[in] pNetworkConnection Reference to the network connection.\r
890  * @param[in] pNetworkInterface Function pointers used to interact with the\r
891  * network.\r
892  * @param[out] pIncomingByte The byte read from the network.\r
893  *\r
894  * @return `true` if a byte was successfully received from the network; `false`\r
895  * otherwise.\r
896  */\r
897 bool _IotMqtt_GetNextByte( void * pNetworkConnection,\r
898                            const IotNetworkInterface_t * pNetworkInterface,\r
899                            uint8_t * pIncomingByte );\r
900 \r
901 /**\r
902  * @brief Closes the network connection associated with an MQTT connection.\r
903  *\r
904  * A network disconnect function must be set in the network interface for the\r
905  * network connection to be closed.\r
906  *\r
907  * @param[in] disconnectReason A reason to pass to the connection's disconnect\r
908  * callback.\r
909  * @param[in] pMqttConnection The MQTT connection with the network connection\r
910  * to close.\r
911  */\r
912 void _IotMqtt_CloseNetworkConnection( IotMqttDisconnectReason_t disconnectReason,\r
913                                       _mqttConnection_t * pMqttConnection );\r
914 \r
915 #endif /* ifndef IOT_MQTT_INTERNAL_H_ */\r