summaryrefslogtreecommitdiff
path: root/src/protocol_decoder/http/http_decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocol_decoder/http/http_decoder.cpp')
-rw-r--r--src/protocol_decoder/http/http_decoder.cpp506
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);
-}