From 3edf740e3a6372bc50e8d3fac1ce54a46f71c194 Mon Sep 17 00:00:00 2001 From: Huanhuan Zheng <140379011+cherylsy@users.noreply.github.com> Date: Wed, 8 Nov 2023 20:37:04 +0800 Subject: [PATCH] [+]Merge interop into main (#364) * [!] fix interop testcase: antiamplication, multiplexing, zerortt, recovery, keyupdate * [+] Add new case test & Merge master change into interop branch (#347) * [+] QUIC datagram (RFC9221), sending datagrams and bytestreams on http3 connections (non-standard extensions), and bugfix (#307) *[!] fix vulnerabilities on parsing STREAM and CRYPTO frame; * [+] update contributor * [!] fix test case errors on ubuntu latest * [+] Export SSL handler of HTTP/3 connection for ssl_protocol, ssl_cipher, etc. (#310) * [+] Export SSL handler of HTTP/3 connection for ssl_protocol, ssl_cipher, etc. * [!] fix format of function return * [+] support standard stateless reset (#313) * [+] update multipath to draft-04; (#317) * [+] support pmtu; * fix complie error: specified bound depends on the length of the source argument (#312) * fix complie error: specified bound depends on the length of the source argument * fix stringop-overflow complie error * fix stringop-overflow complie error * Doc/rfc9114 (#223) * Update draft-ietf-quic-http-34-zh.md * Update draft-ietf-quic-http-34-zh.md * Update draft-ietf-quic-http-34-zh.md * Create rfc9114-http3-zh.md * [=] add usage specifications for test_client and test_server (#318) * [+] support multipath interop (#320) * [+] add no_crypto and serrial options for mpquic interop (#321) * Update doc (and comment) multipath-[01|02] => 04 (#326) * demo: fix typo (xuqic -> xquic) (#328) * [+] add .gitignore (#329) * fix: use off_t instead of int for filesize (#332) * [!] fix http3 deadloop and segmentation fault, fix stream compose error (#338) * [+]Enable multipath-05 etc. (#340) * [=] fix README-zh-CN doc link (#341) * [!] fix interop testcase: antiamplication, multiplexing, zerortt, recovery, keyupdate * [~]Fix error during rebase * [+]Add new testcase in run endpoint --------- Co-authored-by: Wu Zhao Co-authored-by: lianglli Co-authored-by: Bobo Co-authored-by: robinhzp <9974622@qq.com> Co-authored-by: Alexis La Goutte Co-authored-by: Yanmei Liu Co-authored-by: Marcel Co-authored-by: RuiqiZhou * [~] Add mp option when running ./demo_server (#349) * [~]enable gen new_conn_id (#352) * [~]merge interop & Solve conflicts (#358) [~] merge interop branch to main branch * [+]Add interop mode signal & change param * [~] Fix key update error & add interop mode in demo_client * [~]add casetest being deleted accidentally * [+] Add interop-mod param in run_endpoint.sh * [~]fix rebase code * [+]demo_server add interop param * [~]add continue_send_reqs in hq_close_notify to fix multiplexing failed --------- Co-authored-by: RuiqiZhou Co-authored-by: Wu Zhao Co-authored-by: lianglli Co-authored-by: Bobo Co-authored-by: robinhzp <9974622@qq.com> Co-authored-by: Alexis La Goutte Co-authored-by: Yanmei Liu Co-authored-by: Marcel --- demo/demo_client.c | 14 +++++++-- demo/demo_server.c | 11 ++++++- include/xquic/xquic.h | 6 ++++ interop/run_endpoint.sh | 22 ++++++++++---- scripts/case_test.sh | 1 - src/tls/xqc_crypto.c | 8 ++++-- src/transport/xqc_conn.c | 43 +++++++++++++++++++--------- src/transport/xqc_conn.h | 1 - src/transport/xqc_engine.c | 1 + src/transport/xqc_frame_parser.c | 2 +- src/transport/xqc_packet_out.h | 1 + src/transport/xqc_packet_parser.c | 1 + src/transport/xqc_send_ctl.c | 6 ++-- src/transport/xqc_transport_params.c | 2 +- 14 files changed, 88 insertions(+), 31 deletions(-) diff --git a/demo/demo_client.c b/demo/demo_client.c index 823053a0f..e00370389 100644 --- a/demo/demo_client.c +++ b/demo/demo_client.c @@ -171,6 +171,9 @@ typedef struct xqc_demo_cli_quic_config_s { uint8_t mp_version; + /* support interop test */ + int is_interop_mode; + uint8_t send_path_standby; xqc_msec_t path_status_timer_threshold; @@ -1070,6 +1073,7 @@ xqc_demo_cli_hq_req_close_notify(xqc_hq_request_t *hqr, void *req_user_data) stats.send_body_size, stats.recv_body_size, stats.stream_info); /* task schedule */ + xqc_demo_cli_continue_send_reqs(user_stream->user_conn); xqc_demo_cli_on_stream_fin(user_stream); free(user_stream->send_buf); @@ -1625,6 +1629,7 @@ xqc_demo_cli_init_conneciton_settings(xqc_conn_settings_t* settings, settings->standby_path_probe_timeout = 1000; settings->multipath_version = args->quic_cfg.mp_version; settings->mp_ping_on = 1; + settings->is_interop_mode = args->quic_cfg.is_interop_mode; if (args->req_cfg.throttled_req != -1) { settings->enable_stream_rate_limit = 1; settings->recv_rate_bytes_per_sec = 0; @@ -1756,6 +1761,7 @@ xqc_demo_cli_usage(int argc, char *argv[]) " -u key update packet threshold\n" " -d do not save responses to files\n" " -M enable multipath\n" + " -o use interop mode\n" " -i interface to create a path. For instance, we can use '-i lo -i lo' to create two paths via lo.\n" " -w waiting N ms to start the first request.\n" " -P enable MPQUIC to return ACK_MPs on any paths.\n" @@ -1779,7 +1785,7 @@ void xqc_demo_cli_parse_args(int argc, char *argv[], xqc_demo_cli_client_args_t *args) { int ch = 0; - while ((ch = getopt(argc, argv, "a:p:c:Ct:S:0m:A:D:l:L:k:K:U:u:dMi:w:Ps:bZ:NQT:R:V:B:I:n:eE")) != -1) { + while ((ch = getopt(argc, argv, "a:p:c:Ct:S:0m:A:D:l:L:k:K:U:u:dMoi:w:Ps:bZ:NQT:R:V:B:I:n:eE")) != -1) { switch (ch) { /* server ip */ case 'a': @@ -1920,7 +1926,11 @@ xqc_demo_cli_parse_args(int argc, char *argv[], xqc_demo_cli_client_args_t *args printf("option multipath on\n"); args->net_cfg.multipath = 1; break; - + + case 'o': + printf("set interop mode\n"); + args->quic_cfg.is_interop_mode = 1; + break; case 'i': printf("option adding interface: %s\n", optarg); if (args->net_cfg.ifcnt < MAX_PATH_CNT) { diff --git a/demo/demo_server.c b/demo/demo_server.c index 9d7554655..1291f1ee6 100644 --- a/demo/demo_server.c +++ b/demo/demo_server.c @@ -89,6 +89,8 @@ typedef struct xqc_demo_svr_quic_config_s { /* multipath version */ int multipath_version; + /* support interop test */ + int is_interop_mode; /* ack on any path */ int mp_ack_on_any_path; @@ -1179,6 +1181,7 @@ xqc_demo_svr_usage(int argc, char *argv[]) " -k Key output file path\n" " -r retry\n" " -d do not read responses from files\n" + " -i use interop mode\n" " -M enable MPQUIC.\n" " -P enable MPQUIC to return ACK_MPs on any paths.\n" " -s multipath scheduler (interop, minrtt, backup), default: interop\n" @@ -1228,7 +1231,7 @@ void xqc_demo_svr_parse_args(int argc, char *argv[], xqc_demo_svr_args_t *args) { int ch = 0; - while ((ch = getopt(argc, argv, "p:c:CD:l:L:6k:rdMPs:R:u:a:")) != -1) { + while ((ch = getopt(argc, argv, "p:c:CD:l:L:6k:rdMiPs:R:u:a:")) != -1) { switch (ch) { /* listen port */ case 'p': @@ -1303,6 +1306,11 @@ xqc_demo_svr_parse_args(int argc, char *argv[], xqc_demo_svr_args_t *args) args->quic_cfg.dummy_mode = 1; break; + case 'i': + printf("set interop mode\n"); + args->quic_cfg.is_interop_mode = 1; + break; + case 'M': printf("option multipath enabled\n"); args->quic_cfg.multipath = 1; @@ -1453,6 +1461,7 @@ xqc_demo_svr_init_conn_settings(xqc_demo_svr_args_t *args) .standby_path_probe_timeout = 1000, .keyupdate_pkt_threshold = args->quic_cfg.keyupdate_pkt_threshold, .least_available_cid_count = args->quic_cfg.least_available_cid_count, + .is_interop_mode = args->quic_cfg.is_interop_mode, }; xqc_server_set_conn_settings(&conn_settings); diff --git a/include/xquic/xquic.h b/include/xquic/xquic.h index 8a1dda1e2..6dafb870e 100644 --- a/include/xquic/xquic.h +++ b/include/xquic/xquic.h @@ -1261,6 +1261,12 @@ typedef struct xqc_conn_settings_s { */ uint32_t init_recv_window; + /* + * initial flow control value + */ + xqc_bool_t is_interop_mode; + + } xqc_conn_settings_t; diff --git a/interop/run_endpoint.sh b/interop/run_endpoint.sh index 88d6f2b4f..6a64002a6 100644 --- a/interop/run_endpoint.sh +++ b/interop/run_endpoint.sh @@ -4,7 +4,7 @@ /setup.sh case $TESTCASE in - versionnegotiation|handshake|longrtt|transfer|zerortt|multiconnect|chacha20|resumption|http3|retry|keyupdate) + versionnegotiation|handshake|longrtt|transfer|zerortt|multiconnect|chacha20|resumption|http3|retry|keyupdate|mphandshake|mptransfer|mppathabandon|mppathstatus) : ;; *) @@ -20,7 +20,7 @@ if [ "$ROLE" == "client" ]; then /wait-for-it.sh sim:57832 -s -t 30 # client args - ARGS="-l d -L "$LOG_DIR/client.log" -D "/downloads" -k $SSLKEYLOGFILE -K 30" + ARGS="-l d -L "$LOG_DIR/client.log" -D "/downloads" -k $SSLKEYLOGFILE -K 30 -o" # zerortt if [ "$TESTCASE" == "zerortt" ]; then @@ -45,9 +45,9 @@ if [ "$ROLE" == "client" ]; then for REQ in $REQUESTS; do echo -e "\nstart requesty[$i]: $REQ" - echo -e "./demo_client -l d -L \"/logs/log_$i.log\" -D \"/downloads\" -k $SSLKEYLOGFILE -U \"$REQ\" -K 60\n" + echo -e "./demo_client -l d -L \"/logs/log_$i.log\" -D \"/downloads\" -k $SSLKEYLOGFILE -U \"$REQ\" -K 90 -o\n" # ./demo_client -l d -L "/logs/log_$i.log" -D "/downloads" -k $SSLKEYLOGFILE -U "$REQ" -A "h3" -0 -K 90 - ./demo_client -l d -L "/logs/log_$i.log" -D "/downloads" -k $SSLKEYLOGFILE -U "$REQ" -0 -K 90 + ./demo_client -l d -L "/logs/log_$i.log" -D "/downloads" -k $SSLKEYLOGFILE -U "$REQ" -0 -K 90 -o i=`expr $i + 1` done @@ -62,7 +62,19 @@ if [ "$ROLE" == "client" ]; then elif [ "$TESTCASE" == "keyupdate" ]; then echo "./demo_client $ARGS -U $REQUESTS -u 30" ./demo_client $ARGS -U "$REQUESTS" -u 30 + + elif [ "$TESTCASE" == "mphandshake" ] || [ "$TESTCASE" == "mptransfer" ]; then + echo "./demo_client $ARGS -U $REQUESTS -M -i eth0 -i eth0 -w 3000" + ./demo_client $ARGS -U "$REQUESTS" -M -i eth0 -i eth0 -w 3000 + elif [ "$TESTCASE" == "mppathabandon" ]; then + echo "./demo_client $ARGS -U $REQUESTS -M -i eth0 -i eth0 -w 3000 -Z 1000" + ./demo_client $ARGS -U "$REQUESTS" -M -i eth0 -i eth0 -w 3000 -Z 1000 + + elif [ "$TESTCASE" == "mppathstatus" ]; then + echo "./demo_client $ARGS -U $REQUESTS -M -i eth0 -i eth0 -w 3000 -b" + ./demo_client $ARGS -U "$REQUESTS" -M -i eth0 -i eth0 -w 3000 -b + # common testcase else echo -e "./demo_client $ARGS -U \"$REQUESTS\"\n" @@ -85,7 +97,7 @@ elif [ "$ROLE" == "server" ]; then #cp -r /www /logs - ARGS="-l d -L "$LOG_DIR/server.log" -p 443 -D "/www" -k $SSLKEYLOGFILE" + ARGS="-l d -L "$LOG_DIR/server.log" -p 443 -D "/www" -k $SSLKEYLOGFILE -i -M" echo "./demo_server $ARGS" ./demo_server $ARGS fi diff --git a/scripts/case_test.sh b/scripts/case_test.sh index 9d939f0ea..9782ab3f6 100755 --- a/scripts/case_test.sh +++ b/scripts/case_test.sh @@ -3475,7 +3475,6 @@ if [ "$cli_res1" == "1" ] && [ -n "$cli_res2" ] \ else echo ">>>>>>>> pass:0" case_print_result "h3_ext_finish_bytestream_during_transmission" "fail" - exit fi # close bytestream during transmission (-x 305) diff --git a/src/tls/xqc_crypto.c b/src/tls/xqc_crypto.c index 02b5300fb..56e709a93 100644 --- a/src/tls/xqc_crypto.c +++ b/src/tls/xqc_crypto.c @@ -661,9 +661,13 @@ xqc_crypto_derive_updated_keys(xqc_crypto_t *crypto, xqc_key_type_t type) /* update application traffic secret */ static uint8_t LABEL[] = "quic ku"; - uint8_t dest_buf[INITIAL_SECRET_MAX_LEN]; + uint8_t dest_buf[XQC_MAX_KNP_LEN]; - ret = xqc_hkdf_expand_label(dest_buf, INITIAL_SECRET_MAX_LEN, + if (current_ckm->secret.len > XQC_MAX_KNP_LEN) { + return -XQC_TLS_UPDATE_KEY_ERROR; + } + + ret = xqc_hkdf_expand_label(dest_buf, current_ckm->secret.len, current_ckm->secret.base, current_ckm->secret.len, LABEL, xqc_lengthof(LABEL), &crypto->md); if (ret != XQC_OK) { diff --git a/src/transport/xqc_conn.c b/src/transport/xqc_conn.c index 8155b7fff..c83a66033 100644 --- a/src/transport/xqc_conn.c +++ b/src/transport/xqc_conn.c @@ -70,6 +70,8 @@ xqc_conn_settings_t default_conn_settings = { .recv_rate_bytes_per_sec = 0, .enable_stream_rate_limit = 0, + + .is_interop_mode = 0, }; @@ -158,6 +160,7 @@ xqc_server_set_conn_settings(const xqc_conn_settings_t *settings) } default_conn_settings.enable_multipath = settings->enable_multipath; + default_conn_settings.is_interop_mode = settings->is_interop_mode; if (xqc_conn_is_current_mp_version_supported(settings->multipath_version) == XQC_OK) { default_conn_settings.multipath_version = settings->multipath_version; @@ -325,9 +328,17 @@ xqc_conn_init_trans_settings(xqc_connection_t *conn) xqc_conn_set_default_settings(rs); /* set local default setting values */ - ls->max_streams_bidi = 1024; - ls->max_stream_data_bidi_remote = XQC_MAX_RECV_WINDOW; + if (conn->conn_settings.is_interop_mode) { + ls->max_streams_bidi = 128; + ls->max_streams_uni = 128; + } else { + ls->max_streams_bidi = 1024; + ls->max_streams_uni = 1024; + } + ls->max_stream_data_bidi_remote = XQC_MAX_RECV_WINDOW; + ls->max_stream_data_uni = XQC_MAX_RECV_WINDOW; + if (conn->conn_settings.enable_stream_rate_limit) { ls->max_stream_data_bidi_local = conn->conn_settings.init_recv_window; @@ -335,18 +346,20 @@ xqc_conn_init_trans_settings(xqc_connection_t *conn) ls->max_stream_data_bidi_local = XQC_MAX_RECV_WINDOW; } - ls->max_streams_uni = 1024; - ls->max_stream_data_uni = XQC_MAX_RECV_WINDOW; - - if (conn->conn_settings.recv_rate_bytes_per_sec) { - ls->max_data = conn->conn_settings.recv_rate_bytes_per_sec * XQC_FC_INIT_RTT / 1000000; - ls->max_data = xqc_max(XQC_MIN_RECV_WINDOW, ls->max_data); - ls->max_data = xqc_min(XQC_MAX_RECV_WINDOW, ls->max_data); - + if (conn->conn_settings.is_interop_mode) { + ls->max_data = 1024 * 1024; + } else { - /* max_data is the sum of stream_data on all uni and bidi streams */ - ls->max_data = ls->max_streams_bidi * ls->max_stream_data_bidi_local - + ls->max_streams_uni * ls->max_stream_data_uni; + if (conn->conn_settings.recv_rate_bytes_per_sec) { + ls->max_data = conn->conn_settings.recv_rate_bytes_per_sec * XQC_FC_INIT_RTT / 1000000; + ls->max_data = xqc_max(XQC_MIN_RECV_WINDOW, ls->max_data); + ls->max_data = xqc_min(XQC_MAX_RECV_WINDOW, ls->max_data); + + } else { + /* max_data is the sum of stream_data on all uni and bidi streams */ + ls->max_data = ls->max_streams_bidi * ls->max_stream_data_bidi_local + + ls->max_streams_uni * ls->max_stream_data_uni; + } } ls->max_idle_timeout = conn->conn_settings.idle_time_out; @@ -371,6 +384,8 @@ xqc_conn_init_flow_ctl(xqc_connection_t *conn) { xqc_conn_flow_ctl_t *flow_ctl = &conn->conn_flow_ctl; xqc_trans_settings_t * settings = & conn->local_settings; + + /* TODO: send params are inited to be zero, until zerortt inited or handshake done */ flow_ctl->fc_max_data_can_send = settings->max_data; /* replace with the value specified by peer after handshake */ flow_ctl->fc_max_data_can_recv = settings->max_data; flow_ctl->fc_max_streams_bidi_can_send = settings->max_streams_bidi; /* replace with the value specified by peer after handshake */ @@ -1805,7 +1820,7 @@ xqc_conn_enc_packet(xqc_connection_t *conn, conn->conn_state = XQC_CONN_STATE_CLOSED; return -XQC_EENCRYPT; } - + packet_out->po_sent_time = current_time; return XQC_OK; } diff --git a/src/transport/xqc_conn.h b/src/transport/xqc_conn.h index 7fe56dce3..2700a8d6d 100644 --- a/src/transport/xqc_conn.h +++ b/src/transport/xqc_conn.h @@ -666,5 +666,4 @@ 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 7f8b2a6d7..779d880e7 100644 --- a/src/transport/xqc_engine.c +++ b/src/transport/xqc_engine.c @@ -754,6 +754,7 @@ xqc_engine_process_conn(xqc_connection_t *conn, xqc_usec_t now) } XQC_CHECK_IMMEDIATE_CLOSE(); + ret = xqc_conn_try_add_new_conn_id(conn, 0); if (ret) { xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_conn_try_add_new_conn_id error|"); diff --git a/src/transport/xqc_frame_parser.c b/src/transport/xqc_frame_parser.c index d7e3edf7f..f999ca502 100644 --- a/src/transport/xqc_frame_parser.c +++ b/src/transport/xqc_frame_parser.c @@ -2466,4 +2466,4 @@ xqc_parse_path_available_frame(xqc_packet_in_t *packet_in, packet_in->pi_frame_types |= XQC_FRAME_BIT_PATH_AVAILABLE; return XQC_OK; -} \ No newline at end of file +} diff --git a/src/transport/xqc_packet_out.h b/src/transport/xqc_packet_out.h index aff345178..fea842bcc 100644 --- a/src/transport/xqc_packet_out.h +++ b/src/transport/xqc_packet_out.h @@ -72,6 +72,7 @@ typedef struct xqc_packet_out_s { size_t po_buf_cap; /* capcacity of po_buf */ unsigned int po_buf_size; /* size of po_buf can be used */ unsigned int po_used_size; + unsigned int po_enc_size; /* size of po after being encrypted */ unsigned int po_ack_offset; xqc_packet_out_flag_t po_flag; /* Largest Acknowledged in ACK frame, initiated to be 0 */ diff --git a/src/transport/xqc_packet_parser.c b/src/transport/xqc_packet_parser.c index a55ed8e28..5ce865809 100644 --- a/src/transport/xqc_packet_parser.c +++ b/src/transport/xqc_packet_parser.c @@ -714,6 +714,7 @@ xqc_packet_encrypt_buf(xqc_connection_t *conn, xqc_packet_out_t *packet_out, } } + packet_out->po_enc_size = *enc_pkt_len; return XQC_OK; } diff --git a/src/transport/xqc_send_ctl.c b/src/transport/xqc_send_ctl.c index b9f9e3037..64c67f85d 100644 --- a/src/transport/xqc_send_ctl.c +++ b/src/transport/xqc_send_ctl.c @@ -618,8 +618,8 @@ xqc_send_ctl_on_packet_sent(xqc_send_ctl_t *send_ctl, xqc_pn_ctl_t *pn_ctl, xqc_ xqc_packet_number_t orig_pktnum = packet_out->po_origin ? packet_out->po_origin->po_pkt.pkt_num : 0; xqc_log(send_ctl->ctl_conn->log, XQC_LOG_DEBUG, - "|conn:%p|path:%ui|pkt_num:%ui|origin_pktnum:%ui|size:%ud|pkt_type:%s|frame:%s|conn_state:%s|po_in_flight:%d|", - send_ctl->ctl_conn, send_ctl->ctl_path->path_id, packet_out->po_pkt.pkt_num, orig_pktnum, packet_out->po_used_size, + "|conn:%p|path:%ui|pkt_num:%ui|origin_pktnum:%ui|size:%ud|enc_size:%ud|pkt_type:%s|frame:%s|conn_state:%s|po_in_flight:%d|", + send_ctl->ctl_conn, send_ctl->ctl_path->path_id, packet_out->po_pkt.pkt_num, orig_pktnum, packet_out->po_used_size, packet_out->po_enc_size, xqc_pkt_type_2_str(packet_out->po_pkt.pkt_type), xqc_frame_type_2_str(packet_out->po_frame_types), xqc_conn_state_2_str(send_ctl->ctl_conn->conn_state), @@ -646,7 +646,7 @@ xqc_send_ctl_on_packet_sent(xqc_send_ctl_t *send_ctl, xqc_pn_ctl_t *pn_ctl, xqc_ pn_ctl->ctl_largest_sent[pns] = packet_out->po_pkt.pkt_num; } - send_ctl->ctl_bytes_send += packet_out->po_used_size; + send_ctl->ctl_bytes_send += packet_out->po_enc_size; if (packet_out->po_largest_ack > 0) { xqc_ack_sent_record_add(&pn_ctl->ack_sent_record[pns], packet_out, send_ctl->ctl_srtt, now); diff --git a/src/transport/xqc_transport_params.c b/src/transport/xqc_transport_params.c index 312e4ace7..944ee5e63 100644 --- a/src/transport/xqc_transport_params.c +++ b/src/transport/xqc_transport_params.c @@ -682,7 +682,7 @@ xqc_trans_param_get_index(uint64_t param_type) case XQC_TRANSPORT_PARAM_ENABLE_MULTIPATH_04: case XQC_TRANSPORT_PARAM_ENABLE_MULTIPATH_05: - case XQC_TRANSPORT_PARAM_ENABLE_MULTIPATH_06: + case XQC_TRANSPORT_PARAM_ENABLE_MULTIPATH_06: return XQC_TRANSPORT_PARAM_PROTOCOL_MAX + 1; case XQC_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE: