mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-26 21:18:33 -04:00
Add the Labs projects provided in the V10.2.1_191129 zip file.
This commit is contained in:
parent
46e5937529
commit
e5708b38e9
801 changed files with 356576 additions and 0 deletions
|
@ -0,0 +1,852 @@
|
|||
/*
|
||||
* Amazon FreeRTOS HTTPS Client V1.1.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.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_https_client.h
|
||||
* @brief User-facing functions of the Amazon FreeRTOS HTTPS Client library.
|
||||
*/
|
||||
|
||||
#ifndef IOT_HTTPS_CLIENT_H_
|
||||
#define IOT_HTTPS_CLIENT_H_
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* HTTP types include. */
|
||||
#include "types/iot_https_types.h"
|
||||
|
||||
/**
|
||||
* @functionspage{https_client,HTTPS Client Library}
|
||||
* - @functionname{https_client_function_init}
|
||||
* - @functionname{https_client_function_deinit}
|
||||
* - @functionname{https_client_function_disconnect}
|
||||
* - @functionname{https_client_function_connect}
|
||||
* - @functionname{https_client_function_initializerequest}
|
||||
* - @functionname{https_client_function_addheader}
|
||||
* - @functionname{https_client_function_writerequestbody}
|
||||
* - @functionname{https_client_function_sendsync}
|
||||
* - @functionname{https_client_function_sendasync}
|
||||
* - @functionname{https_client_function_cancelrequestasync}
|
||||
* - @functionname{https_client_function_cancelresponseasync}
|
||||
* - @functionname{https_client_function_readresponsestatus}
|
||||
* - @functionname{https_client_function_readcontentlength}
|
||||
* - @functionname{https_client_function_readheader}
|
||||
* - @functionname{https_client_function_readresponsebody}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @functionpage{IotHttpsClient_Init,https_client,init}
|
||||
* @functionpage{IotHttpsClient_Deinit,https_client,deinit}
|
||||
* @functionpage{IotHttpsClient_Disconnect,https_client,disconnect}
|
||||
* @functionpage{IotHttpsClient_Connect,https_client,connect}
|
||||
* @functionpage{IotHttpsClient_InitializeRequest,https_client,initializerequest}
|
||||
* @functionpage{IotHttpsClient_AddHeader,https_client,addheader}
|
||||
* @functionpage{IotHttpsClient_WriteRequestBody,https_client,writerequestbody}
|
||||
* @functionpage{IotHttpsClient_SendSync,https_client,sendsync}
|
||||
* @functionpage{IotHttpsClient_SendAsync,https_client,sendasync}
|
||||
* @functionpage{IotHttpsClient_CancelRequestAsync,https_client,cancelrequestasync}
|
||||
* @functionpage{IotHttpsClient_CancelResponseAsync,https_client,cancelresponseasync}
|
||||
* @functionpage{IotHttpsClient_ReadResponseStatus,https_client,readresponsestatus}
|
||||
* @functionpage{IotHttpsClient_ReadContentLength,https_client,readcontentlength}
|
||||
* @functionpage{IotHttpsClient_ReadHeader,https_client,readheader}
|
||||
* @functionpage{IotHttpsClient_ReadResponseBody,https_client,readresponsebody}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief One-time initialization of the IoT HTTPS Client library.
|
||||
*
|
||||
* <b>This must be called once before calling any API.</b>
|
||||
*
|
||||
* @warning No thread safety guarantees are provided for this function.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the HTTPS library is successfully initialized.
|
||||
*
|
||||
* @see @ref https_client_function_cleanup
|
||||
*/
|
||||
/* @[declare_https_client_init] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_Init( void );
|
||||
/* @[declare_https_client_init] */
|
||||
|
||||
/**
|
||||
* @brief One time clean up of the IoT HTTPS Client library.
|
||||
*
|
||||
* This function frees resources taken in in @ref https_client_function_init. It should be called after
|
||||
* all HTTPS Connections have been close. HTTPS Connections are represented by #IotHttpsConnectionHandle_t and returned
|
||||
* by @ref https_client_function_connect. After this function returns @ref https_client_function_init
|
||||
* must be called again to use this library.
|
||||
*
|
||||
* @warning No thread safety guarantees are provided for this function.
|
||||
*/
|
||||
/* @[declare_https_client_cleanup] */
|
||||
void IotHttpsClient_Cleanup( void );
|
||||
/* @[declare_https_client_cleanup] */
|
||||
|
||||
/**
|
||||
* @cond DOXYGEN_IGNORE
|
||||
*
|
||||
* Backward compatibility function for one time clean up of the IoT HTTPS Client library.
|
||||
*/
|
||||
#define IotHttpsClient_Deinit IotHttpsClient_Cleanup
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Explicitly connect to the HTTPS server given the connection configuration pConnConfig.
|
||||
*
|
||||
* This routine blocks until the connection is complete.
|
||||
*
|
||||
* This function opens a new HTTPS connection with the server specified in #IotHttpsConnectionInfo_t.pAddress. The
|
||||
* connection is established by default on top of TLS over TCP. If the application wants to connect over TCP only, then
|
||||
* it must add the @ref IOT_HTTPS_IS_NON_TLS_FLAG to #IotHttpsConnectionInfo_t.flags. This is done at the application's
|
||||
* own risk.
|
||||
*
|
||||
* When the the last HTTP request sent on the connection is specified as persistent and we want to close the connection,
|
||||
* @ref https_client_function_disconnect must always be called on the valid #IotHttpsConnectionHandle_t. For more
|
||||
* information about persistent HTTP connections please see #IotHttpsRequestInfo_t.isNonPersistent.
|
||||
*
|
||||
* If the application receives a #IOT_HTTPS_NETWORK_ERROR from @ref https_client_function_sendsync or
|
||||
* @ref https_client_function_sendasync, on a persistent request, then the connection will be closed. The application
|
||||
* can call this this function again to reestablish the connection.
|
||||
*
|
||||
* If pConnHandle passed in is valid and represents a previously opened connection, this function will disconnect,
|
||||
* then reconnect. Before calling this function make sure that all outstanding requests on the connection have
|
||||
* completed. Outstanding requests are completed when @ref https_client_function_sendsync has returned or when
|
||||
* #IotHttpsClientCallbacks_t.responseCompleteCallback has been invoked for requests scheduled with
|
||||
* @ref https_client_function_sendasync.
|
||||
*
|
||||
* Keep in mind that many HTTP servers will close a connection, if it does not receive any requests, after a certain
|
||||
* amount of time. Many web servers may close the connection after 30-60 seconds. The state of pConnHandle will still be
|
||||
* in a connected state if this happens. If the server closed the connection, then the next request on the connection
|
||||
* will fail to send with a network error and the connection will move to a closed state.
|
||||
*
|
||||
* Also keep in mind that some HTTP servers do not accept persistent requests. Some HTTP servers will ignore that the
|
||||
* request contains the "Connection: keep-alive" header and close the connection immediately after sending the response.
|
||||
* If this happens, then the next request on the connection will fail to send with a network error and the connection
|
||||
* will close.
|
||||
*
|
||||
* To know if the connection was closed by the server, debug logging can be turned on to view the network error code
|
||||
* received. Debug logging is configured when @ref IOT_LOG_LEVEL_HTTPS is set to @ref IOT_LOG_DEBUG in iot_config.h.
|
||||
*
|
||||
* #IotHttpsConnectionInfo_t.userBuffer is used to store the internal context and therefore, multiple threads
|
||||
* calling this function simultaneously must ensure to use different #IotHttpsConnectionInfo_t objects.
|
||||
*
|
||||
* See @ref connectionUserBufferMinimumSize for information about the user buffer configured in
|
||||
* #IotHttpsConnectionInfo_t.userBuffer needed to create a valid connection handle.
|
||||
*
|
||||
* @param[out] pConnHandle - Handle returned representing the open connection. NULL if the function failed.
|
||||
* @param[in] pConnInfo - Configurations for the HTTPS connection.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the connection was successful.
|
||||
* - #IOT_HTTPS_CONNECTION_ERROR if the connection failed.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER if NULL parameters were passed in.
|
||||
* - #IOT_HTTPS_INTERNAL_ERROR if there was an error creating resources for the connection context.
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
* // An initialized network interface.
|
||||
* IotNetworkInterface_t* pNetworkInterface;
|
||||
*
|
||||
* // Parameters to HTTPS Client connect.
|
||||
* IotHttpsConnectionInfo_t connInfo = IOT_HTTPS_CONNECTION_INFO_INITIALIZER;
|
||||
* IotHttpsConnectionHandle_t connHandle = IOT_HTTPS_CONNECTION_HANDLE_INITIALIZER;
|
||||
* uint8_t* pConnUserBuffer = (uint8_t*)malloc(connectionUserBufferMinimumSize);
|
||||
*
|
||||
* // Set the connection configuration information.
|
||||
* connInfo.pAddress = "www.amazon.com";
|
||||
* connInfo.addressLen = strlen("www.amazon.com");
|
||||
* connInfo.port = 443;
|
||||
* connInfo.flags = 0;
|
||||
* connInfo.pAlpnProtocols = "alpnproto0,alpnproto1"
|
||||
* connInfo.pCaCert = HTTPS_TRUSTED_ROOT_CA; // defined elsewhere
|
||||
* connInfo.caCertLen = sizeof( HTTPS_TRUSTED_ROOT_CA );
|
||||
* connInfo.userBuffer.pBuffer = pConnUserBuffer;
|
||||
* connInfo.userBuffer.bufferLen = connectionUserBufferMinimumSize;
|
||||
* connInfo.pClientCert = TLS_CLIENT_CERT;
|
||||
* connInfo.clientCertLen = sizeof( TLS_CLIENT_CERT );
|
||||
* connInfo.pPrivateKey = TLS_CLIENT_PRIV_KEY;
|
||||
* connInfo.privateKeyLen = sizeof( TLS_CLIENT_PRIV_KEY );
|
||||
* connInfo.pNetworkInterface = pNetworkInterface;
|
||||
*
|
||||
* IotHttpsReturnCode_t returnCode = IotHttpsClient_Connect(&connHandle, &connInfo);
|
||||
* if( returnCode == IOT_HTTPS_OK )
|
||||
* {
|
||||
* // Do something with the HTTPS connection...
|
||||
*
|
||||
* // Clean up and close the HTTPS connection once it's no longer needed.
|
||||
* IotHttpsClient_Disconnect(connHandle);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_https_client_connect] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_Connect( IotHttpsConnectionHandle_t * pConnHandle,
|
||||
IotHttpsConnectionInfo_t * pConnInfo );
|
||||
/* @[declare_https_client_connect] */
|
||||
|
||||
/**
|
||||
* @brief Disconnect from the HTTPS server given the connection handle connHandle.
|
||||
*
|
||||
* This routine blocks until the disconnect is complete.
|
||||
* If the connection handle is not valid, the behavior is undefined.
|
||||
* If the connection handle is already disconnected then this routine will return IOT_HTTPS_OK.
|
||||
*
|
||||
* When the HTTP request is specified as persistent and we want to close the connection, this API must always
|
||||
* be called on the valid #IotHttpsConnectionHandle_t. For more information about persistent HTTP connections please see
|
||||
* #IotHttpsRequestInfo_t.isNonPersistent.
|
||||
*
|
||||
* When the HTTP request is specified as non-persistent, by setting #IotHttpsRequestInfo_t.isNonPersistent to true, then
|
||||
* this function will be called automatically on the valid IotHttpsConnectionHandle_t after receiving the response. There
|
||||
* is no need to call this function in case of a non-persistent request.
|
||||
*
|
||||
* This will put the internal connection state in #IotHttpsConnectionHandle_t to disconnected.
|
||||
*
|
||||
* If the application receives a #IOT_HTTPS_NETWORK_ERROR from @ref https_client_function_sendsync or
|
||||
* @ref https_client_function_sendasync, on a persistent request, that does not always mean the connection has been
|
||||
* disconnected. This function MUST be called to close the connection and clean up connection resources taken by
|
||||
* #IotHttpsConnectionHandle_t.
|
||||
*
|
||||
* This function will cancel all pending requests on the connection. If a request currently being sent on the connection,
|
||||
* then this function will disconnect the connection, but it will not free network connection resource and will return
|
||||
* with #IOT_HTTPS_BUSY. The application may call this function again later to try again.
|
||||
*
|
||||
* Multiple threads must not call this function for the same #IotHttpsConnectionHandle_t. Multiple threads
|
||||
* can call this function for different #IotHttpsConnectionHandle_t. Make sure that all request/responses
|
||||
* have finished on the connection before calling this API. Outstanding requests are completed when
|
||||
* @ref https_client_function_sendsync has returned or when #IotHttpsClientCallbacks_t.responseCompleteCallback
|
||||
* has been invoked for requests scheduled with @ref https_client_function_sendasync.
|
||||
*
|
||||
* @param[in] connHandle - Valid handle representing an open connection.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the disconnect was successful
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER if NULL parameters were passed in.
|
||||
* - #IOT_HTTPS_BUSY if the connection is in use and cannot be destroyed.
|
||||
*/
|
||||
/* @[declare_https_client_disconnect] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_Disconnect( IotHttpsConnectionHandle_t connHandle );
|
||||
/* @[declare_https_client_disconnect] */
|
||||
|
||||
/**
|
||||
* @brief Initializes the request by adding a formatted Request-Line to the start of HTTPS request header buffer.
|
||||
*
|
||||
* This function will initialize the HTTP request context by setting where to write the next headers to the start
|
||||
* of the configured header buffer in #IotHttpsRequestInfo_t.userBuffer.
|
||||
*
|
||||
* The Request-Line will be added to the start of the headers space in #IotHttpsRequestInfo_t.userBuffer.
|
||||
* The header space follows the request context in the user buffer. See @ref requestUserBufferMinimumSize for more
|
||||
* information on sizing the #IotHttpsRequestInfo_t.userBuffer so that this function does not fail.
|
||||
*
|
||||
* The Request-Line generated is of the following format:
|
||||
*
|
||||
* @code
|
||||
* method path version\r\n
|
||||
* @endcode
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @code
|
||||
* GET /path/to/item.file?possible_query HTTP/1.1\r\n
|
||||
* @endcode
|
||||
*
|
||||
* The initial required headers are also added to the #IotHttpsRequestInfo_t.userBuffer. These headers are User-Agent
|
||||
* and Host. The User-Agent value is configured in iot_config.h using IOT_HTTPS_USER_AGENT. The Host value is the DNS
|
||||
* resolvable server address.
|
||||
*
|
||||
* @param[out] pReqHandle - request handle representing the internal request context is returned. NULL if the function failed.
|
||||
* @param[in] pReqInfo - HTTPS request information.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the Request-Line was successfully added to the header space in #IotHttpsRequestInfo_t.userBuffer.
|
||||
* - #IOT_HTTPS_INSUFFICIENT_MEMORY if the Request-Line generated exceeds #IotHttpsUserBuffer_t.bufferLen in #IotHttpsRequestInfo_t.userBuffer.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER for NULL parameters.
|
||||
* - #IOT_HTTPS_INTERNAL_ERROR for library internal errors.
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
* // An initialized network interface.
|
||||
* IotNetworkInterface_t* pNetworkInterface;
|
||||
*
|
||||
* // Parameters to HTTPS Client request initialization.
|
||||
* IotHttpsRequestInfo_t reqInfo = IOT_HTTPS_REQUEST_INFO_INITIALIZER;
|
||||
* IotHttpsRequestHandle_t reqHandle = IOT_HTTPS_REQUEST_HANDLE_INITIALIZER;
|
||||
* IotHttpsSyncInfo_t syncInfo = IOT_HTTPS_SYNC_INFO_INITIALIZER;
|
||||
* // Leave some room for extra headers.
|
||||
* uint32_t userBufferSize = requestUserBufferMinimumSize + 256;
|
||||
* uint8_t* pRequestUserBuffer = (uint8_t*)malloc(userBufferSize);
|
||||
*
|
||||
* // Set the synchronous information.
|
||||
* syncInfo.pBody = PREDEFINED_BODY_BUFFER;
|
||||
* syncInfo.bodyLen = PREDEFINED_BODY_BUFFER_LEN;
|
||||
*
|
||||
* // Set the request configuration information.
|
||||
* reqInfo.pPath = "/path_to_item?query_maybe";
|
||||
* reqInfo.pPathLen = strlen("/path_to_item?query_maybe");
|
||||
* reqInfo.method = IOT_HTTPS_METHOD_GET;
|
||||
* reqInfo.pHost = "www.amazon.com";
|
||||
* reqInfo.hostLen = strlen("www.amazon.com");
|
||||
* reqInfo.isNonPersistent = false;
|
||||
* reqInfo.userBuffer.pBuffer = pRequestUserBuffer;
|
||||
* reqInfo.userBuffer.bufferLen = userBufferSize;
|
||||
* reqInfo.isAsync = false;
|
||||
* reqInfo.pSyncInfo = &syncInfo;
|
||||
*
|
||||
* IotHttpsReturnCode_t returnCode = IotHttpsClient_InitializeRequest(&reqHandle, &reqInfo);
|
||||
* if( returnCode == IOT_HTTPS_OK )
|
||||
* {
|
||||
* // Handle the error.
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_https_client_initializerequest] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_InitializeRequest( IotHttpsRequestHandle_t * pReqHandle,
|
||||
IotHttpsRequestInfo_t * pReqInfo );
|
||||
/* @[declare_https_client_initializerequest] */
|
||||
|
||||
/**
|
||||
* @brief Add a header to the current HTTPS request represented by reqHandle.
|
||||
*
|
||||
* The header line is appended to the request header buffer space in #IotHttpsRequestInfo_t.userBuffer.
|
||||
* Please see #requestUserBufferMinimumSize for information about sizing the #IotHttpsRequestInfo_t.userBuffer so
|
||||
* that this function does not fail.
|
||||
*
|
||||
* Header lines are appended in the following format:
|
||||
* @code
|
||||
* header_field_name: header_value\r\n"
|
||||
* @endcode
|
||||
* Example:
|
||||
* @code
|
||||
* Range: bytes=1024-2047\r\n
|
||||
* @endcode
|
||||
* The last header line must be followed by a "\r\n" to separate the last header line from
|
||||
* the entity body. These 2 characters are accounted for in #requestUserBufferMinimumSize.
|
||||
*
|
||||
* The remaining length, after the header is added, is printed to the system configured standard debug output when
|
||||
* @ref IOT_LOG_LEVEL_HTTPS is set to @ref IOT_LOG_DEBUG in iot_config.h.
|
||||
*
|
||||
* For an asynchronous request, this function can be invoked before the request is sent with
|
||||
* @ref https_client_function_sendasync, or during #IotHttpsClientCallbacks_t.appendHeaderCallback. It is
|
||||
* recommended to invoke this function in #IotHttpsClientCallbacks_t.appendHeaderCallback.
|
||||
*
|
||||
* <b> Asynchronous Example </b>
|
||||
* @code{c}
|
||||
* void _applicationDefined_appendHeaderCallback(void * pPrivData, IotHttpsRequestHandle_t reqHandle)
|
||||
* {
|
||||
* ...
|
||||
* char date_in_iso8601[17] = { 0 };
|
||||
* GET_DATE_IN_ISO8601(date_in_iso8601);
|
||||
* const char amz_date_header[] = "x-amz-date";
|
||||
* uint32_t amz_date_header_length = strlen(amz_date_header);
|
||||
* IotHttpsClient_AddHeader(reqHandle, amz_date_header, amz_date_header_length, date_in_iso8601, strlen(date_in_iso8601));
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* For a synchronous request, if extra headers are desired to be added, this function must be invoked before
|
||||
* @ref https_client_function_sendsync.
|
||||
* <b> Synchronous Example </b>
|
||||
* @code{c}
|
||||
* ...
|
||||
* char date_in_iso8601[17] = { 0 };
|
||||
* GET_DATE_IN_ISO8601(date_in_iso8601);
|
||||
* const char amz_date_header[] = "x-amz-date";
|
||||
* uint32_t amz_date_header_length = strlen(amz_date_header);
|
||||
* IotHttpsClient_AddHeader(reqHandle, amz_date_header, amz_date_header_length, date_in_iso8601, strlen(date_in_iso8601));
|
||||
* ...
|
||||
* IotHttpsClient_SendSync(connHandle, reqHandle, &respHandle, &respInfo, timeout);
|
||||
* ...
|
||||
* @endcode
|
||||
*
|
||||
* The following header fields are automatically added to the request header buffer and must NOT be added again with
|
||||
* this routine:
|
||||
* - Connection: - This header is added to the request when the headers are being sent on the network.
|
||||
* - User-agent: - This header is added during @ref https_client_function_initializerequest
|
||||
* - Host: - This header is added during @ref https_client_function_initializerequest
|
||||
* - Content-Length: - This header is added to the request when the headers are being sent on the network.
|
||||
*
|
||||
* The reqHandle is not thread safe. If two threads have the same reqHandle and attempt to add headers at the same
|
||||
* time, garbage strings may be written to the reqHandle.
|
||||
*
|
||||
* @param[in] reqHandle - HTTPS request to write the header line to.
|
||||
* @param[in] pName - String header field name to write.
|
||||
* @param[in] nameLen - The length of the header name to write.
|
||||
* @param[in] pValue - https header value buffer pointer. Do not include token name.
|
||||
* @param[in] valueLen - length of header value to write.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the header line was successfully added to the header space in #IotHttpsRequestInfo_t.userBuffer.
|
||||
* - #IOT_HTTPS_INSUFFICIENT_MEMORY if the header line cannot fit into the header buffer.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER for NULL parameters or if an attempt to add automatically added headers is made.
|
||||
*/
|
||||
/* @[declare_https_client_addheader] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_AddHeader( IotHttpsRequestHandle_t reqHandle,
|
||||
char * pName,
|
||||
uint32_t nameLen,
|
||||
char * pValue,
|
||||
uint32_t valueLen );
|
||||
/* @[declare_https_client_addheader] */
|
||||
|
||||
/**
|
||||
* @brief Writes the request body to the network for the request represented by reqHandle.
|
||||
*
|
||||
* This function is intended to be used by an asynchronous request. It must be called within the
|
||||
* #IotHttpsClientCallbacks_t.writeCallback.
|
||||
*
|
||||
* In HTTP/1.1 the headers are sent on the network first before any body can be sent. The auto-generated header
|
||||
* Content-Length is taken from the len parameter and sent first before the data in parameter pBuf is sent.
|
||||
* This library does not support Transfer-Encoding: chunked or other requests where the Content-Length is unknown, so
|
||||
* this function cannot be called more than once in #IotHttpsClientCallbacks_t.writeCallback for an HTTP/1.1 request.
|
||||
*
|
||||
* isComplete must always be set to 1 in this current version of the HTTPS client library.
|
||||
*
|
||||
* If there are network errors in sending the HTTP headers, then the #IotHttpsClientCallbacks_t.errorCallback will be
|
||||
* invoked following a return from the #IotHttpsClientCallbacks_t.writeCallback.
|
||||
*
|
||||
* <b> Example Asynchronous Code </b>
|
||||
* @code{c}
|
||||
* void applicationDefined_writeCallback(void * pPrivData, IotHttpsRequestHandle_t reqHandle)
|
||||
* {
|
||||
* ...
|
||||
* char * writeData[1024];
|
||||
* IotHttpsClient_WriteRequestBody(reqHandle, writeData, 1024, 1);
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] reqHandle - identifier of the connection.
|
||||
* @param[in] pBuf - client write data buffer pointer.
|
||||
* @param[in] len - length of data to write.
|
||||
* @param[in] isComplete - This parameter parameter must be set to 1.
|
||||
*
|
||||
* @return one of the following:
|
||||
* - #IOT_HTTPS_OK if write successfully, failure code otherwise.
|
||||
* - #IOT_HTTPS_MESSAGE_FINISHED if this function is called a second time with the same reqHandle.
|
||||
* - #IOT_HTTPS_NOT_SUPPORTED if isComplete is set to 0.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER if this API is used for a synchronous request.
|
||||
* - #IOT_HTTPS_NETWORK_ERROR if there was an error sending the headers or body on the network.
|
||||
* - Please see #IotHttpsReturnCode_t for other failure codes.
|
||||
*/
|
||||
/* @[declare_https_client_writerequestbody] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_WriteRequestBody( IotHttpsRequestHandle_t reqHandle,
|
||||
uint8_t * pBuf,
|
||||
uint32_t len,
|
||||
int isComplete );
|
||||
/* @[declare_https_client_writerequestbody] */
|
||||
|
||||
/**
|
||||
* @brief Synchronous send of the HTTPS request.
|
||||
*
|
||||
* This function blocks waiting for the entirety of sending the request and receiving the response.
|
||||
*
|
||||
* If #IotHttpsRequestInfo_t.isNonPersistent is set to true, then the connection will disconnect, close, and clean all
|
||||
* taken resources automatically after receiving the first response.
|
||||
*
|
||||
* See @ref connectionUserBufferMinimumSize for information about the user buffer configured in
|
||||
* #IotHttpsConnectionInfo_t.userBuffer needed to create a valid connection handle.
|
||||
*
|
||||
* To retrieve the response body applications must directly refer #IotHttpsSyncInfo_t.pBody configured in #IotHttpsRequestInfo_t.u.
|
||||
*
|
||||
* If the response body does not fit in the configured #IotHttpsSyncInfo_t.pBody, then this function will return with error
|
||||
* #IOT_HTTPS_MESSAGE_TOO_LARGE. To avoid this issue, the application needs to determine beforehand how large the file
|
||||
* to download is. This can be done with a HEAD request first, then extracting the "Content-Length" with
|
||||
* @ref https_client_function_readcontentlength. This could also be done with a GET request with the header
|
||||
* "Range: bytes=0-0", then extracting the "Content-Range" with @ref https_client_function_readheader. Keep in mind that
|
||||
* not all HTTP servers support Partial Content responses.
|
||||
*
|
||||
* Once a the file size is known, the application can initialize the request with a large
|
||||
* enough buffer or the application can make a partial content request with the header
|
||||
* "Range: bytes=N-M", where N is the starting byte requested and M is the ending byte requested.
|
||||
*
|
||||
* The response headers as received from the network will be stored in the header buffer space in
|
||||
* #IotHttpsResponseInfo_t.userBuffer. If the configured #IotHttpsResponseInfo_t.userBuffer is too small
|
||||
* to fit the headers received, then headers that don't fit will be thrown away. Please see
|
||||
* #responseUserBufferMinimumSize for information about sizing the #IotHttpsResponseInfo_t.userBuffer.
|
||||
* To receive feedback on headers discarded, debug logging must be turned on in iot_config.h by setting
|
||||
* @ref IOT_LOG_LEVEL_HTTPS to @ref IOT_LOG_DEBUG.
|
||||
*
|
||||
* Multiple threads must not call this function for the same #IotHttpsRequestHandle_t. Multiple threads can call this
|
||||
* function for a different #IotHttpsRequestHandle_t, even on the same #IotHttpsConnectionHandle_t. An application must
|
||||
* wait util a request is fully sent, before scheduling it again. A request is fully sent when this function has returned.
|
||||
*
|
||||
* @param[in] connHandle - Handle from an HTTPS connection created with @ref https_client_function_connect.
|
||||
* @param[in] reqHandle - Handle from a request created with @ref https_client_function_initializerequest.
|
||||
* @param[out] pRespHandle - HTTPS response handle resulting from a successful send and receive.
|
||||
* @param[in] pRespInfo - HTTP response configuration information.
|
||||
* @param[in] timeoutMs - Timeout waiting for the sync request to finish. Set this to 0 to wait forever.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the request was sent and the response was received successfully.
|
||||
* - #IOT_HTTPS_MESSAGE_TOO_LARGE if the response cannot fit in the configured struct IotHttpsRequestHandle.userBuffer.pBuffer and struct IotHttpsRequestHandle.u.pSyncInfo.pRespData.
|
||||
* - #IOT_HTTPS_CONNECTION_ERROR if the connection failed.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER if there are NULL parameters or the request is asynchronous.
|
||||
* - #IOT_HTTPS_NETWORK_ERROR if there was an error sending the data on the network.
|
||||
* - #IOT_HTTPS_PARSING_ERROR if there was an error parsing the HTTP response.
|
||||
* - #IOT_HTTPS_TIMEOUT_ERROR if the timeoutMs is reached when waiting for a response to the request.
|
||||
*/
|
||||
/* @[declare_https_client_sendsync] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_SendSync( IotHttpsConnectionHandle_t connHandle,
|
||||
IotHttpsRequestHandle_t reqHandle,
|
||||
IotHttpsResponseHandle_t * pRespHandle,
|
||||
IotHttpsResponseInfo_t * pRespInfo,
|
||||
uint32_t timeoutMs );
|
||||
/* @[declare_https_client_sendsync] */
|
||||
|
||||
/**
|
||||
* @brief Asynchronous send of the the HTTPS request.
|
||||
*
|
||||
* This function will invoke, as needed, each of the non-NULL callbacks configured in #IotHttpsAsyncInfo_t.callbacks
|
||||
* when the scheduled asynchronous request is progress. Please see #IotHttpsClientCallbacks_t for information on each of
|
||||
* the callbacks.
|
||||
*
|
||||
* After this API is executed, the scheduled async response will store the response headers as received from
|
||||
* the network, in the header buffer space configured in #IotHttpsResponseInfo_t.userBuffer. If the
|
||||
* configured #IotHttpsResponseInfo_t.userBuffer is too small to fit the headers received, then headers that don't
|
||||
* fit will be thrown away. Please see #responseUserBufferMinimumSize for information about sizing the
|
||||
* #IotHttpsResponseInfo_t.userBuffer.
|
||||
*
|
||||
* If #IotHttpsRequestInfo_t.isNonPersistent is set to true, then the connection will disconnect, close, and clean all
|
||||
* taken resources automatically after receiving the first response.
|
||||
*
|
||||
* See @ref connectionUserBufferMinimumSize for information about the user buffer configured in
|
||||
* #IotHttpsConnectionInfo_t.userBuffer needed to create a valid connection handle.
|
||||
*
|
||||
* A #IotHttpsRequestHandle_t cannot be schedule again or reused until the request has finished sending. The request
|
||||
* has safely finished sending once #IotHttpsClientCallbacks_t.readReadyCallback is invoked. After the
|
||||
* #IotHttpsClientCallbacks_t.readReadyCallback is invoked the #IotHttpsRequestInfo_t.userBuffer can freed,
|
||||
* modified, or reused.
|
||||
*
|
||||
* @param[in] connHandle - Handle from an HTTPS connection.
|
||||
* @param[in] reqHandle - Handle from a request created with IotHttpsClient_initialize_request.
|
||||
* @param[out] pRespHandle - HTTPS response handle.
|
||||
* @param[in] pRespInfo - HTTP response configuration information.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the request was sent and the response was received successfully.
|
||||
* - #IOT_HTTPS_MESSAGE_TOO_LARGE if the response cannot fit in the configured
|
||||
* IotHttpsRequestHandle_t.response_message.headers and IotHttpsRequestHandle_t.response_message.body.
|
||||
* - #IOT_HTTPS_CONNECTION_ERROR if the connection failed.
|
||||
* - #IOT_HTTPS_FATAL if there was a grave error with the last async job finishing.
|
||||
* - #IOT_HTTPS_ASYNC_SCHEDULING_ERROR if there was an error scheduling the asynchronous request.
|
||||
* - #IOT_HTTPS_INTERNAL_ERROR if there was an internal error with starting an asynchronous request servicing task.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER if there were NULL parameters or the request passed in was a synchronous type.
|
||||
*
|
||||
*/
|
||||
/* @[declare_https_client_sendasync] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_SendAsync( IotHttpsConnectionHandle_t connHandle,
|
||||
IotHttpsRequestHandle_t reqHandle,
|
||||
IotHttpsResponseHandle_t * pRespHandle,
|
||||
IotHttpsResponseInfo_t * pRespInfo );
|
||||
/* @[declare_https_client_sendasync] */
|
||||
|
||||
/**
|
||||
* @brief Cancel an Asynchronous request.
|
||||
*
|
||||
* This will stop an asynchronous request. When an asynchronous request is stopped it will not proceed to do any of
|
||||
* the following: send headers, send body, receive headers, or receive body. This depends on where in the process
|
||||
* the request is. For example, if the request is cancelled after sending the headers, then it will not attempt tp
|
||||
* send the body. A cancelled return code will be returned to the application.
|
||||
*
|
||||
* If this is called before the scheduled asynchronous request actually runs, then request will not be sent.
|
||||
* If this is called during any of the asynchronous callbacks, then the library will stop processing the request when
|
||||
* the callback returns. This is useful for any error conditions, found during the asynchronous callbacks, where the
|
||||
* application wants to stop the rest of the request processing.
|
||||
*
|
||||
* If the asynchronous request stops processing, the buffers in #IotHttpsRequestInfo_t.userBuffer can be safely freed,
|
||||
* modified, or reused, only once #IotHttpsClientCallbacks_t.readReadyCallback is invoked.
|
||||
*
|
||||
* <b> Example Asynchronous Code </b>
|
||||
* @code{c}
|
||||
* void _applicationDefined_appendHeaderCallback(void * pPrivData, IotHttpsRequestHandle_t reqHandle)
|
||||
* {
|
||||
* char token[MAX_TOKEN_LENGTH] = { 0 }
|
||||
* int len = MAX_TOKEN_LENGTH;
|
||||
* int status = gen_auth_token(token, &len);
|
||||
* if( status == GEN_TOKEN_FAIL)
|
||||
* {
|
||||
* IotHttpsClient_CancelRequestAsync(reqHandle);
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* void _applicationDefined_writeCallback(void * pPrivData, IotHttpsRequestHandle_t reqHandle)
|
||||
* {
|
||||
* if( application_data_get(writeBuffer, writeBufferLen) == GEN_TOKEN_FAIL)
|
||||
* {
|
||||
* IotHttpsClient_CancelRequestAsync(reqHandle);
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] reqHandle - Request handle associated with the request.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - IOT_HTTPS_OK if the request was successfully cancelled.
|
||||
*/
|
||||
/* @[declare_https_client_cancelrequestasync] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_CancelRequestAsync( IotHttpsRequestHandle_t reqHandle );
|
||||
/* @[declare_https_client_cancelrequestasync] */
|
||||
|
||||
/**
|
||||
* @brief Cancel an Asynchronous response.
|
||||
*
|
||||
* This will stop an asynchronous response. When an asynchronous response is stopped it will not proceed to do any of
|
||||
* the following: send headers, send body, receive headers, or receive body. This depends on where in the process
|
||||
* the response is. For example, if the response is cancelled after receiving the headers, then it will not attempt tp
|
||||
* receive the body. A cancelled return code will be returned to the application.
|
||||
*
|
||||
* If this is called during ANY of the asynchronous callbacks, then the library will stop processing the response when
|
||||
* the callback returns. This is useful for any error conditions, found during the asynchronous callbacks, where the
|
||||
* application wants to stop the rest of the response processing.
|
||||
*
|
||||
* If the asynchronous response stops processing, the buffers configured in #IotHttpsResponseInfo_t.userBuffer can
|
||||
* be freed, modified, or reused only after the #IotHttpsClientCallbacks_t.responseCompleteCallback in invoked.
|
||||
*
|
||||
* <b> Example Asynchronous Code </b>
|
||||
* @code{c}
|
||||
*
|
||||
* void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsResponseHandle_t respHandle, IotHttpsReturnCode_t rc, uint16_t status)
|
||||
* {
|
||||
* ...
|
||||
* if (status != IOT_HTTPS_STATUS_OK)
|
||||
* {
|
||||
* IotHttpsClient_CancelResponseAsync(NULL, respHandle);
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] respHandle - Response handle associated with the response.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the response was successfully cancelled.
|
||||
*/
|
||||
/* @[declare_https_client_cancelresponseasync] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_CancelResponseAsync( IotHttpsResponseHandle_t respHandle );
|
||||
/* @[declare_https_client_cancelresponseasync] */
|
||||
|
||||
/**
|
||||
* @brief Retrieve the HTTPS response status.
|
||||
*
|
||||
* The HTTP response status code is contained in the Status-Line of the response header buffer configured in
|
||||
* #IotHttpsResponseInfo_t.userBuffer. It is the first line of a standard HTTP response message. If the response
|
||||
* Status-Line could not fit into #IotHttpsResponseInfo_t.userBuffer, then this function will return an error code.
|
||||
* Please see #responseUserBufferMinimumSize for information about sizing the #IotHttpsResponseInfo_t.userBuffer.
|
||||
*
|
||||
* This routine can be used for both a synchronous and asynchronous response.
|
||||
*
|
||||
* <b> Example Synchronous Code </b>
|
||||
* @code{c}
|
||||
* ...
|
||||
* IotHttpsClient_SendSync(connHandle, reqHandle, &respHandle, &respInfo, timeout);
|
||||
* uint16_t status = 0;
|
||||
* IotHttpsClient_ReadResponseStatus(respHandle, &status);
|
||||
* if (status != IOT_HTTPS_STATUS_OK)
|
||||
* {
|
||||
* // Handle server response status.
|
||||
* }
|
||||
* ...
|
||||
* @endcode
|
||||
*
|
||||
* For an asynchronous response the response status is the status parameter in
|
||||
* #IotHttpsClientCallbacks_t.readReadyCallback and #IotHttpsClientCallbacks_t.responseCompleteCallback. The application
|
||||
* should refer to that instead of using this function.
|
||||
* <b> Example Asynchronous Code </b>
|
||||
* @code
|
||||
* void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsResponseHandle_t respHandle, IotHttpsReturnCode_t rc, uint16_t status)
|
||||
* {
|
||||
* ...
|
||||
* if (status != IOT_HTTPS_STATUS_OK)
|
||||
* {
|
||||
* // Handle error server response status.
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] respHandle - Unique handle representing the HTTPS response.
|
||||
* @param[out] pStatus - Integer status returned by the server.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the response status was successfully read into *status.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER for NULL parameters.
|
||||
* - #IOT_HTTPS_NOT_FOUND if the HTTP response status was not found in the header buffer.
|
||||
*/
|
||||
/* @[declare_https_client_readresponsestatus] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_ReadResponseStatus( IotHttpsResponseHandle_t respHandle,
|
||||
uint16_t * pStatus );
|
||||
/* @[declare_https_client_readresponsestatus] */
|
||||
|
||||
/**
|
||||
* @brief Retrieve the HTTPS response content length.
|
||||
*
|
||||
* If the "Content-Length" header is available in #IotHttpsResponseInfo_t.userBuffer, this routine extracts that
|
||||
* value. In some cases the "Content-Length" header is not available. This could be because the server sent a multi-part
|
||||
* encoded response (For example, "Transfer-Encoding: chunked") or the "Content-Length" header was far down in the list
|
||||
* of response headers and could not fit into the header buffer configured in #IotHttpsResponseInfo_t.userBuffer.
|
||||
* Please see #responseUserBufferMinimumSize for information about sizing the #IotHttpsResponseInfo_t.userBuffer.
|
||||
*
|
||||
* In the asynchronous request process, the Content-Length is not available until the
|
||||
* #IotHttpsClientCallbacks_t.readReadyCallback. Before the #IotHttpsClientCallbacks_t.readReadyCallback is invoked, the
|
||||
* headers are read into as much as can fit in in the header buffer space of #IotHttpsResponseInfo_t.userBuffer.
|
||||
* <b> Example Asynchronous Code </b>
|
||||
* @code{c}
|
||||
* void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsResponseHandle_t respHandle, IotHttpsReturnCode_t rc, uint16_t status)
|
||||
* {
|
||||
* uint8_t * readBuffer = NULL;
|
||||
* uint32_t contentLength = 0;
|
||||
* IotHttpsClient_ReadContentLength(respHandle, &contentLength);
|
||||
* readBuffer = (uint8_t*)malloc(contentLength);
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* In a synchronous request process, the Content-Length is available after @ref https_client_function_sendsync has
|
||||
* returned successfully.
|
||||
* <b> Example Synchronous Code </b>
|
||||
* @code{c}
|
||||
* ...
|
||||
* IotHttpsClient_SendSync(connHandle, reqHandle, &respHandle, &respInfo, timeout);
|
||||
* uint32_t contentLength = 0;
|
||||
* IotHttpsClient_ReadContentLength(respHandle, &contentLength);
|
||||
* printf("Content-Length: %u", (unsigned int)contentLength);
|
||||
* ...
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] respHandle - Unique handle representing the HTTPS response.
|
||||
* @param[out] pContentLength - Integer content length from the Content-Length header from the server. If the content
|
||||
* length is not found this will be 0.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the response body Content-Length was successfully read into contentLength.
|
||||
* - #IOT_HTTPS_NOT_FOUND if the Content-Length header was not found in the header buffer.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER if NULL parameters are passed in.
|
||||
*/
|
||||
/* @[declare_https_client_readcontentlength] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_ReadContentLength( IotHttpsResponseHandle_t respHandle,
|
||||
uint32_t * pContentLength );
|
||||
/* @[declare_https_client_readcontentlength] */
|
||||
|
||||
/**
|
||||
* @brief Retrieve the header of interest from the response represented by respHandle.
|
||||
*
|
||||
* The response headers as received from the network will be stored in the header buffer space in
|
||||
* #IotHttpsResponseInfo_t.userBuffer. If the configured #IotHttpsResponseInfo_t.userBuffer is too small to fit
|
||||
* the headers received, then headers that don't fit will be thrown away. Please see #responseUserBufferMinimumSize for
|
||||
* information about sizing the #IotHttpsResponseInfo_t.userBuffer.
|
||||
*
|
||||
* This routine parses the formatted HTTPS header lines in the header buffer for the header field name specified. If the
|
||||
* header is not available, then #IOT_HTTPS_NOT_FOUND is returned.
|
||||
*
|
||||
* For an asynchronous response, this routine is to be called during the #IotHttpsClientCallbacks_t.readReadyCallback.
|
||||
* Before the #IotHttpsClientCallbacks_t.readReadyCallback is invoked, the
|
||||
* headers are read into as much as can fit in in the header buffer space of #IotHttpsResponseInfo_t.userBuffer.
|
||||
* <b> Example Asynchronous Code </b>
|
||||
* @code{c}
|
||||
* void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsResponseHandle_t respHandle, IotHttpsReturnCode_t rc, uint16_t status)
|
||||
* {
|
||||
* ...
|
||||
* char valueBuf[64];
|
||||
* const char contentTypeName[] = "Content-Type";
|
||||
* uint32_t contentTypeNmeLength = strlen(contentTypeName);
|
||||
* IotHttpsClient_ReadHeader(respHandle, contentTypeName, contentTypeNameLength, valueBuf, sizeof(valueBuf));
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* For a syncrhonous response, this routine is to be called after @ref https_client_function_sendsync has
|
||||
* returned successfully.
|
||||
* <b> Example Synchronous Code </b>
|
||||
* @code{c}
|
||||
* ...
|
||||
* IotHttpsClient_SendSync(&connHandle, reqHandle, &respHandle, &respInfo, timeout);
|
||||
* char valueBuf[10];
|
||||
* const char contentTypeName[] = "Content-Type";
|
||||
* uint32_t contentTypeNmeLength = strlen(contentTypeName);
|
||||
* IotHttpsClient_ReadHeader(respHandle, contentTypeName, contentTypeNmeLength, valueBuf, sizeof(valueBuf));
|
||||
* uint32_t length = strtoul(valueBuf, NULL, 10);
|
||||
* ...
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] respHandle - Unique handle representing the HTTPS response.
|
||||
* @param[in] pName - HTTPS Header field name we want the value of. This must be NULL terminated.
|
||||
* @param[in] nameLen - The length of the name string.
|
||||
* @param[out] pValue - Buffer to hold the HTTPS field's value. The returned value will be NULL terminated
|
||||
* and therfore the buffer must be large enough to hold the terminating NULL character.
|
||||
* @param[in] valueLen - The length of the value buffer.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the header's corresponding value was read into *pValue.
|
||||
* - #IOT_HTTPS_NOT_FOUND if the header value was not found.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER if the respHandle is not valid, there is no response saved or the handle does not exist.
|
||||
* - #IOT_HTTPS_INSUFFICIENT_MEMORY if the value is too large to fit into *pValue.
|
||||
*/
|
||||
/* @[declare_https_client_readheader] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_ReadHeader( IotHttpsResponseHandle_t respHandle,
|
||||
char * pName,
|
||||
uint32_t nameLen,
|
||||
char * pValue,
|
||||
uint32_t valueLen );
|
||||
/* @[declare_https_client_readheader] */
|
||||
|
||||
/**
|
||||
* @brief Read the HTTPS response body from the network.
|
||||
*
|
||||
* This is intended to be used with an asynchronous response, this is to be invoked during the
|
||||
* #IotHttpsClientCallbacks_t.readReadyCallback to read data directly from the network into pBuf.
|
||||
* <b> Example Asynchronous Code </b>
|
||||
* @code{c}
|
||||
* void applicationDefined_readReadyCallback(void * pPrivData, IotHttpsRequestHandle_t handle, IotHttpsReturnCode_t rc, uint16_t status)
|
||||
* {
|
||||
* ...
|
||||
* char * myBuf = STORE_ADDRESS;
|
||||
* uint32_t len = STORE_READ_SIZE;
|
||||
* IotHttpsClient_ReadResponseBody(handle, myBuf, &len);
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* For a syncrhonous response, to retrieve the response body applications must directly refer to the memory configured
|
||||
* to receive the response body: #IotHttpsSyncInfo_t.pBody in #IotHttpsResponseInfo_t.pSyncInfo. Otherwise this function
|
||||
* will return an #IOT_HTTPS_INVALID_PARAMETER error code. This function is intended to read the response entity body
|
||||
* from the network and the synchronous response process handles all of that in @ref https_client_function_sendsync.
|
||||
*
|
||||
* @param[in] respHandle - Unique handle representing the HTTPS response.
|
||||
* @param[out] pBuf - Pointer to the response body memory location. This is not a char* because the body may have binary data.
|
||||
* @param[in,out] pLen - The length of the response to read. This should not exceed the size of the buffer that we are reading into. This will be replace with the amount of data read upon return.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the response body was successfully retrieved.
|
||||
* - #IOT_HTTPS_INVALID_PARAMETER if there are NULL parameters or if the response is a synchronous type.
|
||||
* - #IOT_HTTPS_NETWORK_ERROR if there was an error sending the data on the network.
|
||||
* - #IOT_HTTPS_PARSING_ERROR if there was an error parsing the HTTP response.
|
||||
*/
|
||||
/* @[declare_https_client_readresponsebody] */
|
||||
IotHttpsReturnCode_t IotHttpsClient_ReadResponseBody( IotHttpsResponseHandle_t respHandle,
|
||||
uint8_t * pBuf,
|
||||
uint32_t * pLen );
|
||||
/* @[declare_https_client_readresponsebody] */
|
||||
|
||||
#endif /* IOT_HTTPS_CLIENT_ */
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Amazon FreeRTOS HTTPS Client V1.1.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.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_https_utils.h
|
||||
* @brief User facing HTTPS Client library utilities.
|
||||
*/
|
||||
|
||||
#ifndef IOT_HTTPS_UTILS_H_
|
||||
#define IOT_HTTPS_UTILS_H_
|
||||
|
||||
#include "types/iot_https_types.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Retrieve the path from the input URL.
|
||||
*
|
||||
* This function retrieves the location and length of the path from within the
|
||||
* input the URL. The query is not included in the length returned.
|
||||
*
|
||||
* The URL MUST start with "http://" or "https://" to find the path.
|
||||
*
|
||||
* For example, if the URL is:
|
||||
* pUrl = "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff"
|
||||
*
|
||||
* *pPath = "/path/to/item.txt?optionalquery=stuff"
|
||||
* *pPathLen = 17
|
||||
*
|
||||
* @param[in] pUrl - URL string to parse.
|
||||
* @param[in] urlLen - The length of the URL string input.
|
||||
* @param[out] pPath - pointer within input url that the path starts at.
|
||||
* @param[out] pPathLen - Length of the path.
|
||||
*
|
||||
* - #IOT_HTTPS_OK if the path was successfully parsed.
|
||||
* - #IOT_HTTPS_PARSING_ERROR if there was an error parsing the URL.
|
||||
* - #IOT_HTTPS_NOT_FOUND if the path was not found.
|
||||
*/
|
||||
IotHttpsReturnCode_t IotHttpsClient_GetUrlPath( const char * pUrl,
|
||||
size_t urlLen,
|
||||
const char ** pPath,
|
||||
size_t * pPathLen );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Address from the input URL.
|
||||
*
|
||||
* This function retrieves the location and length of the address from within
|
||||
* the input URL. The path and query are not included in the length returned.
|
||||
*
|
||||
* The URL MUST start with "http://" or "https://" to find the address.
|
||||
*
|
||||
* For example, if the URL is:
|
||||
* pUrl = "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff"
|
||||
*
|
||||
* *pAddress = "www.somewebsite.com/path/to/item.txt?optionalquery=stuff"
|
||||
* *pAddressLen = 19
|
||||
*
|
||||
* @param[in] pUrl - URL string to parse.
|
||||
* @param[in] urlLen - The length of the URL string input.
|
||||
* @param[out] pAddress - pointer within input url that the address starts at.
|
||||
* @param[out] pAddressLen - Length of the address.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_HTTPS_OK if the path was successfully parsed.
|
||||
* - #IOT_HTTPS_PARSING_ERROR if there was an error parsing the URL.
|
||||
* - #IOT_HTTPS_NOT_FOUND if the address was not found.
|
||||
*/
|
||||
IotHttpsReturnCode_t IotHttpsClient_GetUrlAddress( const char * pUrl,
|
||||
size_t urlLen,
|
||||
const char ** pAddress,
|
||||
size_t * pAddressLen );
|
||||
|
||||
#endif /* IOT_HTTPS_UTILS_H_ */
|
|
@ -0,0 +1,907 @@
|
|||
/*
|
||||
* Amazon FreeRTOS HTTPS Client V1.1.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.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_https_types.h
|
||||
* @brief Types of the HTTPS Client library.
|
||||
*/
|
||||
|
||||
#ifndef IOT_HTTPS_TYPES_H_
|
||||
#define IOT_HTTPS_TYPES_H_
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* C standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Type includes. */
|
||||
#include "types/iot_platform_types.h"
|
||||
|
||||
/* Platform network include. */
|
||||
#include "platform/iot_network.h"
|
||||
|
||||
/*------------------------- HTTPS defined constants --------------------------*/
|
||||
|
||||
/**
|
||||
* @constantspage{https_client,HTTPS Client library}
|
||||
*
|
||||
* @section https_minimum_user_buffer_sizes HTTPS Client Minimum User Buffer Sizes
|
||||
* @brief Variables calculating the size of #IotHttpsUserBuffer_t.bufferLen needed for the request, response, and
|
||||
* connection.
|
||||
*
|
||||
* @note These user buffer minimum values may change at any time in future versions, but their names will remain the
|
||||
* same.
|
||||
* - @ref requestUserBufferMinimumSize <br>
|
||||
* @copybrief requestUserBufferMinimumSize
|
||||
* - @ref responseUserBufferMinimumSize <br>
|
||||
* @copybrief responseUserBufferMinimumSize
|
||||
* - @ref connectionUserBufferMinimumSize <br>
|
||||
* @copybrief connectionUserBufferMinimumSize
|
||||
*
|
||||
* @section https_connection_flags HTTPS Client Connection Flags
|
||||
* @brief Flags that modify the behavior of the HTTPS Connection.
|
||||
*
|
||||
* Flags should be bitwise-ORed with each other to change the behavior of @ref https_client_function_sendasync and
|
||||
* @ref https_client_function_sendsync. These flags are set in #IotHttpsConnectionInfo_t.flags.
|
||||
*
|
||||
* @note The values of flags may change at any time in future versions, but their names will remain the same.
|
||||
*
|
||||
* @section https_initializers HTTP Initializers
|
||||
* @brief Provide default values for the data types of the HTTP Client Library.
|
||||
*
|
||||
* @snippet this define_https_initializers
|
||||
*
|
||||
* All user-facing data types of the HTTPS Client library should be initialized using one of the following.
|
||||
*
|
||||
* @warning Failing to initialize an HTTPS Client data type with the appropriate initializer may result in undefined
|
||||
* behavior.
|
||||
* @note The initializers may change at any time in future versions, but their names will remain the same.
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
* IotHttpsConnectionHandle_t connHandle = IOT_HTTPS_CONNECTION_HANDLE_INITIALIZER;
|
||||
* IotHttpsRequestHandle_t reqHandle = IOT_HTTPS_REQUEST_HANDLE_INITIALIZER;
|
||||
* IotHttpsResponseHandle_t respHandle = IOT_HTTPS_RESPONSE_HANDLE_INITIALIZER;
|
||||
* IotHttpsUserBuffer_t userBuffer = IOT_HTTPS_USER_BUFFER_INITIALIZER;
|
||||
* IotHttpsSyncInfo_t syncInfoReq = IOT_HTTPS_SYNC_INFO_INITIALIZER;
|
||||
* IotHttpsSyncInfo_t syncInfoResp = IOT_HTTPS_SYNC_INFO_INITIALIZER;
|
||||
* IotHttpsConnectionInfo_t connInfo = IOT_HTTPS_CONNECTION_INFO_INITIALIZER;
|
||||
* IotHttpsRequestInfo_t reqInfo = IOT_HTTPS_REQUEST_INFO_INITIALIZER
|
||||
* IotHttpsResponseInfo_t respInfo = IOT_HTTPS_RESPONSE_INFO_INITIALIZER
|
||||
* @endcode
|
||||
*
|
||||
* @section http_constants_connection_flags HTTPS Client Connection Flags
|
||||
* @brief Flags that modify the behavior the HTTPS connection.
|
||||
* - #IOT_HTTPS_IS_NON_TLS_FLAG <br>
|
||||
* @copybrief IOT_HTTPS_IS_NON_TLS_FLAG
|
||||
* - #IOT_HTTPS_DISABLE_SNI <br>
|
||||
* @copybrief IOT_HTTPS_DISABLE_SNI
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The minimum user buffer size for the HTTP request context and headers.
|
||||
*
|
||||
* This helps to calculate the size of the buffer needed for #IotHttpsRequestInfo_t.userBuffer.
|
||||
*
|
||||
* This buffer size is calculated to fit the HTTP Request-Line and the default headers. It does not account for the
|
||||
* length of the path in the Request-Line nor does it account for the length of the host name. It also does not account
|
||||
* for extra headers that the application may add. These sizes need to be accounted for by the application when
|
||||
* assigning a buffer.
|
||||
*
|
||||
* A typical value for sizing the request user buffer for the request context is 512 bytes. See the example below.
|
||||
* @code{c}
|
||||
* uint8_t requestUserBuffer[512] = { 0 };
|
||||
* IotHttpsRequestInfo_t requestInfo = IOT_HTTPS_REQUEST_INFO_INITIALIZER;
|
||||
* requestInfo.userBuffer.pBuffer = requestUserBuffer;
|
||||
* @endcode
|
||||
*
|
||||
* By the application providing the memory for the internal context, no memory is needed to be allocated internally to
|
||||
* the library for the internal context. The application has control over the memory allocation related to the request,
|
||||
* response, and connection.
|
||||
*/
|
||||
extern const uint32_t requestUserBufferMinimumSize;
|
||||
|
||||
/**
|
||||
* @brief The minimum user buffer size for the HTTP response context and headers.
|
||||
*
|
||||
* This helps to calculate the size of the buffer needed for #IotHttpsResponseInfo_t.userBuffer.
|
||||
*
|
||||
* The buffer size is calculated to fit the HTTP response context only. It does not account for the HTTP response status
|
||||
* line. It does not account for any HTTP response headers. If the buffer assigned to
|
||||
* #IotHttpsResponseInfo_t.userBuffer is of this minimum size, then the response Status-Line and the response headers
|
||||
* will not be stored. These sizes need to be accounted for by the application when assigning a buffer.
|
||||
*
|
||||
* If the response Status-Line and response headers cannot fit into #IotHttpsResponseInfo_t.userBuffer, then after a
|
||||
* call to @ref https_client_function_sendsync, calls to @ref https_client_function_readresponsestatus,
|
||||
* @ref https_client_function_readcontentlength, and @ref https_client_function_readheader will return a failure code.
|
||||
*
|
||||
* A typical value for sizing the response user buffer for the response context is 512 bytes. See the example below.
|
||||
* @code{c}
|
||||
* uint8_t responseUserBuffer[512] = { 0 };
|
||||
* IotHttpsResponseInfo_t responseInfo = IOT_HTTPS_RESPONSE_INFO_INITIALIZER;
|
||||
* responseInfo.userBuffer.pBuffer = responseUserBuffer;
|
||||
* @endcode
|
||||
*
|
||||
* By the application providing the memory for the internal context, no memory is needed to be allocated internally to
|
||||
* the library for the internal context. The application has control over the memory allocation related to the request,
|
||||
* response, and connection.
|
||||
*/
|
||||
extern const uint32_t responseUserBufferMinimumSize;
|
||||
|
||||
/**
|
||||
* @brief The minimum user buffer size for the HTTP connection context and headers.
|
||||
*
|
||||
* This helps to calculate the size of the buffer needed for #IotHttpsConnectionInfo_t.userBuffer.
|
||||
*
|
||||
* The buffer size is calculated to fit the HTTP connection context only. The buffer assigned by the application must be
|
||||
* at least this size.
|
||||
*
|
||||
* A typical value for sizing the request user buffer for the connection context is 512 bytes. See the example below.
|
||||
* @code{c}
|
||||
* uint8_t connectionUserBuffer[512] = { 0 };
|
||||
* IotHttpsConnectionInfo_t connectionInfo = IOT_HTTPS_CONNECTION_INFO_INITIALIZER;
|
||||
* connectionInfo.userBuffer.pBuffer = connectionUserBuffer;
|
||||
* @endcode
|
||||
*
|
||||
* By the application providing the memory for the internal context, no memory is needed to be allocated internally to
|
||||
* the library for the internal context. The application has control over the memory allocation related to the request,
|
||||
* response, and connection.
|
||||
*/
|
||||
extern const uint32_t connectionUserBufferMinimumSize;
|
||||
|
||||
/**
|
||||
* @brief Flag for #IotHttpsConnectionInfo_t that disables TLS.
|
||||
*
|
||||
* Set this bit in #IotHttpsConnectionInfo_t.flags to disable use of TLS when the connection is created. This library
|
||||
* creates secure connections by default.
|
||||
*/
|
||||
#define IOT_HTTPS_IS_NON_TLS_FLAG ( 0x00000001 )
|
||||
|
||||
/**
|
||||
* @brief Flag for #IotHttpsConnectionInfo_t that disables Server Name Indication (SNI).
|
||||
*
|
||||
* Set this bit #IotHttpsConnectionInfo_t.flags to disable SNI. SNI is enabled by default in this library. When SNI is
|
||||
* enabled #IotHttpsConnectionInfo_t.pAddress will be used for the server name verification.
|
||||
*/
|
||||
#define IOT_HTTPS_DISABLE_SNI ( 0x00000008 )
|
||||
|
||||
/* @[define_https_initializers] */
|
||||
/** @brief Initializer for #IotHttpsConnectionHandle_t. */
|
||||
#define IOT_HTTPS_CONNECTION_HANDLE_INITIALIZER NULL
|
||||
/** @brief Initializer for #IotHttpsRequestHandle_t. */
|
||||
#define IOT_HTTPS_REQUEST_HANDLE_INITIALIZER NULL
|
||||
/** @brief Initializer for #IotHttpsResponseHandle_t. */
|
||||
#define IOT_HTTPS_RESPONSE_HANDLE_INITIALIZER NULL
|
||||
/** @brief Initializer for #IotHttpsUserBuffer_t. */
|
||||
#define IOT_HTTPS_USER_BUFFER_INITIALIZER { 0 }
|
||||
/** @brief Initializer for #IotHttpsSyncInfo_t. */
|
||||
#define IOT_HTTPS_SYNC_INFO_INITIALIZER { 0 }
|
||||
/** @brief Initializer for #IotHttpsAsyncInfo_t. */
|
||||
#define IOT_HTTPS_ASYNC_INFO_INITIALIZER { 0 }
|
||||
/** @brief Initializer for #IotHttpsConnectionInfo_t. */
|
||||
#define IOT_HTTPS_CONNECTION_INFO_INITIALIZER { 0 }
|
||||
/** @brief Initializer for #IotHttpsRequestInfo_t. */
|
||||
#define IOT_HTTPS_REQUEST_INFO_INITIALIZER { 0 }
|
||||
/** @brief Initializer for #IotHttpsResponseInfo_t. */
|
||||
#define IOT_HTTPS_RESPONSE_INFO_INITIALIZER { 0 }
|
||||
/* @[define_https_initializers] */
|
||||
|
||||
/* Network include for the network types below. */
|
||||
#include "platform/iot_network.h"
|
||||
|
||||
/**
|
||||
* @brief Type for the network interface containing the operations to send, receive, connect, and disconnect from
|
||||
* the network.
|
||||
*/
|
||||
#define IOT_HTTPS_NETWORK_INTERFACE_TYPE const IotNetworkInterface_t *
|
||||
|
||||
/*---------------------------- HTTPS handle types ----------------------------*/
|
||||
|
||||
/**
|
||||
* @handles{https_client,HTTPS Client library}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_handles
|
||||
* @brief Opaque handle of an HTTP connection.
|
||||
*
|
||||
* A connection handle is needed to send many requests over a single persistent connection. This handle is valid after
|
||||
* a successful call to @ref https_client_function_connect or @ref https_client_function_sendsync or
|
||||
* @ref https_client_function_sendasync. A variable of this type is passed to @ref https_client_function_sendsync,
|
||||
* @ref https_client_function_sendasync, and @ref https_client_function_disconnect to identify which connection that
|
||||
* function acts on.
|
||||
*
|
||||
* A call to @ref https_client_function_disconnect makes a connection handle invalid. Once @ref https_client_function_disconnect
|
||||
* returns, the connection handle should no longer be used. The application must call @ref https_client_function_connect
|
||||
* again to retrieve a new handle and a new connection.
|
||||
*
|
||||
* Typical web servers disconnect the client in around 30-60 seconds. The application needs to be aware of this, when
|
||||
* taking time between requests in a persistent connection.
|
||||
*
|
||||
* A connection handle is not thread safe. Multiple threads cannot connect and disconnect with the same handle at the
|
||||
* same time.
|
||||
*
|
||||
* Multiple threads can call @ref https_client_function_sendasync or @ref https_client_function_sendsync with the same
|
||||
* connection handle.
|
||||
*/
|
||||
typedef struct _httpsConnection * IotHttpsConnectionHandle_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_handles
|
||||
* @brief Opaque handle of an HTTP request.
|
||||
*
|
||||
* Having a separate handle for the HTTP request allows the application to re-use a request.
|
||||
*
|
||||
* This handle is valid after a successful call to @ref https_client_function_initializerequest. A variable of this type
|
||||
* is passed to @ref https_client_function_sendasync or @ref https_client_function_sendsync.
|
||||
*
|
||||
* A request handle cannot be sent on multiple connections at the same time.
|
||||
*
|
||||
* A request handle is not thread safe. Multiple threads cannot write headers to the same request handle.
|
||||
*/
|
||||
typedef struct _httpsRequest * IotHttpsRequestHandle_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_handles
|
||||
* @brief Opaque handle of an HTTP response.
|
||||
*
|
||||
* This handle is valid after a successful call to @ref https_client_function_sendsync or
|
||||
* @ref https_client_function_sendasync. A variable of this type is passed to
|
||||
* @ref https_client_function_readresponsestatus, @ref https_client_function_readcontentlength,
|
||||
* @ref https_client_function_readheader, and @ref https_client_function_readresponsebody.
|
||||
*
|
||||
* When returned from @ref https_client_function_sendsync or @ref https_client_function_sendasync, there is an
|
||||
* associated #IotHttpsRequestHandle_t. If the #IotHttpsRequestHandle_t associated with this response is re-initialized
|
||||
* with @ref https_client_function_initializerequest, then this response handle is no longer valid.
|
||||
*
|
||||
* A response handle is not thread safe. Multiple threads cannot read the headers in a response at the same time.
|
||||
*/
|
||||
typedef struct _httpsResponse * IotHttpsResponseHandle_t;
|
||||
|
||||
/*-------------------------- HTTPS enumerated types --------------------------*/
|
||||
|
||||
/**
|
||||
* @enums{https_client,HTTPS Client library}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_enums
|
||||
* @brief Return codes of [HTTPS Client functions](@ref https_client_functions).
|
||||
*/
|
||||
typedef enum IotHttpsReturnCode
|
||||
{
|
||||
/**
|
||||
* @brief Returned for a successful operation.
|
||||
*/
|
||||
IOT_HTTPS_OK = 0,
|
||||
|
||||
/**
|
||||
* @brief An invalid parameter was passed into an API function.
|
||||
*/
|
||||
IOT_HTTPS_INVALID_PARAMETER = 101,
|
||||
|
||||
/**
|
||||
* @brief Invalid payload.
|
||||
*/
|
||||
IOT_HTTPS_INVALID_PAYLOAD = 102,
|
||||
|
||||
/**
|
||||
* @brief HTTPS message was too large to fit into a configured synchronous body buffer.
|
||||
*/
|
||||
IOT_HTTPS_MESSAGE_TOO_LARGE = 103,
|
||||
|
||||
/**
|
||||
* @brief Overflow occurred somewhere.
|
||||
*/
|
||||
IOT_HTTPS_OVERFLOW = 104,
|
||||
|
||||
/**
|
||||
* @brief A buffer provided could not hold data required by the library.
|
||||
*/
|
||||
IOT_HTTPS_INSUFFICIENT_MEMORY = 105,
|
||||
|
||||
/**
|
||||
* @brief Queue full.
|
||||
*/
|
||||
IOT_HTTPS_QUEUE_FULL = 106,
|
||||
|
||||
/**
|
||||
* @brief Operation retry.
|
||||
*/
|
||||
IOT_HTTPS_RETRY = 107,
|
||||
|
||||
/**
|
||||
* @brief Could not find an item specified by an API.
|
||||
*
|
||||
* Returned for not being able to find the address in a URL, the path in a URL, or a header field from the response
|
||||
* headers.
|
||||
*/
|
||||
IOT_HTTPS_NOT_FOUND = 108,
|
||||
|
||||
/**
|
||||
* @brief The HTTP request message was finished being written and we cannot write more with @ref https_client_function_writerequestbody.
|
||||
*/
|
||||
IOT_HTTPS_MESSAGE_FINISHED = 109,
|
||||
|
||||
/**
|
||||
* @brief An error occurred internally to the library.
|
||||
*/
|
||||
IOT_HTTPS_INTERNAL_ERROR = 201,
|
||||
|
||||
/**
|
||||
* @brief A network error occurred.
|
||||
*/
|
||||
IOT_HTTPS_NETWORK_ERROR = 202,
|
||||
|
||||
/**
|
||||
* @brief A network connection error occurred.
|
||||
*/
|
||||
IOT_HTTPS_CONNECTION_ERROR = 203,
|
||||
|
||||
/**
|
||||
* @brief A stream error occurred.
|
||||
*/
|
||||
IOT_HTTPS_STREAM_ERROR = 204,
|
||||
|
||||
/**
|
||||
* @brief An authentication error occurred.
|
||||
*/
|
||||
IOT_HTTPS_AUTHENTICATION_ERROR = 205,
|
||||
|
||||
/**
|
||||
* @brief A TLS error occurred.
|
||||
*/
|
||||
IOT_HTTPS_TLS_ERROR = 206,
|
||||
|
||||
/**
|
||||
* @brief An error occurred during the user callback.
|
||||
*/
|
||||
IOT_HTTPS_USER_CALLBACK_ERROR = 207,
|
||||
|
||||
/**
|
||||
* @brief The synchronous response could not be received in the specified timeout in @ref https_client_function_sendsync.
|
||||
*/
|
||||
IOT_HTTPS_TIMEOUT_ERROR = 208,
|
||||
|
||||
/**
|
||||
* @brief An error in the HTTP protocol.
|
||||
*/
|
||||
IOT_HTTPS_PROTOCOL_ERROR = 209,
|
||||
|
||||
/**
|
||||
* @brief The HTTPS request send was cancelled.
|
||||
*/
|
||||
IOT_HTTPS_SEND_ABORT = 210,
|
||||
|
||||
/**
|
||||
* @brief The HTTPS response receiving was cancelled.
|
||||
*/
|
||||
IOT_HTTPS_RECEIVE_ABORT = 211,
|
||||
|
||||
/**
|
||||
* @brief The asynchronous request had an error being scheduled.
|
||||
*/
|
||||
IOT_HTTPS_ASYNC_SCHEDULING_ERROR = 212,
|
||||
|
||||
/**
|
||||
* @brief There was an error parsing the HTTP response.
|
||||
*/
|
||||
IOT_HTTPS_PARSING_ERROR = 213,
|
||||
|
||||
/**
|
||||
* @brief Fatal HTTP library error.
|
||||
*/
|
||||
IOT_HTTPS_FATAL = 901,
|
||||
|
||||
/**
|
||||
* @brief The connection is busy and cannot be cleaned up.
|
||||
*
|
||||
* The connection was closed, but @ref https_client_function_disconnect must be called again to cleanup connection
|
||||
* resources.
|
||||
*/
|
||||
IOT_HTTPS_BUSY = 902,
|
||||
|
||||
/**
|
||||
* @brief Try again.
|
||||
*/
|
||||
IOT_HTTPS_TRY_AGAIN = 903,
|
||||
|
||||
/**
|
||||
* @brief Data exists.
|
||||
*/
|
||||
IOT_HTTPS_DATA_EXIST = 904,
|
||||
|
||||
/**
|
||||
* @brief The operation on the public API is not supported.
|
||||
*/
|
||||
IOT_HTTPS_NOT_SUPPORTED = 905
|
||||
} IotHttpsReturnCode_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_enums
|
||||
* @brief Types of HTTP methods.
|
||||
*
|
||||
* The HTTP method is configured in #IotHttpsRequestInfo_t.method.
|
||||
*/
|
||||
typedef enum IotHttpsMethod
|
||||
{
|
||||
IOT_HTTPS_METHOD_GET = 0, /* Client-to-server method GET */
|
||||
IOT_HTTPS_METHOD_HEAD, /* Client-to-server method HEAD */
|
||||
IOT_HTTPS_METHOD_PUT, /* Client-to-server method PUT */
|
||||
IOT_HTTPS_METHOD_POST /* Client-to-server method POST. */
|
||||
} IotHttpsMethod_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_enums
|
||||
* @brief Types of standard HTTP Response status codes.
|
||||
*
|
||||
* These status codes are taken from RFC 2616. Please see RFC 2616 for a description of each response status.
|
||||
*/
|
||||
enum IotHttpsResponseStatus
|
||||
{
|
||||
IOT_HTTPS_STATUS_CONTINUE = 100,
|
||||
IOT_HTTPS_STATUS_SWITCHING_PROTOCOLS,
|
||||
IOT_HTTPS_STATUS_OK = 200,
|
||||
IOT_HTTPS_STATUS_CREATED,
|
||||
IOT_HTTPS_STATUS_ACCEPTED,
|
||||
IOT_HTTPS_STATUS_NON_AUTHORITIVE_INFORMATION,
|
||||
IOT_HTTPS_STATUS_NO_CONTENT,
|
||||
IOT_HTTPS_STATUS_RESET_CONTENT,
|
||||
IOT_HTTPS_STATUS_PARTIAL_CONTENT,
|
||||
IOT_HTTPS_STATUS_MULTIPLE_CHOICES = 300,
|
||||
IOT_HTTPS_STATUS_MOVED_PERMANENTLY,
|
||||
IOT_HTTPS_STATUS_FOUND,
|
||||
IOT_HTTPS_STATUS_SEE_OTHER,
|
||||
IOT_HTTPS_STATUS_NOT_MODIFIED,
|
||||
IOT_HTTPS_STATUS_USE_PROXY,
|
||||
IOT_HTTPS_STATUS_UNUSED,
|
||||
IOT_HTTPS_STATUS_TEMPORARY_REDIRECT,
|
||||
IOT_HTTPS_STATUS_BAD_REQUEST = 400,
|
||||
IOT_HTTPS_STATUS_UNAUTHORIZED,
|
||||
IOT_HTTPS_STATUS_PAYMENT_REQUIRED,
|
||||
IOT_HTTPS_STATUS_FORBIDDEN,
|
||||
IOT_HTTPS_STATUS_NOT_FOUND,
|
||||
IOT_HTTPS_STATUS_METHOD_NOT_ALLOWED,
|
||||
IOT_HTTPS_STATUS_NOT_ACCEPTABLE,
|
||||
IOT_HTTPS_STATUS_PROXY_AUTHENTICATION_REQUIRED,
|
||||
IOT_HTTPS_STATUS_REQUEST_TIMEOUT,
|
||||
IOT_HTTPS_STATUS_CONFLICT,
|
||||
IOT_HTTPS_STATUS_GONE,
|
||||
IOT_HTTPS_STATUS_LENGTH_REQUIRED,
|
||||
IOT_HTTPS_STATUS_PRECONDITION_FAILED,
|
||||
IOT_HTTPS_STATUS_REQUEST_ENTITY_TOO_LARGE,
|
||||
IOT_HTTPS_STATUS_REQUEST_URI_TOO_LONG,
|
||||
IOT_HTTPS_STATUS_UNSUPPORTED_MEDIA_TYPE,
|
||||
IOT_HTTPS_STATUS_REQUEST_RANGE_NOT_SATISFIABLE,
|
||||
IOT_HTTPS_STATUS_EXPECTATION_FAILED,
|
||||
IOT_HTTPS_STATUS_INTERNAL_SERVER_ERROR = 500,
|
||||
IOT_HTTPS_STATUS_NOT_IMPLEMENTED,
|
||||
IOT_HTTPS_STATUS_BAD_GATEWAY,
|
||||
IOT_HTTPS_STATUS_SERVICE_UNAVAILABLE,
|
||||
IOT_HTTPS_STATUS_GATEWAY_TIMEOUT,
|
||||
IOT_HTTPS_STATUS_HTTP_VERSION_NOT_SUPPORTED
|
||||
};
|
||||
|
||||
/*------------------------- HTTPS parameter structs --------------------------*/
|
||||
|
||||
/**
|
||||
* @paramstructs{https_client,HTTPS Client library}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_paramstructs
|
||||
*
|
||||
* @brief HTTPS Client library callbacks for asynchronous requests.
|
||||
*
|
||||
* @paramfor @ref https_client_function_initializerequest
|
||||
*
|
||||
* This type is a parameter in #IotHttpsResponseInfo_t.
|
||||
*
|
||||
* If any of the members in this type are set to NULL, then they will not be invoked during the asynchronous
|
||||
* request/response process.
|
||||
*
|
||||
* See @ref Asynchronous_Callback_Order for the order of the order of the callbacks and when they will be invoked.
|
||||
*/
|
||||
typedef struct IotHttpsClientCallbacks
|
||||
{
|
||||
/**
|
||||
* @brief User-provided callback function signature for appending a header to current asynchronous request.
|
||||
*
|
||||
* If this is set to NULL, then it will not be invoked.
|
||||
* See @ref https_client_function_addheader for more information on adding a header in this callback.
|
||||
*
|
||||
* Appending the header when request is in progress is good for things like time limited authentication tokens.
|
||||
*
|
||||
* @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData
|
||||
* @param[in] reqHandle - The handle for the current HTTP request in progress.
|
||||
*/
|
||||
void ( * appendHeaderCallback )( void * pPrivData,
|
||||
IotHttpsRequestHandle_t reqHandle );
|
||||
|
||||
/**
|
||||
* @brief User-provided callback function signature for writing data to the network for a current asynchronous
|
||||
* request.
|
||||
*
|
||||
* If this is set to NULL, then it will not be invoked.
|
||||
* See @ref https_client_function_writerequestbody for more information on writing request body.
|
||||
*
|
||||
* @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData
|
||||
* @param[in] reqHandle - The handle for the current HTTP request in progress.
|
||||
*/
|
||||
void ( * writeCallback )( void * pPrivData,
|
||||
IotHttpsRequestHandle_t reqHandle );
|
||||
|
||||
/**
|
||||
* @brief User-provided callback function signature for reading data from the network for a current asynchronous
|
||||
* response.
|
||||
*
|
||||
* The network indicated that after sending the associated request, the response is available for reading.
|
||||
* If this is set to NULL, then it will not be invoked and any response body received will be ignored.
|
||||
* See @ref https_client_function_readresponsebody for more information about reading the response body in this
|
||||
* callback.
|
||||
*
|
||||
* @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData
|
||||
* @param[in] respHandle - The handle for the current HTTP response in progress.
|
||||
* @param[in] rc - A return code indicating any errors before this callback was invoked.
|
||||
* @param[in] status - The HTTP response status code of the current response in progress.
|
||||
*/
|
||||
void ( * readReadyCallback )( void * pPrivData,
|
||||
IotHttpsResponseHandle_t respHandle,
|
||||
IotHttpsReturnCode_t rc,
|
||||
uint16_t status );
|
||||
|
||||
/**
|
||||
* @brief User-provided callback function signature to indicate that the asynchronous response is completed.
|
||||
*
|
||||
* If this is set to NULL, then it will not be invoked.
|
||||
*
|
||||
* This callback is invoked when the response is fully received from the network and the request/response pair is
|
||||
* complete.
|
||||
* If there was an error in sending the request or an error in receiving the associated response, this callback will
|
||||
* be invoked, if the error caused the request or associated response to finish.
|
||||
* #IotHttpsClientCallbacks_t.errorCallback will be invoked first before this callback.
|
||||
* This callback is invoked to let the application know that memory used by #IotHttpsRequestInfo_t.userBuffer and
|
||||
* #IotHttpsResponseInfo_t.userBuffer can be freed, modified, or reused.
|
||||
*
|
||||
* For a non-persistent connection, the connection will be closed first before invoking this callback.
|
||||
*
|
||||
* @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData
|
||||
* @param[in] respHandle - The handle for the current HTTP response in progress.
|
||||
* @param[in] rc - A return code indicating any errors before this callback was invoked.
|
||||
* @param[in] status - The HTTP response status code of the current response in progress.
|
||||
*/
|
||||
void ( * responseCompleteCallback )( void * pPrivData,
|
||||
IotHttpsResponseHandle_t respHandle,
|
||||
IotHttpsReturnCode_t rc,
|
||||
uint16_t status );
|
||||
|
||||
/**
|
||||
* @brief User-provided callback function signature to indicate that the connection has been close in an asynchronous
|
||||
* request process.
|
||||
*
|
||||
* If this is set to NULL, then it will not be invoked.
|
||||
* If there are errors during sending/receiving in the asynchronous process, the connection is not automatically
|
||||
* closed. If the server closes the connection during the asynchronous process, this callback is not invoked.
|
||||
* This callback is invoked only if the connection was flagged as non-persistent in
|
||||
* #IotHttpsConnectionInfo_t.flags.
|
||||
*
|
||||
* @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData
|
||||
* @param[in] connHandle - The handle for the current HTTP connection.
|
||||
* @param[in] rc - A return code indicating any errors before this callback was invoked.
|
||||
*/
|
||||
void ( * connectionClosedCallback )( void * pPrivData,
|
||||
IotHttpsConnectionHandle_t connHandle,
|
||||
IotHttpsReturnCode_t rc );
|
||||
|
||||
/**
|
||||
* @brief User-provided callback function signature to indicate that an error occurred during the asynchronous
|
||||
* request process.
|
||||
*
|
||||
* If respHandle is NULL, then reqHandle will not be NULL and vise-versa. This signals which handle the error
|
||||
* occurred and if it is during the sending or receiving.
|
||||
*
|
||||
* @param[in] pPrivData - User context configured in #IotHttpsAsyncInfo_t.pPrivData
|
||||
* @param[in] respHandle - The handle for the current HTTP response.
|
||||
* @param[in] reqHandle - The handle for the current HTTP request.
|
||||
* @param[in] rc - A return code indicating any errors before this callback was invoked.
|
||||
*/
|
||||
void ( * errorCallback )( void * pPrivData,
|
||||
IotHttpsRequestHandle_t reqHandle,
|
||||
IotHttpsResponseHandle_t respHandle,
|
||||
IotHttpsReturnCode_t rc );
|
||||
} IotHttpsClientCallbacks_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_paramstructs
|
||||
* @brief User-provided buffer for storing the HTTPS headers and library internal context.
|
||||
*
|
||||
* @paramfor @ref https_client_function_initializerequest.
|
||||
*
|
||||
* The user buffer is configured in #IotHttpsConnectionInfo_t.userBuffer, #IotHttpsRequestInfo_t.userBuffer and
|
||||
* #IotHttpsResponseInfo_t.userBuffer.
|
||||
*
|
||||
* The minimum size that the buffer must be configured to is indicated by requestUserBufferMinimumSize,
|
||||
* responseUserBufferMinimumSize, connectionUserBufferMinimumSize.
|
||||
*/
|
||||
typedef struct IotHttpsUserBuffer
|
||||
{
|
||||
uint8_t * pBuffer; /**< @brief Application provided buffer pointer. */
|
||||
uint32_t bufferLen; /**< @brief The length of the application provided buffer. */
|
||||
} IotHttpsUserBuffer_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_paramstructs
|
||||
* @brief HTTPS Client synchronous request information.
|
||||
*
|
||||
* @paramfor @ref https_client_function_initializerequest, @ref https_client_function_sendsync,
|
||||
* @ref https_client_function_sendasync
|
||||
*
|
||||
* This structure is configured in #IotHttpsRequestInfo_t.u and #IotHttpsResponseInfo_t.
|
||||
*
|
||||
* A synchronous request will block until the response is fully received from the network.
|
||||
* This structure defines memory locations to store the response body.
|
||||
*/
|
||||
typedef struct IotHttpsSyncRequestInfo
|
||||
{
|
||||
/**
|
||||
* Pointer to the HTTP message body.
|
||||
*
|
||||
* For a request this is the file or data we want to send. The data is separated from the headers for the
|
||||
* flexibility to point to an already established file elsewhere in memory.
|
||||
*
|
||||
* For a response this is where to receive the response entity body.
|
||||
* If the length of the buffer provided to store the response body is smaller than the amount of body received,
|
||||
* then @ref https_client_function_sendsync will return a IOT_HTTPS_INSUFFICIENT_MEMORY error code. Although an error
|
||||
* was returned, the first #IotHttpsSyncInfo_t.bodyLen of the response received on the network will
|
||||
* still be available in the buffer.
|
||||
*/
|
||||
uint8_t * pBody;
|
||||
uint32_t bodyLen; /**< @brief The length of the HTTP message body. */
|
||||
} IotHttpsSyncInfo_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_paramstructs
|
||||
* @brief HTTPS Client asynchronous request information.
|
||||
*
|
||||
* @paramfor @ref https_client_function_initializerequest.
|
||||
*
|
||||
* This is parameter in #IotHttpsRequestInfo_t.u.
|
||||
*
|
||||
* An asynchronous request will ask the application for headers and body right before the request is ready
|
||||
* to be sent onto the network.
|
||||
* An asynchronous request will have the application read headers and body as soon as the response is received
|
||||
* on the network.
|
||||
*/
|
||||
typedef struct IotHttpsAsyncInfo
|
||||
{
|
||||
/**
|
||||
* @brief Callbacks are used for an asynchronous request.
|
||||
* See #IotHttpsClientCallbacks_t for more information.
|
||||
*/
|
||||
IotHttpsClientCallbacks_t callbacks;
|
||||
void * pPrivData; /**< @brief User private data to provide context to the asynchronous callbacks. */
|
||||
} IotHttpsAsyncInfo_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_paramstructs
|
||||
* @brief HTTP connection configuration.
|
||||
*
|
||||
* @paramfor @ref https_client_function_connect or @ref https_client_function_sendsync or
|
||||
* @ref https_client_function_sendasync.
|
||||
*
|
||||
* This parameter is used to connection in @ref https_client_function_connect.
|
||||
*
|
||||
* @note The lengths of the strings in this struct should not include the NULL
|
||||
* terminator. Strings in this struct do not need to be NULL-terminated.
|
||||
*/
|
||||
typedef struct IotHttpsConnectionInfo
|
||||
{
|
||||
/**
|
||||
* @brief Remote server address that is DNS discoverable.
|
||||
*
|
||||
* For example: avs-alexa-na.amazon.com.
|
||||
*/
|
||||
const char * pAddress;
|
||||
uint32_t addressLen; /**< @brief remote address length. */
|
||||
|
||||
uint16_t port; /**< @brief Remote port number */
|
||||
|
||||
/**
|
||||
* @brief Flags to configure the HTTPS connection.
|
||||
*
|
||||
* See @ref https_connection_flags for the available flags.
|
||||
*
|
||||
* Unknown flags are ignored.
|
||||
*/
|
||||
uint32_t flags; /**< @brief Flags to configure the HTTPS connection. */
|
||||
|
||||
/**
|
||||
* @brief Timeout waiting for a response from the network in milliseconds.
|
||||
*
|
||||
* If this is set to zero, it will default to @ref IOT_HTTPS_RESPONSE_WAIT_MS.
|
||||
*/
|
||||
uint32_t timeout;
|
||||
|
||||
const char * pCaCert; /**< @brief Server trusted certificate store for this connection. */
|
||||
uint32_t caCertLen; /**< @brief Server trusted certificate store size. */
|
||||
|
||||
const char * pClientCert; /**< @brief Client certificate store for this connection. */
|
||||
uint32_t clientCertLen; /**< @brief Client certificate store size. */
|
||||
|
||||
const char * pPrivateKey; /**< @brief Client private key store for this connection. */
|
||||
uint32_t privateKeyLen; /**< @brief Client private key store size. */
|
||||
|
||||
/**
|
||||
* @brief String of all the ALPN protocols separated by commas needed for this connection.
|
||||
*
|
||||
* For the protocols needed for the AWS Iot Message broker endpoint please see:
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html
|
||||
*/
|
||||
char * pAlpnProtocols;
|
||||
uint32_t alpnProtocolsLen; /**< @brief ALPN protocol string length. */
|
||||
|
||||
/**
|
||||
* @brief User buffer to store the internal connection context.
|
||||
*
|
||||
* See @ref connectionUserBufferMinimumSize for information about the user buffer configured in
|
||||
* #IotHttpsConnectionInfo_t.userBuffer needed to create a valid connection handle.
|
||||
*/
|
||||
IotHttpsUserBuffer_t userBuffer;
|
||||
|
||||
/**
|
||||
* @brief The IOT network abstraction interface.
|
||||
*
|
||||
* This contains the interface to connect, disconnect, send data, and receive data from the network.
|
||||
*
|
||||
* In Amazon FreeRTOS this should be of the type IotNetworkInterface_t.
|
||||
*/
|
||||
IOT_HTTPS_NETWORK_INTERFACE_TYPE pNetworkInterface;
|
||||
} IotHttpsConnectionInfo_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_paramstructs
|
||||
* @brief HTTP request configuration.
|
||||
*
|
||||
* @paramfor @ref https_client_function_initializerequest.
|
||||
*
|
||||
* This parameter is used to configure the request in https_client_function_initializerequest.
|
||||
*
|
||||
* @note The lengths of the strings in this struct should not include the NULL
|
||||
* terminator. Strings in this struct do not need to be NULL-terminated.
|
||||
*/
|
||||
typedef struct IotHttpsRequestInfo
|
||||
{
|
||||
/**
|
||||
* @brief The absolute path to the HTTP request object.
|
||||
*
|
||||
* The absolute path includes the path to the file AND the optional query.
|
||||
* An example URI path: "/v20160207/directives?query".
|
||||
*
|
||||
* If this is NULL, a "/" will be added to the Request-Line automatically.
|
||||
*
|
||||
* This is used to generate the Request-Line in the HTTP request message, see
|
||||
* @ref https_client_function_initializerequest for more information.
|
||||
*/
|
||||
const char * pPath;
|
||||
uint32_t pathLen; /**< @brief URI path length */
|
||||
|
||||
/**
|
||||
* @brief On of the HTTP method tokens defined in #IotHttpsMethod_t.
|
||||
*
|
||||
* This is used to generate the Request-Line in the HTTP request message, see
|
||||
* @ref https_client_function_initializerequest for more information.
|
||||
*/
|
||||
IotHttpsMethod_t method;
|
||||
|
||||
/**
|
||||
* @brief Host address this request is intended for, e.g., "awsamazon.com".
|
||||
*
|
||||
* This is the same as the address in #IotHttpsConnectionInfo_t.pAddress. This is here in the request structure to
|
||||
* automatically generate the "Host" header field in the header buffer space configured in
|
||||
* #IotHttpsRequestInfo_t.userBuffer. See @ref https_client_function_initializerequest for more information.
|
||||
*/
|
||||
const char * pHost;
|
||||
uint32_t hostLen; /**< @brief Host address length. */
|
||||
|
||||
/**
|
||||
* @brief Flag denoting if the connection should be non-persistent.
|
||||
*
|
||||
* If this flag is set to false, then the connection is persistent. When the connection is persistent, the HTTP
|
||||
* header "Connection: keep-alive" is automatically added to the headers to send to the server. This header
|
||||
* asks the server to not close the connection after sending the response.
|
||||
*
|
||||
* If this flag is set to true, then the connection is non-persistent. When the connection is non-persistent, then
|
||||
* HTTP header "Connection: close" is automatically added to the headers to send to the server. This header asks
|
||||
* the server to close the connection after sending the response.
|
||||
*
|
||||
* Please see https://tools.ietf.org/html/rfc2616#section-8.1.1 for more details.
|
||||
*/
|
||||
bool isNonPersistent;
|
||||
|
||||
/**
|
||||
* @brief Application owned buffer for storing the request headers and internal request context.
|
||||
*
|
||||
* For an asynchronous request, if the application owns the memory for this buffer, then it must not be modified,
|
||||
* freed, or reused until the the #IotHttpsClientCallbacks_t.responseCompleteCallback is invoked.
|
||||
*
|
||||
* Please see #IotHttpsUserBuffer_t for more information.
|
||||
*/
|
||||
IotHttpsUserBuffer_t userBuffer;
|
||||
|
||||
/**
|
||||
* @brief Indicator if this request is sync or async.
|
||||
*
|
||||
* Set this to false to use a synchronous request. Set this to true to use an asynchronous request.
|
||||
*/
|
||||
bool isAsync;
|
||||
|
||||
/**
|
||||
* @brief Specific information for either a synchronous request or an asynchronous request.
|
||||
*
|
||||
* See #IotHttpsAsyncInfo_t for information on pAsyncInfo.
|
||||
* See #IotHttpsSyncInfo_t for information on u.pSyncInfo.
|
||||
*/
|
||||
union
|
||||
{
|
||||
IotHttpsAsyncInfo_t * pAsyncInfo; /**< @brief Information specifically for Asynchronous requests. */
|
||||
IotHttpsSyncInfo_t * pSyncInfo; /**< @brief Information specifically for synchronous requests. */
|
||||
} u;
|
||||
} IotHttpsRequestInfo_t;
|
||||
|
||||
/**
|
||||
* @ingroup https_client_datatypes_paramstructs
|
||||
* @brief HTTP request configuration.
|
||||
*
|
||||
* @paramfor @ref https_client_function_sendsync and @ref https_client_function_sendasync
|
||||
*
|
||||
* A separate response info is defined so that the application can re-initialize a request for re-use while still
|
||||
* processing a response that was already completed.
|
||||
*/
|
||||
typedef struct IotHttpsResponseInfo
|
||||
{
|
||||
/**
|
||||
* The application owned buffer for storing the response headers and internal response context.
|
||||
*
|
||||
* For an asynchronous request, if the application owns the memory for this buffer, then it must not be modified,
|
||||
* freed, or reused until the the #IotHttpsClientCallbacks_t.responseCompleteCallback is invoked.
|
||||
*
|
||||
* Please see #IotHttpsUserBuffer_t for more information.
|
||||
*/
|
||||
IotHttpsUserBuffer_t userBuffer;
|
||||
|
||||
/**
|
||||
* @brief Specific information for a synchronously received response.
|
||||
*
|
||||
* Set this to NULL if the response is to be received asynchronously.
|
||||
*
|
||||
* See #IotHttpsSyncInfo_t for more information.
|
||||
*/
|
||||
IotHttpsSyncInfo_t * pSyncInfo;
|
||||
} IotHttpsResponseInfo_t;
|
||||
|
||||
#endif /* ifndef IOT_HTTPS_TYPES_H_ */
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Amazon FreeRTOS HTTPS Client V1.1.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.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_https_utils.c
|
||||
* @brief Implements functions for HTTPS Client library utilities.
|
||||
*/
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* iot_https_includes */
|
||||
#include "iot_https_utils.h"
|
||||
#include "http_parser.h"
|
||||
#include "private/iot_https_internal.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
IotHttpsReturnCode_t IotHttpsClient_GetUrlPath( const char * pUrl,
|
||||
size_t urlLen,
|
||||
const char ** pPath,
|
||||
size_t * pPathLen )
|
||||
{
|
||||
/* http-parser status. Initialized to 0 to signify success. */
|
||||
int parserStatus = 0;
|
||||
struct http_parser_url urlParser;
|
||||
IotHttpsReturnCode_t returnStatus = IOT_HTTPS_OK;
|
||||
|
||||
/* Sets all members in urlParser to 0. */
|
||||
http_parser_url_init( &urlParser );
|
||||
|
||||
if( ( pUrl == NULL ) || ( pPath == NULL ) || ( pPathLen == NULL ) )
|
||||
{
|
||||
IotLogError( "NULL parameter passed to IotHttpsClient_GetUrlPath()." );
|
||||
returnStatus = IOT_HTTPS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if( returnStatus == IOT_HTTPS_OK )
|
||||
{
|
||||
parserStatus = http_parser_parse_url( pUrl, urlLen, 0, &urlParser );
|
||||
|
||||
if( parserStatus != 0 )
|
||||
{
|
||||
IotLogError( "Error parsing the input URL %.*s. Error code: %d.", urlLen, pUrl, parserStatus );
|
||||
returnStatus = IOT_HTTPS_PARSING_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if( returnStatus == IOT_HTTPS_OK )
|
||||
{
|
||||
*pPathLen = ( size_t ) ( urlParser.field_data[ UF_PATH ].len );
|
||||
|
||||
if( *pPathLen == 0 )
|
||||
{
|
||||
returnStatus = IOT_HTTPS_NOT_FOUND;
|
||||
*pPath = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pPath = &pUrl[ urlParser.field_data[ UF_PATH ].off ];
|
||||
}
|
||||
}
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
IotHttpsReturnCode_t IotHttpsClient_GetUrlAddress( const char * pUrl,
|
||||
size_t urlLen,
|
||||
const char ** pAddress,
|
||||
size_t * pAddressLen )
|
||||
{
|
||||
/* http-parser status. Initialized to 0 to signify success. */
|
||||
int parserStatus = 0;
|
||||
struct http_parser_url urlParser;
|
||||
IotHttpsReturnCode_t returnStatus = IOT_HTTPS_OK;
|
||||
|
||||
/* Sets all members in urlParser to 0. */
|
||||
http_parser_url_init( &urlParser );
|
||||
|
||||
if( ( pUrl == NULL ) || ( pAddress == NULL ) || ( pAddressLen == NULL ) )
|
||||
{
|
||||
IotLogError( "NULL parameter passed to IotHttpsClient_GetUrlAddress()." );
|
||||
returnStatus = IOT_HTTPS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if( returnStatus == IOT_HTTPS_OK )
|
||||
{
|
||||
parserStatus = http_parser_parse_url( pUrl, urlLen, 0, &urlParser );
|
||||
|
||||
if( parserStatus != 0 )
|
||||
{
|
||||
IotLogError( "Error parsing the input URL %.*s. Error code: %d.", urlLen, pUrl, parserStatus );
|
||||
returnStatus = IOT_HTTPS_PARSING_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if( returnStatus == IOT_HTTPS_OK )
|
||||
{
|
||||
*pAddressLen = ( size_t ) ( urlParser.field_data[ UF_HOST ].len );
|
||||
|
||||
if( *pAddressLen == 0 )
|
||||
{
|
||||
returnStatus = IOT_HTTPS_NOT_FOUND;
|
||||
*pAddress = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pAddress = &pUrl[ urlParser.field_data[ UF_HOST ].off ];
|
||||
}
|
||||
}
|
||||
|
||||
return returnStatus;
|
||||
}
|
|
@ -0,0 +1,497 @@
|
|||
/*
|
||||
* Amazon FreeRTOS HTTPS Client V1.1.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.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
#ifndef IOT_HTTPS_INTERNAL_H_
|
||||
#define IOT_HTTPS_INTERNAL_H_
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* Standard Includes. */
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Third party http-parser include. */
|
||||
#include "http_parser.h"
|
||||
|
||||
/* HTTPS Client library includes. */
|
||||
#include "iot_https_client.h"
|
||||
|
||||
/* Task pool include. */
|
||||
#include "iot_taskpool_freertos.h"
|
||||
|
||||
/* Linear containers (lists and queues) include. */
|
||||
#include "iot_linear_containers.h"
|
||||
|
||||
/* Types include. */
|
||||
#include "types/iot_taskpool_types_freertos.h"
|
||||
|
||||
/* Platform layer includes. */
|
||||
#include "platform/iot_threads.h"
|
||||
#include "platform/iot_network.h"
|
||||
|
||||
/* Error handling include. */
|
||||
#include "iot_error.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Convenience macros for handling errors in a standard way. */
|
||||
|
||||
/**
|
||||
* @brief Every public API return an enumeration value with an underlying value of 0 in case of success.
|
||||
*/
|
||||
#define HTTPS_SUCCEEDED( x ) ( ( x ) == IOT_HTTPS_OK )
|
||||
|
||||
/**
|
||||
* @brief Every public API returns an enumeration value with an underlying value different than 0 in case of success.
|
||||
*/
|
||||
#define HTTPS_FAILED( x ) ( ( x ) != IOT_HTTPS_OK )
|
||||
|
||||
/**
|
||||
* @brief Declare the storage for the error status variable.
|
||||
*/
|
||||
#define HTTPS_FUNCTION_ENTRY( result ) IOT_FUNCTION_ENTRY( IotHttpsReturnCode_t, result )
|
||||
|
||||
/**
|
||||
* @brief Jump to the cleanup area.
|
||||
*/
|
||||
#define HTTPS_GOTO_CLEANUP() IOT_GOTO_CLEANUP()
|
||||
|
||||
/**
|
||||
* @brief Set error and leave.
|
||||
*/
|
||||
#define HTTPS_SET_AND_GOTO_CLEANUP( statusValue ) IOT_SET_AND_GOTO_CLEANUP( statusValue )
|
||||
|
||||
/**
|
||||
* @brief Initialize error and declare start of cleanup area.
|
||||
*/
|
||||
#define HTTPS_FUNCTION_CLEANUP_BEGIN() IOT_FUNCTION_CLEANUP_BEGIN()
|
||||
|
||||
/**
|
||||
* @brief Initialize error and declare end of cleanup area.
|
||||
*/
|
||||
#define HTTPS_FUNCTION_CLEANUP_END() IOT_FUNCTION_CLEANUP_END()
|
||||
|
||||
/**
|
||||
* @brief Create an empty cleanup area.
|
||||
*/
|
||||
#define HTTPS_FUNCTION_EXIT_NO_CLEANUP() IOT_FUNCTION_EXIT_NO_CLEANUP()
|
||||
|
||||
/**
|
||||
* @brief Exit if an argument is NULL.
|
||||
*/
|
||||
#define HTTPS_ON_NULL_ARG_GOTO_CLEANUP( ptr ) \
|
||||
if( ( ptr == NULL ) ) \
|
||||
{ \
|
||||
IotLogError( # ptr " was NULL." ); \
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exit if an condition is false.
|
||||
*/
|
||||
#define HTTPS_ON_ARG_ERROR_GOTO_CLEANUP( expr ) \
|
||||
if( ( expr ) == false ) \
|
||||
{ \
|
||||
IotLogError( # expr " must be true." ); \
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_HTTPS_INVALID_PARAMETER ); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exit if an argument is false with a message.
|
||||
*/
|
||||
#define HTTPS_ON_ARG_ERROR_MSG_GOTO_CLEANUP( expr, statusValue, ... ) \
|
||||
if( ( expr ) == false ) \
|
||||
{ \
|
||||
IotLogError( __VA_ARGS__ ); \
|
||||
IOT_SET_AND_GOTO_CLEANUP( statusValue ); \
|
||||
}
|
||||
|
||||
/* Configure logs for HTTPS Client functions. */
|
||||
#ifdef IOT_LOG_LEVEL_HTTPS
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_HTTPS
|
||||
#else
|
||||
#ifdef IOT_LOG_LEVEL_GLOBAL
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
|
||||
#else
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_NONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LIBRARY_LOG_NAME ( "HTTPS Client" )
|
||||
#include "iot_logging_setup.h"
|
||||
|
||||
/*
|
||||
* Provide default values for undefined memory allocation functions based on
|
||||
* the usage of dynamic memory allocation.
|
||||
*/
|
||||
#if IOT_STATIC_MEMORY_ONLY == 1
|
||||
#include "iot_static_memory.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @cond DOXYGEN_IGNORE
|
||||
* Doxygen should ignore this section.
|
||||
*
|
||||
* Provide default values for undefined configuration constants.
|
||||
*/
|
||||
#ifndef AWS_IOT_HTTPS_ENABLE_METRICS
|
||||
#define AWS_IOT_HTTPS_ENABLE_METRICS ( 1 )
|
||||
#endif
|
||||
#ifndef IOT_HTTPS_USER_AGENT
|
||||
#define IOT_HTTPS_USER_AGENT "FreeRTOS"
|
||||
#endif
|
||||
#ifndef IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE
|
||||
#define IOT_HTTPS_MAX_FLUSH_BUFFER_SIZE ( 1024 )
|
||||
#endif
|
||||
#ifndef IOT_HTTPS_RESPONSE_WAIT_MS
|
||||
#define IOT_HTTPS_RESPONSE_WAIT_MS ( 1000 )
|
||||
#endif
|
||||
#ifndef IOT_HTTPS_MAX_HOST_NAME_LENGTH
|
||||
#define IOT_HTTPS_MAX_HOST_NAME_LENGTH ( 255 ) /* Per FQDN, the maximum host name length is 255 bytes. */
|
||||
#endif
|
||||
#ifndef IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH
|
||||
#define IOT_HTTPS_MAX_ALPN_PROTOCOLS_LENGTH ( 255 ) /* The maximum alpn protocols length is chosen arbitrarily. */
|
||||
#endif
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief The HTTP protocol version of this library is HTTP/1.1.
|
||||
*/
|
||||
#define HTTPS_PROTOCOL_VERSION "HTTP/1.1"
|
||||
|
||||
/**
|
||||
* @brief An empty path for a NULL specified path in the request initialization configuration.
|
||||
*/
|
||||
#define HTTPS_EMPTY_PATH "/"
|
||||
|
||||
/**
|
||||
* @brief HTTPS "CONNECT" method, defined as the longest string length method.
|
||||
*/
|
||||
#define HTTPS_CONNECT_METHOD "CONNECT"
|
||||
|
||||
/*
|
||||
* Constants for the values of the HTTP "Connection" header field.
|
||||
*
|
||||
* This is used for writing headers automatically during the sending of the HTTP request.
|
||||
* "Connection: keep-alive\r\n" is written automatically for a persistent connection.
|
||||
* "Connection: close\r\n" is written automatically for a non-persistent connection.
|
||||
*/
|
||||
#define HTTPS_CONNECTION_KEEP_ALIVE_HEADER_VALUE "keep-alive"
|
||||
#define HTTPS_CONNECTION_CLOSE_HEADER_VALUE "close"
|
||||
|
||||
/**
|
||||
* Constants for HTTP header formatting.
|
||||
*
|
||||
* ": " separates and header field from the header value.
|
||||
*/
|
||||
#define HTTPS_HEADER_FIELD_SEPARATOR ": "
|
||||
#define HTTPS_HEADER_FIELD_SEPARATOR_LENGTH ( 2 )
|
||||
#define COLON_CHARACTER ':'
|
||||
#define SPACE_CHARACTER ' '
|
||||
|
||||
/**
|
||||
* Constants for HTTP header formatting.
|
||||
*
|
||||
* "\r\n" Ends the header line.
|
||||
*/
|
||||
#define HTTPS_END_OF_HEADER_LINES_INDICATOR "\r\n"
|
||||
#define HTTPS_END_OF_HEADER_LINES_INDICATOR_LENGTH ( 2 )
|
||||
#define CARRIAGE_RETURN_CHARACTER '\r'
|
||||
#define NEWLINE_CHARACTER '\n'
|
||||
|
||||
/*
|
||||
* Constants for header fields added automatically during the request initialization.
|
||||
*/
|
||||
#define HTTPS_USER_AGENT_HEADER "User-Agent"
|
||||
#define HTTPS_HOST_HEADER "Host"
|
||||
|
||||
/*
|
||||
* Constants for the header fields added automatically during the sending of the HTTP request.
|
||||
*/
|
||||
#define HTTPS_CONTENT_LENGTH_HEADER "Content-Length"
|
||||
#define HTTPS_CONNECTION_HEADER "Connection"
|
||||
|
||||
/**
|
||||
* @brief The maximum Content-Length header line size.
|
||||
*
|
||||
* This is the length of header line string: "Content-Length: 4294967296\r\n". 4294967296 is 2^32. This number is chosen
|
||||
* because it is the maximum file size that can be represented in a 32 bit system.
|
||||
*
|
||||
* This is used to initialize a local array for the final headers to send.
|
||||
*/
|
||||
#define HTTPS_MAX_CONTENT_LENGTH_LINE_LENGTH ( 26 )
|
||||
|
||||
/**
|
||||
* @brief Macro for fast string length calculation of string macros.
|
||||
*
|
||||
* We subtract 1 to subtract the NULL terminating character.
|
||||
* We do not assume that the size of a character is a single byte or 8 bits with this calculation.
|
||||
*/
|
||||
#define FAST_MACRO_STRLEN( x ) ( ( sizeof( x ) / sizeof( char ) ) - 1 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The state of the HTTP response parsing.
|
||||
*
|
||||
* This state notes what has been parsed in the HTTP response. As soon as any part of the HTTP response is received from
|
||||
* the network, it is sent to be parsed.
|
||||
*
|
||||
* The states move as follows:
|
||||
* PARSER_STATE_NONE --> PARSER_STATE_IN_HEADERS --> PARSER_STATE_HEADERS_COMPLETE --> PARSER_STATE_BODY_COMPLETE
|
||||
*
|
||||
* The parser callbacks are called in the following order:
|
||||
* 1. _httpParserOnMessageBeginCallback()
|
||||
* 2. _httpParserOnStatusCallback()
|
||||
* 3. _httpParserOnHeaderFieldCallback()
|
||||
* 4. _httpParserOnHeaderValueCallback()
|
||||
* 5. _httpParserOnHeadersCompleteCallback()
|
||||
* 6. _httpParserOnChunkHeaderCallback() (optional only if the response is chunked)
|
||||
* 7. _httpParserOnBodyCallback()
|
||||
* 8. _httpParserOnChunkCompleteCallback() (optional only if the response is chunked)
|
||||
* 9. _httpParserOnMessageCompleteCallback()
|
||||
*
|
||||
* Theses states are set in the parser callbacks and used outside the callbacks to determine action.
|
||||
*
|
||||
* PARSER_STATE_NONE is assigned to #_httpsResponse_t.parserState when the _httpsResponse_t.parserState is initialized
|
||||
* in @ref IotHttpsClient_InitializeRequest and before parsing a new respone message from the server.
|
||||
*
|
||||
* PARSER_STATE_IN_HEADERS is assigned at the start of the HTTP Response message. This occurs in the
|
||||
* _httpParserOnMessageBeginCallback(). HTTP headers are always first and there is always the response status line
|
||||
* and some headers in a response message according to RFC 2616.
|
||||
*
|
||||
* PARSER_STATE_HEADERS_COMPLETE is assigned when all of the headers are finished being parsed in the HTTP response
|
||||
* message. This occurs in the _httpParserOnHeadersCompleteCallback(). The state can end here if the response has no
|
||||
* body, like for a response to a HEAD request.
|
||||
* If this state is not reached after receiving headers from the network into the user configured header buffer and
|
||||
* running it through the parser, then we know that not all of the headers from the response could fit into the buffer.
|
||||
*
|
||||
* PARSER_STATE_IN_BODY is assigned each time the parser reaches HTTP response body. This occurs in the
|
||||
* _httpParserOnBodyCallback().
|
||||
*
|
||||
* PARSER_STATE_BODY_COMPLETE is assigned when the parser has finished with the whole HTTP response message. This
|
||||
* happens when _httpParserOnMessageCompleteCallback() is invoked.
|
||||
* If this state is not reached after receiving body from the network into the user configured body buffer and
|
||||
* running it through the parser, then we know that not all of the body from the response could fit into the buffer.
|
||||
*/
|
||||
typedef enum IotHttpsResponseParserState
|
||||
{
|
||||
PARSER_STATE_NONE = 0, /**< @brief The parser has not started so we are neither in the headers or the body. */
|
||||
PARSER_STATE_IN_HEADERS, /**< @brief The parser is currently parsing the HTTP respone headers. */
|
||||
PARSER_STATE_HEADERS_COMPLETE, /**< @brief The parser has finished parsing the headers. */
|
||||
PARSER_STATE_IN_BODY, /**< @brief The parser is currently parsing the HTTP response body. */
|
||||
PARSER_STATE_BODY_COMPLETE /**< @brief The parser has completed parsing the HTTP response body. */
|
||||
} IotHttpsResponseParserState_t;
|
||||
|
||||
/**
|
||||
* @brief The state denoting which buffer (the header buffer or the body buffer) is currently being processed
|
||||
* and for what.
|
||||
*
|
||||
* This state is set outside of the parser callbacks and used inside the of parser callbacks to determine actions.
|
||||
*
|
||||
* The state moves as follows:
|
||||
* Receiving and parsing a response: PROCESSING_STATE_NONE --> PROCESSING_STATE_FILLING_HEADER_BUFFER --> PROCESSING_STATE_FILLING_BODY_BUFFER --> PROCESSING_STATE_FINISHED
|
||||
* Searching a response for headers: ((enter state)) --> PROCESSING_STATE_SEARCHING_HEADER_BUFFER --> ((enter state))
|
||||
*
|
||||
* PROCESSING_STATE_NONE is assigned when #_httpsResponse_t.bufferProcessingState is initialized in
|
||||
* @ref IotHttpsClient_InitializeRequest.
|
||||
*
|
||||
* PROCESSING_STATE_FILLING_HEADER_BUFFER is assigned at the start of receiving HTTP response headers from the network
|
||||
* into the header buffer, before processing the received headers with the parser.
|
||||
* This state is then used in the parser callbacks _httpParserOnStatusCallback(), _httpParserOnHeaderFieldCallback(),
|
||||
* _httpParserOnHeaderValueCallback(), and _httpParserOnHeadersCompleteCallback() to move the
|
||||
* #_httpsResponse_t.headersCur pointer along in the header buffer.
|
||||
* Since the server sends the HTTP response as a single continuous message, sometimes during receiving of the HTTP
|
||||
* headers we may receive part or all of the HTTP response body:
|
||||
* ((example header buffer))[headers headers headers headers body body body]
|
||||
* When parsing this header buffer the parser will execute _httpParserOnBodyCallback() in the
|
||||
* PROCESSING_STATE_FILLING_HEADER_BUFFER state. The state is used here, for an asynchronous response, to save where
|
||||
* and how much body is inside the of the header buffer. When a body buffer becomes available, the body in the header
|
||||
* buffer will be copied to the body buffer.
|
||||
*
|
||||
* PROCESSING_STATE_FILLING_BODY_BUFFER is assigned at the start of receiving the HTTP response body form the network
|
||||
* into the body buffer, before processing the received body with the parser.
|
||||
*
|
||||
* PROCESSING_STATE_FINISHED is assigned at the end of IotHttpsClient_SendSync() or at the end of
|
||||
* IotHttpsClient_SendAsync() when both the header and body buffer are finished being filled with network data and
|
||||
* parsed.
|
||||
*
|
||||
* PROCESSING_STATE_SEARCHING_HEADER_BUFFER is assigned in IotHttpsClient_ReadHeader() when searching for a header
|
||||
* in the header buffer.
|
||||
* This state is used in the parser callback _httpParserOnHeaderFieldCallback() to check if the current header field
|
||||
* parsed equals the header we are searching for. It is used in parser callback _httpParserOnHeaderValueCallback() to
|
||||
* return the header value if the corresponding field we are searching for was found. It is used in parser callback
|
||||
* _httpParserOnHeadersCompleteCallback() to stop parsing the header buffer if the header we are searching for was not
|
||||
* found.
|
||||
*
|
||||
* The header buffer is separate from the body buffer.
|
||||
* The header buffer is configured in #IotHttpRequestInfo_t.respUserBuff. The body buffer is configured in
|
||||
* #IotHttpRequestInfo_t.syncInfo->respData or as buffer provided asynchronously during the
|
||||
* #IotHttpsClientCallbacks_t.readReadyCallback() to call to @ref IotHttpsClient_ReadResponseBody().
|
||||
*/
|
||||
typedef enum IotHttpsResponseBufferState
|
||||
{
|
||||
PROCESSING_STATE_NONE, /**< @brief There is no buffer processing currently. */
|
||||
PROCESSING_STATE_FILLING_HEADER_BUFFER, /**< @brief The header buffer is being filled and parsed. */
|
||||
PROCESSING_STATE_FILLING_BODY_BUFFER, /**< @brief The body buffer is being filled and parsed. */
|
||||
PROCESSING_STATE_FINISHED, /**< @brief Filling and parsing of both buffers is finished. */
|
||||
PROCESSING_STATE_SEARCHING_HEADER_BUFFER /**< @brief The header buffer is being searched. */
|
||||
} IotHttpsResponseBufferState_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Represents an HTTP connection.
|
||||
*/
|
||||
typedef struct _httpsConnection
|
||||
{
|
||||
const IotNetworkInterface_t * pNetworkInterface; /**< @brief Network interface with calls for connect, disconnect, send, and receive. */
|
||||
IotNetworkConnection_t pNetworkConnection; /**< @brief Pointer to the network connection to use pNetworkInterface calls on. */
|
||||
uint32_t timeout; /**< @brief Timeout for a connection and waiting for a response from the network. */
|
||||
|
||||
/**
|
||||
* @brief true if a connection was successful most recently on this context
|
||||
*
|
||||
* We have no way of knowing if the server closed the connection because that error is unique to the underlying TLS
|
||||
* layer. This is set to false initially, then set to true for a successful intentional call to connect.
|
||||
* Post connection, this is set to false only after an implicit disconnect with a non-persistent request, an implicit
|
||||
* disconnect with a network error, or an explicit disconnect with a call to @ref https_client_function_disconnect.
|
||||
*/
|
||||
bool isConnected;
|
||||
bool isDestroyed; /**< @brief true if the connection is already destroyed and we should call anymore */
|
||||
IotMutex_t connectionMutex; /**< @brief Mutex protecting operations on this entire connection context. */
|
||||
IotDeQueue_t reqQ; /**< @brief The queue for the requests that are not finished yet. */
|
||||
IotDeQueue_t respQ; /**< @brief The queue for the responses that are waiting to be processed. */
|
||||
IotTaskPoolJobStorage_t taskPoolJobStorage; /**< @brief An asynchronous operation requires storage for the task pool job. */
|
||||
IotTaskPoolJob_t taskPoolJob; /**< @brief The task pool job identifier for an asynchronous request. */
|
||||
} _httpsConnection_t;
|
||||
|
||||
/**
|
||||
* @brief Third party library http-parser information.
|
||||
*
|
||||
* There are two separate structures for http_parser state information. This is so that the application can read
|
||||
* a header during it's readReadyCallback. The readReadyCallback could be invoked many times and the parser will
|
||||
* therefore be invoked many times for each response read from the network. In order to ensure that the state of
|
||||
* the parser remains intact whilst headers may be read, two structures holding the state are kept.
|
||||
*/
|
||||
typedef struct _httpParserInfo
|
||||
{
|
||||
http_parser responseParser; /**< @brief http_parser state information for parsing the response. */
|
||||
size_t ( * parseFunc )( http_parser * parser,
|
||||
const http_parser_settings * settings,
|
||||
const char * data,
|
||||
size_t len ); /**< @brief http_parser_execute function is to be plugged in here during initialization of the response. */
|
||||
http_parser readHeaderParser; /**< @brief http_parser state information for parsing the header buffer for reading a header. */
|
||||
} _httpParserInfo_t;
|
||||
|
||||
/**
|
||||
* @brief Represents an HTTP response.
|
||||
*/
|
||||
typedef struct _httpsResponse
|
||||
{
|
||||
IotLink_t link; /**< @brief The link to insert the job in the connection's respQ. */
|
||||
uint8_t * pHeaders; /**< @brief Pointer to the start of the headers buffer. */
|
||||
uint8_t * pHeadersEnd; /**< @brief Pointer to the end of the headers buffer. */
|
||||
uint8_t * pHeadersCur; /**< @brief Pointer to the next location to write in the headers buffer. */
|
||||
uint8_t * pBody; /**< @brief Pointer to the start of the body buffer. */
|
||||
uint8_t * pBodyEnd; /**< @brief Pointer to the end of the body buffer. */
|
||||
uint8_t * pBodyCur; /**< @brief Pointer to the next location to write in the body buffer. */
|
||||
_httpParserInfo_t httpParserInfo; /**< @brief Third party http-parser information. */
|
||||
uint16_t status; /**< @brief The HTTP response status code of this response. */
|
||||
IotHttpsMethod_t method; /**< @brief The method of the originating request. */
|
||||
IotHttpsResponseParserState_t parserState; /**< @brief The current state of the parser. See IotHttpsResponseParserState_t documentation for more details. */
|
||||
IotHttpsResponseBufferState_t bufferProcessingState; /**< @brief Which buffer is currently being processed and for what. See IotHttpsResponseBufferState_t documentation. */
|
||||
char * pReadHeaderField; /**< @brief Header field that we want to read from the headers buffer when IotHttpsClient_ReadHeader() is called. */
|
||||
size_t readHeaderFieldLength; /**< @brief Length of pReadHeaderField */
|
||||
char * pReadHeaderValue; /**< @brief Header value that we read from the headers buffer when IotHttpsClient_ReadHeader() is called. */
|
||||
size_t readHeaderValueLength; /**< @brief Length of pReadHeaderValue. */
|
||||
bool foundHeaderField; /**< @brief State to use during parsing to let us know when we found the header field in the https-parser callbacks.
|
||||
* This is set to true when the header field is found in parser callback _httpParserOnHeaderFieldCallback().
|
||||
* On the following parser callback _httpParserOnHeaderValueCallback() we will store the value in pReadHeaderValue and then exit the parsing. */
|
||||
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. */
|
||||
bool isAsync; /**< @brief This is set to true if this response is to be retrieved asynchronously. Set to false otherwise. */
|
||||
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. */
|
||||
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. */
|
||||
IotHttpsReturnCode_t bodyRxStatus; /**< @brief The status of network receiving the HTTPS body to be returned during the #IotHttpsClientCallbacks_t.readReadyCallback. */
|
||||
bool cancelled; /**< @brief This is set to true to stop the request/response processing in the asynchronous request workflow. */
|
||||
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. */
|
||||
IotHttpsReturnCode_t syncStatus; /**< @brief The status of the synchronous response. */
|
||||
|
||||
/**
|
||||
* @brief This is set to true to when the request is finished being sent on the network
|
||||
*
|
||||
* A request is not shared with multiple tasks, so only one task will update this. This is to let the let the
|
||||
* network receive callback know that the request is fully pushed out to the server. This is also to let the
|
||||
* disconnect know that the request is not using the network interface resources anymore.
|
||||
*/
|
||||
bool reqFinishedSending;
|
||||
IotHttpsClientCallbacks_t * pCallbacks; /**< @brief Pointer to the asynchronous request callbacks. */
|
||||
void * pUserPrivData; /**< @brief User private data to hand back in the asynchronous callbacks for context. */
|
||||
bool isNonPersistent; /**< @brief Non-persistent flag to indicate closing the connection immediately after receiving the response. */
|
||||
} _httpsResponse_t;
|
||||
|
||||
/**
|
||||
* @brief Represents and HTTP request.
|
||||
*/
|
||||
typedef struct _httpsRequest
|
||||
{
|
||||
IotLink_t link; /**< @brief The link to insert the job in the connection's reqQ. */
|
||||
uint8_t * pHeaders; /**< @brief Pointer to the start of the headers buffer. */
|
||||
uint8_t * pHeadersEnd; /**< @brief Pointer to the end of the headers buffer. */
|
||||
uint8_t * pHeadersCur; /**< @brief Pointer to the next location to write in the headers buffer. */
|
||||
uint8_t * pBody; /**< @brief Pointer to the start of the body buffer. */
|
||||
uint32_t bodyLength; /**< @brief Length of request body buffer. */
|
||||
IotHttpsMethod_t method; /**< @brief The method of the originating request. */
|
||||
IotHttpsConnectionInfo_t * pConnInfo; /**< @brief Connection info associated with this request. For an implicit connection. */
|
||||
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(). */
|
||||
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. */
|
||||
bool isNonPersistent; /**< @brief Non-persistent flag to indicate closing the connection immediately after receiving the response. */
|
||||
bool isAsync; /**< @brief This is set to true if this request is to be sent asynchronously. Set to false otherwise. */
|
||||
void * pUserPrivData; /**< @brief User private data to hand back in the asynchronous callbacks for context. */
|
||||
IotHttpsClientCallbacks_t * pCallbacks; /**< @brief Pointer to the asynchronous request callbacks. */
|
||||
bool cancelled; /**< @brief Set this to true to stop the response processing in the asynchronous workflow. */
|
||||
IotHttpsReturnCode_t bodyTxStatus; /**< @brief The status of network sending the HTTPS body to be returned during the #IotHttpsClientCallbacks_t.writeCallback. */
|
||||
bool scheduled; /**< @brief Set to true when this request has already been scheduled to the task pool. */
|
||||
} _httpsRequest_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief A map of the method enum to strings
|
||||
*
|
||||
* These are in order to the HTTP request method enums defined in IotHttpsMethod_t.
|
||||
*/
|
||||
static const char * _pHttpsMethodStrings[] = {
|
||||
"GET",
|
||||
"HEAD",
|
||||
"PUT",
|
||||
"POST"
|
||||
};
|
||||
|
||||
#endif /* IOT_HTTPS_INTERNAL_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue