in source/core_http_client.c [57:569]
static HTTPStatus_t sendHttpData( const TransportInterface_t * pTransport,
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
const uint8_t * pData,
size_t dataLen );
/**
* @brief Send the HTTP headers over the transport send interface.
*
* @param[in] pTransport Transport interface.
* @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
* @param[in] pRequestHeaders Request headers to send, it includes the buffer
* and length.
* @param[in] reqBodyLen The length of the request body to be sent. This is
* used to generated a Content-Length header.
* @param[in] sendFlags Application provided flags to #HTTPClient_Send.
*
* @return #HTTPSuccess if successful. If there was a network error or less
* bytes than what were specified were sent, then #HTTPNetworkError is
* returned.
*/
static HTTPStatus_t sendHttpHeaders( const TransportInterface_t * pTransport,
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
HTTPRequestHeaders_t * pRequestHeaders,
size_t reqBodyLen,
uint32_t sendFlags );
/**
* @brief Adds the Content-Length header field and value to the
* @p pRequestHeaders.
*
* @param[in] pRequestHeaders Request header buffer information.
* @param[in] contentLength The Content-Length header value to write.
*
* @return #HTTPSuccess if successful. If there was insufficient memory in the
* application buffer, then #HTTPInsufficientMemory is returned.
*/
static HTTPStatus_t addContentLengthHeader( HTTPRequestHeaders_t * pRequestHeaders,
size_t contentLength );
/**
* @brief Send the HTTP body over the transport send interface.
*
* @param[in] pTransport Transport interface.
* @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
* @param[in] pRequestBodyBuf Request body buffer.
* @param[in] reqBodyBufLen Length of the request body buffer.
*
* @return #HTTPSuccess if successful. If there was a network error or less
* bytes than what was specified were sent, then #HTTPNetworkError is
* returned.
*/
static HTTPStatus_t sendHttpBody( const TransportInterface_t * pTransport,
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
const uint8_t * pRequestBodyBuf,
size_t reqBodyBufLen );
/**
* @brief A strncpy replacement with HTTP header validation.
*
* This function checks for `\r` and `\n` in the @p pSrc while copying.
* This function checks for `:` in the @p pSrc, if @p isField is set to 1.
*
* @param[in] pDest The destination buffer to copy to.
* @param[in] pSrc The source buffer to copy from.
* @param[in] len The length of @p pSrc to copy to pDest.
* @param[in] isField Set to 0 to indicate that @p pSrc is a field. Set to 1 to
* indicate that @p pSrc is a value.
*
* @return @p pDest if the copy was successful, NULL otherwise.
*/
static char * httpHeaderStrncpy( char * pDest,
const char * pSrc,
size_t len,
uint8_t isField );
/**
* @brief Write header based on parameters. This method also adds a trailing
* "\r\n". If a trailing "\r\n" already exists in the HTTP header, this method
* backtracks in order to write over it and updates the length accordingly.
*
* @param[in] pRequestHeaders Request header buffer information.
* @param[in] pField The ISO 8859-1 encoded header field name to write.
* @param[in] fieldLen The byte length of the header field name.
* @param[in] pValue The ISO 8859-1 encoded header value to write.
* @param[in] valueLen The byte length of the header field value.
*
* @return #HTTPSuccess if successful. If there was insufficient memory in the
* application buffer, then #HTTPInsufficientMemory is returned.
*/
static HTTPStatus_t addHeader( HTTPRequestHeaders_t * pRequestHeaders,
const char * pField,
size_t fieldLen,
const char * pValue,
size_t valueLen );
/**
* @brief Add the byte range request header to the request headers store in
* #HTTPRequestHeaders_t.pBuffer once all the parameters are validated.
*
* @param[in] pRequestHeaders Request header buffer information.
* @param[in] rangeStartOrlastNbytes Represents either the starting byte
* for a range OR the last N number of bytes in the requested file.
* @param[in] rangeEnd The ending range for the requested file. For end of file
* byte in Range Specifications 2. and 3., #HTTP_RANGE_REQUEST_END_OF_FILE
* should be passed.
*
* @return #HTTPSuccess if successful. If there was insufficient memory in the
* application buffer, then #HTTPInsufficientMemory is returned.
*/
static HTTPStatus_t addRangeHeader( HTTPRequestHeaders_t * pRequestHeaders,
int32_t rangeStartOrlastNbytes,
int32_t rangeEnd );
/**
* @brief Get the status of the HTTP response given the parsing state and how
* much data is in the response buffer.
*
* @param[in] parsingState State of the parsing on the HTTP response.
* @param[in] totalReceived The amount of network data received in the response
* buffer.
* @param[in] responseBufferLen The length of the response buffer.
*
* @return Returns #HTTPSuccess if the parsing state is complete. If
* the parsing state denotes it never started, then return #HTTPNoResponse. If
* the parsing state is incomplete, then if the response buffer is not full
* #HTTPPartialResponse is returned. If the parsing state is incomplete, then
* if the response buffer is full #HTTPInsufficientMemory is returned.
*/
static HTTPStatus_t getFinalResponseStatus( HTTPParsingState_t parsingState,
size_t totalReceived,
size_t responseBufferLen );
/**
* @brief Receive the HTTP response from the network and parse it.
*
* @param[in] pTransport Transport interface.
* @param[in] pResponse Response message to receive data from the network.
* @param[in] pRequestHeaders Request headers for the corresponding HTTP request.
*
* @return Returns #HTTPSuccess if successful. #HTTPNetworkError for a transport
* receive error. Please see #parseHttpResponse and #getFinalResponseStatus for
* other statuses returned.
*/
static HTTPStatus_t receiveAndParseHttpResponse( const TransportInterface_t * pTransport,
HTTPResponse_t * pResponse,
const HTTPRequestHeaders_t * pRequestHeaders );
/**
* @brief Send the HTTP request over the network.
*
* @param[in] pTransport Transport interface.
* @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
* @param[in] pRequestHeaders Request headers to send over the network.
* @param[in] pRequestBodyBuf Request body buffer to send over the network.
* @param[in] reqBodyBufLen Length of the request body buffer.
* @param[in] sendFlags Application provided flags to #HTTPClient_Send.
*
* @return Returns #HTTPSuccess if successful. Please see #sendHttpHeaders and
* #sendHttpBody for other statuses returned.
*/
static HTTPStatus_t sendHttpRequest( const TransportInterface_t * pTransport,
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
HTTPRequestHeaders_t * pRequestHeaders,
const uint8_t * pRequestBodyBuf,
size_t reqBodyBufLen,
uint32_t sendFlags );
/**
* @brief Converts an integer value to its ASCII representation in the passed
* buffer.
*
* @param[in] value The value to convert to ASCII.
* @param[out] pBuffer The buffer to store the ASCII representation of the
* integer.
* @param[in] bufferLength The length of pBuffer.
*
* @return Returns the number of bytes written to @p pBuffer.
*/
static uint8_t convertInt32ToAscii( int32_t value,
char * pBuffer,
size_t bufferLength );
/**
* @brief This method writes the request line (first line) of the HTTP Header
* into #HTTPRequestHeaders_t.pBuffer and updates length accordingly.
*
* @param pRequestHeaders Request header buffer information.
* @param pMethod The HTTP request method e.g. "GET", "POST", "PUT", or "HEAD".
* @param methodLen The byte length of the request method.
* @param pPath The Request-URI to the objects of interest, e.g. "/path/to/item.txt".
* @param pathLen The byte length of the request path.
*
* @return #HTTPSuccess if successful. If there was insufficient memory in the
* application buffer, then #HTTPInsufficientMemory is returned.
*/
static HTTPStatus_t writeRequestLine( HTTPRequestHeaders_t * pRequestHeaders,
const char * pMethod,
size_t methodLen,
const char * pPath,
size_t pathLen );
/**
* @brief Find the specified header field in the response buffer.
*
* @param[in] pBuffer The response buffer to parse.
* @param[in] bufferLen The length of the response buffer to parse.
* @param[in] pField The header field to search for.
* @param[in] fieldLen The length of pField.
* @param[out] pValueLoc The location of the the header value found in pBuffer.
* @param[out] pValueLen The length of pValue.
*
* @return One of the following:
* - #HTTPSuccess when header is found in the response.
* - #HTTPHeaderNotFound if requested header is not found in response.
* - #HTTPInvalidResponse if passed response is invalid for parsing.
* - #HTTPParserInternalError for any parsing errors.
*/
static HTTPStatus_t findHeaderInResponse( const uint8_t * pBuffer,
size_t bufferLen,
const char * pField,
size_t fieldLen,
const char ** pValueLoc,
size_t * pValueLen );
/**
* @brief The "on_header_field" callback for the HTTP parser used by the
* #findHeaderInResponse function. The callback checks whether the parser
* header field matched the header being searched for, and sets a flag to
* represent reception of the header accordingly.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
* @param[in] pFieldLoc The location of the parsed header field in the response
* buffer.
* @param[in] fieldLen The length of the header field.
*
* @return Returns #HTTP_PARSER_CONTINUE_PARSING to indicate continuation with
* parsing.
*/
static int findHeaderFieldParserCallback( http_parser * pHttpParser,
const char * pFieldLoc,
size_t fieldLen );
/**
* @brief The "on_header_value" callback for the HTTP parser used by the
* #findHeaderInResponse function. The callback sets the user-provided output
* parameters for header value if the requested header's field was found in the
* @ref findHeaderFieldParserCallback function.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
* @param[in] pValueLoc The location of the parsed header value in the response
* buffer.
* @param[in] valueLen The length of the header value.
*
* @return Returns #HTTP_PARSER_STOP_PARSING, if the header field/value pair are
* found, otherwise #HTTP_PARSER_CONTINUE_PARSING is returned.
*/
static int findHeaderValueParserCallback( http_parser * pHttpParser,
const char * pValueLoc,
size_t valueLen );
/**
* @brief The "on_header_complete" callback for the HTTP parser used by the
* #findHeaderInResponse function.
*
* This callback will only be invoked if the requested header is not found in
* the response. This callback is used to signal the parser to halt execution
* if the requested header is not found.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
*
* @return Returns #HTTP_PARSER_STOP_PARSING for the parser to halt further
* execution, as all headers have been parsed in the response.
*/
static int findHeaderOnHeaderCompleteCallback( http_parser * pHttpParser );
/**
* @brief Initialize the parsing context for parsing a response fresh from the
* server.
*
* @param[in] pParsingContext The parsing context to initialize.
* @param[in] pRequestHeaders Request headers for the corresponding HTTP request.
*/
static void initializeParsingContextForFirstResponse( HTTPParsingContext_t * pParsingContext,
const HTTPRequestHeaders_t * pRequestHeaders );
/**
* @brief Parses the response buffer in @p pResponse.
*
* This function may be invoked multiple times for different parts of the the
* HTTP response. The state of what was last parsed in the response is kept in
* @p pParsingContext.
*
* @param[in,out] pParsingContext The response parsing state.
* @param[in,out] pResponse The response information to be updated.
* @param[in] parseLen The next length to parse in pResponse->pBuffer.
*
* @return One of the following:
* - #HTTPSuccess
* - #HTTPInvalidParameter
* - Please see #processHttpParserError for parsing errors returned.
*/
static HTTPStatus_t parseHttpResponse( HTTPParsingContext_t * pParsingContext,
HTTPResponse_t * pResponse,
size_t parseLen );
/**
* @brief Callback invoked during http_parser_execute() to indicate the start of
* the HTTP response message.
*
* This callback is invoked when an "H" in the "HTTP/1.1" that starts a response
* is found.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
*
* @return #HTTP_PARSER_CONTINUE_PARSING to continue parsing.
*/
static int httpParserOnMessageBeginCallback( http_parser * pHttpParser );
/**
* @brief Callback invoked during http_parser_execute() when the HTTP response
* status-code and its associated reason-phrase are found.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
* @param[in] pLoc Location of the HTTP response reason-phrase string in the
* response message buffer.
* @param[in] length Length of the HTTP response status code string.
*
* @return #HTTP_PARSER_CONTINUE_PARSING to continue parsing.
*/
static int httpParserOnStatusCallback( http_parser * pHttpParser,
const char * pLoc,
size_t length );
/**
* @brief Callback invoked during http_parser_execute() when an HTTP response
* header field is found.
*
* If only part of the header field was found, then parsing of the next part of
* the response message will invoke this callback in succession.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
* @param[in] pLoc Location of the header field string in the response
* message buffer.
* @param[in] length Length of the header field.
*
* @return #HTTP_PARSER_CONTINUE_PARSING to continue parsing.
*/
static int httpParserOnHeaderFieldCallback( http_parser * pHttpParser,
const char * pLoc,
size_t length );
/**
* @brief Callback invoked during http_parser_execute() when an HTTP response
* header value is found.
*
* This header value corresponds to the header field that was found in the
* immediately preceding httpParserOnHeaderFieldCallback().
*
* If only part of the header value was found, then parsing of the next part of
* the response message will invoke this callback in succession.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
* @param[in] pLoc Location of the header value in the response message buffer.
* @param[in] length Length of the header value.
*
* @return #HTTP_PARSER_CONTINUE_PARSING to continue parsing.
*/
static int httpParserOnHeaderValueCallback( http_parser * pHttpParser,
const char * pLoc,
size_t length );
/**
* @brief Callback invoked during http_parser_execute() when the end of the
* headers are found.
*
* The end of the headers is signaled in a HTTP response message by another
* "\r\n" after the final header line.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
*
* @return #HTTP_PARSER_CONTINUE_PARSING to continue parsing.
* #HTTP_PARSER_STOP_PARSING is returned if the response is for a HEAD request.
*/
static int httpParserOnHeadersCompleteCallback( http_parser * pHttpParser );
/**
* @brief Callback invoked during http_parser_execute() when the HTTP response
* body is found.
*
* If only part of the response body was found, then parsing of the next part of
* the response message will invoke this callback in succession.
*
* This callback will be also invoked in succession if the response body is of
* type "Transfer-Encoding: chunked". This callback will be invoked after each
* chunk header.
*
* The follow is an example of a Transfer-Encoding chunked response:
*
* @code
* HTTP/1.1 200 OK\r\n
* Content-Type: text/plain\r\n
* Transfer-Encoding: chunked\r\n
* \r\n
* d\r\n
* Hello World! \r\n
* 7\r\n
* I am a \r\n
* a\r\n
* developer.\r\n
* 0\r\n
* \r\n
* @endcode
*
* The first invocation of this callback will contain @p pLoc = "Hello World!"
* and @p length = 13.
* The second invocation of this callback will contain @p pLoc = "I am a " and
* @p length = 7.
* The third invocation of this callback will contain @p pLoc = "developer." and
* @p length = 10.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
* @param[in] pLoc - Pointer to the body string in the response message buffer.
* @param[in] length - The length of the body found.
*
* @return Zero to continue parsing. All other return values will stop parsing
* and http_parser_execute() will return with status HPE_CB_body.
*/
static int httpParserOnBodyCallback( http_parser * pHttpParser,
const char * pLoc,
size_t length );
/**
* @brief Callback invoked during http_parser_execute() to indicate the the
* completion of an HTTP response message.
*
* When there is no response body, the end of the response message is when the
* headers end. This is indicated by another "\r\n" after the final header line.
*
* When there is response body, the end of the response message is when the
* full "Content-Length" value is parsed following the end of the headers. If
* there is no Content-Length header, then http_parser_execute() expects a
* zero length-ed parsing data to indicate the end of the response.
*
* For a "Transfer-Encoding: chunked" type of response message, the complete
* response message is signaled by a terminating chunk header with length zero.
*
* See https://github.com/nodejs/http-parser for more information.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
*
* @return Zero to continue parsing. All other return values will stop parsing
* and http_parser_execute() will return with status HPE_CB_message_complete.
*/
static int httpParserOnMessageCompleteCallback( http_parser * pHttpParser );
/**
* @brief When a complete header is found the HTTP response header count
* increases and the application is notified.
*
* This function is invoked only in callbacks that could follow
* #httpParserOnHeaderValueCallback. These callbacks are
* #httpParserOnHeaderFieldCallback and #httpParserOnHeadersCompleteCallback.
* A header field and value is not is not known to be complete until
* #httpParserOnHeaderValueCallback is not called in succession.
*
* @param[in] pParsingContext Parsing state containing information to notify
* the application of a complete header.
*/
static void processCompleteHeader( HTTPParsingContext_t * pParsingContext );
/**
* @brief When parsing is complete an error could be indicated in
* pHttpParser->http_errno. This function translates that error into a library
* specific error code.
*
* @param[in] pHttpParser Third-party HTTP parsing context.
*
* @return One of the following:
* - #HTTPSuccess
* - #HTTPSecurityAlertResponseHeadersSizeLimitExceeded
* - #HTTPSecurityAlertExtraneousResponseData
* - #HTTPSecurityAlertInvalidChunkHeader
* - #HTTPSecurityAlertInvalidProtocolVersion
* - #HTTPSecurityAlertInvalidStatusCode
* - #HTTPSecurityAlertInvalidCharacter
* - #HTTPSecurityAlertInvalidContentLength
* - #HTTPParserInternalError
*/
static HTTPStatus_t processHttpParserError( const http_parser * pHttpParser );
/**
* @brief Compares at most the first n bytes of str1 and str2 without case sensitivity
* and n must be less than the actual size of either string.
*
* @param[in] str1 First string to be compared.
* @param[in] str2 Second string to be compared.
* @param[in] n The maximum number of characters to be compared.
*
* @return One of the following:
* 0 if str1 is equal to str2
* 1 if str1 is not equal to str2.
*/
static int8_t caseInsensitiveStringCmp( const char * str1,
const char * str2,
size_t n );
/*-----------------------------------------------------------*/
static uint32_t getZeroTimestampMs( void )
{
return 0U;
}