diff options
Diffstat (limited to 'src/protocol_decoder/http/http_decoder.cpp')
| -rw-r--r-- | src/protocol_decoder/http/http_decoder.cpp | 506 |
1 files changed, 0 insertions, 506 deletions
diff --git a/src/protocol_decoder/http/http_decoder.cpp b/src/protocol_decoder/http/http_decoder.cpp deleted file mode 100644 index 8f7707f..0000000 --- a/src/protocol_decoder/http/http_decoder.cpp +++ /dev/null @@ -1,506 +0,0 @@ -#include <stdio.h> -#include <assert.h> -#include <string.h> - -#include "llhttp.h" -#include "http_decoder_util.h" -#include "http_decoder_table.h" -#include "http_decoder.h" - -struct http_decoder -{ - llhttp_t parser; - llhttp_settings_t settings; - enum http_decoder_status status; - struct http_decoder_table *table; - int commit_count; -}; - -/****************************************************************************** - * Private API - ******************************************************************************/ - -static void printf_debug_info(const char *desc, const char *at, size_t length) -{ - if (at) - { - char *temp = http_decoder_safe_dup(at, length); - printf("%s: %s\n", desc, temp); - http_decoder_safe_free(temp); - } - else - { - printf("%s\n", desc); - } -} - -/* Possible return values 0, -1, `HPE_PAUSED` */ -static int on_message_begin(llhttp_t *http) -{ - printf_debug_info("on_message_begin", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - if (decoder->table == NULL) - { - decoder->table = http_decoder_table_create(); - } - else - { - http_decoder_table_reset(decoder->table); - } - decoder->commit_count = 0; - decoder->status = ON_MESSAGE_BEGIN; - - return 0; -} - -/* Possible return values 0, -1, `HPE_PAUSED` */ -static int on_message_complete(llhttp_t *http) -{ - printf_debug_info("on_message_complete", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - enum rstring_status status = http_decoder_table_status(decoder->table, HTTP_ITERM_BODY); - if (status == RSTRING_STATUS_REFER || status == RSTRING_STATUS_CACHE) - { - http_decoder_table_commit(decoder->table, HTTP_ITERM_BODY); - decoder->commit_count++; - } - decoder->status = ON_MESSAGE_COMPLETE; - - return 0; -} - -/* Possible return values 0, -1, HPE_USER */ -static int on_uri(llhttp_t *http, const char *at, size_t length) -{ - printf_debug_info("on_uri", at, length); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_add(decoder->table, HTTP_ITERM_URI, at, length); - decoder->status = ON_URI; - - return 0; -} - -/* Information-only callbacks, return value is ignored */ -static int on_uri_complete(llhttp_t *http) -{ - printf_debug_info("on_uri_complete", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_commit(decoder->table, HTTP_ITERM_URI); - decoder->commit_count++; - decoder->status = ON_URI_COMPLETE; - - return 0; -} - -/* Possible return values 0, -1, HPE_USER */ -static int on_status(llhttp_t *http, const char *at, size_t length) -{ - printf_debug_info("on_status", at, length); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_add(decoder->table, HTTP_ITERM_STATUS, at, length); - decoder->status = ON_STATUS; - - return 0; -} - -/* Information-only callbacks, return value is ignored */ -static int on_status_complete(llhttp_t *http) -{ - printf_debug_info("on_status_complete", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_commit(decoder->table, HTTP_ITERM_STATUS); - decoder->commit_count++; - decoder->status = ON_STATUS_COMPLETE; - - return 0; -} - -/* Possible return values 0, -1, HPE_USER */ -static int on_header_field(llhttp_t *http, const char *at, size_t length) -{ - printf_debug_info("on_header_field", at, length); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_add(decoder->table, HTTP_ITERM_HEADER_FILED, at, length); - decoder->status = ON_HEADER_FIELD; - - return 0; -} - -/* Information-only callbacks, return value is ignored */ -static int on_header_field_complete(llhttp_t *http) -{ - printf_debug_info("on_header_field_complete", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_commit(decoder->table, HTTP_ITERM_HEADER_FILED); - decoder->commit_count++; - decoder->status = ON_HEADER_FIELD_COMPLETE; - - return 0; -} - -/* Possible return values 0, -1, HPE_USER */ -static int on_header_value(llhttp_t *http, const char *at, size_t length) -{ - printf_debug_info("on_header_value", at, length); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_add(decoder->table, HTTP_ITERM_HEADER_VALUE, at, length); - decoder->status = ON_HEADER_VALUE; - - return 0; -} - -/* Information-only callbacks, return value is ignored */ -static int on_header_value_complete(llhttp_t *http) -{ - printf_debug_info("on_header_value_complete", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_commit(decoder->table, HTTP_ITERM_HEADER_VALUE); - decoder->commit_count++; - decoder->status = ON_HEADER_VALUE_COMPLETE; - - return 0; -} - -/* When on_chunk_header is called, the current chunk length is stored - * in parser->content_length. - * Possible return values 0, -1, `HPE_PAUSED` - */ -static int on_chunk_header(llhttp_t *http) -{ - printf_debug_info("on_chunk_header", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - decoder->status = ON_CHUNK_HEADER; - - return 0; -} - -/* When on_chunk_header is called, the current chunk length is stored - * in parser->content_length. - * Possible return values 0, -1, `HPE_PAUSED` - */ -static int on_chunk_header_complete(llhttp_t *http) -{ - printf_debug_info("on_chunk_header_complete", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - decoder->status = ON_CHUNK_HEADER_COMPLETE; - - return 0; -} - -/* Possible return values: - * 0 - Proceed normally - * 1 - Assume that request/response has no body, and proceed to parsing the next message - * 2 - Assume absence of body (as above) and make `llhttp_execute()` return `HPE_PAUSED_UPGRADE` - * -1 - Error `HPE_PAUSED` - */ -static int on_headers_complete(llhttp_t *http) -{ - printf_debug_info("on_headers_complete", NULL, 0); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - decoder->status = ON_HEADERS_COMPLETE; - - return 0; -} - -/* Possible return values 0, -1, HPE_USER */ -static int on_body(llhttp_t *http, const char *at, size_t length) -{ - printf_debug_info("on_body", at, length); - - struct http_decoder *decoder = container_of(http, struct http_decoder, parser); - http_decoder_table_add(decoder->table, HTTP_ITERM_BODY, at, length); - decoder->status = ON_BODY; - - return 0; -} - -/****************************************************************************** - * Manipulate http decoder - ******************************************************************************/ - -struct http_decoder *http_decoder_create() -{ - struct http_decoder *decoder = http_decoder_safe_alloc(struct http_decoder, 1); - - return decoder; -} - -void http_decoder_destory(struct http_decoder *decoder) -{ - if (decoder) - { - http_decoder_table_destory(decoder->table); - http_decoder_safe_free(decoder); - } -} - -void http_decoder_init(struct http_decoder *decoder) -{ - assert(decoder); - - enum llhttp_type type = HTTP_BOTH; // HTTP_BOTH | HTTP_REQUEST | HTTP_RESPONSE - - llhttp_settings_init(&decoder->settings); - llhttp_init(&decoder->parser, type, &decoder->settings); - - decoder->settings.on_message_begin = on_message_begin; - decoder->settings.on_message_complete = on_message_complete; - - decoder->settings.on_url = on_uri; - decoder->settings.on_url_complete = on_uri_complete; - - decoder->settings.on_status = on_status; - decoder->settings.on_status_complete = on_status_complete; - - decoder->settings.on_header_field = on_header_field; - decoder->settings.on_header_field_complete = on_header_field_complete; - - decoder->settings.on_header_value = on_header_value; - decoder->settings.on_header_value_complete = on_header_value_complete; - - decoder->settings.on_chunk_header = on_chunk_header; - decoder->settings.on_chunk_complete = on_chunk_header_complete; - - decoder->settings.on_headers_complete = on_headers_complete; - - decoder->settings.on_body = on_body; - - decoder->status = ON_INIT; -} - -void http_decoder_reset(struct http_decoder *decoder) -{ - if (decoder) - { - http_decoder_init(decoder); - http_decoder_table_reset(decoder->table); - decoder->commit_count = 0; - } -} - -/* - * return 0 : new data that needs to be consumed by upper layers has been parsed - * return -1 : no new data - * return -2 : error or not http protocol - */ -int http_decoder_dispatch(struct http_decoder *decoder, const char *data, size_t len) -{ - assert(decoder); - - enum llhttp_errno err = llhttp_execute(&decoder->parser, data, len); - if (err != HPE_OK) - { - fprintf(stderr, "llhttp_execute parse error: %s %s\n", llhttp_errno_name(err), decoder->parser.reason); - return -2; - } - - if (decoder->table == NULL) - { - return -1; - } - - if (http_decoder_table_status(decoder->table, HTTP_ITERM_URI) == RSTRING_STATUS_REFER) - { - http_decoder_table_cache(decoder->table, HTTP_ITERM_URI); - } - - if (http_decoder_table_status(decoder->table, HTTP_ITERM_STATUS) == RSTRING_STATUS_REFER) - { - http_decoder_table_cache(decoder->table, HTTP_ITERM_STATUS); - } - - if (http_decoder_table_status(decoder->table, HTTP_ITERM_HEADER_FILED) == RSTRING_STATUS_REFER) - { - http_decoder_table_cache(decoder->table, HTTP_ITERM_HEADER_FILED); - } - - if (http_decoder_table_status(decoder->table, HTTP_ITERM_HEADER_VALUE) == RSTRING_STATUS_REFER) - { - http_decoder_table_cache(decoder->table, HTTP_ITERM_HEADER_VALUE); - } - - // do not cache incomplete http body, submit immediately every time - if (http_decoder_table_status(decoder->table, HTTP_ITERM_BODY) == RSTRING_STATUS_REFER || - http_decoder_table_status(decoder->table, HTTP_ITERM_BODY) == RSTRING_STATUS_CACHE) - - { - http_decoder_table_commit(decoder->table, HTTP_ITERM_BODY); - } - - if (decoder->commit_count) - { - return 0; - } - else - { - return -1; - } -} - -// remove the data that has been consumed by the upper layer -void http_decoder_remove(struct http_decoder *decoder) -{ - assert(decoder); - - if (decoder->table) - { - http_decoder_table_remove(decoder->table); - } - decoder->commit_count = 0; -} - -// for debug -void http_decoder_dump(struct http_decoder *decoder) -{ - uint64_t content_length = decoder->parser.content_length; - uint8_t type = decoder->parser.type; - uint8_t method = decoder->parser.method; - uint8_t http_major = decoder->parser.http_major; - uint8_t http_minor = decoder->parser.http_minor; - uint8_t header_state = decoder->parser.header_state; - uint8_t lenient_flags = decoder->parser.lenient_flags; - uint8_t upgrade = decoder->parser.upgrade; - uint8_t finish = decoder->parser.finish; - uint16_t flags = decoder->parser.flags; - uint16_t status_code = decoder->parser.status_code; - - char *method_str = (char *)llhttp_method_name((llhttp_method_t)method); - - printf("\n=====================================================\n"); - printf("content_length: %lu, type: %d, header_state: %d, lenient_flags: %d, upgrade: %d, finish: %d, flags: %d\n", - content_length, type, header_state, lenient_flags, upgrade, finish, flags); - printf("method: %d %s, http_major: %d, http_minor: %d, status_code: %d\n", - method, method_str, http_major, http_minor, status_code); - - if (decoder->table) - { - http_decoder_table_dump(decoder->table); - } - printf("=====================================================\n"); -} - -// for gtest -enum http_decoder_status http_decoder_status(struct http_decoder *decoder) -{ - return decoder->status; -} - -/****************************************************************************** - * Consume decoded table - ******************************************************************************/ - -// HTTP_DIR_UNKNOWN: Not Find -enum http_dir http_decoder_fetch_dir(struct http_decoder *decoder) -{ - if (decoder->status >= ON_URI) - { - switch (decoder->parser.type) - { - case 1: - return HTTP_DIR_REQUEST; - break; - case 2: - return HTTP_DIR_RESPONSE; - default: - return HTTP_DIR_UNKNOWN; - break; - } - } - else - { - return HTTP_DIR_UNKNOWN; - } -} - -// -1 : Not Find -int http_decoder_fetch_status_code(struct http_decoder *decoder) -{ - if (decoder->status >= ON_STATUS_COMPLETE && http_decoder_fetch_dir(decoder) == HTTP_DIR_RESPONSE) - { - return decoder->parser.status_code; - } - else - { - return -1; - } -} - -// -1 : Not Find -int http_decoder_fetch_major_version(struct http_decoder *decoder) -{ - if (decoder->status >= ON_HEADER_FIELD) - { - return decoder->parser.http_major; - } - else - { - return -1; - } -} - -// -1 : Not Find -int http_decoder_fetch_minor_version(struct http_decoder *decoder) -{ - if (decoder->status >= ON_HEADER_FIELD) - { - return decoder->parser.http_minor; - } - else - { - return -1; - } -} - -// ptr == NULL : Not Find -void http_decoder_fetch_method(struct http_decoder *decoder, char **ptr, size_t *len) -{ - if (decoder->status >= ON_URI && http_decoder_fetch_dir(decoder) == HTTP_DIR_REQUEST) - { - const char *method_str = llhttp_method_name((llhttp_method_t)decoder->parser.method); - *ptr = (char *)method_str; - *len = strlen(method_str); - } - else - { - *ptr = NULL; - *len = 0; - } -} - -// ptr == NULL : Not Find -void http_decoder_fetch_uri(struct http_decoder *decoder, char **ptr, size_t *len) -{ - http_decoder_table_get_uri(decoder->table, ptr, len); -} - -// ptr == NULL : Not Find -void http_decoder_fetch_status(struct http_decoder *decoder, char **ptr, size_t *len) -{ - http_decoder_table_get_status(decoder->table, ptr, len); -} - -// ptr == NULL : Not Find -void http_decoder_fetch_body(struct http_decoder *decoder, char **ptr, size_t *len) -{ - http_decoder_table_get_body(decoder->table, ptr, len); -} - -// filed_ptr == NULL : Not Find -void http_decoder_fetch_next_header(struct http_decoder *decoder, int *iter_index, - char **filed_ptr, size_t *filed_len, char **value_ptr, size_t *value_len) -{ - http_decoder_table_next_header(decoder->table, iter_index, filed_ptr, filed_len, value_ptr, value_len); -} |
