| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 |
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "llhttp.h"
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wconversion"
- #pragma GCC diagnostic ignored "-Wsign-conversion"
- #endif
- #define CALLBACK_MAYBE(PARSER, NAME) \
- do { \
- const llhttp_settings_t* settings; \
- settings = (const llhttp_settings_t*) (PARSER)->settings; \
- if (settings == NULL || settings->NAME == NULL) { \
- err = 0; \
- break; \
- } \
- err = settings->NAME((PARSER)); \
- } while (0)
- #define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \
- do { \
- const llhttp_settings_t* settings; \
- settings = (const llhttp_settings_t*) (PARSER)->settings; \
- if (settings == NULL || settings->NAME == NULL) { \
- err = 0; \
- break; \
- } \
- err = settings->NAME((PARSER), (START), (LEN)); \
- if (err == -1) { \
- err = HPE_USER; \
- llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \
- } \
- } while (0)
- void llhttp_init(llhttp_t* parser, llhttp_type_t type,
- const llhttp_settings_t* settings) {
- llhttp__internal_init(parser);
- parser->type = type;
- parser->settings = (void*) settings;
- }
- #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, int status_code,
- uint8_t upgrade, int should_keep_alive);
- extern int wasm_on_body(llhttp_t* p, const char* at, size_t length);
- extern int wasm_on_message_complete(llhttp_t * p);
- static int wasm_on_headers_complete_wrap(llhttp_t* p) {
- return wasm_on_headers_complete(p, p->status_code, p->upgrade,
- llhttp_should_keep_alive(p));
- }
- const llhttp_settings_t wasm_settings = {
- wasm_on_message_begin,
- wasm_on_url,
- wasm_on_status,
- NULL,
- NULL,
- wasm_on_header_field,
- wasm_on_header_value,
- NULL,
- NULL,
- wasm_on_headers_complete_wrap,
- wasm_on_body,
- wasm_on_message_complete,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 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);
- }
- #endif // defined(__wasm__)
- /* 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;
- }
- void llhttp_reset(llhttp_t* parser) {
- llhttp_type_t type = parser->type;
- const llhttp_settings_t* settings = parser->settings;
- void* data = parser->data;
- uint16_t lenient_flags = parser->lenient_flags;
- llhttp__internal_init(parser);
- parser->type = type;
- parser->settings = (void*) settings;
- parser->data = data;
- parser->lenient_flags = lenient_flags;
- }
- llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) {
- return llhttp__internal_execute(parser, data, data + len);
- }
- void llhttp_settings_init(llhttp_settings_t* settings) {
- memset(settings, 0, sizeof(*settings));
- }
- llhttp_errno_t llhttp_finish(llhttp_t* parser) {
- int err;
- /* We're in an error state. Don't bother doing anything. */
- if (parser->error != 0) {
- return 0;
- }
- switch (parser->finish) {
- case HTTP_FINISH_SAFE_WITH_CB:
- CALLBACK_MAYBE(parser, on_message_complete);
- if (err != HPE_OK) return err;
- /* FALLTHROUGH */
- case HTTP_FINISH_SAFE:
- return HPE_OK;
- case HTTP_FINISH_UNSAFE:
- parser->reason = "Invalid EOF state";
- return HPE_INVALID_EOF_STATE;
- default:
- abort();
- }
- }
- void llhttp_pause(llhttp_t* parser) {
- if (parser->error != HPE_OK) {
- return;
- }
- parser->error = HPE_PAUSED;
- parser->reason = "Paused";
- }
- void llhttp_resume(llhttp_t* parser) {
- if (parser->error != HPE_PAUSED) {
- return;
- }
- parser->error = 0;
- }
- void llhttp_resume_after_upgrade(llhttp_t* parser) {
- if (parser->error != HPE_PAUSED_UPGRADE) {
- return;
- }
- parser->error = 0;
- }
- llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
- return parser->error;
- }
- const char* llhttp_get_error_reason(const llhttp_t* parser) {
- return parser->reason;
- }
- void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
- parser->reason = reason;
- }
- const char* llhttp_get_error_pos(const llhttp_t* parser) {
- return parser->error_pos;
- }
- const char* llhttp_errno_name(llhttp_errno_t err) {
- #define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME;
- switch (err) {
- HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
- default: abort();
- }
- #undef HTTP_ERRNO_GEN
- }
- const char* llhttp_method_name(llhttp_method_t method) {
- #define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
- switch (method) {
- HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN)
- default: abort();
- }
- #undef HTTP_METHOD_GEN
- }
- const char* llhttp_status_name(llhttp_status_t status) {
- #define HTTP_STATUS_GEN(NUM, NAME, STRING) case HTTP_STATUS_##NAME: return #STRING;
- switch (status) {
- HTTP_STATUS_MAP(HTTP_STATUS_GEN)
- default: abort();
- }
- #undef HTTP_STATUS_GEN
- }
- void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_HEADERS;
- } else {
- parser->lenient_flags &= ~LENIENT_HEADERS;
- }
- }
- void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_CHUNKED_LENGTH;
- } else {
- parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH;
- }
- }
- 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;
- }
- }
- void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_TRANSFER_ENCODING;
- } else {
- parser->lenient_flags &= ~LENIENT_TRANSFER_ENCODING;
- }
- }
- void llhttp_set_lenient_version(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_VERSION;
- } else {
- parser->lenient_flags &= ~LENIENT_VERSION;
- }
- }
- void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_DATA_AFTER_CLOSE;
- } else {
- parser->lenient_flags &= ~LENIENT_DATA_AFTER_CLOSE;
- }
- }
- void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_OPTIONAL_LF_AFTER_CR;
- } else {
- parser->lenient_flags &= ~LENIENT_OPTIONAL_LF_AFTER_CR;
- }
- }
- void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;
- } else {
- parser->lenient_flags &= ~LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;
- }
- }
- void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF;
- } else {
- parser->lenient_flags &= ~LENIENT_OPTIONAL_CR_BEFORE_LF;
- }
- }
- void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled) {
- if (enabled) {
- parser->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE;
- } else {
- parser->lenient_flags &= ~LENIENT_SPACES_AFTER_CHUNK_SIZE;
- }
- }
- /* Callbacks */
- int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_message_begin);
- return err;
- }
- int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p);
- return err;
- }
- int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_url_complete);
- return err;
- }
- int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p);
- return err;
- }
- int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_status_complete);
- return err;
- }
- int llhttp__on_method(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_method, p, endp - p);
- return err;
- }
- int llhttp__on_method_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_method_complete);
- return err;
- }
- int llhttp__on_version(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_version, p, endp - p);
- return err;
- }
- int llhttp__on_version_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_version_complete);
- return err;
- }
- int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p);
- return err;
- }
- int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_header_field_complete);
- return err;
- }
- int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p);
- return err;
- }
- int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_header_value_complete);
- return err;
- }
- int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_headers_complete);
- return err;
- }
- int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_message_complete);
- return err;
- }
- int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p);
- return err;
- }
- int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_chunk_header);
- return err;
- }
- int llhttp__on_chunk_extension_name(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_chunk_extension_name, p, endp - p);
- return err;
- }
- int llhttp__on_chunk_extension_name_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_chunk_extension_name_complete);
- return err;
- }
- int llhttp__on_chunk_extension_value(llhttp_t* s, const char* p, const char* endp) {
- int err;
- SPAN_CALLBACK_MAYBE(s, on_chunk_extension_value, p, endp - p);
- return err;
- }
- int llhttp__on_chunk_extension_value_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_chunk_extension_value_complete);
- return err;
- }
- int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_chunk_complete);
- return err;
- }
- int llhttp__on_reset(llhttp_t* s, const char* p, const char* endp) {
- int err;
- CALLBACK_MAYBE(s, on_reset);
- return err;
- }
- /* Private */
- void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
- const char* msg) {
- if (p == endp) {
- fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type,
- s->flags, msg);
- } else {
- fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s,
- s->type, s->flags, *p, msg);
- }
- }
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|