Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit06e384a

Browse files
Enable llhttp for HTTP parsing
Fixes:#6074We now try to use llhttp by default, falling back to http-parserif the former is not available.As a last resort, we use the bundled http-parser.Co-authored-by: Sergio Correia <scorreia@redhat.com>Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>Signed-off-by: Sergio Correia <scorreia@redhat.com>
1 parent00eb347 commit06e384a

File tree

5 files changed

+169
-38
lines changed

5 files changed

+169
-38
lines changed

‎cmake/FindLLHTTP.cmake

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# - Try to find llhttp
2+
#
3+
# Defines the following variables:
4+
#
5+
# LLHTTP_FOUND - system has llhttp
6+
# LLHTTP_INCLUDE_DIR - the llhttp include directory
7+
# LLHTTP_LIBRARIES - Link these to use llhttp
8+
# LLHTTP_VERSION_MAJOR - major version
9+
# LLHTTP_VERSION_MINOR - minor version
10+
# LLHTTP_VERSION_STRING - the version of llhttp found
11+
12+
# Find the header and library
13+
find_path(LLHTTP_INCLUDE_DIRNAMESllhttp.h)
14+
find_library(LLHTTP_LIBRARYNAMESllhttplibllhttp)
15+
16+
# Found the header, read version
17+
if(LLHTTP_INCLUDE_DIRANDEXISTS"${LLHTTP_INCLUDE_DIR}/llhttp.h")
18+
file(READ"${LLHTTP_INCLUDE_DIR}/llhttp.h"LLHTTP_H)
19+
if(LLHTTP_H)
20+
string(REGEXREPLACE".*#define[\t ]+LLHTTP_VERSION_MAJOR[\t ]+([0-9]+).*""\\1"LLHTTP_VERSION_MAJOR"${LLHTTP_H}")
21+
string(REGEXREPLACE".*#define[\t ]+LLHTTP_VERSION_MINOR[\t ]+([0-9]+).*""\\1"LLHTTP_VERSION_MINOR"${LLHTTP_H}")
22+
set(LLHTTP_VERSION_STRING"${LLHTTP_VERSION_MAJOR}.${LLHTTP_VERSION_MINOR}")
23+
endif()
24+
unset(LLHTTP_H)
25+
endif()
26+
27+
# Handle the QUIETLY and REQUIRED arguments and set LLHTTP_FOUND
28+
# to TRUE if all listed variables are TRUE
29+
include(FindPackageHandleStandardArgs)
30+
find_package_handle_standard_args(LLHTTPREQUIRED_VARSLLHTTP_INCLUDE_DIRLLHTTP_LIBRARY)
31+
32+
# Hide advanced variables
33+
mark_as_advanced(LLHTTP_INCLUDE_DIRLLHTTP_LIBRARY)
34+
35+
# Set standard variables
36+
if(LLHTTP_FOUND)
37+
set(LLHTTP_LIBRARIES${LLHTTP_LIBRARY})
38+
set(LLHTTP_INCLUDE_DIRS${LLHTTP_INCLUDE_DIR})
39+
endif()

‎cmake/SelectHTTPParser.cmake

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,39 @@
11
# Optional external dependency: http-parser
2-
if(USE_HTTP_PARSERSTREQUAL"system")
3-
find_package(HTTPParser)
2+
if(USE_HTTP_PARSERSTREQUAL"builtin")
3+
message(STATUS"support for bundled (legacy) http-parser explicitly requested")
44

5-
if(HTTP_PARSER_FOUNDANDHTTP_PARSER_VERSION_MAJOREQUAL2)
6-
list(APPENDLIBGIT2_SYSTEM_INCLUDES${HTTP_PARSER_INCLUDE_DIRS})
7-
list(APPENDLIBGIT2_SYSTEM_LIBS${HTTP_PARSER_LIBRARIES})
8-
list(APPENDLIBGIT2_PC_LIBS"-lhttp_parser")
9-
add_feature_info(http-parserON"http-parser support (system)")
10-
else()
11-
message(FATAL_ERROR"http-parser support was requested but not found")
12-
endif()
13-
else()
14-
message(STATUS"http-parser version 2 was not found or disabled; using bundled 3rd-party sources.")
155
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/http-parser""${PROJECT_BINARY_DIR}/deps/http-parser")
166
list(APPENDLIBGIT2_DEPENDENCY_INCLUDES"${PROJECT_SOURCE_DIR}/deps/http-parser")
177
list(APPENDLIBGIT2_DEPENDENCY_OBJECTS"$<TARGET_OBJECTS:http-parser>")
188
add_feature_info(http-parserON"http-parser support (bundled)")
9+
else()
10+
# By default, try to use system LLHTTP. Fall back to
11+
# system http-parser, and even to bundled http-parser
12+
# as a last resort.
13+
find_package(LLHTTP)
14+
15+
if(LLHTTP_FOUNDANDLLHTTP_VERSION_MAJOREQUAL9)
16+
add_compile_definitions(USE_LLHTTP)
17+
list(APPENDLIBGIT2_SYSTEM_INCLUDES${LLHTTP_INCLUDE_DIRS})
18+
list(APPENDLIBGIT2_SYSTEM_LIBS${LLHTTP_LIBRARIES})
19+
list(APPENDLIBGIT2_PC_LIBS"-lllhttp")
20+
add_feature_info(llhttpON"llhttp support (system)")
21+
else()
22+
message(STATUS"llhttp support was requested but not found; checking (legacy) http-parser support")
23+
find_package(HTTPParser)
24+
25+
if(HTTP_PARSER_FOUNDANDHTTP_PARSER_VERSION_MAJOREQUAL2)
26+
list(APPENDLIBGIT2_SYSTEM_INCLUDES${HTTP_PARSER_INCLUDE_DIRS})
27+
list(APPENDLIBGIT2_SYSTEM_LIBS${HTTP_PARSER_LIBRARIES})
28+
list(APPENDLIBGIT2_PC_LIBS"-lhttp_parser")
29+
add_feature_info(http-parserON"http-parser support (system)")
30+
else()
31+
message(STATUS"neither llhttp nor http-parser support was found; proceeding with bundled (legacy) http-parser")
32+
33+
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/http-parser""${PROJECT_BINARY_DIR}/deps/http-parser")
34+
list(APPENDLIBGIT2_DEPENDENCY_INCLUDES"${PROJECT_SOURCE_DIR}/deps/http-parser")
35+
list(APPENDLIBGIT2_DEPENDENCY_OBJECTS"$<TARGET_OBJECTS:http-parser>")
36+
add_feature_info(http-parserON"http-parser support (bundled)")
37+
endif()
38+
endif()
1939
endif()

‎src/libgit2/transports/http.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
#ifndefGIT_WINHTTP
1111

12-
#include"http_parser.h"
1312
#include"net.h"
1413
#include"remote.h"
1514
#include"smart.h"

‎src/libgit2/transports/httpclient.c

Lines changed: 98 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,32 @@
77

88
#include"common.h"
99
#include"git2.h"
10-
#include"http_parser.h"
10+
11+
#ifdefUSE_LLHTTP
12+
#include<llhttp.h>
13+
typedefllhttp_settings_thttp_settings_t;
14+
typedefllhttp_thttp_parser_t;
15+
GIT_INLINE(http_settings_t*)http_client_parser_settings(void);
16+
#definegit_http_parser_init(parser) llhttp_init(parser, HTTP_RESPONSE, http_client_parser_settings())
17+
#definegit_http_parser_pause(parser) llhttp_pause(parser)
18+
#definegit_http_parser_resume(parser) llhttp_resume(parser)
19+
#definegit_http_parser_errno(parser) parser.error
20+
#definegit_http_should_keep_alive(parser) llhttp_should_keep_alive(parser)
21+
#definegit_http_errno_description(parser,errno) llhttp_get_error_reason(parser)
22+
#else
23+
#include<http_parser.h>
24+
/* Legacy http-parser. */
25+
typedefhttp_parser_settingshttp_settings_t;
26+
typedefstructhttp_parserhttp_parser_t;
27+
GIT_INLINE(http_settings_t*)http_client_parser_settings(void);
28+
#definegit_http_parser_init(parser) http_parser_init(parser, HTTP_RESPONSE)
29+
#definegit_http_parser_pause(parser) http_parser_pause(parser, 1)
30+
#definegit_http_parser_resume(parser) http_parser_pause(parser, 0)
31+
#definegit_http_parser_errno(parser) parser.http_errno
32+
#definegit_http_should_keep_alive(parser) http_should_keep_alive(parser)
33+
#definegit_http_errno_description(parser,errno) http_errno_description(errno)
34+
#endif/* USE_LLHTTP */
35+
1136
#include"vector.h"
1237
#include"trace.h"
1338
#include"httpclient.h"
@@ -108,7 +133,7 @@ struct git_http_client {
108133
git_http_server_tcurrent_server;
109134
http_client_statestate;
110135

111-
http_parserparser;
136+
http_parser_tparser;
112137

113138
git_http_serverserver;
114139
git_http_serverproxy;
@@ -154,7 +179,7 @@ void git_http_response_dispose(git_http_response *response)
154179
memset(response,0,sizeof(git_http_response));
155180
}
156181

157-
staticinton_header_complete(http_parser*parser)
182+
staticinton_header_complete(http_parser_t*parser)
158183
{
159184
http_parser_context*ctx= (http_parser_context*)parser->data;
160185
git_http_client*client=ctx->client;
@@ -219,7 +244,7 @@ static int on_header_complete(http_parser *parser)
219244
return0;
220245
}
221246

222-
staticinton_header_field(http_parser*parser,constchar*str,size_tlen)
247+
staticinton_header_field(http_parser_t*parser,constchar*str,size_tlen)
223248
{
224249
http_parser_context*ctx= (http_parser_context*)parser->data;
225250

@@ -254,7 +279,7 @@ static int on_header_field(http_parser *parser, const char *str, size_t len)
254279
return0;
255280
}
256281

257-
staticinton_header_value(http_parser*parser,constchar*str,size_tlen)
282+
staticinton_header_value(http_parser_t*parser,constchar*str,size_tlen)
258283
{
259284
http_parser_context*ctx= (http_parser_context*)parser->data;
260285

@@ -342,7 +367,7 @@ static int resend_needed(git_http_client *client, git_http_response *response)
342367
return0;
343368
}
344369

345-
staticinton_headers_complete(http_parser*parser)
370+
staticinton_headers_complete(http_parser_t*parser)
346371
{
347372
http_parser_context*ctx= (http_parser_context*)parser->data;
348373

@@ -365,7 +390,7 @@ static int on_headers_complete(http_parser *parser)
365390
}
366391

367392
ctx->response->status=parser->status_code;
368-
ctx->client->keepalive=http_should_keep_alive(parser);
393+
ctx->client->keepalive=git_http_should_keep_alive(parser);
369394

370395
/* Prepare for authentication */
371396
collect_authinfo(&ctx->response->server_auth_schemetypes,
@@ -378,18 +403,28 @@ static int on_headers_complete(http_parser *parser)
378403
ctx->response->resend_credentials=resend_needed(ctx->client,
379404
ctx->response);
380405

381-
/* Stop parsing. */
382-
http_parser_pause(parser,1);
406+
#ifndefUSE_LLHTTP
407+
/* Stop parsing. llhttp documentation says about llhttp_pause():
408+
* "Do not call this from user callbacks! User callbacks must
409+
* return HPE_PAUSED if pausing is required", so that's what
410+
* we will do, and call git_http_parser_pause() only for
411+
* http-parser. */
412+
git_http_parser_pause(parser);
413+
#endif
383414

384415
if (ctx->response->content_type||ctx->response->chunked)
385416
ctx->client->state=READING_BODY;
386417
else
387418
ctx->client->state=DONE;
388419

420+
#ifdefUSE_LLHTTP
421+
returnHPE_PAUSED;
422+
#else
389423
return0;
424+
#endif
390425
}
391426

392-
staticinton_body(http_parser*parser,constchar*buf,size_tlen)
427+
staticinton_body(http_parser_t*parser,constchar*buf,size_tlen)
393428
{
394429
http_parser_context*ctx= (http_parser_context*)parser->data;
395430
size_tmax_len;
@@ -411,7 +446,7 @@ static int on_body(http_parser *parser, const char *buf, size_t len)
411446
return0;
412447
}
413448

414-
staticinton_message_complete(http_parser*parser)
449+
staticinton_message_complete(http_parser_t*parser)
415450
{
416451
http_parser_context*ctx= (http_parser_context*)parser->data;
417452

@@ -878,7 +913,7 @@ GIT_INLINE(int) server_setup_from_url(
878913

879914
staticvoidreset_parser(git_http_client*client)
880915
{
881-
http_parser_init(&client->parser,HTTP_RESPONSE);
916+
git_http_parser_init(&client->parser);
882917
}
883918

884919
staticintsetup_hosts(
@@ -1122,9 +1157,46 @@ GIT_INLINE(int) client_read(git_http_client *client)
11221157
}
11231158

11241159
staticboolparser_settings_initialized;
1125-
statichttp_parser_settingsparser_settings;
1160+
statichttp_settings_tparser_settings;
1161+
1162+
staticsize_tgit_http_parser_execute(http_parser_t*parser,constchar*data,size_tlen)
1163+
{
1164+
#ifdefUSE_LLHTTP
1165+
llhttp_errno_terror;
1166+
size_tparsed_len;
1167+
1168+
/*
1169+
* Unlike http_parser, which returns the number of parsed
1170+
* bytes in the _execute() call, llhttp returns an error
1171+
* code.
1172+
*/
1173+
1174+
if (data==NULL||len==0) {
1175+
error=llhttp_finish(parser);
1176+
}else {
1177+
error=llhttp_execute(parser,data,len);
1178+
}
1179+
1180+
parsed_len=len;
1181+
/*
1182+
* Adjust number of parsed bytes in case of error.
1183+
*/
1184+
if (error!=HPE_OK) {
1185+
parsed_len=llhttp_get_error_pos(parser)-data;
1186+
1187+
/* This isn't a real pause, just a way to stop parsing early. */
1188+
if (error==HPE_PAUSED_UPGRADE) {
1189+
llhttp_resume_after_upgrade(parser);
1190+
}
1191+
}
1192+
1193+
returnparsed_len;
1194+
#else
1195+
returnhttp_parser_execute(parser,http_client_parser_settings(),data,len);
1196+
#endif
1197+
}
11261198

1127-
GIT_INLINE(http_parser_settings*)http_client_parser_settings(void)
1199+
GIT_INLINE(http_settings_t*)http_client_parser_settings(void)
11281200
{
11291201
if (!parser_settings_initialized) {
11301202
parser_settings.on_header_field=on_header_field;
@@ -1141,7 +1213,7 @@ GIT_INLINE(http_parser_settings *) http_client_parser_settings(void)
11411213

11421214
GIT_INLINE(int)client_read_and_parse(git_http_client*client)
11431215
{
1144-
http_parser*parser=&client->parser;
1216+
http_parser_t*parser=&client->parser;
11451217
http_parser_context*ctx= (http_parser_context*)parser->data;
11461218
unsignedcharhttp_errno;
11471219
intread_len;
@@ -1155,11 +1227,10 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
11551227
if (!client->read_buf.size&& (read_len=client_read(client))<0)
11561228
returnread_len;
11571229

1158-
parsed_len=http_parser_execute(parser,
1159-
http_client_parser_settings(),
1230+
parsed_len=git_http_parser_execute(parser,
11601231
client->read_buf.ptr,
11611232
client->read_buf.size);
1162-
http_errno=client->parser.http_errno;
1233+
http_errno=git_http_parser_errno(client->parser);
11631234

11641235
if (parsed_len>INT_MAX) {
11651236
git_error_set(GIT_ERROR_HTTP,"unexpectedly large parse");
@@ -1179,33 +1250,36 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
11791250
* where the server gives you a 100 and 200 simultaneously.)
11801251
*/
11811252
if (http_errno==HPE_PAUSED) {
1253+
#ifndefUSE_LLHTTP
11821254
/*
11831255
* http-parser has a "feature" where it will not deliver the
11841256
* final byte when paused in a callback. Consume that byte.
11851257
* https://github.com/nodejs/http-parser/issues/97
11861258
*/
11871259
GIT_ASSERT(client->read_buf.size>parsed_len);
11881260

1189-
http_parser_pause(parser,0);
1261+
#endif
1262+
git_http_parser_resume(parser);
11901263

1191-
parsed_len+=http_parser_execute(parser,
1192-
http_client_parser_settings(),
1264+
#ifndefUSE_LLHTTP
1265+
parsed_len+=git_http_parser_execute(parser,
11931266
client->read_buf.ptr+parsed_len,
11941267
1);
1268+
#endif
11951269
}
11961270

11971271
/* Most failures will be reported in http_errno */
1198-
elseif (parser->http_errno!=HPE_OK) {
1272+
elseif (git_http_parser_errno(client->parser)!=HPE_OK) {
11991273
git_error_set(GIT_ERROR_HTTP,"http parser error: %s",
1200-
http_errno_description(http_errno));
1274+
git_http_errno_description(parser,http_errno));
12011275
return-1;
12021276
}
12031277

12041278
/* Otherwise we should have consumed the entire buffer. */
12051279
elseif (parsed_len!=client->read_buf.size) {
12061280
git_error_set(GIT_ERROR_HTTP,
12071281
"http parser did not consume entire buffer: %s",
1208-
http_errno_description(http_errno));
1282+
git_http_errno_description(parser,http_errno));
12091283
return-1;
12101284
}
12111285

‎src/util/net.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
#include"posix.h"
1313
#include"str.h"
14-
#include"http_parser.h"
1514
#include"runtime.h"
1615

1716
#defineDEFAULT_PORT_HTTP "80"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp