diff --git a/.gitignore b/.gitignore index e420459..0d58cab 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ build*/ src/inc src/lib64 cmake-build-*/ +.vscode/ \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b6c1d7f..ad95b54 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,10 +1,12 @@ variables: GIT_STRATEGY: "clone" - BUILD_IMAGE_CENTOS7: "git.mesalab.cn:7443/mesa_platform/build-env:master" BUILD_IMAGE_CENTOS8: "git.mesalab.cn:7443/mesa_platform/build-env:rockylinux" BUILD_PADDING_PREFIX: /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX/ INSTALL_DEPENDENCY_PLATFORM: sapp-devel libasan systemd-devel libnsl glib2-devel - INSTALL_DEPENDENCY_FRAMEWORK: libMESA_handle_logger-devel libcjson-devel libMESA_field_stat2-devel framework_env libMESA_prof_load-devel libbreakpad_mini-devel libMESA_htable-devel + INSTALL_DEPENDENCY_FRAMEWORK: libMESA_handle_logger-devel libcjson-devel libcjson libMESA_field_stat2-devel framework_env + libMESA_prof_load-devel libbreakpad_mini-devel libMESA_htable-devel + stellar-on-sapp-devel stellar-on-sapp systemd-devel libfieldstat3-devel libfieldstat3 libMESA_field_stat2 + libMESA_jump_layer libMESA_htable libMESA_handle_logger INSTALL_PREFIX: "/home/mesasoft/sapp_run/" stages: @@ -21,19 +23,6 @@ stages: - yum makecache - yum install -y elfutils-libelf-devel - -.build_by_travis_for_centos7: - stage: build - image: $BUILD_IMAGE_CENTOS7 - extends: .build_before_script - script: - - yum install -y libmnl-devel - - yum install -y libnfnetlink-devel - - ./ci/travis.sh - - cd build - tags: - - share - .build_by_travis_for_centos8: stage: build image: $BUILD_IMAGE_CENTOS8 @@ -45,15 +34,6 @@ 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 @@ -63,98 +43,6 @@ run_test_for_centos8: - cd build - ctest3 --verbose -branch_build_debug_for_centos7: - stage: build - extends: .build_by_travis_for_centos7 - variables: - BUILD_TYPE: Debug - except: - - /^develop.*$/i - - /^master.*$/i - - tags - -branch_build_release_for_centos7: - stage: build - variables: - BUILD_TYPE: RelWithDebInfo - extends: .build_by_travis_for_centos7 - except: - - /^develop.*$/i - - /^master.*$/i - - tags - -develop_build_debug_for_centos7: - stage: build - extends: .build_by_travis_for_centos7 - variables: - BUILD_TYPE: Debug - PACKAGE: 1 - UPLOAD_RPM: 1 - ASAN_OPTION: ADDRESS - TESTING_VERSION_BUILD: 1 - PULP3_REPO_NAME: protocol-testing-x86_64.el7 - PULP3_DIST_NAME: protocol-testing-x86_64.el7 - artifacts: - name: "quic-$CI_COMMIT_REF_NAME-debug" - paths: - - build/*.rpm - only: - - /^develop.*$/i - - /^master.*$/i - -develop_build_release_for_centos7: - stage: build - extends: .build_by_travis_for_centos7 - variables: - BUILD_TYPE: RelWithDebInfo - PACKAGE: 1 - UPLOAD_RPM: 1 - TESTING_VERSION_BUILD: 1 - PULP3_REPO_NAME: protocol-testing-x86_64.el7 - PULP3_DIST_NAME: protocol-testing-x86_64.el7 - artifacts: - name: "quic-$CI_COMMIT_REF_NAME-release" - paths: - - build/*.rpm - only: - - /^develop.*$/i - - /^master.*$/i - -release_build_debug_for_centos7: - stage: package - variables: - BUILD_TYPE: Debug - PACKAGE: 1 - UPLOAD_RPM: 1 - ASAN_OPTION: ADDRESS - PULP3_REPO_NAME: protocol-stable-x86_64.el7 - PULP3_DIST_NAME: protocol-stable-x86_64.el7 - extends: .build_by_travis_for_centos7 - artifacts: - name: "quic-$CI_COMMIT_REF_NAME-debug" - paths: - - build/*.rpm - only: - - tags - -release_build_release_for_centos7: - stage: package - variables: - BUILD_TYPE: RelWithDebInfo - PACKAGE: 1 - UPLOAD_RPM: 1 - UPLOAD_SYMBOL_FILES: 1 - SYMBOL_TARGET: quic - PULP3_REPO_NAME: protocol-stable-x86_64.el7 - PULP3_DIST_NAME: protocol-stable-x86_64.el7 - extends: .build_by_travis_for_centos7 - artifacts: - name: "quic-$CI_COMMIT_REF_NAME-release" - paths: - - build/*.rpm - only: - - tags - branch_build_debug_for_centos8: stage: build extends: .build_by_travis_for_centos8 diff --git a/CMakeLists.txt b/CMakeLists.txt index 50937bd..3eba420 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,28 +34,17 @@ include_directories(include) include_directories(/opt/MESA/include/MESA/) add_subdirectory(support) - -file(GLOB SRC - "src/*.cpp" -) -set(DEPEND_DYN_LIB MESA_handle_logger) - -# Shared Library Output -add_library(quic SHARED ${SRC}) -set_target_properties(quic PROPERTIES LINK_FLAGS "-Wl,--version-script=${PROJECT_SOURCE_DIR}/src/version.map") -set_target_properties(quic PROPERTIES PREFIX "") -target_link_libraries(quic ${DNS_DEPEND_DYN_LIB} pthread -Wl,--no-whole-archive openssl-crypto-static -Wl,--no-whole-archive openssl-ssl-static) -set_target_properties(quic PROPERTIES OUTPUT_NAME ${lib_name}) +add_subdirectory(src) enable_testing() add_subdirectory(test) -set(CPACK_RPM_USER_FILELIST "%config(noreplace) ${CMAKE_INSTALL_PREFIX}/plug/protocol/quic/quic.inf" - "%config(noreplace) ${CMAKE_INSTALL_PREFIX}/conf/quic/quic.conf") +set(CPACK_RPM_USER_FILELIST "%config(noreplace) ${CMAKE_INSTALL_PREFIX}/conf/quic/quic.conf" + "%config(noreplace) ${CMAKE_INSTALL_PREFIX}/conf/quic/main.conf") -install(TARGETS quic LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/plug/protocol/quic COMPONENT LIBRARIES) install(FILES bin/quic.inf DESTINATION ${CMAKE_INSTALL_PREFIX}/plug/protocol/quic COMPONENT PROFILE) install(FILES bin/quic.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/conf/quic COMPONENT PROFILE) +install(FILES bin/main.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/conf/quic COMPONENT PROFILE) install(FILES include/quic.h DESTINATION /opt/MESA/include/MESA COMPONENT HEADER) include(Package) diff --git a/bin/main.conf b/bin/main.conf new file mode 100644 index 0000000..8109155 --- /dev/null +++ b/bin/main.conf @@ -0,0 +1,6 @@ +[QUIC] +QUIC_PORT_LIST=443;8443;4433; +LOG_LEVEL=30 +LOG_PATH="./log/quic/quic" +DECRYPTED_SWITCH=2 +MAX_PARSE_PKT_NUM=3 diff --git a/bin/quic.inf b/bin/quic.inf index 1946dcf..684de9b 100755 --- a/bin/quic.inf +++ b/bin/quic.inf @@ -1,12 +1,9 @@ -[PLUGINFO] -PLUGNAME=QUIC -SO_PATH=./plug/protocol/quic/quic.so -INIT_FUNC=QUIC_INIT -DESTROY_FUNC=QUIC_DESTROY -FLAGCHANGE_FUNC=QUIC_FLAG_CHANGE -FLAGSTATE_FUNC=QUIC_PROT_FUNSTAT -GETPLUGID_FUNC=QUIC_GETPLUGID +[[plugin]] +path = "./stellar_plugin/quic.so" +init = "QUIC_ONLOAD" +exit = "QUIC_UNLOAD" -[UDP] -FUNC_FLAG=ALL -FUNC_NAME=QUIC_ENTRY +[[plugin]] +path = "./stellar_plugin/quic_test_plug.so" +init = "QUIC_TEST_PLUG_INIT" +exit = "QUIC_TEST_PLUG_DESTROY" \ No newline at end of file diff --git a/include/quic.h b/include/quic.h index dcb25c8..bd112aa 100644 --- a/include/quic.h +++ b/include/quic.h @@ -1,55 +1,41 @@ -/* - * quic.h - * - * Created on: 2021-11-08 - * Author: liuxueli - */ +#pragma once -#ifndef __QUIC_H__ -#define __QUIC_H__ - -#define QUIC_INTEREST_KEY (1< - -#include +#include #include #include @@ -15,15 +14,19 @@ #include "quic_entry.h" #include "quic_process.h" #include "quic_deprotection.h" +#include "quic_util.h" -struct quic_param g_quic_param; -const char *g_quic_proto_conffile="./conf/quic/main.conf"; -const char *g_quic_regionname_conffile="./conf/quic/quic.conf"; - +static const char *g_quic_proto_conffile="./conf/quic/main.conf"; +// static const char *g_quic_regionname_conffile="./conf/quic/quic.conf"; +static const char *g_quic_log_path = "./log/quic/quic"; #ifdef __cplusplus extern "C" { #endif +#include +#include +#include +#include #define GIT_VERSION_CATTER(v) __attribute__((__used__)) const char * GIT_VERSION_##v = NULL #define GIT_VERSION_EXPEND(v) GIT_VERSION_CATTER(v) @@ -100,233 +103,140 @@ static int parse_quic_port(char *port_list, unsigned short *quic_port, int quic_ for(i=s_port; i<=e_port && port_numsni.str) + FREE(quic_info->sni.str); - *pme=(void*)context; - - return 0; -} - -void quic_free_client_hello(struct quic_client_hello *client_hello, int thread_seq) -{ - if(client_hello==NULL) - { - return ; - } - - if(client_hello->sni) - { - dictator_free(thread_seq, client_hello->sni); - client_hello->sni=NULL; - } - - if(client_hello->user_agent) - { - dictator_free(thread_seq, client_hello->user_agent); - client_hello->user_agent=NULL; - } - - dictator_free(thread_seq, client_hello); - client_hello=NULL; - + if(quic_info->user_agent.str) + FREE(quic_info->user_agent.str); return ; } -void quic_free_context(const struct streaminfo *a_stream, int bridge_id, void *data) +extern "C" void quic_on_session_msg_cb(struct session *sess, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env) { - if(NULL!=data) - { - struct quic_context *context = (struct quic_context *)data; - quic_free_client_hello(context->quic_info.client_hello, a_stream->threadnum); - - dictator_free(a_stream->threadnum, data); - } -} + struct quic_param *quic_plugin_env = (struct quic_param *)plugin_env; + struct quic_context *context = (struct quic_context *)per_session_ctx; -extern "C" unsigned char QUIC_ENTRY(const struct streaminfo *pstream, void**pme, int thread_seq, const void *a_packet) -{ - if((g_quic_param.quic_interested_region_flagquic_topic_id, qmsg); + context->msg_state[QUIC_FREE] = 1; } - if(pstream->opstate==OP_STATE_PENDING) + payload = session_get0_current_payload(sess, &payload_len); + if(NULL == payload || payload_len <= 0) { - *pme=stream_bridge_async_data_get(pstream, g_quic_param.context_bridge_id); - if(*pme==NULL) - { - *pme=dictator_malloc(thread_seq, sizeof(struct quic_context)); - memset(*pme, 0, sizeof(struct quic_context)); - } - } - - unsigned char state=0; - struct quic_context *context=(struct quic_context *)*pme; - - state=quic_analyze_entry(pstream, context, thread_seq, a_packet); - - if(state&APP_STATE_DROPME || pstream->opstate==OP_STATE_CLOSE) - { - if(context->link_state==1) - { - quic_call_business_plug(pstream, context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet); - } - - quic_free_context(pstream, g_quic_param.context_bridge_id, *pme); - stream_bridge_async_data_put(pstream, g_quic_param.context_bridge_id, NULL); - *pme=NULL; - return state; - } - - return APP_STATE_GIVEME; -} - -extern "C" int QUIC_INIT(void) -{ - int ret=0; - FILE *fp=NULL; - char buff[2048]={0}; - int region_id=0; - char region_name[REGION_NAME_LEN]={0}; - - memset(&g_quic_param,0,sizeof(struct quic_param)); - - MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "LOG_LEVEL", &g_quic_param.level, RLOG_LV_FATAL); - MESA_load_profile_string_def(g_quic_proto_conffile, "QUIC", "LOG_PATH", g_quic_param.log_path, sizeof(g_quic_param.log_path), "./log/quic/quic"); - - MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "DECRYPTED_SWITCH", &g_quic_param.decrypted_switch, 2); - MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "MAX_PARSE_PKT_NUM", &g_quic_param.max_parse_pkt_num, 3); - - MESA_load_profile_string_def(g_quic_proto_conffile, "QUIC", "QUIC_PORT_LIST", buff, sizeof(buff), "443;8443;"); - g_quic_param.quic_port_num=parse_quic_port(buff, g_quic_param.quic_port_list, SUPPORT_QUIC_PORT_NUM); - - g_quic_param.logger=MESA_create_runtime_log_handle(g_quic_param.log_path, g_quic_param.level); - if(g_quic_param.logger==NULL) - { - printf("MESA_create_runtime_log_handle failed, level: %d log_path: %s", g_quic_param.level, g_quic_param.log_path); - return -1; - } - - if(((fp = fopen(g_quic_regionname_conffile, "r"))!=NULL)) - { - while(fgets(buff, sizeof(buff), fp)) - { - ret = sscanf(buff, "%d\t%s", ®ion_id, region_name); - if(2>ret) - { - fclose(fp); - MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_READCONF", "Read error, Please check %s, region_line: %s", g_quic_regionname_conffile, buff); - return -1; - } - if(region_id>MAX_REGION_NUM) - { - fclose(fp); - MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_READCONF", "Read error, Please check %s, bigger than MAX_REGION_NUM, region_line: %s", g_quic_regionname_conffile, buff); - return -1; - } - - memcpy(g_quic_param.quic_conf_regionname[region_id], region_name, MIN(sizeof(g_quic_param.quic_conf_regionname[region_id])-1, strlen(region_name))); - g_quic_param.quic_region_cnt++; - memset(region_name, 0, sizeof(region_name)); - } - - fclose(fp); - } - else - { - MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_READCONF", "Open %s error, Please check %s", g_quic_regionname_conffile, g_quic_regionname_conffile); - return -1; - } - - g_quic_param.context_bridge_id=stream_bridge_build("QUIC_CONTEXT", "w"); - stream_bridge_register_data_free_cb(g_quic_param.context_bridge_id, quic_free_context); - - return 0; -} - -extern "C" void QUIC_GETPLUGID(unsigned short plugid) -{ - g_quic_param.quic_plugid = plugid; - MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_GETPLUGID", "quic_plugid: %d", plugid); -} - -extern "C" void QUIC_PROT_FUNSTAT(unsigned long long protflag) -{ - if(0==protflag){ return; } - g_quic_param.quic_interested_region_flag=protflag; - MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_PROT_FUNSTAT", "interested_region_flag: %llu", g_quic_param.quic_interested_region_flag); + quic_analyze_entry(sess, quic_plugin_env, context, thread_seq, payload, payload_len); + return; } -extern "C" unsigned long long quic_getRegionID(char *string, int str_len,const char g_string[MAX_REGION_NUM][REGION_NAME_LEN]) +void *quic_session_ctx_new_cb(struct session *sess, void *plugin_env) { - unsigned long long i=0; - for(i=0;iquic_info, &tmp_qinfo, sizeof(struct quic_info)); + struct quic_message *qmsg = quic_create_message(QUIC_NEW, qcontext); + quic_session_mq_publish_message_safe(sess, quic_plugin_env->quic_topic_id, qmsg); + return (void *)qcontext; } -extern "C" long long QUIC_FLAG_CHANGE(char* flag_str) +void quic_session_ctx_free_cb(struct session *sess, void *session_ctx, void *plugin_env) { - if(flag_str==NULL) return -1; - long long protflag = 0; - long long region_id = 0; - char *start_token = flag_str; - char *end_token = flag_str; - char *end_pos = flag_str+strlen(flag_str); - char region_name[REGION_NAME_LEN] = {0}; - - while (end_token < end_pos) - { - end_token = (char*)memchr(start_token, ',', end_pos-start_token); - if(end_token!=NULL) - { - memcpy(region_name, start_token, end_token-start_token); - start_token = end_token+1; - end_token += 1; - } - else - { - memcpy(region_name, start_token, end_pos-start_token); - end_token = end_pos; - } - region_id = quic_getRegionID(region_name, strlen(region_name), g_quic_param.quic_conf_regionname); - if(-1==region_id) - { - MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_FLAG_CHANGE", "Read %s error, flag_str: %d", region_name, flag_str); - return -1; - } - protflag |= ((long long)1)<quic_info); + FREE(session_ctx); } + return; +} +void quic_session_exdata_free_cb(struct session *sess, int idx, void *ex_ptr, void *arg) +{ + return; +} + +void quic_msg_free_cb(struct session *sess, void *msg, void *msg_free_arg) +{ + FREE(msg); +} + +extern "C" void *QUIC_ONLOAD(struct stellar *st) +{ + char buff[2048]={0}; + + struct quic_param *quic_plugin_env = (struct quic_param *)CALLOC(1, sizeof(struct quic_param)); + quic_plugin_env->st = st; + + MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "LOG_LEVEL", &quic_plugin_env->level, RLOG_LV_FATAL); + MESA_load_profile_string_def(g_quic_proto_conffile, "QUIC", "LOG_PATH", quic_plugin_env->log_path, sizeof(quic_plugin_env->log_path), g_quic_log_path); - MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_FLAG_CHANGE", "protflag: %llu", protflag); - return protflag; + MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "DECRYPTED_SWITCH", &quic_plugin_env->decrypted_switch, 2); + MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "MAX_PARSE_PKT_NUM", &quic_plugin_env->max_parse_pkt_num, 3); + + MESA_load_profile_string_def(g_quic_proto_conffile, "QUIC", "QUIC_PORT_LIST", buff, sizeof(buff), "443;8443;"); + quic_plugin_env->quic_port_num=parse_quic_port(buff, quic_plugin_env->quic_port_list, SUPPORT_QUIC_PORT_NUM); + + quic_plugin_env->logger=MESA_create_runtime_log_handle(quic_plugin_env->log_path, quic_plugin_env->level); + if(quic_plugin_env->logger==NULL) + { + fprintf(stderr, "MESA_create_runtime_log_handle failed, level: %d log_path: %s", quic_plugin_env->level, quic_plugin_env->log_path); + return NULL; + } + + quic_plugin_env->quic_plugid = stellar_session_plugin_register(st, quic_session_ctx_new_cb, quic_session_ctx_free_cb, quic_plugin_env); + assert(quic_plugin_env->quic_plugid >= 0); + + quic_plugin_env->exdata_id=stellar_session_exdata_new_index(st, "QUIC_EXDATA", quic_session_exdata_free_cb, quic_plugin_env); + assert(quic_plugin_env->exdata_id >= 0); + quic_plugin_env->udp_topic_id=stellar_session_mq_get_topic_id(st, TOPIC_UDP); + assert(quic_plugin_env->udp_topic_id >= 0); + stellar_session_mq_subscribe(st, quic_plugin_env->udp_topic_id, quic_on_session_msg_cb, quic_plugin_env->quic_plugid); + + quic_plugin_env->quic_topic_id=stellar_session_mq_create_topic(st, QUIC_DECODER_TOPIC, quic_msg_free_cb, quic_plugin_env); + assert(quic_plugin_env->quic_topic_id >= 0); + return (void *)quic_plugin_env; } -extern "C" void QUIC_DESTROY(void) +extern "C" void QUIC_UNLOAD(void *plugin_env) { - MESA_destroy_runtime_log_handle(g_quic_param.logger); - g_quic_param.logger = NULL; - return ; -} - + struct quic_param *quic_plugin_env = (struct quic_param *)plugin_env; + MESA_destroy_runtime_log_handle(quic_plugin_env->logger); + FREE(plugin_env); + return; +} \ No newline at end of file diff --git a/src/quic_entry.h b/src/quic_entry.h index 27a33e7..9b4e6fa 100644 --- a/src/quic_entry.h +++ b/src/quic_entry.h @@ -26,15 +26,17 @@ struct quic_param { - unsigned long long quic_interested_region_flag; - unsigned long long quic_region_cnt; - unsigned short quic_plugid; + struct stellar *st; + int quic_plugid; int level; int quic_port_num; int decrypted_switch; int max_parse_pkt_num; - int context_bridge_id; - unsigned short quic_port_list[SUPPORT_QUIC_PORT_NUM]; + // int context_bridge_id; + int exdata_id; + int udp_topic_id; //as subscriber + int quic_topic_id; //as publisher + unsigned short quic_port_list[SUPPORT_QUIC_PORT_NUM]; //network order char quic_conf_regionname[MAX_REGION_NUM][REGION_NAME_LEN]; char log_path[128]; void *logger; @@ -51,8 +53,5 @@ enum quic_mes_type{ MSG_UNKNOWN = 255 }; -extern struct quic_param g_quic_param; -int is_quic_port(const struct streaminfo *pstream); - #endif /* SRC_QUIC_ANALYSIS_H_ */ diff --git a/src/quic_process.cpp b/src/quic_process.cpp index 076001e..946a486 100644 --- a/src/quic_process.cpp +++ b/src/quic_process.cpp @@ -11,21 +11,23 @@ #include #include #include -#include #include - #include "quic_entry.h" #include "quic_process.h" #include "quic_deprotection.h" -enum PARSE_RESULT +#ifdef __cplusplus +extern "C" { - PARSE_RESULT_UNKNOWN, - PARSE_RESULT_VERSION, - PARSE_RESULT_CLIENT_HELLO, - PARSE_RESULT_PAYLOAD, - PARSE_RESULT_MAX -}; +#endif +#include "quic_util.h" +#include +#include +#include +#include +#ifdef __cplusplus +} +#endif #ifndef PRINTADDR #define PRINTADDR(a, b) ((b)addr), a->threadnum) : "") @@ -39,49 +41,73 @@ struct quic_client_hello_msg_hdr uint8_t random[32]; }; -int check_port(unsigned short port) +static int check_port(const struct quic_param *quic_plugin_env, unsigned short port) { - int i=0; - for(i=0; i< g_quic_param.quic_port_num; i++) + for (int i = 0; i < quic_plugin_env->quic_port_num; i++) { - if(g_quic_param.quic_port_list[i]==port) + if (quic_plugin_env->quic_port_list[i] == port) { return 1; } } - return 0; } -int is_quic_port(const struct streaminfo *pstream) +int quic_protocol_identify(struct session *sess, struct quic_param *quic_plugin_env) { - unsigned short source=0, dest=0; - - switch(pstream->addr.addrtype) + enum session_addr_type addr_type; + struct session_addr *saddr = session_get0_addr(sess, &addr_type); + unsigned short sport, dport; + if (addr_type == SESSION_ADDR_TYPE_IPV4_UDP) { - case ADDR_TYPE_IPV4: - case __ADDR_TYPE_IP_PAIR_V4: - source=(unsigned short)ntohs(pstream->addr.ipv4->source); - dest=(unsigned short)ntohs(pstream->addr.ipv4->dest); - break; - case ADDR_TYPE_IPV6: - case __ADDR_TYPE_IP_PAIR_V6: - source=(unsigned short)ntohs(pstream->addr.ipv6->source); - dest=(unsigned short)ntohs(pstream->addr.ipv6->dest); - break; - default: - return 0; - break; + sport = saddr->ipv4.sport; + dport = saddr->ipv4.dport; } - - if(check_port(source) || check_port(dest)) + else if (addr_type == SESSION_ADDR_TYPE_IPV6_UDP) { - return 1; + sport = saddr->ipv6.sport; + dport = saddr->ipv6.dport; } - - return 0; + else + { + return 0; + } + if (0 == (check_port(quic_plugin_env, sport) || check_port(quic_plugin_env, dport))) + { + return 0; + } + return 1; } +// int is_quic_port(const struct streaminfo *pstream) +// { +// unsigned short source=0, dest=0; + +// switch(pstream->addr.addrtype) +// { +// case ADDR_TYPE_IPV4: +// case __ADDR_TYPE_IP_PAIR_V4: +// source=(unsigned short)ntohs(pstream->addr.ipv4->source); +// dest=(unsigned short)ntohs(pstream->addr.ipv4->dest); +// break; +// case ADDR_TYPE_IPV6: +// case __ADDR_TYPE_IP_PAIR_V6: +// source=(unsigned short)ntohs(pstream->addr.ipv6->source); +// dest=(unsigned short)ntohs(pstream->addr.ipv6->dest); +// break; +// default: +// return 0; +// break; +// } + +// if(check_port(source) || check_port(dest)) +// { +// return 1; +// } + +// return 0; +// } + static int gquic_pkn_bit2length(unsigned char bit_value) { switch(bit_value) @@ -96,19 +122,18 @@ static int gquic_pkn_bit2length(unsigned char bit_value) return 1; } -static int copy_extension_tag(const char *tag_start_pos, int tag_len, char **out, int thread_seq) +static int copy_extension_tag(const char *tag_start_pos, int tag_len, struct qstring *out, int thread_seq) { if(tag_start_pos!=NULL && tag_len>0) { - if(*out!=NULL) + if(out->str!=NULL) { - dictator_free(thread_seq, *out); - *out=NULL; + FREE(out->str); } - (*out)=(char *)dictator_malloc(thread_seq, tag_len+1); - memcpy(*out, tag_start_pos, tag_len); - (*out)[tag_len]='\0'; + out->str=(char *)CALLOC(1, tag_len+1); + memcpy((void *)out->str, tag_start_pos, tag_len); + out->str_len = tag_len; return tag_len; } @@ -137,57 +162,6 @@ static int msb2_varint_decode(const unsigned char *buf, long *out) return nfollow; } -int quic_call_business_state(struct quic_context *context) -{ - UCHAR state = 0; - - if(0==context->link_state) - { - state=SESSION_STATE_PENDING|SESSION_STATE_DATA; - context->link_state=1; - } - else - { - state=SESSION_STATE_DATA; - } - - return state; -} - -unsigned char quic_call_business_plug(const struct streaminfo *pstream, struct quic_context *context, void *buff, int buff_len, enum quic_interested_region region_mask, const void *a_packet) -{ - char state=PROT_STATE_GIVEME; - char app_state=APP_STATE_GIVEME; - stSessionInfo session_info={0}; - - if(region_mask==QUIC_INTEREST_KEY_MASK) - { - session_info.plugid=g_quic_param.quic_plugid; - session_info.prot_flag=0; - session_info.session_state=SESSION_STATE_CLOSE; - session_info.app_info=NULL; - session_info.buf=NULL; - session_info.buflen=0; - } - else - { - session_info.plugid=g_quic_param.quic_plugid; - session_info.prot_flag=(((unsigned long long)1)<quic_info); - session_info.buf=buff; - session_info.buflen=buff_len; - } - state=PROT_PROCESS(&session_info, &(context->business_pme), pstream->threadnum, (struct streaminfo *)pstream, a_packet); - - if(state&PROT_STATE_DROPPKT) - { - app_state=APP_STATE_DROPPKT; - } - - return app_state; -} - /* //https://docs.google.com/document/d/1FcpCJGTDEMblAs-Bm5TYuqhHyUqeWpqrItw2vkMFsdY/edit @@ -316,11 +290,11 @@ int parse_special_frame_stream(struct quic_info* quic_info, const char *payload, return PARSE_RESULT_VERSION; } - if(quic_info->client_hello==NULL) - { - quic_info->client_hello=(struct quic_client_hello *)dictator_malloc(thread_seq, sizeof(struct quic_client_hello)); - memset(quic_info->client_hello, 0, sizeof(struct quic_client_hello)); - } + // if(quic_info->client_hello==NULL) + // { + // quic_info->client_hello=(struct quic_client_hello *)CALLOC(1, sizeof(struct quic_client_hello)); + // memset(quic_info->client_hello, 0, sizeof(struct quic_client_hello)); + // } tag_value_start_offset=payload_offset+tag_num*4*2; // skip length of type and offset, type(offset)=szieof(int) @@ -341,11 +315,11 @@ int parse_special_frame_stream(struct quic_info* quic_info, const char *payload, switch(ext_tag_type) { case TAG_UAID: - copy_extension_tag(payload+tag_value_start_offset, one_tag_len, &quic_info->client_hello->user_agent, thread_seq); + copy_extension_tag(payload+tag_value_start_offset, one_tag_len, &quic_info->user_agent, thread_seq); parse_result=PARSE_RESULT_CLIENT_HELLO; break; case TAG_SNI: - copy_extension_tag(payload+tag_value_start_offset, one_tag_len, &quic_info->client_hello->sni, thread_seq); + copy_extension_tag(payload+tag_value_start_offset, one_tag_len, &quic_info->sni, thread_seq); parse_result=PARSE_RESULT_CLIENT_HELLO; break; default: @@ -361,7 +335,7 @@ int parse_special_frame_stream(struct quic_info* quic_info, const char *payload, return parse_result; } -int parse_quic_transport_parameter(struct quic_client_hello *client_hello, const char *quic_para, int quic_para_len, int thread_seq) +int parse_quic_transport_parameter(struct quic_info *quic_info, const char *quic_para, int quic_para_len, int thread_seq) { int one_para_length=0; int para_offset=0; @@ -378,7 +352,7 @@ int parse_quic_transport_parameter(struct quic_client_hello *client_hello, const { return 0; } - para_offset+=copy_extension_tag(quic_para+para_offset, one_para_length, &client_hello->user_agent, thread_seq); + para_offset+=copy_extension_tag(quic_para+para_offset, one_para_length, &quic_info->user_agent, thread_seq); return 1; default: one_para_length=(int)(quic_para[para_offset++]); // length=1 @@ -394,7 +368,7 @@ int parse_quic_transport_parameter(struct quic_client_hello *client_hello, const return 0; } -int parse_extension_server_name(struct quic_client_hello *client_hello, const char *ext_server_name, int ext_server_name_length, int thread_seq) +int parse_extension_server_name(struct quic_info *quic_info, const char *ext_server_name, int ext_server_name_length, int thread_seq) { unsigned short sni_type=0; unsigned short sni_length=0; @@ -421,12 +395,12 @@ int parse_extension_server_name(struct quic_client_hello *client_hello, const ch } extension_offset+=2; - copy_extension_tag(ext_server_name+extension_offset, sni_length, &client_hello->sni, thread_seq); + copy_extension_tag(ext_server_name+extension_offset, sni_length, &quic_info->sni, thread_seq); return 1; } -int parse_tls_client_hello(struct quic_client_hello **client_hello, const char *payload, int payload_len, int thread_seq) +int parse_tls_client_hello(struct quic_info *quic_info, const char *payload, int payload_len, int thread_seq) { int ret=0,skip_len=0; int payload_offset=0; @@ -472,11 +446,11 @@ int parse_tls_client_hello(struct quic_client_hello **client_hello, const char * payload_offset+=2; - if(*client_hello==NULL) - { - *client_hello=(struct quic_client_hello *)dictator_malloc(thread_seq, sizeof(struct quic_client_hello)); - memset(*client_hello, 0, sizeof(struct quic_client_hello)); - } + // if(*client_hello==NULL) + // { + // *client_hello=(struct quic_client_hello *)CALLOC(1, sizeof(struct quic_client_hello)); + // // memset(*client_hello, 0, sizeof(struct quic_client_hello)); + // } extension_start_pos=payload+payload_offset; @@ -496,11 +470,11 @@ int parse_tls_client_hello(struct quic_client_hello **client_hello, const char * switch(one_ext_type) { case EXTENSION_SERVER_NAME: - ret=parse_extension_server_name(*client_hello, extension_start_pos+extension_offset, one_ext_len, thread_seq); + ret=parse_extension_server_name(quic_info, extension_start_pos+extension_offset, one_ext_len, thread_seq); break; case EXTENSION_QUIC_PARAM_TLS_13: case EXTENSION_QUIC_PARAM_TLS_33: - ret=parse_quic_transport_parameter(*client_hello, extension_start_pos+extension_offset, one_ext_len, thread_seq); + ret=parse_quic_transport_parameter(quic_info, extension_start_pos+extension_offset, one_ext_len, thread_seq); break; default: break; @@ -538,7 +512,7 @@ int parse_quic_decrypted_payload(struct quic_info *quic_info, const char * paylo if(join_payload[0] == QUIC_HANDSHAKE_TYPE_CLIENTHELLO) { - return parse_tls_client_hello(&(quic_info->client_hello), join_payload, join_payload_len, thread_seq); + return parse_tls_client_hello(quic_info, join_payload, join_payload_len, thread_seq); } } else //if(quic_version>=GQUIC_VERSION_Q047 && quic_version<=GQUIC_VERSION_Q059) @@ -645,11 +619,11 @@ int parse_quic_uncryption_payload(struct quic_info *quic_info, const char * payl +--------+--------+--------+--------+--------+--------+ */ -enum QUIC_VERSION identify_gquic_version0to43(const char *payload, int payload_len, int *payload_offset) +enum QUIC_VERSION_T identify_gquic_version0to43(const char *payload, int payload_len, int *payload_offset) { unsigned char pkn_length=0; unsigned char public_flags=0; - enum QUIC_VERSION quic_version=QUIC_VERSION_UNKNOWN; + enum QUIC_VERSION_T quic_version=QUIC_VERSION_UNKNOWN; public_flags=payload[*payload_offset]; *payload_offset+=1; @@ -671,7 +645,7 @@ enum QUIC_VERSION identify_gquic_version0to43(const char *payload, int payload_l if(public_flags&GQUIC_PUBLIC_FLAG_VERSION && (*(unsigned char *)(payload+*payload_offset)==0x51)) { - quic_version=(enum QUIC_VERSION)ntohl(*(unsigned int *)(payload+*payload_offset)); + quic_version=(enum QUIC_VERSION_T)ntohl(*(unsigned int *)(payload+*payload_offset)); *payload_offset+=sizeof(int); // skip version } @@ -708,9 +682,9 @@ enum QUIC_VERSION identify_gquic_version0to43(const char *payload, int payload_l return quic_version; } -enum QUIC_VERSION identify_quic_version(const char *payload, int payload_len, int *payload_offset) +enum QUIC_VERSION_T identify_quic_version(const char *payload, int payload_len, int *payload_offset) { - enum QUIC_VERSION quic_version=(enum QUIC_VERSION)ntohl(*(unsigned int *)(payload+(*payload_offset+1))); + enum QUIC_VERSION_T quic_version=(enum QUIC_VERSION_T)ntohl(*(unsigned int *)(payload+(*payload_offset+1))); if(quic_version>=GQUIC_VERSION_Q044 && quic_version<=GQUIC_VERSION_Q048) { parse_gquic_version_44to48_header(payload, payload_len, payload_offset); @@ -741,9 +715,9 @@ enum QUIC_VERSION identify_quic_version(const char *payload, int payload_len, in return QUIC_VERSION_UNKNOWN; } -enum QUIC_VERSION is_quic_protocol(const char *payload, int payload_len, int *payload_offset) +enum QUIC_VERSION_T is_quic_protocol(const char *payload, int payload_len, int *payload_offset) { - enum QUIC_VERSION quic_version=QUIC_VERSION_UNKNOWN; + enum QUIC_VERSION_T quic_version=QUIC_VERSION_UNKNOWN; unsigned char frame_type=(unsigned char)(payload[0]); if(payload_len<=4) @@ -767,40 +741,39 @@ enum QUIC_VERSION is_quic_protocol(const char *payload, int payload_len, int *pa return quic_version; } -unsigned char parse_quic_all_version(struct quic_info *quic_info, const char *payload, int payload_len, int thread_seq) +enum PARSE_RESULT parse_quic_all_version(const struct quic_param *g_quic_plugin_env, struct quic_info *quic_info, const char *payload, int payload_len, int thread_seq) { - int ret=0, payload_offset=0; - enum QUIC_VERSION quic_version=QUIC_VERSION_UNKNOWN; + int ret = 0, payload_offset = 0; + enum QUIC_VERSION_T quic_version = QUIC_VERSION_UNKNOWN; - if(payload==NULL || payload_len<=0) + if (payload == NULL || payload_len <= 0) { return PARSE_RESULT_UNKNOWN; } - - quic_version=is_quic_protocol(payload, payload_len, &payload_offset); - if(quic_version==QUIC_VERSION_UNKNOWN) + + quic_version = is_quic_protocol(payload, payload_len, &payload_offset); + if (quic_version == QUIC_VERSION_UNKNOWN) { return PARSE_RESULT_UNKNOWN; } - - quic_info->quic_version=quic_version; - - if(quic_version>=GQUIC_VERSION_Q001 && quic_version<=GQUIC_VERSION_Q048) + + quic_info->quic_version = quic_version; + + if (quic_version >= GQUIC_VERSION_Q001 && quic_version <= GQUIC_VERSION_Q048) { - if(payload_len > payload_offset) + if (payload_len > payload_offset) { - return parse_quic_uncryption_payload(quic_info, payload+payload_offset, payload_len-payload_offset, thread_seq); + return (enum PARSE_RESULT)parse_quic_uncryption_payload(quic_info, payload + payload_offset, payload_len - payload_offset, thread_seq); } return PARSE_RESULT_VERSION; } - else if(((quic_version>=MVFST_VERSION_00 && quic_version<=MVFST_VERSION_0F) || - (quic_version>=GQUIC_VERSION_Q049 && quic_version<=GQUIC_VERSION_Q059) || - (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) || - (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) || - (quic_version>=IQUIC_VERSION_I022 && quic_version<=IQUIC_VERSION_I029) || - (quic_version==IQUIC_VERSION_RFC9000)) - && g_quic_param.decrypted_switch>0 - ) + else if (((quic_version >= MVFST_VERSION_00 && quic_version <= MVFST_VERSION_0F) || + (quic_version >= GQUIC_VERSION_Q049 && quic_version <= GQUIC_VERSION_Q059) || + (quic_version >= GQUIC_VERSION_T050 && quic_version <= GQUIC_VERSION_T059) || + (quic_version >= GQUIC_VERSION_T050 && quic_version <= GQUIC_VERSION_T059) || + (quic_version >= IQUIC_VERSION_I022 && quic_version <= IQUIC_VERSION_I029) || + (quic_version == IQUIC_VERSION_RFC9000)) && + g_quic_plugin_env->decrypted_switch > 0) { quic_dpt_t *dpt = quic_deprotection_new(); if (quic_deprotection(dpt, (const u_char *)payload, payload_len) != 0) @@ -809,11 +782,11 @@ unsigned char parse_quic_all_version(struct quic_info *quic_info, const char *pa return PARSE_RESULT_VERSION; } - if(g_quic_param.decrypted_switch==2) + if (g_quic_plugin_env->decrypted_switch == 2) { - ret = parse_quic_decrypted_payload(quic_info, (const char *)dpt->payload.data, dpt->payload.len, thread_seq); + ret = parse_quic_decrypted_payload(quic_info, (const char *)dpt->payload.data, dpt->payload.len, thread_seq); quic_deprotection_free(dpt); - return ret; + return (enum PARSE_RESULT)ret; } quic_deprotection_free(dpt); } @@ -821,106 +794,121 @@ unsigned char parse_quic_all_version(struct quic_info *quic_info, const char *pa { return PARSE_RESULT_VERSION; } - + return PARSE_RESULT_VERSION; } - -unsigned char quic_analyze_entry(const struct streaminfo *pstream, struct quic_context* context, int thread_seq, const void* a_packet) +void quic_analyze_entry(struct session *sess, const struct quic_param *g_quic_plugin_env, struct quic_context *qcontext, int thread_seq, const char *payload, size_t payload_len) { - unsigned char parse_result=PARSE_RESULT_UNKNOWN; - char state=APP_STATE_GIVEME; + struct quic_message *qmsg; + int push_payload = 0; + enum PARSE_RESULT parse_res = PARSE_RESULT_UNKNOWN; - if(pstream==NULL || pstream->pudpdetail==NULL || context==NULL) - { - return APP_STATE_DROPME; - } + if ((qcontext->parse_pkt_cnt++) >= g_quic_plugin_env->max_parse_pkt_num){ + push_payload = 1; + }else{ + if(0 == qcontext->msg_state[QUIC_VERSION] + || 0 == qcontext->msg_state[QUIC_SNI] + || 0 == qcontext->msg_state[QUIC_USER_AGENT]){ + if(NULL == qcontext->quic_info.sni.str + || NULL == qcontext->quic_info.user_agent.str){ + parse_res = parse_quic_all_version(g_quic_plugin_env, &(qcontext->quic_info), payload, payload_len, thread_seq); + if(PARSE_RESULT_VERSION == parse_res){ + push_payload = 1; + } + } - struct udpdetail *udp_detail=pstream->pudpdetail; - - switch(context->pre_parse_state) - { - case PARSE_RESULT_CLIENT_HELLO: - parse_result=PARSE_RESULT_PAYLOAD; - break; - case PARSE_RESULT_VERSION: - parse_result=parse_quic_all_version(&(context->quic_info), (const char *)udp_detail->pdata, udp_detail->datalen, thread_seq); - if(parse_result==PARSE_RESULT_VERSION || parse_result==PARSE_RESULT_UNKNOWN) - { - parse_result=PARSE_RESULT_PAYLOAD; + if((0 == qcontext->msg_state[QUIC_VERSION]) && (qcontext->quic_info.quic_version != 0)){ + qmsg = quic_create_message(QUIC_VERSION, qcontext); + quic_session_mq_publish_message_safe(sess, g_quic_plugin_env->quic_topic_id, qmsg); + qcontext->msg_state[QUIC_VERSION] = 1; } - break; - case PARSE_RESULT_PAYLOAD: - case PARSE_RESULT_UNKNOWN: - default: - if(context->parse_first_pkt==1) - { - context->parse_first_pkt=0; - if(context->quic_info.client_hello==NULL) - { - parse_result=PARSE_RESULT_VERSION; - } - else - { - parse_result=PARSE_RESULT_CLIENT_HELLO; - } - break; + if((0 == qcontext->msg_state[QUIC_SNI]) && qcontext->quic_info.sni.str){ + qmsg = quic_create_message(QUIC_SNI, qcontext); + quic_session_mq_publish_message_safe(sess, g_quic_plugin_env->quic_topic_id, qmsg); + qcontext->msg_state[QUIC_SNI] = 1; } - - if((context->parse_pkt_cnt++)>=g_quic_param.max_parse_pkt_num) - { - parse_result=PARSE_RESULT_PAYLOAD; - break; + if((0 == qcontext->msg_state[QUIC_USER_AGENT]) && qcontext->quic_info.user_agent.str){ + qmsg = quic_create_message(QUIC_USER_AGENT, qcontext); + quic_session_mq_publish_message_safe(sess, g_quic_plugin_env->quic_topic_id, qmsg); + qcontext->msg_state[QUIC_USER_AGENT] =1; } - parse_result=parse_quic_all_version(&(context->quic_info), (const char *)udp_detail->pdata, udp_detail->datalen, thread_seq); - break; + } } - switch(parse_result) - { - case PARSE_RESULT_VERSION: - context->pre_parse_state=PARSE_RESULT_VERSION; - state=quic_call_business_plug(pstream, context, (void *)&(context->quic_info.quic_version), sizeof(unsigned int), QUIC_USEING_VERSION_MASK, a_packet); - break; - case PARSE_RESULT_CLIENT_HELLO: - context->pre_parse_state=PARSE_RESULT_CLIENT_HELLO; - state=quic_call_business_plug(pstream, context, (void *)&(context->quic_info), sizeof(void *), QUIC_CLIENT_HELLO_MASK, a_packet); - break; - case PARSE_RESULT_PAYLOAD: - state=quic_call_business_plug(pstream, context, udp_detail->pdata, udp_detail->datalen, QUIC_APPLICATION_DATA_MASK, a_packet); - break; - default: - return APP_STATE_DROPME; - break; + if(push_payload){ + qcontext->quic_info.payload.str = payload; + qcontext->quic_info.payload.str_len = payload_len; + qmsg = quic_create_message(QUIC_PAYLOAD, qcontext); + quic_session_mq_publish_message_safe(sess, g_quic_plugin_env->quic_topic_id, qmsg); } - return state; + return; } -struct quic_info *quic_protocol_identify(const struct streaminfo *a_stream) +void quic_session_mq_publish_message_safe(struct session *sess, int topic_id, void *msg) { - if(!is_quic_port(a_stream) || a_stream==NULL || a_stream->pudpdetail==NULL) - { - return NULL; + int ret = session_mq_publish_message(sess, topic_id, msg); + if(ret < 0){ + FREE(msg); } - - struct quic_info tmp_quic_info={0, NULL}; - unsigned char parse_result=APP_STATE_GIVEME; - - parse_result=parse_quic_all_version(&tmp_quic_info, (const char *)a_stream->pudpdetail->pdata, a_stream->pudpdetail->datalen, a_stream->threadnum); - if(parse_result!=PARSE_RESULT_UNKNOWN) - { - struct quic_context *context=(struct quic_context *)dictator_malloc(a_stream->threadnum, sizeof(struct quic_context)); - memset(context, 0, sizeof(struct quic_context)); - context->quic_info=tmp_quic_info; - context->parse_first_pkt=1; - context->pre_parse_state=PARSE_RESULT_UNKNOWN; - - stream_bridge_async_data_put(a_stream, g_quic_param.context_bridge_id, (void *)context); - - return &(context->quic_info); - } - - return NULL; + return; +} +struct quic_message *quic_create_message(enum quic_message_type mtype, struct quic_context *context) +{ + struct quic_message *msg = (struct quic_message *)CALLOC(1, sizeof(struct quic_message)); + msg->magic = QUIC_MSG_HDR_MAGIC; + msg->type = mtype; + msg->qctx = context; + return msg; } +#ifdef __cplusplus +extern "C" +{ +#endif +enum quic_message_type quic_message_type_get(const struct quic_message *msg) +{ + assert(QUIC_MSG_HDR_MAGIC == msg->magic); + if(QUIC_MSG_HDR_MAGIC != msg->magic){ + return QUIC_MSG_MAX; + } + return msg->type; +} + +void quic_message_get_version(const struct quic_message *msg, unsigned int *result) +{ + assert(QUIC_MSG_HDR_MAGIC == msg->magic); + if(result){ + *result = msg->qctx->quic_info.quic_version; + } +} +void quic_message_get_sni(const struct quic_message *msg, struct qstring *result) +{ + assert(QUIC_MSG_HDR_MAGIC == msg->magic); + if(result){ + result->str = msg->qctx->quic_info.sni.str; + result->str_len = msg->qctx->quic_info.sni.str_len; + } +} +void quic_message_get_user_agent(const struct quic_message *msg, struct qstring *result) +{ + assert(QUIC_MSG_HDR_MAGIC == msg->magic); + if(result){ + result->str = msg->qctx->quic_info.user_agent.str; + result->str_len = msg->qctx->quic_info.user_agent.str_len; + } + +} +void quic_message_get_payload(const struct quic_message *msg, struct qstring *result) +{ + assert(QUIC_MSG_HDR_MAGIC == msg->magic); + if(result){ + result->str = msg->qctx->quic_info.payload.str; + result->str_len = msg->qctx->quic_info.payload.str_len; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/src/quic_process.h b/src/quic_process.h index c0583c6..26c7f8b 100644 --- a/src/quic_process.h +++ b/src/quic_process.h @@ -109,7 +109,7 @@ #define EXT_QUIC_PARAM_QUIC_VERSION 0x4752 //https://github.com/quicwg/base-drafts/wiki/QUIC-Versions -enum QUIC_VERSION +enum QUIC_VERSION_T { QUIC_VERSION_UNKNOWN=0, //NetApp @@ -279,19 +279,53 @@ enum QUIC_VERSION IQUIC_VERSION_I032=0xFF000020 }; +// struct quic_client_hello +// { +// char *sni; +// char *user_agent; +// }; + +struct quic_info +{ + unsigned int quic_version; + struct qstring sni; + struct qstring user_agent; + struct qstring payload; + // struct quic_client_hello *client_hello; +}; + struct quic_context { unsigned char link_state; unsigned char parse_pkt_cnt; unsigned char pre_parse_state; unsigned char parse_first_pkt; - unsigned char padding[4]; - void *business_pme; + unsigned char msg_state[QUIC_MSG_MAX]; struct quic_info quic_info; }; -unsigned char quic_analyze_entry(const struct streaminfo *pstream, struct quic_context* context, int thread_seq, const void* a_packet); -unsigned char quic_call_business_plug(const struct streaminfo *pstream, struct quic_context *context, void *buff, int buff_len, enum quic_interested_region region_mask, const void *a_packet); +#define QUIC_MSG_HDR_MAGIC 0x51554943 // ASCII: "QUIC" +struct quic_message +{ + unsigned int magic; + enum quic_message_type type; + struct quic_context *qctx; +}; +enum PARSE_RESULT +{ + PARSE_RESULT_UNKNOWN, + PARSE_RESULT_VERSION, + PARSE_RESULT_CLIENT_HELLO, + PARSE_RESULT_PAYLOAD, + PARSE_RESULT_MAX +}; + +enum PARSE_RESULT parse_quic_all_version(const struct quic_param *g_quic_plugin_env, struct quic_info *quic_info, const char *payload, int payload_len, int thread_seq); +void quic_analyze_entry(struct session *sess, const struct quic_param *g_quic_plug_env, struct quic_context* context, int thread_seq, const char *payload, size_t payload_len); +// unsigned char quic_call_business_plug(const struct streaminfo *pstream, struct quic_context *context, void *buff, int buff_len, enum quic_interested_region region_mask, const void *a_packet); +int quic_protocol_identify(struct session *sess, struct quic_param *g_quic_plug_env); +struct quic_message *quic_create_message(enum quic_message_type mtype, struct quic_context *context); +void quic_session_mq_publish_message_safe(struct session *sess, int topic_id, void *msg); #endif diff --git a/src/quic_util.h b/src/quic_util.h new file mode 100644 index 0000000..e147e23 --- /dev/null +++ b/src/quic_util.h @@ -0,0 +1,5 @@ +#pragma once + +#define CALLOC(nmemb, size) calloc(nmemb, size) +#define REALLOC(ptr, newsize) realloc(ptr, newsize) +#define FREE(p) {free((void *)p); p = NULL;} \ No newline at end of file diff --git a/src/quic_version.cpp b/src/quic_version.cpp index fb83d08..100ce0b 100644 --- a/src/quic_version.cpp +++ b/src/quic_version.cpp @@ -3,7 +3,10 @@ #include "quic.h" #include "quic_process.h" - +#ifdef __cplusplus +extern "C" +{ +#endif int quic_version_int2string(unsigned int version, char *buff, int buff_len) { if(version>=GQUIC_VERSION_Q001 && version<=GQUIC_VERSION_Q099) @@ -82,3 +85,6 @@ int quic_version_int2string(unsigned int version, char *buff, int buff_len) return 0; } +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/version.map b/src/version.map index 1906265..db590f0 100644 --- a/src/version.map +++ b/src/version.map @@ -1,9 +1,10 @@ -VERS_2.4{ +VERS_3.0{ global: - extern "C++" { - QUIC_*; - *quic_version_int2string*; - *quic_protocol_identify*; + extern "C" { + QUIC_ONLOAD; + QUIC_UNLOAD; + quic_version_int2string; + quic_message_*; }; local: *; }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fe765b6..990cd1c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required (VERSION 2.8...3.10) -set(lib_name quic) project(${lib_name}_test) include(ExternalProject) @@ -9,18 +8,14 @@ include(ExternalProject) ExternalProject_Add(ProtoTest PREFIX ProtoTest URL ${CMAKE_CURRENT_SOURCE_DIR}/test_protocol_run.zip - URL_MD5 71d8284b59af0286b5f31f0a3160bc44 + URL_MD5 4b181e88dccdd1ec59a22a16ab8c5051 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/${lib_name}.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/) + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/bin/main.conf /conf/${lib_name}/main.conf + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/bin/${lib_name}.conf /conf/${lib_name}) ExternalProject_Get_Property(ProtoTest INSTALL_DIR) ExternalProject_Get_Property(ProtoTest SOURCE_DIR) @@ -30,13 +25,16 @@ 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_QUIC_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 COPY_QUIC_SO COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/src/${lib_name}.so ${PROTO_TEST_RUN_DIR}/stellar_plugin/${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}/stellar_plugin/${lib_name}_test_plug.so") + +set_tests_properties(COPY_QUIC_SO COPY_TEST_SO + PROPERTIES FIXTURES_SETUP TestFixture) + add_test(NAME IQUIC_29_TEST COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/iquic/29//${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/iquic/29/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) add_test(NAME GQUIC_23_TEST COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/gquic/23/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/gquic/23/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) add_test(NAME GQUIC_25_TEST COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/gquic/25/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/gquic/25/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) @@ -59,3 +57,28 @@ add_test(NAME QUIC_RFC9000_FRAGMENT COMMAND proto_test_main ${CMAKE_CURRENT_SOUR add_test(NAME QUIC_RFC9000_SPECIAL COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/rfc9000-special/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/rfc9000-special/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) add_test(NAME QUIC_AIRPORT COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/airport/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/airport -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) add_test(NAME QUIC_SPECIAL COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/special/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/special/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) + +set_tests_properties(IQUIC_29_TEST + GQUIC_23_TEST + GQUIC_25_TEST + GQUIC_33_TEST + GQUIC_34_TEST + GQUIC_35_TEST + GQUIC_37_TEST + GQUIC_39_TEST + GQUIC_41_TEST + GQUIC_43_TEST + GQUIC_44_TEST + GQUIC_46_TEST + GQUIC_50_TEST + MVFST_01_TEST + MVFST_01_TEST + MVFST_02_TEST + TQUIC_TEST + IQUIC_PORT_8443_TEST + QUIC_RFC9000 + QUIC_RFC9000_FRAGMENT + QUIC_RFC9000_SPECIAL + QUIC_AIRPORT + QUIC_SPECIAL + PROPERTIES FIXTURES_REQUIRED TestFixture) \ No newline at end of file diff --git a/test/quic_test_plug.cpp b/test/quic_test_plug.cpp index ab89087..2d93e7f 100644 --- a/test/quic_test_plug.cpp +++ b/test/quic_test_plug.cpp @@ -3,101 +3,135 @@ * create time:2021-8-21 * */ - #include -#include +#include +#include #include #include - #include "cJSON.h" + +#ifdef __cplusplus +extern "C" +{ +#endif #include "quic.h" -#include "MESA_prof_load.h" -#include +#include +#include +#include +#include extern "C" int commit_test_result_json(cJSON *node, const char *name); +extern "C" int quic_version_int2string(unsigned int version, char *buff, int buff_len); static int g_result_count = 1; -extern "C" unsigned char QUIC_TEST_PLUG_ENTRY(stSessionInfo *session_info, void **pme, - int thread_seq, struct streaminfo *a_tcp, void *a_packet) +#if 0 +#define DEBUG_PRINT(fmt, args...) fprintf(stderr, fmt, ##args) +#else +#define DEBUG_PRINT(fmt, args...) +#endif + +struct quic_gtest_context { - assert(NULL != session_info || pme != NULL); - - cJSON *ctx = (cJSON *)*pme; - struct quic_info *quic_info=NULL; - char version_str[128]={0}; - unsigned int version = 0; - - 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)); - } - } - - switch (session_info->prot_flag) - { - case QUIC_CLIENT_HELLO: - if (session_info == NULL || session_info->app_info == NULL) - { - break; - } - quic_info = (struct quic_info *)session_info->app_info; - if(quic_info->client_hello==NULL) - { - break; - } - if(quic_info->client_hello->sni!=NULL) - { - cJSON_AddStringToObject(ctx, "SNI", (char *)(quic_info->client_hello->sni)); - } - if(quic_info->client_hello->user_agent!=NULL) - { - cJSON_AddStringToObject(ctx, "UA", (char *)(quic_info->client_hello->user_agent)); - } - - quic_version_int2string((unsigned int)(quic_info->quic_version), version_str, sizeof(version_str)); - cJSON_AddStringToObject(ctx, "VERSION", version_str); - break; - case QUIC_USEING_VERSION: - version = *(unsigned int *)(session_info->buf); - quic_version_int2string(version, version_str, sizeof(version_str)); - cJSON_AddStringToObject(ctx, "VERSION", version_str); - break; - default: - break; - } - - if(session_info->session_state&SESSION_STATE_CLOSE) - { - if(ctx) - { - char result_name[16]=""; - sprintf(result_name,"QUIC_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; + cJSON *json_root; +}; +static void cJSON_Add_QStringToObject(cJSON * object, const char *name, const struct qstring * qstring) +{ + char *tmp = (char *)calloc(1, qstring->str_len + 1); + memcpy(tmp, qstring->str, qstring->str_len); + cJSON_AddStringToObject(object, name, tmp); } -extern "C" int QUIC_TEST_PLUG_INIT() +extern "C" void QUIC_TEST_PLUG_ENTRY(struct session *sess, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env) { - return 0; + struct quic_gtest_context *qctx = (struct quic_gtest_context *)per_session_ctx; + struct quic_message *qmsg = (struct quic_message *)msg; + enum quic_message_type mtype = quic_message_type_get(qmsg); + + DEBUG_PRINT("### QUIC_TEST_PLUG_ENTRY: mtype=%d\n", (int)mtype); + + switch(mtype){ + case QUIC_NEW: + qctx->json_root = cJSON_CreateObject(); + cJSON_AddStringToObject(qctx->json_root, "Tuple4", session_get0_readable_addr(sess)); + break; + + case QUIC_VERSION: + { + unsigned int version_int = 0; + char version_str[128]={0}; + quic_message_get_version(qmsg, &version_int); + assert(version_int != 0); + quic_version_int2string(version_int, version_str, sizeof(version_str)); + cJSON_AddStringToObject(qctx->json_root, "VERSION", version_str); + DEBUG_PRINT("### QUIC_TEST_PLUG_ENTRY: version=%x, str_version=%s\n", version_int, version_str); + } + break; + + case QUIC_SNI: + { + struct qstring result = {}; + quic_message_get_sni(qmsg, &result); + cJSON_Add_QStringToObject(qctx->json_root, "SNI", &result); + DEBUG_PRINT("### QUIC_TEST_PLUG_ENTRY: len=%d, SNI=%p, %.*s\n", (int)result.str_len, result.str, (int)result.str_len, result.str); + } + break; + + case QUIC_USER_AGENT: + { + struct qstring result = {}; + quic_message_get_user_agent(qmsg, &result); + cJSON_Add_QStringToObject(qctx->json_root, "UA", &result); + DEBUG_PRINT("### QUIC_TEST_PLUG_ENTRY: len=%d, UA=%p, %.*s\n", (int)result.str_len, result.str, (int)result.str_len, result.str); + } + break; + + case QUIC_FREE: + { + char result_name[16]=""; + sprintf(result_name,"QUIC_RESULT_%d", g_result_count); + commit_test_result_json(qctx->json_root, result_name); + g_result_count+=1; + } + break; + default: + break; + } + + return ; } -extern "C" void QUIC_TEST_PLUG_DESTROY(void) +extern "C" void *quic_gtest_plug_session_ctx_new_cb(struct session *sess, void *plugin_env) +{ + struct quic_gtest_context *ctx = (struct quic_gtest_context *)calloc(1, sizeof(struct quic_gtest_context)); + return ctx; +} + +extern "C" void quic_gtest_session_ctx_free_cb(struct session *sess, void *session_ctx, void *plugin_env) +{ + free(session_ctx); +} + +extern "C" void *QUIC_TEST_PLUG_INIT(struct stellar *st) +{ + void *fake_quic_gtest_plugin_env = (void *)"_fake_plugin_env_"; + int quic_gtest_plug_id = stellar_session_plugin_register(st, quic_gtest_plug_session_ctx_new_cb, quic_gtest_session_ctx_free_cb, fake_quic_gtest_plugin_env); + int quic_topic_id = stellar_session_mq_get_topic_id(st, QUIC_DECODER_TOPIC); + assert(quic_topic_id >= 0); + stellar_session_mq_subscribe(st, quic_topic_id, QUIC_TEST_PLUG_ENTRY, quic_gtest_plug_id); + + return fake_quic_gtest_plugin_env; +} + +extern "C" void QUIC_TEST_PLUG_DESTROY(void *plugin_env) { return ; } +#ifdef __cplusplus +} +#endif + diff --git a/test/test_protocol_run.zip b/test/test_protocol_run.zip index 996f3fa..ff84974 100644 Binary files a/test/test_protocol_run.zip and b/test/test_protocol_run.zip differ