]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/aws/common/src/aws_iot_parser.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-IoT-Libraries / c_sdk / aws / common / src / aws_iot_parser.c
1 /*\r
2  * AWS IoT Common V1.0.0\r
3  * Copyright (C) 2019 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 \r
23 /**\r
24  * @file aws_iot_parser.c\r
25  * @brief Parses topics for Thing Name and status.\r
26  */\r
27 \r
28 /* The config header is always included first. */\r
29 #include "iot_config.h"\r
30 \r
31 /* Standard includes. */\r
32 #include <string.h>\r
33 \r
34 /* AWS IoT include. */\r
35 #include "aws_iot.h"\r
36 \r
37 /* Error handling include. */\r
38 #include "iot_error.h"\r
39 \r
40 /* AWS Parser include. */\r
41 #include "aws_iot_doc_parser.h"\r
42 \r
43 /**\r
44  * @brief Minimum allowed topic length for an AWS IoT status topic.\r
45  *\r
46  * Topics must contain at least:\r
47  * - The common prefix\r
48  * - The suffix "/accepted" or "/rejected"\r
49  * - 1 character for the Thing Name\r
50  * - 2 characters for the operation name and the enclosing slashes\r
51  */\r
52 #define MINIMUM_TOPIC_NAME_LENGTH                   \\r
53     ( uint16_t ) ( AWS_IOT_TOPIC_PREFIX_LENGTH +    \\r
54                    AWS_IOT_ACCEPTED_SUFFIX_LENGTH + \\r
55                    1 + 2 )\r
56 \r
57 /**\r
58  * @brief The longest client token accepted by AWS IoT service, per AWS IoT\r
59  * service limits.\r
60  */\r
61 #define MAX_CLIENT_TOKEN_LENGTH    ( 64 )\r
62 \r
63 /*-----------------------------------------------------------*/\r
64 \r
65 bool AwsIot_GetClientToken( const char * pJsonDocument,\r
66                             size_t jsonDocumentLength,\r
67                             const char ** pClientToken,\r
68                             size_t * pClientTokenLength )\r
69 {\r
70     /* Extract the client token from the JSON document. */\r
71     bool status = AwsIotDocParser_FindValue( pJsonDocument,\r
72                                              jsonDocumentLength,\r
73                                              AWS_IOT_CLIENT_TOKEN_KEY,\r
74                                              AWS_IOT_CLIENT_TOKEN_KEY_LENGTH,\r
75                                              pClientToken,\r
76                                              pClientTokenLength );\r
77 \r
78     if( status == true )\r
79     {\r
80         /* Check that the length of the client token is valid. */\r
81         if( ( *pClientTokenLength < 2 ) ||\r
82             ( *pClientTokenLength > MAX_CLIENT_TOKEN_LENGTH ) )\r
83         {\r
84             status = false;\r
85         }\r
86     }\r
87 \r
88     return status;\r
89 }\r
90 \r
91 /*-----------------------------------------------------------*/\r
92 \r
93 bool AwsIot_ParseThingName( const char * pTopicName,\r
94                             uint16_t topicNameLength,\r
95                             const char ** pThingName,\r
96                             size_t * pThingNameLength )\r
97 {\r
98     IOT_FUNCTION_ENTRY( bool, true );\r
99     const char * pThingNameStart = NULL;\r
100     size_t thingNameLength = 0;\r
101 \r
102     /* Check that the topic name is at least as long as the minimum allowed. */\r
103     if( topicNameLength < MINIMUM_TOPIC_NAME_LENGTH )\r
104     {\r
105         IOT_SET_AND_GOTO_CLEANUP( false );\r
106     }\r
107 \r
108     /* Check that the given topic starts with the common prefix. */\r
109     if( strncmp( AWS_IOT_TOPIC_PREFIX,\r
110                  pTopicName,\r
111                  AWS_IOT_TOPIC_PREFIX_LENGTH ) != 0 )\r
112     {\r
113         IOT_SET_AND_GOTO_CLEANUP( false );\r
114     }\r
115 \r
116     /* The Thing Name starts immediately after the topic prefix. */\r
117     pThingNameStart = pTopicName + AWS_IOT_TOPIC_PREFIX_LENGTH;\r
118 \r
119     /* Calculate the length of the Thing Name, which is terminated with a '/'. */\r
120     while( ( thingNameLength + AWS_IOT_TOPIC_PREFIX_LENGTH < ( size_t ) topicNameLength ) &&\r
121            ( pThingNameStart[ thingNameLength ] != '/' ) )\r
122     {\r
123         thingNameLength++;\r
124     }\r
125 \r
126     /* The end of the topic name was reached without finding a '/'. The topic\r
127      * name is invalid. */\r
128     if( thingNameLength + AWS_IOT_TOPIC_PREFIX_LENGTH >= ( size_t ) topicNameLength )\r
129     {\r
130         IOT_SET_AND_GOTO_CLEANUP( false );\r
131     }\r
132 \r
133     /* Set the output parameters. */\r
134     *pThingName = pThingNameStart;\r
135     *pThingNameLength = thingNameLength;\r
136 \r
137     IOT_FUNCTION_EXIT_NO_CLEANUP();\r
138 }\r
139 \r
140 /*-----------------------------------------------------------*/\r
141 \r
142 AwsIotStatus_t AwsIot_ParseStatus( const char * pTopicName,\r
143                                    uint16_t topicNameLength )\r
144 {\r
145     IOT_FUNCTION_ENTRY( AwsIotStatus_t, AWS_IOT_UNKNOWN );\r
146     const char * pSuffixStart = NULL;\r
147 \r
148     /* Both 'accepted' and  'rejected' topics are of the same length\r
149      * The below is a defensive check at run time to ensure that.\r
150      */\r
151     Iot_DefaultAssert( AWS_IOT_ACCEPTED_SUFFIX_LENGTH == AWS_IOT_REJECTED_SUFFIX_LENGTH );\r
152 \r
153     /* Check that the status topic name is at least as long as the\r
154      * "accepted" suffix. This length check will be good for rejected also\r
155      * as both are of 8 characters in length. */\r
156     if( topicNameLength > AWS_IOT_ACCEPTED_SUFFIX_LENGTH )\r
157     {\r
158         /* Calculate where the "accepted" suffix should start. */\r
159         pSuffixStart = pTopicName + topicNameLength - AWS_IOT_ACCEPTED_SUFFIX_LENGTH;\r
160 \r
161         /* Check if the end of the status topic name is "/accepted". */\r
162         if( strncmp( pSuffixStart,\r
163                      AWS_IOT_ACCEPTED_SUFFIX,\r
164                      AWS_IOT_ACCEPTED_SUFFIX_LENGTH ) == 0 )\r
165         {\r
166             IOT_SET_AND_GOTO_CLEANUP( AWS_IOT_ACCEPTED );\r
167         }\r
168 \r
169         /* Check if the end of the status topic name is "/rejected". */\r
170         if( strncmp( pSuffixStart,\r
171                      AWS_IOT_REJECTED_SUFFIX,\r
172                      AWS_IOT_REJECTED_SUFFIX_LENGTH ) == 0 )\r
173         {\r
174             IOT_SET_AND_GOTO_CLEANUP( AWS_IOT_REJECTED );\r
175         }\r
176     }\r
177 \r
178     IOT_FUNCTION_EXIT_NO_CLEANUP();\r
179 }\r
180 \r
181 /*-----------------------------------------------------------*/\r