summaryrefslogtreecommitdiff
path: root/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/aws/common/include/aws_iot.h
blob: 3c1aacd3fef65c0a5c4eadd2f2d1f5461d6a1889 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*
 * AWS IoT Common V1.0.0
 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @file aws_iot.h
 * @brief Provides routines and constants that are common to AWS IoT libraries.
 * This header should not be included in typical application code.
 */

#ifndef AWS_IOT_H_
#define AWS_IOT_H_

/* The config header is always included first. */
#include "iot_config.h"

/* Standard includes. */
#include <stdbool.h>
#include <stdint.h>

/* Platform types include. */
#include "types/iot_platform_types.h"

/* MQTT types include. */
#include "types/iot_mqtt_types.h"

/**
 * @brief The longest Thing Name accepted by AWS IoT, per the [AWS IoT
 * Service Limits](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_iot).
 */
#define AWS_IOT_MAX_THING_NAME_LENGTH      ( 128 )

/**
 * @brief The common prefix of all AWS IoT MQTT topics.
 */
#define AWS_IOT_TOPIC_PREFIX               "$aws/things/"

/**
 * @brief The length of #AWS_IOT_TOPIC_PREFIX.
 */
#define AWS_IOT_TOPIC_PREFIX_LENGTH        ( ( uint16_t ) ( sizeof( AWS_IOT_TOPIC_PREFIX ) - 1 ) )

/**
 * @brief The suffix for an AWS IoT operation "accepted" topic.
 */
#define AWS_IOT_ACCEPTED_SUFFIX            "/accepted"

/**
 * @brief The length of #AWS_IOT_ACCEPTED_SUFFIX.
 */
#define AWS_IOT_ACCEPTED_SUFFIX_LENGTH     ( ( uint16_t ) ( sizeof( AWS_IOT_ACCEPTED_SUFFIX ) - 1 ) )

/**
 * @brief The suffix for an AWS IoT operation "rejected" topic.
 */
#define AWS_IOT_REJECTED_SUFFIX            "/rejected"

/**
 * @brief The length of #AWS_IOT_REJECTED_SUFFIX.
 */
#define AWS_IOT_REJECTED_SUFFIX_LENGTH     ( ( uint16_t ) ( sizeof( AWS_IOT_REJECTED_SUFFIX ) - 1 ) )

/**
 * @brief The JSON key used to represent client tokens for AWS IoT.
 */
#define AWS_IOT_CLIENT_TOKEN_KEY           "clientToken"

/**
 * @brief The length of #AWS_IOT_CLIENT_TOKEN_KEY.
 */
#define AWS_IOT_CLIENT_TOKEN_KEY_LENGTH    ( sizeof( AWS_IOT_CLIENT_TOKEN_KEY ) - 1 )

/**
 * @brief The length of the longest client token allowed by AWS IoT.
 */
#define AWS_IOT_CLIENT_TOKEN_MAX_LENGTH    ( 64 )

/**
 * @brief A flag to represent persistent subscriptions in a subscriptions
 * object.
 *
 * Its value is negative to distinguish it from valid subscription counts, which
 * are 0 or positive.
 */
#define AWS_IOT_PERSISTENT_SUBSCRIPTION    ( -1 )

/**
 * @brief Function pointer representing an MQTT blocking operation.
 *
 * Currently, this is used to represent @ref mqtt_function_subscribesync or
 * @ref mqtt_function_unsubscribesync.
 *
 * @param[in] mqttConnection The MQTT connection to use for the subscription.
 * @param[in] pSubscriptionList Pointer to the first element in the array of
 * subscriptions.
 * @param[in] subscriptionCount The number of elements in pSubscriptionList.
 * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.
 * Currently, flags are ignored by this function; this parameter is for
 * future-compatibility.
 * @param[in] timeoutMs If the MQTT server does not acknowledge the subscriptions within
 * this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT.
 *
 * @return One of the following:
 * - #IOT_MQTT_SUCCESS
 * - #IOT_MQTT_NOT_INITIALIZED
 * - #IOT_MQTT_BAD_PARAMETER
 * - #IOT_MQTT_NO_MEMORY
 * - #IOT_MQTT_NETWORK_ERROR
 * - #IOT_MQTT_SCHEDULING_ERROR
 * - #IOT_MQTT_BAD_RESPONSE
 * - #IOT_MQTT_TIMEOUT
 * - #IOT_MQTT_SERVER_REFUSED
 */
typedef IotMqttError_t ( * AwsIotMqttFunction_t )( IotMqttConnection_t mqttConnection,
                                                   const IotMqttSubscription_t * pSubscriptionList,
                                                   size_t subscriptionCount,
                                                   uint32_t flags,
                                                   uint32_t timeoutMs );

/**
 * @brief Function pointer representing an MQTT library callback function.
 *
 * @param[in] pArgument Ignored.
 * @param[in] pMessage The received DELTA document (as an MQTT PUBLISH message).
 */
typedef void ( * AwsIotMqttCallbackFunction_t )( void * pArgument,
                                                 IotMqttCallbackParam_t * pMessage );

/**
 * @brief Enumerations representing each of the statuses that may be parsed
 * from a topic.
 */
typedef enum AwsIotStatus
{
    AWS_IOT_ACCEPTED = 0, /**< Operation accepted. */
    AWS_IOT_REJECTED = 1, /**< Operation rejected. */
    AWS_IOT_UNKNOWN = 2   /**< Unknown status (neither accepted nor rejected). */
} AwsIotStatus_t;

/**
 * @brief Information required to generate a topic for AWS IoT.
 */
typedef struct AwsIotTopicInfo
{
    const char * pThingName;                 /**< @brief The Thing Name associated with the operation. */
    size_t thingNameLength;                  /**< @brief The length of `pThingName`. */
    const char * pOperationName;             /**< @brief The operation name to place in the topic. */
    uint16_t operationNameLength;            /**< @brief The length of `pOperationName`. */
    uint16_t longestSuffixLength;            /**< @brief The length of longest suffix that will be placed at the end of the topic. */
    void * ( *mallocString )( size_t size ); /**< @brief Function used to allocate a string, if needed. */
} AwsIotTopicInfo_t;

/**
 * @brief Information needed to modify AWS IoT subscription topics.
 *
 * @warning The buffer passed as `pTopicFilterBase` must be large enough to
 * accommodate the "/accepted" and "/rejected" suffixes.
 */
typedef struct AwsIotSubscriptionInfo_t
{
    IotMqttConnection_t mqttConnection;            /**< @brief The MQTT connection to use. */
    AwsIotMqttCallbackFunction_t callbackFunction; /**< @brief Callback function for MQTT subscribe. */
    uint32_t timeout;                              /**< @brief Timeout for MQTT function. */

    /* Topic filter. */
    char * pTopicFilterBase;        /**< @brief Contains the base topic filter, without "/accepted" or "/rejected". */
    uint16_t topicFilterBaseLength; /**< @brief Length of the base topic filter. */
} AwsIotSubscriptionInfo_t;

/**
 * @brief Thing Name and length, used to match subscriptions.
 */
typedef struct AwsIotThingName
{
    const char * pThingName; /**< @brief Thing Name to compare. */
    size_t thingNameLength;  /**< @brief Length of `pThingName`. */
} AwsIotThingName_t;

/**
 * @brief Initializes the lists used by AWS IoT operations.
 *
 * @param[in] pPendingOperationsList The list that holds pending operations for
 * a library.
 * @param[in] pSubscriptionsList The list that holds subscriptions for a library.
 * @param[in] pPendingOperationsMutex The mutex that guards the pending operations
 * list.
 * @param[in] pSubscriptionsMutex The mutex that guards the subscriptions list.
 *
 * @return `true` if all initialization succeeded; `false` otherwise.
 */
bool AwsIot_InitLists( IotListDouble_t * pPendingOperationsList,
                       IotListDouble_t * pSubscriptionsList,
                       IotMutex_t * pPendingOperationsMutex,
                       IotMutex_t * pSubscriptionsMutex );

/**
 * @brief Checks that a Thing Name is valid for AWS IoT.
 *
 * @param[in] pThingName Thing Name to validate.
 * @param[in] thingNameLength Length of `pThingName`.
 *
 * @return `true` if `pThingName` is valid; `false` otherwise.
 */
bool AwsIot_ValidateThingName( const char * pThingName,
                               size_t thingNameLength );

/**
 * @brief Extracts the client token from a JSON document.
 *
 * The client token is used to differentiate AWS IoT operations. It is unique per
 * operation.
 *
 * @param[in] pJsonDocument The JSON document to parse.
 * @param[in] jsonDocumentLength The length of `pJsonDocument`.
 * @param[out] pClientToken Set to point to the client token in `pJsonDocument`.
 * @param[out] pClientTokenLength Set to the length of the client token.
 *
 * @return `true` if the client token was found; `false` otherwise. The output
 * parameters are only valid if this function returns `true`.
 */
bool AwsIot_GetClientToken( const char * pJsonDocument,
                            size_t jsonDocumentLength,
                            const char ** pClientToken,
                            size_t * pClientTokenLength );

/**
 * @brief Parse the Thing Name from an MQTT topic.
 *
 * @param[in] pTopicName The topic to parse.
 * @param[in] topicNameLength The length of `pTopicName`.
 * @param[out] pThingName Set to point to the Thing Name.
 * @param[out] pThingNameLength Set to the length of the Thing Name.
 *
 * @return `true` if a Thing Name was successfully parsed; `false` otherwise. The output
 * parameters are only valid if this function returns `true`.
 */
bool AwsIot_ParseThingName( const char * pTopicName,
                            uint16_t topicNameLength,
                            const char ** pThingName,
                            size_t * pThingNameLength );

/**
 * @brief Parse the operation status (accepted or rejected) from an MQTT topic.
 *
 * @param[in] pTopicName The topic to parse.
 * @param[in] topicNameLength The length of `pTopicName`.
 *
 * @return Any #AwsIotStatus_t.
 */
AwsIotStatus_t AwsIot_ParseStatus( const char * pTopicName,
                                   uint16_t topicNameLength );

/**
 * @brief Generate a topic to use for an AWS IoT operation.
 *
 * @param[in] pTopicInfo Information needed to generate an AWS IoT topic.
 * @param[in,out] pTopicBuffer Where to place the generated topic. An existing
 * buffer may be passed in. If `NULL`, this function will attempt to allocate a
 * new buffer.
 * @param[out] pOperationTopicLength Set to the length of the generated topic.
 *
 * @warning This function does not check the length of `pTopicBuffer`! Any provided
 * buffer must be long enough to accommodate the Thing Name, operation name, and
 * any other suffixes.
 *
 * @return `true` if the topic was successfully generated; `false` otherwise.
 * This function will always succeed when an input buffer is provided.
 */
bool AwsIot_GenerateOperationTopic( const AwsIotTopicInfo_t * pTopicInfo,
                                    char ** pTopicBuffer,
                                    uint16_t * pOperationTopicLength );

/**
 * @brief Add or remove subscriptions for AWS IoT operations.
 *
 * @param[in] mqttOperation Either @ref mqtt_function_subscribesync or
 * @ref mqtt_function_unsubscribesync.
 * @param[in] pSubscriptionInfo Information needed to process an MQTT
 * operation.
 *
 * @return See the return values of @ref mqtt_function_subscribesync or
 * @ref mqtt_function_unsubscribesync.
 */
IotMqttError_t AwsIot_ModifySubscriptions( AwsIotMqttFunction_t mqttOperation,
                                           const AwsIotSubscriptionInfo_t * pSubscriptionInfo );

#endif /* ifndef AWS_IOT_H_ */