diff --git a/.github/memory_statistics_config.json b/.github/memory_statistics_config.json
index b6ff1be2..8374f109 100644
--- a/.github/memory_statistics_config.json
+++ b/.github/memory_statistics_config.json
@@ -3,14 +3,22 @@
"src": [
"source/core_http_client.c",
{
- "file": "source/dependency/3rdparty/http_parser/http_parser.c",
- "tag": "http-parser"
+ "file": "source/dependency/3rdparty/llhttp/src/api.c",
+ "tag": "llhttp"
+ },
+ {
+ "file": "source/dependency/3rdparty/llhttp/src/http.c",
+ "tag": "llhttp"
+ },
+ {
+ "file": "source/dependency/3rdparty/llhttp/src/llhttp.c",
+ "tag": "llhttp"
}
],
"include": [
"source/include",
"source/interface",
- "source/dependency/3rdparty/http_parser"
+ "source/dependency/3rdparty/llhttp/include"
],
"compiler_flags": [
"HTTP_DO_NOT_USE_CUSTOM_CONFIG"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0bf97d5a..2c38010a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -4,7 +4,7 @@ on:
push:
branches: ["**"]
pull_request:
- branches: [main]
+ branches: ["**"]
workflow_dispatch:
jobs:
diff --git a/.gitmodules b/.gitmodules
index 0eae6012..b49c2727 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -10,6 +10,6 @@
path = test/cbmc/litani
url = https://github.com/awslabs/aws-build-accumulator
update = none
-[submodule "source/dependency/3rdparty/http_parser"]
- path = source/dependency/3rdparty/http_parser
- url = https://github.com/nodejs/http-parser.git
+[submodule "source/dependency/3rdparty/llhttp"]
+ path = source/dependency/3rdparty/llhttp
+ url = https://github.com/nodejs/llhttp.git
diff --git a/README.md b/README.md
index efd78bae..c47d5f12 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
This repository contains a C language HTTP client library designed for embedded
platforms. It has no dependencies on any additional libraries other than the
-standard C library, [http-parser](https://github.com/nodejs/http-parser), and
+standard C library, [llhttp](https://github.com/nodejs/llhttp), and
a customer-implemented transport interface. This library is distributed under
the [MIT Open Source License](LICENSE).
diff --git a/docs/doxygen/include/size_table.md b/docs/doxygen/include/size_table.md
index 41bc6338..fed45453 100644
--- a/docs/doxygen/include/size_table.md
+++ b/docs/doxygen/include/size_table.md
@@ -10,16 +10,26 @@
core_http_client.c |
3.2K |
+ 2.5K |
+
+
+ api.c (llhttp) |
2.6K |
+ 2.0K |
+
+
+ http.c (llhttp) |
+ 0.3K |
+ 0.3K |
- http_parser.c (http-parser) |
- 15.7K |
- 13.0K |
+ llhttp.c (llhttp) |
+ 17.9K |
+ 15.9K |
Total estimates |
- 18.9K |
- 15.6K |
+ 24.0K |
+ 20.7K |
diff --git a/docs/doxygen/pages.dox b/docs/doxygen/pages.dox
index 7c65ef21..4c225127 100644
--- a/docs/doxygen/pages.dox
+++ b/docs/doxygen/pages.dox
@@ -7,7 +7,7 @@ This HTTP Client library implements a subset of the HTTP/1.1 protocol. Features
of this library include:
- Fully synchronous API, to allow applications to completely manage their concurrency and multi-threading.
- Operations on user supplied buffers, so that applications have complete control of their memory allocation strategy.
-- Integration with [http-parser](https://github.com/nodejs/http-parser) to handle chunked encoding.
+- Integration with [llhttp](https://github.com/nodejs/llhttp) to handle chunked encoding.
Feature of HTTP/1.1 not supported in this library:
- Streaming uploads and downloads. Range requests for partial content responses are highly encouraged with this API.
@@ -110,7 +110,7 @@ If the request has a body it is passed as a parameter to @ref HTTPClient_Send.
As soon as the response is received from the network it is parsed. The final
parsed response is represented by the @ref HTTPResponse_t returned from
@ref HTTPClient_Send. Parsing the HTTP response is done using
-[http-parser](https://github.com/nodejs/http-parser). http-parser invokes
+[llhttp](https://github.com/nodejs/llhttp). llhttp invokes
callbacks for each section in the HTTP response it finds. Using these callbacks
the HTTP client library sets the members of @ref HTTPResponse_t to return from
@ref HTTPClient_Send. The overall flow of @ref HTTPClient_Send is
@@ -125,14 +125,14 @@ can be read from the headers found in @ref HTTPResponse_t.pHeaders. The function
@ref HTTPClient_ReadHeader reads the headers from an @ref HTTPResponse_t.
@ref HTTPClient_ReadHeader will re-parse the response in
@ref HTTPResponse_t.pBuffer, looking for the header field of interest.
-Re-parsing involves using http-parser to look at each character starting from
+Re-parsing involves using llhttp to look at each character starting from
the beginning of @ref HTTPResponse_t.pBuffer until the header field of interest
is found.
If the user application wants to avoid re-parsing @ref HTTPResponse_t.pBuffer,
then the user application may register a callback in
@ref HTTPResponse_t.pHeaderParsingCallback. When the HTTP response message is
-first received from the network, in @ref HTTPClient_Send, http-parser is invoked
+first received from the network, in @ref HTTPClient_Send, llhttp is invoked
to parse the response. This first parsing in @ref HTTPClient_Send will invoke
@ref HTTPResponse_t.pHeaderParsingCallback for each header that is found
in response. Please see the sequence diagram below for an illustration of when
diff --git a/httpFilePaths.cmake b/httpFilePaths.cmake
index 0ef3479a..38418f96 100644
--- a/httpFilePaths.cmake
+++ b/httpFilePaths.cmake
@@ -8,10 +8,12 @@
# HTTP library source files.
set( HTTP_SOURCES
${CMAKE_CURRENT_LIST_DIR}/source/core_http_client.c
- ${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/http_parser/http_parser.c )
+ ${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/llhttp/src/api.c
+ ${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/llhttp/src/llhttp.c
+ ${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/llhttp/src/http.c )
# HTTP library public include directories.
set( HTTP_INCLUDE_PUBLIC_DIRS
${CMAKE_CURRENT_LIST_DIR}/source/include
${CMAKE_CURRENT_LIST_DIR}/source/interface
- ${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/http_parser )
+ ${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/llhttp/include )
diff --git a/lexicon.txt b/lexicon.txt
index e2add5f5..89b9bbfe 100644
--- a/lexicon.txt
+++ b/lexicon.txt
@@ -25,6 +25,7 @@ chk
chunked
colspan
com
+cond
config
configpagestyle
const
@@ -42,6 +43,7 @@ defgroup
doesn
doxygen
endcode
+endcond
endif
enums
eof
@@ -122,6 +124,9 @@ lastheadervaluelen
latin
len
linux
+llhttp
+llhttpparser
+llhttpsettings
logdebug
logerror
loginfo
@@ -201,7 +206,7 @@ prequestbodybuf
prequestheaders
prequestinfo
presponse
-processhttpparsererror
+processllhttperror
ptransport
ptransportinterface
pvalue
diff --git a/manifest.yml b/manifest.yml
index 6926c99f..b4720c7a 100644
--- a/manifest.yml
+++ b/manifest.yml
@@ -3,9 +3,9 @@ version: "v2.1.0"
description: |
"Client implementation of the HTTP/1.1 specification for embedded devices.\n"
dependencies:
- - name : "http-parser"
- version: "v2.9.4"
+ - name : "llhttp"
+ version: "release/v6.0.5"
repository:
type: "git"
- url: "https://github.com/nodejs/http-parser"
+ url: "https://github.com/nodejs/llhttp"
license: "MIT"
diff --git a/source/core_http_client.c b/source/core_http_client.c
index 2dd3a228..492bd519 100644
--- a/source/core_http_client.c
+++ b/source/core_http_client.c
@@ -289,10 +289,10 @@ static HTTPStatus_t findHeaderInResponse( const uint8_t * pBuffer,
* buffer.
* @param[in] fieldLen The length of the header field.
*
- * @return Returns #HTTP_PARSER_CONTINUE_PARSING to indicate continuation with
+ * @return Returns #LLHTTP_CONTINUE_PARSING to indicate continuation with
* parsing.
*/
-static int findHeaderFieldParserCallback( http_parser * pHttpParser,
+static int findHeaderFieldParserCallback( llhttp_t * pHttpParser,
const char * pFieldLoc,
size_t fieldLen );
@@ -307,10 +307,10 @@ static int findHeaderFieldParserCallback( http_parser * pHttpParser,
* 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.
+ * @return Returns #LLHTTP_STOP_PARSING, if the header field/value pair are
+ * found, otherwise #LLHTTP_CONTINUE_PARSING is returned.
*/
-static int findHeaderValueParserCallback( http_parser * pHttpParser,
+static int findHeaderValueParserCallback( llhttp_t * pHttpParser,
const char * pValueLoc,
size_t valueLen );
@@ -324,10 +324,10 @@ static int findHeaderValueParserCallback( http_parser * pHttpParser,
*
* @param[in] pHttpParser Parsing object containing state and callback context.
*
- * @return Returns #HTTP_PARSER_STOP_PARSING for the parser to halt further
+ * @return Returns #LLHTTP_STOP_PARSING_NO_HEADER for the parser to halt further
* execution, as all headers have been parsed in the response.
*/
-static int findHeaderOnHeaderCompleteCallback( http_parser * pHttpParser );
+static int findHeaderOnHeaderCompleteCallback( llhttp_t * pHttpParser );
/**
@@ -354,14 +354,14 @@ static void initializeParsingContextForFirstResponse( HTTPParsingContext_t * pPa
* @return One of the following:
* - #HTTPSuccess
* - #HTTPInvalidParameter
- * - Please see #processHttpParserError for parsing errors returned.
+ * - Please see #processLlhttpError 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
+ * @brief Callback invoked during llhttp_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
@@ -369,12 +369,12 @@ static HTTPStatus_t parseHttpResponse( HTTPParsingContext_t * pParsingContext,
*
* @param[in] pHttpParser Parsing object containing state and callback context.
*
- * @return #HTTP_PARSER_CONTINUE_PARSING to continue parsing.
+ * @return #LLHTTP_CONTINUE_PARSING to continue parsing.
*/
-static int httpParserOnMessageBeginCallback( http_parser * pHttpParser );
+static int httpParserOnMessageBeginCallback( llhttp_t * pHttpParser );
/**
- * @brief Callback invoked during http_parser_execute() when the HTTP response
+ * @brief Callback invoked during llhttp_execute() when the HTTP response
* status-code and its associated reason-phrase are found.
*
* @param[in] pHttpParser Parsing object containing state and callback context.
@@ -382,14 +382,14 @@ static int httpParserOnMessageBeginCallback( http_parser * pHttpParser );
* response message buffer.
* @param[in] length Length of the HTTP response status code string.
*
- * @return #HTTP_PARSER_CONTINUE_PARSING to continue parsing.
+ * @return #LLHTTP_CONTINUE_PARSING to continue parsing.
*/
-static int httpParserOnStatusCallback( http_parser * pHttpParser,
+static int httpParserOnStatusCallback( llhttp_t * pHttpParser,
const char * pLoc,
size_t length );
/**
- * @brief Callback invoked during http_parser_execute() when an HTTP response
+ * @brief Callback invoked during llhttp_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
@@ -400,14 +400,14 @@ static int httpParserOnStatusCallback( http_parser * pHttpParser,
* message buffer.
* @param[in] length Length of the header field.
*
- * @return #HTTP_PARSER_CONTINUE_PARSING to continue parsing.
+ * @return #LLHTTP_CONTINUE_PARSING to continue parsing.
*/
-static int httpParserOnHeaderFieldCallback( http_parser * pHttpParser,
+static int httpParserOnHeaderFieldCallback( llhttp_t * pHttpParser,
const char * pLoc,
size_t length );
/**
- * @brief Callback invoked during http_parser_execute() when an HTTP response
+ * @brief Callback invoked during llhttp_execute() when an HTTP response
* header value is found.
*
* This header value corresponds to the header field that was found in the
@@ -420,14 +420,14 @@ static int httpParserOnHeaderFieldCallback( http_parser * pHttpParser,
* @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.
+ * @return #LLHTTP_CONTINUE_PARSING to continue parsing.
*/
-static int httpParserOnHeaderValueCallback( http_parser * pHttpParser,
+static int httpParserOnHeaderValueCallback( llhttp_t * pHttpParser,
const char * pLoc,
size_t length );
/**
- * @brief Callback invoked during http_parser_execute() when the end of the
+ * @brief Callback invoked during llhttp_execute() when the end of the
* headers are found.
*
* The end of the headers is signaled in a HTTP response message by another
@@ -435,13 +435,13 @@ static int httpParserOnHeaderValueCallback( http_parser * pHttpParser,
*
* @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.
+ * @return #LLHTTP_CONTINUE_PARSING to continue parsing.
+ * #LLHTTP_STOP_PARSING_NO_BODY is returned if the response is for a HEAD request.
*/
-static int httpParserOnHeadersCompleteCallback( http_parser * pHttpParser );
+static int httpParserOnHeadersCompleteCallback( llhttp_t * pHttpParser );
/**
- * @brief Callback invoked during http_parser_execute() when the HTTP response
+ * @brief Callback invoked during llhttp_execute() when the HTTP response
* body is found.
*
* If only part of the response body was found, then parsing of the next part of
@@ -480,14 +480,14 @@ static int httpParserOnHeadersCompleteCallback( http_parser * pHttpParser );
* @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.
+ * and llhttp_execute() will return with the same value.
*/
-static int httpParserOnBodyCallback( http_parser * pHttpParser,
+static int httpParserOnBodyCallback( llhttp_t * pHttpParser,
const char * pLoc,
size_t length );
/**
- * @brief Callback invoked during http_parser_execute() to indicate the the
+ * @brief Callback invoked during llhttp_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
@@ -495,20 +495,20 @@ static int httpParserOnBodyCallback( http_parser * pHttpParser,
*
* 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
+ * there is no Content-Length header, then llhttp_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.
+ * See https://github.com/nodejs/llhttp 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.
+ * and llhttp_execute() will return with the same value.
*/
-static int httpParserOnMessageCompleteCallback( http_parser * pHttpParser );
+static int httpParserOnMessageCompleteCallback( llhttp_t * pHttpParser );
/**
* @brief When a complete header is found the HTTP response header count
@@ -527,14 +527,13 @@ 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
+ * pHttpParser->error. 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
@@ -543,7 +542,7 @@ static void processCompleteHeader( HTTPParsingContext_t * pParsingContext );
* - #HTTPSecurityAlertInvalidContentLength
* - #HTTPParserInternalError
*/
-static HTTPStatus_t processHttpParserError( const http_parser * pHttpParser );
+static HTTPStatus_t processLlhttpError( const llhttp_t * pHttpParser );
/**
* @brief Compares at most the first n bytes of str1 and str2 without case sensitivity
@@ -638,7 +637,7 @@ static void processCompleteHeader( HTTPParsingContext_t * pParsingContext )
/*-----------------------------------------------------------*/
-static int httpParserOnMessageBeginCallback( http_parser * pHttpParser )
+static int httpParserOnMessageBeginCallback( llhttp_t * pHttpParser )
{
HTTPParsingContext_t * pParsingContext = NULL;
@@ -652,12 +651,12 @@ static int httpParserOnMessageBeginCallback( http_parser * pHttpParser )
LogDebug( ( "Response parsing: Found the start of the response message." ) );
- return HTTP_PARSER_CONTINUE_PARSING;
+ return LLHTTP_CONTINUE_PARSING;
}
/*-----------------------------------------------------------*/
-static int httpParserOnStatusCallback( http_parser * pHttpParser,
+static int httpParserOnStatusCallback( llhttp_t * pHttpParser,
const char * pLoc,
size_t length )
{
@@ -683,7 +682,7 @@ static int httpParserOnStatusCallback( http_parser * pHttpParser,
pParsingContext->pLastHeaderValue = NULL;
pParsingContext->lastHeaderValueLen = 0U;
- /* httpParserOnStatusCallback() is reached because http_parser_execute() has
+ /* httpParserOnStatusCallback() is reached because llhttp_execute() has
* successfully read the HTTP response status code. */
pResponse->statusCode = ( uint16_t ) ( pHttpParser->status_code );
@@ -693,12 +692,12 @@ static int httpParserOnStatusCallback( http_parser * pHttpParser,
( int ) length,
pLoc ) );
- return HTTP_PARSER_CONTINUE_PARSING;
+ return LLHTTP_CONTINUE_PARSING;
}
/*-----------------------------------------------------------*/
-static int httpParserOnHeaderFieldCallback( http_parser * pHttpParser,
+static int httpParserOnHeaderFieldCallback( llhttp_t * pHttpParser,
const char * pLoc,
size_t length )
{
@@ -731,7 +730,7 @@ static int httpParserOnHeaderFieldCallback( http_parser * pHttpParser,
processCompleteHeader( pParsingContext );
/* If httpParserOnHeaderFieldCallback() is invoked in succession, then the
- * last time http_parser_execute() was called only part of the header field
+ * last time llhttp_execute() was called only part of the header field
* was parsed. The indication of successive invocations is a non-NULL
* pParsingContext->pLastHeaderField. */
if( pParsingContext->pLastHeaderField == NULL )
@@ -750,12 +749,12 @@ static int httpParserOnHeaderFieldCallback( http_parser * pHttpParser,
( int ) length,
pLoc ) );
- return HTTP_PARSER_CONTINUE_PARSING;
+ return LLHTTP_CONTINUE_PARSING;
}
/*-----------------------------------------------------------*/
-static int httpParserOnHeaderValueCallback( http_parser * pHttpParser,
+static int httpParserOnHeaderValueCallback( llhttp_t * pHttpParser,
const char * pLoc,
size_t length )
{
@@ -771,7 +770,7 @@ static int httpParserOnHeaderValueCallback( http_parser * pHttpParser,
pParsingContext->pBufferCur = pLoc + length;
/* If httpParserOnHeaderValueCallback() is invoked in succession, then the
- * last time http_parser_execute() was called only part of the header field
+ * last time llhttp_execute() was called only part of the header field
* was parsed. The indication of successive invocations is a non-NULL
* pParsingContext->pLastHeaderField. */
if( pParsingContext->pLastHeaderValue == NULL )
@@ -786,8 +785,7 @@ static int httpParserOnHeaderValueCallback( http_parser * pHttpParser,
/* Given that httpParserOnHeaderFieldCallback() is ALWAYS invoked before
* httpParserOnHeaderValueCallback() is invoked, then the last header field
- * should never be NULL. This would indicate a bug in the http-parser
- * library. */
+ * should never be NULL. This would indicate a bug in the llhttp library. */
assert( pParsingContext->pLastHeaderField != NULL );
LogDebug( ( "Response parsing: Found a header value: "
@@ -795,14 +793,14 @@ static int httpParserOnHeaderValueCallback( http_parser * pHttpParser,
( int ) length,
pLoc ) );
- return HTTP_PARSER_CONTINUE_PARSING;
+ return LLHTTP_CONTINUE_PARSING;
}
/*-----------------------------------------------------------*/
-static int httpParserOnHeadersCompleteCallback( http_parser * pHttpParser )
+static int httpParserOnHeadersCompleteCallback( llhttp_t * pHttpParser )
{
- int shouldContinueParse = HTTP_PARSER_CONTINUE_PARSING;
+ int shouldContinueParse = LLHTTP_CONTINUE_PARSING;
HTTPParsingContext_t * pParsingContext = NULL;
HTTPResponse_t * pResponse = NULL;
@@ -866,14 +864,14 @@ static int httpParserOnHeadersCompleteCallback( http_parser * pHttpParser )
pResponse->respFlags |= HTTP_RESPONSE_CONNECTION_KEEP_ALIVE_FLAG;
}
- /* http_parser_execute() requires that callback implementations must
+ /* llhttp_execute() requires that callback implementations must
* indicate that parsing stops on headers complete, if response is to a HEAD
* request. A HEAD response will contain Content-Length, but no body. If
* the parser is not stopped here, then it will try to keep parsing past the
* end of the headers up to the Content-Length found. */
if( pParsingContext->isHeadResponse == 1U )
{
- shouldContinueParse = HTTP_PARSER_STOP_PARSING;
+ shouldContinueParse = LLHTTP_STOP_PARSING_NO_BODY;
}
/* If headers are present in the response, then
@@ -890,11 +888,11 @@ static int httpParserOnHeadersCompleteCallback( http_parser * pHttpParser )
/*-----------------------------------------------------------*/
-static int httpParserOnBodyCallback( http_parser * pHttpParser,
+static int httpParserOnBodyCallback( llhttp_t * pHttpParser,
const char * pLoc,
size_t length )
{
- int shouldContinueParse = HTTP_PARSER_CONTINUE_PARSING;
+ int shouldContinueParse = LLHTTP_CONTINUE_PARSING;
HTTPParsingContext_t * pParsingContext = NULL;
HTTPResponse_t * pResponse = NULL;
char * pNextWriteLoc = NULL;
@@ -967,7 +965,7 @@ static int httpParserOnBodyCallback( http_parser * pHttpParser,
/*-----------------------------------------------------------*/
-static int httpParserOnMessageCompleteCallback( http_parser * pHttpParser )
+static int httpParserOnMessageCompleteCallback( llhttp_t * pHttpParser )
{
HTTPParsingContext_t * pParsingContext = NULL;
@@ -981,7 +979,7 @@ static int httpParserOnMessageCompleteCallback( http_parser * pHttpParser )
LogDebug( ( "Response parsing: Response message complete." ) );
- return HTTP_PARSER_CONTINUE_PARSING;
+ return LLHTTP_CONTINUE_PARSING;
}
/*-----------------------------------------------------------*/
@@ -993,11 +991,21 @@ static void initializeParsingContextForFirstResponse( HTTPParsingContext_t * pPa
assert( pRequestHeaders != NULL );
assert( pRequestHeaders->headersLen >= HTTP_MINIMUM_REQUEST_LINE_LENGTH );
+ /* Initialize the callbacks that llhttp_execute will invoke. */
+ llhttp_settings_init( &( pParsingContext->llhttpSettings ) );
+ pParsingContext->llhttpSettings.on_message_begin = httpParserOnMessageBeginCallback;
+ pParsingContext->llhttpSettings.on_status = httpParserOnStatusCallback;
+ pParsingContext->llhttpSettings.on_header_field = httpParserOnHeaderFieldCallback;
+ pParsingContext->llhttpSettings.on_header_value = httpParserOnHeaderValueCallback;
+ pParsingContext->llhttpSettings.on_headers_complete = httpParserOnHeadersCompleteCallback;
+ pParsingContext->llhttpSettings.on_body = httpParserOnBodyCallback;
+ pParsingContext->llhttpSettings.on_message_complete = httpParserOnMessageCompleteCallback;
+
/* Initialize the third-party HTTP parser to parse responses. */
- http_parser_init( &( pParsingContext->httpParser ), HTTP_RESPONSE );
+ llhttp_init( &( pParsingContext->llhttpParser ), HTTP_RESPONSE, &( pParsingContext->llhttpSettings ) );
/* The parser will return an error if this header size limit is exceeded. */
- http_parser_set_max_header_size( HTTP_MAX_RESPONSE_HEADERS_SIZE_BYTES );
+ /*http_parser_set_max_header_size( HTTP_MAX_RESPONSE_HEADERS_SIZE_BYTES ); */
/* No response has been parsed yet. */
pParsingContext->state = HTTP_PARSING_NONE;
@@ -1019,13 +1027,16 @@ static void initializeParsingContextForFirstResponse( HTTPParsingContext_t * pPa
/*-----------------------------------------------------------*/
-static HTTPStatus_t processHttpParserError( const http_parser * pHttpParser )
+static HTTPStatus_t processLlhttpError( const llhttp_t * pHttpParser )
{
HTTPStatus_t returnStatus = HTTPSuccess;
assert( pHttpParser != NULL );
- switch( ( enum http_errno ) ( pHttpParser->http_errno ) )
+ /* llhttp_get_err_pos() may be used to get exact error locations, which was
+ * not possible with the previous http-parser. */
+
+ switch( llhttp_get_errno( pHttpParser ) )
{
case HPE_OK:
/* There were no errors. */
@@ -1038,12 +1049,7 @@ static HTTPStatus_t processHttpParserError( const http_parser * pHttpParser )
* This case is already handled by checking HTTPParsingContext_t.state. */
break;
- case HPE_HEADER_OVERFLOW:
- LogError( ( "Response parsing error: Header byte limit "
- "exceeded: HeaderByteLimit=%u",
- HTTP_MAX_RESPONSE_HEADERS_SIZE_BYTES ) );
- returnStatus = HTTPSecurityAlertResponseHeadersSizeLimitExceeded;
- break;
+ /* No header overflow in llhttp since no header size was set. */
case HPE_CLOSED_CONNECTION:
LogError( ( "Response parsing error: Data received past complete "
@@ -1066,6 +1072,7 @@ static HTTPStatus_t processHttpParserError( const http_parser * pHttpParser )
* character and location. */
LogError( ( "Response parsing error: Invalid character found in "
"HTTP protocol version." ) );
+
returnStatus = HTTPSecurityAlertInvalidProtocolVersion;
break;
@@ -1118,15 +1125,16 @@ static HTTPStatus_t processHttpParserError( const http_parser * pHttpParser )
/* All other error cases cannot be triggered and indicate an error in the
* third-party parsing library if found. */
default:
- LogError( ( "Error in third-party http-parser library." ) );
+ LogError( ( "Error in third-party llhttp library: %s", llhttp_errno_name( llhttp_get_errno( pHttpParser ) ) ) );
returnStatus = HTTPParserInternalError;
break;
}
- /* Errors with CB_ prepending are manual returns of non-zero in the
+ /* Errors with HPE_CB_ prepending are manual returns of non-zero in the
* response parsing callback. */
- LogDebug( ( "http-parser errno description: %s",
- http_errno_description( HTTP_PARSER_ERRNO( pHttpParser ) ) ) );
+ LogDebug( ( "llhttp errno description: %s %s",
+ llhttp_errno_name( llhttp_get_errno( pHttpParser ) ),
+ llhttp_get_error_reason( pHttpParser ) ) );
return returnStatus;
}
@@ -1138,12 +1146,8 @@ static HTTPStatus_t parseHttpResponse( HTTPParsingContext_t * pParsingContext,
size_t parseLen )
{
HTTPStatus_t returnStatus;
- http_parser_settings parserSettings = { 0 };
- size_t bytesParsed = 0U;
const char * parsingStartLoc = NULL;
-
- /* Disable unused variable warning. */
- ( void ) bytesParsed;
+ llhttp_errno_t parserStatus;
assert( pParsingContext != NULL );
assert( pResponse != NULL );
@@ -1177,19 +1181,9 @@ static HTTPStatus_t parseHttpResponse( HTTPParsingContext_t * pParsingContext,
assert( pParsingContext->pResponse == pResponse );
}
- /* Initialize the callbacks that http_parser_execute will invoke. */
- http_parser_settings_init( &parserSettings );
- parserSettings.on_message_begin = httpParserOnMessageBeginCallback;
- parserSettings.on_status = httpParserOnStatusCallback;
- parserSettings.on_header_field = httpParserOnHeaderFieldCallback;
- parserSettings.on_header_value = httpParserOnHeaderValueCallback;
- parserSettings.on_headers_complete = httpParserOnHeadersCompleteCallback;
- parserSettings.on_body = httpParserOnBodyCallback;
- parserSettings.on_message_complete = httpParserOnMessageCompleteCallback;
-
/* Setting this allows the parsing context and response to be carried to
- * each of the callbacks that http_parser_execute() will invoke. */
- pParsingContext->httpParser.data = pParsingContext;
+ * each of the callbacks that llhttp_execute() will invoke. */
+ pParsingContext->llhttpParser.data = pParsingContext;
/* Save the starting response buffer location to parse. This is needed to
* ensure that we move the next location to parse to exactly how many
@@ -1199,21 +1193,12 @@ static HTTPStatus_t parseHttpResponse( HTTPParsingContext_t * pParsingContext,
/* This will begin the parsing. Each of the callbacks set in
* parserSettings will be invoked as parts of the HTTP response are
* reached. */
- bytesParsed = http_parser_execute( &( pParsingContext->httpParser ),
- &parserSettings,
- parsingStartLoc,
- parseLen );
+ parserStatus = llhttp_execute( &( pParsingContext->llhttpParser ), parsingStartLoc, parseLen );
/* The next location to parse will always be after what has already
* been parsed. */
- pParsingContext->pBufferCur = parsingStartLoc + bytesParsed;
-
- LogDebug( ( "Parsed HTTP Response buffer: BytesParsed=%lu, "
- "ExpectedBytesParsed=%lu",
- ( unsigned long ) bytesParsed,
- ( unsigned long ) parseLen ) );
-
- returnStatus = processHttpParserError( &( pParsingContext->httpParser ) );
+ pParsingContext->pBufferCur = parsingStartLoc + parseLen;
+ returnStatus = processLlhttpError( &( pParsingContext->llhttpParser ) );
return returnStatus;
}
@@ -2254,7 +2239,7 @@ HTTPStatus_t HTTPClient_Send( const TransportInterface_t * pTransport,
/*-----------------------------------------------------------*/
-static int findHeaderFieldParserCallback( http_parser * pHttpParser,
+static int findHeaderFieldParserCallback( llhttp_t * pHttpParser,
const char * pFieldLoc,
size_t fieldLen )
{
@@ -2291,16 +2276,16 @@ static int findHeaderFieldParserCallback( http_parser * pHttpParser,
/* Empty else for MISRA 15.7 compliance. */
}
- return HTTP_PARSER_CONTINUE_PARSING;
+ return LLHTTP_CONTINUE_PARSING;
}
/*-----------------------------------------------------------*/
-static int findHeaderValueParserCallback( http_parser * pHttpParser,
+static int findHeaderValueParserCallback( llhttp_t * pHttpParser,
const char * pValueLoc,
size_t valueLen )
{
- int retCode = HTTP_PARSER_CONTINUE_PARSING;
+ int retCode = LLHTTP_CONTINUE_PARSING;
findHeaderContext_t * pContext = NULL;
assert( pHttpParser != NULL );
@@ -2343,7 +2328,7 @@ static int findHeaderValueParserCallback( http_parser * pHttpParser,
/* As we have found the value associated with the header, we don't need
* to parse the response any further. */
- retCode = HTTP_PARSER_STOP_PARSING;
+ retCode = LLHTTP_STOP_PARSING;
}
else
{
@@ -2355,7 +2340,7 @@ static int findHeaderValueParserCallback( http_parser * pHttpParser,
/*-----------------------------------------------------------*/
-static int findHeaderOnHeaderCompleteCallback( http_parser * pHttpParser )
+static int findHeaderOnHeaderCompleteCallback( llhttp_t * pHttpParser )
{
findHeaderContext_t * pContext = NULL;
@@ -2375,8 +2360,14 @@ static int findHeaderOnHeaderCompleteCallback( http_parser * pHttpParser )
( int ) ( pContext->fieldLen ),
pContext->pField ) );
- /* No further parsing is required; thus, indicate the parser to stop parsing. */
- return HTTP_PARSER_STOP_PARSING;
+ /* No further parsing is required; thus, indicate the parser to stop parsing.
+ * The documentation for on_headers_complete states that this function can
+ * return 1 to indicate the response has no body, or -1 to indicate error.
+ * Returning 1 causes llhttp_execute() to exit with success, while -1
+ * causes it to return the HPE_CB_HEADERS_COMPLETE error code (in strict
+ * mode) or success (in non-strict mode). We are fine with the success
+ * return value, as llhttp_execute will not be invoked again in the same call.*/
+ return LLHTTP_STOP_PARSING_NO_HEADER;
}
/*-----------------------------------------------------------*/
@@ -2389,8 +2380,9 @@ static HTTPStatus_t findHeaderInResponse( const uint8_t * pBuffer,
size_t * pValueLen )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser parser = { 0 };
- http_parser_settings parserSettings = { 0 };
+ llhttp_t parser = { 0 };
+ llhttp_settings_t parserSettings = { 0 };
+ llhttp_errno_t parserErrno;
findHeaderContext_t context = { 0 };
size_t numOfBytesParsed = 0U;
@@ -2401,30 +2393,20 @@ static HTTPStatus_t findHeaderInResponse( const uint8_t * pBuffer,
context.fieldFound = 0U;
context.valueFound = 0U;
- /* Disable unused variable warning. This variable is used only in logging. */
- ( void ) numOfBytesParsed;
-
- http_parser_init( &parser, HTTP_RESPONSE );
-
- /* Set the context for the parser. */
- parser.data = &context;
-
/* The intention here to define callbacks just for searching the headers. We will
- * need to create a private context in httpParser->data that has the field and
+ * need to create a private context in llhttp->data that has the field and
* value to update and pass back. */
- http_parser_settings_init( &parserSettings );
+ llhttp_settings_init( &( parserSettings ) );
parserSettings.on_header_field = findHeaderFieldParserCallback;
parserSettings.on_header_value = findHeaderValueParserCallback;
parserSettings.on_headers_complete = findHeaderOnHeaderCompleteCallback;
+ llhttp_init( &parser, HTTP_RESPONSE, &parserSettings );
- /* Start parsing for the header! */
- numOfBytesParsed = http_parser_execute( &parser,
- &parserSettings,
- ( const char * ) pBuffer,
- bufferLen );
+ /* Set the context for the parser. */
+ parser.data = &context;
- LogDebug( ( "Parsed response for header search: NumBytesParsed=%lu",
- ( unsigned long ) numOfBytesParsed ) );
+ /* Start parsing for the header! */
+ parserErrno = llhttp_execute( &parser, ( const char * ) pBuffer, bufferLen );
if( context.fieldFound == 0U )
{
@@ -2444,10 +2426,11 @@ static HTTPStatus_t findHeaderInResponse( const uint8_t * pBuffer,
* in the ": \r\n" format of an HTTP header. */
LogError( ( "Unable to find header value in response: "
"Response data is invalid: "
- "RequestedHeader=%.*s, ParserError=%s",
+ "RequestedHeader=%.*s, ParserError=%s %s",
( int ) fieldLen,
pField,
- http_errno_description( HTTP_PARSER_ERRNO( &( parser ) ) ) ) );
+ llhttp_errno_name( parserErrno ),
+ llhttp_get_error_reason( &parser ) ) );
returnStatus = HTTPInvalidResponse;
}
else
@@ -2466,25 +2449,27 @@ static HTTPStatus_t findHeaderInResponse( const uint8_t * pBuffer,
/* If the header field-value pair is found in response, then the return
* value of "on_header_value" callback (related to the header value) should
- * cause the http_parser.http_errno to be "CB_header_value". */
+ * cause the llhttp.error to be "USER". */
if( ( returnStatus == HTTPSuccess ) &&
- ( parser.http_errno != ( unsigned int ) HPE_CB_header_value ) )
+ ( parserErrno != HPE_USER ) )
{
- LogError( ( "Header found in response but http-parser returned error: "
- "ParserError=%s",
- http_errno_description( HTTP_PARSER_ERRNO( &( parser ) ) ) ) );
+ LogError( ( "Header found in response but llhttp returned error: "
+ "ParserError=%s %s",
+ llhttp_errno_name( parserErrno ),
+ llhttp_get_error_reason( &parser ) ) );
returnStatus = HTTPParserInternalError;
}
/* If header was not found, then the "on_header_complete" callback is
- * expected to be called which should cause the http_parser.http_errno to be
+ * expected to be called which should cause the llhttp.error to be
* "OK" */
else if( ( returnStatus == HTTPHeaderNotFound ) &&
- ( parser.http_errno != ( unsigned int ) ( HPE_OK ) ) )
+ ( parserErrno != HPE_OK ) )
{
- LogError( ( "Header not found in response: http-parser returned error: "
- "ParserError=%s",
- http_errno_description( HTTP_PARSER_ERRNO( &( parser ) ) ) ) );
+ LogError( ( "Header not found in response: llhttp returned error: "
+ "ParserError=%s %s",
+ llhttp_errno_name( parserErrno ),
+ llhttp_get_error_reason( &parser ) ) );
returnStatus = HTTPInvalidResponse;
}
else
diff --git a/source/dependency/3rdparty/http_parser b/source/dependency/3rdparty/http_parser
deleted file mode 160000
index ec8b5ee6..00000000
--- a/source/dependency/3rdparty/http_parser
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit ec8b5ee63f0e51191ea43bb0c6eac7bfbff3141d
diff --git a/source/dependency/3rdparty/llhttp b/source/dependency/3rdparty/llhttp
new file mode 160000
index 00000000..a4aa7a70
--- /dev/null
+++ b/source/dependency/3rdparty/llhttp
@@ -0,0 +1 @@
+Subproject commit a4aa7a70e8b9a67f378b53264c61bb044a224366
diff --git a/source/include/core_http_client.h b/source/include/core_http_client.h
index 0f589a5b..2f005715 100644
--- a/source/include/core_http_client.h
+++ b/source/include/core_http_client.h
@@ -228,7 +228,7 @@ typedef enum HTTPStatus
* #HTTP_MAX_RESPONSE_HEADERS_SIZE_BYTES.
*
* Functions that may return this value:
- * - #HTTPClient_Send
+ * - None
*/
HTTPSecurityAlertResponseHeadersSizeLimitExceeded,
diff --git a/source/include/core_http_client_private.h b/source/include/core_http_client_private.h
index a0af6f9a..fc2ac28b 100644
--- a/source/include/core_http_client_private.h
+++ b/source/include/core_http_client_private.h
@@ -28,8 +28,17 @@
#ifndef CORE_HTTP_CLIENT_PRIVATE_H_
#define CORE_HTTP_CLIENT_PRIVATE_H_
-/* Third-party http-parser include. */
-#include "http_parser.h"
+/**
+ * @cond DOXYGEN_IGNORE
+ * http-parser defaults this to 1, llhttp to 0.
+ */
+#ifndef LLHTTP_STRICT_MODE
+ #define LLHTTP_STRICT_MODE 0
+#endif
+/** @endcond */
+
+/* Third-party llhttp include. */
+#include "llhttp.h"
/* *INDENT-OFF* */
#ifdef __cplusplus
@@ -150,16 +159,31 @@
1U /* Dash character '-' */ + MAX_INT32_NO_OF_DECIMAL_DIGITS )
/**
- * @brief Return value for the http-parser registered callback to signal halting
+ * @brief Return value for llhttp registered callback to signal
+ * continuation of HTTP response parsing. Equal to HPE_OK.
+ */
+#define LLHTTP_CONTINUE_PARSING 0
+
+/**
+ * @brief Return value for llhttp registered callback to signal halting
* further execution.
*/
-#define HTTP_PARSER_STOP_PARSING 1
+#define LLHTTP_STOP_PARSING HPE_USER
/**
- * @brief Return value for http_parser registered callback to signal
- * continuation of HTTP response parsing.
+ * @brief Return value for llhttp_t.on_headers_complete to signal
+ * that the HTTP response has no body and to halt further execution.
*/
-#define HTTP_PARSER_CONTINUE_PARSING 0
+#define LLHTTP_STOP_PARSING_NO_BODY 1
+
+/**
+ * @brief Return value for llhttp_t.on_headers_complete to signal
+ * halting further execution. This is the same return value that
+ * indicates the HTTP response has no body, but unlike the -1 error
+ * code, gives consistent return values for llhttp_execute in both
+ * strict and non-strict modes.
+ */
+#define LLHTTP_STOP_PARSING_NO_HEADER 1
/**
* @brief The minimum request-line in the headers has a possible one character
@@ -261,16 +285,17 @@ typedef struct findHeaderContext
*/
typedef struct HTTPParsingContext
{
- http_parser httpParser; /**< Third-party http-parser context. */
- HTTPParsingState_t state; /**< The current state of the HTTP response parsed. */
- HTTPResponse_t * pResponse; /**< HTTP response associated with this parsing context. */
- uint8_t isHeadResponse; /**< HTTP response is for a HEAD request. */
-
- const char * pBufferCur; /**< The current location of the parser in the response buffer. */
- const char * pLastHeaderField; /**< Holds the last part of the header field parsed. */
- size_t lastHeaderFieldLen; /**< The length of the last header field parsed. */
- const char * pLastHeaderValue; /**< Holds the last part of the header value parsed. */
- size_t lastHeaderValueLen; /**< The length of the last value field parsed. */
+ llhttp_t llhttpParser; /**< Third-party llhttp context. */
+ llhttp_settings_t llhttpSettings; /**< Third-party parser settings. */
+ HTTPParsingState_t state; /**< The current state of the HTTP response parsed. */
+ HTTPResponse_t * pResponse; /**< HTTP response associated with this parsing context. */
+ uint8_t isHeadResponse; /**< HTTP response is for a HEAD request. */
+
+ const char * pBufferCur; /**< The current location of the parser in the response buffer. */
+ const char * pLastHeaderField; /**< Holds the last part of the header field parsed. */
+ size_t lastHeaderFieldLen; /**< The length of the last header field parsed. */
+ const char * pLastHeaderValue; /**< Holds the last part of the header value parsed. */
+ size_t lastHeaderValueLen; /**< The length of the last value field parsed. */
} HTTPParsingContext_t;
/* *INDENT-OFF* */
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 767b9363..d92a942e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -47,18 +47,18 @@ target_include_directories( coverity_analysis PUBLIC ${HTTP_INCLUDE_PUBLIC_DIRS}
# ===================== Clone needed third-party libraries ======================
-# Define an http-paser resource path.
-set( HTTP_PARSER_DIR ${MODULE_ROOT_DIR}/source/dependency/3rdparty/http_parser CACHE INTERNAL "http-parser library source directory." )
+# Define an llhttp paser resource path.
+set( LLHTTP_DIR ${MODULE_ROOT_DIR}/source/dependency/3rdparty/llhttp CACHE INTERNAL "llhttp library source directory." )
-include( http_parser_build.cmake )
+include( llhttp_build.cmake )
-# Check if the http_parser source directory exists.
-if( NOT EXISTS ${HTTP_PARSER_DIR}/http_parser.c )
- # Attempt to clone http_parser.
+# Check if the llhttp_source directory exists.
+if( NOT EXISTS ${LLHTTP_DIR}/src/llhttp.c )
+ # Attempt to clone llhttp.
if( ${BUILD_CLONE_SUBMODULES} )
- clone_http_parser()
+ clone_llhttp()
else()
- message( FATAL_ERROR "The required submodule http_parser does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." )
+ message( FATAL_ERROR "The required submodule llhttp does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." )
endif()
endif()
diff --git a/test/http_parser_build.cmake b/test/http_parser_build.cmake
deleted file mode 100644
index a5dd5609..00000000
--- a/test/http_parser_build.cmake
+++ /dev/null
@@ -1,19 +0,0 @@
-macro( clone_http_parser )
- find_package( Git REQUIRED )
- message( "Cloning submodule http_parser." )
- execute_process( COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${HTTP_PARSER_DIR}
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- RESULT_VARIABLE HTTP_PARSER_CLONE_RESULT )
-
- if( NOT ${HTTP_PARSER_CLONE_RESULT} STREQUAL "0" )
- message( FATAL_ERROR "Failed to clone http_parser submodule." )
- endif()
-endmacro()
-
-# http_parser library target.
-add_library( http_parser
- ${HTTP_PARSER_DIR}/http_parser.c )
-
-# http_parser public include path.
-target_include_directories( http_parser PUBLIC
- ${HTTP_PARSER_DIR} )
diff --git a/test/llhttp_build.cmake b/test/llhttp_build.cmake
new file mode 100644
index 00000000..3f04d0e4
--- /dev/null
+++ b/test/llhttp_build.cmake
@@ -0,0 +1,21 @@
+macro( clone_llhttp )
+ find_package( Git REQUIRED )
+ message( "Cloning submodule llhttp." )
+ execute_process( COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${LLHTTP_DIR}
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ RESULT_VARIABLE LLHTTP_CLONE_RESULT )
+
+ if( NOT ${LLHTTP_CLONE_RESULT} STREQUAL "0" )
+ message( FATAL_ERROR "Failed to clone llhttp submodule." )
+ endif()
+endmacro()
+
+# llhttp library target.
+add_library( llhttp
+ ${LLHTTP_DIR}/src/api.c
+ ${LLHTTP_DIR}/src/http.c
+ ${LLHTTP_DIR}/src/llhttp.c )
+
+# llhttp public include path.
+target_include_directories( llhttp PUBLIC
+ ${LLHTTP_DIR}/include )
diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt
index 838b891b..bf0baf5a 100644
--- a/test/unit-test/CMakeLists.txt
+++ b/test/unit-test/CMakeLists.txt
@@ -8,11 +8,11 @@ set(project_name "core_http")
# list the files to mock here
list(APPEND mock_list
- ${HTTP_PARSER_DIR}/http_parser.h
+ ${LLHTTP_DIR}/include/llhttp.h
)
# list the directories your mocks need
list(APPEND mock_include_list
- ${HTTP_PARSER_DIR}
+ ${LLHTTP_DIR}/include
)
#list the definitions of your mocks to control what to be included
list(APPEND mock_define_list
@@ -41,7 +41,7 @@ list(APPEND test_include_directories
# ============================= (end edit) ===================================
-set(mock_name "http_parser_mock")
+set(mock_name "llhttp_mock")
set(real_name "${project_name}_real")
create_mock_list(${mock_name}
diff --git a/test/unit-test/core_http_send_utest.c b/test/unit-test/core_http_send_utest.c
index 84e1e0bc..4ae0ae78 100644
--- a/test/unit-test/core_http_send_utest.c
+++ b/test/unit-test/core_http_send_utest.c
@@ -31,7 +31,7 @@
/* Private includes for internal macros. */
#include "core_http_client_private.h"
-#include "mock_http_parser.h"
+#include "mock_llhttp.h"
/* Template HTTP request for a HEAD request. */
#define HTTP_TEST_REQUEST_HEAD_HEADERS \
@@ -217,12 +217,12 @@ static uint8_t recvCurrentCall = 0;
/* The test sets this variable to indicate which call count count of transport
* receive to return zero from. */
static uint8_t recvTimeoutCall = 0;
-/* The count of times a mocked http_parser_execute callback has been invoked. */
+/* The count of times a mocked llhttp_execute callback has been invoked. */
static uint8_t httpParserExecuteCallCount;
-/* The error to set to the parsing context when the http_parser_execute_error
+/* The error to set to the parsing context when the llhttp_execute_error
* callback is invoked. */
-static enum http_errno httpParsingErrno;
+static enum llhttp_errno httpParsingErrno;
/* Response shared among the tests. */
static HTTPResponse_t response = { 0 };
@@ -387,26 +387,47 @@ static int32_t transportRecvNetworkError( NetworkContext_t * pNetworkContext,
return -1;
}
-/* Mocked http_parser_execute callback that sets the internal http_errno. */
-static size_t http_parser_execute_error( http_parser * pParser,
- const http_parser_settings * pSettings,
- const char * pData,
- size_t len,
- int cmock_num_calls )
+/* llhttp_init callback that sets the parser settings field. */
+static void llhttp_init_setup( llhttp_t * parser,
+ enum llhttp_type type,
+ const llhttp_settings_t * settings,
+ int cmock_num_calls )
+{
+ ( void ) cmock_num_calls;
+
+ parser->type = type;
+ /* Remove const qualifier. llhttp does this too. */
+ parser->settings = ( llhttp_settings_t * ) settings;
+ parser->error = HPE_OK;
+}
+
+/* llhttp_get_errno callback that returns the errno value. */
+llhttp_errno_t llhttp_get_errno_cb( const llhttp_t * parser,
+ int cmock_num_calls )
+{
+ ( void ) cmock_num_calls;
+
+ return parser->error;
+}
+
+/* Mocked llhttp_execute callback that sets the internal errno. */
+static llhttp_errno_t llhttp_execute_error( llhttp_t * pParser,
+ const char * pData,
+ size_t len,
+ int cmock_num_calls )
{
- ( void ) pSettings;
( void ) pData;
( void ) len;
( void ) cmock_num_calls;
- pParser->http_errno = httpParsingErrno;
- return 0;
+ pParser->error = httpParsingErrno;
+ return httpParsingErrno;
}
/* Mock helper that parses the status line starting from pNext. */
static void helper_parse_status_line( const char ** pNext,
- http_parser * pParser,
- const http_parser_settings * pSettings )
+ llhttp_t * pParser,
+ const llhttp_settings_t * pSettings )
{
const char * pReasonPhraseStart = NULL;
size_t reasonPhraseStartLen = 0;
@@ -432,8 +453,8 @@ static void helper_parse_status_line( const char ** pNext,
/* Mock helper that parses all of the headers starting from pNext. */
static void helper_parse_headers( const char ** pNext,
- http_parser * pParser,
- const http_parser_settings * pSettings )
+ llhttp_t * pParser,
+ const llhttp_settings_t * pSettings )
{
const char * pHeaderFieldStart = NULL;
size_t headerFieldLen = 0;
@@ -461,8 +482,8 @@ static void helper_parse_headers( const char ** pNext,
/* Mock helper that parses the end of the headers starting from pNext. pNext
* will point to the start of the body after this is finished. */
static void helper_parse_headers_finish( const char ** pNext,
- http_parser * pParser,
- const http_parser_settings * pSettings,
+ llhttp_t * pParser,
+ const llhttp_settings_t * pSettings,
uint8_t * isHeadResponse )
{
uint8_t isHeadResponseReturned = 0;
@@ -491,8 +512,8 @@ static void helper_parse_headers_finish( const char ** pNext,
/* Mock helper that parses the response body starting from pNext. */
static void helper_parse_body( const char ** pNext,
- http_parser * pParser,
- const http_parser_settings * pSettings,
+ llhttp_t * pParser,
+ const llhttp_settings_t * pSettings,
uint8_t isHeadResponse,
const char * pData,
size_t len )
@@ -513,17 +534,17 @@ static void helper_parse_body( const char ** pNext,
}
}
-/* Mocked http_parser_execute callback that expects a whole response to be in
+/* Mocked llhttp_execute callback that expects a whole response to be in
* the given data to parse. */
-static size_t http_parser_execute_whole_response( http_parser * pParser,
- const http_parser_settings * pSettings,
- const char * pData,
- size_t len,
- int cmock_num_calls )
+static llhttp_errno_t llhttp_execute_whole_response( llhttp_t * pParser,
+ const char * pData,
+ size_t len,
+ int cmock_num_calls )
{
( void ) cmock_num_calls;
const char * pNext = pData;
uint8_t isHeadResponse = 0;
+ llhttp_settings_t * pSettings = ( llhttp_settings_t * ) pParser->settings;
pSettings->on_message_begin( pParser );
@@ -535,24 +556,24 @@ static size_t http_parser_execute_whole_response( http_parser * pParser,
pSettings->on_message_complete( pParser );
httpParserExecuteCallCount++;
- return len;
+ return HPE_OK;
}
-/* Mocked http_parser_execute callback that will be called the first time on the
+/* Mocked llhttp_execute callback that will be called the first time on the
* response message up to the middle of the first header field, then the second
* time on the response message from the middle of the first header field to the
* end. */
-static size_t http_parser_execute_partial_header_field( http_parser * pParser,
- const http_parser_settings * pSettings,
- const char * pData,
- size_t len,
- int cmock_num_calls )
+static llhttp_errno_t llhttp_execute_partial_header_field( llhttp_t * pParser,
+ const char * pData,
+ size_t len,
+ int cmock_num_calls )
{
( void ) cmock_num_calls;
const char * pNext = pData;
uint8_t isHeadResponse = 0;
const char * pHeaderFieldStart = NULL;
size_t headerFieldLen = 0;
+ llhttp_settings_t * pSettings = ( llhttp_settings_t * ) pParser->settings;
if( httpParserExecuteCallCount == 0 )
{
@@ -567,12 +588,12 @@ static size_t http_parser_execute_partial_header_field( http_parser * pParser,
}
else
{
- /* For testing of invoking http_parser_execute() with a parsing length
+ /* For testing of invoking llhttp_execute() with a parsing length
* of zero, when data had been previously parsed. */
if( len == 0 )
{
- pParser->http_errno = HPE_INVALID_EOF_STATE;
- return 0;
+ pParser->error = HPE_INVALID_EOF_STATE;
+ return HPE_INVALID_EOF_STATE;
}
helper_parse_headers( &pNext, pParser, pSettings );
@@ -582,18 +603,17 @@ static size_t http_parser_execute_partial_header_field( http_parser * pParser,
}
httpParserExecuteCallCount++;
- return len;
+ return HPE_OK;
}
-/* Mocked http_parser_execute callback that will be called the first time on the
+/* Mocked llhttp_execute callback that will be called the first time on the
* response message up to the middle of the first header value, then the second
* time on the response message from the middle of the first header value to the
* end. */
-static size_t http_parser_execute_partial_header_value( http_parser * pParser,
- const http_parser_settings * pSettings,
- const char * pData,
- size_t len,
- int cmock_num_calls )
+static llhttp_errno_t llhttp_execute_partial_header_value( llhttp_t * pParser,
+ const char * pData,
+ size_t len,
+ int cmock_num_calls )
{
( void ) cmock_num_calls;
@@ -603,6 +623,7 @@ static size_t http_parser_execute_partial_header_value( http_parser * pParser,
size_t headerFieldLen = 0;
const char * pHeaderValueStart = NULL;
size_t headerValueLen = 0;
+ llhttp_settings_t * pSettings = ( llhttp_settings_t * ) pParser->settings;
if( httpParserExecuteCallCount == 0 )
{
@@ -625,7 +646,7 @@ static size_t http_parser_execute_partial_header_value( http_parser * pParser,
}
else
{
- /* In this second call to http_parser_execute mock, pData now starts
+ /* In this second call to llhttp_execute mock, pData now starts
* at the partial header value. */
pHeaderValueStart = pNext;
pNext = strstr( pNext, HTTP_HEADER_LINE_SEPARATOR );
@@ -642,21 +663,21 @@ static size_t http_parser_execute_partial_header_value( http_parser * pParser,
}
httpParserExecuteCallCount++;
- return len;
+ return HPE_OK;
}
-/* Mocked http_parser_execute callback that will be called the first time on the
+/* Mocked llhttp_execute callback that will be called the first time on the
* response message up to the middle of the body, then the second time on the
* response message from the middle of the body to the end. */
-static size_t http_parser_execute_partial_body( http_parser * pParser,
- const http_parser_settings * pSettings,
- const char * pData,
- size_t len,
- int cmock_num_calls )
+static llhttp_errno_t llhttp_execute_partial_body( llhttp_t * pParser,
+ const char * pData,
+ size_t len,
+ int cmock_num_calls )
{
( void ) cmock_num_calls;
const char * pNext = pData;
+ llhttp_settings_t * pSettings = ( llhttp_settings_t * ) pParser->settings;
if( httpParserExecuteCallCount == 0 )
{
@@ -676,16 +697,15 @@ static size_t http_parser_execute_partial_body( http_parser * pParser,
}
httpParserExecuteCallCount++;
- return len;
+ return HPE_OK;
}
-/* Mocked http_parser_execute callback that will be on a response of type
+/* Mocked llhttp_execute callback that will be on a response of type
* transfer-encoding chunked. */
-static size_t http_parser_execute_chunked_body( http_parser * pParser,
- const http_parser_settings * pSettings,
- const char * pData,
- size_t len,
- int cmock_num_calls )
+static llhttp_errno_t llhttp_execute_chunked_body( llhttp_t * pParser,
+ const char * pData,
+ size_t len,
+ int cmock_num_calls )
{
( void ) cmock_num_calls;
@@ -694,6 +714,7 @@ static size_t http_parser_execute_chunked_body( http_parser * pParser,
const char * pBody = NULL;
size_t bodyLen = 0;
const char * pChunkHeader = NULL;
+ llhttp_settings_t * pSettings = ( llhttp_settings_t * ) pParser->settings;
pSettings->on_message_begin( pParser );
@@ -725,7 +746,7 @@ static size_t http_parser_execute_chunked_body( http_parser * pParser,
pSettings->on_message_complete( pParser );
httpParserExecuteCallCount++;
- return len;
+ return HPE_OK;
}
/* ============================ UNITY FIXTURES ============================== */
@@ -765,10 +786,12 @@ void setUp( void )
response.pHeaderParsingCallback = &headerParsingCallback;
/* Ignore third-party init functions that return void. */
- http_parser_init_Ignore();
- http_parser_settings_init_Ignore();
- http_parser_set_max_header_size_Ignore();
- http_errno_description_IgnoreAndReturn( "Dummy unit test print." );
+ llhttp_init_Ignore();
+ llhttp_init_Stub( llhttp_init_setup );
+ llhttp_get_errno_Stub( llhttp_get_errno_cb );
+ llhttp_settings_init_Ignore();
+ llhttp_errno_name_IgnoreAndReturn( "Dummy" );
+ llhttp_get_error_reason_IgnoreAndReturn( "Dummy unit test print." );
}
/* ======================== Testing HTTPClient_Send ========================= */
@@ -779,7 +802,7 @@ void test_HTTPClient_Send_HEAD_request_parse_whole_response( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
returnStatus = HTTPClient_Send( &transportInterface,
&requestHeaders,
@@ -808,7 +831,7 @@ void test_HTTPClient_Send_PUT_request_parse_whole_response( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
checkContentLength = 1;
memcpy( requestHeaders.pBuffer,
@@ -847,7 +870,7 @@ void test_HTTPClient_Send_GET_request_parse_whole_response( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
memcpy( requestHeaders.pBuffer,
HTTP_TEST_REQUEST_GET_HEADERS,
@@ -883,7 +906,7 @@ void test_HTTPClient_Send_no_response_headers( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
pNetworkData = ( uint8_t * ) HTTP_TEST_RESPONSE_NO_HEADERS;
networkDataLen = HTTP_TEST_RESPONSE_NO_HEADERS_LENGTH;
@@ -916,7 +939,7 @@ void test_HTTPClient_Send_parse_partial_header_field( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_partial_header_field );
+ llhttp_execute_Stub( llhttp_execute_partial_header_field );
firstPartBytes = HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_FIELD_LENGTH;
returnStatus = HTTPClient_Send( &transportInterface,
@@ -947,7 +970,7 @@ void test_HTTPClient_Send_parse_partial_header_value( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_partial_header_value );
+ llhttp_execute_Stub( llhttp_execute_partial_header_value );
firstPartBytes = HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_VALUE_LENGTH;
returnStatus = HTTPClient_Send( &transportInterface,
@@ -978,7 +1001,7 @@ void test_HTTPClient_Send_parse_partial_body( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_partial_body );
+ llhttp_execute_Stub( llhttp_execute_partial_body );
memcpy( requestHeaders.pBuffer,
HTTP_TEST_REQUEST_GET_HEADERS,
@@ -1013,7 +1036,7 @@ void test_HTTPClient_Send_parse_chunked_body( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_chunked_body );
+ llhttp_execute_Stub( llhttp_execute_chunked_body );
memcpy( requestHeaders.pBuffer,
HTTP_TEST_REQUEST_PUT_HEADERS,
@@ -1048,7 +1071,7 @@ void test_HTTPClient_Send_timeout_recv_immediate( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_ExpectAnyArgsAndReturn( 0 );
+ llhttp_execute_ExpectAnyArgsAndReturn( HPE_OK );
/* Return a zero on the first call. */
recvTimeoutCall = 1;
@@ -1069,8 +1092,9 @@ void test_HTTPClient_Send_timeout_partial_response( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_partial_header_field );
- http_errno_description_IgnoreAndReturn( "Dummy unit test print." );
+ llhttp_execute_Stub( llhttp_execute_partial_header_field );
+ llhttp_errno_name_IgnoreAndReturn( "Dummy" );
+ llhttp_get_error_reason_IgnoreAndReturn( "Dummy unit test print." );
firstPartBytes = HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_VALUE_LENGTH;
/* Return a zero on the second transport receive call. */
@@ -1093,8 +1117,9 @@ void test_HTTPClient_Send_timeout_recv_retry( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
- http_errno_description_IgnoreAndReturn( "Dummy unit test print." );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
+ llhttp_errno_name_IgnoreAndReturn( "Dummy" );
+ llhttp_get_error_reason_IgnoreAndReturn( "Dummy unit test print." );
/* Set the optional time keeping function to retry the receive when zero
* data is read from the network. */
@@ -1123,8 +1148,9 @@ void test_HTTPClient_Send_response_larger_than_buffer( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_partial_body );
- http_errno_description_IgnoreAndReturn( "Dummy unit test print." );
+ llhttp_execute_Stub( llhttp_execute_partial_body );
+ llhttp_errno_name_IgnoreAndReturn( "Dummy" );
+ llhttp_get_error_reason_IgnoreAndReturn( "Dummy unit test print." );
requestHeaders.pBuffer = ( uint8_t * ) ( HTTP_TEST_REQUEST_GET_HEADERS );
requestHeaders.bufferLen = HTTP_TEST_REQUEST_GET_HEADERS_LENGTH;
@@ -1218,7 +1244,7 @@ void test_HTTPClient_Send_timeout_send_retry( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
response.getTime = getTestTime;
/* An zero is returned from the transport send on the first call. */
@@ -1241,7 +1267,7 @@ void test_HTTPClient_Send_timeout_send_retry_fail( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
/* By default a HEAD request is ready to be sent. */
transportInterface.send = transportSendSuccess;
@@ -1269,7 +1295,7 @@ void test_HTTPClient_Send_less_bytes_request_headers( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
transportInterface.send = transportSendSuccess;
/* Send the data partially in the first call to the transport send. */
@@ -1309,7 +1335,7 @@ void test_HTTPClient_Send_less_bytes_request_body( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_execute_Stub( http_parser_execute_whole_response );
+ llhttp_execute_Stub( llhttp_execute_whole_response );
transportInterface.send = transportSendSuccess;
@@ -1351,7 +1377,7 @@ void test_HTTPClient_Send_network_error_response( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_init_Ignore();
+ llhttp_init_Ignore();
transportInterface.recv = transportRecvNetworkError;
returnStatus = HTTPClient_Send( &transportInterface,
@@ -1594,19 +1620,11 @@ void test_HTTPClient_Send_parsing_errors( void )
{
HTTPStatus_t returnStatus = HTTPSuccess;
- http_parser_init_Ignore();
- http_parser_settings_init_Ignore();
- http_parser_execute_Stub( http_parser_execute_error );
- http_errno_description_IgnoreAndReturn( "Dummy unit test print." );
-
- httpParsingErrno = HPE_HEADER_OVERFLOW;
- returnStatus = HTTPClient_Send( &transportInterface,
- &requestHeaders,
- NULL,
- 0,
- &response,
- 0 );
- TEST_ASSERT_EQUAL( HTTPSecurityAlertResponseHeadersSizeLimitExceeded, returnStatus );
+ llhttp_init_Ignore();
+ llhttp_settings_init_Ignore();
+ llhttp_execute_Stub( llhttp_execute_error );
+ llhttp_errno_name_IgnoreAndReturn( "Dummy" );
+ llhttp_get_error_reason_IgnoreAndReturn( "Dummy unit test print." );
httpParsingErrno = HPE_INVALID_CHUNK_SIZE;
returnStatus = HTTPClient_Send( &transportInterface,
@@ -1698,7 +1716,8 @@ void test_HTTPClient_Send_parsing_errors( void )
0 );
TEST_ASSERT_EQUAL( HTTPSecurityAlertInvalidContentLength, returnStatus );
- httpParsingErrno = HPE_UNKNOWN;
+ /* Use -1 to indicate an unknown error. */
+ httpParsingErrno = -1;
returnStatus = HTTPClient_Send( &transportInterface,
&requestHeaders,
NULL,
diff --git a/test/unit-test/core_http_utest.c b/test/unit-test/core_http_utest.c
index fc928327..781f6820 100644
--- a/test/unit-test/core_http_utest.c
+++ b/test/unit-test/core_http_utest.c
@@ -30,8 +30,8 @@
/* Private includes for internal macros. */
#include "core_http_client_private.h"
-/* Include mock implementation of http-parser dependency. */
-#include "mock_http_parser.h"
+/* Include mock implementation of llhttp dependency. */
+#include "mock_llhttp.h"
/* Default size for request buffer. */
#define HTTP_TEST_BUFFER_SIZE ( 100 )
@@ -175,8 +175,8 @@ static const size_t otherHeaderFieldInRespLoc = 98;
static const size_t otherHeaderFieldInRespLen = sizeof( "header_not_in_buffer" ) - 1U;
static const size_t headerValInRespLoc = 58;
static const size_t headerValInRespLen = sizeof( "test-value1" ) - 1U;
-static http_parser * pCapturedParser = NULL;
-static http_parser_settings * pCapturedSettings = NULL;
+static llhttp_t * pCapturedParser = NULL;
+static llhttp_settings_t * pCapturedSettings = NULL;
static const char * pExpectedBuffer = NULL;
static size_t expectedBufferSize = 0U;
static uint8_t invokeHeaderFieldCallback = 0U;
@@ -192,12 +192,13 @@ static unsigned int parserErrNo = 0;
/* ============================ Helper Functions ============================== */
/**
- * @brief Callback that is passed to the mock of http_parse_init function
+ * @brief Callback that is passed to the mock of llhttp_init function
* to set test expectations on input arguments sent by the HTTP API function under
* test.
*/
-void parserInitExpectationCb( http_parser * parser,
- enum http_parser_type type,
+void parserInitExpectationCb( llhttp_t * parser,
+ enum llhttp_type type,
+ const llhttp_settings_t * settings,
int cmock_num_calls )
{
/* Disable unused parameter warning. */
@@ -205,16 +206,19 @@ void parserInitExpectationCb( http_parser * parser,
TEST_ASSERT_NOT_NULL( parser );
pCapturedParser = parser;
+ TEST_ASSERT_EQUAL( pCapturedSettings, settings );
+ /* Set the settings member expected by calls to llhttp_execute(). */
+ parser->settings = ( llhttp_settings_t * ) settings;
TEST_ASSERT_EQUAL( HTTP_RESPONSE, type );
}
/**
- * @brief Callback that is passed to the mock of http_parse_settings_init function
+ * @brief Callback that is passed to the mock of llhttp_settings_init function
* to set test expectations on input arguments sent by the HTTP API function under
* test.
*/
-void parserSettingsInitExpectationCb( http_parser_settings * settings,
+void parserSettingsInitExpectationCb( llhttp_settings_t * settings,
int cmock_num_calls )
{
/* Disable unused parameter warning. */
@@ -225,53 +229,51 @@ void parserSettingsInitExpectationCb( http_parser_settings * settings,
}
/**
- * @brief Callback that is passed to the mock of http_parse_execute() function
+ * @brief Callback that is passed to the mock of llhttp_execute() function
* to set test expectations on input arguments, and inject behavior of invoking
- * http-parser callbacks depending on test-case specific configuration of the
+ * llhttp callbacks depending on test-case specific configuration of the
* function.
*/
-size_t parserExecuteExpectationsCb( http_parser * parser,
- const http_parser_settings * settings,
- const char * data,
- size_t len,
- int cmock_num_calls )
+llhttp_errno_t parserExecuteExpectationsCb( llhttp_t * parser,
+ const char * data,
+ size_t len,
+ int cmock_num_calls )
{
/* Disable unused parameter warning. */
( void ) cmock_num_calls;
- TEST_ASSERT_NOT_NULL( settings );
TEST_ASSERT_EQUAL( pCapturedParser, parser );
TEST_ASSERT_NOT_NULL( parser );
- TEST_ASSERT_EQUAL( pCapturedSettings, settings );
+ TEST_ASSERT_EQUAL( pCapturedSettings, parser->settings );
TEST_ASSERT_EQUAL( expectedBufferSize, len );
TEST_ASSERT_EQUAL( pExpectedBuffer, data );
if( invokeHeaderFieldCallback == 1U )
{
- TEST_ASSERT_EQUAL( HTTP_PARSER_CONTINUE_PARSING,
- settings->on_header_field( parser,
- pFieldLocToReturn,
- fieldLenToReturn ) );
+ TEST_ASSERT_EQUAL( LLHTTP_CONTINUE_PARSING,
+ ( ( llhttp_settings_t * ) ( parser->settings ) )->on_header_field( parser,
+ pFieldLocToReturn,
+ fieldLenToReturn ) );
}
if( invokeHeaderValueCallback == 1U )
{
TEST_ASSERT_EQUAL( expectedValCbRetVal,
- settings->on_header_value( parser,
- pValueLocToReturn,
- valueLenToReturn ) );
+ ( ( llhttp_settings_t * ) ( parser->settings ) )->on_header_value( parser,
+ pValueLocToReturn,
+ valueLenToReturn ) );
}
if( invokeHeaderCompleteCallback == 1U )
{
- TEST_ASSERT_EQUAL( HTTP_PARSER_STOP_PARSING,
- settings->on_headers_complete( parser ) );
+ TEST_ASSERT_EQUAL( LLHTTP_STOP_PARSING_NO_HEADER,
+ ( ( llhttp_settings_t * ) ( parser->settings ) )->on_headers_complete( parser ) );
}
/* Set the error value in the parser. */
- parser->http_errno = parserErrNo;
- return len;
+ parser->error = parserErrNo;
+ return parserErrNo;
}
/**
@@ -347,13 +349,14 @@ void setUp()
testResponse.pBuffer = ( uint8_t * ) &pTestResponse[ 0 ];
testResponse.bufferLen = strlen( pTestResponse );
- /* Configure the http_parser mocks with their callbacks. */
- http_parser_init_AddCallback( parserInitExpectationCb );
- http_parser_settings_init_AddCallback( parserSettingsInitExpectationCb );
- http_parser_execute_AddCallback( parserExecuteExpectationsCb );
+ /* Configure the llhttp mocks with their callbacks. */
+ llhttp_settings_init_AddCallback( parserSettingsInitExpectationCb );
+ llhttp_init_AddCallback( parserInitExpectationCb );
+ llhttp_execute_AddCallback( parserExecuteExpectationsCb );
- /* Ignore the calls to http_errno_description. */
- http_errno_description_IgnoreAndReturn( "Mocked HTTP Parser Status" );
+ /* Ignore the calls to llhttp_get_error_reason. */
+ llhttp_errno_name_IgnoreAndReturn( "Mocked HTTP Parser Status" );
+ llhttp_get_error_reason_IgnoreAndReturn( "Mocked HTTP Parser Status" );
}
/* Called after each test method. */
@@ -1299,21 +1302,21 @@ void test_Http_ReadHeader_Invalid_Params( void )
*/
void test_Http_ReadHeader_Header_Not_In_Response( void )
{
- /* Add expectations for http_parser dependencies. */
- http_parser_init_ExpectAnyArgs();
- http_parser_settings_init_ExpectAnyArgs();
+ /* Add expectations for llhttp dependencies. */
+ llhttp_settings_init_ExpectAnyArgs();
+ llhttp_init_ExpectAnyArgs();
- /* Configure the http_parser_execute mock. */
+ /* Configure the llhttp_execute mock. */
invokeHeaderFieldCallback = 1U;
invokeHeaderValueCallback = 1U;
pFieldLocToReturn = &pTestResponse[ headerFieldInRespLoc ];
fieldLenToReturn = headerFieldInRespLen;
pValueLocToReturn = &pTestResponse[ headerValInRespLoc ];
valueLenToReturn = headerValInRespLen;
- expectedValCbRetVal = HTTP_PARSER_CONTINUE_PARSING;
+ expectedValCbRetVal = LLHTTP_CONTINUE_PARSING;
invokeHeaderCompleteCallback = 1U;
parserErrNo = HPE_OK;
- http_parser_execute_ExpectAnyArgsAndReturn( strlen( pTestResponse ) );
+ llhttp_execute_ExpectAnyArgsAndReturn( HPE_OK );
/* Call the function under test. */
testResponse.bufferLen = strlen( pTestResponse );
@@ -1328,25 +1331,25 @@ void test_Http_ReadHeader_Header_Not_In_Response( void )
* Doing this allows us to take the branch where the actual contents
* of the fields are compared rather than just the length. */
setUp();
- /* Add expectations for http_parser dependencies. */
- http_parser_init_ExpectAnyArgs();
- http_parser_settings_init_ExpectAnyArgs();
+ /* Add expectations for llhttp dependencies. */
+ llhttp_settings_init_ExpectAnyArgs();
+ llhttp_init_ExpectAnyArgs();
/* Ensure that the header field does NOT match what we're searching. */
TEST_ASSERT_EQUAL( otherHeaderFieldInRespLen, HEADER_NOT_IN_BUFFER_LEN );
TEST_ASSERT_TRUE( memcmp( &pTestResponse[ otherHeaderFieldInRespLoc ],
HEADER_NOT_IN_BUFFER,
HEADER_NOT_IN_BUFFER_LEN ) != 0 );
- /* Configure the http_parser_execute mock. */
+ /* Configure the llhttp_execute mock. */
invokeHeaderFieldCallback = 1U;
invokeHeaderValueCallback = 1U;
pFieldLocToReturn = &pTestResponse[ otherHeaderFieldInRespLoc ];
fieldLenToReturn = otherHeaderFieldInRespLen;
pValueLocToReturn = &pTestResponse[ headerValInRespLoc ];
valueLenToReturn = headerValInRespLen;
- expectedValCbRetVal = HTTP_PARSER_CONTINUE_PARSING;
+ expectedValCbRetVal = LLHTTP_CONTINUE_PARSING;
invokeHeaderCompleteCallback = 1U;
parserErrNo = HPE_OK;
- http_parser_execute_ExpectAnyArgsAndReturn( strlen( pTestResponse ) );
+ llhttp_execute_ExpectAnyArgsAndReturn( HPE_OK );
/* Call the function under test. */
testResponse.bufferLen = strlen( pTestResponse );
@@ -1369,17 +1372,17 @@ void test_Http_ReadHeader_Invalid_Response_Only_Header_Field_Found()
"test-header0: test-value0\r\n"
"test-header1:";
- /* Add expectations for http_parser init dependencies. */
- http_parser_init_ExpectAnyArgs();
- http_parser_settings_init_ExpectAnyArgs();
+ /* Add expectations for llhttp init dependencies. */
+ llhttp_settings_init_ExpectAnyArgs();
+ llhttp_init_ExpectAnyArgs();
- /* Configure the http_parser_execute mock. */
+ /* Configure the llhttp_execute mock. */
pExpectedBuffer = pResponseWithoutValue;
expectedBufferSize = strlen( pResponseWithoutValue );
invokeHeaderFieldCallback = 1U;
pFieldLocToReturn = &pTestResponse[ headerFieldInRespLoc ];
fieldLenToReturn = headerFieldInRespLen;
- http_parser_execute_ExpectAnyArgsAndReturn( strlen( pResponseWithoutValue ) );
+ llhttp_execute_ExpectAnyArgsAndReturn( HPE_OK );
/* Call the function under test. */
testResponse.pBuffer = ( uint8_t * ) &pResponseWithoutValue[ 0 ];
@@ -1405,15 +1408,16 @@ void test_Http_ReadHeader_Invalid_Response_No_Headers_Complete_Ending()
tearDown();
- /* Add expectations for http_parser init dependencies. */
- http_parser_init_ExpectAnyArgs();
- http_parser_settings_init_ExpectAnyArgs();
+ /* Add expectations for llhttp init dependencies. */
+ llhttp_settings_init_ExpectAnyArgs();
+ llhttp_init_ExpectAnyArgs();
- /* Configure the http_parser_execute mock. */
+ /* Configure the llhttp_execute mock. */
pExpectedBuffer = &pResponseWithoutHeaders[ 0 ];
expectedBufferSize = strlen( pResponseWithoutHeaders );
- parserErrNo = HPE_UNKNOWN;
- http_parser_execute_ExpectAnyArgsAndReturn( strlen( pResponseWithoutHeaders ) );
+ /* Use -1 for an unknown error. */
+ parserErrNo = -1;
+ llhttp_execute_ExpectAnyArgsAndReturn( -1 );
/* Call the function under test. */
testResponse.pBuffer = ( uint8_t * ) &pResponseWithoutHeaders[ 0 ];
testResponse.bufferLen = strlen( pResponseWithoutHeaders );
@@ -1426,26 +1430,26 @@ void test_Http_ReadHeader_Invalid_Response_No_Headers_Complete_Ending()
}
/**
- * @brief Test when the header is present in response but http_parser_execute()
- * does not set the expected errno value (of "CB_header_value")
+ * @brief Test when the header is present in response but llhttp_execute()
+ * does not set the expected errno value (of "HPE_USER")
* due to an internal error.
*/
void test_Http_ReadHeader_With_HttpParser_Internal_Error()
{
- /* Add expectations for http_parser init dependencies. */
- http_parser_init_ExpectAnyArgs();
- http_parser_settings_init_ExpectAnyArgs();
+ /* Add expectations for llhttp init dependencies. */
+ llhttp_settings_init_ExpectAnyArgs();
+ llhttp_init_ExpectAnyArgs();
- /* Configure the http_parser_execute mock. */
+ /* Configure the llhttp_execute mock. */
invokeHeaderFieldCallback = 1U;
invokeHeaderValueCallback = 1U;
pFieldLocToReturn = &pTestResponse[ headerFieldInRespLoc ];
fieldLenToReturn = headerFieldInRespLen;
pValueLocToReturn = &pTestResponse[ headerValInRespLoc ];
valueLenToReturn = headerValInRespLen;
- expectedValCbRetVal = HTTP_PARSER_STOP_PARSING;
- parserErrNo = HPE_CB_chunk_complete;
- http_parser_execute_ExpectAnyArgsAndReturn( strlen( pTestResponse ) );
+ expectedValCbRetVal = LLHTTP_STOP_PARSING;
+ parserErrNo = HPE_CB_CHUNK_COMPLETE;
+ llhttp_execute_ExpectAnyArgsAndReturn( HPE_CB_CHUNK_COMPLETE );
/* Call the function under test. */
retCode = HTTPClient_ReadHeader( &testResponse,
@@ -1461,20 +1465,21 @@ void test_Http_ReadHeader_With_HttpParser_Internal_Error()
*/
void test_Http_ReadHeader_Happy_Path()
{
- /* Add expectations for http_parser init dependencies. */
- http_parser_init_ExpectAnyArgs();
- http_parser_settings_init_ExpectAnyArgs();
+ /* Add expectations for llhttp init dependencies. */
+ llhttp_settings_init_ExpectAnyArgs();
+ llhttp_init_ExpectAnyArgs();
- /* Configure the http_parser_execute mock. */
- expectedValCbRetVal = HTTP_PARSER_STOP_PARSING;
+ /* Configure the llhttp_execute mock. */
+ expectedValCbRetVal = LLHTTP_STOP_PARSING;
pFieldLocToReturn = &pTestResponse[ headerFieldInRespLoc ];
fieldLenToReturn = headerFieldInRespLen;
pValueLocToReturn = &pTestResponse[ headerValInRespLoc ];
valueLenToReturn = headerValInRespLen;
invokeHeaderFieldCallback = 1U;
invokeHeaderValueCallback = 1U;
- parserErrNo = HPE_CB_header_value;
- http_parser_execute_ExpectAnyArgsAndReturn( strlen( pTestResponse ) );
+ /* Use HPE_USER to indicate the header value callback returns an error. */
+ parserErrNo = HPE_USER;
+ llhttp_execute_ExpectAnyArgsAndReturn( HPE_USER );
/* Call the function under test. */
retCode = HTTPClient_ReadHeader( &testResponse,
@@ -1493,22 +1498,23 @@ void test_Http_ReadHeader_Happy_Path()
*/
void test_Http_ReadHeader_EmptyHeaderValue()
{
- /* Add expectations for http_parser init dependencies. */
- http_parser_init_ExpectAnyArgs();
- http_parser_settings_init_ExpectAnyArgs();
+ /* Add expectations for llhttp init dependencies. */
+ llhttp_settings_init_ExpectAnyArgs();
+ llhttp_init_ExpectAnyArgs();
- /* Configure the http_parser_execute mock. */
- expectedValCbRetVal = HTTP_PARSER_STOP_PARSING;
+ /* Configure the llhttp_execute mock. */
+ expectedValCbRetVal = LLHTTP_STOP_PARSING;
pFieldLocToReturn = &pTestResponseEmptyValue[ headerFieldInRespLoc ];
fieldLenToReturn = headerFieldInRespLen;
/* Add two characters past the empty value to point to the next field. */
pValueLocToReturn = &pTestResponseEmptyValue[ headerValInRespLoc + HTTP_HEADER_LINE_SEPARATOR_LEN ];
- /* http-parser will pass in a value of zero for an empty value. */
+ /* llhttp will pass in a value of zero for an empty value. */
valueLenToReturn = 0U;
invokeHeaderFieldCallback = 1U;
invokeHeaderValueCallback = 1U;
- parserErrNo = HPE_CB_header_value;
- http_parser_execute_ExpectAnyArgsAndReturn( strlen( pTestResponse ) );
+ /* Use HPE_USER to indicate the header value callback returns an error. */
+ parserErrNo = HPE_USER;
+ llhttp_execute_ExpectAnyArgsAndReturn( HPE_USER );
/* Call the function under test. */
retCode = HTTPClient_ReadHeader( &testResponse,
diff --git a/tools/cmock/project.yml b/tools/cmock/project.yml
index 8a90416b..1c01520f 100644
--- a/tools/cmock/project.yml
+++ b/tools/cmock/project.yml
@@ -24,3 +24,5 @@
:treat_externs: :exclude # Now the extern-ed functions will be mocked.
:weak: __attribute__((weak))
:treat_externs: :include
+ :strippables:
+ - LLHTTP_EXPORT