static HTTPStatus_t sendHttpData()

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;
}