diff --git a/src/3rdparty/llhttp/api.c b/src/3rdparty/llhttp/api.c index 0f9b5677..8a4bdd26 100644 --- a/src/3rdparty/llhttp/api.c +++ b/src/3rdparty/llhttp/api.c @@ -24,6 +24,70 @@ void llhttp_init(llhttp_t* parser, llhttp_type_t type, } +#if defined(__wasm__) + +extern int wasm_on_message_begin(llhttp_t * p); +extern int wasm_on_url(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_status(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_headers_complete(llhttp_t * p); +extern int wasm_on_body(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_message_complete(llhttp_t * p); + +const llhttp_settings_t wasm_settings = { + wasm_on_message_begin, + wasm_on_url, + wasm_on_status, + wasm_on_header_field, + wasm_on_header_value, + wasm_on_headers_complete, + wasm_on_body, + wasm_on_message_complete, + NULL, + NULL, +}; + + +llhttp_t* llhttp_alloc(llhttp_type_t type) { + llhttp_t* parser = malloc(sizeof(llhttp_t)); + llhttp_init(parser, type, &wasm_settings); + return parser; +} + +void llhttp_free(llhttp_t* parser) { + free(parser); +} + +/* Some getters required to get stuff from the parser */ + +uint8_t llhttp_get_type(llhttp_t* parser) { + return parser->type; +} + +uint8_t llhttp_get_http_major(llhttp_t* parser) { + return parser->http_major; +} + +uint8_t llhttp_get_http_minor(llhttp_t* parser) { + return parser->http_minor; +} + +uint8_t llhttp_get_method(llhttp_t* parser) { + return parser->method; +} + +int llhttp_get_status_code(llhttp_t* parser) { + return parser->status_code; +} + +uint8_t llhttp_get_upgrade(llhttp_t* parser) { + return parser->upgrade; +} + +#endif // defined(__wasm__) + + void llhttp_reset(llhttp_t* parser) { llhttp_type_t type = parser->type; const llhttp_settings_t* settings = parser->settings; @@ -150,6 +214,7 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) { } } + void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) { if (enabled) { parser->lenient_flags |= LENIENT_CHUNKED_LENGTH; @@ -159,6 +224,14 @@ void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) { } +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_KEEP_ALIVE; + } else { + parser->lenient_flags &= ~LENIENT_KEEP_ALIVE; + } +} + /* Callbacks */ diff --git a/src/3rdparty/llhttp/api.h b/src/3rdparty/llhttp/api.h index f62c57fe..7fdbfc10 100644 --- a/src/3rdparty/llhttp/api.h +++ b/src/3rdparty/llhttp/api.h @@ -5,6 +5,12 @@ extern "C" { #endif #include +#if defined(__wasm__) +#define LLHTTP_EXPORT __attribute__((visibility("default"))) +#else +#define LLHTTP_EXPORT +#endif + typedef llhttp__internal_t llhttp_t; typedef struct llhttp_settings_s llhttp_settings_t; @@ -55,15 +61,46 @@ struct llhttp_settings_s { * the `parser` here. In practice, `settings` has to be either a static * variable or be allocated with `malloc`, `new`, etc. */ +LLHTTP_EXPORT void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings); +#if defined(__wasm__) + +LLHTTP_EXPORT +llhttp_t* llhttp_alloc(llhttp_type_t type); + +LLHTTP_EXPORT +void llhttp_free(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_type(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_major(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_minor(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_method(llhttp_t* parser); + +LLHTTP_EXPORT +int llhttp_get_status_code(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_upgrade(llhttp_t* parser); + +#endif // defined(__wasm__) + /* Reset an already initialized parser back to the start state, preserving the * existing parser type, callback settings, user data, and lenient flags. */ +LLHTTP_EXPORT void llhttp_reset(llhttp_t* parser); /* Initialize the settings object */ +LLHTTP_EXPORT void llhttp_settings_init(llhttp_settings_t* settings); /* Parse full or partial request/response, invoking user callbacks along the @@ -82,6 +119,7 @@ void llhttp_settings_init(llhttp_settings_t* settings); * to return the same error upon each successive call up until `llhttp_init()` * is called. */ +LLHTTP_EXPORT llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); /* This method should be called when the other side has no further bytes to @@ -92,16 +130,19 @@ llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); * connection. This method will invoke `on_message_complete()` callback if the * request was terminated safely. Otherwise a error code would be returned. */ +LLHTTP_EXPORT llhttp_errno_t llhttp_finish(llhttp_t* parser); /* Returns `1` if the incoming message is parsed until the last byte, and has * to be completed by calling `llhttp_finish()` on EOF */ +LLHTTP_EXPORT int llhttp_message_needs_eof(const llhttp_t* parser); /* Returns `1` if there might be any other messages following the last that was * successfully parsed. */ +LLHTTP_EXPORT int llhttp_should_keep_alive(const llhttp_t* parser); /* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set @@ -110,6 +151,7 @@ int llhttp_should_keep_alive(const llhttp_t* parser); * Important: do not call this from user callbacks! User callbacks must return * `HPE_PAUSED` if pausing is required. */ +LLHTTP_EXPORT void llhttp_pause(llhttp_t* parser); /* Might be called to resume the execution after the pause in user's callback. @@ -117,6 +159,7 @@ void llhttp_pause(llhttp_t* parser); * * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. */ +LLHTTP_EXPORT void llhttp_resume(llhttp_t* parser); /* Might be called to resume the execution after the pause in user's callback. @@ -124,9 +167,11 @@ void llhttp_resume(llhttp_t* parser); * * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` */ +LLHTTP_EXPORT void llhttp_resume_after_upgrade(llhttp_t* parser); /* Returns the latest return error */ +LLHTTP_EXPORT llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); /* Returns the verbal explanation of the latest returned error. @@ -134,6 +179,7 @@ llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); * Note: User callback should set error reason when returning the error. See * `llhttp_set_error_reason()` for details. */ +LLHTTP_EXPORT const char* llhttp_get_error_reason(const llhttp_t* parser); /* Assign verbal description to the returned error. Must be called in user @@ -141,6 +187,7 @@ const char* llhttp_get_error_reason(const llhttp_t* parser); * * Note: `HPE_USER` error code might be useful in user callbacks. */ +LLHTTP_EXPORT void llhttp_set_error_reason(llhttp_t* parser, const char* reason); /* Returns the pointer to the last parsed byte before the returned error. The @@ -148,12 +195,15 @@ void llhttp_set_error_reason(llhttp_t* parser, const char* reason); * * Note: this method might be useful for counting the number of parsed bytes. */ +LLHTTP_EXPORT const char* llhttp_get_error_pos(const llhttp_t* parser); /* Returns textual name of error code */ +LLHTTP_EXPORT const char* llhttp_errno_name(llhttp_errno_t err); /* Returns textual name of HTTP method */ +LLHTTP_EXPORT const char* llhttp_method_name(llhttp_method_t method); @@ -166,6 +216,7 @@ const char* llhttp_method_name(llhttp_method_t method); * * **(USE AT YOUR OWN RISK)** */ +LLHTTP_EXPORT void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); @@ -179,8 +230,23 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); * * **(USE AT YOUR OWN RISK)** */ +LLHTTP_EXPORT void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0 + * requests responses. + * + * Normally `llhttp` would error on (in strict mode) or discard (in loose mode) + * the HTTP request/response after the request/response with `Connection: close` + * and `Content-Length`. This is important to prevent cache poisoning attacks, + * but might interact badly with outdated and insecure clients. With this flag + * the extra request/response will be parsed normally. + * + * **(USE AT YOUR OWN RISK)** + */ +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/3rdparty/llhttp/llhttp.c b/src/3rdparty/llhttp/llhttp.c index 33ddcb29..a8efce10 100644 --- a/src/3rdparty/llhttp/llhttp.c +++ b/src/3rdparty/llhttp/llhttp.c @@ -627,6 +627,13 @@ int llhttp__internal__c_update_finish_1( return 0; } +int llhttp__internal__c_test_lenient_flags( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 4) == 4; +} + int llhttp__internal__c_test_flags_1( llhttp__internal_t* state, const unsigned char* p, @@ -634,7 +641,7 @@ int llhttp__internal__c_test_flags_1( return (state->flags & 544) == 544; } -int llhttp__internal__c_test_lenient_flags( +int llhttp__internal__c_test_lenient_flags_1( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -802,7 +809,7 @@ int llhttp__internal__c_update_header_state_2( return 0; } -int llhttp__internal__c_test_lenient_flags_1( +int llhttp__internal__c_test_lenient_flags_2( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -1661,7 +1668,7 @@ static llparse_state_t llhttp__internal__run( goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_2; } default: { - goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_2; } } /* UNREACHABLE */; @@ -5733,10 +5740,20 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } + s_n_llhttp__internal__n_invoke_test_lenient_flags: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_update_finish_2; + default: + goto s_n_llhttp__internal__n_closed; + } + /* UNREACHABLE */; + abort(); + } s_n_llhttp__internal__n_invoke_update_finish_1: { switch (llhttp__internal__c_update_finish_1(state, p, endp)) { default: - goto s_n_llhttp__internal__n_closed; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags; } /* UNREACHABLE */; abort(); @@ -6098,8 +6115,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_test_lenient_flags: { - switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { case 0: goto s_n_llhttp__internal__n_error_15; default: @@ -6111,7 +6128,7 @@ static llparse_state_t llhttp__internal__run( s_n_llhttp__internal__n_invoke_test_flags_1: { switch (llhttp__internal__c_test_flags_1(state, p, endp)) { case 1: - goto s_n_llhttp__internal__n_invoke_test_lenient_flags; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; default: goto s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete; } @@ -6365,8 +6382,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { - switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + s_n_llhttp__internal__n_invoke_test_lenient_flags_2: { + switch (llhttp__internal__c_test_lenient_flags_2(state, p, endp)) { case 1: goto s_n_llhttp__internal__n_header_value_lenient; default: @@ -6727,7 +6744,7 @@ static llparse_state_t llhttp__internal__run( abort(); } s_n_llhttp__internal__n_error_29: { - state->error = 0x16; + state->error = 0x17; state->reason = "Pause on PRI/Upgrade"; state->error_pos = (const char*) p; state->_current = (void*) (intptr_t) s_error; @@ -7906,6 +7923,7 @@ reset: enum llparse_state_e { s_error, + s_n_llhttp__internal__n_closed, s_n_llhttp__internal__n_invoke_llhttp__after_message_complete, s_n_llhttp__internal__n_pause_1, s_n_llhttp__internal__n_invoke_is_equal_upgrade, @@ -8199,6 +8217,13 @@ int llhttp__internal__c_update_finish_1( return 0; } +int llhttp__internal__c_test_lenient_flags( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 4) == 4; +} + int llhttp__internal__c_test_flags_1( llhttp__internal_t* state, const unsigned char* p, @@ -8206,7 +8231,7 @@ int llhttp__internal__c_test_flags_1( return (state->flags & 544) == 544; } -int llhttp__internal__c_test_lenient_flags( +int llhttp__internal__c_test_lenient_flags_1( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -8278,7 +8303,7 @@ int llhttp__internal__c_or_flags( return 0; } -int llhttp__internal__c_update_finish_2( +int llhttp__internal__c_update_finish_3( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -8374,7 +8399,7 @@ int llhttp__internal__c_update_header_state_2( return 0; } -int llhttp__internal__c_test_lenient_flags_1( +int llhttp__internal__c_test_lenient_flags_2( llhttp__internal_t* state, const unsigned char* p, const unsigned char* endp) { @@ -8574,9 +8599,21 @@ static llparse_state_t llhttp__internal__run( const unsigned char* endp) { int match; switch ((llparse_state_t) (intptr_t) state->_current) { + case s_n_llhttp__internal__n_closed: + s_n_llhttp__internal__n_closed: { + if (p == endp) { + return s_n_llhttp__internal__n_closed; + } + p++; + goto s_n_llhttp__internal__n_closed; + /* UNREACHABLE */; + abort(); + } case s_n_llhttp__internal__n_invoke_llhttp__after_message_complete: s_n_llhttp__internal__n_invoke_llhttp__after_message_complete: { switch (llhttp__after_message_complete(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_update_finish_2; default: goto s_n_llhttp__internal__n_invoke_update_finish_1; } @@ -9045,7 +9082,7 @@ static llparse_state_t llhttp__internal__run( case 3: goto s_n_llhttp__internal__n_span_start_llhttp__on_body_1; case 4: - goto s_n_llhttp__internal__n_invoke_update_finish_2; + goto s_n_llhttp__internal__n_invoke_update_finish_3; case 5: goto s_n_llhttp__internal__n_error_10; default: @@ -9184,7 +9221,7 @@ static llparse_state_t llhttp__internal__run( goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_2; } default: { - goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_2; } } /* UNREACHABLE */; @@ -13077,7 +13114,7 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_update_finish_1: { + s_n_llhttp__internal__n_invoke_update_finish_2: { switch (llhttp__internal__c_update_finish_1(state, p, endp)) { default: goto s_n_llhttp__internal__n_start; @@ -13085,6 +13122,24 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } + s_n_llhttp__internal__n_invoke_test_lenient_flags: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_update_finish_2; + default: + goto s_n_llhttp__internal__n_closed; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_finish_1: { + switch (llhttp__internal__c_update_finish_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags; + } + /* UNREACHABLE */; + abort(); + } s_n_llhttp__internal__n_pause_5: { state->error = 0x15; state->reason = "on_message_complete pause"; @@ -13311,8 +13366,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_update_finish_2: { - switch (llhttp__internal__c_update_finish_2(state, p, endp)) { + s_n_llhttp__internal__n_invoke_update_finish_3: { + switch (llhttp__internal__c_update_finish_3(state, p, endp)) { default: goto s_n_llhttp__internal__n_span_start_llhttp__on_body_2; } @@ -13424,8 +13479,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_test_lenient_flags: { - switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { case 0: goto s_n_llhttp__internal__n_error_11; default: @@ -13437,7 +13492,7 @@ static llparse_state_t llhttp__internal__run( s_n_llhttp__internal__n_invoke_test_flags_1: { switch (llhttp__internal__c_test_flags_1(state, p, endp)) { case 1: - goto s_n_llhttp__internal__n_invoke_test_lenient_flags; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; default: goto s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete; } @@ -13673,8 +13728,8 @@ static llparse_state_t llhttp__internal__run( /* UNREACHABLE */; abort(); } - s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { - switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + s_n_llhttp__internal__n_invoke_test_lenient_flags_2: { + switch (llhttp__internal__c_test_lenient_flags_2(state, p, endp)) { case 1: goto s_n_llhttp__internal__n_header_value_lenient; default: @@ -14035,7 +14090,7 @@ static llparse_state_t llhttp__internal__run( abort(); } s_n_llhttp__internal__n_error_23: { - state->error = 0x16; + state->error = 0x17; state->reason = "Pause on PRI/Upgrade"; state->error_pos = (const char*) p; state->_current = (void*) (intptr_t) s_error; diff --git a/src/3rdparty/llhttp/llhttp.h b/src/3rdparty/llhttp/llhttp.h index a7164103..8f9590d3 100644 --- a/src/3rdparty/llhttp/llhttp.h +++ b/src/3rdparty/llhttp/llhttp.h @@ -1,8 +1,8 @@ #ifndef INCLUDE_LLHTTP_H_ #define INCLUDE_LLHTTP_H_ -#define LLHTTP_VERSION_MAJOR 4 -#define LLHTTP_VERSION_MINOR 0 +#define LLHTTP_VERSION_MAJOR 5 +#define LLHTTP_VERSION_MINOR 1 #define LLHTTP_VERSION_PATCH 0 #ifndef LLHTTP_STRICT_MODE @@ -79,7 +79,8 @@ enum llhttp_errno { HPE_CB_CHUNK_COMPLETE = 20, HPE_PAUSED = 21, HPE_PAUSED_UPGRADE = 22, - HPE_USER = 23 + HPE_PAUSED_H2_UPGRADE = 23, + HPE_USER = 24 }; typedef enum llhttp_errno llhttp_errno_t; @@ -98,7 +99,8 @@ typedef enum llhttp_flags llhttp_flags_t; enum llhttp_lenient_flags { LENIENT_HEADERS = 0x1, - LENIENT_CHUNKED_LENGTH = 0x2 + LENIENT_CHUNKED_LENGTH = 0x2, + LENIENT_KEEP_ALIVE = 0x4 }; typedef enum llhttp_lenient_flags llhttp_lenient_flags_t; @@ -190,7 +192,8 @@ typedef enum llhttp_method llhttp_method_t; XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \ XX(21, PAUSED, PAUSED) \ XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \ - XX(23, USER, USER) \ + XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \ + XX(24, USER, USER) \ #define HTTP_METHOD_MAP(XX) \ @@ -255,6 +258,12 @@ extern "C" { #endif #include +#if defined(__wasm__) +#define LLHTTP_EXPORT __attribute__((visibility("default"))) +#else +#define LLHTTP_EXPORT +#endif + typedef llhttp__internal_t llhttp_t; typedef struct llhttp_settings_s llhttp_settings_t; @@ -305,15 +314,46 @@ struct llhttp_settings_s { * the `parser` here. In practice, `settings` has to be either a static * variable or be allocated with `malloc`, `new`, etc. */ +LLHTTP_EXPORT void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings); +#if defined(__wasm__) + +LLHTTP_EXPORT +llhttp_t* llhttp_alloc(llhttp_type_t type); + +LLHTTP_EXPORT +void llhttp_free(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_type(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_major(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_minor(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_method(llhttp_t* parser); + +LLHTTP_EXPORT +int llhttp_get_status_code(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_upgrade(llhttp_t* parser); + +#endif // defined(__wasm__) + /* Reset an already initialized parser back to the start state, preserving the * existing parser type, callback settings, user data, and lenient flags. */ +LLHTTP_EXPORT void llhttp_reset(llhttp_t* parser); /* Initialize the settings object */ +LLHTTP_EXPORT void llhttp_settings_init(llhttp_settings_t* settings); /* Parse full or partial request/response, invoking user callbacks along the @@ -332,6 +372,7 @@ void llhttp_settings_init(llhttp_settings_t* settings); * to return the same error upon each successive call up until `llhttp_init()` * is called. */ +LLHTTP_EXPORT llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); /* This method should be called when the other side has no further bytes to @@ -342,16 +383,19 @@ llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); * connection. This method will invoke `on_message_complete()` callback if the * request was terminated safely. Otherwise a error code would be returned. */ +LLHTTP_EXPORT llhttp_errno_t llhttp_finish(llhttp_t* parser); /* Returns `1` if the incoming message is parsed until the last byte, and has * to be completed by calling `llhttp_finish()` on EOF */ +LLHTTP_EXPORT int llhttp_message_needs_eof(const llhttp_t* parser); /* Returns `1` if there might be any other messages following the last that was * successfully parsed. */ +LLHTTP_EXPORT int llhttp_should_keep_alive(const llhttp_t* parser); /* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set @@ -360,6 +404,7 @@ int llhttp_should_keep_alive(const llhttp_t* parser); * Important: do not call this from user callbacks! User callbacks must return * `HPE_PAUSED` if pausing is required. */ +LLHTTP_EXPORT void llhttp_pause(llhttp_t* parser); /* Might be called to resume the execution after the pause in user's callback. @@ -367,6 +412,7 @@ void llhttp_pause(llhttp_t* parser); * * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. */ +LLHTTP_EXPORT void llhttp_resume(llhttp_t* parser); /* Might be called to resume the execution after the pause in user's callback. @@ -374,9 +420,11 @@ void llhttp_resume(llhttp_t* parser); * * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` */ +LLHTTP_EXPORT void llhttp_resume_after_upgrade(llhttp_t* parser); /* Returns the latest return error */ +LLHTTP_EXPORT llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); /* Returns the verbal explanation of the latest returned error. @@ -384,6 +432,7 @@ llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); * Note: User callback should set error reason when returning the error. See * `llhttp_set_error_reason()` for details. */ +LLHTTP_EXPORT const char* llhttp_get_error_reason(const llhttp_t* parser); /* Assign verbal description to the returned error. Must be called in user @@ -391,6 +440,7 @@ const char* llhttp_get_error_reason(const llhttp_t* parser); * * Note: `HPE_USER` error code might be useful in user callbacks. */ +LLHTTP_EXPORT void llhttp_set_error_reason(llhttp_t* parser, const char* reason); /* Returns the pointer to the last parsed byte before the returned error. The @@ -398,12 +448,15 @@ void llhttp_set_error_reason(llhttp_t* parser, const char* reason); * * Note: this method might be useful for counting the number of parsed bytes. */ +LLHTTP_EXPORT const char* llhttp_get_error_pos(const llhttp_t* parser); /* Returns textual name of error code */ +LLHTTP_EXPORT const char* llhttp_errno_name(llhttp_errno_t err); /* Returns textual name of HTTP method */ +LLHTTP_EXPORT const char* llhttp_method_name(llhttp_method_t method); @@ -416,6 +469,7 @@ const char* llhttp_method_name(llhttp_method_t method); * * **(USE AT YOUR OWN RISK)** */ +LLHTTP_EXPORT void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); @@ -429,8 +483,23 @@ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); * * **(USE AT YOUR OWN RISK)** */ +LLHTTP_EXPORT void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0 + * requests responses. + * + * Normally `llhttp` would error on (in strict mode) or discard (in loose mode) + * the HTTP request/response after the request/response with `Connection: close` + * and `Content-Length`. This is important to prevent cache poisoning attacks, + * but might interact badly with outdated and insecure clients. With this flag + * the extra request/response will be parsed normally. + * + * **(USE AT YOUR OWN RISK)** + */ +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled); + #ifdef __cplusplus } /* extern "C" */ #endif