summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlijia <[email protected]>2024-10-27 18:08:00 +0800
committerlijia <[email protected]>2024-11-08 11:23:16 +0800
commit627cfac992c52e3c7950355c0d447764056a5276 (patch)
treeafb5f8f462d964a764dbb071f5cfadad199cbe4d
parentd0a868591470a4a9d71a65a5d540058e72c8d92c (diff)
httpv2.0 rebase onto develop-2.0dev-http-v2.0
-rw-r--r--conf/stellar.toml3
-rw-r--r--decoders/CMakeLists.txt2
-rw-r--r--decoders/http/CMakeLists.txt20
-rw-r--r--decoders/http/http_content_decompress.c268
-rw-r--r--decoders/http/http_decoder.c1239
-rw-r--r--decoders/http/http_decoder.h104
-rw-r--r--decoders/http/http_decoder_decompress.c274
-rw-r--r--decoders/http/http_decoder_decompress.h (renamed from decoders/http/http_content_decompress.h)9
-rw-r--r--decoders/http/http_decoder_half.c1548
-rw-r--r--decoders/http/http_decoder_half.h263
-rw-r--r--decoders/http/http_decoder_llhttp_wrap.c318
-rw-r--r--decoders/http/http_decoder_module.c299
-rw-r--r--decoders/http/http_decoder_private.h155
-rw-r--r--decoders/http/http_decoder_result_queue.c152
-rw-r--r--decoders/http/http_decoder_result_queue.h51
-rw-r--r--decoders/http/http_decoder_stat.c182
-rw-r--r--decoders/http/http_decoder_stat.h96
-rw-r--r--decoders/http/http_decoder_string.c289
-rw-r--r--decoders/http/http_decoder_string.h73
-rw-r--r--decoders/http/http_decoder_table.c579
-rw-r--r--decoders/http/http_decoder_table.h79
-rw-r--r--decoders/http/http_decoder_tunnel.c116
-rw-r--r--decoders/http/http_decoder_tunnel.h36
-rw-r--r--decoders/http/http_decoder_utils.c536
-rw-r--r--decoders/http/http_decoder_utils.h92
-rw-r--r--decoders/http/version.map9
-rw-r--r--deps/CMakeLists.txt3
-rw-r--r--deps/md5/CMakeLists.txt2
-rw-r--r--include/stellar/http.h151
-rw-r--r--infra/version.map7
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/decoders/http/CMakeLists.txt113
-rw-r--r--test/decoders/http/benchmarks/json/http_6over4_single_trans.json9
-rw-r--r--test/decoders/http/benchmarks/json/http_chn_encode_url.json6
-rw-r--r--test/decoders/http/benchmarks/json/http_chunked_res_gzip.json9
-rw-r--r--test/decoders/http/benchmarks/json/http_connect_single.json20
-rw-r--r--test/decoders/http/benchmarks/json/http_error.json1
-rw-r--r--test/decoders/http/benchmarks/json/http_fin.json1
-rw-r--r--test/decoders/http/benchmarks/json/http_get_encoded_uri.json14
-rw-r--r--test/decoders/http/benchmarks/json/http_get_long_cookie.json5
-rw-r--r--test/decoders/http/benchmarks/json/http_get_multi_trans.json41
-rw-r--r--test/decoders/http/benchmarks/json/http_get_req_pipeline.json13
-rw-r--r--test/decoders/http/benchmarks/json/http_get_single_trans.json5
-rw-r--r--test/decoders/http/benchmarks/json/http_gzip_out_of_order.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_hdrs_exceed_maximum.json97
-rw-r--r--test/decoders/http/benchmarks/json/http_incomplete_header.json1
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state.json22
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state_c2s.json12
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state_exception_c2s.json10
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state_exception_s2c.json14
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state_pipeline.json82
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state_s2c.json12
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state_tunnel.json6
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_c2s.json2
-rw-r--r--test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_s2c.json2
-rw-r--r--test/decoders/http/benchmarks/json/http_multi_parse_error.json8
-rw-r--r--test/decoders/http/benchmarks/json/http_no_content_length.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_no_cr_line_eof.json18
-rw-r--r--test/decoders/http/benchmarks/json/http_out_of_order.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_over_pppoe.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_over_tcp_keepalive.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_pipeline_C2S.json313
-rw-r--r--test/decoders/http/benchmarks/json/http_pipeline_S2C.json181
-rw-r--r--test/decoders/http/benchmarks/json/http_pipeline_header_splitting.json138
-rw-r--r--test/decoders/http/benchmarks/json/http_post.json39
-rw-r--r--test/decoders/http/benchmarks/json/http_post_c2s.json22
-rw-r--r--test/decoders/http/benchmarks/json/http_post_multipart_form_data.json14
-rw-r--r--test/decoders/http/benchmarks/json/http_post_s2c.json22
-rw-r--r--test/decoders/http/benchmarks/json/http_post_single_trans.json76
-rw-r--r--test/decoders/http/benchmarks/json/http_put_continue100.json44
-rw-r--r--test/decoders/http/benchmarks/json/http_req_1byte_sliding_window.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_res_1byte_sliding_window.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_res_gzip.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_session_exception_c2s.json26
-rw-r--r--test/decoders/http/benchmarks/json/http_session_exception_s2c.json35
-rw-r--r--test/decoders/http/benchmarks/json/http_trans_pipeline.json890
-rw-r--r--test/decoders/http/benchmarks/json/http_upgrade_websocket.json6
-rw-r--r--test/decoders/http/benchmarks/json/http_url_test_with_host.json8
-rw-r--r--test/decoders/http/benchmarks/json/http_url_test_without_host.json7
-rw-r--r--test/decoders/http/benchmarks/json/http_url_test_without_host_v6.json6
-rw-r--r--test/decoders/http/benchmarks/json/http_whitespace_before_header.json1
-rw-r--r--test/decoders/http/benchmarks/json/http_zlib_deadlock.json7
-rw-r--r--test/decoders/http/benchmarks/pcap/http_connect_single.pcapbin0 -> 1236 bytes
-rw-r--r--test/decoders/http/benchmarks/pcap/http_incomplete_header.pcapbin0 -> 711 bytes
-rw-r--r--test/decoders/http/benchmarks/pcap/http_no_cr_line_eof.pcapbin0 -> 1400 bytes
-rw-r--r--test/decoders/http/benchmarks/pcap/http_put_continue100.pcapbin0 -> 2880 bytes
-rw-r--r--test/decoders/http/http_gtest.cpp313
-rw-r--r--test/decoders/http/http_gtest.h8
-rw-r--r--test/decoders/http/http_gtest_llhttp.cpp98
-rw-r--r--test/decoders/http/http_gtest_llhttp_headers_buf.cpp424
-rw-r--r--test/decoders/http/http_gtest_main.cpp97
-rw-r--r--test/decoders/http/http_gtest_module.cpp474
-rw-r--r--test/decoders/http/http_module.toml11
-rw-r--r--test/decoders/http/http_test_plug.cpp674
-rw-r--r--test/decoders/http/test_based_on_stellar/CMakeLists.txt125
-rw-r--r--test/decoders/http/test_based_on_stellar/env/gtest_entry.toml3
-rw-r--r--test/decoders/http/test_based_on_stellar/env/http_decoder.toml18
-rw-r--r--test/decoders/http/test_based_on_stellar/env/log.toml4
-rw-r--r--test/decoders/http/test_based_on_stellar/env/spec.toml9
-rw-r--r--test/decoders/http/test_based_on_stellar/env/stellar.toml64
100 files changed, 5456 insertions, 6237 deletions
diff --git a/conf/stellar.toml b/conf/stellar.toml
index fdd7ba9..8f363f7 100644
--- a/conf/stellar.toml
+++ b/conf/stellar.toml
@@ -72,6 +72,9 @@
cli_request_timeout = 3 # second
pktdump_task_max_num = 3
+[http]
+ decompress_enable = 1
+
[[module]]
path = ""
init = "monitor_on_init"
diff --git a/decoders/CMakeLists.txt b/decoders/CMakeLists.txt
index 7946822..eaba19e 100644
--- a/decoders/CMakeLists.txt
+++ b/decoders/CMakeLists.txt
@@ -1,5 +1,5 @@
add_subdirectory(lpi_plus)
-#add_subdirectory(http)
+add_subdirectory(http)
#add_subdirectory(socks)
#add_subdirectory(stratum)
#add_subdirectory(session_flags) \ No newline at end of file
diff --git a/decoders/http/CMakeLists.txt b/decoders/http/CMakeLists.txt
index c242afe..3a2b637 100644
--- a/decoders/http/CMakeLists.txt
+++ b/decoders/http/CMakeLists.txt
@@ -1,15 +1,15 @@
+add_definitions(-fPIC)
include_directories(${CMAKE_SOURCE_DIR}/deps)
-set(HTTP_SRC http_decoder.c http_decoder_utils.c http_decoder_half.c
- http_decoder_table.c http_decoder_string.c http_content_decompress.c
- http_decoder_result_queue.c http_decoder_stat.c http_decoder_tunnel.c)
+set(HTTP_SRC http_decoder_module.c http_decoder.c
+ http_decoder_llhttp_wrap.c
+ http_decoder_utils.c
+ http_decoder_decompress.c
+ http_decoder_half.c
+ http_decoder_stat.c )
-add_library(http STATIC ${HTTP_SRC})
-add_library(http_dyn SHARED ${HTTP_SRC})
+add_library(http ${HTTP_SRC})
set_target_properties(http PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/version.map")
target_include_directories(http PUBLIC ${CMAKE_SOURCE_DIR}/deps/)
-target_link_libraries(http z llhttp-static fieldstat4 brotli-dec-static brotli-common-static nmx_pool toml)
-set_target_properties(http PROPERTIES PREFIX "")
-
-set_target_properties(http_dyn PROPERTIES PREFIX "")
-target_link_libraries(http_dyn z llhttp-static fieldstat4 brotli-dec-static brotli-common-static nmx_pool toml) \ No newline at end of file
+target_link_libraries(http z llhttp-static fieldstat4 brotli-dec-static brotli-common-static toml)
+set_target_properties(http PROPERTIES PREFIX "") \ No newline at end of file
diff --git a/decoders/http/http_content_decompress.c b/decoders/http/http_content_decompress.c
deleted file mode 100644
index 922c624..0000000
--- a/decoders/http/http_content_decompress.c
+++ /dev/null
@@ -1,268 +0,0 @@
-#include <zlib.h>
-#include <string.h>
-#include <assert.h>
-#include <brotli/decode.h>
-#include "http_decoder_private.h"
-
-#define HTTP_DECOMPRESS_BUFFER_SIZE (4096)
-
-struct http_content_decompress
-{
- enum http_content_encoding encoding;
- z_stream *z_stream_ptr;
- BrotliDecoderState *br_state;
- char *buffer;
- size_t buffer_size;
-};
-
-void http_content_decompress_ownership_borrow(struct http_content_decompress *decompress)
-{
- decompress->buffer = NULL; // ownership move to data->decompress_buffer_list, will be freed when message has been processed by all plugins
-}
-
-enum http_content_encoding http_content_encoding_str2int(const char *content_encoding, size_t encoding_str_len)
-{
- if (http_strncasecmp_safe("gzip", content_encoding, 4, encoding_str_len) == 0)
- {
- return HTTP_CONTENT_ENCODING_GZIP;
- }
- if (http_strncasecmp_safe("deflate", content_encoding, 7, encoding_str_len) == 0)
- {
- return HTTP_CONTENT_ENCODING_DEFLATE;
- }
- if (http_strncasecmp_safe("br", content_encoding, 2, encoding_str_len) == 0)
- {
- return HTTP_CONTENT_ENCODING_BR;
- }
- return HTTP_CONTENT_ENCODING_NONE;
-}
-
-const char *http_content_encoding_int2str(enum http_content_encoding content_encoding)
-{
- if (content_encoding == HTTP_CONTENT_ENCODING_GZIP)
- {
- return "gzip";
- }
- if (content_encoding == HTTP_CONTENT_ENCODING_DEFLATE)
- {
- return "deflate";
- }
- if (content_encoding == HTTP_CONTENT_ENCODING_BR)
- {
- return "br";
- }
- return "unknown";
-}
-
-struct http_content_decompress *http_content_decompress_create(enum http_content_encoding encoding)
-{
- struct http_content_decompress *decompress =
- CALLOC(struct http_content_decompress, 1);
- assert(decompress);
-
- decompress->encoding = encoding;
- decompress->z_stream_ptr = NULL;
- decompress->br_state = NULL;
-
- if (encoding == HTTP_CONTENT_ENCODING_GZIP || encoding == HTTP_CONTENT_ENCODING_DEFLATE)
- {
- decompress->z_stream_ptr = CALLOC(z_stream, 1);
- assert(decompress->z_stream_ptr);
-
- decompress->z_stream_ptr->zalloc = NULL;
- decompress->z_stream_ptr->zfree = NULL;
- decompress->z_stream_ptr->opaque = NULL;
- decompress->z_stream_ptr->avail_in = 0;
- decompress->z_stream_ptr->next_in = Z_NULL;
-
- if (encoding == HTTP_CONTENT_ENCODING_GZIP)
- {
- if (inflateInit2(decompress->z_stream_ptr, MAX_WBITS + 16) != Z_OK)
- {
- goto error;
- }
- }
- if (encoding == HTTP_CONTENT_ENCODING_DEFLATE)
- {
- if (inflateInit2(decompress->z_stream_ptr, -MAX_WBITS) != Z_OK)
- {
- goto error;
- }
- }
- }
-
- if (encoding == HTTP_CONTENT_ENCODING_BR)
- {
- decompress->br_state = BrotliDecoderCreateInstance(NULL, NULL, NULL);
- if (decompress->br_state == NULL)
- {
- goto error;
- }
- }
- return decompress;
-
-error:
- http_content_decompress_destroy(decompress);
- return NULL;
-}
-
-void http_content_decompress_destroy(struct http_content_decompress *decompress)
-{
- if (NULL == decompress)
- {
- return;
- }
- if (decompress->z_stream_ptr != NULL)
- {
- inflateEnd(decompress->z_stream_ptr);
- FREE(decompress->z_stream_ptr);
- }
- if (decompress->br_state)
- {
- BrotliDecoderDestroyInstance(decompress->br_state);
- decompress->br_state = NULL;
- }
- FREE(decompress->buffer);
- FREE(decompress);
-}
-
-static int http_content_decompress_write_zlib(struct http_content_decompress *decompress,
- const char *indata, size_t indata_len,
- char **outdata, size_t *outdata_len)
-{
- z_stream *z_stream_ptr = decompress->z_stream_ptr;
- z_stream_ptr->avail_in = (unsigned int)indata_len;
- z_stream_ptr->next_in = (unsigned char *)indata;
- z_stream_ptr->avail_out = (unsigned int)HTTP_DECOMPRESS_BUFFER_SIZE;
- z_stream_ptr->next_out = (unsigned char *)decompress->buffer;
- *outdata = NULL;
- *outdata_len = 0;
- size_t total_have = 0;
- int no_buffer;
-
- do
- {
- int ret = inflate(z_stream_ptr, Z_NO_FLUSH);
- if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
- {
- (void)inflateEnd(z_stream_ptr);
- return -1;
- }
- size_t have = HTTP_DECOMPRESS_BUFFER_SIZE - z_stream_ptr->avail_out;
- if (have > 0)
- {
- total_have += have;
- if (0 == z_stream_ptr->avail_out)
- {
- decompress->buffer_size += HTTP_DECOMPRESS_BUFFER_SIZE;
- decompress->buffer = REALLOC(char, decompress->buffer, decompress->buffer_size);
- z_stream_ptr->avail_out = HTTP_DECOMPRESS_BUFFER_SIZE;
- z_stream_ptr->next_out = (unsigned char *)decompress->buffer + total_have;
- *outdata = decompress->buffer;
- *outdata_len = total_have;
- no_buffer = 1;
- }
- else
- {
- *outdata = decompress->buffer;
- *outdata_len = total_have;
- no_buffer = 0;
- }
- }
- else
- {
- break;
- }
- if (Z_STREAM_END == ret)
- {
- break;
- }
- } while (no_buffer == 1);
- return 0;
-}
-
-static int http_content_decompress_write_br(struct http_content_decompress *decompress,
- const char *indata, size_t indata_len,
- char **outdata, size_t *outdata_len)
-{
- size_t available_in = indata_len;
- const unsigned char *next_in = (const unsigned char *)indata;
- size_t available_out = HTTP_DECOMPRESS_BUFFER_SIZE;
- unsigned char *next_out = (unsigned char *)decompress->buffer;
-
- *outdata = NULL;
- *outdata_len = 0;
- size_t total_have = 0;
- int no_buffer;
-
- do
- {
- int ret = BrotliDecoderDecompressStream(decompress->br_state, &available_in,
- &next_in, &available_out, &next_out, NULL);
- if (ret == BROTLI_DECODER_RESULT_ERROR)
- {
- // BrotliDecoderErrorCode errcode = BrotliDecoderGetErrorCode(decompress->br_state);
- *outdata = NULL;
- *outdata_len = 0;
- return -1;
- }
- size_t have = HTTP_DECOMPRESS_BUFFER_SIZE - available_out;
- if (have > 0)
- {
- total_have += have;
- if (0 == available_out)
- {
- decompress->buffer_size += HTTP_DECOMPRESS_BUFFER_SIZE;
- decompress->buffer = REALLOC(char, decompress->buffer, decompress->buffer_size);
- available_out = HTTP_DECOMPRESS_BUFFER_SIZE;
- next_out = (unsigned char *)decompress->buffer + total_have;
- *outdata = decompress->buffer;
- *outdata_len = total_have;
- no_buffer = 1;
- }
- else
- {
- *outdata = decompress->buffer;
- *outdata_len = have;
- no_buffer = 0;
- }
- }
- else
- {
- break;
- }
- } while (no_buffer == 1);
- return 0;
-}
-
-int http_content_decompress_write(struct http_content_decompress *decompress,
- const char *indata, size_t indata_len,
- char **outdata, size_t *outdata_len)
-{
- assert(decompress);
- assert(indata);
- assert(indata_len > 0);
- assert(outdata);
- assert(outdata_len);
- *outdata = NULL;
- *outdata_len = 0;
-
- if (NULL == decompress->buffer)
- {
- decompress->buffer = CALLOC(char, HTTP_DECOMPRESS_BUFFER_SIZE);
- assert(decompress->buffer);
- decompress->buffer_size = HTTP_DECOMPRESS_BUFFER_SIZE;
- }
-
- if (decompress->encoding == HTTP_CONTENT_ENCODING_GZIP ||
- decompress->encoding == HTTP_CONTENT_ENCODING_DEFLATE)
- {
- return http_content_decompress_write_zlib(decompress, indata, indata_len, outdata, outdata_len);
- }
- if (decompress->encoding == HTTP_CONTENT_ENCODING_BR)
- {
- return http_content_decompress_write_br(decompress, indata, indata_len, outdata, outdata_len);
- }
- assert(0);
- return -1;
-} \ No newline at end of file
diff --git a/decoders/http/http_decoder.c b/decoders/http/http_decoder.c
index 10f8369..39406a3 100644
--- a/decoders/http/http_decoder.c
+++ b/decoders/http/http_decoder.c
@@ -1,1205 +1,184 @@
-#include "stellar/http.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include "http_decoder_private.h"
-
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-
-struct http_message *http_message_new(enum http_message_type type, struct http_decoder_result_queue *queue,
- int queue_index, uint8_t flow_type)
-{
- struct http_message *msg = CALLOC(struct http_message, 1);
- msg->type = type;
- msg->ref_queue = queue;
- msg->queue_index = queue_index;
- msg->flow_type = flow_type;
- return msg;
-}
-
-struct http_message *http_body_message_new(enum http_message_type type, struct http_decoder_result_queue *queue,
- int queue_index, uint8_t flow_type, hstring *raw_payload, hstring *decompress_payload)
-{
- struct http_message *msg = CALLOC(struct http_message, 1);
- msg->type = type;
- msg->ref_queue = queue;
- msg->queue_index = queue_index;
- msg->flow_type = flow_type;
- if (raw_payload)
- {
- msg->raw_payload.iov_base = raw_payload->iov_base;
- msg->raw_payload.iov_len = raw_payload->iov_len;
- }
- if (decompress_payload)
- {
- msg->decompress_payload.iov_base = decompress_payload->iov_base;
- msg->decompress_payload.iov_len = decompress_payload->iov_len;
- }
- return msg;
-}
-
-static void http_message_decompress_buffer_free(struct http_message *msg)
-{
- struct http_decoder_half_data *ref_data = NULL;
- if (HTTP_MESSAGE_REQ_BODY_START == msg->type || HTTP_MESSAGE_REQ_BODY == msg->type || HTTP_MESSAGE_REQ_BODY_END == msg->type)
- {
- ref_data = msg->ref_queue->array[msg->queue_index].req_data;
- }
- else if (HTTP_MESSAGE_RES_BODY_START == msg->type || HTTP_MESSAGE_RES_BODY == msg->type || HTTP_MESSAGE_RES_BODY_END == msg->type)
- {
- ref_data = msg->ref_queue->array[msg->queue_index].res_data;
- }
- if (ref_data != NULL && msg->decompress_payload.iov_base != NULL)
- {
- http_half_decompress_buffer_free(ref_data, &msg->decompress_payload);
- }
-}
-
-static void http_message_free(void *http_msg, void *cb_arg)
-{
- if (http_msg)
- {
- http_message_decompress_buffer_free((struct http_message *)http_msg);
- FREE(http_msg);
- }
-}
-
-static void http_event_handler(enum http_event event, struct http_decoder_half_data **data,
- struct http_event_context *ev_ctx, void *httpd_plugin_env)
-{
- assert(ev_ctx);
- assert(httpd_plugin_env);
- struct http_decoder_env *httpd_env = (struct http_decoder_env *)httpd_plugin_env;
- size_t queue_idx = 0;
- nmx_pool_t *mempool = ev_ctx->ref_mempool;
- struct http_decoder_result_queue *queue = ev_ctx->ref_queue;
- struct http_message *msg = NULL;
- struct http_decoder_half_data *half_data = NULL;
- int ret = 0;
- u_int8_t flow_flag = 0;
- struct http_decoder_exdata *exdata = ev_ctx->ref_httpd_ctx;
-
- int thread_id = stellar_get_current_thread_index();
-
- if (http_event_is_req(event))
- {
- queue_idx = http_decoder_result_queue_req_index(queue);
- half_data = http_decoder_result_queue_peek_req(queue);
- }
- else
- {
- queue_idx = http_decoder_result_queue_res_index(queue);
- half_data = http_decoder_result_queue_peek_res(queue);
- }
-
- switch (event)
- {
- case HTTP_EVENT_REQ_INIT:
- half_data = http_decoder_result_queue_peek_req(queue);
- if (half_data != NULL)
- {
- http_decoder_result_queue_inc_req_index(queue);
- }
-
- half_data = http_decoder_result_queue_peek_req(queue);
- if (half_data != NULL)
- {
- half_data = http_decoder_result_queue_pop_req(queue);
- http_decoder_half_data_free(mempool, half_data);
- half_data = NULL;
- }
-
- half_data = http_decoder_half_data_new(mempool);
- ret = http_decoder_result_queue_push_req(queue, half_data);
- if (ret < 0)
- {
- fprintf(stderr, "http_decoder_result_queue_push req failed.");
- http_decoder_half_data_free(mempool, half_data);
- half_data = NULL;
- }
- *data = half_data;
- queue_idx = http_decoder_result_queue_req_index(queue); // get the index after inc
- /* llhttp always call on_message_begin() even if llhttp_execute() error!!! */
- msg = http_message_new(HTTP_TRANSACTION_START, queue, queue_idx, HTTP_REQUEST);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_TRANSACTION_NEW, 1);
- break;
- case HTTP_EVENT_REQ_LINE:
- msg = http_message_new(HTTP_MESSAGE_REQ_LINE, queue, queue_idx, HTTP_REQUEST);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- if (httpd_tunnel_identify(httpd_env, FLOW_TYPE_C2S, half_data))
- {
- exdata->tunnel_state = HTTP_TUN_C2S_HDR_START;
- // http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTPD_STAT_TUNNEL, 1);
- }
- if (httpd_is_tunnel_session(httpd_env, exdata))
- {
- http_decoder_get_url(half_data, mempool);
- }
- break;
- case HTTP_EVENT_REQ_HDR:
- msg = http_message_new(HTTP_MESSAGE_REQ_HEADER, queue, queue_idx, HTTP_REQUEST);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- break;
- case HTTP_EVENT_REQ_HDR_END:
- {
- http_decoder_join_url_finally(ev_ctx, half_data, mempool);
- /* maybe some parsed headers in buffer, but has not pushed to plugins yet */
-
- if (http_decoder_half_data_has_parsed_header(half_data))
- {
- msg = http_message_new(HTTP_MESSAGE_REQ_HEADER, queue, queue_idx, HTTP_REQUEST);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- }
- http_half_data_update_commit_index(half_data);
- msg = http_message_new(HTTP_MESSAGE_REQ_HEADER_END, queue, queue_idx, HTTP_REQUEST);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
-
- int tot_c2s_headers = http_half_data_get_total_parsed_header_count(half_data);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_HEADERS, tot_c2s_headers);
-
- const char *tmp_url = NULL;
- size_t tmp_url_len = 0;
- http_half_data_get_url(half_data, &tmp_url, &tmp_url_len);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_URL_BYTES, tmp_url_len);
- }
- break;
- case HTTP_EVENT_REQ_BODY_BEGIN:
- msg = http_message_new(HTTP_MESSAGE_REQ_BODY_START, queue, queue_idx, HTTP_REQUEST);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- break;
- case HTTP_EVENT_REQ_BODY_DATA:
- {
- hstring raw_body = {};
- hstring decompress_body = {};
- http_decoder_half_data_get_raw_body(half_data, (const char **)&raw_body.iov_base, &raw_body.iov_len);
- http_half_get_lastest_decompress_buffer(half_data, &decompress_body);
- msg = http_body_message_new(HTTP_MESSAGE_REQ_BODY, queue, queue_idx, HTTP_REQUEST, &raw_body, &decompress_body);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- if (decompress_body.iov_base != NULL)
- {
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_ZIP_BYTES, raw_body.iov_len);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_UNZIP_BYTES, decompress_body.iov_len);
- }
- }
- break;
- case HTTP_EVENT_REQ_BODY_END:
- msg = http_message_new(HTTP_MESSAGE_REQ_BODY_END, queue, queue_idx, HTTP_REQUEST);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- break;
- case HTTP_EVENT_REQ_END:
- {
- session_is_symmetric(ev_ctx->ref_session, &flow_flag);
-
- if (SESSION_SEEN_C2S_FLOW == flow_flag)
- {
- msg = http_message_new(HTTP_TRANSACTION_END, queue, queue_idx, HTTP_REQUEST);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_TRANSACTION_FREE, 1);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_ASYMMETRY_TRANSACTION, 1);
- }
- if (httpd_is_tunnel_session(httpd_env, exdata))
- {
- if (SESSION_SEEN_C2S_FLOW == flow_flag)
- {
- exdata->tunnel_state = HTTP_TUN_INNER_STARTING;
- exdata->pub_topic_id = httpd_env->topic_exdata_compose[HTTPD_TOPIC_HTTP_TUNNEL_INDEX].sub_topic_id;
- }
- else
- {
- exdata->tunnel_state = HTTP_TUN_C2S_END;
- }
- }
- http_half_update_state(half_data, event);
- http_decoder_result_queue_inc_req_index(queue);
- half_data = http_decoder_result_queue_pop_req(queue);
- if (half_data != NULL)
- {
- http_decoder_half_data_free(mempool, half_data);
- half_data = NULL;
- }
- }
- break;
-
- case HTTP_EVENT_RES_INIT:
- half_data = http_decoder_result_queue_peek_res(queue);
- if (half_data != NULL)
- {
- http_decoder_result_queue_inc_res_index(queue);
- }
-
- half_data = http_decoder_result_queue_peek_res(queue);
- if (half_data != NULL)
- {
- half_data = http_decoder_result_queue_pop_res(queue);
- http_decoder_half_data_free(mempool, half_data);
- half_data = NULL;
- }
-
- half_data = http_decoder_half_data_new(mempool);
- ret = http_decoder_result_queue_push_res(queue, half_data);
- if (ret < 0)
- {
- fprintf(stderr, "http_decoder_result_queue_push res failed.");
- http_decoder_half_data_free(mempool, half_data);
- half_data = NULL;
- }
- queue_idx = http_decoder_result_queue_res_index(queue); // get the index after inc
- *data = half_data;
- if (0 == session_is_symmetric(ev_ctx->ref_session, &flow_flag))
- {
- if (SESSION_SEEN_S2C_FLOW == flow_flag)
- {
- msg = http_message_new(HTTP_TRANSACTION_START, queue, queue_idx, HTTP_RESPONSE);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- }
- }
- break;
- case HTTP_EVENT_RES_LINE:
- msg = http_message_new(HTTP_MESSAGE_RES_LINE, queue, queue_idx, HTTP_RESPONSE);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- if (httpd_tunnel_identify(httpd_env, FLOW_TYPE_S2C, half_data))
- {
- exdata->tunnel_state = HTTP_TUN_S2C_START;
- }
- else
- {
- // connect response fail, reset tunnel_state
- exdata->tunnel_state = HTTP_TUN_NON;
- }
- break;
- case HTTP_EVENT_RES_HDR:
- msg = http_message_new(HTTP_MESSAGE_RES_HEADER, queue, queue_idx, HTTP_RESPONSE);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- break;
- case HTTP_EVENT_RES_HDR_END:
- {
- /* maybe some header in table buffer but has not pushed to plugins */
- half_data = http_decoder_result_queue_peek_res(queue);
- if (http_decoder_half_data_has_parsed_header(half_data))
- {
- msg = http_message_new(HTTP_MESSAGE_RES_HEADER, queue, queue_idx, HTTP_RESPONSE);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- }
- http_half_data_update_commit_index(half_data);
- msg = http_message_new(HTTP_MESSAGE_RES_HEADER_END, queue, queue_idx, HTTP_RESPONSE);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
-
- int tot_s2c_headers = http_half_data_get_total_parsed_header_count(half_data);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_HEADERS, tot_s2c_headers);
-
- if (httpd_is_tunnel_session(httpd_env, exdata))
- {
- exdata->tunnel_state = HTTP_TUN_INNER_STARTING;
- http_half_pre_context_free(ev_ctx->ref_session, exdata);
- exdata->pub_topic_id = httpd_env->topic_exdata_compose[HTTPD_TOPIC_HTTP_TUNNEL_INDEX].sub_topic_id;
- }
- }
- break;
- case HTTP_EVENT_RES_BODY_BEGIN:
- msg = http_message_new(HTTP_MESSAGE_RES_BODY_START, queue, queue_idx, HTTP_RESPONSE);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- break;
- case HTTP_EVENT_RES_BODY_DATA:
- {
- hstring raw_body = {};
- http_decoder_half_data_get_raw_body(half_data, (const char **)&raw_body.iov_base, &raw_body.iov_len);
- hstring decompress_body = {};
- http_half_get_lastest_decompress_buffer(half_data, &decompress_body);
- msg = http_body_message_new(HTTP_MESSAGE_RES_BODY, queue, queue_idx, HTTP_RESPONSE, &raw_body, &decompress_body);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- if (decompress_body.iov_base != NULL)
- {
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_ZIP_BYTES, raw_body.iov_len);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_UNZIP_BYTES, decompress_body.iov_len);
- }
- }
- break;
- case HTTP_EVENT_RES_BODY_END:
- msg = http_message_new(HTTP_MESSAGE_RES_BODY_END, queue, queue_idx, HTTP_RESPONSE);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- break;
- case HTTP_EVENT_RES_END:
- msg = http_message_new(HTTP_TRANSACTION_END, queue, queue_idx, HTTP_RESPONSE);
- session_mq_publish_message(ev_ctx->ref_session, exdata->pub_topic_id, msg);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_TRANSACTION_FREE, 1);
- session_is_symmetric(ev_ctx->ref_session, &flow_flag);
- if (SESSION_SEEN_S2C_FLOW == flow_flag)
- {
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_ASYMMETRY_TRANSACTION, 1);
- }
-
- http_half_update_state(half_data, event);
- http_decoder_result_queue_inc_res_index(queue);
- half_data = http_decoder_result_queue_pop_res(queue);
- if (half_data != NULL)
- {
- http_decoder_half_data_free(mempool, half_data);
- half_data = NULL;
- }
- break;
- default:
- assert(0);
- break;
- }
- if (half_data)
- {
- http_half_update_state(half_data, event);
- }
-}
+#include "stellar/utils.h"
+#include "stellar/http.h"
+#include "stellar/session.h"
+#include "http_decoder.h"
+#include "http_decoder_utils.h"
+#include "http_decoder_stat.h"
+#include "http_decoder_half.h"
-static struct http_decoder *http_decoder_new(struct http_decoder_exdata *hd_ctx, nmx_pool_t *mempool,
- http_event_cb *ev_cb, int decompress_switch, struct http_decoder_env *httpd_env,
- long long req_start_seq, long long res_start_seq)
+static struct http_decoder *http_decoder_new(void)
{
- struct http_decoder *decoder = MEMPOOL_CALLOC(mempool, struct http_decoder, 1);
- assert(decoder);
- decoder->c2s_half = http_decoder_half_new(hd_ctx, mempool, ev_cb, HTTP_REQUEST, decompress_switch, httpd_env, req_start_seq);
- decoder->s2c_half = http_decoder_half_new(hd_ctx, mempool, ev_cb, HTTP_RESPONSE, decompress_switch, httpd_env, res_start_seq);
+ struct http_decoder *decoder = (struct http_decoder *)calloc(1, sizeof(struct http_decoder));
return decoder;
}
-static void http_decoder_free(nmx_pool_t *mempool, struct http_decoder *decoder)
+static void http_decoder_free(struct http_decoder *decoder)
{
if (NULL == decoder)
{
return;
}
- if (decoder->c2s_half != NULL)
+ if (decoder->flow_c2s)
{
- http_decoder_half_free(mempool, decoder->c2s_half);
- decoder->c2s_half = NULL;
+ http_half_free(decoder->flow_c2s);
}
- if (decoder->s2c_half != NULL)
+ if (decoder->flow_s2c)
{
- http_decoder_half_free(mempool, decoder->s2c_half);
- decoder->s2c_half = NULL;
+ http_half_free(decoder->flow_s2c);
}
- MEMPOOL_FREE(mempool, decoder);
-}
-
-static struct http_decoder_exdata *http_decoder_exdata_new(size_t mempool_size, size_t queue_size,
- int decompress_switch, struct http_decoder_env *httpd_env,
- long long req_start_seq, long long res_start_seq)
-{
- struct http_decoder_exdata *hd_ctx = CALLOC(struct http_decoder_exdata, 1);
- hd_ctx->mempool = nmx_create_pool(mempool_size);
- hd_ctx->decoder = http_decoder_new(hd_ctx, hd_ctx->mempool, http_event_handler, decompress_switch,
- httpd_env, req_start_seq, res_start_seq);
- hd_ctx->queue = http_decoder_result_queue_new(hd_ctx->mempool, queue_size);
- return hd_ctx;
+ free(decoder);
}
-static void http_decoder_exdata_free(struct http_decoder_exdata *ex_data)
+static struct http_exdata *http_session_new(struct session *sess, struct http *http_env,
+ const char *tcp_payload, uint32_t tcp_payload_len)
{
- if (unlikely(NULL == ex_data))
- {
- return;
- }
- if (ex_data->decoder != NULL)
- {
- http_decoder_free(ex_data->mempool, ex_data->decoder);
- ex_data->decoder = NULL;
- }
- if (ex_data->queue != NULL)
+ struct http_exdata *exdata = (struct http_exdata *)calloc(1, sizeof(struct http_exdata));
+ session_set_exdata(sess, http_env->exdata_id, exdata);
+ exdata->sess = sess;
+ exdata->http_env = http_env;
+ size_t http_identify_len = MIN(tcp_payload_len, HTTP_IDENTIFY_LEN);
+ int ret = http_protocol_identify(tcp_payload, http_identify_len);
+ if (ret < 0)
{
- http_decoder_result_queue_free(ex_data->mempool, ex_data->queue);
- ex_data->queue = NULL;
+ STELLAR_LOG_DEBUG(http_env->logger_ref, HTTP_MODULE_NAME,
+ "http identify error, ignore this session: %s", session_get_readable_addr(sess));
+ exdata->ignore_session = 1;
+ return exdata;
}
- if (ex_data->mempool)
- {
- nmx_destroy_pool(ex_data->mempool);
- }
- FREE(ex_data);
-}
-
-static int http_protocol_identify(const char *data, size_t data_len)
-{
- llhttp_t parser;
- llhttp_settings_t settings;
- enum llhttp_errno error;
-
- llhttp_settings_init(&settings);
- llhttp_init(&parser, HTTP_BOTH, &settings);
-
- error = llhttp_execute(&parser, data, data_len);
- if (error != HPE_OK)
- {
- return -1;
- }
- return 1;
-}
-
-static void _http_decoder_context_free(struct http_decoder_env *env)
-{
- if (NULL == env)
- {
- return;
- }
-
- http_decoder_stat_free(&env->hd_stat);
-
- for (int i = 0; i < HTTPD_TOPIC_INDEX_MAX; i++)
- {
- if (env->topic_exdata_compose[i].msg_free_cb)
- {
- stellar_mq_destroy_topic(env->st, env->topic_exdata_compose[i].sub_topic_id);
- }
- }
-
- FREE(env);
-}
-
-static int load_http_decoder_config(const char *cfg_path,
- struct http_decoder_config *hd_cfg)
-{
- FILE *fp = fopen(cfg_path, "r");
- if (NULL == fp)
- {
- fprintf(stderr, "[%s:%d]Can't open config file:%s",
- __FUNCTION__, __LINE__, cfg_path);
- return -1;
- }
-
- int ret = 0;
- char errbuf[256] = {0};
-
- toml_table_t *root = toml_parse_file(fp, errbuf, sizeof(errbuf));
- fclose(fp);
-
- toml_table_t *basic_sec_tbl = toml_table_in(root, "basic");
- if (NULL == basic_sec_tbl)
- {
- fprintf(stderr, "[%s:%d]config file:%s has no key: [basic]",
- __FUNCTION__, __LINE__, cfg_path);
- toml_free(root);
- return -1;
- }
-
- toml_datum_t int_val = toml_int_in(basic_sec_tbl, "decompress");
- if (int_val.ok != 0)
- {
- hd_cfg->decompress_switch = int_val.u.b;
- }
-
- int_val = toml_int_in(basic_sec_tbl, "mempool_size");
- if (int_val.ok != 0)
- {
- hd_cfg->mempool_size = int_val.u.i;
- }
- else
- {
- hd_cfg->mempool_size = DEFAULT_MEMPOOL_SIZE;
- }
-
- int_val = toml_int_in(basic_sec_tbl, "result_queue_len");
- if (int_val.ok != 0)
- {
- hd_cfg->result_queue_len = int_val.u.i;
- }
- else
- {
- hd_cfg->result_queue_len = HD_RESULT_QUEUE_LEN;
- }
-
- int_val = toml_int_in(basic_sec_tbl, "stat_interval_pkts");
- if (int_val.ok != 0)
- {
- hd_cfg->stat_interval_pkts = int_val.u.i;
- }
- else
- {
- hd_cfg->stat_interval_pkts = DEFAULT_STAT_INTERVAL_PKTS;
- }
-
- int_val = toml_int_in(basic_sec_tbl, "stat_output_interval");
- if (int_val.ok != 0)
- {
- hd_cfg->stat_output_interval = int_val.u.i;
- }
- else
- {
- hd_cfg->stat_output_interval = DEFAULT_STAT_OUTPUT_INTERVAL;
- }
-
- int_val = toml_int_in(basic_sec_tbl, "proxy_enable");
- if (int_val.ok != 0)
- {
- hd_cfg->proxy_enable = int_val.u.i;
- }
- else
- {
- hd_cfg->proxy_enable = 0;
- }
-
- toml_free(root);
- return ret;
-}
-
-static int http_msg_get_request_header(const struct http_message *msg, const char *name, size_t name_len,
- struct http_header_field *hdr_result)
-{
- const struct http_decoder_half_data *req_data =
- msg->ref_queue->array[msg->queue_index].req_data;
- return http_decoder_half_data_get_header(req_data, name, name_len, hdr_result);
-}
-
-static int http_msg_get_response_header(const struct http_message *msg, const char *name, size_t name_len,
- struct http_header_field *hdr_result)
-{
- const struct http_decoder_half_data *res_data =
- msg->ref_queue->array[msg->queue_index].res_data;
- return http_decoder_half_data_get_header(res_data, name, name_len, hdr_result);
-}
-
-static int http_msg_request_header_next(const struct http_message *msg,
- struct http_header_field *hdr)
-{
- const struct http_decoder_half_data *req_data =
- msg->ref_queue->array[msg->queue_index].req_data;
- return http_decoder_half_data_iter_header((struct http_decoder_half_data *)req_data, hdr);
-}
-
-static int http_msg_response_header_next(const struct http_message *msg, struct http_header_field *hdr)
-{
- const struct http_decoder_half_data *res_data =
- msg->ref_queue->array[msg->queue_index].res_data;
- return http_decoder_half_data_iter_header((struct http_decoder_half_data *)res_data, hdr);
-}
-
-#if 0
-static int http_msg_get_request_raw_body(const struct http_message *msg, hstring *body)
-{
- const struct http_decoder_half_data *req_data =
- msg->ref_queue->array[msg->queue_index].req_data;
- return http_decoder_half_data_get_raw_body(req_data, body);
-}
-
-static int http_msg_get_response_raw_body(const struct http_message *msg, hstring *body)
-{
- const struct http_decoder_half_data *res_data =
- msg->ref_queue->array[msg->queue_index].res_data;
- return http_decoder_half_data_get_raw_body(res_data, body);
-}
-
-static int http_msg_get_request_decompress_body(const struct http_message *msg, hstring *body)
-{
- const struct http_decoder_half_data *req_data =
- msg->ref_queue->array[msg->queue_index].req_data;
- return http_decoder_half_data_get_decompress_body(req_data, body);
-}
-
-static int http_msg_get_response_decompress_body(const struct http_message *msg, hstring *body)
-{
- const struct http_decoder_half_data *res_data =
- msg->ref_queue->array[msg->queue_index].res_data;
- return http_decoder_half_data_get_decompress_body(res_data, body);
-}
-#endif
-
-static struct http_decoder_exdata *httpd_session_exdata_new(struct session *sess, struct http_decoder_env *httpd_env,
- long long req_start_seq, long long res_start_seq)
-{
- struct http_decoder_exdata *exdata = http_decoder_exdata_new(httpd_env->hd_cfg.mempool_size,
- httpd_env->hd_cfg.result_queue_len,
- httpd_env->hd_cfg.decompress_switch,
- httpd_env, req_start_seq, res_start_seq);
- // exdata->sub_topic_id = sub_topic_id;
- int thread_id = stellar_get_current_thread_index();
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_SESSION_NEW, 1);
+ exdata->decoder = http_decoder_new();
+ int thread_id = module_manager_get_thread_id(http_env->mod_mgr_ref);
+ http_stat_update(&http_env->stat, thread_id, HTTP_SESSION_NEW, 1);
+ STELLAR_LOG_INFO(http_env->logger_ref, HTTP_MODULE_NAME,
+ "http identify succ, session: %s", session_get_readable_addr(sess));
return exdata;
}
-#ifdef __cplusplus
-extern "C"
+static void http_decoder_execute(struct session *sess, struct http *http_env, struct http_exdata *exdata,
+ const char *tcp_payload, uint16_t tcp_payload_len)
{
-#endif
+ int thread_id = module_manager_get_thread_id(http_env->mod_mgr_ref);
+ enum flow_type flow_dir = session_get_flow_type(sess);
- void httpd_ex_data_free_cb(int idx, void *ex_data, void *arg)
+ http_stat_update_tcp_seg(&http_env->stat, thread_id, flow_dir, tcp_payload_len);
+ struct http_half *half = http_flow_get_nx(exdata, flow_dir, sess, http_env);
+ int ret = http_half_flow_process(half, tcp_payload, tcp_payload_len);
+ if (ret < 0)
{
- if (NULL == ex_data)
- {
- return;
- }
- struct http_decoder_exdata *exdata = (struct http_decoder_exdata *)ex_data;
- http_decoder_exdata_free(exdata);
- }
-
- void *httpd_session_ctx_new_cb(struct session *sess, void *plugin_env)
- {
- return (void *)HTTP_CTX_IS_HTTP;
- }
-
- void httpd_session_ctx_free_cb(struct session *sess, void *session_ctx, void *plugin_env)
- {
- if (NULL == plugin_env || NULL == session_ctx)
- {
- return;
- }
- if (strncmp((const char *)session_ctx, HTTP_CTX_NOT_HTTP, strlen(HTTP_CTX_NOT_HTTP)) == 0)
- {
- return;
- }
- struct http_decoder_env *httpd_env = (struct http_decoder_env *)plugin_env;
- int thread_id = stellar_get_current_thread_index();
- unsigned char flow_flag = 0;
- session_is_symmetric(sess, &flow_flag);
-
- if (SESSION_SEEN_C2S_FLOW == flow_flag)
- {
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_ASYMMETRY_SESSION, 1);
- }
- else if (SESSION_SEEN_S2C_FLOW == flow_flag)
- {
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_ASYMMETRY_SESSION, 1);
- }
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_SESSION_FREE, 1);
- }
-
- static void http_decoder_execute(struct session *sess, struct http_decoder_env *httpd_env, struct http_decoder_exdata *exdata, const char *payload, uint16_t payload_len)
- {
- if (httpd_in_tunnel_transmitting(httpd_env, exdata))
- {
- http_decoder_push_tunnel_data(sess, exdata, httpd_tunnel_state_to_msg(exdata), payload, payload_len);
- httpd_tunnel_state_update(exdata);
- return;
- }
-
- int thread_id = stellar_get_current_thread_index();
- struct http_decoder_half *cur_half = NULL;
- enum flow_type sess_dir = session_get_flow_type(sess);
- if (FLOW_TYPE_C2S == sess_dir)
- {
- cur_half = exdata->decoder->c2s_half;
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_BYTES, payload_len);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_C2S_TCP_SEG, 1);
- }
- else
- {
- cur_half = exdata->decoder->s2c_half;
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_BYTES, payload_len);
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_S2C_TCP_SEG, 1);
- }
-
- http_decoder_half_reinit(cur_half, exdata->queue, exdata->mempool, sess);
- int ret = http_decoder_half_parse(httpd_env->hd_cfg.proxy_enable, cur_half, payload, payload_len);
- if (ret < 0)
- {
- http_decoder_stat_update(&httpd_env->hd_stat, thread_id, HTTP_STAT_PARSE_ERR, 1);
- stellar_session_plugin_dettach_current_session(sess);
- }
- }
-
- void http_decoder_tunnel_msg_cb(struct session *sess, int topic_id, const void *tmsg, void *per_session_ctx, void *plugin_env)
- {
- struct http_decoder_env *httpd_env = (struct http_decoder_env *)plugin_env;
- if (0 == httpd_env->hd_cfg.proxy_enable)
- {
- return;
- }
- hstring tunnel_payload;
- http_tunnel_message_get_payload((const struct http_tunnel_message *)tmsg, &tunnel_payload);
- uint16_t payload_len = tunnel_payload.iov_len;
- const char *payload = (char *)tunnel_payload.iov_base;
- if (NULL == payload || 0 == payload_len)
- {
- return;
- }
-
- struct http_decoder_exdata *exdata = (struct http_decoder_exdata *)session_exdata_get(sess, httpd_env->topic_exdata_compose[HTTPD_TOPIC_HTTP_TUNNEL_INDEX].exdata_id);
- enum http_tunnel_message_type tmsg_type = http_tunnel_message_type_get((const struct http_tunnel_message *)tmsg);
-
- switch (tmsg_type)
- {
- case HTTP_TUNNEL_OPENING:
- {
- if (NULL != exdata)
- {
- // not support nested http tunnel
- session_mq_ignore_message(sess, topic_id, httpd_env->plugin_id);
- return;
- }
- size_t http_identify_len = payload_len > HTTP_IDENTIFY_LEN ? HTTP_IDENTIFY_LEN : payload_len;
- int is_http = http_protocol_identify(payload, http_identify_len);
- if (is_http)
- {
- long long max_req_seq = 0, max_res_seq = 0;
- struct http_decoder_exdata *tcp_stream_exdata = (struct http_decoder_exdata *)session_exdata_get(sess, httpd_env->topic_exdata_compose[HTTPD_TOPIC_TCP_STREAM_INDEX].exdata_id);
- http_half_get_max_transaction_seq(tcp_stream_exdata, &max_req_seq, &max_res_seq);
- exdata = httpd_session_exdata_new(sess, httpd_env, max_req_seq, max_res_seq);
- session_exdata_set(sess, httpd_env->topic_exdata_compose[HTTPD_TOPIC_HTTP_TUNNEL_INDEX].exdata_id, exdata);
- exdata->pub_topic_id = httpd_env->topic_exdata_compose[HTTPD_TOPIC_HTTP_MSG_INDEX].sub_topic_id;
- exdata->in_tunnel_is_http = 1;
- }
- else
- {
- // inner tunnel is not http, do nothing, do not push this message again !!!
- session_mq_ignore_message(sess, topic_id, httpd_env->plugin_id);
- return;
- }
- }
- break;
-
- case HTTP_TUNNEL_ACTIVE:
- if (NULL == exdata)
- {
- session_mq_ignore_message(sess, topic_id, httpd_env->plugin_id);
- http_decoder_stat_update(&httpd_env->hd_stat, stellar_get_current_thread_index(), HTTP_STAT_PARSE_ERR, 1);
- return;
- }
- break;
-
- case HTTP_TUNNEL_CLOSING:
- if (NULL == exdata)
- {
- http_decoder_stat_update(&httpd_env->hd_stat, stellar_get_current_thread_index(), HTTP_STAT_PARSE_ERR, 1);
- return;
- }
- if (exdata->in_tunnel_is_http)
- {
- http_half_pre_context_free(sess, exdata);
- }
- return;
- break;
-
- default:
- break;
- }
- if (exdata->in_tunnel_is_http)
- {
- http_decoder_execute(sess, httpd_env, exdata, payload, payload_len);
- }
+ STELLAR_LOG_WARN(http_env->logger_ref, HTTP_MODULE_NAME,
+ "llhttp parse error, ignore this session: %s", session_get_readable_addr(sess));
+ http_stat_update(&http_env->stat, thread_id, HTTP_STAT_PARSE_ERR, 1);
+ exdata->ignore_session = 1;
return;
}
-
-static void http_decoder_on_session_free(struct session *sess,void *per_session_ctx, void *plugin_env)
-{
- struct http_decoder_env *httpd_env = (struct http_decoder_env *)plugin_env;
- struct http_decoder_exdata *exdata = (struct http_decoder_exdata *)session_exdata_get(sess, httpd_env->topic_exdata_compose[HTTPD_TOPIC_TCP_STREAM_INDEX].exdata_id);
- if (httpd_in_tunnel_transmitting(httpd_env, exdata))
- {
- http_decoder_push_tunnel_data(sess, exdata, HTTP_TUNNEL_CLOSING, NULL, 0);
- }
- else
- {
- http_half_pre_context_free(sess, exdata);
- }
- return;
}
- void http_decoder_tcp_stream_msg_cb(struct session *sess, int topic_id, const void *msg, void *nouse_session_ctx, void *plugin_env)
- {
- struct http_decoder_env *httpd_env = (struct http_decoder_env *)plugin_env;
- struct http_decoder_exdata *exdata = (struct http_decoder_exdata *)session_exdata_get(sess, httpd_env->topic_exdata_compose[HTTPD_TOPIC_TCP_STREAM_INDEX].exdata_id);
- const char *payload = NULL;
- uint16_t payload_len = 0;
- assert(msg != NULL);
-
- payload_len = tcp_segment_get_len((struct tcp_segment *)msg);
- payload = tcp_segment_get_data((const struct tcp_segment *)msg);
- if (unlikely(0 == payload_len || NULL == payload))
- {
- return;
- }
- if (NULL == exdata) // first packet
- {
- size_t http_identify_len = payload_len > HTTP_IDENTIFY_LEN ? HTTP_IDENTIFY_LEN : payload_len;
- int ret = http_protocol_identify(payload, http_identify_len);
- if (ret < 0)
- {
- stellar_session_plugin_dettach_current_session(sess);
- return;
- }
- exdata = httpd_session_exdata_new(sess, httpd_env, 0, 0);
- exdata->pub_topic_id = httpd_env->topic_exdata_compose[HTTPD_TOPIC_HTTP_MSG_INDEX].sub_topic_id;
- session_exdata_set(sess, httpd_env->topic_exdata_compose[HTTPD_TOPIC_TCP_STREAM_INDEX].exdata_id, exdata);
- }
- http_decoder_execute(sess, httpd_env, exdata, payload, payload_len);
- return;
- }
-
- static const struct http_topic_exdata_compose g_topic_exdata_compose[HTTPD_TOPIC_INDEX_MAX] =
- {
- {HTTPD_TOPIC_TCP_STREAM_INDEX, TOPIC_TCP_STREAM, http_decoder_tcp_stream_msg_cb, NULL, "HTTP_DECODER_EXDATA_BASEON_TCP_STREAM", httpd_ex_data_free_cb, -1, -1},
- {HTTPD_TOPIC_HTTP_MSG_INDEX, HTTP_TOPIC, NULL, http_message_free, NULL, NULL, -1, -1},
- {HTTPD_TOPIC_HTTP_TUNNEL_INDEX, HTTP_DECODER_TUNNEL_TOPIC, http_decoder_tunnel_msg_cb, http_message_free, "HTTP_DECODER_EXDATA_BASEON_HTTP_TUNNEL", httpd_ex_data_free_cb, -1, -1},
- };
-
- static void http_decoder_topic_exdata_compose_init(struct http_decoder_env *httpd_env)
+void http_message_free_cb(void *msg, void *msg_free_arg UNUSED)
+{
+ struct http_message *hmsg = (struct http_message *)msg;
+ struct http_half_data *flow_data = hmsg->flow_data;
+ if (hmsg->topic_type == HTTP_TOPIC_REQ_HEADER || hmsg->topic_type == HTTP_TOPIC_RES_HEADER)
{
- memcpy(httpd_env->topic_exdata_compose, g_topic_exdata_compose, sizeof(g_topic_exdata_compose));
- for (int i = 0; i < HTTPD_TOPIC_INDEX_MAX; i++)
+ if (flow_data)
{
- httpd_env->topic_exdata_compose[i].sub_topic_id = stellar_session_mq_get_topic_id_reliable(httpd_env->st,
- httpd_env->topic_exdata_compose[i].topic_name,
- httpd_env->topic_exdata_compose[i].msg_free_cb,
- NULL);
- assert(httpd_env->topic_exdata_compose[i].sub_topic_id >= 0);
-
- if (httpd_env->topic_exdata_compose[i].exdata_name)
+ if (flow_data->ut_filed_array)
{
- httpd_env->topic_exdata_compose[i].exdata_id = stellar_exdata_new_index(httpd_env->st,
- httpd_env->topic_exdata_compose[i].exdata_name,
- httpd_env->topic_exdata_compose[i].exdata_free_cb,
- NULL);
- assert(httpd_env->topic_exdata_compose[i].exdata_id >= 0);
+ utarray_free(flow_data->ut_filed_array);
+ flow_data->ut_filed_array = NULL;
}
-
- if (httpd_env->topic_exdata_compose[i].on_msg_cb)
+ if (flow_data->joint_url.iov_base)
{
- stellar_session_mq_subscribe(httpd_env->st, httpd_env->topic_exdata_compose[i].sub_topic_id,
- httpd_env->topic_exdata_compose[i].on_msg_cb, httpd_env->plugin_id);
+ free(flow_data->joint_url.iov_base);
+ flow_data->joint_url.iov_base = NULL;
}
- }
- }
-
- int http_topic_exdata_compose_get_index(const struct http_decoder_env *httpd_env, int by_topic_id)
- {
- for (int i = 0; i < HTTPD_TOPIC_INDEX_MAX; i++)
- {
- if (httpd_env->topic_exdata_compose[i].sub_topic_id == by_topic_id)
+ if (flow_data->cached_header_buffer != NULL)
{
- return i;
+ assert(flow_data->cached_header_buffer->reference > 0);
+ flow_data->cached_header_buffer->reference--;
+ if (flow_data->cached_header_buffer->reference == 0)
+ {
+ free(flow_data->cached_header_buffer->buffer);
+ free(flow_data->cached_header_buffer);
+ flow_data->cached_header_buffer = NULL;
+ }
}
}
- assert(0);
- return -1;
- }
-
- void *http_decoder_init(struct stellar *st)
- {
- int thread_num = 0;
-
- struct http_decoder_env *httpd_env = CALLOC(struct http_decoder_env, 1);
- int ret = load_http_decoder_config(HTTPD_CFG_FILE, &httpd_env->hd_cfg);
- if (ret < 0)
- {
- goto failed;
- }
- httpd_env->st = st;
- httpd_env->plugin_id = stellar_plugin_register(st, httpd_session_ctx_new_cb,
- httpd_session_ctx_free_cb, NULL,http_decoder_on_session_free,(void *)httpd_env);
- if (httpd_env->plugin_id < 0)
- {
- goto failed;
- }
- http_decoder_topic_exdata_compose_init(httpd_env);
-
- thread_num = stellar_get_worker_thread_num(st);
- assert(thread_num >= 1);
- if (http_decoder_stat_init(&httpd_env->hd_stat, thread_num,
- httpd_env->hd_cfg.stat_interval_pkts, httpd_env->hd_cfg.stat_output_interval) < 0)
- {
- goto failed;
- }
-
- return httpd_env;
-
- failed:
- fprintf(stderr, "http_decoder_init fail!\n");
- _http_decoder_context_free(httpd_env);
- return NULL;
- }
-
- void http_decoder_exit(void *plugin_env)
- {
- if (NULL == plugin_env)
- {
- return;
- }
- struct http_decoder_env *httpd_env = (struct http_decoder_env *)plugin_env;
- _http_decoder_context_free(httpd_env);
}
-
- enum http_message_type http_message_get_type(const struct http_message *msg)
+ if (hmsg->event == HTTP_EVENT_REQ_BODY_DATA || hmsg->event == HTTP_EVENT_RES_BODY_DATA)
{
- if (unlikely(NULL == msg))
+ if (flow_data->decompress_body.body != NULL)
{
- return HTTP_MESSAGE_MAX;
+ FREE(flow_data->decompress_body.body);
}
- return msg->type;
}
-
- void http_message_get0_request_line(const struct http_message *msg,
- struct http_request_line *line)
+ if (hmsg->event == HTTP_EVENT_REQ_END || hmsg->event == HTTP_EVENT_RES_END)
{
- if (unlikely(NULL == msg || msg->type != HTTP_MESSAGE_REQ_LINE))
+ if (flow_data)
{
- if (line)
- {
- line->method = NULL;
- line->uri = NULL;
- line->version = NULL;
- }
- return;
+ http_half_data_free(flow_data);
+ hmsg->flow_data = NULL;
}
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
-
- struct http_decoder_half_data *req_data =
- msg->ref_queue->array[msg->queue_index].req_data;
-
- http_decoder_half_data_get_request_line(req_data, line);
}
- void http_message_get0_response_line(const struct http_message *msg,
- struct http_response_line *line)
- {
- if (unlikely(NULL == msg || msg->type != HTTP_MESSAGE_RES_LINE))
- {
- if (line)
- {
- line->version = NULL;
- line->status = NULL;
- }
- return;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
-
- struct http_decoder_half_data *res_data =
- msg->ref_queue->array[msg->queue_index].res_data;
-
- http_decoder_half_data_get_response_line(res_data, line);
- }
+ free(hmsg);
+}
- void http_message_get0_header(const struct http_message *msg, const char *name, size_t name_len,
- struct http_header_field *hdr_result)
+void http_exdata_free_cb(UNUSED int idx, void *ex_data, UNUSED void *plugin_env)
+{
+ if (NULL == ex_data)
{
- int ret = -1;
- if (unlikely(NULL == msg || NULL == name || 0 == name_len))
- {
- goto fail;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- if (HTTP_MESSAGE_REQ_HEADER == msg->type)
- {
- ret = http_msg_get_request_header(msg, name, name_len, hdr_result);
- }
- else if (HTTP_MESSAGE_RES_HEADER == msg->type)
- {
- ret = http_msg_get_response_header(msg, name, name_len, hdr_result);
- }
- if (ret >= 0)
- {
- return;
- }
- fail:
- if (hdr_result)
- {
- hdr_result->name = NULL;
- hdr_result->value = NULL;
- }
return;
}
+ struct http_exdata *exdata = (struct http_exdata *)ex_data;
+ struct http *http_env = (struct http *)plugin_env;
- int http_message_get0_next_header(const struct http_message *msg, struct http_header_field *header)
+ if (exdata->ignore_session == 0)
{
- int ret = 1;
- if (unlikely(NULL == msg))
- {
- goto fail;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- if (HTTP_MESSAGE_REQ_HEADER == msg->type)
- {
- ret = http_msg_request_header_next(msg, header);
- }
- else if (HTTP_MESSAGE_RES_HEADER == msg->type)
- {
- ret = http_msg_response_header_next(msg, header);
- }
- if (ret < 0)
- {
- goto fail;
- }
- return 0;
- fail:
- if (header)
- {
- header->name = NULL;
- header->value = NULL;
- }
- return -1;
- }
-
- int http_message_reset_header_iter(struct http_message *msg)
- {
- if (unlikely(NULL == msg))
+ int thread_id = module_manager_get_thread_id(http_env->mod_mgr_ref);
+ unsigned char flow_flag = 0;
+ if (exdata->sess)
{
- return -1;
+ session_is_symmetric(exdata->sess, &flow_flag);
+ STELLAR_LOG_INFO(http_env->logger_ref, HTTP_MODULE_NAME,
+ "http session free: %s", session_get_readable_addr(exdata->sess));
}
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- if (HTTP_MESSAGE_REQ_HEADER == msg->type)
+ if (SESSION_SEEN_C2S_FLOW == flow_flag)
{
- struct http_decoder_half_data *req_data =
- msg->ref_queue->array[msg->queue_index].req_data;
- return http_decoder_half_data_reset_header_iter(req_data);
+ http_stat_update(&http_env->stat, thread_id, HTTP_C2S_ASYMMETRY_SESSION, 1);
}
- else if (HTTP_MESSAGE_RES_HEADER == msg->type)
+ else if (SESSION_SEEN_S2C_FLOW == flow_flag)
{
- struct http_decoder_half_data *res_data =
- msg->ref_queue->array[msg->queue_index].res_data;
- return http_decoder_half_data_reset_header_iter(res_data);
+ http_stat_update(&http_env->stat, thread_id, HTTP_S2C_ASYMMETRY_SESSION, 1);
}
- return -1;
+ http_stat_update(&http_env->stat, thread_id, HTTP_SESSION_FREE, 1);
}
+ http_decoder_free(exdata->decoder);
+ exdata->decoder = NULL;
+ free(exdata);
+}
- void http_message_get0_uncompressed_body(const struct http_message *msg, const char **body_ptr, size_t *body_len)
- {
- if (unlikely(NULL == msg))
- {
- goto fail;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- if (msg->raw_payload.iov_base != NULL && msg->raw_payload.iov_len != 0)
- {
- *body_ptr = msg->raw_payload.iov_base;
- *body_len = msg->raw_payload.iov_len;
- return;
- }
- fail:
- if (body_ptr)
- {
- *body_ptr = NULL;
- *body_len = 0;
- }
- return;
- }
+void http_on_tcp_stream_cb(struct session *sess, enum session_state state UNUSED, const char *tcp_payload, uint32_t tcp_payload_len, void *args)
+{
+ struct http *http_env = (struct http *)args;
+ struct http_exdata *exdata = (struct http_exdata *)session_get_exdata(sess, http_env->exdata_id);
- void http_message_get0_decompressed_body(const struct http_message *msg, const char **dec_body_ptr, size_t *dec_body_len)
+ if (unlikely(0 == tcp_payload_len || NULL == tcp_payload))
{
- enum http_content_encoding ecode = HTTP_CONTENT_ENCODING_NONE;
- struct http_decoder_half_data *ref_data = NULL;
- if (unlikely(NULL == msg))
- {
- goto fail;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- if (msg->decompress_payload.iov_base != NULL && msg->decompress_payload.iov_len != 0)
- {
- *dec_body_ptr = msg->decompress_payload.iov_base;
- *dec_body_len = msg->decompress_payload.iov_len;
- return;
- }
- /**
- * @brief If the body hasn't been compressed, same as http_message_get0_uncompressed_body().
- *
- */
-
- if (HTTP_MESSAGE_REQ_BODY_START == msg->type || HTTP_MESSAGE_REQ_BODY == msg->type || HTTP_MESSAGE_REQ_BODY_END == msg->type)
- {
- ref_data = msg->ref_queue->array[msg->queue_index].req_data;
- }
- else if (HTTP_MESSAGE_RES_BODY_START == msg->type || HTTP_MESSAGE_RES_BODY == msg->type || HTTP_MESSAGE_RES_BODY_END == msg->type)
- {
- ref_data = msg->ref_queue->array[msg->queue_index].res_data;
- }
- ecode = http_half_data_get_content_encoding(ref_data);
- if (ref_data != NULL && HTTP_CONTENT_ENCODING_NONE != ecode)
- {
- goto fail;
- }
-
- if (msg->raw_payload.iov_base != NULL && msg->raw_payload.iov_len != 0)
- {
- *dec_body_ptr = msg->raw_payload.iov_base;
- *dec_body_len = msg->raw_payload.iov_len;
- }
- return;
- fail:
- if (dec_body_ptr)
- {
- *dec_body_ptr = NULL;
- *dec_body_len = 0;
- }
return;
}
-
- void http_message_get0_raw_url(const struct http_message *msg, const char **url_val, size_t *url_len)
+ if (unlikely(NULL == exdata)) // first packet
{
- struct http_decoder_half_data *req_data = NULL;
- if (unlikely(NULL == msg))
- {
- goto fail;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
-
- req_data = msg->ref_queue->array[msg->queue_index].req_data;
-
- if (http_half_data_get_url(req_data, url_val, url_len) < 0)
- {
- goto fail;
- }
- return;
-
- fail:
- if (url_val)
- {
- *url_val = NULL;
- *url_len = 0;
- }
- return;
+ exdata = http_session_new(sess, http_env, tcp_payload, tcp_payload_len);
}
-#if 0
- void http_message_decoded_url_get0(const struct http_message *msg, struct iovec *url)
+ if (exdata->ignore_session) // quic path
{
- if (unlikely(NULL == msg))
- {
- if (url)
- {
- url->iov_base = NULL;
- url->iov_len = 0;
- }
- return;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
-
- struct http_decoder_half_data *req_data =
- msg->ref_queue->array[msg->queue_index].req_data;
-
- if (http_half_data_get_decode_url(req_data, url) < 0)
- {
- goto fail;
- }
- return;
-
- fail:
- if (url)
- {
- url->iov_base = NULL;
- url->iov_len = 0;
- }
return;
}
-#endif
- int http_message_get_transaction_seq(const struct http_message *msg)
- {
- if (unlikely(NULL == msg))
- {
- return -1;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- struct http_decoder_half_data *hf_data = NULL;
- if (HTTP_REQUEST == msg->flow_type)
- {
- hf_data = msg->ref_queue->array[msg->queue_index].req_data;
- }
- else
- {
- hf_data = msg->ref_queue->array[msg->queue_index].res_data;
- }
- return http_half_data_get_transaction_seq(hf_data);
- }
-#ifdef __cplusplus
-}
-#endif \ No newline at end of file
+ STELLAR_LOG_DEBUG(http_env->logger_ref, HTTP_MODULE_NAME,
+ "sess: %s, rcv tcp payload len: %u", session_get_readable_addr(exdata->sess), tcp_payload_len);
+ http_decoder_execute(sess, http_env, exdata, tcp_payload, tcp_payload_len);
+ return;
+} \ No newline at end of file
diff --git a/decoders/http/http_decoder.h b/decoders/http/http_decoder.h
new file mode 100644
index 0000000..06cc72b
--- /dev/null
+++ b/decoders/http/http_decoder.h
@@ -0,0 +1,104 @@
+
+#pragma once
+#include <stdint.h>
+#include <stddef.h>
+#include "stellar/session.h"
+#include "stellar/http.h"
+#include "llhttp.h"
+#include "http_decoder_stat.h"
+#include "http_decoder_half.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define HTTP_IDENTIFY_LEN 16
+#define HTTP_HEADERS_CACHE_MAX_SIZE 4096
+
+#define HTTP_MODULE_NAME "HTTP"
+#define HTTP_EXDATA_NAME "HTTP_EXDATA"
+
+#ifndef likely
+#define likely(x) __builtin_expect((x), 1)
+#endif
+#ifndef unlikely
+#define unlikely(x) __builtin_expect((x), 0)
+#endif
+
+#ifndef UNUSED
+#define UNUSED __attribute__((unused))
+#endif
+
+ struct http_config
+ {
+ int decompress_switch;
+ // int stat_output_interval;
+ // size_t mempool_size; // per session mempool size
+ };
+
+ enum http_topic_type
+ {
+ HTTP_TOPIC_REQ_HEADER = 0,
+ HTTP_TOPIC_REQ_BODY,
+ HTTP_TOPIC_RES_HEADER,
+ HTTP_TOPIC_RES_BODY,
+ HTTP_TOPIC_MAX,
+ };
+
+ struct http_topic_compose
+ {
+ const char *topic_name;
+ int topic_id;
+ };
+
+ struct http_topic_manager
+ {
+ struct http_topic_compose topic_compose[HTTP_TOPIC_MAX];
+ };
+
+ struct http
+ {
+ struct module_manager *mod_mgr_ref;
+ struct logger *logger_ref;
+ struct http_topic_manager *http_topic_mgr;
+ int exdata_id;
+ int plugin_id;
+ struct http_config hd_cfg;
+ struct http_stat stat;
+ };
+
+ struct http_half;
+ struct http_half_data;
+ struct http_decoder
+ {
+ struct http_half *flow_c2s;
+ struct http_half *flow_s2c;
+ };
+
+ struct http_exdata
+ {
+ int ignore_session;
+ struct http *http_env;
+ struct session *sess;
+ struct http_decoder *decoder;
+ };
+
+ struct http_message
+ {
+ struct session *sess_ref;
+ enum http_topic_type topic_type;
+ struct http_half_data *flow_data;
+ enum http_event event;
+ };
+
+ void http_on_tcp_stream_cb(struct session *sess, enum session_state state, const char *tcp_payload, uint32_t tcp_payload_len, void *args);
+ struct http_topic_manager *http_topic_mgr_init(struct module_manager *mod_mgr);
+ struct http_half *http_flow_get_nx(struct http_exdata *exdata, enum flow_type flow_dir, struct session *sess, struct http *http_env);
+ void http_message_free_cb(void *msg, void *msg_free_arg);
+ void http_exdata_free_cb(int idx, void *ex_data, void *plugin_env);
+ void http_topic_mgr_free(struct http_topic_manager *topic_mgr);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/decoders/http/http_decoder_decompress.c b/decoders/http/http_decoder_decompress.c
new file mode 100644
index 0000000..438987e
--- /dev/null
+++ b/decoders/http/http_decoder_decompress.c
@@ -0,0 +1,274 @@
+#include <zlib.h>
+#include <string.h>
+#include <assert.h>
+#include <brotli/decode.h>
+#include "http_decoder_utils.h"
+#include "http_decoder_decompress.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ struct http_content_decompress
+ {
+ enum http_content_encoding encoding;
+ z_stream *z_stream_ptr;
+ BrotliDecoderState *br_state;
+ char *buffer;
+ size_t buffer_size;
+ };
+
+ void http_content_decompress_ownership_borrow(struct http_content_decompress *decompress)
+ {
+ decompress->buffer = NULL; // ownership move to flow_data, will be freed when message has been processed by all modules
+ }
+
+ enum http_content_encoding http_content_encoding_str2int(const char *content_encoding, size_t encoding_str_len)
+ {
+ if (http_strncasecmp_safe("gzip", content_encoding, 4, encoding_str_len) == 0)
+ {
+ return HTTP_CONTENT_ENCODING_GZIP;
+ }
+ if (http_strncasecmp_safe("deflate", content_encoding, 7, encoding_str_len) == 0)
+ {
+ return HTTP_CONTENT_ENCODING_DEFLATE;
+ }
+ if (http_strncasecmp_safe("br", content_encoding, 2, encoding_str_len) == 0)
+ {
+ return HTTP_CONTENT_ENCODING_BR;
+ }
+ return HTTP_CONTENT_ENCODING_NONE;
+ }
+
+ const char *http_content_encoding_int2str(enum http_content_encoding content_encoding)
+ {
+ if (content_encoding == HTTP_CONTENT_ENCODING_GZIP)
+ {
+ return "gzip";
+ }
+ if (content_encoding == HTTP_CONTENT_ENCODING_DEFLATE)
+ {
+ return "deflate";
+ }
+ if (content_encoding == HTTP_CONTENT_ENCODING_BR)
+ {
+ return "br";
+ }
+ return "unknown";
+ }
+
+ struct http_content_decompress *http_content_decompress_create(enum http_content_encoding encoding)
+ {
+ struct http_content_decompress *decompress = CALLOC(struct http_content_decompress, 1);
+ assert(decompress);
+
+ decompress->encoding = encoding;
+ decompress->z_stream_ptr = NULL;
+ decompress->br_state = NULL;
+
+ if (encoding == HTTP_CONTENT_ENCODING_GZIP || encoding == HTTP_CONTENT_ENCODING_DEFLATE)
+ {
+ decompress->z_stream_ptr = CALLOC(z_stream, 1);
+ assert(decompress->z_stream_ptr);
+
+ decompress->z_stream_ptr->zalloc = NULL;
+ decompress->z_stream_ptr->zfree = NULL;
+ decompress->z_stream_ptr->opaque = NULL;
+ decompress->z_stream_ptr->avail_in = 0;
+ decompress->z_stream_ptr->next_in = Z_NULL;
+
+ if (encoding == HTTP_CONTENT_ENCODING_GZIP)
+ {
+ if (inflateInit2(decompress->z_stream_ptr, MAX_WBITS + 16) != Z_OK)
+ {
+ goto error;
+ }
+ }
+ if (encoding == HTTP_CONTENT_ENCODING_DEFLATE)
+ {
+ if (inflateInit2(decompress->z_stream_ptr, -MAX_WBITS) != Z_OK)
+ {
+ goto error;
+ }
+ }
+ }
+
+ if (encoding == HTTP_CONTENT_ENCODING_BR)
+ {
+ decompress->br_state = BrotliDecoderCreateInstance(NULL, NULL, NULL);
+ if (decompress->br_state == NULL)
+ {
+ goto error;
+ }
+ }
+ return decompress;
+
+ error:
+ http_content_decompress_destroy(decompress);
+ return NULL;
+ }
+
+ void http_content_decompress_destroy(struct http_content_decompress *decompress)
+ {
+ if (NULL == decompress)
+ {
+ return;
+ }
+ if (decompress->z_stream_ptr != NULL)
+ {
+ inflateEnd(decompress->z_stream_ptr);
+ FREE(decompress->z_stream_ptr);
+ }
+ if (decompress->br_state)
+ {
+ BrotliDecoderDestroyInstance(decompress->br_state);
+ decompress->br_state = NULL;
+ }
+ FREE(decompress->buffer);
+ FREE(decompress);
+ }
+
+ static int http_content_decompress_write_zlib(struct http_content_decompress *decompress,
+ const char *indata, size_t indata_len,
+ char **outdata, size_t *outdata_len)
+ {
+ z_stream *z_stream_ptr = decompress->z_stream_ptr;
+ z_stream_ptr->avail_in = (unsigned int)indata_len;
+ z_stream_ptr->next_in = (unsigned char *)indata;
+ z_stream_ptr->avail_out = (unsigned int)HTTP_DECOMPRESS_BUFFER_SIZE;
+ z_stream_ptr->next_out = (unsigned char *)decompress->buffer;
+ *outdata = NULL;
+ *outdata_len = 0;
+ size_t total_have = 0;
+ int no_buffer;
+
+ do
+ {
+ int ret = inflate(z_stream_ptr, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
+ {
+ (void)inflateEnd(z_stream_ptr);
+ return -1;
+ }
+ size_t have = HTTP_DECOMPRESS_BUFFER_SIZE - z_stream_ptr->avail_out;
+ if (have > 0)
+ {
+ total_have += have;
+ if (0 == z_stream_ptr->avail_out)
+ {
+ decompress->buffer_size += HTTP_DECOMPRESS_BUFFER_SIZE;
+ decompress->buffer = REALLOC(char, decompress->buffer, decompress->buffer_size);
+ z_stream_ptr->avail_out = HTTP_DECOMPRESS_BUFFER_SIZE;
+ z_stream_ptr->next_out = (unsigned char *)decompress->buffer + total_have;
+ *outdata = decompress->buffer;
+ *outdata_len = total_have;
+ no_buffer = 1;
+ }
+ else
+ {
+ *outdata = decompress->buffer;
+ *outdata_len = total_have;
+ no_buffer = 0;
+ }
+ }
+ else
+ {
+ break;
+ }
+ if (Z_STREAM_END == ret)
+ {
+ break;
+ }
+ } while (no_buffer == 1);
+ return 0;
+ }
+
+ static int http_content_decompress_write_br(struct http_content_decompress *decompress,
+ const char *indata, size_t indata_len,
+ char **outdata, size_t *outdata_len)
+ {
+ size_t available_in = indata_len;
+ const unsigned char *next_in = (const unsigned char *)indata;
+ size_t available_out = HTTP_DECOMPRESS_BUFFER_SIZE;
+ unsigned char *next_out = (unsigned char *)decompress->buffer;
+
+ *outdata = NULL;
+ *outdata_len = 0;
+ size_t total_have = 0;
+ int no_buffer;
+
+ do
+ {
+ int ret = BrotliDecoderDecompressStream(decompress->br_state, &available_in,
+ &next_in, &available_out, &next_out, NULL);
+ if (ret == BROTLI_DECODER_RESULT_ERROR)
+ {
+ // BrotliDecoderErrorCode errcode = BrotliDecoderGetErrorCode(decompress->br_state);
+ *outdata = NULL;
+ *outdata_len = 0;
+ return -1;
+ }
+ size_t have = HTTP_DECOMPRESS_BUFFER_SIZE - available_out;
+ if (have > 0)
+ {
+ total_have += have;
+ if (0 == available_out)
+ {
+ decompress->buffer_size += HTTP_DECOMPRESS_BUFFER_SIZE;
+ decompress->buffer = REALLOC(char, decompress->buffer, decompress->buffer_size);
+ available_out = HTTP_DECOMPRESS_BUFFER_SIZE;
+ next_out = (unsigned char *)decompress->buffer + total_have;
+ *outdata = decompress->buffer;
+ *outdata_len = total_have;
+ no_buffer = 1;
+ }
+ else
+ {
+ *outdata = decompress->buffer;
+ *outdata_len = have;
+ no_buffer = 0;
+ }
+ }
+ else
+ {
+ break;
+ }
+ } while (no_buffer == 1);
+ return 0;
+ }
+
+ int http_content_decompress_write(struct http_content_decompress *decompress,
+ const char *indata, size_t indata_len,
+ char **outdata, size_t *outdata_len)
+ {
+ assert(decompress);
+ assert(indata);
+ assert(indata_len > 0);
+ assert(outdata);
+ assert(outdata_len);
+ *outdata = NULL;
+ *outdata_len = 0;
+
+ if (NULL == decompress->buffer)
+ {
+ decompress->buffer = CALLOC(char, HTTP_DECOMPRESS_BUFFER_SIZE);
+ assert(decompress->buffer);
+ decompress->buffer_size = HTTP_DECOMPRESS_BUFFER_SIZE;
+ }
+
+ if (decompress->encoding == HTTP_CONTENT_ENCODING_GZIP ||
+ decompress->encoding == HTTP_CONTENT_ENCODING_DEFLATE)
+ {
+ return http_content_decompress_write_zlib(decompress, indata, indata_len, outdata, outdata_len);
+ }
+ if (decompress->encoding == HTTP_CONTENT_ENCODING_BR)
+ {
+ return http_content_decompress_write_br(decompress, indata, indata_len, outdata, outdata_len);
+ }
+ assert(0);
+ return -1;
+ }
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/decoders/http/http_content_decompress.h b/decoders/http/http_decoder_decompress.h
index 2ac4689..fd82dd5 100644
--- a/decoders/http/http_content_decompress.h
+++ b/decoders/http/http_decoder_decompress.h
@@ -6,6 +6,9 @@ extern "C"
#endif
#include <stddef.h>
+#include "stellar/http.h"
+
+#define HTTP_DECOMPRESS_BUFFER_SIZE (4096)
enum http_content_encoding
{
@@ -13,18 +16,14 @@ extern "C"
HTTP_CONTENT_ENCODING_GZIP = 1 << 1,
HTTP_CONTENT_ENCODING_DEFLATE = 1 << 2,
HTTP_CONTENT_ENCODING_BR = 1 << 3,
+ HTTP_CONTENT_ENCODING_UNKNOWN = 1 << 4,
};
struct http_content_decompress;
-
enum http_content_encoding http_content_encoding_str2int(const char *content_encoding, size_t encoding_str_len);
-
const char *http_content_encoding_int2str(enum http_content_encoding content_encoding);
-
struct http_content_decompress *http_content_decompress_create(enum http_content_encoding encoding);
-
void http_content_decompress_destroy(struct http_content_decompress *decompress);
-
// return 0 : success
// return -1 : error
int http_content_decompress_write(struct http_content_decompress *decompress,
diff --git a/decoders/http/http_decoder_half.c b/decoders/http/http_decoder_half.c
index 70991c6..84874a3 100644
--- a/decoders/http/http_decoder_half.c
+++ b/decoders/http/http_decoder_half.c
@@ -2,1187 +2,689 @@
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
-#include "http_decoder_private.h"
+#include "http_decoder.h"
+#include "http_decoder_half.h"
+#include "http_decoder_utils.h"
+#include "http_decoder_decompress.h"
#include "llhttp.h"
+#include "stellar/session.h"
#include "uthash/utlist.h"
+#include "uthash/utarray.h"
-struct http_decompress_buffer
+#ifdef __cplusplus
+extern "C"
{
- struct iovec iov;
- char is_commit;
- struct http_decompress_buffer *next, *prev;
-};
-
-struct http_decoder_half_data
-{
- struct http_decoder_table *table;
-
- int major_version;
- int minor_version;
- int status_code;
-
- enum http_event state;
-
- enum http_content_encoding content_encoding;
- struct http_content_decompress *decompress;
-#if 0
- char *ref_decompress_body;
- size_t decompress_body_len;
-#else
- struct http_decompress_buffer *decompress_buffer_list;
-#endif
- int joint_url_complete;
- int url_is_encoded;
- // http://<host>[:<port>]/<path>?<searchpart>
- hstring joint_url;
- hstring decoded_url;
- long long transaction_index;
-};
-
-struct http_decoder_half
-{
- llhttp_t parser;
- llhttp_settings_t settings;
- enum llhttp_errno error;
- int decompress_switch;
- struct http_decoder_env *httpd_env;
-
- // uint8_t is_request_flow;
- enum http_event event;
- http_event_cb *http_ev_cb;
- struct http_event_context *http_ev_ctx;
-
- struct http_decoder_half_data *ref_data;
-
- long long trans_counter;
- long long err_counter;
- long long transaction_seq; // accumulated
-
- const char *data;
- int data_len;
-};
-
-// #define HTTP_DECODER_DEBUG
-#ifdef HTTP_DECODER_DEBUG
-static void printf_debug_info(const char *desc, const char *at, size_t length)
-{
- if (at)
- {
- char *temp = http_safe_dup(at, length);
- printf("HTTP PARSER STAGE: %s: %s\n", desc, temp);
- FREE(temp);
- }
- else
- {
- printf("HTTP PARSER STAGE: %s\n", desc);
- }
-}
-#else
-#define printf_debug_info(desc, at, length)
#endif
-void http_half_decompress_buffer_free(struct http_decoder_half_data *data, hstring *decompress_body)
-{
- struct http_decompress_buffer *el, *tmp;
- DL_FOREACH_SAFE(data->decompress_buffer_list, el, tmp)
+ static inline void http_half_stage_reset_flow_data(struct http_half *half)
{
- if (el->iov.iov_base == decompress_body->iov_base && el->iov.iov_len == decompress_body->iov_len)
+ if (half->flow_data)
{
- DL_DELETE(data->decompress_buffer_list, el);
- if (el->iov.iov_base)
+ memset(&half->flow_data->req_line, 0, sizeof(struct http_request_line));
+ memset(&half->flow_data->status_line, 0, sizeof(struct http_status_line));
+ memset(&half->flow_data->header, 0, sizeof(struct http_header));
+ if (half->flow_data->ut_filed_array)
{
- FREE(el->iov.iov_base);
+ utarray_clear(half->flow_data->ut_filed_array);
}
- FREE(el);
- break;
}
}
-}
-
-void http_half_get_lastest_decompress_buffer(struct http_decoder_half_data *data, hstring *decompress_body)
-{
- if (data->content_encoding == HTTP_CONTENT_ENCODING_NONE)
- {
- return;
- }
- if (data->decompress_buffer_list == NULL)
- {
- decompress_body->iov_base = NULL;
- decompress_body->iov_len = 0;
- return;
- }
- if (data->decompress_buffer_list->prev->is_commit == 1)
+ static inline void http_half_stage_reset_stat(struct http_half *half)
{
- decompress_body->iov_base = NULL;
- decompress_body->iov_len = 0;
- return;
+ memset(&half->half_stage, 0, sizeof(struct http_half_llhttp_stage));
}
- decompress_body->iov_base = data->decompress_buffer_list->prev->iov.iov_base;
- decompress_body->iov_len = data->decompress_buffer_list->prev->iov.iov_len;
- data->decompress_buffer_list->prev->is_commit = 1;
-}
-
-static void http_decoder_half_data_decompress(struct http_decoder_half_data *data)
-{
- assert(data);
-
- if (data->content_encoding == HTTP_CONTENT_ENCODING_NONE)
+ static void http_half_stage_reset(struct http_half *half)
{
- return;
+ http_half_stage_reset_stat(half);
+ http_half_stage_reset_flow_data(half);
}
- hstring raw_body = {};
- http_decoder_table_get_body(data->table, (char **)&raw_body.iov_base, &raw_body.iov_len);
- if (raw_body.iov_base == NULL || raw_body.iov_len == 0)
+ void http_flow_append_header_filed(struct http_half_data *flow_data, const char *at, size_t length)
{
- return;
+ if (NULL == flow_data->ut_filed_array) // the first field
+ {
+ UT_icd header_icd = {sizeof(struct http_header_field), NULL, NULL, NULL};
+ utarray_new(flow_data->ut_filed_array, &header_icd);
+ assert(flow_data->ut_filed_array != NULL);
+ utarray_reserve(flow_data->ut_filed_array, HTTP_HEADER_FIELD_RESERVE_NUM);
+ }
+ struct http_header_field new_filed = {};
+ new_filed.field_name = (char *)at;
+ new_filed.field_name_len = length;
+ utarray_push_back(flow_data->ut_filed_array, &new_filed);
}
- if (NULL == data->decompress)
+ void http_flow_append_header_value(struct http_half_data *flow_data, const char *at, size_t length)
{
- data->decompress = http_content_decompress_create(data->content_encoding);
+ assert(flow_data->ut_filed_array != NULL);
+ struct http_header_field *last_field = (struct http_header_field *)utarray_back(flow_data->ut_filed_array);
+ assert(last_field != NULL);
+ if (last_field)
+ {
+ last_field->field_value = (char *)at;
+ last_field->field_value_len = length;
+ }
}
- assert(data->decompress);
- char *local_outdata = NULL;
- size_t local_outdata_len = 0;
- if (http_content_decompress_write(data->decompress, (char *)raw_body.iov_base,
- raw_body.iov_len,
- &local_outdata,
- &local_outdata_len) == -1)
+ static struct http_message *http_produce_message(struct session *sess, enum http_event event,
+ enum http_topic_type topic_type, struct http_half_data *flow_data)
{
- // log error
- http_content_decompress_destroy(data->decompress);
- data->decompress = NULL;
- return;
+ struct http_message *msg = (struct http_message *)calloc(1, sizeof(struct http_message));
+ msg->sess_ref = sess;
+ msg->topic_type = topic_type;
+ msg->flow_data = flow_data;
+ msg->event = event;
+ return msg;
}
- if (local_outdata != NULL && local_outdata_len > 0)
+ static struct http_half_data *http_half_data_new(enum flow_type flow_dir)
{
- struct http_decompress_buffer *decompress_buffer = CALLOC(struct http_decompress_buffer, 1);
- assert(decompress_buffer);
- decompress_buffer->iov.iov_base = local_outdata;
- decompress_buffer->iov.iov_len = local_outdata_len;
- DL_APPEND(data->decompress_buffer_list, decompress_buffer);
- http_content_decompress_ownership_borrow(data->decompress);
+ struct http_half_data *half_data = (struct http_half_data *)calloc(1, sizeof(struct http_half_data));
+ half_data->flow_dir = flow_dir;
+ /* update transaction seq in http_half_parse_headers_finally(), not here */
+ return half_data;
}
-}
-
-/* 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
- if (half->parser.type == HTTP_REQUEST)
- {
- half->event = HTTP_EVENT_REQ_INIT;
- }
- else
+ void http_half_data_free(struct http_half_data *half_data)
{
- half->event = HTTP_EVENT_RES_INIT;
+ if (NULL == half_data)
+ {
+ return;
+ }
+ if (half_data->ut_filed_array)
+ {
+ utarray_free(half_data->ut_filed_array);
+ half_data->ut_filed_array = NULL;
+ }
+ if (half_data->joint_url.iov_base)
+ {
+ FREE(half_data->joint_url.iov_base);
+ }
+ if (half_data->decompress)
+ {
+ http_content_decompress_destroy(half_data->decompress);
+ half_data->decompress = NULL;
+ }
+ free(half_data);
}
- half->ref_data = NULL;
-
- assert(half->http_ev_cb != NULL);
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); // http_event_handler()
-
- half->trans_counter++;
- half->ref_data->transaction_index = half->transaction_seq++;
- return 0;
-}
-
-static int on_message_complete(llhttp_t *http)
-{
- printf_debug_info("on_message_complete", NULL, 0);
-
- struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- if (half->parser.type == HTTP_REQUEST)
+ void http_half_free(struct http_half *half)
{
- if (half->event == HTTP_EVENT_REQ_BODY_DATA)
+ if (NULL == half)
{
- half->event = HTTP_EVENT_REQ_BODY_END;
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env);
+ return;
}
- }
- else
- {
- if (half->event == HTTP_EVENT_RES_BODY_DATA)
+ llhttp_reset(&half->parser.llhttp_parser);
+ http_half_data_free(half->flow_data);
+ if (half->cached_header_buffer)
{
- half->event = HTTP_EVENT_RES_BODY_END;
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env);
+ if (half->cached_header_buffer->buffer)
+ {
+ FREE(half->cached_header_buffer->buffer);
+ }
+ FREE(half->cached_header_buffer);
}
+ free(half);
}
- // trigger req_end/res_end
- if (half->parser.type == HTTP_REQUEST)
- {
- half->event = HTTP_EVENT_REQ_END;
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env);
- }
- else
+ struct http_half *http_half_new(enum flow_type flow_dir)
{
- half->event = HTTP_EVENT_RES_END;
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env);
+ struct http_half *half = (struct http_half *)calloc(1, sizeof(struct http_half));
+ if (FLOW_TYPE_C2S == flow_dir)
+ {
+ http_flow_parser_init(&half->parser, HTTP_REQUEST);
+ }
+ else
+ {
+ http_flow_parser_init(&half->parser, HTTP_RESPONSE);
+ }
+ half->parser.half_ref = half;
+ return half;
}
- return 0;
-}
-
-static int on_reset(llhttp_t *http __attribute__((unused)))
-{
- printf_debug_info("on_reset", NULL, 0);
-
- return 0;
-}
-
-static inline int is_line_crlf(struct http_decoder_half *half)
-{
- const char *chr_r = (char *)memrchr(half->data, '\r', half->data_len);
- const char *chr_n = (char *)memrchr(half->data, '\n', half->data_len);
- if (chr_r && chr_n && (chr_r + 1 == chr_n))
+ static struct http_header_field *http_flow_get_header_field(struct http_half_data *flow_data, const char *field_name, size_t field_name_len)
{
- return 1;
+ struct http_header_field *p;
+ if (NULL == flow_data->ut_filed_array) // some response no header fileds, such as "HTTP/1.1 100 Continue\r\n\r\n"
+ {
+ return NULL;
+ }
+ for (p = (struct http_header_field *)utarray_front(flow_data->ut_filed_array);
+ p != NULL;
+ p = (struct http_header_field *)utarray_next(flow_data->ut_filed_array, p))
+ {
+ if ((field_name_len == p->field_name_len) &&
+ (strncasecmp(p->field_name, field_name, field_name_len) == 0))
+ {
+ return p;
+ }
+ }
+ return NULL;
}
- return 0;
-}
-
-static int on_method(llhttp_t *http, const char *at, size_t length)
-{
- printf_debug_info("on_method", at, length);
-
- struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_METHOD, at, length);
- return 0;
-}
-
-/* Information-only callbacks, return value is ignored */
-static int on_method_complete(llhttp_t *http)
-{
- printf_debug_info("on_method_complete", NULL, 0);
-
- struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
- if (is_line_crlf(half) == 0)
+ static void http_using_session_addr_as_host(struct session *ref_session, struct http_header_field *host_result)
{
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_METHOD);
- }
-
- http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_METHOD);
-
- 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_URI, at, length);
- return 0;
-}
-
-static void http_decoder_cached_portion_url(struct http_decoder_half *half, const hstring *uri_result)
-{
- struct http_decoder_half_data *ref_data = half->ref_data;
- int uri_skip_len = 0;
+ memset(host_result, 0, sizeof(struct http_header_field));
+ struct http_session_addr ssaddr = {};
+ httpd_session_get_addr(ref_session, &ssaddr);
+ char ip_string_buf[INET6_ADDRSTRLEN];
- if ((uri_result->iov_len) > 7 && (strncasecmp("http://", (char *)uri_result->iov_base, 7) == 0)) // absolute URI
- {
- uri_skip_len = strlen("http://");
- ref_data->joint_url_complete = 1;
- }
- else
- {
- ref_data->joint_url_complete = 0;
+ if (4 == ssaddr.ipver)
+ {
+ host_result->field_value = (char *)calloc(1, (INET6_ADDRSTRLEN + 7) /* "ip:port" max length */);
+ inet_ntop(AF_INET, &ssaddr.daddr4, ip_string_buf, INET6_ADDRSTRLEN);
+ snprintf((char *)host_result->field_value, INET6_ADDRSTRLEN + 7, "%s:%u", ip_string_buf, ntohs(ssaddr.dport));
+ host_result->field_value_len = strlen(host_result->field_value);
+ }
+ else if (6 == ssaddr.ipver)
+ {
+ host_result->field_value = (char *)calloc(1, (INET6_ADDRSTRLEN + 7) /* "ip:port" max length */);
+ inet_ntop(AF_INET6, &ssaddr.daddr6, ip_string_buf, INET6_ADDRSTRLEN);
+ snprintf((char *)host_result->field_value, INET6_ADDRSTRLEN + 7, "%s:%u", ip_string_buf, ntohs(ssaddr.dport));
+ host_result->field_value_len = strlen(host_result->field_value);
+ }
+ else
+ {
+ host_result->field_value = (char *)calloc(1, 1);
+ host_result->field_value_len = 1;
+ }
+ return;
}
- ref_data->joint_url.iov_len = uri_result->iov_len - uri_skip_len;
- ref_data->joint_url.iov_base = MEMPOOL_CALLOC(half->http_ev_ctx->ref_mempool, char, ref_data->joint_url.iov_len);
- memcpy(ref_data->joint_url.iov_base, (char *)uri_result->iov_base + uri_skip_len, ref_data->joint_url.iov_len);
-}
-
-/* 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- if (is_line_crlf(half) == 0)
+ static void http_flow_join_url(struct http_half_data *flow_data, const struct http_header_field *host_filed)
{
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_URI);
- }
-
- http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_URI);
-
- hstring uri_result = {};
- http_decoder_table_get_uri(half->ref_data->table, (char **)&uri_result.iov_base, &uri_result.iov_len);
- assert(uri_result.iov_base);
- http_decoder_cached_portion_url(half, &uri_result);
-
- return 0;
-}
+ int append_slash_len = 0;
+ const char *join_uri = flow_data->req_line.uri;
+ size_t join_url_len = flow_data->req_line.uri_len;
-/* Possible return values 0, -1, HPE_USER */
-static int on_version(llhttp_t *http, const char *at, size_t length)
-{
- printf_debug_info("on_version", at, length);
-
- struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_VERSION, at, length);
- return 0;
-}
+ // skip schema "http://"
+ if (join_url_len > 7 && strncasecmp(join_uri, "http://", 7) == 0)
+ {
+ join_uri += 7;
+ join_url_len -= 7;
+ }
-/* Information-only callbacks, return value is ignored */
-static int on_version_complete(llhttp_t *http)
-{
- printf_debug_info("on_version_complete", NULL, 0);
+ // if uri not absolute path(start with '/'), append '/'
+ if ('/' != join_uri[0])
+ {
+ append_slash_len = 1;
+ }
+ int url_cache_str_len = host_filed->field_value_len + join_url_len + append_slash_len;
+ char *url_cache_str = (char *)calloc(1, url_cache_str_len);
- struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
+ char *ptr = url_cache_str;
+ memcpy(ptr, host_filed->field_value, host_filed->field_value_len);
+ ptr += host_filed->field_value_len;
+ if (append_slash_len)
+ {
+ *ptr = '/';
+ ptr++;
+ }
+ memcpy(ptr, join_uri, join_url_len);
- if (is_line_crlf(half) == 0)
- {
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_VERSION);
+ flow_data->joint_url.iov_base = url_cache_str;
+ flow_data->joint_url.iov_len = url_cache_str_len;
}
- http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_VERSION);
-
- half->ref_data->major_version = llhttp_get_http_major(&half->parser);
- half->ref_data->minor_version = llhttp_get_http_minor(&half->parser);
-
- if (half->parser.type == HTTP_REQUEST)
+ // todo: optimize use hash table
+ static void http_half_get_frequently_used_fileds(struct http_half_data *flow_data)
{
- half->event = HTTP_EVENT_REQ_LINE;
- if (half->http_ev_cb) // http_event_handler()
+ if (FLOW_TYPE_C2S == flow_data->flow_dir)
+ {
+ flow_data->header.host = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_HOST, strlen(HTTP_HEADER_FIELD_NAME_HOST));
+ flow_data->header.user_agent = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_USER_AGENT, strlen(HTTP_HEADER_FIELD_NAME_USER_AGENT));
+ flow_data->header.referer = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_REFERER, strlen(HTTP_HEADER_FIELD_NAME_REFERER));
+ flow_data->header.cookie = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_COOKIE, strlen(HTTP_HEADER_FIELD_NAME_COOKIE));
+ }
+ else
{
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env);
+ flow_data->header.set_cookie = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_SET_COOKIE, strlen(HTTP_HEADER_FIELD_NAME_SET_COOKIE));
}
+ flow_data->header.content_type = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_CONTENT_TYPE, strlen(HTTP_HEADER_FIELD_NAME_CONTENT_TYPE));
}
- 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_STATUS, at, length);
- 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- if (is_line_crlf(half) == 0)
+ static int http_half_parse_headers_finally(struct http_half *half)
{
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_STATUS);
- }
+ struct http_half_data *flow_data = half->flow_data;
+ http_half_get_frequently_used_fileds(flow_data);
- http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_STATUS);
- half->ref_data->status_code = llhttp_get_status_code(&half->parser);
+ /* update transaction_seq when headers completed */
+ half->flow_data->transaction_seq = half->transaction_num++;
- if (half->parser.type == HTTP_RESPONSE)
- {
- half->event = HTTP_EVENT_RES_LINE;
- if (half->http_ev_cb != NULL) // http_event_handler()
+ if (FLOW_TYPE_C2S == flow_data->flow_dir)
{
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env);
+ struct http_header_field tmp_host_field = {};
+ const struct http_header_field *host_filed = flow_data->header.host;
+ if (NULL == host_filed)
+ {
+ http_using_session_addr_as_host(half->sess_ref, &tmp_host_field);
+ host_filed = &tmp_host_field;
+ }
+ http_flow_join_url(flow_data, host_filed);
+ FREE(tmp_host_field.field_name);
+ FREE(tmp_host_field.field_value);
}
- }
- 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_HDRKEY, at, length);
- 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_HDRKEY);
-
- 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_HDRVAL, at, length);
- return 0;
-}
-
-#define MAX_ENCODING_STR_LEN 8
-/* 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_HDRKEY) ==
- STRING_STATE_CACHE)
- {
- http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_HDRKEY);
- }
-
- http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_HDRVAL);
+ struct http_header_field *encoding_field = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_CONTENT_ENCODING, strlen(HTTP_HEADER_FIELD_NAME_CONTENT_ENCODING));
+ if (NULL == encoding_field)
+ {
+ flow_data->content_encoding_type = HTTP_CONTENT_ENCODING_NONE;
+ }
+ else
+ {
+ flow_data->content_encoding_type = http_content_encoding_str2int(encoding_field->field_value, encoding_field->field_value_len);
+ }
- if (half->ref_data->content_encoding == HTTP_CONTENT_ENCODING_NONE)
- {
- struct http_header_field http_hdr = {};
+ struct http_header_field *content_len_field = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_CONTENT_LENGTH, strlen(HTTP_HEADER_FIELD_NAME_CONTENT_LENGTH));
+ if (NULL == content_len_field)
+ {
+ flow_data->header.content_length = -1;
+ }
+ else
+ {
+ flow_data->header.content_length = http_strtoll(content_len_field->field_value, content_len_field->field_value_len);
+ }
- if (http_decoder_table_get_header(half->ref_data->table, (char *)"Content-Encoding", 16, &http_hdr) == 0)
+ struct http_header_field *transf_encoding_field = http_flow_get_header_field(flow_data, HTTP_HEADER_FIELD_NAME_TRANSFER_ENCODING, strlen(HTTP_HEADER_FIELD_NAME_TRANSFER_ENCODING));
+ if (NULL == transf_encoding_field)
{
- half->ref_data->content_encoding = http_content_encoding_str2int(http_hdr.value, http_hdr.value_len);
+ flow_data->transfer_encoding_is_chunked = -1;
}
- }
+ else
+ {
+ if (http_strncasecmp_safe(transf_encoding_field->field_value, "chunked", transf_encoding_field->field_value_len, strlen("chunked")) == 0)
+ {
+ flow_data->transfer_encoding_is_chunked = 1;
+ }
+ else
+ {
+ flow_data->transfer_encoding_is_chunked = 0;
+ }
+ }
+ flow_data->header.header_buf = half->half_stage.first_header_name_ptr;
+ flow_data->header.header_buf_sz = half->half_stage.last_headers_complete_ptr - half->half_stage.first_header_name_ptr;
- if (http->type == HTTP_REQUEST)
- {
- http_decoder_get_host_feed_url(half);
+ // todo, parse other frequently used fields
+ return 0;
}
- 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 __attribute__((unused)))
-{
- printf_debug_info("on_chunk_header", NULL, 0);
- 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 __attribute__((unused)))
-{
- printf_debug_info("on_chunk_header_complete", NULL, 0);
-
- 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
- assert(half->ref_data);
-
- http_decoder_table_set_header_complete(half->ref_data->table);
-
- if (half->parser.type == HTTP_REQUEST)
- {
- half->event = HTTP_EVENT_REQ_HDR_END;
- }
- else
+ int http_get_header_field_count(struct http_half_data *flow_data)
{
- half->event = HTTP_EVENT_RES_HDR_END;
+ if (NULL == flow_data->ut_filed_array)
+ {
+ return 0; // some response no header fileds, such as "HTTP/1.1 100 Continue\r\n\r\n"
+ }
+ return utarray_len(flow_data->ut_filed_array);
}
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); // http_event_handler()
-
- 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_half *half = container_of(http, struct http_decoder_half, parser);
- assert(half);
-
- // trigger body_begin event
- if (half->parser.type == HTTP_REQUEST)
+ void http_flow_body_decompress(struct http_half_data *flow_data, const char *zipdata, size_t zipdatalen)
{
- if (half->event == HTTP_EVENT_REQ_HDR_END)
+ assert(flow_data);
+ if (flow_data->content_encoding_type == HTTP_CONTENT_ENCODING_NONE)
{
- half->event = HTTP_EVENT_REQ_BODY_BEGIN;
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); // http_event_handler()
+ return;
}
- }
- else
- {
- if (half->event == HTTP_EVENT_RES_HDR_END)
+ if (zipdata == NULL || zipdatalen == 0)
{
- half->event = HTTP_EVENT_RES_BODY_BEGIN;
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env);
+ return;
}
- }
-
- if (half->ref_data != NULL)
- {
- if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_BODY) ==
- STRING_STATE_COMMIT)
+ if (NULL == flow_data->decompress)
{
- http_decoder_table_reset(half->ref_data->table, HTTP_ITEM_BODY);
+ flow_data->decompress = http_content_decompress_create(flow_data->content_encoding_type);
}
- http_decoder_table_refer(half->ref_data->table, HTTP_ITEM_BODY, at, length);
- http_decoder_table_commit(half->ref_data->table, HTTP_ITEM_BODY);
- }
+ char *local_outdata = NULL;
+ size_t local_outdata_len = 0;
+ if (http_content_decompress_write(flow_data->decompress, (char *)zipdata,
+ zipdatalen, &local_outdata, &local_outdata_len) == -1)
+ {
+ http_content_decompress_destroy(flow_data->decompress);
+ flow_data->decompress = NULL;
+ flow_data->decompress_body.body = NULL;
+ flow_data->decompress_body.body_sz = 0;
+ return;
+ }
- if (1 == half->decompress_switch && half->ref_data->content_encoding != HTTP_CONTENT_ENCODING_NONE)
- {
- http_decoder_half_data_decompress(half->ref_data);
+ if (local_outdata != NULL && local_outdata_len > 0)
+ {
+ flow_data->decompress_body.body = local_outdata;
+ flow_data->decompress_body.body_sz = local_outdata_len;
+ http_content_decompress_ownership_borrow(flow_data->decompress);
+ }
}
- if (half->parser.type == HTTP_REQUEST)
- {
- half->event = HTTP_EVENT_REQ_BODY_DATA;
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); // http_event_handler()
- }
- else
+ static void http_add_header_buf_reference(struct http_half *half)
{
- half->event = HTTP_EVENT_RES_BODY_DATA;
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env);
- }
-
- return 0;
-}
-
-static void http_decoder_half_init(struct http_decoder_half *half, http_event_cb *http_ev_cb, enum llhttp_type type)
-{
- llhttp_settings_init(&half->settings);
- llhttp_init(&half->parser, type, &half->settings);
-
- // half->is_request_flow = (type == HTTP_REQUEST) ? 1 : 0;
- half->settings.on_message_begin = on_message_begin;
- half->settings.on_message_complete = on_message_complete;
- half->settings.on_reset = on_reset;
-
- half->settings.on_url = on_uri;
- half->settings.on_url_complete = on_uri_complete;
-
- half->settings.on_status = on_status;
- half->settings.on_status_complete = on_status_complete;
-
- half->settings.on_method = on_method;
- half->settings.on_method_complete = on_method_complete;
-
- half->settings.on_version = on_version;
- half->settings.on_version_complete = on_version_complete;
-
- half->settings.on_header_field = on_header_field;
- half->settings.on_header_field_complete = on_header_field_complete;
-
- half->settings.on_header_value = on_header_value;
- half->settings.on_header_value_complete = on_header_value_complete;
-
- half->settings.on_chunk_header = on_chunk_header;
- half->settings.on_chunk_complete = on_chunk_header_complete;
-
- half->settings.on_headers_complete = on_headers_complete;
- half->settings.on_body = on_body;
-
- half->error = HPE_OK;
- half->http_ev_cb = http_ev_cb; // http_event_handler()
- half->ref_data = NULL;
-}
-
-struct http_decoder_half *http_decoder_half_new(struct http_decoder_exdata *hd_ctx, nmx_pool_t *mempool,
- http_event_cb *ev_cb, enum llhttp_type http_type,
- int decompress_switch, struct http_decoder_env *httpd_env, long long start_seq)
-{
- struct http_decoder_half *half = MEMPOOL_CALLOC(mempool, struct http_decoder_half, 1);
- assert(half);
-
- half->decompress_switch = decompress_switch;
- half->http_ev_ctx = MEMPOOL_CALLOC(mempool, struct http_event_context, 1);
- http_decoder_half_init(half, ev_cb, http_type);
- half->http_ev_ctx->ref_httpd_ctx = hd_ctx;
- half->httpd_env = httpd_env;
- half->transaction_seq = start_seq;
- return half;
-}
-
-void http_decoder_half_free(nmx_pool_t *mempool, struct http_decoder_half *half)
-{
- if (NULL == half)
- {
- return;
+ if (half->cached_header_buffer != NULL)
+ {
+ // add reference but not move ownership, because the buffer will be referenced of multiple transaction in pipeline mode
+ half->cached_header_buffer->reference++;
+ half->flow_data->cached_header_buffer = half->cached_header_buffer;
+ }
}
- if (half->http_ev_ctx != NULL)
+ static void http_update_body_offset(struct http_half_data *flow_data)
{
- MEMPOOL_FREE(mempool, half->http_ev_ctx);
- half->http_ev_ctx = NULL;
+ if (flow_data->decompress_body.body != NULL || flow_data->decompress_body.offset > 0)
+ {
+ flow_data->decompress_body.offset += flow_data->decompress_body.body_sz;
+ }
+ else
+ {
+ flow_data->raw_body.offset += flow_data->raw_body.body_sz;
+ }
}
- MEMPOOL_FREE(mempool, half);
-}
-
-void http_decoder_half_reinit(struct http_decoder_half *half,
- struct http_decoder_result_queue *queue,
- nmx_pool_t *mempool, struct session *sess)
-{
- assert(half != NULL);
- if (half->ref_data != NULL)
+ static void http_set_body_finish(struct http_half_data *flow_data)
{
- http_decoder_table_reinit(half->ref_data->table);
+ if (flow_data->decompress_body.offset > 0)
+ {
+ flow_data->decompress_body.body = NULL;
+ flow_data->decompress_body.body_sz = 0;
+ flow_data->decompress_body.is_finished = 1;
+ }
+ else
+ {
+ flow_data->raw_body.body = NULL;
+ flow_data->raw_body.body_sz = 0;
+ flow_data->raw_body.is_finished = 1;
+ }
}
- half->http_ev_ctx->ref_mempool = mempool;
- half->http_ev_ctx->ref_session = sess;
- half->http_ev_ctx->ref_queue = queue;
-}
-static void publish_message_for_parsed_header(struct http_decoder_half *half)
-{
- if (0 == http_decoder_table_has_parsed_header(half->ref_data->table))
- {
- return;
- }
- if (half->parser.type == HTTP_REQUEST)
+ void http_event_handler(struct http_half *half, enum http_event event, struct http *http_env)
{
- half->event = HTTP_EVENT_REQ_HDR;
- }
- else
- {
- half->event = HTTP_EVENT_RES_HDR;
- }
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx, half->httpd_env); // http_event_handler();
- return;
-}
+ struct http_message *msg = NULL;
+ int thread_id = module_manager_get_thread_id(http_env->mod_mgr_ref);
+ uint8_t flow_flag = 0;
+ struct mq_runtime *mq_rt = module_manager_get_mq_runtime(http_env->mod_mgr_ref);
-int http_decoder_half_parse(int proxy_enable, struct http_decoder_half *half, const char *data, size_t data_len)
-{
- assert(half && data);
-
- half->data = (const char *)data;
- half->data_len = data_len;
- half->error = llhttp_execute(&half->parser, data, data_len);
-
- int ret = 0;
- enum llhttp_type type = HTTP_BOTH;
+ switch (event)
+ {
+ case HTTP_EVENT_REQ_INIT:
+ http_half_stage_reset(half);
+ if (NULL == half->flow_data) /* call llhttp_reset when headers is not completed */
+ {
+ half->flow_data = http_half_data_new(FLOW_TYPE_C2S);
+ }
+ break;
- switch (half->error)
- {
- case HPE_OK:
- break;
- case HPE_PAUSED:
- llhttp_resume(&half->parser);
- break;
- case HPE_PAUSED_UPGRADE:
- if (proxy_enable)
+ case HTTP_EVENT_REQ_HDR_END:
{
- llhttp_resume_after_upgrade(&half->parser);
+ http_half_parse_headers_finally(half);
+ int tot_c2s_headers = http_get_header_field_count(half->flow_data);
+ http_stat_update(&http_env->stat, thread_id, HTTP_TRANSACTION_NEW, 1);
+ http_stat_update(&http_env->stat, thread_id, HTTP_C2S_HEADERS, tot_c2s_headers);
+ http_stat_update(&http_env->stat, thread_id, HTTP_URL_BYTES, half->flow_data->joint_url.iov_len);
+ http_add_header_buf_reference(half);
+ msg = http_produce_message(half->sess_ref, event, HTTP_TOPIC_REQ_HEADER, half->flow_data);
+ mq_runtime_publish_message(mq_rt, http_env->http_topic_mgr->topic_compose[HTTP_TOPIC_REQ_HEADER].topic_id, msg);
}
- ret = 0;
break;
- default:
- type = (enum llhttp_type)half->parser.type;
- llhttp_init(&half->parser, type, &half->settings);
- ret = -1;
- break;
- }
-
- if (ret < 0)
- {
- // fprintf(stdout,
- // "llhttp_execute parse error: %s err_reason:%s\n",
- // llhttp_errno_name(half->error), half->parser.reason);
- return half->error;
- }
-
- if (half->ref_data != NULL)
- {
- if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_URI) == STRING_STATE_REFER)
+ case HTTP_EVENT_REQ_BODY_BEGIN:
+ break;
+ case HTTP_EVENT_REQ_BODY_DATA:
{
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_URI);
+ http_update_body_offset(half->flow_data);
+ msg = http_produce_message(half->sess_ref, event, HTTP_TOPIC_REQ_BODY, half->flow_data);
+ mq_runtime_publish_message(mq_rt, http_env->http_topic_mgr->topic_compose[HTTP_TOPIC_REQ_BODY].topic_id, msg);
}
-
- if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_STATUS) == STRING_STATE_REFER)
+ break;
+ case HTTP_EVENT_REQ_BODY_END:
{
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_STATUS);
+ http_set_body_finish(half->flow_data);
+ msg = http_produce_message(half->sess_ref, event, HTTP_TOPIC_REQ_BODY, half->flow_data);
+ mq_runtime_publish_message(mq_rt, http_env->http_topic_mgr->topic_compose[HTTP_TOPIC_REQ_BODY].topic_id, msg);
}
-
- if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_METHOD) == STRING_STATE_REFER)
+ break;
+ case HTTP_EVENT_REQ_END:
{
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_METHOD);
+ if ((0 == session_is_symmetric(half->sess_ref, &flow_flag) && (SESSION_SEEN_C2S_FLOW == flow_flag)))
+ {
+ http_stat_update(&http_env->stat, thread_id, HTTP_TRANSACTION_FREE, 1);
+ http_stat_update(&http_env->stat, thread_id, HTTP_C2S_ASYMMETRY_TRANSACTION, 1);
+ }
+ msg = http_produce_message(half->sess_ref, event, HTTP_TOPIC_REQ_BODY, half->flow_data);
+ mq_runtime_publish_message(mq_rt, http_env->http_topic_mgr->topic_compose[HTTP_TOPIC_REQ_BODY].topic_id, msg);
+ half->flow_data = NULL; // ownership move to message, free it in message free callback
}
+ break;
- if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_VERSION) == STRING_STATE_REFER)
+ case HTTP_EVENT_RES_INIT:
{
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_VERSION);
+ http_half_stage_reset(half);
+ if (NULL == half->flow_data) /* call llhttp_reset when headers is not completed */
+ {
+ half->flow_data = http_half_data_new(FLOW_TYPE_S2C);
+ }
}
+ break;
- if (http_decoder_table_header_complete(half->ref_data->table))
+ case HTTP_EVENT_RES_HDR_END:
{
- http_decoder_table_reset_header_complete(half->ref_data->table);
+ http_half_parse_headers_finally(half);
+ int tot_s2c_headers = http_get_header_field_count(half->flow_data);
+ http_stat_update(&http_env->stat, thread_id, HTTP_S2C_HEADERS, tot_s2c_headers);
+ if ((0 == session_is_symmetric(half->sess_ref, &flow_flag) && (SESSION_SEEN_S2C_FLOW == flow_flag)))
+ {
+ http_stat_update(&http_env->stat, thread_id, HTTP_TRANSACTION_NEW, 1);
+ }
+ http_add_header_buf_reference(half);
+ msg = http_produce_message(half->sess_ref, event, HTTP_TOPIC_RES_HEADER, half->flow_data);
+ mq_runtime_publish_message(mq_rt, http_env->http_topic_mgr->topic_compose[HTTP_TOPIC_RES_HEADER].topic_id, msg);
}
- else
+ break;
+ case HTTP_EVENT_RES_BODY_BEGIN:
+ break;
+ case HTTP_EVENT_RES_BODY_DATA:
{
- // if headers are not completed with EOF \r\n\r\n, push the parsed headers so far
- publish_message_for_parsed_header(half);
+ http_update_body_offset(half->flow_data);
+ msg = http_produce_message(half->sess_ref, event, HTTP_TOPIC_RES_BODY, half->flow_data);
+ mq_runtime_publish_message(mq_rt, http_env->http_topic_mgr->topic_compose[HTTP_TOPIC_RES_BODY].topic_id, msg);
}
-
- enum string_state hdr_key_state =
- http_decoder_table_state(half->ref_data->table, HTTP_ITEM_HDRKEY);
- enum string_state hdr_val_state =
- http_decoder_table_state(half->ref_data->table, HTTP_ITEM_HDRVAL);
-
- /* Truncated in http header key
- For example http header k-v => User-Agent: Chrome
- case1:
- packet1: User- hdr_key_state == STRING_STATE_REFER
- packet2: Agent: Chrome
-
- case2:
- packet1: User-Agent: hdr_key_state == STRING_STATE_COMMIT
- hdr_val_state == STRING_STATE_INIT
- packet2: Chrome
- */
- if (hdr_key_state == STRING_STATE_REFER ||
- (hdr_key_state == STRING_STATE_COMMIT && hdr_val_state == STRING_STATE_INIT))
+ break;
+ case HTTP_EVENT_RES_BODY_END:
{
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_HDRKEY);
+ http_set_body_finish(half->flow_data);
+ msg = http_produce_message(half->sess_ref, event, HTTP_TOPIC_RES_BODY, half->flow_data);
+ mq_runtime_publish_message(mq_rt, http_env->http_topic_mgr->topic_compose[HTTP_TOPIC_RES_BODY].topic_id, msg);
}
-
- /* Truncated in http header value
- For example http header k-v => User-Agent: Chrome
- packet1: User-Agent: Ch hdr_key_state == STRING_STATE_COMMIT
- hdr_val_state == STRING_STATE_REFER
-
- packet2: rome
- */
- if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_HDRVAL) == STRING_STATE_REFER)
+ break;
+ case HTTP_EVENT_RES_END:
{
- /* Header key should have been committed
- If it's not cached, cache it for next packet to use
- */
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_HDRKEY);
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_HDRVAL);
+ if ((0 == session_is_symmetric(half->sess_ref, &flow_flag) && (SESSION_SEEN_S2C_FLOW == flow_flag)))
+ {
+ http_stat_update(&http_env->stat, thread_id, HTTP_S2C_ASYMMETRY_TRANSACTION, 1);
+ }
+ http_stat_update(&http_env->stat, thread_id, HTTP_TRANSACTION_FREE, 1);
+ msg = http_produce_message(half->sess_ref, event, HTTP_TOPIC_RES_BODY, half->flow_data);
+ mq_runtime_publish_message(mq_rt, http_env->http_topic_mgr->topic_compose[HTTP_TOPIC_RES_BODY].topic_id, msg);
+ half->flow_data = NULL; // ownership move to message, free it in message free callback
}
-
- if (http_decoder_table_state(half->ref_data->table, HTTP_ITEM_BODY) == STRING_STATE_REFER)
- {
- http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_BODY);
+ break;
+ default:
+ assert(0);
+ break;
}
}
- return 0;
-}
-
-long long http_decoder_half_trans_count(struct http_decoder_half *half)
-{
- if (NULL == half)
- {
- return 0;
- }
-
- long long trans_cnt = half->trans_counter;
- half->trans_counter = 0;
-
- return trans_cnt;
-}
-
-struct http_decoder_half_data *
-http_decoder_half_data_new(nmx_pool_t *mempool)
-{
- struct http_decoder_half_data *data =
- MEMPOOL_CALLOC(mempool, struct http_decoder_half_data, 1);
- assert(data);
-
- data->table = http_decoder_table_new(mempool);
- assert(data->table);
-
- data->major_version = -1;
- data->minor_version = -1;
- data->status_code = -1;
-
- data->content_encoding = HTTP_CONTENT_ENCODING_NONE;
- // data->ref_decompress_body = NULL;
- // data->decompress_body_len = 0;
- data->decompress_buffer_list = NULL;
- return data;
-}
-
-static void http_decoder_half_decompress_buf_free(struct http_decoder_half_data *ref_data)
-{
- if (ref_data == NULL)
+ static void http_half_stage_buf_free(struct http_half *half)
{
- return;
- }
- struct http_decompress_buffer *el, *tmp;
- DL_FOREACH_SAFE(ref_data->decompress_buffer_list, el, tmp)
- {
- DL_DELETE(ref_data->decompress_buffer_list, el);
- if (el->iov.iov_base != NULL)
+ if (half->cached_header_buffer != NULL)
{
- FREE(el->iov.iov_base);
+ http_buffer_free(half->cached_header_buffer);
}
- FREE(el);
- }
- ref_data->decompress_buffer_list = NULL;
-}
-
-void http_decoder_half_data_free(nmx_pool_t *mempool, struct http_decoder_half_data *data)
-{
- if (NULL == data)
- {
- return;
- }
-
- if (data->table != NULL)
- {
- http_decoder_table_free(data->table);
- data->table = NULL;
+ half->cached_header_buffer = NULL;
}
- if (data->decompress != NULL)
+ static void http_half_stage_buf_reuse(struct http_half *half)
{
- http_content_decompress_destroy(data->decompress);
- data->decompress = NULL;
+ http_half_stage_buf_free(half);
+ half->cached_header_buffer = http_buffer_new();
}
- if (data->joint_url.iov_base)
- {
- MEMPOOL_FREE(mempool, data->joint_url.iov_base);
- data->joint_url.iov_base = NULL;
- data->joint_url_complete = 0;
- }
- http_decoder_half_decompress_buf_free(data);
- MEMPOOL_FREE(mempool, data);
-}
-
-int http_decoder_half_data_get_request_line(struct http_decoder_half_data *data,
- struct http_request_line *line)
-{
- http_decoder_table_get_method(data->table, &line->method, &line->method_len);
- http_decoder_table_get_uri(data->table, &line->uri, &line->uri_len);
- http_decoder_table_get_version(data->table, &line->version, &line->version_len);
-
- line->major_version = data->major_version;
- line->minor_version = data->minor_version;
-
- return 0;
-}
-
-int http_decoder_half_data_get_response_line(struct http_decoder_half_data *data,
- struct http_response_line *line)
-{
- http_decoder_table_get_version(data->table, &line->version, &line->version_len);
- http_decoder_table_get_status(data->table, &line->status, &line->status_len);
-
- line->major_version = data->major_version;
- line->minor_version = data->minor_version;
- line->status_code = data->status_code;
-
- return 0;
-}
-
-int http_decoder_half_data_get_header(const struct http_decoder_half_data *data,
- const char *name, size_t name_len,
- struct http_header_field *hdr_result)
-{
- return http_decoder_table_get_header(data->table, name, name_len, hdr_result);
-}
-
-int http_decoder_half_data_iter_header(struct http_decoder_half_data *data,
- struct http_header_field *header)
-{
- return http_decoder_table_iter_header((struct http_decoder_table *)data->table, header);
-}
-
-int http_decoder_half_data_reset_header_iter(struct http_decoder_half_data *req_data)
-{
- if (NULL == req_data)
- {
- return -1;
- }
- return http_decoder_table_reset_header_iter(req_data->table);
-}
-
-int http_decoder_half_data_has_parsed_header(struct http_decoder_half_data *data)
-{
- if (NULL == data)
+ static int http_half_stage_buf_append(struct http_half *half, const char *newdata, size_t newdata_len)
{
+ if (half->cached_header_buffer == NULL)
+ {
+ half->cached_header_buffer = http_buffer_new();
+ }
+ if (half->cached_header_buffer->buffer_size > HTTP_HEADERS_CACHE_MAX_SIZE)
+ {
+ return -1;
+ }
+ http_buffer_add(half->cached_header_buffer, newdata, newdata_len);
return 0;
}
- return http_decoder_table_has_parsed_header(data->table);
-}
-
-int http_decoder_half_data_get_raw_body(const struct http_decoder_half_data *data, const char **body, size_t *body_len)
-{
- if (NULL == data || NULL == body)
- {
- return -1;
- }
- return http_decoder_table_get_body(data->table, (char **)body, body_len);
-}
-#if 0
-int http_decoder_half_data_get_decompress_body(const struct http_decoder_half_data *data, hstring *body)
-{
- if (HTTP_CONTENT_ENCODING_NONE == data->content_encoding)
- {
- return http_decoder_table_get_body(data->table, body);
- }
-
- body->iov_base = data->ref_decompress_body;
- body->iov_len = data->decompress_body_len;
- return 0;
-}
-#endif
-
-void http_decoder_half_data_dump(struct http_decoder_half *half)
-{
- if (NULL == half || NULL == half->ref_data)
- {
- return;
- }
-
- http_decoder_table_dump(half->ref_data->table);
-}
-
-static void using_session_addr_as_host(struct session *ref_session, struct http_header_field *host_result, nmx_pool_t *mempool)
-{
-#if 1 // in native steallar, can't get the tuple4 from the session yet!!!
- struct httpd_session_addr ssaddr = {};
- httpd_session_get_addr(ref_session, &ssaddr);
- if (ssaddr.ipver != 4 && ssaddr.ipver != 6)
- {
- host_result->value = MEMPOOL_CALLOC(mempool, char, 1);
- sprintf((char *)host_result->value, "%s", "");
- host_result->value_len = strlen((char *)host_result->value);
- return;
- }
-
- char ip_string_buf[INET6_ADDRSTRLEN];
- if (4 == ssaddr.ipver)
- {
- host_result->value = MEMPOOL_CALLOC(mempool, char, (INET_ADDRSTRLEN + 7) /* "ip:port" max length */);
- inet_ntop(AF_INET, &ssaddr.daddr4, ip_string_buf, INET_ADDRSTRLEN);
- sprintf((char *)host_result->value, "%s:%u", ip_string_buf, ntohs(ssaddr.dport));
- host_result->value_len = strlen((char *)host_result->value);
- }
- else if (6 == ssaddr.ipver)
- {
- host_result->value = MEMPOOL_CALLOC(mempool, char, (INET6_ADDRSTRLEN + 7) /* "ip:port" max length */);
- inet_ntop(AF_INET6, &ssaddr.daddr6, ip_string_buf, INET6_ADDRSTRLEN);
- sprintf((char *)host_result->value, "%s:%u", ip_string_buf, ntohs(ssaddr.dport));
- host_result->value_len = strlen((char *)host_result->value);
- }
- else
- {
- assert(0);
- }
-#else
- host_result->val.iov_base = MEMPOOL_CALLOC(mempool, char, 32);
- sprintf((char *)host_result->val.iov_base, "%s", "todo:get_tuple4");
- host_result->val.iov_len = strlen((char *)host_result->val.iov_base);
-#endif
-}
-void http_decoder_join_url(struct http_decoder_half_data *hfdata, nmx_pool_t *mempool, const struct http_header_field *host_hdr)
-{
- int append_slash_len = 0;
- if ('/' != ((char *)hfdata->joint_url.iov_base)[0])
+ static int http_half_cache_uncompleted_header(struct http_half *half, int mem_merged, const char *data, size_t data_len)
{
- append_slash_len = 1;
- }
- int url_cache_str_len = host_hdr->value_len + hfdata->joint_url.iov_len + append_slash_len;
- char *url_cache_str = MEMPOOL_CALLOC(mempool, char, url_cache_str_len);
+ int ret = 0;
+ const char *cached_begin_ptr = NULL;
+ long long cached_len = 0;
+ if (half->half_stage.last_headers_complete_ptr == NULL)
+ {
+ if (mem_merged)
+ {
+ ret = 0; // no pipeline and memory have been merged, do nothing
+ }
+ else
+ {
+ ret = http_half_stage_buf_append(half, data, (size_t)data_len);
+ }
+ }
+ else
+ {
+ /*
+ has pipeline, cache begin ptr is the last completed header_field_value + "\r\n\r\n",
+ for example:
+ GET xxx \r\nheader_name:header:value\r\nheader_name:header:value\r\n\r\nGET yyy ...
+ ^
+ |
+ cache begin ptr
+ */
+ cached_begin_ptr = half->half_stage.last_headers_complete_ptr;
+ cached_len = (long long)data_len - (long long)(cached_begin_ptr - data);
+ assert(cached_len > 0);
- char *ptr = url_cache_str;
- memcpy(ptr, host_hdr->value, host_hdr->value_len);
- ptr += host_hdr->value_len;
- if (append_slash_len)
- {
- *ptr = '/';
- ptr++;
+ if (mem_merged)
+ {
+ /* some message have beed pushed, and pointer to half->half_stage->half_buffer,
+ the half->half_stage->half_buffer is maintain by messages ,
+ so, we can reset the half->half_stage->half_buffer, and append the new data to it.
+ */
+ http_half_stage_buf_reuse(half);
+ ret = http_half_stage_buf_append(half, cached_begin_ptr, (size_t)cached_len);
+ }
+ else
+ {
+ ret = http_half_stage_buf_append(half, cached_begin_ptr, (size_t)cached_len);
+ }
+ }
+ return ret;
}
- memcpy(ptr, hfdata->joint_url.iov_base, hfdata->joint_url.iov_len);
- MEMPOOL_FREE(mempool, hfdata->joint_url.iov_base); // free the cached uri buffer
- hfdata->joint_url.iov_base = url_cache_str;
- hfdata->joint_url.iov_len = url_cache_str_len;
- hfdata->joint_url_complete = 1;
-}
-
-void http_decoder_get_url(struct http_decoder_half_data *hfdata, nmx_pool_t *mempool)
-{
- struct http_request_line reqline = {};
- http_decoder_half_data_get_request_line(hfdata, &reqline);
- if (unlikely(http_strncasecmp_safe("CONNECT", (char *)reqline.method, 7, reqline.method_len) == 0))
+ int http_flow_parse(struct http_half *half, const char *data, size_t data_len)
{
- hfdata->joint_url.iov_base = MEMPOOL_CALLOC(mempool, char, reqline.uri_len + 1);
- memcpy(hfdata->joint_url.iov_base, reqline.uri, reqline.uri_len);
- hfdata->joint_url.iov_len = reqline.uri_len;
- hfdata->joint_url_complete = 1;
+ assert(half && data);
+ llhttp_errno_t ret = HPE_OK /* HPE_OK = 0 */;
+ ret = llhttp_execute(&half->parser.llhttp_parser, data, data_len);
+ switch (ret)
+ {
+ case HPE_OK:
+ break;
+ case HPE_PAUSED:
+ llhttp_resume(&half->parser.llhttp_parser);
+ break;
+ case HPE_PAUSED_UPGRADE:
+ llhttp_resume_after_upgrade(&half->parser.llhttp_parser);
+ break;
+ default:
+ break;
+ }
+ return ret;
}
-}
-int http_decoder_join_url_finally(struct http_event_context *ev_ctx, struct http_decoder_half_data *hfdata, nmx_pool_t *mempool)
-{
- if (hfdata->joint_url_complete)
+ struct http_half *http_flow_get_nx(struct http_exdata *exdata, enum flow_type flow_dir, struct session *sess, struct http *http_env)
{
- return 0;
- }
- struct http_header_field addr_as_host = {};
- using_session_addr_as_host(ev_ctx->ref_session, &addr_as_host, mempool);
- http_decoder_join_url(hfdata, mempool, &addr_as_host);
- MEMPOOL_FREE(mempool, addr_as_host.value); // free session addr to host buffer
- return 1;
-}
+ struct http_half **flow = NULL;
-void http_decoder_get_host_feed_url(struct http_decoder_half *half)
-{
- if (half->ref_data->joint_url_complete)
- {
- return;
- }
- struct http_header_field host_result = {};
- int host_header_cnt = http_decoder_half_data_get_header(half->ref_data, (char *)"Host", 4, &host_result);
- if (host_header_cnt < 0)
- {
- return;
+ if (FLOW_TYPE_C2S == flow_dir)
+ {
+ flow = &exdata->decoder->flow_c2s;
+ }
+ else if (FLOW_TYPE_S2C == flow_dir)
+ {
+ flow = &exdata->decoder->flow_s2c;
+ }
+ else
+ {
+ assert(0);
+ return NULL;
+ }
+ if (NULL == *flow)
+ {
+ *flow = http_half_new(flow_dir);
+ (*flow)->http_env_ref = http_env;
+ (*flow)->sess_ref = sess;
+ }
+ return *flow;
}
- http_decoder_join_url(half->ref_data, half->http_ev_ctx->ref_mempool, &host_result);
-}
-int http_half_data_get_url(struct http_decoder_half_data *res_data, const char **url_val, size_t *url_len)
-{
- if (0 == res_data->joint_url_complete)
- {
- return -1;
- }
- *url_val = res_data->joint_url.iov_base;
- *url_len = res_data->joint_url.iov_len;
- return 0;
-}
-#if 0
-int http_half_data_get_decode_url(struct http_decoder_half_data *res_data, hstring *url)
-{
- if (0 == res_data->joint_url_complete)
+ int http_half_flow_process(struct http_half *half, const char *newdata, size_t newdata_len)
{
- return -1;
- }
- url->iov_base = res_data->decoded_url.iov_base;
- url->iov_len = res_data->decoded_url.iov_len;
- return 0;
-}
-#endif
-
-int http_half_data_get_transaction_seq(struct http_decoder_half_data *hf_data)
-{
- return hf_data->transaction_index;
-}
-
-void http_half_data_update_commit_index(struct http_decoder_half_data *half_data)
-{
- http_decoder_table_update_commit_index(half_data->table);
-}
+ int ret = 0;
+ int mem_merged = 0;
+ const char *parse_data = newdata;
+ size_t parse_data_len = newdata_len;
-int http_half_data_get_total_parsed_header_count(struct http_decoder_half_data *half_data)
-{
- return http_decoder_table_get_total_parsed_header(half_data->table);
-}
-
-void http_half_pre_context_free(struct session *sess, struct http_decoder_exdata *exdata)
-{
- struct http_message *msg = NULL;
- struct http_decoder_half_data *res_data = NULL;
- struct http_decoder_result_queue *queue = NULL;
-
- if (exdata)
- {
- queue = exdata->queue;
- for (size_t i = 0; i < queue->queue_size; i++)
+ /* merge cached uncompleted header and current tcp payload first */
+ if (half->cached_header_buffer != NULL && half->cached_header_buffer->buffer != NULL)
{
- struct http_decoder_half_data *req_data = queue->array[i].req_data;
- res_data = queue->array[i].res_data;
- if ((req_data != NULL) && (NULL == res_data) && (req_data->state < HTTP_EVENT_REQ_END))
+ http_half_stage_buf_append(half, newdata, newdata_len);
+ parse_data = half->cached_header_buffer->buffer;
+ parse_data_len = half->cached_header_buffer->buffer_size;
+ mem_merged = 1;
+ if (parse_data_len > HTTP_HEADERS_CACHE_MAX_SIZE)
{
- msg = http_message_new(HTTP_TRANSACTION_END, queue, i, HTTP_REQUEST);
- session_mq_publish_message(sess, exdata->pub_topic_id, msg);
+ STELLAR_LOG_FATAL(half->http_env_ref->logger_ref, HTTP_MODULE_NAME,
+ "sess: %s, headers buf len more than %d", session_get_readable_addr(half->sess_ref), HTTP_HEADERS_CACHE_MAX_SIZE);
+ return -1;
}
}
+ ret = http_flow_parse(half, parse_data, parse_data_len);
+ if (ret != HPE_OK)
+ {
+ STELLAR_LOG_FATAL(half->http_env_ref->logger_ref, HTTP_MODULE_NAME,
+ "llhttp parser error: %d, %s. sess: %s", ret, llhttp_errno_name(ret), session_get_readable_addr(half->sess_ref));
+ return -1;
+ }
- for (size_t i = 0; i < queue->queue_size; i++)
+ if (half->half_stage.llhttp_last_stage >= LLHTTP_STAGE_MESSAGE_BEGIN &&
+ half->half_stage.llhttp_last_stage < LLHTTP_STAGE_HEADERS_COMPLETE) /* some headers not completed */
{
- res_data = queue->array[i].res_data;
- if ((res_data != NULL) && (res_data->state < HTTP_EVENT_RES_END))
+ STELLAR_LOG_DEBUG(half->http_env_ref->logger_ref, HTTP_MODULE_NAME,
+ "sess: %s, header not completed, need caching, %.*s",
+ session_get_readable_addr(half->sess_ref), parse_data_len > 16 ? 16 : parse_data_len, parse_data);
+ if (http_half_cache_uncompleted_header(half, mem_merged, parse_data, parse_data_len) < 0)
{
- msg = http_message_new(HTTP_TRANSACTION_END, queue, i, HTTP_RESPONSE);
- session_mq_publish_message(sess, exdata->pub_topic_id, msg);
+ STELLAR_LOG_FATAL(half->http_env_ref->logger_ref, HTTP_MODULE_NAME,
+ "sess: %s, headers buf len more than %d", session_get_readable_addr(half->sess_ref), HTTP_HEADERS_CACHE_MAX_SIZE);
+ return -1;
}
+
+ /* uncompleted_header, reset llhttp state and all headers */
+ http_half_stage_reset(half);
+ llhttp_reset(&half->parser.llhttp_parser);
+ return 0;
+ }
+ else
+ {
+ /* ownership is maintained by header message, free it here (reference-- actually) */
+ http_half_stage_buf_free(half);
}
+ return 0;
}
-}
-void http_half_update_state(struct http_decoder_half_data *hf_data, enum http_event state)
-{
- hf_data->state = state;
+#ifdef __cplusplus
}
-
-void http_half_get_max_transaction_seq(struct http_decoder_exdata *exdata, long long *max_req_seq, long long *max_res_seq)
-{
- assert(exdata && max_req_seq && max_res_seq);
- *max_req_seq = exdata->decoder->c2s_half->transaction_seq;
- *max_res_seq = exdata->decoder->s2c_half->transaction_seq;
-}
-
-enum http_content_encoding http_half_data_get_content_encoding(struct http_decoder_half_data *hf_data)
-{
- if (NULL == hf_data)
- {
- return HTTP_CONTENT_ENCODING_NONE;
- }
- return hf_data->content_encoding;
-} \ No newline at end of file
+#endif
diff --git a/decoders/http/http_decoder_half.h b/decoders/http/http_decoder_half.h
index f525f78..6daf32c 100644
--- a/decoders/http/http_decoder_half.h
+++ b/decoders/http/http_decoder_half.h
@@ -1,109 +1,172 @@
#pragma once
+#include <stdint.h>
#include <stddef.h>
#include "stellar/session.h"
#include "stellar/http.h"
-#include "http_content_decompress.h"
-#include "http_decoder_result_queue.h"
-#include <llhttp.h>
+#include "llhttp.h"
+#include "uthash/utarray.h"
+#include "http_decoder_decompress.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#define HTTP_HEADER_FIELD_RESERVE_NUM (16)
+
+#define HTTP_HEADER_FIELD_NAME_HOST "Host"
+#define HTTP_HEADER_FIELD_NAME_USER_AGENT "User-Agent"
+#define HTTP_HEADER_FIELD_NAME_REFERER "Referer"
+#define HTTP_HEADER_FIELD_NAME_COOKIE "Cookie"
+#define HTTP_HEADER_FIELD_NAME_SET_COOKIE "Set-Cookie"
+#define HTTP_HEADER_FIELD_NAME_CONTENT_TYPE "Content-Type"
+#define HTTP_HEADER_FIELD_NAME_CONTENT_LENGTH "Content-Length"
+#define HTTP_HEADER_FIELD_NAME_CONTENT_ENCODING "Content-Encoding"
+#define HTTP_HEADER_FIELD_NAME_TRANSFER_ENCODING "Transfer-Encoding"
+
+ enum http_event
+ {
+ __HTTP_EVENT_RESERVED = 0,
+ HTTP_EVENT_REQ_INIT = 1 << 1,
+ HTTP_EVENT_REQ_LINE = 1 << 2,
+ HTTP_EVENT_REQ_HDR = 1 << 3,
+ HTTP_EVENT_REQ_HDR_END = 1 << 4,
+ HTTP_EVENT_REQ_BODY_BEGIN = 1 << 5,
+ HTTP_EVENT_REQ_BODY_DATA = 1 << 6,
+ HTTP_EVENT_REQ_BODY_END = 1 << 7,
+ HTTP_EVENT_REQ_END = 1 << 8,
+
+ HTTP_EVENT_RES_INIT = 1 << 9,
+ HTTP_EVENT_RES_LINE = 1 << 10,
+ HTTP_EVENT_RES_HDR = 1 << 11,
+ HTTP_EVENT_RES_HDR_END = 1 << 12,
+ HTTP_EVENT_RES_BODY_BEGIN = 1 << 13,
+ HTTP_EVENT_RES_BODY_DATA = 1 << 14,
+ HTTP_EVENT_RES_BODY_END = 1 << 15,
+ HTTP_EVENT_RES_END = 1 << 16,
+ };
+
+ struct http_body
+ {
+ char *body;
+ size_t body_sz;
+ size_t offset; // accumulated
+ int is_finished;
+ };
#ifndef hstring
#include <bits/types/struct_iovec.h>
-typedef struct iovec hstring;
+ typedef struct iovec hstring;
#endif
-// only one http event is fired at a time
-enum http_event
-{
- HTTP_EVENT_REQ_INIT = 1 << 1,
- HTTP_EVENT_REQ_LINE = 1 << 2,
- HTTP_EVENT_REQ_HDR = 1 << 3,
- HTTP_EVENT_REQ_HDR_END = 1 << 4,
- HTTP_EVENT_REQ_BODY_BEGIN = 1 << 5,
- HTTP_EVENT_REQ_BODY_DATA = 1 << 6,
- HTTP_EVENT_REQ_BODY_END = 1 << 7,
- HTTP_EVENT_REQ_END = 1 << 8,
-
- HTTP_EVENT_RES_INIT = 1 << 9,
- HTTP_EVENT_RES_LINE = 1 << 10,
- HTTP_EVENT_RES_HDR = 1 << 11,
- HTTP_EVENT_RES_HDR_END = 1 << 12,
- HTTP_EVENT_RES_BODY_BEGIN = 1 << 13,
- HTTP_EVENT_RES_BODY_DATA = 1 << 14,
- HTTP_EVENT_RES_BODY_END = 1 << 15,
- HTTP_EVENT_RES_END = 1 << 16,
-};
-
-struct http_event_context
-{
- struct http_decoder_exdata *ref_httpd_ctx;
- nmx_pool_t *ref_mempool;
- struct session *ref_session;
- struct http_decoder_result_queue *ref_queue;
-};
-
-struct http_decoder_half;
-struct http_decoder_half_data;
-struct http_decoder_env;
-
-typedef void http_event_cb(enum http_event event, struct http_decoder_half_data **data,
- struct http_event_context *ev_ctx, void *httpd_plugin_env);
-
-struct http_decoder_half *
-http_decoder_half_new(struct http_decoder_exdata *hd_ctx, nmx_pool_t *mempool, http_event_cb *event_cb,
- enum llhttp_type http_type, int decompress_switch, struct http_decoder_env *httpd_env, long long start_seq);
-
-void http_decoder_half_free(nmx_pool_t *mempool, struct http_decoder_half *half);
-
-void http_decoder_half_reinit(struct http_decoder_half *half,
- struct http_decoder_result_queue *queue,
- nmx_pool_t *mempool, struct session *sess);
-
-int http_decoder_half_parse(int proxy_enable, struct http_decoder_half *half, const char *data, size_t data_len);
-
-long long http_decoder_half_trans_count(struct http_decoder_half *half);
-
-// http decoder half data API
-struct http_decoder_half_data *
-http_decoder_half_data_new(nmx_pool_t *mempool);
-
-void http_decoder_half_data_free(nmx_pool_t *mempool, struct http_decoder_half_data *data);
-
-int http_decoder_half_data_get_request_line(struct http_decoder_half_data *data,
- struct http_request_line *line);
-
-int http_decoder_half_data_get_response_line(struct http_decoder_half_data *data,
- struct http_response_line *line);
-
-int http_decoder_half_data_get_header(const struct http_decoder_half_data *data,
- const char *name, size_t name_len, struct http_header_field *hdr_res);
-
-int http_decoder_half_data_iter_header(struct http_decoder_half_data *data,
- struct http_header_field *header);
-int http_decoder_half_data_reset_header_iter(struct http_decoder_half_data *req_data);
-int http_decoder_half_data_has_parsed_header(struct http_decoder_half_data *data);
-
-int http_decoder_half_data_get_raw_body(const struct http_decoder_half_data *data, const char **body, size_t *body_len);
-
-int http_decoder_half_data_get_decompress_body(const struct http_decoder_half_data *data, const char **body, size_t *body_len);
-void http_half_get_lastest_decompress_buffer(struct http_decoder_half_data *data, hstring *decompress_body);
-void http_half_decompress_buffer_free(struct http_decoder_half_data *data, hstring *decompress_body);
-void http_decoder_half_data_dump(struct http_decoder_half *half);
-
-void http_decoder_get_host_feed_url(struct http_decoder_half *half);
-void http_decoder_get_url(struct http_decoder_half_data *hfdata, nmx_pool_t *mempool);
-int http_half_data_get_decode_url(struct http_decoder_half_data *res_data, hstring *url);
-void http_decoder_join_url(struct http_decoder_half_data *hfdata,
- nmx_pool_t *mempool,
- const struct http_header_field *host_hdr);
-int http_decoder_join_url_finally(struct http_event_context *ev_ctx,
- struct http_decoder_half_data *hfdata,
- nmx_pool_t *mempool);
-int http_half_data_get_url(struct http_decoder_half_data *res_data, const char **url_val, size_t *url_len);
-int http_half_data_get_transaction_seq(struct http_decoder_half_data *hf_data);
-
-void http_half_data_update_commit_index(struct http_decoder_half_data *half_data);
-void http_half_pre_context_free(struct session *sess, struct http_decoder_exdata *exdata);
-void http_half_update_state(struct http_decoder_half_data *hf_data, enum http_event state);
-int http_half_data_get_total_parsed_header_count(struct http_decoder_half_data *half_data);
-void http_half_get_max_transaction_seq(struct http_decoder_exdata *exdata, long long *max_req_seq, long long *max_res_seq);
-enum http_content_encoding http_half_data_get_content_encoding(struct http_decoder_half_data *hf_data); \ No newline at end of file
+ struct http_half_data
+ {
+ enum flow_type flow_dir;
+ uint32_t transaction_seq; // seq of this half flow, is last http_lalf->transaction_num value
+ union
+ {
+ struct http_request_line req_line;
+ struct http_status_line status_line;
+ };
+
+ /* headers */
+ struct http_buffer *cached_header_buffer; // maybe null
+ hstring joint_url; // malloc, need be free
+ enum http_content_encoding content_encoding_type;
+ int transfer_encoding_is_chunked; // -1: not set, 0: false, 1: true
+ UT_array *ut_filed_array; // inner struct, need to transform to header->field_array
+ struct http_header header;
+
+ /* body */
+ struct http_body raw_body;
+ struct http_content_decompress *decompress;
+ struct http_body decompress_body;
+ };
+
+ struct http_half_parser
+ {
+ llhttp_t llhttp_parser;
+ llhttp_settings_t settings;
+ struct http_half *half_ref; // used in llhttp callback context to get flow
+ };
+
+ enum http_stage
+ {
+ HTTP_STAGE_INIT = 0,
+ HTTP_STAGE_PENDING = 1, /* body without Content-Length, no Chunk-Encoding */
+ HTTP_STAGE_HEADER_PARTIAL = 2,
+ HTTP_STAGE_BODY = 3,
+ };
+
+ struct http_stage_shaper
+ {
+ enum http_stage stage;
+ char *data;
+ size_t data_len;
+ long long remain_content_length;
+ const char *headers_start; // the first header field name
+ const char *headers_end; // the last char of \r\n\r\n
+ struct http_buffer *headers_cache; /* ownership move to struct http_decoder_half_data when headers completed */
+ };
+
+ struct http_half_buffer
+ {
+ int is_malloc; // need free
+ int ref_count; // +1 when push a new message
+ char *buffer;
+ size_t buffer_size;
+ };
+
+ enum http_half_llhttp_stage_type
+ {
+ LLHTTP_STAGE_MESSAGE_BEGIN = 0,
+ LLHTTP_STAGE_URI,
+ LLHTTP_STAGE_METHOD,
+ LLHTTP_STAGE_STATUS,
+ LLHTTP_STAGE_VERSION,
+ LLHTTP_STAGE_HEADER_FIELD,
+ LLHTTP_STAGE_HEADER_FIELD_COMPLETE,
+ LLHTTP_STAGE_HEADER_VALUE,
+ LLHTTP_STAGE_HEADER_VALUE_COMPLETE,
+ LLHTTP_STAGE_HEADERS_COMPLETE,
+ LLHTTP_STAGE_BODY,
+ LLHTTP_STAGE_MESSAGE_COMPLETE,
+ __LLHTTP_STAGE_MAX,
+ };
+
+ struct http_half_llhttp_stage
+ {
+ const char *first_header_name_ptr;
+ const char *last_header_value_complete_ptr; /* at + length + 4 \r\n\r\n) */
+ const char *last_headers_complete_ptr;
+ enum http_half_llhttp_stage_type llhttp_last_stage;
+ uint8_t llhttp_cb_count[__LLHTTP_STAGE_MAX];
+ };
+
+ struct http_half
+ {
+ struct session *sess_ref;
+ struct http *http_env_ref;
+
+ uint32_t transaction_num; // accumulated of all flows in this session
+ enum http_event event;
+ // struct http_stage_shaper shaper;
+
+ struct http_half_parser parser;
+ struct http_half_data *flow_data; // malloc when every transaction start, ownership move to message when message completed
+
+ struct http_buffer *cached_header_buffer;
+ struct http_half_llhttp_stage half_stage;
+ };
+ void http_half_free(struct http_half *half);
+ void http_half_data_free(struct http_half_data *half_data);
+ void http_flow_parser_init(struct http_half_parser *flow_parser, enum llhttp_type type);
+ void http_flow_body_decompress(struct http_half_data *flow_data, const char *zipdata, size_t zipdatalen);
+ void http_event_handler(struct http_half *half, enum http_event event, struct http *httpd_env);
+ int http_flow_stage_shaping(struct http_half *half, const char *newdata, size_t newdata_len);
+ int http_half_flow_process(struct http_half *half, const char *newdata, size_t newdata_len);
+ int http_get_header_field_count(struct http_half_data *flow_data);
+ void http_flow_append_header_filed(struct http_half_data *flow_data, const char *at, size_t length);
+ void http_flow_append_header_value(struct http_half_data *flow_data, const char *at, size_t length);
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/decoders/http/http_decoder_llhttp_wrap.c b/decoders/http/http_decoder_llhttp_wrap.c
new file mode 100644
index 0000000..b025311
--- /dev/null
+++ b/decoders/http/http_decoder_llhttp_wrap.c
@@ -0,0 +1,318 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include "stellar/utils.h"
+#include "http_decoder.h"
+#include "llhttp.h"
+#include "http_decoder_half.h"
+
+/* Possible return values 0, -1, `HPE_PAUSED` */
+static int on_message_begin(llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_MESSAGE_BEGIN;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_MESSAGE_BEGIN]++;
+ if (http->type == HTTP_REQUEST)
+ {
+ half->event = HTTP_EVENT_REQ_INIT;
+ }
+ else
+ {
+ half->event = HTTP_EVENT_RES_INIT;
+ }
+ http_event_handler(parser->half_ref, half->event, parser->half_ref->http_env_ref);
+ return 0;
+}
+
+static int on_message_complete(llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_MESSAGE_COMPLETE;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_MESSAGE_COMPLETE]++;
+ if (http->type == HTTP_REQUEST)
+ {
+ if (half->event == HTTP_EVENT_REQ_BODY_DATA)
+ {
+ half->event = HTTP_EVENT_REQ_BODY_END;
+ http_event_handler(parser->half_ref, half->event, parser->half_ref->http_env_ref);
+ }
+ }
+ else
+ {
+ if (half->event == HTTP_EVENT_RES_BODY_DATA)
+ {
+ half->event = HTTP_EVENT_RES_BODY_END;
+ http_event_handler(parser->half_ref, half->event, parser->half_ref->http_env_ref);
+ }
+ }
+
+ // trigger req_end/res_end
+ if (http->type == HTTP_REQUEST)
+ {
+ half->event = HTTP_EVENT_REQ_END;
+ }
+ else
+ {
+ half->event = HTTP_EVENT_RES_END;
+ }
+ http_event_handler(parser->half_ref, half->event, parser->half_ref->http_env_ref);
+ half->event = __HTTP_EVENT_RESERVED;
+ return 0;
+}
+
+static int on_method(llhttp_t *http, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->flow_data->req_line.method = (char *)at;
+ half->flow_data->req_line.method_len = length;
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_METHOD;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_METHOD]++;
+ return 0;
+}
+
+/* Possible return values 0, -1, HPE_USER */
+static int on_uri(llhttp_t *http, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->flow_data->req_line.uri = (char *)at;
+ half->flow_data->req_line.uri_len = length;
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_URI;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_URI]++;
+ return 0;
+}
+
+/* Possible return values 0, -1, HPE_USER */
+static int on_version(llhttp_t *http, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ if (http->type == HTTP_REQUEST)
+ {
+ half->flow_data->req_line.version = (char *)at;
+ half->flow_data->req_line.version_len = length;
+ }
+ else
+ {
+ half->flow_data->status_line.version = (char *)at;
+ half->flow_data->status_line.version_len = length;
+ }
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_VERSION;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_VERSION]++;
+ return 0;
+}
+
+/* Information-only callbacks, return value is ignored */
+static int on_version_complete(llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ if (http->type == HTTP_REQUEST)
+ {
+ half->flow_data->req_line.major_version = llhttp_get_http_major(http);
+ half->flow_data->req_line.minor_version = llhttp_get_http_minor(http);
+ }
+ else
+ {
+ half->flow_data->status_line.major_version = llhttp_get_http_major(http);
+ half->flow_data->status_line.minor_version = llhttp_get_http_minor(http);
+ }
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_VERSION;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_VERSION]++;
+ return 0;
+}
+
+/* Possible return values 0, -1, HPE_USER */
+static int on_status(llhttp_t *http, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->flow_data->status_line.status = (char *)at;
+ half->flow_data->status_line.status_len = length;
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_STATUS;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_STATUS]++;
+ return 0;
+}
+
+/* Information-only callbacks, return value is ignored */
+static int on_status_complete(llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->flow_data->status_line.status_code = llhttp_get_status_code(http);
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_STATUS;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_STATUS]++;
+ return 0;
+}
+
+/* Possible return values 0, -1, HPE_USER */
+static int on_header_field(llhttp_t *http, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ http_flow_append_header_filed(half->flow_data, at, length);
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_HEADER_FIELD;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_HEADER_FIELD]++;
+ if (half->half_stage.first_header_name_ptr == NULL)
+ {
+ half->half_stage.first_header_name_ptr = at;
+ }
+ return 0;
+}
+
+static int on_header_field_complete(llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_HEADER_FIELD_COMPLETE;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_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)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ http_flow_append_header_value(half->flow_data, at, length);
+ half->half_stage.last_header_value_complete_ptr = at + length;
+ return 0;
+}
+
+static int on_header_value_complete(llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_HEADER_VALUE_COMPLETE;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_HEADER_VALUE_COMPLETE]++;
+ if (NULL != half->half_stage.last_header_value_complete_ptr) /* header value maybe empty(NULL) */
+ {
+ if (strncmp("\r\n", half->half_stage.last_header_value_complete_ptr, 2) == 0)
+ {
+ half->half_stage.last_header_value_complete_ptr += 2;
+ }
+ }
+ 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)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ if (http->type == HTTP_REQUEST)
+ {
+ half->event = HTTP_EVENT_REQ_HDR_END;
+ }
+ else
+ {
+ half->event = HTTP_EVENT_RES_HDR_END;
+ }
+ half->half_stage.last_headers_complete_ptr = half->half_stage.last_header_value_complete_ptr;
+ if (half->half_stage.last_headers_complete_ptr != NULL &&
+ strncmp("\r\n", half->half_stage.last_headers_complete_ptr, 2) == 0)
+ {
+ half->half_stage.last_headers_complete_ptr += 2;
+ }
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_HEADERS_COMPLETE;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_HEADERS_COMPLETE]++;
+ http_event_handler(half, half->event, half->http_env_ref);
+ return 0;
+}
+
+/* Possible return values 0, -1, HPE_USER */
+static int on_body(llhttp_t *http, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ int has_new_data = 0;
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *half = parser->half_ref;
+ half->half_stage.llhttp_last_stage = LLHTTP_STAGE_BODY;
+ half->half_stage.llhttp_cb_count[LLHTTP_STAGE_BODY]++;
+
+ if (half->http_env_ref->hd_cfg.decompress_switch != 0 &&
+ half->flow_data->content_encoding_type != HTTP_CONTENT_ENCODING_NONE)
+ {
+ http_flow_body_decompress(half->flow_data, at, length);
+ if (half->flow_data->decompress_body.body != NULL && half->flow_data->decompress_body.body_sz > 0)
+ {
+ has_new_data = 1;
+ }
+ }
+ else
+ {
+ half->flow_data->raw_body.body = (char *)at;
+ half->flow_data->raw_body.body_sz = length;
+ has_new_data = 1;
+ }
+ if (has_new_data)
+ {
+ if (http->type == HTTP_REQUEST)
+ {
+ half->event = HTTP_EVENT_REQ_BODY_DATA;
+ }
+ else
+ {
+ half->event = HTTP_EVENT_RES_BODY_DATA;
+ }
+ http_event_handler(half, half->event, half->http_env_ref);
+ }
+ return 0;
+}
+
+void http_flow_parser_init(struct http_half_parser *flow_parser, enum llhttp_type type)
+{
+ llhttp_settings_init(&flow_parser->settings);
+ llhttp_settings_t *sets = &flow_parser->settings;
+ sets->on_message_begin = on_message_begin;
+ sets->on_url = on_uri;
+ sets->on_status = on_status;
+ sets->on_status_complete = on_status_complete;
+ sets->on_method = on_method;
+ sets->on_version = on_version;
+ sets->on_version_complete = on_version_complete;
+ sets->on_header_field = on_header_field;
+ sets->on_header_field_complete = on_header_field_complete;
+ sets->on_header_value = on_header_value;
+ sets->on_header_value_complete = on_header_value_complete;
+ sets->on_headers_complete = on_headers_complete;
+ sets->on_body = on_body;
+ sets->on_message_complete = on_message_complete;
+ llhttp_init(&flow_parser->llhttp_parser, type, sets);
+} \ No newline at end of file
diff --git a/decoders/http/http_decoder_module.c b/decoders/http/http_decoder_module.c
new file mode 100644
index 0000000..53ff71b
--- /dev/null
+++ b/decoders/http/http_decoder_module.c
@@ -0,0 +1,299 @@
+#include <stdio.h>
+#include <assert.h>
+#include "stellar/session.h"
+#include "stellar/module.h"
+#include "http_decoder_utils.h"
+#include "http_decoder_half.h"
+#include "http_decoder.h"
+#include "toml/toml.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ __thread struct http_topic_manager *chaotic_http_topic_mgr;
+
+#define HTTP_TOPIC_NAME_REQ_HDR "HTTP_TOPIC_REQ_HDR"
+#define HTTP_TOPIC_NAME_REQ_BODY "HTTP_TOPIC_REQ_BODY"
+#define HTTP_TOPIC_NAME_RES_HDR "HTTP_TOPIC_RES_HDR"
+#define HTTP_TOPIC_NAME_RES_BODY "HTTP_TOPIC_RES_BODY"
+
+ static void http_set_default_config(struct http_config *hd_cfg)
+ {
+ hd_cfg->decompress_switch = 1;
+ }
+ static int http_load_config(const char *cfg_path, struct http_config *hd_cfg)
+ {
+ FILE *fp = fopen(cfg_path, "r");
+ if (NULL == fp)
+ {
+ fprintf(stderr, "[%s]Can't open config file:%s", __FUNCTION__, cfg_path);
+ return -1;
+ }
+ int ret = 0;
+ char errbuf[256] = {0};
+ toml_table_t *root = toml_parse_file(fp, errbuf, sizeof(errbuf));
+ fclose(fp);
+
+ toml_table_t *section = toml_table_in(root, "http");
+ if (section == NULL)
+ {
+ fprintf(stderr, "(logger) config file %s missing 'http' section\n", cfg_path);
+ goto error_exit;
+ }
+
+ toml_datum_t int_val = toml_int_in(section, "decompress_enable");
+ if (int_val.ok != 0)
+ {
+ hd_cfg->decompress_switch = int_val.u.b;
+ }
+ error_exit:
+ toml_free(root);
+ return ret;
+ }
+
+ static void http_update_header_array(struct http_half_data *flow_data)
+ {
+ if (0 == http_get_header_field_count(flow_data))
+ {
+ flow_data->header.field_array = NULL;
+ flow_data->header.field_array_num = 0;
+ }
+ else
+ {
+ flow_data->header.field_array = (struct http_header_field *)utarray_front(flow_data->ut_filed_array);
+ flow_data->header.field_array_num = utarray_len(flow_data->ut_filed_array);
+ }
+ }
+
+ static void http_on_msg_dispatch(int topic_id UNUSED, void *msg, on_msg_cb_func *on_msg_cb,
+ void *on_msg_cb_arg, void *dispatch_arg UNUSED)
+ {
+ assert(msg != NULL && on_msg_cb != NULL);
+ struct http_message *hmsg = (struct http_message *)msg;
+ struct http_half_data *flow_data = hmsg->flow_data;
+
+ if (hmsg->event == HTTP_EVENT_REQ_END || hmsg->event == HTTP_EVENT_RES_END)
+ {
+ /* notify subscriber ? */
+ return;
+ }
+ switch (hmsg->topic_type)
+ {
+ case HTTP_TOPIC_REQ_HEADER:
+ {
+ http_update_header_array(flow_data);
+ http_on_request_header_cb *on_req_hdr_cb = (http_on_request_header_cb *)((void *)on_msg_cb);
+ on_req_hdr_cb(hmsg->sess_ref, flow_data->transaction_seq, &flow_data->req_line, &flow_data->header,
+ (const char *)flow_data->joint_url.iov_base, flow_data->joint_url.iov_len,
+ on_msg_cb_arg);
+ }
+ break;
+ case HTTP_TOPIC_RES_HEADER:
+ {
+ http_update_header_array(flow_data);
+ http_on_response_header_cb *on_res_hdr_cb = (http_on_response_header_cb *)((void *)on_msg_cb);
+ on_res_hdr_cb(hmsg->sess_ref, flow_data->transaction_seq, &flow_data->status_line, &flow_data->header, on_msg_cb_arg);
+ }
+ break;
+ case HTTP_TOPIC_REQ_BODY:
+ case HTTP_TOPIC_RES_BODY:
+ {
+ http_on_body_cb *on_body_cb = (http_on_body_cb *)((void *)on_msg_cb);
+ if (flow_data->decompress_body.body != NULL || flow_data->decompress_body.offset > 0)
+ {
+ on_body_cb(hmsg->sess_ref, flow_data->decompress_body.body, flow_data->decompress_body.body_sz, flow_data->decompress_body.offset,
+ flow_data->transaction_seq, flow_data->decompress_body.is_finished, on_msg_cb_arg);
+ }
+ else
+ {
+ on_body_cb(hmsg->sess_ref, flow_data->raw_body.body, flow_data->raw_body.body_sz, flow_data->raw_body.offset,
+ flow_data->transaction_seq, flow_data->raw_body.is_finished, on_msg_cb_arg);
+ }
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ static int http_create_topic_nx(struct module_manager *mod_mgr, const char *topic_name)
+ {
+ struct mq_schema *mq_s = module_manager_get_mq_schema(mod_mgr);
+ assert(mq_s != NULL);
+ int quic_topic_id = mq_schema_get_topic_id(mq_s, topic_name);
+ if (quic_topic_id >= 0)
+ {
+ return quic_topic_id;
+ }
+ int topic_id = mq_schema_create_topic(mq_s, topic_name, (on_msg_dispatch_cb_func *)http_on_msg_dispatch,
+ NULL, http_message_free_cb, NULL);
+ return topic_id;
+ }
+
+ struct http_topic_manager *http_topic_mgr_init(struct module_manager *mod_mgr)
+ {
+ if (chaotic_http_topic_mgr != NULL)
+ {
+ return chaotic_http_topic_mgr;
+ }
+ struct http_topic_manager *http_topic_mgr = (struct http_topic_manager *)calloc(1, sizeof(struct http_topic_manager));
+ assert(http_topic_mgr != NULL);
+ struct http_topic_compose *topic_compose = http_topic_mgr->topic_compose;
+
+ topic_compose[HTTP_TOPIC_REQ_HEADER].topic_name = HTTP_TOPIC_NAME_REQ_HDR;
+ topic_compose[HTTP_TOPIC_REQ_BODY].topic_name = HTTP_TOPIC_NAME_REQ_BODY;
+ topic_compose[HTTP_TOPIC_RES_HEADER].topic_name = HTTP_TOPIC_NAME_RES_HDR;
+ topic_compose[HTTP_TOPIC_RES_BODY].topic_name = HTTP_TOPIC_NAME_RES_BODY;
+
+ topic_compose[HTTP_TOPIC_REQ_HEADER].topic_id = http_create_topic_nx(mod_mgr, HTTP_TOPIC_NAME_REQ_HDR);
+ topic_compose[HTTP_TOPIC_REQ_BODY].topic_id = http_create_topic_nx(mod_mgr, HTTP_TOPIC_NAME_REQ_BODY);
+ topic_compose[HTTP_TOPIC_RES_HEADER].topic_id = http_create_topic_nx(mod_mgr, HTTP_TOPIC_NAME_RES_HDR);
+ topic_compose[HTTP_TOPIC_RES_BODY].topic_id = http_create_topic_nx(mod_mgr, HTTP_TOPIC_NAME_RES_BODY);
+ chaotic_http_topic_mgr = http_topic_mgr;
+ return http_topic_mgr;
+ }
+
+ void http_topic_mgr_free(struct http_topic_manager *topic_mgr)
+ {
+ assert(topic_mgr != NULL);
+ FREE(topic_mgr);
+ }
+
+ static int http_subscribe_common(struct module_manager *mod_mgr, enum http_topic_type topic_type, void *cb, void *args)
+ {
+ struct http_topic_manager *http_topic_mgr = chaotic_http_topic_mgr;
+ if (http_topic_mgr == NULL)
+ {
+ http_topic_mgr = http_topic_mgr_init(mod_mgr);
+ chaotic_http_topic_mgr = http_topic_mgr;
+ }
+ return mq_schema_subscribe(module_manager_get_mq_schema(mod_mgr),
+ http_topic_mgr->topic_compose[topic_type].topic_id,
+ (on_msg_cb_func *)cb, args);
+ }
+
+ int http_subscribe_request_header(struct module_manager *mod_mgr, http_on_request_header_cb *cb, void *args)
+ {
+ assert(mod_mgr != NULL);
+ return http_subscribe_common(mod_mgr, HTTP_TOPIC_REQ_HEADER, cb, args);
+ }
+
+ int http_subscribe_response_header(struct module_manager *mod_mgr, http_on_response_header_cb *cb, void *args)
+ {
+ assert(mod_mgr != NULL);
+ return http_subscribe_common(mod_mgr, HTTP_TOPIC_RES_HEADER, cb, args);
+ }
+
+ int http_subscribe_request_body(struct module_manager *mod_mgr, http_on_body_cb *cb, void *args)
+ {
+ assert(mod_mgr != NULL);
+ return http_subscribe_common(mod_mgr, HTTP_TOPIC_REQ_BODY, cb, args);
+ }
+
+ int http_subscribe_response_body(struct module_manager *mod_mgr, http_on_body_cb *cb, void *args)
+ {
+ assert(mod_mgr != NULL);
+ return http_subscribe_common(mod_mgr, HTTP_TOPIC_RES_BODY, cb, args);
+ }
+
+ int http_subscribe(struct http *http, struct http_subscirbe_params *params, void *arg)
+ {
+ assert(http != NULL && params != NULL);
+ struct module_manager *mod_mgr = http->mod_mgr_ref;
+ int ret = 0;
+ if (params->req_hdr_cb != NULL)
+ {
+ ret = http_subscribe_request_header(mod_mgr, params->req_hdr_cb, arg);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+ if (params->res_hdr_cb != NULL)
+ {
+ ret = http_subscribe_response_header(mod_mgr, params->res_hdr_cb, arg);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+ if (params->req_body_cb != NULL)
+ {
+ ret = http_subscribe_request_body(mod_mgr, params->req_body_cb, arg);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+ if (params->res_body_cb != NULL)
+ {
+ ret = http_subscribe_response_body(mod_mgr, params->res_body_cb, arg);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+ return ret;
+ }
+
+ struct module *http_init(struct module_manager *mod_mgr)
+ {
+ assert(mod_mgr != NULL);
+ struct http *http_env = (struct http *)calloc(1, sizeof(struct http));
+ http_set_default_config(&http_env->hd_cfg);
+ http_load_config(module_manager_get_toml_path(mod_mgr), &http_env->hd_cfg);
+ http_stat_init(mod_mgr, &http_env->stat);
+ struct module *mod = module_new(HTTP_MODULE_NAME, http_env);
+ http_env->mod_mgr_ref = mod_mgr;
+
+ http_env->logger_ref = module_manager_get_logger(mod_mgr);
+ assert(http_env->logger_ref != NULL);
+ struct module *sess_mod = module_manager_get_module(mod_mgr, SESSION_MANAGER_MODULE_NAME);
+ struct session_manager *sess_mgr = module_to_session_manager(sess_mod);
+ assert(sess_mgr != NULL);
+
+ struct http_topic_manager *http_topic_mgr = http_topic_mgr_init(mod_mgr);
+ assert(http_topic_mgr != NULL);
+ http_env->http_topic_mgr = http_topic_mgr;
+
+ session_manager_subscribe_tcp_stream(sess_mgr, http_on_tcp_stream_cb, http_env);
+ http_env->exdata_id = session_manager_new_session_exdata_index(sess_mgr, HTTP_EXDATA_NAME, http_exdata_free_cb, http_env);
+ STELLAR_LOG_FATAL(http_env->logger_ref, HTTP_MODULE_NAME,
+ "http init success, decompress_switch:%d", http_env->hd_cfg.decompress_switch);
+ return mod;
+ }
+ struct module *http_get_module(struct module_manager *mod_mgr)
+ {
+ assert(mod_mgr != NULL);
+
+ struct module *http_mod = module_manager_get_module(mod_mgr, HTTP_MODULE_NAME);
+ if (NULL == http_mod)
+ {
+ http_mod = http_init(mod_mgr);
+ }
+ return http_mod;
+ }
+
+ struct http *http_module_to_http(struct module *http_mod)
+ {
+ assert(http_mod);
+ return (struct http *)module_get_ctx(http_mod);
+ }
+
+ void http_exit(struct module_manager *mod_mgr UNUSED, struct module *mod)
+ {
+ assert(mod != NULL);
+ struct http *http_env = (struct http *)module_get_ctx(mod);
+ http_stat_free(&http_env->stat);
+ http_topic_mgr_free(http_env->http_topic_mgr);
+ STELLAR_LOG_FATAL(http_env->logger_ref, HTTP_MODULE_NAME, "http exit!");
+ FREE(http_env);
+ module_free(mod);
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/decoders/http/http_decoder_private.h b/decoders/http/http_decoder_private.h
deleted file mode 100644
index 04130f0..0000000
--- a/decoders/http/http_decoder_private.h
+++ /dev/null
@@ -1,155 +0,0 @@
-
-#pragma once
-
-#ifndef __USE_MISC
-#define __USE_MISC 1
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-#include <bits/types/struct_iovec.h>
-#include "stellar/stellar.h"
-#include "stellar/packet.h"
-#include "stellar/utils.h"
-#include "stellar/session.h"
-#include "stellar/stellar_mq.h"
-#include "stellar/stellar_exdata.h"
-
-#include "nmx_pool/nmx_palloc.h"
-#include "stellar/utils.h"
-#include "stellar/http.h"
-#include "http_decoder_result_queue.h"
-#include "http_decoder_half.h"
-#include "http_decoder_table.h"
-#include "http_decoder_result_queue.h"
-#include "http_decoder_utils.h"
-#include "http_decoder_stat.h"
-#include "http_decoder_tunnel.h"
-#include "fieldstat/fieldstat_easy.h"
-#include "toml/toml.h"
-
-#ifndef hstring
-#include <bits/types/struct_iovec.h>
-typedef struct iovec hstring;
-#endif
-
-#ifndef likely
-#define likely(x) __builtin_expect((x), 1)
-#endif
-#ifndef unlikely
-#define unlikely(x) __builtin_expect((x), 0)
-#endif
-
-#define MEMPOOL_CALLOC(pool, type, number) ((type *)nmx_pcalloc(pool, sizeof(type) * number))
-#define MEMPOOL_REALLOC(pool)
-#define MEMPOOL_FREE(pool, p) nmx_pfree(pool, p)
-
-#define ENABLE_MEMPOOL 0
-#if ENABLE_MEMPOOL
-#define HD_CALLOC(pool, type, number) MEMPOOL_CALLOC(pool, number, type)
-#define HD_FREE(pool, p) MEMPOOL_FREE(pool, p)
-#else
-#define HD_CALLOC(pool, type, number) CALLOC(type, number)
-#define HD_FREE(pool, p) FREE(p)
-#endif
-
-#define HTTP_IDENTIFY_LEN 16
-#define HD_RESULT_QUEUE_LEN 16
-
-#define DEFAULT_STAT_OUTPUT_INTERVAL 1
-#define DEFAULT_STAT_INTERVAL_PKTS 1000
-#define DEFAULT_MEMPOOL_SIZE (32 * 1024)
-
-#define HTTPD_CFG_FILE "./etc/http/http_decoder.toml"
-#define FILEDSTAT_OUTPUT_FILE "./metrics/http_decoder_fs4.json"
-
-#define HTTP_CTX_NOT_HTTP "__NOT_HTTP_SESS__"
-#define HTTP_CTX_IS_HTTP "__FAKE_HTTP_CTX__"
-
- struct http_decoder_config
- {
- int decompress_switch;
- int stat_interval_pkts; // call fieldstat_incrby every stat_interval_pkts
- int stat_output_interval;
- int proxy_enable;
- size_t result_queue_len; // per session result queue length
- size_t mempool_size; // per session mempool size
- };
-
- /**
- * NOTE: http_message don't have the ownership of data
- */
- struct http_message
- {
- uint8_t flow_type;
- enum http_message_type type;
- size_t queue_index;
- struct http_decoder_result_queue *ref_queue;
- hstring raw_payload; // cause tcp reorder, maybe receive many tcp segments for one packet
- hstring decompress_payload;
- hstring tunnel_payload;
- };
-
- struct http_decoder
- {
- struct http_decoder_half *c2s_half;
- struct http_decoder_half *s2c_half;
- };
-
- enum httpd_topic_index
- {
- HTTPD_TOPIC_TCP_STREAM_INDEX = 0,
- HTTPD_TOPIC_HTTP_MSG_INDEX,
- HTTPD_TOPIC_HTTP_TUNNEL_INDEX,
- HTTPD_TOPIC_INDEX_MAX,
- };
-
- struct http_decoder_exdata
- {
- int sub_topic_id; // tcp_stream
- int pub_topic_id; // http message or http tunnel msg
- struct http_decoder_result_queue *queue;
- struct http_decoder *decoder;
- nmx_pool_t *mempool;
- enum http_tunnel_state tunnel_state;
- int in_tunnel_is_http;
- };
-
- // struct http_decoder_context{
- // int array_size;
- // struct http_decoder_exdata **exdata_array; //raw tcp stream for http msg; http tunnel for inner http transaction.
- // };
-
- struct http_topic_exdata_compose
- {
- enum httpd_topic_index index;
- const char *topic_name;
- on_session_msg_cb_func *on_msg_cb;
- stellar_msg_free_cb_func *msg_free_cb;
- const char *exdata_name;
- stellar_exdata_free *exdata_free_cb;
- int sub_topic_id; // as consumer
- int exdata_id;
- };
-
- struct http_decoder_env
- {
- struct stellar *st;
- int plugin_id;
- struct http_topic_exdata_compose topic_exdata_compose[HTTPD_TOPIC_INDEX_MAX];
- struct http_decoder_config hd_cfg;
- struct http_decoder_stat hd_stat;
- };
-
- struct http_message;
-
- struct http_message *http_message_new(enum http_message_type type, struct http_decoder_result_queue *queue,
- int queue_index, uint8_t flow_type);
- struct http_message *http_body_message_new(enum http_message_type type, struct http_decoder_result_queue *queue,
- int queue_index, uint8_t flow_type, hstring *raw_payload, hstring *decompress_payload);
- int http_topic_exdata_compose_get_index(const struct http_decoder_env *httpd_env, int by_topic_id);
-#ifdef __cplusplus
-}
-#endif
diff --git a/decoders/http/http_decoder_result_queue.c b/decoders/http/http_decoder_result_queue.c
deleted file mode 100644
index 5695138..0000000
--- a/decoders/http/http_decoder_result_queue.c
+++ /dev/null
@@ -1,152 +0,0 @@
-#include <assert.h>
-#include "http_decoder_private.h"
-
-struct http_decoder_result_queue *
-http_decoder_result_queue_new(nmx_pool_t *mempool, size_t queue_size)
-{
- struct http_decoder_result_queue *queue =
- MEMPOOL_CALLOC(mempool, struct http_decoder_result_queue, 1);
- assert(queue);
-
- queue->req_index = 0;
- queue->res_index = 0;
- queue->queue_size = queue_size;
- queue->array = MEMPOOL_CALLOC(mempool, struct http_decoder_result,
- queue->queue_size);
- assert(queue->array);
- return queue;
-}
-
-void http_decoder_result_queue_free(nmx_pool_t *mempool, struct http_decoder_result_queue *queue)
-{
- if (NULL == queue)
- {
- return;
- }
-
- if (queue->array != NULL)
- {
- for (size_t i = 0; i < queue->queue_size; i++)
- {
- if (queue->array[i].req_data != NULL)
- {
- http_decoder_half_data_free(mempool, queue->array[i].req_data);
- queue->array[i].req_data = NULL;
- }
-
- if (queue->array[i].res_data != NULL)
- {
- http_decoder_half_data_free(mempool, queue->array[i].res_data);
- queue->array[i].res_data = NULL;
- }
- }
- MEMPOOL_FREE(mempool, queue->array);
- }
- MEMPOOL_FREE(mempool, queue);
-}
-
-void http_decoder_result_queue_inc_req_index(struct http_decoder_result_queue *queue)
-{
- assert(queue);
- queue->req_index++;
- queue->req_index = queue->req_index % queue->queue_size;
-}
-
-void http_decoder_result_queue_inc_res_index(struct http_decoder_result_queue *queue)
-{
- assert(queue);
- queue->res_index++;
- queue->res_index = queue->res_index % queue->queue_size;
-}
-
-size_t http_decoder_result_queue_req_index(struct http_decoder_result_queue *queue)
-{
- assert(queue);
- return queue->req_index;
-}
-
-size_t http_decoder_result_queue_res_index(struct http_decoder_result_queue *queue)
-{
- assert(queue);
- return queue->res_index;
-}
-
-int http_decoder_result_queue_push_req(struct http_decoder_result_queue *queue,
- struct http_decoder_half_data *req_data)
-{
- if (NULL == queue || NULL == req_data)
- {
- return -1;
- }
- assert(queue->array[queue->req_index].req_data == NULL);
- if (queue->array[queue->req_index].req_data != NULL)
- {
- return -1;
- }
- queue->array[queue->req_index].req_data = req_data;
- return 0;
-}
-
-int http_decoder_result_queue_push_res(struct http_decoder_result_queue *queue,
- struct http_decoder_half_data *res_data)
-{
- if (NULL == queue || NULL == res_data)
- {
- return -1;
- }
- assert(queue->array[queue->res_index].res_data == NULL);
- if (queue->array[queue->res_index].res_data != NULL)
- {
- return -1;
- }
-
- queue->array[queue->res_index].res_data = res_data;
- return 0;
-}
-
-struct http_decoder_half_data *
-http_decoder_result_queue_pop_req(struct http_decoder_result_queue *queue)
-{
- if (NULL == queue)
- {
- return NULL;
- }
- struct http_decoder_half_data *req_data = queue->array[queue->req_index].req_data;
- queue->array[queue->req_index].req_data = NULL;
- return req_data;
-}
-
-struct http_decoder_half_data *
-http_decoder_result_queue_pop_res(struct http_decoder_result_queue *queue)
-{
- if (NULL == queue)
- {
- return NULL;
- }
-
- struct http_decoder_half_data *res_data = queue->array[queue->res_index].res_data;
- queue->array[queue->res_index].res_data = NULL;
- return res_data;
-}
-
-struct http_decoder_half_data *
-http_decoder_result_queue_peek_req(struct http_decoder_result_queue *queue)
-{
- if (NULL == queue)
- {
- return NULL;
- }
- assert(queue->req_index < queue->queue_size);
- return queue->array[queue->req_index].req_data;
-}
-
-struct http_decoder_half_data *
-http_decoder_result_queue_peek_res(struct http_decoder_result_queue *queue)
-{
- if (NULL == queue)
- {
- return NULL;
- }
- assert(queue->res_index < queue->queue_size);
- return queue->array[queue->res_index].res_data;
-} \ No newline at end of file
diff --git a/decoders/http/http_decoder_result_queue.h b/decoders/http/http_decoder_result_queue.h
deleted file mode 100644
index a6ff0ca..0000000
--- a/decoders/http/http_decoder_result_queue.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#include <stddef.h>
-#include "nmx_pool/nmx_palloc.h"
-#include "http_decoder_half.h"
-
-struct http_decoder_result
-{
- struct http_decoder_half_data *req_data;
- struct http_decoder_half_data *res_data;
-};
-
-struct http_decoder_result_queue
-{
- size_t req_index;
- size_t res_index;
- size_t queue_size;
- struct http_decoder_result *array;
-};
-
-struct http_decoder_result_queue *
-http_decoder_result_queue_new(nmx_pool_t *mempool, size_t queue_size);
-
-void http_decoder_result_queue_free(nmx_pool_t *mempool,
- struct http_decoder_result_queue *queue);
-
-void http_decoder_result_queue_inc_req_index(struct http_decoder_result_queue *queue);
-
-void http_decoder_result_queue_inc_res_index(struct http_decoder_result_queue *queue);
-
-size_t http_decoder_result_queue_req_index(struct http_decoder_result_queue *queue);
-
-size_t http_decoder_result_queue_res_index(struct http_decoder_result_queue *queue);
-
-struct http_decoder_half_data *
-http_decoder_result_queue_pop_req(struct http_decoder_result_queue *queue);
-
-struct http_decoder_half_data *
-http_decoder_result_queue_pop_res(struct http_decoder_result_queue *queue);
-
-int http_decoder_result_queue_push_req(struct http_decoder_result_queue *queue,
- struct http_decoder_half_data *req_data);
-
-int http_decoder_result_queue_push_res(struct http_decoder_result_queue *queue,
- struct http_decoder_half_data *res_data);
-
-struct http_decoder_half_data *
-http_decoder_result_queue_peek_req(struct http_decoder_result_queue *queue);
-
-struct http_decoder_half_data *
-http_decoder_result_queue_peek_res(struct http_decoder_result_queue *queue);
diff --git a/decoders/http/http_decoder_stat.c b/decoders/http/http_decoder_stat.c
index dec6c91..a8240c2 100644
--- a/decoders/http/http_decoder_stat.c
+++ b/decoders/http/http_decoder_stat.c
@@ -2,126 +2,104 @@
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
-#include "http_decoder_private.h"
+#include "http_decoder_stat.h"
-static const struct hd_stat_config_tuple g_httpd_stat_tuple[HTTP_STAT_MAX] =
- {
- {HTTP_C2S_BYTES, "http_c2s_bytes"},
- {HTTP_S2C_BYTES, "http_s2c_bytes"},
- {HTTP_C2S_TCP_SEG, "http_c2s_tcp_seg"},
- {HTTP_S2C_TCP_SEG, "http_s2c_tcp_seg"},
- {HTTP_C2S_HEADERS, "http_c2s_headers"},
- {HTTP_S2C_HEADERS, "http_s2c_headers"},
- {HTTP_C2S_ZIP_BYTES, "http_c2s_zip_bytes"},
- {HTTP_S2C_ZIP_BYTES, "http_s2c_zip_bytes"},
- {HTTP_C2S_UNZIP_BYTES, "http_c2s_unzip_bytes"},
- {HTTP_S2C_UNZIP_BYTES, "http_s2c_unzip_bytes"},
- {HTTP_URL_BYTES, "http_url_bytes"},
- {HTTP_SESSION_NEW, "http_session_new"},
- {HTTP_SESSION_FREE, "http_session_free"},
- {HTTP_TRANSACTION_NEW, "http_transaction_new"},
- {HTTP_TRANSACTION_FREE, "http_transaction_free"},
- {HTTP_C2S_ASYMMETRY_SESSION, "http_c2s_asymmetry_sess"},
- {HTTP_S2C_ASYMMETRY_SESSION, "http_s2c_asymmetry_sess"},
- {HTTP_C2S_ASYMMETRY_TRANSACTION, "http_c2s_asymmetry_trans"},
- {HTTP_S2C_ASYMMETRY_TRANSACTION, "http_s2c_asymmetry_trans"},
- {HTTP_STAT_PARSE_ERR, "http_parse_error"},
-};
-
-void http_decoder_stat_free(struct http_decoder_stat *hd_stat)
+#ifdef __cplusplus
+extern "C"
{
- if (hd_stat->timer_pid != 0)
- {
- pthread_cancel(hd_stat->timer_pid);
- }
- if (hd_stat->stats != NULL)
- {
- free(hd_stat->stats);
- }
- if (hd_stat->fse != NULL)
- {
- fieldstat_easy_free(hd_stat->fse);
- }
-}
+#endif
+ static const struct hd_stat_config_tuple g_httpd_stat_tuple[HTTP_STAT_MAX] =
+ {
+ {HTTP_C2S_BYTES, "http_c2s_bytes"},
+ {HTTP_S2C_BYTES, "http_s2c_bytes"},
+ {HTTP_C2S_TCP_SEG, "http_c2s_tcp_seg"},
+ {HTTP_S2C_TCP_SEG, "http_s2c_tcp_seg"},
+ {HTTP_C2S_HEADERS, "http_c2s_headers"},
+ {HTTP_S2C_HEADERS, "http_s2c_headers"},
+ {HTTP_C2S_ZIP_BYTES, "http_c2s_zip_bytes"},
+ {HTTP_S2C_ZIP_BYTES, "http_s2c_zip_bytes"},
+ {HTTP_C2S_UNZIP_BYTES, "http_c2s_unzip_bytes"},
+ {HTTP_S2C_UNZIP_BYTES, "http_s2c_unzip_bytes"},
+ {HTTP_URL_BYTES, "http_url_bytes"},
+ {HTTP_SESSION_NEW, "http_session_new"},
+ {HTTP_SESSION_FREE, "http_session_free"},
+ {HTTP_TRANSACTION_NEW, "http_transaction_new"},
+ {HTTP_TRANSACTION_FREE, "http_transaction_free"},
+ {HTTP_C2S_ASYMMETRY_SESSION, "http_c2s_asymmetry_sess"},
+ {HTTP_S2C_ASYMMETRY_SESSION, "http_s2c_asymmetry_sess"},
+ {HTTP_C2S_ASYMMETRY_TRANSACTION, "http_c2s_asymmetry_trans"},
+ {HTTP_S2C_ASYMMETRY_TRANSACTION, "http_s2c_asymmetry_trans"},
+ {HTTP_STAT_PARSE_ERR, "http_parse_error"},
+ };
-static void *httpd_stat_timer_thread(void *arg)
-{
- pthread_setname_np(pthread_self(), "http_decoder_timer_thread");
- struct http_decoder_stat *hd_stat = (struct http_decoder_stat *)arg;
- struct timespec res;
- while (1)
+ void http_stat_free(struct http_stat *hd_stat)
{
- clock_gettime(CLOCK_MONOTONIC, &res);
- hd_stat->current_time_ms = (res.tv_sec * 1000) + (res.tv_nsec / 1000000);
- usleep(800);
+ if (hd_stat->fs4_ins != NULL)
+ {
+ fieldstat_easy_free(hd_stat->fs4_ins);
+ }
}
- return NULL;
-}
-int http_decoder_stat_init(struct http_decoder_stat *hd_stat, int thread_max, int stat_interval_pkts, int stat_interval_time)
-{
- assert(sizeof(g_httpd_stat_tuple) / sizeof(struct hd_stat_config_tuple) == HTTP_STAT_MAX);
- if (sizeof(g_httpd_stat_tuple) / sizeof(struct hd_stat_config_tuple) != HTTP_STAT_MAX)
- {
- fprintf(stderr, "enum http_decoder_stat_type number not match with g_httpd_stat_tuple!");
- return -1;
- }
- hd_stat->fse = fieldstat_easy_new(thread_max, "http_decoder_statistics", NULL, 0);
- if (NULL == hd_stat->fse)
+ static struct fieldstat_easy *http_get_fs4_ins(struct module_manager *mod_mgr)
{
- fprintf(stderr, "fieldstat_easy_new failed.");
- return -1;
+ // todo: use stellar global fieldstat4 instance
+ struct fieldstat_easy *fs4 = fieldstat_easy_new(module_manager_get_max_thread_num(mod_mgr), "HTTP", NULL, 0);
+ fieldstat_easy_enable_auto_output(fs4, "./log/http.fs4", 1);
+ return fs4;
}
- for (int i = 0; i < HTTP_STAT_MAX; i++)
+ int http_stat_init(struct module_manager *mod_mgr, struct http_stat *hd_stat)
{
- hd_stat->field_stat_id[i] = fieldstat_easy_register_counter(hd_stat->fse, g_httpd_stat_tuple[i].name);
- if (hd_stat->field_stat_id[i] < 0)
+ assert(sizeof(g_httpd_stat_tuple) / sizeof(struct hd_stat_config_tuple) == HTTP_STAT_MAX);
+ if (sizeof(g_httpd_stat_tuple) / sizeof(struct hd_stat_config_tuple) != HTTP_STAT_MAX)
{
- fprintf(stderr, "fieldstat_easy_register_counter %s failed.", g_httpd_stat_tuple[i].name);
- fieldstat_easy_free(hd_stat->fse);
- hd_stat->fse = NULL;
+ fprintf(stderr, "enum http_decoder_stat_type number not match with g_httpd_stat_tuple!");
+ return -1;
+ }
+ hd_stat->fs4_ins = http_get_fs4_ins(mod_mgr);
+ if (NULL == hd_stat->fs4_ins)
+ {
+ fprintf(stderr, "fieldstat_easy_new failed.");
return -1;
}
- }
- int ret = fieldstat_easy_enable_auto_output(hd_stat->fse, FILEDSTAT_OUTPUT_FILE, stat_interval_time);
- if (ret < 0)
- {
- fprintf(stderr, "fieldstat_easy_enable_auto_output failed.");
- fieldstat_easy_free(hd_stat->fse);
- hd_stat->fse = NULL;
- return -1;
+ for (int i = 0; i < HTTP_STAT_MAX; i++)
+ {
+ hd_stat->field_stat_id[i] = fieldstat_easy_register_counter(hd_stat->fs4_ins, g_httpd_stat_tuple[i].name);
+ if (hd_stat->field_stat_id[i] < 0)
+ {
+ fprintf(stderr, "fieldstat_easy_register_counter %s failed.", g_httpd_stat_tuple[i].name);
+ fieldstat_easy_free(hd_stat->fs4_ins);
+ hd_stat->fs4_ins = NULL;
+ return -1;
+ }
+ }
+ return 0;
}
- hd_stat->stats = (struct hd_statistics *)calloc(thread_max, sizeof(struct hd_statistics));
- hd_stat->stat_interval_pkts = stat_interval_pkts;
- hd_stat->stat_interval_time = stat_interval_time;
- pthread_create(&hd_stat->timer_pid, NULL, httpd_stat_timer_thread, hd_stat);
- pthread_detach(hd_stat->timer_pid);
- return 0;
-}
-
-void http_decoder_stat_update(struct http_decoder_stat *hd_stat, int thread_id, enum http_decoder_stat_type type, long long value)
-{
- assert(hd_stat);
- assert(thread_id >= 0);
- assert(type < HTTP_STAT_MAX);
- if (unlikely(hd_stat->stats == NULL))
+ void http_stat_update(struct http_stat *hd_stat, int thread_id, enum http_decoder_stat_type type, long long value)
{
- return;
+ assert(hd_stat);
+ assert(thread_id >= 0);
+ assert(type < HTTP_STAT_MAX);
+ // todo: performance optimization, use batch update
+ fieldstat_easy_counter_incrby(hd_stat->fs4_ins, thread_id, hd_stat->field_stat_id[type], NULL, 0, value);
}
- struct hd_statistics *cur_hds = &hd_stat->stats[thread_id];
-
- cur_hds->counter[type] += value;
- cur_hds->batch[type]++;
-
- if (cur_hds->batch[type] >= hd_stat->stat_interval_pkts || cur_hds->time_ms[type] + 1000 < hd_stat->current_time_ms)
+ void http_stat_update_tcp_seg(struct http_stat *stat, int thread_id, enum flow_type ftype, long long value)
{
- fieldstat_easy_counter_incrby(hd_stat->fse, thread_id, hd_stat->field_stat_id[type], NULL, 0, cur_hds->counter[type]);
- cur_hds->counter[type] = 0;
- cur_hds->batch[type] = 0;
- cur_hds->time_ms[type] = hd_stat->current_time_ms;
+ if (FLOW_TYPE_C2S == ftype)
+ {
+ http_stat_update(stat, thread_id, HTTP_C2S_BYTES, value);
+ http_stat_update(stat, thread_id, HTTP_C2S_TCP_SEG, 1);
+ }
+ else
+ {
+ http_stat_update(stat, thread_id, HTTP_S2C_BYTES, value);
+ http_stat_update(stat, thread_id, HTTP_S2C_TCP_SEG, 1);
+ }
}
-} \ No newline at end of file
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/decoders/http/http_decoder_stat.h b/decoders/http/http_decoder_stat.h
index 339e81d..0f9c1a7 100644
--- a/decoders/http/http_decoder_stat.h
+++ b/decoders/http/http_decoder_stat.h
@@ -1,55 +1,57 @@
#pragma once
#include <fieldstat/fieldstat_easy.h>
-enum http_decoder_stat_type
-{
- HTTP_C2S_BYTES = 0,
- HTTP_S2C_BYTES,
- HTTP_C2S_TCP_SEG,
- HTTP_S2C_TCP_SEG,
- HTTP_C2S_HEADERS,
- HTTP_S2C_HEADERS,
- HTTP_C2S_ZIP_BYTES, // only if Content-Encoding is gzip, deflate, br
- HTTP_S2C_ZIP_BYTES, // only if Content-Encoding is gzip, deflate, br
- HTTP_C2S_UNZIP_BYTES, // only if Content-Encoding is gzip, deflate, br
- HTTP_S2C_UNZIP_BYTES, // only if Content-Encoding is gzip, deflate, br
- HTTP_URL_BYTES,
- HTTP_SESSION_NEW,
- HTTP_SESSION_FREE,
- HTTP_TRANSACTION_NEW,
- HTTP_TRANSACTION_FREE,
- HTTP_C2S_ASYMMETRY_SESSION,
- HTTP_S2C_ASYMMETRY_SESSION,
- HTTP_C2S_ASYMMETRY_TRANSACTION,
- HTTP_S2C_ASYMMETRY_TRANSACTION,
- HTTP_STAT_PARSE_ERR,
- HTTP_STAT_MAX,
-};
+#include "stellar/module.h"
+#include "stellar/session.h"
-struct hd_stat_config_tuple
+#ifdef __cplusplus
+extern "C"
{
- enum http_decoder_stat_type type;
- const char *name;
-};
+#endif
-struct hd_statistics
-{
- long long time_ms[HTTP_STAT_MAX];
- long long counter[HTTP_STAT_MAX];
- int batch[HTTP_STAT_MAX]; // call fieldstat_easy_counter_incrby() per batch
-} __attribute__((aligned(64)));
+ enum http_decoder_stat_type
+ {
+ HTTP_C2S_BYTES = 0,
+ HTTP_S2C_BYTES,
+ HTTP_C2S_TCP_SEG,
+ HTTP_S2C_TCP_SEG,
+ HTTP_C2S_HEADERS,
+ HTTP_S2C_HEADERS,
+ HTTP_C2S_ZIP_BYTES, // only update if Content-Encoding is gzip, deflate, br
+ HTTP_S2C_ZIP_BYTES, // only update if Content-Encoding is gzip, deflate, br
+ HTTP_C2S_UNZIP_BYTES, // only update if Content-Encoding is gzip, deflate, br
+ HTTP_S2C_UNZIP_BYTES, // only update if Content-Encoding is gzip, deflate, br
+ HTTP_URL_BYTES,
+ HTTP_SESSION_NEW,
+ HTTP_SESSION_FREE,
+ HTTP_TRANSACTION_NEW,
+ HTTP_TRANSACTION_FREE,
+ HTTP_C2S_ASYMMETRY_SESSION,
+ HTTP_S2C_ASYMMETRY_SESSION,
+ HTTP_C2S_ASYMMETRY_TRANSACTION,
+ HTTP_S2C_ASYMMETRY_TRANSACTION,
+ HTTP_STAT_PARSE_ERR,
+ HTTP_STAT_MAX,
+ };
-struct http_decoder_stat
-{
- pthread_t timer_pid;
- long long current_time_ms;
- struct fieldstat_easy *fse;
- int stat_interval_pkts; // call fieldstat_incrby every stat_interval_pkts
- int stat_interval_time; // second
- int field_stat_id[HTTP_STAT_MAX];
- struct hd_statistics *stats; // size is thread number
-};
+ struct hd_stat_config_tuple
+ {
+ enum http_decoder_stat_type type;
+ const char *name;
+ };
+
+ struct http_stat
+ {
+ struct fieldstat_easy *fs4_ins;
+ int stat_interval_time; // second
+ int field_stat_id[HTTP_STAT_MAX];
+ };
+
+ int http_stat_init(struct module_manager *mod_mgr, struct http_stat *hd_stat);
+ void http_stat_free(struct http_stat *hd_stat);
+ void http_stat_update(struct http_stat *hd_stat, int thread_id, enum http_decoder_stat_type type, long long value);
+ void http_stat_update_tcp_seg(struct http_stat *stat, int thread_id, enum flow_type ftype, long long value);
-int http_decoder_stat_init(struct http_decoder_stat *hd_stat, int thread_max, int stat_interval_pkts, int stat_interval_time);
-void http_decoder_stat_free(struct http_decoder_stat *hd_stat);
-void http_decoder_stat_update(struct http_decoder_stat *hd_stat, int thread_id, enum http_decoder_stat_type type, long long value);
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/decoders/http/http_decoder_string.c b/decoders/http/http_decoder_string.c
deleted file mode 100644
index 6fd5b04..0000000
--- a/decoders/http/http_decoder_string.c
+++ /dev/null
@@ -1,289 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "http_decoder_private.h"
-
-static const char *string_state_to_desc(enum string_state state)
-{
- switch (state)
- {
- case STRING_STATE_INIT:
- return "init";
- break;
- case STRING_STATE_REFER:
- return "refer";
- break;
- case STRING_STATE_CACHE:
- return "cache";
- break;
- case STRING_STATE_COMMIT:
- return "commit";
- break;
- default:
- return "unknown";
- break;
- }
-}
-
-void http_decoder_string_refer(struct http_decoder_string *rstr, const char *at, size_t length)
-{
- if (NULL == rstr)
- {
- return;
- }
-
- switch (rstr->state)
- {
- case STRING_STATE_INIT:
- case STRING_STATE_CACHE:
- rstr->refer.iov_base = (char *)at;
- rstr->refer.iov_len = length;
- break;
- default:
- abort();
- break;
- }
-
- rstr->state = STRING_STATE_REFER;
-}
-
-static void string_refer2cache(struct http_decoder_string *rstr)
-{
- if (0 == rstr->refer.iov_len)
- {
- return;
- }
- if (rstr->cache.iov_len >= rstr->max_cache_size)
- {
- return;
- }
-
- size_t length = rstr->cache.iov_len + rstr->refer.iov_len;
- if (length > rstr->max_cache_size)
- {
- length = rstr->max_cache_size;
- }
-
- if (NULL == rstr->cache.iov_base)
- {
- rstr->cache.iov_base = CALLOC(char, length + 1);
- memcpy(rstr->cache.iov_base, rstr->refer.iov_base, length);
- }
- else
- {
- rstr->cache.iov_base = REALLOC(char, rstr->cache.iov_base, length + 1);
- memcpy((char *)rstr->cache.iov_base + rstr->cache.iov_len, rstr->refer.iov_base,
- (length - rstr->cache.iov_len));
- }
-
- rstr->cache.iov_len = length;
- rstr->refer.iov_base = NULL;
- rstr->refer.iov_len = 0;
-}
-
-static void string_commit2cache(struct http_decoder_string *rstr)
-{
- if (rstr->cache.iov_len == rstr->commit.iov_len &&
- rstr->cache.iov_base == rstr->commit.iov_base)
- {
- rstr->commit.iov_base = NULL;
- rstr->commit.iov_len = 0;
- return;
- }
-
- // Only http header key need to backward to cache
- size_t length = 0;
- if (rstr->commit.iov_len > rstr->max_cache_size)
- {
- length = rstr->max_cache_size;
- }
- else
- {
- length = rstr->commit.iov_len;
- }
-
- if (length > 0)
- {
- if (NULL == rstr->cache.iov_base)
- {
- rstr->cache.iov_base = CALLOC(char, length + 1);
- }
- else
- {
- abort();
- }
- memcpy(rstr->cache.iov_base, rstr->commit.iov_base, length);
- rstr->cache.iov_len = length;
-
- rstr->commit.iov_base = NULL;
- rstr->commit.iov_len = 0;
- }
-}
-
-void http_decoder_string_cache(struct http_decoder_string *rstr)
-{
- if (NULL == rstr)
- {
- return;
- }
-
- switch (rstr->state)
- {
- case STRING_STATE_REFER:
- string_refer2cache(rstr);
- break;
- case STRING_STATE_CACHE:
- break;
- case STRING_STATE_COMMIT:
- // commit backward to cache
- string_commit2cache(rstr);
- break;
- default:
- abort();
- break;
- }
- rstr->state = STRING_STATE_CACHE;
-}
-
-void http_decoder_string_commit(struct http_decoder_string *rstr)
-{
- if (NULL == rstr)
- {
- return;
- }
-
- switch (rstr->state)
- {
- case STRING_STATE_REFER:
- if (rstr->cache.iov_len)
- {
- http_decoder_string_cache(rstr);
-
- rstr->commit.iov_base = rstr->cache.iov_base;
- rstr->commit.iov_len = rstr->cache.iov_len;
- // not overwrite rstr->cache.iov_base
- }
- else
- {
- rstr->commit.iov_base = rstr->refer.iov_base;
- rstr->commit.iov_len = rstr->refer.iov_len;
-
- rstr->refer.iov_base = NULL;
- rstr->refer.iov_len = 0;
- }
- break;
- case STRING_STATE_CACHE:
- rstr->commit.iov_base = rstr->cache.iov_base;
- rstr->commit.iov_len = rstr->cache.iov_len;
- // not overwrite rstr->cache.iov_base
- break;
- default:
- // abort();
- break;
- }
-
- rstr->state = STRING_STATE_COMMIT;
-}
-
-void http_decoder_string_reset(struct http_decoder_string *rstr)
-{
- assert(rstr);
-
- switch (rstr->state)
- {
- case STRING_STATE_INIT:
- case STRING_STATE_REFER:
- case STRING_STATE_CACHE:
- case STRING_STATE_COMMIT:
- FREE(rstr->cache.iov_base);
- memset(rstr, 0, sizeof(struct http_decoder_string));
- break;
- default:
- abort();
- break;
- }
-
- rstr->state = STRING_STATE_INIT;
-}
-
-void http_decoder_string_init(struct http_decoder_string *rstr, size_t max_cache_size)
-{
- rstr->max_cache_size = max_cache_size;
-}
-
-void http_decoder_string_reinit(struct http_decoder_string *rstr)
-{
- if (rstr->state == STRING_STATE_CACHE)
- {
- return;
- }
-
- if (rstr->state == STRING_STATE_COMMIT &&
- rstr->cache.iov_base == rstr->commit.iov_base &&
- rstr->cache.iov_len == rstr->commit.iov_len)
- {
- return;
- }
-
- if (rstr->cache.iov_base != NULL)
- {
- FREE(rstr->cache.iov_base);
- rstr->cache.iov_len = 0;
- }
-
-#if 0
- rstr->refer.iov_base = NULL;
- rstr->refer.iov_len = 0;
- rstr->commit.iov_base = NULL;
- rstr->commit.iov_len = 0;
- rstr->state = STRING_STATE_INIT;
-#endif
-}
-
-enum string_state http_decoder_string_state(const struct http_decoder_string *rstr)
-{
- return rstr->state;
-}
-
-int http_decoder_string_get(const struct http_decoder_string *rstr, char **name, size_t *name_len)
-{
- if (NULL == rstr || NULL == name || 0 == name_len)
- {
- return -1;
- }
-
- if (http_decoder_string_state(rstr) == STRING_STATE_COMMIT)
- {
- *name = rstr->commit.iov_base;
- *name_len = rstr->commit.iov_len;
- }
- else
- {
- *name = NULL;
- *name_len = 0;
- }
- return 0;
-}
-
-void http_decoder_string_dump(struct http_decoder_string *rstr, const char *desc)
-{
- if (NULL == rstr)
- {
- return;
- }
-
- char *refer_str = http_safe_dup((char *)rstr->refer.iov_base, rstr->refer.iov_len);
- char *cache_str = http_safe_dup((char *)rstr->cache.iov_base, rstr->cache.iov_len);
- char *commit_str = http_safe_dup((char *)rstr->commit.iov_base, rstr->commit.iov_len);
-
- printf("%s: state: %s, refer: {len: %02zu, iov_base: %s}, cache: {len: %02zu, iov_base: %s}, commit: {len: %02zu, iov_base: %s}\n",
- desc, string_state_to_desc(rstr->state),
- rstr->refer.iov_len, refer_str,
- rstr->cache.iov_len, cache_str,
- rstr->commit.iov_len, commit_str);
-
- FREE(refer_str);
- FREE(cache_str);
- FREE(commit_str);
-} \ No newline at end of file
diff --git a/decoders/http/http_decoder_string.h b/decoders/http/http_decoder_string.h
deleted file mode 100644
index 83721e9..0000000
--- a/decoders/http/http_decoder_string.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#pragma once
-
-#include "stellar/http.h"
-
-enum string_state {
- STRING_STATE_INIT,
- STRING_STATE_REFER,
- STRING_STATE_CACHE,
- STRING_STATE_COMMIT,
-};
-
-/* state transition diagram
- * +----------+
- * | |
- * \|/ |
- * +------+ |
- * | init | |
- * +------+ |
- * | |
- * +---->| |
- * | \|/ |
- * | +-------+ |
- * | | refer |--+ |
- * | +-------+ | |
- * | | | |
- * | \|/ | |
- * | +-------+ | |
- * +--| cache | | |
- * +-------+ | |
- * | | |
- * |<------+ |
- * \|/ |
- * +--------+ |
- * | commit | |
- * +--------+ |
- * | |
- * \|/ |
- * +--------+ |
- * | reset |----+
- * +--------+
- */
-
-
-//http decoder string
-struct http_decoder_string {
- hstring refer; // shallow copy
- hstring cache; // deep copy
- hstring commit;
-
- enum string_state state;
- size_t max_cache_size;
-};
-
-void http_decoder_string_refer(struct http_decoder_string *rstr,
- const char *at, size_t length);
-
-void http_decoder_string_cache(struct http_decoder_string *rstr);
-
-void http_decoder_string_commit(struct http_decoder_string *rstr);
-
-void http_decoder_string_reset(struct http_decoder_string *rstr);
-
-void http_decoder_string_init(struct http_decoder_string *rstr,
- size_t max_cache_size);
-
-void http_decoder_string_reinit(struct http_decoder_string *rstr);
-
-enum string_state http_decoder_string_state(const struct http_decoder_string *rstr);
-
-int http_decoder_string_get(const struct http_decoder_string *rstr, char **name, size_t *name_len);
-
-void http_decoder_string_dump(struct http_decoder_string *rstr, const char *desc);
- \ No newline at end of file
diff --git a/decoders/http/http_decoder_table.c b/decoders/http/http_decoder_table.c
deleted file mode 100644
index c85b876..0000000
--- a/decoders/http/http_decoder_table.c
+++ /dev/null
@@ -1,579 +0,0 @@
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "http_decoder_private.h"
-
-#define INIT_HEADER_CNT 16
-#define MAX_URI_CACHE_SIZE 2048
-#define MAX_STATUS_CACHE_SIZE 32
-#define MAX_METHOD_CACHE_SIZE 8
-#define MAX_VERSION_CACHE_SIZE 4
-#define MAX_HEADER_KEY_CACHE_SIZE 4096
-#define MAX_HEADER_VALUE_CACHE_SIZE 4096
-
-struct http_decoder_header
-{
- struct http_decoder_string key;
- struct http_decoder_string val;
-};
-
-struct http_decoder_table
-{
- struct http_decoder_string uri;
- struct http_decoder_string status;
- struct http_decoder_string method;
- struct http_decoder_string version;
- struct http_decoder_string body;
-
- nmx_pool_t *ref_mempool;
- int header_complete; // flag for all headers parsed completely
- size_t header_cnt;
- size_t header_index; // current parsing header
- size_t header_iter; // plugins iterate cursor
- size_t commit_header_index; // pushed to plugins, whether has called http_message_get0_next_header()
- struct http_decoder_header *headers;
-};
-
-static void http_decoder_table_init(struct http_decoder_table *table)
-{
- if (NULL == table)
- {
- return;
- }
-
- struct http_decoder_header *header = NULL;
- assert(table);
-
- http_decoder_string_init(&table->uri, MAX_URI_CACHE_SIZE);
- http_decoder_string_init(&table->status, MAX_STATUS_CACHE_SIZE);
- http_decoder_string_init(&table->method, MAX_METHOD_CACHE_SIZE);
- http_decoder_string_init(&table->version, MAX_METHOD_CACHE_SIZE);
-
- for (size_t i = 0; i < table->header_cnt; i++)
- {
- header = &table->headers[i];
- http_decoder_string_init(&header->key, MAX_HEADER_KEY_CACHE_SIZE);
- http_decoder_string_init(&header->val, MAX_HEADER_VALUE_CACHE_SIZE);
- }
-
- http_decoder_string_init(&table->body, 0);
-}
-
-struct http_decoder_table *http_decoder_table_new(nmx_pool_t *mempool)
-{
- struct http_decoder_table *table =
- MEMPOOL_CALLOC(mempool, struct http_decoder_table, 1);
- assert(table);
-
- table->ref_mempool = mempool;
- table->header_cnt = INIT_HEADER_CNT;
- table->headers = MEMPOOL_CALLOC(mempool, struct http_decoder_header,
- table->header_cnt);
- table->commit_header_index = 0;
- http_decoder_table_init(table);
-
- return table;
-}
-
-void http_decoder_table_free(struct http_decoder_table *table)
-{
- if (NULL == table)
- {
- return;
- }
- if (table->uri.cache.iov_base != NULL)
- {
- FREE(table->uri.cache.iov_base);
- }
- if (table->status.cache.iov_base != NULL)
- {
- FREE(table->status.cache.iov_base);
- }
- if (table->method.cache.iov_base != NULL)
- {
- FREE(table->method.cache.iov_base);
- }
- if (table->version.cache.iov_base != NULL)
- {
- FREE(table->version.cache.iov_base);
- }
- if (table->body.cache.iov_base != NULL)
- {
- FREE(table->body.cache.iov_base);
- }
-
- if (table->headers != NULL)
- {
- for (size_t i = 0; i < table->header_cnt; i++)
- {
- if (table->headers[i].key.cache.iov_base != NULL)
- {
- FREE(table->headers[i].key.cache.iov_base);
- }
-
- if (table->headers[i].val.cache.iov_base != NULL)
- {
- FREE(table->headers[i].val.cache.iov_base);
- }
- }
-
- MEMPOOL_FREE(table->ref_mempool, table->headers);
- table->headers = NULL;
- }
- MEMPOOL_FREE(table->ref_mempool, table);
-}
-
-enum string_state http_decoder_table_state(struct http_decoder_table *table, enum http_item type)
-{
- if (NULL == table)
- {
- return STRING_STATE_INIT;
- }
- struct http_decoder_header *header = NULL;
- enum string_state state = STRING_STATE_INIT;
- assert(table);
-
- switch (type)
- {
- case HTTP_ITEM_URI:
- state = http_decoder_string_state(&table->uri);
- break;
- case HTTP_ITEM_STATUS:
- state = http_decoder_string_state(&table->status);
- break;
- case HTTP_ITEM_METHOD:
- state = http_decoder_string_state(&table->method);
- break;
- case HTTP_ITEM_VERSION:
- state = http_decoder_string_state(&table->version);
- break;
- case HTTP_ITEM_HDRKEY:
- assert(table->header_index < table->header_cnt);
- header = &table->headers[table->header_index];
- state = http_decoder_string_state(&header->key);
- break;
- case HTTP_ITEM_HDRVAL:
- assert(table->header_index < table->header_cnt);
- header = &table->headers[table->header_index];
- state = http_decoder_string_state(&header->val);
- break;
- case HTTP_ITEM_BODY:
- state = http_decoder_string_state(&table->body);
- break;
- default:
- abort();
- break;
- }
-
- return state;
-}
-
-void http_decoder_table_refer(struct http_decoder_table *table, enum http_item type, const char *at, size_t len)
-{
- if (NULL == table)
- {
- return;
- }
-
- struct http_decoder_header *header = NULL;
- assert(table);
-
- switch (type)
- {
- case HTTP_ITEM_URI:
- http_decoder_string_refer(&table->uri, at, len);
- break;
- case HTTP_ITEM_STATUS:
- http_decoder_string_refer(&table->status, at, len);
- break;
- case HTTP_ITEM_METHOD:
- http_decoder_string_refer(&table->method, at, len);
- break;
- case HTTP_ITEM_VERSION:
- http_decoder_string_refer(&table->version, at, len);
- break;
- case HTTP_ITEM_HDRKEY:
- assert(table->header_index < table->header_cnt);
- header = &table->headers[table->header_index];
- http_decoder_string_refer(&header->key, at, len);
- break;
- case HTTP_ITEM_HDRVAL:
- assert(table->header_index < table->header_cnt);
- header = &table->headers[table->header_index];
- http_decoder_string_refer(&header->val, at, len);
- break;
- case HTTP_ITEM_BODY:
- http_decoder_string_refer(&table->body, at, len);
- break;
- default:
- abort();
- break;
- }
-}
-
-void http_decoder_table_cache(struct http_decoder_table *table, enum http_item type)
-{
- if (NULL == table)
- {
- return;
- }
-
- struct http_decoder_header *header = NULL;
- assert(table);
-
- switch (type)
- {
- case HTTP_ITEM_URI:
- http_decoder_string_cache(&table->uri);
- break;
- case HTTP_ITEM_STATUS:
- http_decoder_string_cache(&table->status);
- break;
- case HTTP_ITEM_METHOD:
- http_decoder_string_cache(&table->method);
- break;
- case HTTP_ITEM_VERSION:
- http_decoder_string_cache(&table->version);
- break;
- case HTTP_ITEM_HDRKEY:
- assert(table->header_index < table->header_cnt);
- header = &table->headers[table->header_index];
- http_decoder_string_cache(&header->key);
- break;
- case HTTP_ITEM_HDRVAL:
- assert(table->header_index < table->header_cnt);
- header = &table->headers[table->header_index];
- http_decoder_string_cache(&header->val);
- break;
- case HTTP_ITEM_BODY:
- http_decoder_string_cache(&table->body);
- break;
- default:
- abort();
- break;
- }
-}
-
-void http_decoder_table_commit(struct http_decoder_table *table, enum http_item type)
-{
- if (NULL == table)
- {
- return;
- }
-
- size_t i = 0;
- struct http_decoder_header *header = NULL;
- assert(table);
-
- switch (type)
- {
- case HTTP_ITEM_URI:
- http_decoder_string_commit(&table->uri);
- break;
- case HTTP_ITEM_STATUS:
- http_decoder_string_commit(&table->status);
- break;
- case HTTP_ITEM_METHOD:
- http_decoder_string_commit(&table->method);
- break;
- case HTTP_ITEM_VERSION:
- http_decoder_string_commit(&table->version);
- break;
- case HTTP_ITEM_HDRKEY:
- assert(table->header_index < table->header_cnt);
- header = &table->headers[table->header_index];
- http_decoder_string_commit(&header->key);
- break;
- case HTTP_ITEM_HDRVAL:
- header = &table->headers[table->header_index];
- http_decoder_string_commit(&header->val);
- // inc index
- if ((table->header_index + 1) >= table->header_cnt)
- {
- struct http_decoder_header *old_headers = table->headers;
- table->headers =
- MEMPOOL_CALLOC(table->ref_mempool, struct http_decoder_header,
- table->header_cnt * 2);
- table->header_cnt *= 2;
-
- for (i = 0; i <= table->header_index; i++)
- {
- table->headers[i] = old_headers[i];
- }
-
- MEMPOOL_FREE(table->ref_mempool, old_headers);
-
- for (i = table->header_index + 1; i < table->header_cnt; i++)
- {
- header = &table->headers[i];
- memset(header, 0, sizeof(struct http_decoder_header));
- http_decoder_string_init(&header->key, MAX_HEADER_KEY_CACHE_SIZE);
- http_decoder_string_init(&header->val, MAX_HEADER_VALUE_CACHE_SIZE);
- }
- }
- table->header_index++;
- break;
- case HTTP_ITEM_BODY:
- http_decoder_string_commit(&table->body);
- break;
- default:
- abort();
- break;
- }
-}
-
-void http_decoder_table_reset(struct http_decoder_table *table, enum http_item type)
-{
- if (NULL == table)
- {
- return;
- }
-
- struct http_decoder_header *header = NULL;
- assert(table);
-
- switch (type)
- {
- case HTTP_ITEM_URI:
- http_decoder_string_reset(&table->uri);
- break;
- case HTTP_ITEM_STATUS:
- http_decoder_string_reset(&table->status);
- break;
- case HTTP_ITEM_METHOD:
- http_decoder_string_reset(&table->method);
- break;
- case HTTP_ITEM_VERSION:
- http_decoder_string_reset(&table->version);
- break;
- case HTTP_ITEM_HDRKEY:
- header = &table->headers[table->header_index];
- http_decoder_string_reset(&header->key);
- break;
- case HTTP_ITEM_HDRVAL:
- header = &table->headers[table->header_index];
- http_decoder_string_reset(&header->val);
- break;
- case HTTP_ITEM_BODY:
- http_decoder_string_reset(&table->body);
- break;
- default:
- abort();
- break;
- }
-}
-
-void http_decoder_table_reinit(struct http_decoder_table *table)
-{
- assert(table);
- struct http_decoder_header *header = NULL;
-
- http_decoder_string_reinit(&table->uri);
- http_decoder_string_reinit(&table->status);
- http_decoder_string_reinit(&table->method);
- http_decoder_string_reinit(&table->version);
- // for (size_t i = 0; i < table->header_iter; i++) {
- for (size_t i = 0; i < table->commit_header_index; i++)
- {
- // todo, reset header_index, avoid realloc headers as much as possible
- header = &table->headers[i];
- http_decoder_string_reinit(&header->key);
- http_decoder_string_reinit(&header->val);
- }
-
- http_decoder_string_reinit(&table->body);
-}
-
-void http_decoder_table_dump(struct http_decoder_table *table)
-{
- if (NULL == table)
- {
- return;
- }
-
- http_decoder_string_dump(&table->uri, "uri");
- http_decoder_string_dump(&table->status, "status");
- http_decoder_string_dump(&table->method, "method");
- http_decoder_string_dump(&table->version, "version");
- http_decoder_string_dump(&table->body, "body");
-
- for (size_t i = 0; i < table->header_cnt; i++)
- {
- struct http_decoder_header *header = &table->headers[i];
- if (NULL == header)
- {
- continue;
- }
-
- http_decoder_string_dump(&header->key, "key");
- http_decoder_string_dump(&header->val, "val");
- }
-}
-
-int http_decoder_table_get_uri(const struct http_decoder_table *table, char **out, size_t *out_len)
-{
- if (NULL == table || NULL == out)
- {
- return -1;
- }
- return http_decoder_string_get(&table->uri, out, out_len);
-}
-
-int http_decoder_table_get_method(const struct http_decoder_table *table, char **out, size_t *out_len)
-{
- if (NULL == table || NULL == out)
- {
- return -1;
- }
- return http_decoder_string_get(&table->method, out, out_len);
-}
-
-int http_decoder_table_get_status(const struct http_decoder_table *table, char **out, size_t *out_len)
-{
- if (NULL == table || NULL == out)
- {
- return -1;
- }
- return http_decoder_string_get(&table->status, out, out_len);
-}
-
-int http_decoder_table_get_version(const struct http_decoder_table *table, char **out, size_t *out_len)
-{
- if (NULL == table || NULL == out)
- {
- return -1;
- }
- return http_decoder_string_get(&table->version, out, out_len);
-}
-
-int http_decoder_table_get_body(const struct http_decoder_table *table, char **out, size_t *out_len)
-{
- if (NULL == table || NULL == out)
- {
- return -1;
- }
- return http_decoder_string_get(&table->body, (char **)out, out_len);
-}
-
-int http_decoder_table_get_header(const struct http_decoder_table *table, const char *name, size_t name_len,
- struct http_header_field *hdr_result)
-{
- for (size_t i = 0; i < table->header_cnt; i++)
- {
- const struct http_decoder_header *tmp_header = &table->headers[i];
- if (tmp_header->key.commit.iov_len != name_len)
- {
- continue;
- }
-
- if (http_decoder_string_state(&tmp_header->key) == STRING_STATE_COMMIT &&
- http_decoder_string_state(&tmp_header->val) == STRING_STATE_COMMIT)
- {
- hstring tmp_key;
- http_decoder_string_get(&tmp_header->key, (char **)&tmp_key.iov_base, &tmp_key.iov_len);
-
- if (tmp_key.iov_len == name_len &&
- (0 == strncasecmp((char *)tmp_key.iov_base, name, name_len)))
- {
- http_decoder_string_get(&tmp_header->key, &hdr_result->name, &hdr_result->name_len);
- http_decoder_string_get(&tmp_header->val, &hdr_result->value, &hdr_result->value_len);
- return 0;
- }
- }
- }
- return -1;
-}
-
-int http_decoder_table_iter_header(struct http_decoder_table *table, struct http_header_field *hdr)
-{
- if (NULL == table || NULL == hdr)
- {
- return -1;
- }
- if (table->header_iter >= table->header_cnt)
- {
- return -1;
- }
-
- struct http_decoder_header *tmp_header = &table->headers[table->header_iter];
- if (tmp_header != NULL)
- {
- if (http_decoder_string_state(&tmp_header->key) == STRING_STATE_COMMIT &&
- http_decoder_string_state(&tmp_header->val) == STRING_STATE_COMMIT)
- {
-
- http_decoder_string_get(&tmp_header->key, &hdr->name, &hdr->name_len);
- http_decoder_string_get(&tmp_header->val, &hdr->value, &hdr->value_len);
- table->header_iter++;
- return 1;
- }
- }
-
- hdr->name = NULL;
- hdr->name_len = 0;
- hdr->value = NULL;
- hdr->value_len = 0;
-
- return -1;
-}
-
-int http_decoder_table_reset_header_iter(struct http_decoder_table *table)
-{
- table->header_iter = 0;
- return 0;
-}
-
-int http_decoder_table_has_parsed_header(struct http_decoder_table *table)
-{
- // if (NULL == table || (table->header_iter == table->header_index)) {
- if (NULL == table || (table->commit_header_index == table->header_index))
- {
- return 0;
- }
-
- const struct http_decoder_header *tmp_header = &table->headers[table->header_iter];
-
- if (http_decoder_string_state(&tmp_header->key) == STRING_STATE_COMMIT && http_decoder_string_state(&tmp_header->val) == STRING_STATE_COMMIT)
- {
- return 1;
- }
-
- return 0;
-}
-
-int http_decoder_table_header_complete(struct http_decoder_table *table)
-{
- if (NULL == table)
- {
- return -1;
- }
- return table->header_complete;
-}
-
-void http_decoder_table_set_header_complete(struct http_decoder_table *table)
-{
- if (NULL == table)
- {
- return;
- }
- table->header_complete = 1;
-}
-
-void http_decoder_table_reset_header_complete(struct http_decoder_table *table)
-{
- if (NULL == table)
- {
- return;
- }
- table->header_complete = 0;
-}
-
-void http_decoder_table_update_commit_index(struct http_decoder_table *table)
-{
- table->commit_header_index = table->header_index;
-}
-
-int http_decoder_table_get_total_parsed_header(struct http_decoder_table *table)
-{
- return table->header_index;
-} \ No newline at end of file
diff --git a/decoders/http/http_decoder_table.h b/decoders/http/http_decoder_table.h
deleted file mode 100644
index 9a8d948..0000000
--- a/decoders/http/http_decoder_table.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#pragma once
-#include <stddef.h>
-#include "stellar/http.h"
-#include "http_decoder_private.h"
-#include "http_decoder_string.h"
-
-enum http_item
-{
- HTTP_ITEM_URI = 0x01,
- HTTP_ITEM_STATUS = 0x02,
- HTTP_ITEM_METHOD = 0x03,
- HTTP_ITEM_VERSION = 0x04,
- HTTP_ITEM_HDRKEY = 0x05,
- HTTP_ITEM_HDRVAL = 0x06,
- HTTP_ITEM_BODY = 0x07,
-};
-
-struct http_decoder_table;
-struct http_decoder_table *http_decoder_table_new(nmx_pool_t *mempool);
-
-void http_decoder_table_free(struct http_decoder_table *table);
-
-enum string_state
-http_decoder_table_state(struct http_decoder_table *table, enum http_item type);
-
-void http_decoder_table_refer(struct http_decoder_table *table, enum http_item type,
- const char *at, size_t len);
-
-void http_decoder_table_cache(struct http_decoder_table *table, enum http_item type);
-
-void http_decoder_table_commit(struct http_decoder_table *table, enum http_item type);
-
-void http_decoder_table_reset(struct http_decoder_table *table, enum http_item type);
-
-void http_decoder_table_reinit(struct http_decoder_table *table);
-
-void http_decoder_table_dump(struct http_decoder_table *table);
-
-int http_decoder_table_get_uri(const struct http_decoder_table *table, char **out, size_t *out_len);
-
-int http_decoder_table_get_method(const struct http_decoder_table *table, char **out, size_t *out_len);
-
-int http_decoder_table_get_status(const struct http_decoder_table *table, char **out, size_t *out_len);
-
-int http_decoder_table_get_version(const struct http_decoder_table *table, char **out, size_t *out_len);
-
-int http_decoder_table_get_body(const struct http_decoder_table *table, char **out, size_t *out_len);
-
-int http_decoder_table_get_header(const struct http_decoder_table *table,
- const char *name, size_t name_len,
- struct http_header_field *hdr_res);
-
-int http_decoder_table_iter_header(struct http_decoder_table *table,
- struct http_header_field *hdr);
-int http_decoder_table_reset_header_iter(struct http_decoder_table *table);
-/**
- * @brief Is there a parsed header
- *
- * @retval yes(1) no(0)
- */
-int http_decoder_table_has_parsed_header(struct http_decoder_table *table);
-
-/**
- * @brief If headers have been parsed completely
- *
- * @retval yes(1) no(0)
- */
-int http_decoder_table_header_complete(struct http_decoder_table *table);
-
-/**
- * @brief set flag for headers parsed completely
- */
-void http_decoder_table_set_header_complete(struct http_decoder_table *table);
-
-void http_decoder_table_reset_header_complete(struct http_decoder_table *table);
-
-void http_decoder_table_update_commit_index(struct http_decoder_table *table);
-
-int http_decoder_table_get_total_parsed_header(struct http_decoder_table *table);
diff --git a/decoders/http/http_decoder_tunnel.c b/decoders/http/http_decoder_tunnel.c
deleted file mode 100644
index a6abda8..0000000
--- a/decoders/http/http_decoder_tunnel.c
+++ /dev/null
@@ -1,116 +0,0 @@
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-#include "http_decoder_private.h"
-#include "llhttp.h"
-
-struct http_tunnel_message
-{
- enum http_tunnel_message_type type;
- hstring tunnel_payload;
-};
-
-int httpd_tunnel_identify(struct http_decoder_env *httpd_env, int curdir, struct http_decoder_half_data *hfdata)
-{
- if (0 == httpd_env->hd_cfg.proxy_enable)
- {
- return 0;
- }
-
- if (FLOW_TYPE_C2S == curdir)
- {
- struct http_request_line reqline = {};
- http_decoder_half_data_get_request_line(hfdata, &reqline);
- if (0 == http_strncasecmp_safe("CONNECT", (char *)reqline.method,
- 7, reqline.method_len))
- {
- return 1;
- }
- }
- else
- {
- struct http_response_line resline = {};
- http_decoder_half_data_get_response_line(hfdata, &resline);
- if (resline.status_code == HTTP_STATUS_OK && 0 == http_strncasecmp_safe("Connection established", (char *)resline.status,
- strlen("Connection established"), resline.status_len))
- {
- return 1;
- }
- }
-
- return 0;
-}
-
-int httpd_is_tunnel_session(const struct http_decoder_env *httpd_env, const struct http_decoder_exdata *ex_data)
-{
- if (0 == httpd_env->hd_cfg.proxy_enable)
- {
- return 0;
- }
- return (ex_data && ex_data->tunnel_state != HTTP_TUN_NON);
-}
-
-int httpd_in_tunnel_transmitting(const struct http_decoder_env *httpd_env, struct http_decoder_exdata *ex_data)
-{
- if (0 == httpd_env->hd_cfg.proxy_enable)
- {
- return 0;
- }
- return (ex_data && ex_data->tunnel_state >= HTTP_TUN_INNER_STARTING);
-}
-
-enum http_tunnel_message_type httpd_tunnel_state_to_msg(const struct http_decoder_exdata *ex_data)
-{
- if (ex_data->tunnel_state == HTTP_TUN_INNER_STARTING)
- {
- return HTTP_TUNNEL_OPENING;
- }
- if (ex_data->tunnel_state == HTTP_TUN_INNER_TRANS)
- {
- return HTTP_TUNNEL_ACTIVE;
- }
- return HTTP_TUNNEL_MSG_MAX;
-}
-
-void httpd_tunnel_state_update(struct http_decoder_exdata *ex_data)
-{
- if (ex_data->tunnel_state == HTTP_TUN_INNER_STARTING)
- {
- ex_data->tunnel_state = HTTP_TUN_INNER_TRANS;
- }
-}
-
-void http_decoder_push_tunnel_data(struct session *sess, const struct http_decoder_exdata *exdata, enum http_tunnel_message_type type, const char *payload, uint16_t payload_len)
-{
- struct http_tunnel_message *tmsg = (struct http_tunnel_message *)CALLOC(struct http_tunnel_message, 1);
- tmsg->type = type;
- tmsg->tunnel_payload.iov_base = (char *)payload;
- tmsg->tunnel_payload.iov_len = payload_len;
- session_mq_publish_message(sess, exdata->pub_topic_id, tmsg);
-}
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
- void http_tunnel_message_get_payload(const struct http_tunnel_message *tmsg,
- hstring *tunnel_payload)
- {
- if (unlikely(NULL == tmsg || tunnel_payload == NULL))
- {
- return;
- }
- tunnel_payload->iov_base = tmsg->tunnel_payload.iov_base;
- tunnel_payload->iov_len = tmsg->tunnel_payload.iov_len;
- }
-
- enum http_tunnel_message_type http_tunnel_message_type_get(const struct http_tunnel_message *tmsg)
- {
- return tmsg->type;
- }
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/decoders/http/http_decoder_tunnel.h b/decoders/http/http_decoder_tunnel.h
deleted file mode 100644
index 52882e5..0000000
--- a/decoders/http/http_decoder_tunnel.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-#include "http_decoder_private.h"
-#include "http_decoder_half.h"
-
-enum http_tunnel_state
-{
- HTTP_TUN_NON = 0, // init, or not tunnel session
- HTTP_TUN_C2S_HDR_START, // CONNECT ...
- HTTP_TUN_C2S_END, // CONNECT request end
- HTTP_TUN_S2C_START, // HTTP 200 connet established
- HTTP_TUN_INNER_STARTING, // http inner tunnel protocol starting
- HTTP_TUN_INNER_TRANS, // http inner tunnel protocol transmitting
-};
-
-/************************************************************
- * HTTP TUNNEL WITH CONNECT METHOD.
- *************************************************************/
-struct http_tunnel_message;
-#define HTTP_DECODER_TUNNEL_TOPIC "HTTP_DECODER_TUNNEL_MESSAGE"
-
-enum http_tunnel_message_type
-{
- HTTP_TUNNEL_OPENING,
- HTTP_TUNNEL_ACTIVE,
- HTTP_TUNNEL_CLOSING,
- HTTP_TUNNEL_MSG_MAX
-};
-enum http_tunnel_message_type http_tunnel_message_type_get(const struct http_tunnel_message *tmsg);
-void http_tunnel_message_get_payload(const struct http_tunnel_message *tmsg, struct iovec *tunnel_payload);
-
-int httpd_tunnel_identify(struct http_decoder_env *httpd_env, int curdir, struct http_decoder_half_data *hfdata);
-int httpd_is_tunnel_session(const struct http_decoder_env *httpd_env, const struct http_decoder_exdata *ex_data);
-int httpd_in_tunnel_transmitting(const struct http_decoder_env *httpd_env, struct http_decoder_exdata *ex_data);
-void httpd_tunnel_state_update(struct http_decoder_exdata *ex_data);
-void http_decoder_push_tunnel_data(struct session *sess, const struct http_decoder_exdata *exdata, enum http_tunnel_message_type type, const char *payload, uint16_t payload_len);
-enum http_tunnel_message_type httpd_tunnel_state_to_msg(const struct http_decoder_exdata *ex_data); \ No newline at end of file
diff --git a/decoders/http/http_decoder_utils.c b/decoders/http/http_decoder_utils.c
index 08c66b0..6c20ce7 100644
--- a/decoders/http/http_decoder_utils.c
+++ b/decoders/http/http_decoder_utils.c
@@ -1,311 +1,367 @@
#include <string.h>
#include <assert.h>
+#include <arpa/inet.h>
#include "stellar/http.h"
-#include "http_decoder_private.h"
+#include "stellar/utils.h"
+#include "http_decoder_utils.h"
+#include "http_decoder.h"
+#include "llhttp.h"
-char *http_safe_dup(const char *str, size_t len)
+#ifdef __cplusplus
+extern "C"
{
- if (str == NULL || len == 0)
- {
- return NULL;
- }
- char *dup = CALLOC(char, len + 1);
- memcpy(dup, str, len);
- return dup;
-}
+#endif
-int http_strncasecmp_safe(const char *fix_s1, const char *dyn_s2, size_t fix_n1, size_t dyn_n2)
-{
- if (fix_s1 == NULL || dyn_s2 == NULL)
+ char *http_safe_dup(const char *str, size_t len)
{
- return -1;
+ if (str == NULL || len == 0)
+ {
+ return NULL;
+ }
+ char *dup = CALLOC(char, len + 1);
+ memcpy(dup, str, len);
+ return dup;
}
- if (fix_n1 != dyn_n2)
+
+ int http_strncasecmp_safe(const char *fix_s1, const char *dyn_s2, size_t fix_n1, size_t dyn_n2)
{
- return -1;
+ if (fix_s1 == NULL || dyn_s2 == NULL)
+ {
+ return -1;
+ }
+ if (fix_n1 != dyn_n2)
+ {
+ return -1;
+ }
+ return strncasecmp(fix_s1, dyn_s2, fix_n1);
}
- return strncasecmp(fix_s1, dyn_s2, fix_n1);
-}
-const char *http_message_type_to_string(enum http_message_type type)
-{
- const char *sname = "unknown_msg_type";
-
- switch (type)
+ const char *http_topic_type_to_string(enum http_topic_type type)
{
- case HTTP_MESSAGE_REQ_LINE:
- sname = "HTTP_MESSAGE_REQ_LINE";
- break;
- case HTTP_MESSAGE_REQ_HEADER:
- sname = "HTTP_MESSAGE_REQ_HEADER";
- break;
- case HTTP_MESSAGE_REQ_HEADER_END:
- sname = "HTTP_MESSAGE_REQ_HEADER_END";
- break;
- case HTTP_MESSAGE_REQ_BODY_START:
- sname = "HTTP_MESSAGE_REQ_BODY_START";
- break;
- case HTTP_MESSAGE_REQ_BODY:
- sname = "HTTP_MESSAGE_REQ_BODY";
- break;
- case HTTP_MESSAGE_REQ_BODY_END:
- sname = "HTTP_MESSAGE_REQ_BODY_END";
- break;
- case HTTP_MESSAGE_RES_LINE:
- sname = "HTTP_MESSAGE_RES_LINE";
- break;
- case HTTP_MESSAGE_RES_HEADER:
- sname = "HTTP_MESSAGE_RES_HEADER";
- break;
- case HTTP_MESSAGE_RES_HEADER_END:
- sname = "HTTP_MESSAGE_RES_HEADER_END";
- break;
- case HTTP_MESSAGE_RES_BODY_START:
- sname = "HTTP_MESSAGE_RES_BODY_START";
- break;
- case HTTP_MESSAGE_RES_BODY:
- sname = "HTTP_MESSAGE_RES_BODY";
- break;
- case HTTP_MESSAGE_RES_BODY_END:
- sname = "HTTP_MESSAGE_RES_BODY_END";
- break;
- case HTTP_TRANSACTION_START:
- sname = "HTTP_TRANSACTION_START";
- break;
- case HTTP_TRANSACTION_END:
- sname = "HTTP_TRANSACTION_END";
- break;
+ const char *sname = "unknown_topic";
- default:
- break;
+ switch (type)
+ {
+ case HTTP_TOPIC_REQ_HEADER:
+ sname = "HTTP_TOPIC_REQ_HEADER";
+ break;
+ case HTTP_TOPIC_REQ_BODY:
+ sname = "HTTP_TOPIC_REQ_BODY";
+ break;
+ case HTTP_TOPIC_RES_HEADER:
+ sname = "HTTP_TOPIC_RES_HEADER";
+ break;
+ case HTTP_TOPIC_RES_BODY:
+ sname = "HTTP_TOPIC_RES_BODY";
+ break;
+ default:
+ break;
+ }
+ return sname;
}
- return sname;
-}
-
-int http_message_type_is_req(struct session *sess, enum http_message_type msg_type)
-{
- int is_req_msg = 0;
-
- switch (msg_type)
- {
- case HTTP_MESSAGE_REQ_LINE:
- case HTTP_MESSAGE_REQ_HEADER:
- case HTTP_MESSAGE_REQ_HEADER_END:
- case HTTP_MESSAGE_REQ_BODY_START:
- case HTTP_MESSAGE_REQ_BODY:
- case HTTP_MESSAGE_REQ_BODY_END:
- is_req_msg = 1;
- break;
+ static const unsigned char __g_httpd_hextable[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
+ 0, 10, 11, 12, 13, 14, 15 /* 0x60 - 0x66 */
+ };
- case HTTP_MESSAGE_RES_LINE:
- case HTTP_MESSAGE_RES_HEADER:
- case HTTP_MESSAGE_RES_HEADER_END:
- case HTTP_MESSAGE_RES_BODY_START:
- case HTTP_MESSAGE_RES_BODY:
- case HTTP_MESSAGE_RES_BODY_END:
- is_req_msg = 0;
- break;
+/* the input is a single hex digit */
+#define onehex2dec(x) __g_httpd_hextable[x - '0']
- case HTTP_TRANSACTION_START:
- case HTTP_TRANSACTION_END:
+#include <ctype.h>
+ // https://github.com/curl/curl/blob/2e930c333658725657b94a923d175c6622e0f41d/lib/urlapi.c
+ // void httpd_url_decode(const char *string, size_t length, char *ostring, size_t *olen)
+ size_t http_url_decode(const char *string, size_t length, char *ostring, size_t olen)
{
- enum flow_type cur_dir = session_get_flow_type(sess);
- if (FLOW_TYPE_C2S == cur_dir)
+ char *ns = ostring;
+ if (NULL == string || NULL == ostring || 0 == olen)
{
- is_req_msg = 1;
+ return 0;
}
- else
+ size_t alloc = length;
+ while (alloc)
{
- is_req_msg = 0;
+ unsigned char in = (unsigned char)*string;
+ if (('%' == in) && (alloc > 2) &&
+ isxdigit(string[1]) && isxdigit(string[2]))
+ {
+ /* this is two hexadecimal digits following a '%' */
+ in = (unsigned char)(onehex2dec(string[1]) << 4) | onehex2dec(string[2]);
+ string += 3;
+ alloc -= 3;
+ }
+ else
+ {
+ string++;
+ alloc--;
+ }
+ *ns++ = (char)in;
+ // if ((size_t)(ns - ostring) >= olen - 1)
+ // {
+ // return 1;
+ // }
}
+ return ns - ostring;
}
- break;
-
- default:
- assert(0);
- fprintf(stderr, "unknow message type:%d\n", (int)msg_type);
- break;
- }
- return is_req_msg;
-}
-int http_event_is_req(enum http_event event)
-{
- switch (event)
+ int httpd_url_is_encoded(const char *url, size_t len)
{
- case HTTP_EVENT_REQ_INIT:
- case HTTP_EVENT_REQ_LINE:
- case HTTP_EVENT_REQ_HDR:
- case HTTP_EVENT_REQ_HDR_END:
- case HTTP_EVENT_REQ_BODY_BEGIN:
- case HTTP_EVENT_REQ_BODY_DATA:
- case HTTP_EVENT_REQ_BODY_END:
- case HTTP_EVENT_REQ_END:
- return 1;
- break;
-
- case HTTP_EVENT_RES_INIT:
- case HTTP_EVENT_RES_LINE:
- case HTTP_EVENT_RES_HDR:
- case HTTP_EVENT_RES_HDR_END:
- case HTTP_EVENT_RES_BODY_BEGIN:
- case HTTP_EVENT_RES_BODY_DATA:
- case HTTP_EVENT_RES_BODY_END:
- case HTTP_EVENT_RES_END:
+ for (size_t i = 0; i < len; i++)
+ {
+ if (url[i] == '%')
+ {
+ return 1;
+ }
+ }
return 0;
- break;
-
- default:
- assert(0);
- fprintf(stderr, "unknow event type:%d\n", (int)event);
- break;
}
- return -1;
-}
-int stellar_session_mq_get_topic_id_reliable(struct stellar *st, const char *topic_name,
- stellar_msg_free_cb_func *msg_free_cb, void *msg_free_arg)
-{
- int topic_id = stellar_mq_get_topic_id(st, topic_name);
- if (topic_id < 0)
+ static void httpd_set_tcp_addr(const struct tcphdr *tcph, struct http_session_addr *addr, enum flow_type fdir)
{
- topic_id = stellar_mq_create_topic(st, topic_name, msg_free_cb, msg_free_arg);
+ if (FLOW_TYPE_C2S == fdir)
+ {
+ addr->sport = tcph->th_sport;
+ addr->dport = tcph->th_dport;
+ }
+ else
+ {
+ addr->sport = tcph->th_dport;
+ addr->dport = tcph->th_sport;
+ }
}
- return topic_id;
-}
-
-static const unsigned char __g_httpd_hextable[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
- 0, 10, 11, 12, 13, 14, 15 /* 0x60 - 0x66 */
-};
-
-/* the input is a single hex digit */
-#define onehex2dec(x) __g_httpd_hextable[x - '0']
-
-#include <ctype.h>
-// https://github.com/curl/curl/blob/2e930c333658725657b94a923d175c6622e0f41d/lib/urlapi.c
-// void httpd_url_decode(const char *string, size_t length, char *ostring, size_t *olen)
-size_t http_url_decode(const char *string, size_t length, char *ostring, size_t olen)
-{
- char *ns = ostring;
- if (NULL == string || NULL == ostring || 0 == olen)
+ static void httpd_set_ipv4_addr(const struct ip *ip4h, struct http_session_addr *addr, enum flow_type fdir)
{
- return 0;
+ addr->ipver = 4;
+ if (FLOW_TYPE_C2S == fdir)
+ {
+ addr->saddr4 = ip4h->ip_src.s_addr;
+ addr->daddr4 = ip4h->ip_dst.s_addr;
+ }
+ else
+ {
+ addr->saddr4 = ip4h->ip_dst.s_addr;
+ addr->daddr4 = ip4h->ip_src.s_addr;
+ }
}
- size_t alloc = length;
- while (alloc)
+ static void httpd_set_ipv6_addr(const struct ip6_hdr *ip6h, struct http_session_addr *addr, enum flow_type fdir)
{
- unsigned char in = (unsigned char)*string;
- if (('%' == in) && (alloc > 2) &&
- isxdigit(string[1]) && isxdigit(string[2]))
+ addr->ipver = 6;
+ if (FLOW_TYPE_C2S == fdir)
{
- /* this is two hexadecimal digits following a '%' */
- in = (unsigned char)(onehex2dec(string[1]) << 4) | onehex2dec(string[2]);
- string += 3;
- alloc -= 3;
+ memcpy(&addr->saddr6, &ip6h->ip6_src, sizeof(struct in6_addr));
+ memcpy(&addr->daddr6, &ip6h->ip6_dst, sizeof(struct in6_addr));
}
else
{
- string++;
- alloc--;
+ memcpy(&addr->saddr6, &ip6h->ip6_dst, sizeof(struct in6_addr));
+ memcpy(&addr->daddr6, &ip6h->ip6_src, sizeof(struct in6_addr));
}
- *ns++ = (char)in;
- // if ((size_t)(ns - ostring) >= olen - 1)
- // {
- // return 1;
- // }
}
- return ns - ostring;
-}
-int httpd_url_is_encoded(const char *url, size_t len)
-{
- for (size_t i = 0; i < len; i++)
+ void httpd_session_get_addr(const struct session *sess, struct http_session_addr *addr)
{
- if (url[i] == '%')
+ if (sess == NULL || addr == NULL)
+ {
+ return;
+ }
+ enum flow_type fdir = session_get_flow_type(sess);
+ const struct packet *raw_pkt = session_get_first_packet(sess, fdir);
+ if (NULL == raw_pkt)
{
- return 1;
+ addr->ipver = 0;
+ return;
+ }
+
+ int count = packet_get_layer_count(raw_pkt);
+ for (int i = count - 1; i >= 0; i--)
+ {
+ const struct layer *layer = packet_get_layer_by_idx(raw_pkt, i);
+ if (layer->proto == LAYER_PROTO_TCP)
+ {
+ httpd_set_tcp_addr(layer->hdr.tcp, addr, fdir);
+ }
+ else if (layer->proto == LAYER_PROTO_IPV4)
+ {
+ httpd_set_ipv4_addr(layer->hdr.ip4, addr, fdir);
+ break;
+ }
+ else if (layer->proto == LAYER_PROTO_IPV6)
+ {
+ httpd_set_ipv6_addr(layer->hdr.ip6, addr, fdir);
+ break;
+ }
}
}
- return 0;
-}
-static void httpd_set_tcp_addr(const struct tcphdr *tcph, struct httpd_session_addr *addr, enum flow_type fdir)
-{
- if (FLOW_TYPE_C2S == fdir)
+ void http_session_addr_ntop(const struct http_session_addr *sesaddr, char *buf, size_t buflen)
{
- addr->sport = tcph->th_sport;
- addr->dport = tcph->th_dport;
+ char sip_str[INET6_ADDRSTRLEN] = {0};
+ char dip_str[INET6_ADDRSTRLEN] = {0};
+ uint16_t sport_host, dport_host;
+ if (sesaddr->ipver == 4)
+ {
+ inet_ntop(AF_INET, &sesaddr->saddr4, sip_str, sizeof(sip_str));
+ inet_ntop(AF_INET, &sesaddr->daddr4, dip_str, sizeof(dip_str));
+ }
+ else if (sesaddr->ipver == 6)
+ {
+ inet_ntop(AF_INET6, &sesaddr->saddr6, sip_str, sizeof(sip_str));
+ inet_ntop(AF_INET6, &sesaddr->daddr6, dip_str, sizeof(dip_str));
+ }
+ sport_host = ntohs(sesaddr->sport);
+ dport_host = ntohs(sesaddr->dport);
+ snprintf(buf, buflen, "%s:%u-%s:%u", sip_str, sport_host, dip_str, dport_host);
}
- else
+
+ struct http_buffer *http_buffer_new(void)
{
- addr->sport = tcph->th_dport;
- addr->dport = tcph->th_sport;
+ struct http_buffer *buffer = CALLOC(struct http_buffer, 1);
+ buffer->buffer = NULL;
+ buffer->buffer_size = 0;
+ buffer->reference = 1;
+ return buffer;
}
-}
-static void httpd_set_ipv4_addr(const struct ip *ip4h, struct httpd_session_addr *addr, enum flow_type fdir)
-{
- addr->ipver = 4;
- if (FLOW_TYPE_C2S == fdir)
+
+ void http_buffer_free(struct http_buffer *buffer)
{
- addr->saddr4 = ip4h->ip_src.s_addr;
- addr->daddr4 = ip4h->ip_dst.s_addr;
+ if (NULL == buffer)
+ {
+ return;
+ }
+ if (buffer->reference > 1)
+ {
+ buffer->reference--;
+ return;
+ }
+ if (buffer->buffer)
+ {
+ FREE(buffer->buffer);
+ }
+ FREE(buffer);
}
- else
+
+ int http_buffer_add(struct http_buffer *buffer, const char *data, size_t data_len)
{
- addr->saddr4 = ip4h->ip_dst.s_addr;
- addr->daddr4 = ip4h->ip_src.s_addr;
+ if (NULL == buffer || NULL == data || 0 == data_len)
+ {
+ return -1;
+ }
+ buffer->buffer = REALLOC(char, buffer->buffer, buffer->buffer_size + data_len);
+ memcpy(buffer->buffer + buffer->buffer_size, data, data_len);
+ buffer->buffer_size += data_len;
+ return 0;
}
-}
-static void httpd_set_ipv6_addr(const struct ip6_hdr *ip6h, struct httpd_session_addr *addr, enum flow_type fdir)
-{
- addr->ipver = 6;
- if (FLOW_TYPE_C2S == fdir)
+
+ int http_buffer_read(struct http_buffer *buffer, char **data, size_t *data_len)
{
- memcpy(&addr->saddr6, &ip6h->ip6_src, sizeof(struct in6_addr));
- memcpy(&addr->daddr6, &ip6h->ip6_dst, sizeof(struct in6_addr));
+ if (NULL == buffer)
+ {
+ if (data)
+ {
+ *data = NULL;
+ }
+ if (data_len)
+ {
+ *data_len = 0;
+ }
+ return -1;
+ }
+ *data = buffer->buffer;
+ *data_len = buffer->buffer_size;
+ return 0;
}
- else
+
+ char *http_string_dup(const char *str, size_t len)
{
- memcpy(&addr->saddr6, &ip6h->ip6_dst, sizeof(struct in6_addr));
- memcpy(&addr->daddr6, &ip6h->ip6_src, sizeof(struct in6_addr));
+ if (NULL == str || 0 == len)
+ {
+ return NULL;
+ }
+ char *new_str = ALLOC(char, len);
+ memcpy(new_str, str, len);
+ return new_str;
}
-}
-void httpd_session_get_addr(const struct session *sess, struct httpd_session_addr *addr)
-{
- if (sess == NULL || addr == NULL)
+ long long http_strtoll(const char *str, size_t strlen)
{
- return;
+ if (NULL == str || 0 == strlen || strlen >= 19 /* INT64_MAX */)
+ {
+ return 0;
+ }
+ char tmp_str[strlen + 1];
+ memcpy(tmp_str, str, strlen);
+ tmp_str[strlen] = '\0';
+ return strtoll(tmp_str, NULL, 10);
}
- enum flow_type fdir = session_get_flow_type(sess);
- const struct packet *raw_pkt = session_get_first_packet(sess, fdir);
- if (NULL == raw_pkt)
+
+ /*
+ * return value:
+ * EOF offset of beggining.
+ */
+ size_t http_line_header_completed(const char *data, size_t data_len)
{
- addr->ipver = 0;
- return;
+ if (data_len < 4) //"\r\n\r\n"
+ {
+ return 0;
+ }
+ void *ptr = memmem(data, data_len, "\r\n\r\n", 4);
+ if (ptr != NULL)
+ {
+ return (char *)ptr - data + 4;
+ }
+ return 0;
}
- int count = packet_get_layer_count(raw_pkt);
- for (int i = count - 1; i >= 0; i--)
+ int http_protocol_identify(const char *data, size_t data_len)
{
- const struct layer *layer = packet_get_layer_by_idx(raw_pkt, i);
- if (layer->proto == LAYER_PROTO_TCP)
+ llhttp_t parser;
+ llhttp_settings_t settings;
+ enum llhttp_errno error;
+
+ if (NULL == data || 0 == data_len)
{
- httpd_set_tcp_addr(layer->hdr.tcp, addr, fdir);
+ return -1;
}
- else if (layer->proto == LAYER_PROTO_IPV4)
+ llhttp_settings_init(&settings);
+ llhttp_init(&parser, HTTP_BOTH, &settings);
+
+ data_len = MIN(HTTP_IDENTIFY_LEN, data_len);
+ error = llhttp_execute(&parser, data, data_len);
+ if (error != HPE_OK)
{
- httpd_set_ipv4_addr(layer->hdr.ip4, addr, fdir);
- break;
+ return -1;
}
- else if (layer->proto == LAYER_PROTO_IPV6)
+ return 1;
+ }
+
+ void http_truncate_extract_headers(const char *raw_data, size_t raw_data_len, const char **headers_start, const char **headers_end)
+ {
+ const char *start = memmem(raw_data, raw_data_len, "\r\n", 2);
+ if (start != NULL)
{
- httpd_set_ipv6_addr(layer->hdr.ip6, addr, fdir);
- break;
+ start += 2;
+ *headers_start = start;
}
+ else
+ {
+ *headers_start = NULL;
+ }
+ const char *end = memmem(raw_data, raw_data_len, "\r\n\r\n", 4);
+ if (end != NULL)
+ {
+ end += 4;
+ *headers_end = end;
+ }
+ else
+ {
+ *headers_start = NULL;
+ *headers_end = NULL;
+ }
+ return;
}
-} \ No newline at end of file
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/decoders/http/http_decoder_utils.h b/decoders/http/http_decoder_utils.h
index 01a32b2..c370228 100644
--- a/decoders/http/http_decoder_utils.h
+++ b/decoders/http/http_decoder_utils.h
@@ -10,31 +10,27 @@ extern "C"
#include "stellar/stellar.h"
#include "stellar/utils.h"
#include "stellar/session.h"
-#include "stellar/stellar_mq.h"
-#include "stellar/stellar_exdata.h"
-#ifdef __cplusplus
-}
+#include "llhttp.h"
+
+#ifndef UNUSED
+#define UNUSED __attribute__((unused))
#endif
-char *http_safe_dup(const char *str, size_t len);
-int http_strncasecmp_safe(const char *fix_s1, const char *dyn_s2, size_t fix_n1, size_t dyn_n2);
-const char *http_message_type_to_string(enum http_message_type type);
-int http_message_type_is_req(struct session *sess, enum http_message_type msg_type);
-int http_event_is_req(enum http_event event);
-int stellar_session_mq_get_topic_id_reliable(struct stellar *st, const char *topic_name, stellar_msg_free_cb_func *msg_free_cb, void *msg_free_arg);
-void httpd_url_decode(const char *string, size_t length, char *ostring, size_t *olen);
-int httpd_url_is_encoded(const char *url, size_t len);
-/******************************************************************************
- * Logger
- ******************************************************************************/
+ char *http_safe_dup(const char *str, size_t len);
+ int http_strncasecmp_safe(const char *fix_s1, const char *dyn_s2, size_t fix_n1, size_t dyn_n2);
+ void httpd_url_decode(const char *string, size_t length, char *ostring, size_t *olen);
+ int httpd_url_is_encoded(const char *url, size_t len);
+ /******************************************************************************
+ * Logger
+ ******************************************************************************/
-enum http_decoder_log_level
-{
- DEBUG = 0x11,
- WARN = 0x12,
- INFO = 0x13,
- ERROR = 0x14,
-};
+ enum http_decoder_log_level
+ {
+ DEBUG = 0x11,
+ WARN = 0x12,
+ INFO = 0x13,
+ ERROR = 0x14,
+ };
#ifndef http_decoder_log
#define http_decoder_log(level, format, ...) \
@@ -63,17 +59,45 @@ enum http_decoder_log_level
#include <netinet/in.h>
-struct httpd_session_addr
-{
- uint8_t ipver; /* 4 or 6 */
- uint16_t sport; /* network order */
- uint16_t dport; /* network order */
- union
+ struct http_session_addr
+ {
+ uint8_t ipver; /* 4 or 6 */
+ uint16_t sport; /* network order */
+ uint16_t dport; /* network order */
+ union
+ {
+ uint32_t saddr4;
+ struct in6_addr saddr6;
+ };
+ union
+ {
+ uint32_t daddr4;
+ struct in6_addr daddr6;
+ };
+ };
+ /*
+ why not use libevent evbuffer?
+ 1. evbuffer is a buffer chain, it is not suitable for http half flow cache;
+ 2. http_half_flow_buffer is a whole continuous buffer;
+ */
+ struct http_buffer
{
- uint32_t saddr4;
- uint32_t daddr4;
- struct in6_addr saddr6;
- struct in6_addr daddr6;
+ int reference; // used by other
+ char *buffer;
+ size_t buffer_size;
};
-};
-void httpd_session_get_addr(const struct session *sess, struct httpd_session_addr *addr);
+ int http_protocol_identify(const char *data, size_t data_len);
+ void httpd_session_get_addr(const struct session *sess, struct http_session_addr *addr);
+ void http_session_addr_ntop(const struct http_session_addr *sesaddr, char *buf, size_t buflen);
+ struct http_buffer *http_buffer_new(void);
+ void http_buffer_free(struct http_buffer *buffer);
+ int http_buffer_add(struct http_buffer *buffer, const char *data, size_t data_len);
+ int http_buffer_read(struct http_buffer *buffer, char **data, size_t *data_len);
+ char *http_string_dup(const char *str, size_t len);
+ long long http_strtoll(const char *str, size_t strlen);
+ size_t http_line_header_completed(const char *data, size_t data_len);
+ void http_truncate_extract_headers(const char *raw_data, size_t raw_data_len, const char **headers_start, const char **headers_end);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/decoders/http/version.map b/decoders/http/version.map
index a64b729..c20d021 100644
--- a/decoders/http/version.map
+++ b/decoders/http/version.map
@@ -1,11 +1,12 @@
VERS_3.0{
global:
extern "C" {
- http_message_*;
- http_decoder_init;
- http_decoder_exit;
- http_decoder_tcp_stream_msg_cb;
+ http_init;
+ http_exit;
+ http_subscribe_*;
+ http_get0_*;
http_url_decode;
+ http_module_to_http;
};
local: *;
}; \ No newline at end of file
diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt
index a00ff10..728126a 100644
--- a/deps/CMakeLists.txt
+++ b/deps/CMakeLists.txt
@@ -8,4 +8,5 @@ add_subdirectory(nmx_pool)
add_subdirectory(logger)
add_subdirectory(sds)
add_subdirectory(linenoise)
-add_subdirectory(ringbuf) \ No newline at end of file
+add_subdirectory(ringbuf)
+add_subdirectory(md5) \ No newline at end of file
diff --git a/deps/md5/CMakeLists.txt b/deps/md5/CMakeLists.txt
new file mode 100644
index 0000000..acdd6b5
--- /dev/null
+++ b/deps/md5/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_library(md5 STATIC md5.c)
+target_include_directories(md5 PUBLIC ${CMAKE_CURRENT_LIST_DIR}) \ No newline at end of file
diff --git a/include/stellar/http.h b/include/stellar/http.h
index 1cc5bec..4622b71 100644
--- a/include/stellar/http.h
+++ b/include/stellar/http.h
@@ -1,45 +1,21 @@
#pragma once
#include <stddef.h>
+#include <assert.h>
#ifdef __cplusplus
extern "C"
{
#endif
+#include "stellar/session.h"
+#include "stellar/module.h"
-#define HTTP_TOPIC "HTTP_MESSAGE"
- struct http_message;
+#define HTTP_MODULE_NAME "HTTP"
- enum http_message_type
- {
- HTTP_TRANSACTION_START,
-
- HTTP_MESSAGE_REQ_LINE,
- HTTP_MESSAGE_REQ_HEADER,
- HTTP_MESSAGE_REQ_HEADER_END, // todo, delete END, push all fileds at once
- HTTP_MESSAGE_REQ_BODY_START,
- HTTP_MESSAGE_REQ_BODY,
- HTTP_MESSAGE_REQ_BODY_END,
-
- HTTP_MESSAGE_RES_LINE,
- HTTP_MESSAGE_RES_HEADER,
- HTTP_MESSAGE_RES_HEADER_END, // todo, delete END, push all fileds at once
- HTTP_MESSAGE_RES_BODY_START,
- HTTP_MESSAGE_RES_BODY,
- HTTP_MESSAGE_RES_BODY_END,
-
- HTTP_TRANSACTION_END,
-
- HTTP_MESSAGE_MAX
- };
-
- struct http_header_field
- {
- char *name;
- size_t name_len;
- char *value;
- size_t value_len;
- };
+ /*
+ * Pay attention:
+ * HTTP scheme, method, uri, field name characters are case-insensitive.
+ */
- struct http_request_line
+ struct http_request_line // RFC2616-5.1
{
char *method;
size_t method_len;
@@ -47,12 +23,11 @@ extern "C"
size_t uri_len;
char *version;
size_t version_len;
-
int major_version;
int minor_version;
};
- struct http_response_line
+ struct http_status_line // RFC2616-6.1
{
char *version;
size_t version_len;
@@ -63,50 +38,86 @@ extern "C"
int status_code;
};
- enum http_message_type http_message_get_type(const struct http_message *msg);
-
- void http_message_get0_request_line(const struct http_message *msg, struct http_request_line *line);
-
- void http_message_get0_response_line(const struct http_message *msg, struct http_response_line *line);
-
- /*
- * Pay attention: key->iov_base is case-insensitive.
- */
- void http_message_get0_header(const struct http_message *msg, const char *name, size_t name_len, struct http_header_field *field_result);
-
- /**
- * @brief loop reading all headers.
- *
- * @retval succeed( >= 0) failed(-1)
- */
- int http_message_get0_next_header(const struct http_message *msg, struct http_header_field *header);
-
- /**
- * @retval succeed( >= 0) failed(-1)
- */
- int http_message_reset_header_iter(struct http_message *msg); // to do , obsoleted
-
- void http_message_get0_uncompressed_body(const struct http_message *msg, const char **body, size_t *body_len);
+ struct http_header_field // RFC2616-4.2
+ {
+ char *field_name;
+ size_t field_name_len;
+ char *field_value;
+ size_t field_value_len;
+ };
- /**
- * @brief If the body hasn't been compressed, same as http_message_get0_uncompressed_body().
- *
- */
- void http_message_get0_decompressed_body(const struct http_message *msg, const char **body, size_t *body_len);
+ struct http_header
+ {
+ /* most frequently used fields, is a pointer to field_array element, that is: host = &field_array[N] */
+ const struct http_header_field *host;
+ const struct http_header_field *content_type;
+ const struct http_header_field *referer;
+ const struct http_header_field *user_agent;
+ const struct http_header_field *cookie;
+ const struct http_header_field *set_cookie;
+ long long content_length; /* -1 is not found, or chunked */
+
+ const struct http_header_field *field_array;
+ size_t field_array_num;
+
+ /* whole original headers content, start with first header field name, end with \r\n\r\n */
+ const char *header_buf;
+ size_t header_buf_sz;
+ };
- void http_message_get0_raw_url(const struct http_message *msg, const char **url, size_t *url_len);
+ inline const struct http_header_field *http_get0_header_field(const struct http_header_field *field_array, size_t field_array_num,
+ const char *expect_field_name, size_t field_name_len)
+ {
+ assert(field_array && expect_field_name);
+ for (size_t i = 0; i < field_array_num; i++)
+ {
+ if ((field_array[i].field_name_len == field_name_len) &&
+ (strncasecmp(field_array[i].field_name, expect_field_name, field_name_len) == 0))
+ {
+ return &field_array[i];
+ }
+ }
+ return NULL;
+ }
/*
return value:
- 0: failed
+ <=0: failed
>1: success, length of decoded_url_buffer, not C string( no EOF with '\0' )
*/
size_t http_url_decode(const char *raw_url, size_t raw_url_len, char *decoded_url_buffer, size_t decoded_url_buffer_len);
- /**
- * @retval succeed( >= 0) failed(-1)
- */
- int http_message_get_transaction_seq(const struct http_message *msg);
+ typedef void(http_on_request_header_cb)(struct session *sess, int transaction_seq,
+ const struct http_request_line *req_line,
+ const struct http_header *header,
+ const char *url, size_t url_sz,
+ void *args);
+ typedef void(http_on_response_header_cb)(struct session *sess, int transaction_seq,
+ const struct http_status_line *status_line,
+ const struct http_header *header,
+ void *args);
+ typedef void(http_on_body_cb)(struct session *sess, const char *body, size_t body_sz, size_t offset,
+ int transaction_seq, int is_finished, void *args);
+
+ struct http_subscirbe_params
+ {
+ http_on_request_header_cb *req_hdr_cb;
+ http_on_response_header_cb *res_hdr_cb;
+ /*
+ stellar.toml->[http].decompress_switch = enable:
+ clear text if not compressed, decompressed data if compressed.
+
+ stellar.toml->[http].decompress_switch = disable:
+ the tcp payload is passed directly to subscriber without processing.
+ */
+ http_on_body_cb *req_body_cb; // config ->decompress_switch = enbale or disable
+ http_on_body_cb *res_body_cb;
+ };
+
+ struct http;
+ // use stellar_module_manager_get_module() get http module
+ struct http *http_module_to_http(struct module *http_mod);
+ int http_subscribe(struct http *http, struct http_subscirbe_params *params, void *arg);
#ifdef __cplusplus
}
diff --git a/infra/version.map b/infra/version.map
index 385a2a2..7c5ba83 100644
--- a/infra/version.map
+++ b/infra/version.map
@@ -67,11 +67,10 @@ global:
log_print;
log_check_level;
- http_message_*;
- http_decoder_init;
- http_decoder_exit;
- http_decoder_tcp_stream_msg_cb;
+ http_init;
+ http_exit;
http_url_decode;
+ http_subscribe_*;
lpi_plus_init;
lpi_plus_exit;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 11d1abc..4425594 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,7 +2,7 @@
add_subdirectory(packet_tool)
add_subdirectory(session_debugger)
add_subdirectory(lpi_plus)
-#add_subdirectory(decoders/http)
+add_subdirectory(decoders/http)
#add_subdirectory(decoders/socks)
#add_subdirectory(decoders/stratum)
#add_subdirectory(decoders/session_flags)
diff --git a/test/decoders/http/CMakeLists.txt b/test/decoders/http/CMakeLists.txt
index 5011a95..06270be 100644
--- a/test/decoders/http/CMakeLists.txt
+++ b/test/decoders/http/CMakeLists.txt
@@ -1,34 +1,107 @@
aux_source_directory(${PROJECT_SOURCE_DIR}/deps/toml DEPS_SRC)
aux_source_directory(${PROJECT_SOURCE_DIR}/deps/md5 DEPS_SRC)
-add_library(http_test SHARED http_test_plug.cpp ${DEPS_SRC})
-add_dependencies(http_test http)
-target_link_libraries(http_test cjson-static llhttp-static)
-set_target_properties(http_test PROPERTIES PREFIX "")
+# add_library(http_test SHARED http_test_plug.cpp ${DEPS_SRC})
+# add_dependencies(http_test http)
+# target_link_libraries(http_test cjson-static llhttp-static)
+# set_target_properties(http_test PROPERTIES PREFIX "")
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_SOURCE_DIR}/deps)
include_directories(${PROJECT_SOURCE_DIR}/decoders/http)
include_directories(${PROJECT_SOURCE_DIR}/include/stellar)
-add_executable(gtest_http http_gtest.cpp ${PROJECT_SOURCE_DIR}/decoders/http/http_decoder_utils.c ${PROJECT_SOURCE_DIR}/decoders/http/http_content_decompress.c ${PROJECT_SOURCE_DIR}/deps/md5/md5.c)
-target_link_libraries(gtest_http gtest stellar_lib llhttp-static z brotli-dec-static brotli-enc-static brotli-common-static libevent-static)
+add_executable(gtest_llhttp http_gtest_llhttp.cpp )
+add_executable(gtest_llhttp_header http_gtest_llhttp_headers_buf.cpp )
+target_link_libraries(gtest_llhttp gtest llhttp-static)
+target_link_libraries(gtest_llhttp_header gtest llhttp-static)
-add_executable(http_test_main plugin_test_main.cpp)
-set_target_properties(http_test_main
- PROPERTIES
- LINK_OPTIONS
- "-rdynamic"
- )
-set_target_properties(http_test_main
- PROPERTIES
- LINK_FLAGS
- "-rdynamic"
+# add_executable(gtest_http http_gtest.cpp
+# ${CMAKE_SOURCE_DIR}/decoders/http/http_decoder_utils.c
+# ${CMAKE_SOURCE_DIR}/decoders/http/http_decoder_stat.c
+# ${CMAKE_SOURCE_DIR}/decoders/http/http_decoder_decompress.c
+# )
+# target_link_libraries(gtest_http gtest stellar_lib llhttp-static z brotli-dec-static brotli-enc-static brotli-common-static fieldstat4 md5)
+
+
+add_executable(gtest_http_main http_gtest_main.cpp http_gtest_module.cpp )
+target_link_libraries(gtest_http_main gtest stellar_lib llhttp-static z brotli-dec-static brotli-enc-static brotli-common-static fieldstat4 cjson-static md5
+ -Wl,--whole-archive stellar_lib http -Wl,--no-whole-archive
+ dl "-rdynamic"
+ gtest gmock)
+
+set(TEST_PREFIX HTTP)
+add_test(NAME ${TEST_PREFIX}.SETUP COMMAND sh -c "
+ mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/conf &&
+ mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/log &&
+ cp ${CMAKE_SOURCE_DIR}/conf/stellar.toml ${CMAKE_CURRENT_BINARY_DIR}/conf/ &&
+ cat ${CMAKE_SOURCE_DIR}/test/decoders/http/http_module.toml >> ${CMAKE_CURRENT_BINARY_DIR}/conf/stellar.toml &&
+ tomlq -t -i '.packet_io.pcap_path=\"-\"' ${CMAKE_CURRENT_BINARY_DIR}/conf/stellar.toml &&
+ tomlq -t -i '.packet_io.mode=\"pcaplist\"' ${CMAKE_CURRENT_BINARY_DIR}/conf/stellar.toml
+ ")
+set_tests_properties(${TEST_PREFIX}.SETUP
+ PROPERTIES FIXTURES_SETUP ${TEST_PREFIX}.SETUP)
+
+set(HTTP_BENCHMARK_PCAP ${CMAKE_SOURCE_DIR}/test/decoders/http/benchmarks/pcap)
+set(HTTP_BENCHMARK_JSON ${CMAKE_SOURCE_DIR}/test/decoders/http/benchmarks/json)
+set(HTTP_GTEST_MAIN ${CMAKE_CURRENT_BINARY_DIR}/gtest_http_main)
+set(HTTP_TEST_JSON http_gtest.json)
+
+set(HTTP_BENCHMARK_CAESES
+ http_6over4_single_trans
+ http_chn_encode_url
+ http_chunked_res_gzip
+ # http_connect_flood
+ # http_connect_single not get c2s payload from stellar
+ http_error
+ http_fin
+ http_get_encoded_uri
+ http_get_long_cookie
+ http_get_malformed
+ http_get_multi_trans
+ http_get_req_pipeline
+ http_get_single_trans
+ http_gzip_out_of_order
+ http_hdrs_exceed_maximum
+ # http_hdr_truncated_after_kv # no SYN
+ # http_hdr_truncated_in_kv # no SYN
+ # http_hdr_value_empty #no SYN
+ http_incomplete_header
+ http_multi_parse_error
+ http_no_content_length
+ # http_no_cr_line_eof //url decode error
+ http_out_of_order
+ http_over_pppoe
+ http_over_tcp_keepalive
+ http_over_tls
+ http_pipeline_C2S
+ http_pipeline_header_splitting
+ http_pipeline_S2C
+ http_post_c2s
+ http_post_multipart_form_data
+ http_post
+ http_post_s2c
+ http_post_single_trans
+ http_put_continue100
+ http_req_1byte_sliding_window
+ http_res_1byte_sliding_window
+ http_res_gzip
+ http_session_exception_c2s
+ http_session_exception_s2c
+ http_trans_pipeline
+ http_url_test_with_host
+ http_url_test_without_host
+ http_url_test_without_host_v6
+ http_whitespace_before_header
+ http_zlib_deadlock
+ non_http
)
-set(LINK_FLAGS "-rdynamic")
-target_link_libraries(http_test_main gtest cjson-static stellar_lib llhttp-static)
-add_subdirectory(test_based_on_stellar)
+foreach(case_name ${HTTP_BENCHMARK_CAESES})
+ add_test(NAME ${TEST_PREFIX}.${case_name} COMMAND sh -c "find ${HTTP_BENCHMARK_PCAP} -type f -name ${case_name}.pcap | sort -V | ${HTTP_GTEST_MAIN} ${HTTP_BENCHMARK_JSON}/${case_name}.json ${HTTP_TEST_JSON}" )
+ set_tests_properties(${TEST_PREFIX}.${case_name} PROPERTIES FIXTURES_REQUIRED ${TEST_PREFIX}.SETUP)
+endforeach()
include(GoogleTest)
-gtest_discover_tests(gtest_http)
+# gtest_discover_tests(gtest_http)
+gtest_discover_tests(gtest_llhttp)
diff --git a/test/decoders/http/benchmarks/json/http_6over4_single_trans.json b/test/decoders/http/benchmarks/json/http_6over4_single_trans.json
index 34d999d..c0f092c 100644
--- a/test/decoders/http/benchmarks/json/http_6over4_single_trans.json
+++ b/test/decoders/http/benchmarks/json/http_6over4_single_trans.json
@@ -1,6 +1,6 @@
[
{
- "__X_HTTP_TUPLE4": "2001:da8:200:900e:200:5efe:d24d:58a3.52556>2600:140e:6::1702:1058.80"
+ "__X_HTTP_TUPLE4": "2001:da8:200:900e:200:5efe:d24d:58a3:52556-2600:140e:6::1702:1058:80-6-0"
},
{
"__X_HTTP_TRANSACTION": "request",
@@ -13,7 +13,8 @@
"Connection": "Close",
"User-Agent": "Microsoft NCSI",
"Host": "www.msftncsi.com",
- "__X_HTTP_URL": "www.msftncsi.com/ncsi.txt"
+ "__X_HTTP_URL": "www.msftncsi.com/ncsi.txt",
+ "__X_HTTP_HEADERS_INTERGRATION": "Connection: Close\r\nUser-Agent: Microsoft NCSI\r\nHost: www.msftncsi.com\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -28,7 +29,7 @@
"Connection": "close",
"Content-Type": "text/plain",
"Cache-Control": "max-age=30, must-revalidate",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "cd5a4d3fdd5bffc16bf959ef75cf37bc",
- "__X_HTTP_PAYLOAD": "TWljcm9zb2Z0IE5DU0k="
+ "__X_HTTP_HEADERS_INTERGRATION": "Content-Length: 14\r\nDate: Tue, 01 Dec 2015 03:41:27 GMT\r\nConnection: close\r\nContent-Type: text/plain\r\nCache-Control: max-age=30, must-revalidate\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "cd5a4d3fdd5bffc16bf959ef75cf37bc"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_chn_encode_url.json b/test/decoders/http/benchmarks/json/http_chn_encode_url.json
index 5453415..e5be533 100644
--- a/test/decoders/http/benchmarks/json/http_chn_encode_url.json
+++ b/test/decoders/http/benchmarks/json/http_chn_encode_url.json
@@ -20,7 +20,8 @@
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Cookie": "_gcl_au=1.1.240068387.1720059437; _ga_CGYVD7S4G4=GS1.1.1720059448.3.0.1720059453.0.0.0; HMF_CI=7967e38cc3874dbbefa260b8dcbee31fa827a01fc2b7073105a5e05f4a1ea361c74f6d4c37fb199bfc9470036f06fb537da2a74e96450b7949e0b686f0569f9680; HMY_JC=84f9c8a99e076ee2dda5ba48cd953f61c4dc2707823205d8171c8818eea9d60fda,; _ga=GA1.3.822493162.1711101509; _gid=GA1.3.304369429.1721120134; arialoadData=true; ariawapChangeViewPort=false; C3VK=be8842; HBB_HC=faa7f3e2477e14525534a5560ed6a307b29ae2c324e1f631a428e53fb74c9d72575c155d682554ba15cc9e52afe31218b1; mbox=check#true#1721120252|session#1721120133635-517642#1721122052; s_pers=%20s_fid%3D52863027521849CD-3A72894997C48527%7C1878886591105%3B; s_sess=%20s_cc%3Dtrue%3B",
"__X_HTTP_URL": "www.airchina.com.cn/%E6%B5%8B%E8%AF%95%E4%B8%AD%E6%96%87URL%E7%BC%96%E8%A7%A3%E7%A0%81",
- "__X_HTTP_DECODED_URL": "www.airchina.com.cn/测试中文URL编解码"
+ "__X_HTTP_DECODED_URL": "www.airchina.com.cn/测试中文URL编解码",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: www.airchina.com.cn\r\nConnection: keep-alive\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nCookie: _gcl_au=1.1.240068387.1720059437; _ga_CGYVD7S4G4=GS1.1.1720059448.3.0.1720059453.0.0.0; HMF_CI=7967e38cc3874dbbefa260b8dcbee31fa827a01fc2b7073105a5e05f4a1ea361c74f6d4c37fb199bfc9470036f06fb537da2a74e96450b7949e0b686f0569f9680; HMY_JC=84f9c8a99e076ee2dda5ba48cd953f61c4dc2707823205d8171c8818eea9d60fda,; _ga=GA1.3.822493162.1711101509; _gid=GA1.3.304369429.1721120134; arialoadData=true; ariawapChangeViewPort=false; C3VK=be8842; HBB_HC=faa7f3e2477e14525534a5560ed6a307b29ae2c324e1f631a428e53fb74c9d72575c155d682554ba15cc9e52afe31218b1; mbox=check#true#1721120252|session#1721120133635-517642#1721122052; s_pers=%20s_fid%3D52863027521849CD-3A72894997C48527%7C1878886591105%3B; s_sess=%20s_cc%3Dtrue%3B\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -37,6 +38,7 @@
"Location": "https://www.airchina.com.cn/%E6%B5%8B%E8%AF%95%E4%B8%AD%E6%96%87URL%E7%BC%96%E8%A7%A3%E7%A0%81",
"x-ws-origin-error": "-",
"X-Via": "1.1 PSjsczBGPiv194:0 (Cdn Cache Server V2.0), 1.1 PStjdxpn34:6 (Cdn Cache Server V2.0)",
- "X-Ws-Request-Id": "669635fc_PStjdxks32_7630-15285"
+ "X-Ws-Request-Id": "669635fc_PStjdxks32_7630-15285",
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Tue, 16 Jul 2024 08:57:32 GMT\r\nContent-Length: 0\r\nConnection: keep-alive\r\nServer: waf/4.39.0-0.el7\r\nLocation: https://www.airchina.com.cn/%E6%B5%8B%E8%AF%95%E4%B8%AD%E6%96%87URL%E7%BC%96%E8%A7%A3%E7%A0%81\r\nx-ws-origin-error: -\r\nX-Via: 1.1 PSjsczBGPiv194:0 (Cdn Cache Server V2.0), 1.1 PStjdxpn34:6 (Cdn Cache Server V2.0)\r\nX-Ws-Request-Id: 669635fc_PStjdxks32_7630-15285\r\n\r\n"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_chunked_res_gzip.json b/test/decoders/http/benchmarks/json/http_chunked_res_gzip.json
index 370b4a7..4eafc0d 100644
--- a/test/decoders/http/benchmarks/json/http_chunked_res_gzip.json
+++ b/test/decoders/http/benchmarks/json/http_chunked_res_gzip.json
@@ -15,7 +15,8 @@
"Accept": "*/*",
"Connection": "close",
"Accept-Encoding": "chunked, gzip",
- "__X_HTTP_URL": "www.wireshark.org:8080/"
+ "__X_HTTP_URL": "www.wireshark.org:8080/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: www.wireshark.org:8080\r\nUser-Agent: curl/7.46.0\r\nAccept: */*\r\nConnection: close\r\nAccept-Encoding: chunked, gzip\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -37,10 +38,10 @@
"X-Mod-Pagespeed": "1.9.32.11-7550",
"Vary": "Accept-Encoding",
"Cache-control": "max-age=0, no-cache, no-store",
- "X-Slogan1": "Go deep.",
+ "X-Slogan.1": "Go deep.",
"CF-RAY": "260a3f709d7b0761-AMS",
"Content-Encoding": "gzip",
- "__X_HTTP_RAW_PAYLOAD_MD5": "5387fc115327b819ba920ad6ce8f3e3a",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "855f8310be999de806e89a420a95435d"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: cloudflare-nginx\r\nDate: Wed, 06 Jan 2016 20:42:10 GMT\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\nConnection: close\r\nSet-Cookie: __cfduid=d8d37b52eaa3137bdfd7fd67a4ffc8a7a1452112929; expires=Thu, 05-Jan-17 20:42:09 GMT; path=/; domain=.wireshark.org; HttpOnly\r\nX-Frame-Options: SAMEORIGIN\r\nStrict-Transport-Security: max-age=31536000;\r\nX-Slogan: It's a great product with a great story to tell. I'm pumped!\r\nX-Mod-Pagespeed: 1.9.32.11-7550\r\nVary: Accept-Encoding\r\nCache-control: max-age=0, no-cache, no-store\r\nX-Slogan: Go deep.\r\nCF-RAY: 260a3f709d7b0761-AMS\r\nContent-Encoding: gzip\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "855f8310be999de806e89a420a95435d"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_connect_single.json b/test/decoders/http/benchmarks/json/http_connect_single.json
new file mode 100644
index 0000000..752a21e
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_connect_single.json
@@ -0,0 +1,20 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "10.128.0.2:18762-10.0.0.2:80-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.1",
+ "res_status": "Forbidden",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 403,
+ "Date": "Thu, 03 Sep 2020 10:26:38 GMT",
+ "Server": "Apache",
+ "Content-Length": "199",
+ "Content-Type": "text/html; charset=iso-8859-1",
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Thu, 03 Sep 2020 10:26:38 GMT\r\nServer: Apache\r\nContent-Length: 199\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "bb8f534fbff5ee61a95af9c4740ae043"
+ }
+] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_error.json b/test/decoders/http/benchmarks/json/http_error.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_error.json
@@ -0,0 +1 @@
+[]
diff --git a/test/decoders/http/benchmarks/json/http_fin.json b/test/decoders/http/benchmarks/json/http_fin.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_fin.json
@@ -0,0 +1 @@
+[]
diff --git a/test/decoders/http/benchmarks/json/http_get_encoded_uri.json b/test/decoders/http/benchmarks/json/http_get_encoded_uri.json
index de1419a..314c6e4 100644
--- a/test/decoders/http/benchmarks/json/http_get_encoded_uri.json
+++ b/test/decoders/http/benchmarks/json/http_get_encoded_uri.json
@@ -22,7 +22,8 @@
"Host": "58.16.70.122",
"Content-Length": "0",
"Accept-Encoding": "gzip, deflate",
- "__X_HTTP_URL": "58.16.70.122/disAll/tcCertType.html"
+ "__X_HTTP_URL": "58.16.70.122/disAll/tcCertType.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36\r\nAccept: */*\r\nAccept-Language: en-US,en;q=0.8,en-us,en;q=0.5\r\nOrigin: http://58.16.70.122\r\nX-Requested-With: XMLHttpRequest\r\nReferer: http://58.16.70.122/register.jsp?redirect:http://58.16.70.122.r87.com/?\r\nCache-Control: no-cache\r\nX-Scanner: Netsparker\r\nCookie: JSESSIONID=385C79E211D561C0CA13D90F150F603D\r\nHost: 58.16.70.122\r\nContent-Length: 0\r\nAccept-Encoding: gzip, deflate\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -38,8 +39,8 @@
"Content-Type": "text/html;charset=UTF-8",
"Transfer-Encoding": "chunked",
"Date": "Sat, 18 May 2019 01:36:57 GMT",
- "__X_HTTP_RAW_PAYLOAD_MD5": "d545e0faf20f7ffe90e31cfc1aef1782",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d545e0faf20f7ffe90e31cfc1aef1782"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: Apache-Coyote/1.1\r\nPragma: No-cache\r\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\r\nContent-Type: text/html;charset=UTF-8\r\nTransfer-Encoding: chunked\r\nDate: Sat, 18 May 2019 01:36:57 GMT\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d545e0faf20f7ffe90e31cfc1aef1782"
},
{
"__X_HTTP_TRANSACTION": "request",
@@ -58,7 +59,8 @@
"Host": "58.16.70.122",
"Accept-Encoding": "gzip, deflate",
"__X_HTTP_URL": "58.16.70.122/upload/%E6%B3%95%E5%BE%8B%E6%B3%95%E8%A7%84/%E5%B8%82%E4%BA%BA%E6%B0%91%E6%94%BF%E5%BA%9C%E5%8A%9E%E5%85%AC%E5%8E%85%E5%8D%B0%E5%8F%91%E8%B4%B5%E9%98%B3%E5%B8%82%E5%85%B3%E4%BA%8E%E6%8E%A8%E8%BF%9B%E5%B7%A5%E5%95%86%E8%90%A5%E4%B8%9A%E6%89%A7%E7%85%A7%E3%80%81%E7%BB%84%E7%BB%87%E6%9C%BA%E6%9E%84%E4%BB%A3%E7%A0%81%E8%AF%81%E5%92%8C%E7%A8%8E%E5%8A%A1%E7%99%BB%E8%AE%B0%E8%AF%81%E2%80%9C%E4%B8%89%E8%AF%81%E5%90%88%E4%B8%80%E2%80%9D%E7%99%BB%E8%AE%B0%E5%88%B6%E5%BA%A6%E6%94%B9%E9%9D%A9%E5%AE%9E%E6%96%BD%E6%96%B9%E6%A1%88%E7%9A%84%E9%80%9A%E7%9F%A5%EF%BC%88%E7%AD%91%E5%BA%9C%E5%8A%9E%E5%87%BD%E3%80%902015%E3%80%91162%E5%8F%B7%EF%BC%89.docx?nsextt=N3TSP4RKE2",
- "__X_HTTP_DECODED_URL": "58.16.70.122/upload/法律法规/市人民政府办公厅印发贵阳市关于推进工商营业执照、组织机构代码证和税务登记证“三证合一”登记制度改革实施方案的通知(筑府办函【2015】162号).docx?nsextt=N3TSP4RKE2"
+ "__X_HTTP_DECODED_URL": "58.16.70.122/upload/法律法规/市人民政府办公厅印发贵阳市关于推进工商营业执照、组织机构代码证和税务登记证“三证合一”登记制度改革实施方案的通知(筑府办函【2015】162号).docx?nsextt=N3TSP4RKE2",
+ "__X_HTTP_HEADERS_INTERGRATION": "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36\r\nCache-Control: no-cache\r\nAccept-Language: en-us,en;q=0.5\r\nX-Scanner: Netsparker\r\nCookie: JSESSIONID=385C79E211D561C0CA13D90F150F603D\r\nHost: 58.16.70.122\r\nAccept-Encoding: gzip, deflate\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -75,7 +77,7 @@
"Content-Type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8",
"Content-Length": "1703517",
"Date": "Sat, 18 May 2019 01:37:00 GMT",
- "__X_HTTP_RAW_PAYLOAD_MD5": "3598c468910611a3128d068e20ae0e82",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "3598c468910611a3128d068e20ae0e82"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: Apache-Coyote/1.1\r\nAccept-Ranges: bytes\r\nETag: W/\"1703517-1546572172000\"\r\nLast-Modified: Fri, 04 Jan 2019 03:22:52 GMT\r\nContent-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8\r\nContent-Length: 1703517\r\nDate: Sat, 18 May 2019 01:37:00 GMT\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "3598c468910611a3128d068e20ae0e82"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_get_long_cookie.json b/test/decoders/http/benchmarks/json/http_get_long_cookie.json
index 118022d..6643f36 100644
--- a/test/decoders/http/benchmarks/json/http_get_long_cookie.json
+++ b/test/decoders/http/benchmarks/json/http_get_long_cookie.json
@@ -18,7 +18,8 @@
"Accept-Encoding": "gzip,deflate,sdch",
"Accept-Language": "zh-CN,zh;q=0.8",
"__X_HTTP_URL": "livep.l.qq.com/livemsg?imagemd5=02f5efd8a349c50280f8540b2735bd54&tailroll=1&plugin=1.3.8&pf=out&si=3766845706&url=http%3A%2F%2Fsports.qq.com%2Fa%2F20160106%2F008987.htm&soid=CA7F9C5B0120568CDC2F68726300&chid=0&ping_data=dXNlcl9pbmZvPXVCWDluVDg5SFJhOUFQK0JQVGdKRUxVYi9Kdz0&t=0&iptype=0&vptag=&pid=7F993E38C0E676ACC07DE764D1F3DEF56AA8F90A&adtype=LD&oadid=6012&ev=3236&l=4020&ufc_filter=0&imagelog=1&pid2=7F993E38C0E676ACC07DE764D1F3DEF56AA8F90A&mt=15000&coverid=&reqtime=1452071981&requestl=4020&isthirdip=0&cid=0&isfloatindex=0&o=100654557&lcount=2&refluence=4020&from=0&vid=m01794rm5ej&cip=202.127.156.91&aver=0&ip_filter=0&adlength=30000&tagid=&v=TencentPlayerOutV3.2.19.346&live=0&dura=105",
- "__X_HTTP_DECODED_URL": "livep.l.qq.com/livemsg?imagemd5=02f5efd8a349c50280f8540b2735bd54&tailroll=1&plugin=1.3.8&pf=out&si=3766845706&url=http://sports.qq.com/a/20160106/008987.htm&soid=CA7F9C5B0120568CDC2F68726300&chid=0&ping_data=dXNlcl9pbmZvPXVCWDluVDg5SFJhOUFQK0JQVGdKRUxVYi9Kdz0&t=0&iptype=0&vptag=&pid=7F993E38C0E676ACC07DE764D1F3DEF56AA8F90A&adtype=LD&oadid=6012&ev=3236&l=4020&ufc_filter=0&imagelog=1&pid2=7F993E38C0E676ACC07DE764D1F3DEF56AA8F90A&mt=15000&coverid=&reqtime=1452071981&requestl=4020&isthirdip=0&cid=0&isfloatindex=0&o=100654557&lcount=2&refluence=4020&from=0&vid=m01794rm5ej&cip=202.127.156.91&aver=0&ip_filter=0&adlength=30000&tagid=&v=TencentPlayerOutV3.2.19.346&live=0&dura=105",
- "Cookie": "flashuser=95621BA8CB862E09; piao_city=179; lv_irt_id=3628e1bbe25a6c941da9fac02ec2df8b; cm_cookie=V1,10017&-EP5mRruXhQarsCl5LD-2YzgjVTvyr2K&AQEBh7uoLMUB9lnaB5Tz9XdYnGIWflXmsDrU&150723&150723,10035&7t-tEmfJ076VAsM9&AQEBh7uoLMUB9lnc4tpW7vbazqdrRdBYOUCi&150724&150807,110054&ucO0Z0gctNn3&AQEBh7uoLMUB9llxMNl45F3RAIsKK0iMOJAG&150716&151008,10040&ACZ1r0A70NaEFcGT&AQEBh7uoLMUB9lmVgSoTwuuXZi896zSVsXIF&150818&151014,110015&1&AQEBh7uoLMUB9lkt2LUHO6ARwODHLI_Y51rj&150928&151103,10037&1433388364186289251984&AQEBh7uoLMUB9llIBencOqTAEh2aQ2SURSSQ&150909&151110,10011&jL40Z03uUFI0&AQEBh7uoLMUB9lkfw2sJVNx9g12Fzs12rPSN&150717&151125,10016&F64E6LFZs0W&AQEBh7uoLMUB9llE4yoPFNUykSj7WKaRK5lH&150805&151127,10019&WQAO-C1K9qI5OP8W_t2pSw&AQEBh7uoLMUB9llhpZE87GmOk3XGo_MJgV6K&150826&151130,10015&820490997316506147&AQEBh7uoLMUB9llXiynsGYRhMO3XuPnkuHUt&150715&151201,10012&x3X1yY6b&AQEBh7uoLMUB9ll9mraU_LJCDBYsE0Sbk_V9&151202&151202,110065&ucO0Z0gctNn3&AQEBh7uoLMUB9lkJcK3KDBQTKF0YfZ5wB7r5&150716&151203,110066&jL40Z03uUFI0&AQEBh7uoLMUB9lnyvKSYhcJD1X_rSs_DLVWx&150916&151221,10013&ePyYB2MSKa0TCbebpxKjmU&AQEBh7uoLMUB9ln6_6nGNidqml4nFKXhtE58&151221&151221,110061&d9cfa518d82abee&AQEBh7uoLMUB9llj2NYzmCjxaLWXALTcAGIH&150818&151224,10038&CAESEPZbUhToZJ39CS9MlgXGUSQ&AQEBh7uoLMUB9lmhnrDM5lIGtl6vc1NxMD6F&151110&151224,10077&820490997316506147&AQEBh7uoLMUB9lmkUdUe2xSHGkvM0IRu9Jt9&151214&151228,10008&0yPSvk92ie1nhB8wTUlTq&AQEBh7uoLMUB9lnL5ZCYvXJNvlv53G0CKEkj&150817&151228,10045&0&AQEBh7uoLMUB9llW3v1Vh7W72lv14RlAjUXn&151023&151228,110064&jL40Z03uUFI0&AQEBh7uoLMUB9lkBYuCUDLDrOcGURJcilogv&151016&160104,110069&26d49ecc&AQEBh7uoLMUB9lmlBLTxQY9BkCmimkMFqTo5&151204&160105,10079&B8hGto5y1e3uDXwCMsIun3rjk--dVCof&AQEBh7uoLMUB9llxnFrhDtdNMjZ1hs1il5J4&151214&160105; LHTturn=24; ptisp=ctc; RK=hRWyd82Gd8; pgv_pvi=7567882240; image_md5=bd21d5fb2f401b37cf3a02724dc06545; LTPturn=27; pt2gguin=o0583115900; uin=o0583115900; skey=@Mp9aCinaO; ptcz=10d4b1b7bde835d64663338a8008fd4f81e2c6b5f0ba81a90da3627ee617c7ee; pgv_info=ssid=s4768939310; pgv_pvid=6872592818; o_cookie=583115900; lv_play_index_textAd=47; lv_play_indexl.=32; dc_vplaying=1; LKBturn=29; Lturn=29; adid=583115900; appuser=95621BA8CB862E09; o_minduid=phhdxyNLkxBWMa74VTm5zU4y5EbUv5vR; appuser_95621BA8CB862E09_0=2b7gwp=1453219199_6&2btemv=1455551999_1&2c8311=1453305599_3&2cfx4j=1453651199_3&2cfx9l=1453651199_1&2d49y9=1453823999_2&2d67kl=1454255999_2&2d69mf=1454255999_3&2dxv8l=1455465599_6&2dzhfl=1452614399_1&f_pogvwp=1452095999_1&f_pogvwv=1452095999_2&f_pogw0m=1452095999_1&fd_15bm2t7=1452095999_1&fd_1h2pbsd=1452095999_2&fd_1k6so62=1452095999_1&fd_rhmjmq=1452095999_2&m_roiw0t=1452095999_3&m_xty8wl=1452095999_1&pogree=1452095999_2; TX.boid=100655474=1452072582_1&701041365=1452072585_1; appuser_95621BA8CB862E09_effect_0=fd_1ez2rcc=1452095999_1&fd_qdh7zw=1452095999_1&fd_ul215j=1452095999_1; psessionid=ca7f9c5b_1452071982_583115900_30754; psessiontime=1452071990"
+ "__X_HTTP_DECODED_URL": "livep.l.qq.com/livemsg?imagemd5=02f5efd8a349c50280f8540b2735bd54&tailroll=1&plugin=1.3.8&pf=out&si=3766845706&url=http://sports.qq.com/a/20160106/008987.htm&soid=CA7F9C5B0120568CDC2F68726300&chid=0&ping_data=dXNlcl9pbmZvPXVCWDluVDg5SFJhOUFQK0JQVGdKRUxVYi9Kdz0&t=0&iptype=0&vptag=&pid=7F993E38C0E676ACC07DE764D1F3DEF56AA8F90A&adtype=LD&oadid=6012&ev=3236&l=4020&ufc_filter=0&imagelog=1&pid2=7F993E38C0E676ACC07DE764D1F3DEF56AA8F90A&mt=15000&coverid=&reqtime=1452071981&requestl=4020&isthirdip=0&cid=0&isfloatindex=0&o=100654557&lcount=2&refluence=4020&from=0&vid=m01794rm5ej&cip=202.127.156.91&aver=0&ip_filter=0&adlength=30000&tagid=&v=TencentPlayerOutV3.2.19.346&live=0&dura=105",
+ "Cookie": "flashuser=95621BA8CB862E09; piao_city=179; lv_irt_id=3628e1bbe25a6c941da9fac02ec2df8b; cm_cookie=V1,10017&-EP5mRruXhQarsCl5LD-2YzgjVTvyr2K&AQEBh7uoLMUB9lnaB5Tz9XdYnGIWflXmsDrU&150723&150723,10035&7t-tEmfJ076VAsM9&AQEBh7uoLMUB9lnc4tpW7vbazqdrRdBYOUCi&150724&150807,110054&ucO0Z0gctNn3&AQEBh7uoLMUB9llxMNl45F3RAIsKK0iMOJAG&150716&151008,10040&ACZ1r0A70NaEFcGT&AQEBh7uoLMUB9lmVgSoTwuuXZi896zSVsXIF&150818&151014,110015&1&AQEBh7uoLMUB9lkt2LUHO6ARwODHLI_Y51rj&150928&151103,10037&1433388364186289251984&AQEBh7uoLMUB9llIBencOqTAEh2aQ2SURSSQ&150909&151110,10011&jL40Z03uUFI0&AQEBh7uoLMUB9lkfw2sJVNx9g12Fzs12rPSN&150717&151125,10016&F64E6LFZs0W&AQEBh7uoLMUB9llE4yoPFNUykSj7WKaRK5lH&150805&151127,10019&WQAO-C1K9qI5OP8W_t2pSw&AQEBh7uoLMUB9llhpZE87GmOk3XGo_MJgV6K&150826&151130,10015&820490997316506147&AQEBh7uoLMUB9llXiynsGYRhMO3XuPnkuHUt&150715&151201,10012&x3X1yY6b&AQEBh7uoLMUB9ll9mraU_LJCDBYsE0Sbk_V9&151202&151202,110065&ucO0Z0gctNn3&AQEBh7uoLMUB9lkJcK3KDBQTKF0YfZ5wB7r5&150716&151203,110066&jL40Z03uUFI0&AQEBh7uoLMUB9lnyvKSYhcJD1X_rSs_DLVWx&150916&151221,10013&ePyYB2MSKa0TCbebpxKjmU&AQEBh7uoLMUB9ln6_6nGNidqml4nFKXhtE58&151221&151221,110061&d9cfa518d82abee&AQEBh7uoLMUB9llj2NYzmCjxaLWXALTcAGIH&150818&151224,10038&CAESEPZbUhToZJ39CS9MlgXGUSQ&AQEBh7uoLMUB9lmhnrDM5lIGtl6vc1NxMD6F&151110&151224,10077&820490997316506147&AQEBh7uoLMUB9lmkUdUe2xSHGkvM0IRu9Jt9&151214&151228,10008&0yPSvk92ie1nhB8wTUlTq&AQEBh7uoLMUB9lnL5ZCYvXJNvlv53G0CKEkj&150817&151228,10045&0&AQEBh7uoLMUB9llW3v1Vh7W72lv14RlAjUXn&151023&151228,110064&jL40Z03uUFI0&AQEBh7uoLMUB9lkBYuCUDLDrOcGURJcilogv&151016&160104,110069&26d49ecc&AQEBh7uoLMUB9lmlBLTxQY9BkCmimkMFqTo5&151204&160105,10079&B8hGto5y1e3uDXwCMsIun3rjk--dVCof&AQEBh7uoLMUB9llxnFrhDtdNMjZ1hs1il5J4&151214&160105; LHTturn=24; ptisp=ctc; RK=hRWyd82Gd8; pgv_pvi=7567882240; image_md5=bd21d5fb2f401b37cf3a02724dc06545; LTPturn=27; pt2gguin=o0583115900; uin=o0583115900; skey=@Mp9aCinaO; ptcz=10d4b1b7bde835d64663338a8008fd4f81e2c6b5f0ba81a90da3627ee617c7ee; pgv_info=ssid=s4768939310; pgv_pvid=6872592818; o_cookie=583115900; lv_play_index_textAd=47; lv_play_indexl.=32; dc_vplaying=1; LKBturn=29; Lturn=29; adid=583115900; appuser=95621BA8CB862E09; o_minduid=phhdxyNLkxBWMa74VTm5zU4y5EbUv5vR; appuser_95621BA8CB862E09_0=2b7gwp=1453219199_6&2btemv=1455551999_1&2c8311=1453305599_3&2cfx4j=1453651199_3&2cfx9l=1453651199_1&2d49y9=1453823999_2&2d67kl=1454255999_2&2d69mf=1454255999_3&2dxv8l=1455465599_6&2dzhfl=1452614399_1&f_pogvwp=1452095999_1&f_pogvwv=1452095999_2&f_pogw0m=1452095999_1&fd_15bm2t7=1452095999_1&fd_1h2pbsd=1452095999_2&fd_1k6so62=1452095999_1&fd_rhmjmq=1452095999_2&m_roiw0t=1452095999_3&m_xty8wl=1452095999_1&pogree=1452095999_2; TX.boid=100655474=1452072582_1&701041365=1452072585_1; appuser_95621BA8CB862E09_effect_0=fd_1ez2rcc=1452095999_1&fd_qdh7zw=1452095999_1&fd_ul215j=1452095999_1; psessionid=ca7f9c5b_1452071982_583115900_30754; psessiontime=1452071990",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: livep.l.qq.com\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36\r\nAccept: */*\r\nReferer: http://imgcache.qq.com/tencentvideo_v1/player/TPout.swf?max_age=86400&v=20140714\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\nCookie: flashuser=95621BA8CB862E09; piao_city=179; lv_irt_id=3628e1bbe25a6c941da9fac02ec2df8b; cm_cookie=V1,10017&-EP5mRruXhQarsCl5LD-2YzgjVTvyr2K&AQEBh7uoLMUB9lnaB5Tz9XdYnGIWflXmsDrU&150723&150723,10035&7t-tEmfJ076VAsM9&AQEBh7uoLMUB9lnc4tpW7vbazqdrRdBYOUCi&150724&150807,110054&ucO0Z0gctNn3&AQEBh7uoLMUB9llxMNl45F3RAIsKK0iMOJAG&150716&151008,10040&ACZ1r0A70NaEFcGT&AQEBh7uoLMUB9lmVgSoTwuuXZi896zSVsXIF&150818&151014,110015&1&AQEBh7uoLMUB9lkt2LUHO6ARwODHLI_Y51rj&150928&151103,10037&1433388364186289251984&AQEBh7uoLMUB9llIBencOqTAEh2aQ2SURSSQ&150909&151110,10011&jL40Z03uUFI0&AQEBh7uoLMUB9lkfw2sJVNx9g12Fzs12rPSN&150717&151125,10016&F64E6LFZs0W&AQEBh7uoLMUB9llE4yoPFNUykSj7WKaRK5lH&150805&151127,10019&WQAO-C1K9qI5OP8W_t2pSw&AQEBh7uoLMUB9llhpZE87GmOk3XGo_MJgV6K&150826&151130,10015&820490997316506147&AQEBh7uoLMUB9llXiynsGYRhMO3XuPnkuHUt&150715&151201,10012&x3X1yY6b&AQEBh7uoLMUB9ll9mraU_LJCDBYsE0Sbk_V9&151202&151202,110065&ucO0Z0gctNn3&AQEBh7uoLMUB9lkJcK3KDBQTKF0YfZ5wB7r5&150716&151203,110066&jL40Z03uUFI0&AQEBh7uoLMUB9lnyvKSYhcJD1X_rSs_DLVWx&150916&151221,10013&ePyYB2MSKa0TCbebpxKjmU&AQEBh7uoLMUB9ln6_6nGNidqml4nFKXhtE58&151221&151221,110061&d9cfa518d82abee&AQEBh7uoLMUB9llj2NYzmCjxaLWXALTcAGIH&150818&151224,10038&CAESEPZbUhToZJ39CS9MlgXGUSQ&AQEBh7uoLMUB9lmhnrDM5lIGtl6vc1NxMD6F&151110&151224,10077&820490997316506147&AQEBh7uoLMUB9lmkUdUe2xSHGkvM0IRu9Jt9&151214&151228,10008&0yPSvk92ie1nhB8wTUlTq&AQEBh7uoLMUB9lnL5ZCYvXJNvlv53G0CKEkj&150817&151228,10045&0&AQEBh7uoLMUB9llW3v1Vh7W72lv14RlAjUXn&151023&151228,110064&jL40Z03uUFI0&AQEBh7uoLMUB9lkBYuCUDLDrOcGURJcilogv&151016&160104,110069&26d49ecc&AQEBh7uoLMUB9lmlBLTxQY9BkCmimkMFqTo5&151204&160105,10079&B8hGto5y1e3uDXwCMsIun3rjk--dVCof&AQEBh7uoLMUB9llxnFrhDtdNMjZ1hs1il5J4&151214&160105; LHTturn=24; ptisp=ctc; RK=hRWyd82Gd8; pgv_pvi=7567882240; image_md5=bd21d5fb2f401b37cf3a02724dc06545; LTPturn=27; pt2gguin=o0583115900; uin=o0583115900; skey=@Mp9aCinaO; ptcz=10d4b1b7bde835d64663338a8008fd4f81e2c6b5f0ba81a90da3627ee617c7ee; pgv_info=ssid=s4768939310; pgv_pvid=6872592818; o_cookie=583115900; lv_play_index_textAd=47; lv_play_indexl.=32; dc_vplaying=1; LKBturn=29; Lturn=29; adid=583115900; appuser=95621BA8CB862E09; o_minduid=phhdxyNLkxBWMa74VTm5zU4y5EbUv5vR; appuser_95621BA8CB862E09_0=2b7gwp=1453219199_6&2btemv=1455551999_1&2c8311=1453305599_3&2cfx4j=1453651199_3&2cfx9l=1453651199_1&2d49y9=1453823999_2&2d67kl=1454255999_2&2d69mf=1454255999_3&2dxv8l=1455465599_6&2dzhfl=1452614399_1&f_pogvwp=1452095999_1&f_pogvwv=1452095999_2&f_pogw0m=1452095999_1&fd_15bm2t7=1452095999_1&fd_1h2pbsd=1452095999_2&fd_1k6so62=1452095999_1&fd_rhmjmq=1452095999_2&m_roiw0t=1452095999_3&m_xty8wl=1452095999_1&pogree=1452095999_2; TX.boid=100655474=1452072582_1&701041365=1452072585_1; appuser_95621BA8CB862E09_effect_0=fd_1ez2rcc=1452095999_1&fd_qdh7zw=1452095999_1&fd_ul215j=1452095999_1; psessionid=ca7f9c5b_1452071982_583115900_30754; psessiontime=1452071990\r\n\r\n"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_get_multi_trans.json b/test/decoders/http/benchmarks/json/http_get_multi_trans.json
index 917b1c7..8defd2e 100644
--- a/test/decoders/http/benchmarks/json/http_get_multi_trans.json
+++ b/test/decoders/http/benchmarks/json/http_get_multi_trans.json
@@ -18,7 +18,8 @@
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cookie": "Hm_lvt_1b8c1194303ef64e02f003f0cb8a1906=1653898514; _gcl_au=1.1.1010551181.1653898515; _ga=GA1.2.1419569885.1653898515; _gid=GA1.2.2007113907.1653898515; authtoken_pro=tea83b3beef07488bb8571811385db42; userId_pro=1160; pid_pro=1; eid_pro=1; pname_pro=name; Hm_lpvt_1b8c1194303ef64e02f003f0cb8a1906=1653961741; JSESSIONID=531AACA879469EDAB825E28113490E10",
- "__X_HTTP_URL": "test.pro.testin.cn/account/login.htm"
+ "__X_HTTP_URL": "test.pro.testin.cn/account/login.htm",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: test.pro.testin.cn\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: Hm_lvt_1b8c1194303ef64e02f003f0cb8a1906=1653898514; _gcl_au=1.1.1010551181.1653898515; _ga=GA1.2.1419569885.1653898515; _gid=GA1.2.2007113907.1653898515; authtoken_pro=tea83b3beef07488bb8571811385db42; userId_pro=1160; pid_pro=1; eid_pro=1; pname_pro=name; Hm_lpvt_1b8c1194303ef64e02f003f0cb8a1906=1653961741; JSESSIONID=531AACA879469EDAB825E28113490E10\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -32,10 +33,11 @@
"Content-Length": "0",
"Connection": "keep-alive",
"Set-Cookie": "JSESSIONID=CFAB9C0C3F4D9D6C2837E3BA9425AFCA; Path=/; HttpOnly",
- "Set-Cookie1": "authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
- "Set-Cookie2": "userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
+ "Set-Cookie.1": "authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
+ "Set-Cookie.2": "userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
"Location": "http://test.pro.testin.cn/enterprise/index.htm",
- "Content-Language": "zh-CN"
+ "Content-Language": "zh-CN",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx/1.16.1\r\nDate: Tue, 31 May 2022 06:41:23 GMT\r\nContent-Length: 0\r\nConnection: keep-alive\r\nSet-Cookie: JSESSIONID=CFAB9C0C3F4D9D6C2837E3BA9425AFCA; Path=/; HttpOnly\r\nSet-Cookie: authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nSet-Cookie: userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nLocation: http://test.pro.testin.cn/enterprise/index.htm\r\nContent-Language: zh-CN\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "request",
@@ -53,7 +55,8 @@
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cookie": "Hm_lvt_1b8c1194303ef64e02f003f0cb8a1906=1653898514; _gcl_au=1.1.1010551181.1653898515; _ga=GA1.2.1419569885.1653898515; _gid=GA1.2.2007113907.1653898515; authtoken_pro=tea83b3beef07488bb8571811385db42; userId_pro=1160; pid_pro=1; eid_pro=1; pname_pro=name; Hm_lpvt_1b8c1194303ef64e02f003f0cb8a1906=1653961741; JSESSIONID=CFAB9C0C3F4D9D6C2837E3BA9425AFCA",
- "__X_HTTP_URL": "test.pro.testin.cn/enterprise/index.htm"
+ "__X_HTTP_URL": "test.pro.testin.cn/enterprise/index.htm",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: test.pro.testin.cn\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: Hm_lvt_1b8c1194303ef64e02f003f0cb8a1906=1653898514; _gcl_au=1.1.1010551181.1653898515; _ga=GA1.2.1419569885.1653898515; _gid=GA1.2.2007113907.1653898515; authtoken_pro=tea83b3beef07488bb8571811385db42; userId_pro=1160; pid_pro=1; eid_pro=1; pname_pro=name; Hm_lpvt_1b8c1194303ef64e02f003f0cb8a1906=1653961741; JSESSIONID=CFAB9C0C3F4D9D6C2837E3BA9425AFCA\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -67,9 +70,10 @@
"Content-Length": "0",
"Connection": "keep-alive",
"Set-Cookie": "authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
- "Set-Cookie1": "userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
+ "Set-Cookie.1": "userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
"Location": "http://test.pro.testin.cn/enterprise/into.htm?eid=1",
- "Content-Language": "zh-CN"
+ "Content-Language": "zh-CN",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx/1.16.1\r\nDate: Tue, 31 May 2022 06:41:23 GMT\r\nContent-Length: 0\r\nConnection: keep-alive\r\nSet-Cookie: authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nSet-Cookie: userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nLocation: http://test.pro.testin.cn/enterprise/into.htm?eid=1\r\nContent-Language: zh-CN\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "request",
@@ -87,7 +91,8 @@
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cookie": "Hm_lvt_1b8c1194303ef64e02f003f0cb8a1906=1653898514; _gcl_au=1.1.1010551181.1653898515; _ga=GA1.2.1419569885.1653898515; _gid=GA1.2.2007113907.1653898515; authtoken_pro=tea83b3beef07488bb8571811385db42; userId_pro=1160; pid_pro=1; eid_pro=1; pname_pro=name; Hm_lpvt_1b8c1194303ef64e02f003f0cb8a1906=1653961741; JSESSIONID=CFAB9C0C3F4D9D6C2837E3BA9425AFCA",
- "__X_HTTP_URL": "test.pro.testin.cn/enterprise/into.htm?eid=1"
+ "__X_HTTP_URL": "test.pro.testin.cn/enterprise/into.htm?eid=1",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: test.pro.testin.cn\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: Hm_lvt_1b8c1194303ef64e02f003f0cb8a1906=1653898514; _gcl_au=1.1.1010551181.1653898515; _ga=GA1.2.1419569885.1653898515; _gid=GA1.2.2007113907.1653898515; authtoken_pro=tea83b3beef07488bb8571811385db42; userId_pro=1160; pid_pro=1; eid_pro=1; pname_pro=name; Hm_lpvt_1b8c1194303ef64e02f003f0cb8a1906=1653961741; JSESSIONID=CFAB9C0C3F4D9D6C2837E3BA9425AFCA\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -101,9 +106,10 @@
"Content-Length": "0",
"Connection": "keep-alive",
"Set-Cookie": "authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
- "Set-Cookie1": "userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
+ "Set-Cookie.1": "userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
"Location": "http://test.pro.testin.cn/realmachine/index.htm",
- "Content-Language": "zh-CN"
+ "Content-Language": "zh-CN",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx/1.16.1\r\nDate: Tue, 31 May 2022 06:41:23 GMT\r\nContent-Length: 0\r\nConnection: keep-alive\r\nSet-Cookie: authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nSet-Cookie: userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nLocation: http://test.pro.testin.cn/realmachine/index.htm\r\nContent-Language: zh-CN\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "request",
@@ -121,7 +127,8 @@
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cookie": "Hm_lvt_1b8c1194303ef64e02f003f0cb8a1906=1653898514; _gcl_au=1.1.1010551181.1653898515; _ga=GA1.2.1419569885.1653898515; _gid=GA1.2.2007113907.1653898515; authtoken_pro=tea83b3beef07488bb8571811385db42; userId_pro=1160; pid_pro=1; eid_pro=1; pname_pro=name; Hm_lpvt_1b8c1194303ef64e02f003f0cb8a1906=1653961741; JSESSIONID=CFAB9C0C3F4D9D6C2837E3BA9425AFCA",
- "__X_HTTP_URL": "test.pro.testin.cn/realmachine/index.htm"
+ "__X_HTTP_URL": "test.pro.testin.cn/realmachine/index.htm",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: test.pro.testin.cn\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: Hm_lvt_1b8c1194303ef64e02f003f0cb8a1906=1653898514; _gcl_au=1.1.1010551181.1653898515; _ga=GA1.2.1419569885.1653898515; _gid=GA1.2.2007113907.1653898515; authtoken_pro=tea83b3beef07488bb8571811385db42; userId_pro=1160; pid_pro=1; eid_pro=1; pname_pro=name; Hm_lpvt_1b8c1194303ef64e02f003f0cb8a1906=1653961741; JSESSIONID=CFAB9C0C3F4D9D6C2837E3BA9425AFCA\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -137,13 +144,13 @@
"Connection": "keep-alive",
"Vary": "Accept-Encoding",
"Set-Cookie": "authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
- "Set-Cookie1": "userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
- "Set-Cookie2": "pid_pro=1; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
- "Set-Cookie3": "eid_pro=1; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
- "Set-Cookie4": "pname_pro=name; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
+ "Set-Cookie.1": "userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
+ "Set-Cookie.2": "pid_pro=1; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
+ "Set-Cookie.3": "eid_pro=1; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
+ "Set-Cookie.4": "pname_pro=name; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly",
"Content-Language": "zh-CN",
"Content-Encoding": "gzip",
- "__X_HTTP_RAW_PAYLOAD_MD5": "5d761720e42f13d01ba981fb19b850ca",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "39cb5f3a9cbcfbd16f66e040ec49b8c4"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx/1.16.1\r\nDate: Tue, 31 May 2022 06:41:23 GMT\r\nContent-Type: text/html;charset=UTF-8\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\nVary: Accept-Encoding\r\nSet-Cookie: authtoken_pro=tea83b3beef07488bb8571811385db42; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nSet-Cookie: userId_pro=1160; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nSet-Cookie: pid_pro=1; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nSet-Cookie: eid_pro=1; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nSet-Cookie: pname_pro=name; Max-Age=28800; Expires=Tue, 31-May-2022 14:41:23 GMT; Domain=testin.cn; Path=/; HttpOnly\r\nContent-Language: zh-CN\r\nContent-Encoding: gzip\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "39cb5f3a9cbcfbd16f66e040ec49b8c4"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_get_req_pipeline.json b/test/decoders/http/benchmarks/json/http_get_req_pipeline.json
index af8ff75..d7668f3 100644
--- a/test/decoders/http/benchmarks/json/http_get_req_pipeline.json
+++ b/test/decoders/http/benchmarks/json/http_get_req_pipeline.json
@@ -16,7 +16,8 @@
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1636.2 Safari/537.36",
"Accept-Encoding": "gzip,deflate,sdch",
"Accept-Language": "zh-CN,zh;q=0.8",
- "__X_HTTP_URL": "113.31.27.226/aa.mp4?asf=sdaf"
+ "__X_HTTP_URL": "113.31.27.226/aa.mp4?asf=sdaf",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 113.31.27.226\r\nConnection: keep-alive\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1636.2 Safari/537.36\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "request",
@@ -32,7 +33,8 @@
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1636.2 Safari/537.36",
"Accept-Encoding": "gzip,deflate,sdch",
"Accept-Language": "zh-CN,zh;q=0.8",
- "__X_HTTP_URL": "ns.pb.cachecn.net/fetch_ldns.png"
+ "__X_HTTP_URL": "ns.pb.cachecn.net/fetch_ldns.png",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: ns.pb.cachecn.net\r\nConnection: keep-alive\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1636.2 Safari/537.36\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "request",
@@ -48,7 +50,8 @@
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1636.2 Safari/537.36",
"Accept-Encoding": "gzip,deflate,sdch",
"Accept-Language": "zh-CN,zh;q=0.8",
- "__X_HTTP_URL": "ns.pb.cachecn.net/40x.jpg"
+ "__X_HTTP_URL": "ns.pb.cachecn.net/40x.jpg",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: ns.pb.cachecn.net\r\nConnection: keep-alive\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1636.2 Safari/537.36\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -62,7 +65,7 @@
"Date": "Wed, 25 Oct 2023 06:43:35 GMT",
"Content-Type": "text/html",
"Connection": "close",
- "__X_HTTP_RAW_PAYLOAD_MD5": "6fb335f443cfc8a9d952d27cf3dc1059",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "6fb335f443cfc8a9d952d27cf3dc1059"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: SimpleHTTP/0.6 Python/2.7.5\r\nDate: Wed, 25 Oct 2023 06:43:35 GMT\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "6fb335f443cfc8a9d952d27cf3dc1059"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_get_single_trans.json b/test/decoders/http/benchmarks/json/http_get_single_trans.json
index 165bb65..9d7c3dd 100644
--- a/test/decoders/http/benchmarks/json/http_get_single_trans.json
+++ b/test/decoders/http/benchmarks/json/http_get_single_trans.json
@@ -13,7 +13,8 @@
"Host": "192.168.40.137",
"User-Agent": "curl/7.79.1",
"Accept": "*/*",
- "__X_HTTP_URL": "192.168.40.137/index.html"
+ "__X_HTTP_URL": "192.168.40.137/index.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 192.168.40.137\r\nUser-Agent: curl/7.79.1\r\nAccept: */*\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -28,7 +29,7 @@
"Content-type": "text/html",
"Content-Length": "144",
"Last-Modified": "Thu, 30 Nov 2023 08:38:54 GMT",
- "__X_HTTP_RAW_PAYLOAD_MD5": "3e11876cd3a234541ae37d833c088a76",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: SimpleHTTP/0.6 Python/2.7.5\r\nDate: Thu, 30 Nov 2023 08:42:24 GMT\r\nContent-type: text/html\r\nContent-Length: 144\r\nLast-Modified: Thu, 30 Nov 2023 08:38:54 GMT\r\n\r\n",
"__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "3e11876cd3a234541ae37d833c088a76"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_gzip_out_of_order.json b/test/decoders/http/benchmarks/json/http_gzip_out_of_order.json
index 1952b9d..5e084f2 100644
--- a/test/decoders/http/benchmarks/json/http_gzip_out_of_order.json
+++ b/test/decoders/http/benchmarks/json/http_gzip_out_of_order.json
@@ -18,7 +18,8 @@
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
- "__X_HTTP_URL": "192.168.40.139:8088/"
+ "__X_HTTP_URL": "192.168.40.139:8088/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 192.168.40.139:8088\r\nConnection: keep-alive\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -33,7 +34,7 @@
"Content-type": "text/html; charset=utf-8",
"Content-Encoding": "gzip",
"Content-length": "28425",
- "__X_HTTP_RAW_PAYLOAD_MD5": "873ed9c8c691a5f9f144fbf0fbfca011",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "7047cf4ae8ce6fd7bcd363e2b626f338"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: BaseHTTP/0.6 Python/3.6.8\r\nDate: Tue, 13 Aug 2024 14:21:42 GMT\r\nContent-type: text/html; charset=utf-8\r\nContent-Encoding: gzip\r\nContent-length: 28425\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "7047cf4ae8ce6fd7bcd363e2b626f338"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_hdrs_exceed_maximum.json b/test/decoders/http/benchmarks/json/http_hdrs_exceed_maximum.json
index 9bc751b..ee58111 100644
--- a/test/decoders/http/benchmarks/json/http_hdrs_exceed_maximum.json
+++ b/test/decoders/http/benchmarks/json/http_hdrs_exceed_maximum.json
@@ -1,51 +1,48 @@
-[
- {
- "__X_HTTP_TUPLE4": "10.0.0.1:61462-10.0.0.2:80-6-0"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "method": "GET",
- "uri": "/x/xx/xxxxxxxxxxxxxxxxxxx/x/xxxxxx/xxxxxxxxxxxxxxx?xxx=1&xxx=1&x=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&vmf=xxxxxxxxxx.xxx.xxx.xxx&ce=UTF-8&ns=xxxxxxxxxx&pageName=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&g=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jsp&r=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&events=xxxxxxxxxxxxxxxxxxxxxxxxxxx&products=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&v1=xxxxxxxxxxxxxxx&v2=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&v17=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&c49=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&AQE=1",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "xxxxx.xxxxxxxx.xxxxxxxxxx.xxx",
- "Connection": "keep-alive",
- "Accept": "image/webp,*/*;q=0.8",
- "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
- "Referer": "http://www.xxxxxxxxxx.xxx/xx/xxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxx.jsp",
- "Accept-Encoding": "gzip,deflate,sdch",
- "Accept-Language": "en-US,en;q=0.8,en-GB;q=0.6",
- "__X_HTTP_URL": "xxxxx.xxxxxxxx.xxxxxxxxxx.xxx/x/xx/xxxxxxxxxxxxxxxxxxx/x/xxxxxx/xxxxxxxxxxxxxxx?xxx=1&xxx=1&x=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&vmf=xxxxxxxxxx.xxx.xxx.xxx&ce=UTF-8&ns=xxxxxxxxxx&pageName=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&g=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jsp&r=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&events=xxxxxxxxxxxxxxxxxxxxxxxxxxx&products=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&v1=xxxxxxxxxxxxxxx&v2=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&v17=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&c49=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&AQE=1",
- "Cookie": "xxxxxxxxxxxxxxxxxxx=ie; xxxxxxxxxxxxxxxxxxxxxx=true; lp=xxxxxx; rememberUn=false; xxx.xxxxxxxxxx.xxxxxxxxxx=xx; xxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; autocomplete=1; xxxx=xxxx; xxxx=xxxxv1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; xxxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "res_version": "1.1",
- "res_status": "OK",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 200,
- "Date": "Mon, 30 Jun 2014 13:35:21 GMT",
- "Server": "xxxxxxxxxxxxxxxxx",
- "Access-Control-Allow-Origin": "*",
- "Set-Cookie": "xxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Expires=Wed, 29 Jun 2016 13:35:21 GMT; Domain=.xxxxxxxxxx.xxx; Path=/",
- "X-C": "ms-4.9",
- "Expires": "Sun, 29 Jun 2014 13:35:21 GMT",
- "Last-Modified": "Tue, 01 Jul 2014 13:35:21 GMT",
- "Cache-Control": "no-cache, no-store, max-age=0, no-transform, private",
- "Pragma": "no-cache",
- "ETag": "\"xxxxxxxxxxxxxxxxxxxxxx\"",
- "Vary": "*",
- "P3P": "policyref=\"/w3c/p3p.xml\", CP=\"NOI DSP COR NID PSA OUR IND COM NAV STA\"",
- "xserver": "xxxxxx",
- "Content-Length": "43",
- "Keep-Alive": "timeout=15",
- "Connection": "Keep-Alive",
- "Content-Type": "image/gif",
- "__X_HTTP_RAW_PAYLOAD_MD5": "ad480fd0732d0f6f1a8b06359e3a42bb",
+[{
+ "__X_HTTP_TUPLE4": "10.0.0.1:61462-10.0.0.2:80-6-0"
+ }, {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "GET",
+ "uri": "/x/xx/xxxxxxxxxxxxxxxxxxx/x/xxxxxx/xxxxxxxxxxxxxxx?xxx=1&xxx=1&x=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&vmf=xxxxxxxxxx.xxx.xxx.xxx&ce=UTF-8&ns=xxxxxxxxxx&pageName=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&g=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jsp&r=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&events=xxxxxxxxxxxxxxxxxxxxxxxxxxx&products=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&v1=xxxxxxxxxxxxxxx&v2=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&v17=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&c49=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&AQE=1",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "xxxxx.xxxxxxxx.xxxxxxxxxx.xxx",
+ "Connection": "keep-alive",
+ "Accept": "image/webp,*/*;q=0.8",
+ "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
+ "Referer": "http://www.xxxxxxxxxx.xxx/xx/xxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxx.jsp",
+ "Accept-Encoding": "gzip,deflate,sdch",
+ "Accept-Language": "en-US,en;q=0.8,en-GB;q=0.6",
+ "Cookie": "xxxxxxxxxxxxxxxxxxx=ie; xxxxxxxxxxxxxxxxxxxxxx=true; lp=xxxxxx; rememberUn=false; xxx.xxxxxxxxxx.xxxxxxxxxx=xx; xxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; autocomplete=1; xxxx=xxxx; xxxx=xxxxv1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; xxxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "__X_HTTP_URL": "xxxxx.xxxxxxxx.xxxxxxxxxx.xxx/x/xx/xxxxxxxxxxxxxxxxxxx/x/xxxxxx/xxxxxxxxxxxxxxx?xxx=1&xxx=1&x=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&vmf=xxxxxxxxxx.xxx.xxx.xxx&ce=UTF-8&ns=xxxxxxxxxx&pageName=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&g=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jsp&r=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&events=xxxxxxxxxxxxxxxxxxxxxxxxxxx&products=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&v1=xxxxxxxxxxxxxxx&v2=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&v17=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&c49=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&AQE=1",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: xxxxx.xxxxxxxx.xxxxxxxxxx.xxx\r\nConnection: keep-alive\r\nAccept: image/webp,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36\r\nReferer: http://www.xxxxxxxxxx.xxx/xx/xxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxx.jsp\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8,en-GB;q=0.6\r\nCookie: xxxxxxxxxxxxxxxxxxx=ie; xxxxxxxxxxxxxxxxxxxxxx=true; lp=xxxxxx; rememberUn=false; xxx.xxxxxxxxxx.xxxxxxxxxx=xx; xxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; autocomplete=1; xxxx=xxxx; xxxx=xxxxv1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; xxxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n\r\n"
+ }, {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.1",
+ "res_status": "OK",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 200,
+ "Date": "Mon, 30 Jun 2014 13:35:21 GMT",
+ "Server": "xxxxxxxxxxxxxxxxx",
+ "Access-Control-Allow-Origin": "*",
+ "Set-Cookie": "xxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Expires=Wed, 29 Jun 2016 13:35:21 GMT; Domain=.xxxxxxxxxx.xxx; Path=/",
+ "X-C": "ms-4.9",
+ "Expires": "Sun, 29 Jun 2014 13:35:21 GMT",
+ "Last-Modified": "Tue, 01 Jul 2014 13:35:21 GMT",
+ "Cache-Control": "no-cache, no-store, max-age=0, no-transform, private",
+ "Pragma": "no-cache",
+ "ETag": "\"xxxxxxxxxxxxxxxxxxxxxx\"",
+ "Vary": "*",
+ "P3P": "policyref=\"/w3c/p3p.xml\", CP=\"NOI DSP COR NID PSA OUR IND COM NAV STA\"",
+ "xserver": "xxxxxx",
+ "Content-Length": "43",
+ "Keep-Alive": "timeout=15",
+ "Connection": "Keep-Alive",
+ "Content-Type": "image/gif",
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Mon, 30 Jun 2014 13:35:21 GMT\r\nServer: xxxxxxxxxxxxxxxxx\r\nAccess-Control-Allow-Origin: *\r\nSet-Cookie: xxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Expires=Wed, 29 Jun 2016 13:35:21 GMT; Domain=.xxxxxxxxxx.xxx; Path=/\r\nX-C: ms-4.9\r\nExpires: Sun, 29 Jun 2014 13:35:21 GMT\r\nLast-Modified: Tue, 01 Jul 2014 13:35:21 GMT\r\nCache-Control: no-cache, no-store, max-age=0, no-transform, private\r\nPragma: no-cache\r\nETag: \"xxxxxxxxxxxxxxxxxxxxxx\"\r\nVary: *\r\nP3P: policyref=\"/w3c/p3p.xml\", CP=\"NOI DSP COR NID PSA OUR IND COM NAV STA\"\r\nxserver: xxxxxx\r\nContent-Length: 43\r\nKeep-Alive: timeout=15\r\nConnection: Keep-Alive\r\nContent-Type: image/gif\r\n\r\n",
"__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "ad480fd0732d0f6f1a8b06359e3a42bb"
- }
-] \ No newline at end of file
+ }]
diff --git a/test/decoders/http/benchmarks/json/http_incomplete_header.json b/test/decoders/http/benchmarks/json/http_incomplete_header.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_incomplete_header.json
@@ -0,0 +1 @@
+[]
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state.json b/test/decoders/http/benchmarks/json/http_msg_type_state.json
index 5dc0564..31cd5ac 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state.json
@@ -1,20 +1,16 @@
[
{
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
- "msg_1": "HTTP_MESSAGE_REQ_LINE",
- "msg_2": "HTTP_MESSAGE_REQ_HEADER",
- "msg_3": "HTTP_MESSAGE_REQ_HEADER_END",
- "msg_4": "HTTP_MESSAGE_REQ_BODY_START",
- "msg_5": "HTTP_MESSAGE_REQ_BODY",
- "msg_6": "HTTP_MESSAGE_REQ_BODY_END"
+ "msg_1": "HTTP_MESSAGE_REQ_LINE_HEADERS",
+ "msg_2": "HTTP_MESSAGE_REQ_BODY_START",
+ "msg_3": "HTTP_MESSAGE_REQ_BODY",
+ "msg_4": "HTTP_MESSAGE_REQ_BODY_END"
},
{
- "msg_7": "HTTP_MESSAGE_RES_LINE",
- "msg_8": "HTTP_MESSAGE_RES_HEADER",
- "msg_9": "HTTP_MESSAGE_RES_HEADER_END",
- "msg_10": "HTTP_MESSAGE_RES_BODY_START",
- "msg_11": "HTTP_MESSAGE_RES_BODY",
- "msg_12": "HTTP_MESSAGE_RES_BODY_END",
- "msg_13": "HTTP_TRANSACTION_END_transaction_0"
+ "msg_5": "HTTP_MESSAGE_RES_LINE_HEADERS",
+ "msg_6": "HTTP_MESSAGE_RES_BODY_START",
+ "msg_7": "HTTP_MESSAGE_RES_BODY",
+ "msg_8": "HTTP_MESSAGE_RES_BODY_END",
+ "msg_9": "HTTP_TRANSACTION_END_transaction_0"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state_c2s.json b/test/decoders/http/benchmarks/json/http_msg_type_state_c2s.json
index 8533bb9..15385ad 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state_c2s.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state_c2s.json
@@ -1,13 +1,11 @@
[
{
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
- "msg_1": "HTTP_MESSAGE_REQ_LINE",
- "msg_2": "HTTP_MESSAGE_REQ_HEADER",
- "msg_3": "HTTP_MESSAGE_REQ_HEADER_END",
- "msg_4": "HTTP_MESSAGE_REQ_BODY_START",
- "msg_5": "HTTP_MESSAGE_REQ_BODY",
- "msg_6": "HTTP_MESSAGE_REQ_BODY_END",
- "msg_7": "HTTP_TRANSACTION_END_transaction_0"
+ "msg_1": "HTTP_MESSAGE_REQ_LINE_HEADERS",
+ "msg_2": "HTTP_MESSAGE_REQ_BODY_START",
+ "msg_3": "HTTP_MESSAGE_REQ_BODY",
+ "msg_4": "HTTP_MESSAGE_REQ_BODY_END",
+ "msg_5": "HTTP_TRANSACTION_END_transaction_0"
},
{}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state_exception_c2s.json b/test/decoders/http/benchmarks/json/http_msg_type_state_exception_c2s.json
index e694238..c78cf34 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state_exception_c2s.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state_exception_c2s.json
@@ -1,13 +1,11 @@
[
{
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
- "msg_1": "HTTP_MESSAGE_REQ_LINE",
- "msg_2": "HTTP_MESSAGE_REQ_HEADER",
- "msg_3": "HTTP_MESSAGE_REQ_HEADER_END",
- "msg_4": "HTTP_MESSAGE_REQ_BODY_START",
- "msg_5": "HTTP_MESSAGE_REQ_BODY"
+ "msg_1": "HTTP_MESSAGE_REQ_LINE_HEADERS",
+ "msg_2": "HTTP_MESSAGE_REQ_BODY_START",
+ "msg_3": "HTTP_MESSAGE_REQ_BODY"
},
{
- "msg_6": "HTTP_TRANSACTION_END_transaction_0"
+ "msg_4": "HTTP_TRANSACTION_END_transaction_0"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state_exception_s2c.json b/test/decoders/http/benchmarks/json/http_msg_type_state_exception_s2c.json
index cf03270..a7c9865 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state_exception_s2c.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state_exception_s2c.json
@@ -1,16 +1,12 @@
[
{
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
- "msg_1": "HTTP_MESSAGE_REQ_LINE",
- "msg_2": "HTTP_MESSAGE_REQ_HEADER",
- "msg_3": "HTTP_MESSAGE_REQ_HEADER_END"
+ "msg_1": "HTTP_MESSAGE_REQ_LINE_HEADERS"
},
{
- "msg_4": "HTTP_MESSAGE_RES_LINE",
- "msg_5": "HTTP_MESSAGE_RES_HEADER",
- "msg_6": "HTTP_MESSAGE_RES_HEADER_END",
- "msg_7": "HTTP_MESSAGE_RES_BODY_START",
- "msg_8": "HTTP_MESSAGE_RES_BODY",
- "msg_9": "HTTP_TRANSACTION_END_transaction_0"
+ "msg_2": "HTTP_MESSAGE_RES_LINE_HEADERS",
+ "msg_3": "HTTP_MESSAGE_RES_BODY_START",
+ "msg_4": "HTTP_MESSAGE_RES_BODY",
+ "msg_5": "HTTP_TRANSACTION_END_transaction_0"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state_pipeline.json b/test/decoders/http/benchmarks/json/http_msg_type_state_pipeline.json
index d50f4ac..4028c0f 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state_pipeline.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state_pipeline.json
@@ -1,61 +1,45 @@
[
{
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
- "msg_1": "HTTP_MESSAGE_REQ_LINE",
- "msg_2": "HTTP_MESSAGE_REQ_HEADER",
- "msg_3": "HTTP_MESSAGE_REQ_HEADER_END",
- "msg_8": "HTTP_TRANSACTION_START_transaction_1",
- "msg_9": "HTTP_MESSAGE_REQ_LINE",
- "msg_10": "HTTP_MESSAGE_REQ_HEADER",
- "msg_11": "HTTP_MESSAGE_REQ_HEADER_END",
- "msg_16": "HTTP_TRANSACTION_START_transaction_2",
- "msg_17": "HTTP_MESSAGE_REQ_LINE",
- "msg_18": "HTTP_MESSAGE_REQ_HEADER",
- "msg_19": "HTTP_MESSAGE_REQ_HEADER_END",
- "msg_24": "HTTP_TRANSACTION_START_transaction_3",
- "msg_25": "HTTP_MESSAGE_REQ_LINE",
- "msg_26": "HTTP_MESSAGE_REQ_HEADER",
- "msg_27": "HTTP_MESSAGE_REQ_HEADER_END"
+ "msg_1": "HTTP_MESSAGE_REQ_LINE_HEADERS",
+ "msg_4": "HTTP_TRANSACTION_START_transaction_1",
+ "msg_5": "HTTP_MESSAGE_REQ_LINE_HEADERS",
+ "msg_8": "HTTP_TRANSACTION_START_transaction_2",
+ "msg_9": "HTTP_MESSAGE_REQ_LINE_HEADERS",
+ "msg_12": "HTTP_TRANSACTION_START_transaction_3",
+ "msg_13": "HTTP_MESSAGE_REQ_LINE_HEADERS"
},
{
- "msg_4": "HTTP_MESSAGE_RES_LINE",
- "msg_5": "HTTP_MESSAGE_RES_HEADER",
- "msg_6": "HTTP_MESSAGE_RES_HEADER_END",
- "msg_7": "HTTP_TRANSACTION_END_transaction_0",
- "msg_12": "HTTP_MESSAGE_RES_LINE",
- "msg_13": "HTTP_MESSAGE_RES_HEADER",
- "msg_14": "HTTP_MESSAGE_RES_HEADER_END",
- "msg_15": "HTTP_TRANSACTION_END_transaction_1",
- "msg_20": "HTTP_MESSAGE_RES_LINE",
- "msg_21": "HTTP_MESSAGE_RES_HEADER",
- "msg_22": "HTTP_MESSAGE_RES_HEADER_END",
- "msg_23": "HTTP_TRANSACTION_END_transaction_2",
- "msg_28": "HTTP_MESSAGE_RES_LINE",
- "msg_29": "HTTP_MESSAGE_RES_HEADER",
- "msg_30": "HTTP_MESSAGE_RES_HEADER_END",
- "msg_31": "HTTP_MESSAGE_RES_BODY_START",
+ "msg_2": "HTTP_MESSAGE_RES_LINE_HEADERS",
+ "msg_3": "HTTP_TRANSACTION_END_transaction_0",
+ "msg_6": "HTTP_MESSAGE_RES_LINE_HEADERS",
+ "msg_7": "HTTP_TRANSACTION_END_transaction_1",
+ "msg_10": "HTTP_MESSAGE_RES_LINE_HEADERS",
+ "msg_11": "HTTP_TRANSACTION_END_transaction_2",
+ "msg_14": "HTTP_MESSAGE_RES_LINE_HEADERS",
+ "msg_15": "HTTP_MESSAGE_RES_BODY_START",
+ "msg_16": "HTTP_MESSAGE_RES_BODY",
+ "msg_17": "HTTP_MESSAGE_RES_BODY",
+ "msg_18": "HTTP_MESSAGE_RES_BODY",
+ "msg_19": "HTTP_MESSAGE_RES_BODY",
+ "msg_20": "HTTP_MESSAGE_RES_BODY",
+ "msg_21": "HTTP_MESSAGE_RES_BODY",
+ "msg_22": "HTTP_MESSAGE_RES_BODY",
+ "msg_23": "HTTP_MESSAGE_RES_BODY",
+ "msg_24": "HTTP_MESSAGE_RES_BODY",
+ "msg_25": "HTTP_MESSAGE_RES_BODY",
+ "msg_26": "HTTP_MESSAGE_RES_BODY",
+ "msg_27": "HTTP_MESSAGE_RES_BODY",
+ "msg_28": "HTTP_MESSAGE_RES_BODY",
+ "msg_29": "HTTP_MESSAGE_RES_BODY",
+ "msg_30": "HTTP_MESSAGE_RES_BODY",
+ "msg_31": "HTTP_MESSAGE_RES_BODY",
"msg_32": "HTTP_MESSAGE_RES_BODY",
"msg_33": "HTTP_MESSAGE_RES_BODY",
"msg_34": "HTTP_MESSAGE_RES_BODY",
"msg_35": "HTTP_MESSAGE_RES_BODY",
"msg_36": "HTTP_MESSAGE_RES_BODY",
- "msg_37": "HTTP_MESSAGE_RES_BODY",
- "msg_38": "HTTP_MESSAGE_RES_BODY",
- "msg_39": "HTTP_MESSAGE_RES_BODY",
- "msg_40": "HTTP_MESSAGE_RES_BODY",
- "msg_41": "HTTP_MESSAGE_RES_BODY",
- "msg_42": "HTTP_MESSAGE_RES_BODY",
- "msg_43": "HTTP_MESSAGE_RES_BODY",
- "msg_44": "HTTP_MESSAGE_RES_BODY",
- "msg_45": "HTTP_MESSAGE_RES_BODY",
- "msg_46": "HTTP_MESSAGE_RES_BODY",
- "msg_47": "HTTP_MESSAGE_RES_BODY",
- "msg_48": "HTTP_MESSAGE_RES_BODY",
- "msg_49": "HTTP_MESSAGE_RES_BODY",
- "msg_50": "HTTP_MESSAGE_RES_BODY",
- "msg_51": "HTTP_MESSAGE_RES_BODY",
- "msg_52": "HTTP_MESSAGE_RES_BODY",
- "msg_53": "HTTP_MESSAGE_RES_BODY_END",
- "msg_54": "HTTP_TRANSACTION_END_transaction_3"
+ "msg_37": "HTTP_MESSAGE_RES_BODY_END",
+ "msg_38": "HTTP_TRANSACTION_END_transaction_3"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state_s2c.json b/test/decoders/http/benchmarks/json/http_msg_type_state_s2c.json
index c59d0bb..92f9df0 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state_s2c.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state_s2c.json
@@ -2,12 +2,10 @@
{},
{
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
- "msg_1": "HTTP_MESSAGE_RES_LINE",
- "msg_2": "HTTP_MESSAGE_RES_HEADER",
- "msg_3": "HTTP_MESSAGE_RES_HEADER_END",
- "msg_4": "HTTP_MESSAGE_RES_BODY_START",
- "msg_5": "HTTP_MESSAGE_RES_BODY",
- "msg_6": "HTTP_MESSAGE_RES_BODY_END",
- "msg_7": "HTTP_TRANSACTION_END_transaction_0"
+ "msg_1": "HTTP_MESSAGE_RES_LINE_HEADERS",
+ "msg_2": "HTTP_MESSAGE_RES_BODY_START",
+ "msg_3": "HTTP_MESSAGE_RES_BODY",
+ "msg_4": "HTTP_MESSAGE_RES_BODY_END",
+ "msg_5": "HTTP_TRANSACTION_END_transaction_0"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel.json b/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel.json
index 4a66f37..ad22440 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel.json
@@ -3,20 +3,16 @@
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
"msg_1": "HTTP_MESSAGE_REQ_LINE",
"msg_2": "HTTP_MESSAGE_REQ_HEADER",
- "msg_3": "HTTP_MESSAGE_REQ_HEADER_END",
"msg_8": "HTTP_TRANSACTION_START_transaction_1",
"msg_9": "HTTP_MESSAGE_REQ_LINE",
- "msg_10": "HTTP_MESSAGE_REQ_HEADER",
- "msg_11": "HTTP_MESSAGE_REQ_HEADER_END"
+ "msg_10": "HTTP_MESSAGE_REQ_HEADER"
},
{
"msg_4": "HTTP_MESSAGE_RES_LINE",
"msg_5": "HTTP_MESSAGE_RES_HEADER",
- "msg_6": "HTTP_MESSAGE_RES_HEADER_END",
"msg_7": "HTTP_TRANSACTION_END_transaction_0",
"msg_12": "HTTP_MESSAGE_RES_LINE",
"msg_13": "HTTP_MESSAGE_RES_HEADER",
- "msg_14": "HTTP_MESSAGE_RES_HEADER_END",
"msg_15": "HTTP_MESSAGE_RES_BODY",
"msg_16": "HTTP_MESSAGE_RES_BODY",
"msg_17": "HTTP_MESSAGE_RES_BODY",
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_c2s.json b/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_c2s.json
index 5b7e588..6f8857b 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_c2s.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_c2s.json
@@ -3,12 +3,10 @@
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
"msg_1": "HTTP_MESSAGE_REQ_LINE",
"msg_2": "HTTP_MESSAGE_REQ_HEADER",
- "msg_3": "HTTP_MESSAGE_REQ_HEADER_END",
"msg_4": "HTTP_TRANSACTION_END_transaction_0",
"msg_5": "HTTP_TRANSACTION_START_transaction_1",
"msg_6": "HTTP_MESSAGE_REQ_LINE",
"msg_7": "HTTP_MESSAGE_REQ_HEADER",
- "msg_8": "HTTP_MESSAGE_REQ_HEADER_END",
"msg_9": "HTTP_TRANSACTION_END_transaction_1"
},
{}
diff --git a/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_s2c.json b/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_s2c.json
index 07a1451..66704f1 100644
--- a/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_s2c.json
+++ b/test/decoders/http/benchmarks/json/http_msg_type_state_tunnel_s2c.json
@@ -4,12 +4,10 @@
"msg_0": "HTTP_TRANSACTION_START_transaction_0",
"msg_1": "HTTP_MESSAGE_RES_LINE",
"msg_2": "HTTP_MESSAGE_RES_HEADER",
- "msg_3": "HTTP_MESSAGE_RES_HEADER_END",
"msg_4": "HTTP_TRANSACTION_END_transaction_0",
"msg_5": "HTTP_TRANSACTION_START_transaction_1",
"msg_6": "HTTP_MESSAGE_RES_LINE",
"msg_7": "HTTP_MESSAGE_RES_HEADER",
- "msg_8": "HTTP_MESSAGE_RES_HEADER_END",
"msg_9": "HTTP_MESSAGE_RES_BODY",
"msg_10": "HTTP_MESSAGE_RES_BODY",
"msg_11": "HTTP_MESSAGE_RES_BODY",
diff --git a/test/decoders/http/benchmarks/json/http_multi_parse_error.json b/test/decoders/http/benchmarks/json/http_multi_parse_error.json
index c49d41e..d8d80cf 100644
--- a/test/decoders/http/benchmarks/json/http_multi_parse_error.json
+++ b/test/decoders/http/benchmarks/json/http_multi_parse_error.json
@@ -10,13 +10,14 @@
"req_version": "1.1",
"major_version": 1,
"minor_version": 1,
+ "Host": "",
"User-Agent": "ulxmlrpcpp/1.7.5",
"Connection": "Close",
"Content-Type": "text/xml",
"Date": "Sat Sep 7 10:05:13 2019",
"Content-Length": "468",
- "__X_HTTP_URL": ":4445/RPC2",
- "__X_HTTP_RAW_PAYLOAD_MD5": "6eccbcf261f04aabfa69884aa283f4f3",
+ "__X_HTTP_URL": "/:4445/RPC2",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: \r\nUser-Agent: ulxmlrpcpp/1.7.5\r\nConnection: Close\r\nContent-Type: text/xml\r\nDate: Sat Sep 7 10:05:13 2019\r\nContent-Length: 468\r\n\r\n",
"__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "6eccbcf261f04aabfa69884aa283f4f3"
},
{
@@ -31,8 +32,9 @@
"Content-Type": "text/xml",
"Transfer-Encoding": "chunked",
"X-Powered-By": "ulxmlrpcpp/1.7.4",
+ "Server": "",
"Date": "Sat Sep 7 01:09:24 2019",
- "__X_HTTP_RAW_PAYLOAD_MD5": "5cf8a4aa9a54e7f2d05b55ed05bf9071",
+ "__X_HTTP_HEADERS_INTERGRATION": "Connection: Close\r\nContent-Type: text/xml\r\nTransfer-Encoding: chunked\r\nX-Powered-By: ulxmlrpcpp/1.7.4\r\nServer: \r\nDate: Sat Sep 7 01:09:24 2019\r\n\r\n",
"__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "5cf8a4aa9a54e7f2d05b55ed05bf9071"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_no_content_length.json b/test/decoders/http/benchmarks/json/http_no_content_length.json
index 9310d04..e495a12 100644
--- a/test/decoders/http/benchmarks/json/http_no_content_length.json
+++ b/test/decoders/http/benchmarks/json/http_no_content_length.json
@@ -20,7 +20,8 @@
"Connection": "keep-alive",
"Referer": "http://www.xxxxxxxx.com/xxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxx.html",
"Cookie": "trafic_ranking=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
- "__X_HTTP_URL": "xxxxxxx.xxxxxx.xx/js/xxxxxx.js"
+ "__X_HTTP_URL": "xxxxxxx.xxxxxx.xx/js/xxxxxx.js",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: xxxxxxx.xxxxxx.xx\r\nUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\nAccept: */*\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip,deflate\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 115\r\nConnection: keep-alive\r\nReferer: http://www.xxxxxxxx.com/xxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxx.html\r\nCookie: trafic_ranking=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -40,7 +41,7 @@
"P3P": "policyref=\"/w3c/p3p.xml\", CP=\"ALL IND DSP COR ADM CONo CUR IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"",
"Set-Cookie": "trafic_ranking=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; expires=Sun, 11-Jan-2037 14:00:00 GMT; path=/; domain=.xxxxxx.xx",
"connection": "close",
- "__X_HTTP_RAW_PAYLOAD_MD5": "9fb54a2726ca3cf54a82804d0e66d08a",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "9fb54a2726ca3cf54a82804d0e66d08a"
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Mon, 10 May 2010 08:31:02 GMT\r\nServer: Apache\r\nContent-type: application/x-javascript\r\nExpires: Thu, 11 Jan 1973 16:00:00 GMT\r\nLast-Modified: Mon, 10 May 2010 08:31:02 GMT\r\nCache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\nPragma: no-cache\r\nP3P: policyref=\"/w3c/p3p.xml\", CP=\"ALL IND DSP COR ADM CONo CUR IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"\r\nSet-Cookie: trafic_ranking=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; expires=Sun, 11-Jan-2037 14:00:00 GMT; path=/; domain=.xxxxxx.xx\r\nconnection: close\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "9fb54a2726ca3cf54a82804d0e66d08a"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_no_cr_line_eof.json b/test/decoders/http/benchmarks/json/http_no_cr_line_eof.json
new file mode 100644
index 0000000..62e90a5
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_no_cr_line_eof.json
@@ -0,0 +1,18 @@
+[{
+ "__X_HTTP_TUPLE4": "172.15.10.65:62992-10.48.139.110:6969-6-0"
+}, {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "GET",
+ "uri": "/announce?info_hash=%8e%3e%16%be%a5c%f8%9bq%a4%9f%03b%f1%3f%9b%80%c1%2b0&peer_id=-LT1000-qooO5nKqTd*l&port=21881&uploaded=0&downloaded=0&left=381722&corrupt=0&key=B34AECB8&numwant=200&compact=1&no_peer_id=1&supportcrypto=1&redundant=0",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "10.48.139.110:6969",
+ "User-Agent": "gscbthlper/1.0.10.0",
+ "Accept-Encoding": "gzip",
+ "Connection": "close",
+ "__X_HTTP_URL": "10.48.139.110:6969/announce?info_hash=%8e%3e%16%be%a5c%f8%9bq%a4%9f%03b%f1%3f%9b%80%c1%2b0&peer_id=-LT1000-qooO5nKqTd*l&port=21881&uploaded=0&downloaded=0&left=381722&corrupt=0&key=B34AECB8&numwant=200&compact=1&no_peer_id=1&supportcrypto=1&redundant=0",
+ "__X_HTTP_DECODED_URL": "10.48.139.110:6969/announce?info_hash=>\u0016¾¥c򱤟\u0003b󿛀󿿫0&peer_id=-LT1000-qooO5nKqTd*l&port=21881&uploaded=0&downloaded=0&left=381722&corrupt=0&key=B34AECB8&numwant=200&compact=1&no_peer_id=1&supportcrypto=1&redundant=0",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 10.48.139.110:6969\r\nUser-Agent: gscbthlper/1.0.10.0\r\nAccept-Encoding: gzip\r\nConnection:close\r\n\r\n"
+}] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_out_of_order.json b/test/decoders/http/benchmarks/json/http_out_of_order.json
index 489b7c1..aeaade5 100644
--- a/test/decoders/http/benchmarks/json/http_out_of_order.json
+++ b/test/decoders/http/benchmarks/json/http_out_of_order.json
@@ -19,7 +19,8 @@
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Cookie": "_ga=GA1.2.1223391296.1710844147; _ga_CGYVD7S4G4=GS1.1.1711101500.1.1.1711101524.0.0.0; _gcl_au=1.1.45985360.1720059434; arialoadData=true; ariawapChangeViewPort=false; JSESSIONID=ZoFJbBlIeHCsA5414j6JC-vO6jvcBw7_xphcV3qerj5Q8htV6XH8!-1677015109",
- "__X_HTTP_URL": "www.airchina.com/cn/images/globesite/airchina.jpg"
+ "__X_HTTP_URL": "www.airchina.com/cn/images/globesite/airchina.jpg",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: www.airchina.com\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36\r\nDNT: 1\r\nAccept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8\r\nReferer: http://www.airchina.com/website/ip2.jsp?v=20230128\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nCookie: _ga=GA1.2.1223391296.1710844147; _ga_CGYVD7S4G4=GS1.1.1711101500.1.1.1711101524.0.0.0; _gcl_au=1.1.45985360.1720059434; arialoadData=true; ariawapChangeViewPort=false; JSESSIONID=ZoFJbBlIeHCsA5414j6JC-vO6jvcBw7_xphcV3qerj5Q8htV6XH8!-1677015109\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -38,7 +39,7 @@
"Keep-Alive": "timeout=120, max=1000",
"Connection": "Keep-Alive",
"Content-Type": "image/jpeg",
- "__X_HTTP_RAW_PAYLOAD_MD5": "c4c9d459415e922f877a2af6afd9d316",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "c4c9d459415e922f877a2af6afd9d316"
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Tue, 13 Aug 2024 01:48:28 GMT\r\nServer: Apache\r\nX-Frame-Options: SAMEORIGIN\r\nLast-Modified: Tue, 06 Aug 2019 02:10:09 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 67424\r\nKeep-Alive: timeout=120, max=1000\r\nConnection: Keep-Alive\r\nContent-Type: image/jpeg\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "c4c9d459415e922f877a2af6afd9d316"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_over_pppoe.json b/test/decoders/http/benchmarks/json/http_over_pppoe.json
index b4b4bfb..a6c9386 100644
--- a/test/decoders/http/benchmarks/json/http_over_pppoe.json
+++ b/test/decoders/http/benchmarks/json/http_over_pppoe.json
@@ -13,7 +13,8 @@
"User-Agent": "curl/7.34.0",
"Host": "ipv6.icanhazip.com",
"Accept": "*/*",
- "__X_HTTP_URL": "ipv6.icanhazip.com/"
+ "__X_HTTP_URL": "ipv6.icanhazip.com/",
+ "__X_HTTP_HEADERS_INTERGRATION": "User-Agent: curl/7.34.0\r\nHost: ipv6.icanhazip.com\r\nAccept: */*\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -30,7 +31,7 @@
"X-RTFM": "Learn about this site at http://bit.ly/14DAh2o and don't abuse the service",
"X-YOU-SHOULD-APPLY-FOR-A-JOB": "If you're reading this, apply here: http://rackertalent.com/",
"X-ICANHAZNODE": "icanhazip1.nugget",
- "__X_HTTP_RAW_PAYLOAD_MD5": "624520ac54235ac2284ed2dd2b17e1ad",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "624520ac54235ac2284ed2dd2b17e1ad"
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Thu, 02 Jan 2014 08:38:06 GMT\r\nServer: Apache\r\nContent-Length: 38\r\nContent-Type: text/plain; charset=UTF-8\r\nX-RTFM: Learn about this site at http://bit.ly/14DAh2o and don't abuse the service\r\nX-YOU-SHOULD-APPLY-FOR-A-JOB: If you're reading this, apply here: http://rackertalent.com/\r\nX-ICANHAZNODE: icanhazip1.nugget\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "624520ac54235ac2284ed2dd2b17e1ad"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_over_tcp_keepalive.json b/test/decoders/http/benchmarks/json/http_over_tcp_keepalive.json
index 2754249..669c865 100644
--- a/test/decoders/http/benchmarks/json/http_over_tcp_keepalive.json
+++ b/test/decoders/http/benchmarks/json/http_over_tcp_keepalive.json
@@ -19,7 +19,8 @@
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cookie": "UM_distinctid=17d37645f9c1a1-0281befa480414-b7a1a38-144000-17d37645f9d336; CNZZDATA1258295942=1778021578-1637307701-%7C1637307701; Hm_lvt_a6dc86f6e27435039966e994bd7f0792=1637311872; yumi_sid=JaMlFyTA07ikpZjTHZsRTWyGdMqFyFy%2B4hXGj%2FSoQRJYbrfBUQuOTIMZ8jUGmugDC594AYcbeRhg75xidhRxCW4zq9Y0gPwTmkhq4LQuprp4DrtDMLI3L5wLMqkG%2FuAX1aVFPfud5GRNxNFTSp%2Bos%2FKhfCFKhfN5%2BuT2xyVYSAjy2ftiSOGDi7FN13icuuyPhFCoWqOxWVu1CZ3AiYPJssv6kXqiR6paf75icdeROZY2bkFCDKkcIQcPy7o9EKpkL1Mbimeb40JMg9hUsWdmyhDkzVjSHJmC4z2ujpzSDTsjRIQOnxTy1PHZi%2FMwg3uyGLCusDwqbagpO4pcgEJ5ONDy%2BGwO7FmHXU3mFfR56c9HxxiiuLPnBt9ErpqqWKsxH6lUrlHaUp6AzyrgX7PFdksiMfPSk6%2F3%2FWOYr%2FkYuI4fopw7z8%2FLhxC9AiLr9Czz3MngFUGzkmaMVvAhZOSPzg%3D%3D; Hm_lpvt_a6dc86f6e27435039966e994bd7f0792=1637313847",
- "__X_HTTP_URL": "www.yumi.com/"
+ "__X_HTTP_URL": "www.yumi.com/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: www.yumi.com\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: UM_distinctid=17d37645f9c1a1-0281befa480414-b7a1a38-144000-17d37645f9d336; CNZZDATA1258295942=1778021578-1637307701-%7C1637307701; Hm_lvt_a6dc86f6e27435039966e994bd7f0792=1637311872; yumi_sid=JaMlFyTA07ikpZjTHZsRTWyGdMqFyFy%2B4hXGj%2FSoQRJYbrfBUQuOTIMZ8jUGmugDC594AYcbeRhg75xidhRxCW4zq9Y0gPwTmkhq4LQuprp4DrtDMLI3L5wLMqkG%2FuAX1aVFPfud5GRNxNFTSp%2Bos%2FKhfCFKhfN5%2BuT2xyVYSAjy2ftiSOGDi7FN13icuuyPhFCoWqOxWVu1CZ3AiYPJssv6kXqiR6paf75icdeROZY2bkFCDKkcIQcPy7o9EKpkL1Mbimeb40JMg9hUsWdmyhDkzVjSHJmC4z2ujpzSDTsjRIQOnxTy1PHZi%2FMwg3uyGLCusDwqbagpO4pcgEJ5ONDy%2BGwO7FmHXU3mFfR56c9HxxiiuLPnBt9ErpqqWKsxH6lUrlHaUp6AzyrgX7PFdksiMfPSk6%2F3%2FWOYr%2FkYuI4fopw7z8%2FLhxC9AiLr9Czz3MngFUGzkmaMVvAhZOSPzg%3D%3D; Hm_lpvt_a6dc86f6e27435039966e994bd7f0792=1637313847\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -39,7 +40,7 @@
"Pragma": "no-cache",
"Cache-Control": "no-store",
"Content-Encoding": "gzip",
- "__X_HTTP_RAW_PAYLOAD_MD5": "3f80dc84438b2f2d6b5e58084e31671c",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "af9b1a0118edd2920db355f9eee4ab75"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: Tengine\r\nDate: Fri, 19 Nov 2021 09:57:40 GMT\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\nVary: Accept-Encoding\r\nSet-Cookie: yumi_sid=V6EhlyovLp46BBzQWLVOBg%2F73RUD5E%2FfaRlkR8RLa8aKhGrPVdVHvHfFWRKKd9wZ%2BfFF4Tb2wnVOOn%2F9iXbBpyHsbxjmUqnbFSoAX7QIJjt%2BEEjAL3M7O7VSpAyMnrFKt7qu46oXV%2B6teyyTUY7Ucy285v6otvZcu8bN%2B5YxKZ1gYh56iJ0bHxnrnQ0vvAx3l%2BLwfw2y0c5IaF2tjrL%2Fn83nrHsPoYYRWAR2zLIXD%2FEMKRtyerwsM5LKhZZteFGWD2w%2B15alKF5T65i0lPvPcAdaqpceL5xz23twQULhs1tIJsOfJZ8JudLlRy6x3DvxQYqRe2xTCex5c77zJqfq%2FdryNbBycIq9gf6C2hXDRwDqRqVgXDMadwGnooKFkv%2ByCbohjHyBCZJypBcYFmglYhin23UC9i%2B%2BOA%2FxhlxcnU8kT8udpTNCktSmF950SQLOmvdvYuXGydKs8v05cxe5fg%3D%3D; expires=Fri, 19-Nov-2021 11:57:38 GMT; Max-Age=7200; path=/; domain=.yumi.com\r\nPragma: no-cache\r\nCache-Control: no-store\r\nContent-Encoding: gzip\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "af9b1a0118edd2920db355f9eee4ab75"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_pipeline_C2S.json b/test/decoders/http/benchmarks/json/http_pipeline_C2S.json
new file mode 100644
index 0000000..4143138
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_pipeline_C2S.json
@@ -0,0 +1,313 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "223.72.39.14:2545-192.168.182.147:80-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "GET",
+ "uri": "/postinfo.html",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/postinfo.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 1,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/author.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 2,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/author.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 3,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/dvwssr.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/dvwssr.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 4,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_adm/admin.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 5,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_adm/admin.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 6,
+ "method": "GET",
+ "uri": "/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 7,
+ "method": "GET",
+ "uri": "/postinfo.html",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/postinfo.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 8,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/author.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 9,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/author.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 10,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/dvwssr.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/dvwssr.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 11,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_adm/admin.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 12,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_adm/admin.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 13,
+ "method": "GET",
+ "uri": "/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 14,
+ "method": "GET",
+ "uri": "/_vti_bin/shtml.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/shtml.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 15,
+ "method": "GET",
+ "uri": "/_vti_bin/shtml.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/shtml.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 16,
+ "method": "GET",
+ "uri": "/_vti_pvt/_x_todo.htm",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/_x_todo.htm",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 17,
+ "method": "GET",
+ "uri": "/_vti_pvt/_x_todoh.htm",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/_x_todoh.htm",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 18,
+ "method": "GET",
+ "uri": "/_vti_pvt/access.cnf",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/access.cnf",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 19,
+ "method": "GET",
+ "uri": "/_vti_pvt/administrator.pwd",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/administrator.pwd",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 20,
+ "method": "GET",
+ "uri": "/_vti_pvt/administrators.pwd",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/administrators.pwd",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 21,
+ "method": "GET",
+ "uri": "/_vti_pvt/authors.pwd",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/authors.pwd",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ }
+] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_pipeline_S2C.json b/test/decoders/http/benchmarks/json/http_pipeline_S2C.json
new file mode 100644
index 0000000..13e29a3
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_pipeline_S2C.json
@@ -0,0 +1,181 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "223.72.39.14:2545-192.168.182.147:80-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:01 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:01 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "32dc0b2772bd73a952abba009291a399"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 1,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:02 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:02 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "db2ff8008149d8e70d8a2929acbb0f56"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 2,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:03 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:03 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "f5df152f7d8f34c630f298d2fcb46ed3"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 3,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:04 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:04 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "73e98ca7b62764869357b3e3c40dcd68"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 4,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:05 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:05 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "a5733c8989bde7f08506fa68c20f0c62"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 5,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:06 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:06 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "4bc0dde3722f76d60fef6f1d878cbb14"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 6,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:07 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:07 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "728dc2eafd49c9be8149add7c6aff207"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 7,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:08 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:08 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "0cde98e33181ee0ded49e8d0a3178d55"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 8,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:09 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:09 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d627268e0aba817d818b6e2b7e41aa11"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 9,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:10 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:10 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "e99d9829d50bd94b3497b91011f6e349"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 10,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:11 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "86",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:11 GMT\r\nContent-Type: text/html\r\nContent-Length: 86\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "599705569a418eac39192bd13b133a35"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_pipeline_header_splitting.json b/test/decoders/http/benchmarks/json/http_pipeline_header_splitting.json
index bebfa94..b5d24b8 100644
--- a/test/decoders/http/benchmarks/json/http_pipeline_header_splitting.json
+++ b/test/decoders/http/benchmarks/json/http_pipeline_header_splitting.json
@@ -1,69 +1,71 @@
[
- {
- "__X_HTTP_TUPLE4": "127.0.0.1:44980-127.0.0.1:8080-6-0"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "method": "GET",
- "uri": "/111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111.html",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "127.0.0.1:8080 ",
- "User-Agent": "curl/7.61.111",
- "Accept": "*/*",
- "-X-header1": "value111",
- "-X-header2": "value222",
- "-X-header3": "value333",
- "-X-header4": "value444",
- "-X-header5": "value5555",
- "__X_HTTP_URL": "127.0.0.1:8080 /111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111.html"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "res_version": "1.1",
- "res_status": "OK",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 200,
- "Server": "BaseHTTP/0.6 Python/3.6.88",
- "Date": "Sun, 01 Sep 2024 07:31:09 GMTT",
- "Content-length": "88",
- "__X_HTTP_RAW_PAYLOAD_MD5": "c396b63d897591e928fae959915e9ebc",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "c396b63d897591e928fae959915e9ebc"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 1,
- "method": "GET",
- "uri": "/2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222.html",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "127.0.0.1:8080",
- "User-Agent": "curl/7.61.1",
- "Accept": "*/*",
- "-X-header1": "value111",
- "-X-header2": "value2222",
- "-X-header3": "value3333",
- "-X-header4": "value4444",
- "-X-header5": "value55555",
- "__X_HTTP_URL": "127.0.0.1:8080/2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222.html"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 1,
- "res_version": "1.1",
- "res_status": "OK",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 200,
- "Server": "BaseHTTP/0.6 Python/3.6.88",
- "Date": "Sun, 01 Sep 2024 07:31:09 GMTT",
- "Content-length": "89",
- "__X_HTTP_RAW_PAYLOAD_MD5": "5e3c5a7de2696e52ef42d9ccfd8ce831",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "5e3c5a7de2696e52ef42d9ccfd8ce831"
- }
-] \ No newline at end of file
+ {
+ "__X_HTTP_TUPLE4": "127.0.0.1:44980-127.0.0.1:8080-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "GET",
+ "uri": "/111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111.html",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "127.0.0.1:8080 ",
+ "User-Agent": "curl/7.61.111",
+ "Accept": "*/*",
+ "-X-header1": "value111",
+ "-X-header2": "value222",
+ "-X-header3": "value333",
+ "-X-header4": "value444",
+ "-X-header5": "value5555",
+ "__X_HTTP_URL": "127.0.0.1:8080 /111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 127.0.0.1:8080 \r\nUser-Agent: curl/7.61.111\r\nAccept: */*\r\n-X-header1: value111\r\n-X-header2: value222\r\n-X-header3: value333\r\n-X-header4: value444\r\n-X-header5: value5555\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 1,
+ "method": "GET",
+ "uri": "/2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222.html",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "127.0.0.1:8080",
+ "User-Agent": "curl/7.61.1",
+ "Accept": "*/*",
+ "-X-header1": "value111",
+ "-X-header2": "value2222",
+ "-X-header3": "value3333",
+ "-X-header4": "value4444",
+ "-X-header5": "value55555",
+ "__X_HTTP_URL": "127.0.0.1:8080/2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 127.0.0.1:8080\r\nUser-Agent: curl/7.61.1\r\nAccept: */*\r\n-X-header1: value111\r\n-X-header2: value2222\r\n-X-header3: value3333\r\n-X-header4: value4444\r\n-X-header5: value55555\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.1",
+ "res_status": "OK",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 200,
+ "Server": "BaseHTTP/0.6 Python/3.6.88",
+ "Date": "Sun, 01 Sep 2024 07:31:09 GMTT",
+ "Content-length": "88",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: BaseHTTP/0.6 Python/3.6.88\r\nDate: Sun, 01 Sep 2024 07:31:09 GMTT\r\nContent-length:88\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "c396b63d897591e928fae959915e9ebc"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 1,
+ "res_version": "1.1",
+ "res_status": "OK",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 200,
+ "Server": "BaseHTTP/0.6 Python/3.6.88",
+ "Date": "Sun, 01 Sep 2024 07:31:09 GMTT",
+ "Content-length": "89",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: BaseHTTP/0.6 Python/3.6.88\r\nDate: Sun, 01 Sep 2024 07:31:09 GMTT\r\nContent-length:89\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "5e3c5a7de2696e52ef42d9ccfd8ce831"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_post.json b/test/decoders/http/benchmarks/json/http_post.json
new file mode 100644
index 0000000..cff5abc
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_post.json
@@ -0,0 +1,39 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "192.168.40.139:48662-107.155.25.121:80-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "POST",
+ "uri": "/",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "www.xiongan.gov.cn",
+ "User-Agent": "curl/7.61.1",
+ "Accept": "*/*",
+ "Content-Length": "22",
+ "Content-Type": "application/x-www-form-urlencoded",
+ "__X_HTTP_URL": "www.xiongan.gov.cn/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: www.xiongan.gov.cn\r\nUser-Agent: curl/7.61.1\r\nAccept: */*\r\nContent-Length: 22\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d065af995d50f24b4fb2865c765cf72a"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.1",
+ "res_status": "Method Not Allowed",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 405,
+ "Date": "Thu, 30 May 2024 10:53:44 GMT",
+ "Content-Type": "text/html",
+ "Transfer-Encoding": "chunked",
+ "Connection": "keep-alive",
+ "X-Ser": "BC9_dx-lt-yd-zhejiang-jinhua-5-cache-1, BC194_lt-obgp-fujian-xiamen-33-cache-1, BC68_SG-singapore-singapore-8-cache-2, BC121_HK-xianggang-xianggang-4-cache-3",
+ "X-Cache": "MISS from BC121_HK-xianggang-xianggang-4-cache-3(baishan)",
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Thu, 30 May 2024 10:53:44 GMT\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\nX-Ser: BC9_dx-lt-yd-zhejiang-jinhua-5-cache-1, BC194_lt-obgp-fujian-xiamen-33-cache-1, BC68_SG-singapore-singapore-8-cache-2, BC121_HK-xianggang-xianggang-4-cache-3\r\nX-Cache: MISS from BC121_HK-xianggang-xianggang-4-cache-3(baishan)\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "1858899995d46bf1ba568aa7f11761dc"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_post_c2s.json b/test/decoders/http/benchmarks/json/http_post_c2s.json
new file mode 100644
index 0000000..69e41de
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_post_c2s.json
@@ -0,0 +1,22 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "192.168.40.139:48662-107.155.25.121:80-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "POST",
+ "uri": "/",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "www.xiongan.gov.cn",
+ "User-Agent": "curl/7.61.1",
+ "Accept": "*/*",
+ "Content-Length": "22",
+ "Content-Type": "application/x-www-form-urlencoded",
+ "__X_HTTP_URL": "www.xiongan.gov.cn/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: www.xiongan.gov.cn\r\nUser-Agent: curl/7.61.1\r\nAccept: */*\r\nContent-Length: 22\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d065af995d50f24b4fb2865c765cf72a"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_post_multipart_form_data.json b/test/decoders/http/benchmarks/json/http_post_multipart_form_data.json
index ac524f6..71a8235 100644
--- a/test/decoders/http/benchmarks/json/http_post_multipart_form_data.json
+++ b/test/decoders/http/benchmarks/json/http_post_multipart_form_data.json
@@ -17,7 +17,8 @@
"Accept-Encoding": "gzip,deflate,sdch",
"Accept-Language": "zh-CN,zh;q=0.8",
"Cookie": "JSESSIONID=969AC5FBD069EE6218EB10513726B244; JSESSIONID=400CC78DF5784F303702CC7F02C6122C",
- "__X_HTTP_URL": "192.168.57.14:8080/fileupload/"
+ "__X_HTTP_URL": "192.168.57.14:8080/fileupload/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 192.168.57.14:8080\r\nConnection: keep-alive\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\nCookie: JSESSIONID=969AC5FBD069EE6218EB10513726B244; JSESSIONID=400CC78DF5784F303702CC7F02C6122C\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -31,7 +32,7 @@
"Content-Type": "text/html;charset=UTF-8",
"Content-Length": "468",
"Date": "Thu, 28 Mar 2019 08:13:33 GMT",
- "__X_HTTP_RAW_PAYLOAD_MD5": "2b8cd757ab5ffba85acac26c008a1ffc",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: Apache-Coyote/1.1\r\nContent-Type: text/html;charset=UTF-8\r\nContent-Length: 468\r\nDate: Thu, 28 Mar 2019 08:13:33 GMT\r\n\r\n",
"__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "2b8cd757ab5ffba85acac26c008a1ffc"
},
{
@@ -49,7 +50,8 @@
"Accept-Encoding": "gzip,deflate,sdch",
"Accept-Language": "zh-CN,zh;q=0.8",
"Cookie": "JSESSIONID=969AC5FBD069EE6218EB10513726B244; JSESSIONID=400CC78DF5784F303702CC7F02C6122C",
- "__X_HTTP_URL": "192.168.57.14:8080/fileupload/"
+ "__X_HTTP_URL": "192.168.57.14:8080/fileupload/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 192.168.57.14:8080\r\nConnection: keep-alive\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\nCookie: JSESSIONID=969AC5FBD069EE6218EB10513726B244; JSESSIONID=400CC78DF5784F303702CC7F02C6122C\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -63,7 +65,7 @@
"Content-Type": "text/html;charset=UTF-8",
"Content-Length": "468",
"Date": "Thu, 28 Mar 2019 08:13:33 GMT",
- "__X_HTTP_RAW_PAYLOAD_MD5": "2b8cd757ab5ffba85acac26c008a1ffc",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: Apache-Coyote/1.1\r\nContent-Type: text/html;charset=UTF-8\r\nContent-Length: 468\r\nDate: Thu, 28 Mar 2019 08:13:33 GMT\r\n\r\n",
"__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "2b8cd757ab5ffba85acac26c008a1ffc"
},
{
@@ -87,7 +89,7 @@
"Accept-Language": "zh-CN,zh;q=0.8",
"Cookie": "JSESSIONID=969AC5FBD069EE6218EB10513726B244; JSESSIONID=400CC78DF5784F303702CC7F02C6122C",
"__X_HTTP_URL": "192.168.57.14:8080/fileupload/servlet/UploadHandleServlet",
- "__X_HTTP_RAW_PAYLOAD_MD5": "550be33bf0ac01b6f7ac175bb8f4522a",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 192.168.57.14:8080\r\nConnection: keep-alive\r\nContent-Length: 449\r\nCache-Control: max-age=0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nOrigin: http://192.168.57.14:8080\r\nUser-Agent: Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36\r\nContent-Type: multipart/form-data; boundary=----WebKitFormBoundaryAe47vGj7ybAe6RwO\r\nReferer: http://192.168.57.14:8080/fileupload/\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\nCookie: JSESSIONID=969AC5FBD069EE6218EB10513726B244; JSESSIONID=400CC78DF5784F303702CC7F02C6122C\r\n\r\n",
"__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "550be33bf0ac01b6f7ac175bb8f4522a"
},
{
@@ -102,7 +104,7 @@
"Content-Type": "text/html;charset=UTF-8",
"Content-Length": "144",
"Date": "Thu, 28 Mar 2019 08:13:37 GMT",
- "__X_HTTP_RAW_PAYLOAD_MD5": "3fa07f3ec9f9fefed96e9886f80760bb",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: Apache-Coyote/1.1\r\nContent-Type: text/html;charset=UTF-8\r\nContent-Length: 144\r\nDate: Thu, 28 Mar 2019 08:13:37 GMT\r\n\r\n",
"__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "3fa07f3ec9f9fefed96e9886f80760bb"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_post_s2c.json b/test/decoders/http/benchmarks/json/http_post_s2c.json
new file mode 100644
index 0000000..f82f3a5
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_post_s2c.json
@@ -0,0 +1,22 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "192.168.40.139:48662-107.155.25.121:80-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.1",
+ "res_status": "Method Not Allowed",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 405,
+ "Date": "Thu, 30 May 2024 10:53:44 GMT",
+ "Content-Type": "text/html",
+ "Transfer-Encoding": "chunked",
+ "Connection": "keep-alive",
+ "X-Ser": "BC9_dx-lt-yd-zhejiang-jinhua-5-cache-1, BC194_lt-obgp-fujian-xiamen-33-cache-1, BC68_SG-singapore-singapore-8-cache-2, BC121_HK-xianggang-xianggang-4-cache-3",
+ "X-Cache": "MISS from BC121_HK-xianggang-xianggang-4-cache-3(baishan)",
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Thu, 30 May 2024 10:53:44 GMT\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\nX-Ser: BC9_dx-lt-yd-zhejiang-jinhua-5-cache-1, BC194_lt-obgp-fujian-xiamen-33-cache-1, BC68_SG-singapore-singapore-8-cache-2, BC121_HK-xianggang-xianggang-4-cache-3\r\nX-Cache: MISS from BC121_HK-xianggang-xianggang-4-cache-3(baishan)\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "1858899995d46bf1ba568aa7f11761dc"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_post_single_trans.json b/test/decoders/http/benchmarks/json/http_post_single_trans.json
index 823c310..e6c1bdf 100644
--- a/test/decoders/http/benchmarks/json/http_post_single_trans.json
+++ b/test/decoders/http/benchmarks/json/http_post_single_trans.json
@@ -1,38 +1,40 @@
[
- {
- "__X_HTTP_TUPLE4": "192.168.38.83.55186>192.168.40.139.8080"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "method": "POST",
- "uri": "/",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Content-Type": "application/json",
- "User-Agent": "PostmanRuntime/7.37.3",
- "Accept": "*/*",
- "Cache-Control": "no-cache",
- "Postman-Token": "71a004ad-901b-4461-ac3c-db9adb303c47",
- "Host": "192.168.40.139:8080",
- "Accept-Encoding": "gzip, deflate, br",
- "Connection": "keep-alive",
- "Content-Length": "26",
- "__X_HTTP_URL": "192.168.40.139:8080/",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "5ffe2871e6d5f6ee25ad7c1bfdd9f7b3"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "res_version": "1.0",
- "res_status": "OK",
- "major_version": 1,
- "minor_version": 0,
- "status_code": 200,
- "Server": "BaseHTTP/0.6 Python/3.6.8",
- "Date": "Mon, 08 Apr 2024 07:19:16 GMT",
- "Content-length": "84",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "cd8a54dd3e915946c4df262111e5aa05"
- }
-] \ No newline at end of file
+ {
+ "__X_HTTP_TUPLE4": "192.168.38.83:55186-192.168.40.139:8080-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "POST",
+ "uri": "/",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Content-Type": "application/json",
+ "User-Agent": "PostmanRuntime/7.37.3",
+ "Accept": "*/*",
+ "Cache-Control": "no-cache",
+ "Postman-Token": "71a004ad-901b-4461-ac3c-db9adb303c47",
+ "Host": "192.168.40.139:8080",
+ "Accept-Encoding": "gzip, deflate, br",
+ "Connection": "keep-alive",
+ "Content-Length": "26",
+ "__X_HTTP_URL": "192.168.40.139:8080/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Content-Type: application/json\r\nUser-Agent: PostmanRuntime/7.37.3\r\nAccept: */*\r\nCache-Control: no-cache\r\nPostman-Token: 71a004ad-901b-4461-ac3c-db9adb303c47\r\nHost: 192.168.40.139:8080\r\nAccept-Encoding: gzip, deflate, br\r\nConnection: keep-alive\r\nContent-Length: 26\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "5ffe2871e6d5f6ee25ad7c1bfdd9f7b3"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.0",
+ "res_status": "OK",
+ "major_version": 1,
+ "minor_version": 0,
+ "status_code": 200,
+ "Server": "BaseHTTP/0.6 Python/3.6.8",
+ "Date": "Mon, 08 Apr 2024 07:19:16 GMT",
+ "Content-length": "84",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: BaseHTTP/0.6 Python/3.6.8\r\nDate: Mon, 08 Apr 2024 07:19:16 GMT\r\nContent-length: 84\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "cd8a54dd3e915946c4df262111e5aa05"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_put_continue100.json b/test/decoders/http/benchmarks/json/http_put_continue100.json
new file mode 100644
index 0000000..eda56b9
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_put_continue100.json
@@ -0,0 +1,44 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "20.132.32.101:49732-10.254.0.2:10003-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.1",
+ "res_status": "Continue",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 100
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "PUT",
+ "uri": "/upload",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "10.254.0.2:10003",
+ "Accept": "*/*",
+ "Content-Length": "440",
+ "Expect": "100-continue",
+ "__X_HTTP_URL": "10.254.0.2:10003/upload",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 10.254.0.2:10003\r\nAccept: */*\r\nContent-Length: 440\r\nExpect: 100-continue\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "0f877bf24817b059d121a24e7c3e3c11"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 1,
+ "res_version": "1.1",
+ "res_status": "OK",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 200,
+ "Date": "Wed, 27 Jul 2022 02:07:52 GMT",
+ "Content-Length": "123",
+ "Content-Type": "text/xml; charset=utf-8",
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Wed, 27 Jul 2022 02:07:52 GMT\r\nContent-Length: 123\r\nContent-Type: text/xml; charset=utf-8\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "c387cb453dac1f48217edc338d891602"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_req_1byte_sliding_window.json b/test/decoders/http/benchmarks/json/http_req_1byte_sliding_window.json
index 13b360d..47b34e0 100644
--- a/test/decoders/http/benchmarks/json/http_req_1byte_sliding_window.json
+++ b/test/decoders/http/benchmarks/json/http_req_1byte_sliding_window.json
@@ -13,8 +13,9 @@
"User-Agent": "Wget/1.14 (linux-gnu)",
"Accept": "*/*",
"Host": "192.168.42.40",
+ "Connection": "Keep-Alive",
"__X_HTTP_URL": "192.168.42.40/index.html",
- "Connection": "Keep-Alive"
+ "__X_HTTP_HEADERS_INTERGRATION": "User-Agent: Wget/1.14 (linux-gnu)\r\nAccept: */*\r\nHost: 192.168.42.40\r\nConnection: Keep-Alive\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -29,7 +30,7 @@
"Content-type": "text/html",
"Content-Length": "144",
"Last-Modified": "Fri, 29 Dec 2023 08:50:53 GMT",
- "__X_HTTP_RAW_PAYLOAD_MD5": "3e11876cd3a234541ae37d833c088a76",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "3e11876cd3a234541ae37d833c088a76"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: SimpleHTTP/0.6 Python/2.7.5\r\nDate: Fri, 29 Dec 2023 09:11:12 GMT\r\nContent-type: text/html\r\nContent-Length: 144\r\nLast-Modified: Fri, 29 Dec 2023 08:50:53 GMT\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "3e11876cd3a234541ae37d833c088a76"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_res_1byte_sliding_window.json b/test/decoders/http/benchmarks/json/http_res_1byte_sliding_window.json
index f527839..bccbc7d 100644
--- a/test/decoders/http/benchmarks/json/http_res_1byte_sliding_window.json
+++ b/test/decoders/http/benchmarks/json/http_res_1byte_sliding_window.json
@@ -14,7 +14,8 @@
"Accept": "*/*",
"Host": "192.168.40.137",
"Connection": "Keep-Alive",
- "__X_HTTP_URL": "192.168.40.137/index.html"
+ "__X_HTTP_URL": "192.168.40.137/index.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "User-Agent: Wget/1.14 (linux-gnu)\r\nAccept: */*\r\nHost: 192.168.40.137\r\nConnection: Keep-Alive\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -29,7 +30,7 @@
"Content-type": "text/html",
"Content-Length": "144",
"Last-Modified": "Fri, 29 Dec 2023 08:50:53 GMT",
- "__X_HTTP_RAW_PAYLOAD_MD5": "3e11876cd3a234541ae37d833c088a76",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "3e11876cd3a234541ae37d833c088a76"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: SimpleHTTP/0.6 Python/2.7.5\r\nDate: Fri, 29 Dec 2023 09:32:21 GMT\r\nContent-type: text/html\r\nContent-Length: 144\r\nLast-Modified: Fri, 29 Dec 2023 08:50:53 GMT\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "3e11876cd3a234541ae37d833c088a76"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_res_gzip.json b/test/decoders/http/benchmarks/json/http_res_gzip.json
index 9d3e9c7..355c4b3 100644
--- a/test/decoders/http/benchmarks/json/http_res_gzip.json
+++ b/test/decoders/http/benchmarks/json/http_res_gzip.json
@@ -19,7 +19,8 @@
"Keep-Alive": "300",
"Connection": "keep-alive",
"Cookie": "FGNCLIID=05c04axp1yaqynldtcdiwis0ag1",
- "__X_HTTP_URL": "cerberus/test/ethereal.html"
+ "__X_HTTP_URL": "cerberus/test/ethereal.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: cerberus\r\nUser-Agent: Mozilla/5.0 (X11; U; Linux ppc; rv:1.7.3) Gecko/20041004 Firefox/0.10.1\r\nAccept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip,deflate\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 300\r\nConnection: keep-alive\r\nCookie: FGNCLIID=05c04axp1yaqynldtcdiwis0ag1\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -39,7 +40,7 @@
"Content-Length": "92",
"Connection": "close",
"Content-Type": "text/html; charset=UTF-8",
- "__X_HTTP_RAW_PAYLOAD_MD5": "dc2c0aff94148ca24acb516113a4d018",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "61b9e97f96045587bb55db781f7543ad"
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Fri, 29 Oct 2004 05:21:00 GMT\r\nServer: Apache/2.0.50 (Fedora)\r\nLast-Modified: Fri, 29 Oct 2004 05:20:21 GMT\r\nETag: \"126e1f-6d-371b2f40\"\r\nAccept-Ranges: bytes\r\nVary: Accept-Encoding\r\nContent-Encoding: gzip\r\nContent-Length: 92\r\nConnection: close\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "61b9e97f96045587bb55db781f7543ad"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_session_exception_c2s.json b/test/decoders/http/benchmarks/json/http_session_exception_c2s.json
new file mode 100644
index 0000000..5a0c0d9
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_session_exception_c2s.json
@@ -0,0 +1,26 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "192.168.38.83:55186-192.168.40.139:8080-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "POST",
+ "uri": "/",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Content-Type": "application/json",
+ "User-Agent": "PostmanRuntime/7.37.3",
+ "Accept": "*/*",
+ "Cache-Control": "no-cache",
+ "Postman-Token": "71a004ad-901b-4461-ac3c-db9adb303c47",
+ "Host": "192.168.40.139:8080",
+ "Accept-Encoding": "gzip, deflate, br",
+ "Connection": "keep-alive",
+ "Content-Length": "99",
+ "__X_HTTP_URL": "192.168.40.139:8080/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Content-Type: application/json\r\nUser-Agent: PostmanRuntime/7.37.3\r\nAccept: */*\r\nCache-Control: no-cache\r\nPostman-Token: 71a004ad-901b-4461-ac3c-db9adb303c47\r\nHost: 192.168.40.139:8080\r\nAccept-Encoding: gzip, deflate, br\r\nConnection: keep-alive\r\nContent-Length: 99\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "a69d01b43757e639dc2b015bafcacda9"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_session_exception_s2c.json b/test/decoders/http/benchmarks/json/http_session_exception_s2c.json
new file mode 100644
index 0000000..857071e
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_session_exception_s2c.json
@@ -0,0 +1,35 @@
+[
+ {
+ "__X_HTTP_TUPLE4": "192.168.38.73:50806-192.168.40.137:80-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "GET",
+ "uri": "/index.html",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "192.168.40.137",
+ "User-Agent": "curl/7.79.1",
+ "Accept": "*/*",
+ "__X_HTTP_URL": "192.168.40.137/index.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 192.168.40.137\r\nUser-Agent: curl/7.79.1\r\nAccept: */*\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.0",
+ "res_status": "OK",
+ "major_version": 1,
+ "minor_version": 0,
+ "status_code": 200,
+ "Server": "SimpleHTTP/0.6 Python/2.7.5",
+ "Date": "Thu, 30 Nov 2023 08:42:24 GMT",
+ "Content-type": "text/html",
+ "Content-Length": "999",
+ "Last-Modified": "Thu, 30 Nov 2023 08:38:54 GMT",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: SimpleHTTP/0.6 Python/2.7.5\r\nDate: Thu, 30 Nov 2023 08:42:24 GMT\r\nContent-type: text/html\r\nContent-Length: 999\r\nLast-Modified: Thu, 30 Nov 2023 08:38:54 GMT\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "f31e3caabfd0f38ed179b6ad262d857e"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_trans_pipeline.json b/test/decoders/http/benchmarks/json/http_trans_pipeline.json
index 4bd0879..f803a7a 100644
--- a/test/decoders/http/benchmarks/json/http_trans_pipeline.json
+++ b/test/decoders/http/benchmarks/json/http_trans_pipeline.json
@@ -1,389 +1,503 @@
[
- {
- "__X_HTTP_TUPLE4": "223.72.39.14:2545-192.168.182.147:80-6-0"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "method": "GET",
- "uri": "/postinfo.html",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/postinfo.html"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 1,
- "method": "GET",
- "uri": "/_vti_bin/_vti_aut/author.dll",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.dll"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 2,
- "method": "GET",
- "uri": "/_vti_bin/_vti_aut/author.exe",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.exe"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 3,
- "method": "GET",
- "uri": "/_vti_bin/_vti_aut/dvwssr.dll",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/dvwssr.dll"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 4,
- "method": "GET",
- "uri": "/_vti_bin/_vti_adm/admin.dll",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.dll"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 5,
- "method": "GET",
- "uri": "/_vti_bin/_vti_adm/admin.exe",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.exe"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 6,
- "method": "GET",
- "uri": "/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_bin/fpcount.exe?Page=default.asp|Image=3"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:01 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "32dc0b2772bd73a952abba009291a399",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "32dc0b2772bd73a952abba009291a399"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 1,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:02 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "db2ff8008149d8e70d8a2929acbb0f56",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "db2ff8008149d8e70d8a2929acbb0f56"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 2,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:03 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "f5df152f7d8f34c630f298d2fcb46ed3",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "f5df152f7d8f34c630f298d2fcb46ed3"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 3,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:04 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "73e98ca7b62764869357b3e3c40dcd68",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "73e98ca7b62764869357b3e3c40dcd68"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 4,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:05 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "a5733c8989bde7f08506fa68c20f0c62",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "a5733c8989bde7f08506fa68c20f0c62"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 7,
- "method": "GET",
- "uri": "/_vti_bin/shtml.dll",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "__X_HTTP_URL": "116.181.2.152/_vti_bin/shtml.dll",
- "Connection": "keep-alive"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 8,
- "method": "GET",
- "uri": "/_vti_bin/shtml.exe",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_bin/shtml.exe"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 9,
- "method": "GET",
- "uri": "/_vti_pvt/_x_todo.htm",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_pvt/_x_todo.htm"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 10,
- "method": "GET",
- "uri": "/_vti_pvt/_x_todoh.htm",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_pvt/_x_todoh.htm"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 11,
- "method": "GET",
- "uri": "/_vti_pvt/access.cnf",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_pvt/access.cnf"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 12,
- "method": "GET",
- "uri": "/_vti_pvt/administrator.pwd",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_pvt/administrator.pwd"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 13,
- "method": "GET",
- "uri": "/_vti_pvt/administrators.pwd",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_pvt/administrators.pwd"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 14,
- "method": "GET",
- "uri": "/_vti_pvt/authors.pwd",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_pvt/authors.pwd"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 5,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:06 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "4bc0dde3722f76d60fef6f1d878cbb14",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "4bc0dde3722f76d60fef6f1d878cbb14"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 6,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:07 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "728dc2eafd49c9be8149add7c6aff207",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "728dc2eafd49c9be8149add7c6aff207"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 7,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:08 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "0cde98e33181ee0ded49e8d0a3178d55",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "0cde98e33181ee0ded49e8d0a3178d55"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 8,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:09 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "d627268e0aba817d818b6e2b7e41aa11",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d627268e0aba817d818b6e2b7e41aa11"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 9,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:10 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "e99d9829d50bd94b3497b91011f6e349",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "e99d9829d50bd94b3497b91011f6e349"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 15,
- "method": "GET",
- "uri": "/_vti_pvt/bots.cnf",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1,
- "Host": "116.181.2.152",
- "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
- "Connection": "keep-alive",
- "__X_HTTP_URL": "116.181.2.152/_vti_pvt/bots.cnf"
- },
- {
- "__X_HTTP_TRANSACTION": "response",
- "__X_HTTP_TRANSACTION_SEQ": 10,
- "res_version": "1.1",
- "res_status": "Not Found",
- "major_version": 1,
- "minor_version": 1,
- "status_code": 404,
- "Server": "nginx",
- "Date": "Thu, 29 Oct 2020 09:59:11 GMT",
- "Content-Type": "text/html",
- "Content-Length": "146",
- "Connection": "keep-alive",
- "__X_HTTP_RAW_PAYLOAD_MD5": "99a813d29c5da4e6f7269be4c1a31c8e",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "99a813d29c5da4e6f7269be4c1a31c8e"
- }
-] \ No newline at end of file
+ {
+ "__X_HTTP_TUPLE4": "223.72.39.14:2545-192.168.182.147:80-6-0"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "method": "GET",
+ "uri": "/postinfo.html",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/postinfo.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 1,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/author.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 2,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/author.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 3,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/dvwssr.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/dvwssr.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 4,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_adm/admin.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 5,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_adm/admin.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 6,
+ "method": "GET",
+ "uri": "/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 0,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:01 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:01 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "32dc0b2772bd73a952abba009291a399"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 1,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:02 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:02 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "db2ff8008149d8e70d8a2929acbb0f56"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 2,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:03 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:03 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "f5df152f7d8f34c630f298d2fcb46ed3"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 3,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:04 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:04 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "73e98ca7b62764869357b3e3c40dcd68"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 4,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:05 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:05 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "a5733c8989bde7f08506fa68c20f0c62"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 7,
+ "method": "GET",
+ "uri": "/postinfo.html",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/postinfo.html",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 8,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/author.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 9,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/author.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/author.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 10,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_aut/dvwssr.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_aut/dvwssr.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 11,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_adm/admin.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 12,
+ "method": "GET",
+ "uri": "/_vti_bin/_vti_adm/admin.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/_vti_adm/admin.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 13,
+ "method": "GET",
+ "uri": "/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/fpcount.exe?Page=default.asp|Image=3",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 14,
+ "method": "GET",
+ "uri": "/_vti_bin/shtml.dll",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/shtml.dll",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 15,
+ "method": "GET",
+ "uri": "/_vti_bin/shtml.exe",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_bin/shtml.exe",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 16,
+ "method": "GET",
+ "uri": "/_vti_pvt/_x_todo.htm",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/_x_todo.htm",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 17,
+ "method": "GET",
+ "uri": "/_vti_pvt/_x_todoh.htm",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/_x_todoh.htm",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 18,
+ "method": "GET",
+ "uri": "/_vti_pvt/access.cnf",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/access.cnf",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 19,
+ "method": "GET",
+ "uri": "/_vti_pvt/administrator.pwd",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/administrator.pwd",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 20,
+ "method": "GET",
+ "uri": "/_vti_pvt/administrators.pwd",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/administrators.pwd",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 21,
+ "method": "GET",
+ "uri": "/_vti_pvt/authors.pwd",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/authors.pwd",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "request",
+ "__X_HTTP_TRANSACTION_SEQ": 22,
+ "method": "GET",
+ "uri": "/_vti_pvt/bots.cnf",
+ "req_version": "1.1",
+ "major_version": 1,
+ "minor_version": 1,
+ "Host": "116.181.2.152",
+ "User-Agent": "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)",
+ "Connection": "keep-alive",
+ "__X_HTTP_URL": "116.181.2.152/_vti_pvt/bots.cnf",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 116.181.2.152\r\nUser-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)\r\nConnection: keep-alive\r\n\r\n"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 5,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:06 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:06 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "4bc0dde3722f76d60fef6f1d878cbb14"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 6,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:07 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:07 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "728dc2eafd49c9be8149add7c6aff207"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 7,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:08 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:08 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "0cde98e33181ee0ded49e8d0a3178d55"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 8,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:09 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:09 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d627268e0aba817d818b6e2b7e41aa11"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 9,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:10 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:10 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "e99d9829d50bd94b3497b91011f6e349"
+ },
+ {
+ "__X_HTTP_TRANSACTION": "response",
+ "__X_HTTP_TRANSACTION_SEQ": 10,
+ "res_version": "1.1",
+ "res_status": "Not Found",
+ "major_version": 1,
+ "minor_version": 1,
+ "status_code": 404,
+ "Server": "nginx",
+ "Date": "Thu, 29 Oct 2020 09:59:11 GMT",
+ "Content-Type": "text/html",
+ "Content-Length": "146",
+ "Connection": "keep-alive",
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: nginx\r\nDate: Thu, 29 Oct 2020 09:59:11 GMT\r\nContent-Type: text/html\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "99a813d29c5da4e6f7269be4c1a31c8e"
+ }
+]
diff --git a/test/decoders/http/benchmarks/json/http_upgrade_websocket.json b/test/decoders/http/benchmarks/json/http_upgrade_websocket.json
index 6a7dfc3..05ae445 100644
--- a/test/decoders/http/benchmarks/json/http_upgrade_websocket.json
+++ b/test/decoders/http/benchmarks/json/http_upgrade_websocket.json
@@ -23,7 +23,8 @@
"Cookie": "s_cc=true; s_sq=%5B%5BB%5D%5D; iwe_user_noticecount_urn%3amace%3aucla.edu%3appid%3aperson%3a1223EF7211FC4EC1965579D0B8D85FBA=2; __utma=125574670.1759122974.1407127284.1407127284.1415755402.2; __utmc=125574670; __utma=126236063.2139843507.1390525421.1433785187.1435706244.46; __utmc=126236063; __utmz=126236063.1427934389.33.5.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); _ucla_sso=2015-07-02T11%3A34%3A30-07%3A00; _ga=GA1.2.1759122974.1407127284",
"Sec-WebSocket-Key": "sgD1adxQ3mk6BbBqab7owA==",
"Sec-WebSocket-Extensions": "permessage-deflate; client_max_window_bits",
- "__X_HTTP_URL": "spurs.cs.ucla.edu:9696/"
+ "__X_HTTP_URL": "spurs.cs.ucla.edu:9696/",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: spurs.cs.ucla.edu:9696\r\nConnection: Upgrade\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\nOrigin: null\r\nSec-WebSocket-Version: 13\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-US,en;q=0.8,lv;q=0.6,ru;q=0.4\r\nCookie: s_cc=true; s_sq=%5B%5BB%5D%5D; iwe_user_noticecount_urn%3amace%3aucla.edu%3appid%3aperson%3a1223EF7211FC4EC1965579D0B8D85FBA=2; __utma=125574670.1759122974.1407127284.1407127284.1415755402.2; __utmc=125574670; __utma=126236063.2139843507.1390525421.1433785187.1435706244.46; __utmc=126236063; __utmz=126236063.1427934389.33.5.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); _ucla_sso=2015-07-02T11%3A34%3A30-07%3A00; _ga=GA1.2.1759122974.1407127284\r\nSec-WebSocket-Key: sgD1adxQ3mk6BbBqab7owA==\r\nSec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -36,6 +37,7 @@
"Connection": "upgrade",
"Sec-WebSocket-Accept": "FRh9fmH0UaoLdY5BSFO4hP2Pcjw=",
"Server": "WebSocket++/0.5.1",
- "Upgrade": "websocket"
+ "Upgrade": "websocket",
+ "__X_HTTP_HEADERS_INTERGRATION": "Connection: upgrade\r\nSec-WebSocket-Accept: FRh9fmH0UaoLdY5BSFO4hP2Pcjw=\r\nServer: WebSocket++/0.5.1\r\nUpgrade: websocket\r\n\r\n"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_url_test_with_host.json b/test/decoders/http/benchmarks/json/http_url_test_with_host.json
index ab91ded..59f98cc 100644
--- a/test/decoders/http/benchmarks/json/http_url_test_with_host.json
+++ b/test/decoders/http/benchmarks/json/http_url_test_with_host.json
@@ -1,6 +1,6 @@
[
{
- "__X_HTTP_TUPLE4": "192.168.244.1.52412>192.168.244.128.8080"
+ "__X_HTTP_TUPLE4": "192.168.244.1:52412-192.168.244.128:8080-6-0"
},
{
"__X_HTTP_TRANSACTION": "request",
@@ -17,7 +17,8 @@
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
- "__X_HTTP_URL": "192.168.244.128:8080/urltest/ttt"
+ "__X_HTTP_URL": "192.168.244.128:8080/urltest/ttt",
+ "__X_HTTP_HEADERS_INTERGRATION": "Host: 192.168.244.128:8080\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -30,6 +31,7 @@
"Server": "BaseHTTP/0.6 Python/3.6.8",
"Date": "Thu, 14 Mar 2024 07:37:43 GMT",
"Content-type": "application/json",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "49dfdd54b01cbcd2d2ab5e9e5ee6b9b9"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: BaseHTTP/0.6 Python/3.6.8\r\nDate: Thu, 14 Mar 2024 07:37:43 GMT\r\nContent-type: application/json\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "49dfdd54b01cbcd2d2ab5e9e5ee6b9b9"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_url_test_without_host.json b/test/decoders/http/benchmarks/json/http_url_test_without_host.json
index 09427a7..3fc4621 100644
--- a/test/decoders/http/benchmarks/json/http_url_test_without_host.json
+++ b/test/decoders/http/benchmarks/json/http_url_test_without_host.json
@@ -11,7 +11,8 @@
"major_version": 1,
"minor_version": 1,
"User-Agent": "no h",
- "__X_HTTP_URL": "192.168.244.128:8080/urltest/ttt"
+ "__X_HTTP_URL": "192.168.244.128:8080/urltest/ttt",
+ "__X_HTTP_HEADERS_INTERGRATION": "User-Agent: no h\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -24,7 +25,7 @@
"Server": "BaseHTTP/0.6 Python/3.6.8",
"Date": "Thu, 14 Mar 2024 06:15:20 GMT",
"Content-type": "application/json",
- "__X_HTTP_RAW_PAYLOAD_MD5": "49dfdd54b01cbcd2d2ab5e9e5ee6b9b9",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "49dfdd54b01cbcd2d2ab5e9e5ee6b9b9"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: BaseHTTP/0.6 Python/3.6.8\r\nDate: Thu, 14 Mar 2024 06:15:20 GMT\r\nContent-type: application/json\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "49dfdd54b01cbcd2d2ab5e9e5ee6b9b9"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_url_test_without_host_v6.json b/test/decoders/http/benchmarks/json/http_url_test_without_host_v6.json
index 2bc3934..7af1493 100644
--- a/test/decoders/http/benchmarks/json/http_url_test_without_host_v6.json
+++ b/test/decoders/http/benchmarks/json/http_url_test_without_host_v6.json
@@ -19,7 +19,8 @@
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"If-Modified-Since": "Mon, 05 Aug 2024 00:26:26 GMT",
- "__X_HTTP_URL": "2408:8722:840:f8::83:80/dist/aria.js?appid=1cea560ed256bea7ae52761bd9042164"
+ "__X_HTTP_URL": "2408:8722:840:f8::83:80/dist/aria.js?appid=1cea560ed256bea7ae52761bd9042164",
+ "__X_HTTP_HEADERS_INTERGRATION": "_HOT: ent.govwza.cn\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36\r\nDNT: 1\r\nAccept: */*\r\nReferer: http://www.airchina.com/\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nIf-Modified-Since: Mon, 05 Aug 2024 00:26:26 GMT\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -37,6 +38,7 @@
"Connection": "close",
"X-Cache-Lookup": "Cache Hit",
"Access-Control-Allow-Origin": "*",
- "Cache-Control": "max-age=86400"
+ "Cache-Control": "max-age=86400",
+ "__X_HTTP_HEADERS_INTERGRATION": "Date: Mon, 05 Aug 2024 07:51:04 GMT\r\nContent-Type: application/javascript;charset=UTF-8\r\nVary: origin,access-control-request-method,access-control-request-headers,accept-encoding\r\nServer: SLT-MID\r\nX-NWS-LOG-UUID: 1242198743243161630\r\nConnection: close\r\nX-Cache-Lookup: Cache Hit\r\nAccess-Control-Allow-Origin: *\r\nCache-Control: max-age=86400\r\n\r\n"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/json/http_whitespace_before_header.json b/test/decoders/http/benchmarks/json/http_whitespace_before_header.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/test/decoders/http/benchmarks/json/http_whitespace_before_header.json
@@ -0,0 +1 @@
+[]
diff --git a/test/decoders/http/benchmarks/json/http_zlib_deadlock.json b/test/decoders/http/benchmarks/json/http_zlib_deadlock.json
index 0ea9b7f..425dab5 100644
--- a/test/decoders/http/benchmarks/json/http_zlib_deadlock.json
+++ b/test/decoders/http/benchmarks/json/http_zlib_deadlock.json
@@ -17,7 +17,8 @@
"Host": "xmc.ximalaya.com",
"Connection": "Keep-Alive",
"Accept-Encoding": "gzip",
- "__X_HTTP_URL": "xmc.ximalaya.com/xmlymain-login-web/login/ts-1657244122966?appId=mainApp&appStatus=2&clientType=android&isFirstReq=false&lastSuccessIp=180.153.250.247:3814&userId=175776850"
+ "__X_HTTP_URL": "xmc.ximalaya.com/xmlymain-login-web/login/ts-1657244122966?appId=mainApp&appStatus=2&clientType=android&isFirstReq=false&lastSuccessIp=180.153.250.247:3814&userId=175776850",
+ "__X_HTTP_HEADERS_INTERGRATION": "Cookie2: $version=1\r\nAccept: */*\r\nuser-agent: ting_xmim1.0(Mi+10,Android29)\r\nxmTraceId: f30c74a5-c62d-46a0-80bd-d51dbf139976163\r\nHost: xmc.ximalaya.com\r\nConnection: Keep-Alive\r\nAccept-Encoding: gzip\r\n\r\n"
},
{
"__X_HTTP_TRANSACTION": "response",
@@ -37,7 +38,7 @@
"X-NWS-LOG-UUID": "12197298277844186084",
"Connection": "keep-alive",
"X-Cache-Lookup": "Cache Miss",
- "__X_HTTP_RAW_PAYLOAD_MD5": "3979c98326c16f482f364ee94be3c382",
- "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d383effc464d797b5fdb4d98f4ab0111"
+ "__X_HTTP_HEADERS_INTERGRATION": "Server: Tengine\r\nDate: Fri, 08 Jul 2022 01:35:24 GMT\r\nContent-Type: application/json;charset=UTF-8\r\nVary: Accept-Encoding\r\nx-idc-gw: 0\r\nContent-Encoding: gzip\r\nTransfer-Encoding: chunked\r\nX-NWS-LOG-UUID: 12197298277844186084\r\nConnection: keep-alive\r\nX-Cache-Lookup: Cache Miss\r\n\r\n",
+ "__X_HTTP_DECOMPRESS_PAYLOAD_MD5": "d383effc464d797b5fdb4d98f4ab0111"
}
] \ No newline at end of file
diff --git a/test/decoders/http/benchmarks/pcap/http_connect_single.pcap b/test/decoders/http/benchmarks/pcap/http_connect_single.pcap
new file mode 100644
index 0000000..791ce05
--- /dev/null
+++ b/test/decoders/http/benchmarks/pcap/http_connect_single.pcap
Binary files differ
diff --git a/test/decoders/http/benchmarks/pcap/http_incomplete_header.pcap b/test/decoders/http/benchmarks/pcap/http_incomplete_header.pcap
new file mode 100644
index 0000000..0e07df9
--- /dev/null
+++ b/test/decoders/http/benchmarks/pcap/http_incomplete_header.pcap
Binary files differ
diff --git a/test/decoders/http/benchmarks/pcap/http_no_cr_line_eof.pcap b/test/decoders/http/benchmarks/pcap/http_no_cr_line_eof.pcap
new file mode 100644
index 0000000..63763cd
--- /dev/null
+++ b/test/decoders/http/benchmarks/pcap/http_no_cr_line_eof.pcap
Binary files differ
diff --git a/test/decoders/http/benchmarks/pcap/http_put_continue100.pcap b/test/decoders/http/benchmarks/pcap/http_put_continue100.pcap
new file mode 100644
index 0000000..7f43528
--- /dev/null
+++ b/test/decoders/http/benchmarks/pcap/http_put_continue100.pcap
Binary files differ
diff --git a/test/decoders/http/http_gtest.cpp b/test/decoders/http/http_gtest.cpp
index 4f99fb6..300e221 100644
--- a/test/decoders/http/http_gtest.cpp
+++ b/test/decoders/http/http_gtest.cpp
@@ -3,14 +3,45 @@
#include <stdio.h>
#include "zlib.h"
#include "md5/md5.h"
+#include "stellar/http.h"
+#include "http_decoder.h"
+#include "http_decoder_utils.h"
+#include "http_decoder_half.h"
+#include "http_decoder_decompress.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
#include "http.h"
-#include "http_decoder_private.h"
+#include "llhttp.h"
#include "brotli/decode.h"
#include "brotli/encode.h"
-#include "event2/buffer.h"
+#ifdef __cplusplus
+}
+#endif
#define ZIP_UNZIP_TEST_DATA_LEN (1024 * 1024)
void httpd_url_decode(const char *string, size_t length, char *ostring, size_t *olen);
+TEST(http_url_decoder, onebyte_ascii)
+{
+ char decoded_url_buf[2048] = {};
+ size_t decode_url_buf_len = sizeof(decoded_url_buf);
+ const char *encode_url = "h";
+ size_t decoded_url_len = http_url_decode(encode_url, strlen(encode_url), decoded_url_buf, decode_url_buf_len);
+ EXPECT_EQ(decoded_url_len, strlen("h"));
+ EXPECT_STREQ("h", decoded_url_buf);
+}
+
+TEST(http_url_decoder, onebyte_hex)
+{
+ char decoded_url_buf[2048] = {};
+ size_t decode_url_buf_len = sizeof(decoded_url_buf);
+ const char *encode_url = "%FF";
+ size_t decoded_url_len = http_url_decode(encode_url, strlen(encode_url), decoded_url_buf, decode_url_buf_len);
+ EXPECT_EQ(decoded_url_len, 1);
+ EXPECT_EQ((unsigned char)decoded_url_buf[0], 0xFF);
+}
+
TEST(http_url_decoder, none_encode)
{
char decoded_url_buf[2048] = {};
@@ -60,27 +91,55 @@ TEST(http_url_decoder, chinese2)
EXPECT_EQ(decoded_url_len, strlen("http://www.baidu.com/\xE7\xBC\x96\xE8\xA7\xA3\xE7\xA0\x81\xE6\xB5\x8B\xE8\xAF\x95\xE5\x93\x88\xE5\x93\x88"));
}
-TEST(http, event_buffer)
+TEST(http, buffer)
{
- struct evbuffer *evbuf = evbuffer_new();
+ struct http_buffer *hbuf = http_buffer_new();
- evbuffer_add(evbuf, "hello", 5);
+ http_buffer_add(hbuf, "hello", 5);
+
+ char *data;
+ size_t len;
+ http_buffer_read(hbuf, &data, &len);
- size_t len = evbuffer_get_length(evbuf);
- EXPECT_EQ(len, 5);
- char outbuf[16];
- len = evbuffer_copyout(evbuf, outbuf, sizeof(outbuf));
EXPECT_EQ(len, 5);
- EXPECT_EQ(0, memcmp(outbuf, "hello", 5));
+ EXPECT_EQ(0, memcmp(data, "hello", 5));
- evbuffer_add(evbuf, ",", 1);
- evbuffer_add(evbuf, "world", 5);
+ http_buffer_add(hbuf, ",", 1);
+ http_buffer_add(hbuf, "world", 5);
- len = evbuffer_copyout(evbuf, outbuf, sizeof(outbuf));
+ http_buffer_read(hbuf, &data, &len);
EXPECT_EQ(len, 11);
- EXPECT_EQ(0, memcmp(outbuf, "hello,world", 11));
+ EXPECT_EQ(0, memcmp(data, "hello,world", 11));
+
+ http_buffer_free(hbuf);
+}
+
+TEST(http, strtoll)
+{
+ ASSERT_EQ(0, http_strtoll(NULL, 0));
+ ASSERT_EQ(0, http_strtoll("", 1));
+ ASSERT_EQ(0, http_strtoll("abcd", 4));
+ ASSERT_EQ(123, http_strtoll("123", 3));
+ ASSERT_EQ(123, http_strtoll(" 123", 4));
+ ASSERT_EQ(123, http_strtoll(" 123\r\n", 6));
+ ASSERT_EQ(123456789, http_strtoll("123456789", 9));
+}
- evbuffer_free(evbuf);
+TEST(http, line_header_is_completed)
+{
+ ASSERT_EQ(0, http_line_header_completed(NULL, 0));
+ ASSERT_EQ(0, http_line_header_completed("GET ", 4));
+ ASSERT_EQ(0, http_line_header_completed("GET / HTTP/1.1\r\n", strlen("GET / HTTP/1.1\r\n")));
+ ASSERT_EQ(strlen("GET / HTTP/1.1\r\n\r\n"), http_line_header_completed("GET / HTTP/1.1\r\n\r\n", strlen("GET / HTTP/1.1\r\n\r\n")));
+}
+
+TEST(http, identify)
+{
+ ASSERT_EQ(-1, http_protocol_identify(NULL, 0));
+ ASSERT_EQ(-1, http_protocol_identify("123", 3));
+ ASSERT_EQ(1, http_protocol_identify("GET / HTTP/1.1\r\n", strlen("GET / HTTP/1.1\r\n")));
+ ASSERT_EQ(1, http_protocol_identify("POST / HTTP/1.1\r\n", strlen("POST / HTTP/1.1\r\n")));
+ ASSERT_EQ(1, http_protocol_identify("HTTP/1.1 200 OK\r\n", strlen("HTTP/1.1 200 OK\r\n")));
}
static int http_compress_use_deflate(unsigned char *indata, size_t indata_len, unsigned char *zip_data, size_t *zip_data_len)
@@ -351,6 +410,230 @@ TEST(http, DISABLED_brotli_ascii)
free(raw_data);
}
+#include "http_decoder_half.c"
+#include "http_decoder_llhttp_wrap.c"
+struct gtest_llhttp_callback_flag
+{
+ uint8_t on_message_begin;
+ uint8_t on_message_complete;
+ uint8_t on_uri;
+ uint8_t on_uri_complete;
+ uint8_t on_status;
+ uint8_t on_status_complete;
+ uint8_t on_method;
+ uint8_t on_method_complete;
+ uint8_t on_version;
+ uint8_t on_version_complete;
+ uint8_t on_header_field;
+ uint8_t on_header_field_complete;
+ uint8_t on_header_value;
+ uint8_t on_header_value_complete;
+ uint8_t on_chunk_header;
+ uint8_t on_chunk_header_complete;
+ uint8_t on_headers_complete;
+ uint8_t on_body;
+};
+static struct gtest_llhttp_callback_flag gtest_llhttp_cb_flags;
+static struct http_half_data gtest_flow_data;
+
+static int gtest_llhttp_on_message_begin(UNUSED llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *flow = parser->flow_ref;
+ flow->event = HTTP_EVENT_REQ_INIT;
+ gtest_llhttp_cb_flags.on_message_begin++;
+ return 0;
+}
+static int gtest_llhttp_on_message_complete(llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *flow = parser->flow_ref;
+ flow->event = __HTTP_EVENT_RESERVED;
+ flow->shaper.headers_cache = NULL;
+ gtest_llhttp_cb_flags.on_message_complete++;
+ return 0;
+}
+static int gtest_llhttp_on_headers_complete(llhttp_t *http)
+{
+ struct http_half_parser *parser = container_of(http, struct http_half_parser, llhttp_parser);
+ struct http_half *flow = parser->flow_ref;
+ flow->event = HTTP_EVENT_REQ_HDR_END;
+ gtest_llhttp_cb_flags.on_headers_complete++;
+ return 0;
+}
+static int gtest_llhttp_on_uri(UNUSED llhttp_t *http, UNUSED const char *at, UNUSED size_t length)
+{
+ gtest_llhttp_cb_flags.on_uri++;
+ return 0;
+}
+static int gtest_llhttp_on_method(UNUSED llhttp_t *http, UNUSED const char *at, UNUSED size_t length)
+{
+ gtest_llhttp_cb_flags.on_method++;
+ return 0;
+}
+static int gtest_llhttp_on_version(UNUSED llhttp_t *http, UNUSED const char *at, UNUSED size_t length)
+{
+ gtest_llhttp_cb_flags.on_version++;
+ return 0;
+}
+static int gtest_llhttp_on_body(UNUSED llhttp_t *http, UNUSED const char *at, UNUSED size_t length)
+{
+ gtest_llhttp_cb_flags.on_body++;
+ return 0;
+}
+
+static void gtest_llhttp_init(struct http_half *flow)
+{
+ memset(flow, 0, sizeof(struct http_half));
+ flow->flow_data = &gtest_flow_data;
+ flow->parser.flow_ref = flow;
+ llhttp_settings_init(&flow->parser.settings);
+ memset(&gtest_llhttp_cb_flags, 0, sizeof(gtest_llhttp_cb_flags));
+ flow->parser.settings.on_message_begin = gtest_llhttp_on_message_begin;
+ flow->parser.settings.on_message_complete = gtest_llhttp_on_message_complete;
+ flow->parser.settings.on_url = gtest_llhttp_on_uri;
+ flow->parser.settings.on_method = gtest_llhttp_on_method;
+ flow->parser.settings.on_version = gtest_llhttp_on_version;
+ flow->parser.settings.on_body = gtest_llhttp_on_body;
+ flow->parser.settings.on_headers_complete = gtest_llhttp_on_headers_complete;
+
+ llhttp_init(&flow->parser.llhttp_parser, HTTP_BOTH, &flow->parser.settings);
+}
+
+TEST(http, stage_request_completed)
+{
+ const char *newdata = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: keep-alive\r\n\r\n";
+ size_t new_datalen = strlen(newdata);
+ struct http_half flow = {};
+ gtest_llhttp_init(&flow);
+
+ http_flow_stage_shaping(&flow, newdata, new_datalen);
+
+ llhttp_finish(&flow.parser.llhttp_parser);
+ http_buffer_free(flow.shaper.headers_cache);
+
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_message_begin);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_method);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_uri);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_version);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_message_complete);
+}
+
+TEST(http, headers_extract)
+{
+ const char *raw_data = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: keep-alive\r\n\r\n";
+ const char *headers_start, *headers_end;
+ http_truncate_extract_headers(raw_data, strlen(raw_data), &headers_start, &headers_end);
+ ASSERT_TRUE(headers_start != NULL);
+ ASSERT_TRUE(headers_end != NULL);
+ ASSERT_EQ(0, memcmp(headers_start, "Host: www.example.com\r\nConnection: keep-alive\r\n\r\n", headers_end - headers_start));
+}
+
+TEST(http, stage_request_with_body)
+{
+ const char *newdata = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: keep-alive\r\nContent-Length: 11\r\n\r\nhello,world";
+ size_t new_datalen = strlen(newdata);
+ struct http_half flow = {};
+ gtest_llhttp_init(&flow);
+
+ gtest_flow_data.header.content_length = 11;
+ http_flow_stage_shaping(&flow, newdata, new_datalen);
+
+ llhttp_finish(&flow.parser.llhttp_parser);
+ http_buffer_free(flow.shaper.headers_cache);
+
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_message_begin);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_method);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_uri);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_version);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_body);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_message_complete);
+}
+
+TEST(http, stage_request_with_body_pipeline_many)
+{
+ const char *newdata = "GET / HTTP/1.1\r\nHost: www.example1.com\r\nConnection: keep-alive\r\nContent-Length: 11\r\n\r\nhello,worldGET / HTTP/1.1\r\nHost: www.example2.com\r\nConnection: keep-alive\r\nContent-Length: 11\r\n\r\nhello,secndGET / HTTP/1.1\r\nHost: www.example3.com\r\nConnection: keep-alive\r\nContent-Length: 11\r\n\r\nhello,third";
+ size_t new_datalen = strlen(newdata);
+ struct http_half flow = {};
+ gtest_llhttp_init(&flow);
+
+ gtest_flow_data.header.content_length = 11;
+ http_flow_stage_shaping(&flow, newdata, new_datalen);
+
+ llhttp_finish(&flow.parser.llhttp_parser);
+ http_buffer_free(flow.shaper.headers_cache);
+
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_message_begin);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_method);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_uri);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_version);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_body);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_message_complete);
+}
+
+TEST(http, stage_request_with_body_pipeline_many_one_by_one)
+{
+ const char *newdata = "GET / HTTP/1.1\r\nHost: www.example1.com\r\nConnection: keep-alive\r\nContent-Length: 11\r\n\r\nhello,worldGET / HTTP/1.1\r\nHost: www.example2.com\r\nConnection: keep-alive\r\nContent-Length: 11\r\n\r\nhello,secndGET / HTTP/1.1\r\nHost: www.example3.com\r\nConnection: keep-alive\r\nContent-Length: 11\r\n\r\nhello,third";
+ size_t new_datalen = strlen(newdata);
+ struct http_half flow = {};
+ gtest_llhttp_init(&flow);
+
+ gtest_flow_data.header.content_length = 11;
+
+ for (size_t i = 0; i < new_datalen; i++)
+ {
+ http_flow_stage_shaping(&flow, newdata + i, 1);
+ }
+
+ llhttp_finish(&flow.parser.llhttp_parser);
+ http_buffer_free(flow.shaper.headers_cache);
+
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_message_begin);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_method);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_uri);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_version);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_message_complete);
+}
+
+TEST(http, stage_request_completed_pipeline)
+{
+ const char *newdata = "GET / HTTP/1.1\r\nHost: www.example1.com\r\nConnection: keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost: www.example2.com\r\nConnection: keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost: www.example3.com\r\nConnection: keep-alive\r\n\r\n";
+ size_t new_datalen = strlen(newdata);
+ struct http_half flow = {};
+ gtest_llhttp_init(&flow);
+
+ http_flow_stage_shaping(&flow, newdata, new_datalen);
+ llhttp_finish(&flow.parser.llhttp_parser);
+ http_buffer_free(flow.shaper.headers_cache);
+
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_message_begin);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_method);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_uri);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_version);
+ ASSERT_EQ(3, gtest_llhttp_cb_flags.on_message_complete);
+}
+
+TEST(http, stage_request_one_by_one)
+{
+ const char *newdata = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: keep-alive\r\n\r\n";
+ size_t new_datalen = strlen(newdata);
+ struct http_half flow = {};
+ gtest_llhttp_init(&flow);
+
+ for (size_t i = 0; i < new_datalen; i++)
+ {
+ http_flow_stage_shaping(&flow, newdata + i, 1);
+ }
+ llhttp_finish(&flow.parser.llhttp_parser);
+ http_buffer_free(flow.shaper.headers_cache);
+
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_message_begin);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_method);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_uri);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_version);
+ ASSERT_EQ(1, gtest_llhttp_cb_flags.on_message_complete);
+}
+
int main(int argc, char const *argv[])
{
::testing::InitGoogleTest(&argc, (char **)argv);
diff --git a/test/decoders/http/http_gtest.h b/test/decoders/http/http_gtest.h
index 362bd39..7c74379 100644
--- a/test/decoders/http/http_gtest.h
+++ b/test/decoders/http/http_gtest.h
@@ -4,8 +4,8 @@ extern "C"
{
#endif
#include <stellar/session.h>
-#include <stellar/stellar_mq.h>
-#include <stellar/stellar_exdata.h>
+#include <stellar/mq.h>
+#include <stellar/exdata.h>
#include <stellar/stellar.h>
#ifdef __cplusplus
}
@@ -44,6 +44,7 @@ extern "C"
#define EX_DATA_MAX_SIZE 10
#define PIPELINE_MAX_NUM 8
+#define GTEST_RESULT_FILENAME "http_gtest.json"
#define GTEST_FIX_PAYLOAD_CSTR "<Hello http decoder World!!!>"
#define GTEST_FIX_PAYLOAD_MD5 "e91e072f772737c7a45013cc3b1a916c"
@@ -53,8 +54,9 @@ extern "C"
#define GTEST_HTTP_TRANS_SEQ_NAME "__X_HTTP_TRANSACTION_SEQ"
#define GTEST_HTTP_TUPLE4_NAME "__X_HTTP_TUPLE4"
#define GTEST_HTTP_PAYLOAD_NAME "__X_HTTP_PAYLOAD"
-#define GTEST_HTTP_RAW_PAYLOAD_MD5_NAME "__X_HTTP_RAW_PAYLOAD_MD5"
+#define GTEST_HTTP_RAW_PAYLOAD_MD5_NAME "__X_HTTP_DECOMPRESS_PAYLOAD_MD5"
#define GTEST_HTTP_DECOMPRESS_PAYLOAD_MD5_NAME "__X_HTTP_DECOMPRESS_PAYLOAD_MD5"
+#define GTEST_HTTP_ALL_HEADERS "__X_HTTP_HEADERS_INTERGRATION"
struct stellar *stellar_init(void);
diff --git a/test/decoders/http/http_gtest_llhttp.cpp b/test/decoders/http/http_gtest_llhttp.cpp
index 58ff281..ce3c4f4 100644
--- a/test/decoders/http/http_gtest_llhttp.cpp
+++ b/test/decoders/http/http_gtest_llhttp.cpp
@@ -51,6 +51,10 @@ static int on_message_begin(llhttp_t *parser)
static int on_url(llhttp_t *parser, const char *at, size_t length)
{
+ if (length == 0)
+ {
+ return 0;
+ }
printf("URI cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_url++;
@@ -59,6 +63,10 @@ static int on_url(llhttp_t *parser, const char *at, size_t length)
static int on_method(llhttp_t *parser, const char *at, size_t length)
{
+ if (length == 0)
+ {
+ return 0;
+ }
printf("method cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_method++;
@@ -67,6 +75,10 @@ static int on_method(llhttp_t *parser, const char *at, size_t length)
static int on_status(llhttp_t *parser, const char *at, size_t length)
{
+ if (length == 0)
+ {
+ return 0;
+ }
printf("status cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_status++;
@@ -75,6 +87,10 @@ static int on_status(llhttp_t *parser, const char *at, size_t length)
static int on_version(llhttp_t *parser, const char *at, size_t length)
{
+ if (length == 0)
+ {
+ return 0;
+ }
printf("version cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_version++;
@@ -83,6 +99,10 @@ static int on_version(llhttp_t *parser, const char *at, size_t length)
static int on_header_field(llhttp_t *parser, const char *at, size_t length)
{
+ if (length == 0)
+ {
+ return 0;
+ }
printf("Header field cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_header_field++;
@@ -99,6 +119,10 @@ static int on_header_field_complete(llhttp_t *parser)
static int on_header_value(llhttp_t *parser, const char *at, size_t length)
{
+ if (length == 0)
+ {
+ return 0;
+ }
printf("Header value cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_header_value++;
@@ -131,6 +155,10 @@ static int on_message_complete(llhttp_t *parser)
static int on_body(llhttp_t *parser, const char *at, size_t length)
{
+ if (length == 0)
+ {
+ return 0;
+ }
printf("on_body cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_body++;
@@ -174,6 +202,27 @@ TEST(HTTP_llhttp, request_base)
ASSERT_EQ(para.count.flag_on_message_complete, 1);
}
+TEST(HTTP_llhttp, request_one_bytes)
+{
+ struct gtest_http_parm para = {};
+ gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
+ const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example.com\r\nContent-Length: 0\r\n\r\n";
+ for (size_t i = 0; i < strlen(request); i++)
+ {
+ enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request + i, 1);
+ ASSERT_EQ(lerr, HPE_OK);
+ }
+ ASSERT_EQ(para.count.flag_on_message_begin, 1);
+ ASSERT_EQ(para.count.flag_on_url, 16);
+ ASSERT_EQ(para.count.flag_on_method, 3);
+ ASSERT_EQ(para.count.flag_on_version, 3);
+ ASSERT_EQ(para.count.flag_on_header_field, 18);
+ ASSERT_EQ(para.count.flag_on_header_value, 12);
+ ASSERT_EQ(para.count.flag_on_header_field_complete, 2);
+ ASSERT_EQ(para.count.flag_on_headers_complete, 1);
+ ASSERT_EQ(para.count.flag_on_message_complete, 1);
+}
+
TEST(HTTP_llhttp, request_dir_error)
{
struct gtest_http_parm para = {};
@@ -197,7 +246,7 @@ TEST(HTTP_llhttp, request_uncompleted)
ASSERT_EQ(para.count.flag_on_message_complete, 0);
}
-TEST(HTTP_llhttp, request_hdr_pipeline)
+TEST(HTTP_llhttp, get_request_hdr_pipeline_cont_len_zero)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
@@ -212,6 +261,51 @@ TEST(HTTP_llhttp, request_hdr_pipeline)
ASSERT_EQ(para.count.flag_on_message_complete, 3);
}
+TEST(HTTP_llhttp, post_request_hdr_pipeline_cont_len_zero)
+{
+ struct gtest_http_parm para = {};
+ gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
+ const char *request = "POST /path/index.html HTTP/1.1\r\nHost: example1.com\r\nContent-Length: 0\r\n\r\nPOST /path/index.html HTTP/1.1\r\nHost: example2.com\r\nContent-Length: 0\r\n\r\nPOST /path/index.html HTTP/1.1\r\nHost: example3.com\r\nContent-Length: 0\r\n\r\n";
+ enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
+ ASSERT_EQ(lerr, HPE_OK);
+ ASSERT_EQ(para.count.flag_on_message_begin, 3);
+ ASSERT_EQ(para.count.flag_on_url, 3);
+ ASSERT_EQ(para.count.flag_on_method, 3);
+ ASSERT_EQ(para.count.flag_on_version, 3);
+ ASSERT_EQ(para.count.flag_on_headers_complete, 3);
+ ASSERT_EQ(para.count.flag_on_message_complete, 3);
+}
+
+TEST(HTTP_llhttp, get_request_hdr_pipeline_no_cont_len)
+{
+ struct gtest_http_parm para = {};
+ gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
+ const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example1.com\r\n\r\nGET /path/index.html HTTP/1.1\r\nHost: example2.com\r\n\r\nGET /path/index.html HTTP/1.1\r\nHost: example3.com\r\n\r\n";
+ enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
+ ASSERT_EQ(lerr, HPE_OK);
+ ASSERT_EQ(para.count.flag_on_message_begin, 3);
+ ASSERT_EQ(para.count.flag_on_url, 3);
+ ASSERT_EQ(para.count.flag_on_method, 3);
+ ASSERT_EQ(para.count.flag_on_version, 3);
+ ASSERT_EQ(para.count.flag_on_headers_complete, 3);
+ ASSERT_EQ(para.count.flag_on_message_complete, 3);
+}
+
+TEST(HTTP_llhttp, post_request_hdr_pipeline_no_cont_len)
+{
+ struct gtest_http_parm para = {};
+ gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
+ const char *request = "POST /path/index.html HTTP/1.1\r\nHost: example1.com\r\n\r\nPOST /path/index.html HTTP/1.1\r\nHost: example2.com\r\n\r\nPOST /path/index.html HTTP/1.1\r\nHost: example3.com\r\n\r\n";
+ enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
+ ASSERT_EQ(lerr, HPE_OK);
+ ASSERT_EQ(para.count.flag_on_message_begin, 3);
+ ASSERT_EQ(para.count.flag_on_url, 3);
+ ASSERT_EQ(para.count.flag_on_method, 3);
+ ASSERT_EQ(para.count.flag_on_version, 3);
+ ASSERT_EQ(para.count.flag_on_headers_complete, 3);
+ ASSERT_EQ(para.count.flag_on_message_complete, 3);
+}
+
TEST(HTTP_llhttp, request_hdr_body_pipeline)
{
struct gtest_http_parm para = {};
@@ -431,6 +525,7 @@ TEST(HTTP_llhttp, response_no_len_no_type_body)
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 0); // no completed
+ llhttp_reset(&para.llhttp_parser);
}
TEST(HTTP_llhttp, response_no_len_has_type_body)
@@ -446,6 +541,7 @@ TEST(HTTP_llhttp, response_no_len_has_type_body)
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 0); // no completed
+ llhttp_reset(&para.llhttp_parser);
}
TEST(HTTP_llhttp, response_no_len_no_type_pipeline)
diff --git a/test/decoders/http/http_gtest_llhttp_headers_buf.cpp b/test/decoders/http/http_gtest_llhttp_headers_buf.cpp
new file mode 100644
index 0000000..f3f8044
--- /dev/null
+++ b/test/decoders/http/http_gtest_llhttp_headers_buf.cpp
@@ -0,0 +1,424 @@
+#include <cstdint>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <gtest/gtest.h>
+#include <bits/types/struct_iovec.h>
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <llhttp.h>
+#include "stellar/utils.h"
+#ifdef __cplusplus
+}
+#endif
+
+#define MAX_HEADER_FIELD_NUM (32)
+
+struct http_filed
+{
+ struct iovec field_name;
+ struct iovec field_value;
+};
+
+enum gtest_llhttp_callback_type
+{
+ CALLBACK_TYPE_MESSAGE_BEGIN = 0,
+ CALLBACK_TYPE_URL,
+ CALLBACK_TYPE_METHOD,
+ CALLBACK_TYPE_STATUS,
+ CALLBACK_TYPE_VERSION,
+ CALLBACK_TYPE_HEADER_FIELD,
+ CALLBACK_TYPE_HEADER_FIELD_COMPLETE,
+ CALLBACK_TYPE_HEADER_VALUE,
+ CALLBACK_TYPE_HEADER_VALUE_COMPLETE,
+ CALLBACK_TYPE_HEADERS_COMPLETE,
+ CALLBACK_TYPE_BODY,
+ CALLBACK_TYPE_MESSAGE_COMPLETE,
+};
+
+struct gtest_http_counter
+{
+ uint8_t flag_on_message_begin;
+ uint8_t flag_on_url;
+ uint8_t flag_on_method;
+ uint8_t flag_on_status;
+ uint8_t flag_on_version;
+ uint8_t flag_on_header_field;
+ uint8_t flag_on_header_field_complete;
+ uint8_t flag_on_header_value;
+ uint8_t flag_on_header_value_complete;
+ uint8_t flag_on_headers_complete;
+ uint8_t flag_on_body;
+ uint8_t flag_on_message_complete;
+};
+
+struct header_buffer
+{
+ char *data;
+ size_t len;
+};
+
+struct gtest_http_header_compose
+{
+ llhttp_t llhttp_parser;
+ llhttp_settings_t settings;
+ struct gtest_http_counter count;
+ const char *last_header_value_complete_ptr; /* at + length + 4 \r\n\r\n) */
+ const char *last_headers_complete_ptr;
+ size_t last_callback_offset; /* at + length + eof (header_value = 2, header_completed = 4) */
+ struct header_buffer hdr_buf;
+
+ enum gtest_llhttp_callback_type lastest_callback_type;
+
+ struct http_filed header_fields[MAX_HEADER_FIELD_NUM];
+ int current_header_field_index;
+ const char *header_begin;
+ size_t headers_len;
+};
+
+static int on_message_begin(llhttp_t *parser)
+{
+ printf("Message begin cb\n");
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_message_begin++;
+ para->lastest_callback_type = CALLBACK_TYPE_MESSAGE_BEGIN;
+ return 0;
+}
+
+static int on_url(llhttp_t *parser, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ printf("URI cb: %.*s\n", (int)length, at);
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_url++;
+ para->lastest_callback_type = CALLBACK_TYPE_URL;
+ return 0;
+}
+
+static int on_method(llhttp_t *parser, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ printf("method cb: %.*s\n", (int)length, at);
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_method++;
+ para->lastest_callback_type = CALLBACK_TYPE_METHOD;
+ return 0;
+}
+
+static int on_status(llhttp_t *parser, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ printf("status cb: %.*s\n", (int)length, at);
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_status++;
+ para->lastest_callback_type = CALLBACK_TYPE_STATUS;
+ return 0;
+}
+
+static int on_version(llhttp_t *parser, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ printf("version cb: %.*s\n", (int)length, at);
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_version++;
+ para->lastest_callback_type = CALLBACK_TYPE_VERSION;
+ return 0;
+}
+
+static int on_header_field(llhttp_t *parser, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ printf("Header field cb: %.*s\n", (int)length, at);
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_header_field++;
+ para->lastest_callback_type = CALLBACK_TYPE_HEADER_FIELD;
+ para->header_fields[para->current_header_field_index].field_name.iov_base = (void *)at;
+ para->header_fields[para->current_header_field_index].field_name.iov_len = length;
+ return 0;
+}
+
+static int on_header_field_complete(llhttp_t *parser)
+{
+ printf("Header field complete cb\n");
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_header_field_complete++;
+ para->lastest_callback_type = CALLBACK_TYPE_HEADER_FIELD_COMPLETE;
+ return 0;
+}
+
+static int on_header_value(llhttp_t *parser, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ printf("Header value cb: %.*s\n", (int)length, at);
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_header_value++;
+ para->lastest_callback_type = CALLBACK_TYPE_HEADER_VALUE;
+
+ para->header_fields[para->current_header_field_index].field_value.iov_base = (void *)at;
+ para->header_fields[para->current_header_field_index].field_value.iov_len = length;
+
+ para->last_header_value_complete_ptr = at + length;
+ return 0;
+}
+
+static int on_header_value_complete(llhttp_t *parser)
+{
+ printf("Header value complete cb\n");
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_header_value_complete++;
+ para->lastest_callback_type = CALLBACK_TYPE_HEADER_VALUE_COMPLETE;
+ para->current_header_field_index++;
+
+ if (strncmp("\r\n", para->last_header_value_complete_ptr, 2) == 0)
+ {
+ para->last_header_value_complete_ptr += 2;
+ }
+ return 0;
+}
+
+static int on_headers_complete(llhttp_t *parser)
+{
+ printf("All Headers complete cb\n");
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_headers_complete++;
+ para->lastest_callback_type = CALLBACK_TYPE_HEADERS_COMPLETE;
+
+ para->last_headers_complete_ptr = para->last_header_value_complete_ptr;
+ if (strncmp("\r\n", para->last_headers_complete_ptr, 2) == 0)
+ {
+ para->last_headers_complete_ptr += 2;
+ }
+ return 0;
+}
+
+static int on_body(llhttp_t *parser, const char *at, size_t length)
+{
+ if (length == 0)
+ {
+ return 0;
+ }
+ printf("on_body cb: %.*s\n", (int)length, at);
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_body++;
+ para->lastest_callback_type = CALLBACK_TYPE_BODY;
+ return 0;
+}
+
+static int on_message_complete(llhttp_t *parser)
+{
+ printf("Message complete cb\n");
+ struct gtest_http_header_compose *para = container_of(parser, struct gtest_http_header_compose, llhttp_parser);
+ para->count.flag_on_message_complete++;
+ para->lastest_callback_type = CALLBACK_TYPE_MESSAGE_COMPLETE;
+ return 0;
+}
+
+static int gtest_llhttp_init(llhttp_t *parser, llhttp_type_t type, llhttp_settings_t *settings)
+{
+ llhttp_settings_init(settings);
+ settings->on_message_begin = on_message_begin;
+ settings->on_url = on_url;
+ settings->on_version = on_version;
+ settings->on_status = on_status;
+ settings->on_method = on_method;
+ settings->on_header_field = on_header_field;
+ settings->on_header_field_complete = on_header_field_complete;
+ settings->on_header_value = on_header_value;
+ settings->on_header_value_complete = on_header_value_complete;
+ settings->on_headers_complete = on_headers_complete;
+ settings->on_body = on_body;
+ settings->on_message_complete = on_message_complete;
+
+ llhttp_init(parser, type, settings);
+ return 0;
+}
+
+static void header_buf_append(struct header_buffer *hdr_buf, char *newdata, size_t len)
+{
+ hdr_buf->data = (char *)realloc(hdr_buf->data, hdr_buf->len + len);
+ memcpy(hdr_buf->data + hdr_buf->len, newdata, len);
+ hdr_buf->len += len;
+}
+
+static void header_buf_free(struct header_buffer *hdr_buf)
+{
+ if (hdr_buf->data)
+ {
+ free(hdr_buf->data);
+ hdr_buf->data = NULL;
+ }
+ hdr_buf->len = 0;
+}
+
+static void header_compose_reset(struct gtest_http_header_compose *para)
+{
+ llhttp_reset(&para->llhttp_parser);
+ para->last_header_value_complete_ptr = NULL;
+ para->last_headers_complete_ptr = NULL;
+ para->last_callback_offset = 0;
+ para->current_header_field_index = 0;
+ para->header_begin = NULL;
+ para->headers_len = 0;
+ memset(&para->count, 0, sizeof(para->count));
+ // can not reset hdr_buf
+}
+
+#if 1
+TEST(HTTP_llhttp_header, one_transaction_no_pipeline)
+{
+ struct gtest_http_header_compose para = {};
+ gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
+
+ /* first packet : header is not complete */
+ char *pkt_data = strdup("GET /path/index1.html HTTP/1.1\r\nHost: example.com\r\nContent-Length");
+ size_t pkt_datalen = strlen(pkt_data);
+ enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, pkt_data, pkt_datalen);
+ ASSERT_EQ(lerr, HPE_OK);
+ if (para.count.flag_on_headers_complete == 0)
+ {
+ header_buf_append(&para.hdr_buf, pkt_data, pkt_datalen);
+ printf("headers not complete\n");
+ header_compose_reset(&para);
+ }
+ free(pkt_data);
+
+ /* second packet: recv some new header filed, but headers not completed */
+ if (para.hdr_buf.len > 0)
+ {
+ lerr = llhttp_execute(&para.llhttp_parser, para.hdr_buf.data, para.hdr_buf.len);
+ ASSERT_EQ(lerr, HPE_OK);
+ }
+ char *pkt_data2 = strdup(": 0\r\nUser-Agent:");
+ size_t pkt_datalen2 = strlen(pkt_data2);
+ lerr = llhttp_execute(&para.llhttp_parser, pkt_data2, pkt_datalen2);
+ ASSERT_EQ(lerr, HPE_OK);
+ if (para.count.flag_on_headers_complete == 0)
+ {
+ header_buf_append(&para.hdr_buf, pkt_data2, pkt_datalen2);
+ printf("headers not complete\n");
+ header_compose_reset(&para);
+ }
+ free(pkt_data2);
+
+ /* third packet: recv last header filed, all headers completed */
+ if (para.hdr_buf.len > 0)
+ {
+ lerr = llhttp_execute(&para.llhttp_parser, para.hdr_buf.data, para.hdr_buf.len);
+ ASSERT_EQ(lerr, HPE_OK);
+ }
+ char *pkt_data3 = strdup(" Mozilla/5.0\r\n\r\n");
+ size_t pkt_datalen3 = strlen(pkt_data3);
+ lerr = llhttp_execute(&para.llhttp_parser, pkt_data3, pkt_datalen3);
+ ASSERT_EQ(lerr, HPE_OK);
+ if (para.count.flag_on_headers_complete)
+ {
+ header_buf_append(&para.hdr_buf, pkt_data3, pkt_datalen3);
+ printf("headers complete\n");
+ header_compose_reset(&para);
+ lerr = llhttp_execute(&para.llhttp_parser, para.hdr_buf.data, para.hdr_buf.len);
+ ASSERT_EQ(lerr, HPE_OK);
+ para.header_begin = para.hdr_buf.data;
+ para.headers_len = para.hdr_buf.len;
+ printf("===================================================\r\n");
+ printf("headers completed buf: \r\n%.*s\n", (int)para.headers_len, para.header_begin);
+ for (int i = 0; i < para.current_header_field_index; i++)
+ {
+ printf("header field: %.*s, header value: %.*s\n",
+ (int)para.header_fields[i].field_name.iov_len, (char *)para.header_fields[i].field_name.iov_base,
+ (int)para.header_fields[i].field_value.iov_len, (char *)para.header_fields[i].field_value.iov_base);
+ }
+ printf("===================================================\r\n");
+ }
+ free(pkt_data3);
+ header_buf_free(&para.hdr_buf);
+}
+#endif
+
+#if 1
+TEST(HTTP_llhttp_header, two_transaction_and_pipeline)
+{
+ struct gtest_http_header_compose para = {};
+ gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
+
+ /* first packet : transqction-1 is completed! transqction-2 headers is not complete */
+ char *pkt_data = strdup("GET /path/index1.html HTTP/1.1\r\nHost: example1.com\r\n\r\nGET /path/index2.html HTTP/1.1\r\nHost: example2.com");
+ size_t pkt_datalen = strlen(pkt_data);
+ enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, pkt_data, pkt_datalen);
+ ASSERT_EQ(lerr, HPE_OK);
+
+ /*
+ some headers not complete, in middle state
+ ignore transaction-1, all start-line and fileds are pointer to raw packet.
+ */
+ if (para.count.flag_on_headers_complete != 0 && para.lastest_callback_type < CALLBACK_TYPE_HEADERS_COMPLETE)
+ {
+ const char *cached_begin_ptr = pkt_data;
+ long long cached_len = (long long)pkt_datalen;
+ if (para.last_headers_complete_ptr != NULL)
+ {
+ cached_begin_ptr = para.last_headers_complete_ptr + 4;
+ cached_len = (long long)pkt_datalen - (long long)(para.last_headers_complete_ptr + 4 - pkt_data);
+ header_buf_append(&para.hdr_buf, (char *)cached_begin_ptr, (size_t)cached_len);
+ free(pkt_data);
+
+ printf("### transaction-2 cached header data: %.*s\n", (int)para.hdr_buf.len, para.hdr_buf.data);
+ }
+ printf("headers not complete\n");
+ header_compose_reset(&para);
+ }
+
+ /* second packet: transaction-2 completed */
+ if (para.hdr_buf.len > 0)
+ {
+ lerr = llhttp_execute(&para.llhttp_parser, para.hdr_buf.data, para.hdr_buf.len);
+ ASSERT_EQ(lerr, HPE_OK);
+ }
+ char *pkt_data2 = strdup("\r\nContent-Length: 0\r\n\r\n");
+ size_t pkt_datalen2 = strlen(pkt_data2);
+ lerr = llhttp_execute(&para.llhttp_parser, pkt_data2, pkt_datalen2);
+ ASSERT_EQ(lerr, HPE_OK);
+ if (para.lastest_callback_type >= CALLBACK_TYPE_HEADERS_COMPLETE)
+ {
+ header_buf_append(&para.hdr_buf, pkt_data2, pkt_datalen2);
+
+ printf("headers complete\n");
+ header_compose_reset(&para);
+
+ lerr = llhttp_execute(&para.llhttp_parser, para.hdr_buf.data, para.hdr_buf.len);
+ ASSERT_EQ(lerr, HPE_OK);
+ para.header_begin = para.hdr_buf.data;
+ para.headers_len = para.hdr_buf.len;
+ printf("=========================================\r\n");
+ printf("headers complete buf: \r\n%.*s\n", (int)para.headers_len, para.header_begin);
+ printf("=========================================\r\n");
+ }
+ free(pkt_data2);
+ header_buf_free(&para.hdr_buf);
+}
+#endif
+
+int main(int argc, char const *argv[])
+{
+ ::testing::InitGoogleTest(&argc, (char **)argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/decoders/http/http_gtest_main.cpp b/test/decoders/http/http_gtest_main.cpp
new file mode 100644
index 0000000..64203c7
--- /dev/null
+++ b/test/decoders/http/http_gtest_main.cpp
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <assert.h>
+#include <gtest/gtest.h>
+#include "stellar/stellar.h"
+#include "cJSON.h"
+
+static cJSON *load_result_from_jsonfile(const char *json_path)
+{
+ if (json_path == NULL)
+ return NULL;
+
+ long file_len = 0;
+ char *file_content = NULL;
+ FILE *fp = NULL;
+
+ fp = fopen(json_path, "r+");
+ if (NULL == fp)
+ {
+ return NULL;
+ }
+ fseek(fp, 0, SEEK_END);
+ file_len = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ if (file_len == 0)
+ {
+ fclose(fp);
+ return NULL;
+ }
+ file_content = (char *)malloc(file_len + 1);
+ fread(file_content, file_len, 1, fp);
+ file_content[file_len] = '\0';
+ cJSON *load = cJSON_Parse(file_content);
+ free(file_content);
+ fclose(fp);
+ return load;
+}
+
+static void show_json_diff(cJSON *expect_json_root, cJSON *test_module_root)
+{
+ if (NULL == expect_json_root || NULL == test_module_root)
+ {
+ return;
+ }
+ cJSON *t_load = expect_json_root->child, *t_test = test_module_root->child;
+ int ret;
+ char *load_json_str = NULL;
+ char *result_json_str = NULL;
+ while (t_load != NULL && t_test != NULL)
+ {
+ ret = cJSON_Compare(t_load, t_test, 0);
+ if (ret != 1)
+ {
+ load_json_str = cJSON_Print(t_load);
+ printf("LOAD Diff:\n%s\n", load_json_str);
+ free(load_json_str);
+ result_json_str = cJSON_Print(t_test);
+ printf("TEST Diff:\n%s\n", result_json_str);
+ free(result_json_str);
+ }
+ t_load = t_load->next;
+ t_test = t_test->next;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 3)
+ {
+ fprintf(stderr, "\nUsage: ./%s <expect-result> <test-module-result>\n\n", argv[0]);
+ exit(1);
+ }
+ ::testing::InitGoogleTest(&argc, (char **)argv);
+ const char *expect_json_path = argv[1];
+ const char *test_module_json_path = argv[2];
+
+ struct stellar *st = stellar_new("./conf/stellar.toml");
+ EXPECT_TRUE(st != NULL);
+ stellar_run(st);
+ stellar_free(st);
+
+ cJSON *expect_json_root = load_result_from_jsonfile(expect_json_path);
+ EXPECT_TRUE(expect_json_root != NULL);
+ cJSON *test_json_root = load_result_from_jsonfile(test_module_json_path);
+ EXPECT_TRUE(test_json_root != NULL);
+
+ int ret = cJSON_Compare(expect_json_root, test_json_root, 0);
+ EXPECT_EQ(1, ret);
+ if (ret != 1)
+ {
+ show_json_diff(expect_json_root, test_json_root);
+ }
+ cJSON_Delete(expect_json_root);
+ cJSON_Delete(test_json_root);
+ return ::testing::Test::HasFailure() ? 1 : 0;
+}
diff --git a/test/decoders/http/http_gtest_module.cpp b/test/decoders/http/http_gtest_module.cpp
new file mode 100644
index 0000000..42e507f
--- /dev/null
+++ b/test/decoders/http/http_gtest_module.cpp
@@ -0,0 +1,474 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include "cJSON.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include "stellar/http.h"
+#include "stellar/session.h"
+#include "stellar/module.h"
+#include "http_gtest.h"
+#include "http_decoder_utils.h"
+#include "md5/md5.h"
+#include "toml/toml.h"
+
+#define SAVE_BODY_AS_LOCAL_FILE 1 /* for debug */
+
+#define MAX_KEY_STR_LEN 2048
+ static int g_result_count = 0;
+ static cJSON *gtest_http_json_root;
+
+ enum http_transaction_type
+ {
+ HTTP_TRANSACTION_REQ = 0,
+ HTTP_TRANSACTION_RES,
+ HTTP_TRANSACTION_SESSION, // global session info
+ HTTP_TRANSACTION_MAX
+ };
+ enum payload_compress_mode
+ {
+ PAYLOAD_RAW = 0,
+ PAYLOAD_DECOMPRESS = 1,
+ PAYLOAD_MAX = 2,
+ };
+
+ struct http_gtest_exdata
+ {
+ cJSON *result_jnode[HTTP_TRANSACTION_MAX];
+ MD5_CTX *payload_md5ctx[PAYLOAD_MAX][HTTP_TRANSACTION_MAX];
+#if SAVE_BODY_AS_LOCAL_FILE
+ FILE *body_fp[HTTP_TRANSACTION_MAX];
+#endif
+ };
+
+ struct http_gtest_env
+ {
+ struct module_manager *mod_mgr;
+ int exdata_idx;
+ };
+
+ static int commit_test_result_json(cJSON *node)
+ {
+ if (gtest_http_json_root)
+ {
+ // cJSON_AddItemToObject(g_test_result_root, name, node);
+ // cJSON_AddStringToObject(node, "name", name);
+ cJSON_AddItemToArray(gtest_http_json_root, node);
+ return 0;
+ }
+ return -1;
+ }
+
+ void cJSON_Add_QStringToObject(cJSON *object, const char *name, const char *value, size_t value_len)
+ {
+ char *tmp = (char *)calloc(1, value_len + 1);
+ memcpy(tmp, value, value_len);
+ cJSON_AddStringToObject(object, name, tmp);
+ free(tmp);
+ }
+
+ void http_gtest_trans_id_to_json(cJSON *ctx, int transaction_index)
+ {
+ cJSON_AddNumberToObject(ctx, GTEST_HTTP_TRANS_SEQ_NAME, transaction_index);
+ }
+
+ static int http_field_to_json(cJSON *object, const char *key, char *val, size_t val_len)
+ {
+ if (NULL == object || NULL == key || NULL == val || 0 == val_len)
+ {
+ return -1;
+ }
+ char *tmp = CALLOC(char, val_len + 1);
+ memcpy(tmp, val, val_len);
+ cJSON_AddStringToObject(object, key, tmp);
+ FREE(tmp);
+ return 0;
+ }
+
+ static void http_header_to_json(cJSON *ctx, const struct http_header_field *header, int *uniq_name_count)
+ {
+ char key[MAX_KEY_STR_LEN] = {0};
+ if ((header->field_name == NULL))
+ {
+ return;
+ }
+ const char *field_value = header->field_value;
+ size_t field_value_len = header->field_value_len;
+ if (header->field_value == NULL || header->field_value_len == 0)
+ {
+ /* header value mayby NULL */
+ field_value = "";
+ field_value_len = 1;
+ }
+
+ memcpy(key, header->field_name, header->field_name_len);
+ if (cJSON_HasObjectItem(ctx, key) == FALSE)
+ {
+ http_field_to_json(ctx, key, (char *)field_value, field_value_len);
+ }
+ else
+ {
+ // ctx already has the same name key, so rename key plus index(%d)
+ char new_key[field_value_len + 64] = {0};
+ if (uniq_name_count)
+ {
+ snprintf(new_key, sizeof(new_key), "%s.%d", key, ++(*uniq_name_count));
+ }
+ else
+ {
+ snprintf(new_key, sizeof(new_key), "%s.%d", key, 1);
+ }
+ http_field_to_json(ctx, new_key, (char *)field_value, field_value_len);
+ }
+ }
+
+ static void http_gtest_url_add_to_json(cJSON *ctx, const char *url, size_t url_sz)
+ {
+ if (cJSON_GetObjectItem(ctx, GTEST_HTTP_URL_NAME))
+ {
+ return;
+ }
+ struct http_header_field raw_url_header_result = {};
+ raw_url_header_result.field_name = (char *)GTEST_HTTP_URL_NAME;
+ raw_url_header_result.field_name_len = strlen(GTEST_HTTP_URL_NAME);
+ raw_url_header_result.field_value = (char *)url;
+ raw_url_header_result.field_value_len = url_sz;
+ http_header_to_json(ctx, &raw_url_header_result, NULL);
+
+ char decoded_url_buffer[url_sz] = {0};
+ size_t decode_url_len = http_url_decode((const char *)url, url_sz, decoded_url_buffer, sizeof(decoded_url_buffer));
+
+ if (decode_url_len < url_sz)
+ {
+ struct http_header_field decode_url_header_result = {};
+ decode_url_header_result.field_name = (char *)"__X_HTTP_DECODED_URL";
+ decode_url_header_result.field_name_len = strlen("__X_HTTP_DECODED_URL");
+ decode_url_header_result.field_value = decoded_url_buffer;
+ decode_url_header_result.field_value_len = decode_url_len;
+ http_header_to_json(ctx, &decode_url_header_result, NULL);
+ }
+ }
+
+ static void http_gtest_commit_body_md5(cJSON *last_jnode, struct http_gtest_exdata *gtest_plug_exdata, enum http_transaction_type type)
+ {
+ // finish md5 streming hash
+ for (int mode = 0; mode < PAYLOAD_MAX; mode++)
+ {
+ if (gtest_plug_exdata->payload_md5ctx[mode][type])
+ {
+ unsigned char md5_result_bin[16] = {0};
+ unsigned char md5_result_cstr[33] = {0};
+ MD5Final(md5_result_bin, gtest_plug_exdata->payload_md5ctx[mode][type]);
+
+ for (int i = 0; i < 16; i++)
+ sprintf((char *)md5_result_cstr + 2 * i, "%02x", md5_result_bin[i]);
+ md5_result_cstr[32] = '\0';
+ if (mode == PAYLOAD_RAW)
+ {
+ cJSON_AddStringToObject(last_jnode, GTEST_HTTP_RAW_PAYLOAD_MD5_NAME, (char *)md5_result_cstr);
+ }
+ else
+ {
+ cJSON_AddStringToObject(last_jnode, GTEST_HTTP_DECOMPRESS_PAYLOAD_MD5_NAME, (char *)md5_result_cstr);
+ }
+ FREE(gtest_plug_exdata->payload_md5ctx[mode][type]);
+ gtest_plug_exdata->payload_md5ctx[mode][type] = NULL;
+ }
+ }
+ }
+
+ static void http_gtest_update_session_tuple4(struct session *sess, struct http_gtest_exdata *gtest_plug_exdata)
+ {
+ char sess_addr_string[256] = {};
+
+ enum session_state state = session_get_current_state(sess);
+ if (state == SESSION_STATE_CLOSED)
+ {
+ return;
+ }
+
+ struct http_session_addr sesaddr = {};
+ httpd_session_get_addr(sess, &sesaddr);
+ http_session_addr_ntop(&sesaddr, sess_addr_string, sizeof(sess_addr_string));
+
+ if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] == NULL)
+ {
+ const char *human_addr_cstr = session_get_readable_addr(sess);
+ if (NULL == human_addr_cstr)
+ {
+ fprintf(stderr, "can't get readable_addr, to use session_get_readable_addr() the log level must <= INFO\n");
+ return;
+ }
+ assert(0 == strncasecmp(human_addr_cstr, sess_addr_string, strlen(sess_addr_string)));
+ char result_name[MAX_KEY_STR_LEN] = {0};
+ gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] = cJSON_CreateObject();
+ cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], GTEST_HTTP_TUPLE4_NAME, human_addr_cstr);
+ sprintf(result_name, "%d", g_result_count++);
+ commit_test_result_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION]);
+ }
+ }
+
+ static void req_line_to_json(cJSON *ctx, const struct http_request_line *req_line)
+ {
+ http_field_to_json(ctx, "method", (char *)req_line->method, req_line->method_len);
+ http_field_to_json(ctx, "uri", (char *)req_line->uri, req_line->uri_len);
+ http_field_to_json(ctx, "req_version", (char *)req_line->version, req_line->version_len);
+ cJSON_AddNumberToObject(ctx, "major_version", req_line->major_version);
+ cJSON_AddNumberToObject(ctx, "minor_version", req_line->minor_version);
+ }
+
+ static void http_gtest_status_line_to_json(cJSON *ctx, const struct http_status_line *res_line)
+ {
+ http_field_to_json(ctx, "res_version", (char *)res_line->version, res_line->version_len);
+ http_field_to_json(ctx, "res_status", (char *)res_line->status, res_line->status_len);
+ cJSON_AddNumberToObject(ctx, "major_version", res_line->major_version);
+ cJSON_AddNumberToObject(ctx, "minor_version", res_line->minor_version);
+ cJSON_AddNumberToObject(ctx, "status_code", res_line->status_code);
+ }
+
+ static void http_gtest_header_buf_to_json(cJSON *ctx, const char *header_buf, size_t buf_len)
+ {
+ if (NULL == header_buf || 0 == buf_len)
+ {
+ return;
+ }
+ http_field_to_json(ctx, GTEST_HTTP_ALL_HEADERS, (char *)header_buf, buf_len);
+ }
+
+ static void http_gtest_append_body(struct http_gtest_exdata *gtest_plug_exdata, enum payload_compress_mode mode,
+ const char *body, size_t body_sz, enum http_transaction_type type)
+ {
+ if (NULL == body || 0 == body_sz)
+ {
+ return;
+ }
+ if (NULL == gtest_plug_exdata->payload_md5ctx[mode][type])
+ {
+ gtest_plug_exdata->payload_md5ctx[mode][type] = MMALLOC(MD5_CTX, sizeof(MD5_CTX));
+ MD5Init(gtest_plug_exdata->payload_md5ctx[mode][type]);
+ }
+ MD5Update(gtest_plug_exdata->payload_md5ctx[mode][type], (unsigned char *)body, body_sz);
+#if SAVE_BODY_AS_LOCAL_FILE
+ if (NULL == gtest_plug_exdata->body_fp[type])
+ {
+ const char *filename = (type == HTTP_TRANSACTION_REQ) ? "gtest_request.body" : "gtest_response.body";
+ gtest_plug_exdata->body_fp[type] = fopen(filename, "w+");
+ }
+ fwrite(body, body_sz, 1, gtest_plug_exdata->body_fp[type]);
+#endif
+ }
+
+ static int http_request_flow_is_finished(const struct http_request_line *req_line, const struct http_header *header)
+ {
+ if (strncasecmp(req_line->method, "get", 3) == 0)
+ {
+ return 1;
+ }
+ if (header->content_length == 0)
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+ static void http_gtest_on_request_header_cb(struct session *sess, int transaction_seq,
+ const struct http_request_line *req_line,
+ const struct http_header *header,
+ const char *url, size_t url_sz,
+ void *args)
+ {
+ struct http_gtest_env *env = (struct http_gtest_env *)args;
+ struct http_gtest_exdata *http_ext = (struct http_gtest_exdata *)session_get_exdata(sess, env->exdata_idx);
+ if (NULL == http_ext)
+ {
+ http_ext = (struct http_gtest_exdata *)calloc(1, sizeof(struct http_gtest_exdata));
+ session_set_exdata(sess, env->exdata_idx, http_ext);
+ }
+
+ http_gtest_update_session_tuple4(sess, http_ext);
+
+ cJSON *cur_flow_json = http_ext->result_jnode[HTTP_TRANSACTION_REQ];
+ if (NULL == cur_flow_json)
+ {
+ http_ext->result_jnode[HTTP_TRANSACTION_REQ] = cJSON_CreateObject();
+ cur_flow_json = http_ext->result_jnode[HTTP_TRANSACTION_REQ];
+ cJSON_AddStringToObject(cur_flow_json, GTEST_HTTP_TRANS_NAME, "request");
+ }
+
+ http_gtest_trans_id_to_json(cur_flow_json, transaction_seq);
+ req_line_to_json(cur_flow_json, req_line);
+ int uniq_name_count = 0;
+ for (size_t i = 0; i < header->field_array_num; i++)
+ {
+ http_header_to_json(cur_flow_json, &header->field_array[i], &uniq_name_count);
+ }
+ http_gtest_url_add_to_json(cur_flow_json, url, url_sz);
+ http_gtest_header_buf_to_json(cur_flow_json, header->header_buf, header->header_buf_sz);
+
+ if (http_request_flow_is_finished(req_line, header))
+ {
+ cJSON_AddItemToArray(gtest_http_json_root, http_ext->result_jnode[HTTP_TRANSACTION_REQ]);
+ http_ext->result_jnode[HTTP_TRANSACTION_REQ] = NULL;
+ }
+ }
+
+ static int http_response_flow_is_finished(const struct http_status_line *status_line, const struct http_header *header)
+ {
+ if (100 == status_line->status_code)
+ {
+ return 1;
+ }
+ if (header->content_length == 0)
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+ static void http_gtest_on_response_header_cb(struct session *sess, int transaction_seq,
+ const struct http_status_line *status_line,
+ const struct http_header *header,
+ void *args)
+ {
+ struct http_gtest_env *env = (struct http_gtest_env *)args;
+ struct http_gtest_exdata *http_ext = (struct http_gtest_exdata *)session_get_exdata(sess, env->exdata_idx);
+ if (NULL == http_ext)
+ {
+ http_ext = (struct http_gtest_exdata *)calloc(1, sizeof(struct http_gtest_exdata));
+ session_set_exdata(sess, env->exdata_idx, http_ext);
+ }
+
+ http_gtest_update_session_tuple4(sess, http_ext);
+
+ cJSON *cur_flow_json = http_ext->result_jnode[HTTP_TRANSACTION_RES];
+ if (NULL == cur_flow_json)
+ {
+ http_ext->result_jnode[HTTP_TRANSACTION_RES] = cJSON_CreateObject();
+ cur_flow_json = http_ext->result_jnode[HTTP_TRANSACTION_RES];
+ cJSON_AddStringToObject(cur_flow_json, GTEST_HTTP_TRANS_NAME, "response");
+ }
+
+ http_gtest_trans_id_to_json(cur_flow_json, transaction_seq);
+ http_gtest_status_line_to_json(cur_flow_json, status_line);
+ int uniq_name_count = 0;
+ for (size_t i = 0; i < header->field_array_num; i++)
+ {
+ http_header_to_json(cur_flow_json, &header->field_array[i], &uniq_name_count);
+ }
+ http_gtest_header_buf_to_json(cur_flow_json, header->header_buf, header->header_buf_sz);
+
+ if (http_response_flow_is_finished(status_line, header))
+ {
+ cJSON_AddItemToArray(gtest_http_json_root, http_ext->result_jnode[HTTP_TRANSACTION_RES]);
+ http_ext->result_jnode[HTTP_TRANSACTION_RES] = NULL;
+ }
+ }
+
+ static void http_gtest_on_body_cb(struct session *sess, const char *body, size_t body_sz, size_t offset,
+ int transaction_seq, int is_finished, void *args, enum http_transaction_type trans_type)
+ {
+ (void)offset;
+ (void)transaction_seq;
+ struct http_gtest_env *env = (struct http_gtest_env *)args;
+ struct http_gtest_exdata *http_ext = (struct http_gtest_exdata *)session_get_exdata(sess, env->exdata_idx);
+ http_gtest_append_body(http_ext, PAYLOAD_DECOMPRESS, body, body_sz, trans_type);
+ if (is_finished)
+ {
+ http_gtest_commit_body_md5(http_ext->result_jnode[trans_type], http_ext, trans_type);
+ cJSON_AddItemToArray(gtest_http_json_root, http_ext->result_jnode[trans_type]);
+ http_ext->result_jnode[trans_type] = NULL;
+ }
+ }
+ static void http_gtest_on_reqbody_cb(struct session *sess, const char *body, size_t body_sz, size_t offset,
+ int transaction_seq, int is_finished, void *args)
+ {
+ http_gtest_on_body_cb(sess, body, body_sz, offset, transaction_seq, is_finished, args, HTTP_TRANSACTION_REQ);
+ }
+ static void http_gtest_on_resbody_cb(struct session *sess, const char *body, size_t body_sz, size_t offset,
+ int transaction_seq, int is_finished, void *args)
+ {
+ http_gtest_on_body_cb(sess, body, body_sz, offset, transaction_seq, is_finished, args, HTTP_TRANSACTION_RES);
+ }
+
+ static void http_gtest_session_exdata_free_cb(int idx, void *ex_ptr, void *arg)
+ {
+ (void)idx;
+ (void)arg;
+ struct http_gtest_exdata *http_ext = (struct http_gtest_exdata *)ex_ptr;
+#if SAVE_BODY_AS_LOCAL_FILE
+ if (http_ext && http_ext->body_fp[HTTP_TRANSACTION_REQ])
+ {
+ fclose(http_ext->body_fp[HTTP_TRANSACTION_REQ]);
+ }
+ if (http_ext && http_ext->body_fp[HTTP_TRANSACTION_RES])
+ {
+ fclose(http_ext->body_fp[HTTP_TRANSACTION_RES]);
+ }
+#endif
+ if (http_ext)
+ {
+ for (int i = 0; i < PAYLOAD_MAX; i++)
+ {
+ for (int j = 0; j < HTTP_TRANSACTION_MAX; j++)
+ {
+ http_gtest_commit_body_md5(http_ext->result_jnode[j], http_ext, (enum http_transaction_type)j);
+ }
+ }
+ }
+ if (http_ext && gtest_http_json_root)
+ {
+ if (http_ext->result_jnode[HTTP_TRANSACTION_REQ])
+ {
+ cJSON_AddItemToArray(gtest_http_json_root, http_ext->result_jnode[HTTP_TRANSACTION_REQ]);
+ }
+ if (http_ext->result_jnode[HTTP_TRANSACTION_RES])
+ {
+ cJSON_AddItemToArray(gtest_http_json_root, http_ext->result_jnode[HTTP_TRANSACTION_RES]);
+ }
+ free(ex_ptr);
+ }
+ }
+
+ struct module *gtest_http_init(struct module_manager *mod_mgr)
+ {
+ gtest_http_json_root = cJSON_CreateArray();
+ struct http_gtest_env *env = (struct http_gtest_env *)calloc(1, sizeof(struct http_gtest_env));
+ env->mod_mgr = mod_mgr;
+
+ struct module *http_mod = module_manager_get_module(mod_mgr, HTTP_MODULE_NAME);
+ struct http *http = http_module_to_http(http_mod);
+
+ struct http_subscirbe_params sub_para = {};
+ sub_para.req_hdr_cb = http_gtest_on_request_header_cb;
+ sub_para.res_hdr_cb = http_gtest_on_response_header_cb;
+ sub_para.req_body_cb = http_gtest_on_reqbody_cb;
+ sub_para.res_body_cb = http_gtest_on_resbody_cb;
+ http_subscribe(http, &sub_para, env);
+ struct module *sess_mod = module_manager_get_module(mod_mgr, SESSION_MANAGER_MODULE_NAME);
+ struct session_manager *sess_mgr = module_to_session_manager(sess_mod);
+ env->exdata_idx = session_manager_new_session_exdata_index(sess_mgr, "HTTP_GTEST_EXDATA", http_gtest_session_exdata_free_cb, env);
+ return module_new("GTEST_HTTP", env);
+ }
+
+ void gtest_http_exit(struct module_manager *mod_mgr, struct module *mod)
+ {
+ (void)mod_mgr;
+ struct http_gtest_env *env = (struct http_gtest_env *)module_get_ctx(mod);
+ free(env);
+ char *json_str = cJSON_PrintUnformatted(gtest_http_json_root);
+ FILE *json_fp = fopen(GTEST_RESULT_FILENAME, "w+");
+ fwrite(json_str, strlen(json_str), 1, json_fp);
+ fclose(json_fp);
+ free(json_str);
+ cJSON_Delete(gtest_http_json_root);
+ module_free(mod);
+ return;
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/test/decoders/http/http_module.toml b/test/decoders/http/http_module.toml
new file mode 100644
index 0000000..1274423
--- /dev/null
+++ b/test/decoders/http/http_module.toml
@@ -0,0 +1,11 @@
+#load http module
+[[module]]
+path = ""
+init = "http_init"
+exit = "http_exit"
+
+#load http gtest module
+[[module]]
+path = ""
+init = "gtest_http_init"
+exit = "gtest_http_exit"
diff --git a/test/decoders/http/http_test_plug.cpp b/test/decoders/http/http_test_plug.cpp
deleted file mode 100644
index 8085ab2..0000000
--- a/test/decoders/http/http_test_plug.cpp
+++ /dev/null
@@ -1,674 +0,0 @@
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-
-#include "http.h"
-#include "http_decoder_private.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#include "cJSON.h"
-#include "http_gtest.h"
-#include "md5/md5.h"
-#include "toml/toml.h"
-
- int commit_test_result_json(cJSON *node, const char *name);
- extern void http_decoder_test_entry(struct session *sess, int topic_id, const void *raw_msg, void *no_use_ctx, void *plugin_env);
- extern void http_decoder_test_state_entry(struct session *sess, int topic_id, const void *raw_msg, void *no_use_ctx, void *plugin_env);
- extern void http_decoder_tunnel_entry(struct session *sess, int topic_id, const void *raw_msg, void *no_use_ctx, void *plugin_env);
- static on_session_msg_cb_func *g_entry_fun = http_decoder_test_entry;
-}
-#endif
-
-#define MAX_KEY_STR_LEN 2048
-#define GTEST_PLUG_ENTRY_CFG "./etc/http/gtest_entry.toml"
-
-struct plug_entry_t
-{
- const char *name;
- on_session_msg_cb_func *entry;
-};
-
-static struct plug_entry_t g_entry_tbl[] = {
- {"http_decoder_test_entry", http_decoder_test_entry},
- {"http_decoder_test_state_entry", http_decoder_test_state_entry},
- {"http_decoder_tunnel_entry", http_decoder_tunnel_entry},
- {NULL, NULL}};
-
-enum http_transaction_type
-{
- HTTP_TRANSACTION_REQ = 0,
- HTTP_TRANSACTION_RES,
- HTTP_TRANSACTION_SESSION, // global session info
- HTTP_TRANSACTION_MAX
-};
-
-enum payload_compress_mode
-{
- PAYLOAD_RAW = 0,
- PAYLOAD_DECOMPRESS = 1,
- PAYLOAD_MAX = 2,
-};
-
-struct gtest_plug_exdata_t
-{
- cJSON *result_jnode[HTTP_TRANSACTION_MAX];
- MD5_CTX *payload_md5ctx[PAYLOAD_MAX][HTTP_TRANSACTION_MAX];
-};
-
-static int g_result_count = 0;
-static int g_header_count = 1;
-static int g_http_gtest_plugin_id = -1;
-static int g_exdata_idx = -1;
-static int g_topic_id = -1;
-
-#if 0
-void output_http_req_line(struct http_request_line *req_line)
-{
- char tmp_str[MAX_KEY_STR_LEN] = {0};
- memcpy(tmp_str, req_line->method.iov_base, req_line->method.iov_len);
- printf("req_method:%s\n", tmp_str);
-
- memset(tmp_str, 0, sizeof(tmp_str));
- memcpy(tmp_str, req_line->uri.iov_base, req_line->uri.iov_len);
- printf("req_uri:%s\n", tmp_str);
-
- memset(tmp_str, 0, sizeof(tmp_str));
- memcpy(tmp_str, req_line->version.iov_base, req_line->version.iov_len);
- printf("req_version:%s\n", tmp_str);
-}
-
-void output_http_res_line(struct http_response_line *res_line)
-{
- char tmp_str[MAX_KEY_STR_LEN] = {0};
- memcpy(tmp_str, res_line->version.iov_base, res_line->version.iov_len);
- printf("res_version:%s\n", tmp_str);
-
- memset(tmp_str, 0, sizeof(tmp_str));
- memcpy(tmp_str, res_line->status.iov_base, res_line->status.iov_len);
- printf("res_status:%s\n", tmp_str);
-}
-
-void output_http_header(struct http_header_field *header)
-{
- char tmp_key[MAX_KEY_STR_LEN] = {0};
- char tmp_val[MAX_KEY_STR_LEN] = {0};
-
- memcpy(tmp_key, header->key.iov_base, header->key.iov_len);
- memcpy(tmp_val, header->val.iov_base, header->val.iov_len);
- printf("<%s:%s>\n", tmp_key, tmp_val);
-}
-
-void output_http_body(hstring *body, int decompress_flag)
-{
- int counter = 0;
-
- if (1 == decompress_flag)
- {
- printf("\n\n----------------decompress body len:%zu---------------\n",
- body->iov_len);
- }
- else
- {
- printf("\n\n----------------raw body len:%zu---------------\n",
- body->iov_len);
- }
-
- for (size_t i = 0; i < body->iov_len; i++)
- {
- if (counter % 16 == 0)
- {
- printf("\n");
- }
- printf("%02x ", (unsigned char)body->iov_base[i]);
- counter++;
- }
- printf("\n");
-}
-#endif
-
-static void append_http_payload(struct session *sess, struct gtest_plug_exdata_t *gtest_plug_exdata, enum payload_compress_mode mode,
- const hstring *body, enum http_transaction_type type)
-{
- (void)sess;
- if (NULL == body->iov_base || 0 == body->iov_len)
- {
- return;
- }
- if (NULL == gtest_plug_exdata->payload_md5ctx[mode][type])
- {
- gtest_plug_exdata->payload_md5ctx[mode][type] = MMALLOC(MD5_CTX, sizeof(MD5_CTX));
- MD5Init(gtest_plug_exdata->payload_md5ctx[mode][type]);
- }
- MD5Update(gtest_plug_exdata->payload_md5ctx[mode][type], (unsigned char *)body->iov_base, body->iov_len);
-}
-
-int http_field_to_json(cJSON *object, const char *key, char *val, size_t val_len)
-{
- if (NULL == object || NULL == key || NULL == val || 0 == val_len)
- {
- return -1;
- }
-
- char *tmp = CALLOC(char, val_len + 1);
- memcpy(tmp, val, val_len);
- cJSON_AddStringToObject(object, key, tmp);
- FREE(tmp);
-
- return 0;
-}
-
-void transaction_index_to_json(cJSON *ctx, int transaction_index)
-{
- cJSON_AddNumberToObject(ctx, GTEST_HTTP_TRANS_SEQ_NAME, transaction_index);
-}
-
-void req_line_to_json(cJSON *ctx, struct http_request_line *req_line)
-{
- http_field_to_json(ctx, "method", (char *)req_line->method, req_line->method_len);
- http_field_to_json(ctx, "uri", (char *)req_line->uri, req_line->uri_len);
- http_field_to_json(ctx, "req_version", (char *)req_line->version, req_line->version_len);
-
- cJSON_AddNumberToObject(ctx, "major_version", req_line->major_version);
- cJSON_AddNumberToObject(ctx, "minor_version", req_line->minor_version);
-}
-
-void res_line_to_json(cJSON *ctx, struct http_response_line *res_line)
-{
- http_field_to_json(ctx, "res_version", (char *)res_line->version, res_line->version_len);
- http_field_to_json(ctx, "res_status", (char *)res_line->status, res_line->status_len);
-
- cJSON_AddNumberToObject(ctx, "major_version", res_line->major_version);
- cJSON_AddNumberToObject(ctx, "minor_version", res_line->minor_version);
- cJSON_AddNumberToObject(ctx, "status_code", res_line->status_code);
-}
-
-void http_header_to_json(cJSON *ctx, struct http_header_field *header)
-{
- char key[MAX_KEY_STR_LEN] = {0};
- if ((header->name == NULL) || (header->value == NULL))
- {
- return;
- }
-
- memcpy(key, header->name, header->name_len);
-
- if (cJSON_HasObjectItem(ctx, key) == FALSE)
- {
- http_field_to_json(ctx, key, (char *)header->value, header->value_len);
- }
- else
- {
- // ctx already has the key, so rename key by key%d
- char new_key[header->value_len + 64] = {0};
- snprintf(new_key, sizeof(new_key), "%s%d", key, g_header_count++);
- http_field_to_json(ctx, new_key, (char *)header->value, header->value_len);
- }
-}
-
-void http_url_add_to_json(cJSON *ctx, struct http_message *msg)
-{
- hstring raw_url_result = {};
-
- if (cJSON_GetObjectItem(ctx, GTEST_HTTP_URL_NAME))
- {
- return;
- }
-
- http_message_get0_raw_url(msg, (const char **)&raw_url_result, &raw_url_result.iov_len);
- if (raw_url_result.iov_base == NULL)
- {
- return;
- }
-
- struct http_header_field raw_url_header_result = {};
-
- raw_url_header_result.name = (char *)GTEST_HTTP_URL_NAME;
- raw_url_header_result.name_len = strlen(GTEST_HTTP_URL_NAME);
- raw_url_header_result.value = (char *)raw_url_result.iov_base;
- raw_url_header_result.value_len = raw_url_result.iov_len;
-
- http_header_to_json(ctx, &raw_url_header_result);
-
- char decoded_url_buffer[raw_url_result.iov_len] = {0};
- size_t decode_url_len = http_url_decode((const char *)raw_url_result.iov_base, raw_url_result.iov_len, decoded_url_buffer, sizeof(decoded_url_buffer));
-
- if (decode_url_len < raw_url_result.iov_len)
- {
- struct http_header_field decode_url_header_result = {};
- decode_url_header_result.name = (char *)"__X_HTTP_DECODED_URL";
- decode_url_header_result.name_len = strlen("__X_HTTP_DECODED_URL");
- decode_url_header_result.value = decoded_url_buffer;
- decode_url_header_result.value_len = decode_url_len;
- http_header_to_json(ctx, &decode_url_header_result);
- }
-}
-
-static void commit_payload_md5sum(cJSON *last_jnode, struct gtest_plug_exdata_t *gtest_plug_exdata, enum http_transaction_type type)
-{
- // finish md5 streming hash
- for (int mode = 0; mode < PAYLOAD_MAX; mode++)
- {
- if (gtest_plug_exdata->payload_md5ctx[mode][type])
- {
- unsigned char md5_result_bin[16] = {0};
- unsigned char md5_result_cstr[33] = {0};
- MD5Final(md5_result_bin, gtest_plug_exdata->payload_md5ctx[mode][type]);
-
- for (int i = 0; i < 16; i++)
- sprintf((char *)md5_result_cstr + 2 * i, "%02x", md5_result_bin[i]);
- md5_result_cstr[32] = '\0';
- if (mode == PAYLOAD_RAW)
- {
- cJSON_AddStringToObject(last_jnode, GTEST_HTTP_RAW_PAYLOAD_MD5_NAME, (char *)md5_result_cstr);
- }
- else
- {
- cJSON_AddStringToObject(last_jnode, GTEST_HTTP_DECOMPRESS_PAYLOAD_MD5_NAME, (char *)md5_result_cstr);
- }
- FREE(gtest_plug_exdata->payload_md5ctx[mode][type]);
- gtest_plug_exdata->payload_md5ctx[mode][type] = NULL;
- }
- }
-}
-
-// Full duplex
-static void commit_last_half_flow_data(struct gtest_plug_exdata_t *gtest_plug_exdata,
- struct http_message *msg, enum http_transaction_type type, int final)
-{
- char result_name[MAX_KEY_STR_LEN] = {0};
-
- cJSON *last_jnode = gtest_plug_exdata->result_jnode[type];
- if (last_jnode)
- {
- commit_payload_md5sum(last_jnode, gtest_plug_exdata, type);
- sprintf(result_name, "%d", g_result_count);
- commit_test_result_json(last_jnode, result_name);
- gtest_plug_exdata->result_jnode[type] = NULL;
- g_result_count++;
- }
-
- if (0 == final)
- {
- gtest_plug_exdata->result_jnode[type] = cJSON_CreateObject();
- if (HTTP_TRANSACTION_REQ == type)
- {
- cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[type], GTEST_HTTP_TRANS_NAME, "request");
- }
- else if (HTTP_TRANSACTION_RES == type)
- {
- cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[type], GTEST_HTTP_TRANS_NAME, "response");
- }
- if (msg)
- {
- transaction_index_to_json(gtest_plug_exdata->result_jnode[type], http_message_get_transaction_seq(msg));
- }
- }
-}
-
-static void http_decoder_test_update_session_tuple4(struct session *sess, struct gtest_plug_exdata_t *gtest_plug_exdata)
-{
- if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] == NULL)
- {
- const char *human_addr_cstr = session_get_readable_addr(sess);
- if (NULL == human_addr_cstr)
- {
- fprintf(stderr, "can't get readable_addr, to use session_get_readable_addr() the sapp_log.conf level must <= INFO\n");
- return;
- }
- char result_name[MAX_KEY_STR_LEN] = {0};
- gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] = cJSON_CreateObject();
- cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], GTEST_HTTP_TUPLE4_NAME, human_addr_cstr);
- sprintf(result_name, "%d", g_result_count++);
- commit_test_result_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], result_name);
- }
-}
-
-static int get_gtest_plug_entry(const char *cfg_path, char *entry_name, int max_len, char *topic_name, int topic_max_len)
-{
- FILE *fp = fopen(cfg_path, "r");
- if (NULL == fp)
- {
- fprintf(stderr, "[%s:%d]Can't open config file:%s",
- __FUNCTION__, __LINE__, cfg_path);
- return -1;
- }
-
- char errbuf[256] = {0};
-
- toml_table_t *root = toml_parse_file(fp, errbuf, sizeof(errbuf));
- fclose(fp);
-
- toml_table_t *basic_sec_tbl = toml_table_in(root, "entry");
- if (NULL == basic_sec_tbl)
- {
- fprintf(stderr, "[%s:%d]config file:%s has no key: [entry]",
- __FUNCTION__, __LINE__, cfg_path);
- toml_free(root);
- return -1;
- }
-
- toml_datum_t str_val = toml_string_in(basic_sec_tbl, "name");
- if (str_val.ok != 0)
- {
- strncpy(entry_name, str_val.u.s, max_len);
- free(str_val.u.s);
- }
-
- toml_datum_t topic_str_val = toml_string_in(basic_sec_tbl, "topic");
- if (str_val.ok != 0)
- {
- strncpy(topic_name, topic_str_val.u.s, topic_max_len);
- free(topic_str_val.u.s);
- }
-
- toml_free(root);
- return 0;
-}
-
-static void set_gtest_plug_entry(const char *entry_name)
-{
- if (NULL == entry_name)
- {
- g_entry_fun = http_decoder_test_entry; // set default
- return;
- }
- for (size_t i = 0; g_entry_tbl[i].name != NULL; i++)
- {
- if (strcmp(entry_name, g_entry_tbl[i].name) == 0)
- {
- g_entry_fun = g_entry_tbl[i].entry;
- return;
- }
- }
- g_entry_fun = http_decoder_test_entry; // set default
-}
-
-extern "C" void http_decoder_test_entry(struct session *sess, int topic_id, const void *raw_msg, void *no_use_ctx, void *plugin_env)
-{
- (void)topic_id;
- (void)no_use_ctx;
- (void)plugin_env;
- struct http_request_line req_line = {};
- struct http_response_line res_line = {};
- struct http_header_field header = {};
- hstring body = {};
- struct http_message *msg = (struct http_message *)raw_msg;
- enum http_message_type msg_type = http_message_get_type(msg);
-
- struct gtest_plug_exdata_t *gtest_plug_exdata = (struct gtest_plug_exdata_t *)session_exdata_get(sess, g_exdata_idx);
- if (NULL == gtest_plug_exdata)
- {
- gtest_plug_exdata = (struct gtest_plug_exdata_t *)calloc(1, sizeof(struct gtest_plug_exdata_t));
- session_exdata_set(sess, g_exdata_idx, gtest_plug_exdata);
- }
-
- // if (http_message_type_is_req(sess, msg_type))
- // {
- // cJSON *json = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ];
- // }
- // else
- // {
- // cJSON *json = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES];
- // }
-
- http_decoder_test_update_session_tuple4(sess, gtest_plug_exdata);
-
- switch (msg_type)
- {
- case HTTP_MESSAGE_REQ_LINE:
- commit_last_half_flow_data(gtest_plug_exdata, msg, HTTP_TRANSACTION_REQ, 0);
- http_message_get0_request_line(msg, &req_line);
- req_line_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], &req_line);
- break;
- case HTTP_MESSAGE_REQ_HEADER:
- while (http_message_get0_next_header(msg, &header) >= 0)
- {
- http_header_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], &header);
- }
- g_header_count = 1;
- break;
- case HTTP_MESSAGE_REQ_HEADER_END:
- http_url_add_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], msg);
- break;
- case HTTP_MESSAGE_REQ_BODY_START:
- case HTTP_MESSAGE_REQ_BODY:
- memset(&body, 0, sizeof(hstring));
- http_message_get0_uncompressed_body(msg, (const char **)&body.iov_base, &body.iov_len);
- if (body.iov_base && body.iov_len)
- {
- append_http_payload(sess, gtest_plug_exdata, PAYLOAD_RAW, &body, HTTP_TRANSACTION_REQ);
- }
- // output_http_body(&body, 0);
- http_message_get0_decompressed_body(msg, (const char **)&body.iov_base, &body.iov_len);
- // output_http_body(&body, 1);
- if (body.iov_base && body.iov_len)
- {
- append_http_payload(sess, gtest_plug_exdata, PAYLOAD_DECOMPRESS, &body, HTTP_TRANSACTION_REQ);
- }
- break;
- case HTTP_MESSAGE_RES_LINE:
- commit_last_half_flow_data(gtest_plug_exdata, msg, HTTP_TRANSACTION_RES, 0);
- http_message_get0_response_line(msg, &res_line);
- res_line_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], &res_line);
- break;
- case HTTP_MESSAGE_RES_HEADER:
- while (http_message_get0_next_header(msg, &header) >= 0)
- {
- http_header_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], &header);
- }
- g_header_count = 1;
- break;
- case HTTP_MESSAGE_RES_BODY_START:
- case HTTP_MESSAGE_RES_BODY:
- memset(&body, 0, sizeof(hstring));
- http_message_get0_uncompressed_body(msg, (const char **)&body.iov_base, &body.iov_len);
- if (body.iov_base && body.iov_len)
- {
- append_http_payload(sess, gtest_plug_exdata, PAYLOAD_RAW, &body, HTTP_TRANSACTION_RES);
- }
- // output_http_body(&body, 0);
- memset(&body, 0, sizeof(hstring));
- http_message_get0_decompressed_body(msg, (const char **)&body.iov_base, &body.iov_len);
- // output_http_body(&body, 1);
- if (body.iov_base && body.iov_len)
- {
- append_http_payload(sess, gtest_plug_exdata, PAYLOAD_DECOMPRESS, &body, HTTP_TRANSACTION_RES);
- }
- break;
-
- // to do: check payload
- default:
- break;
- }
-
- return;
-}
-
-void http_decoder_test_exdata_free(int idx, void *ex_ptr, void *arg)
-{
- (void)idx;
- (void)arg;
- if (ex_ptr != NULL)
- {
- struct gtest_plug_exdata_t *gtest_plug_exdata = (struct gtest_plug_exdata_t *)ex_ptr;
- if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ])
- {
- commit_last_half_flow_data(gtest_plug_exdata, NULL, HTTP_TRANSACTION_REQ, 1);
- }
- if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES])
- {
- commit_last_half_flow_data(gtest_plug_exdata, NULL, HTTP_TRANSACTION_RES, 1);
- }
- free(ex_ptr);
- }
-}
-
-// static int update_config_file(const char *filename, const char *key, const char *value)
-// {
-// char cmd_buf[1024] = {};
-// snprintf(cmd_buf, 1024, "sed 's/^[ \t]*%s=.*/%s=%s/g' -i %s", key, key, value, filename);
-// int ret = system(cmd_buf);
-// return ret;
-// }
-
-extern "C" void http_decoder_test_state_entry(struct session *sess, int topic_id, const void *raw_msg, void *no_use_ctx, void *plugin_env)
-{
- (void)topic_id;
- (void)no_use_ctx;
- (void)plugin_env;
- static int msg_index = 0;
- char msg_index_name[64] = {};
- char msg_index_value[64] = {};
- cJSON *json_object = NULL;
- enum http_message_type msg_type = http_message_get_type((struct http_message *)raw_msg);
-
- struct gtest_plug_exdata_t *gtest_plug_exdata = (struct gtest_plug_exdata_t *)session_exdata_get(sess, g_exdata_idx);
- if (NULL == gtest_plug_exdata)
- {
- gtest_plug_exdata = (struct gtest_plug_exdata_t *)calloc(1, sizeof(struct gtest_plug_exdata_t));
- gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ] = cJSON_CreateObject();
- gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES] = cJSON_CreateObject();
- session_exdata_set(sess, g_exdata_idx, gtest_plug_exdata);
- }
-
- if (http_message_type_is_req(sess, msg_type))
- {
- json_object = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ];
- }
- else
- {
- json_object = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES];
- }
- if (HTTP_TRANSACTION_END == msg_type)
- {
- unsigned char flow_flag;
- session_is_symmetric(sess, &flow_flag);
- if (SESSION_SEEN_C2S_FLOW == flow_flag)
- {
- json_object = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ];
- }
- else if (SESSION_SEEN_S2C_FLOW == flow_flag)
- {
- json_object = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES];
- }
- else
- { // is symmetric
- json_object = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES];
- }
- }
- int cur_transaction_id = http_message_get_transaction_seq((const http_message *)raw_msg);
-
- if (HTTP_TRANSACTION_START == msg_type || HTTP_TRANSACTION_END == msg_type)
- {
- snprintf(msg_index_name, sizeof(msg_index_name), "msg_%d", msg_index++);
- snprintf(msg_index_value, sizeof(msg_index_value), "%s_transaction_%d", http_message_type_to_string(msg_type), cur_transaction_id);
- cJSON_AddStringToObject(json_object, msg_index_name, msg_index_value);
- }
- else
- {
- snprintf(msg_index_name, sizeof(msg_index_name), "msg_%d", msg_index++);
- cJSON_AddStringToObject(json_object, msg_index_name, http_message_type_to_string(msg_type));
- }
- return;
-}
-
-extern "C" void http_decoder_tunnel_entry(struct session *sess, int topic_id, const void *raw_msg, void *no_use_ctx, void *plugin_env)
-{
- (void)topic_id;
- (void)no_use_ctx;
- (void)plugin_env;
- struct gtest_plug_exdata_t *gtest_plug_exdata;
- enum http_tunnel_message_type tmsg_type = http_tunnel_message_type_get((const struct http_tunnel_message *)raw_msg);
- static size_t req_payload_block = 0, req_payload_size = 0;
- static size_t res_payload_block = 0, res_payload_size = 0;
- gtest_plug_exdata = (struct gtest_plug_exdata_t *)session_exdata_get(sess, g_exdata_idx);
-
- switch (tmsg_type)
- {
- case HTTP_TUNNEL_OPENING:
- {
- if (NULL == gtest_plug_exdata)
- {
- gtest_plug_exdata = (struct gtest_plug_exdata_t *)calloc(1, sizeof(struct gtest_plug_exdata_t));
- session_exdata_set(sess, g_exdata_idx, gtest_plug_exdata);
- }
- const char *human_addr_cstr = session_get_readable_addr(sess);
- gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ] = cJSON_CreateObject();
- gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES] = cJSON_CreateObject();
- gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] = cJSON_CreateObject();
- cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], GTEST_HTTP_TUPLE4_NAME, human_addr_cstr);
- commit_test_result_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], "TUNNEL_NEW");
- }
- break;
-
- case HTTP_TUNNEL_ACTIVE:
- {
- enum flow_type curdir = session_get_flow_type(sess);
- hstring tunnel_payload = {};
- http_tunnel_message_get_payload((const struct http_tunnel_message *)raw_msg, &tunnel_payload);
- if (FLOW_TYPE_C2S == curdir)
- {
- req_payload_block++;
- req_payload_size += tunnel_payload.iov_len;
- }
- else
- {
- res_payload_block++;
- res_payload_size += tunnel_payload.iov_len;
- }
- }
- break;
- case HTTP_TUNNEL_CLOSING:
- {
- cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], "flow", "C2S");
- cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], "flow", "S2C");
- cJSON_AddNumberToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], "payload_block", req_payload_block);
- cJSON_AddNumberToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], "payload_size", req_payload_size);
- cJSON_AddNumberToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], "payload_block", res_payload_block);
- cJSON_AddNumberToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], "payload_size", res_payload_size);
- }
- break;
- default:
- assert(0);
- break;
- }
-}
-
-extern "C" void *http_decoder_test_init(struct stellar *st)
-{
- g_http_gtest_plugin_id = stellar_session_plugin_register(st, NULL, NULL, NULL);
- g_exdata_idx = stellar_exdata_new_index(st, "HTTP_DECODER_GTEST_EXDATA", http_decoder_test_exdata_free, NULL);
- if (g_exdata_idx < 0)
- {
- printf("[%s:%d]: can't get http_decoder exdata index !!!\n", __FUNCTION__, __LINE__);
- return NULL;
- }
-
- char entry_name[64] = "";
- char topic_name[64] = "";
- get_gtest_plug_entry(GTEST_PLUG_ENTRY_CFG, entry_name, sizeof(entry_name) - 1, topic_name, sizeof(topic_name) - 1);
- set_gtest_plug_entry(entry_name);
- g_topic_id = stellar_mq_get_topic_id(st, topic_name);
- if (g_topic_id < 0)
- {
- printf("[%s:%d]: can't get http_decoder topic:%s id !!!\n", __FUNCTION__, __LINE__, topic_name);
- return NULL;
- }
- stellar_session_mq_subscribe(st, g_topic_id, g_entry_fun, g_http_gtest_plugin_id);
- printf("http_decoder_gtest_init succ, plugin_id:%d, sub_topic_id:%d\n", g_http_gtest_plugin_id, g_topic_id);
-
- return (void *)strdup("http_decoder_test_ctx");
-}
-
-extern "C" void http_decoder_test_exit(void *test_ctx)
-{
- if (test_ctx != NULL)
- {
- FREE(test_ctx);
- }
- printf("http_decoder_test_exit OK!\n");
-} \ No newline at end of file
diff --git a/test/decoders/http/test_based_on_stellar/CMakeLists.txt b/test/decoders/http/test_based_on_stellar/CMakeLists.txt
deleted file mode 100644
index bc08289..0000000
--- a/test/decoders/http/test_based_on_stellar/CMakeLists.txt
+++ /dev/null
@@ -1,125 +0,0 @@
-set(DECODER_NAME http)
-
-set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/test/decoders/http)
-set(SAPP_DEVEL_DIR ${TEST_RUN_DIR}/lib)
-set(TEST_MAIN http_test_main)
-
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_SOURCE_DIR}/test)
-
-#various ways to add -rdynamic for centos7, centos8, and different cmake version
-add_definitions(-rdynamic)
-
-# assemble test env
-add_test(NAME HTTP_MKDIR_METRIC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/metrics; mkdir -p ${TEST_RUN_DIR}/plugin; mkdir -p ${TEST_RUN_DIR}/log; mkdir -p ${TEST_RUN_DIR}/pcap")
-add_test(NAME HTTP_COPY_SPEC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plugin/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/spec.toml ${TEST_RUN_DIR}/plugin/spec.toml")
-add_test(NAME HTTP_COPY_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/stellar.toml ${TEST_RUN_DIR}/conf/stellar.toml")
-add_test(NAME HTTP_COPY_LOG_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/conf/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/log.toml ${TEST_RUN_DIR}/conf/log.toml")
-add_test(NAME HTTP_COPY_HTTP_DECODER_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/etc/http && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/http_decoder.toml ${TEST_RUN_DIR}/etc/http/")
-add_test(NAME HTTP_COPY_HTTP_GTEST_ENTRY_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/etc/http && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/gtest_entry.toml ${TEST_RUN_DIR}/etc/http/")
-
-# update config files
-add_test(NAME HTTP_UPDATE_GTEST_PLUG_ENTRY COMMAND bash -c "sed -i 's/name=.*/name=\\x22http_decoder_test_entry\\x22/' ${TEST_RUN_DIR}/etc/http/gtest_entry.toml")
-add_test(NAME HTTP_UPDATE_GTEST_PLUG_TOPIC COMMAND bash -c "sed -i 's/topic=.*/topic=\\x22HTTP_MESSAGE\\x22/' ${TEST_RUN_DIR}/etc/http/gtest_entry.toml")
-
-# update plugin to be tested
-add_test(NAME HTTP_CP_DECODER_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/decoders/http/http_dyn.so ${TEST_RUN_DIR}/plugin/http.so")
-add_test(NAME HTTP_CP_DECODER_GTEST_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/decoders/http/http_test.so ${TEST_RUN_DIR}/plugin/http_test.so")
-
-set_tests_properties(HTTP_MKDIR_METRIC HTTP_COPY_SPEC HTTP_COPY_HTTP_DECODER_CONF HTTP_COPY_HTTP_GTEST_ENTRY_CONF
- HTTP_COPY_CONF HTTP_COPY_LOG_CONF
- HTTP_CP_DECODER_SO HTTP_CP_DECODER_GTEST_SO
- HTTP_UPDATE_GTEST_PLUG_ENTRY HTTP_UPDATE_GTEST_PLUG_TOPIC
- PROPERTIES FIXTURES_SETUP HTTP_GTEST)
-
-set(TEST_JSON_DIR ${PROJECT_SOURCE_DIR}/test/decoders/http/benchmarks/json)
-set(TEST_PCAP_DIR ${PROJECT_SOURCE_DIR}/test/decoders/http/benchmarks/pcap)
-
-# run tests
-add_test(NAME HTTP_GET_SINGLE_TRANS_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_get_single_trans.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_get_single_trans.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_GET_MULTI_TRANS_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_get_multi_trans.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_get_multi_trans.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_GET_LONG_COOKIE_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_get_long_cookie.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_get_long_cookie.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_GET_ENCODED_URI_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_get_encoded_uri.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_get_encoded_uri.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_RES_GZIP_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_res_gzip.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_res_gzip.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_CHUNKED_RES_GZIP_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_chunked_res_gzip.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_chunked_res_gzip.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_OVER_TCP_KEEPALIVE_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_over_tcp_keepalive.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_over_tcp_keepalive.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_OVER_PPPOE_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_over_pppoe.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_over_pppoe.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_OVER_TLS_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_over_tls.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_over_tls.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME NON_HTTP_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/non_http.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/non_http.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_REQ_1BYTE_SLIDING_WINDOW_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_req_1byte_sliding_window.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_req_1byte_sliding_window.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_RES_1BYTE_SLIDING_WINDOW_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_res_1byte_sliding_window.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_res_1byte_sliding_window.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_NO_CONTENT_LENGTH_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_no_content_length.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_no_content_length.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_POST_MULTIPART_FORM_DATA_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_post_multipart_form_data.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_post_multipart_form_data.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_HEADERS_EXCEED_MAXIMUM_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_hdrs_exceed_maximum.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_hdrs_exceed_maximum.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_GET_MALFORMED_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_get_malformed.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_get_malformed.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_URL_WITHOUT_HOST_V4_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_url_test_without_host.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_url_test_without_host.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_URL_WITHOUT_HOST_V6_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_url_test_without_host_v6.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_url_test_without_host_v6.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-#no SYN, steallar not support !
-# add_test(NAME HTTP_HEADER_VALUE_EMPTY_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_hdr_value_empty.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_hdr_value_empty.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_UPGRADE_WEBSOCKET_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_upgrade_websocket.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_upgrade_websocket.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_MULTI_PARSE_ERROR_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_multi_parse_error.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_multi_parse_error.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_GET_REQ_PIPELINE_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_get_req_pipeline.pcap ${TEST_RUN_DIR}/pcap/test.pcap;./${TEST_MAIN} ${TEST_JSON_DIR}/http_get_req_pipeline.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_TRANS_PIPELINE_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_trans_pipeline.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_trans_pipeline.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-#no SYN, steallar not support !
-# add_test(NAME HTTP_HEADER_TRUNCATED_IN_KV_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_hdr_truncated_in_kv.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_hdr_truncated_in_kv.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-# add_test(NAME HTTP_HEADER_TRUNCATED_AFTER_KV_TEST COMMAND ./${TEST_MAIN} ${TEST_JSON_DIR}/http_hdr_truncated_after_kv.json -r ${TEST_PCAP_DIR}/http_hdr_truncated_after_kv.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_FIN_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_fin.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/non_http.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-# add_test(NAME HTTP_TUNNEL_ONLY_HDR_TEST COMMAND ./${TEST_MAIN} ${TEST_JSON_DIR}/http_tunnel_s2c_only_hdr.json
-# -r ${TEST_PCAP_DIR}/http_tunnel_s2c_only_hdr.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_CHN_ENCODE_URL COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_chn_encode_url.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_chn_encode_url.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_ZLIB_DEADLOCK COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_zlib_deadlock.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_zlib_deadlock.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_OUT_OF_ORDER COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_out_of_order.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_out_of_order.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_GZIP_OUT_OF_ORDER COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_gzip_out_of_order.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_gzip_out_of_order.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_HEADER_SPLITTING COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_pipeline_header_splitting.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_pipeline_header_splitting.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-set_tests_properties(HTTP_GET_SINGLE_TRANS_TEST
- HTTP_GET_MULTI_TRANS_TEST
- HTTP_GET_LONG_COOKIE_TEST
- HTTP_GET_ENCODED_URI_TEST
- HTTP_RES_GZIP_TEST
- HTTP_CHUNKED_RES_GZIP_TEST
- HTTP_OVER_TCP_KEEPALIVE_TEST
- HTTP_OVER_PPPOE_TEST
- HTTP_OVER_TLS_TEST
- NON_HTTP_TEST
- HTTP_REQ_1BYTE_SLIDING_WINDOW_TEST
- HTTP_RES_1BYTE_SLIDING_WINDOW_TEST
- HTTP_NO_CONTENT_LENGTH_TEST
- HTTP_POST_MULTIPART_FORM_DATA_TEST
- HTTP_HEADERS_EXCEED_MAXIMUM_TEST
- HTTP_GET_MALFORMED_TEST
- HTTP_URL_WITHOUT_HOST_V4_TEST
- HTTP_URL_WITHOUT_HOST_V6_TEST
- HTTP_MULTI_PARSE_ERROR_TEST
- HTTP_UPGRADE_WEBSOCKET_TEST
- HTTP_GET_REQ_PIPELINE_TEST
- HTTP_TRANS_PIPELINE_TEST
- HTTP_FIN_TEST
- HTTP_CHN_ENCODE_URL
- HTTP_ZLIB_DEADLOCK
- HTTP_OUT_OF_ORDER
- HTTP_GZIP_OUT_OF_ORDER
- HTTP_HEADER_SPLITTING
- PROPERTIES FIXTURES_REQUIRED HTTP_GTEST)
-
-add_test(NAME HTTP_UPDATE_STATE_PLUG_ENTRY COMMAND bash -c "sed -i 's/name=.*/name=\\x22http_decoder_test_state_entry\\x22/' ${TEST_RUN_DIR}/etc/http/gtest_entry.toml")
-add_test(NAME HTTP_UPDATE_STATE_PLUG_TOPIC COMMAND bash -c "sed -i 's/topic=.*/topic=\\x22HTTP_MESSAGE\\x22/' ${TEST_RUN_DIR}/etc/http/gtest_entry.toml")
-
-set_tests_properties(HTTP_UPDATE_STATE_PLUG_ENTRY HTTP_UPDATE_STATE_PLUG_TOPIC HTTP_CP_DECODER_SO HTTP_CP_DECODER_GTEST_SO HTTP_MKDIR_METRIC
- PROPERTIES FIXTURES_SETUP HTTP_STATE_TEST)
-
-add_test(NAME HTTP_MSG_TYPE_STATE_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_post.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_MSG_TYPE_STATE_C2S_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_post_c2s.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state_c2s.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_MSG_TYPE_STATE_S2C_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_post_s2c.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state_s2c.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_MSG_TYPE_STATE_PIPELINE_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_get_multi_trans.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state_pipeline.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_MSG_TYPE_STATE_SES_EXCEPTION_C2S_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_session_exception_c2s.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state_exception_c2s.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-add_test(NAME HTTP_MSG_TYPE_STATE_SES_EXCEPTION_S2C_TEST COMMAND sh -c "ln -sf ${TEST_PCAP_DIR}/http_session_exception_s2c.pcap ${TEST_RUN_DIR}/pcap/test.pcap; ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state_exception_s2c.json" WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-set_tests_properties(HTTP_MSG_TYPE_STATE_TEST
- HTTP_MSG_TYPE_STATE_C2S_TEST
- HTTP_MSG_TYPE_STATE_S2C_TEST
- HTTP_MSG_TYPE_STATE_PIPELINE_TEST
- HTTP_MSG_TYPE_STATE_SES_EXCEPTION_C2S_TEST
- HTTP_MSG_TYPE_STATE_SES_EXCEPTION_S2C_TEST
- PROPERTIES FIXTURES_REQUIRED HTTP_STATE_TEST)
-
diff --git a/test/decoders/http/test_based_on_stellar/env/gtest_entry.toml b/test/decoders/http/test_based_on_stellar/env/gtest_entry.toml
deleted file mode 100644
index 7491e9d..0000000
--- a/test/decoders/http/test_based_on_stellar/env/gtest_entry.toml
+++ /dev/null
@@ -1,3 +0,0 @@
-[entry]
-name="http_decoder_test_state_entry"
-topic="HTTP_MESSAGE"
diff --git a/test/decoders/http/test_based_on_stellar/env/http_decoder.toml b/test/decoders/http/test_based_on_stellar/env/http_decoder.toml
deleted file mode 100644
index a2bb060..0000000
--- a/test/decoders/http/test_based_on_stellar/env/http_decoder.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[basic]
-# Switch for decompress body, open(1) closed(0), default(0)
-decompress=1
-
-# per session mempool size, default(32Ki)
-mempool_size=32768
-
-# per session http parsed result queue length
-result_queue_len=16
-
-# call fieldstat every stat_interval_pkts
-stat_interval_pkts=1000
-
-# fieldstat output interval
-stat_output_interval=1
-
-# connect tunnel
-proxy_enable=0 \ No newline at end of file
diff --git a/test/decoders/http/test_based_on_stellar/env/log.toml b/test/decoders/http/test_based_on_stellar/env/log.toml
deleted file mode 100644
index b5213d9..0000000
--- a/test/decoders/http/test_based_on_stellar/env/log.toml
+++ /dev/null
@@ -1,4 +0,0 @@
-[log]
-output = "stderr" # stderr, file
-file = "log/stellar.log"
-level = "INFO" # TRACE, DEBUG, INFO, WARN, ERROR, FATAL
diff --git a/test/decoders/http/test_based_on_stellar/env/spec.toml b/test/decoders/http/test_based_on_stellar/env/spec.toml
deleted file mode 100644
index cce2c71..0000000
--- a/test/decoders/http/test_based_on_stellar/env/spec.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[[plugin]]
-path = "./plugin/http.so"
-init = "http_decoder_init"
-exit = "http_decoder_exit"
-
-[[plugin]]
-path = "./plugin/http_test.so"
-init = "http_decoder_test_init"
-exit = "http_decoder_test_exit"
diff --git a/test/decoders/http/test_based_on_stellar/env/stellar.toml b/test/decoders/http/test_based_on_stellar/env/stellar.toml
deleted file mode 100644
index 308c884..0000000
--- a/test/decoders/http/test_based_on_stellar/env/stellar.toml
+++ /dev/null
@@ -1,64 +0,0 @@
-[instance]
- id = 1 # range: [0, 4095] (20 bit)
-
-[packet_io]
- mode = "pcapfile" # pcapfile, pcaplist, marsio
- app_symbol = "stellar"
- dev_symbol = "nf_0_fw"
- pcap_path = "./pcap/test.pcap"
- nr_worker_thread = 1 # range: [1, 256]
- cpu_mask = [5, 6, 7, 8, 9, 10, 11, 12]
- idle_yield_interval_ms = 90 # range: [0, 60000] (ms)
-
-[ip_reassembly]
- enable = 1
- bucket_entries = 32 # range: [1, 4294967295] (must be power of 2)
- bucket_num = 1024 # range: [1, 4294967295]
-
- ip_frag_timeout_ms = 1000 # range: [1, 60000] (ms)
- ip_frag_expire_polling_interval_ms = 0 # range: [0, 60000] (ms)
- ip_frag_expire_polling_limit = 1024 # range: [1, 1024]
-
-[session_manager]
- tcp_session_max = 500
- udp_session_max = 500
-
- evict_old_on_tcp_table_limit = 1 # range: [0, 1]
- evict_old_on_udp_table_limit = 1 # range: [0, 1]
-
- expire_period_ms = 0 # range: [0, 60000] (ms)
- expire_batch_max = 1024 # range: [1, 1024]
-
- [session_manager.tcp_timeout_ms]
- init = 500 # range: [1, 60000] (ms)
- handshake = 500 # range: [1, 60000] (ms)
- data = 500 # range: [1, 15999999000] (ms)
- half_closed = 500 # range: [1, 604800000] (ms)
- time_wait = 500 # range: [1, 600000] (ms)
- discard_default = 1000 # range: [1, 15999999000] (ms)
- unverified_rst = 500 # range: [1, 600000] (ms)
-
- [session_manager.udp_timeout_ms]
- data = 500 # range: [1, 15999999000] (ms)
- discard_default = 500 # range: [1, 15999999000] (ms)
-
- [session_manager.duplicated_packet_bloom_filter]
- enable = 0
- capacity = 1000000 # range: [1, 4294967295]
- time_window_ms = 10000 # range: [1, 60000] (ms)
- error_rate = 0.00001 # range: [0.0, 1.0]
-
- [session_manager.evicted_session_bloom_filter]
- enable = 0 # range: [0, 1]
- capacity = 1000000 # range: [1, 4294967295]
- time_window_ms = 10000 # range: [1, 60000] (ms)
- error_rate = 0.00001 # range: [0.0, 1.0]
-
- [session_manager.tcp_reassembly]
- enable = 1 # range: [0, 1]
- timeout_ms = 100 # range: [1, 60000] (ms)
- buffered_segments_max = 256 # range: [2, 4096] per flow
-
-[stat]
- merge_interval_ms = 500 # range: [0, 60000] (ms)
- output_interval_ms = 1000 # range: [0, 60000] (ms)