Skip to content

Commit 668db4b

Browse files
authored
Expose Internal Functions for Enhanced Usability (FreeRTOS#167)
This exposes the internal functions sendHttpHeaders, sendHttpData, and receiveAndParseHttpResponse. Exposing these functions aims to provide developers with more control over the HTTP communication process, enabling the support for chunked body reads and writes, streaming, and other advanced HTTP functionalities which are essential for building more sophisticated applications atop coreHTTP.
1 parent 15213f4 commit 668db4b

File tree

4 files changed

+139
-80
lines changed

4 files changed

+139
-80
lines changed

docs/doxygen/include/size_table.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<tr>
1111
<td>core_http_client.c</td>
1212
<td><center>3.2K</center></td>
13-
<td><center>2.5K</center></td>
13+
<td><center>2.6K</center></td>
1414
</tr>
1515
<tr>
1616
<td>api.c (llhttp)</td>
@@ -30,6 +30,6 @@
3030
<tr>
3131
<td><b>Total estimates</b></td>
3232
<td><b><center>24.0K</center></b></td>
33-
<td><b><center>20.7K</center></b></td>
33+
<td><b><center>20.8K</center></b></td>
3434
</tr>
3535
</table>

source/core_http_client.c

+44-76
Original file line numberDiff line numberDiff line change
@@ -43,43 +43,18 @@
4343
*/
4444
static uint32_t getZeroTimestampMs( void );
4545

46-
/**
47-
* @brief Send HTTP bytes over the transport send interface.
48-
*
49-
* @param[in] pTransport Transport interface.
50-
* @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
51-
* @param[in] pData HTTP request data to send.
52-
* @param[in] dataLen HTTP request data length.
53-
*
54-
* @return #HTTPSuccess if successful. If there was a network error or less
55-
* bytes than what were specified were sent, then #HTTPNetworkError is
56-
* returned.
57-
*/
58-
static HTTPStatus_t sendHttpData( const TransportInterface_t * pTransport,
59-
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
60-
const uint8_t * pData,
61-
size_t dataLen );
6246

63-
/**
64-
* @brief Send the HTTP headers over the transport send interface.
65-
*
66-
* @param[in] pTransport Transport interface.
67-
* @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
68-
* @param[in] pRequestHeaders Request headers to send, it includes the buffer
69-
* and length.
70-
* @param[in] reqBodyLen The length of the request body to be sent. This is
71-
* used to generated a Content-Length header.
72-
* @param[in] sendFlags Application provided flags to #HTTPClient_Send.
73-
*
74-
* @return #HTTPSuccess if successful. If there was a network error or less
75-
* bytes than what were specified were sent, then #HTTPNetworkError is
76-
* returned.
77-
*/
78-
static HTTPStatus_t sendHttpHeaders( const TransportInterface_t * pTransport,
79-
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
80-
HTTPRequestHeaders_t * pRequestHeaders,
81-
size_t reqBodyLen,
82-
uint32_t sendFlags );
47+
HTTPStatus_t HTTPClient_SendHttpData( const TransportInterface_t * pTransport,
48+
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
49+
const uint8_t * pData,
50+
size_t dataLen );
51+
52+
53+
HTTPStatus_t HTTPClient_SendHttpHeaders( const TransportInterface_t * pTransport,
54+
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
55+
HTTPRequestHeaders_t * pRequestHeaders,
56+
size_t reqBodyLen,
57+
uint32_t sendFlags );
8358

8459
/**
8560
* @brief Adds the Content-Length header field and value to the
@@ -187,20 +162,10 @@ static HTTPStatus_t getFinalResponseStatus( HTTPParsingState_t parsingState,
187162
size_t totalReceived,
188163
size_t responseBufferLen );
189164

190-
/**
191-
* @brief Receive the HTTP response from the network and parse it.
192-
*
193-
* @param[in] pTransport Transport interface.
194-
* @param[in] pResponse Response message to receive data from the network.
195-
* @param[in] pRequestHeaders Request headers for the corresponding HTTP request.
196-
*
197-
* @return Returns #HTTPSuccess if successful. #HTTPNetworkError for a transport
198-
* receive error. Please see #parseHttpResponse and #getFinalResponseStatus for
199-
* other statuses returned.
200-
*/
201-
static HTTPStatus_t receiveAndParseHttpResponse( const TransportInterface_t * pTransport,
202-
HTTPResponse_t * pResponse,
203-
const HTTPRequestHeaders_t * pRequestHeaders );
165+
166+
HTTPStatus_t HTTPClient_ReceiveAndParseHttpResponse( const TransportInterface_t * pTransport,
167+
HTTPResponse_t * pResponse,
168+
const HTTPRequestHeaders_t * pRequestHeaders );
204169

205170
/**
206171
* @brief Send the HTTP request over the network.
@@ -212,7 +177,7 @@ static HTTPStatus_t receiveAndParseHttpResponse( const TransportInterface_t * pT
212177
* @param[in] reqBodyBufLen Length of the request body buffer.
213178
* @param[in] sendFlags Application provided flags to #HTTPClient_Send.
214179
*
215-
* @return Returns #HTTPSuccess if successful. Please see #sendHttpHeaders and
180+
* @return Returns #HTTPSuccess if successful. Please see #HTTPClient_SendHttpHeaders and
216181
* #sendHttpBody for other statuses returned.
217182
*/
218183
static HTTPStatus_t sendHttpRequest( const TransportInterface_t * pTransport,
@@ -833,6 +798,9 @@ static int httpParserOnHeadersCompleteCallback( llhttp_t * pHttpParser )
833798
assert( pResponse != NULL );
834799
assert( pParsingContext->pBufferCur != NULL );
835800

801+
/* Flag indicating that the headers have been completely signed - useful for libraries built on top of corehttp. */
802+
pResponse->areHeadersComplete = 1;
803+
836804
/* The current location to parse was updated in previous callbacks and MUST
837805
* always be within the response buffer. */
838806
assert( pParsingContext->pBufferCur >= ( const char * ) ( pResponse->pBuffer ) );
@@ -1796,10 +1764,10 @@ HTTPStatus_t HTTPClient_AddRangeHeader( HTTPRequestHeaders_t * pRequestHeaders,
17961764

17971765
/*-----------------------------------------------------------*/
17981766

1799-
static HTTPStatus_t sendHttpData( const TransportInterface_t * pTransport,
1800-
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
1801-
const uint8_t * pData,
1802-
size_t dataLen )
1767+
HTTPStatus_t HTTPClient_SendHttpData( const TransportInterface_t * pTransport,
1768+
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
1769+
const uint8_t * pData,
1770+
size_t dataLen )
18031771
{
18041772
HTTPStatus_t returnStatus = HTTPSuccess;
18051773
const uint8_t * pIndex = pData;
@@ -1908,11 +1876,11 @@ static HTTPStatus_t addContentLengthHeader( HTTPRequestHeaders_t * pRequestHeade
19081876

19091877
/*-----------------------------------------------------------*/
19101878

1911-
static HTTPStatus_t sendHttpHeaders( const TransportInterface_t * pTransport,
1912-
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
1913-
HTTPRequestHeaders_t * pRequestHeaders,
1914-
size_t reqBodyLen,
1915-
uint32_t sendFlags )
1879+
HTTPStatus_t HTTPClient_SendHttpHeaders( const TransportInterface_t * pTransport,
1880+
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
1881+
HTTPRequestHeaders_t * pRequestHeaders,
1882+
size_t reqBodyLen,
1883+
uint32_t sendFlags )
19161884
{
19171885
HTTPStatus_t returnStatus = HTTPSuccess;
19181886
uint8_t shouldSendContentLength = 0U;
@@ -1935,10 +1903,10 @@ static HTTPStatus_t sendHttpHeaders( const TransportInterface_t * pTransport,
19351903
{
19361904
LogDebug( ( "Sending HTTP request headers: HeaderBytes=%lu",
19371905
( unsigned long ) ( pRequestHeaders->headersLen ) ) );
1938-
returnStatus = sendHttpData( pTransport,
1939-
getTimestampMs,
1940-
pRequestHeaders->pBuffer,
1941-
pRequestHeaders->headersLen );
1906+
returnStatus = HTTPClient_SendHttpData( pTransport,
1907+
getTimestampMs,
1908+
pRequestHeaders->pBuffer,
1909+
pRequestHeaders->headersLen );
19421910
}
19431911

19441912
return returnStatus;
@@ -1960,7 +1928,7 @@ static HTTPStatus_t sendHttpBody( const TransportInterface_t * pTransport,
19601928
/* Send the request body. */
19611929
LogDebug( ( "Sending the HTTP request body: BodyBytes=%lu",
19621930
( unsigned long ) reqBodyBufLen ) );
1963-
returnStatus = sendHttpData( pTransport, getTimestampMs, pRequestBodyBuf, reqBodyBufLen );
1931+
returnStatus = HTTPClient_SendHttpData( pTransport, getTimestampMs, pRequestBodyBuf, reqBodyBufLen );
19641932

19651933
return returnStatus;
19661934
}
@@ -2014,9 +1982,9 @@ static HTTPStatus_t getFinalResponseStatus( HTTPParsingState_t parsingState,
20141982

20151983
/*-----------------------------------------------------------*/
20161984

2017-
static HTTPStatus_t receiveAndParseHttpResponse( const TransportInterface_t * pTransport,
2018-
HTTPResponse_t * pResponse,
2019-
const HTTPRequestHeaders_t * pRequestHeaders )
1985+
HTTPStatus_t HTTPClient_ReceiveAndParseHttpResponse( const TransportInterface_t * pTransport,
1986+
HTTPResponse_t * pResponse,
1987+
const HTTPRequestHeaders_t * pRequestHeaders )
20201988
{
20211989
HTTPStatus_t returnStatus = HTTPSuccess;
20221990
size_t totalReceived = 0U;
@@ -2149,11 +2117,11 @@ static HTTPStatus_t sendHttpRequest( const TransportInterface_t * pTransport,
21492117
assert( getTimestampMs != NULL );
21502118

21512119
/* Send the headers, which are at one location in memory. */
2152-
returnStatus = sendHttpHeaders( pTransport,
2153-
getTimestampMs,
2154-
pRequestHeaders,
2155-
reqBodyBufLen,
2156-
sendFlags );
2120+
returnStatus = HTTPClient_SendHttpHeaders( pTransport,
2121+
getTimestampMs,
2122+
pRequestHeaders,
2123+
reqBodyBufLen,
2124+
sendFlags );
21572125

21582126
/* Send the body, which is at another location in memory. */
21592127
if( returnStatus == HTTPSuccess )
@@ -2269,9 +2237,9 @@ HTTPStatus_t HTTPClient_Send( const TransportInterface_t * pTransport,
22692237

22702238
if( returnStatus == HTTPSuccess )
22712239
{
2272-
returnStatus = receiveAndParseHttpResponse( pTransport,
2273-
pResponse,
2274-
pRequestHeaders );
2240+
returnStatus = HTTPClient_ReceiveAndParseHttpResponse( pTransport,
2241+
pResponse,
2242+
pRequestHeaders );
22752243
}
22762244

22772245
return returnStatus;

source/include/core_http_client.h

+91
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,13 @@ typedef struct HTTPResponse
528528
*/
529529
size_t headerCount;
530530

531+
/**
532+
* @brief Indicates whether the HTTP response headers have been fully received.
533+
*
534+
* This variable is set to 1 after all headers have been received and processed by #HTTPClient_Send.
535+
*/
536+
uint8_t areHeadersComplete;
537+
531538
/**
532539
* @brief Flags of useful headers found in the response.
533540
*
@@ -730,6 +737,69 @@ HTTPStatus_t HTTPClient_AddRangeHeader( HTTPRequestHeaders_t * pRequestHeaders,
730737
int32_t rangeEnd );
731738
/* @[declare_httpclient_addrangeheader] */
732739

740+
/**
741+
* @brief Send the request headers in @p pRequestHeaders over the transport.
742+
*
743+
* If #HTTP_SEND_DISABLE_CONTENT_LENGTH_FLAG is not set in parameter @p sendFlags,
744+
* then the Content-Length to be sent to the server is automatically written to
745+
* @p pRequestHeaders. The Content-Length will not be written when there is
746+
* no request body. If there is not enough room in the buffer to write the
747+
* Content-Length then #HTTPInsufficientMemory is returned. Please see
748+
* #HTTP_MAX_CONTENT_LENGTH_HEADER_LENGTH for the maximum Content-Length header
749+
* field and value that could be written to the buffer.
750+
*
751+
* The application should close the connection with the server if any of the
752+
* following errors are returned:
753+
* - #HTTPSecurityAlertExtraneousResponseData
754+
* - #HTTPSecurityAlertInvalidChunkHeader
755+
* - #HTTPSecurityAlertInvalidProtocolVersion
756+
* - #HTTPSecurityAlertInvalidStatusCode
757+
* - #HTTPSecurityAlertInvalidCharacter
758+
* - #HTTPSecurityAlertInvalidContentLength
759+
*
760+
*
761+
* @param[in] pTransport Transport interface, see #TransportInterface_t for
762+
* more information.
763+
* @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
764+
* @param[in] pRequestHeaders Request configuration containing the buffer of headers to
765+
* send.
766+
* @param[in] reqBodyLen The length of the request entity in bytes.
767+
* @param[in] sendFlags Flags which modify the behavior of this function. Please see @ref
768+
* http_send_flags for more information.
769+
*
770+
* @return #HTTPSuccess if successful. If there was a network error or less
771+
* bytes than what were specified were sent, then #HTTPNetworkError is
772+
* returned.
773+
*
774+
*/
775+
/* @[declare_httpclient_sendhttpheaders] */
776+
HTTPStatus_t HTTPClient_SendHttpHeaders( const TransportInterface_t * pTransport,
777+
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
778+
HTTPRequestHeaders_t * pRequestHeaders,
779+
size_t reqBodyLen,
780+
uint32_t sendFlags );
781+
/* @[declare_httpclient_sendhttpheaders] */
782+
783+
/**
784+
* @brief Send the request body in @p pRequestBodyBuf over the transport.
785+
*
786+
* @param[in] pTransport Transport interface, see #TransportInterface_t for
787+
* more information.
788+
* @param[in] getTimestampMs Function to retrieve a timestamp in milliseconds.
789+
* @param[in] pData HTTP request data to send.
790+
* @param[in] dataLen HTTP request data length.
791+
*
792+
* @return #HTTPSuccess if successful. If there was a network error or less
793+
* bytes than what were specified were sent, then #HTTPNetworkError is
794+
* returned.
795+
*/
796+
/* @[declare_httpclient_sendhttpdata] */
797+
HTTPStatus_t HTTPClient_SendHttpData( const TransportInterface_t * pTransport,
798+
HTTPClient_GetCurrentTimeFunc_t getTimestampMs,
799+
const uint8_t * pData,
800+
size_t dataLen );
801+
/* @[declare_httpclient_sendhttpdata] */
802+
733803
/**
734804
* @brief Send the request headers in #HTTPRequestHeaders_t.pBuffer and request
735805
* body in @p pRequestBodyBuf over the transport. The response is received in
@@ -832,6 +902,27 @@ HTTPStatus_t HTTPClient_Send( const TransportInterface_t * pTransport,
832902
uint32_t sendFlags );
833903
/* @[declare_httpclient_send] */
834904

905+
/**
906+
* @brief Receive the HTTP response from the network and parse it.
907+
*
908+
* @param[in] pTransport Transport interface, see #TransportInterface_t for more
909+
* information.
910+
* @param[in] pResponse The response message and some notable response parameters will be
911+
* returned here on success.
912+
* @param[in] pRequestHeaders Request configuration containing the buffer of headers to
913+
* send.
914+
*
915+
* @return Returns #HTTPSuccess if successful. #HTTPNetworkError for a transport
916+
* receive error. Please see #parseHttpResponse and #getFinalResponseStatus for
917+
* other statuses returned.
918+
*
919+
*/
920+
/* @[declare_httpclient_receiveandparsehttpresponse] */
921+
HTTPStatus_t HTTPClient_ReceiveAndParseHttpResponse( const TransportInterface_t * pTransport,
922+
HTTPResponse_t * pResponse,
923+
const HTTPRequestHeaders_t * pRequestHeaders );
924+
/* @[declare_httpclient_receiveandparsehttpresponse] */
925+
835926
/**
836927
* @brief Read a header from a buffer containing a complete HTTP response.
837928
* This will return the location of the response header value in the

test/cbmc/proofs/HTTPClient_Send/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpHeaderStrncp
5757
# than the total possible iterations in the int32_t to ASCII converation.
5858
UNWINDSET += __CPROVER_file_local_core_http_client_c_convertInt32ToAscii.0:11
5959
UNWINDSET += __CPROVER_file_local_core_http_client_c_convertInt32ToAscii.1:11
60-
UNWINDSET += __CPROVER_file_local_core_http_client_c_receiveAndParseHttpResponse.0:10
61-
UNWINDSET += __CPROVER_file_local_core_http_client_c_sendHttpData.0:10
60+
UNWINDSET += HTTPClient_ReceiveAndParseHttpResponse.0:10
61+
UNWINDSET += HTTPClient_SendHttpData.0:10
6262

6363
# strncmp is used to find if there exists "\r\n\r\n" at the end of the header
6464
# buffer. Therefore, we need to unwind strncmp to the length of "\r\n\r\n" + 1.

0 commit comments

Comments
 (0)