2 * AWS IoT Common V1.0.0
\r
3 * Copyright (C) 2019 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
24 * @file aws_iot_parser.c
\r
25 * @brief Parses topics for Thing Name and status.
\r
28 /* The config header is always included first. */
\r
29 #include "iot_config.h"
\r
31 /* Standard includes. */
\r
34 /* AWS IoT include. */
\r
35 #include "aws_iot.h"
\r
37 /* Error handling include. */
\r
38 #include "iot_error.h"
\r
40 /* AWS Parser include. */
\r
41 #include "aws_iot_doc_parser.h"
\r
44 * @brief Minimum allowed topic length for an AWS IoT status topic.
\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
52 #define MINIMUM_TOPIC_NAME_LENGTH \
\r
53 ( uint16_t ) ( AWS_IOT_TOPIC_PREFIX_LENGTH + \
\r
54 AWS_IOT_ACCEPTED_SUFFIX_LENGTH + \
\r
58 * @brief The longest client token accepted by AWS IoT service, per AWS IoT
\r
61 #define MAX_CLIENT_TOKEN_LENGTH ( 64 )
\r
63 /*-----------------------------------------------------------*/
\r
65 bool AwsIot_GetClientToken( const char * pJsonDocument,
\r
66 size_t jsonDocumentLength,
\r
67 const char ** pClientToken,
\r
68 size_t * pClientTokenLength )
\r
70 /* Extract the client token from the JSON document. */
\r
71 bool status = AwsIotDocParser_FindValue( pJsonDocument,
\r
73 AWS_IOT_CLIENT_TOKEN_KEY,
\r
74 AWS_IOT_CLIENT_TOKEN_KEY_LENGTH,
\r
76 pClientTokenLength );
\r
78 if( status == true )
\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
91 /*-----------------------------------------------------------*/
\r
93 bool AwsIot_ParseThingName( const char * pTopicName,
\r
94 uint16_t topicNameLength,
\r
95 const char ** pThingName,
\r
96 size_t * pThingNameLength )
\r
98 IOT_FUNCTION_ENTRY( bool, true );
\r
99 const char * pThingNameStart = NULL;
\r
100 size_t thingNameLength = 0;
\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
105 IOT_SET_AND_GOTO_CLEANUP( false );
\r
108 /* Check that the given topic starts with the common prefix. */
\r
109 if( strncmp( AWS_IOT_TOPIC_PREFIX,
\r
111 AWS_IOT_TOPIC_PREFIX_LENGTH ) != 0 )
\r
113 IOT_SET_AND_GOTO_CLEANUP( false );
\r
116 /* The Thing Name starts immediately after the topic prefix. */
\r
117 pThingNameStart = pTopicName + AWS_IOT_TOPIC_PREFIX_LENGTH;
\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
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
130 IOT_SET_AND_GOTO_CLEANUP( false );
\r
133 /* Set the output parameters. */
\r
134 *pThingName = pThingNameStart;
\r
135 *pThingNameLength = thingNameLength;
\r
137 IOT_FUNCTION_EXIT_NO_CLEANUP();
\r
140 /*-----------------------------------------------------------*/
\r
142 AwsIotStatus_t AwsIot_ParseStatus( const char * pTopicName,
\r
143 uint16_t topicNameLength )
\r
145 IOT_FUNCTION_ENTRY( AwsIotStatus_t, AWS_IOT_UNKNOWN );
\r
146 const char * pSuffixStart = NULL;
\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
151 Iot_DefaultAssert( AWS_IOT_ACCEPTED_SUFFIX_LENGTH == AWS_IOT_REJECTED_SUFFIX_LENGTH );
\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
158 /* Calculate where the "accepted" suffix should start. */
\r
159 pSuffixStart = pTopicName + topicNameLength - AWS_IOT_ACCEPTED_SUFFIX_LENGTH;
\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
166 IOT_SET_AND_GOTO_CLEANUP( AWS_IOT_ACCEPTED );
\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
174 IOT_SET_AND_GOTO_CLEANUP( AWS_IOT_REJECTED );
\r
178 IOT_FUNCTION_EXIT_NO_CLEANUP();
\r
181 /*-----------------------------------------------------------*/
\r