diff options
37 files changed, 1488 insertions, 3379 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c84bfaa..129b6f6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ variables: 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/" 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/include/http_decoder.h b/include/http_decoder.h index 56c107a..99d0baf 100644 --- a/include/http_decoder.h +++ b/include/http_decoder.h @@ -58,6 +58,7 @@ struct http_response_line { }; struct http_message; +#define HTTP_DECODER_TOPIC "HTTP_DECODER_MESSAGE" enum http_message_type http_message_type(struct http_message *msg); @@ -91,7 +92,6 @@ int http_message_reset_header_iter(struct http_message *msg); int http_message_get_raw_body(struct http_message *msg, struct hstring *body); - /** * @brief If the body hasn't been compressed, return raw body * 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..f156105 --- /dev/null +++ b/src/http_decoder.cpp @@ -0,0 +1,762 @@ +/* +********************************************************************************************** +* 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 "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) +{ + 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 (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; + + 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 (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; +} +#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(struct http_message *msg) + { + if (unlikely(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 (unlikely(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 (unlikely(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 (unlikely(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 (unlikely(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 (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; + } + + 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 (unlikely(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 (unlikely(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 (unlikely(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 (unlikely(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); + } +#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..e2190d7 100644 --- a/src/http_decoder_half.c +++ b/src/http_decoder_half.cpp @@ -7,21 +7,12 @@ * 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 { @@ -205,10 +196,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 +229,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 +282,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 +320,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); } @@ -374,7 +365,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); } @@ -614,7 +605,7 @@ static int on_body(llhttp_t *http, const char *at, size_t length) static void http_decoder_half_init(struct http_decoder_half *half, - http_event_cb *http_ev_cb, int type) + http_event_cb *http_ev_cb, enum llhttp_type type) { if (NULL == half) { @@ -653,14 +644,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->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); @@ -752,7 +741,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 +756,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; @@ -1115,7 +1104,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; diff --git a/src/http_decoder_half.h b/src/http_decoder_half.h index a2ff5f8..4e4461b 100644 --- a/src/http_decoder_half.h +++ b/src/http_decoder_half.h @@ -7,22 +7,15 @@ * 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 +52,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); @@ -111,9 +104,4 @@ int http_decoder_join_url_finally(struct http_event_context *ev_ctx, nmx_pool_t *mempool); 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 - #endif
\ No newline at end of file diff --git a/src/http_decoder_inc.h b/src/http_decoder_inc.h index 2d6a5c0..489af3e 100644 --- a/src/http_decoder_inc.h +++ b/src/http_decoder_inc.h @@ -15,29 +15,104 @@ 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" +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) #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 +{ + 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 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; 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..6744a1e 100644 --- a/src/http_decoder_string.c +++ b/src/http_decoder_string.cpp @@ -12,10 +12,7 @@ #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 +61,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 +80,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 +88,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 +135,6 @@ void http_decoder_string_cache(struct http_decoder_string *rstr) abort(); break; } - rstr->state = STRING_STATE_CACHE; } @@ -226,10 +219,8 @@ 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; } diff --git a/src/http_decoder_string.h b/src/http_decoder_string.h index f9d81dd..ef3a1cc 100644 --- a/src/http_decoder_string.h +++ b/src/http_decoder_string.h @@ -11,14 +11,8 @@ #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, @@ -87,9 +81,4 @@ enum string_state http_decoder_string_state(struct http_decoder_string *rstr); int http_decoder_string_get(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..d0f42f0 100644 --- a/src/http_decoder_table.c +++ b/src/http_decoder_table.cpp @@ -7,16 +7,10 @@ * 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 @@ -90,23 +84,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 +114,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 +123,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); @@ -409,7 +396,6 @@ int http_decoder_table_get_uri(struct http_decoder_table *table, struct hstring if (NULL == table || NULL == out) { return -1; } - return http_decoder_string_get(&table->uri, out); } @@ -418,7 +404,6 @@ int http_decoder_table_get_method(struct http_decoder_table *table, struct hstri if (NULL == table || NULL == out) { return -1; } - return http_decoder_string_get(&table->method, out); } @@ -427,7 +412,6 @@ int http_decoder_table_get_status(struct http_decoder_table *table, struct hstri if (NULL == table || NULL == out) { return -1; } - return http_decoder_string_get(&table->status, out); } @@ -436,7 +420,6 @@ int http_decoder_table_get_version(struct http_decoder_table *table, struct hstr if (NULL == table || NULL == out) { return -1; } - return http_decoder_string_get(&table->version, out); } @@ -445,7 +428,6 @@ int http_decoder_table_get_body(struct http_decoder_table *table, struct hstring if (NULL == table || NULL == out) { return -1; } - return http_decoder_string_get(&table->body, out); } @@ -485,7 +467,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; } @@ -504,7 +485,6 @@ int http_decoder_table_iter_header(struct http_decoder_table *table, hdr->key.str = NULL; hdr->key.str_len = 0; - hdr->val.str = NULL; hdr->val.str_len = 0; @@ -537,7 +517,6 @@ int http_decoder_table_header_complete(struct http_decoder_table *table) if (NULL == table) { return -1; } - return table->header_complete; } @@ -546,7 +525,6 @@ void http_decoder_table_set_header_complete(struct http_decoder_table *table) if (NULL == table) { return; } - table->header_complete = 1; } @@ -555,6 +533,5 @@ void http_decoder_table_reset_header_complete(struct http_decoder_table *table) if (NULL == table) { return; } - table->header_complete = 0; }
\ No newline at end of file diff --git a/src/http_decoder_table.h b/src/http_decoder_table.h index 906a28d..de80b9d 100644 --- a/src/http_decoder_table.h +++ b/src/http_decoder_table.h @@ -7,17 +7,9 @@ * 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" @@ -90,9 +82,4 @@ int http_decoder_table_header_complete(struct http_decoder_table *table); 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 - #endif
\ No newline at end of file diff --git a/src/http_decoder_utils.c b/src/http_decoder_utils.cpp index a5dfbe1..77d716d 100644 --- a/src/http_decoder_utils.c +++ b/src/http_decoder_utils.cpp @@ -7,19 +7,15 @@ * Copyright: (c) Since 2022 Geedge Networks, Ltd. All rights reserved. *********************************************************************************************** */ - #include <string.h> - -#include "stellar/utils.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; }
\ No newline at end of file diff --git a/src/http_decoder_utils.h b/src/http_decoder_utils.h index 9c031a3..8cda4ab 100644 --- a/src/http_decoder_utils.h +++ b/src/http_decoder_utils.h @@ -7,20 +7,12 @@ * 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); /****************************************************************************** @@ -58,9 +50,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..478995c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,170 +5,28 @@ 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) +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_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) +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(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}) - -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}) - -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") +set_tests_properties(INSTALL_PERF_TEST_MAIN + PROPERTIES FIXTURES_REQUIRED TestFixture)
\ 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..a135081 100644 --- a/test/http_decoder_gtest.cpp +++ b/test/http_decoder_gtest.cpp @@ -28,8 +28,8 @@ extern "C" #include "stellar/session_mq.h" #include "md5.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); + static on_msg_cb_func *g_entry_fun = http_decoder_test_entry; } #endif @@ -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; @@ -224,7 +225,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 +254,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,22 +288,21 @@ 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) +extern "C" void http_decoder_test_entry(struct session *sess, int topic_id, const void *raw_msg, void *no_use_ctx, void *plugin_env) +// extern "C" int http_decoder_test_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 body = {0}; - struct http_message *msg = (struct http_message *)data; + struct http_message *msg = (struct http_message *)raw_msg; enum http_message_type msg_type = http_message_type(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) @@ -317,7 +319,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 +339,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,22 +363,21 @@ 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); } @@ -384,29 +385,26 @@ void http_decoder_test_exdata_free(struct session *sess, int idx, void *ex_ptr, 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; } + 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); - session_mq_subscribe_topic(st, g_topic_id, g_entry_fun, NULL); - // printf("http_decoder_test_init OK!\n"); - - return NULL; + return (void *)strdup("http_decoder_test_ctx"); } extern "C" void http_decoder_test_exit(void *test_ctx) @@ -415,11 +413,10 @@ extern "C" void http_decoder_test_exit(void *test_ctx) { FREE(test_ctx); } - printf("http_decoder_test_exit OK!\n"); } -extern "C" void http_decoder_plug_set_entry_fuc(HTTP_DECODER_PLUG_ENTRY_FUN_T entry_fun) +extern "C" void http_decoder_plug_set_entry_fuc(on_msg_cb_func *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..4bdd840 100644 --- a/test/http_decoder_gtest.h +++ b/test/http_decoder_gtest.h @@ -1,7 +1,8 @@ #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> @@ -42,87 +43,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..93e13ad --- /dev/null +++ b/test/http_decoder_perf_main.cpp @@ -0,0 +1,358 @@ +#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; + 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, 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_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(msg, NULL); + } + return 0; +} + +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 size, 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 < size; 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); + } + perf_test_free_per_session(sess); + TIME_DIFF(); + // printf("time diff: %lld ns\n", time_diff_ns); + fieldstat_easy_histogram_record(fs4_instance, 0, fs4_metric_id, tag, 1, time_diff_ns); +} + +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..295e733 100644 --- a/test/http_decoder_perf.cpp +++ b/test/http_decoder_perf_plug.cpp @@ -5,19 +5,13 @@ #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 +19,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; + struct http_message *msg = (struct http_message *)raw_msg; enum http_message_type msg_type = http_message_type(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 +54,10 @@ 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); + } + if(http_message_get_url(msg, &url) >= 0){ + DEBUG_PRINT("URL: %.*s\n", url.str_len, url.str); } break; case HTTP_MESSAGE_REQ_BODY: @@ -64,34 +70,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_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 +107,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 +136,10 @@ 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) +extern "C" void http_decoder_plug_set_entry_fuc(on_msg_cb_func *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/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_based_on_stellar/CMakeLists.txt b/test_based_on_stellar/CMakeLists.txt index 70663bf..af3f8f9 100644 --- a/test_based_on_stellar/CMakeLists.txt +++ b/test_based_on_stellar/CMakeLists.txt @@ -32,24 +32,26 @@ 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/") # 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 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_SAPP_REORDER COMMAND bash -c "sed -i 's/reorder_pkt_max=32/reorder_pkt_max=5/' ${TEST_RUN_DIR}/etc/sapp.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_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 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) 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) + |
