summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlijia <[email protected]>2024-05-24 22:47:32 +0800
committerlijia <[email protected]>2024-06-03 11:08:06 +0800
commit1c232f0176c43c93c3e787ac83f3573bf42c58f1 (patch)
tree734c31a97ec38847972b70a18ec075fd415bb5f6
parent22d071e23ff423242f51dce2eab1477b5fb9d106 (diff)
Adapt to stellar2.0;update API,add HDR_END,BODY_END,TRANSACTION_NEW,FREE msg.v2.0.2
-rw-r--r--.gitlab-ci.yml88
-rw-r--r--CMakeLists.txt4
-rw-r--r--conf/gtest_entry.toml2
-rw-r--r--include/http_decoder.h78
-rw-r--r--src/CMakeLists.txt7
-rw-r--r--src/http_content_decompress.cpp (renamed from src/http_content_decompress.c)22
-rw-r--r--src/http_decoder.c991
-rw-r--r--src/http_decoder.cpp833
-rw-r--r--src/http_decoder_half.cpp (renamed from src/http_decoder_half.c)203
-rw-r--r--src/http_decoder_half.h33
-rw-r--r--src/http_decoder_inc.h94
-rw-r--r--src/http_decoder_result_queue.cpp (renamed from src/http_decoder_result_queue.c)19
-rw-r--r--src/http_decoder_result_queue.h12
-rw-r--r--src/http_decoder_stat.cpp99
-rw-r--r--src/http_decoder_stat.h5
-rw-r--r--src/http_decoder_string.cpp (renamed from src/http_decoder_string.c)25
-rw-r--r--src/http_decoder_string.h25
-rw-r--r--src/http_decoder_table.cpp (renamed from src/http_decoder_table.c)89
-rw-r--r--src/http_decoder_table.h35
-rw-r--r--src/http_decoder_utils.c25
-rw-r--r--src/http_decoder_utils.cpp137
-rw-r--r--src/http_decoder_utils.h26
-rw-r--r--src/version.map2
-rw-r--r--test/CMakeLists.txt174
-rw-r--r--test/http_decoder_driver.cpp981
-rw-r--r--test/http_decoder_gtest.cpp228
-rw-r--r--test/http_decoder_gtest.h93
-rw-r--r--test/http_decoder_perf_main.cpp363
-rw-r--r--test/http_decoder_perf_plug.cpp (renamed from test/http_decoder_perf.cpp)73
-rw-r--r--test/http_decoder_stub.cpp254
-rw-r--r--test/http_gtest_main.cpp44
-rw-r--r--test/http_gtest_unit.cpp569
-rw-r--r--test/http_pcap/http_pipeline_C2S.pcapbin0 -> 3240 bytes
-rw-r--r--test/http_pcap/http_pipeline_S2C.pcapbin0 -> 3616 bytes
-rw-r--r--test/http_pcap/http_post.pcapbin0 -> 1478 bytes
-rw-r--r--test/http_pcap/http_post_c2s.pcapbin0 -> 634 bytes
-rw-r--r--test/http_pcap/http_post_s2c.pcapbin0 -> 868 bytes
-rw-r--r--test/test_result_json/http_get_malformed.json26
-rw-r--r--test/test_result_json/http_msg_type_state.json18
-rw-r--r--test/test_result_json/http_msg_type_state_c2s.json12
-rw-r--r--test/test_result_json/http_msg_type_state_pipeline.json60
-rw-r--r--test/test_result_json/http_msg_type_state_s2c.json12
-rw-r--r--test_based_on_stellar/CMakeLists.txt37
-rw-r--r--test_based_on_stellar/env/conflist.inf1
-rw-r--r--test_based_on_stellar/env/defer_loader.inf14
-rw-r--r--test_based_on_stellar/env/start_loader.inf21
-rw-r--r--test_based_on_stellar/plugin_test_main.cpp13
-rw-r--r--vendor/CMakeLists.txt17
48 files changed, 2075 insertions, 3789 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c84bfaa..94b7255 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,13 +1,12 @@
variables:
GIT_STRATEGY: "clone"
BUILD_PADDING_PREFIX: /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX/
- BUILD_IMAGE_CENTOS7: "git.mesalab.cn:7443/mesa_platform/build-env:master"
BUILD_IMAGE_CENTOS8: "git.mesalab.cn:7443/mesa_platform/build-env:rockylinux"
INSTALL_DEPENDENCY_LIBRARY: sapp sapp-devel framework_env libMESA_prof_load-devel libasan
libMESA_htable-devel libMESA_jump_layer libMESA_jump_layer-devel
libMESA_handle_logger-devel libMESA_field_stat2-devel
libfieldstat3-devel libfieldstat4-devel libbreakpad_mini-devel
- zlib-devel brotli brotli-devel stellar-c-devel stellar-c systemd-devel
+ zlib-devel brotli brotli-devel stellar-on-sapp-devel stellar-on-sapp systemd-devel
SYMBOL_TARGET: http_decoder
TEST_NAME: gtest_http_decoder
INSTALL_PREFIX: "/opt/tsg/"
@@ -57,10 +56,6 @@ stages:
tags:
- share
-run_cppcheck_for_centos7:
- extends: .cppcheck_script
- image: $BUILD_IMAGE_CENTOS7
-
run_cppcheck_for_centos8:
extends: .cppcheck_script
image: $BUILD_IMAGE_CENTOS8
@@ -79,51 +74,6 @@ run_cppcheck_for_centos8:
tags:
- share
-.build_by_travis_for_centos7:
- extends: .build_before_script
- stage: build
- image: $BUILD_IMAGE_CENTOS7
-
-
-develop_build_for_centos7:
- extends: .build_by_travis_for_centos7
- variables:
- BUILD_TYPE: RelWithDebInfo
- artifacts:
- name: "$SYMBOL_TARGET-$CI_COMMIT_REF_NAME-debug"
- paths:
- - build/*
- except:
- - tags
-
-release_build_debug_for_centos7:
- extends: .build_by_travis_for_centos7
- variables:
- BUILD_TYPE: Debug
- PACKAGE: 1
- ASAN_OPTION: "ADDRESS"
- script:
- - source /opt/rh/devtoolset-7/enable || true
- - ./ci/travis.sh
- artifacts:
- name: "$SYMBOL_TARGET-$CI_COMMIT_REF_NAME-release"
- paths:
- - build/*
- only:
- - tags
-
-release_build_for_centos7:
- extends: .build_by_travis_for_centos7
- variables:
- BUILD_TYPE: RelWithDebInfo
- PACKAGE: 1
- artifacts:
- name: "$SYMBOL_TARGET-$CI_COMMIT_REF_NAME-release"
- paths:
- - build/*
- only:
- - tags
-
.build_by_travis_for_centos8:
stage: build
image: $BUILD_IMAGE_CENTOS8
@@ -168,20 +118,6 @@ release_build_for_centos8:
###############################################################################
# test
###############################################################################
-test_in_centos7:
- stage: test
- image: $BUILD_IMAGE_CENTOS7
- allow_failure: false
- script:
- - *everything_before_script
- - ls -l /opt/MESA/lib && echo "/opt/MESA/lib" >> /etc/ld.so.conf
- - cd build; make test
- dependencies:
- - develop_build_for_centos7
- - release_build_for_centos7
- tags:
- - share
-
test_in_centos8:
stage: test
image: $BUILD_IMAGE_CENTOS8
@@ -199,28 +135,6 @@ test_in_centos8:
###############################################################################
# upload
###############################################################################
-.define_before_upload_centos7:
- stage: upload
- image: $BUILD_IMAGE_CENTOS7
- before_script:
- - pwd; ls -l ; cd build ; ls -l
- - cp /root/rpm_upload_tools.py ./
- variables:
- PULP3_REPO_NAME: protocol-stable-x86_64.el7
- PULP3_DIST_NAME: protocol-stable-x86_64.el7
- only:
- - tags
- tags:
- - share
-
-rpm_upload_for_centos7:
- extends: .define_before_upload_centos7
- dependencies:
- - release_build_debug_for_centos7
- - release_build_for_centos7
- script:
- - python3 rpm_upload_tools.py $PULP3_REPO_NAME $PULP3_DIST_NAME *.rpm
-
.define_before_upload_centos8:
stage: upload
image: $BUILD_IMAGE_CENTOS8
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b31dc88..1c2c41b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -56,6 +56,10 @@ else()
message(FATAL_ERROR "Could not find the program cppcheck.")
endif()
+set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
+ " set CMAKE_BUILD_TYPE chosen by the user, using RelWithDebInfo as default")
+set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel)
+
#ASAN option
set(ASAN_OPTION "OFF" CACHE STRING
" set asan type chosen by the user, using OFF as default")
diff --git a/conf/gtest_entry.toml b/conf/gtest_entry.toml
new file mode 100644
index 0000000..03c5660
--- /dev/null
+++ b/conf/gtest_entry.toml
@@ -0,0 +1,2 @@
+[entry]
+name="http_decoder_test_state_entry"
diff --git a/include/http_decoder.h b/include/http_decoder.h
index 56c107a..449d498 100644
--- a/include/http_decoder.h
+++ b/include/http_decoder.h
@@ -1,13 +1,3 @@
-/*
-**********************************************************************************************
-* File: http_decoder.h
-* Description:
-* Authors: Liu WenTan <[email protected]>
-* Date: 2024-01-10
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
#ifndef _HTTP_DECODER_H_
#define _HTTP_DECODER_H_
@@ -16,19 +6,25 @@ extern "C"
{
#endif
-#include <stddef.h>
-
enum http_message_type {
- HTTP_MESSAGE_REQ_LINE,
+ HTTP_MESSAGE_REQ_LINE,
HTTP_MESSAGE_REQ_HEADER,
+ HTTP_MESSAGE_REQ_HEADER_END,
HTTP_MESSAGE_REQ_BODY,
+ HTTP_MESSAGE_REQ_BODY_END,
+
HTTP_MESSAGE_RES_LINE,
HTTP_MESSAGE_RES_HEADER,
+ HTTP_MESSAGE_RES_HEADER_END,
HTTP_MESSAGE_RES_BODY,
+ HTTP_MESSAGE_RES_BODY_END,
+
+ HTTP_TRANSACTION_NEW,
+ HTTP_TRANSACTION_FREE,
+
HTTP_MESSAGE_MAX
};
-//http string
struct hstring {
char *str;
size_t str_len;
@@ -43,7 +39,6 @@ struct http_request_line {
struct hstring method;
struct hstring uri;
struct hstring version;
-
int major_version;
int minor_version;
};
@@ -51,64 +46,59 @@ struct http_request_line {
struct http_response_line {
struct hstring version;
struct hstring status;
-
int major_version;
int minor_version;
int status_code;
};
struct http_message;
+#define HTTP_DECODER_TOPIC "HTTP_DECODER_MESSAGE"
-enum http_message_type http_message_type(struct http_message *msg);
+enum http_message_type http_message_type_get(const struct http_message *msg);
-/**
- * @retval succeed(0) failed(-1)
-*/
-int http_message_get_request_line(struct http_message *msg,
- struct http_request_line *line);
+void http_message_get_request_line(const struct http_message *msg,
+ struct http_request_line *line);
-int http_message_get_response_line(struct http_message *msg,
- struct http_response_line *line);
+void http_message_get_response_line(const struct http_message *msg,
+ struct http_response_line *line);
/*
-* @retval succeed(0) failed(-1)
+* Pay attention: key->str is case-insensitive.
*/
-int http_message_get_header(struct http_message *msg, struct hstring *key,
- struct http_header *hdr_result);
+void http_message_get_header(const struct http_message *msg,
+ const struct hstring *key,
+ struct http_header *hdr_result);
/**
- * @brief loop reading all headers
+ * @brief loop reading all headers.
*
- * @retval succeed(0) failed(<= 0)
+ * @retval succeed( >= 0) failed(-1)
*/
-int http_message_header_next(struct http_message *msg,
+int http_message_header_next(const struct http_message *msg,
struct http_header *header);
-int http_message_reset_header_iter(struct http_message *msg);
-
/**
- * @retval succeed(0) failed(-1)
+ * @retval succeed( >= 0) failed(-1)
*/
-int http_message_get_raw_body(struct http_message *msg,
- struct hstring *body);
+int http_message_reset_header_iter(struct http_message *msg);
+
+void http_message_get_raw_body(const struct http_message *msg,
+ struct hstring *body);
/**
- * @brief If the body hasn't been compressed, return raw body
+ * @brief If the body hasn't been compressed, same as http_message_get_raw_body().
*
- * @retval succeed(0) failed(-1)
*/
-int http_message_get_decompress_body(struct http_message *msg,
- struct hstring *body);
+void http_message_get_decompress_body(const struct http_message *msg,
+ struct hstring *body);
-/**
- * @retval succeed(0) failed(-1)
-*/
-int http_message_get_url(struct http_message *msg, struct hstring *url);
+void http_message_get_url(const struct http_message *msg,
+ struct hstring *url);
/**
* @retval succeed( >= 0) failed(-1)
*/
-int http_message_get_transaction_seq(struct http_message *msg);
+int http_message_get_transaction_seq(const struct http_message *msg);
#ifdef __cplusplus
}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 533eea8..1d3c949 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,13 +3,14 @@ add_definitions(-fPIC)
include_directories(/opt/MESA/include/)
include_directories(/opt/tsg/framework/include/)
include_directories(${PROJECT_SOURCE_DIR}/deps/)
+include_directories(${CMAKE_BINARY_DIR}/vendor/vbuild/include)
aux_source_directory(${PROJECT_SOURCE_DIR}/deps/mempool DEPS_SRC)
aux_source_directory(${PROJECT_SOURCE_DIR}/deps/toml DEPS_SRC)
-set(HTTP_SRC ${DEPS_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)
+set(HTTP_SRC ${DEPS_SRC} http_decoder.cpp http_decoder_utils.cpp http_decoder_half.cpp
+ http_decoder_table.cpp http_decoder_string.cpp http_content_decompress.cpp
+ http_decoder_result_queue.cpp http_decoder_stat.cpp)
add_library(http_decoder SHARED ${HTTP_SRC})
set_target_properties(http_decoder PROPERTIES LINK_FLAGS "-Wl,--version-script=${PROJECT_SOURCE_DIR}/src/version.map")
diff --git a/src/http_content_decompress.c b/src/http_content_decompress.cpp
index 5fe08a8..e761f1d 100644
--- a/src/http_content_decompress.c
+++ b/src/http_content_decompress.cpp
@@ -7,25 +7,18 @@
* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
***********************************************************************************************
*/
-
-
#include <zlib.h>
#include <string.h>
#include <assert.h>
#include <brotli/decode.h>
-
-#include "stellar/utils.h"
-#include "http_decoder_utils.h"
-#include "http_content_decompress.h"
+#include "http_decoder_inc.h"
#define BUFFER_SIZE (16 * 1024)
struct http_content_decompress {
enum http_content_encoding encoding;
-
z_stream *z_stream_ptr;
BrotliDecoderState *br_state;
-
char *buffer;
size_t buffer_size;
};
@@ -36,15 +29,12 @@ http_content_encoding_str2int(const char *content_encoding)
if (strcasestr(content_encoding, "gzip") != NULL) {
return HTTP_CONTENT_ENCODING_GZIP;
}
-
if (strcasestr(content_encoding, "deflate") != NULL) {
return HTTP_CONTENT_ENCODING_DEFLATE;
}
-
if (strcasestr(content_encoding, "br") != NULL) {
return HTTP_CONTENT_ENCODING_BR;
}
-
return HTTP_CONTENT_ENCODING_NONE;
}
@@ -54,15 +44,12 @@ 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";
}
@@ -98,7 +85,6 @@ http_content_decompress_create(enum http_content_encoding encoding)
goto error;
}
}
-
if (encoding == HTTP_CONTENT_ENCODING_DEFLATE) {
if (inflateInit2(decompress->z_stream_ptr, -MAX_WBITS) != Z_OK) {
goto error;
@@ -112,7 +98,6 @@ http_content_decompress_create(enum http_content_encoding encoding)
goto error;
}
}
-
return decompress;
error:
@@ -125,17 +110,14 @@ 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);
}
@@ -257,12 +239,10 @@ int http_content_decompress_write(struct http_content_decompress *decompress,
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/src/http_decoder.c b/src/http_decoder.c
deleted file mode 100644
index 9dcffe2..0000000
--- a/src/http_decoder.c
+++ /dev/null
@@ -1,991 +0,0 @@
-/*
-**********************************************************************************************
-* File: http_decoder.c
-* Description:
-* Authors: Liu WenTan <[email protected]>
-* Date: 2024-01-10
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "toml/toml.h"
-#include "stellar/utils.h"
-#include "stellar/session.h"
-#include "stellar/session_mq.h"
-#include "stellar/session_exdata.h"
-#include "http_decoder.h"
-#include "http_decoder_half.h"
-#include "http_decoder_table.h"
-#include "http_decoder_result_queue.h"
-#include "llhttp.h"
-#include "http_decoder_inc.h"
-#include "fieldstat/fieldstat_easy.h"
-
-#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)
-
-const char *g_hd_cfg_path = "./etc/http/http_decoder.toml";
-const char *http_decoder_topic = "HTTP_DECODER_MESSAGE";
-const char *fs_file_name = "http_decoder.fs";
-
-struct http_decoder_config
-{
- int decompress_switch;
- int stat_interval_pkts; // call fieldstat_incrby every stat_interval_pkts
- int stat_output_interval;
- 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
-{
- enum http_message_type type;
- struct http_decoder_result_queue *ref_queue;
- size_t queue_index;
-};
-
-struct http_decoder
-{
- struct http_decoder_half *c2s_half;
- struct http_decoder_half *s2c_half;
-};
-
-struct http_decoder_exdata
-{
- struct http_decoder_result_queue *queue;
- struct http_decoder *decoder;
- nmx_pool_t *mempool;
-};
-
-struct http_decoder_stat
-{
- long long incoming_bytes;
- long long incoming_pkts;
- long long incoming_trans;
- long long err_pkts;
- int counter;
-};
-
-struct http_decoder_context
-{
- int plugin_id;
- int topic_id;
- int ex_data_idx;
- int fs_incoming_bytes_id;
- int fs_incoming_pkts_id;
- int fs_incoming_trans_id;
- int fs_err_pkts_id;
- struct stellar *st;
- struct fieldstat_easy *fse;
- struct http_decoder_config hd_cfg;
-};
-
-__thread struct http_decoder_stat _th_stat;
-
-struct http_message *
-http_message_new(enum http_message_type type,
- struct http_decoder_result_queue *queue,
- int queue_index)
-{
- struct http_message *msg = CALLOC(struct http_message, 1);
-
- msg->type = type;
- msg->ref_queue = queue;
- msg->queue_index = queue_index;
-
- return msg;
-}
-
-static void http_message_free(void *http_msg, void *cb_arg)
-{
- if (NULL == http_msg)
- {
- return;
- }
-
- FREE(http_msg);
-}
-
-static void http_event_handler(enum http_event event,
- struct http_decoder_half_data **data,
- struct http_event_context *ev_ctx)
-{
- assert(ev_ctx);
-
- 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;
-
- 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;
- break;
- case HTTP_EVENT_REQ_LINE:
- queue_idx = http_decoder_result_queue_req_index(queue);
- msg = http_message_new(HTTP_MESSAGE_REQ_LINE, queue, queue_idx);
- session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
- break;
- case HTTP_EVENT_REQ_HDR_END:
- {
- int build_url_final = http_decoder_join_url_finally(ev_ctx, http_decoder_result_queue_peek_req(queue), mempool);
- ret = http_decoder_half_data_has_parsed_header(*data);
- if (0 == ret && 0 == build_url_final)
- {
- break;
- }
- queue_idx = http_decoder_result_queue_req_index(queue);
- msg = http_message_new(HTTP_MESSAGE_REQ_HEADER, queue, queue_idx);
- session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
- }
- break;
- case HTTP_EVENT_REQ_BODY_BEGIN:
- break;
- case HTTP_EVENT_REQ_BODY_DATA:
- queue_idx = http_decoder_result_queue_req_index(queue);
- msg = http_message_new(HTTP_MESSAGE_REQ_BODY, queue, queue_idx);
- session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
- break;
- case HTTP_EVENT_REQ_BODY_END:
- break;
- case HTTP_EVENT_REQ_END:
- 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;
- }
- *data = half_data;
- break;
- case HTTP_EVENT_RES_LINE:
- queue_idx = http_decoder_result_queue_res_index(queue);
- msg = http_message_new(HTTP_MESSAGE_RES_LINE, queue, queue_idx);
- session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
- break;
- case HTTP_EVENT_RES_HDR:
- break;
- case HTTP_EVENT_RES_HDR_END:
- ret = http_decoder_half_data_has_parsed_header(*data);
- if (0 == ret)
- {
- break;
- }
-
- queue_idx = http_decoder_result_queue_res_index(queue);
- msg = http_message_new(HTTP_MESSAGE_RES_HEADER, queue, queue_idx);
- session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
- break;
- case HTTP_EVENT_RES_BODY_BEGIN:
- break;
- case HTTP_EVENT_RES_BODY_DATA:
- queue_idx = http_decoder_result_queue_res_index(queue);
- msg = http_message_new(HTTP_MESSAGE_RES_BODY, queue, queue_idx);
- session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
- break;
- case HTTP_EVENT_RES_BODY_END:
- break;
- case HTTP_EVENT_RES_END:
- 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;
- }
-}
-
-static struct http_decoder *
-http_decoder_new(nmx_pool_t *mempool, http_event_cb *ev_cb,
- int decompress_switch)
-{
- struct http_decoder *decoder = MEMPOOL_CALLOC(mempool, struct http_decoder, 1);
- assert(decoder);
-
- decoder->c2s_half = http_decoder_half_new(mempool, ev_cb, HTTP_REQUEST,
- decompress_switch);
- decoder->s2c_half = http_decoder_half_new(mempool, ev_cb, HTTP_RESPONSE,
- decompress_switch);
-
- return decoder;
-}
-
-static void
-http_decoder_free(nmx_pool_t *mempool, struct http_decoder *decoder)
-{
- if (NULL == decoder)
- {
- return;
- }
-
- if (decoder->c2s_half != NULL)
- {
- http_decoder_half_free(mempool, decoder->c2s_half);
- decoder->c2s_half = NULL;
- }
-
- if (decoder->s2c_half != NULL)
- {
- http_decoder_half_free(mempool, decoder->s2c_half);
- decoder->s2c_half = NULL;
- }
-
- 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_exdata *ex_data = CALLOC(struct http_decoder_exdata, 1);
-
- ex_data->mempool = nmx_create_pool(mempool_size);
- ex_data->decoder = http_decoder_new(ex_data->mempool, http_event_handler,
- decompress_switch);
- ex_data->queue = http_decoder_result_queue_new(ex_data->mempool, queue_size);
-
- return ex_data;
-}
-
-static void http_decoder_exdata_free(struct http_decoder_exdata *ex_data)
-{
- if (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)
- {
- http_decoder_result_queue_free(ex_data->mempool, ex_data->queue);
- ex_data->queue = NULL;
- }
-
- 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 0;
-}
-
-static int
-http_decoder_stat_init(struct http_decoder_context *ctx, int thread_num)
-{
- ctx->fse =
- fieldstat_easy_new(thread_num, "http_decoder_statistics", NULL, 0);
- if (NULL == ctx->fse)
- {
- fprintf(stderr, "fieldstat_easy_new failed.");
- return -1;
- }
-
- ctx->fs_incoming_bytes_id =
- fieldstat_easy_register_counter(ctx->fse, "incoming_bytes");
- if (ctx->fs_incoming_bytes_id < 0)
- {
- fprintf(stderr, "fieldstat_easy_register_counter incoming_bytes failed.");
- return -1;
- }
-
- ctx->fs_incoming_trans_id =
- fieldstat_easy_register_counter(ctx->fse, "incoming_trans");
- if (ctx->fs_incoming_trans_id < 0)
- {
- fprintf(stderr, "fieldstat_easy_register_counter incoming_trans failed.");
- return -1;
- }
-
- ctx->fs_incoming_pkts_id =
- fieldstat_easy_register_counter(ctx->fse, "incoming_pkts");
- if (ctx->fs_incoming_pkts_id < 0)
- {
- fprintf(stderr, "fieldstat_easy_register_counter incoming_pkts failed.");
- return -1;
- }
-
- ctx->fs_err_pkts_id = fieldstat_easy_register_counter(ctx->fse, "err_pkts");
- if (ctx->fs_err_pkts_id < 0)
- {
- fprintf(stderr, "fieldstat_easy_register_counter err_pkts failed.");
- return -1;
- }
-
- int stat_output_interval = DEFAULT_STAT_OUTPUT_INTERVAL;
- if (ctx->hd_cfg.stat_output_interval > 0)
- {
- stat_output_interval = ctx->hd_cfg.stat_output_interval;
- }
-
- int ret = fieldstat_easy_enable_auto_output(ctx->fse, fs_file_name,
- stat_output_interval);
- if (ret < 0)
- {
- fprintf(stderr, "fieldstat_easy_enable_auto_output failed.");
- return -1;
- }
-
- sleep(1);
-
- return 0;
-}
-
-static void
-http_decoder_stat_output(struct http_decoder_context *ctx, int thread_id)
-{
- if (NULL == ctx || thread_id < 0)
- {
- return;
- }
-
- int stat_interval_pkts = DEFAULT_STAT_INTERVAL_PKTS;
- if (ctx->hd_cfg.stat_interval_pkts > 0)
- {
- stat_interval_pkts = ctx->hd_cfg.stat_interval_pkts;
- }
-
- if (_th_stat.counter >= stat_interval_pkts)
- {
- fieldstat_easy_counter_incrby(ctx->fse, thread_id,
- ctx->fs_incoming_bytes_id, NULL, 0,
- _th_stat.incoming_bytes);
-
- fieldstat_easy_counter_incrby(ctx->fse, thread_id,
- ctx->fs_incoming_pkts_id, NULL, 0,
- _th_stat.incoming_pkts);
-
- fieldstat_easy_counter_incrby(ctx->fse, thread_id,
- ctx->fs_incoming_trans_id, NULL, 0,
- _th_stat.incoming_trans);
-
- fieldstat_easy_counter_incrby(ctx->fse, thread_id,
- ctx->fs_err_pkts_id, NULL, 0,
- _th_stat.err_pkts);
-
- _th_stat.counter = 0;
- _th_stat.err_pkts = 0;
- _th_stat.incoming_bytes = 0;
- _th_stat.incoming_pkts = 0;
- _th_stat.incoming_trans = 0;
- }
-}
-
-int http_decoder_entry(struct session *sess, int events,
- const struct packet *pkt, void *cb_arg)
-{
- struct http_decoder_context *ctx = (struct http_decoder_context *)cb_arg;
- size_t payload_len = 0;
- uint64_t inner_flag = 0;
-
- int ret = session_is_inner_most(sess, &inner_flag);
- if (0 == ret)
- {
- return 0;
- }
-
- struct http_decoder_exdata *ex_data =
- session_get_ex_data(sess, ctx->ex_data_idx);
-
- if (events & SESS_EV_CLOSING)
- {
- if (ex_data != NULL)
- {
- http_decoder_exdata_free(ex_data);
- session_set_ex_data(sess, ctx->ex_data_idx, NULL);
- }
-
- return 0;
- }
-
- const char *payload = session_get0_current_payload(sess, &payload_len);
-
- if (events & SESS_EV_OPENING)
- {
- assert(ex_data == NULL);
-
- // If not http, ignore this session
- if (payload_len > 0)
- {
- size_t http_identify_len = payload_len > HTTP_IDENTIFY_LEN
- ? HTTP_IDENTIFY_LEN
- : payload_len;
-
- ret = http_protocol_identify(payload, http_identify_len);
- if (ret < 0)
- {
- // ignore this session's event
- struct session_event *s_event =
- session_get_intrinsic_event(sess, ctx->plugin_id);
-
- session_event_assign(s_event, ctx->st, sess, 0,
- http_decoder_entry, ctx);
- return 0;
- }
- }
-
- ex_data = http_decoder_exdata_new(ctx->hd_cfg.mempool_size,
- ctx->hd_cfg.result_queue_len,
- ctx->hd_cfg.decompress_switch);
- session_set_ex_data(sess, ctx->ex_data_idx, ex_data);
- }
-
- if (0 == payload_len || NULL == ex_data)
- {
- return 0;
- }
-
- int dir = packet_get_direction(pkt);
- if (dir < 0)
- {
- return -1;
- }
-
- int thread_id = session_get_current_thread_id(sess);
- struct http_decoder_half *cur_half = NULL;
-
- if (dir == PACKET_DIRECTION_C2S)
- {
- cur_half = ex_data->decoder->c2s_half;
- }
- else
- {
- cur_half = ex_data->decoder->s2c_half;
- }
-
- http_decoder_half_reinit(cur_half, ctx->topic_id, ex_data->queue,
- ex_data->mempool, sess);
- ret = http_decoder_half_parse(cur_half, payload, payload_len);
- if (ret < 0)
- {
- _th_stat.err_pkts += 1;
- }
-
- _th_stat.incoming_bytes += payload_len;
- _th_stat.incoming_pkts += 1;
- _th_stat.incoming_trans += http_decoder_half_trans_count(cur_half);
- _th_stat.counter++;
-
- http_decoder_stat_output(ctx, thread_id);
-
- return 0;
-}
-
-static void _http_decoder_context_free(struct http_decoder_context *ctx)
-{
- if (NULL == ctx)
- {
- return;
- }
-
- if (ctx->fse != NULL)
- {
- fieldstat_easy_free(ctx->fse);
- ctx->fse = NULL;
- }
-
- if (ctx->topic_id >= 0)
- {
- session_mq_destroy_topic(ctx->st, ctx->topic_id);
- ctx->topic_id = -1;
- }
-
- FREE(ctx);
-}
-
-static void http_decoder_ex_data_free(struct session *s, int idx,
- void *ex_data, void *arg)
-{
- if (NULL == ex_data)
- {
- return;
- }
-
- struct http_decoder_exdata *exdata = (struct http_decoder_exdata *)ex_data;
- http_decoder_exdata_free(exdata);
-}
-
-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);
- ret = -1;
- goto next;
- }
-
- 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;
- }
-
-next:
- toml_free(root);
- return ret;
-}
-
-void *http_decoder_init(struct stellar *st)
-{
- int plugin_id = -1;
- int topic_id = -1;
- int thread_num = 0;
-
- struct http_decoder_context *ctx = CALLOC(struct http_decoder_context, 1);
-
- int ret = load_http_decoder_config(g_hd_cfg_path, &ctx->hd_cfg);
- if (ret < 0)
- {
- goto failed;
- }
-
- ctx->st = st;
- ctx->ex_data_idx = stellar_session_get_ex_new_index(st, "HTTP_DECODER",
- http_decoder_ex_data_free,
- NULL);
-
- plugin_id = stellar_plugin_register(st, SESS_EV_TCP | SESS_EV_CLOSING,
- http_decoder_entry, ctx);
- if (plugin_id < 0)
- {
- goto failed;
- }
-
- ctx->plugin_id = plugin_id;
-
- topic_id = session_mq_get_topic_id(st, http_decoder_topic);
- if (topic_id < 0)
- {
- topic_id = session_mq_create_topic(st, http_decoder_topic,
- http_message_free, NULL);
- }
-
- ctx->topic_id = topic_id;
-
- thread_num = stellar_get_worker_thread_num(st);
-
- if (http_decoder_stat_init(ctx, thread_num) < 0)
- {
- goto failed;
- }
-
- // printf("http_decoder_init: ex_data_idx:%d, plugin_id:%d, topic_id:%d\n",
- // ctx->ex_data_idx, ctx->plugin_id, ctx->topic_id);
- return ctx;
-
-failed:
- _http_decoder_context_free(ctx);
- return NULL;
-}
-
-void http_decoder_exit(void *decoder_ctx)
-{
- if (NULL == decoder_ctx)
- {
- return;
- }
-
- struct http_decoder_context *ctx =
- (struct http_decoder_context *)decoder_ctx;
-
- _http_decoder_context_free(ctx);
-}
-
-enum http_message_type http_message_type(struct http_message *msg)
-{
- if (NULL == msg)
- {
- return HTTP_MESSAGE_MAX;
- }
-
- return msg->type;
-}
-
-int http_message_get_request_line(struct http_message *msg,
- struct http_request_line *line)
-{
- if (NULL == msg || msg->type != HTTP_MESSAGE_REQ_LINE ||
- NULL == line)
- {
- return -1;
- }
-
- 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;
-
- return http_decoder_half_data_get_request_line(req_data, line);
-}
-
-int http_message_get_response_line(struct http_message *msg,
- struct http_response_line *line)
-{
- if (NULL == msg || msg->type != HTTP_MESSAGE_RES_LINE ||
- NULL == line)
- {
- return -1;
- }
-
- 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;
-
- return http_decoder_half_data_get_response_line(res_data, line);
-}
-
-static int http_msg_get_request_header(struct http_message *msg, struct hstring *key,
- struct http_header *hdr_result)
-{
- 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, key, hdr_result);
-}
-
-static int http_msg_get_response_header(struct http_message *msg, struct hstring *key,
- struct http_header *hdr_result)
-{
- 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, key, hdr_result);
-}
-
-int http_message_get_header(struct http_message *msg, struct hstring *key,
- struct http_header *hdr_result)
-{
- if (NULL == msg || NULL == key || NULL == hdr_result)
- {
- return -1;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- if (HTTP_MESSAGE_REQ_HEADER == msg->type)
- {
- return http_msg_get_request_header(msg, key, hdr_result);
- }
- else if (HTTP_MESSAGE_RES_HEADER == msg->type)
- {
- return http_msg_get_response_header(msg, key, hdr_result);
- }
-
- return -1;
-}
-
-static int http_msg_request_header_next(struct http_message *msg,
- struct http_header *hdr)
-{
- struct http_decoder_half_data *req_data =
- msg->ref_queue->array[msg->queue_index].req_data;
- return http_decoder_half_data_iter_header(req_data, hdr);
-}
-
-static int http_msg_response_header_next(struct http_message *msg,
- struct http_header *hdr)
-{
- struct http_decoder_half_data *res_data =
- msg->ref_queue->array[msg->queue_index].res_data;
- return http_decoder_half_data_iter_header(res_data, hdr);
-}
-
-int http_message_header_next(struct http_message *msg,
- struct http_header *header)
-{
- if (NULL == msg || NULL == header)
- {
- return -1;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- if (HTTP_MESSAGE_REQ_HEADER == msg->type)
- {
- return http_msg_request_header_next(msg, header);
- }
- else if (HTTP_MESSAGE_RES_HEADER == msg->type)
- {
- return http_msg_response_header_next(msg, header);
- }
-
- return -1;
-}
-
-int http_message_reset_header_iter(struct http_message *msg)
-{
- if (NULL == msg)
- {
- return -1;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- if (HTTP_MESSAGE_REQ_HEADER == msg->type)
- {
- 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);
- }
- else if (HTTP_MESSAGE_RES_HEADER == msg->type)
- {
- 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);
- }
-
- return -1;
-}
-
-static int http_msg_get_request_raw_body(struct http_message *msg,
- struct hstring *body)
-{
- 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(struct http_message *msg,
- struct hstring *body)
-{
- 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);
-}
-
-int http_message_get_raw_body(struct http_message *msg,
- struct hstring *body)
-{
- if (NULL == msg || NULL == body)
- {
- return -1;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
-
- if (HTTP_MESSAGE_REQ_BODY == msg->type)
- {
- return http_msg_get_request_raw_body(msg, body);
- }
- else if (HTTP_MESSAGE_RES_BODY == msg->type)
- {
- return http_msg_get_response_raw_body(msg, body);
- }
-
- return -1;
-}
-
-int http_msg_get_request_decompress_body(struct http_message *msg,
- struct hstring *body)
-{
- 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);
-}
-
-int http_msg_get_response_decompress_body(struct http_message *msg,
- struct hstring *body)
-{
- 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);
-}
-
-int http_message_get_decompress_body(struct http_message *msg,
- struct hstring *body)
-{
- if (NULL == msg || NULL == body)
- {
- return -1;
- }
-
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
-
- if (HTTP_MESSAGE_REQ_BODY == msg->type)
- {
- return http_msg_get_request_decompress_body(msg, body);
- }
- else if (HTTP_MESSAGE_RES_BODY == msg->type)
- {
- return http_msg_get_response_decompress_body(msg, body);
- }
-
- return -1;
-}
-
-int http_message_get_url(struct http_message *msg, struct hstring *url)
-{
- if (NULL == msg || NULL == url)
- {
- return -1;
- }
-
- 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;
-
- return http_half_data_get_url(req_data, url);
-}
-
-int http_message_get_transaction_seq(struct http_message *msg)
-{
- if (NULL == msg)
- {
- return -1;
- }
- assert(msg->ref_queue);
- assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
- struct http_decoder_half_data *hf_data;
- if (HTTP_MESSAGE_REQ_LINE == msg->type || HTTP_MESSAGE_REQ_HEADER == msg->type || HTTP_MESSAGE_REQ_BODY == msg->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);
- ;
-} \ No newline at end of file
diff --git a/src/http_decoder.cpp b/src/http_decoder.cpp
new file mode 100644
index 0000000..750a739
--- /dev/null
+++ b/src/http_decoder.cpp
@@ -0,0 +1,833 @@
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "http_decoder_inc.h"
+
+__thread struct http_decoder_stat _th_stat;
+
+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;
+}
+
+static void http_message_free(struct session *sess, void *http_msg, void *cb_arg)
+{
+ if (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)
+{
+ assert(ev_ctx);
+
+ 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;
+
+ if(http_event_is_req(event)){
+ queue_idx = http_decoder_result_queue_req_index(queue);
+ }else{
+ queue_idx = http_decoder_result_queue_res_index(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
+ msg = http_message_new(HTTP_TRANSACTION_NEW, queue, queue_idx, HTTP_REQUEST);
+ session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
+ 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, ev_ctx->topic_id, msg);
+ 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, ev_ctx->topic_id, msg);
+ break;
+ case HTTP_EVENT_REQ_HDR_END:
+ {
+ http_decoder_join_url_finally(ev_ctx, http_decoder_result_queue_peek_req(queue), mempool);
+ /* maybe some parsed headers in buffer, but has not pushed to plugins yet */
+ half_data = http_decoder_result_queue_peek_req(queue);
+ 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, ev_ctx->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, ev_ctx->topic_id, msg);
+ }
+ break;
+ case HTTP_EVENT_REQ_BODY_BEGIN:
+ //do nothing, in BODY_DATA event
+ break;
+ case HTTP_EVENT_REQ_BODY_DATA:
+ msg = http_message_new(HTTP_MESSAGE_REQ_BODY, queue, queue_idx, HTTP_REQUEST);
+ session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
+ 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, ev_ctx->topic_id, msg);
+ break;
+ case HTTP_EVENT_REQ_END:
+ {
+ if(0 == session_is_symmetric(ev_ctx->ref_session, &flow_flag)){
+ if(SESSION_SEEN_C2S_FLOW == flow_flag){
+ msg = http_message_new(HTTP_TRANSACTION_FREE, queue, queue_idx, HTTP_REQUEST);
+ session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
+ }
+ }
+ 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_NEW, queue, queue_idx, HTTP_RESPONSE);
+ session_mq_publish_message(ev_ctx->ref_session, ev_ctx->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, ev_ctx->topic_id, msg);
+ break;
+ case HTTP_EVENT_RES_HDR:
+ msg = http_message_new(HTTP_MESSAGE_RES_HEADER, queue, queue_idx, HTTP_REQUEST);
+ session_mq_publish_message(ev_ctx->ref_session, ev_ctx->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, ev_ctx->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, ev_ctx->topic_id, msg);
+ break;
+ case HTTP_EVENT_RES_BODY_BEGIN:
+ break;
+ case HTTP_EVENT_RES_BODY_DATA:
+ msg = http_message_new(HTTP_MESSAGE_RES_BODY, queue, queue_idx, HTTP_RESPONSE);
+ session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
+ 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, ev_ctx->topic_id, msg);
+ break;
+ case HTTP_EVENT_RES_END:
+ msg = http_message_new(HTTP_TRANSACTION_FREE, queue, queue_idx, HTTP_RESPONSE);
+ session_mq_publish_message(ev_ctx->ref_session, ev_ctx->topic_id, msg);
+ 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;
+ }
+}
+
+static struct http_decoder *http_decoder_new(nmx_pool_t *mempool, http_event_cb *ev_cb, int decompress_switch)
+{
+ struct http_decoder *decoder = MEMPOOL_CALLOC(mempool, struct http_decoder, 1);
+ assert(decoder);
+ decoder->c2s_half = http_decoder_half_new(mempool, ev_cb, HTTP_REQUEST, decompress_switch);
+ decoder->s2c_half = http_decoder_half_new(mempool, ev_cb, HTTP_RESPONSE, decompress_switch);
+ return decoder;
+}
+
+static void http_decoder_free(nmx_pool_t *mempool, struct http_decoder *decoder)
+{
+ if (NULL == decoder)
+ {
+ return;
+ }
+ if (decoder->c2s_half != NULL)
+ {
+ http_decoder_half_free(mempool, decoder->c2s_half);
+ decoder->c2s_half = NULL;
+ }
+ if (decoder->s2c_half != NULL)
+ {
+ http_decoder_half_free(mempool, decoder->s2c_half);
+ decoder->s2c_half = NULL;
+ }
+ 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_exdata *ex_data = CALLOC(struct http_decoder_exdata, 1);
+ ex_data->mempool = nmx_create_pool(mempool_size);
+ ex_data->decoder = http_decoder_new(ex_data->mempool, http_event_handler, decompress_switch);
+ ex_data->queue = http_decoder_result_queue_new(ex_data->mempool, queue_size);
+ return ex_data;
+}
+
+static void http_decoder_exdata_free(struct http_decoder_exdata *ex_data)
+{
+ 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)
+ {
+ http_decoder_result_queue_free(ex_data->mempool, ex_data->queue);
+ ex_data->queue = NULL;
+ }
+
+ 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 0;
+}
+
+static void _http_decoder_context_free(struct http_decoder_context *ctx)
+{
+ if (NULL == ctx)
+ {
+ return;
+ }
+
+ if (ctx->fse != NULL)
+ {
+ fieldstat_easy_free(ctx->fse);
+ ctx->fse = NULL;
+ }
+
+ if (ctx->httpd_msg_topic_id >= 0)
+ {
+ stellar_session_mq_destroy_topic(ctx->st, ctx->httpd_msg_topic_id);
+ ctx->httpd_msg_topic_id = -1;
+ }
+
+ FREE(ctx);
+}
+
+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;
+ }
+
+ toml_free(root);
+ return ret;
+}
+
+static int http_msg_get_request_header(const struct http_message *msg, const struct hstring *key,
+ struct http_header *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, key, hdr_result);
+}
+
+static int http_msg_get_response_header(const struct http_message *msg, const struct hstring *key,
+ struct http_header *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, key, hdr_result);
+}
+
+static int http_msg_request_header_next(const struct http_message *msg,
+ struct http_header *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 *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);
+}
+
+static int http_msg_get_request_raw_body(const struct http_message *msg,
+ struct 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,
+ struct 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,
+ struct 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,
+ struct 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);
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void _httpd_ex_data_free_cb(struct session *s, int idx,
+ void *ex_data, void *arg)
+ {
+ 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)
+ {
+ // If not http, ignore this session
+ size_t payload_len;
+ const struct http_decoder_context *httpd_env = (struct http_decoder_context *)plugin_env;
+ const char *payload = session_get0_current_payload(sess, &payload_len);
+ if (payload != NULL && payload_len > 0)
+ {
+ 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 NULL;
+ }
+ }
+
+ struct http_decoder_exdata *ex_data = http_decoder_exdata_new(httpd_env->hd_cfg.mempool_size,
+ httpd_env->hd_cfg.result_queue_len,
+ httpd_env->hd_cfg.decompress_switch);
+ session_exdata_set(sess, httpd_env->ex_data_idx, ex_data);
+ return (void *)"fake_http_decoder_ctx"; // http decoder not use ctx, use exdata only!
+ }
+
+ void _httpd_session_ctx_free_cb(struct session *sess, void *session_ctx, void *plugin_env)
+ {
+ // done in _httpd_ex_data_free_cb()
+ }
+
+ void http_decoder_tcp_stream_msg_cb(struct session *sess, int topic_id, const void *msg, void *no_use_ctx, void *plugin_env)
+ {
+ struct http_decoder_context *httpd_env = (struct http_decoder_context *)plugin_env;
+ struct http_decoder_exdata *ex_data = (struct http_decoder_exdata *)session_exdata_get(sess, httpd_env->ex_data_idx);
+ size_t payload_len;
+
+ const char *payload = session_get0_current_payload(sess, &payload_len);
+ if (unlikely(0 == payload_len || NULL == ex_data))
+ {
+ return;
+ }
+
+ int thread_id = stellar_get_current_thread_id(httpd_env->st);
+ struct http_decoder_half *cur_half = NULL;
+
+ if (PACKET_DIRECTION_C2S == packet_get_direction(session_get0_current_packet(sess)))
+ {
+ cur_half = ex_data->decoder->c2s_half;
+ }
+ else
+ {
+ cur_half = ex_data->decoder->s2c_half;
+ }
+
+ http_decoder_half_reinit(cur_half, httpd_env->httpd_msg_topic_id, ex_data->queue,
+ ex_data->mempool, sess);
+ int ret = http_decoder_half_parse(cur_half, payload, payload_len);
+ if (ret < 0)
+ {
+ _th_stat.err_pkts += 1;
+ }
+ _th_stat.incoming_bytes += payload_len;
+ _th_stat.incoming_pkts += 1;
+ _th_stat.incoming_trans += http_decoder_half_trans_count(cur_half);
+ _th_stat.counter++;
+
+ http_decoder_stat_output(httpd_env, thread_id);
+ return;
+ }
+
+ void *http_decoder_init(struct stellar *st)
+ {
+ int httpd_msg_topic_id = -1, tcp_stream_topic_id = -1;
+ int thread_num = 0;
+
+ struct http_decoder_context *httpd_env = CALLOC(struct http_decoder_context, 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->ex_data_idx = stellar_session_exdata_new_index(st, "HTTP_DECODER",
+ _httpd_ex_data_free_cb,
+ NULL);
+ httpd_env->plugin_id = stellar_session_plugin_register(st, _httpd_session_ctx_new_cb,
+ _httpd_session_ctx_free_cb, (void *)httpd_env);
+ if (httpd_env->plugin_id < 0)
+ {
+ goto failed;
+ }
+
+ httpd_msg_topic_id = stellar_session_mq_get_topic_id(st, HTTP_DECODER_TOPIC);
+ if (httpd_msg_topic_id < 0)
+ {
+ httpd_msg_topic_id = stellar_session_mq_create_topic(st, HTTP_DECODER_TOPIC,
+ http_message_free, NULL);
+ }
+ httpd_env->httpd_msg_topic_id = httpd_msg_topic_id;
+
+ tcp_stream_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_TCP_STREAM);
+ assert(tcp_stream_topic_id >= 0);
+ stellar_session_mq_subscribe(st, tcp_stream_topic_id, http_decoder_tcp_stream_msg_cb, httpd_env->plugin_id);
+
+ thread_num = stellar_get_worker_thread_num(st);
+ assert(thread_num >= 1);
+ if (http_decoder_stat_init(httpd_env, thread_num) < 0)
+ {
+ goto failed;
+ }
+
+ printf("http_decoder_init succ: ex_data_idx:%d, plugin_id:%d, topic_id:%d\n",
+ httpd_env->ex_data_idx, httpd_env->plugin_id, httpd_env->httpd_msg_topic_id);
+ 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_context *httpd_env = (struct http_decoder_context *)plugin_env;
+ _http_decoder_context_free(httpd_env);
+ }
+
+ enum http_message_type http_message_type_get(const struct http_message *msg)
+ {
+ if (unlikely(NULL == msg))
+ {
+ return HTTP_MESSAGE_MAX;
+ }
+ return msg->type;
+ }
+
+ void http_message_get_request_line(const struct http_message *msg,
+ struct http_request_line *line)
+ {
+ if (unlikely(NULL == msg || msg->type != HTTP_MESSAGE_REQ_LINE))
+ {
+ if(line){
+ line->method.str = NULL;
+ line->uri.str = NULL;
+ line->version.str = NULL;
+ }
+ 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;
+
+ http_decoder_half_data_get_request_line(req_data, line);
+ }
+
+ void http_message_get_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.str = NULL;
+ line->status.str = 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);
+ }
+
+ void http_message_get_header(const struct http_message *msg, const struct hstring *key,
+ struct http_header *hdr_result)
+ {
+ int ret = -1;
+ if (unlikely(NULL == msg || NULL == key))
+ {
+ 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, key, hdr_result);
+ }
+ else if (HTTP_MESSAGE_RES_HEADER == msg->type)
+ {
+ ret = http_msg_get_response_header(msg, key, hdr_result);
+ }
+ if(ret >= 0){
+ return;
+ }
+ fail:
+ if(hdr_result){
+ hdr_result->key.str = NULL;
+ hdr_result->val.str = NULL;
+ }
+ return;
+ }
+
+ int http_message_header_next(const struct http_message *msg,
+ struct http_header *header)
+ {
+ 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->key.str = NULL;
+ header->val.str = NULL;
+ }
+ return -1;
+ }
+
+ int http_message_reset_header_iter(struct http_message *msg)
+ {
+ if (unlikely(NULL == msg))
+ {
+ return -1;
+ }
+ assert(msg->ref_queue);
+ assert(msg->queue_index < HD_RESULT_QUEUE_LEN);
+ if (HTTP_MESSAGE_REQ_HEADER == msg->type)
+ {
+ 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);
+ }
+ else if (HTTP_MESSAGE_RES_HEADER == msg->type)
+ {
+ 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);
+ }
+ return -1;
+ }
+
+ void http_message_get_raw_body(const struct http_message *msg,
+ struct hstring *body)
+ {
+ 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_BODY == msg->type)
+ {
+ ret = http_msg_get_request_raw_body(msg, body);
+ }
+ else if (HTTP_MESSAGE_RES_BODY == msg->type)
+ {
+ ret = http_msg_get_response_raw_body(msg, body);
+ }
+ if(ret < 0){
+ goto fail;
+ }
+ return;
+ fail:
+ if(body){
+ body->str = NULL;
+ body->str_len = 0;
+ }
+ return;
+ }
+
+ void http_message_get_decompress_body(const struct http_message *msg,
+ struct hstring *body)
+ {
+ 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_BODY == msg->type)
+ {
+ ret = http_msg_get_request_decompress_body(msg, body);
+ }
+ else if (HTTP_MESSAGE_RES_BODY == msg->type)
+ {
+ ret = http_msg_get_response_decompress_body(msg, body);
+ }
+ if(ret < 0){
+ goto fail;
+ }
+ return;
+ fail:
+ if(body){
+ body->str = NULL;
+ body->str_len = 0;
+ }
+ return;
+ }
+
+ void http_message_get_url(const struct http_message *msg, struct hstring *url)
+ {
+ if (unlikely(NULL == msg))
+ {
+ if(url){
+ url->str = NULL;
+ url->str_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_url(req_data, url) < 0){
+ goto fail;
+ }
+ return;
+
+ fail:
+ if(url){
+ url->str = NULL;
+ url->str_len = 0;
+ }
+ return;
+ }
+
+ 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
diff --git a/src/http_decoder_half.c b/src/http_decoder_half.cpp
index 7af1956..d3c2ee2 100644
--- a/src/http_decoder_half.c
+++ b/src/http_decoder_half.cpp
@@ -1,27 +1,9 @@
-/*
-**********************************************************************************************
-* File: http_decoder_half.c
-* Description:
-* Authors: Liu WenTan <[email protected]>
-* Date: 2024-01-10
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
-
-#include "stellar/utils.h"
-#include "stellar/session_mq.h"
-#include "llhttp.h"
-#include "http_decoder.h"
#include "http_decoder_inc.h"
-#include "http_decoder_utils.h"
-#include "http_decoder_half.h"
-#include "http_decoder_table.h"
-#include "http_content_decompress.h"
+#include "llhttp.h"
struct http_decoder_half_data
{
@@ -46,9 +28,9 @@ struct http_decoder_half
llhttp_t parser;
llhttp_settings_t settings;
enum llhttp_errno error;
-
int decompress_switch;
+ // uint8_t is_request_flow;
enum http_event event;
http_event_cb *http_ev_cb;
struct http_event_context *http_ev_ctx;
@@ -79,7 +61,7 @@ static void printf_debug_info(const char *desc, const char *at, size_t length)
}
}
#else
-#define printf_debug_info(desc, at, length)
+#define printf_debug_info(desc, at, length)
#endif
static void
@@ -137,7 +119,7 @@ static int on_message_begin(llhttp_t *http)
half->ref_data = NULL;
assert(half->http_ev_cb != NULL);
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx); // http_event_handler()
half->trans_counter++;
half->ref_data->transaction_index = half->transaction_seq++;
@@ -148,8 +130,7 @@ 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);
+ struct http_decoder_half *half = container_of(http, struct http_decoder_half, parser);
assert(half);
if (half->parser.type == HTTP_REQUEST)
@@ -157,11 +138,7 @@ static int on_message_complete(llhttp_t *http)
if (half->event == HTTP_EVENT_REQ_BODY_DATA)
{
half->event = HTTP_EVENT_REQ_BODY_END;
- if (half->http_ev_cb != NULL)
- {
- half->http_ev_cb(half->event, &half->ref_data,
- half->http_ev_ctx);
- }
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
}
}
else
@@ -169,11 +146,7 @@ static int on_message_complete(llhttp_t *http)
if (half->event == HTTP_EVENT_RES_BODY_DATA)
{
half->event = HTTP_EVENT_RES_BODY_END;
- if (half->http_ev_cb != NULL)
- {
- half->http_ev_cb(half->event, &half->ref_data,
- half->http_ev_ctx);
- }
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
}
}
@@ -181,18 +154,12 @@ static int on_message_complete(llhttp_t *http)
if (half->parser.type == HTTP_REQUEST)
{
half->event = HTTP_EVENT_REQ_END;
- if (half->http_ev_cb != NULL)
- {
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
- }
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
}
else
{
half->event = HTTP_EVENT_RES_END;
- if (half->http_ev_cb != NULL)
- {
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
- }
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
}
return 0;
@@ -205,10 +172,10 @@ static int on_reset(llhttp_t *http)
return 0;
}
-static inline int is_line_eof(struct http_decoder_half *half)
+static inline int is_line_crlf(struct http_decoder_half *half)
{
- const char *chr_r = memrchr(half->data, '\r', half->data_len);
- const char *chr_n = memrchr(half->data, '\n', half->data_len);
+ 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))
{
return 1;
@@ -238,7 +205,7 @@ static int on_method_complete(llhttp_t *http)
container_of(http, struct http_decoder_half, parser);
assert(half);
- if (is_line_eof(half) == 0)
+ if (is_line_crlf(half) == 0)
{
http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_METHOD);
}
@@ -291,7 +258,7 @@ static int on_uri_complete(llhttp_t *http)
container_of(http, struct http_decoder_half, parser);
assert(half);
- if (is_line_eof(half) == 0)
+ if (is_line_crlf(half) == 0)
{
http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_URI);
}
@@ -329,7 +296,7 @@ static int on_version_complete(llhttp_t *http)
container_of(http, struct http_decoder_half, parser);
assert(half);
- if (is_line_eof(half) == 0)
+ if (is_line_crlf(half) == 0)
{
http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_VERSION);
}
@@ -342,7 +309,7 @@ static int on_version_complete(llhttp_t *http)
if (half->parser.type == HTTP_REQUEST)
{
half->event = HTTP_EVENT_REQ_LINE;
- if (half->http_ev_cb)
+ if (half->http_ev_cb) // http_event_handler()
{
half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
}
@@ -374,7 +341,7 @@ static int on_status_complete(llhttp_t *http)
container_of(http, struct http_decoder_half, parser);
assert(half);
- if (is_line_eof(half) == 0)
+ if (is_line_crlf(half) == 0)
{
http_decoder_table_cache(half->ref_data->table, HTTP_ITEM_STATUS);
}
@@ -385,7 +352,7 @@ static int on_status_complete(llhttp_t *http)
if (half->parser.type == HTTP_RESPONSE)
{
half->event = HTTP_EVENT_RES_LINE;
- if (half->http_ev_cb != NULL)
+ if (half->http_ev_cb != NULL) // http_event_handler()
{
half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
}
@@ -459,8 +426,7 @@ static int on_header_value_complete(llhttp_t *http)
struct http_header http_hdr = {0};
struct hstring key = {.str = (char *)"Content-Encoding", .str_len = 16};
- if (http_decoder_table_get_header(half->ref_data->table, &key,
- &http_hdr) == 0)
+ if (http_decoder_table_get_header(half->ref_data->table, &key, &http_hdr) == 0)
{
char encoding_str[MAX_ENCODING_STR_LEN + 1] = {0};
size_t str_len = http_hdr.val.str_len;
@@ -520,20 +486,12 @@ static int on_headers_complete(llhttp_t *http)
if (half->parser.type == HTTP_REQUEST)
{
half->event = HTTP_EVENT_REQ_HDR_END;
- if (half->http_ev_cb)
- {
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
- }
}
-
- if (half->parser.type == HTTP_RESPONSE)
+ else
{
half->event = HTTP_EVENT_RES_HDR_END;
- if (half->http_ev_cb)
- {
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
- }
}
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx); // http_event_handler()
return 0;
}
@@ -553,11 +511,7 @@ static int on_body(llhttp_t *http, const char *at, size_t length)
if (half->event == HTTP_EVENT_REQ_HDR_END)
{
half->event = HTTP_EVENT_REQ_BODY_BEGIN;
- if (half->http_ev_cb)
- {
- half->http_ev_cb(half->event, &half->ref_data,
- half->http_ev_ctx);
- }
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx); // http_event_handler()
}
}
else
@@ -565,11 +519,7 @@ static int on_body(llhttp_t *http, const char *at, size_t length)
if (half->event == HTTP_EVENT_RES_HDR_END)
{
half->event = HTTP_EVENT_RES_BODY_BEGIN;
- if (half->http_ev_cb)
- {
- half->http_ev_cb(half->event, &half->ref_data,
- half->http_ev_ctx);
- }
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
}
}
@@ -595,35 +545,24 @@ static int on_body(llhttp_t *http, const char *at, size_t length)
if (half->parser.type == HTTP_REQUEST)
{
half->event = HTTP_EVENT_REQ_BODY_DATA;
- if (half->http_ev_cb)
- {
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
- }
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx); // http_event_handler()
}
else
{
half->event = HTTP_EVENT_RES_BODY_DATA;
- if (half->http_ev_cb)
- {
- half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
- }
+ half->http_ev_cb(half->event, &half->ref_data, half->http_ev_ctx);
}
return 0;
}
-static void
-http_decoder_half_init(struct http_decoder_half *half,
- http_event_cb *http_ev_cb, int type)
+static void http_decoder_half_init(struct http_decoder_half *half,
+ http_event_cb *http_ev_cb, enum llhttp_type type)
{
- if (NULL == half)
- {
- return;
- }
-
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;
@@ -653,14 +592,12 @@ http_decoder_half_init(struct http_decoder_half *half,
half->settings.on_body = on_body;
half->error = HPE_OK;
-
- half->http_ev_cb = http_ev_cb;
-
+ half->http_ev_cb = http_ev_cb; // http_event_handler()
half->ref_data = NULL;
}
struct http_decoder_half *
-http_decoder_half_new(nmx_pool_t *mempool, http_event_cb *ev_cb, int http_type,
+http_decoder_half_new(nmx_pool_t *mempool, http_event_cb *ev_cb, enum llhttp_type http_type,
int decompress_switch)
{
struct http_decoder_half *half = MEMPOOL_CALLOC(mempool, struct http_decoder_half, 1);
@@ -694,7 +631,6 @@ void http_decoder_half_reinit(struct http_decoder_half *half, int topic_id,
nmx_pool_t *mempool, struct session *sess)
{
assert(half != NULL);
-
if (half->ref_data != NULL)
{
http_decoder_table_reinit(half->ref_data->table);
@@ -712,31 +648,13 @@ static void publish_message_for_parsed_header(struct http_decoder_half *half)
{
return;
}
-
- // publish complete kv-header message
- struct http_message *msg = NULL;
- size_t queue_idx = 0;
- struct http_decoder_result_queue *queue = half->http_ev_ctx->ref_queue;
-
- if (half->parser.type == HTTP_REQUEST)
- {
- queue_idx = http_decoder_result_queue_req_index(queue);
-
- msg = http_message_new(HTTP_MESSAGE_REQ_HEADER, queue, queue_idx);
-
- session_mq_publish_message(half->http_ev_ctx->ref_session,
- half->http_ev_ctx->topic_id, msg);
- }
- else
- {
- // http response
- queue_idx = http_decoder_result_queue_res_index(queue);
-
- msg = http_message_new(HTTP_MESSAGE_RES_HEADER, queue, queue_idx);
-
- session_mq_publish_message(half->http_ev_ctx->ref_session,
- half->http_ev_ctx->topic_id, msg);
+ if (half->parser.type == HTTP_REQUEST){
+ 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); // http_event_handler();
+ return;
}
int http_decoder_half_parse(struct http_decoder_half *half, const char *data,
@@ -752,7 +670,7 @@ int http_decoder_half_parse(struct http_decoder_half *half, const char *data,
half->error = llhttp_execute(&half->parser, data, data_len);
int ret = 0;
- uint8_t type = 0;
+ enum llhttp_type type = HTTP_BOTH;
struct http_decoder_half_data *half_data = NULL;
switch (half->error)
@@ -767,7 +685,7 @@ int http_decoder_half_parse(struct http_decoder_half *half, const char *data,
ret = 0;
break;
default:
- type = half->parser.type;
+ type = (enum llhttp_type)half->parser.type;
llhttp_init(&half->parser, type, &half->settings);
ret = -1;
break;
@@ -807,8 +725,9 @@ int http_decoder_half_parse(struct http_decoder_half *half, const char *data,
{
http_decoder_table_reset_header_complete(half->ref_data->table);
}
- else
+ else
{
+ //if headers are not completed with EOF \r\n\r\n, push the parsed headers so far
publish_message_for_parsed_header(half);
}
@@ -926,11 +845,6 @@ void http_decoder_half_data_free(nmx_pool_t *mempool,
int http_decoder_half_data_get_request_line(struct http_decoder_half_data *data,
struct http_request_line *line)
{
- if (NULL == data || NULL == line)
- {
- return -1;
- }
-
http_decoder_table_get_method(data->table, &line->method);
http_decoder_table_get_uri(data->table, &line->uri);
http_decoder_table_get_version(data->table, &line->version);
@@ -944,11 +858,6 @@ int http_decoder_half_data_get_request_line(struct http_decoder_half_data *data,
int http_decoder_half_data_get_response_line(struct http_decoder_half_data *data,
struct http_response_line *line)
{
- if (NULL == data || NULL == line)
- {
- return -1;
- }
-
http_decoder_table_get_version(data->table, &line->version);
http_decoder_table_get_status(data->table, &line->status);
@@ -959,25 +868,17 @@ int http_decoder_half_data_get_response_line(struct http_decoder_half_data *data
return 0;
}
-int http_decoder_half_data_get_header(struct http_decoder_half_data *data,
- struct hstring *key,
+int http_decoder_half_data_get_header(const struct http_decoder_half_data *data,
+ const struct hstring *key,
struct http_header *hdr_result)
{
- if (NULL == data || NULL == key || NULL == hdr_result)
- {
- return -1;
- }
return http_decoder_table_get_header(data->table, key, hdr_result);
}
int http_decoder_half_data_iter_header(struct http_decoder_half_data *data,
struct http_header *header)
{
- if (NULL == data || NULL == header)
- {
- return -1;
- }
- return http_decoder_table_iter_header(data->table, 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)
@@ -998,7 +899,7 @@ int http_decoder_half_data_has_parsed_header(struct http_decoder_half_data *data
return http_decoder_table_has_parsed_header(data->table);
}
-int http_decoder_half_data_get_raw_body(struct http_decoder_half_data *data,
+int http_decoder_half_data_get_raw_body(const struct http_decoder_half_data *data,
struct hstring *body)
{
if (NULL == data || NULL == body)
@@ -1008,14 +909,9 @@ int http_decoder_half_data_get_raw_body(struct http_decoder_half_data *data,
return http_decoder_table_get_body(data->table, body);
}
-int http_decoder_half_data_get_decompress_body(struct http_decoder_half_data *data,
+int http_decoder_half_data_get_decompress_body(const struct http_decoder_half_data *data,
struct hstring *body)
{
- if (NULL == data || NULL == body)
- {
- return -1;
- }
-
if (HTTP_CONTENT_ENCODING_NONE == data->content_encoding)
{
return http_decoder_table_get_body(data->table, body);
@@ -1115,7 +1011,7 @@ int http_decoder_join_url_finally(struct http_event_context *ev_ctx,
void http_decoder_get_host_feed_url(struct http_decoder_half *half)
{
struct http_header host_result = {};
- struct hstring host_key = {"Host", 4};
+ struct hstring host_key = {(char *)"Host", 4};
const char *host_refer_str = NULL;
int host_refer_len = 0;
@@ -1140,14 +1036,17 @@ int http_half_data_get_url(struct http_decoder_half_data *res_data, struct hstri
{
return -1;
}
-
url->str = res_data->joint_url.str;
url->str_len = res_data->joint_url.str_len;
-
return 0;
}
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);
} \ No newline at end of file
diff --git a/src/http_decoder_half.h b/src/http_decoder_half.h
index a2ff5f8..362708a 100644
--- a/src/http_decoder_half.h
+++ b/src/http_decoder_half.h
@@ -1,28 +1,12 @@
-/*
-**********************************************************************************************
-* File: http_decoder_half.h
-* Description:
-* Authors: Liu WenTan <[email protected]>
-* Date: 2024-01-10
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
-
#ifndef _HTTP_DECODER_HALF_H_
#define _HTTP_DECODER_HALF_H_
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
#include <stddef.h>
-
#include "stellar/session.h"
#include "http_decoder.h"
#include "http_content_decompress.h"
#include "http_decoder_result_queue.h"
+#include "llhttp.h"
// only one http event is fired at a time
enum http_event {
@@ -59,7 +43,7 @@ typedef void http_event_cb(enum http_event event, struct http_decoder_half_data
struct http_event_context *ev_ctx);
struct http_decoder_half *
-http_decoder_half_new(nmx_pool_t *mempool, http_event_cb *event_cb, int http_type,
+http_decoder_half_new(nmx_pool_t *mempool, http_event_cb *event_cb, enum llhttp_type http_type,
int decompress_switch);
void http_decoder_half_free(nmx_pool_t *mempool, struct http_decoder_half *half);
@@ -86,18 +70,18 @@ int http_decoder_half_data_get_request_line(struct http_decoder_half_data *data,
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(struct http_decoder_half_data *data,
- struct hstring *key, struct http_header *hdr_res);
+int http_decoder_half_data_get_header(const struct http_decoder_half_data *data,
+ const struct hstring *key, struct http_header *hdr_res);
int http_decoder_half_data_iter_header(struct http_decoder_half_data *data,
struct http_header *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(struct http_decoder_half_data *data,
+int http_decoder_half_data_get_raw_body(const struct http_decoder_half_data *data,
struct hstring *body);
-int http_decoder_half_data_get_decompress_body(struct http_decoder_half_data *data,
+int http_decoder_half_data_get_decompress_body(const struct http_decoder_half_data *data,
struct hstring *body);
void http_decoder_half_data_dump(struct http_decoder_half *half);
@@ -112,8 +96,5 @@ int http_decoder_join_url_finally(struct http_event_context *ev_ctx,
int http_half_data_get_url(struct http_decoder_half_data *res_data, struct hstring *url);
int http_half_data_get_transaction_seq(struct http_decoder_half_data *hf_data);
-#ifdef __cplusplus
-}
-#endif
-
+void http_half_data_update_commit_index(struct http_decoder_half_data * half_data);
#endif \ No newline at end of file
diff --git a/src/http_decoder_inc.h b/src/http_decoder_inc.h
index 2d6a5c0..3e2939d 100644
--- a/src/http_decoder_inc.h
+++ b/src/http_decoder_inc.h
@@ -15,36 +15,114 @@
extern "C"
{
#endif
+#include "stellar/stellar.h"
+#include "stellar/utils.h"
+#include "stellar/session.h"
+#include "stellar/session_mq.h"
+#include "stellar/session_exdata.h"
#include "mempool/nmx_palloc.h"
#include "stellar/utils.h"
#include "http_decoder.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 "fieldstat/fieldstat_easy.h"
+#include "toml/toml.h"
+#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 1
#ifdef 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 "./http_decoder.fs"
+
+struct http_decoder_config
+{
+ int decompress_switch;
+ int stat_interval_pkts; // call fieldstat_incrby every stat_interval_pkts
+ int stat_output_interval;
+ 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;
+};
+
+struct http_decoder
+{
+ struct http_decoder_half *c2s_half;
+ struct http_decoder_half *s2c_half;
+};
+
+struct http_decoder_exdata
+{
+ struct http_decoder_result_queue *queue;
+ struct http_decoder *decoder;
+ nmx_pool_t *mempool;
+};
+
+struct http_decoder_stat
+{
+ long long incoming_bytes;
+ long long incoming_pkts;
+ long long incoming_trans;
+ long long err_pkts;
+ int counter;
+};
+
+struct http_decoder_context
+{
+ int plugin_id;
+ int httpd_msg_topic_id;
+ int ex_data_idx;
+ int fs_incoming_bytes_id;
+ int fs_incoming_pkts_id;
+ int fs_incoming_trans_id;
+ int fs_err_pkts_id;
+ struct stellar *st;
+ struct fieldstat_easy *fse;
+ struct http_decoder_config hd_cfg;
+};
struct http_message;
-struct http_message *
-http_message_new(enum http_message_type type,
- struct http_decoder_result_queue *queue,
- int queue_index);
+struct http_message *http_message_new(enum http_message_type type, struct http_decoder_result_queue *queue,
+ int queue_index, unsigned char flow_type);
#ifdef __cplusplus
}
diff --git a/src/http_decoder_result_queue.c b/src/http_decoder_result_queue.cpp
index 9a60d15..32d2895 100644
--- a/src/http_decoder_result_queue.c
+++ b/src/http_decoder_result_queue.cpp
@@ -7,13 +7,8 @@
* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
***********************************************************************************************
*/
-
#include <assert.h>
-
-#include "stellar/utils.h"
-#include "http_decoder_half.h"
#include "http_decoder_inc.h"
-#include "http_decoder_result_queue.h"
struct http_decoder_result_queue *
http_decoder_result_queue_new(nmx_pool_t *mempool, size_t queue_size)
@@ -25,11 +20,9 @@ http_decoder_result_queue_new(nmx_pool_t *mempool, size_t queue_size)
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;
}
@@ -52,17 +45,14 @@ void http_decoder_result_queue_free(nmx_pool_t *mempool,
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;
}
@@ -70,7 +60,6 @@ void http_decoder_result_queue_inc_req_index(struct http_decoder_result_queue *q
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;
}
@@ -78,14 +67,12 @@ void http_decoder_result_queue_inc_res_index(struct http_decoder_result_queue *q
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;
}
@@ -95,12 +82,10 @@ int http_decoder_result_queue_push_req(struct http_decoder_result_queue *queue,
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;
}
@@ -111,7 +96,6 @@ int http_decoder_result_queue_push_res(struct http_decoder_result_queue *queue,
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;
@@ -127,7 +111,6 @@ 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;
@@ -155,7 +138,6 @@ 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;
}
@@ -166,7 +148,6 @@ 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/src/http_decoder_result_queue.h b/src/http_decoder_result_queue.h
index cd2163a..4d024eb 100644
--- a/src/http_decoder_result_queue.h
+++ b/src/http_decoder_result_queue.h
@@ -7,18 +7,10 @@
* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
***********************************************************************************************
*/
-
-
#ifndef _HTTP_DECODER_RESULT_QUEUE_H_
#define _HTTP_DECODER_RESULT_QUEUE_H_
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
#include <stddef.h>
-
#include "mempool/nmx_palloc.h"
#include "http_decoder_half.h"
@@ -66,8 +58,4 @@ 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);
-#ifdef __cplusplus
-}
-#endif
-
#endif \ No newline at end of file
diff --git a/src/http_decoder_stat.cpp b/src/http_decoder_stat.cpp
new file mode 100644
index 0000000..ffa01eb
--- /dev/null
+++ b/src/http_decoder_stat.cpp
@@ -0,0 +1,99 @@
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "http_decoder_inc.h"
+
+static __thread struct http_decoder_stat _th_stat;
+
+int http_decoder_stat_init(struct http_decoder_context *ctx, int thread_num)
+{
+ ctx->fse = fieldstat_easy_new(thread_num, "http_decoder_statistics", NULL, 0);
+ if (NULL == ctx->fse)
+ {
+ fprintf(stderr, "fieldstat_easy_new failed.");
+ return -1;
+ }
+
+ ctx->fs_incoming_bytes_id =
+ fieldstat_easy_register_counter(ctx->fse, "incoming_bytes");
+ if (ctx->fs_incoming_bytes_id < 0)
+ {
+ fprintf(stderr, "fieldstat_easy_register_counter incoming_bytes failed.");
+ return -1;
+ }
+
+ ctx->fs_incoming_trans_id =
+ fieldstat_easy_register_counter(ctx->fse, "incoming_trans");
+ if (ctx->fs_incoming_trans_id < 0)
+ {
+ fprintf(stderr, "fieldstat_easy_register_counter incoming_trans failed.");
+ return -1;
+ }
+
+ ctx->fs_incoming_pkts_id =
+ fieldstat_easy_register_counter(ctx->fse, "incoming_pkts");
+ if (ctx->fs_incoming_pkts_id < 0)
+ {
+ fprintf(stderr, "fieldstat_easy_register_counter incoming_pkts failed.");
+ return -1;
+ }
+
+ ctx->fs_err_pkts_id = fieldstat_easy_register_counter(ctx->fse, "err_pkts");
+ if (ctx->fs_err_pkts_id < 0)
+ {
+ fprintf(stderr, "fieldstat_easy_register_counter err_pkts failed.");
+ return -1;
+ }
+
+ int stat_output_interval = DEFAULT_STAT_OUTPUT_INTERVAL;
+ if (ctx->hd_cfg.stat_output_interval > 0)
+ {
+ stat_output_interval = ctx->hd_cfg.stat_output_interval;
+ }
+
+ int ret = fieldstat_easy_enable_auto_output(ctx->fse, FILEDSTAT_OUTPUT_FILE,
+ stat_output_interval);
+ if (ret < 0)
+ {
+ fprintf(stderr, "fieldstat_easy_enable_auto_output failed.");
+ return -1;
+ }
+
+ return 0;
+}
+
+void http_decoder_stat_output(struct http_decoder_context *ctx, int thread_id)
+{
+ assert(ctx != NULL);
+
+ int stat_interval_pkts = DEFAULT_STAT_INTERVAL_PKTS;
+ if (ctx->hd_cfg.stat_interval_pkts > 0)
+ {
+ stat_interval_pkts = ctx->hd_cfg.stat_interval_pkts;
+ }
+
+ if (_th_stat.counter >= stat_interval_pkts)
+ {
+ fieldstat_easy_counter_incrby(ctx->fse, thread_id,
+ ctx->fs_incoming_bytes_id, NULL, 0,
+ _th_stat.incoming_bytes);
+
+ fieldstat_easy_counter_incrby(ctx->fse, thread_id,
+ ctx->fs_incoming_pkts_id, NULL, 0,
+ _th_stat.incoming_pkts);
+
+ fieldstat_easy_counter_incrby(ctx->fse, thread_id,
+ ctx->fs_incoming_trans_id, NULL, 0,
+ _th_stat.incoming_trans);
+
+ fieldstat_easy_counter_incrby(ctx->fse, thread_id,
+ ctx->fs_err_pkts_id, NULL, 0,
+ _th_stat.err_pkts);
+
+ _th_stat.counter = 0;
+ _th_stat.err_pkts = 0;
+ _th_stat.incoming_bytes = 0;
+ _th_stat.incoming_pkts = 0;
+ _th_stat.incoming_trans = 0;
+ }
+}
diff --git a/src/http_decoder_stat.h b/src/http_decoder_stat.h
new file mode 100644
index 0000000..dbf245f
--- /dev/null
+++ b/src/http_decoder_stat.h
@@ -0,0 +1,5 @@
+#ifndef _HTTP_DECODER_STAT_H_
+#define _HTTP_DECODER_STAT_H_ 1
+int http_decoder_stat_init(struct http_decoder_context *ctx, int thread_num);
+void http_decoder_stat_output(struct http_decoder_context *ctx, int thread_id);
+#endif \ No newline at end of file
diff --git a/src/http_decoder_string.c b/src/http_decoder_string.cpp
index 5414c5b..e10b4a0 100644
--- a/src/http_decoder_string.c
+++ b/src/http_decoder_string.cpp
@@ -1,21 +1,8 @@
-/*
-**********************************************************************************************
-* File: http_decoder_string.h
-* Description:
-* Authors: LuWenPeng <[email protected]>
-* Date: 2022-10-31
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-
-#include "stellar/utils.h"
-#include "http_decoder_utils.h"
-#include "http_decoder_string.h"
+#include "http_decoder_inc.h"
static const char *string_state_to_desc(enum string_state state)
{
@@ -64,7 +51,6 @@ static void string_refer2cache(struct http_decoder_string *rstr)
if (0 == rstr->refer.str_len) {
return;
}
-
if (rstr->cache.str_len >= rstr->max_cache_size) {
return;
}
@@ -84,7 +70,6 @@ static void string_refer2cache(struct http_decoder_string *rstr)
}
rstr->cache.str_len = length;
-
rstr->refer.str = NULL;
rstr->refer.str_len = 0;
}
@@ -93,7 +78,6 @@ static void string_commit2cache(struct http_decoder_string *rstr)
{
if (rstr->cache.str_len == rstr->commit.str_len &&
rstr->cache.str == rstr->commit.str) {
-
rstr->commit.str = NULL;
rstr->commit.str_len = 0;
return;
@@ -141,7 +125,6 @@ void http_decoder_string_cache(struct http_decoder_string *rstr)
abort();
break;
}
-
rstr->state = STRING_STATE_CACHE;
}
@@ -226,19 +209,17 @@ void http_decoder_string_reinit(struct http_decoder_string *rstr)
rstr->refer.str = NULL;
rstr->refer.str_len = 0;
-
rstr->commit.str = NULL;
rstr->commit.str_len = 0;
-
rstr->state = STRING_STATE_INIT;
}
-enum string_state http_decoder_string_state(struct http_decoder_string *rstr)
+enum string_state http_decoder_string_state(const struct http_decoder_string *rstr)
{
return rstr->state;
}
-int http_decoder_string_get(struct http_decoder_string *rstr, struct hstring *out)
+int http_decoder_string_get(const struct http_decoder_string *rstr, struct hstring *out)
{
if (NULL == rstr || NULL == out) {
return -1;
diff --git a/src/http_decoder_string.h b/src/http_decoder_string.h
index f9d81dd..4c95960 100644
--- a/src/http_decoder_string.h
+++ b/src/http_decoder_string.h
@@ -1,24 +1,8 @@
-/*
-**********************************************************************************************
-* File: http_decoder_string.h
-* Description:
-* Authors: LuWenPeng <[email protected]>
-* Date: 2022-10-31
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
#ifndef _HTTP_DECODER_STRING_H_
#define _HTTP_DECODER_STRING_H_
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
#include "http_decoder.h"
-
enum string_state {
STRING_STATE_INIT,
STRING_STATE_REFER,
@@ -82,14 +66,9 @@ void http_decoder_string_init(struct http_decoder_string *rstr,
void http_decoder_string_reinit(struct http_decoder_string *rstr);
-enum string_state http_decoder_string_state(struct http_decoder_string *rstr);
+enum string_state http_decoder_string_state(const struct http_decoder_string *rstr);
-int http_decoder_string_get(struct http_decoder_string *rstr, struct hstring *out);
+int http_decoder_string_get(const struct http_decoder_string *rstr, struct hstring *out);
void http_decoder_string_dump(struct http_decoder_string *rstr, const char *desc);
-
-#ifdef __cplusplus
-}
-#endif
-
#endif \ No newline at end of file
diff --git a/src/http_decoder_table.c b/src/http_decoder_table.cpp
index cc3e7cb..b11e1b9 100644
--- a/src/http_decoder_table.c
+++ b/src/http_decoder_table.cpp
@@ -1,22 +1,7 @@
-/*
-**********************************************************************************************
-* File: http_decoder_table.c
-* Description:
-* Authors: LuWenPeng <[email protected]>
-* Date: 2022-10-31
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
-
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-
-#include "http_decoder_table.h"
-#include "http_decoder.h"
-#include "http_decoder_string.h"
-#include "stellar/utils.h"
+#include "http_decoder_inc.h"
#define INIT_HEADER_CNT 16
#define MAX_URI_CACHE_SIZE 2048
@@ -41,8 +26,9 @@ struct http_decoder_table {
nmx_pool_t *ref_mempool;
int header_complete; // flag for all headers parsed completely
size_t header_cnt;
- size_t header_index;
- size_t header_iter;
+ 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_header_next()
struct http_decoder_header *headers;
};
@@ -79,7 +65,7 @@ struct http_decoder_table *http_decoder_table_new(nmx_pool_t *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;
@@ -90,23 +76,18 @@ void http_decoder_table_free(struct http_decoder_table *table)
if (NULL == table) {
return;
}
-
if (table->uri.cache.str != NULL) {
FREE(table->uri.cache.str);
}
-
if (table->status.cache.str != NULL) {
FREE(table->status.cache.str);
}
-
if (table->method.cache.str != NULL) {
FREE(table->method.cache.str);
}
-
if (table->version.cache.str != NULL) {
FREE(table->version.cache.str);
}
-
if (table->body.cache.str != NULL) {
FREE(table->body.cache.str);
}
@@ -125,7 +106,6 @@ void http_decoder_table_free(struct http_decoder_table *table)
MEMPOOL_FREE(table->ref_mempool, table->headers);
table->headers = NULL;
}
-
MEMPOOL_FREE(table->ref_mempool, table);
}
@@ -135,7 +115,6 @@ 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);
@@ -361,18 +340,16 @@ void http_decoder_table_reset(struct http_decoder_table *table, enum http_item t
void http_decoder_table_reinit(struct http_decoder_table *table)
{
- if (NULL == table) {
- return;
- }
-
- struct http_decoder_header *header = NULL;
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->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);
@@ -404,60 +381,51 @@ void http_decoder_table_dump(struct http_decoder_table *table)
}
}
-int http_decoder_table_get_uri(struct http_decoder_table *table, struct hstring *out)
+int http_decoder_table_get_uri(const struct http_decoder_table *table, struct hstring *out)
{
if (NULL == table || NULL == out) {
return -1;
}
-
return http_decoder_string_get(&table->uri, out);
}
-int http_decoder_table_get_method(struct http_decoder_table *table, struct hstring *out)
+int http_decoder_table_get_method(const struct http_decoder_table *table, struct hstring *out)
{
if (NULL == table || NULL == out) {
return -1;
}
-
return http_decoder_string_get(&table->method, out);
}
-int http_decoder_table_get_status(struct http_decoder_table *table, struct hstring *out)
+int http_decoder_table_get_status(const struct http_decoder_table *table, struct hstring *out)
{
if (NULL == table || NULL == out) {
return -1;
}
-
return http_decoder_string_get(&table->status, out);
}
-int http_decoder_table_get_version(struct http_decoder_table *table, struct hstring *out)
+int http_decoder_table_get_version(const struct http_decoder_table *table, struct hstring *out)
{
if (NULL == table || NULL == out) {
return -1;
}
-
return http_decoder_string_get(&table->version, out);
}
-int http_decoder_table_get_body(struct http_decoder_table *table, struct hstring *out)
+int http_decoder_table_get_body(const struct http_decoder_table *table, struct hstring *out)
{
if (NULL == table || NULL == out) {
return -1;
}
-
return http_decoder_string_get(&table->body, out);
}
-int http_decoder_table_get_header(struct http_decoder_table *table, struct hstring *key,
+int http_decoder_table_get_header(const struct http_decoder_table *table, const struct hstring *key,
struct http_header *hdr_result)
{
- if (NULL == table || NULL == key->str || 0 == key->str_len || NULL == hdr_result) {
- return -1;
- }
-
for (size_t i = 0; i < table->header_cnt; i++) {
- struct http_decoder_header *tmp_header = &table->headers[i];
+ const struct http_decoder_header *tmp_header = &table->headers[i];
if (tmp_header->key.commit.str_len != key->str_len) {
continue;
}
@@ -475,7 +443,6 @@ int http_decoder_table_get_header(struct http_decoder_table *table, struct hstri
}
}
}
-
return -1;
}
@@ -485,7 +452,6 @@ int http_decoder_table_iter_header(struct http_decoder_table *table,
if (NULL == table || NULL == hdr) {
return -1;
}
-
if (table->header_iter >= table->header_cnt) {
return -1;
}
@@ -498,13 +464,12 @@ int http_decoder_table_iter_header(struct http_decoder_table *table,
http_decoder_string_get(&tmp_header->key, &hdr->key);
http_decoder_string_get(&tmp_header->val, &hdr->val);
table->header_iter++;
- return 0;
+ return 1;
}
}
hdr->key.str = NULL;
hdr->key.str_len = 0;
-
hdr->val.str = NULL;
hdr->val.str_len = 0;
@@ -519,13 +484,15 @@ int http_decoder_table_reset_header_iter(struct http_decoder_table *table)
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->header_iter == table->header_index)) {
+ if (NULL == table || (table->commit_header_index == table->header_index)) {
return 0;
}
- 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) {
+ 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;
}
@@ -537,7 +504,6 @@ int http_decoder_table_header_complete(struct http_decoder_table *table)
if (NULL == table) {
return -1;
}
-
return table->header_complete;
}
@@ -546,7 +512,6 @@ void http_decoder_table_set_header_complete(struct http_decoder_table *table)
if (NULL == table) {
return;
}
-
table->header_complete = 1;
}
@@ -555,6 +520,10 @@ 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;
} \ No newline at end of file
diff --git a/src/http_decoder_table.h b/src/http_decoder_table.h
index 906a28d..ce79d46 100644
--- a/src/http_decoder_table.h
+++ b/src/http_decoder_table.h
@@ -1,23 +1,6 @@
-/*
-**********************************************************************************************
-* File: http_decoder_table.h
-* Description:
-* Authors: LuWenPeng <[email protected]>
-* Date: 2022-10-31
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
-
#ifndef _HTTP_DECODER_TABLE_H_
#define _HTTP_DECODER_TABLE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include <stddef.h>
-
#include "http_decoder.h"
#include "http_decoder_inc.h"
#include "http_decoder_string.h"
@@ -53,18 +36,18 @@ 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(struct http_decoder_table *table, struct hstring *out);
+int http_decoder_table_get_uri(const struct http_decoder_table *table, struct hstring *out);
-int http_decoder_table_get_method(struct http_decoder_table *table, struct hstring *out);
+int http_decoder_table_get_method(const struct http_decoder_table *table, struct hstring *out);
-int http_decoder_table_get_status(struct http_decoder_table *table, struct hstring *out);
+int http_decoder_table_get_status(const struct http_decoder_table *table, struct hstring *out);
-int http_decoder_table_get_version(struct http_decoder_table *table, struct hstring *out);
+int http_decoder_table_get_version(const struct http_decoder_table *table, struct hstring *out);
-int http_decoder_table_get_body(struct http_decoder_table *table, struct hstring *out);
+int http_decoder_table_get_body(const struct http_decoder_table *table, struct hstring *out);
-int http_decoder_table_get_header(struct http_decoder_table *table,
- struct hstring *key,
+int http_decoder_table_get_header(const struct http_decoder_table *table,
+ const struct hstring *key,
struct http_header *hdr_res);
int http_decoder_table_iter_header(struct http_decoder_table *table,
@@ -91,8 +74,6 @@ void http_decoder_table_set_header_complete(struct http_decoder_table *table);
void http_decoder_table_reset_header_complete(struct http_decoder_table *table);
-#ifdef __cplusplus
-}
-#endif
+void http_decoder_table_update_commit_index(struct http_decoder_table *table);
#endif \ No newline at end of file
diff --git a/src/http_decoder_utils.c b/src/http_decoder_utils.c
deleted file mode 100644
index a5dfbe1..0000000
--- a/src/http_decoder_utils.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-**********************************************************************************************
-* File: http_decoder_utils.c
-* Description:
-* Authors: LuWenPeng <[email protected]>
-* Date: 2022-10-31
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
-#include <string.h>
-
-#include "stellar/utils.h"
-
-char *safe_dup(const char *str, size_t len)
-{
- if (str == NULL || len == 0) {
- return NULL;
- }
-
- char *dup = CALLOC(char, len + 1);
- memcpy(dup, str, len);
-
- return dup;
-} \ No newline at end of file
diff --git a/src/http_decoder_utils.cpp b/src/http_decoder_utils.cpp
new file mode 100644
index 0000000..5686e2d
--- /dev/null
+++ b/src/http_decoder_utils.cpp
@@ -0,0 +1,137 @@
+#include <string.h>
+#include <assert.h>
+#include "http_decoder_inc.h"
+
+char *safe_dup(const char *str, size_t len)
+{
+ if (str == NULL || len == 0) {
+ return NULL;
+ }
+ char *dup = CALLOC(char, len + 1);
+ memcpy(dup, str, len);
+ return dup;
+}
+
+const char *http_message_type_to_string(enum http_message_type type)
+{
+ const char *sname = "unknown_msg_type";
+
+ switch (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:
+ 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:
+ sname = "HTTP_MESSAGE_RES_BODY";
+ break;
+ case HTTP_MESSAGE_RES_BODY_END:
+ sname = "HTTP_MESSAGE_RES_BODY_END";
+ break;
+ case HTTP_TRANSACTION_NEW:
+ sname = "HTTP_TRANSACTION_NEW";
+ break;
+ case HTTP_TRANSACTION_FREE:
+ sname = "HTTP_TRANSACTION_FREE";
+ break;
+
+ default:
+ break;
+ }
+
+ 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:
+ case HTTP_MESSAGE_REQ_BODY_END:
+ is_req_msg = 1;
+ break;
+
+ case HTTP_MESSAGE_RES_LINE:
+ case HTTP_MESSAGE_RES_HEADER:
+ case HTTP_MESSAGE_RES_HEADER_END:
+ case HTTP_MESSAGE_RES_BODY:
+ case HTTP_MESSAGE_RES_BODY_END:
+ is_req_msg = 0;
+ break;
+
+ case HTTP_TRANSACTION_NEW:
+ case HTTP_TRANSACTION_FREE:
+ {
+ int cur_dir = packet_get_direction(session_get0_current_packet(sess));
+ if(PACKET_DIRECTION_C2S == cur_dir){
+ is_req_msg = 1;
+ }else{
+ is_req_msg = 0;
+ }
+ }
+ 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){
+ 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:
+ return 0;
+ break;
+
+ default:
+ assert(0);
+ fprintf(stderr, "unknow event type:%d\n", (int)event);
+ break;
+ }
+ return -1;
+} \ No newline at end of file
diff --git a/src/http_decoder_utils.h b/src/http_decoder_utils.h
index 9c031a3..0661641 100644
--- a/src/http_decoder_utils.h
+++ b/src/http_decoder_utils.h
@@ -1,28 +1,13 @@
-/*
-**********************************************************************************************
-* File: http_decoder_utils.h
-* Description:
-* Authors: LuWenPeng <[email protected]>
-* Date: 2022-10-31
-* Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
-
#ifndef _HTTP_DECODER_UTILS_H_
#define _HTTP_DECODER_UTILS_H_
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
#include <stdlib.h>
#include <stdio.h>
-
char *safe_dup(const char *str, size_t len);
-
+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);
/******************************************************************************
* Logger
******************************************************************************/
@@ -58,9 +43,4 @@ enum http_decoder_log_level {
} \
}
#endif
-
-#ifdef __cplusplus
-}
-#endif
-
#endif \ No newline at end of file
diff --git a/src/version.map b/src/version.map
index 4b8c6d0..be433c2 100644
--- a/src/version.map
+++ b/src/version.map
@@ -3,8 +3,8 @@ global:
extern "C" {
http_message_*;
http_decoder_init;
- http_decoder_entry;
http_decoder_exit;
+ http_decoder_tcp_stream_msg_cb;
};
local: *;
}; \ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 4869a90..2445ef2 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,174 +1,32 @@
set(DECODER_NAME http_decoder)
-add_library(${DECODER_NAME}_test SHARED http_decoder_gtest.cpp md5.c)
+aux_source_directory(${PROJECT_SOURCE_DIR}/deps/toml DEPS_SRC)
+
+add_library(${DECODER_NAME}_test SHARED http_decoder_gtest.cpp md5.c ${DEPS_SRC})
add_dependencies(${DECODER_NAME}_test ${DECODER_NAME})
target_link_libraries(${DECODER_NAME}_test MESA_prof_load cjson-static)
set_target_properties(${DECODER_NAME}_test PROPERTIES PREFIX "")
-add_library(${DECODER_NAME}_perf SHARED http_decoder_perf.cpp)
+add_library(${DECODER_NAME}_perf SHARED http_decoder_perf_plug.cpp)
add_dependencies(${DECODER_NAME}_perf ${DECODER_NAME})
set_target_properties(${DECODER_NAME}_perf PROPERTIES PREFIX "")
-set(TEST_RUN_DIR ${CMAKE_BINARY_DIR}/testing)
+set(TEST_RUN_DIR /home/mesasoft/sapp_run)
include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(/usr/local/include/cjson)
-include_directories(/opt/tsg/framework/include/stellar)
+include_directories(${CMAKE_SOURCE_DIR}/src)
+include_directories(${CMAKE_SOURCE_DIR}/deps)
+# include_directories(/usr/local/include/cjson)
include_directories(/opt/tsg/framework/include/)
include_directories(/opt/MESA/include/MESA)
+include_directories(${CMAKE_BINARY_DIR}/vendor/vbuild/include)
+include_directories(${CMAKE_BINARY_DIR}/vendor/cjson/src/cjson/include)
-add_executable(gtest_http_decoder http_gtest_main.cpp http_decoder_driver.cpp http_decoder_stub.cpp http_decoder_gtest.cpp md5.c base64.c)
-link_directories(${CMAKE_BINARY_DIR}/src)
-target_link_libraries(gtest_http_decoder http_decoder gtest pcap MESA_jump_layer cjson-static)
-
-add_executable(gtest_unit http_gtest_unit.cpp http_decoder_driver.cpp http_decoder_stub.cpp http_decoder_gtest.cpp md5.c base64.c)
-target_link_libraries(gtest_unit http_decoder gtest pcap MESA_jump_layer cjson-static)
-
-set(TEST_MAIN gtest_http_decoder)
-
-add_test(NAME CREATE_RUN_ENV COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}")
-add_test(NAME COPY_TEST_MAIN COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/${TEST_MAIN} ${TEST_RUN_DIR}/${TEST_MAIN}")
-add_test(NAME COPY_TEST_UNIT COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/gtest_unit ${TEST_RUN_DIR}/gtest_unit")
-add_test(NAME COPY_HTTP_DECODER_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/etc/http && cp ${PROJECT_SOURCE_DIR}/conf/http_decoder.toml ${TEST_RUN_DIR}/etc/http/")
-
-
-set_tests_properties(CREATE_RUN_ENV COPY_TEST_MAIN COPY_TEST_UNIT COPY_HTTP_DECODER_CONF
- PROPERTIES FIXTURES_SETUP TestFixture)
-
-# run tests
-add_test(NAME HTTP_UNIT_TEST COMMAND ./gtest_unit WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_GET_SINGLE_TRANS_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_single_trans.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_get_single_trans.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_GET_SINGLE_TRANS_MSS1_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_single_trans.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_get_single_trans.pcap -m 1 WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_GET_MULTI_TRANS_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_multi_trans.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_get_multi_trans.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_GET_LONG_COOKIE_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_long_cookie.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_get_long_cookie.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_GET_ENCODED_URI_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_encoded_uri.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_get_encoded_uri.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_RES_GZIP_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_res_gzip.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_res_gzip.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_CHUNKED_RES_GZIP_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_chunked_res_gzip.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_chunked_res_gzip.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_OVER_TCP_KEEPALIVE_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_over_tcp_keepalive.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_over_tcp_keepalive.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-#todo: support http tunnel to fully parse pop3 protocol
-add_test(NAME HTTP_TUNNEL_FOR_POP3_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_tunnel_for_pop3.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_tunnel_for_pop3.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_OVER_PPPOE_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_over_pppoe.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_over_pppoe.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_OVER_TLS_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_over_tls.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_over_tls.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME NON_HTTP_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/non_http.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/non_http.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_REQ_1BYTE_SLIDING_WINDOW_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_req_1byte_sliding_window.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_req_1byte_sliding_window.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_RES_1BYTE_SLIDING_WINDOW_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_res_1byte_sliding_window.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_res_1byte_sliding_window.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_NO_CONTENT_LENGTH_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_no_content_length.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_no_content_length.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_POST_MULTIPART_FORM_DATA_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_post_multipart_form_data.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_post_multipart_form_data.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_HEADERS_EXCEED_MAXIMUM_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_hdrs_exceed_maximum.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_hdrs_exceed_maximum.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-#add_test(NAME HTTP_CONNECT_FLOOD_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_connect_flood.json
-# -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_connect_flood.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_GET_MALFORMED_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_malformed.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_get_malformed.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_HEADER_VALUE_EMPTY_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_hdr_value_empty.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_hdr_value_empty.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_UPGRADE_WEBSOCKET_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_upgrade_websocket.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_upgrade_websocket.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_UPGRADE_HTTP2_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_upgrade_http2.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_upgrade_http2.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_MULTI_PARSE_ERROR_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_multi_parse_error.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_multi_parse_error.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_GET_REQ_PIPELINE_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_req_pipeline.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_get_req_pipeline.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_TRANS_PIPELINE_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_trans_pipeline.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_trans_pipeline.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_HEADER_TRUNCATED_IN_KV_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_hdr_truncated_in_kv.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_hdr_truncated_in_kv.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_HEADER_TRUNCATED_AFTER_KV_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_hdr_truncated_after_kv.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_hdr_truncated_after_kv.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_URL_WITH_HOST_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_url_test_with_host.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_url_test_with_host.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_URL_WITHOUT_HOST_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_url_test_without_host.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_url_test_without_host.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_6OVER4_SINGLE_TRANS_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_6over4_single_trans.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_6over4_single_trans.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_POST_SINGLE_TRANS_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_post_single_trans.json
- -p ${CMAKE_CURRENT_SOURCE_DIR}/http_pcap/http_post_single_trans.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
-
-add_test(NAME HTTP_SELF_CONSISTENT_V4_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_single_trans.json
- -s ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_get_single_trans.json WORKING_DIRECTORY ${TEST_RUN_DIR})
+aux_source_directory(${PROJECT_SOURCE_DIR}/deps/mempool PERF_TEST_DEP_SRC)
+aux_source_directory(${PROJECT_SOURCE_DIR}/deps/toml PERF_TEST_DEP_SRC)
+aux_source_directory(${PROJECT_SOURCE_DIR}/src PERF_TEST_DEP_SRC)
-add_test(NAME HTTP_SELF_CONSISTENT_V6_TEST COMMAND ${TEST_MAIN} -b ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_6over4_single_trans.json
- -s ${CMAKE_CURRENT_SOURCE_DIR}/test_result_json/http_6over4_single_trans.json WORKING_DIRECTORY ${TEST_RUN_DIR})
+add_executable(httpd_perf_test ${PERF_TEST_DEP_SRC} http_decoder_perf_main.cpp http_decoder_perf_plug.cpp)
+target_link_libraries(httpd_perf_test z brotlidec llhttp-static fieldstat4 pthread)
-set_tests_properties(HTTP_UNIT_TEST
- HTTP_GET_SINGLE_TRANS_TEST
- HTTP_GET_SINGLE_TRANS_MSS1_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_TUNNEL_FOR_POP3_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_HEADER_VALUE_EMPTY_TEST
- HTTP_MULTI_PARSE_ERROR_TEST
- HTTP_UPGRADE_WEBSOCKET_TEST
- HTTP_UPGRADE_HTTP2_TEST
- HTTP_GET_REQ_PIPELINE_TEST
- HTTP_TRANS_PIPELINE_TEST
- HTTP_HEADER_TRUNCATED_IN_KV_TEST
- HTTP_HEADER_TRUNCATED_AFTER_KV_TEST
- HTTP_URL_WITH_HOST_TEST
- HTTP_URL_WITHOUT_HOST_TEST
- HTTP_6OVER4_SINGLE_TRANS_TEST
- HTTP_POST_SINGLE_TRANS_TEST
- HTTP_SELF_CONSISTENT_V4_TEST
- HTTP_SELF_CONSISTENT_V6_TEST
- PROPERTIES FIXTURES_REQUIRED TestFixture)
+#add_test(NAME INSTALL_PERF_TEST_MAIN COMMAND sh -c "cp ${CMAKE_CURRENT_BINARY_DIR}/httpd_perf_test ${TEST_RUN_DIR}/httpd_perf_test") \ No newline at end of file
diff --git a/test/http_decoder_driver.cpp b/test/http_decoder_driver.cpp
deleted file mode 100644
index be10f97..0000000
--- a/test/http_decoder_driver.cpp
+++ /dev/null
@@ -1,981 +0,0 @@
-/*
- Http Decoder Google Test driver module
-*/
-#include <stdio.h>
-#include <string.h>
-#ifndef __USE_MISC
-#define __USE_MISC 1
-#endif
-#ifndef __FAVOR_BSD
-#define __FAVOR_BSD 1
-#endif
-#ifndef __USE_BSD
-#define __USE_BSD 1
-#endif
-#include <netinet/tcp.h>
-#include <netinet/ip.h>
-#include <arpa/inet.h>
-#include <time.h>
-#include <unistd.h>
-#include <assert.h>
-#include <getopt.h>
-#include <gtest/gtest.h>
-#include <pcap/pcap.h>
-#include "http_decoder_gtest.h"
-#include "MESA_jump_layer.h"
-#include "base64.h"
-
-extern "C" int http_decoder_entry(struct session *sess, int events,
- const struct packet *pkt, void *cb_arg);
-extern "C" void http_decoder_test_exit(void *test_ctx);
-extern "C" void *http_decoder_test_init(struct stellar *st);
-extern "C" void *http_decoder_init(struct stellar *st);
-
-static const char *hdgt_cla_short_options = "hb:p:s:m:";
-static const struct option hdgt_cla_long_options[] =
- {
- {"help", no_argument, NULL, 'h'},
- {"benchmark-file", required_argument, NULL, 'b'},
- {"data-pcap-file", required_argument, NULL, 'p'},
- {"data-json-file", required_argument, NULL, 's'},
- {"mss", required_argument, NULL, 'm'},
- {NULL, 0, NULL, 0}};
-
-static const char *g_data_src_json_non_headers[] = {
- GTEST_HTTP_URL_NAME,
- GTEST_HTTP_TRANS_NAME,
- GTEST_HTTP_TRANS_SEQ_NAME,
- GTEST_HTTP_TUPLE4_NAME,
- GTEST_HTTP_PAYLOAD_NAME,
- GTEST_HTTP_PAYLOAD_MD5_NAME,
- "method",
- "uri",
- "req_version",
- "major_version",
- "minor_version",
- "res_version",
- "res_status",
- "status_code",
- NULL};
-
-static void hdgt_cmd_usage(int argc, char **argv)
-{
- fprintf(stderr, "Usage:\n");
- fprintf(stderr, "\t -b set benchmark json file\n");
- fprintf(stderr, "\t -p set data source as pcap file\n");
- fprintf(stderr, "\t -s set data source as json file\n");
- fprintf(stderr, "\t -m set tcp Max Segment Size\n");
- exit(1);
-}
-
-void hdgt_set_data_source_type(fake_stellar *fst, enum data_source_type_t type)
-{
- fst->data_source_type = type;
-}
-
-static int hdgt_parse_cmd_args(fake_stellar *fst, int argc, char **argv)
-{
- int c, ret;
-
- while (1)
- {
- c = getopt_long(argc, argv, hdgt_cla_short_options, hdgt_cla_long_options, NULL);
- if (c == -1)
- {
- ret = 0;
- break;
- }
-
- switch (c)
- {
- case 'h':
- hdgt_cmd_usage(argc, argv);
- break;
- case 'b':
- fst->benchmark_json_file_name = optarg;
- break;
- case 'p':
- hdgt_set_data_source_type(fst, DATA_SOURCE_PCAP);
- fst->data_source_file_name = optarg;
- break;
- case 's':
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- fst->data_source_file_name = optarg;
- break;
- case 'm':
- fst->tcp_mss = atoi(optarg);
- if (fst->tcp_mss <= 0 || fst->tcp_mss > 65535)
- {
- DEBUG_PRINT("Invalid tcp mss value! must be [1, 65535]\n");
- hdgt_cmd_usage(argc, argv);
- }
- break;
- default:
- return -1;
- break;
- }
- }
-
- // check args
- // if (!fst->benchmark_json_file_name)
- // {
- // DEBUG_PRINT("benchmark json file is not set!\n");
- // hdgt_cmd_usage(argc, argv);
- // return -1;
- // }
-
- if (__DATA_SOURCE_NULL == fst->data_source_type)
- {
- DEBUG_PRINT("data source is not set!\n");
- hdgt_cmd_usage(argc, argv);
- return -1;
- }
-
- return ret;
-}
-
-int hdgt_compare_result(struct fake_stellar *fst)
-{
- int final_result = 0;
- cJSON_bool case_sensitive = FLASE;
-
- if (!fst->http_plug_test_result_root)
- {
- DEBUG_PRINT("Not found test json result!\n");
- return -1;
- }
-
- if (!fst->load_benchmark_json_root)
- {
- DEBUG_PRINT("Not found benchmark json instance!\n");
- return -1;
- }
-
- if (cJSON_GetArraySize(fst->load_benchmark_json_root) != cJSON_GetArraySize(fst->http_plug_test_result_root))
- {
- DEBUG_PRINT("Compare json result: array size is diff!\n");
- final_result++;
- }
-
- int ret = cJSON_Compare(fst->load_benchmark_json_root, fst->http_plug_test_result_root, case_sensitive);
- if (ret != TRUE)
- {
- char *load_json_str = cJSON_Print(fst->load_benchmark_json_root);
- printf("LOAD Raw:\n%s\n", load_json_str);
-
- char *result_json_str = cJSON_Print(fst->http_plug_test_result_root);
- printf("TEST Raw:\n%s\n", result_json_str);
-
- int min_len = MIN(strlen(load_json_str), strlen(result_json_str));
- for (size_t i = 0; i < min_len; i++)
- {
- if (load_json_str[i] != result_json_str[i])
- {
- printf("######### JSON Diff at len:%d: \n\tLOAD: %.*s\n\tTEST: %.*s\n", (int)i, 16, load_json_str + i, 16, result_json_str + i);
- break;
- }
- }
-
- free(load_json_str);
- free(result_json_str);
-
- cJSON *t_load = fst->load_benchmark_json_root->child;
- cJSON *t_test = fst->http_plug_test_result_root->child;
- while (t_load != NULL && t_test != NULL)
- {
- ret = cJSON_Compare(t_load, t_test, case_sensitive);
- if (ret != TRUE)
- {
- 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);
- final_result++;
- }
- t_load = t_load->next;
- t_test = t_test->next;
- }
- }
- else
- {
- DEBUG_PRINT("Compare json result success!\n");
- }
-
- return final_result;
-}
-
-static char *hdgt_get_file_content(const char *filename)
-{
- FILE *fp = fopen(filename, "r");
- if (NULL == fp)
- {
- DEBUG_PRINT("fopen() fail!\n");
- return NULL;
- }
- fseek(fp, 0, SEEK_END);
- long file_size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- char *file_content = MMALLOC(char, file_size + 1);
- if (fread(file_content, 1, file_size, fp) != file_size)
- {
- DEBUG_PRINT("fread() %s fail!\n", filename);
- fclose(fp);
- MFREE(file_content);
- return NULL;
- }
- fclose(fp);
- return file_content;
-}
-
-static struct fake_session *hdgt_session_new(struct fake_stellar *fst)
-{
- struct fake_session *fses = MMALLOC(struct fake_session, sizeof(struct fake_session));
-
- fses->fst = fst;
- fses->tcp_mss = fst->tcp_mss;
- // todo : get protocol type from packet, not fixed
- fses->type = SESSION_TYPE_TCP;
- return fses;
-}
-
-static int hdgt_get_packet_from_pcap(struct fake_stellar *fst, struct fake_packet *fpkt)
-{
- struct pcap_pkthdr *pkt_hdr;
- const u_char *pkt_data;
- int ret = pcap_next_ex(fst->pcap_ins, &pkt_hdr, &pkt_data);
- if (1 == ret)
- {
- fpkt->raw_pkt_data = (char *)pkt_data;
- fpkt->raw_pkt_data_len = pkt_hdr->caplen;
- DEBUG_PRINT("Warning! this is a rough packet decoder, not support tcp out of order, seq overlap...\n");
- return 1;
- }
- else if (-2 == ret)
- {
- DEBUG_PRINT("pcap file over!\n");
- return 0;
- }
- DEBUG_PRINT("pcap_next_ex() fail: %s!\n", pcap_geterr(fst->pcap_ins));
- return -1;
-}
-
-static int hdgt_get_packet_from_json(struct fake_stellar *fst, struct fake_packet *fpkt)
-{
- cJSON *json_root = fst->data_src_json_para.json_root;
- cJSON *json_item = cJSON_GetArrayItem(json_root, fst->data_src_json_para.current_json_array_idx);
- if (NULL == json_item)
- {
- DEBUG_PRINT("Not found json object at index %d!\n", fst->data_src_json_para.current_json_array_idx);
- return -1;
- }
- fst->data_src_json_para.current_object = json_item;
- fst->data_src_json_para.current_json_array_idx++;
- return 1;
-}
-
-static int hdgt_is_reserverd_json_header(const cJSON *json_object)
-{
- for (size_t i = 0; g_data_src_json_non_headers[i] != NULL; i++)
- {
- if (strlen(json_object->string) == strlen(g_data_src_json_non_headers[i]) && (0 == strncmp(json_object->string, g_data_src_json_non_headers[i], strlen(g_data_src_json_non_headers[i]))))
- {
- return 1;
- }
- }
-
- return 0;
-}
-
-static int hdgt_get_packet_dir_from_json(cJSON *json)
-{
- cJSON *json_dir = cJSON_GetObjectItem(json, GTEST_HTTP_TRANS_NAME);
- if (NULL == json_dir)
- {
- return -1;
- }
- if (strncasecmp("request", json_dir->valuestring, strlen("request")) == 0)
- {
- return PACKET_DIRECTION_C2S;
- }
- else if (strncasecmp("response", json_dir->valuestring, strlen("response")) == 0)
- {
- return PACKET_DIRECTION_S2C;
- }
- else
- {
- return -1;
- }
-}
-
-static void hdgt_get_req_line_from_json(struct data_src_json_para_t *data_src_json_para)
-{
- cJSON *json_item = data_src_json_para->current_object;
- cJSON *method, *uri, *major_version, *minor_version;
-
- method = cJSON_GetObjectItem(json_item, "method");
- uri = cJSON_GetObjectItem(json_item, "uri");
- major_version = cJSON_GetObjectItem(json_item, "major_version");
- minor_version = cJSON_GetObjectItem(json_item, "minor_version");
-
- if (method && uri && major_version && minor_version)
- {
- sprintf(data_src_json_para->key_value_buf, "%s %s HTTP/%d.%d\r\n",
- method->valuestring, uri->valuestring, major_version->valueint, minor_version->valueint);
- }
- else
- {
- DEBUG_PRINT("get request line from json fail!\n");
- }
-}
-
-static void hdgt_get_res_line_from_json(struct data_src_json_para_t *data_src_json_para)
-{
- cJSON *json_item = data_src_json_para->current_object;
- cJSON *res_status, *status_code, *major_version, *minor_version;
-
- res_status = cJSON_GetObjectItem(json_item, "res_status");
- status_code = cJSON_GetObjectItem(json_item, "status_code");
- major_version = cJSON_GetObjectItem(json_item, "major_version");
- minor_version = cJSON_GetObjectItem(json_item, "minor_version");
-
- if (res_status && status_code && major_version && minor_version)
- {
- sprintf(data_src_json_para->key_value_buf, "HTTP/%d.%d %d %s\r\n",
- major_version->valueint, minor_version->valueint, status_code->valueint, res_status->valuestring);
- }
- else
- {
- DEBUG_PRINT("get response line from json fail!\n");
- }
-}
-
-static void hdgt_get_headers_from_json(struct data_src_json_para_t *data_src_json_para)
-{
- cJSON *json_item = data_src_json_para->current_object->child;
- char *data_ptr = data_src_json_para->key_value_buf + strlen(data_src_json_para->key_value_buf);
- int len;
-
- while (json_item)
- {
- if (0 == hdgt_is_reserverd_json_header(json_item))
- {
- if (cJSON_IsString(json_item))
- {
- len = sprintf(data_ptr, "%s: %s\r\n", json_item->string, json_item->valuestring);
- }
- else if (cJSON_IsNumber(json_item))
- {
- len = sprintf(data_ptr, "%s: %d\r\n", json_item->string, json_item->valueint);
- }
- else if (cJSON_IsBool(json_item))
- {
- len = sprintf(data_ptr, "%s: %s\r\n", json_item->string, json_item->valueint ? "true" : "false");
- }
- else
- {
- len = sprintf(data_ptr, "%s: %s\r\n", json_item->string, cJSON_Print(json_item));
- }
- data_ptr += len;
- }
- json_item = json_item->next;
- }
- sprintf(data_ptr, "\r\n"); // headers EOF
-}
-
-static void hdgt_get_body_from_json(struct data_src_json_para_t *data_src_json_para)
-{
- cJSON *json_root = data_src_json_para->current_object;
- char *data_ptr = data_src_json_para->key_value_buf + strlen(data_src_json_para->key_value_buf);
-
- // todo, support gzip, deflate, etc.
- // todo, cjson not support binary data, need base64 encode/decode
- cJSON *json_body = cJSON_GetObjectItem(json_root, GTEST_HTTP_PAYLOAD_NAME);
- if (json_body)
- {
- int base64_cont_len = strlen(json_body->valuestring);
- char *raw_cont_buf = (char *)calloc(1, base64_cont_len + 1);
- int raw_cont_len = base64_decode(json_body->valuestring, base64_cont_len, (unsigned char *)raw_cont_buf);
- sprintf(data_ptr, "%s", raw_cont_buf);
- }
-}
-
-static int hdgt_update_packet_detail_by_json(struct fake_stellar *fst, struct fake_packet *fpkt)
-{
- fpkt->dir = hdgt_get_packet_dir_from_json(fst->data_src_json_para.current_object);
- if (PACKET_DIRECTION_C2S != fpkt->dir && PACKET_DIRECTION_S2C != fpkt->dir)
- {
- DEBUG_PRINT("get packet direction from json fail!\n");
- return -1;
- }
-
- if (PACKET_DIRECTION_C2S == fpkt->dir)
- {
- hdgt_get_req_line_from_json(&fst->data_src_json_para);
- }
- else
- {
- hdgt_get_res_line_from_json(&fst->data_src_json_para);
- }
- hdgt_get_headers_from_json(&fst->data_src_json_para);
-
- hdgt_get_body_from_json(&fst->data_src_json_para);
-
- fpkt->payload_data = fst->data_src_json_para.key_value_buf;
- fpkt->payload_data_len = strlen(fst->data_src_json_para.key_value_buf);
- fpkt->payload_submit_offset = 0;
-
- return 0;
-}
-
-static int hdgt_get_packet(struct fake_stellar *fst, struct fake_packet *fpkt)
-{
- int ret = -1;
- memset(fpkt, 0, sizeof(struct fake_packet));
- if (DATA_SOURCE_PCAP == fst->data_source_type)
- {
- ret = hdgt_get_packet_from_pcap(fst, fpkt);
- }
- else if (DATA_SOURCE_JSON == fst->data_source_type)
- {
- ret = hdgt_get_packet_from_json(fst, fpkt);
- }
- else
- {
- fprintf(stderr, "hdgt_get_packet(): invalid data source type!\n");
- ret = -1;
- }
-
- return ret;
-}
-
-static int hdgt_has_data_left(struct fake_packet *fpkt)
-{
- return fpkt->payload_submit_offset < fpkt->payload_data_len;
-}
-
-static int hdgt_get_packet_dir_of_tcp(const struct tcphdr *th)
-{
- int dir;
-
- if (TH_SYN == th->th_flags)
- {
- dir = PACKET_DIRECTION_C2S;
- }
- else if ((TH_SYN | TH_ACK) == th->th_flags)
- {
- dir = PACKET_DIRECTION_S2C;
- }
- else
- {
- if (ntohs(th->th_sport) > ntohs(th->th_dport)) // Unwritten rule, not sure
- {
- dir = PACKET_DIRECTION_C2S;
- }
- else
- {
- dir = PACKET_DIRECTION_S2C;
- }
- }
-
- return dir;
-}
-
-static void hdgt_determine_packet_dir(struct fake_session *fses, struct fake_packet *fpkt, const struct tcphdr *th)
-{
- if (SESSION_ADDR_TYPE_IPV4_TCP == fses->addr_type)
- {
- if (th->th_sport == fses->addr->ipv4.sport)
- {
- fpkt->dir = PACKET_DIRECTION_C2S;
- }
- else
- {
- fpkt->dir = PACKET_DIRECTION_S2C;
- }
- }
- else
- {
- if (th->th_sport == fses->addr->ipv6.sport)
- {
- fpkt->dir = PACKET_DIRECTION_C2S;
- }
- else
- {
- fpkt->dir = PACKET_DIRECTION_S2C;
- }
- }
-}
-
-static void hdgt_update_packet_payload(struct fake_packet *fpkt, const struct tcphdr *th, int from_tcp_len)
-{
- // todo, support UDP?
- fpkt->payload_data = (char *)th + th->th_off * 4;
-#if 0
- /* for ethernet, maybe end with padding bytes, must not use packet length, use ip header len */
- fpkt->payload_data_len = fpkt->raw_pkt_data_len - ((char *)th - fpkt->raw_pkt_data) - (th->th_off * 4);
-#else
- fpkt->payload_data_len = from_tcp_len - (th->th_off * 4);
-#endif
- fpkt->payload_submit_offset = 0;
-}
-
-static int hdgt_update_packet_detail_by_pcap(struct fake_session *fses, struct fake_packet *fpkt)
-{
- size_t from_tcp_len = 0;
- if (SESSION_ADDR_TYPE_IPV4_TCP == fses->addr_type)
- {
- struct ip *i4h = (struct ip *)MESA_jump_layer_greedy(fpkt->raw_pkt_data, ADDR_TYPE_MAC, ADDR_TYPE_IPV4);
- if (NULL == i4h)
- {
- DEBUG_PRINT("Not found ipv4 header!\n");
- return -1;
- }
- from_tcp_len = ntohs(i4h->ip_len) - i4h->ip_hl * 4;
- }
- else
- {
- struct ip6_hdr *i6h = (struct ip6_hdr *)MESA_jump_layer_greedy(fpkt->raw_pkt_data, ADDR_TYPE_MAC, ADDR_TYPE_IPV6);
- if (NULL == i6h)
- {
- DEBUG_PRINT("Not found ipv6 header!\n");
- return -1;
- }
- from_tcp_len = ntohs(i6h->ip6_plen);
- }
-
- struct tcphdr *th = (struct tcphdr *)MESA_jump_layer_greedy(fpkt->raw_pkt_data, ADDR_TYPE_MAC, ADDR_TYPE_TCP);
- if (NULL == th)
- {
- DEBUG_PRINT("Not found tcp header!\n");
- return -1;
- }
-
- hdgt_determine_packet_dir(fses, fpkt, th);
- hdgt_update_packet_payload(fpkt, th, from_tcp_len);
- return 0;
-}
-
-static int hdgt_update_packet_detail(struct fake_session *fses, struct fake_packet *fpkt)
-{
- int ret;
- if (DATA_SOURCE_PCAP == fses->fst->data_source_type)
- {
- ret = hdgt_update_packet_detail_by_pcap(fses, fpkt);
- }
- else
- {
- ret = hdgt_update_packet_detail_by_json(fses->fst, fpkt);
- }
- return ret;
-}
-
-static struct session_addr *hgdt_get_session_addr_by_pcap(struct fake_session *fses, struct fake_packet *fpkt)
-{
- if (fses->addr != NULL)
- {
- return fses->addr;
- }
-
- struct session_addr tmp_addr = {};
- int innermost_l3_layer_type;
-
- struct tcphdr *th = (struct tcphdr *)MESA_jump_layer_greedy(fpkt->raw_pkt_data, ADDR_TYPE_MAC, ADDR_TYPE_TCP);
- if (NULL == th)
- {
- DEBUG_PRINT("Not found tcp header!\n");
- // todo, support UDP ?
- return NULL;
- }
- fpkt->l4_header = (char *)th;
- struct ip *i4h = (struct ip *)MESA_jump_layer_greedy(fpkt->raw_pkt_data, ADDR_TYPE_MAC, ADDR_TYPE_IPV4);
- struct ip6_hdr *i6h = (struct ip6_hdr *)MESA_jump_layer_greedy(fpkt->raw_pkt_data, ADDR_TYPE_MAC, ADDR_TYPE_IPV6);
- if ((NULL == i6h) && (NULL == i4h))
- {
- DEBUG_PRINT("Not found ipv4 or ipv6 header!\n");
- return NULL;
- }
-
- if (i4h && (NULL == i6h))
- {
- innermost_l3_layer_type = ADDR_TYPE_IPV4;
- }
- else if (i6h && (NULL == i4h))
- {
- innermost_l3_layer_type = ADDR_TYPE_IPV6;
- }
- else // both ipv4 and ipv6 exist, maybe 4over6, 6over4, gtp etc.
- {
- if ((char *)i4h - (char *)i6h > 0)
- {
- innermost_l3_layer_type = ADDR_TYPE_IPV4;
- }
- else
- {
- innermost_l3_layer_type = ADDR_TYPE_IPV6;
- }
- }
-
- int cur_pkt_dir = hdgt_get_packet_dir_of_tcp(th);
-
- if (ADDR_TYPE_IPV4 == innermost_l3_layer_type)
- {
- fses->addr_type = SESSION_ADDR_TYPE_IPV4_TCP;
- if (PACKET_DIRECTION_C2S == cur_pkt_dir)
- {
-
- tmp_addr.ipv4.saddr = i4h->ip_src.s_addr;
- tmp_addr.ipv4.daddr = i4h->ip_dst.s_addr;
- tmp_addr.ipv4.sport = th->th_sport;
- tmp_addr.ipv4.dport = th->th_dport;
- }
- else
- {
- tmp_addr.ipv4.saddr = i4h->ip_dst.s_addr;
- tmp_addr.ipv4.daddr = i4h->ip_src.s_addr;
- tmp_addr.ipv4.sport = th->th_dport;
- tmp_addr.ipv4.dport = th->th_sport;
- }
- }
- else
- {
- fses->addr_type = SESSION_ADDR_TYPE_IPV6_TCP;
- if (PACKET_DIRECTION_C2S == cur_pkt_dir)
- {
- memcpy(tmp_addr.ipv6.saddr, i6h->ip6_src.s6_addr, IPV6_ADDR_LEN);
- memcpy(tmp_addr.ipv6.daddr, i6h->ip6_dst.s6_addr, IPV6_ADDR_LEN);
- tmp_addr.ipv6.sport = th->th_sport;
- tmp_addr.ipv6.dport = th->th_dport;
- }
- else
- {
- memcpy(tmp_addr.ipv6.saddr, i6h->ip6_dst.s6_addr, IPV6_ADDR_LEN);
- memcpy(tmp_addr.ipv6.daddr, i6h->ip6_src.s6_addr, IPV6_ADDR_LEN);
- tmp_addr.ipv6.sport = th->th_dport;
- tmp_addr.ipv6.dport = th->th_sport;
- }
- }
-
- fses->addr = MMALLOC(struct session_addr, sizeof(struct session_addr));
- memcpy(fses->addr, &tmp_addr, sizeof(struct session_addr));
-
- return fses->addr;
-}
-
-/* example: "1.1.1.1.12345>2.2.2.2.80" */
-static void hdgt_json_session_adddr_pton_v4(struct session_addr *addr, const char *tuple4_cstr)
-{
- const char *delim = ".>";
- char *dup_str = strdup(tuple4_cstr);
- char *sip1 = strtok(dup_str, delim);
- char *sip2 = strtok(NULL, delim);
- char *sip3 = strtok(NULL, delim);
- char *sip4 = strtok(NULL, delim);
- char *sport = strtok(NULL, delim);
-
- char *dip1 = strtok(NULL, delim);
- char *dip2 = strtok(NULL, delim);
- char *dip3 = strtok(NULL, delim);
- char *dip4 = strtok(NULL, delim);
- char *dport = strtok(NULL, delim);
-
- char sip_str[INET_ADDRSTRLEN] = {};
- char dip_str[INET_ADDRSTRLEN] = {};
- sprintf(sip_str, "%s.%s.%s.%s", sip1, sip2, sip3, sip4);
- inet_pton(AF_INET, sip_str, &addr->ipv4.saddr);
- sprintf(dip_str, "%s.%s.%s.%s", dip1, dip2, dip3, dip4);
- inet_pton(AF_INET, dip_str, &addr->ipv4.daddr);
- addr->ipv4.sport = htons(atoi(sport));
- addr->ipv4.dport = htons(atoi(dport));
-}
-
-/* fe80::8c19:7aff:fef2:11e5.12345>fe80::8c19:7aff:fef2:11e5.80 */
-static void hdgt_json_session_adddr_pton_v6(struct session_addr *addr, const char *tuple4_cstr)
-{
- char *dup_str = strdup(tuple4_cstr);
- char *sip = dup_str;
- char *ptr = strchr(dup_str, '.');
- *ptr = '\0';
- ptr++;
- char *sport = ptr;
- ptr = strchr(sport, '>');
- *ptr = '\0';
- ptr++;
- char *dip = ptr;
- ptr = strchr(dip, '.');
- *ptr = '\0';
- ptr++;
- char *dport = ptr;
-
- char sip_str[INET6_ADDRSTRLEN] = {};
- char dip_str[INET6_ADDRSTRLEN] = {};
- inet_pton(AF_INET6, sip, addr->ipv6.saddr);
- inet_pton(AF_INET6, dip, addr->ipv6.daddr);
- addr->ipv6.sport = htons(atoi(sport));
- addr->ipv6.dport = htons(atoi(dport));
-}
-
-static void hdgt_json_session_adddr_pton(struct fake_session *fses, const char *tuple4_cstr)
-{
- struct session_addr *addr = fses->addr;
- if (strchr(tuple4_cstr, ':') != NULL)
- {
- hdgt_json_session_adddr_pton_v6(addr, tuple4_cstr);
- fses->addr_type = SESSION_ADDR_TYPE_IPV6_TCP;
- return;
- }
- else
- {
- hdgt_json_session_adddr_pton_v4(addr, tuple4_cstr);
- fses->addr_type = SESSION_ADDR_TYPE_IPV4_TCP;
- }
-}
-
-static struct session_addr *hgdt_get_session_addr_by_json(struct fake_session *fses, struct fake_packet *fpkt)
-{
- if (fses->addr != NULL)
- {
- return fses->addr;
- }
-
- cJSON *tuple4_obj = cJSON_GetObjectItem(fses->fst->data_src_json_para.current_object, GTEST_HTTP_TUPLE4_NAME);
- if (NULL == tuple4_obj)
- {
- fprintf(stderr, "Not found tuple4 object!\n");
- return NULL;
- }
- fses->addr = MMALLOC(struct session_addr, sizeof(struct session_addr));
- hdgt_json_session_adddr_pton(fses, tuple4_obj->valuestring);
- return fses->addr;
-}
-
-static struct session_addr *hgdt_get_session_addr(struct fake_session *fses, struct fake_packet *fpkt)
-{
- if (fses->fst->data_source_type == DATA_SOURCE_PCAP)
- {
- return hgdt_get_session_addr_by_pcap(fses, fpkt);
- }
- return hgdt_get_session_addr_by_json(fses, fpkt);
-}
-
-static void hdgt_session_update(struct fake_stellar *fst, struct fake_session *fses, int event)
-{
- fst->http_decoder_entry((struct session *)fses, event, (struct packet *)fses->fpkt, fst->http_decoder_ctx);
-}
-
-int hdgt_data_source_init_by_json_text(struct fake_stellar *fst, const char *json_cont)
-{
- fst->data_src_json_para.json_root = cJSON_Parse(json_cont);
- if (NULL == fst->data_src_json_para.json_root)
- {
- fprintf(stderr, "cJSON_Parse() %s fail!\n", json_cont);
- return -1;
- }
- fst->data_src_json_para.json_array_size = cJSON_GetArraySize(fst->data_src_json_para.json_root);
- fst->data_src_json_para.current_json_array_idx = 0;
- return 0;
-}
-
-int hdgt_data_source_init_by_json_file(struct fake_stellar *fst, const char *json_file)
-{
- char *file_cont = hdgt_get_file_content(json_file);
- int ret;
- if (NULL == file_cont)
- {
- fprintf(stderr, "Open json file fail: %s\n", json_file);
- return -1;
- }
- ret = hdgt_data_source_init_by_json_text(fst, file_cont);
- MFREE(file_cont);
- return ret;
-}
-
-int hdgt_data_source_init(struct fake_stellar *fst)
-{
- if (DATA_SOURCE_PCAP == fst->data_source_type)
- {
- char errbuf[PCAP_ERRBUF_SIZE];
- fst->pcap_ins = pcap_open_offline(fst->data_source_file_name, errbuf);
- if (NULL == fst->pcap_ins)
- {
- fprintf(stderr, "pcap_open_offline() fail: %s\n", errbuf);
- return -1;
- }
- }
- else if (DATA_SOURCE_JSON == fst->data_source_type)
- {
- return hdgt_data_source_init_by_json_file(fst, fst->data_source_file_name);
- }
- else
- {
- DEBUG_PRINT("Invalid data source type!\n");
- return -1;
- }
-
- return 0;
-}
-
-static void hdgt_prune_non_result_item(cJSON *benchmark_json_root)
-{
- int array_size = cJSON_GetArraySize(benchmark_json_root);
-
- for (int i = 0; i < array_size; i++)
- {
- cJSON *object_root = cJSON_GetArrayItem(benchmark_json_root, i);
- cJSON_DeleteItemFromObject(object_root, GTEST_HTTP_PAYLOAD_NAME);
- }
-}
-
-static int hdgt_benchmakr_json_parse(struct fake_stellar *fst)
-{
- char *file_cont = hdgt_get_file_content(fst->benchmark_json_file_name);
- if (NULL == file_cont)
- {
- fprintf(stderr, "Open json file fail: %s\n", fst->benchmark_json_file_name);
- return -1;
- }
- fst->load_benchmark_json_root = cJSON_Parse(file_cont);
- if (NULL == fst->load_benchmark_json_root)
- {
- fprintf(stderr, "cJSON_Parse() %s fail!\n", fst->benchmark_json_file_name);
- MFREE(file_cont);
- return -1;
- }
- fst->http_plug_test_result_root = cJSON_CreateArray();
- MFREE(file_cont);
-
- hdgt_prune_non_result_item(fst->load_benchmark_json_root);
- return 0;
-}
-
-int hdgt_under_test_module_init(struct fake_stellar *fst, HTTP_DECODER_INIT_FUN_T init_fun, HTTP_DECODER_ENTRY_FUN_T entry_fun)
-{
- fst->http_decoder_ctx = init_fun((struct stellar *)fst);
- fst->http_decoder_entry = entry_fun;
- return 0;
-}
-
-int hdgt_test_plug_init(struct fake_stellar *fst, HTTP_DECODER_INIT_FUN_T init_fun, HTTP_DECODER_PLUG_ENTRY_FUN_T entry_fun)
-{
- http_decoder_plug_set_entry_fuc(entry_fun);
- fst->http_http_plug_ctx = init_fun((struct stellar *)fst);
- return 0;
-}
-
-struct fake_stellar *hdgt_create(void)
-{
- struct fake_stellar *fst = MMALLOC(struct fake_stellar, sizeof(struct fake_stellar));
- fst->tcp_mss = 1460; // set default value
- return fst;
-}
-
-int hdgt_init_once(struct fake_stellar *fst, int argc, char **argv,
- HTTP_DECODER_INIT_FUN_T hd_init_fun, HTTP_DECODER_ENTRY_FUN_T hd_entry_fun,
- HTTP_DECODER_INIT_FUN_T hd_plug_init_fun, HTTP_DECODER_PLUG_ENTRY_FUN_T hd_plug_entry_fun)
-{
- if (hdgt_parse_cmd_args(fst, argc, argv) < 0)
- {
- fprintf(stderr, "hdgt_parse_cmd_args() fail!\n");
- goto fail_exit;
- }
- if (hdgt_data_source_init(fst) < 0)
- {
- fprintf(stderr, "hdgt_data_source_init() fail!\n");
- goto fail_exit;
- }
- if (hdgt_benchmakr_json_parse(fst) < 0)
- {
- fprintf(stderr, "hdgt_benchmakr_json_parse() fail!\n");
- goto fail_exit;
- }
- if (hdgt_under_test_module_init(fst, hd_init_fun, hd_entry_fun) < 0)
- {
- fprintf(stderr, "hdgt_under_test_module_init() fail!\n");
- goto fail_exit;
- }
- if (hdgt_test_plug_init(fst, hd_plug_init_fun, hd_plug_entry_fun) < 0)
- {
- fprintf(stderr, "hdgt_test_plug_init() fail!\n");
- goto fail_exit;
- }
-
- return 0;
-
-fail_exit:
- return -1;
-}
-
-void hdgt_destroy(struct fake_stellar *fst)
-{
- cJSON_free(fst->load_benchmark_json_root);
- cJSON_free(fst->http_plug_test_result_root);
- if (fst->data_src_json_para.json_root)
- {
- cJSON_free(fst->data_src_json_para.json_root);
- }
- if (fst->pcap_ins)
- {
- pcap_close(fst->pcap_ins);
- }
-
- MFREE(fst);
- return;
-}
-
-static void hdgt_session_free(struct fake_session *fses)
-{
- const struct fake_exdata_manage *ex_mgr = fses->fst->fake_exdata_mgr;
-
- for (int i = 0; i < EX_DATA_MAX_SIZE; i++)
- {
- if (fses->plug_exdata_array[i] != NULL)
- {
- ex_mgr[i].free_func((struct session *)fses, i, fses->plug_exdata_array[i], ex_mgr[i].arg);
- }
- }
-
- if (fses->readable_addr_cstr)
- {
- MFREE(fses->readable_addr_cstr);
- }
-
- if (fses->addr)
- {
- MFREE(fses->addr);
- }
-
- MFREE(fses);
-}
-
-void hdgt_main_loop(struct fake_stellar *fst)
-{
- struct fake_packet __null_pkt = {};
- struct fake_packet fpkt = {};
- struct fake_session *fses = hdgt_session_new(fst);
-
- fses->fpkt = &__null_pkt;
- hdgt_session_update(fst, fses, SESS_EV_OPENING);
-
- fses->fpkt = &fpkt;
- while (hdgt_get_packet(fst, &fpkt) == 1)
- {
- if (NULL == hgdt_get_session_addr(fses, &fpkt))
- {
- continue; // not tcp, not ip
- }
- if (hdgt_update_packet_detail(fses, &fpkt) < 0)
- {
- continue;
- }
- while (hdgt_has_data_left(&fpkt))
- {
- hdgt_session_update(fst, fses, SESS_EV_PACKET);
- }
- }
-
- fses->fpkt = &__null_pkt;
- hdgt_session_update(fst, fses, SESS_EV_CLOSING);
-
- hdgt_session_free(fses);
-}
diff --git a/test/http_decoder_gtest.cpp b/test/http_decoder_gtest.cpp
index a853080..3956a28 100644
--- a/test/http_decoder_gtest.cpp
+++ b/test/http_decoder_gtest.cpp
@@ -1,39 +1,39 @@
-/*
-**********************************************************************************************
-* File: http_decoder_gtest.cpp
-* Description:
-* Authors: Liu WenTan <[email protected]>
-* Date: 2023-12-15
-* Copyright: (c) Since 2023 Geedge Networks, Ltd. All rights reserved.
-***********************************************************************************************
-*/
-
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
-#include "../include/http_decoder.h"
+#include "http_decoder_inc.h"
#ifdef __cplusplus
extern "C"
{
-
#include "cJSON.h"
#include "http_decoder_gtest.h"
-#include "stellar/utils.h"
-#include "stellar/stellar.h"
-#include "stellar/session_exdata.h"
-#include "stellar/session_mq.h"
#include "md5.h"
+#include "toml/toml.h"
+
int commit_test_result_json(cJSON *node, const char *name);
- extern int http_decoder_test_entry(struct session *sess, int topic_id, const void *data,void *cb_arg);
- static HTTP_DECODER_PLUG_ENTRY_FUN_T g_entry_fun = http_decoder_test_entry;
+ 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);
+ 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},
+ {NULL, NULL}
+};
enum http_transaction_type
{
@@ -51,8 +51,9 @@ struct gtest_plug_exdata_t
static int g_result_count = 0;
static int g_header_count = 1;
-static int g_exdata_idx = 0;
-static int g_topic_id = 0;
+static int g_http_gtest_plugin_id = -1;
+static int g_exdata_idx = -1;
+static int g_topic_id = -1;
@@ -207,7 +208,8 @@ void http_url_add_to_json(cJSON *ctx, struct http_message *msg)
return;
}
- if (http_message_get_url(msg, &url_result) < 0)
+ http_message_get_url(msg, &url_result);
+ if(url_result.str == NULL)
{
// printf("url:%s\n", url_result.str);
return;
@@ -224,7 +226,7 @@ void http_url_add_to_json(cJSON *ctx, struct http_message *msg)
// Full duplex
static void commit_last_half_flow_data(struct session *sess, struct gtest_plug_exdata_t *gtest_plug_exdata,
- struct http_message *msg, enum http_transaction_type type)
+ struct http_message *msg, enum http_transaction_type type, int final)
{
char result_name[MAX_KEY_STR_LEN] = {0};
@@ -253,18 +255,20 @@ static void commit_last_half_flow_data(struct session *sess, struct gtest_plug_e
g_result_count++;
}
- 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));
+ 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));
+ }
}
}
@@ -285,25 +289,74 @@ static void http_decoder_test_update_session_tuple4(struct session *sess, struct
}
}
-extern "C" int
-http_decoder_test_entry(struct session *sess, int topic_id, const void *data,
- void *cb_arg)
+static int get_gtest_plug_entry(const char *cfg_path, char *entry_name, int 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;
+ }
+
+ 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, "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_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)
{
struct http_request_line req_line = {0};
struct http_response_line res_line = {0};
struct http_header header = {0};
struct hstring body = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
+ struct http_message *msg = (struct http_message *)raw_msg;
+ enum http_message_type msg_type = http_message_type_get(msg);
- struct gtest_plug_exdata_t *gtest_plug_exdata = (struct gtest_plug_exdata_t *)session_get_ex_data(sess, g_exdata_idx);
+ 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_set_ex_data(sess, g_exdata_idx, gtest_plug_exdata);
+ session_exdata_set(sess, g_exdata_idx, gtest_plug_exdata);
}
- if (msg_type == HTTP_MESSAGE_REQ_LINE || msg_type == HTTP_MESSAGE_REQ_HEADER || msg_type == HTTP_MESSAGE_REQ_BODY)
+ if (http_message_type_is_req(sess, msg_type))
{
cJSON *json = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ];
}
@@ -317,7 +370,7 @@ http_decoder_test_entry(struct session *sess, int topic_id, const void *data,
switch (msg_type)
{
case HTTP_MESSAGE_REQ_LINE:
- commit_last_half_flow_data(sess, gtest_plug_exdata, msg, HTTP_TRANSACTION_REQ);
+ commit_last_half_flow_data(sess, gtest_plug_exdata, msg, HTTP_TRANSACTION_REQ, 0);
http_message_get_request_line(msg, &req_line);
req_line_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], &req_line);
break;
@@ -337,7 +390,7 @@ http_decoder_test_entry(struct session *sess, int topic_id, const void *data,
append_http_payload(sess, gtest_plug_exdata, &body, HTTP_TRANSACTION_REQ);
break;
case HTTP_MESSAGE_RES_LINE:
- commit_last_half_flow_data(sess, gtest_plug_exdata, msg, HTTP_TRANSACTION_RES);
+ commit_last_half_flow_data(sess, gtest_plug_exdata, msg, HTTP_TRANSACTION_RES, 0);
http_message_get_response_line(msg, &res_line);
res_line_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], &res_line);
break;
@@ -361,52 +414,96 @@ http_decoder_test_entry(struct session *sess, int topic_id, const void *data,
break;
}
- return 0;
+ return;
}
-void http_decoder_test_exdata_free(struct session *sess, int idx, void *ex_ptr,
- void *arg)
+void http_decoder_test_exdata_free(struct session *sess, int idx, void *ex_ptr, 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(sess, gtest_plug_exdata, NULL, HTTP_TRANSACTION_REQ);
+ commit_last_half_flow_data(sess, gtest_plug_exdata, NULL, HTTP_TRANSACTION_REQ, 1);
}
if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES])
{
- commit_last_half_flow_data(sess, gtest_plug_exdata, NULL, HTTP_TRANSACTION_RES);
+ commit_last_half_flow_data(sess, 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)
+{
+ 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_type_get((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];
+ }
+
+ int cur_transaction_id = http_message_get_transaction_seq((const http_message* )raw_msg);
+
+ if(HTTP_TRANSACTION_NEW ==msg_type || HTTP_TRANSACTION_FREE == 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_test_init(struct stellar *st)
{
- g_exdata_idx =
- stellar_session_get_ex_new_index(st, "HTTP_DECODER_REQ_TEST",
+ g_http_gtest_plugin_id = stellar_session_plugin_register(st, NULL, NULL, NULL);
+ g_exdata_idx = stellar_session_exdata_new_index(st, "HTTP_DECODER_REQ_TEST",
http_decoder_test_exdata_free,
- NULL);
+ NULL);
if (g_exdata_idx < 0)
{
- printf("[%s:%d]: can't get http_decoder exdata index !!!\n",
- __FUNCTION__, __LINE__);
- exit(-1);
+ printf("[%s:%d]: can't get http_decoder exdata index !!!\n", __FUNCTION__, __LINE__);
+ return NULL;
}
- g_topic_id = session_mq_get_topic_id(st, "HTTP_DECODER_MESSAGE");
+ g_topic_id = stellar_session_mq_get_topic_id(st, HTTP_DECODER_TOPIC);
if (g_topic_id < 0)
{
- printf("[%s:%d]: can't get http_decoder topic id !!!\n",
- __FUNCTION__, __LINE__);
- exit(-1);
+ printf("[%s:%d]: can't get http_decoder topic id !!!\n", __FUNCTION__, __LINE__);
+ return NULL;
}
- session_mq_subscribe_topic(st, g_topic_id, g_entry_fun, NULL);
- // printf("http_decoder_test_init OK!\n");
+ char entry_name[64] = "";
+ get_gtest_plug_entry(GTEST_PLUG_ENTRY_CFG, entry_name, sizeof(entry_name)-1);
+ set_gtest_plug_entry(entry_name);
+ stellar_session_mq_subscribe(st, g_topic_id, g_entry_fun, g_http_gtest_plugin_id);
+ printf("http_decoder_test_init succ, plugin_id:%d, topic_id:%d\n", g_http_gtest_plugin_id, g_topic_id);
- return NULL;
+ return (void *)strdup("http_decoder_test_ctx");
}
extern "C" void http_decoder_test_exit(void *test_ctx)
@@ -415,11 +512,6 @@ extern "C" void http_decoder_test_exit(void *test_ctx)
{
FREE(test_ctx);
}
-
+ // update_config_file(GTEST_PLUG_ENTRY_CFG, "name", "\\x22http_decoder_test_entry\\x22");
printf("http_decoder_test_exit OK!\n");
-}
-
-extern "C" void http_decoder_plug_set_entry_fuc(HTTP_DECODER_PLUG_ENTRY_FUN_T entry_fun)
-{
- g_entry_fun = entry_fun;
} \ No newline at end of file
diff --git a/test/http_decoder_gtest.h b/test/http_decoder_gtest.h
index 8e83a70..c413d08 100644
--- a/test/http_decoder_gtest.h
+++ b/test/http_decoder_gtest.h
@@ -1,7 +1,7 @@
#pragma once
-
#include "http_decoder.h"
-#include "session.h"
+#include "stellar/session.h"
+#include "stellar/session_mq.h"
#include "md5.h"
#include <stdint.h>
#include <stdlib.h>
@@ -14,8 +14,12 @@
#define JSON_KEY_VALUE_STRING_MAX_LEN (4096)
+#ifndef MAX
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+#endif
+#ifndef MIN
#define MIN(a, b) ((a) >= (b) ? (b) : (a))
+#endif
#define MMALLOC(type, size) ((type *)calloc(1, size))
#define MFREE(p) \
@@ -42,87 +46,4 @@
#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_PAYLOAD_MD5_NAME "__X_HTTP_PAYLOAD_MD5"
-
-struct fake_exdata_manage
-{
- char *name;
- int name_len;
- void *arg;
- void (*free_func)(struct session *sess, int idx, void *ex_ptr, void *arg);
-};
-
-struct fake_packet
-{
- int dir;
- size_t raw_pkt_data_len;
- const char *raw_pkt_data; // referred to packet Ethernet MAC header
- const char *l4_header; // referred to TCP, UDP header
- size_t payload_data_len;
- const char *payload_data; // referred to L7 data, such as HTTP, DNS, etc.
- size_t payload_submit_offset;
-};
-
-enum data_source_type_t
-{
- __DATA_SOURCE_NULL = 0,
- DATA_SOURCE_PCAP,
- DATA_SOURCE_JSON,
- __DATA_SOURCE_MAX
-};
-
-struct data_src_json_para_t
-{
- cJSON *json_root;
- cJSON *current_object;
- int json_array_size;
- int current_json_array_idx;
- char key_value_buf[JSON_KEY_VALUE_STRING_MAX_LEN];
-};
-
-struct fake_stellar
-{
- struct fake_exdata_manage fake_exdata_mgr[EX_DATA_MAX_SIZE];
- int tcp_mss;
- void *http_decoder_ctx;
- void *http_http_plug_ctx;
- int (*http_decoder_entry)(struct session *sess, int events,
- const struct packet *pkt, void *cb_arg);
- cJSON *http_plug_test_result_root;
- enum data_source_type_t data_source_type;
- const char *benchmark_json_file_name;
- const char *data_source_file_name;
- cJSON *load_benchmark_json_root;
- pcap_t *pcap_ins;
-
- struct data_src_json_para_t data_src_json_para;
-};
-
-struct fake_session
-{
- enum session_type type;
- struct fake_stellar *fst;
- struct fake_packet *fpkt;
- int events;
- int tcp_mss;
- enum session_addr_type addr_type;
- struct session_addr *addr;
- char *readable_addr_cstr;
- void *plug_exdata_array[EX_DATA_MAX_SIZE];
-};
-
-typedef void *(*HTTP_DECODER_INIT_FUN_T)(struct stellar *st);
-typedef int (*HTTP_DECODER_ENTRY_FUN_T)(struct session *sess, int events, const struct packet *pkt, void *cb_arg);
-typedef int (*HTTP_DECODER_PLUG_ENTRY_FUN_T)(struct session *sess, int topic_id, const void *data, void *cb_arg);
-extern struct fake_stellar *hdgt_create(void);
-extern int hdgt_init_once(struct fake_stellar *fst, int argc, char **argv,
- HTTP_DECODER_INIT_FUN_T hd_init_fun, HTTP_DECODER_ENTRY_FUN_T hd_entry_fun,
- HTTP_DECODER_INIT_FUN_T hd_plug_init_fun, HTTP_DECODER_PLUG_ENTRY_FUN_T hd_plug_entry_fun);
-extern int hdgt_data_source_init_by_json_text(struct fake_stellar *fst, const char *json_cont);
-int hdgt_under_test_module_init(struct fake_stellar *fst, HTTP_DECODER_INIT_FUN_T init_fun, HTTP_DECODER_ENTRY_FUN_T entry_fun);
-int hdgt_test_plug_init(struct fake_stellar *fst, HTTP_DECODER_INIT_FUN_T init_fun, HTTP_DECODER_PLUG_ENTRY_FUN_T entry_fun);
-extern void hdgt_main_loop(struct fake_stellar *fst);
-extern void hdgt_destroy(struct fake_stellar *fst);
-extern int hdgt_compare_result(struct fake_stellar *fst);
-extern void hdgt_set_data_source_type(fake_stellar *fst, enum data_source_type_t type);
-extern "C" void http_decoder_plug_set_entry_fuc(HTTP_DECODER_PLUG_ENTRY_FUN_T entry_fun); \ No newline at end of file
+#define GTEST_HTTP_PAYLOAD_MD5_NAME "__X_HTTP_PAYLOAD_MD5" \ No newline at end of file
diff --git a/test/http_decoder_perf_main.cpp b/test/http_decoder_perf_main.cpp
new file mode 100644
index 0000000..1dd7734
--- /dev/null
+++ b/test/http_decoder_perf_main.cpp
@@ -0,0 +1,363 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include "http_decoder_inc.h"
+
+#define TIME_MEASURE 1
+#if TIME_MEASURE
+#define TIME_START() struct timespec _start_time, _end_time; clock_gettime(CLOCK_REALTIME, &_start_time)
+#define TIME_DIFF() \
+ long long time_diff_ns;\
+ do { \
+ clock_gettime(CLOCK_REALTIME, &_end_time); \
+ if (likely(_end_time.tv_sec == _start_time.tv_sec))\
+ {\
+ time_diff_ns = (_end_time.tv_nsec - _start_time.tv_nsec);\
+ }else{\
+ time_diff_ns = (_end_time.tv_sec * 1000 * 1000 * 1000 + _end_time.tv_nsec) - (_start_time.tv_sec * 1000 * 1000 * 1000 + _start_time.tv_nsec);\
+ }\
+ }while (0)
+#else
+#define TIME_START()
+#define TIME_DIFF()
+#endif
+
+struct packet{
+ const char *payload;
+ size_t payload_len;
+ u_int8_t dir;
+};
+
+struct stellar{
+ int plugin_id;
+ void *plugin_env;
+ int exdata_id;
+ void *exdata;
+ int consumer_topid_id;
+ int publish_topic_id;
+ session_exdata_free *free_func;
+ session_msg_free_cb_func *publish_msg_free_cb;
+};
+
+struct session{
+ struct stellar *st;
+ struct session_addr addr;
+ void *context;
+ void *exdata;
+ void *message;
+ const struct packet *current_payload_st;
+};
+
+extern "C" void *http_decoder_init(struct stellar *st);
+extern "C" void http_decoder_exit(void *plugin_env);
+extern "C" void *_httpd_session_ctx_new_cb(struct session *sess, void *plugin_env);
+extern "C" void _httpd_ex_data_free_cb(struct session *s, int idx,void *ex_data, void *arg);
+extern "C" void http_decoder_tcp_stream_msg_cb(struct session *sess, int topic_id, const void *msg, void *no_use_ctx, void *plugin_env);
+extern "C" void http_decoder_perf_entry(struct session *sess, int topic_id, const void *raw_msg, void *per_session_ctx, void *plugin_env);
+
+static struct fieldstat_easy *fs4_instance;
+static struct fieldstat_tag FS4_SIMPLE_HISGRAM_TAG;
+static int fs4_simple_id;
+
+static struct fieldstat_tag FS4_LONG_LONG_URL_HISGRAM_TAG;
+static int fs4_long_long_url_id;
+
+static struct fieldstat_tag FS4_FRAG_HISGRAM_TAG;
+static int fs4_frag_id;
+
+void stellar_session_plugin_dettach_current_session(struct session *sess)
+{
+ return;
+}
+
+int stellar_session_mq_destroy_topic(struct stellar *st, int topic_id)
+{
+ return 0;
+}
+int stellar_get_worker_thread_num(struct stellar *st)
+{
+ return 1;
+}
+int stellar_get_current_thread_id(struct stellar *st)
+{
+ return 0;
+}
+int stellar_session_plugin_register(struct stellar *st,
+ session_ctx_new_func session_ctx_new,
+ session_ctx_free_func session_ctx_free,
+ void *plugin_env)
+{
+ return 0;
+}
+int stellar_session_exdata_new_index(struct stellar *st, const char *name, session_exdata_free *free_func,void *arg)
+{
+ st->free_func = free_func;
+ return 0;
+}
+int session_exdata_set(struct session *sess, int idx, void *ex_ptr)
+{
+ sess->exdata = ex_ptr;
+ return 0;
+}
+void *session_exdata_get(struct session *sess, int idx)
+{
+ return sess->exdata;
+}
+
+int stellar_session_mq_get_topic_id(struct stellar *st, const char *topic_name)
+{
+ if(strcmp(topic_name, "HTTP_DECODER_MESSAGE") == 0){
+ return st->publish_topic_id;
+ }
+ if(strcmp(topic_name, "TCP_STREAM") == 0){
+ return st->consumer_topid_id;
+ }
+ assert(0);
+ return -1;
+}
+
+int stellar_session_mq_create_topic(struct stellar *st, const char *topic_name, session_msg_free_cb_func *msg_free_cb, void *msg_free_arg)
+{
+ if(strcmp(topic_name, "HTTP_DECODER_MESSAGE") == 0){
+ st->publish_topic_id = 1;
+ st->publish_msg_free_cb = msg_free_cb;
+ return 1;
+ }
+ if(strcmp(topic_name, "TCP_STREAM") == 0){
+ st->consumer_topid_id = 2;
+ return 2;
+ }
+ return -1;
+}
+const char *session_get0_current_payload(struct session *sess, size_t *payload_len)
+{
+ const struct packet *test_payload = sess->current_payload_st;
+ *payload_len = test_payload->payload_len;
+ return test_payload->payload;
+}
+
+
+struct session_addr *session_get0_addr(struct session *sess, enum session_addr_type *addr_type)
+{
+ *addr_type = SESSION_ADDR_TYPE_IPV4_TCP;
+ return &sess->addr;
+}
+
+int packet_get_direction(const struct packet *pkt)
+{
+ return pkt->dir;
+}
+
+const struct packet *session_get0_current_packet(struct session *sess)
+{
+ return sess->current_payload_st;
+}
+int stellar_session_mq_subscribe(struct stellar *st, int topic_id, on_session_msg_cb_func *plugin_on_msg_cb, int plugin_id)
+{
+ return 0;
+}
+int session_mq_publish_message(struct session *sess, int topic_id, void *msg)
+{
+ if(topic_id == sess->st->publish_topic_id){
+ http_decoder_perf_entry(sess, topic_id, msg, NULL, NULL);
+ //maybe generate many messages for one packet, so free msg immediately
+ sess->st->publish_msg_free_cb(sess, msg, NULL);
+ }
+ return 0;
+}
+
+int session_is_symmetric(struct session *sess, unsigned char *flag)
+{
+ *flag = (SESSION_SEEN_C2S_FLOW | SESSION_SEEN_S2C_FLOW);
+ return 1;
+}
+
+static void perf_test_init_per_session(struct session *sess)
+{
+ sess->context = _httpd_session_ctx_new_cb(sess, sess->st->plugin_env);
+}
+
+static void perf_test_free_per_session(struct session *sess)
+{
+ sess->st->free_func(sess, sess->st->exdata_id, sess->exdata, NULL);
+}
+
+static void perf_test_loop(struct session *sess, struct packet *test_payload, int test_payload_index_max, const struct fieldstat_tag *tag, int fs4_metric_id)
+{
+ TIME_START();
+ sess->current_payload_st = &test_payload[0];
+ perf_test_init_per_session(sess);
+
+ for(int i = 0; i < test_payload_index_max; i++)
+ {
+ sess->current_payload_st = &test_payload[i];
+ http_decoder_tcp_stream_msg_cb(sess, sess->st->consumer_topid_id, test_payload[i].payload, NULL, sess->st->plugin_env);
+ TIME_DIFF();
+ fieldstat_easy_histogram_record(fs4_instance, 0, fs4_metric_id, tag, 1, time_diff_ns);
+ }
+ perf_test_free_per_session(sess);
+}
+
+static void perf_test_load_plug(struct stellar *st)
+{
+ st->plugin_env = http_decoder_init(st);
+ assert(st->plugin_env != NULL);
+ return;
+}
+
+static void perf_test_init(struct stellar *st, struct session *sess)
+{
+ memset(st, 0, sizeof(struct stellar));
+ memset(sess, 0, sizeof(struct session));
+ st->plugin_id = 0;
+ st->exdata_id = 0;
+ st->publish_topic_id = -1; //init
+ st->consumer_topid_id = 2; //init
+ perf_test_load_plug(st);
+
+ sess->st = st;
+ sess->addr.ipv4.saddr = 0x01020304;
+ sess->addr.ipv4.daddr = 0x05060708;
+ sess->addr.ipv4.sport = 12345;
+ sess->addr.ipv4.dport = 80;
+}
+
+#define SET_DATA_LENGTH_DIR(pkt_payload, cstr_in_heap, cur_dir, tmp_index) \
+ pkt_payload.payload = cstr_in_heap; \
+ pkt_payload.payload_len = strlen(cstr_in_heap); \
+ pkt_payload.dir = cur_dir;\
+ tmp_index++;
+
+static void init_test_data_simple(struct packet *test_payload, int *index)
+{
+ int tmp_index = 0;
+ const char *c2s_payload = "GET / HTTP/1.1\r\nHost: www.simple.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/58.0.3029.110 Safari/537.36 Edge/16.16299\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n";
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], c2s_payload, PACKET_DIRECTION_C2S, tmp_index);
+
+ const char *content = "Hello, http decoder perf test simple!!!";
+ int content_length = strlen(content);
+ char *s2c_payload = (char *)malloc(1024);
+ snprintf(s2c_payload, 1024, "HTTP/1.1 200 OK\r\nServer: Apache-Coyote/1.1\r\nConnection: keep-alive\r\nDate: Sat, 01 May 2024 01:36:57 GMT\r\nContent-Type: text/html;charset=UTF-8\r\nContent-Length: %d\r\n\r\n%s", content_length, content);
+
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], s2c_payload, PACKET_DIRECTION_S2C, tmp_index);
+
+ *index = tmp_index;
+}
+
+static void init_test_data_frag(struct packet *test_payload, int *index)
+{
+ int tmp_index = 0;
+ /* c2s */
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "GET / HTTP/1.1\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Host: www.fragment.com\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Cache-Control: max-age=0\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Connection: keep-alive\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Referer: http://fragment.com/register.jsp?redirect:http://aa.bb.cc.dd.com/?\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Cookie: JSESSIONID=385C79E211D561C0CA13D90F150F603D34875GH87FSHG8S7RTHG74875GHS8R7THG87SRTH\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Accept: */*\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Accept-Encoding: gzip, deflate\r\n", PACKET_DIRECTION_C2S, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "\r\n", PACKET_DIRECTION_C2S, tmp_index); //header EOF
+
+ /* s2c */
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "HTTP/1.1 200 OK\r\n", PACKET_DIRECTION_S2C, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Server: Apache-Coyote/1.1\r\n", PACKET_DIRECTION_S2C, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Connection: keep-alive\r\n", PACKET_DIRECTION_S2C, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Content-Type: text/html;charset=UTF-8\r\n", PACKET_DIRECTION_S2C, tmp_index);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "Date: Sat, 01 May 2024 01:36:57 GMT\r\n", PACKET_DIRECTION_S2C, tmp_index);
+
+ char *cont_len_buf = (char *)malloc(1024);
+ const char *s2c_payload = "Hello, http decoder perf test fragment!!!";
+ int content_length = strlen(s2c_payload);
+ snprintf(cont_len_buf, 1024, "Content-Length: %d\r\n\r\n", content_length);
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], cont_len_buf, PACKET_DIRECTION_S2C, tmp_index);
+
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], "\r\n", PACKET_DIRECTION_S2C, tmp_index); //header EOF
+
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], s2c_payload, PACKET_DIRECTION_S2C, tmp_index);
+
+ *index = tmp_index;
+}
+
+static void init_test_data_long_long_url(struct packet *test_payload, int *index)
+{
+ int tmp_index = 0;
+
+ const char *request_line_frag1 = "GET /long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/";
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], request_line_frag1, PACKET_DIRECTION_C2S, tmp_index);
+
+ const char *request_line_frag2 = "long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/\
+/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long/long.index.html HTTP/1.1\r\n";
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], request_line_frag2, PACKET_DIRECTION_C2S, tmp_index);
+
+ const char *request_line_frag3 = "Host: www.long-long-url.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/58.0.3029.110 Safari/537.36 Edge/16.16299\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n";
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], request_line_frag3, PACKET_DIRECTION_C2S, tmp_index);
+
+ const char *content = "Hello, http decoder perf test long long url!!!";
+ int content_length = strlen(content);
+ char *s2c_payload = (char *)malloc(1024);
+ snprintf(s2c_payload, 1024, "HTTP/1.1 200 OK\r\nServer: Apache-Coyote/1.1\r\nConnection: keep-alive\r\nDate: Sat, 01 May 2024 01:36:57 GMT\r\nContent-Type: text/html;charset=UTF-8\r\nContent-Length: %d\r\n\r\n%s", content_length, content);
+
+ SET_DATA_LENGTH_DIR(test_payload[tmp_index], s2c_payload, PACKET_DIRECTION_S2C, tmp_index);
+
+ *index = tmp_index;
+}
+
+static void perf_stat_init(void)
+{
+ fs4_instance = fieldstat_easy_new(1, "http_decoder_test", NULL, 0);
+ fieldstat_easy_enable_auto_output(fs4_instance, "./httpd_fs4.json", 1);
+
+ FS4_SIMPLE_HISGRAM_TAG.key = "simple";
+ FS4_SIMPLE_HISGRAM_TAG.type = TAG_DOUBLE;
+ FS4_SIMPLE_HISGRAM_TAG.value_double = 0.00001;
+ fs4_simple_id = fieldstat_easy_register_histogram(fs4_instance, "simple", 1, 99999999, 5);
+
+ FS4_FRAG_HISGRAM_TAG.key = "frag";
+ FS4_FRAG_HISGRAM_TAG.type = TAG_DOUBLE;
+ FS4_FRAG_HISGRAM_TAG.value_double = 0.00001;
+ fs4_frag_id = fieldstat_easy_register_histogram(fs4_instance, "frag", 1, 99999999, 5);
+
+ FS4_LONG_LONG_URL_HISGRAM_TAG.key = "long-url";
+ FS4_LONG_LONG_URL_HISGRAM_TAG.type = TAG_DOUBLE;
+ FS4_LONG_LONG_URL_HISGRAM_TAG.value_double = 0.00001;
+ fs4_long_long_url_id = fieldstat_easy_register_histogram(fs4_instance, "long-url", 1, 99999999, 5);
+}
+
+int main(int argc, char const *argv[])
+{
+ struct stellar st;
+ struct session sess;
+ struct packet test_payload_simple [4] = {};
+ int payload_index_simple = 0;
+
+ struct packet test_payload_long_long_url [8] = {};
+ int payload_index_long_long_url = 0;
+
+ struct packet test_payload_frag [32] = {};
+ int payload_index_frag = 0;
+
+ perf_test_init(&st, &sess);
+ perf_stat_init();
+
+ init_test_data_simple(test_payload_simple, &payload_index_simple);
+ init_test_data_long_long_url(test_payload_long_long_url, &payload_index_long_long_url);
+ init_test_data_frag(test_payload_frag, &payload_index_frag);
+
+ while(1){
+ perf_test_loop(&sess, test_payload_simple, payload_index_simple, &FS4_SIMPLE_HISGRAM_TAG, fs4_simple_id);
+ perf_test_loop(&sess, test_payload_long_long_url, payload_index_long_long_url, &FS4_LONG_LONG_URL_HISGRAM_TAG, fs4_long_long_url_id);
+ perf_test_loop(&sess, test_payload_frag, payload_index_frag, &FS4_FRAG_HISGRAM_TAG, fs4_frag_id);
+ }
+ return 0;
+}
diff --git a/test/http_decoder_perf.cpp b/test/http_decoder_perf_plug.cpp
index 767de46..f588683 100644
--- a/test/http_decoder_perf.cpp
+++ b/test/http_decoder_perf_plug.cpp
@@ -1,23 +1,14 @@
-
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
-#include "../include/http_decoder.h"
-
#ifdef __cplusplus
extern "C"
{
-
+#include "http_decoder_inc.h"
#include "cJSON.h"
-#include "http_decoder_gtest.h"
-#include "stellar/utils.h"
-#include "stellar/stellar.h"
-#include "stellar/session_exdata.h"
-#include "stellar/session_mq.h"
-#include "md5.h"
}
#endif
@@ -25,26 +16,34 @@ extern "C"
static int g_result_count = 0;
static int g_header_count = 1;
-static int g_exdata_idx = 0;
-static int g_topic_id = 0;
+static int g_exdata_idx = -1;
+static int g_topic_id = -1;
+static int g_plugin_id = -1;
-extern "C" int http_decoder_perf_entry(struct session *sess, int topic_id, const void *data, void *cb_arg)
+#define DEBUG_PRINT(fmt, ...) ///printf(fmt, ##__VA_ARGS__)
+
+extern "C" void http_decoder_perf_entry(struct session *sess, int topic_id, const void *raw_msg, void *per_session_ctx, void *plugin_env)
+// extern "C" int http_decoder_perf_entry(struct session *sess, int topic_id, const void *data, void *cb_arg)
{
struct http_request_line req_line = {0};
struct http_response_line res_line = {0};
struct http_header header = {0};
+ struct hstring url = {0};
struct hstring body = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
+ struct http_message *msg = (struct http_message *)raw_msg;
+ enum http_message_type msg_type = http_message_type_get(msg);
void *ret1, *ret2;
switch (msg_type)
{
case HTTP_MESSAGE_REQ_LINE:
+ DEBUG_PRINT("---------------------------------------------------------------\n");
http_message_get_request_line(msg, &req_line);
if (req_line.uri.str)
{
- ret1 = memmem(req_line.uri.str, req_line.uri.str_len, "index", 5);
+ DEBUG_PRINT("req_line.method.str: %.*s\n", req_line.method.str_len, req_line.method.str);
+ ret1 = memmem(req_line.method.str, req_line.method.str_len, "PUT", 3);
+ DEBUG_PRINT("req_line.version.str: %.*s\n", req_line.version.str_len, req_line.version.str);
}
break;
case HTTP_MESSAGE_REQ_HEADER:
@@ -52,6 +51,11 @@ extern "C" int http_decoder_perf_entry(struct session *sess, int topic_id, const
{
ret1 = memmem(header.key.str, header.key.str_len, "key", 3);
ret2 = memmem(header.val.str, header.val.str_len, "val", 3);
+ DEBUG_PRINT("REQ header: %.*s : %.*s\n", (int)header.key.str_len, header.key.str, (int)header.val.str_len, header.val.str);
+ }
+ http_message_get_url(msg, &url);
+ if(url.str && url.str_len){
+ DEBUG_PRINT("URL: %.*s\n", url.str_len, url.str);
}
break;
case HTTP_MESSAGE_REQ_BODY:
@@ -64,34 +68,35 @@ extern "C" int http_decoder_perf_entry(struct session *sess, int topic_id, const
case HTTP_MESSAGE_RES_LINE:
http_message_get_response_line(msg, &res_line);
ret1 = memmem(res_line.status.str, res_line.status.str_len, "OK", 2);
+ DEBUG_PRINT("res_line.status.str: %.*s\n", (int)res_line.status.str_len, res_line.status.str);
break;
case HTTP_MESSAGE_RES_HEADER:
while (http_message_header_next(msg, &header) >= 0)
{
ret1 = memmem(header.key.str, header.key.str_len, "key", 3);
ret2 = memmem(header.val.str, header.val.str_len, "val", 3);
+ DEBUG_PRINT("RES header: %.*s : %.*s\n", (int)header.key.str_len, header.key.str, (int)header.val.str_len, header.val.str);
}
break;
case HTTP_MESSAGE_RES_BODY:
- // http_message_get_response_raw_body(msg, &body);
+ http_message_get_raw_body(msg, &body);
+ DEBUG_PRINT("res raw body: %.*s\n", body.str_len, body.str);
// output_http_body(&body, 0);
http_message_get_decompress_body(msg, &body);
// output_http_body(&body, 1);
ret1 = memmem(body.str, body.str_len, "</html>", 7);
+ DEBUG_PRINT("res unzip body: %.*s\n", body.str_len, body.str);
+ DEBUG_PRINT("---------------------------------------------------------------\n");
break;
// to do: check payload
default:
break;
}
-
- if(ret1 && ret2){
- return 1;
- }
- return 0;
+ return;
}
-static int (*g_entry_fun)(struct session *sess, int topic_id, const void *data, void *cb_arg) = &http_decoder_perf_entry;
+static on_session_msg_cb_func*g_entry_fun = &http_decoder_perf_entry;
static void http_decoder_test_exdata_free(struct session *sess, int idx, void *ex_ptr, void *arg)
{
@@ -100,26 +105,24 @@ static void http_decoder_test_exdata_free(struct session *sess, int idx, void *e
extern "C" void *http_decoder_perf_init(struct stellar *st)
{
- g_exdata_idx =
- stellar_session_get_ex_new_index(st, "HTTP_DECODER_REQ_TEST",
+ g_plugin_id = stellar_session_plugin_register(st, NULL, NULL, NULL);
+ g_exdata_idx = stellar_session_exdata_new_index(st, "HTTP_DECODER_REQ_TEST",
http_decoder_test_exdata_free,
- NULL);
+ NULL);
if (g_exdata_idx < 0)
{
- printf("[%s:%d]: can't get http_decoder exdata index !!!\n",
- __FUNCTION__, __LINE__);
+ printf("[%s:%d]: can't get http_decoder exdata index !!!\n", __FUNCTION__, __LINE__);
exit(-1);
}
- g_topic_id = session_mq_get_topic_id(st, "HTTP_DECODER_MESSAGE");
+ g_topic_id = stellar_session_mq_get_topic_id(st, "HTTP_DECODER_MESSAGE");
if (g_topic_id < 0)
{
- printf("[%s:%d]: can't get http_decoder topic id !!!\n",
- __FUNCTION__, __LINE__);
+ printf("[%s:%d]: can't get http_decoder topic id !!!\n", __FUNCTION__, __LINE__);
exit(-1);
}
- session_mq_subscribe_topic(st, g_topic_id, g_entry_fun, NULL);
+ stellar_session_mq_subscribe(st, g_topic_id, g_entry_fun, g_plugin_id);
// printf("http_decoder_test_init OK!\n");
return NULL;
@@ -131,11 +134,5 @@ extern "C" void http_decoder_perf_exit(void *test_ctx)
{
FREE(test_ctx);
}
-
printf("http_decoder_perf plug exit OK!\n");
}
-
-extern "C" void http_decoder_plug_set_entry_fuc(HTTP_DECODER_PLUG_ENTRY_FUN_T entry_fun)
-{
- g_entry_fun = entry_fun;
-} \ No newline at end of file
diff --git a/test/http_decoder_stub.cpp b/test/http_decoder_stub.cpp
deleted file mode 100644
index e719ebe..0000000
--- a/test/http_decoder_stub.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- Http Decoder Google Test stub module
-*/
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-#include "http_decoder.h"
-
-
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-#include "session.h"
-#include "session_exdata.h"
-#include "session_mq.h"
-#include "stellar.h"
-#include "http_decoder_gtest.h"
-#include "MESA_jump_layer.h"
-extern struct fake_stellar *g_fake_stellar;
-
- static int g_topic_id = -1;
- static msg_free_cb_func *g_msg_free_cb = NULL;
- static void *g_msg_free_cb_arg = NULL;
- static on_msg_cb_func *g_topic_sub_cb = NULL;
- static void *g_topic_sub_cb_arg = NULL;
-
- int commit_test_result_json(cJSON *node, const char *name)
- {
- assert(node != NULL || name != NULL);
- if (g_fake_stellar->http_plug_test_result_root)
- {
- // cJSON_AddStringToObject(node, "__X_HTTP_RESULT_INDEX", name);
- cJSON_AddItemToArray(g_fake_stellar->http_plug_test_result_root, node);
- return 0;
- }
- return -1;
- }
-
- int packet_get_direction(const struct packet *pkt)
- {
- struct fake_packet *fpkt = (struct fake_packet *)pkt;
- return fpkt->dir;
- }
-
- int session_event_assign(struct session_event *ev, struct stellar *st, struct session *sess, int events, session_event_cb_func *cb, void *cb_arg)
- {
- DEBUG_PRINT("todo: fake session_event_assign()\n");
- return 0;
- }
-
- const char *session_get0_readable_addr(struct session *sess)
- {
- struct fake_session *fses = (struct fake_session *)sess;
-
- if (fses->readable_addr_cstr)
- {
- return fses->readable_addr_cstr;
- }
-
- char ip_src_buf[INET6_ADDRSTRLEN] = {};
- char ip_dst_buf[INET6_ADDRSTRLEN] = {};
- char port_src_buf[16] = {};
- char port_dst_buf[16] = {};
- char tuple4_buf[256] = {};
-
- if (SESSION_ADDR_TYPE_IPV4_TCP == fses->addr_type)
- {
- inet_ntop(AF_INET, &fses->addr->ipv4.saddr, ip_src_buf, INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &fses->addr->ipv4.daddr, ip_dst_buf, INET_ADDRSTRLEN);
- sprintf(port_src_buf, "%u", ntohs(fses->addr->ipv4.sport));
- sprintf(port_dst_buf, "%u", ntohs(fses->addr->ipv4.dport));
- }
- else
- {
- inet_ntop(AF_INET6, fses->addr->ipv6.saddr, ip_src_buf, INET6_ADDRSTRLEN);
- inet_ntop(AF_INET6, fses->addr->ipv6.daddr, ip_dst_buf, INET6_ADDRSTRLEN);
- sprintf(port_src_buf, "%u", ntohs(fses->addr->ipv6.sport));
- sprintf(port_dst_buf, "%u", ntohs(fses->addr->ipv6.dport));
- }
-
- snprintf(tuple4_buf, sizeof(tuple4_buf), "%s.%s>%s.%s", ip_src_buf, port_src_buf, ip_dst_buf, port_dst_buf);
- fses->readable_addr_cstr = MMALLOC(char, strlen(tuple4_buf) + 1);
- memcpy(fses->readable_addr_cstr, tuple4_buf, strlen(tuple4_buf));
-
- return fses->readable_addr_cstr;
- }
-
- struct session_addr *session_get0_addr(struct session *sess, enum session_addr_type *addr_type)
- {
- struct fake_session *fses = (struct fake_session *)sess;
- *addr_type = fses->addr_type;
- return fses->addr;
- }
-
- static int __find_ex_data(struct fake_stellar *fst, const char *name)
- {
- int find_name_len = strlen(name);
-
- for (int i = 0; i < EX_DATA_MAX_SIZE; i++)
- {
- if ((fst->fake_exdata_mgr[i].name != NULL) && (strncasecmp(name, fst->fake_exdata_mgr[i].name, find_name_len) == 0) && (find_name_len == fst->fake_exdata_mgr[i].name_len))
- {
- return i;
- }
- }
-
- return -1;
- }
-
- static int __save_ex_data(struct fake_stellar *fst, const char *name, session_ex_free *free_func, void *arg)
- {
- for (int i = 0; i < EX_DATA_MAX_SIZE; i++)
- {
- if (fst->fake_exdata_mgr[i].name == NULL && fst->fake_exdata_mgr[i].name_len == 0)
- {
- fst->fake_exdata_mgr[i].name = MMALLOC(char, strlen(name) + 1);
- fst->fake_exdata_mgr[i].name_len = strlen(name) + 1;
- memcpy(fst->fake_exdata_mgr[i].name, name, strlen(name));
- fst->fake_exdata_mgr[i].free_func = free_func;
- fst->fake_exdata_mgr[i].arg = arg;
- return i;
- }
- }
-
- return -1;
- }
-
- int stellar_session_get_ex_new_index(struct stellar *st, const char *name, session_ex_free *free_func, void *arg)
- {
- int ex_id = __find_ex_data((struct fake_stellar *)st, name);
- if (-1 == ex_id)
- {
- ex_id = __save_ex_data((struct fake_stellar *)st, name, free_func, arg);
- }
-
- return ex_id;
- }
-
- int session_mq_get_topic_id(struct stellar *st, const char *topic_name)
- {
- return g_topic_id;
- }
-
- int session_get_current_thread_id(struct session *sess)
- {
- return 0;
- }
-
- int session_mq_destroy_topic(struct stellar *st, int topic_id)
- {
- return 0;
- }
-
- int session_set_ex_data(struct session *sess, int idx, void *ex_ptr)
- {
- struct fake_session *fses = (struct fake_session *)sess;
- fses->plug_exdata_array[idx] = ex_ptr;
-
- return 0;
- }
-
- void *session_get_ex_data(struct session *sess, int idx)
- {
- struct fake_session *fses = (struct fake_session *)sess;
- return fses->plug_exdata_array[idx];
- }
-
- void hdd_session_free_exdata(struct fake_session *fake_ses)
- {
- for (int i = 0; i < EX_DATA_MAX_SIZE; i++)
- {
- if (fake_ses->plug_exdata_array[i] != NULL)
- {
- fake_ses->fst->fake_exdata_mgr[i].free_func((struct session *)fake_ses, i, fake_ses->plug_exdata_array[i], NULL);
- }
- }
- }
-
- int stellar_plugin_register(struct stellar *st, int events, session_event_cb_func *cb, void *cb_arg)
- {
- return 0; // fix plugin id
- }
-
- extern int http_decoder_test_entry(struct session *sess, int topic_id, const void *data, void *cb_arg);
- int session_mq_publish_message(struct session *sess, int topic_id, void *data)
- {
- g_topic_sub_cb(sess, topic_id, data, g_topic_sub_cb_arg);
- g_msg_free_cb(data, g_msg_free_cb_arg);
- return 0;
- }
-
- int stellar_get_worker_thread_num(struct stellar *st)
- {
- return 1;
- }
-
- int session_mq_create_topic(struct stellar *st, const char *topic_name, msg_free_cb_func *free_cb, void *cb_arg)
- {
- g_msg_free_cb = free_cb;
- g_msg_free_cb_arg = cb_arg;
-
- g_topic_id = 0; // KISS, use fix value
- return g_topic_id;
- }
-
- const char *session_get0_current_payload(struct session *sess, size_t *payload_len)
- {
- struct fake_session *fses = (struct fake_session *)sess;
- struct fake_packet *fpkt = fses->fpkt;
- const char *payload_ptr = NULL;
-
- if (!fpkt || !fpkt->payload_data || fpkt->payload_data_len == 0)
- {
- return NULL;
- }
-
- int submit_len = MIN(fses->tcp_mss, fpkt->payload_data_len - fpkt->payload_submit_offset);
- if (submit_len <= 0)
- {
- *payload_len = 0;
- return NULL;
- }
- payload_ptr = fpkt->payload_data + fpkt->payload_submit_offset;
- *payload_len = submit_len;
- fpkt->payload_submit_offset += submit_len;
-
- return payload_ptr;
- }
-
- struct session_event *session_get_intrinsic_event(struct session *sess, int plugin_id)
- {
- return NULL;
- }
-
- int session_is_inner_most(struct session *sess, uint64_t *flag)
- {
- return 1; // no tunnel
- }
-
- int session_mq_subscribe_topic(struct stellar *st, int topic_id, on_msg_cb_func *sub_cb, void *cb_arg)
- {
- //todo, support multiple topic?
- g_topic_sub_cb = sub_cb;
- g_topic_sub_cb_arg = cb_arg;
- return 0;
- }
-
-#ifdef __cplusplus
-}
-#endif \ No newline at end of file
diff --git a/test/http_gtest_main.cpp b/test/http_gtest_main.cpp
deleted file mode 100644
index 5b7aee5..0000000
--- a/test/http_gtest_main.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <assert.h>
-#include <getopt.h>
-#include <gtest/gtest.h>
-#include "http_decoder_gtest.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-struct fake_stellar *g_fake_stellar; //export symbol for commit_test_result_json()
-extern int http_decoder_entry(struct session *sess, int events,const struct packet *pkt, void *cb_arg);
-extern int http_decoder_test_entry(struct session *sess, int topic_id, const void *data, void *cb_arg);
-extern void *http_decoder_init(struct stellar *st);
-extern void *http_decoder_test_init(struct stellar *st);
-}
-#endif
-
-TEST(HTTP_DECODER, GTEST)
-{
- ASSERT_EQ(0, hdgt_compare_result(g_fake_stellar));
-}
-
-int main(int argc, char **argv)
-{
- g_fake_stellar = hdgt_create();
-
- if(hdgt_init_once(g_fake_stellar, argc, argv, http_decoder_init, http_decoder_entry, http_decoder_test_init, http_decoder_test_entry) < 0)
- {
- fprintf(stderr, "hdgt_init_once() fail!\n");
- exit(1);
- }
-
- hdgt_main_loop(g_fake_stellar);
-
- ::testing::InitGoogleTest(&argc, argv);
- int ret = RUN_ALL_TESTS();
-
- hdgt_destroy(g_fake_stellar);
-
- return ret;
-} \ No newline at end of file
diff --git a/test/http_gtest_unit.cpp b/test/http_gtest_unit.cpp
deleted file mode 100644
index 8b35d0c..0000000
--- a/test/http_gtest_unit.cpp
+++ /dev/null
@@ -1,569 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <assert.h>
-#include <getopt.h>
-#include <gtest/gtest.h>
-#include "http_decoder_gtest.h"
-
-#ifdef __cplusplus
-extern "C"
-{
- struct fake_stellar *g_fake_stellar; // export symbol for commit_test_result_json()
- extern int http_decoder_entry(struct session *sess, int events, const struct packet *pkt, void *cb_arg);
- extern int http_decoder_test_entry(struct session *sess, int topic_id, const void *data, void *cb_arg);
- extern void *http_decoder_init(struct stellar *st);
- extern void *http_decoder_test_init(struct stellar *st);
-}
-#endif
-
-#define UNIT_TEST_SUCC_SSTRING "http unit test succ!"
-#define UNIT_TEST_FAIL_SSTRING "http unit test fail!"
-
-#define PRINT_TEST_RESULT(ret) \
- do \
- { \
- if (0 == ret) \
- { \
- fprintf(stderr, "%s\n", UNIT_TEST_SUCC_SSTRING); \
- exit(200); \
- } \
- else \
- { \
- fprintf(stderr, "%s\n", UNIT_TEST_FAIL_SSTRING); \
- exit(404); \
- } \
- } while (0)
-
-static int hgut_compare_hstring(const struct hstring *hs1, const struct hstring *hs2)
-{
- if (hs1->str_len != hs2->str_len)
- {
- return -1;
- }
- if (strncmp(hs1->str, hs2->str, hs1->str_len) != 0)
- {
- return -1;
- }
- return 0;
-}
-
-static int hgut_compare_req_line(const struct http_request_line *req_line1, const struct http_request_line *req_line2)
-{
- if (hgut_compare_hstring(&req_line1->method, &req_line2->method) != 0)
- {
- return -1;
- }
- if (hgut_compare_hstring(&req_line1->uri, &req_line2->uri) != 0)
- {
- return -1;
- }
- if (hgut_compare_hstring(&req_line1->version, &req_line2->version) != 0)
- {
- return -1;
- }
- if (req_line1->major_version != req_line2->major_version)
- {
- return -1;
- }
- if (req_line1->minor_version != req_line2->minor_version)
- {
- return -1;
- }
-
- return 0;
-}
-
-static int hgut_compare_res_line(const struct http_response_line *res_line1, const struct http_response_line *res_line2)
-{
- if (hgut_compare_hstring(&res_line1->version, &res_line2->version) != 0)
- {
- return -1;
- }
- if (hgut_compare_hstring(&res_line1->status, &res_line2->status) != 0)
- {
- return -1;
- }
- if (res_line1->major_version != res_line2->major_version)
- {
- return -1;
- }
- if (res_line1->minor_version != res_line2->minor_version)
- {
- return -1;
- }
- if (res_line1->status_code != res_line2->status_code)
- {
- return -1;
- }
-
- return 0;
-}
-
-static int hgut_compare_header(const struct http_header *hdr1, const struct http_header *hdr2)
-{
- if (hdr1->key.str_len != hdr2->key.str_len)
- {
- return -1;
- }
- if (hdr1->val.str_len != hdr2->val.str_len)
- {
- return -1;
- }
- if (strncmp(hdr1->key.str, hdr2->key.str, hdr1->key.str_len) != 0)
- {
- return -1;
- }
- if (strncmp(hdr1->val.str, hdr2->val.str, hdr1->val.str_len) != 0)
- {
- return -1;
- }
-
- return 0;
-}
-
-extern "C" int ut_get_req_line_entry(struct session *sess, int topic_id, const void *data, void *cb_arg)
-{
- int ret;
- struct http_request_line expect_req_line = {0};
- struct http_request_line req_line = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
-
- expect_req_line.method.str = (char *)"GET";
- expect_req_line.method.str_len = 3;
- expect_req_line.uri.str = (char *)"/test_req_line/index.html";
- expect_req_line.uri.str_len = strlen("/test_req_line/index.html");
- expect_req_line.version.str = (char *)"1.1";
- expect_req_line.version.str_len = 3;
- expect_req_line.major_version = 1;
- expect_req_line.minor_version = 1;
-
- if (HTTP_MESSAGE_REQ_LINE == msg_type)
- {
- EXPECT_EQ(0, http_message_get_request_line(msg, &req_line));
- ret = hgut_compare_req_line(&expect_req_line, &req_line);
- PRINT_TEST_RESULT(ret);
- }
-
- return 0;
-}
-
-extern "C" int ut_get_url_entry(struct session *sess, int topic_id, const void *data, void *cb_arg)
-{
- int ret;
- struct hstring expect_url = {0};
- struct hstring get_url = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
-
- expect_url.str = (char *)"get_url_test.com/test_url/index.html";
- expect_url.str_len = strlen(expect_url.str);
-
- if (HTTP_MESSAGE_REQ_LINE == msg_type)
- {
- EXPECT_EQ(-1, http_message_get_url(msg, &get_url));
- }
-
- if (HTTP_MESSAGE_REQ_HEADER == msg_type || HTTP_MESSAGE_REQ_BODY == msg_type || HTTP_MESSAGE_RES_LINE == msg_type || HTTP_MESSAGE_RES_HEADER == msg_type || HTTP_MESSAGE_RES_BODY == msg_type)
- {
- EXPECT_EQ(0, http_message_get_url(msg, &get_url));
- ret = hgut_compare_hstring(&expect_url, &get_url);
- if (ret != 0)
- {
- fprintf(stderr, "http_message_get_url value is diff! expect:%.*s, but actual:%.*s\n",
- expect_url.str_len,
- expect_url.str,
- get_url.str_len,
- get_url.str);
- }
- PRINT_TEST_RESULT(ret);
- }
-
- return 0;
-}
-
-extern "C" int ut_get_res_line_entry(struct session *sess, int topic_id, const void *data, void *cb_arg)
-{
- int ret;
- struct http_response_line expect_res_line = {0};
- struct http_response_line res_line = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
-
- expect_res_line.version.str = (char *)"1.1";
- expect_res_line.version.str_len = 3;
- expect_res_line.status.str = (char *)"OK";
- expect_res_line.status.str_len = 2;
- expect_res_line.status_code = 200;
- expect_res_line.major_version = 1;
- expect_res_line.minor_version = 1;
-
- if (HTTP_MESSAGE_REQ_LINE == msg_type || HTTP_MESSAGE_REQ_HEADER == msg_type || HTTP_MESSAGE_REQ_BODY == msg_type)
- {
- EXPECT_EQ(-1, http_message_get_response_line(msg, &res_line));
- }
-
- if (HTTP_MESSAGE_RES_LINE == msg_type)
- {
- EXPECT_EQ(0, http_message_get_response_line(msg, &res_line));
- ret = hgut_compare_res_line(&expect_res_line, &res_line);
- PRINT_TEST_RESULT(ret);
- }
-
- return 0;
-}
-
-extern "C" int ut_get_req_header(struct session *sess, int topic_id, const void *data, void *cb_arg)
-{
- int ret;
- struct http_header expect_hdr = {0};
- struct http_header req_hdr = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
-
- expect_hdr.key.str = (char *)"Host";
- expect_hdr.key.str_len = strlen("Host");
- expect_hdr.val.str = (char *)"192.168.40.137";
- expect_hdr.val.str_len = strlen("192.168.40.137");
-
- struct hstring fetch_key = expect_hdr.key;
-
- if (HTTP_MESSAGE_REQ_LINE == msg_type)
- {
- EXPECT_EQ(-1, http_message_get_header(msg, &fetch_key, &req_hdr));
- }
-
- if (HTTP_MESSAGE_REQ_HEADER == msg_type)
- {
- if (0 == http_message_get_header(msg, &fetch_key, &req_hdr))
- {
- ret = hgut_compare_header(&expect_hdr, &req_hdr);
- PRINT_TEST_RESULT(ret);
- }
- }
-
- return 0;
-}
-
-extern "C" int ut_get_res_header(struct session *sess, int topic_id, const void *data, void *cb_arg)
-{
- int ret;
- struct http_header expect_hdr = {0};
- struct http_header req_hdr = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
-
- expect_hdr.key.str = (char *)"Server";
- expect_hdr.key.str_len = strlen("Server");
- expect_hdr.val.str = (char *)"SimpleHTTP/0.6 Python/2.7.5";
- expect_hdr.val.str_len = strlen("SimpleHTTP/0.6 Python/2.7.5");
-
- struct hstring fetch_key = expect_hdr.key;
-
- if (HTTP_MESSAGE_REQ_LINE == msg_type || HTTP_MESSAGE_REQ_HEADER == msg_type || HTTP_MESSAGE_REQ_BODY == msg_type)
- {
- EXPECT_EQ(-1, http_message_get_header(msg, &fetch_key, &req_hdr));
- }
-
- if (HTTP_MESSAGE_RES_HEADER == msg_type)
- {
- if (0 == http_message_get_header(msg, &fetch_key, &req_hdr))
- {
- ret = hgut_compare_header(&expect_hdr, &req_hdr);
- PRINT_TEST_RESULT(ret);
- }
- }
-
- return 0;
-}
-
-extern "C" int ut_iterate_req_headers(struct session *sess, int topic_id, const void *data, void *cb_arg)
-{
- int ret;
- struct http_header expect_hdr_array[16] = {0};
- struct http_header req_hdr_array[16] = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
- static int hdr_count = 0;
-
- if (HTTP_MESSAGE_REQ_LINE == msg_type)
- {
- EXPECT_EQ(-1, http_message_header_next(msg, &req_hdr_array[0]));
- }
-
- expect_hdr_array[0].key.str = (char *)"Host";
- expect_hdr_array[0].key.str_len = strlen("Host");
- expect_hdr_array[0].val.str = (char *)"192.168.40.137";
- expect_hdr_array[0].val.str_len = strlen("192.168.40.137");
-
- expect_hdr_array[1].key.str = (char *)"User-Agent";
- expect_hdr_array[1].key.str_len = strlen("User-Agent");
- expect_hdr_array[1].val.str = (char *)"curl/7.79.1";
- expect_hdr_array[1].val.str_len = strlen("curl/7.79.1");
-
- expect_hdr_array[2].key.str = (char *)"Accept";
- expect_hdr_array[2].key.str_len = strlen("Accept");
- expect_hdr_array[2].val.str = (char *)"*/*";
- expect_hdr_array[2].val.str_len = strlen("*/*");
-
- if (HTTP_MESSAGE_REQ_HEADER == msg_type)
- {
- while (0 == http_message_header_next(msg, &req_hdr_array[hdr_count]))
- {
- ret = hgut_compare_header(&expect_hdr_array[hdr_count], &req_hdr_array[hdr_count]);
- if (0 != ret)
- {
- fprintf(stderr, "header value is diff!\n");
- PRINT_TEST_RESULT(ret);
- }
- hdr_count++;
- }
-
- hdr_count = 0;
- http_message_reset_header_iter(msg);
- // retry after reset iter
-
- while (0 == http_message_header_next(msg, &req_hdr_array[hdr_count]))
- {
- ret = hgut_compare_header(&expect_hdr_array[hdr_count], &req_hdr_array[hdr_count]);
- if (0 != ret)
- {
- fprintf(stderr, "header value is diff!\n");
- PRINT_TEST_RESULT(ret);
- }
- hdr_count++;
- }
- }
-
- if (HTTP_MESSAGE_REQ_BODY == msg_type || HTTP_MESSAGE_RES_LINE == msg_type || HTTP_MESSAGE_RES_HEADER == msg_type || HTTP_MESSAGE_RES_BODY == msg_type)
- {
- ret = hdr_count == 3 ? 0 : -1;
- PRINT_TEST_RESULT(ret);
- }
-
- return 0;
-}
-
-extern "C" int ut_iterate_res_headers(struct session *sess, int topic_id, const void *data, void *cb_arg)
-{
- int ret;
- struct http_header expect_hdr_array[16] = {0};
- struct http_header res_hdr_array[16] = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
- static int hdr_count = 0;
-
- if (HTTP_MESSAGE_REQ_LINE == msg_type || HTTP_MESSAGE_REQ_HEADER == msg_type || HTTP_MESSAGE_REQ_BODY == msg_type)
- {
- EXPECT_EQ(-1, http_message_header_next(msg, &res_hdr_array[0]));
- }
-
- expect_hdr_array[0].key.str = (char *)"Server";
- expect_hdr_array[0].key.str_len = strlen("Server");
- expect_hdr_array[0].val.str = (char *)"SimpleHTTP/0.6 Python/2.7.5";
- expect_hdr_array[0].val.str_len = strlen("SimpleHTTP/0.6 Python/2.7.5");
-
- expect_hdr_array[1].key.str = (char *)"Date";
- expect_hdr_array[1].key.str_len = strlen("Date");
- expect_hdr_array[1].val.str = (char *)"Thu, 30 Nov 2023 08:42:24 GMT";
- expect_hdr_array[1].val.str_len = strlen("Thu, 30 Nov 2023 08:42:24 GMT");
-
- expect_hdr_array[2].key.str = (char *)"Content-type";
- expect_hdr_array[2].key.str_len = strlen("Content-type");
- expect_hdr_array[2].val.str = (char *)"text/html";
- expect_hdr_array[2].val.str_len = strlen("text/html");
-
- expect_hdr_array[3].key.str = (char *)"Content-Length";
- expect_hdr_array[3].key.str_len = strlen("Content-Length");
- expect_hdr_array[3].val.str = (char *)"144";
- expect_hdr_array[3].val.str_len = strlen("144");
-
- expect_hdr_array[4].key.str = (char *)"Last-Modified";
- expect_hdr_array[4].key.str_len = strlen("Last-Modified");
- expect_hdr_array[4].val.str = (char *)"Thu, 30 Nov 2023 08:38:54 GMT";
- expect_hdr_array[4].val.str_len = strlen("Thu, 30 Nov 2023 08:38:54 GMT");
-
- if (HTTP_MESSAGE_RES_HEADER == msg_type)
- {
- while (0 == http_message_header_next(msg, &res_hdr_array[hdr_count]))
- {
- ret = hgut_compare_header(&expect_hdr_array[hdr_count], &res_hdr_array[hdr_count]);
- if (0 != ret)
- {
- fprintf(stderr, "header value is diff! expect:%.*s, but actual:%.*s\n",
- expect_hdr_array[hdr_count].key.str_len,
- expect_hdr_array[hdr_count].key.str,
- res_hdr_array[hdr_count].key.str_len,
- res_hdr_array[hdr_count].key.str);
- PRINT_TEST_RESULT(ret);
- }
- hdr_count++;
- }
-
- hdr_count = 0;
- http_message_reset_header_iter(msg);
- // retry after reset iter
-
- while (0 == http_message_header_next(msg, &res_hdr_array[hdr_count]))
- {
- ret = hgut_compare_header(&expect_hdr_array[hdr_count], &res_hdr_array[hdr_count]);
- if (0 != ret)
- {
- fprintf(stderr, "after reset iter, header value is diff! expect:%.*s, but actual:%.*s\n",
- expect_hdr_array[hdr_count].key.str_len,
- expect_hdr_array[hdr_count].key.str,
- res_hdr_array[hdr_count].key.str_len,
- res_hdr_array[hdr_count].key.str);
- PRINT_TEST_RESULT(ret);
- }
- hdr_count++;
- }
-
- ret = hdr_count == 5 ? 0 : -1;
- PRINT_TEST_RESULT(ret);
- }
-
- return 0;
-}
-
-
-extern "C" int ut_get_raw_body(struct session *sess, int topic_id, const void *data, void *cb_arg)
-{
- int ret;
- struct hstring expect_body = {0};
- struct hstring get_body = {0};
- struct http_message *msg = (struct http_message *)data;
- enum http_message_type msg_type = http_message_type(msg);
- static int hdr_count = 0;
-
- /*
- Raw body is html, including \r\n, is not easy to copy, so uses md5sum validation
- */
- expect_body.str = (char *)"3e11876cd3a234541ae37d833c088a76";
- expect_body.str_len = strlen(expect_body.str);
-
- if (HTTP_MESSAGE_REQ_LINE == msg_type || HTTP_MESSAGE_REQ_HEADER == msg_type || HTTP_MESSAGE_RES_LINE == msg_type || HTTP_MESSAGE_RES_HEADER == msg_type)
- {
- EXPECT_EQ(-1, http_message_get_raw_body(msg, &get_body));
- }
-
- if(HTTP_MESSAGE_RES_BODY == msg_type)
- {
- EXPECT_EQ(0, http_message_get_raw_body(msg, &get_body));
- char md5_result_string[33];
- MESA_MD5_sum_str((unsigned char *)get_body.str, (unsigned int)get_body.str_len, md5_result_string);
- ret = strcmp(expect_body.str, md5_result_string);
- PRINT_TEST_RESULT(ret);
- }
-
- return 0;
-}
-
-TEST(HTTP_DECODER_UNIT, GET_REQ_LINE)
-{
- // go https://www.bejson.com to format JSON
- const char *test_json = "[{\"__X_HTTP_TUPLE4\":\"192.168.38.73.50806>192.168.40.137.80\"},{\"__X_HTTP_TRANSACTION\":\"request\",\"__X_HTTP_TRANSACTION_SEQ\":0,\"method\":\"GET\",\"uri\":\"/test_req_line/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\"}]";
- struct fake_stellar *fst = hdgt_create();
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- EXPECT_EQ(0, hdgt_data_source_init_by_json_text(fst, test_json));
- EXPECT_EQ(0, hdgt_under_test_module_init(fst, http_decoder_init, http_decoder_entry));
- EXPECT_EQ(0, hdgt_test_plug_init(fst, http_decoder_test_init, ut_get_req_line_entry));
- EXPECT_EXIT(hdgt_main_loop(fst), testing::ExitedWithCode(200), UNIT_TEST_SUCC_SSTRING);
-}
-
-TEST(HTTP_DECODER_UNIT, GET_URL)
-{
- // go https://www.bejson.com to format JSON
- const char *test_json = "[{\"__X_HTTP_TUPLE4\":\"192.168.38.73.50806>192.168.40.137.80\"},{\"__X_HTTP_TRANSACTION\":\"request\",\"__X_HTTP_TRANSACTION_SEQ\":0,\"method\":\"GET\",\"uri\":\"/test_url/index.html\",\"req_version\":\"1.1\",\"major_version\":1,\"minor_version\":1,\"Host\":\"get_url_test.com\",\"User-Agent\":\"curl/7.79.1\",\"Accept\":\"*/*\",\"__X_HTTP_URL\":\"192.168.40.137/index.html\"}]";
- struct fake_stellar *fst = hdgt_create();
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- EXPECT_EQ(0, hdgt_data_source_init_by_json_text(fst, test_json));
- EXPECT_EQ(0, hdgt_under_test_module_init(fst, http_decoder_init, http_decoder_entry));
- EXPECT_EQ(0, hdgt_test_plug_init(fst, http_decoder_test_init, ut_get_url_entry));
- EXPECT_EXIT(hdgt_main_loop(fst), testing::ExitedWithCode(200), UNIT_TEST_SUCC_SSTRING);
-}
-
-TEST(HTTP_DECODER_UNIT, GET_RES_LINE)
-{
- // go https://www.bejson.com to format JSON
- const char *test_json = "[{\"__X_HTTP_TUPLE4\":\"192.168.38.73.50806>192.168.40.137.80\"},{\"__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_TRANSACTION\":\"response\",\"__X_HTTP_TRANSACTION_SEQ\":0,\"res_version\":\"1.1\",\"res_status\":\"OK\",\"major_version\":1,\"minor_version\":1,\"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\":\"144\",\"Last-Modified\":\"Thu, 30 Nov 2023 08:38:54 GMT\",\"__X_HTTP_PAYLOAD_MD5\":\"3e11876cd3a234541ae37d833c088a76\",\"__X_HTTP_PAYLOAD\":\"PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KPHRpdGxlPlBhZ2UgVGl0bGU8L3RpdGxlPgo8L2hlYWQ+Cjxib2R5PgoKPGgxPlRoaXMgaXMgYSBIZWFkaW5nPC9oMT4KPHA+VGhpcyBpcyBhIHBhcmFncmFwaC48L3A+Cgo8L2JvZHk+CjwvaHRtbD4K\"}]";
- struct fake_stellar *fst = hdgt_create();
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- EXPECT_EQ(0, hdgt_data_source_init_by_json_text(fst, test_json));
- EXPECT_EQ(0, hdgt_under_test_module_init(fst, http_decoder_init, http_decoder_entry));
- EXPECT_EQ(0, hdgt_test_plug_init(fst, http_decoder_test_init, ut_get_res_line_entry));
- EXPECT_EXIT(hdgt_main_loop(fst), testing::ExitedWithCode(200), UNIT_TEST_SUCC_SSTRING);
-}
-
-TEST(HTTP_DECODER_UNIT, GET_REQ_HEADER)
-{
- // go https://www.bejson.com to format JSON
- const char *test_json = "[{\"__X_HTTP_TUPLE4\":\"192.168.38.73.50806>192.168.40.137.80\"},{\"__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_TRANSACTION\":\"response\",\"__X_HTTP_TRANSACTION_SEQ\":0,\"res_version\":\"1.1\",\"res_status\":\"OK\",\"major_version\":1,\"minor_version\":1,\"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\":\"144\",\"Last-Modified\":\"Thu, 30 Nov 2023 08:38:54 GMT\",\"__X_HTTP_PAYLOAD_MD5\":\"3e11876cd3a234541ae37d833c088a76\",\"__X_HTTP_PAYLOAD\":\"PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KPHRpdGxlPlBhZ2UgVGl0bGU8L3RpdGxlPgo8L2hlYWQ+Cjxib2R5PgoKPGgxPlRoaXMgaXMgYSBIZWFkaW5nPC9oMT4KPHA+VGhpcyBpcyBhIHBhcmFncmFwaC48L3A+Cgo8L2JvZHk+CjwvaHRtbD4K\"}]";
- struct fake_stellar *fst = hdgt_create();
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- EXPECT_EQ(0, hdgt_data_source_init_by_json_text(fst, test_json));
- EXPECT_EQ(0, hdgt_under_test_module_init(fst, http_decoder_init, http_decoder_entry));
- EXPECT_EQ(0, hdgt_test_plug_init(fst, http_decoder_test_init, ut_get_req_header));
- EXPECT_EXIT(hdgt_main_loop(fst), testing::ExitedWithCode(200), UNIT_TEST_SUCC_SSTRING);
-}
-
-TEST(HTTP_DECODER_UNIT, GET_RES_HEADER)
-{
- // go https://www.bejson.com to format JSON
- const char *test_json = "[{\"__X_HTTP_TUPLE4\":\"192.168.38.73.50806>192.168.40.137.80\"},{\"__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_TRANSACTION\":\"response\",\"__X_HTTP_TRANSACTION_SEQ\":0,\"res_version\":\"1.1\",\"res_status\":\"OK\",\"major_version\":1,\"minor_version\":1,\"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\":\"144\",\"Last-Modified\":\"Thu, 30 Nov 2023 08:38:54 GMT\",\"__X_HTTP_PAYLOAD_MD5\":\"3e11876cd3a234541ae37d833c088a76\",\"__X_HTTP_PAYLOAD\":\"PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KPHRpdGxlPlBhZ2UgVGl0bGU8L3RpdGxlPgo8L2hlYWQ+Cjxib2R5PgoKPGgxPlRoaXMgaXMgYSBIZWFkaW5nPC9oMT4KPHA+VGhpcyBpcyBhIHBhcmFncmFwaC48L3A+Cgo8L2JvZHk+CjwvaHRtbD4K\"}]";
- struct fake_stellar *fst = hdgt_create();
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- EXPECT_EQ(0, hdgt_data_source_init_by_json_text(fst, test_json));
- EXPECT_EQ(0, hdgt_under_test_module_init(fst, http_decoder_init, http_decoder_entry));
- EXPECT_EQ(0, hdgt_test_plug_init(fst, http_decoder_test_init, ut_get_res_header));
- EXPECT_EXIT(hdgt_main_loop(fst), testing::ExitedWithCode(200), UNIT_TEST_SUCC_SSTRING);
-}
-
-TEST(HTTP_DECODER_UNIT, ITERATE_REQ_HEADERS)
-{
- // go https://www.bejson.com to format JSON
- const char *test_json = "[{\"__X_HTTP_TUPLE4\":\"192.168.38.73.50806>192.168.40.137.80\"},{\"__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_TRANSACTION\":\"response\",\"__X_HTTP_TRANSACTION_SEQ\":0,\"res_version\":\"1.1\",\"res_status\":\"OK\",\"major_version\":1,\"minor_version\":1,\"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\":\"144\",\"Last-Modified\":\"Thu, 30 Nov 2023 08:38:54 GMT\",\"__X_HTTP_PAYLOAD_MD5\":\"3e11876cd3a234541ae37d833c088a76\",\"__X_HTTP_PAYLOAD\":\"PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KPHRpdGxlPlBhZ2UgVGl0bGU8L3RpdGxlPgo8L2hlYWQ+Cjxib2R5PgoKPGgxPlRoaXMgaXMgYSBIZWFkaW5nPC9oMT4KPHA+VGhpcyBpcyBhIHBhcmFncmFwaC48L3A+Cgo8L2JvZHk+CjwvaHRtbD4K\"}]";
- struct fake_stellar *fst = hdgt_create();
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- EXPECT_EQ(0, hdgt_data_source_init_by_json_text(fst, test_json));
- EXPECT_EQ(0, hdgt_under_test_module_init(fst, http_decoder_init, http_decoder_entry));
- EXPECT_EQ(0, hdgt_test_plug_init(fst, http_decoder_test_init, ut_iterate_req_headers));
- // hdgt_main_loop(fst);
- EXPECT_EXIT(hdgt_main_loop(fst), testing::ExitedWithCode(200), UNIT_TEST_SUCC_SSTRING);
-}
-
-TEST(HTTP_DECODER_UNIT, ITERATE_RES_HEADERS)
-{
- // go https://www.bejson.com to format JSON
- const char *test_json = "[{\"__X_HTTP_TUPLE4\":\"192.168.38.73.50806>192.168.40.137.80\"},{\"__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_TRANSACTION\":\"response\",\"__X_HTTP_TRANSACTION_SEQ\":0,\"res_version\":\"1.1\",\"res_status\":\"OK\",\"major_version\":1,\"minor_version\":1,\"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\":\"144\",\"Last-Modified\":\"Thu, 30 Nov 2023 08:38:54 GMT\",\"__X_HTTP_PAYLOAD_MD5\":\"3e11876cd3a234541ae37d833c088a76\",\"__X_HTTP_PAYLOAD\":\"PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KPHRpdGxlPlBhZ2UgVGl0bGU8L3RpdGxlPgo8L2hlYWQ+Cjxib2R5PgoKPGgxPlRoaXMgaXMgYSBIZWFkaW5nPC9oMT4KPHA+VGhpcyBpcyBhIHBhcmFncmFwaC48L3A+Cgo8L2JvZHk+CjwvaHRtbD4K\"}]";
- struct fake_stellar *fst = hdgt_create();
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- EXPECT_EQ(0, hdgt_data_source_init_by_json_text(fst, test_json));
- EXPECT_EQ(0, hdgt_under_test_module_init(fst, http_decoder_init, http_decoder_entry));
- EXPECT_EQ(0, hdgt_test_plug_init(fst, http_decoder_test_init, ut_iterate_res_headers));
- // hdgt_main_loop(fst);
- EXPECT_EXIT(hdgt_main_loop(fst), testing::ExitedWithCode(200), UNIT_TEST_SUCC_SSTRING);
-}
-
-TEST(HTTP_DECODER_UNIT, GET_RAW_BODY)
-{
- // go https://www.bejson.com to format JSON
- const char *test_json = "[{\"__X_HTTP_TUPLE4\":\"192.168.38.73.50806>192.168.40.137.80\"},{\"__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_TRANSACTION\":\"response\",\"__X_HTTP_TRANSACTION_SEQ\":0,\"res_version\":\"1.1\",\"res_status\":\"OK\",\"major_version\":1,\"minor_version\":1,\"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\":\"144\",\"Last-Modified\":\"Thu, 30 Nov 2023 08:38:54 GMT\",\"__X_HTTP_PAYLOAD_MD5\":\"3e11876cd3a234541ae37d833c088a76\",\"__X_HTTP_PAYLOAD\":\"PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KPHRpdGxlPlBhZ2UgVGl0bGU8L3RpdGxlPgo8L2hlYWQ+Cjxib2R5PgoKPGgxPlRoaXMgaXMgYSBIZWFkaW5nPC9oMT4KPHA+VGhpcyBpcyBhIHBhcmFncmFwaC48L3A+Cgo8L2JvZHk+CjwvaHRtbD4K\"}]";
- struct fake_stellar *fst = hdgt_create();
- hdgt_set_data_source_type(fst, DATA_SOURCE_JSON);
- EXPECT_EQ(0, hdgt_data_source_init_by_json_text(fst, test_json));
- EXPECT_EQ(0, hdgt_under_test_module_init(fst, http_decoder_init, http_decoder_entry));
- EXPECT_EQ(0, hdgt_test_plug_init(fst, http_decoder_test_init, ut_get_raw_body));
- // hdgt_main_loop(fst);
- EXPECT_EXIT(hdgt_main_loop(fst), testing::ExitedWithCode(200), UNIT_TEST_SUCC_SSTRING);
-}
-
-int main(int argc, char **argv)
-{
- ::testing::InitGoogleTest(&argc, argv);
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- int ret = RUN_ALL_TESTS();
- return ret;
-} \ No newline at end of file
diff --git a/test/http_pcap/http_pipeline_C2S.pcap b/test/http_pcap/http_pipeline_C2S.pcap
new file mode 100644
index 0000000..360e0ed
--- /dev/null
+++ b/test/http_pcap/http_pipeline_C2S.pcap
Binary files differ
diff --git a/test/http_pcap/http_pipeline_S2C.pcap b/test/http_pcap/http_pipeline_S2C.pcap
new file mode 100644
index 0000000..a7d473f
--- /dev/null
+++ b/test/http_pcap/http_pipeline_S2C.pcap
Binary files differ
diff --git a/test/http_pcap/http_post.pcap b/test/http_pcap/http_post.pcap
new file mode 100644
index 0000000..cb5843e
--- /dev/null
+++ b/test/http_pcap/http_post.pcap
Binary files differ
diff --git a/test/http_pcap/http_post_c2s.pcap b/test/http_pcap/http_post_c2s.pcap
new file mode 100644
index 0000000..973a5fb
--- /dev/null
+++ b/test/http_pcap/http_post_c2s.pcap
Binary files differ
diff --git a/test/http_pcap/http_post_s2c.pcap b/test/http_pcap/http_post_s2c.pcap
new file mode 100644
index 0000000..0be23a8
--- /dev/null
+++ b/test/http_pcap/http_post_s2c.pcap
Binary files differ
diff --git a/test/test_result_json/http_get_malformed.json b/test/test_result_json/http_get_malformed.json
index dacb51f..3a04d38 100644
--- a/test/test_result_json/http_get_malformed.json
+++ b/test/test_result_json/http_get_malformed.json
@@ -1,28 +1,2 @@
[
- {
- "__X_HTTP_TUPLE4": "192.168.4.2.36598>108.61.176.217.80"
- },
- {
- "__X_HTTP_TRANSACTION": "request",
- "__X_HTTP_TRANSACTION_SEQ": 0,
- "method": "GET",
- "uri": "/",
- "req_version": "1.1",
- "major_version": 1,
- "minor_version": 1
- },
- {
- "__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": "FakeNet/1.3",
- "Date": "Wed, 12 Sep 2018 19:45:55 GMT",
- "Content-Type": "text/html",
- "Content-Length": "1547",
- "__X_HTTP_PAYLOAD_MD5": "1807c0ebdda65240e058706d9626d2af"
- }
] \ No newline at end of file
diff --git a/test/test_result_json/http_msg_type_state.json b/test/test_result_json/http_msg_type_state.json
new file mode 100644
index 0000000..8fae48a
--- /dev/null
+++ b/test/test_result_json/http_msg_type_state.json
@@ -0,0 +1,18 @@
+[
+ {
+ "msg_0": "HTTP_TRANSACTION_NEW_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",
+ "msg_5": "HTTP_MESSAGE_REQ_BODY_END"
+ },
+ {
+ "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_END",
+ "msg_11": "HTTP_TRANSACTION_FREE_transaction_0"
+ }
+] \ No newline at end of file
diff --git a/test/test_result_json/http_msg_type_state_c2s.json b/test/test_result_json/http_msg_type_state_c2s.json
new file mode 100644
index 0000000..05ed4f1
--- /dev/null
+++ b/test/test_result_json/http_msg_type_state_c2s.json
@@ -0,0 +1,12 @@
+[
+ {
+ "msg_0": "HTTP_TRANSACTION_NEW_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",
+ "msg_5": "HTTP_MESSAGE_REQ_BODY_END",
+ "msg_6": "HTTP_TRANSACTION_FREE_transaction_0"
+ },
+ {}
+] \ No newline at end of file
diff --git a/test/test_result_json/http_msg_type_state_pipeline.json b/test/test_result_json/http_msg_type_state_pipeline.json
new file mode 100644
index 0000000..5384420
--- /dev/null
+++ b/test/test_result_json/http_msg_type_state_pipeline.json
@@ -0,0 +1,60 @@
+[
+ {
+ "msg_0": "HTTP_TRANSACTION_NEW_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_NEW_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_NEW_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_NEW_transaction_3",
+ "msg_25": "HTTP_MESSAGE_REQ_LINE",
+ "msg_26": "HTTP_MESSAGE_REQ_HEADER",
+ "msg_27": "HTTP_MESSAGE_REQ_HEADER_END"
+ },
+ {
+ "msg_4": "HTTP_MESSAGE_RES_LINE",
+ "msg_5": "HTTP_MESSAGE_RES_HEADER",
+ "msg_6": "HTTP_MESSAGE_RES_HEADER_END",
+ "msg_7": "HTTP_TRANSACTION_FREE_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_FREE_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_FREE_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",
+ "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_END",
+ "msg_53": "HTTP_TRANSACTION_FREE_transaction_3"
+ }
+] \ No newline at end of file
diff --git a/test/test_result_json/http_msg_type_state_s2c.json b/test/test_result_json/http_msg_type_state_s2c.json
new file mode 100644
index 0000000..8a05b49
--- /dev/null
+++ b/test/test_result_json/http_msg_type_state_s2c.json
@@ -0,0 +1,12 @@
+[
+ {},
+ {
+ "msg_0": "HTTP_TRANSACTION_NEW_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",
+ "msg_5": "HTTP_MESSAGE_RES_BODY_END",
+ "msg_6": "HTTP_TRANSACTION_FREE_transaction_0"
+ }
+] \ No newline at end of file
diff --git a/test_based_on_stellar/CMakeLists.txt b/test_based_on_stellar/CMakeLists.txt
index 70663bf..088bfc4 100644
--- a/test_based_on_stellar/CMakeLists.txt
+++ b/test_based_on_stellar/CMakeLists.txt
@@ -32,24 +32,27 @@ target_link_libraries(plugin_test_main gtest cjson-static sapp_devel pthread pca
add_test(NAME STELLAR_INSTALL_TEST_MAIN COMMAND sh -c "cp ${CMAKE_CURRENT_BINARY_DIR}/${TEST_MAIN} ${TEST_RUN_DIR}/${TEST_MAIN}")
add_test(NAME STELLAR_COPY_SPEC COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/stellar_plugin/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/spec.toml ${TEST_RUN_DIR}/stellar_plugin/spec.toml")
add_test(NAME STELLAR_COPY_CONFLIST COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plug/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/conflist.inf ${TEST_RUN_DIR}/plug/conflist.inf")
-add_test(NAME STELLAR_COPY_LOADER_INF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plug/stellar_on_sapp && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/start_loader.inf ${TEST_RUN_DIR}/plug/stellar_on_sapp/start_loader.inf")
+add_test(NAME STELLAR_COPY_START_LOADER_INF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plug/stellar_on_sapp && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/start_loader.inf ${TEST_RUN_DIR}/plug/stellar_on_sapp/start_loader.inf")
+add_test(NAME STELLAR_COPY_DEFER_LOADER_INF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/plug/stellar_on_sapp && cp ${CMAKE_CURRENT_SOURCE_DIR}/env/defer_loader.inf ${TEST_RUN_DIR}/plug/stellar_on_sapp/defer_loader.inf")
add_test(NAME STELLAR_COPY_HTTP_DECODER_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/etc/http && cp ${PROJECT_SOURCE_DIR}/conf/http_decoder.toml ${TEST_RUN_DIR}/etc/http/")
+add_test(NAME STELLAR_COPY_HTTP_GTEST_ENTRY_CONF COMMAND sh -c "mkdir -p ${TEST_RUN_DIR}/etc/http && cp ${PROJECT_SOURCE_DIR}/conf/gtest_entry.toml ${TEST_RUN_DIR}/etc/http/")
# update config files
add_test(NAME STELLAR_UPDATE_SAPP_LOG_LEVEL COMMAND bash -c "sed -i 's/sapp_log.fatal/sapp_log.info/' ${TEST_RUN_DIR}/etc/sapp_log.conf")
add_test(NAME STELLAR_UPDATE_SAPP_SYN_MODE COMMAND bash -c "sed -i 's/syn_mandatory=1/syn_mandatory=0/' ${TEST_RUN_DIR}/etc/sapp.toml")
-# add_test(NAME UPDATE_SAPP_REORDER COMMAND bash -c "sed -i 's/reorder_pkt_max=32/reorder_pkt_max=5/' ${TEST_RUN_DIR}/etc/sapp.toml")
+add_test(NAME STELLAR_ENABLE_SAPP_MONITOR COMMAND bash -c "sed -i 's/monitor_thread_enabled=0/monitor_thread_enabled=1/' ${TEST_RUN_DIR}/etc/sapp.toml")
+add_test(NAME 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")
# update plugin to be tested
-add_test(NAME STELLAR_ON_SAPP_SO COMMAND sh -c "cp ${STELLAR_ON_SAPP_LIB_DIR}/stellar_on_sapp.so ${TEST_RUN_DIR}/plug/stellar_on_sapp/stellar_on_sapp.so")
+# add_test(NAME STELLAR_ON_SAPP_SO COMMAND sh -c "cp ${STELLAR_ON_SAPP_LIB_DIR}/stellar_on_sapp.so ${TEST_RUN_DIR}/plug/stellar_on_sapp/stellar_on_sapp.so")
+add_test(NAME STELLAR_ON_SAPP_SO COMMAND sh -c "rpm -ql stellar-on-sapp | grep stellar_on_sapp.so | xargs -i cp -f {} ${TEST_RUN_DIR}/plug/stellar_on_sapp/stellar_on_sapp.so")
add_test(NAME STELLAR_HTTP_DECODER_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/src/${DECODER_NAME}.so ${TEST_RUN_DIR}/stellar_plugin/${DECODER_NAME}.so")
add_test(NAME STELLAR_HTTP_DECODER_GTEST_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/${DECODER_NAME}_test.so ${TEST_RUN_DIR}/stellar_plugin/${DECODER_NAME}_test.so")
-set_tests_properties(STELLAR_INSTALL_TEST_MAIN STELLAR_COPY_SPEC STELLAR_COPY_CONFLIST STELLAR_COPY_LOADER_INF
- STELLAR_ON_SAPP_SO STELLAR_HTTP_DECODER_SO STELLAR_HTTP_DECODER_GTEST_SO STELLAR_UPDATE_SAPP_LOG_LEVEL
+set_tests_properties(STELLAR_INSTALL_TEST_MAIN STELLAR_COPY_SPEC STELLAR_COPY_CONFLIST STELLAR_COPY_START_LOADER_INF STELLAR_COPY_DEFER_LOADER_INF STELLAR_COPY_HTTP_DECODER_CONF STELLAR_COPY_HTTP_GTEST_ENTRY_CONF
+ STELLAR_ON_SAPP_SO STELLAR_HTTP_DECODER_SO STELLAR_HTTP_DECODER_GTEST_SO STELLAR_UPDATE_SAPP_LOG_LEVEL STELLAR_UPDATE_SAPP_SYN_MODE STELLAR_ENABLE_SAPP_MONITOR UPDATE_GTEST_PLUG_ENTRY
PROPERTIES FIXTURES_SETUP TestFixture)
-
set(TEST_JSON_DIR ${PROJECT_SOURCE_DIR}/test/test_result_json)
set(TEST_PCAP_DIR ${PROJECT_SOURCE_DIR}/test/http_pcap)
@@ -154,4 +157,24 @@ set_tests_properties(STELLAR_HTTP_GET_SINGLE_TRANS_TEST
STELLAR_HTTP_TRANS_PIPELINE_TEST
STELLAR_HTTP_HEADER_TRUNCATED_IN_KV_TEST
STELLAR_HTTP_HEADER_TRUNCATED_AFTER_KV_TEST
- PROPERTIES FIXTURES_REQUIRED TestFixture) \ No newline at end of file
+ PROPERTIES FIXTURES_REQUIRED TestFixture)
+
+add_test(NAME 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")
+
+set_tests_properties(UPDATE_STATE_PLUG_ENTRY
+ PROPERTIES FIXTURES_SETUP TestState)
+
+add_test(NAME STELLAR_HTTP_MSG_TYPE_STATE_TEST COMMAND ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state.json
+ -r ${TEST_PCAP_DIR}/http_post.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
+add_test(NAME STELLAR_HTTP_MSG_TYPE_STATE_C2S_TEST COMMAND ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state_c2s.json
+ -r ${TEST_PCAP_DIR}/http_post_c2s.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
+add_test(NAME STELLAR_HTTP_MSG_TYPE_STATE_S2C_TEST COMMAND ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state_s2c.json
+ -r ${TEST_PCAP_DIR}/http_post_s2c.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
+add_test(NAME STELLAR_HTTP_MSG_TYPE_STATE_PIPELINE_TEST COMMAND ./${TEST_MAIN} ${TEST_JSON_DIR}/http_msg_type_state_pipeline.json
+ -r ${TEST_PCAP_DIR}/http_get_multi_trans.pcap WORKING_DIRECTORY ${TEST_RUN_DIR})
+
+set_tests_properties(STELLAR_HTTP_MSG_TYPE_STATE_TEST
+ STELLAR_HTTP_MSG_TYPE_STATE_C2S_TEST
+ STELLAR_HTTP_MSG_TYPE_STATE_S2C_TEST
+ STELLAR_HTTP_MSG_TYPE_STATE_PIPELINE_TEST
+ PROPERTIES FIXTURES_REQUIRED TestState) \ No newline at end of file
diff --git a/test_based_on_stellar/env/conflist.inf b/test_based_on_stellar/env/conflist.inf
index 1b70e78..5449f7d 100644
--- a/test_based_on_stellar/env/conflist.inf
+++ b/test_based_on_stellar/env/conflist.inf
@@ -4,3 +4,4 @@
[protocol]
[business]
+./plug/stellar_on_sapp/defer_loader.inf
diff --git a/test_based_on_stellar/env/defer_loader.inf b/test_based_on_stellar/env/defer_loader.inf
new file mode 100644
index 0000000..f31e043
--- /dev/null
+++ b/test_based_on_stellar/env/defer_loader.inf
@@ -0,0 +1,14 @@
+[PLUGINFO]
+PLUGNAME=stellar_defer_loader
+SO_PATH=./plug/stellar_on_sapp/stellar_on_sapp.so
+INIT_FUNC=STELLAR_DEFER_LOADER_INIT
+DESTROY_FUNC=STELLAR_DEFER_LOADER_EXIT
+
+[TCP_ALL]
+FUNC_FLAG=ALL
+FUNC_NAME=stellar_on_sapp_defer_entry
+
+[UDP]
+FUNC_FLAG=ALL
+FUNC_NAME=stellar_on_sapp_defer_entry
+
diff --git a/test_based_on_stellar/env/start_loader.inf b/test_based_on_stellar/env/start_loader.inf
index 545c4f7..ce1dc1b 100644
--- a/test_based_on_stellar/env/start_loader.inf
+++ b/test_based_on_stellar/env/start_loader.inf
@@ -8,14 +8,23 @@ DESTROY_FUNC=STELLAR_START_LOADER_EXIT
FUNC_FLAG=ALL
FUNC_NAME=stellar_on_sapp_tcpall_entry
-#[TCP]
-#FUNC_FLAG=ALL
-#FUNC_NAME=stellar_on_sapp_tcp_entry
+[TCP]
+FUNC_FLAG=ALL
+FUNC_NAME=stellar_on_sapp_tcp_entry
-#[TCP]
-#FUNC_FLAG=ALL
-#FUNC_NAME=stellar_on_sapp_detach_check_entry
[UDP]
FUNC_FLAG=ALL
FUNC_NAME=stellar_on_sapp_udp_entry
+
+[IP]
+FUNC_FLAG=ALL
+FUNC_NAME=stellar_on_sapp_ip4_entry
+
+[IPV6]
+FUNC_FLAG=ALL
+FUNC_NAME=stellar_on_sapp_ip6_entry
+
+[POLLING]
+FUNC_FLAG=ALL
+FUNC_NAME=stellar_on_sapp_polling_entry
diff --git a/test_based_on_stellar/plugin_test_main.cpp b/test_based_on_stellar/plugin_test_main.cpp
index 8ff6ef7..c26a5d5 100644
--- a/test_based_on_stellar/plugin_test_main.cpp
+++ b/test_based_on_stellar/plugin_test_main.cpp
@@ -15,6 +15,10 @@ cJSON *g_test_result_root = NULL;
cJSON *g_load_result_root = NULL;
int g_ret = 0;
+extern "C" int get_current_worker_thread_id(void)
+{
+ return 0;
+}
extern "C" int libsapp_setup_env(int argc, char *argv[]);
@@ -102,12 +106,19 @@ TEST(PROTOCOL, compare_result_json)
result_json_str = cJSON_Print(t_test);
printf("TEST Diff:\n%s\n", result_json_str);
free(result_json_str);
- ASSERT_EQ(1, ret);
+ goto fail;
}
t_load = t_load->next;
t_test = t_test->next;
}
}
+ cJSON_Delete(g_load_result_root);
+ cJSON_Delete(g_test_result_root);
+ return;
+fail:
+ cJSON_Delete(g_load_result_root);
+ cJSON_Delete(g_test_result_root);
+ return;
}
void run_gtest_main()
diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt
index 1f15068..2020e8c 100644
--- a/vendor/CMakeLists.txt
+++ b/vendor/CMakeLists.txt
@@ -22,9 +22,10 @@ add_dependencies(gmock googletest)
set_property(TARGET gmock PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libgmock.a)
set_property(TARGET gmock PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
-#llhttp-9.1.2
+#llhttp-9.1.3
ExternalProject_Add(llhttp PREFIX llhttp
URL ${CMAKE_CURRENT_SOURCE_DIR}/llhttp-release-v9.1.3.tar.gz
+ URL_MD5 f15cd242f55a38b30d3031b560d2c8ef
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${VENDOR_BUILD} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_C_FLAGS="-fPIC")
file(MAKE_DIRECTORY ${VENDOR_BUILD}/include)
@@ -35,14 +36,15 @@ add_dependencies(llhttp-static llhttp)
set_property(TARGET llhttp-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${VENDOR_BUILD}/include)
set_property(TARGET llhttp-static PROPERTY IMPORTED_LOCATION ${VENDOR_BUILD}/lib64/libllhttp.a)
+
#libcjson-1.7.17
ExternalProject_Add(cjson PREFIX cjson
-URL ${CMAKE_CURRENT_SOURCE_DIR}/libcjson_v1.7.17.tar.gz
-URL_MD5 4b2ab12cf065c079004aa44495ade04a
-CONFIGURE_COMMAND ""
-BUILD_COMMAND make
-INSTALL_COMMAND make install
-BUILD_IN_SOURCE 1)
+ URL ${CMAKE_CURRENT_SOURCE_DIR}/libcjson_v1.7.17.tar.gz
+ URL_MD5 4b2ab12cf065c079004aa44495ade04a
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND make
+ INSTALL_COMMAND make install
+ BUILD_IN_SOURCE 1)
ExternalProject_Get_Property(cjson INSTALL_DIR)
file(MAKE_DIRECTORY ${VENDOR_BUILD}/include/cjson)
@@ -51,3 +53,4 @@ add_library(cjson-static STATIC IMPORTED GLOBAL)
add_dependencies(cjson-static cjson)
set_property(TARGET cjson-static PROPERTY IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/vendor/cjson/src/cjson/libcjson.a)
set_property(TARGET cjson-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${VENDOR_BUILD}/include/cjson)
+