]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/https/src/private/iot_https_internal.h
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-IoT-Libraries / c_sdk / standard / https / src / private / iot_https_internal.h
1 /*\r
2  * Amazon FreeRTOS HTTPS Client V1.1.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  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 #ifndef IOT_HTTPS_INTERNAL_H_\r
27 #define IOT_HTTPS_INTERNAL_H_\r
28 \r
29 /* The config header is always included first. */\r
30 #include "iot_config.h"\r
31 \r
32 /* Standard Includes. */\r
33 #include <string.h>\r
34 #include <stdbool.h>\r
35 #include <stdlib.h>\r
36 #include <stdio.h>\r
37 \r
38 /* Third party http-parser include. */\r
39 #include "http_parser.h"\r
40 \r
41 /* HTTPS Client library includes. */\r
42 #include "iot_https_client.h"\r
43 \r
44 /* Task pool include. */\r
45 #include "iot_taskpool_freertos.h"\r
46 \r
47 /* Linear containers (lists and queues) include. */\r
48 #include "iot_linear_containers.h"\r
49 \r
50 /* Types include. */\r
51 #include "types/iot_taskpool_types_freertos.h"\r
52 \r
53 /* Platform layer includes. */\r
54 #include "platform/iot_threads.h"\r
55 #include "platform/iot_network.h"\r
56 \r
57 /* Error handling include. */\r
58 #include "iot_error.h"\r
59 \r
60 /*-----------------------------------------------------------*/\r
61 \r
62 /* Convenience macros for handling errors in a standard way. */\r
63 \r
64 /**\r
65  * @brief Every public API return an enumeration value with an underlying value of 0 in case of success.\r
66  */\r
67 #define HTTPS_SUCCEEDED( x )                         ( ( x ) == IOT_HTTPS_OK )\r
68 \r
69 /**\r
70  * @brief Every public API returns an enumeration value with an underlying value different than 0 in case of success.\r
71  */\r
72 #define HTTPS_FAILED( x )                            ( ( x ) != IOT_HTTPS_OK )\r
73 \r
74 /**\r
75  * @brief Declare the storage for the error status variable.\r
76  */\r
77 #define HTTPS_FUNCTION_ENTRY( result )               IOT_FUNCTION_ENTRY( IotHttpsReturnCode_t, result )\r
78 \r
79 /**\r
80  * @brief Jump to the cleanup area.\r
81  */\r
82 #define HTTPS_GOTO_CLEANUP()                         IOT_GOTO_CLEANUP()\r
83 \r
84 /**\r
85  * @brief Set error and leave.\r
86  */\r
87 #define HTTPS_SET_AND_GOTO_CLEANUP( statusValue )    IOT_SET_AND_GOTO_CLEANUP( statusValue )\r
88 \r
89 /**\r
90  * @brief Initialize error and declare start of cleanup area.\r
91  */\r
92 #define HTTPS_FUNCTION_CLEANUP_BEGIN()               IOT_FUNCTION_CLEANUP_BEGIN()\r
93 \r
94 /**\r
95  * @brief Initialize error and declare end of cleanup area.\r
96  */\r
97 #define HTTPS_FUNCTION_CLEANUP_END()                 IOT_FUNCTION_CLEANUP_END()\r
98 \r
99 /**\r
100  * @brief Create an empty cleanup area.\r
101  */\r
102 #define HTTPS_FUNCTION_EXIT_NO_CLEANUP()             IOT_FUNCTION_EXIT_NO_CLEANUP()\r
103 \r
104 /**\r
105  * @brief Exit if an argument is NULL.\r
106  */\r
107 #define HTTPS_ON_NULL_ARG_GOTO_CLEANUP( ptr )                    \\r
108     if( ( ptr == NULL ) )                                        \\r
109     {                                                            \\r
110         IotLogError( # ptr " was NULL." );                       \\r
111         IOT_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); \\r
112     }\r
113 \r
114 /**\r
115  * @brief Exit if an condition is false.\r
116  */\r
117 #define HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( expr )                  \\r
118     if( ( expr ) == false )                                      \\r
119     {                                                            \\r
120         IotLogError( # expr " must be true." );                  \\r
121         IOT_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); \\r
122     }\r
123 \r
124 /**\r
125  * @brief Exit if an argument is false with a message.\r
126  */\r
127 #define HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( expr, statusValue, ... ) \\r
128     if( ( expr ) == false )                                           \\r
129     {                                                                 \\r
130         IotLogError( __VA_ARGS__ );                                   \\r
131         IOT_SET_AND_GOTO_CLEANUP( statusValue );                      \\r
132     }\r
133 \r
134 /* Configure logs for HTTPS Client functions. */\r
135 #ifdef IOT_LOG_LEVEL_HTTPS\r
136     #define LIBRARY_LOG_LEVEL        IOT_LOG_LEVEL_HTTPS\r
137 #else\r
138     #ifdef IOT_LOG_LEVEL_GLOBAL\r
139         #define LIBRARY_LOG_LEVEL    IOT_LOG_LEVEL_GLOBAL\r
140     #else\r
141         #define LIBRARY_LOG_LEVEL    IOT_LOG_NONE\r
142     #endif\r
143 #endif\r
144 \r
145 #define LIBRARY_LOG_NAME    ( "HTTPS Client" )\r
146 #include "iot_logging_setup.h"\r
147 \r
148 /*\r
149  * Provide default values for undefined memory allocation functions based on\r
150  * the usage of dynamic memory allocation.\r
151  */\r
152 #if IOT_STATIC_MEMORY_ONLY == 1\r
153     #include "iot_static_memory.h"\r
154 #endif\r
155 \r
156 /**\r
157  * @cond DOXYGEN_IGNORE\r
158  * Doxygen should ignore this section.\r
159  *\r
160  * Provide default values for undefined configuration constants.\r
161  */\r
162 #ifndef AWS_IOT_HTTPS_ENABLE_METRICS\r
163     #define AWS_IOT_HTTPS_ENABLE_METRICS           ( 1 )\r
164 #endif\r
165 #ifndef IOT_HTTPS_USER_AGENT\r
166     #define IOT_HTTPS_USER_AGENT                   "FreeRTOS"\r
167 #endif\r
168 #ifndef IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE\r
169     #define IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE        ( 1024 )\r
170 #endif\r
171 #ifndef IOT_HTTPS_RESPONSE_WAIT_MS\r
172     #define IOT_HTTPS_RESPONSE_WAIT_MS             ( 1000 )\r
173 #endif\r
174 #ifndef IOT_HTTPS_MAX_HOST_NAME_LENGTH\r
175     #define IOT_HTTPS_MAX_HOST_NAME_LENGTH         ( 255 ) /* Per FQDN, the maximum host name length is 255 bytes. */\r
176 #endif\r
177 #ifndef IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH\r
178     #define IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH    ( 255 ) /* The maximum alpn protocols length is chosen arbitrarily. */\r
179 #endif\r
180 \r
181 /** @endcond */\r
182 \r
183 /**\r
184  * @brief The HTTP protocol version of this library is HTTP/1.1.\r
185  */\r
186 #define HTTPS_PROTOCOL_VERSION                        "HTTP/1.1"\r
187 \r
188 /**\r
189  * @brief An empty path for a NULL specified path in the request initialization configuration.\r
190  */\r
191 #define HTTPS_EMPTY_PATH                              "/"\r
192 \r
193 /**\r
194  * @brief HTTPS "CONNECT" method, defined as the longest string length method.\r
195  */\r
196 #define HTTPS_CONNECT_METHOD                          "CONNECT"\r
197 \r
198 /*\r
199  * Constants for the values of the HTTP "Connection" header field.\r
200  *\r
201  * This is used for writing headers automatically during the sending of the HTTP request.\r
202  * "Connection: keep-alive\r\n" is written automatically for a persistent connection.\r
203  * "Connection: close\r\n" is written automatically for a non-persistent connection.\r
204  */\r
205 #define HTTPS_CONNECTION_KEEP_ALIVE_HEADER_VALUE      "keep-alive"\r
206 #define HTTPS_CONNECTION_CLOSE_HEADER_VALUE           "close"\r
207 \r
208 /**\r
209  * Constants for HTTP header formatting.\r
210  *\r
211  * ": " separates and header field from the header value.\r
212  */\r
213 #define HTTPS_HEADER_FIELD_SEPARATOR                  ": "\r
214 #define HTTPS_HEADER_FIELD_SEPARATOR_LENGTH           ( 2 )\r
215 #define COLON_CHARACTER                               ':'\r
216 #define SPACE_CHARACTER                               ' '\r
217 \r
218 /**\r
219  * Constants for HTTP header formatting.\r
220  *\r
221  * "\r\n" Ends the header line.\r
222  */\r
223 #define HTTPS_END_OF_HEADER_LINES_INDICATOR           "\r\n"\r
224 #define HTTPS_END_OF_HEADER_LINES_INDICATOR_LENGTH    ( 2 )\r
225 #define CARRIAGE_RETURN_CHARACTER                     '\r'\r
226 #define NEWLINE_CHARACTER                             '\n'\r
227 \r
228 /*\r
229  * Constants for header fields added automatically during the request initialization.\r
230  */\r
231 #define HTTPS_USER_AGENT_HEADER                       "User-Agent"\r
232 #define HTTPS_HOST_HEADER                             "Host"\r
233 \r
234 /*\r
235  * Constants for the header fields added automatically during the sending of the HTTP request.\r
236  */\r
237 #define HTTPS_CONTENT_LENGTH_HEADER                   "Content-Length"\r
238 #define HTTPS_CONNECTION_HEADER                       "Connection"\r
239 \r
240 /**\r
241  * @brief The maximum Content-Length header line size.\r
242  *\r
243  * This is the length of header line string: "Content-Length: 4294967296\r\n". 4294967296 is 2^32. This number is chosen\r
244  * because it is the maximum file size that can be represented in a 32 bit system.\r
245  *\r
246  * This is used to initialize a local array for the final headers to send.\r
247  */\r
248 #define HTTPS_MAX_CONTENT_LENGTH_LINE_LENGTH          ( 26 )\r
249 \r
250 /**\r
251  * @brief Macro for fast string length calculation of string macros.\r
252  *\r
253  * We subtract 1 to subtract the NULL terminating character.\r
254  * We do not assume that the size of a character is a single byte or 8 bits with this calculation.\r
255  */\r
256 #define FAST_MACRO_STRLEN( x )    ( ( sizeof( x ) / sizeof( char ) ) - 1 )\r
257 \r
258 /*-----------------------------------------------------------*/\r
259 \r
260 /**\r
261  * @brief The state of the HTTP response parsing.\r
262  *\r
263  * This state notes what has been parsed in the HTTP response. As soon as any part of the HTTP response is received from\r
264  * the network, it is sent to be parsed.\r
265  *\r
266  * The states move as follows:\r
267  * PARSER_STATE_NONE --> PARSER_STATE_IN_HEADERS --> PARSER_STATE_HEADERS_COMPLETE --> PARSER_STATE_BODY_COMPLETE\r
268  *\r
269  * The parser callbacks are called in the following order:\r
270  * 1. _httpParserOnMessageBeginCallback()\r
271  * 2. _httpParserOnStatusCallback()\r
272  * 3. _httpParserOnHeaderFieldCallback()\r
273  * 4. _httpParserOnHeaderValueCallback()\r
274  * 5. _httpParserOnHeadersCompleteCallback()\r
275  * 6. _httpParserOnChunkHeaderCallback() (optional only if the response is chunked)\r
276  * 7. _httpParserOnBodyCallback()\r
277  * 8. _httpParserOnChunkCompleteCallback() (optional only if the response is chunked)\r
278  * 9. _httpParserOnMessageCompleteCallback()\r
279  *\r
280  * Theses states are set in the parser callbacks and used outside the callbacks to determine action.\r
281  *\r
282  * PARSER_STATE_NONE is assigned to #_httpsResponse_t.parserState when the _httpsResponse_t.parserState is initialized\r
283  * in @ref IotHttpsClient_InitializeRequest and before parsing a new respone message from the server.\r
284  *\r
285  * PARSER_STATE_IN_HEADERS is assigned at the start of the HTTP Response message. This occurs in the\r
286  * _httpParserOnMessageBeginCallback(). HTTP headers are always first and there is always the response status line\r
287  * and some headers in a response message according to RFC 2616.\r
288  *\r
289  * PARSER_STATE_HEADERS_COMPLETE is assigned when all of the headers are finished being parsed in the HTTP response\r
290  * message. This occurs in the _httpParserOnHeadersCompleteCallback(). The state can end here if the response has no\r
291  * body, like for a response to a HEAD request.\r
292  * If this state is not reached after receiving headers from the network into the user configured header buffer and\r
293  * running it through the parser, then we know that not all of the headers from the response could fit into the buffer.\r
294  *\r
295  * PARSER_STATE_IN_BODY is assigned each time the parser reaches HTTP response body. This occurs in the\r
296  * _httpParserOnBodyCallback().\r
297  *\r
298  * PARSER_STATE_BODY_COMPLETE is assigned when the parser has finished with the whole HTTP response message. This\r
299  * happens when _httpParserOnMessageCompleteCallback() is invoked.\r
300  * If this state is not reached after receiving body from the network into the user configured body buffer and\r
301  * running it through the parser, then we know that not all of the body from the response could fit into the buffer.\r
302  */\r
303 typedef enum IotHttpsResponseParserState\r
304 {\r
305     PARSER_STATE_NONE = 0,         /**< @brief The parser has not started so we are neither in the headers or the body. */\r
306     PARSER_STATE_IN_HEADERS,       /**< @brief The parser is currently parsing the HTTP respone headers. */\r
307     PARSER_STATE_HEADERS_COMPLETE, /**< @brief The parser has finished parsing the headers. */\r
308     PARSER_STATE_IN_BODY,          /**< @brief The parser is currently parsing the HTTP response body. */\r
309     PARSER_STATE_BODY_COMPLETE     /**< @brief The parser has completed parsing the HTTP response body. */\r
310 } IotHttpsResponseParserState_t;\r
311 \r
312 /**\r
313  * @brief The state denoting which buffer (the header buffer or the body buffer) is currently being processed\r
314  * and for what.\r
315  *\r
316  * This state is set outside of the parser callbacks and used inside the of parser callbacks to determine actions.\r
317  *\r
318  * The state moves as follows:\r
319  * Receiving and parsing a response: PROCESSING_STATE_NONE --> PROCESSING_STATE_FILLING_HEADER_BUFFER --> PROCESSING_STATE_FILLING_BODY_BUFFER --> PROCESSING_STATE_FINISHED\r
320  * Searching a response for headers: ((enter state)) --> PROCESSING_STATE_SEARCHING_HEADER_BUFFER --> ((enter state))\r
321  *\r
322  * PROCESSING_STATE_NONE is assigned when #_httpsResponse_t.bufferProcessingState is initialized in\r
323  * @ref IotHttpsClient_InitializeRequest.\r
324  *\r
325  * PROCESSING_STATE_FILLING_HEADER_BUFFER is assigned at the start of receiving HTTP response headers from the network\r
326  * into the header buffer, before processing the received headers with the parser.\r
327  * This state is then used in the parser callbacks _httpParserOnStatusCallback(), _httpParserOnHeaderFieldCallback(),\r
328  * _httpParserOnHeaderValueCallback(), and _httpParserOnHeadersCompleteCallback() to move the\r
329  * #_httpsResponse_t.headersCur pointer along in the header buffer.\r
330  * Since the server sends the HTTP response as a single continuous message, sometimes during receiving of the HTTP\r
331  * headers we may receive part or all of the HTTP response body:\r
332  * ((example header buffer))[headers headers headers headers body body body]\r
333  * When parsing this header buffer the parser will execute _httpParserOnBodyCallback() in the\r
334  * PROCESSING_STATE_FILLING_HEADER_BUFFER state. The state is used here, for an asynchronous response, to save where\r
335  * and how much body is inside the of the header buffer. When a body buffer becomes available, the body in the header\r
336  * buffer will be copied to the body buffer.\r
337  *\r
338  * PROCESSING_STATE_FILLING_BODY_BUFFER is assigned at the start of receiving the HTTP response body form the network\r
339  * into the body buffer, before processing the received body with the parser.\r
340  *\r
341  * PROCESSING_STATE_FINISHED is assigned at the end of IotHttpsClient_SendSync() or at the end of\r
342  * IotHttpsClient_SendAsync() when both the header and body buffer are finished being filled with network data and\r
343  * parsed.\r
344  *\r
345  * PROCESSING_STATE_SEARCHING_HEADER_BUFFER is assigned in IotHttpsClient_ReadHeader() when searching for a header\r
346  * in the header buffer.\r
347  * This state is used in the parser callback _httpParserOnHeaderFieldCallback() to check if the current header field\r
348  * parsed equals the header we are searching for. It is used in parser callback _httpParserOnHeaderValueCallback() to\r
349  * return the header value if the corresponding field we are searching for was found. It is used in parser callback\r
350  * _httpParserOnHeadersCompleteCallback() to stop parsing the header buffer if the header we are searching for was not\r
351  * found.\r
352  *\r
353  * The header buffer is separate from the body buffer.\r
354  * The header buffer is configured in #IotHttpRequestInfo_t.respUserBuff. The body buffer is configured in\r
355  * #IotHttpRequestInfo_t.syncInfo->respData or as buffer provided asynchronously during the\r
356  * #IotHttpsClientCallbacks_t.readReadyCallback() to call to @ref IotHttpsClient_ReadResponseBody().\r
357  */\r
358 typedef enum IotHttpsResponseBufferState\r
359 {\r
360     PROCESSING_STATE_NONE,                   /**< @brief There is no buffer processing currently. */\r
361     PROCESSING_STATE_FILLING_HEADER_BUFFER,  /**< @brief The header buffer is being filled and parsed. */\r
362     PROCESSING_STATE_FILLING_BODY_BUFFER,    /**< @brief The body buffer is being filled and parsed. */\r
363     PROCESSING_STATE_FINISHED,               /**< @brief Filling and parsing of both buffers is finished. */\r
364     PROCESSING_STATE_SEARCHING_HEADER_BUFFER /**< @brief The header buffer is being searched. */\r
365 } IotHttpsResponseBufferState_t;\r
366 \r
367 /*-----------------------------------------------------------*/\r
368 \r
369 /**\r
370  * @brief Represents an HTTP connection.\r
371  */\r
372 typedef struct _httpsConnection\r
373 {\r
374     const IotNetworkInterface_t * pNetworkInterface; /**< @brief Network interface with calls for connect, disconnect, send, and receive. */\r
375     IotNetworkConnection_t pNetworkConnection;       /**< @brief Pointer to the network connection to use pNetworkInterface calls on. */\r
376     uint32_t timeout;                                /**< @brief Timeout for a connection and waiting for a response from the network. */\r
377 \r
378     /**\r
379      * @brief true if a connection was successful most recently on this context\r
380      *\r
381      * We have no way of knowing if the server closed the connection because that error is unique to the underlying TLS\r
382      * layer. This is set to false initially, then set to true for a successful intentional call to connect.\r
383      * Post connection, this is set to false only after an implicit disconnect with a non-persistent request, an implicit\r
384      * disconnect with a network error, or an explicit disconnect with a call to @ref https_client_function_disconnect.\r
385      */\r
386     bool isConnected;\r
387     bool isDestroyed;                           /**< @brief true if the connection is already destroyed and we should call anymore  */\r
388     IotMutex_t connectionMutex;                 /**< @brief Mutex protecting operations on this entire connection context. */\r
389     IotDeQueue_t reqQ;                          /**< @brief The queue for the requests that are not finished yet. */\r
390     IotDeQueue_t respQ;                         /**< @brief The queue for the responses that are waiting to be processed. */\r
391     IotTaskPoolJobStorage_t taskPoolJobStorage; /**< @brief An asynchronous operation requires storage for the task pool job. */\r
392     IotTaskPoolJob_t taskPoolJob;               /**< @brief The task pool job identifier for an asynchronous request. */\r
393 } _httpsConnection_t;\r
394 \r
395 /**\r
396  * @brief Third party library http-parser information.\r
397  *\r
398  * There are two separate structures for http_parser state information. This is so that the application can read\r
399  * a header during it's readReadyCallback. The readReadyCallback could be invoked many times and the parser will\r
400  * therefore be invoked many times for each response read from the network. In order to ensure that the state of\r
401  * the parser remains intact whilst headers may be read, two structures holding the state are kept.\r
402  */\r
403 typedef struct _httpParserInfo\r
404 {\r
405     http_parser responseParser; /**< @brief http_parser state information for parsing the response. */\r
406     size_t ( * parseFunc )( http_parser * parser,\r
407                             const http_parser_settings * settings,\r
408                             const char * data,\r
409                             size_t len ); /**< @brief http_parser_execute function is to be plugged in here during initialization of the response. */\r
410     http_parser readHeaderParser;         /**< @brief http_parser state information for parsing the header buffer for reading a header. */\r
411 } _httpParserInfo_t;\r
412 \r
413 /**\r
414  * @brief Represents an HTTP response.\r
415  */\r
416 typedef struct _httpsResponse\r
417 {\r
418     IotLink_t link;                                      /**< @brief The link to insert the job in the connection's respQ. */\r
419     uint8_t * pHeaders;                                  /**< @brief Pointer to the start of the headers buffer. */\r
420     uint8_t * pHeadersEnd;                               /**< @brief Pointer to the end of the headers buffer. */\r
421     uint8_t * pHeadersCur;                               /**< @brief Pointer to the next location to write in the headers buffer. */\r
422     uint8_t * pBody;                                     /**< @brief Pointer to the start of the body buffer. */\r
423     uint8_t * pBodyEnd;                                  /**< @brief Pointer to the end of the body buffer. */\r
424     uint8_t * pBodyCur;                                  /**< @brief Pointer to the next location to write in the body buffer. */\r
425     _httpParserInfo_t httpParserInfo;                    /**< @brief Third party http-parser information. */\r
426     uint16_t status;                                     /**< @brief The HTTP response status code of this response. */\r
427     IotHttpsMethod_t method;                             /**< @brief The method of the originating request. */\r
428     IotHttpsResponseParserState_t parserState;           /**< @brief The current state of the parser. See IotHttpsResponseParserState_t documentation for more details. */\r
429     IotHttpsResponseBufferState_t bufferProcessingState; /**< @brief Which buffer is currently being processed and for what. See IotHttpsResponseBufferState_t documentation. */\r
430     char * pReadHeaderField;                             /**< @brief Header field that we want to read from the headers buffer when IotHttpsClient_ReadHeader() is called. */\r
431     size_t readHeaderFieldLength;                        /**< @brief Length of pReadHeaderField */\r
432     char * pReadHeaderValue;                             /**< @brief Header value that we read from the headers buffer when IotHttpsClient_ReadHeader() is called. */\r
433     size_t readHeaderValueLength;                        /**< @brief Length of pReadHeaderValue. */\r
434     bool foundHeaderField;                               /**< @brief State to use during parsing to let us know when we found the header field in the https-parser callbacks.\r
435                                                           *          This is set to true when the header field is found in parser callback _httpParserOnHeaderFieldCallback().\r
436                                                           *          On the following parser callback _httpParserOnHeaderValueCallback() we will store the value in pReadHeaderValue and then exit the parsing. */\r
437     struct _httpsConnection * pHttpsConnection;          /**< @brief Connection associated with response. This is set during IotHttpsClient_SendAsync(). This is needed during the asynchronous workflow to receive data given the respHandle only in the callback. */\r
438     bool isAsync;                                        /**< @brief This is set to true if this response is to be retrieved asynchronously. Set to false otherwise. */\r
439     uint8_t * pBodyInHeaderBuf;                          /**< @brief Pointer to the start of body inside the header buffer for copying to a body buffer provided later by the asynchronous response process. */\r
440     uint8_t * pBodyCurInHeaderBuf;                       /**< @brief Pointer to the next location to write body data during processing of the header buffer. This is necessary in case there is a chunk encoded HTTP response. */\r
441     IotHttpsReturnCode_t bodyRxStatus;                   /**< @brief The status of network receiving the HTTPS body to be returned during the #IotHttpsClientCallbacks_t.readReadyCallback. */\r
442     bool cancelled;                                      /**< @brief This is set to true to stop the request/response processing in the asynchronous request workflow. */\r
443     IotSemaphore_t respFinishedSem;                      /**< @brief This is for synchronous response to post that is finished being received. It is better to use a task event signal, but that is not implemented yet in the iot_threads.h API. */\r
444     IotHttpsReturnCode_t syncStatus;                     /**< @brief The status of the synchronous response. */\r
445 \r
446     /**\r
447      * @brief This is set to true to when the request is finished being sent on the network\r
448      *\r
449      * A request is not shared with multiple tasks, so only one task will update this. This is to let the let the\r
450      * network receive callback know that the request is fully pushed out to the server. This is also to let the\r
451      * disconnect know that the request is not using the network interface resources anymore.\r
452      */\r
453     bool reqFinishedSending;\r
454     IotHttpsClientCallbacks_t * pCallbacks; /**< @brief Pointer to the asynchronous request callbacks. */\r
455     void * pUserPrivData;                   /**< @brief User private data to hand back in the asynchronous callbacks for context. */\r
456     bool isNonPersistent;                   /**< @brief Non-persistent flag to indicate closing the connection immediately after receiving the response. */\r
457 } _httpsResponse_t;\r
458 \r
459 /**\r
460  * @brief Represents and HTTP request.\r
461  */\r
462 typedef struct _httpsRequest\r
463 {\r
464     IotLink_t link;                             /**< @brief The link to insert the job in the connection's reqQ. */\r
465     uint8_t * pHeaders;                         /**< @brief Pointer to the start of the headers buffer. */\r
466     uint8_t * pHeadersEnd;                      /**< @brief Pointer to the end of the headers buffer. */\r
467     uint8_t * pHeadersCur;                      /**< @brief Pointer to the next location to write in the headers buffer. */\r
468     uint8_t * pBody;                            /**< @brief Pointer to the start of the body buffer. */\r
469     uint32_t bodyLength;                        /**< @brief Length of request body buffer. */\r
470     IotHttpsMethod_t method;                    /**< @brief The method of the originating request. */\r
471     IotHttpsConnectionInfo_t * pConnInfo;       /**< @brief Connection info associated with this request. For an implicit connection. */\r
472     struct _httpsResponse * pHttpsResponse;     /**< @brief Response associated with request. This is initialized during IotHttpsClient_InitializeRequest(), then returned to the application in IotHttpsClient_SendAsync() and IotHttpsClient_SendSync(). */\r
473     struct _httpsConnection * pHttpsConnection; /**< @brief Connection associated with request. This is set during IotHttpsClient_SendAsync(). It is needed for the asynchronous workflow to use to send data given the reqHandle only in the callback. */\r
474     bool isNonPersistent;                       /**< @brief Non-persistent flag to indicate closing the connection immediately after receiving the response. */\r
475     bool isAsync;                               /**< @brief This is set to true if this request is to be sent asynchronously. Set to false otherwise. */\r
476     void * pUserPrivData;                       /**< @brief User private data to hand back in the asynchronous callbacks for context. */\r
477     IotHttpsClientCallbacks_t * pCallbacks;     /**< @brief Pointer to the asynchronous request callbacks. */\r
478     bool cancelled;                             /**< @brief Set this to true to stop the response processing in the asynchronous workflow. */\r
479     IotHttpsReturnCode_t bodyTxStatus;          /**< @brief The status of network sending the HTTPS body to be returned during the #IotHttpsClientCallbacks_t.writeCallback. */\r
480     bool scheduled;                             /**< @brief Set to true when this request has already been scheduled to the task pool. */\r
481 } _httpsRequest_t;\r
482 \r
483 /*-----------------------------------------------------------*/\r
484 \r
485 /**\r
486  * @brief A map of the method enum to strings\r
487  *\r
488  * These are in order to the HTTP request method enums defined in IotHttpsMethod_t.\r
489  */\r
490 static const char * _pHttpsMethodStrings[] = {\r
491     "GET",\r
492     "HEAD",\r
493     "PUT",\r
494     "POST"\r
495 };\r
496 \r
497 #endif /* IOT_HTTPS_INTERNAL_H_ */\r