From 084338b1a2bec0ffcee1dadf2ff846c5919226e5 Mon Sep 17 00:00:00 2001 From: George Wang Date: Wed, 2 Jun 2021 00:39:15 -0400 Subject: [PATCH] Release 3.0.0 --- CHANGELOG | 8 +++++++ docs/conf.py | 4 ++-- include/lsquic.h | 32 +++++---------------------- src/liblsquic/lsquic_conn_public.h | 1 + src/liblsquic/lsquic_enc_sess.h | 1 - src/liblsquic/lsquic_enc_sess_ietf.c | 7 +++--- src/liblsquic/lsquic_engine.c | 4 ---- src/liblsquic/lsquic_full_conn.c | 5 ++++- src/liblsquic/lsquic_full_conn_ietf.c | 27 ++++++++++++++-------- src/liblsquic/lsquic_ietf.h | 2 +- src/liblsquic/lsquic_parse.h | 2 +- src/liblsquic/lsquic_parse_common.c | 30 ------------------------- src/liblsquic/lsquic_send_ctl.c | 7 ++++++ src/liblsquic/lsquic_stream.c | 4 +++- src/liblsquic/lsquic_version.c | 8 ------- tests/test_h3_framing.c | 2 +- 16 files changed, 55 insertions(+), 89 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 51931f2..8d266d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,11 @@ +2021-06-02 + - 3.0.0 + - Enable HTTP/3 v1 by default, drop draft 34. + - Prevent connection timeout when client does not send PING frame. + - Close connection ASAP after recieve CONNECTION_CLOSE (issue #284) + - Do not assert() when decode a trailer. + - Properly handle GOAWAY frame, do not close the last acknowledged stream. + 2021-04-20 - 2.30.2 - Update ls-hpack to 2.3.0 to address dynamic table size limit (issue #260). diff --git a/docs/conf.py b/docs/conf.py index 8641e4f..e0e2209 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,9 +24,9 @@ copyright = u'2021, LiteSpeed Technologies' author = u'LiteSpeed Technologies' # The short X.Y version -version = u'2.30' +version = u'3.0' # The full version, including alpha/beta/rc tags -release = u'2.30.2' +release = u'3.0.0' # -- General configuration --------------------------------------------------- diff --git a/include/lsquic.h b/include/lsquic.h index 32ea94f..42706d0 100644 --- a/include/lsquic.h +++ b/include/lsquic.h @@ -23,9 +23,9 @@ struct sockaddr; extern "C" { #endif -#define LSQUIC_MAJOR_VERSION 2 -#define LSQUIC_MINOR_VERSION 30 -#define LSQUIC_PATCH_VERSION 2 +#define LSQUIC_MAJOR_VERSION 3 +#define LSQUIC_MINOR_VERSION 0 +#define LSQUIC_PATCH_VERSION 0 /** * Engine flags: @@ -64,18 +64,6 @@ enum lsquic_version */ LSQVER_050, -#if LSQUIC_USE_Q098 - /** - * Q098. This is a made-up, experimental version used to test version - * negotiation. The choice of 98 is similar to Google's choice of 99 - * as the "IETF" version. - */ - LSQVER_098, -#define LSQUIC_EXPERIMENTAL_Q098 (1 << LSQVER_098) -#else -#define LSQUIC_EXPERIMENTAL_Q098 0 -#endif - /** * IETF QUIC Draft-27 */ @@ -87,13 +75,7 @@ enum lsquic_version LSQVER_ID29, /** - * IETF QUIC Draft-34 - */ - LSQVER_ID34, - - /** - * IETF QUIC v1. Functionally the same as Draft-34, but marked - * experimental for now. + * IETF QUIC v1. */ LSQVER_I001, @@ -119,8 +101,7 @@ enum lsquic_version #define LSQUIC_FORCED_TCID0_VERSIONS ((1 << LSQVER_046)|(1 << LSQVER_050)) #define LSQUIC_EXPERIMENTAL_VERSIONS ( \ - (1 << LSQVER_I001) | \ - (1 << LSQVER_VERNEG) | LSQUIC_EXPERIMENTAL_Q098) + (1 << LSQVER_VERNEG)) #define LSQUIC_DEPRECATED_VERSIONS ((1 << LSQVER_ID27)) @@ -128,12 +109,11 @@ enum lsquic_version #define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) \ | (1 << LSQVER_ID29) \ - | (1 << LSQVER_ID34) \ | (1 << LSQVER_I001) | (1 << LSQVER_VERNEG)) #define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) \ | (1 << LSQVER_ID29) \ - | (1 << LSQVER_ID34) | (1 << LSQVER_VERNEG)) + | (1 << LSQVER_VERNEG)) enum lsquic_hsk_status { diff --git a/src/liblsquic/lsquic_conn_public.h b/src/liblsquic/lsquic_conn_public.h index ac732d0..21e31f1 100644 --- a/src/liblsquic/lsquic_conn_public.h +++ b/src/liblsquic/lsquic_conn_public.h @@ -67,6 +67,7 @@ struct lsquic_conn_public { /* Used for no-progress timeout */ lsquic_time_t last_tick, last_prog; unsigned max_peer_ack_usec; + uint8_t n_special_streams; }; #endif diff --git a/src/liblsquic/lsquic_enc_sess.h b/src/liblsquic/lsquic_enc_sess.h index a7d0bf2..400500c 100644 --- a/src/liblsquic/lsquic_enc_sess.h +++ b/src/liblsquic/lsquic_enc_sess.h @@ -340,7 +340,6 @@ extern const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1; #define select_esf_common_by_ver(ver) ( \ ver == LSQVER_ID27 ? &lsquic_enc_session_common_ietf_v1 : \ ver == LSQVER_ID29 ? &lsquic_enc_session_common_ietf_v1 : \ - ver == LSQVER_ID34 ? &lsquic_enc_session_common_ietf_v1 : \ ver == LSQVER_I001 ? &lsquic_enc_session_common_ietf_v1 : \ ver == LSQVER_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \ ver == LSQVER_050 ? &lsquic_enc_session_common_gquic_2 : \ diff --git a/src/liblsquic/lsquic_enc_sess_ietf.c b/src/liblsquic/lsquic_enc_sess_ietf.c index e6ea02a..a70557f 100644 --- a/src/liblsquic/lsquic_enc_sess_ietf.c +++ b/src/liblsquic/lsquic_enc_sess_ietf.c @@ -73,7 +73,6 @@ static const struct alpn_map { } s_h3_alpns[] = { { LSQVER_ID27, (unsigned char *) "\x05h3-27", }, { LSQVER_ID29, (unsigned char *) "\x05h3-29", }, - { LSQVER_ID34, (unsigned char *) "\x05h3-34", }, { LSQVER_I001, (unsigned char *) "\x02h3", }, { LSQVER_VERNEG, (unsigned char *) "\x05h3-34", }, }; @@ -928,7 +927,7 @@ iquic_esfi_create_client (const char *hostname, } #if BORINGSSL_API_VERSION >= 13 SSL_set_quic_use_legacy_codepoint(enc_sess->esi_ssl, - enc_sess->esi_ver_neg->vn_ver < LSQVER_ID34); + enc_sess->esi_ver_neg->vn_ver < LSQVER_I001); #endif transpa_len = gen_trans_params(enc_sess, trans_params, @@ -1138,7 +1137,7 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid) if (enc_sess->esi_conn->cn_version < LSQVER_ID29) salt = HSK_SALT_PRE29; - else if (enc_sess->esi_conn->cn_version < LSQVER_ID34) + else if (enc_sess->esi_conn->cn_version < LSQVER_I001) salt = HSK_SALT_PRE33; else salt = HSK_SALT; @@ -1394,7 +1393,7 @@ iquic_esfi_init_server (enc_session_t *enc_session_p) } #if BORINGSSL_API_VERSION >= 13 SSL_set_quic_use_legacy_codepoint(enc_sess->esi_ssl, - enc_sess->esi_conn->cn_version < LSQVER_ID34); + enc_sess->esi_conn->cn_version < LSQVER_I001); #endif if (!(SSL_set_quic_method(enc_sess->esi_ssl, &cry_quic_method))) { diff --git a/src/liblsquic/lsquic_engine.c b/src/liblsquic/lsquic_engine.c index be6341d..c3dcff5 100644 --- a/src/liblsquic/lsquic_engine.c +++ b/src/liblsquic/lsquic_engine.c @@ -3007,11 +3007,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine, parse_packet_in_begin = lsquic_Q050_parse_packet_in_begin; else { -#if LSQUIC_USE_Q098 - assert(conn->cn_version == LSQVER_046 || conn->cn_version == LSQVER_098); -#else assert(conn->cn_version == LSQVER_046); -#endif parse_packet_in_begin = lsquic_Q046_parse_packet_in_begin; } } diff --git a/src/liblsquic/lsquic_full_conn.c b/src/liblsquic/lsquic_full_conn.c index 5348824..ab5ebf5 100644 --- a/src/liblsquic/lsquic_full_conn.c +++ b/src/liblsquic/lsquic_full_conn.c @@ -3499,7 +3499,10 @@ full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now) * more than 1 packet over CWND. */ tick |= TICK_SEND; - goto end_write; + if (conn->fc_flags & FC_CLOSING) + goto end_write; + else + goto end; } /* Try to fit any of the following three frames -- STOP_WAITING, diff --git a/src/liblsquic/lsquic_full_conn_ietf.c b/src/liblsquic/lsquic_full_conn_ietf.c index 85ad937..28f2eac 100644 --- a/src/liblsquic/lsquic_full_conn_ietf.c +++ b/src/liblsquic/lsquic_full_conn_ietf.c @@ -1041,6 +1041,8 @@ create_uni_stream_out (struct ietf_full_conn *conn, int priority, } if (priority >= 0) lsquic_stream_set_priority_internal(stream, priority); + else + ++conn->ifc_pub.n_special_streams; lsquic_stream_call_on_new(stream); return 0; } @@ -1682,12 +1684,12 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub, LSQ_DEBUG("Calling on_new_conn callback"); conn->ifc_conn.cn_conn_ctx = conn->ifc_enpub->enp_stream_if->on_new_conn( conn->ifc_enpub->enp_stream_if_ctx, &conn->ifc_conn); + conn->ifc_idle_to = conn->ifc_settings->es_idle_timeout * 1000000; if (0 != handshake_ok(&conn->ifc_conn)) goto err3; conn->ifc_created = imc->imc_created; - conn->ifc_idle_to = conn->ifc_settings->es_idle_timeout * 1000000; if (conn->ifc_idle_to) lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE, imc->imc_created + conn->ifc_idle_to); @@ -5262,6 +5264,7 @@ struct buffered_priority_update }; +#define MAX_CRITICAL_STREAM_ID 12 /* This function is called to create incoming streams */ static struct lsquic_stream * new_stream (struct ietf_full_conn *conn, lsquic_stream_id_t stream_id, @@ -5287,7 +5290,11 @@ new_stream (struct ietf_full_conn *conn, lsquic_stream_id_t stream_id, * to address this is to reclassify them later? */ #endif - flags |= SCF_CRITICAL; + if (stream_id < MAX_CRITICAL_STREAM_ID) + { + flags |= SCF_CRITICAL; + ++conn->ifc_pub.n_special_streams; + } } else { @@ -8248,7 +8255,10 @@ ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now) * than 1 packet over CWND. */ tick |= TICK_SEND; - goto end_write; + if (conn->ifc_flags & IFC_CLOSING) + goto end_write; + else + goto end; } /* Try to fit MAX_DATA before checking if we have run out of room. @@ -8409,7 +8419,8 @@ ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now) * packets and poor performance. */ if (conn->ifc_ping_period - && lsquic_hash_count(conn->ifc_pub.all_streams) > 0) + && lsquic_hash_count(conn->ifc_pub.all_streams) > + conn->ifc_pub.n_special_streams) lsquic_alarmset_set(&conn->ifc_alset, AL_PING, now + conn->ifc_ping_period); @@ -9100,7 +9111,7 @@ on_goaway_client_27 (void *ctx, uint64_t stream_id) el = lsquic_hash_next(conn->ifc_pub.all_streams)) { stream = lsquic_hashelem_getdata(el); - if (stream->id >= stream_id + if (stream->id > stream_id && (stream->id & SIT_MASK) == SIT_BIDI_CLIENT) { lsquic_stream_received_goaway(stream); @@ -9155,7 +9166,7 @@ on_goaway_client (void *ctx, uint64_t stream_id) el = lsquic_hash_next(conn->ifc_pub.all_streams)) { stream = lsquic_hashelem_getdata(el); - if (stream->id >= stream_id + if (stream->id > stream_id && (stream->id & SIT_MASK) == SIT_BIDI_CLIENT) { lsquic_stream_received_goaway(stream); @@ -9177,7 +9188,7 @@ on_goaway_server (void *ctx, uint64_t max_push_id) el = lsquic_hash_next(conn->ifc_pub.u.ietf.promises)) { promise = lsquic_hashelem_getdata(el); - if (promise->pp_id >= max_push_id) + if (promise->pp_id > max_push_id) cancel_push_promise(conn, promise); } } @@ -9427,7 +9438,6 @@ hcsi_on_new (void *stream_if_ctx, struct lsquic_stream *stream) callbacks = &hcsi_callbacks_server_27; break; case (0 << 8) | LSQVER_ID29: - case (0 << 8) | LSQVER_ID34: case (0 << 8) | LSQVER_I001: callbacks = &hcsi_callbacks_client_29; break; @@ -9435,7 +9445,6 @@ hcsi_on_new (void *stream_if_ctx, struct lsquic_stream *stream) assert(0); /* fallthru */ case (1 << 8) | LSQVER_ID29: - case (1 << 8) | LSQVER_ID34: case (1 << 8) | LSQVER_I001: callbacks = &hcsi_callbacks_server_29; break; diff --git a/src/liblsquic/lsquic_ietf.h b/src/liblsquic/lsquic_ietf.h index 73a04bb..367713c 100644 --- a/src/liblsquic/lsquic_ietf.h +++ b/src/liblsquic/lsquic_ietf.h @@ -38,7 +38,7 @@ extern const unsigned char *const lsquic_retry_key_buf[N_IETF_RETRY_VERSIONS]; extern const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS]; #define lsquic_version_2_retryver(ver_) ( \ (ver_) <= LSQVER_ID27 ? 0 : \ - (ver_) <= LSQVER_ID34 ? 1 : \ + (ver_) <= LSQVER_I001 ? 1 : \ 2) #endif diff --git a/src/liblsquic/lsquic_parse.h b/src/liblsquic/lsquic_parse.h index e702fe6..562104d 100644 --- a/src/liblsquic/lsquic_parse.h +++ b/src/liblsquic/lsquic_parse.h @@ -345,7 +345,7 @@ extern const struct parse_funcs lsquic_parse_funcs_ietf_v1; &lsquic_parse_funcs_gquic_Q043 : \ (1 << (ver)) & (1 << LSQVER_046) ? \ &lsquic_parse_funcs_gquic_Q046 : \ - (1 << (ver)) & ((1 << LSQVER_050)|LSQUIC_EXPERIMENTAL_Q098) ? \ + (1 << (ver)) & (1 << LSQVER_050) ? \ &lsquic_parse_funcs_gquic_Q050 : \ &lsquic_parse_funcs_ietf_v1) diff --git a/src/liblsquic/lsquic_parse_common.c b/src/liblsquic/lsquic_parse_common.c index 1c47e3a..ee7bcc5 100644 --- a/src/liblsquic/lsquic_parse_common.c +++ b/src/liblsquic/lsquic_parse_common.c @@ -366,36 +366,6 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] = | QUIC_FTBIT_DATAGRAM , }, - [LSQVER_ID34] = { - [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING - | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE, - [ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING - | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM - | QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE - | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA - | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED - | QUIC_FTBIT_STREAMS_BLOCKED - | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING - | QUIC_FTBIT_PATH_CHALLENGE - | QUIC_FTBIT_DATAGRAM - | QUIC_FTBIT_RETIRE_CONNECTION_ID, - [ENC_LEV_INIT] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING - | QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE, - [ENC_LEV_FORW] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING - | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE - | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM - | QUIC_FTBIT_BLOCKED - | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA - | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED - | QUIC_FTBIT_STREAMS_BLOCKED - | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING - | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE - | QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY - | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN - | QUIC_FTBIT_TIMESTAMP - | QUIC_FTBIT_DATAGRAM - , - }, [LSQVER_ID29] = { [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE, diff --git a/src/liblsquic/lsquic_send_ctl.c b/src/liblsquic/lsquic_send_ctl.c index d5d5d62..78b4dd7 100644 --- a/src/liblsquic/lsquic_send_ctl.c +++ b/src/liblsquic/lsquic_send_ctl.c @@ -1240,6 +1240,13 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl, ctl->sc_flags &= ~SC_WAS_QUIET; LSQ_DEBUG("ACK comes after a period of quiescence"); ctl->sc_ci->cci_was_quiet(CGP(ctl), now, ctl->sc_bytes_unacked_all); + if (packet_out && (packet_out->po_frame_types & QUIC_FTBIT_PING) + && ctl->sc_conn_pub->last_prog) + { + LSQ_DEBUG("ACK to PING frame, update last progress to %"PRIu64, + ctl->sc_conn_pub->last_tick); + ctl->sc_conn_pub->last_prog = ctl->sc_conn_pub->last_tick; + } } if (UNLIKELY(!packet_out)) diff --git a/src/liblsquic/lsquic_stream.c b/src/liblsquic/lsquic_stream.c index 2651e10..b68aaed 100644 --- a/src/liblsquic/lsquic_stream.c +++ b/src/liblsquic/lsquic_stream.c @@ -5067,7 +5067,9 @@ hq_filter_df (struct lsquic_stream *stream, struct data_frame *data_frame) (unsigned) data_frame->df_size - data_frame->df_read_off); else { - assert(data_frame->df_read_off == data_frame->df_size); + if (!(filter->hqfi_type == HQFT_HEADERS + && (filter->hqfi_flags & HQFI_FLAG_BLOCKED))) + assert(data_frame->df_read_off == data_frame->df_size); return 0; } } diff --git a/src/liblsquic/lsquic_version.c b/src/liblsquic/lsquic_version.c index 067b97f..c643cb7 100644 --- a/src/liblsquic/lsquic_version.c +++ b/src/liblsquic/lsquic_version.c @@ -15,12 +15,8 @@ static const unsigned char version_tags[N_LSQVER][4] = [LSQVER_043] = { 'Q', '0', '4', '3', }, [LSQVER_046] = { 'Q', '0', '4', '6', }, [LSQVER_050] = { 'Q', '0', '5', '0', }, -#if LSQUIC_USE_Q098 - [LSQVER_098] = { 'Q', '0', '9', '8', }, -#endif [LSQVER_ID27] = { 0xFF, 0, 0, 27, }, [LSQVER_ID29] = { 0xFF, 0, 0, 29, }, - [LSQVER_ID34] = { 0xFF, 0, 0, 34, }, [LSQVER_I001] = { 0, 0, 0, 1, }, [LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, }, }; @@ -55,12 +51,8 @@ const char *const lsquic_ver2str[N_LSQVER] = { [LSQVER_043] = "Q043", [LSQVER_046] = "Q046", [LSQVER_050] = "Q050", -#if LSQUIC_USE_Q098 - [LSQVER_098] = "Q098", -#endif [LSQVER_ID27] = "FF00001B", [LSQVER_ID29] = "FF00001D", - [LSQVER_ID34] = "FF000022", [LSQVER_I001] = "00000001", [LSQVER_VERNEG] = "FAFAFAFA", }; diff --git a/tests/test_h3_framing.c b/tests/test_h3_framing.c index 5b6694e..9e4c951 100644 --- a/tests/test_h3_framing.c +++ b/tests/test_h3_framing.c @@ -1143,7 +1143,7 @@ fuzz_guided_pwritev_testing (const char *input) case 3: version = LSQVER_ID27; break; case 4: version = LSQVER_ID29; break; default: - case 5: version = LSQVER_ID34; break; + case 5: version = LSQVER_I001; break; } sched_immed = !!(buf[8] & 0x08);