FreeRTOS: HTTPS Client
HTTPS Client v1.0.0 library
Return to main page ↑
iot_https_internal.h
1 /*
2  * FreeRTOS HTTPS Client V1.1.3
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * http://aws.amazon.com/freertos
23  * http://www.FreeRTOS.org
24  */
25 
26 #ifndef IOT_HTTPS_INTERNAL_H_
27 #define IOT_HTTPS_INTERNAL_H_
28 
29 /* The config header is always included first. */
30 #include "iot_config.h"
31 
32 /* Standard Includes. */
33 #include <string.h>
34 #include <stdbool.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 
38 /* Third party http-parser include. */
39 #include "http_parser.h"
40 
41 /* HTTPS Client library includes. */
42 #include "iot_https_client.h"
43 
44 /* Task pool include. */
45 #include "iot_taskpool.h"
46 
47 /* Linear containers (lists and queues) include. */
48 #include "iot_linear_containers.h"
49 
50 /* Types include. */
51 #include "types/iot_taskpool_types.h"
52 
53 /* Platform layer includes. */
54 #include "platform/iot_threads.h"
55 #include "platform/iot_network.h"
56 
57 /* Error handling include. */
58 #include "private/iot_error.h"
59 
60 /*-----------------------------------------------------------*/
61 
62 /* Convenience macros for handling errors in a standard way. */
63 
67 #define HTTPS_SUCCEEDED( x ) ( ( x ) == IOT_HTTPS_OK )
68 
72 #define HTTPS_FAILED( x ) ( ( x ) != IOT_HTTPS_OK )
73 
77 #define HTTPS_FUNCTION_ENTRY( result ) IOT_FUNCTION_ENTRY( IotHttpsReturnCode_t, result )
78 
82 #define HTTPS_GOTO_CLEANUP() IOT_GOTO_CLEANUP()
83 
87 #define HTTPS_SET_AND_GOTO_CLEANUP( statusValue ) IOT_SET_AND_GOTO_CLEANUP( statusValue )
88 
92 #define HTTPS_FUNCTION_CLEANUP_BEGIN() IOT_FUNCTION_CLEANUP_BEGIN()
93 
97 #define HTTPS_FUNCTION_CLEANUP_END() IOT_FUNCTION_CLEANUP_END()
98 
102 #define HTTPS_FUNCTION_EXIT_NO_CLEANUP() IOT_FUNCTION_EXIT_NO_CLEANUP()
103 
107 #define HTTPS_ON_NULL_ARG_GOTO_CLEANUP( ptr ) \
108  if( ( ptr == NULL ) ) \
109  { \
110  IotLogError( # ptr " was NULL." ); \
111  IOT_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); \
112  }
113 
117 #define HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( expr ) \
118  if( ( expr ) == false ) \
119  { \
120  IotLogError( # expr " must be true." ); \
121  IOT_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); \
122  }
123 
127 #define HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( expr, statusValue, ... ) \
128  if( ( expr ) == false ) \
129  { \
130  IotLogError( __VA_ARGS__ ); \
131  IOT_SET_AND_GOTO_CLEANUP( statusValue ); \
132  }
133 
134 /* Configure logs for HTTPS Client functions. */
135 #ifdef IOT_LOG_LEVEL_HTTPS
136  #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_HTTPS
137 #else
138  #ifdef IOT_LOG_LEVEL_GLOBAL
139  #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
140  #else
141  #define LIBRARY_LOG_LEVEL IOT_LOG_NONE
142  #endif
143 #endif
144 
145 #define LIBRARY_LOG_NAME ( "HTTPS Client" )
146 #include "iot_logging_setup.h"
147 
148 /*
149  * Provide default values for undefined memory allocation functions based on
150  * the usage of dynamic memory allocation.
151  */
152 #if IOT_STATIC_MEMORY_ONLY == 1
153  #include "private/iot_static_memory.h"
154 #endif
155 
162 #ifndef AWS_IOT_HTTPS_ENABLE_METRICS
163  #define AWS_IOT_HTTPS_ENABLE_METRICS ( 1 )
164 #endif
165 #ifndef IOT_HTTPS_USER_AGENT
166  #define IOT_HTTPS_USER_AGENT "amazon-freertos"
167 #endif
168 #ifndef IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE
169  #define IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE ( 1024 )
170 #endif
171 #ifndef IOT_HTTPS_RESPONSE_WAIT_MS
172  #define IOT_HTTPS_RESPONSE_WAIT_MS ( 1000 )
173 #endif
174 #ifndef IOT_HTTPS_MAX_HOST_NAME_LENGTH
175  #define IOT_HTTPS_MAX_HOST_NAME_LENGTH ( 255 ) /* Per FQDN, the maximum host name length is 255 bytes. */
176 #endif
177 #ifndef IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH
178  #define IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH ( 255 ) /* The maximum alpn protocols length is chosen arbitrarily. */
179 #endif
180 
186 #define HTTPS_PROTOCOL_VERSION "HTTP/1.1"
187 
191 #define HTTPS_EMPTY_PATH "/"
192 
196 #define HTTPS_CONNECT_METHOD "CONNECT"
197 
198 /*
199  * Constants for the values of the HTTP "Connection" header field.
200  *
201  * This is used for writing headers automatically during the sending of the HTTP request.
202  * "Connection: keep-alive\r\n" is written automatically for a persistent connection.
203  * "Connection: close\r\n" is written automatically for a non-persistent connection.
204  */
205 #define HTTPS_CONNECTION_KEEP_ALIVE_HEADER_VALUE "keep-alive"
206 #define HTTPS_CONNECTION_CLOSE_HEADER_VALUE "close"
207 
213 #define HTTPS_HEADER_FIELD_SEPARATOR ": "
214 #define HTTPS_HEADER_FIELD_SEPARATOR_LENGTH ( 2 )
215 #define COLON_CHARACTER ':'
216 #define SPACE_CHARACTER ' '
217 
223 #define HTTPS_END_OF_HEADER_LINES_INDICATOR "\r\n"
224 #define HTTPS_END_OF_HEADER_LINES_INDICATOR_LENGTH ( 2 )
225 #define CARRIAGE_RETURN_CHARACTER '\r'
226 #define NEWLINE_CHARACTER '\n'
227 
228 /*
229  * Constants for header fields added automatically during the request initialization.
230  */
231 #define HTTPS_USER_AGENT_HEADER "User-Agent"
232 #define HTTPS_HOST_HEADER "Host"
233 
234 /*
235  * Constants for the header fields added automatically during the sending of the HTTP request.
236  */
237 #define HTTPS_CONTENT_LENGTH_HEADER "Content-Length"
238 #define HTTPS_CONNECTION_HEADER "Connection"
239 
248 #define HTTPS_MAX_CONTENT_LENGTH_LINE_LENGTH ( 26 )
249 
256 #define FAST_MACRO_STRLEN( x ) ( ( sizeof( x ) / sizeof( char ) ) - 1 )
257 
258 /*-----------------------------------------------------------*/
259 
303 typedef enum IotHttpsResponseParserState
304 {
305  PARSER_STATE_NONE = 0,
306  PARSER_STATE_IN_HEADERS,
307  PARSER_STATE_HEADERS_COMPLETE,
308  PARSER_STATE_IN_BODY,
309  PARSER_STATE_BODY_COMPLETE
310 } IotHttpsResponseParserState_t;
311 
358 typedef enum IotHttpsResponseBufferState
359 {
360  PROCESSING_STATE_NONE,
361  PROCESSING_STATE_FILLING_HEADER_BUFFER,
362  PROCESSING_STATE_FILLING_BODY_BUFFER,
363  PROCESSING_STATE_FINISHED,
364  PROCESSING_STATE_SEARCHING_HEADER_BUFFER
365 } IotHttpsResponseBufferState_t;
366 
367 /*-----------------------------------------------------------*/
368 
372 typedef struct _httpsConnection
373 {
376  uint32_t timeout;
387  bool isDestroyed;
389  IotDeQueue_t reqQ;
390  IotDeQueue_t respQ;
391  IotTaskPoolJobStorage_t taskPoolJobStorage;
392  IotTaskPoolJob_t taskPoolJob;
394 
403 typedef struct _httpParserInfo
404 {
405  http_parser responseParser;
406  size_t ( * parseFunc )( http_parser * parser,
407  const http_parser_settings * settings,
408  const char * data,
409  size_t len );
410  http_parser readHeaderParser;
412 
416 typedef struct _httpsResponse
417 {
418  IotLink_t link;
419  uint8_t * pHeaders;
420  uint8_t * pHeadersEnd;
421  uint8_t * pHeadersCur;
422  uint8_t * pBody;
423  uint8_t * pBodyEnd;
424  uint8_t * pBodyCur;
426  uint16_t status;
428  IotHttpsResponseParserState_t parserState;
429  IotHttpsResponseBufferState_t bufferProcessingState;
437  struct _httpsConnection * pHttpsConnection;
438  bool isAsync;
439  uint8_t * pBodyInHeaderBuf;
442  bool cancelled;
455  void * pUserPrivData;
458 
462 typedef struct _httpsRequest
463 {
464  IotLink_t link;
465  uint8_t * pHeaders;
466  uint8_t * pHeadersEnd;
467  uint8_t * pHeadersCur;
468  uint8_t * pBody;
469  uint32_t bodyLength;
472  struct _httpsResponse * pHttpsResponse;
473  struct _httpsConnection * pHttpsConnection;
475  bool isAsync;
476  void * pUserPrivData;
478  bool cancelled;
480  bool scheduled;
482 
483 /*-----------------------------------------------------------*/
484 
490 extern const char * _pHttpsMethodStrings[];
491 
492 #endif /* IOT_HTTPS_INTERNAL_H_ */
IotSemaphore_t
_IotSystemSemaphore_t IotSemaphore_t
_httpsResponse_t::isNonPersistent
bool isNonPersistent
Non-persistent flag to indicate closing the connection immediately after receiving the response.
Definition: iot_https_internal.h:456
_httpsConnection_t::pNetworkInterface
const IotNetworkInterface_t * pNetworkInterface
Network interface with calls for connect, disconnect, send, and receive.
Definition: iot_https_internal.h:374
_httpsResponse_t::bodyRxStatus
IotHttpsReturnCode_t bodyRxStatus
The status of network receiving the HTTPS body to be returned during the IotHttpsClientCallbacks_t....
Definition: iot_https_internal.h:441
_httpsRequest_t::pHttpsResponse
struct _httpsResponse * pHttpsResponse
Response associated with request. This is initialized during IotHttpsClient_InitializeRequest(),...
Definition: iot_https_internal.h:472
_httpsRequest_t::isAsync
bool isAsync
This is set to true if this request is to be sent asynchronously. Set to false otherwise.
Definition: iot_https_internal.h:475
_httpParserInfo_t
Third party library http-parser information.
Definition: iot_https_internal.h:404
_httpsResponse_t::status
uint16_t status
The HTTP response status code of this response.
Definition: iot_https_internal.h:426
_httpsRequest_t::cancelled
bool cancelled
Set this to true to stop the response processing in the asynchronous workflow.
Definition: iot_https_internal.h:478
_httpsRequest_t::pHeadersEnd
uint8_t * pHeadersEnd
Pointer to the end of the headers buffer.
Definition: iot_https_internal.h:466
_httpsResponse_t::syncStatus
IotHttpsReturnCode_t syncStatus
The status of the synchronous response.
Definition: iot_https_internal.h:444
_httpsResponse_t::pReadHeaderField
char * pReadHeaderField
Header field that we want to read from the headers buffer when IotHttpsClient_ReadHeader() is called.
Definition: iot_https_internal.h:430
_httpsRequest_t
Represents and HTTP request.
Definition: iot_https_internal.h:463
IotMutex_t
_IotSystemMutex_t IotMutex_t
_httpParserInfo_t::readHeaderParser
http_parser readHeaderParser
http_parser state information for parsing the header buffer for reading a header.
Definition: iot_https_internal.h:410
_httpsResponse_t::parserState
IotHttpsResponseParserState_t parserState
The current state of the parser. See #IotHttpsResponseParserState_t documentation for more details.
Definition: iot_https_internal.h:428
_pHttpsMethodStrings
const char * _pHttpsMethodStrings[]
Definition of HTTP method enum to strings array.
Definition: iot_https_client.c:102
_httpsConnection_t::pNetworkConnection
void * pNetworkConnection
Pointer to the network connection to use pNetworkInterface calls on.
Definition: iot_https_internal.h:375
_httpsResponse_t::pBodyCurInHeaderBuf
uint8_t * pBodyCurInHeaderBuf
Pointer to the next location to write body data during processing of the header buffer....
Definition: iot_https_internal.h:440
_httpsConnection_t::isDestroyed
bool isDestroyed
true if the connection is already destroyed and we should call anymore
Definition: iot_https_internal.h:387
IotHttpsClientCallbacks_t
HTTPS Client library callbacks for asynchronous requests.
Definition: iot_https_types.h:529
_httpsConnection_t::timeout
uint32_t timeout
Timeout for a connection and waiting for a response from the network.
Definition: iot_https_internal.h:376
_httpsRequest_t::bodyLength
uint32_t bodyLength
Length of request body buffer.
Definition: iot_https_internal.h:469
_httpsResponse_t::pHttpsConnection
struct _httpsConnection * pHttpsConnection
Connection associated with response. This is set during IotHttpsClient_SendAsync()....
Definition: iot_https_internal.h:437
_httpsRequest_t::pUserPrivData
void * pUserPrivData
User private data to hand back in the asynchronous callbacks for context.
Definition: iot_https_internal.h:476
_httpsRequest_t::link
IotLink_t link
The link to insert the job in the connection's reqQ.
Definition: iot_https_internal.h:464
_httpsResponse_t::pHeaders
uint8_t * pHeaders
Pointer to the start of the headers buffer.
Definition: iot_https_internal.h:419
_httpsRequest_t::pCallbacks
IotHttpsClientCallbacks_t * pCallbacks
Pointer to the asynchronous request callbacks.
Definition: iot_https_internal.h:477
_httpsConnection_t::connectionMutex
IotMutex_t connectionMutex
Mutex protecting operations on this entire connection context.
Definition: iot_https_internal.h:388
_httpsResponse_t::pHeadersEnd
uint8_t * pHeadersEnd
Pointer to the end of the headers buffer.
Definition: iot_https_internal.h:420
_httpsResponse_t::pReadHeaderValue
char * pReadHeaderValue
Header value that we read from the headers buffer when IotHttpsClient_ReadHeader() is called.
Definition: iot_https_internal.h:432
_httpsResponse_t::pUserPrivData
void * pUserPrivData
User private data to hand back in the asynchronous callbacks for context.
Definition: iot_https_internal.h:455
IotHttpsMethod_t
IotHttpsMethod_t
Types of HTTP methods.
Definition: iot_https_types.h:449
_httpsResponse_t::pBodyEnd
uint8_t * pBodyEnd
Pointer to the end of the body buffer.
Definition: iot_https_internal.h:423
_httpsResponse_t::pCallbacks
IotHttpsClientCallbacks_t * pCallbacks
Pointer to the asynchronous request callbacks.
Definition: iot_https_internal.h:454
_httpsResponse_t
Represents an HTTP response.
Definition: iot_https_internal.h:417
IotNetworkInterface_t
_httpsResponse_t::respFinishedSem
IotSemaphore_t respFinishedSem
This is for synchronous response to post that is finished being received. It is better to use a task ...
Definition: iot_https_internal.h:443
_httpsResponse_t::httpParserInfo
_httpParserInfo_t httpParserInfo
Third party http-parser information.
Definition: iot_https_internal.h:425
_httpsResponse_t::pBodyCur
uint8_t * pBodyCur
Pointer to the next location to write in the body buffer.
Definition: iot_https_internal.h:424
_httpsConnection_t::reqQ
IotDeQueue_t reqQ
The queue for the requests that are not finished yet.
Definition: iot_https_internal.h:389
_httpsResponse_t::readHeaderFieldLength
size_t readHeaderFieldLength
Length of pReadHeaderField.
Definition: iot_https_internal.h:431
_httpsConnection_t::respQ
IotDeQueue_t respQ
The queue for the responses that are waiting to be processed.
Definition: iot_https_internal.h:390
_httpsRequest_t::pBody
uint8_t * pBody
Pointer to the start of the body buffer.
Definition: iot_https_internal.h:468
_httpsResponse_t::cancelled
bool cancelled
This is set to true to stop the request/response processing in the asynchronous request workflow.
Definition: iot_https_internal.h:442
_httpsResponse_t::pBodyInHeaderBuf
uint8_t * pBodyInHeaderBuf
Pointer to the start of body inside the header buffer for copying to a body buffer provided later by ...
Definition: iot_https_internal.h:439
_httpsRequest_t::pHttpsConnection
struct _httpsConnection * pHttpsConnection
Connection associated with request. This is set during IotHttpsClient_SendAsync()....
Definition: iot_https_internal.h:473
_httpsResponse_t::pBody
uint8_t * pBody
Pointer to the start of the body buffer.
Definition: iot_https_internal.h:422
_httpsRequest_t::method
IotHttpsMethod_t method
The method of the originating request.
Definition: iot_https_internal.h:470
_httpsResponse_t::readHeaderValueLength
size_t readHeaderValueLength
Length of pReadHeaderValue.
Definition: iot_https_internal.h:433
_httpsResponse_t::link
IotLink_t link
The link to insert the job in the connection's respQ.
Definition: iot_https_internal.h:418
_httpsRequest_t::pConnInfo
IotHttpsConnectionInfo_t * pConnInfo
Connection info associated with this request. For an implicit connection.
Definition: iot_https_internal.h:471
_httpsResponse_t::bufferProcessingState
IotHttpsResponseBufferState_t bufferProcessingState
Which buffer is currently being processed and for what. See #IotHttpsResponseBufferState_t documentat...
Definition: iot_https_internal.h:429
_httpsRequest_t::isNonPersistent
bool isNonPersistent
Non-persistent flag to indicate closing the connection immediately after receiving the response.
Definition: iot_https_internal.h:474
_httpsResponse_t::foundHeaderField
bool foundHeaderField
State to use during parsing to let us know when we found the header field in the https-parser callbac...
Definition: iot_https_internal.h:434
_httpsResponse_t::pHeadersCur
uint8_t * pHeadersCur
Pointer to the next location to write in the headers buffer.
Definition: iot_https_internal.h:421
iot_https_client.h
User-facing functions of the FreeRTOS HTTPS Client library.
_httpsResponse_t::reqFinishedSending
bool reqFinishedSending
This is set to true to when the request is finished being sent on the network.
Definition: iot_https_internal.h:453
_httpsRequest_t::pHeaders
uint8_t * pHeaders
Pointer to the start of the headers buffer.
Definition: iot_https_internal.h:465
_httpsResponse_t::method
IotHttpsMethod_t method
The method of the originating request.
Definition: iot_https_internal.h:427
iot_threads.h
_httpsConnection_t::taskPoolJob
IotTaskPoolJob_t taskPoolJob
The task pool job identifier for an asynchronous request.
Definition: iot_https_internal.h:392
_httpsRequest_t::bodyTxStatus
IotHttpsReturnCode_t bodyTxStatus
The status of network sending the HTTPS body to be returned during the IotHttpsClientCallbacks_t....
Definition: iot_https_internal.h:479
_httpsConnection_t::isConnected
bool isConnected
true if a connection was successful most recently on this context
Definition: iot_https_internal.h:386
IotHttpsReturnCode_t
IotHttpsReturnCode_t
Return codes of HTTPS Client functions.
Definition: iot_https_types.h:294
iot_network.h
_httpsResponse_t::isAsync
bool isAsync
This is set to true if this response is to be retrieved asynchronously. Set to false otherwise.
Definition: iot_https_internal.h:438
IotHttpsConnectionInfo_t
HTTP connection configuration.
Definition: iot_https_types.h:721
_httpsConnection_t::taskPoolJobStorage
IotTaskPoolJobStorage_t taskPoolJobStorage
An asynchronous operation requires storage for the task pool job.
Definition: iot_https_internal.h:391
_httpsRequest_t::pHeadersCur
uint8_t * pHeadersCur
Pointer to the next location to write in the headers buffer.
Definition: iot_https_internal.h:467
_httpParserInfo_t::responseParser
http_parser responseParser
http_parser state information for parsing the response.
Definition: iot_https_internal.h:405
_httpsRequest_t::scheduled
bool scheduled
Set to true when this request has already been scheduled to the task pool.
Definition: iot_https_internal.h:480
_httpsConnection_t
Represents an HTTP connection.
Definition: iot_https_internal.h:373