diff --git a/docs/doxygen/include/size_table.md b/docs/doxygen/include/size_table.md
index fed45453..2170e484 100644
--- a/docs/doxygen/include/size_table.md
+++ b/docs/doxygen/include/size_table.md
@@ -10,7 +10,7 @@
core_http_client.c |
3.2K |
- 2.5K |
+ 2.6K |
api.c (llhttp) |
@@ -30,6 +30,6 @@
Total estimates |
24.0K |
- 20.7K |
+ 20.8K |
diff --git a/source/core_http_client.c b/source/core_http_client.c
index f5693eac..995143ff 100644
--- a/source/core_http_client.c
+++ b/source/core_http_client.c
@@ -43,43 +43,18 @@
*/
static uint32_t getZeroTimestampMs( void );
-/**
- * @brief Send HTTP bytes over the transport send interface.
- *
- * @param[in] pTransport Transport interface.
- * @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
- * @param[in] pData HTTP request data to send.
- * @param[in] dataLen HTTP request data length.
- *
- * @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 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 );
+HTTPStatus_t HTTPClient_SendHttpData( const TransportInterface_t * pTransport,
+ HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
+ const uint8_t * pData,
+ size_t dataLen );
+
+
+HTTPStatus_t HTTPClient_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
@@ -187,20 +162,10 @@ 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 );
+
+HTTPStatus_t HTTPClient_ReceiveAndParseHttpResponse( const TransportInterface_t * pTransport,
+ HTTPResponse_t * pResponse,
+ const HTTPRequestHeaders_t * pRequestHeaders );
/**
* @brief Send the HTTP request over the network.
@@ -212,7 +177,7 @@ static HTTPStatus_t receiveAndParseHttpResponse( const TransportInterface_t * pT
* @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
+ * @return Returns #HTTPSuccess if successful. Please see #HTTPClient_SendHttpHeaders and
* #sendHttpBody for other statuses returned.
*/
static HTTPStatus_t sendHttpRequest( const TransportInterface_t * pTransport,
@@ -833,6 +798,9 @@ static int httpParserOnHeadersCompleteCallback( llhttp_t * pHttpParser )
assert( pResponse != NULL );
assert( pParsingContext->pBufferCur != NULL );
+ /* Flag indicating that the headers have been completely signed - useful for libraries built on top of corehttp. */
+ pResponse->areHeadersComplete = 1;
+
/* The current location to parse was updated in previous callbacks and MUST
* always be within the response buffer. */
assert( pParsingContext->pBufferCur >= ( const char * ) ( pResponse->pBuffer ) );
@@ -1796,10 +1764,10 @@ HTTPStatus_t HTTPClient_AddRangeHeader( HTTPRequestHeaders_t * pRequestHeaders,
/*-----------------------------------------------------------*/
-static HTTPStatus_t sendHttpData( const TransportInterface_t * pTransport,
- HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
- const uint8_t * pData,
- size_t dataLen )
+HTTPStatus_t HTTPClient_SendHttpData( const TransportInterface_t * pTransport,
+ HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
+ const uint8_t * pData,
+ size_t dataLen )
{
HTTPStatus_t returnStatus = HTTPSuccess;
const uint8_t * pIndex = pData;
@@ -1908,11 +1876,11 @@ static HTTPStatus_t addContentLengthHeader( HTTPRequestHeaders_t * pRequestHeade
/*-----------------------------------------------------------*/
-static HTTPStatus_t sendHttpHeaders( const TransportInterface_t * pTransport,
- HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
- HTTPRequestHeaders_t * pRequestHeaders,
- size_t reqBodyLen,
- uint32_t sendFlags )
+HTTPStatus_t HTTPClient_SendHttpHeaders( const TransportInterface_t * pTransport,
+ HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
+ HTTPRequestHeaders_t * pRequestHeaders,
+ size_t reqBodyLen,
+ uint32_t sendFlags )
{
HTTPStatus_t returnStatus = HTTPSuccess;
uint8_t shouldSendContentLength = 0U;
@@ -1935,10 +1903,10 @@ static HTTPStatus_t sendHttpHeaders( const TransportInterface_t * pTransport,
{
LogDebug( ( "Sending HTTP request headers: HeaderBytes=%lu",
( unsigned long ) ( pRequestHeaders->headersLen ) ) );
- returnStatus = sendHttpData( pTransport,
- getTimestampMs,
- pRequestHeaders->pBuffer,
- pRequestHeaders->headersLen );
+ returnStatus = HTTPClient_SendHttpData( pTransport,
+ getTimestampMs,
+ pRequestHeaders->pBuffer,
+ pRequestHeaders->headersLen );
}
return returnStatus;
@@ -1960,7 +1928,7 @@ static HTTPStatus_t sendHttpBody( const TransportInterface_t * pTransport,
/* Send the request body. */
LogDebug( ( "Sending the HTTP request body: BodyBytes=%lu",
( unsigned long ) reqBodyBufLen ) );
- returnStatus = sendHttpData( pTransport, getTimestampMs, pRequestBodyBuf, reqBodyBufLen );
+ returnStatus = HTTPClient_SendHttpData( pTransport, getTimestampMs, pRequestBodyBuf, reqBodyBufLen );
return returnStatus;
}
@@ -2014,9 +1982,9 @@ static HTTPStatus_t getFinalResponseStatus( HTTPParsingState_t parsingState,
/*-----------------------------------------------------------*/
-static HTTPStatus_t receiveAndParseHttpResponse( const TransportInterface_t * pTransport,
- HTTPResponse_t * pResponse,
- const HTTPRequestHeaders_t * pRequestHeaders )
+HTTPStatus_t HTTPClient_ReceiveAndParseHttpResponse( const TransportInterface_t * pTransport,
+ HTTPResponse_t * pResponse,
+ const HTTPRequestHeaders_t * pRequestHeaders )
{
HTTPStatus_t returnStatus = HTTPSuccess;
size_t totalReceived = 0U;
@@ -2149,11 +2117,11 @@ static HTTPStatus_t sendHttpRequest( const TransportInterface_t * pTransport,
assert( getTimestampMs != NULL );
/* Send the headers, which are at one location in memory. */
- returnStatus = sendHttpHeaders( pTransport,
- getTimestampMs,
- pRequestHeaders,
- reqBodyBufLen,
- sendFlags );
+ returnStatus = HTTPClient_SendHttpHeaders( pTransport,
+ getTimestampMs,
+ pRequestHeaders,
+ reqBodyBufLen,
+ sendFlags );
/* Send the body, which is at another location in memory. */
if( returnStatus == HTTPSuccess )
@@ -2269,9 +2237,9 @@ HTTPStatus_t HTTPClient_Send( const TransportInterface_t * pTransport,
if( returnStatus == HTTPSuccess )
{
- returnStatus = receiveAndParseHttpResponse( pTransport,
- pResponse,
- pRequestHeaders );
+ returnStatus = HTTPClient_ReceiveAndParseHttpResponse( pTransport,
+ pResponse,
+ pRequestHeaders );
}
return returnStatus;
diff --git a/source/include/core_http_client.h b/source/include/core_http_client.h
index 96f2d1bd..8dc2a098 100644
--- a/source/include/core_http_client.h
+++ b/source/include/core_http_client.h
@@ -528,6 +528,13 @@ typedef struct HTTPResponse
*/
size_t headerCount;
+ /**
+ * @brief Indicates whether the HTTP response headers have been fully received.
+ *
+ * This variable is set to 1 after all headers have been received and processed by #HTTPClient_Send.
+ */
+ uint8_t areHeadersComplete;
+
/**
* @brief Flags of useful headers found in the response.
*
@@ -730,6 +737,69 @@ HTTPStatus_t HTTPClient_AddRangeHeader( HTTPRequestHeaders_t * pRequestHeaders,
int32_t rangeEnd );
/* @[declare_httpclient_addrangeheader] */
+/**
+ * @brief Send the request headers in @p pRequestHeaders over the transport.
+ *
+ * If #HTTP_SEND_DISABLE_CONTENT_LENGTH_FLAG is not set in parameter @p sendFlags,
+ * then the Content-Length to be sent to the server is automatically written to
+ * @p pRequestHeaders. The Content-Length will not be written when there is
+ * no request body. If there is not enough room in the buffer to write the
+ * Content-Length then #HTTPInsufficientMemory is returned. Please see
+ * #HTTP_MAX_CONTENT_LENGTH_HEADER_LENGTH for the maximum Content-Length header
+ * field and value that could be written to the buffer.
+ *
+ * The application should close the connection with the server if any of the
+ * following errors are returned:
+ * - #HTTPSecurityAlertExtraneousResponseData
+ * - #HTTPSecurityAlertInvalidChunkHeader
+ * - #HTTPSecurityAlertInvalidProtocolVersion
+ * - #HTTPSecurityAlertInvalidStatusCode
+ * - #HTTPSecurityAlertInvalidCharacter
+ * - #HTTPSecurityAlertInvalidContentLength
+ *
+ *
+ * @param[in] pTransport Transport interface, see #TransportInterface_t for
+ * more information.
+ * @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
+ * @param[in] pRequestHeaders Request configuration containing the buffer of headers to
+ * send.
+ * @param[in] reqBodyLen The length of the request entity in bytes.
+ * @param[in] sendFlags Flags which modify the behavior of this function. Please see @ref
+ * http_send_flags for more information.
+ *
+ * @return #HTTPSuccess if successful. If there was a network error or less
+ * bytes than what were specified were sent, then #HTTPNetworkError is
+ * returned.
+ *
+ */
+/* @[declare_httpclient_sendhttpheaders] */
+HTTPStatus_t HTTPClient_SendHttpHeaders( const TransportInterface_t * pTransport,
+ HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
+ HTTPRequestHeaders_t * pRequestHeaders,
+ size_t reqBodyLen,
+ uint32_t sendFlags );
+/* @[declare_httpclient_sendhttpheaders] */
+
+/**
+ * @brief Send the request body in @p pRequestBodyBuf over the transport.
+ *
+ * @param[in] pTransport Transport interface, see #TransportInterface_t for
+ * more information.
+ * @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
+ * @param[in] pData HTTP request data to send.
+ * @param[in] dataLen HTTP request data length.
+ *
+ * @return #HTTPSuccess if successful. If there was a network error or less
+ * bytes than what were specified were sent, then #HTTPNetworkError is
+ * returned.
+ */
+/* @[declare_httpclient_sendhttpdata] */
+HTTPStatus_t HTTPClient_SendHttpData( const TransportInterface_t * pTransport,
+ HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
+ const uint8_t * pData,
+ size_t dataLen );
+/* @[declare_httpclient_sendhttpdata] */
+
/**
* @brief Send the request headers in #HTTPRequestHeaders_t.pBuffer and request
* body in @p pRequestBodyBuf over the transport. The response is received in
@@ -832,6 +902,27 @@ HTTPStatus_t HTTPClient_Send( const TransportInterface_t * pTransport,
uint32_t sendFlags );
/* @[declare_httpclient_send] */
+/**
+ * @brief Receive the HTTP response from the network and parse it.
+ *
+ * @param[in] pTransport Transport interface, see #TransportInterface_t for more
+ * information.
+ * @param[in] pResponse The response message and some notable response parameters will be
+ * returned here on success.
+ * @param[in] pRequestHeaders Request configuration containing the buffer of headers to
+ * send.
+ *
+ * @return Returns #HTTPSuccess if successful. #HTTPNetworkError for a transport
+ * receive error. Please see #parseHttpResponse and #getFinalResponseStatus for
+ * other statuses returned.
+ *
+ */
+/* @[declare_httpclient_receiveandparsehttpresponse] */
+HTTPStatus_t HTTPClient_ReceiveAndParseHttpResponse( const TransportInterface_t * pTransport,
+ HTTPResponse_t * pResponse,
+ const HTTPRequestHeaders_t * pRequestHeaders );
+/* @[declare_httpclient_receiveandparsehttpresponse] */
+
/**
* @brief Read a header from a buffer containing a complete HTTP response.
* This will return the location of the response header value in the
diff --git a/test/cbmc/proofs/HTTPClient_Send/Makefile b/test/cbmc/proofs/HTTPClient_Send/Makefile
index 931729ad..064330a3 100644
--- a/test/cbmc/proofs/HTTPClient_Send/Makefile
+++ b/test/cbmc/proofs/HTTPClient_Send/Makefile
@@ -57,8 +57,8 @@ REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpHeaderStrncp
# than the total possible iterations in the int32_t to ASCII converation.
UNWINDSET += __CPROVER_file_local_core_http_client_c_convertInt32ToAscii.0:11
UNWINDSET += __CPROVER_file_local_core_http_client_c_convertInt32ToAscii.1:11
-UNWINDSET += __CPROVER_file_local_core_http_client_c_receiveAndParseHttpResponse.0:10
-UNWINDSET += __CPROVER_file_local_core_http_client_c_sendHttpData.0:10
+UNWINDSET += HTTPClient_ReceiveAndParseHttpResponse.0:10
+UNWINDSET += HTTPClient_SendHttpData.0:10
# strncmp is used to find if there exists "\r\n\r\n" at the end of the header
# buffer. Therefore, we need to unwind strncmp to the length of "\r\n\r\n" + 1.