diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71cd089cb..0b9665755 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,7 +61,7 @@ jobs: SSL_LIB_PATH_STR="${PWD}/third_party/boringssl/build/ssl/libssl.a;${PWD}/third_party/boringssl/build/crypto/libcrypto.a" mkdir -p build cd build - cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_DISABLE_RENO=0 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. + cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. make -j - name: Test diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 158ba07b2..6445f8af7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -60,7 +60,7 @@ jobs: SSL_LIB_PATH_STR="${PWD}/third_party/boringssl/build/ssl/libssl.a;${PWD}/third_party/boringssl/build/crypto/libcrypto.a" mkdir -p build cd build - cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_DISABLE_RENO=0 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. + cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. make -j - name: Perform CodeQL Analysis diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c87c6e3d..304b635d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,12 @@ set (xquic_VERSION_MAJOR 0) set (xquic_VERSION_MINOR 1) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -# build type +option (XQC_ENABLE_BBR2 "enable bbr2" ON) +option (XQC_ENABLE_COPA "enable copa" ON) +option (XQC_ENABLE_RENO "enable reno" ON) +option (XQC_ENABLE_UNLIMITED "enable unlimited cc" ON) +option (XQC_ENABLE_MP_INTEROP "enable MPQUIC interop" ON) + if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() @@ -74,6 +79,9 @@ if(XQC_COMPAT_DUPLICATE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_COMPAT_DUPLICATE") endif() +if(XQC_COMPAT_GENERATE_SR_PKT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_COMPAT_GENERATE_SR_PKT") +endif() # print only error log if(XQC_ONLY_ERROR_LOG) @@ -116,8 +124,8 @@ endif() # configure file configure_file ( - xqc_configure.h.in - xqc_configure.h + "${CMAKE_CURRENT_SOURCE_DIR}/xqc_configure.h.in" + "${CMAKE_CURRENT_SOURCE_DIR}/include/xquic/xqc_configure.h" ) include_directories( @@ -127,8 +135,6 @@ include_directories( "${CMAKE_CURRENT_BINARY_DIR}/include" ) - - # http3/qpack source set( HTTP3_SOURCES @@ -185,9 +191,16 @@ set( "src/transport/scheduler/xqc_scheduler_common.c" "src/transport/scheduler/xqc_scheduler_backup.c" "src/transport/scheduler/xqc_scheduler_rap.c" - "src/transport/scheduler/xqc_scheduler_interop.c" ) +if(XQC_ENABLE_MP_INTEROP) + set( + TRANSPORT_SOURCES + ${TRANSPORT_SOURCES} + "src/transport/scheduler/xqc_scheduler_interop.c" + ) +endif() + # TLS source set ( TLS_SOURCE @@ -240,15 +253,11 @@ set( CONGESTION_CONTROL_SOURCES "src/congestion_control/xqc_cubic.c" "src/congestion_control/xqc_bbr.c" - "src/congestion_control/xqc_unlimited_cc.c" - "src/congestion_control/xqc_copa.c" "src/congestion_control/xqc_window_filter.c" "src/congestion_control/xqc_sample.c" ) -if(XQC_DISABLE_RENO) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_DISABLE_RENO ") -else() +if(XQC_ENABLE_RENO) set( CONGESTION_CONTROL_SOURCES ${CONGESTION_CONTROL_SOURCES} @@ -257,15 +266,30 @@ else() endif() if(XQC_ENABLE_BBR2) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_ENABLE_BBR2 ") set( CONGESTION_CONTROL_SOURCES - ${CONGESTION_CONTROL_SOURCES} "src/congestion_control/xqc_bbr2.c" ) endif() +if(XQC_ENABLE_COPA) + set( + CONGESTION_CONTROL_SOURCES + ${CONGESTION_CONTROL_SOURCES} + "src/congestion_control/xqc_copa.c" + ) +endif() + +if(XQC_ENABLE_UNLIMITED) + set( + CONGESTION_CONTROL_SOURCES + ${CONGESTION_CONTROL_SOURCES} + "src/congestion_control/xqc_unlimited_cc.c" + ) +endif() + + # xquic source set ( XQC_SOURCE @@ -392,13 +416,13 @@ if (XQC_ENABLE_TESTING) endif() if(PLATFORM STREQUAL "mac32") - target_link_libraries(test_server xquic -lm ${CMAKE_CURRENT_SOURCE_DIR}/../libevent32/lib/libevent.dylib) - target_link_libraries(test_client xquic -lm ${CMAKE_CURRENT_SOURCE_DIR}/../libevent32/lib/libevent.dylib) + target_link_libraries(test_server xquic-static ${SSL_LIB_PATH} -ldl -lpthread -lm ${CMAKE_CURRENT_SOURCE_DIR}/../libevent32/lib/libevent.dylib) + target_link_libraries(test_client xquic-static ${SSL_LIB_PATH} -ldl -lpthread -lm ${CMAKE_CURRENT_SOURCE_DIR}/../libevent32/lib/libevent.dylib) target_link_libraries(demo_server xquic -lm ${CMAKE_CURRENT_SOURCE_DIR}/../libevent32/lib/libevent.dylib) target_link_libraries(demo_client xquic -lm ${CMAKE_CURRENT_SOURCE_DIR}/../libevent32/lib/libevent.dylib) elseif(PLATFORM STREQUAL "mac") - target_link_libraries(test_server xquic -lm -L/usr/local/lib -levent) - target_link_libraries(test_client xquic -lm -L/usr/local/lib -levent) + target_link_libraries(test_server xquic-static ${SSL_LIB_PATH} -ldl -lpthread -lm -L/usr/local/lib -levent) + target_link_libraries(test_client xquic-static ${SSL_LIB_PATH} -ldl -lpthread -lm -L/usr/local/lib -levent) target_link_libraries(demo_server xquic -lm -L/usr/local/lib -levent) target_link_libraries(demo_client xquic -lm -L/usr/local/lib -levent) elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") @@ -407,8 +431,8 @@ if (XQC_ENABLE_TESTING) target_link_libraries(demo_server xquic ${EVENT_LIB_PATH} -lm) target_link_libraries(demo_client xquic ${EVENT_LIB_PATH} -lm) else() - target_link_libraries(test_server xquic -levent -lm) - target_link_libraries(test_client xquic -levent -lm) + target_link_libraries(test_server xquic-static ${SSL_LIB_PATH} -ldl -lpthread -levent -lm) + target_link_libraries(test_client xquic-static ${SSL_LIB_PATH} -ldl -lpthread -levent -lm) target_link_libraries(demo_server xquic -levent -lm) target_link_libraries(demo_client xquic -levent -lm) endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77f9d2cf9..a6186e2e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -219,5 +219,7 @@ In no particular order, thanks to these excellent individuals who contributed co * @yunwei37 * @keengo99 * @ruanshanshan +* @alagoutte +* @MPK1 This list will be continuously updated. Contributions are welcome! diff --git a/README.md b/README.md index 9a15d1aec..3425dfa42 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ cd ../.. # build XQUIC with BoringSSL git submodule update --init --recursive mkdir -p build; cd build -cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_DISABLE_RENO=0 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. +cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. make -j ``` @@ -114,7 +114,7 @@ cd - # build XQUIC with BabaSSL git submodule update --init --recursive mkdir -p build; cd build -cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_DISABLE_RENO=0 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. +cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. make -j ``` diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 129ae28fb..27e951a88 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -63,6 +63,10 @@ if (XQC_DISABLE_LOG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_DISABLE_LOG") endif() +if(XQC_COMPAT_GENERATE_SR_PKT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_COMPAT_GENERATE_SR_PKT") +endif() + if (XQC_ONLY_ERROR_LOG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_ONLY_ERROR_LOG") endif() @@ -71,11 +75,6 @@ if (XQC_ENABLE_EVENT_LOG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_ENABLE_EVENT_LOG ") endif() -if(XQC_COMPAT_GENERATE_SR_PKT) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_COMPAT_GENERATE_SR_PKT") -endif() - - if(ANDROID) set(DYMAMIC_LINK_OPTION ${DYMAMIC_LINK_OPTION} @@ -126,7 +125,11 @@ else() endif() -configure_file (xqc_configure.h.in include/xquic/xqc_configure.h @ONLY) +configure_file ( + "${CMAKE_CURRENT_SOURCE_DIR}/xqc_configure.h.in" + "${CMAKE_CURRENT_SOURCE_DIR}/include/xquic/xqc_configure.h" + @ONLY +) include_directories( include/ @@ -191,9 +194,16 @@ set( "src/transport/scheduler/xqc_scheduler_common.c" "src/transport/scheduler/xqc_scheduler_backup.c" "src/transport/scheduler/xqc_scheduler_rap.c" - "src/transport/scheduler/xqc_scheduler_interop.c" ) +if(XQC_ENABLE_MP_INTEROP) + set( + TRANSPORT_SOURCES + ${TRANSPORT_SOURCES} + "src/transport/scheduler/xqc_scheduler_interop.c" + ) +endif() + # TLS source set ( TLS_SOURCE @@ -246,15 +256,11 @@ set( CONGESTION_CONTROL_SOURCES "src/congestion_control/xqc_cubic.c" "src/congestion_control/xqc_bbr.c" - "src/congestion_control/xqc_unlimited_cc.c" - "src/congestion_control/xqc_copa.c" "src/congestion_control/xqc_window_filter.c" "src/congestion_control/xqc_sample.c" ) -if (XQC_DISABLE_RENO) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_DISABLE_RENO") -else() +if(XQC_ENABLE_RENO) set( CONGESTION_CONTROL_SOURCES ${CONGESTION_CONTROL_SOURCES} @@ -262,8 +268,7 @@ else() ) endif() -if (XQC_ENABLE_BBR2) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXQC_ENABLE_BBR2") +if(XQC_ENABLE_BBR2) set( CONGESTION_CONTROL_SOURCES ${CONGESTION_CONTROL_SOURCES} @@ -271,6 +276,35 @@ if (XQC_ENABLE_BBR2) ) endif() +if(XQC_ENABLE_COPA) + set( + CONGESTION_CONTROL_SOURCES + ${CONGESTION_CONTROL_SOURCES} + "src/congestion_control/xqc_copa.c" + ) +endif() + +if(XQC_ENABLE_UNLIMITED) + set( + CONGESTION_CONTROL_SOURCES + ${CONGESTION_CONTROL_SOURCES} + "src/congestion_control/xqc_unlimited_cc.c" + ) +endif() + + +if(XQC_ENABLE_TH3) + set(XQC_ENABLE_TUNNEL 1) + set( + TH3_SOURCES + "tunnel/tunnel_h3/th3_ctx.c" + "tunnel/tunnel_h3/th3_vconn.c" + ) +endif() + + ) +endif() + if (XQC_NO_SHARED) set(XQC_BINARY_TYPE STATIC) endif() @@ -312,3 +346,4 @@ if (XQC_BUILD_SAMPLE) target_link_libraries(test_client xquic event) target_link_libraries(test_server xquic event) endif() + diff --git a/demo/common.h b/demo/common.h index 6ced07f35..a6fd22808 100644 --- a/demo/common.h +++ b/demo/common.h @@ -12,10 +12,10 @@ #define CIPHER_SUIT_LEN 256 #define TLS_GROUPS_LEN 64 -#define PATH_LEN 512 -#define RESOURCE_LEN 256 +#define PATH_LEN 1024 +#define RESOURCE_LEN 1024 #define AUTHORITY_LEN 128 -#define URL_LEN 512 +#define URL_LEN 1024 /* the congestion control types */ typedef enum cc_type_s { diff --git a/demo/demo_client.c b/demo/demo_client.c index 2f176a834..4533b7fdc 100644 --- a/demo/demo_client.c +++ b/demo/demo_client.c @@ -127,9 +127,9 @@ typedef struct xqc_demo_cli_net_config_s { */ /* definition for quic */ -#define MAX_SESSION_TICKET_LEN 2048 /* session ticket len */ -#define MAX_TRANSPORT_PARAMS_LEN 2048 /* transport parameter len */ -#define XQC_MAX_TOKEN_LEN 256 /* token len */ +#define MAX_SESSION_TICKET_LEN 8192 /* session ticket len */ +#define MAX_TRANSPORT_PARAMS_LEN 8192 /* transport parameter len */ +#define XQC_MAX_TOKEN_LEN 8192 /* token len */ #define SESSION_TICKET_FILE "session_ticket" #define TRANSPORT_PARAMS_FILE "transport_params" @@ -794,6 +794,11 @@ xqc_demo_cli_path_removed(const xqc_cid_t *scid, uint64_t path_id, { user_conn->paths[i].is_active = 0; user_conn->active_path_cnt--; + /* remove event handle */ + event_del(user_conn->paths[i].ev_socket); + event_del(user_conn->paths[i].ev_timeout); + /* close socket */ + close(user_conn->paths[i].fd); printf("No.%d path removed id = %"PRIu64"\n", i, path_id); } } @@ -1366,23 +1371,27 @@ xqc_demo_cli_init_conneciton_settings(xqc_conn_settings_t* settings, break; case CC_TYPE_CUBIC: - cong_ctrl = xqc_reno_cb; + cong_ctrl = xqc_cubic_cb; break; +#ifdef XQC_ENABLE_RENO case CC_TYPE_RENO: - cong_ctrl = xqc_cubic_cb; + cong_ctrl = xqc_reno_cb; break; +#endif default: break; } - xqc_scheduler_callback_t sched; + xqc_scheduler_callback_t sched = xqc_minrtt_scheduler_cb; if (strncmp(args->quic_cfg.mp_sched, "minrtt", strlen("minrtt")) == 0) { sched = xqc_minrtt_scheduler_cb; } else { +#ifdef XQC_ENABLE_MP_INTEROP sched = xqc_interop_scheduler_cb; +#endif } memset(settings, 0, sizeof(xqc_conn_settings_t)); @@ -2278,11 +2287,14 @@ xqc_demo_cli_create_socket(xqc_demo_cli_user_path_t *user_path, memset(&ifr, 0x00, sizeof(ifr)); strncpy(ifr.ifr_name, cfg->iflist[path_seq], sizeof(ifr.ifr_name) - 1); +#if !defined(__APPLE__) printf("fd: %d. bind to nic: %s\n", fd, cfg->iflist[path_seq]); if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr)) < 0) { printf("bind to nic error: %d, try use sudo\n", errno); goto err; } +#endif + } user_path->last_sock_op_time = xqc_demo_now(); @@ -2301,7 +2313,7 @@ xqc_demo_cli_init_user_path(xqc_demo_cli_user_conn_t *user_conn, int path_seq, u xqc_demo_cli_user_path_t *user_path = &user_conn->paths[path_seq]; /* create the initial path */ - user_path->fd = xqc_demo_cli_create_socket(user_path, &ctx->args->net_cfg, 0); + user_path->fd = xqc_demo_cli_create_socket(user_path, &ctx->args->net_cfg, path_seq); if (user_path->fd < 0) { printf("xqc_create_socket error\n"); return -1; diff --git a/demo/demo_server.c b/demo/demo_server.c index 33f02a44d..8075da059 100644 --- a/demo/demo_server.c +++ b/demo/demo_server.c @@ -1373,9 +1373,11 @@ xqc_demo_svr_init_conn_settings(xqc_demo_svr_args_t *args) case CC_TYPE_CUBIC: ccc = xqc_cubic_cb; break; +#ifdef XQC_ENABLE_RENO case CC_TYPE_RENO: ccc = xqc_reno_cb; break; +#endif default: break; } @@ -1385,7 +1387,9 @@ xqc_demo_svr_init_conn_settings(xqc_demo_svr_args_t *args) sched = xqc_minrtt_scheduler_cb; } else { +#ifdef XQC_ENABLE_MP_INTEROP sched = xqc_interop_scheduler_cb; +#endif } /* init connection settings */ diff --git a/docs/docs-zh/README-zh.md b/docs/docs-zh/README-zh.md index a4a3a54d8..bf8393313 100644 --- a/docs/docs-zh/README-zh.md +++ b/docs/docs-zh/README-zh.md @@ -45,7 +45,7 @@ cd - # 使用 BabaSSL 编译 XQUIC git submodule update --init --recursive mkdir -p build; cd build -cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_DISABLE_RENO=0 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. +cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. make -j ``` @@ -72,7 +72,7 @@ cd ../.. # 使用 BoringSSL 编译 XQUIC git submodule update --init --recursive mkdir -p build; cd build -cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_DISABLE_RENO=0 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. +cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. make -j ``` diff --git a/include/xquic/xqc_configure.h b/include/xquic/xqc_configure.h new file mode 100644 index 000000000..1139f9153 --- /dev/null +++ b/include/xquic/xqc_configure.h @@ -0,0 +1,9 @@ +/* the configured options and settings for xquic */ +#define xquic_VERSION_MAJOR 0 +#define xquic_VERSION_MINOR 1 + +/* #undef XQC_ENABLE_BBR2 */ +/* #undef XQC_ENABLE_RENO */ +/* #undef XQC_ENABLE_COPA */ +/* #undef XQC_ENABLE_UNLIMITED */ +/* #undef XQC_ENABLE_MP_INTEROP */ diff --git a/include/xquic/xquic.h b/include/xquic/xquic.h index 16e7f091a..83906b8a7 100644 --- a/include/xquic/xquic.h +++ b/include/xquic/xquic.h @@ -15,6 +15,8 @@ #include #include #endif + +#include "xqc_configure.h" #include "xquic_typedef.h" #ifdef __cplusplus @@ -911,7 +913,7 @@ typedef struct xqc_congestion_control_callback_s { xqc_bbr_info_interface_t *xqc_cong_ctl_info_cb; } xqc_cong_ctrl_callback_t; -#ifndef XQC_DISABLE_RENO +#ifdef XQC_ENABLE_RENO XQC_EXPORT_PUBLIC_API extern const xqc_cong_ctrl_callback_t xqc_reno_cb; #endif #ifdef XQC_ENABLE_BBR2 @@ -919,8 +921,12 @@ XQC_EXPORT_PUBLIC_API extern const xqc_cong_ctrl_callback_t xqc_bbr2_cb; #endif XQC_EXPORT_PUBLIC_API extern const xqc_cong_ctrl_callback_t xqc_bbr_cb; XQC_EXPORT_PUBLIC_API extern const xqc_cong_ctrl_callback_t xqc_cubic_cb; +#ifdef XQC_ENABLE_UNLIMITED XQC_EXPORT_PUBLIC_API extern const xqc_cong_ctrl_callback_t xqc_unlimited_cc_cb; +#endif +#ifdef XQC_ENABLE_COPA XQC_EXPORT_PUBLIC_API extern const xqc_cong_ctrl_callback_t xqc_copa_cb; +#endif typedef enum xqc_scheduler_path_event_e { XQC_SCHED_EVENT_PATH_NOT_FULL = 0, @@ -939,7 +945,7 @@ typedef struct xqc_scheduler_callback_s { xqc_path_ctx_t * (*xqc_scheduler_get_path)(void *scheduler, xqc_connection_t *conn, xqc_packet_out_t *packet_out, - int check_cwnd, int reinject); + int check_cwnd, int reinject, xqc_bool_t *cc_blocked); void (*xqc_scheduler_handle_path_event)(void *scheduler, xqc_path_ctx_t *path, xqc_scheduler_path_event_t event, void *event_arg); @@ -952,7 +958,9 @@ typedef struct xqc_scheduler_callback_s { XQC_EXPORT_PUBLIC_API extern const xqc_scheduler_callback_t xqc_minrtt_scheduler_cb; XQC_EXPORT_PUBLIC_API extern const xqc_scheduler_callback_t xqc_backup_scheduler_cb; XQC_EXPORT_PUBLIC_API extern const xqc_scheduler_callback_t xqc_rap_scheduler_cb; +#ifdef XQC_ENABLE_MP_INTEROP XQC_EXPORT_PUBLIC_API extern const xqc_scheduler_callback_t xqc_interop_scheduler_cb; +#endif typedef enum { XQC_REINJ_UNACK_AFTER_SCHED = 1 << 0, @@ -1200,6 +1208,13 @@ typedef struct xqc_conn_settings_s { * paths according to the scheduler. */ uint8_t mp_ack_on_any_path; + + /* + * When sending a ping packet for connection keep-alive, we replicate the + * the packet on all acitve paths to keep all paths alive (disable:0, enable:1). + * The default value is 0. + */ + uint8_t mp_ping_on; /* scheduler callback, default: xqc_minrtt_scheduler_cb */ xqc_scheduler_callback_t scheduler_callback; @@ -1296,6 +1311,8 @@ typedef struct xqc_conn_stats_s { xqc_path_metrics_t paths_info[XQC_MAX_PATHS_COUNT]; char conn_info[XQC_CONN_INFO_LEN]; + + char alpn[XQC_MAX_ALPN_BUF_LEN]; } xqc_conn_stats_t; typedef struct xqc_path_stats_s { @@ -1809,6 +1826,15 @@ xqc_int_t xqc_conn_mark_path_standby(xqc_engine_t *engine, const xqc_cid_t *cid, XQC_EXPORT_PUBLIC_API xqc_int_t xqc_conn_mark_path_available(xqc_engine_t *engine, const xqc_cid_t *cid, uint64_t path_id); +/** + * Mark a path as "frozen", i.e., both peers should not send any traffic on this path. + * @param cid scid for connection + * @param path_id path identifier for the path + * @return XQC_OK (0) when success, <0 for error + */ +XQC_EXPORT_PUBLIC_API +xqc_int_t xqc_conn_mark_path_frozen(xqc_engine_t *engine, const xqc_cid_t *cid, uint64_t path_id); + XQC_EXPORT_PUBLIC_API xqc_conn_type_t xqc_conn_get_type(xqc_connection_t *conn); diff --git a/include/xquic/xquic_typedef.h b/include/xquic/xquic_typedef.h index 75740d87e..b02b6f2a4 100644 --- a/include/xquic/xquic_typedef.h +++ b/include/xquic/xquic_typedef.h @@ -51,6 +51,7 @@ typedef struct xqc_bbr_info_interface_s xqc_bbr_info_interface_t; typedef struct xqc_path_ctx_s xqc_path_ctx_t; typedef struct xqc_timer_manager_s xqc_timer_manager_t; typedef struct xqc_h3_ext_bytestream_s xqc_h3_ext_bytestream_t; +typedef struct xqc_ping_record_s xqc_ping_record_t; typedef uint64_t xqc_msec_t; /* store millisecond values */ typedef uint64_t xqc_usec_t; /* store microsecond values */ @@ -148,6 +149,9 @@ typedef struct xqc_http_priority_s { #define XQC_DEFINED_ALPN_H3_29 "h3-29" #define XQC_DEFINED_ALPN_H3_EXT "h3-ext" +/* max alpn buffer length */ +#define XQC_MAX_ALPN_BUF_LEN 256 + typedef enum xqc_conn_settings_type_e { XQC_CONN_SETTINGS_DEFAULT, XQC_CONN_SETTINGS_LOW_DELAY, diff --git a/scripts/case_test.sh b/scripts/case_test.sh index 75ebc1cfd..d07469e2d 100755 --- a/scripts/case_test.sh +++ b/scripts/case_test.sh @@ -52,10 +52,33 @@ fi rm -f test_session tp_localhost xqc_token +killall test_server 2> /dev/null +./test_server -l d -e -x 17 > /dev/null & + +clear_log +echo -e "server-inited stream ...\c" +./test_client -l d -E -t 3 >> stdlog +client_refuse=`grep "ignore server initiated bidi-streams at client" clog` +client_discard=`grep "data discarded" clog` +client_check=`grep "xqc_h3_stream_close_notify" clog | grep "|stream_id:1|"` +client_std_res=`grep ">>>>>>>> pass" stdlog` +clog_res=`grep "xqc_destroy_stream" clog | grep "close_msg:finished" | grep "stream_id:1"` +if [ -n "$client_refuse" ] && [ -n "$client_discard" ] && [ -n "$client_std_res" ] && [ -n "$clog_res" ] && [ -z "$client_check" ]; then + echo ">>>>>>>> pass:1" + case_print_result "server_inited_stream" "pass" +else + echo ">>>>>>>> pass:0" + case_print_result "server_inited_stream" "fail" +fi + + + killall test_server 2> /dev/null ./test_server -l d -e -x 99 > /dev/null & sleep 1 +rm -f test_session tp_localhost xqc_token + clear_log echo -e "stream send pure fin ...\c" ./test_client -s 1024 -l d -t 1 -E -x 99 -T 1 >> clog @@ -75,7 +98,7 @@ rm -f test_session clear_log echo -e "h3 stream send pure fin ...\c" ./test_client -s 1024 -l d -t 1 -E -x 99 >> clog -errlog=`grep_err_log` +errlog=`grep_err_log | grep -v "send data after fin sent"` clog_res=`cat clog | grep "|send_state:3|recv_state:3|stream_id:0|stream_type:0|send_bytes:0|read_bytes:0|recv_bytes:0|stream_len:0|"` slog_res=`cat slog | grep "|send_state:3|recv_state:3|stream_id:0|stream_type:0|send_bytes:0|read_bytes:0|recv_bytes:0|stream_len:0|"` if [ -z "$errlog" ] && [ -n "$clog_res" ] && [ -n "$slog_res" ] ; then @@ -255,6 +278,43 @@ else echo "$errlog" fi +clear_log +echo -e "send data after fin ...\c" +result=`./test_client -s 5120 -l d -t 1 -E -x 50 |grep ">>>>>>>> pass"` +errlog=`grep_err_log | grep -v "send data after fin sent"` +echo "$result" +if [ -z "$errlog" ] && [ "$result" == ">>>>>>>> pass:1" ]; then + case_print_result "send_data_after_fin" "pass" +else + case_print_result "send_data_after_fin" "fail" + echo "$errlog" +fi + +clear_log +echo -e "send header after fin ...\c" +result=`./test_client -s 5120 -l d -t 1 -E -x 51 |grep ">>>>>>>> pass"` +errlog=`grep_err_log | grep -v "send data after fin sent"` +echo "$result" +if [ -z "$errlog" ] && [ "$result" == ">>>>>>>> pass:1" ]; then + case_print_result "send_header_after_fin" "pass" +else + case_print_result "send_header_after_fin" "fail" + echo "$errlog" +fi + +clear_log +echo -e "send fin after fin ...\c" +result=`./test_client -s 5120 -l d -t 1 -E -x 52 |grep ">>>>>>>> pass"` +errlog=`grep_err_log | grep -v "send data after fin sent"` +echo "$result" +if [ -z "$errlog" ] && [ "$result" == ">>>>>>>> pass:1" ]; then + case_print_result "send_fin_after_fin" "pass" +else + case_print_result "send_fin_after_fin" "fail" + echo "$errlog" +fi + + clear_log echo -e "header header data ...\c" ./test_client -s 5120 -l d -t 1 -E -x 30 >> clog @@ -3373,7 +3433,7 @@ cli_res3=`grep "\[h3-dgram\]|recv_dgram_bytes:102400|sent_dgram_bytes:102400|los cli_res4=`grep "\[bytestream\]|bytes_sent:102400|bytes_rcvd:102400|recv_fin:1|" stdlog` cli_res5=`grep "\[bytestream\]|same_content:yes|" stdlog | wc -l` cli_res6=`grep "send pure fin" clog` -errlog=`grep_err_log` +errlog=`grep_err_log | grep -v "send data after fin sent"` if [ "$cli_res1" == "1" ] && [ -n "$cli_res2" ] && [ -n "$cli_res3" ] && [ -n "$cli_res4" ] && [ "$cli_res5" == "1" ] && [ -n "$cli_res6" ] && [ -z "$errlog" ]; then echo ">>>>>>>> pass:1" case_print_result "h3_ext_finish_bytestream_during_transmission" "pass" @@ -3963,6 +4023,80 @@ fi grep_err_log +killall test_server +stdbuf -oL ./test_server -l d -e -M > /dev/null & +sleep 1 + +rm -rf tp_localhost test_session xqc_token +clear_log +echo -e "transport MP ping ...\c" +sudo ./test_client -s 1024 -l d -E -T 1 -e 1 --epoch_timeout 2000000 -t 3 --mp_ping 1 -M -i lo -i lo >> clog +ret_ping_id=`grep "====>ping_id:" clog` +ret_no_ping_id=`grep "====>no ping_id" clog` +path0_ping=`grep -E "xqc_send_packet_with_pn.*path:0.*PING" clog` +path1_ping=`grep -E "xqc_send_packet_with_pn.*path:1.*PING" clog` +if [ -n "$ret_ping_id" ] && [ -n "$ret_no_ping_id" ] && [ -n "$path0_ping" ] && [ -n "$path1_ping" ] ; then + echo ">>>>>>>> pass:1" + case_print_result "transport_MP_ping" "pass" +else + echo ">>>>>>>> pass:0" + case_print_result "transport_MP_ping" "fail" +fi + + +rm -rf tp_localhost test_session xqc_token +clear_log +echo -e "h3 MP ping ...\c" +sudo ./test_client -s 1024 -l d -E -e 1 --epoch_timeout 2000000 -t 3 --mp_ping 1 -M -i lo -i lo >> clog +ret_ping_id=`grep "====>ping_id:" clog` +ret_no_ping_id=`grep "====>no ping_id" clog` +path0_ping=`grep -E "xqc_send_packet_with_pn.*path:0.*PING" clog` +path1_ping=`grep -E "xqc_send_packet_with_pn.*path:1.*PING" clog` +if [ -n "$ret_ping_id" ] && [ -n "$ret_no_ping_id" ] && [ -n "$path0_ping" ] && [ -n "$path1_ping" ] ; then + echo ">>>>>>>> pass:1" + case_print_result "h3_MP_ping" "pass" +else + echo ">>>>>>>> pass:0" + case_print_result "h3_MP_ping" "fail" +fi + + +rm -rf tp_localhost test_session xqc_token +clear_log +echo -e "freeze path0 ...\c" +sudo ./test_client -s 1024000 -l d -E -e 4 -T 2 --epoch_timeout 2000000 -t 4 -M -i lo -i lo -x 107 > stdlog +stream_info3=`grep "stream_info:" stdlog | head -n 3 | tail -n 1 | grep -v "#0" | grep "#1"` +stream_info5=`grep "stream_info:" stdlog | tail -n 1 | grep -E "#0.*#1"` +clog_res1=`grep -E "path:0.*app_path_status:2->3" clog` +clog_res2=`grep -E "path:0.*app_path_status:3->1" clog` +slog_res1=`grep -E "path:0.*app_path_status:2->3" slog` +slog_res2=`grep -E "path:0.*app_path_status:3->1" slog` +if [ -n "$stream_info3" ] && [ -n "$stream_info5" ] && [ -n "$clog_res1" ] && [ -n "$clog_res2" ] && [ -n "$slog_res1" ] && [ -n "$slog_res2" ] ; then + echo ">>>>>>>> pass:1" + case_print_result "freeze_path0" "pass" +else + echo ">>>>>>>> pass:0" + case_print_result "freeze_path0" "fail" +fi + +rm -rf tp_localhost test_session xqc_token +clear_log +echo -e "freeze path1 ...\c" +sudo ./test_client -s 1024000 -l d -E -e 4 -T 2 --epoch_timeout 2000000 -t 4 -M -i lo -i lo -x 108 > stdlog +stream_info3=`grep "stream_info:" stdlog | head -n 3 | tail -n 1 | grep -v "#1" | grep "#0"` +stream_info5=`grep "stream_info:" stdlog | tail -n 1 | grep -E "#0.*#1"` +clog_res1=`grep -E "path:1.*app_path_status:2->3" clog` +clog_res2=`grep -E "path:1.*app_path_status:3->1" clog` +slog_res1=`grep -E "path:1.*app_path_status:2->3" slog` +slog_res2=`grep -E "path:1.*app_path_status:3->1" slog` +if [ -n "$stream_info3" ] && [ -n "$stream_info5" ] && [ -n "$clog_res1" ] && [ -n "$clog_res2" ] && [ -n "$slog_res1" ] && [ -n "$slog_res2" ] ; then + echo ">>>>>>>> pass:1" + case_print_result "freeze_path1" "pass" +else + echo ">>>>>>>> pass:0" + case_print_result "freeze_path1" "fail" +fi + killall test_server cd - diff --git a/scripts/xquic.lds b/scripts/xquic.lds index e19c385c0..6524af00f 100644 --- a/scripts/xquic.lds +++ b/scripts/xquic.lds @@ -74,6 +74,7 @@ XQUIC_VERS_1.0 { xqc_conn_close_path; xqc_conn_mark_path_standby; xqc_conn_mark_path_available; + xqc_conn_mark_path_frozen; xqc_dcid_str_by_scid; xqc_h3_ctx_init; xqc_h3_ctx_destroy; diff --git a/scripts/xquic_test.sh b/scripts/xquic_test.sh index c4274ba75..31df14314 100644 --- a/scripts/xquic_test.sh +++ b/scripts/xquic_test.sh @@ -61,7 +61,7 @@ function do_compile() { fi #turn on Code Coverage - cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_PRINT_SECRET=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_DISABLE_RENO=0 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. + cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_PRINT_SECRET=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} .. make -j rm -f CMakeCache.txt diff --git a/src/common/xqc_str.h b/src/common/xqc_str.h index 9852c194c..6c4b6f036 100644 --- a/src/common/xqc_str.h +++ b/src/common/xqc_str.h @@ -51,6 +51,21 @@ unsigned char *xqc_vsprintf(unsigned char *buf, unsigned char *last, const char unsigned char *xqc_sprintf_num(unsigned char *buf, unsigned char *last, uint64_t ui64, unsigned char zero, uintptr_t hexadecimal, uintptr_t width); +static inline int +xqc_memcpy_with_cap(void *dst, size_t cap, const void *src, size_t n) +{ + if (n == 0) { + return XQC_OK; + } + + if (n <= cap) { + xqc_memcpy(dst, src, n); + return XQC_OK; + } + + return -XQC_ENOBUF; +} + static inline void xqc_str_tolower(unsigned char *dst, unsigned char *src, size_t n) { diff --git a/src/http3/xqc_h3_stream.c b/src/http3/xqc_h3_stream.c index 5ca9a03ce..bca47bb83 100644 --- a/src/http3/xqc_h3_stream.c +++ b/src/http3/xqc_h3_stream.c @@ -119,35 +119,47 @@ xqc_h3_stream_send_buffer(xqc_h3_stream_t *h3s) xqc_list_buf_t *list_buf = xqc_list_entry(pos, xqc_list_buf_t, list_head); xqc_var_buf_t *buf = list_buf->buf; - if (buf->data != NULL) { - /* buf with bytes remain and buf with fin only */ - if (buf->consumed_len < buf->data_len - || (buf->data_len == 0 && buf->fin_flag)) - { - /* send buffer with transport stream */ - ssize_t sent = xqc_stream_send(h3s->stream, buf->data + buf->consumed_len, - buf->data_len - buf->consumed_len, buf->fin_flag); - if (sent < 0) { - /* don't print XQC_EAGAIN and XQC_ESTREAM_RESET */ - if (sent != -XQC_EAGAIN && sent != -XQC_ESTREAM_RESET) { - xqc_log(h3s->log, XQC_LOG_ERROR, "|xqc_stream_send error|ret:%z|", sent); + if (!(h3s->flags & XQC_HTTP3_STREAM_FLAG_FIN_SENT)) { + + if (buf->data != NULL) { + /* buf with bytes remain and buf with fin only */ + if (buf->consumed_len < buf->data_len + || (buf->data_len == 0 && buf->fin_flag)) + { + /* send buffer with transport stream */ + ssize_t sent = xqc_stream_send(h3s->stream, buf->data + buf->consumed_len, + buf->data_len - buf->consumed_len, buf->fin_flag); + if (sent < 0) { + /* don't print XQC_EAGAIN and XQC_ESTREAM_RESET */ + if (sent != -XQC_EAGAIN && sent != -XQC_ESTREAM_RESET) { + xqc_log(h3s->log, XQC_LOG_ERROR, "|xqc_stream_send error|ret:%z|", sent); + } + + return sent; + } + + buf->consumed_len += sent; + if (buf->consumed_len != buf->data_len) { + return -XQC_EAGAIN; } - return sent; + } else if (buf->data_len > 0) { + xqc_log(h3s->log, XQC_LOG_ERROR, "|send_buf is empty|buf->consumed_len:%uz" + "|buf->data_len:%uz", buf->consumed_len, buf->data_len); } - buf->consumed_len += sent; - if (buf->consumed_len != buf->data_len) { - return -XQC_EAGAIN; + /* a buffer with fin flag is sent, mark the FIN_SENT flag */ + if (buf->data_len == buf->consumed_len && buf->fin_flag) { + h3s->flags |= XQC_HTTP3_STREAM_FLAG_FIN_SENT; } - } else if (buf->data_len > 0) { - xqc_log(h3s->log, XQC_LOG_ERROR, "|send_buf is empty|buf->consumed_len:%uz" - "|buf->data_len:%uz", buf->consumed_len, buf->data_len); + } else { + xqc_log(h3s->log, XQC_LOG_ERROR, "|send_buf is NULL|"); } } else { - xqc_log(h3s->log, XQC_LOG_ERROR, "|send_buf is NULL|"); + xqc_log(h3s->log, XQC_LOG_ERROR, + "|send data after fin sent|stream_id:%ui", h3s->stream_id); } xqc_list_buf_free(list_buf); @@ -337,16 +349,21 @@ xqc_h3_stream_write_bidi_stream_type_to_buffer(xqc_h3_stream_t *h3s, uint64_t st ssize_t xqc_h3_stream_send_headers(xqc_h3_stream_t *h3s, xqc_http_headers_t *headers, uint8_t fin) { + xqc_h3_conn_t *h3c; + uint64_t fields_size; + uint64_t max_field_section_size; + ssize_t write; + /* nothing to send */ if (headers->count == 0) { return 0; } - xqc_h3_conn_t *h3c = h3s->h3c; + h3c = h3s->h3c; /* header size constrains */ - uint64_t fields_size = xqc_h3_uncompressed_fields_size(headers); - uint64_t max_field_section_size = h3c->peer_h3_conn_settings.max_field_section_size; + fields_size = xqc_h3_uncompressed_fields_size(headers); + max_field_section_size = h3c->peer_h3_conn_settings.max_field_section_size; if (fields_size > max_field_section_size) { xqc_log(h3c->log, XQC_LOG_ERROR, "|large nv|conn:%p|fields_size:%ui|exceed|" "SETTINGS_MAX_FIELD_SECTION_SIZE:%ui|", h3c->conn, fields_size, @@ -357,7 +374,7 @@ xqc_h3_stream_send_headers(xqc_h3_stream_t *h3s, xqc_http_headers_t *headers, ui h3s->flags |= XQC_HTTP3_STREAM_NEED_WRITE_NOTIFY; /* QPACK & gen HEADERS frame */ - ssize_t write = xqc_h3_stream_write_headers(h3s, headers, fin); + write = xqc_h3_stream_write_headers(h3s, headers, fin); if (write < 0) { xqc_log(h3c->log, XQC_LOG_ERROR, "|xqc_h3_stream_write_headers error|ret:%z||stream_id:%ui", write, h3s->stream_id); @@ -397,6 +414,12 @@ xqc_h3_stream_send_data_frame(xqc_h3_stream_t *h3s, unsigned char *data, size_t xqc_log(h3s->log, XQC_LOG_DEBUG, "|xqc_h3_stream_send_buffer|success|"); do { + if (h3s->flags & XQC_HTTP3_STREAM_FLAG_FIN_SENT) { + xqc_log(h3s->log, XQC_LOG_ERROR, + "|send data after fin sent|stream_id:%ui", h3s->stream_id); + break; + } + if (h3s->data_frame.data_sent > h3s->data_frame.data_len) { xqc_log(h3s->log, XQC_LOG_ERROR, "|data_sent exceed data_len|"); XQC_H3_CONN_ERR(h3s->h3c, H3_INTERNAL_ERROR, -XQC_H3_STATE_ERROR); @@ -417,7 +440,7 @@ xqc_h3_stream_send_data_frame(xqc_h3_stream_t *h3s, unsigned char *data, size_t fin_flag_for_quic_stream = fin; } else { - /* there is already a old dataframe */ + /* there is already a old data_frame */ if ((data_size - data_sent) <= (h3s->data_frame.data_len - h3s->data_frame.data_sent)) { fin_flag_for_quic_stream = fin; @@ -433,9 +456,11 @@ xqc_h3_stream_send_data_frame(xqc_h3_stream_t *h3s, unsigned char *data, size_t h3s->data_frame.header_len - h3s->data_frame.header_sent, fin_only); if (sent == -XQC_EAGAIN) { break; + } else if (sent < 0) { return sent; } + h3s->data_frame.header_sent += sent; xqc_log(h3s->log, XQC_LOG_DEBUG, "|send_header|success|fin:%d|fin_only:%d|\n", fin, fin_only); @@ -443,6 +468,7 @@ xqc_h3_stream_send_data_frame(xqc_h3_stream_t *h3s, unsigned char *data, size_t if (fin_only) { if (h3s->data_frame.header_sent == h3s->data_frame.header_len) { fin_only_sent = 1; + h3s->flags |= XQC_HTTP3_STREAM_FLAG_FIN_SENT; } break; } @@ -453,11 +479,21 @@ xqc_h3_stream_send_data_frame(xqc_h3_stream_t *h3s, unsigned char *data, size_t xqc_min(data_size - data_sent, h3s->data_frame.data_len - h3s->data_frame.data_sent), fin_flag_for_quic_stream); if (sent == -XQC_EAGAIN) { break; + } else if (sent < 0) { return sent; } + data_sent += sent; h3s->data_frame.data_sent += sent; + + /* if all data and fin is sent, mark the FIN_SENT flag */ + if (fin_flag_for_quic_stream + && h3s->data_frame.data_sent == h3s->data_frame.data_len) + { + h3s->flags |= XQC_HTTP3_STREAM_FLAG_FIN_SENT; + } + } while (data_sent < data_size); /* Nothing sent */ @@ -1726,6 +1762,28 @@ xqc_h3_stream_process_blocked_stream(xqc_h3_stream_t *h3s) } +xqc_int_t +xqc_h3_stream_create_notify(xqc_stream_t *stream, void *user_data) +{ + xqc_connection_t *conn = stream->stream_conn; + xqc_h3_conn_t *h3c = conn->proto_data; + + /* do not accept server initiated bidirectional streams at client */ + if (conn->conn_type == XQC_CONN_TYPE_CLIENT + && stream->stream_type == XQC_SVR_BID) + { + /* xquic do not support server-inited bidi stream, return error and + discard all subsequent stream data */ + xqc_log(h3c->log, XQC_LOG_ERROR, + "|ignore server initiated bidi-streams at client|"); + return -XQC_ECREATE_STREAM; + } + + return XQC_OK; +} + + + int xqc_h3_stream_read_notify(xqc_stream_t *stream, void *user_data) { @@ -1832,7 +1890,8 @@ int xqc_h3_stream_close_notify(xqc_stream_t *stream, void *user_data) { if (!(stream->stream_flag & XQC_STREAM_FLAG_HAS_H3)) { - xqc_log(stream->stream_conn->log, XQC_LOG_DEBUG, "|has no h3 stream|"); + xqc_log(stream->stream_conn->log, XQC_LOG_DEBUG, + "|has no h3 stream|stream_id:%ui", xqc_stream_id(stream)); return XQC_OK; } @@ -1906,6 +1965,7 @@ xqc_h3_stream_closing_notify(xqc_stream_t *stream, * transport callback */ const xqc_stream_callbacks_t h3_stream_callbacks = { + .stream_create_notify = xqc_h3_stream_create_notify, .stream_write_notify = xqc_h3_stream_write_notify, .stream_read_notify = xqc_h3_stream_read_notify, .stream_close_notify = xqc_h3_stream_close_notify, diff --git a/src/http3/xqc_h3_stream.h b/src/http3/xqc_h3_stream.h index 7f9df105d..5867974fa 100644 --- a/src/http3/xqc_h3_stream.h +++ b/src/http3/xqc_h3_stream.h @@ -71,6 +71,8 @@ typedef enum { blocked and waiting for encoder stream insertions while Transport stream notify its close */ XQC_HTTP3_STREAM_FLAG_ACTIVELY_CLOSED = 0x1000, + /* FIN was sent and no data will be sent any more */ + XQC_HTTP3_STREAM_FLAG_FIN_SENT = 0x2000, } xqc_h3_stream_flag; typedef struct xqc_h3_stream_pctx_s { diff --git a/src/transport/reinjection_control/xqc_reinj_deadline.c b/src/transport/reinjection_control/xqc_reinj_deadline.c index e92f4deec..dc1e9e841 100644 --- a/src/transport/reinjection_control/xqc_reinj_deadline.c +++ b/src/transport/reinjection_control/xqc_reinj_deadline.c @@ -61,8 +61,7 @@ xqc_deadline_reinj_can_reinject_before_sched(xqc_deadline_reinj_ctl_t *rctl, if ((po->po_frame_types & XQC_FRAME_BIT_STREAM) && !(po->po_flag & XQC_POF_NOT_REINJECT) - && !(XQC_MP_PKT_REINJECTED(po) - && (po->po_origin? XQC_MP_PKT_REINJECTED(po->po_origin): XQC_TRUE)) + && !(XQC_MP_PKT_REINJECTED(po)) && (po->po_flag & XQC_POF_IN_FLIGHT) && ((double)(now - po->po_sent_time) >= deadline)) { diff --git a/src/transport/reinjection_control/xqc_reinj_default.c b/src/transport/reinjection_control/xqc_reinj_default.c index 319a7668e..5a1c9c8f6 100644 --- a/src/transport/reinjection_control/xqc_reinj_default.c +++ b/src/transport/reinjection_control/xqc_reinj_default.c @@ -51,8 +51,7 @@ xqc_default_reinj_can_reinject_after_sched(xqc_default_reinj_ctl_t *rctl, if (xqc_list_empty(&conn->conn_send_queue->sndq_send_packets) && (po->po_frame_types & XQC_FRAME_BIT_STREAM) && !(po->po_flag & XQC_POF_NOT_REINJECT) - && !(XQC_MP_PKT_REINJECTED(po) - && (po->po_origin? XQC_MP_PKT_REINJECTED(po->po_origin): XQC_TRUE)) + && !(XQC_MP_PKT_REINJECTED(po)) && (po->po_flag & XQC_POF_IN_FLIGHT)) { return XQC_TRUE; diff --git a/src/transport/reinjection_control/xqc_reinj_dgram.c b/src/transport/reinjection_control/xqc_reinj_dgram.c index ac7635dfd..dba910e9b 100644 --- a/src/transport/reinjection_control/xqc_reinj_dgram.c +++ b/src/transport/reinjection_control/xqc_reinj_dgram.c @@ -50,8 +50,7 @@ xqc_dgram_reinj_can_reinject_after_send(xqc_dgram_reinj_ctl_t *rctl, if ((po->po_frame_types & XQC_FRAME_BIT_DATAGRAM) && !(po->po_flag & XQC_POF_NOT_REINJECT) - && !(XQC_MP_PKT_REINJECTED(po) - && (po->po_origin? XQC_MP_PKT_REINJECTED(po->po_origin): XQC_TRUE)) + && !(XQC_MP_PKT_REINJECTED(po)) && (po->po_flag & XQC_POF_IN_FLIGHT)) { return XQC_TRUE; diff --git a/src/transport/scheduler/xqc_scheduler_backup.c b/src/transport/scheduler/xqc_scheduler_backup.c index 9e5661b19..1c355df58 100644 --- a/src/transport/scheduler/xqc_scheduler_backup.c +++ b/src/transport/scheduler/xqc_scheduler_backup.c @@ -68,7 +68,8 @@ xqc_path_can_probe(xqc_path_ctx_t *path) xqc_path_ctx_t * xqc_backup_scheduler_get_path(void *scheduler, - xqc_connection_t *conn, xqc_packet_out_t *packet_out, int check_cwnd, int reinject) + xqc_connection_t *conn, xqc_packet_out_t *packet_out, int check_cwnd, int reinject, + xqc_bool_t *cc_blocked) { xqc_path_ctx_t *best_path = NULL; @@ -79,6 +80,11 @@ xqc_backup_scheduler_get_path(void *scheduler, /* min RTT */ uint64_t min_rtt = XQC_MAX_UINT64_VALUE; uint64_t path_srtt; + xqc_bool_t reached_cwnd_check = XQC_FALSE; + + if (cc_blocked) { + *cc_blocked = XQC_FALSE; + } xqc_list_for_each_safe(pos, next, &conn->conn_paths_list) { path = xqc_list_entry(pos, xqc_path_ctx_t, path_list); @@ -94,10 +100,21 @@ xqc_backup_scheduler_get_path(void *scheduler, } } + if (!reached_cwnd_check) { + reached_cwnd_check = XQC_TRUE; + if (cc_blocked) { + *cc_blocked = XQC_TRUE; + } + } + if (!xqc_scheduler_check_path_can_send(path, packet_out, check_cwnd)) { continue; } + if (cc_blocked) { + *cc_blocked = XQC_FALSE; + } + path_srtt = xqc_send_ctl_get_srtt(path->path_send_ctl); xqc_log(conn->log, XQC_LOG_DEBUG, "|path srtt|conn:%p|path_id:%ui|path_srtt:%ui|", conn, path->path_id, path_srtt); diff --git a/src/transport/scheduler/xqc_scheduler_interop.c b/src/transport/scheduler/xqc_scheduler_interop.c index 823504f19..1d207a79b 100644 --- a/src/transport/scheduler/xqc_scheduler_interop.c +++ b/src/transport/scheduler/xqc_scheduler_interop.c @@ -2,7 +2,6 @@ * @copyright Copyright (c) 2022, Alibaba Group Holding Limited */ - #include "src/transport/scheduler/xqc_scheduler_interop.h" #include "src/transport/scheduler/xqc_scheduler_common.h" #include "src/transport/xqc_send_ctl.h" @@ -22,7 +21,8 @@ xqc_interop_scheduler_init(void *scheduler, xqc_log_t *log, xqc_scheduler_params xqc_path_ctx_t * xqc_interop_scheduler_get_path(void *scheduler, - xqc_connection_t *conn, xqc_packet_out_t *packet_out, int check_cwnd, int reinject) + xqc_connection_t *conn, xqc_packet_out_t *packet_out, int check_cwnd, int reinject, + xqc_bool_t *cc_blocked) { xqc_path_ctx_t *best_path = NULL; xqc_path_ctx_t *best_standby_path = NULL; @@ -37,6 +37,11 @@ xqc_interop_scheduler_get_path(void *scheduler, uint64_t min_rtt_standby = XQC_MAX_UINT64_VALUE; uint64_t path_srtt; uint32_t avail_path_cnt = 0; + xqc_bool_t reached_cwnd_check = XQC_FALSE; + + if (cc_blocked) { + *cc_blocked = XQC_FALSE; + } xqc_list_for_each_safe(pos, next, &conn->conn_paths_list) { path = xqc_list_entry(pos, xqc_path_ctx_t, path_list); @@ -53,10 +58,21 @@ xqc_interop_scheduler_get_path(void *scheduler, continue; } + if (!reached_cwnd_check) { + reached_cwnd_check = XQC_TRUE; + if (cc_blocked) { + *cc_blocked = XQC_TRUE; + } + } + if (!xqc_scheduler_check_path_can_send(path, packet_out, check_cwnd)) { continue; } + if (cc_blocked) { + *cc_blocked = XQC_FALSE; + } + path_srtt = xqc_send_ctl_get_srtt(path->path_send_ctl); xqc_log(conn->log, XQC_LOG_DEBUG, "|path srtt|conn:%p|path_id:%ui|path_srtt:%ui|", conn, path->path_id, path_srtt); @@ -96,4 +112,4 @@ const xqc_scheduler_callback_t xqc_interop_scheduler_cb = { .xqc_scheduler_size = xqc_interop_scheduler_size, .xqc_scheduler_init = xqc_interop_scheduler_init, .xqc_scheduler_get_path = xqc_interop_scheduler_get_path, -}; \ No newline at end of file +}; diff --git a/src/transport/scheduler/xqc_scheduler_minrtt.c b/src/transport/scheduler/xqc_scheduler_minrtt.c index f73786219..ea2783734 100644 --- a/src/transport/scheduler/xqc_scheduler_minrtt.c +++ b/src/transport/scheduler/xqc_scheduler_minrtt.c @@ -22,7 +22,8 @@ xqc_minrtt_scheduler_init(void *scheduler, xqc_log_t *log, xqc_scheduler_params_ xqc_path_ctx_t * xqc_minrtt_scheduler_get_path(void *scheduler, - xqc_connection_t *conn, xqc_packet_out_t *packet_out, int check_cwnd, int reinject) + xqc_connection_t *conn, xqc_packet_out_t *packet_out, int check_cwnd, int reinject, + xqc_bool_t *cc_blocked) { xqc_path_ctx_t *best_path = NULL; @@ -33,6 +34,11 @@ xqc_minrtt_scheduler_get_path(void *scheduler, /* min RTT */ uint64_t min_rtt = XQC_MAX_UINT64_VALUE; uint64_t path_srtt; + xqc_bool_t reached_cwnd_check = XQC_FALSE; + + if (cc_blocked) { + *cc_blocked = XQC_FALSE; + } xqc_list_for_each_safe(pos, next, &conn->conn_paths_list) { path = xqc_list_entry(pos, xqc_path_ctx_t, path_list); @@ -41,10 +47,22 @@ xqc_minrtt_scheduler_get_path(void *scheduler, continue; } + /* skip the frozen path */ + if (path->app_path_status == XQC_APP_PATH_STATUS_FROZEN) { + continue; + } + if (reinject && (packet_out->po_path_id == path->path_id)) { continue; } + if (!reached_cwnd_check) { + reached_cwnd_check = XQC_TRUE; + if (cc_blocked) { + *cc_blocked = XQC_TRUE; + } + } + /* @TODO: It is not correct for BBR/BBRv2, as they do not used cwnd to decide * how much data can be sent in one RTT. But, currently, BBR does not * work well for MPQUIC due to the problem of applimit. We may adapt this @@ -54,6 +72,10 @@ xqc_minrtt_scheduler_get_path(void *scheduler, continue; } + if (cc_blocked) { + *cc_blocked = XQC_FALSE; + } + path_srtt = xqc_send_ctl_get_srtt(path->path_send_ctl); xqc_log(conn->log, XQC_LOG_DEBUG, "|path srtt|conn:%p|path_id:%ui|path_srtt:%ui|", conn, path->path_id, path_srtt); diff --git a/src/transport/scheduler/xqc_scheduler_rap.c b/src/transport/scheduler/xqc_scheduler_rap.c index bb1c989eb..96a13373d 100644 --- a/src/transport/scheduler/xqc_scheduler_rap.c +++ b/src/transport/scheduler/xqc_scheduler_rap.c @@ -22,7 +22,8 @@ xqc_rap_scheduler_init(void *scheduler, xqc_log_t *log, xqc_scheduler_params_t * xqc_path_ctx_t * xqc_rap_scheduler_get_path(void *scheduler, - xqc_connection_t *conn, xqc_packet_out_t *packet_out, int check_cwnd, int reinject) + xqc_connection_t *conn, xqc_packet_out_t *packet_out, int check_cwnd, int reinject, + xqc_bool_t *cc_blocked) { xqc_path_ctx_t *best_path = NULL; xqc_path_ctx_t *original_path = NULL; @@ -34,6 +35,11 @@ xqc_rap_scheduler_get_path(void *scheduler, /* min RTT */ uint64_t min_rtt = XQC_MAX_UINT64_VALUE; uint64_t path_srtt; + xqc_bool_t reached_cwnd_check = XQC_FALSE; + + if (cc_blocked) { + *cc_blocked = XQC_FALSE; + } xqc_list_for_each_safe(pos, next, &conn->conn_paths_list) { path = xqc_list_entry(pos, xqc_path_ctx_t, path_list); @@ -42,10 +48,26 @@ xqc_rap_scheduler_get_path(void *scheduler, continue; } + /* skip the frozen path */ + if (path->app_path_status == XQC_APP_PATH_STATUS_FROZEN) { + continue; + } + + if (!reached_cwnd_check) { + reached_cwnd_check = XQC_TRUE; + if (cc_blocked) { + *cc_blocked = XQC_TRUE; + } + } + if (!xqc_scheduler_check_path_can_send(path, packet_out, check_cwnd)) { continue; } + if (cc_blocked) { + *cc_blocked = XQC_FALSE; + } + if (reinject && (packet_out->po_path_id == path->path_id)) { original_path = path; continue; diff --git a/src/transport/xqc_conn.c b/src/transport/xqc_conn.c index 16bb13012..8e05900aa 100644 --- a/src/transport/xqc_conn.c +++ b/src/transport/xqc_conn.c @@ -48,6 +48,7 @@ xqc_conn_settings_t default_conn_settings = { .max_datagram_frame_size = 0, .mp_enable_reinjection = 0, .mp_ack_on_any_path = 0, + .mp_ping_on = 0, .max_ack_delay = XQC_DEFAULT_MAX_ACK_DELAY, .ack_frequency = 2, .loss_detection_pkt_thresh = XQC_kPacketThreshold, @@ -99,6 +100,7 @@ xqc_server_set_conn_settings(const xqc_conn_settings_t *settings) default_conn_settings.enable_pmtud = settings->enable_pmtud; default_conn_settings.marking_reinjection = settings->marking_reinjection; default_conn_settings.mp_ack_on_any_path = settings->mp_ack_on_any_path; + default_conn_settings.mp_ping_on = settings->mp_ping_on; if (settings->pmtud_probing_interval) { default_conn_settings.pmtud_probing_interval = settings->pmtud_probing_interval; @@ -375,6 +377,15 @@ xqc_conn_init_timer_manager(xqc_connection_t *conn) { xqc_timer_set(timer_manager, XQC_TIMER_PING, now, XQC_PING_TIMEOUT * 1000); } + + if (conn->conn_settings.enable_pmtud) { + if (conn->conn_settings.enable_multipath) { + xqc_timer_set(timer_manager, XQC_TIMER_PMTUD_PROBING, now, XQC_PMTUD_START_DELAY * 1000); + + } else { + xqc_timer_set(timer_manager, XQC_TIMER_PMTUD_PROBING, now, 1); + } + } } xqc_connection_t * @@ -532,10 +543,6 @@ xqc_conn_create(xqc_engine_t *engine, xqc_cid_t *dcid, xqc_cid_t *scid, xc->probing_pkt_out_size = XQC_MAX_PACKET_OUT_SIZE; xc->probing_cnt = 0; - if (xc->conn_settings.enable_pmtud) { - xc->conn_flag |= XQC_CONN_FLAG_PMTUD_PROBING; - } - for (xqc_encrypt_level_t encrypt_level = XQC_ENC_LEV_INIT; encrypt_level < XQC_ENC_LEV_MAX; encrypt_level++) { xc->undecrypt_count[encrypt_level] = 0; } @@ -640,6 +647,7 @@ xqc_conn_create(xqc_engine_t *engine, xqc_cid_t *dcid, xqc_cid_t *scid, /* for datagram */ xc->next_dgram_id = 0; xqc_init_list_head(&xc->dgram_0rtt_buffer_list); + xqc_init_list_head(&xc->ping_notification_list); xqc_log(xc->log, XQC_LOG_DEBUG, "|success|scid:%s|dcid:%s|conn:%p|", xqc_scid_str(&xc->scid_set.user_scid), xqc_dcid_str(&xc->dcid_set.current_dcid), xc); @@ -767,10 +775,29 @@ xqc_conn_server_create(xqc_engine_t *engine, const struct sockaddr *local_addr, xqc_dcid_str(&conn->original_dcid), conn); } - xqc_memcpy(conn->local_addr, local_addr, local_addrlen); - xqc_memcpy(conn->peer_addr, peer_addr, peer_addrlen); - conn->local_addrlen = local_addrlen; - conn->peer_addrlen = peer_addrlen; + ret = xqc_memcpy_with_cap(conn->local_addr, sizeof(conn->local_addr), + local_addr, local_addrlen); + if (ret == XQC_OK) { + conn->local_addrlen = local_addrlen; + + } else { + xqc_log(conn->log, XQC_LOG_ERROR, + "|local addr too large|addr_len:%d|", + (int)local_addrlen); + goto fail; + } + + ret = xqc_memcpy_with_cap(conn->peer_addr, sizeof(conn->peer_addr), + peer_addr, peer_addrlen); + if (ret == XQC_OK) { + conn->peer_addrlen = peer_addrlen; + + } else { + xqc_log(conn->log, XQC_LOG_ERROR, + "|peer addr too large|addr_len:%d|", + (int)peer_addrlen); + goto fail; + } ret = xqc_conn_create_server_tls(conn); if (ret != XQC_OK) { @@ -1011,6 +1038,8 @@ xqc_conn_destroy(xqc_connection_t *xc) } } + xqc_conn_destroy_ping_notification_list(xc); + /* remove from engine's conns_hash and destroy cid_set*/ xqc_conn_destroy_cids(xc); @@ -1068,6 +1097,51 @@ xqc_conn_get_local_addr(xqc_connection_t *conn, struct sockaddr *addr, socklen_t return XQC_OK; } +xqc_int_t +xqc_conn_send_ping_internal(xqc_connection_t *conn, void *ping_user_data, xqc_bool_t notify) +{ + xqc_int_t ret = XQC_OK; + + if (conn->conn_state >= XQC_CONN_STATE_CLOSING) { + return ret; + } + + if (conn->enable_multipath && conn->conn_settings.mp_ping_on) { + + xqc_path_ctx_t *path; + xqc_list_head_t *pos, *next; + xqc_bool_t has_ping = XQC_FALSE; + xqc_ping_record_t *pr = xqc_conn_create_ping_record(conn); + + xqc_list_for_each_safe(pos, next, &conn->conn_paths_list) { + path = xqc_list_entry(pos, xqc_path_ctx_t, path_list); + if (path->path_state == XQC_PATH_STATE_ACTIVE) { + ret = xqc_write_ping_to_packet(conn, path, ping_user_data, notify, pr); + if (ret < 0) { + xqc_log(conn->log, XQC_LOG_ERROR, "|write ping error|path:%ui|", path->path_id); + + } else { + has_ping = XQC_TRUE; + } + } + } + + if (!has_ping) { + xqc_conn_destroy_ping_record(pr); + return ret; + } + + } else { + ret = xqc_write_ping_to_packet(conn, NULL, ping_user_data, notify, NULL); + if (ret < 0) { + xqc_log(conn->log, XQC_LOG_ERROR, "|write ping error|"); + return ret; + } + } + + return XQC_OK; +} + /* used by upper level, shall never be invoked in xquic */ xqc_int_t xqc_conn_send_ping(xqc_engine_t *engine, const xqc_cid_t *cid, void *ping_user_data) @@ -1081,13 +1155,8 @@ xqc_conn_send_ping(xqc_engine_t *engine, const xqc_cid_t *cid, void *ping_user_d return -XQC_ECONN_NFOUND; } - if (conn->conn_state >= XQC_CONN_STATE_CLOSING) { - return XQC_OK; - } - - ret = xqc_write_ping_to_packet(conn, ping_user_data, XQC_TRUE); - if (ret < 0) { - xqc_log(engine->log, XQC_LOG_ERROR, "|write ping error|"); + ret = xqc_conn_send_ping_internal(conn, ping_user_data, XQC_TRUE); + if (ret) { return ret; } @@ -1232,6 +1301,7 @@ xqc_conn_schedule_packets(xqc_connection_t *conn, xqc_list_head_t *head, xqc_list_head_t *pos, *next; xqc_path_ctx_t *path; xqc_packet_out_t *packet_out; + xqc_bool_t cc_blocked; xqc_list_for_each_safe(pos, next, head) { packet_out = xqc_list_entry(pos, xqc_packet_out_t, po_list); @@ -1255,8 +1325,12 @@ xqc_conn_schedule_packets(xqc_connection_t *conn, xqc_list_head_t *head, path = conn->scheduler_callback-> xqc_scheduler_get_path(conn->scheduler, conn, packet_out, - packets_are_limited_by_cc, 0); + packets_are_limited_by_cc, + 0, &cc_blocked); if (path == NULL) { + if (cc_blocked) { + conn->sched_cc_blocked++; + } break; } } @@ -1406,6 +1480,7 @@ xqc_path_send_burst_packets(xqc_connection_t *conn, xqc_path_ctx_t *path, if (congest && !xqc_send_packet_check_cc(send_ctl, packet_out, total_bytes_to_send)) { + send_ctl->ctl_conn->send_cc_blocked++; break; } @@ -1533,6 +1608,7 @@ xqc_path_send_packets(xqc_connection_t *conn, xqc_path_ctx_t *path, if (congest && !xqc_send_packet_check_cc(send_ctl, packet_out, 0)) { + send_ctl->ctl_conn->send_cc_blocked++; break; } @@ -1692,6 +1768,9 @@ xqc_send(xqc_connection_t *conn, xqc_path_ctx_t *path, unsigned char *data, unsi if (sent != len) { xqc_log(conn->log, XQC_LOG_ERROR, "|write_socket error|conn:%p|size:%ud|sent:%z|", conn, len, sent); + xqc_log(conn->log, XQC_LOG_ERROR, + "|write_socket error|path:%ui|path_addr:%s|peer_addrlen:%d|", + path->path_id, xqc_path_addr_str(path), (int)path->peer_addrlen); /* if callback return XQC_SOCKET_ERROR, close the connection */ if (sent == XQC_SOCKET_ERROR) { @@ -2038,7 +2117,8 @@ xqc_conn_gen_ping(xqc_connection_t *conn, xqc_pkt_num_space_t pns) } xqc_int_t -xqc_path_send_ping_to_probe(xqc_path_ctx_t *path, xqc_pkt_num_space_t pns) +xqc_path_send_ping_to_probe(xqc_path_ctx_t *path, xqc_pkt_num_space_t pns, + xqc_path_specified_flag_t flag) { xqc_connection_t *conn = path->parent_conn; @@ -2048,7 +2128,7 @@ xqc_path_send_ping_to_probe(xqc_path_ctx_t *path, xqc_pkt_num_space_t pns) return -XQC_EWRITE_PKT; } - packet_out->po_path_flag |= XQC_PATH_SPECIFIED_BY_PTO; + packet_out->po_path_flag |= flag; packet_out->po_path_id = path->path_id; /* put PING into probe list, which is not limited by amplification or congestion-control */ @@ -2134,7 +2214,7 @@ xqc_path_send_one_or_two_ack_elicit_pkts(xqc_path_ctx_t *path, xqc_pkt_num_space while (probe_num > 0) { xqc_log(c->log, XQC_LOG_DEBUG, "|PING on PTO, cnt: %d|", probe_num); - xqc_path_send_ping_to_probe(path, pns); + xqc_path_send_ping_to_probe(path, pns, XQC_PATH_SPECIFIED_BY_PTO); probe_num--; } } @@ -2505,15 +2585,19 @@ xqc_conn_info_print(xqc_connection_t *conn, xqc_conn_stats_t *conn_stats) } /* conn info */ - ret = snprintf(buff, buff_size, "%u,%u,%u,%u,%u," - "%u,%u,", + ret = snprintf(buff, buff_size, "%u,%u,%u,%u,%u,%u,%u," + "%u,%u,%u,%u,", mp_settings, conn->create_path_count, + conn->validated_path_count, + conn->active_path_count, conn->dgram_stats.total_dgram, conn->dgram_stats.hp_dgram, conn->dgram_stats.hp_red_dgram, conn->dgram_stats.hp_red_dgram_mp, - conn->dgram_stats.timer_red_dgram); + conn->dgram_stats.timer_red_dgram, + conn->sched_cc_blocked, + conn->send_cc_blocked); curr_size += ret; @@ -2572,6 +2656,22 @@ void xqc_conn_get_stats_internal(xqc_connection_t *conn, xqc_conn_stats_t *conn_stats) { /* 1. 与路径无关的连接级别埋点 */ + const char *out_alpn = NULL; + size_t out_alpn_len = 0; + + if (conn->tls) { + xqc_tls_get_selected_alpn(conn->tls, &out_alpn, &out_alpn_len); + } + + xqc_memset(conn_stats->alpn, 0, XQC_MAX_ALPN_BUF_LEN); + if (out_alpn) { + strncpy(conn_stats->alpn, out_alpn, xqc_min(out_alpn_len, XQC_MAX_ALPN_BUF_LEN)); + + } else { + conn_stats->alpn[0] = '-'; + conn_stats->alpn[1] = '1'; + } + conn_stats->conn_err = (int)conn->conn_err; conn_stats->early_data_flag = XQC_0RTT_NONE; conn_stats->enable_multipath = conn->enable_multipath; @@ -2927,6 +3027,14 @@ xqc_conn_handshake_complete(xqc_connection_t *conn) /* determine multipath mode */ conn->enable_multipath = xqc_conn_enable_multipath(conn); + if (!conn->enable_multipath + && xqc_timer_is_set(&conn->conn_timer_manager, XQC_TIMER_PMTUD_PROBING)) + { + conn->probing_cnt = 0; + conn->conn_flag |= XQC_CONN_FLAG_PMTUD_PROBING; + xqc_timer_unset(&conn->conn_timer_manager, XQC_TIMER_PMTUD_PROBING); + } + /* conn's handshake is complete when TLS stack has reported handshake complete */ conn->conn_flag |= XQC_CONN_FLAG_HANDSHAKE_COMPLETED; @@ -4948,6 +5056,33 @@ xqc_conn_destroy_0rtt_datagram_buffer_list(xqc_connection_t *conn) } } +xqc_ping_record_t* +xqc_conn_create_ping_record(xqc_connection_t *conn) +{ + xqc_ping_record_t *pr = xqc_calloc(1, sizeof(xqc_ping_record_t)); + xqc_init_list_head(&pr->list); + xqc_list_add_tail(&pr->list, &conn->ping_notification_list); + return pr; +} + +void +xqc_conn_destroy_ping_record(xqc_ping_record_t *pr) +{ + xqc_list_del_init(&pr->list); + xqc_free(pr); +} + +void +xqc_conn_destroy_ping_notification_list(xqc_connection_t *conn) +{ + xqc_list_head_t *pos, *next; + xqc_ping_record_t *pr; + xqc_list_for_each_safe(pos, next, &conn->ping_notification_list) { + pr = xqc_list_entry(pos, xqc_ping_record_t, list); + xqc_conn_destroy_ping_record(pr); + } +} + xqc_bool_t xqc_conn_should_clear_0rtt_ticket(xqc_int_t conn_err) { diff --git a/src/transport/xqc_conn.h b/src/transport/xqc_conn.h index c2ad0f09c..c9e8b4f2b 100644 --- a/src/transport/xqc_conn.h +++ b/src/transport/xqc_conn.h @@ -241,6 +241,12 @@ typedef struct { } xqc_key_update_ctx_t; +typedef struct xqc_ping_record_s { + xqc_list_head_t list; + uint8_t notified; + uint32_t ref_cnt; +} xqc_ping_record_t; + struct xqc_connection_s { xqc_conn_settings_t conn_settings; @@ -392,6 +398,13 @@ struct xqc_connection_s { size_t max_pkt_out_size; size_t probing_pkt_out_size; uint32_t probing_cnt; + + /* pending ping notification */ + xqc_list_head_t ping_notification_list; + + /* cc blocking stats */ + uint32_t sched_cc_blocked; + uint32_t send_cc_blocked; }; const char *xqc_conn_flag_2_str(xqc_conn_flag_t conn_flag); @@ -425,7 +438,7 @@ void xqc_conn_transmit_pto_probe_packets(xqc_connection_t *conn); void xqc_conn_transmit_pto_probe_packets_batch(xqc_connection_t *conn); void xqc_conn_retransmit_lost_packets(xqc_connection_t *conn); void xqc_conn_retransmit_lost_packets_batch(xqc_connection_t *conn); -xqc_int_t xqc_path_send_ping_to_probe(xqc_path_ctx_t *path, xqc_pkt_num_space_t pns); +xqc_int_t xqc_path_send_ping_to_probe(xqc_path_ctx_t *path, xqc_pkt_num_space_t pns, xqc_path_specified_flag_t flag); void xqc_path_send_one_or_two_ack_elicit_pkts(xqc_path_ctx_t *path, xqc_pkt_num_space_t pns); void xqc_conn_send_one_ack_eliciting_pkt(xqc_connection_t *conn, xqc_pkt_num_space_t pns); @@ -596,4 +609,12 @@ void xqc_conn_try_to_update_mss(xqc_connection_t *conn); void xqc_conn_get_stats_internal(xqc_connection_t *conn, xqc_conn_stats_t *stats); +xqc_ping_record_t* xqc_conn_create_ping_record(xqc_connection_t *conn); + +void xqc_conn_destroy_ping_record(xqc_ping_record_t *pr); + +void xqc_conn_destroy_ping_notification_list(xqc_connection_t *conn); + +xqc_int_t xqc_conn_send_ping_internal(xqc_connection_t *conn, void *ping_user_data, xqc_bool_t notify); + #endif /* _XQC_CONN_H_INCLUDED_ */ diff --git a/src/transport/xqc_engine.c b/src/transport/xqc_engine.c index aa3455011..219d8bf7b 100644 --- a/src/transport/xqc_engine.c +++ b/src/transport/xqc_engine.c @@ -779,7 +779,7 @@ xqc_engine_process_conn(xqc_connection_t *conn, xqc_usec_t now) } if (XQC_UNLIKELY(conn->conn_flag & XQC_CONN_FLAG_PING)) { - ret = xqc_write_ping_to_packet(conn, NULL, XQC_FALSE); + ret = xqc_conn_send_ping_internal(conn, NULL, XQC_FALSE); if (ret) { xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_write_ping_to_packet error|"); XQC_CONN_ERR(conn, TRA_INTERNAL_ERROR); @@ -1179,8 +1179,15 @@ xqc_engine_packet_process(xqc_engine_t *engine, conn, packet_in_size, xqc_conn_state_2_str(conn->conn_state), recv_time); if (XQC_UNLIKELY(conn->local_addrlen == 0)) { - xqc_memcpy(conn->local_addr, local_addr, local_addrlen); - conn->local_addrlen = local_addrlen; + ret = xqc_memcpy_with_cap(conn->local_addr, sizeof(conn->local_addr), + local_addr, local_addrlen); + if (ret == XQC_OK) { + conn->local_addrlen = local_addrlen; + + } else { + xqc_log(conn->log, XQC_LOG_ERROR, + "|local addr too large|addr_len:%d|", (int)local_addrlen); + } xqc_log_event(conn->log, CON_CONNECTION_STARTED, conn, XQC_LOG_LOCAL_EVENT); } @@ -1196,9 +1203,16 @@ xqc_engine_packet_process(xqc_engine_t *engine, && !xqc_timer_is_set(&path->path_send_ctl->path_timer_manager, XQC_TIMER_NAT_REBINDING)) { /* set rebinding_addr & send PATH_CHALLENGE */ - xqc_memcpy(path->rebinding_addr, peer_addr, peer_addrlen); - path->rebinding_addrlen = peer_addrlen; + ret = xqc_memcpy_with_cap(path->rebinding_addr, sizeof(path->rebinding_addr), + peer_addr, peer_addrlen); + if (ret == XQC_OK) { + path->rebinding_addrlen = peer_addrlen; + } else { + xqc_log(conn->log, XQC_LOG_ERROR, + "|REBINDING|peer addr too large|addr_len:%d|", (int)peer_addrlen); + } + ret = xqc_conn_send_path_challenge(conn, path); if (ret == XQC_OK) { xqc_log(conn->log, XQC_LOG_INFO, "|REBINDING|path:%ui|send PATH_CHALLENGE|", path->path_id); diff --git a/src/transport/xqc_frame.c b/src/transport/xqc_frame.c index 5cdaec75d..5e23d9645 100644 --- a/src/transport/xqc_frame.c +++ b/src/transport/xqc_frame.c @@ -95,6 +95,7 @@ xqc_insert_stream_frame(xqc_connection_t *conn, xqc_stream_t *stream, xqc_stream unsigned char inserted = 0; xqc_list_head_t *pos; xqc_stream_frame_t *frame; + xqc_list_for_each_reverse(pos, &stream->stream_data_in.frames_tailq) { frame = xqc_list_entry(pos, xqc_stream_frame_t, sf_list); @@ -149,10 +150,9 @@ xqc_insert_stream_frame(xqc_connection_t *conn, xqc_stream_t *stream, xqc_stream pos = new_frame->sf_list.next; xqc_list_for_each_from(pos, &stream->stream_data_in.frames_tailq) { frame = xqc_list_entry(pos, xqc_stream_frame_t, sf_list); - if (stream->stream_data_in.merged_offset_end >= frame->data_offset - && stream->stream_data_in.merged_offset_end < frame->data_offset + frame->data_length) - { - stream->stream_data_in.merged_offset_end = frame->data_offset + frame->data_length; + if (stream->stream_data_in.merged_offset_end >= frame->data_offset) { + stream->stream_data_in.merged_offset_end = xqc_max(frame->data_offset + frame->data_length, + stream->stream_data_in.merged_offset_end); xqc_log(conn->log, XQC_LOG_DEBUG, "|merge right|merged_offset_end:%ui|offset:%ui|len:%ud|", stream->stream_data_in.merged_offset_end, frame->data_offset, frame->data_length); } else { @@ -325,12 +325,13 @@ xqc_process_padding_frame(xqc_connection_t *conn, xqc_packet_in_t *packet_in) xqc_int_t xqc_process_stream_frame(xqc_connection_t *conn, xqc_packet_in_t *packet_in) { - xqc_int_t ret = 0; + xqc_int_t ret; + xqc_stream_id_t stream_id; + xqc_stream_type_t stream_type; + xqc_stream_t *stream = NULL; + xqc_stream_frame_t *stream_frame; - xqc_stream_id_t stream_id; - xqc_stream_type_t stream_type; - xqc_stream_t *stream = NULL; - xqc_stream_frame_t *stream_frame = xqc_calloc(1, sizeof(xqc_stream_frame_t)); + stream_frame = xqc_calloc(1, sizeof(xqc_stream_frame_t)); if (stream_frame == NULL) { xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_calloc error|"); return -XQC_EMALLOC; @@ -413,6 +414,21 @@ xqc_process_stream_frame(xqc_connection_t *conn, xqc_packet_in_t *packet_in) goto error; } + /* if stream is discarded, drop all data */ + if (stream->stream_flag & XQC_STREAM_FLAG_DISCARDED) { + xqc_log(conn->log, XQC_LOG_DEBUG, "|stream[%ui] data discarded|" + "offset:%ui|len:%ui", stream->stream_id, + stream_frame->data_offset, + stream_frame->data_length); + + /* if all data is discarded, try to close the stream */ + if (stream_frame->fin) { + xqc_stream_close_discarded_stream(stream); + } + + goto free; + } + ret = xqc_insert_stream_frame(conn, stream, stream_frame); if (ret == -XQC_EDUP_FRAME) { ret = XQC_OK; @@ -757,7 +773,7 @@ xqc_process_retire_conn_id_frame(xqc_connection_t *conn, xqc_packet_in_t *packet return ret; } - if (seq_num >= conn->scid_set.largest_scid_seq_num) { + if (seq_num > conn->scid_set.largest_scid_seq_num) { /* * Receipt of a RETIRE_CONNECTION_ID frame containing a sequence number * greater than any previously sent to the peer MUST be treated as a @@ -802,7 +818,7 @@ xqc_process_retire_conn_id_frame(xqc_connection_t *conn, xqc_packet_in_t *packet xqc_log(conn->log, XQC_LOG_DEBUG, "|switch scid to %ui|", conn->scid_set.user_scid.cid_seq_num); } - /* TODO: 如果对应 “Avtive” Path 则需要替换 CID */ + /* TODO: 如果对应 “Active” Path 则需要替换 CID */ xqc_path_ctx_t *path = xqc_conn_find_path_by_scid(conn, &inner_cid->cid); if (path != NULL) { xqc_log(conn->log, XQC_LOG_DEBUG, "|path:%ui|state:%d|", path->path_id, path->path_state); @@ -1513,10 +1529,16 @@ xqc_process_path_status_frame(xqc_connection_t *conn, xqc_packet_in_t *packet_in return XQC_OK; /* ignore */ } - xqc_usec_t now = xqc_monotonic_timestamp(); if (path_status_seq_num > path->app_path_status_recv_seq_num) { path->app_path_status_recv_seq_num = path_status_seq_num; - xqc_set_application_path_status(path, path_status, now); + path->next_app_path_state = path_status; + + if (path->path_state < XQC_PATH_STATE_ACTIVE) { + path->path_flag |= XQC_PATH_FLAG_RECV_STATUS; + + } else { + xqc_set_application_path_status(path, path->next_app_path_state, XQC_FALSE); + } } return XQC_OK; diff --git a/src/transport/xqc_multipath.c b/src/transport/xqc_multipath.c index c0d942ae1..010a5f94f 100644 --- a/src/transport/xqc_multipath.c +++ b/src/transport/xqc_multipath.c @@ -201,6 +201,11 @@ xqc_path_init(xqc_path_ctx_t *path, xqc_connection_t *conn) xqc_set_path_state(path, XQC_PATH_STATE_VALIDATING); } + xqc_log(conn->log, XQC_LOG_DEBUG, + "|path:%ui|conn_addr:%s|cp_addr_len:%d|path_addr:%s|pp_addr_len:%d|", + path->path_id, xqc_conn_addr_str(conn), conn->peer_addrlen, + xqc_path_addr_str(path), path->peer_addrlen); + xqc_log(conn->engine->log, XQC_LOG_DEBUG, "|path:%ui|dcid:%s|scid:%s|state:%d|", path->path_id, xqc_dcid_str(&path->path_dcid), xqc_scid_str(&path->path_scid), path->path_state); @@ -250,7 +255,7 @@ xqc_path_move_unack_packets_from_conn(xqc_path_ctx_t *path, xqc_connection_t *co xqc_send_queue_maybe_remove_unacked(po, conn->conn_send_queue, NULL); } else { - /* if a packet don't need to be repair, don't retransmit it */ + /* if a packet needs no retransmission, we remove it. */ xqc_send_queue_remove_unacked(po, conn->conn_send_queue); xqc_send_queue_insert_free(po, &conn->conn_send_queue->sndq_free_packets, conn->conn_send_queue); } @@ -922,11 +927,7 @@ xqc_path_send_buffer_clear(xqc_connection_t *conn, xqc_path_ctx_t *path, xqc_lis packet_out = xqc_list_entry(pos, xqc_packet_out_t, po_list); xqc_path_send_buffer_remove(path, packet_out); - if (packet_out->po_flag & XQC_POF_REINJECTED_REPLICA) { - xqc_disassociate_packet_with_reinjection(packet_out->po_origin, packet_out); - xqc_send_queue_insert_free(packet_out, &send_queue->sndq_free_packets, send_queue); - - } else if (head != NULL) { + if (head != NULL) { /* remove from path scheduled buffer & add to the head of conn send queue */ xqc_send_queue_move_to_head(&packet_out->po_list, head); @@ -1029,13 +1030,28 @@ xqc_conn_server_init_path_addr(xqc_connection_t *conn, uint64_t path_id, } if (local_addr && local_addrlen > 0) { - xqc_memcpy(path->local_addr, local_addr, local_addrlen); - path->local_addrlen = local_addrlen; + ret = xqc_memcpy_with_cap(path->local_addr, sizeof(path->local_addr), local_addr, local_addrlen); + if (ret == XQC_OK) { + path->local_addrlen = local_addrlen; + + } else { + xqc_log(conn->log, XQC_LOG_ERROR, + "|local addr too large|addr_len:%d|", (int)local_addrlen); + return -XQC_ENOBUF; + } + } if (peer_addr && peer_addrlen > 0) { - xqc_memcpy(path->peer_addr, peer_addr, peer_addrlen); - path->peer_addrlen = peer_addrlen; + ret = xqc_memcpy_with_cap(path->peer_addr, sizeof(path->peer_addr), peer_addr, peer_addrlen); + if (ret == XQC_OK) { + path->peer_addrlen = peer_addrlen; + + } else { + xqc_log(conn->log, XQC_LOG_ERROR, + "|peer addr too large|addr_len:%d|", (int)peer_addrlen); + return -XQC_ENOBUF; + } } if (path_id != XQC_INITIAL_PATH_ID) { @@ -1091,6 +1107,11 @@ xqc_conn_client_init_path_addr(xqc_connection_t *conn) path->local_addrlen = conn->local_addrlen; } + xqc_log(conn->log, XQC_LOG_DEBUG, + "|path:%ui|conn_addr:%s|cp_addr_len:%d|path_addr:%s|pp_addr_len:%d|", + path->path_id, xqc_conn_addr_str(conn), conn->peer_addrlen, + xqc_path_addr_str(path), path->peer_addrlen); + return XQC_OK; } @@ -1116,17 +1137,19 @@ xqc_path_validate(xqc_path_ctx_t *path) if (path->path_flag & XQC_PATH_FLAG_SEND_STATUS) { path->path_flag &= ~XQC_PATH_FLAG_SEND_STATUS; - - xqc_int_t ret = xqc_write_path_status_frame_to_packet(conn, path); + xqc_int_t ret = xqc_set_application_path_status(path, path->next_app_path_state, XQC_TRUE); if (ret != XQC_OK) { xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_write_path_status_frame_to_packet error|"); } } - /* PMTUD: reset probing info & launch probing immediately */ + if (path->path_flag & XQC_PATH_FLAG_RECV_STATUS) { + path->path_flag &= ~XQC_PATH_FLAG_RECV_STATUS; + xqc_set_application_path_status(path, path->next_app_path_state, XQC_FALSE); + } + + /* PMTUD: launch probing immediately */ if (conn->conn_settings.enable_pmtud) { - conn->max_pkt_out_size = path->path_max_pkt_out_size; - conn->probing_pkt_out_size = path->path_max_pkt_out_size; conn->probing_cnt = 0; conn->conn_flag |= XQC_CONN_FLAG_PMTUD_PROBING; xqc_timer_unset(&conn->conn_timer_manager, XQC_TIMER_PMTUD_PROBING); @@ -1228,24 +1251,49 @@ xqc_path_is_full(xqc_path_ctx_t *path) uint64_t cwnd = ctl->ctl_cong_callback->xqc_cong_ctl_get_cwnd(ctl->ctl_cong); return (bytes_on_path + xqc_conn_get_mss(path->parent_conn)) > cwnd; } -void -xqc_set_application_path_status(xqc_path_ctx_t *path, xqc_app_path_status_t status, xqc_usec_t now) + +xqc_int_t +xqc_set_application_path_status(xqc_path_ctx_t *path, xqc_app_path_status_t status, xqc_bool_t is_tx) { - if (path->app_path_status == status) { - return; - } + if (path->app_path_status != status + && status > XQC_APP_PATH_STATUS_NONE + && status < XQC_APP_PATH_STATUS_MAX) + { + xqc_app_path_status_t last_status = path->app_path_status; + xqc_connection_t *conn = path->parent_conn; - xqc_log(path->parent_conn->log, XQC_LOG_DEBUG, "|path:%ui|app_path_status:%d->%d|", path->path_id, path->app_path_status, status); - path->app_path_status = status; + path->app_path_status = status; - path->app_path_status_changed_count++; - path->last_app_path_status_changed_time = now; - xqc_set_transport_path_status(path, (xqc_tra_path_status_t)status, now); + if (is_tx) { + xqc_int_t ret = xqc_write_path_status_frame_to_packet(conn, path); + if (ret != XQC_OK) { + path->app_path_status = last_status; + xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_write_path_status_frame_to_packet error|%d|", ret); + return ret; + } + } + xqc_log(conn->log, XQC_LOG_DEBUG, "|path:%ui|app_path_status:%d->%d|", path->path_id, last_status, status); + path->app_path_status_changed_count++; + path->last_app_path_status_changed_time = xqc_monotonic_timestamp(); + xqc_set_transport_path_status(path, (xqc_tra_path_status_t)status, path->last_app_path_status_changed_time); + + if (status == XQC_APP_PATH_STATUS_FROZEN) { + xqc_path_move_unack_packets_from_conn(path, conn); + for (xqc_send_type_t type = 0; type < XQC_SEND_TYPE_N; type++) { + xqc_path_send_buffer_clear(conn, path, NULL, type); + } + } + } + + return XQC_OK; } void xqc_set_transport_path_status(xqc_path_ctx_t *path, xqc_tra_path_status_t status, xqc_usec_t now) { - if (path->tra_path_status == status) { + if (path->tra_path_status == status + || status <= XQC_TRA_PATH_STATUS_NONE + || status >= XQC_TRA_PATH_STATUS_MAX) + { return; } @@ -1309,21 +1357,64 @@ xqc_conn_mark_path_standby(xqc_engine_t *engine, const xqc_cid_t *cid, uint64_t return -XQC_EMP_PATH_NOT_FOUND; } - xqc_usec_t now = xqc_monotonic_timestamp(); - xqc_set_application_path_status(path, XQC_APP_PATH_STATUS_STANDBY, now); + path->next_app_path_state = XQC_APP_PATH_STATUS_STANDBY; if (path->path_state < XQC_PATH_STATE_ACTIVE) { path->path_flag |= XQC_PATH_FLAG_SEND_STATUS; return XQC_OK; } - xqc_int_t ret = xqc_write_path_status_frame_to_packet(conn, path); - if (ret != XQC_OK) { - xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_write_path_status_frame_to_packet error|%d|", ret); - return ret; + return xqc_set_application_path_status(path, path->next_app_path_state, XQC_TRUE); +} + +xqc_int_t +xqc_conn_mark_path_frozen(xqc_engine_t *engine, const xqc_cid_t *cid, uint64_t path_id) +{ + xqc_connection_t *conn = NULL; + xqc_path_ctx_t *path = NULL; + + conn = xqc_engine_conns_hash_find(engine, cid, 's'); + if (!conn) { + xqc_log(engine->log, XQC_LOG_ERROR, "|can not find connection|"); + return -XQC_ECONN_NFOUND; + } + if (conn->conn_state >= XQC_CONN_STATE_CLOSING) { + return -XQC_CLOSING; } - return XQC_OK; + /* check mp-support */ + if (!conn->enable_multipath) { + xqc_log(engine->log, XQC_LOG_WARN, + "|Multipath is not supported in connection|%p|", conn); + return -XQC_EMP_NOT_SUPPORT_MP; + } + + /* find path */ + path = xqc_conn_find_path_by_path_id(conn, path_id); + if (path == NULL) { + xqc_log(engine->log, XQC_LOG_WARN, + "|path is not found by path_id in connection|%p|%ui|", + conn, path_id); + return -XQC_EMP_PATH_NOT_FOUND; + } + + /* do not freeze the only active path */ + if (path->path_state == XQC_PATH_STATE_ACTIVE + && conn->active_path_count == 1) + { + xqc_log(conn->log, XQC_LOG_WARN, + "|can not freeze the only active path|path:%ui", path_id); + return -XQC_EMP_NO_ACTIVE_PATH; + } + + path->next_app_path_state = XQC_APP_PATH_STATUS_FROZEN; + + if (path->path_state < XQC_PATH_STATE_ACTIVE) { + path->path_flag |= XQC_PATH_FLAG_SEND_STATUS; + return XQC_OK; + } + + return xqc_set_application_path_status(path, path->next_app_path_state, XQC_TRUE); } @@ -1358,21 +1449,14 @@ xqc_conn_mark_path_available(xqc_engine_t *engine, const xqc_cid_t *cid, uint64_ return -XQC_EMP_PATH_NOT_FOUND; } - xqc_usec_t now = xqc_monotonic_timestamp(); - xqc_set_application_path_status(path, XQC_APP_PATH_STATUS_AVAILABLE, now); + path->next_app_path_state = XQC_APP_PATH_STATUS_AVAILABLE; if (path->path_state < XQC_PATH_STATE_ACTIVE) { path->path_flag |= XQC_PATH_FLAG_SEND_STATUS; return XQC_OK; } - xqc_int_t ret = xqc_write_path_status_frame_to_packet(conn, path); - if (ret != XQC_OK) { - xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_write_path_status_frame_to_packet error|%d|", ret); - return ret; - } - - return XQC_OK; + return xqc_set_application_path_status(path, path->next_app_path_state, XQC_TRUE); } @@ -1381,7 +1465,8 @@ xqc_path_standby_probe(xqc_path_ctx_t *path) { xqc_connection_t *conn = path->parent_conn; - xqc_int_t ret = xqc_path_send_ping_to_probe(path, XQC_PNS_APP_DATA); + xqc_int_t ret = xqc_path_send_ping_to_probe(path, XQC_PNS_APP_DATA, + XQC_PATH_SPECIFIED_BY_PQP); if (ret != XQC_OK) { return ret; } diff --git a/src/transport/xqc_multipath.h b/src/transport/xqc_multipath.h index a793eaf5e..90f6eb203 100644 --- a/src/transport/xqc_multipath.h +++ b/src/transport/xqc_multipath.h @@ -32,16 +32,24 @@ typedef enum { /* application layer path status */ typedef enum { + /* max */ + XQC_APP_PATH_STATUS_NONE, /* suggest that no traffic should be sent on that path if another path is available */ XQC_APP_PATH_STATUS_STANDBY = 1, /* allow the peer to use its own logic to split traffic among available paths */ XQC_APP_PATH_STATUS_AVAILABLE = 2, + /* freeze a path */ + XQC_APP_PATH_STATUS_FROZEN = 3, + /* max */ + XQC_APP_PATH_STATUS_MAX, } xqc_app_path_status_t; /* transport layer path status */ typedef enum { + XQC_TRA_PATH_STATUS_NONE, XQC_TRA_PATH_STATUS_BACKUP = 1, XQC_TRA_PATH_STATUS_IN_USE = 2, + XQC_TRA_PATH_STATUS_MAX, } xqc_tra_path_status_t; /* path close mode: passive & proactive */ @@ -60,6 +68,7 @@ typedef enum { typedef enum { XQC_PATH_FLAG_SEND_STATUS = 1 << 0, + XQC_PATH_FLAG_RECV_STATUS = 1 << 1, } xqc_path_flag_t; typedef enum { @@ -68,6 +77,8 @@ typedef enum { XQC_PATH_SPECIFIED_BY_PTO = 1 << 2, /* PTO probe */ XQC_PATH_SPECIFIED_BY_REINJ = 1 << 3, /* reinjection on a specific path */ XQC_PATH_SPECIFIED_BY_PTMUD = 1 << 4, /* PMTUD Probe */ + XQC_PATH_SPECIFIED_BY_KAP = 1 << 5, /* Keepalive Probe */ + XQC_PATH_SPECIFIED_BY_PQP = 1 << 6, /* Path Quality Probe */ } xqc_path_specified_flag_t; /* path context */ @@ -106,6 +117,7 @@ struct xqc_path_ctx_s { xqc_tra_path_status_t tra_path_status; /* application layer path status, sync via PATH_STATUS frame */ xqc_app_path_status_t app_path_status; + xqc_app_path_status_t next_app_path_state; uint64_t app_path_status_send_seq_num; uint64_t app_path_status_recv_seq_num; @@ -215,7 +227,7 @@ void xqc_path_send_buffer_append(xqc_path_ctx_t *path, xqc_packet_out_t *packet_ void xqc_path_send_buffer_remove(xqc_path_ctx_t *path, xqc_packet_out_t *packet_out); void xqc_path_send_buffer_clear(xqc_connection_t *conn, xqc_path_ctx_t *path, xqc_list_head_t *head, xqc_send_type_t send_type); -void xqc_set_application_path_status(xqc_path_ctx_t *path, xqc_app_path_status_t status, xqc_usec_t now); +xqc_int_t xqc_set_application_path_status(xqc_path_ctx_t *path, xqc_app_path_status_t status, xqc_bool_t is_tx); void xqc_set_transport_path_status(xqc_path_ctx_t *path, xqc_tra_path_status_t status, xqc_usec_t now); /* path statistics */ diff --git a/src/transport/xqc_packet_out.c b/src/transport/xqc_packet_out.c index 5a9fcfdf6..1fa4a4176 100644 --- a/src/transport/xqc_packet_out.c +++ b/src/transport/xqc_packet_out.c @@ -69,28 +69,24 @@ xqc_packet_out_create(size_t po_buf_size) *path = xqc_conn_find_path_by_path_id(conn, po->po_path_id); - /* no packets can be sent on a closing/closed path */ - if ((*path == NULL) || ((*path)->path_state >= XQC_PATH_STATE_CLOSING)) { - - po->po_path_flag &= ~(XQC_PATH_SPECIFIED_BY_ACK | XQC_PATH_SPECIFIED_BY_PTO); - - if (po->po_path_flag & XQC_PATH_SPECIFIED_BY_REINJ) { - if (po->po_flag & XQC_POF_REINJECTED_REPLICA) { - /* replicated packets should be removed */ - xqc_disassociate_packet_with_reinjection(po->po_origin, po); - - } else { - /* the origin packet can be rescheduled */ - po->po_path_flag &= ~XQC_PATH_SPECIFIED_BY_REINJ; - } - } + /* no packets can be sent on a closing/closed/frozen path */ + if ((*path == NULL) + || ((*path)->path_state >= XQC_PATH_STATE_CLOSING) + || (*path)->app_path_status == XQC_APP_PATH_STATUS_FROZEN) + { + po->po_path_flag &= ~(XQC_PATH_SPECIFIED_BY_ACK | XQC_PATH_SPECIFIED_BY_PTO | XQC_PATH_SPECIFIED_BY_REINJ); - /* if the packet can not be rescheduled, we remove it. */ if (po->po_path_flag) { - xqc_send_queue_remove_send(&po->po_list); - xqc_send_queue_insert_free(po, &conn->conn_send_queue->sndq_free_packets, conn->conn_send_queue); + if ((*path == NULL) + || ((*path)->path_state >= XQC_PATH_STATE_CLOSING)) + { + /* if the packet can not be rescheduled and the path is closed, we remove it. */ + xqc_send_queue_remove_send(&po->po_list); + xqc_send_queue_insert_free(po, &conn->conn_send_queue->sndq_free_packets, conn->conn_send_queue); + } ret = XQC_TRUE; } + *path = NULL; } else { @@ -509,7 +505,8 @@ xqc_write_ack_to_packets(xqc_connection_t *conn) } int -xqc_write_ping_to_packet(xqc_connection_t *conn, void *po_user_data, xqc_bool_t notify) +xqc_write_ping_to_packet(xqc_connection_t *conn, xqc_path_ctx_t *path, + void *po_user_data, xqc_bool_t notify, xqc_ping_record_t *pr) { ssize_t ret; xqc_packet_out_t *packet_out; @@ -536,6 +533,15 @@ xqc_write_ping_to_packet(xqc_connection_t *conn, void *po_user_data, xqc_bool_t */ if (notify) { packet_out->po_flag |= XQC_POF_NOTIFY; + if (pr) { + packet_out->po_pr = pr; + pr->ref_cnt++; + } + } + + if (path) { + packet_out->po_path_id = path->path_id; + packet_out->po_path_flag |= XQC_PATH_SPECIFIED_BY_KAP; } conn->conn_flag &= ~XQC_CONN_FLAG_PING; diff --git a/src/transport/xqc_packet_out.h b/src/transport/xqc_packet_out.h index a7b55f584..89b9b2074 100644 --- a/src/transport/xqc_packet_out.h +++ b/src/transport/xqc_packet_out.h @@ -110,6 +110,9 @@ typedef struct xqc_packet_out_s { /* PMTUD Probing */ size_t po_max_pkt_out_size; + + /* ping notification */ + xqc_ping_record_t *po_pr; } xqc_packet_out_t; xqc_bool_t xqc_packet_out_on_specific_path(xqc_connection_t *conn, @@ -147,7 +150,8 @@ int xqc_write_ack_to_packets(xqc_connection_t *conn); int xqc_write_ack_to_one_packet(xqc_connection_t *conn, xqc_packet_out_t *packet_out, xqc_pkt_num_space_t pns); -int xqc_write_ping_to_packet(xqc_connection_t *conn, void *po_user_data, xqc_bool_t notify); +int xqc_write_ping_to_packet(xqc_connection_t *conn, xqc_path_ctx_t *path, + void *po_user_data, xqc_bool_t notify, xqc_ping_record_t *pr); int xqc_write_conn_close_to_packet(xqc_connection_t *conn, uint64_t err_code); diff --git a/src/transport/xqc_reinjection.c b/src/transport/xqc_reinjection.c index 921265768..c4e4399c3 100644 --- a/src/transport/xqc_reinjection.c +++ b/src/transport/xqc_reinjection.c @@ -70,25 +70,6 @@ xqc_associate_packet_with_reinjection(xqc_packet_out_t *reinj_origin, } } -void -xqc_disassociate_packet_with_reinjection(xqc_packet_out_t *reinj_origin, - xqc_packet_out_t *reinj_replica) -{ - if (reinj_origin) { - reinj_origin->po_flag &= ~XQC_POF_REINJECTED_ORIGIN; - reinj_origin->po_path_flag &= ~XQC_PATH_SPECIFIED_BY_REINJ; - } - - if (reinj_replica) { - reinj_replica->po_flag &= ~XQC_POF_REINJECTED_REPLICA; - reinj_origin->po_path_flag &= ~XQC_PATH_SPECIFIED_BY_REINJ; - if (reinj_replica->po_origin) { - reinj_replica->po_origin->po_origin_ref_cnt--; - reinj_replica->po_origin = NULL; - } - } -} - static void xqc_packet_out_replicate(xqc_packet_out_t *dst, xqc_packet_out_t *src) @@ -116,7 +97,7 @@ xqc_packet_out_replicate(xqc_packet_out_t *dst, xqc_packet_out_t *src) static xqc_int_t xqc_conn_try_reinject_packet(xqc_connection_t *conn, xqc_packet_out_t *packet_out) { - xqc_path_ctx_t *path = conn->scheduler_callback->xqc_scheduler_get_path(conn->scheduler, conn, packet_out, 1, 1); + xqc_path_ctx_t *path = conn->scheduler_callback->xqc_scheduler_get_path(conn->scheduler, conn, packet_out, 1, 1, NULL); if (path == NULL) { xqc_log(conn->log, XQC_LOG_DEBUG, "|MP|REINJ|fail to schedule a path|reinject|"); return -XQC_EMP_SCHEDULE_PATH; diff --git a/src/transport/xqc_reinjection.h b/src/transport/xqc_reinjection.h index d1dbc9dd2..7fdd2afbd 100644 --- a/src/transport/xqc_reinjection.h +++ b/src/transport/xqc_reinjection.h @@ -22,8 +22,6 @@ xqc_bool_t xqc_packet_can_reinject(xqc_packet_out_t *packet_out); void xqc_associate_packet_with_reinjection(xqc_packet_out_t *reinj_origin, xqc_packet_out_t *reinj_replica); -void xqc_disassociate_packet_with_reinjection(xqc_packet_out_t *reinj_origin, - xqc_packet_out_t *reinj_replica); void xqc_conn_reinject_unack_packets(xqc_connection_t *conn, xqc_reinjection_mode_t mode); diff --git a/src/transport/xqc_send_ctl.c b/src/transport/xqc_send_ctl.c index ec3bdb5ec..1ac5e19fe 100644 --- a/src/transport/xqc_send_ctl.c +++ b/src/transport/xqc_send_ctl.c @@ -1460,6 +1460,7 @@ xqc_send_ctl_on_packet_acked(xqc_send_ctl_t *send_ctl, xqc_stream_t *stream; xqc_packet_out_t *packet_out = acked_packet; xqc_connection_t *conn = send_ctl->ctl_conn; + xqc_bool_t notify_ping; if ((conn->conn_type == XQC_CONN_TYPE_SERVER) && (acked_packet->po_frame_types & XQC_FRAME_BIT_HANDSHAKE_DONE)) { conn->conn_flag |= XQC_CONN_FLAG_HANDSHAKE_DONE_ACKED; @@ -1483,8 +1484,19 @@ xqc_send_ctl_on_packet_acked(xqc_send_ctl_t *send_ctl, if (conn->app_proto_cbs.conn_cbs.conn_ping_acked && (packet_out->po_flag & XQC_POF_NOTIFY)) { - conn->app_proto_cbs.conn_cbs.conn_ping_acked(conn, &conn->scid_set.user_scid, + notify_ping = XQC_TRUE; + if (packet_out->po_pr && packet_out->po_pr->notified) { + notify_ping = XQC_FALSE; + } + + if (notify_ping) { + conn->app_proto_cbs.conn_cbs.conn_ping_acked(conn, &conn->scid_set.user_scid, packet_out->po_user_data, conn->user_data, conn->proto_data); + if (packet_out->po_pr) { + packet_out->po_pr->notified = XQC_TRUE; + } + } + } /* PTMUD probing success */ if (packet_out->po_flag & XQC_POF_PMTUD_PROBING) { diff --git a/src/transport/xqc_send_queue.c b/src/transport/xqc_send_queue.c index a056c8e59..082224416 100644 --- a/src/transport/xqc_send_queue.c +++ b/src/transport/xqc_send_queue.c @@ -8,6 +8,7 @@ #include "src/transport/xqc_send_ctl.h" #include "src/transport/xqc_stream.h" #include "src/transport/xqc_reinjection.h" +#include "src/transport/xqc_conn.h" xqc_send_queue_t * @@ -225,6 +226,15 @@ xqc_send_queue_remove_lost(xqc_list_head_t *pos) void xqc_send_queue_insert_free(xqc_packet_out_t *po, xqc_list_head_t *head, xqc_send_queue_t *send_queue) { + if (po->po_pr) { + if (po->po_pr->ref_cnt <= 1) { + xqc_conn_destroy_ping_record(po->po_pr); + + } else { + po->po_pr->ref_cnt--; + po->po_pr = NULL; + } + } xqc_list_add_tail(&po->po_list, head); send_queue->sndq_packets_free++; send_queue->sndq_packets_used--; @@ -343,13 +353,6 @@ xqc_send_queue_copy_to_lost(xqc_packet_out_t *packet_out, xqc_send_queue_t *send new_po->po_path_flag &= ~XQC_PATH_SPECIFIED_BY_PTO; } - /* clear the flag if the packet is not a reinjected packet anymore */ - if ((new_po->po_flag & XQC_POF_REINJECTED_ORIGIN) - && (new_po->po_origin && !(new_po->po_origin->po_flag & XQC_POF_REINJECTED_ORIGIN))) { - new_po->po_flag &= ~XQC_POF_REINJECTED_ORIGIN; - new_po->po_path_flag &= ~XQC_PATH_SPECIFIED_BY_REINJ; - } - xqc_send_queue_insert_lost(&new_po->po_list, &send_queue->sndq_lost_packets); send_queue->sndq_packets_used++; packet_out->po_flag |= XQC_POF_RETRANSED; @@ -372,13 +375,6 @@ xqc_send_queue_copy_to_probe(xqc_packet_out_t *packet_out, xqc_send_queue_t *sen new_po->po_path_flag |= XQC_PATH_SPECIFIED_BY_PTO; new_po->po_path_id = path->path_id; - /* clear the flag if the packet is not a reinjected packet anymore */ - if ((new_po->po_flag & XQC_POF_REINJECTED_ORIGIN) - && (new_po->po_origin && !(new_po->po_origin->po_flag & XQC_POF_REINJECTED_ORIGIN))) { - new_po->po_flag &= ~XQC_POF_REINJECTED_ORIGIN; - new_po->po_path_flag &= ~XQC_PATH_SPECIFIED_BY_REINJ; - } - xqc_send_queue_insert_probe(&new_po->po_list, &send_queue->sndq_pto_probe_packets); send_queue->sndq_packets_used++; packet_out->po_flag |= XQC_POF_RETRANSED; diff --git a/src/transport/xqc_stream.c b/src/transport/xqc_stream.c index c8479598c..eda1bd23f 100644 --- a/src/transport/xqc_stream.c +++ b/src/transport/xqc_stream.c @@ -134,6 +134,44 @@ xqc_stream_maybe_need_close(xqc_stream_t *stream) } } +void +xqc_stream_close_discarded_stream(xqc_stream_t *stream) +{ + xqc_timer_manager_t *timer_manager; + xqc_usec_t now; + xqc_usec_t pto; + xqc_usec_t new_expire; + + if (stream->stream_flag & XQC_STREAM_FLAG_NEED_CLOSE) { + return; + } + + xqc_log(stream->stream_conn->log, XQC_LOG_DEBUG, + "|stream_id:%ui|stream_type:%d|", + stream->stream_id, stream->stream_type); + + stream->stream_flag |= XQC_STREAM_FLAG_NEED_CLOSE; + + now = xqc_monotonic_timestamp(); + pto = xqc_conn_get_max_pto(stream->stream_conn); + new_expire = now + 3 * pto; + + timer_manager = &stream->stream_conn->conn_timer_manager; + + if ((timer_manager->timer[XQC_TIMER_STREAM_CLOSE].timer_is_set + && new_expire < timer_manager->timer[XQC_TIMER_STREAM_CLOSE].expire_time) + || !timer_manager->timer[XQC_TIMER_STREAM_CLOSE].timer_is_set) + { + xqc_timer_set(timer_manager, XQC_TIMER_STREAM_CLOSE, now, 3 * pto); + } + + stream->stream_close_time = new_expire; + + xqc_list_add_tail(&stream->closing_stream_list, &stream->stream_conn->conn_closing_streams); + xqc_stream_shutdown_read(stream); + xqc_stream_shutdown_write(stream); +} + xqc_stream_t * xqc_find_stream_by_id(xqc_stream_id_t stream_id, xqc_id_hash_table_t *streams_hash) { @@ -432,6 +470,8 @@ xqc_stream_t * xqc_create_stream_with_conn(xqc_connection_t *conn, xqc_stream_id_t stream_id, xqc_stream_type_t stream_type, void *user_data) { + xqc_int_t ret; + if (conn->conn_state >= XQC_CONN_STATE_CLOSING) { xqc_log(conn->log, XQC_LOG_ERROR, "|conn closing, cannot create stream|type:%d|state:%d|flag:%s|", conn->conn_type, conn->conn_state, xqc_conn_flag_2_str(conn->conn_flag)); @@ -494,7 +534,12 @@ xqc_create_stream_with_conn(xqc_connection_t *conn, xqc_stream_id_t stream_id, } if (stream->stream_if->stream_create_notify) { - stream->stream_if->stream_create_notify(stream, stream->user_data); + ret = stream->stream_if->stream_create_notify(stream, stream->user_data); + if (XQC_OK != ret) { + xqc_log(conn->log, XQC_LOG_WARN, "|stream create notify error|" + "|stream_id:%ui", stream->stream_id); + stream->stream_flag |= XQC_STREAM_FLAG_DISCARDED; + } } return stream; @@ -535,7 +580,9 @@ xqc_destroy_stream(xqc_stream_t *stream) xqc_log(stream->stream_conn->log, XQC_LOG_DEBUG, "|send_state:%d|recv_state:%d|stream_id:%ui|stream_type:%d|", stream->stream_state_send, stream->stream_state_recv, stream->stream_id, stream->stream_type); - if (stream->stream_if->stream_close_notify) { + if (stream->stream_if->stream_close_notify + && !(stream->stream_flag & XQC_STREAM_FLAG_DISCARDED)) + { stream->stream_if->stream_close_notify(stream, stream->user_data); } diff --git a/src/transport/xqc_stream.h b/src/transport/xqc_stream.h index ecf37eb05..2297a3f65 100644 --- a/src/transport/xqc_stream.h +++ b/src/transport/xqc_stream.h @@ -35,6 +35,8 @@ typedef enum { XQC_STREAM_FLAG_NEED_CLOSE = 1 << 5, XQC_STREAM_FLAG_FIN_WRITE = 1 << 6, XQC_STREAM_FLAG_CLOSED = 1 << 7, + XQC_STREAM_FLAG_UNEXPECTED = 1 << 8, + XQC_STREAM_FLAG_DISCARDED = 1 << 9, /* stream create_notify with error, all stream data will be discarded */ } xqc_stream_flag_t; typedef enum { @@ -237,5 +239,7 @@ void xqc_stream_set_multipath_usage(xqc_stream_t *stream, uint8_t schedule, uint void xqc_stream_closing(xqc_stream_t *stream, xqc_int_t err); +void xqc_stream_close_discarded_stream(xqc_stream_t *stream); + #endif /* _XQC_STREAM_H_INCLUDED_ */ diff --git a/src/transport/xqc_timer.c b/src/transport/xqc_timer.c index 7df913732..5f3c70e26 100644 --- a/src/transport/xqc_timer.c +++ b/src/transport/xqc_timer.c @@ -143,8 +143,13 @@ xqc_timer_path_idle_timeout(xqc_timer_type_t type, xqc_usec_t now, void *user_da return; } + if (path->path_state < XQC_PATH_STATE_CLOSING) { + xqc_log(conn->log, XQC_LOG_DEBUG, "|closing path:%ui|", path->path_id); + xqc_path_immediate_close(path); + } + if (path->path_state < XQC_PATH_STATE_CLOSED) { - xqc_log(conn->log, XQC_LOG_DEBUG, "|close path:%ui|", path->path_id); + xqc_log(conn->log, XQC_LOG_DEBUG, "|closed path:%ui|", path->path_id); xqc_path_closed(path); } diff --git a/src/transport/xqc_timer.h b/src/transport/xqc_timer.h index 7c261e06f..f2604c02a 100644 --- a/src/transport/xqc_timer.h +++ b/src/transport/xqc_timer.h @@ -17,6 +17,8 @@ */ #define XQC_PING_TIMEOUT 15000 +#define XQC_PMTUD_START_DELAY 10000 + typedef enum xqc_timer_level { XQC_PATH_LEVEL_TIMER, XQC_CONN_LEVEL_TIMER, diff --git a/src/transport/xqc_transport_params.h b/src/transport/xqc_transport_params.h index 4bf5e8b7c..c503c2105 100644 --- a/src/transport/xqc_transport_params.h +++ b/src/transport/xqc_transport_params.h @@ -178,4 +178,4 @@ ssize_t xqc_write_transport_params(char *tp_buf, size_t cap, void xqc_init_transport_params(xqc_transport_params_t *params); -#endif /* XQC_TRANSPORT_PARAMS_H_ */ +#endif /* XQC_TRANSPORT_PARAMS_H_ */ \ No newline at end of file diff --git a/tests/test_client.c b/tests/test_client.c index d81a62ba6..ce69a64ff 100644 --- a/tests/test_client.c +++ b/tests/test_client.c @@ -211,6 +211,7 @@ int g_send_body_size_from_cdf; cdf_entry_t *cdf_list; int cdf_list_size; int g_req_paral = 1; +int g_recovery = 0; int g_save_body; int g_read_body; int g_echo_check; @@ -229,7 +230,7 @@ int g_ipv6; int g_no_crypt; int g_conn_timeout = 1; int g_conn_abs_timeout = 0; -int g_path_timeout = 700000; /* 300ms */ +int g_path_timeout = 5000000; /* 5s */ int g_epoch_timeout = 1000000; /* us */ char g_write_file[256]; char g_read_file[256]; @@ -253,6 +254,7 @@ int g_mp_request_accelerate = 0; double g_copa_ai = 1.0; double g_copa_delta = 0.05; int g_pmtud_on = 0; +int g_mp_ping_on = 0; char g_header_key[MAX_HEADER_KEY_LEN]; char g_header_value[MAX_HEADER_VALUE_LEN]; @@ -1197,7 +1199,7 @@ xqc_client_write_socket_ex(uint64_t path_id, res = sendto(fd, send_buf, send_buf_size, 0, peer_addr, peer_addrlen); if (res < 0) { - printf("xqc_client_write_socket_ex path:%lu err %zd %s %zu\n", path_id, res, strerror(errno), send_buf_size); + printf("xqc_client_write_socket_ex path:%"PRIu64" err %zd %s %zu\n", path_id, res, strerror(errno), send_buf_size); if (errno == EAGAIN) { res = XQC_SOCKET_EAGAIN; } else { @@ -1346,6 +1348,7 @@ xqc_client_bind_to_interface(int fd, memset(&ifr, 0x00, sizeof(ifr)); strncpy(ifr.ifr_name, interface_name, sizeof(ifr.ifr_name) - 1); +#if !defined(__APPLE__) // #if (XQC_TEST_MP) printf("fd: %d. bind to nic: %s\n", fd, interface_name); if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr)) < 0) { @@ -1353,6 +1356,7 @@ xqc_client_bind_to_interface(int fd, return XQC_ERROR; } // #endif +#endif return XQC_OK; } @@ -1387,8 +1391,10 @@ xqc_client_create_socket(int type, goto err; } +#if !defined(__APPLE__) int val = IP_PMTUDISC_DO; setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)); +#endif g_last_sock_op_time = now(); @@ -1610,14 +1616,14 @@ xqc_client_create_conn_socket(user_conn_t *user_conn) void xqc_client_set_path_debug_timer(user_conn_t *user_conn) { - if (g_debug_path) { + if (g_debug_path || g_test_case == 110) { if (user_conn->ev_path == NULL) { user_conn->ev_path = event_new(eb, -1, 0, xqc_client_path_callback, user_conn); } struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = g_path_timeout; + tv.tv_sec = g_path_timeout / 1000000; + tv.tv_usec = g_path_timeout % 1000000; event_add(user_conn->ev_path, &tv); } } @@ -1684,8 +1690,8 @@ xqc_client_conn_close_notify(xqc_connection_t *conn, const xqc_cid_t *cid, void printf("should_clear_0rtt_ticket, conn_err:%d, clear_0rtt_ticket:%d\n", err, xqc_conn_should_clear_0rtt_ticket(err)); xqc_conn_stats_t stats = xqc_conn_get_stats(p_ctx->engine, cid); - printf("send_count:%u, lost_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" early_data_flag:%d, conn_err:%d, mp_state:%d, ack_info:%s\n", - stats.send_count, stats.lost_count, stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err, stats.mp_state, stats.ack_info); + printf("send_count:%u, lost_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" early_data_flag:%d, conn_err:%d, mp_state:%d, ack_info:%s, alpn:%s\n", + stats.send_count, stats.lost_count, stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err, stats.mp_state, stats.ack_info, stats.alpn); printf("conn_info: \"%s\"\n", stats.conn_info); @@ -1739,8 +1745,10 @@ xqc_client_conn_handshake_finished(xqc_connection_t *conn, void *user_data, void DEBUG; user_conn_t *user_conn = (user_conn_t *) user_data; if (!g_test_qch_mode) { - xqc_conn_send_ping(ctx.engine, &user_conn->cid, NULL); - xqc_conn_send_ping(ctx.engine, &user_conn->cid, &g_ping_id); + if (!g_mp_ping_on) { + xqc_conn_send_ping(ctx.engine, &user_conn->cid, NULL); + xqc_conn_send_ping(ctx.engine, &user_conn->cid, &g_ping_id); + } printf("====>DCID:%s\n", xqc_dcid_str_by_scid(ctx.engine, &user_conn->cid)); printf("====>SCID:%s\n", xqc_scid_str(&user_conn->cid)); @@ -1829,8 +1837,8 @@ xqc_client_h3_conn_close_notify(xqc_h3_conn_t *conn, const xqc_cid_t *cid, void printf("should_clear_0rtt_ticket, conn_err:%d, clear_0rtt_ticket:%d\n", err, xqc_conn_should_clear_0rtt_ticket(err)); xqc_conn_stats_t stats = xqc_conn_get_stats(p_ctx->engine, cid); - printf("send_count:%u, lost_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" early_data_flag:%d, conn_err:%d, mp_state:%d, ack_info:%s, conn_info:%s\n", - stats.send_count, stats.lost_count, stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err, stats.mp_state, stats.ack_info, stats.conn_info); + printf("send_count:%u, lost_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" early_data_flag:%d, conn_err:%d, mp_state:%d, ack_info:%s, alpn:%s, conn_info:%s\n", + stats.send_count, stats.lost_count, stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err, stats.mp_state, stats.ack_info, stats.alpn, stats.conn_info); if (!g_test_qch_mode) { printf("[h3-dgram]|recv_dgram_bytes:%zu|sent_dgram_bytes:%zu|lost_dgram_bytes:%zu|lost_cnt:%zu|\n", @@ -1861,8 +1869,10 @@ xqc_client_h3_conn_handshake_finished(xqc_h3_conn_t *h3_conn, void *user_data) p_ctx = &ctx; } - xqc_h3_conn_send_ping(p_ctx->engine, &user_conn->cid, NULL); - xqc_h3_conn_send_ping(p_ctx->engine, &user_conn->cid, &g_ping_id); + if (!g_mp_ping_on) { + xqc_h3_conn_send_ping(p_ctx->engine, &user_conn->cid, NULL); + xqc_h3_conn_send_ping(p_ctx->engine, &user_conn->cid, &g_ping_id); + } xqc_conn_stats_t stats = xqc_conn_get_stats(p_ctx->engine, &user_conn->cid); printf("0rtt_flag:%d\n", stats.early_data_flag); @@ -2686,6 +2696,22 @@ xqc_client_request_send(xqc_h3_request_t *h3_request, user_stream_t *user_stream printf("xqc_h3_request_send_body sent:%zd, offset=%"PRIu64", fin=1\n", ret, user_stream->send_offset); } } + + if (g_test_case == 50) { + ret = xqc_h3_request_send_body(h3_request, user_stream->send_body, 10, 0); + printf("xqc_h3_request_send_body sent:%zd\n", ret); + } + + if (g_test_case == 51) { + ret = xqc_h3_request_send_headers(h3_request, &headers, 1); + printf("xqc_h3_request_send_headers sent:%zd\n", ret); + } + + if (g_test_case == 52) { + ret = xqc_h3_request_finish(h3_request); + } + + return 0; } @@ -3378,6 +3404,9 @@ xqc_client_path_callback(int fd, short what, void *arg) // 判断conn状态 // TODO + if (g_test_case == 110) { + g_test_case = -1; + } int b_add_path = 0; @@ -3419,6 +3448,7 @@ static void xqc_client_epoch_callback(int fd, short what, void *arg) { user_conn_t *user_conn = (user_conn_t *) arg; + int ret; g_cur_epoch++; printf("|xqc_client_epoch_callback|epoch:%d|\n", g_cur_epoch); @@ -3456,7 +3486,52 @@ xqc_client_epoch_callback(int fd, short what, void *arg) } } + if (g_mp_ping_on) { + if (user_conn->h3 == 1) { + xqc_conn_send_ping(ctx.engine, &user_conn->cid, NULL); + xqc_conn_send_ping(ctx.engine, &user_conn->cid, &g_ping_id); + } else { + xqc_h3_conn_send_ping(ctx.engine, &user_conn->cid, NULL); + xqc_h3_conn_send_ping(ctx.engine, &user_conn->cid, &g_ping_id); + } + } + + if (g_test_case == 107 && !g_recovery) { + /* freeze the first path */ + ret = xqc_conn_mark_path_frozen(ctx.engine, &(user_conn->cid), 0); + if (ret < 0) { + printf("xqc_conn_mark_path_frozen err = %d\n", ret); + } + g_recovery = g_cur_epoch + 2; + } + + if (g_test_case == 108 && !g_recovery) { + /* freeze the second path */ + ret = xqc_conn_mark_path_frozen(ctx.engine, &(user_conn->cid), 1); + if (ret < 0) { + printf("xqc_conn_mark_path_frozen err = %d\n", ret); + } + g_recovery = g_cur_epoch + 2; + } + + if (g_test_case == 107 && g_recovery == g_cur_epoch) { + g_test_case = -1; + /* freeze the first path */ + ret = xqc_conn_mark_path_standby(ctx.engine, &(user_conn->cid), 0); + if (ret < 0) { + printf("xqc_conn_mark_path_standby err = %d\n", ret); + } + } + + if (g_test_case == 108 && g_recovery == g_cur_epoch) { + g_test_case = -1; + /* freeze the second path */ + ret = xqc_conn_mark_path_standby(ctx.engine, &(user_conn->cid), 1); + if (ret < 0) { + printf("xqc_conn_mark_path_standby err = %d\n", ret); + } + } if (g_cur_epoch < g_epoch) { struct timeval tv; @@ -3588,44 +3663,48 @@ xqc_client_ready_to_create_path(const xqc_cid_t *cid, return; } - for (int i = 0; i < g_multi_interface_cnt; i++) { - if (g_client_path[i].is_in_used == 1) { - continue; - } - - int ret = xqc_conn_create_path(ctx.engine, &(user_conn->cid), &path_id); - - if (ret < 0) { - printf("not support mp, xqc_conn_create_path err = %d\n", ret); - return; - } - - printf("***** create a new path. index: %d, path_id: %" PRIu64 "\n", i, path_id); - g_client_path[i].path_id = path_id; - g_client_path[i].is_in_used = 1; + if (g_test_case != 110) { + for (int i = 0; i < g_multi_interface_cnt; i++) { + if (g_client_path[i].is_in_used == 1) { + continue; + } + + int ret = xqc_conn_create_path(ctx.engine, &(user_conn->cid), &path_id); - if (g_test_case == 104) { - ret = xqc_conn_mark_path_standby(ctx.engine, &(user_conn->cid), 0); if (ret < 0) { - printf("xqc_conn_mark_path_standby err = %d\n", ret); + printf("not support mp, xqc_conn_create_path err = %d\n", ret); + return; } - ret = xqc_conn_mark_path_available(ctx.engine, &(user_conn->cid), 1); - if (ret < 0) { - printf("xqc_conn_mark_path_available err = %d\n", ret); + + printf("***** create a new path. index: %d, path_id: %" PRIu64 "\n", i, path_id); + g_client_path[i].path_id = path_id; + g_client_path[i].is_in_used = 1; + + if (g_test_case == 104) { + ret = xqc_conn_mark_path_standby(ctx.engine, &(user_conn->cid), 0); + if (ret < 0) { + printf("xqc_conn_mark_path_standby err = %d\n", ret); + } + ret = xqc_conn_mark_path_available(ctx.engine, &(user_conn->cid), 1); + if (ret < 0) { + printf("xqc_conn_mark_path_available err = %d\n", ret); + } } - } - if (g_mp_backup_mode) { - ret = xqc_conn_mark_path_standby(ctx.engine, &(user_conn->cid), path_id); - if (ret < 0) { - printf("xqc_conn_mark_path_standby err = %d\n", ret); + if (g_mp_backup_mode) { + ret = xqc_conn_mark_path_standby(ctx.engine, &(user_conn->cid), path_id); + if (ret < 0) { + printf("xqc_conn_mark_path_standby err = %d\n", ret); + } } - } - xqc_client_set_path_debug_timer(user_conn); + xqc_client_set_path_debug_timer(user_conn); + } + + } else { + xqc_client_set_path_debug_timer(user_conn); } - } static void xqc_client_concurrent_callback(int fd, short what, void *arg){ @@ -3920,6 +3999,7 @@ int main(int argc, char *argv[]) { {"epoch_timeout", required_argument, &long_opt_index, 3}, {"dgram_qos", required_argument, &long_opt_index, 4}, {"pmtud", required_argument, &long_opt_index, 5}, + {"mp_ping", required_argument, &long_opt_index, 6}, {0, 0, 0, 0} }; @@ -4178,6 +4258,11 @@ int main(int argc, char *argv[]) { printf("option g_pmtud_on: %d\n", g_pmtud_on); break; + case 6: + g_mp_ping_on = atoi(optarg); + printf("option g_mp_ping_on: %d\n", g_mp_ping_on); + break; + default: break; } @@ -4246,7 +4331,7 @@ int main(int argc, char *argv[]) { } #endif } -#ifndef XQC_DISABLE_RENO +#ifdef XQC_ENABLE_RENO else if (c_cong_ctl == 'r') { cong_ctrl = xqc_reno_cb; } @@ -4266,13 +4351,19 @@ int main(int argc, char *argv[]) { #endif } #endif +#ifdef XQC_ENABLE_UNLIMITED else if (c_cong_ctl == 'u') { cong_ctrl = xqc_unlimited_cc_cb; - } else if (c_cong_ctl == 'P') { + } +#endif +#ifdef XQC_ENABLE_COPA + else if (c_cong_ctl == 'P') { cong_ctrl = xqc_copa_cb; - } else { + } +#endif + else { printf("unknown cong_ctrl, option is b, r, c, B, bbr+, bbr2+, u\n"); return -1; } @@ -4294,6 +4385,7 @@ int main(int argc, char *argv[]) { .max_datagram_frame_size = g_max_dgram_size, .enable_multipath = g_enable_multipath, .marking_reinjection = 1, + .mp_ping_on = g_mp_ping_on, }; @@ -4537,6 +4629,11 @@ int main(int argc, char *argv[]) { conn_settings.reinj_ctl_callback = xqc_dgram_reinj_ctl_cb; conn_settings.mp_enable_reinjection = 4; conn_settings.scheduler_callback = xqc_rap_scheduler_cb; + } else if (g_enable_reinjection == 4) { + conn_settings.reinj_ctl_callback = xqc_dgram_reinj_ctl_cb; + conn_settings.mp_enable_reinjection = 4; + conn_settings.scheduler_callback = xqc_rap_scheduler_cb; + conn_settings.datagram_redundant_probe = 30000; } if (g_mp_backup_mode) { diff --git a/tests/test_server.c b/tests/test_server.c index 255e29bcf..efd475134 100644 --- a/tests/test_server.c +++ b/tests/test_server.c @@ -81,6 +81,7 @@ typedef struct user_stream_s { int snd_times; int rcv_times; + struct event *ev_timeout; } user_stream_t; typedef struct user_conn_s { @@ -675,8 +676,8 @@ xqc_server_conn_close_notify(xqc_connection_t *conn, const xqc_cid_t *cid, void DEBUG; user_conn_t *user_conn = (user_conn_t *)user_data; xqc_conn_stats_t stats = xqc_conn_get_stats(ctx.engine, cid); - printf("send_count:%u, lost_count:%u, lost_dgram_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" early_data_flag:%d, conn_err:%d, ack_info:%s\n", - stats.send_count, stats.lost_count, stats.lost_dgram_count, stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err, stats.ack_info); + printf("send_count:%u, lost_count:%u, lost_dgram_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" early_data_flag:%d, conn_err:%d, ack_info:%s, alpn:%s\n", + stats.send_count, stats.lost_count, stats.lost_dgram_count, stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err, stats.ack_info, stats.alpn); printf("[dgram]|recv_dgram_bytes:%zu|sent_dgram_bytes:%zu|lost_dgram_bytes:%zu|lost_cnt:%zu|\n", user_conn->dgram_blk->data_recv, user_conn->dgram_blk->data_sent, @@ -772,7 +773,7 @@ xqc_server_stream_send(xqc_stream_t *stream, void *user_data) return 0; } else { - printf("xqc_stream_send sent_bytes=%"PRIu64"\n", ret); + printf("xqc_stream_send sent_bytes=%zd\n", ret); } } else { ret = xqc_stream_send(stream, user_stream->send_body + user_stream->send_offset, user_stream->send_body_len - user_stream->send_offset, 1); @@ -812,6 +813,10 @@ xqc_server_stream_create_notify(xqc_stream_t *stream, void *user_data) xqc_stream_send(stream, NULL, 0, 1); } + if (g_test_case == 15) { + return -1; + } + return 0; } @@ -941,8 +946,8 @@ xqc_server_h3_conn_close_notify(xqc_h3_conn_t *h3_conn, const xqc_cid_t *cid, vo DEBUG; user_conn_t *user_conn = (user_conn_t*)conn_user_data; xqc_conn_stats_t stats = xqc_conn_get_stats(ctx.engine, cid); - printf("send_count:%u, lost_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" early_data_flag:%d, conn_err:%d, ack_info:%s, conn_info:%s\n", - stats.send_count, stats.lost_count, stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err, stats.ack_info, stats.conn_info); + printf("send_count:%u, lost_count:%u, tlp_count:%u, recv_count:%u, srtt:%"PRIu64" early_data_flag:%d, conn_err:%d, ack_info:%s, conn_info:%s, alpn:%s\n", + stats.send_count, stats.lost_count, stats.tlp_count, stats.recv_count, stats.srtt, stats.early_data_flag, stats.conn_err, stats.ack_info, stats.conn_info, stats.alpn); printf("[h3-dgram]|recv_dgram_bytes:%zu|sent_dgram_bytes:%zu|lost_dgram_bytes:%zu|lost_cnt:%zu|\n", user_conn->dgram_blk->data_recv, user_conn->dgram_blk->data_sent, @@ -973,6 +978,19 @@ xqc_server_h3_conn_handshake_finished(xqc_h3_conn_t *h3_conn, void *conn_user_da xqc_conn_stats_t stats = xqc_conn_get_stats(ctx.engine, &user_conn->cid); printf("0rtt_flag:%d\n", stats.early_data_flag); printf("h3_datagram_mss:%zd\n", xqc_h3_ext_datagram_get_mss(h3_conn)); + + + /* pretend to create a server-inited http3 stream */ + if (g_test_case == 17) { + xqc_stream_t * stream = xqc_stream_create_with_direction( + xqc_h3_conn_get_xqc_conn(h3_conn), XQC_STREAM_BIDI, NULL); + printf("--- server create stream\n"); + + unsigned char szbuf[4096] = {0}; + xqc_stream_send(stream, szbuf, 4096, 1); + + } + } void @@ -1114,6 +1132,13 @@ int xqc_h3_ext_bytestream_write_callback(xqc_h3_ext_bytestream_t *h3_ext_bs, return 0; } +void +xqc_client_h3_send_pure_fin(int fd, short what, void *arg) +{ + user_stream_t *user_stream = arg; + xqc_h3_request_finish(user_stream->h3_request); +} + #define MAX_HEADER 100 @@ -1175,12 +1200,23 @@ xqc_server_request_send(xqc_h3_request_t *h3_request, user_stream_t *user_stream }; int header_only = 0; + int send_fin = 1; + if (g_echo && user_stream->recv_body_len == 0) { header_only = 1; } + if (g_test_case == 100) { + user_stream->ev_timeout = event_new(eb, -1, 0, xqc_client_h3_send_pure_fin, user_stream); + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + event_add(user_stream->ev_timeout, &tv); + send_fin = 0; + } + if (user_stream->header_sent == 0) { - ret = xqc_h3_request_send_headers(h3_request, &headers, header_only); + ret = xqc_h3_request_send_headers(h3_request, &headers, header_only && send_fin); if (ret < 0) { printf("xqc_h3_request_send_headers error %zd\n", ret); return ret; @@ -1234,7 +1270,7 @@ xqc_server_request_send(xqc_h3_request_t *h3_request, user_stream_t *user_stream if (user_stream->send_offset < user_stream->send_body_len) { ret = xqc_h3_request_send_body(h3_request, user_stream->send_body + user_stream->send_offset, - user_stream->send_body_len - user_stream->send_offset, 1); + user_stream->send_body_len - user_stream->send_offset, send_fin); if (ret < 0) { printf("xqc_h3_request_send_body error %zd\n", ret); return 0; @@ -1286,6 +1322,13 @@ xqc_server_request_close_notify(xqc_h3_request_t *h3_request, void *user_data) { DEBUG; user_stream_t *user_stream = (user_stream_t*)user_data; + + if (g_test_case == 100) { + if (user_stream->ev_timeout) { + event_free(user_stream->ev_timeout); + } + } + free(user_stream->send_body); free(user_stream->recv_body); free(user_stream); @@ -2298,7 +2341,7 @@ int main(int argc, char *argv[]) { } #endif } -#ifndef XQC_DISABLE_RENO +#ifdef XQC_ENABLE_RENO else if (c_cong_ctl == 'r') { cong_ctrl = xqc_reno_cb; } @@ -2317,13 +2360,19 @@ int main(int argc, char *argv[]) { #endif } #endif +#ifdef XQC_ENABLE_UNLIMITED else if (c_cong_ctl == 'u') { cong_ctrl = xqc_unlimited_cc_cb; - } else if (c_cong_ctl == 'P') { + } +#endif +#ifdef XQC_ENABLE_COPA + else if (c_cong_ctl == 'P') { cong_ctrl = xqc_copa_cb; - } else { + } +#endif + else { printf("unknown cong_ctrl, option is b, r, c, u\n"); return -1; } diff --git a/tests/unittest/xqc_reno_test.c b/tests/unittest/xqc_reno_test.c index f1c1e5f64..d97f962d5 100644 --- a/tests/unittest/xqc_reno_test.c +++ b/tests/unittest/xqc_reno_test.c @@ -20,7 +20,7 @@ print_reno(xqc_new_reno_t *reno) void xqc_test_reno() { -#ifdef XQC_DISABLE_RENO +#ifndef XQC_ENABLE_RENO return; #endif xqc_msec_t now = xqc_monotonic_timestamp(); diff --git a/xqc_build.sh b/xqc_build.sh index 7901772e7..6b1fcabc2 100755 --- a/xqc_build.sh +++ b/xqc_build.sh @@ -53,7 +53,13 @@ if [ x"$platform" == xios ] ; then -DGCOV=OFF -DCMAKE_TOOLCHAIN_FILE=${IOS_CMAKE_TOOLCHAIN} -DENABLE_BITCODE=0 - -DXQC_NO_SHARED=1" + -DXQC_NO_SHARED=1 + -DXQC_COMPAT_GENERATE_SR_PKT=1 + -DXQC_ENABLE_RENO=0 + -DXQC_ENABLE_BBR2=0 + -DXQC_ENABLE_COPA=0 + -DXQC_ENABLE_UNLIMITED=0 + -DXQC_ENABLE_MP_INTEROP=0" elif [ x"$platform" == xandroid ] ; then if [ x"$ANDROID_NDK" == x ] ; then @@ -72,11 +78,15 @@ elif [ x"$platform" == xandroid ] ; then -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_STL=c++_shared -DANDROID_NATIVE_API_LEVEL=android-19 - -DXQC_DISABLE_RENO=OFF - -DXQC_ENABLE_BBR2=ON + -DXQC_ENABLE_RENO=OFF + -DXQC_ENABLE_BBR2=OFF + -DXQC_ENABLE_COPA=OFF + -DXQC_ENABLE_UNLIMITED=OFF + -DXQC_ENABLE_MP_INTEROP=OFF -DXQC_DISABLE_LOG=OFF - -DXQC_ONLY_ERROR_LOG=ON" -else + -DXQC_ONLY_ERROR_LOG=ON + -DXQC_COMPAT_GENERATE_SR_PKT=ON" +else echo "no support platform" exit 0 fi diff --git a/xqc_configure.h.in b/xqc_configure.h.in index c6ca83e53..93347d033 100644 --- a/xqc_configure.h.in +++ b/xqc_configure.h.in @@ -1,4 +1,9 @@ - /* the configured options and settings for xquic */ #define xquic_VERSION_MAJOR @xquic_VERSION_MAJOR@ #define xquic_VERSION_MINOR @xquic_VERSION_MINOR@ + +#cmakedefine XQC_ENABLE_BBR2 +#cmakedefine XQC_ENABLE_RENO +#cmakedefine XQC_ENABLE_COPA +#cmakedefine XQC_ENABLE_UNLIMITED +#cmakedefine XQC_ENABLE_MP_INTEROP \ No newline at end of file