From 274614cde4d166fb1209e51432609377f48ee7e8 Mon Sep 17 00:00:00 2001 From: 刘学利 Date: Wed, 1 Jun 2022 08:02:07 +0000 Subject: TSG-9128, TSG-9650: 提供解析HTTP头部字段的函数http_field_parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitlab-ci.yml | 19 ++ CMakeLists.txt | 5 +- src/HTTP_Parser.c | 279 +++++++++++++++++++------- src/http.h | 16 ++ test/CMakeLists.txt | 42 ++++ test/conflist.inf | 8 + test/empty_array.json | 1 + test/http_test_plug.cpp | 118 +++++++++++ test/http_test_plug.inf | 11 + test/pcap/http_get/http-get.pcap | Bin 0 -> 35841 bytes test/pcap/http_get/http_result.json | 25 +++ test/pcap/http_post/http-post-url-encode.pcap | Bin 0 -> 79756 bytes test/pcap/http_post/http_result.json | 25 +++ test/test_protocol_run.zip | Bin 0 -> 795325 bytes 14 files changed, 472 insertions(+), 77 deletions(-) create mode 100644 test/CMakeLists.txt create mode 100644 test/conflist.inf create mode 100644 test/empty_array.json create mode 100644 test/http_test_plug.cpp create mode 100644 test/http_test_plug.inf create mode 100644 test/pcap/http_get/http-get.pcap create mode 100644 test/pcap/http_get/http_result.json create mode 100644 test/pcap/http_post/http-post-url-encode.pcap create mode 100644 test/pcap/http_post/http_result.json create mode 100644 test/test_protocol_run.zip diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 703152e..9c8c251 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,6 +9,7 @@ variables: stages: - build +- test - package .build_before_script: @@ -44,6 +45,24 @@ stages: tags: - share +run_test_for_centos7: + stage: test + extends: .build_by_travis_for_centos7 + script: + - yum makecache + - ./ci/travis.sh + - cd build + - ctest --verbose + +run_test_for_centos8: + stage: test + extends: .build_by_travis_for_centos8 + script: + - yum makecache + - ./ci/travis.sh + - cd build + - ctest3 --verbose + branch_build_debug_for_centos7: stage: build extends: .build_by_travis_for_centos7 diff --git a/CMakeLists.txt b/CMakeLists.txt index acdbd1f..169c181 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,8 +64,7 @@ install(FILES bin/${lib_name}.inf DESTINATION ${CMAKE_INSTALL_PREFIX}/plug/proto install(FILES bin/http/http.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/conf/${lib_name}/ COMPONENT PROFILE) install(FILES bin/http/http_main.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/conf/${lib_name}/ COMPONENT PROFILE) -file(GLOB DEMO - "test/src/*.c" -) +enable_testing() +add_subdirectory(test) include(Package) diff --git a/src/HTTP_Parser.c b/src/HTTP_Parser.c index 9a0e61b..444fd06 100644 --- a/src/HTTP_Parser.c +++ b/src/HTTP_Parser.c @@ -13,48 +13,100 @@ extern const char* g_http_method[]; -typedef struct host_parser_t +struct http_header_field +{ + int field_flag; + int length; + char *value; +}; + +struct http_header_parse { - char* host_value; char is_http_flag; - char get_host_flag; - char host_field_flag; - char host_value_flag; - uint32 host_valuelen; -}host_parser; + char pad[7]; + long long http_field_flag; + struct http_header_field host; + struct http_header_field uri; + struct http_header_field url; +}; + int http_parser_callback_on_headers_field(struct http_parser * parser, const char * at, size_t length) { - if(((host_parser*)(parser->data))->get_host_flag==0 || ((host_parser*)(parser->data))->host_field_flag==1) return 0; - if(0==strncasecmp(at, "host",strlen("host"))) + if(at==NULL || length<=0 || parser==NULL || parser->data==NULL) { - ((host_parser*)(parser->data))->host_field_flag = 1; + return 0; } + + struct http_header_parse *header_parser=(struct http_header_parse *)(parser->data); + header_parser->is_http_flag=1; + + if((header_parser->host.field_flag==0) && (length==4) && (0==strncasecmp(at, "host", 4))) + { + header_parser->host.field_flag=1; + header_parser->http_field_flag=HTTP_HOST; + } + return 0; } int http_parser_callback_on_headers_value(struct http_parser * parser, const char * at, size_t length) -{ - if(((host_parser*)(parser->data))->get_host_flag==0 || ((host_parser*)(parser->data))->host_field_flag==0 || ((host_parser*)(parser->data))->host_value_flag==1) return 0; - if(0data==NULL) + { + return 0; + } + + struct http_header_parse *header_parser=(struct http_header_parse *)(parser->data); + header_parser->is_http_flag=1; + + switch(header_parser->http_field_flag) { - ((host_parser*)(parser->data))->host_value = (char*)malloc(length); - memcpy(((host_parser*)(parser->data))->host_value, at, length); - ((host_parser*)(parser->data))->host_valuelen = length; - ((host_parser*)(parser->data))->host_value_flag = 1; + case HTTP_HOST: + header_parser->host.value=(char*)malloc(length); + memcpy(header_parser->host.value, at, length); + header_parser->host.length=length; + header_parser->http_field_flag=HTTP_INTEREST_KEY; + break; + default: + break; } + return 0; } int http_parser_callback_on_url(struct http_parser * parser, const char * at, size_t length) { - ((host_parser*)(parser->data))->is_http_flag = 1; + if(at==NULL || length<=0 || parser==NULL || parser->data==NULL) + { + return 0; + } + + struct http_header_parse *header_parser=(struct http_header_parse *)(parser->data); + header_parser->is_http_flag=1; + + if(header_parser->uri.field_flag==0) + { + header_parser->uri.field_flag=1; + header_parser->uri.value=(char*)malloc(length); + memcpy(header_parser->uri.value, at, length); + header_parser->uri.length=length; + header_parser->http_field_flag=HTTP_INTEREST_KEY; + } + return 0; } int http_parser_callback_on_status(struct http_parser * parser, const char * at, size_t length) { - ((host_parser*)(parser->data))->is_http_flag = 1; + if(at==NULL || length<=0 || parser==NULL || parser->data==NULL) + { + return 0; + } + + struct http_header_parse *header_parser=(struct http_header_parse *)(parser->data); + header_parser->is_http_flag=1; + return 0; } @@ -72,7 +124,7 @@ static http_parser_settings http_setting = .on_chunk_complete = NULL }; -int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host) +void *http_field_parser(const char* buf, uint32 buflen, int http_dir) { //bufǰĿոɾ uint32 offset = 0; @@ -85,24 +137,17 @@ int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host) uint32 new_pbuflen = 0; uchar method = HTTP_METHOD_UNKNOWN; int method_idx = 1, new_flags=0; - + struct http_parser http_parse={0}; + if(pbuflen<4) //g_http_method min bytes=3; pbuflen_temp=pbuflen { - return -1; + return NULL; } - - //printf("buf=====================================================\n"); - //printf("%s\n", buf); - - // Ϊṹڴ - http_parser *parser = (http_parser*)calloc(1, sizeof(http_parser)); - host_parser* host_field = (host_parser*)calloc(1, sizeof(host_parser)); - int rec = -1; // ʼ if(http_dir==DIR_C2S) { - http_parser_init(parser, HTTP_REQUEST); + http_parser_init(&http_parse, HTTP_REQUEST); /*⵽methodƶһո񣬲'/',Ҳ"http://"Զһ'/'*/ if(buflen>HTTP_START_FLAGS_LEN+strlen("http://")) { @@ -134,64 +179,150 @@ int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host) } else { - http_parser_init(parser, HTTP_RESPONSE); - } - parser->data = (void*)host_field; - - //ȡhost - if(host!=NULL) - { - ((host_parser*)(parser->data))->get_host_flag = 1; + http_parser_init(&http_parse, HTTP_RESPONSE); } - size_t parsed=0; + struct http_header_parse *http_header=calloc(1, sizeof(struct http_header_parse)); + http_parse.data=(void*)(http_header); + //ִн if(new_flags==0) { - parsed=http_parser_execute(parser, &http_setting, pbuf, (size_t)pbuflen); + http_parser_execute(&http_parse, &http_setting, pbuf, (size_t)pbuflen); } else { - parsed=http_parser_execute(parser, &http_setting, new_pbuf, (size_t)new_pbuflen); + http_parser_execute(&http_parse, &http_setting, new_pbuf, (size_t)new_pbuflen); } - //printf("buflen: %d; parsed: %d\n", pbuflen, parsed); - if(((host_parser*)(parser->data))->is_http_flag == 1) + + if(NULL!=new_pbuf) + { + free(new_pbuf); + new_pbuf = NULL; + } + + if(http_header->is_http_flag==0) { - rec = 0; - if(((host_parser*)(parser->data))->get_host_flag == 1) - { - if(0host_valuelen) - { - rec = host_field->host_valuelen; - *host = memcasemem(pbuf, pbuflen, (const char*)host_field->host_value, host_field->host_valuelen); - } - } - } - else + free(http_header); + http_header=NULL; + return NULL; + } + + if(http_header->host.field_flag==1 && http_header->host.length>0 && http_header->host.value!=NULL) { - rec = -1; + char *p_host=memcasemem(pbuf, pbuflen, (const char*)http_header->host.value, http_header->host.length); + free(http_header->host.value); + http_header->host.value=p_host; } + + return (void *)(http_header); +} - if(NULL!=host_field) +void http_free_filed_result(void *result) +{ + if(result==NULL) { - if(NULL!=host_field->host_value) - { - free(host_field->host_value); - host_field->host_value = NULL; - } - free(host_field); - host_field = NULL; - } - if(NULL!=parser) - { - free(parser); - parser = NULL; + return ; } - if(NULL!=new_pbuf) - { - free(new_pbuf); - new_pbuf = NULL; + + struct http_header_parse *http_header=(struct http_header_parse *)result; + if(http_header->uri.value!=NULL) + { + free(http_header->uri.value); + http_header->uri.value=NULL; + } + + if(http_header->url.value!=NULL) + { + free(http_header->url.value); + http_header->url.value=NULL; } - return rec; + + free(result); + result=NULL; +} + +int http_get_filed_result(void *result, long long field_flag, char **field_value) +{ + if(result==NULL) + { + return 0; + } + + struct http_header_parse *http_header=(struct http_header_parse *)result; + + switch(field_flag) + { + case HTTP_HOST: + if(http_header->host.field_flag==0 || http_header->host.value==NULL || http_header->host.length<=0) + { + break; + } + *field_value=http_header->host.value; + return http_header->host.length; + case HTTP_MESSAGE_URL: + if(http_header->host.field_flag==0 || http_header->host.value==NULL || http_header->host.length<=0) + { + break; + } + + http_header->url.length=http_header->host.length; + http_header->url.value=malloc(http_header->url.length); + memcpy(http_header->url.value, http_header->host.value, http_header->host.length); + + if(http_header->uri.field_flag==0 || http_header->uri.value==NULL || http_header->uri.length<=0) + { + http_header->url.value=realloc(http_header->url.value, http_header->url.length+1); + http_header->url.value[http_header->url.length]='/'; + http_header->url.length+=1; + } + else + { + if(http_header->uri.value[0]=='/') + { + http_header->url.value=realloc(http_header->url.value, http_header->url.length+http_header->uri.length); + } + else + { + http_header->url.value=realloc(http_header->url.value, http_header->url.length+http_header->uri.length+1); + http_header->url.value[http_header->url.length]='/'; + http_header->url.length+=1; + } + + memcpy(http_header->url.value+http_header->url.length, http_header->uri.value, http_header->uri.length); + http_header->url.length+=http_header->uri.length; + } + + *field_value=http_header->url.value; + return http_header->url.length; + default: + break; + } + + return 0; +} + +int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host) +{ + struct http_header_parse *http_header=(struct http_header_parse *)http_field_parser(buf, buflen, http_dir); + if(http_header==NULL) + { + return -1; + } + + int length=0; + + if(http_header->is_http_flag==1) + { + if(http_header->host.field_flag==1 && http_header->host.length>0 && http_header->host.value!=NULL) + { + *host=http_header->host.value; + length=http_header->host.length; + } + } + + http_free_filed_result((void *)http_header); //no need free host, *host=buf+N + + return length; } diff --git a/src/http.h b/src/http.h index 99a8624..91f4041 100644 --- a/src/http.h +++ b/src/http.h @@ -255,6 +255,22 @@ int is_absolute_uri(void* app_info); int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host); +/* +* ˵ +* һݽHTTPͷֶνжǷHTTPЭ飬ظbufHTTPͷֶ +* ˵: +* buf: (ǵHTTPӵ,֧һHTTPݶνҲ֧bufжhttpӵ) +* buflen: ݵij +* http_dir: bufDIR_C2S or DIR_S2C +* ֵresult: +* !=NULL: bufHTTPЭݣͷֶ +* NULL: bufHTTPЭ +*/ +void *http_field_parser(const char* buf, uint32 buflen, int http_dir); +// return length of field_value, field_flag=(HTTP_HOST/HTTP_MESSAGE_URL/...) +int http_get_filed_result(void *result, long long field_flag, char **field_value); +void http_free_filed_result(void *result); + #ifdef __cplusplus } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..7149fed --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required (VERSION 2.8) + +project(${lib_name}_test) + +include(ExternalProject) +#### Protoco_test_run + + +ExternalProject_Add(ProtoTest PREFIX ProtoTest + URL ${CMAKE_CURRENT_SOURCE_DIR}/test_protocol_run.zip + URL_MD5 71d8284b59af0286b5f31f0a3160bc44 + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + COMMAND ${CMAKE_COMMAND} -E make_directory /conf/${lib_name}/ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/bin/http/${lib_name}.conf /conf/${lib_name}/ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/bin/http/${lib_name}_main.conf /conf/${lib_name}/ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/conflist.inf /plug/ + COMMAND ${CMAKE_COMMAND} -E make_directory /plug/protocol/${lib_name}/ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/bin/${lib_name}.inf /plug/protocol/${lib_name}/ + COMMAND ${CMAKE_COMMAND} -E make_directory /plug/business/${lib_name}_test_plug/ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/test/${lib_name}_test_plug.inf /plug/business/${lib_name}_test_plug/) + +ExternalProject_Get_Property(ProtoTest INSTALL_DIR) +ExternalProject_Get_Property(ProtoTest SOURCE_DIR) +set(PROTO_TEST_RUN_DIR ${SOURCE_DIR}) + +add_executable(proto_test_main IMPORTED GLOBAL) +add_dependencies(proto_test_main ProtoTest) +set_property(TARGET proto_test_main PROPERTY IMPORTED_LOCATION ${SOURCE_DIR}/test_protocol_plug_main) + + +add_library(${lib_name}_test_plug SHARED ${lib_name}_test_plug.cpp) +target_link_libraries(${lib_name}_test_plug MESA_prof_load cjson) +set_target_properties(${lib_name}_test_plug PROPERTIES PREFIX "") + +add_test(NAME COPY_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/${lib_name}.so ${PROTO_TEST_RUN_DIR}/plug/protocol/${lib_name}/${lib_name}.so") +add_test(NAME COPY_TEST_SO COMMAND sh -c "cp ${CMAKE_CURRENT_BINARY_DIR}/${lib_name}_test_plug.so ${PROTO_TEST_RUN_DIR}/plug/business/${lib_name}_test_plug/${lib_name}_test_plug.so") + +add_test(NAME RUN_HTTP_GET_TEST COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/http_get/http_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/http_get/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) +add_test(NAME RUN_HTTP_POST_TEST COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/http_post/http_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/http_post/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) diff --git a/test/conflist.inf b/test/conflist.inf new file mode 100644 index 0000000..97e3aee --- /dev/null +++ b/test/conflist.inf @@ -0,0 +1,8 @@ +[platform] + +[protocol] +./plug/protocol/http/http.inf + + +[business] +./plug/business/http_test_plug/http_test_plug.inf diff --git a/test/empty_array.json b/test/empty_array.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/test/empty_array.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/http_test_plug.cpp b/test/http_test_plug.cpp new file mode 100644 index 0000000..9d3a3d8 --- /dev/null +++ b/test/http_test_plug.cpp @@ -0,0 +1,118 @@ +#include +#include +#include +#include + +#include "cJSON.h" +#include "http.h" +#include "MESA_prof_load.h" +#include + +extern "C" int commit_test_result_json(cJSON *node, const char *name); + +static int g_result_count = 1; + +int check_field(char *src, int src_len, char *dst, int dst_len) +{ + if(src==NULL || dst==NULL || src_len==0 || dst_len==0 || src_len!=dst_len) + { + assert(0); + } + + assert(!memcmp(src, dst, src_len)); + + return 0; +} + +int http_field_add_to_json(cJSON *object, const char *name, char *value, char length) +{ + if(value!=NULL && length>0) + { + char *tmp=(char *)calloc(1, length+1); + memcpy(tmp, value, length); + cJSON_AddStringToObject(object, name, tmp); + free(tmp); + tmp=NULL; + } + + return 0; +} + +extern "C" unsigned char HTTP_TEST_PLUG_ENTRY(stSessionInfo *session_info, void **pme, int thread_seq, struct streaminfo *a_tcp, void *a_packet) +{ + assert(NULL != session_info || pme != NULL); + + cJSON *ctx = (cJSON *)*pme; + + if (session_info->session_state & SESSION_STATE_PENDING) + { + if (*pme == NULL) + { + ctx = cJSON_CreateObject(); + *pme = (void *)ctx; + cJSON_AddStringToObject(ctx, "Tuple4", printaddr(&a_tcp->addr, a_tcp->threadnum)); + } + } + + int length=0; + char *url=NULL, *host=NULL; + void *parser_result=NULL; + + switch (session_info->prot_flag) + { + case HTTP_URI: + http_field_add_to_json(ctx, "http_uri", (char *)session_info->buf, session_info->buflen); + break; + case HTTP_HOST: + length=http_host_parser((const char *)a_tcp->ptcpdetail->pdata, a_tcp->ptcpdetail->datalen, a_tcp->curdir, &host); + check_field((char *)session_info->buf, session_info->buflen, host, length); + + parser_result=http_field_parser((const char *)a_tcp->ptcpdetail->pdata, a_tcp->ptcpdetail->datalen, a_tcp->curdir); + length=http_get_filed_result(parser_result, HTTP_HOST, &host); + check_field((char *)session_info->buf, session_info->buflen, host, length); + + http_field_add_to_json(ctx, "http_host", host, length); + http_free_filed_result(parser_result); + break; + case HTTP_MESSAGE_URL: + parser_result=http_field_parser((const char *)a_tcp->ptcpdetail->pdata, a_tcp->ptcpdetail->datalen, a_tcp->curdir); + length=http_get_filed_result(parser_result, HTTP_MESSAGE_URL, &url); + check_field((char *)session_info->buf, session_info->buflen, url, length); + + http_field_add_to_json(ctx, "http_url", url, length); + http_free_filed_result(parser_result); + break; + default: + break; + } + + if(session_info->session_state&SESSION_STATE_CLOSE) + { + if(ctx) + { + char result_name[16]=""; + sprintf(result_name,"HTTP_RESULT_%d", g_result_count); + commit_test_result_json(ctx, result_name); + g_result_count+=1; + } + *pme = NULL; + return PROT_STATE_DROPME; + + } + + return PROT_STATE_GIVEME; + +} + +extern "C" int HTTP_TEST_PLUG_INIT() +{ + return 0; +} + +extern "C" void HTTP_TEST_PLUG_DESTROY(void) +{ + return ; +}/*CHAR_DESTRORY*/ + + + diff --git a/test/http_test_plug.inf b/test/http_test_plug.inf new file mode 100644 index 0000000..61ca4cb --- /dev/null +++ b/test/http_test_plug.inf @@ -0,0 +1,11 @@ +[PLUGINFO] +PLUGNAME=HTTP_TEST_PLUG +SO_PATH=./plug/business/http_test_plug/http_test_plug.so +INIT_FUNC=HTTP_TEST_PLUG_INIT +DESTROY_FUNC=HTTP_TEST_PLUG_DESTROY + +[HTTP] +FUNC_FLAG=ALL +FUNC_NAME=HTTP_TEST_PLUG_ENTRY + + diff --git a/test/pcap/http_get/http-get.pcap b/test/pcap/http_get/http-get.pcap new file mode 100644 index 0000000..9c0d2e7 Binary files /dev/null and b/test/pcap/http_get/http-get.pcap differ diff --git a/test/pcap/http_get/http_result.json b/test/pcap/http_get/http_result.json new file mode 100644 index 0000000..6394263 --- /dev/null +++ b/test/pcap/http_get/http_result.json @@ -0,0 +1,25 @@ +[{ + "Tuple4": "192.168.50.18.60400>192.168.42.1.80", + "http_uri": "/account/login.htm", + "http_host": "test.pro.testin.cn", + "http_url": "test.pro.testin.cn/account/login.htm", + "name": "HTTP_RESULT_1" + }, { + "Tuple4": "192.168.50.18.60400>192.168.42.1.80", + "http_uri": "/enterprise/index.htm", + "http_host": "test.pro.testin.cn", + "http_url": "test.pro.testin.cn/enterprise/index.htm", + "name": "HTTP_RESULT_2" + }, { + "Tuple4": "192.168.50.18.60400>192.168.42.1.80", + "http_uri": "/enterprise/into.htm?eid=1", + "http_host": "test.pro.testin.cn", + "http_url": "test.pro.testin.cn/enterprise/into.htm?eid=1", + "name": "HTTP_RESULT_3" + }, { + "Tuple4": "192.168.50.18.60400>192.168.42.1.80", + "http_uri": "/realmachine/index.htm", + "http_host": "test.pro.testin.cn", + "http_url": "test.pro.testin.cn/realmachine/index.htm", + "name": "HTTP_RESULT_4" +}] diff --git a/test/pcap/http_post/http-post-url-encode.pcap b/test/pcap/http_post/http-post-url-encode.pcap new file mode 100644 index 0000000..0eae429 Binary files /dev/null and b/test/pcap/http_post/http-post-url-encode.pcap differ diff --git a/test/pcap/http_post/http_result.json b/test/pcap/http_post/http_result.json new file mode 100644 index 0000000..951f9bb --- /dev/null +++ b/test/pcap/http_post/http_result.json @@ -0,0 +1,25 @@ +[{ + "Tuple4": "192.168.32.18.63316>221.238.248.3.8000", + "http_uri": "/m_fullsearch/full_search1.jsp", + "http_host": "sou.qhnews.com:8000", + "http_url": "sou.qhnews.com:8000/m_fullsearch/full_search1.jsp", + "name": "HTTP_RESULT_1" + }, { + "Tuple4": "192.168.32.18.63316>221.238.248.3.8000", + "http_uri": "/m_fullsearch/css/css.css", + "http_host": "sou.qhnews.com:8000", + "http_url": "sou.qhnews.com:8000/m_fullsearch/css/css.css", + "name": "HTTP_RESULT_2" + }, { + "Tuple4": "192.168.32.18.63316>221.238.248.3.8000", + "http_uri": "/m_fullsearch/dwr/util.js", + "http_host": "sou.qhnews.com:8000", + "http_url": "sou.qhnews.com:8000/m_fullsearch/dwr/util.js", + "name": "HTTP_RESULT_3" + }, { + "Tuple4": "192.168.32.18.63316>221.238.248.3.8000", + "http_uri": "/m_fullsearch/dwr/call/plaincall/DwrChannel.getChild.dwr", + "http_host": "sou.qhnews.com:8000", + "http_url": "sou.qhnews.com:8000/m_fullsearch/dwr/call/plaincall/DwrChannel.getChild.dwr", + "name": "HTTP_RESULT_4" +}] diff --git a/test/test_protocol_run.zip b/test/test_protocol_run.zip new file mode 100644 index 0000000..996f3fa Binary files /dev/null and b/test/test_protocol_run.zip differ -- cgit v1.2.3