From 0231c9067f02aa3214f27380018ac980fa34d8f5 Mon Sep 17 00:00:00 2001 From: nodejs-github-bot <18269663+nodejs-github-bot@users.noreply.github.com> Date: Sun, 23 Feb 2025 00:34:14 +0000 Subject: [PATCH] deps: update ngtcp2 to 1.11.0 --- .../crypto/includes/ngtcp2/ngtcp2_crypto.h | 4 +- deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c | 47 +- .../ngtcp2/lib/includes/ngtcp2/ngtcp2.h | 8 +- .../ngtcp2/lib/includes/ngtcp2/version.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c | 114 ++ deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h | 44 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c | 23 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h | 30 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c | 79 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h | 1 + deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c | 6 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h | 13 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c | 1300 ++++++----------- deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h | 121 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.c | 497 +++++++ deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.h | 343 +++++ deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c | 20 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h | 44 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c | 27 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c | 2 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c | 6 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c | 8 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c | 8 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h | 10 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c | 16 - deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h | 11 - deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c | 7 + deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h | 18 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c | 2 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h | 2 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c | 11 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c | 11 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h | 6 + deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c | 25 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h | 4 - .../ngtcp2/lib/ngtcp2_transport_params.c | 9 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c | 34 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h | 16 - 40 files changed, 1724 insertions(+), 1215 deletions(-) create mode 100644 deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.c create mode 100644 deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.h diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h index 68093d18b71b14..4eaf615bd309f3 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h @@ -331,7 +331,7 @@ ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp, * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`) to * set negotiated AEAD and message digest algorithm. After the * successful call of this function, application can use - * `ngtcp2_conn_get_crypto_ctx` (or `ngtcp2_conn_get_early_crypto_ctx` + * `ngtcp2_conn_get_crypto_ctx` (or `ngtcp2_conn_get_0rtt_crypto_ctx` * if |level| == * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`) to * get :type:`ngtcp2_crypto_ctx`. @@ -378,7 +378,7 @@ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_rx_key( * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`) to * set negotiated AEAD and message digest algorithm. After the * successful call of this function, application can use - * `ngtcp2_conn_get_crypto_ctx` (or `ngtcp2_conn_get_early_crypto_ctx` + * `ngtcp2_conn_get_crypto_ctx` (or `ngtcp2_conn_get_0rtt_crypto_ctx` * if |level| == * :enum:`ngtcp2_encryption_level.NGTCP2_ENCRYPTION_LEVEL_0RTT`) to * get :type:`ngtcp2_crypto_ctx`. diff --git a/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c b/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c index c3f14f5d444bac..98ebf9e876c053 100644 --- a/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c +++ b/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c @@ -125,7 +125,7 @@ static int supported_cipher_suite(ptls_cipher_suite_t *cs) { #ifdef PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 || cs->aead == &ptls_openssl_chacha20poly1305 #endif /* defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305) */ - ; + ; } ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, @@ -146,7 +146,7 @@ ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, ctx->hp.native_handle = (void *)crypto_cipher_suite_get_hp(cs); ctx->max_encryption = crypto_cipher_suite_get_aead_max_encryption(cs); ctx->max_decryption_failure = - crypto_cipher_suite_get_aead_max_decryption_failure(cs); + crypto_cipher_suite_get_aead_max_decryption_failure(cs); return ctx; } @@ -329,19 +329,22 @@ int ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead, const uint8_t *nonce, size_t noncelen, const uint8_t *aad, size_t aadlen) { ptls_aead_context_t *actx = aead_ctx->native_handle; + size_t nwrite; (void)aead; ptls_aead_xor_iv(actx, nonce, noncelen); - if (ptls_aead_decrypt(actx, dest, ciphertext, ciphertextlen, 0, aad, - aadlen) == SIZE_MAX) { - return -1; - } + nwrite = + ptls_aead_decrypt(actx, dest, ciphertext, ciphertextlen, 0, aad, aadlen); /* zero-out static iv once again */ ptls_aead_xor_iv(actx, nonce, noncelen); + if (nwrite == SIZE_MAX) { + return -1; + } + return 0; } @@ -360,13 +363,13 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, } int ngtcp2_crypto_read_write_crypto_data( - ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, - const uint8_t *data, size_t datalen) { + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + const uint8_t *data, size_t datalen) { ngtcp2_crypto_picotls_ctx *cptls = ngtcp2_conn_get_tls_native_handle(conn); ptls_buffer_t sendbuf; size_t epoch_offsets[5] = {0}; size_t epoch = - ngtcp2_crypto_picotls_from_ngtcp2_encryption_level(encryption_level); + ngtcp2_crypto_picotls_from_ngtcp2_encryption_level(encryption_level); size_t epoch_datalen; size_t i; int rv; @@ -388,7 +391,7 @@ int ngtcp2_crypto_read_write_crypto_data( if (!ngtcp2_conn_is_server(conn) && cptls->handshake_properties.client.early_data_acceptance == - PTLS_EARLY_DATA_REJECTED) { + PTLS_EARLY_DATA_REJECTED) { rv = ngtcp2_conn_tls_early_data_rejected(conn); if (rv != 0) { rv = -1; @@ -405,8 +408,8 @@ int ngtcp2_crypto_read_write_crypto_data( assert(i != 1); if (ngtcp2_conn_submit_crypto_data( - conn, ngtcp2_crypto_picotls_from_epoch(i), - sendbuf.base + epoch_offsets[i], epoch_datalen) != 0) { + conn, ngtcp2_crypto_picotls_from_epoch(i), + sendbuf.base + epoch_offsets[i], epoch_datalen) != 0) { rv = -1; goto fin; } @@ -463,7 +466,7 @@ ngtcp2_encryption_level ngtcp2_crypto_picotls_from_epoch(size_t epoch) { } size_t ngtcp2_crypto_picotls_from_ngtcp2_encryption_level( - ngtcp2_encryption_level encryption_level) { + ngtcp2_encryption_level encryption_level) { switch (encryption_level) { case NGTCP2_ENCRYPTION_LEVEL_INITIAL: return 0; @@ -532,8 +535,8 @@ static int set_additional_extensions(ptls_handshake_properties_t *hsprops, } int ngtcp2_crypto_picotls_collect_extension( - ptls_t *ptls, struct st_ptls_handshake_properties_t *properties, - uint16_t type) { + ptls_t *ptls, struct st_ptls_handshake_properties_t *properties, + uint16_t type) { (void)ptls; (void)properties; @@ -541,8 +544,8 @@ int ngtcp2_crypto_picotls_collect_extension( } int ngtcp2_crypto_picotls_collected_extensions( - ptls_t *ptls, struct st_ptls_handshake_properties_t *properties, - ptls_raw_extension_t *extensions) { + ptls_t *ptls, struct st_ptls_handshake_properties_t *properties, + ptls_raw_extension_t *extensions) { ngtcp2_crypto_conn_ref *conn_ref; ngtcp2_conn *conn; int rv; @@ -558,7 +561,7 @@ int ngtcp2_crypto_picotls_collected_extensions( conn = conn_ref->get_conn(conn_ref); rv = ngtcp2_conn_decode_and_set_remote_transport_params( - conn, extensions->data.base, extensions->data.len); + conn, extensions->data.base, extensions->data.len); if (rv != 0) { ngtcp2_conn_set_tls_error(conn, rv); return -1; @@ -613,7 +616,7 @@ static int update_traffic_key_server_cb(ptls_update_traffic_key_t *self, } static ptls_update_traffic_key_t update_traffic_key_server = { - update_traffic_key_server_cb, + update_traffic_key_server_cb, }; static int update_traffic_key_cb(ptls_update_traffic_key_t *self, ptls_t *ptls, @@ -661,7 +664,7 @@ int ngtcp2_crypto_picotls_configure_client_context(ptls_context_t *ctx) { } int ngtcp2_crypto_picotls_configure_server_session( - ngtcp2_crypto_picotls_ctx *cptls) { + ngtcp2_crypto_picotls_ctx *cptls) { ptls_handshake_properties_t *hsprops = &cptls->handshake_properties; hsprops->collect_extension = ngtcp2_crypto_picotls_collect_extension; @@ -671,7 +674,7 @@ int ngtcp2_crypto_picotls_configure_server_session( } int ngtcp2_crypto_picotls_configure_client_session( - ngtcp2_crypto_picotls_ctx *cptls, ngtcp2_conn *conn) { + ngtcp2_crypto_picotls_ctx *cptls, ngtcp2_conn *conn) { ptls_handshake_properties_t *hsprops = &cptls->handshake_properties; hsprops->client.max_early_data_size = calloc(1, sizeof(size_t)); @@ -692,7 +695,7 @@ int ngtcp2_crypto_picotls_configure_client_session( } void ngtcp2_crypto_picotls_deconfigure_session( - ngtcp2_crypto_picotls_ctx *cptls) { + ngtcp2_crypto_picotls_ctx *cptls) { ptls_handshake_properties_t *hsprops; ptls_raw_extension_t *exts; diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h index 87976b1444b95d..d2a2fe1fe1be0d 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h @@ -167,8 +167,12 @@ typedef void *(*ngtcp2_realloc)(void *ptr, size_t size, void *user_data); * } * * void conn_new() { - * ngtcp2_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb, - * my_realloc_cb}; + * ngtcp2_mem mem = { + * .malloc = my_malloc_cb, + * .free = my_free_cb, + * .calloc = my_calloc_cb, + * .realloc = my_realloc_cb, + * }; * * ... * } diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h index 20c4ac24d2ebcd..bb983f5cf44be3 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h @@ -36,7 +36,7 @@ * * Version number of the ngtcp2 library release. */ -#define NGTCP2_VERSION "1.10.0" +#define NGTCP2_VERSION "1.11.0" /** * @macro @@ -46,6 +46,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGTCP2_VERSION_NUM 0x010a00 +#define NGTCP2_VERSION_NUM 0x010b00 #endif /* !defined(NGTCP2_VERSION_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c index 0e5bfe069e9fab..776dc0c2c3ef1a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c @@ -25,6 +25,7 @@ #include "ngtcp2_acktr.h" #include +#include #include "ngtcp2_macro.h" #include "ngtcp2_tstamp.h" @@ -70,6 +71,9 @@ void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, acktr->flags = NGTCP2_ACKTR_FLAG_NONE; acktr->first_unacked_ts = UINT64_MAX; acktr->rx_npkt = 0; + acktr->max_pkt_num = -1; + acktr->max_pkt_ts = UINT64_MAX; + memset(&acktr->ecn, 0, sizeof(acktr->ecn)); } void ngtcp2_acktr_free(ngtcp2_acktr *acktr) { @@ -180,6 +184,11 @@ int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack, ngtcp2_acktr_entry_objalloc_del(delent, &acktr->objalloc); } + if (acktr->max_pkt_num < pkt_num) { + acktr->max_pkt_num = pkt_num; + acktr->max_pkt_ts = ts; + } + return 0; } @@ -323,3 +332,108 @@ int ngtcp2_acktr_require_active_ack(const ngtcp2_acktr *acktr, void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr) { acktr->flags |= NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK; } + +ngtcp2_frame *ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr, + ngtcp2_frame *fr, uint8_t type, + ngtcp2_tstamp ts, + ngtcp2_duration ack_delay, + uint64_t ack_delay_exponent) { + int64_t last_pkt_num; + ngtcp2_ack_range *range; + ngtcp2_ksl_it it; + ngtcp2_acktr_entry *rpkt; + ngtcp2_ack *ack = &fr->ack; + ngtcp2_tstamp largest_ack_ts; + size_t num_acks; + + if (acktr->flags & NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK) { + ack_delay = 0; + } + + if (!ngtcp2_acktr_require_active_ack(acktr, ack_delay, ts)) { + return NULL; + } + + it = ngtcp2_acktr_get(acktr); + if (ngtcp2_ksl_it_end(&it)) { + ngtcp2_acktr_commit_ack(acktr); + return NULL; + } + + num_acks = ngtcp2_ksl_len(&acktr->ents); + + if (acktr->ecn.ect0 || acktr->ecn.ect1 || acktr->ecn.ce) { + ack->type = NGTCP2_FRAME_ACK_ECN; + ack->ecn.ect0 = acktr->ecn.ect0; + ack->ecn.ect1 = acktr->ecn.ect1; + ack->ecn.ce = acktr->ecn.ce; + } else { + ack->type = NGTCP2_FRAME_ACK; + } + ack->rangecnt = 0; + + rpkt = ngtcp2_ksl_it_get(&it); + + if (rpkt->pkt_num == acktr->max_pkt_num) { + last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); + largest_ack_ts = rpkt->tstamp; + ack->largest_ack = rpkt->pkt_num; + ack->first_ack_range = rpkt->len - 1; + + ngtcp2_ksl_it_next(&it); + --num_acks; + } else if (rpkt->pkt_num + 1 == acktr->max_pkt_num) { + last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); + largest_ack_ts = acktr->max_pkt_ts; + ack->largest_ack = acktr->max_pkt_num; + ack->first_ack_range = rpkt->len; + + ngtcp2_ksl_it_next(&it); + --num_acks; + } else { + assert(rpkt->pkt_num < acktr->max_pkt_num); + + last_pkt_num = acktr->max_pkt_num; + largest_ack_ts = acktr->max_pkt_ts; + ack->largest_ack = acktr->max_pkt_num; + ack->first_ack_range = 0; + } + + if (type == NGTCP2_PKT_1RTT) { + ack->ack_delay_unscaled = ts - largest_ack_ts; + ack->ack_delay = ack->ack_delay_unscaled / NGTCP2_MICROSECONDS / + (1ULL << ack_delay_exponent); + } else { + ack->ack_delay_unscaled = 0; + ack->ack_delay = 0; + } + + num_acks = ngtcp2_min_size(num_acks, NGTCP2_MAX_ACK_RANGES); + + for (; ack->rangecnt < num_acks; ngtcp2_ksl_it_next(&it)) { + rpkt = ngtcp2_ksl_it_get(&it); + + range = &ack->ranges[ack->rangecnt++]; + range->gap = (uint64_t)(last_pkt_num - rpkt->pkt_num - 2); + range->len = rpkt->len - 1; + + last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); + } + + return fr; +} + +void ngtcp2_acktr_increase_ecn_counts(ngtcp2_acktr *acktr, + const ngtcp2_pkt_info *pi) { + switch (pi->ecn & NGTCP2_ECN_MASK) { + case NGTCP2_ECN_ECT_0: + ++acktr->ecn.ect0; + break; + case NGTCP2_ECN_ECT_1: + ++acktr->ecn.ect1; + break; + case NGTCP2_ECN_CE: + ++acktr->ecn.ce; + break; + } +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h index 16aee42f275f67..cf75a774db3e82 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h @@ -128,6 +128,26 @@ typedef struct ngtcp2_acktr { /* rx_npkt is the number of ACK eliciting packets received without sending ACK. */ size_t rx_npkt; + /* max_pkt_num is the largest packet number received so far. */ + int64_t max_pkt_num; + /* max_pkt_ts is the timestamp when max_pkt_num packet is + received. */ + ngtcp2_tstamp max_pkt_ts; + + struct { + /* ect0, ect1, and ce are the number of QUIC packets received + with those markings. */ + size_t ect0; + size_t ect1; + size_t ce; + struct { + /* ect0, ect1, ce are the ECN counts received in the latest + ACK frame. */ + uint64_t ect0; + uint64_t ect1; + uint64_t ce; + } ack; + } ecn; } ngtcp2_acktr; /* @@ -165,7 +185,7 @@ int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack, void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent); /* - * ngtcp2_acktr_get returns the pointer to pointer to the entry which + * ngtcp2_acktr_get returns the iterator to pointer to the entry which * has the largest packet number to be acked. If there is no entry, * returned value satisfies ngtcp2_ksl_it_end(&it) != 0. */ @@ -213,4 +233,26 @@ int ngtcp2_acktr_require_active_ack(const ngtcp2_acktr *acktr, */ void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr); +/* + * ngtcp2_acktr_create_ack_frame creates ACK frame in the object + * pointed by |fr|, and returns |fr| if there are any received packets + * to acknowledge. If there are no packets to acknowledge, this + * function returns NULL. fr->ack.ranges must be able to contain at + * least NGTCP2_MAX_ACK_RANGES elements. + * + * Call ngtcp2_acktr_commit_ack after a created ACK frame is + * successfully serialized into a packet. + */ +ngtcp2_frame *ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr, + ngtcp2_frame *fr, uint8_t type, + ngtcp2_tstamp ts, + ngtcp2_duration ack_delay, + uint64_t ack_delay_exponent); + +/* + * ngtcp2_acktr_increase_ecn_counts increases ECN counts from |pi|. + */ +void ngtcp2_acktr_increase_ecn_counts(ngtcp2_acktr *acktr, + const ngtcp2_pkt_info *pi); + #endif /* !defined(NGTCP2_ACKTR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c index f389abe76d71c8..1fb273d494e8e2 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c @@ -51,8 +51,10 @@ void ngtcp2_addr_copy_byte(ngtcp2_addr *dest, const ngtcp2_sockaddr *addr, } } -static int sockaddr_eq(const ngtcp2_sockaddr *a, const ngtcp2_sockaddr *b) { - assert(a->sa_family == b->sa_family); +int ngtcp2_sockaddr_eq(const ngtcp2_sockaddr *a, const ngtcp2_sockaddr *b) { + if (a->sa_family != b->sa_family) { + return 0; + } switch (a->sa_family) { case NGTCP2_AF_INET: { @@ -73,17 +75,16 @@ static int sockaddr_eq(const ngtcp2_sockaddr *a, const ngtcp2_sockaddr *b) { } int ngtcp2_addr_eq(const ngtcp2_addr *a, const ngtcp2_addr *b) { - return a->addr->sa_family == b->addr->sa_family && - sockaddr_eq(a->addr, b->addr); + return ngtcp2_sockaddr_eq(a->addr, b->addr); } -uint32_t ngtcp2_addr_compare(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { - uint32_t flags = NGTCP2_ADDR_COMPARE_FLAG_NONE; +uint32_t ngtcp2_addr_cmp(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { + uint32_t flags = NGTCP2_ADDR_CMP_FLAG_NONE; const ngtcp2_sockaddr *a = aa->addr; const ngtcp2_sockaddr *b = bb->addr; if (a->sa_family != b->sa_family) { - return NGTCP2_ADDR_COMPARE_FLAG_FAMILY; + return NGTCP2_ADDR_CMP_FLAG_FAMILY; } switch (a->sa_family) { @@ -91,10 +92,10 @@ uint32_t ngtcp2_addr_compare(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { const ngtcp2_sockaddr_in *ai = (const ngtcp2_sockaddr_in *)(void *)a, *bi = (const ngtcp2_sockaddr_in *)(void *)b; if (memcmp(&ai->sin_addr, &bi->sin_addr, sizeof(ai->sin_addr))) { - flags |= NGTCP2_ADDR_COMPARE_FLAG_ADDR; + flags |= NGTCP2_ADDR_CMP_FLAG_ADDR; } if (ai->sin_port != bi->sin_port) { - flags |= NGTCP2_ADDR_COMPARE_FLAG_PORT; + flags |= NGTCP2_ADDR_CMP_FLAG_PORT; } return flags; } @@ -102,10 +103,10 @@ uint32_t ngtcp2_addr_compare(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { const ngtcp2_sockaddr_in6 *ai = (const ngtcp2_sockaddr_in6 *)(void *)a, *bi = (const ngtcp2_sockaddr_in6 *)(void *)b; if (memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr))) { - flags |= NGTCP2_ADDR_COMPARE_FLAG_ADDR; + flags |= NGTCP2_ADDR_CMP_FLAG_ADDR; } if (ai->sin6_port != bi->sin6_port) { - flags |= NGTCP2_ADDR_COMPARE_FLAG_PORT; + flags |= NGTCP2_ADDR_CMP_FLAG_PORT; } return flags; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h index 65ee7cd9f3006b..c2224f85cd9c11 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h @@ -45,22 +45,21 @@ void ngtcp2_addr_copy(ngtcp2_addr *dest, const ngtcp2_addr *src); */ int ngtcp2_addr_eq(const ngtcp2_addr *a, const ngtcp2_addr *b); -/* NGTCP2_ADDR_COMPARE_FLAG_NONE indicates that no flag set. */ -#define NGTCP2_ADDR_COMPARE_FLAG_NONE 0x0u -/* NGTCP2_ADDR_COMPARE_FLAG_ADDR indicates IP addresses do not +/* NGTCP2_ADDR_CMP_FLAG_NONE indicates that no flag set. */ +#define NGTCP2_ADDR_CMP_FLAG_NONE 0x0u +/* NGTCP2_ADDR_CMP_FLAG_ADDR indicates IP addresses do not match. */ +#define NGTCP2_ADDR_CMP_FLAG_ADDR 0x1u +/* NGTCP2_ADDR_CMP_FLAG_PORT indicates ports do not match. */ +#define NGTCP2_ADDR_CMP_FLAG_PORT 0x2u +/* NGTCP2_ADDR_CMP_FLAG_FAMILY indicates address families do not match. */ -#define NGTCP2_ADDR_COMPARE_FLAG_ADDR 0x1u -/* NGTCP2_ADDR_COMPARE_FLAG_PORT indicates ports do not match. */ -#define NGTCP2_ADDR_COMPARE_FLAG_PORT 0x2u -/* NGTCP2_ADDR_COMPARE_FLAG_FAMILY indicates address families do not - match. */ -#define NGTCP2_ADDR_COMPARE_FLAG_FAMILY 0x4u +#define NGTCP2_ADDR_CMP_FLAG_FAMILY 0x4u /* - * ngtcp2_addr_compare compares address and port between |a| and |b|, - * and returns zero or more of NGTCP2_ADDR_COMPARE_FLAG_*. + * ngtcp2_addr_cmp compares address and port between |a| and |b|, and + * returns zero or more of NGTCP2_ADDR_CMP_FLAG_*. */ -uint32_t ngtcp2_addr_compare(const ngtcp2_addr *a, const ngtcp2_addr *b); +uint32_t ngtcp2_addr_cmp(const ngtcp2_addr *a, const ngtcp2_addr *b); /* * ngtcp2_addr_empty returns nonzero if |addr| has zero length @@ -68,4 +67,11 @@ uint32_t ngtcp2_addr_compare(const ngtcp2_addr *a, const ngtcp2_addr *b); */ int ngtcp2_addr_empty(const ngtcp2_addr *addr); +/** + * @function + * + * `ngtcp2_sockaddr_eq` returns nonzero if |a| equals |b|. + */ +int ngtcp2_sockaddr_eq(const ngtcp2_sockaddr *a, const ngtcp2_sockaddr *b); + #endif /* !defined(NGTCP2_ADDR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c index 8777ca4c8a1632..a20f04521e36ca 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c @@ -39,7 +39,7 @@ #define NGTCP2_BBR_EXTRA_ACKED_FILTERLEN 10 #define NGTCP2_BBR_STARTUP_PACING_GAIN_H 277 -#define NGTCP2_BBR_DRAIN_PACING_GAIN_H 35 +#define NGTCP2_BBR_DRAIN_PACING_GAIN_H 50 #define NGTCP2_BBR_DEFAULT_CWND_GAIN_H 200 @@ -130,6 +130,8 @@ static void bbr_start_round(ngtcp2_cc_bbr *bbr); static int bbr_is_in_probe_bw_state(ngtcp2_cc_bbr *bbr); +static int bbr_is_probing_bw(ngtcp2_cc_bbr *bbr); + static void bbr_update_ack_aggregation(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, @@ -137,8 +139,8 @@ static void bbr_update_ack_aggregation(ngtcp2_cc_bbr *bbr, static void bbr_enter_drain(ngtcp2_cc_bbr *bbr); -static void bbr_check_drain(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); +static void bbr_check_drain_done(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); static void bbr_enter_probe_bw(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts); @@ -277,7 +279,8 @@ static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, ngtcp2_window_filter_init(&bbr->extra_acked_filter, NGTCP2_BBR_EXTRA_ACKED_FILTERLEN); - bbr->min_rtt = UINT64_MAX; + bbr->min_rtt = + cstat->first_rtt_sample_ts == UINT64_MAX ? UINT64_MAX : cstat->smoothed_rtt; bbr->min_rtt_stamp = initial_ts; /* remark: Use UINT64_MAX instead of 0 for consistency. */ bbr->probe_rtt_done_stamp = UINT64_MAX; @@ -335,6 +338,8 @@ static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, bbr->max_inflight = 0; bbr->congestion_recovery_start_ts = UINT64_MAX; + + bbr->bdp = 0; } static void bbr_reset_congestion_signals(ngtcp2_cc_bbr *bbr) { @@ -404,8 +409,10 @@ static void bbr_check_startup_high_loss(ngtcp2_cc_bbr *bbr) { } static void bbr_init_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - cstat->pacing_interval = NGTCP2_MILLISECONDS * 100 / - NGTCP2_BBR_STARTUP_PACING_GAIN_H / bbr->initial_cwnd; + cstat->pacing_interval = + (cstat->first_rtt_sample_ts == UINT64_MAX ? NGTCP2_MILLISECONDS + : cstat->smoothed_rtt) * + 100 / NGTCP2_BBR_STARTUP_PACING_GAIN_H / bbr->initial_cwnd; } static void bbr_set_pacing_rate_with_gain(ngtcp2_cc_bbr *bbr, @@ -465,7 +472,7 @@ static void bbr_update_model_and_state(ngtcp2_cc_bbr *bbr, bbr_update_ack_aggregation(bbr, cstat, ack, ts); bbr_check_full_bw_reached(bbr, cstat); bbr_check_startup_done(bbr); - bbr_check_drain(bbr, cstat, ts); + bbr_check_drain_done(bbr, cstat, ts); bbr_update_probe_bw_cycle_phase(bbr, cstat, ack, ts); bbr_update_min_rtt(bbr, ack, ts); bbr_check_probe_rtt(bbr, cstat, ts); @@ -528,7 +535,7 @@ static void bbr_update_congestion_signals(ngtcp2_cc_bbr *bbr, static void bbr_adapt_lower_bounds_from_congestion(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - if (bbr_is_in_probe_bw_state(bbr)) { + if (bbr_is_probing_bw(bbr)) { return; } @@ -607,6 +614,17 @@ static int bbr_is_in_probe_bw_state(ngtcp2_cc_bbr *bbr) { } } +static int bbr_is_probing_bw(ngtcp2_cc_bbr *bbr) { + switch (bbr->state) { + case NGTCP2_BBR_STATE_STARTUP: + case NGTCP2_BBR_STATE_PROBE_BW_REFILL: + case NGTCP2_BBR_STATE_PROBE_BW_UP: + return 1; + default: + return 0; + } +} + static void bbr_update_ack_aggregation(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, @@ -622,8 +640,13 @@ static void bbr_update_ack_aggregation(ngtcp2_cc_bbr *bbr, } bbr->extra_acked_delivered += ack->bytes_delivered; - extra = bbr->extra_acked_delivered - expected_delivered; - extra = ngtcp2_min_uint64(extra, cstat->cwnd); + + if (bbr->extra_acked_delivered <= expected_delivered) { + extra = 0; + } else { + extra = bbr->extra_acked_delivered - expected_delivered; + extra = ngtcp2_min_uint64(extra, cstat->cwnd); + } if (bbr->full_bw_reached) { bbr->extra_acked_filter.window_length = NGTCP2_BBR_EXTRA_ACKED_FILTERLEN; @@ -645,8 +668,8 @@ static void bbr_enter_drain(ngtcp2_cc_bbr *bbr) { bbr->cwnd_gain_h = NGTCP2_BBR_DEFAULT_CWND_GAIN_H; } -static void bbr_check_drain(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { +static void bbr_check_drain_done(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { if (bbr->state == NGTCP2_BBR_STATE_DRAIN && cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, 100)) { bbr_enter_probe_bw(bbr, ts); @@ -825,8 +848,7 @@ static void bbr_raise_inflight_hi_slope(ngtcp2_cc_bbr *bbr, << bbr->bw_probe_up_rounds; bbr->bw_probe_up_rounds = ngtcp2_min_size(bbr->bw_probe_up_rounds + 1, 30); - bbr->probe_up_cnt = ngtcp2_max_uint64(cstat->cwnd / growth_this_round, 1) * - cstat->max_tx_udp_payload_size; + bbr->probe_up_cnt = ngtcp2_max_uint64(cstat->cwnd / growth_this_round, 1); } static void bbr_probe_inflight_hi_upward(ngtcp2_cc_bbr *bbr, @@ -840,10 +862,12 @@ static void bbr_probe_inflight_hi_upward(ngtcp2_cc_bbr *bbr, bbr->bw_probe_up_acks += ack->bytes_delivered; - if (bbr->bw_probe_up_acks >= bbr->probe_up_cnt) { + if (bbr->probe_up_cnt != UINT64_MAX && + bbr->bw_probe_up_acks >= + bbr->probe_up_cnt * cstat->max_tx_udp_payload_size) { delta = bbr->bw_probe_up_acks / bbr->probe_up_cnt; bbr->bw_probe_up_acks -= delta * bbr->probe_up_cnt; - bbr->inflight_hi += delta * cstat->max_tx_udp_payload_size; + bbr->inflight_hi += delta; } if (bbr->round_start) { @@ -901,8 +925,7 @@ static void bbr_pick_probe_wait(ngtcp2_cc_bbr *bbr) { bbr->rand(&rand, 1, &bbr->rand_ctx); - bbr->bw_probe_wait = - 2 * NGTCP2_SECONDS + (ngtcp2_tstamp)(NGTCP2_SECONDS * rand / 255); + bbr->bw_probe_wait = 2 * NGTCP2_SECONDS + NGTCP2_SECONDS * rand / 255; } static int bbr_is_reno_coexistence_probe_time(ngtcp2_cc_bbr *bbr, @@ -915,9 +938,7 @@ static int bbr_is_reno_coexistence_probe_time(ngtcp2_cc_bbr *bbr, static uint64_t bbr_target_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - uint64_t bdp = bbr_bdp_multiple(bbr, bbr->cwnd_gain_h); - - return ngtcp2_min_uint64(bdp, cstat->cwnd); + return ngtcp2_min_uint64(bbr->bdp, cstat->cwnd); } static int bbr_check_inflight_too_high(ngtcp2_cc_bbr *bbr, @@ -957,12 +978,11 @@ static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, } static void bbr_note_loss(ngtcp2_cc_bbr *bbr) { - if (bbr->loss_in_round) { - return; + if (!bbr->loss_in_round) { + bbr->loss_round_delivered = bbr->rst->delivered; } bbr->loss_in_round = 1; - bbr->loss_round_delivered = bbr->rst->delivered; } static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, @@ -977,6 +997,7 @@ static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, rs.tx_in_flight = pkt->tx_in_flight; /* bbr->rst->lost is not incremented for pkt yet */ + assert(bbr->rst->lost + pkt->pktlen >= pkt->lost); rs.lost = bbr->rst->lost + pkt->pktlen - pkt->lost; rs.is_app_limited = pkt->is_app_limited; @@ -1143,15 +1164,13 @@ static void bbr_handle_restart_from_idle(ngtcp2_cc_bbr *bbr, } static uint64_t bbr_bdp_multiple(ngtcp2_cc_bbr *bbr, uint64_t gain_h) { - uint64_t bdp; - if (bbr->min_rtt == UINT64_MAX) { return bbr->initial_cwnd; } - bdp = ngtcp2_max_uint64(bbr->bw * bbr->min_rtt / NGTCP2_SECONDS, 1); + bbr->bdp = ngtcp2_max_uint64(bbr->bw * bbr->min_rtt / NGTCP2_SECONDS, 1); - return (uint64_t)(bdp * gain_h / 100); + return (uint64_t)(bbr->bdp * gain_h / 100); } static uint64_t min_pipe_cwnd(size_t max_udp_payload_size) { @@ -1324,10 +1343,6 @@ static void bbr_cc_on_pkt_lost(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); - if (bbr->state == NGTCP2_BBR_STATE_STARTUP) { - return; - } - bbr_update_on_loss(bbr, cstat, pkt, ts); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h index f266ec5d71e4e4..74eb2d640bd3f2 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h @@ -131,6 +131,7 @@ typedef struct ngtcp2_cc_bbr { uint64_t round_count_at_recovery; uint64_t max_inflight; ngtcp2_tstamp congestion_recovery_start_ts; + uint64_t bdp; } ngtcp2_cc_bbr; void ngtcp2_cc_bbr_init(ngtcp2_cc_bbr *bbr, ngtcp2_log *log, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c index 1ff59f315c5b66..508a5d9ec1d8a7 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c @@ -252,13 +252,15 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, uint64_t w_cubic, w_cubic_next, target, m; ngtcp2_duration rtt_thresh; int round_start; + int is_app_limited = + cubic->rst->rs.is_app_limited && !cubic->rst->is_cwnd_limited; if (in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { return; } if (cubic->current.state == NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE) { - if (cubic->rst->rs.is_app_limited && !cubic->rst->is_cwnd_limited) { + if (is_app_limited) { if (cubic->current.app_limited_start_ts == UINT64_MAX) { cubic->current.app_limited_start_ts = ts; } @@ -271,7 +273,7 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ts - cubic->current.app_limited_start_ts; cubic->current.app_limited_start_ts = UINT64_MAX; } - } else if (cubic->rst->rs.is_app_limited && !cubic->rst->is_cwnd_limited) { + } else if (is_app_limited) { return; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c index 181850cfcbc87a..8bff06c0c1f2da 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c @@ -141,8 +141,10 @@ int ngtcp2_dcid_verify_uniqueness(const ngtcp2_dcid *dcid, uint64_t seq, } int ngtcp2_dcid_verify_stateless_reset_token(const ngtcp2_dcid *dcid, + const ngtcp2_path *path, const uint8_t *token) { - return (dcid->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) && + return ngtcp2_path_eq(&dcid->ps.path, path) && + (dcid->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) && ngtcp2_cmemeq(dcid->token, token, NGTCP2_STATELESS_RESET_TOKENLEN) ? 0 : NGTCP2_ERR_INVALID_ARGUMENT; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h index 6372ef113d6454..c6ab16831a38c4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h @@ -149,7 +149,9 @@ void ngtcp2_dcid_copy(ngtcp2_dcid *dest, const ngtcp2_dcid *src); /* * ngtcp2_dcid_copy_cid_token behaves like ngtcp2_dcid_copy, but it - * only copies cid, seq, and token. + * only copies cid, seq, and token. dest->flags should be initialized + * before this call because NGTCP2_DCID_FLAG_TOKEN_PRESENT is set or + * unset. */ void ngtcp2_dcid_copy_cid_token(ngtcp2_dcid *dest, const ngtcp2_dcid *src); @@ -162,15 +164,16 @@ int ngtcp2_dcid_verify_uniqueness(const ngtcp2_dcid *dcid, uint64_t seq, /* * ngtcp2_dcid_verify_stateless_reset_token verifies stateless reset - * token |token| against the one included in |dcid|. Tokens are - * compared in constant time. This function returns 0 if the - * verification succeeds, or one of the following negative error - * codes: + * token |token| received on |path| against the one included in + * |dcid|. Tokens are compared in constant time. This function + * returns 0 if the verification succeeds, or one of the following + * negative error codes: * * NGTCP2_ERR_INVALID_ARGUMENT * Tokens do not match; or |dcid| does not contain a token. */ int ngtcp2_dcid_verify_stateless_reset_token(const ngtcp2_dcid *dcid, + const ngtcp2_path *path, const uint8_t *token); #endif /* !defined(NGTCP2_CID_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c index 765e4a877e00d7..59eb90f6ea1afa 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -297,13 +297,13 @@ static int conn_call_path_validation(ngtcp2_conn *conn, const ngtcp2_pv *pv, flags |= NGTCP2_PATH_VALIDATION_FLAG_PREFERRED_ADDR; } - if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) { + if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) { old_path = &pv->fallback_dcid.ps.path; } if (conn->server && old_path && - (ngtcp2_addr_compare(&pv->dcid.ps.path.remote, &old_path->remote) & - (NGTCP2_ADDR_COMPARE_FLAG_ADDR | NGTCP2_ADDR_COMPARE_FLAG_FAMILY))) { + (ngtcp2_addr_cmp(&pv->dcid.ps.path.remote, &old_path->remote) & + (NGTCP2_ADDR_CMP_FLAG_ADDR | NGTCP2_ADDR_CMP_FLAG_FAMILY))) { flags |= NGTCP2_PATH_VALIDATION_FLAG_NEW_TOKEN; } @@ -679,7 +679,6 @@ static void pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, pktns->tx.last_pkt_num = initial_pkt_num - 1; pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; - pktns->rx.max_pkt_num = -1; pktns->rx.max_ack_eliciting_pkt_num = -1; pktns->id = pktns_id; @@ -1073,9 +1072,11 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, assert(settings->max_tx_udp_payload_size); assert(settings->max_tx_udp_payload_size <= NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE); assert(settings->initial_pkt_num <= INT32_MAX); + assert(settings->initial_rtt); assert(params->active_connection_id_limit >= NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT); - assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE); + assert(params->active_connection_id_limit <= + NGTCP2_DCIDTR_MAX_UNUSED_DCID_SIZE); assert(params->initial_max_data <= NGTCP2_MAX_VARINT); assert(params->initial_max_stream_data_bidi_local <= NGTCP2_MAX_VARINT); assert(params->initial_max_stream_data_bidi_remote <= NGTCP2_MAX_VARINT); @@ -1157,11 +1158,7 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_objalloc_rtb_entry_init(&(*pconn)->rtb_entry_objalloc, 16, mem); ngtcp2_objalloc_strm_init(&(*pconn)->strm_objalloc, 16, mem); - ngtcp2_static_ringbuf_dcid_bound_init(&(*pconn)->dcid.bound); - - ngtcp2_static_ringbuf_dcid_unused_init(&(*pconn)->dcid.unused); - - ngtcp2_static_ringbuf_dcid_retired_init(&(*pconn)->dcid.retired); + ngtcp2_dcidtr_init(&(*pconn)->dcid.dtr); ngtcp2_gaptr_init(&(*pconn)->dcid.seqgap, mem); @@ -1218,6 +1215,11 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL); ngtcp2_dcid_set_path(&(*pconn)->dcid.current, path); + assert((size_t)path->local.addrlen <= sizeof((*pconn)->hs_local_addr)); + + memcpy(&(*pconn)->hs_local_addr, path->local.addr, + (size_t)path->local.addrlen); + rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1); if (rv != 0) { goto fail_seqgap_push; @@ -1380,10 +1382,12 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, (*pconn)->mem = mem; (*pconn)->user_data = user_data; (*pconn)->idle_ts = settings->initial_ts; + (*pconn)->handshake_confirmed_ts = UINT64_MAX; (*pconn)->crypto.key_update.confirmed_ts = UINT64_MAX; (*pconn)->tx.last_max_data_ts = UINT64_MAX; (*pconn)->tx.pacing.next_ts = UINT64_MAX; (*pconn)->tx.last_blocked_offset = UINT64_MAX; + (*pconn)->rx.preferred_addr.pkt_num = -1; (*pconn)->early.discard_started_ts = UINT64_MAX; conn_reset_ecn_validation_state(*pconn); @@ -1608,7 +1612,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { ngtcp2_idtr_free(&conn->remote.uni.idtr); ngtcp2_idtr_free(&conn->remote.bidi.idtr); - ngtcp2_mem_free(conn->mem, conn->tx.ack); ngtcp2_pq_free(&conn->tx.strmq); ngtcp2_map_each(&conn->strms, delete_strms_each, (void *)conn); ngtcp2_map_free(&conn->strms); @@ -1625,40 +1628,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { ngtcp2_mem_free(conn->mem, conn); } -/* - * conn_ensure_ack_ranges makes sure that conn->tx.ack->ack.ranges can - * contain at least |n| additional ngtcp2_ack_range. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -static int conn_ensure_ack_ranges(ngtcp2_conn *conn, size_t n) { - ngtcp2_frame *fr; - size_t max = conn->tx.max_ack_ranges; - - if (n <= max) { - return 0; - } - - max *= 2; - - assert(max >= n); - - fr = ngtcp2_mem_realloc(conn->mem, conn->tx.ack, - sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_range) * max); - if (fr == NULL) { - return NGTCP2_ERR_NOMEM; - } - - conn->tx.ack = fr; - conn->tx.max_ack_ranges = max; - - return 0; -} - /* * conn_compute_ack_delay computes ACK delay for outgoing protected * ACK. @@ -1669,124 +1638,6 @@ static ngtcp2_duration conn_compute_ack_delay(ngtcp2_conn *conn) { ngtcp2_max_uint64(conn->cstat.smoothed_rtt / 8, NGTCP2_NANOSECONDS)); } -int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, - ngtcp2_pktns *pktns, uint8_t type, - ngtcp2_tstamp ts, ngtcp2_duration ack_delay, - uint64_t ack_delay_exponent) { - /* TODO Measure an actual size of ACK blocks to find the best - default value. */ - const size_t initial_max_ack_ranges = 8; - int64_t last_pkt_num; - ngtcp2_acktr *acktr = &pktns->acktr; - ngtcp2_ack_range *range; - ngtcp2_ksl_it it; - ngtcp2_acktr_entry *rpkt; - ngtcp2_ack *ack; - size_t range_idx; - ngtcp2_tstamp largest_ack_ts; - int rv; - - if (acktr->flags & NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK) { - ack_delay = 0; - } - - if (!ngtcp2_acktr_require_active_ack(acktr, ack_delay, ts)) { - return 0; - } - - it = ngtcp2_acktr_get(acktr); - if (ngtcp2_ksl_it_end(&it)) { - ngtcp2_acktr_commit_ack(acktr); - return 0; - } - - if (conn->tx.ack == NULL) { - conn->tx.ack = ngtcp2_mem_malloc( - conn->mem, - sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_range) * initial_max_ack_ranges); - if (conn->tx.ack == NULL) { - return NGTCP2_ERR_NOMEM; - } - conn->tx.max_ack_ranges = initial_max_ack_ranges; - } - - ack = &conn->tx.ack->ack; - - if (pktns->rx.ecn.ect0 || pktns->rx.ecn.ect1 || pktns->rx.ecn.ce) { - ack->type = NGTCP2_FRAME_ACK_ECN; - ack->ecn.ect0 = pktns->rx.ecn.ect0; - ack->ecn.ect1 = pktns->rx.ecn.ect1; - ack->ecn.ce = pktns->rx.ecn.ce; - } else { - ack->type = NGTCP2_FRAME_ACK; - } - ack->rangecnt = 0; - - rpkt = ngtcp2_ksl_it_get(&it); - - if (rpkt->pkt_num == pktns->rx.max_pkt_num) { - last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); - largest_ack_ts = rpkt->tstamp; - ack->largest_ack = rpkt->pkt_num; - ack->first_ack_range = rpkt->len - 1; - - ngtcp2_ksl_it_next(&it); - } else if (rpkt->pkt_num + 1 == pktns->rx.max_pkt_num) { - last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); - largest_ack_ts = pktns->rx.max_pkt_ts; - ack->largest_ack = pktns->rx.max_pkt_num; - ack->first_ack_range = rpkt->len; - - ngtcp2_ksl_it_next(&it); - } else { - assert(rpkt->pkt_num < pktns->rx.max_pkt_num); - - last_pkt_num = pktns->rx.max_pkt_num; - largest_ack_ts = pktns->rx.max_pkt_ts; - ack->largest_ack = pktns->rx.max_pkt_num; - ack->first_ack_range = 0; - } - - if (type == NGTCP2_PKT_1RTT) { - ack->ack_delay_unscaled = ts - largest_ack_ts; - ack->ack_delay = ack->ack_delay_unscaled / NGTCP2_MICROSECONDS / - (1ULL << ack_delay_exponent); - } else { - ack->ack_delay_unscaled = 0; - ack->ack_delay = 0; - } - - for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) { - if (ack->rangecnt == NGTCP2_MAX_ACK_RANGES) { - break; - } - - rpkt = ngtcp2_ksl_it_get(&it); - - range_idx = ack->rangecnt++; - rv = conn_ensure_ack_ranges(conn, ack->rangecnt); - if (rv != 0) { - return rv; - } - ack = &conn->tx.ack->ack; - range = &ack->ranges[range_idx]; - range->gap = (uint64_t)(last_pkt_num - rpkt->pkt_num - 2); - range->len = rpkt->len - 1; - - last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); - } - - /* TODO Just remove entries which cannot fit into a single ACK frame - for now. */ - if (!ngtcp2_ksl_it_end(&it)) { - ngtcp2_acktr_forget(acktr, ngtcp2_ksl_it_get(&it)); - } - - *pfr = conn->tx.ack; - - return 0; -} - /* * conn_ppe_write_frame writes |fr| to |ppe|. If |hd_logged| is not * NULL and |*hd_logged| is zero, packet header is logged, and 1 is @@ -1894,22 +1745,13 @@ static size_t pktns_select_pkt_numlen(ngtcp2_pktns *pktns) { return 1; } -/* - * conn_get_cwnd returns cwnd for the current path. - */ -static uint64_t conn_get_cwnd(ngtcp2_conn *conn) { - return conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) - ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_tx_udp_payload_size) - : conn->cstat.cwnd; -} - /* * conn_cwnd_is_zero returns nonzero if the number of bytes the local * endpoint can sent at this time is zero. */ static int conn_cwnd_is_zero(ngtcp2_conn *conn) { uint64_t bytes_in_flight = conn->cstat.bytes_in_flight; - uint64_t cwnd = conn_get_cwnd(conn); + uint64_t cwnd = conn->cstat.cwnd; if (bytes_in_flight >= cwnd) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, @@ -2145,33 +1987,36 @@ void ngtcp2_conn_set_keep_alive_timeout(ngtcp2_conn *conn, conn->keep_alive.timeout = timeout; } -/* - * NGTCP2_PKT_PACING_OVERHEAD defines overhead of userspace event - * loop. Packet pacing might require sub milliseconds packet spacing, - * but userspace event loop might not offer such precision. - * Typically, if delay is 0.5 microseconds, the actual delay after - * which we can send packet is well over 1 millisecond when event loop - * is involved (which includes other stuff, like reading packets etc - * in a typical single threaded use case). - */ -#define NGTCP2_PKT_PACING_OVERHEAD NGTCP2_MILLISECONDS - static void conn_cancel_expired_pkt_tx_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (conn->tx.pacing.next_ts == UINT64_MAX) { return; } - if (conn->tx.pacing.next_ts > ts + NGTCP2_PKT_PACING_OVERHEAD) { + if (conn->tx.pacing.next_ts > ts) { return; } + if (ts > conn->tx.pacing.next_ts) { + conn->tx.pacing.compensation += ts - conn->tx.pacing.next_ts; + } + conn->tx.pacing.next_ts = UINT64_MAX; } static int conn_pacing_pkt_tx_allowed(ngtcp2_conn *conn, ngtcp2_tstamp ts) { - return conn->tx.pacing.next_ts == UINT64_MAX || - conn->tx.pacing.next_ts <= ts + NGTCP2_PKT_PACING_OVERHEAD; + if (conn->tx.pacing.next_ts == UINT64_MAX) { + return 1; + } + + if (conn->tx.pacing.next_ts > ts) { + return 0; + } + + conn->tx.pacing.compensation += ts - conn->tx.pacing.next_ts; + conn->tx.pacing.next_ts = UINT64_MAX; + + return 1; } static uint8_t conn_pkt_flags(ngtcp2_conn *conn) { @@ -2225,6 +2070,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, ngtcp2_pkt_hd hd; ngtcp2_frame_chain *frq = NULL, **pfrc = &frq; ngtcp2_frame_chain *nfrc; + ngtcp2_max_frame mfr; ngtcp2_frame *ackfr = NULL, lfr; ngtcp2_ssize spktlen; ngtcp2_crypto_cc cc; @@ -2280,7 +2126,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, ngtcp2_pkt_hd_init( &hd, conn_pkt_flags_long(conn), type, &conn->dcid.current.cid, &conn->oscid, - pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), version, 0); + pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), version); if (!conn->server && type == NGTCP2_PKT_INITIAL && conn->local.settings.tokenlen) { @@ -2300,14 +2146,9 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, return 0; } - rv = ngtcp2_conn_create_ack_frame(conn, &ackfr, pktns, type, ts, - /* ack_delay = */ 0, - NGTCP2_DEFAULT_ACK_DELAY_EXPONENT); - if (rv != 0) { - ngtcp2_frame_chain_list_objalloc_del(frq, &conn->frc_objalloc, conn->mem); - return rv; - } - + ackfr = ngtcp2_acktr_create_ack_frame(&pktns->acktr, &mfr.fr, type, ts, + /* ack_delay = */ 0, + NGTCP2_DEFAULT_ACK_DELAY_EXPONENT); if (ackfr) { rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, ackfr); if (rv != 0) { @@ -2530,12 +2371,12 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, uint8_t type, ngtcp2_tstamp ts) { - int rv; ngtcp2_frame *ackfr; ngtcp2_pktns *pktns; ngtcp2_duration ack_delay; uint64_t ack_delay_exponent; ngtcp2_ssize spktlen; + ngtcp2_max_frame mfr; assert(!(conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING)); @@ -2564,13 +2405,8 @@ static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return 0; } - ackfr = NULL; - rv = ngtcp2_conn_create_ack_frame(conn, &ackfr, pktns, type, ts, ack_delay, - ack_delay_exponent); - if (rv != 0) { - return rv; - } - + ackfr = ngtcp2_acktr_create_ack_frame(&pktns->acktr, &mfr.fr, type, ts, + ack_delay, ack_delay_exponent); if (!ackfr) { return 0; } @@ -3035,6 +2871,10 @@ static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) { return 0; } +static int dcidtr_on_deactivate(const ngtcp2_dcid *dcid, void *user_data) { + return conn_call_deactivate_dcid(user_data, dcid); +} + /* * conn_remove_retired_connection_id removes the already retired * connection ID. It waits PTO before actually removing a connection @@ -3054,7 +2894,6 @@ static int conn_remove_retired_connection_id(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ngtcp2_duration timeout = pto; ngtcp2_scid *scid; - ngtcp2_dcid *dcid; int rv; for (; !ngtcp2_pq_empty(&conn->scid.used);) { @@ -3079,18 +2918,10 @@ static int conn_remove_retired_connection_id(ngtcp2_conn *conn, --conn->scid.num_retired; } - for (; ngtcp2_ringbuf_len(&conn->dcid.retired.rb);) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.retired.rb, 0); - if (dcid->retired_ts + timeout >= ts) { - break; - } - - rv = conn_call_deactivate_dcid(conn, dcid); - if (rv != 0) { - return rv; - } - - ngtcp2_ringbuf_pop_front(&conn->dcid.retired.rb); + rv = ngtcp2_dcidtr_remove_stale_retired_dcid(&conn->dcid.dtr, timeout, ts, + dcidtr_on_deactivate, conn); + if (rv != 0) { + return rv; } return 0; @@ -3197,6 +3028,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, ngtcp2_crypto_cc *cc = &conn->pkt.cc; ngtcp2_ppe *ppe = &conn->pkt.ppe; ngtcp2_pkt_hd *hd = &conn->pkt.hd; + ngtcp2_max_frame mfr; ngtcp2_frame *ackfr = NULL, lfr; ngtcp2_ssize nwrite; ngtcp2_frame_chain **pfrc, *nfrc, *frc; @@ -3348,35 +3180,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, nfrc->fr.max_data.max_data; } - if (stream_blocked && conn_should_send_max_data(conn)) { - rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); - if (rv != 0) { - return rv; - } - - nfrc->fr.type = NGTCP2_FRAME_DATA_BLOCKED; - nfrc->fr.data_blocked.offset = conn->tx.max_offset; - nfrc->next = pktns->tx.frq; - pktns->tx.frq = nfrc; - - conn->tx.last_blocked_offset = conn->tx.max_offset; - } - - if (stream_blocked && !ngtcp2_strm_is_tx_queued(vmsg->stream.strm) && - strm_should_send_stream_data_blocked(vmsg->stream.strm)) { - assert(vmsg); - assert(vmsg->type == NGTCP2_VMSG_TYPE_STREAM); - - vmsg->stream.strm->cycle = conn_tx_strmq_first_cycle(conn); - rv = ngtcp2_conn_tx_strmq_push(conn, vmsg->stream.strm); - if (rv != 0) { - return rv; - } - } - ngtcp2_pkt_hd_init(hd, hd_flags, type, &conn->dcid.current.cid, scid, pktns->tx.last_pkt_num + 1, - pktns_select_pkt_numlen(pktns), version, 0); + pktns_select_pkt_numlen(pktns), version); ngtcp2_ppe_init(ppe, dest, destlen, dgram_offset, cc); @@ -3415,14 +3221,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } } - rv = ngtcp2_conn_create_ack_frame( - conn, &ackfr, pktns, type, ts, conn_compute_ack_delay(conn), + ackfr = ngtcp2_acktr_create_ack_frame( + &pktns->acktr, &mfr.fr, type, ts, conn_compute_ack_delay(conn), conn->local.transport_params.ack_delay_exponent); - if (rv != 0) { - assert(ngtcp2_err_is_fatal(rv)); - return rv; - } - if (ackfr) { rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, ackfr); if (rv != 0) { @@ -3907,7 +3708,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, left = ngtcp2_ppe_left(ppe); - if (*pfrc == NULL && send_stream && + if (*pfrc == NULL && send_stream && ngtcp2_pq_empty(&conn->tx.strmq) && (ndatalen = ngtcp2_pkt_stream_max_datalen( vmsg->stream.strm->stream_id, vmsg->stream.strm->tx.offset, ndatalen, left)) != (size_t)-1 && @@ -4342,7 +4143,7 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( ngtcp2_pkt_hd_init(&hd, hd_flags, type, dcid, scid, pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), - version, 0); + version); ngtcp2_ppe_init(&ppe, dest, destlen, 0, &cc); @@ -4521,31 +4322,20 @@ static int conn_handshake_remnants_left(ngtcp2_conn *conn) { } /* - * conn_retire_dcid_seq retires destination connection ID denoted by - * |seq|. + * conn_enqueue_retire_connection_id enqueues RETIRE_CONNECTION_ID + * frame with |seq|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * NGTCP2_ERR_NOMEM * Out of memory. - * NGTCP2_ERR_CONNECTION_ID_LIMIT - * The number of unacknowledged retirement exceeds the limit. */ -static int conn_retire_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { +static int conn_enqueue_retire_connection_id(ngtcp2_conn *conn, uint64_t seq) { ngtcp2_pktns *pktns = &conn->pktns; ngtcp2_frame_chain *nfrc; int rv; - if (ngtcp2_conn_check_retired_dcid_tracked(conn, seq)) { - return 0; - } - - rv = ngtcp2_conn_track_retired_dcid_seq(conn, seq); - if (rv != 0) { - return rv; - } - rv = ngtcp2_frame_chain_objalloc_new(&nfrc, &conn->frc_objalloc); if (rv != 0) { return rv; @@ -4559,8 +4349,12 @@ static int conn_retire_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { return 0; } +static int dcidtr_on_retire(const ngtcp2_dcid *dcid, void *user_data) { + return conn_enqueue_retire_connection_id(user_data, dcid->seq); +} + /* - * conn_retire_dcid retires |dcid|. + * conn_retire_active_dcid retires the activated |dcid|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -4568,29 +4362,19 @@ static int conn_retire_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { * NGTCP2_ERR_NOMEM * Out of memory */ -static int conn_retire_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid, - ngtcp2_tstamp ts) { - ngtcp2_ringbuf *rb = &conn->dcid.retired.rb; - ngtcp2_dcid *dest, *stale_dcid; +static int conn_retire_active_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid, + ngtcp2_tstamp ts) { int rv; assert(dcid->cid.datalen); - if (ngtcp2_ringbuf_full(rb)) { - stale_dcid = ngtcp2_ringbuf_get(rb, 0); - rv = conn_call_deactivate_dcid(conn, stale_dcid); - if (rv != 0) { - return rv; - } - - ngtcp2_ringbuf_pop_front(rb); + rv = ngtcp2_dcidtr_retire_active_dcid(&conn->dcid.dtr, dcid, ts, + dcidtr_on_deactivate, conn); + if (rv != 0) { + return rv; } - dest = ngtcp2_ringbuf_push_back(rb); - ngtcp2_dcid_copy(dest, dcid); - dest->retired_ts = ts; - - return conn_retire_dcid_seq(conn, dcid->seq); + return conn_enqueue_retire_connection_id(conn, dcid->seq); } /* @@ -4609,61 +4393,28 @@ static int conn_retire_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid, */ static int conn_bind_dcid(ngtcp2_conn *conn, ngtcp2_dcid **pdcid, const ngtcp2_path *path, ngtcp2_tstamp ts) { - ngtcp2_dcid *dcid, *ndcid; - ngtcp2_cid cid; - size_t i, len; - int rv; - assert(!ngtcp2_path_eq(&conn->dcid.current.ps.path, path)); assert(!conn->pv || !ngtcp2_path_eq(&conn->pv->dcid.ps.path, path)); - assert(!conn->pv || !(conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) || + assert(!conn->pv || !(conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) || !ngtcp2_path_eq(&conn->pv->fallback_dcid.ps.path, path)); - len = ngtcp2_ringbuf_len(&conn->dcid.bound.rb); - for (i = 0; i < len; ++i) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, i); - - if (ngtcp2_path_eq(&dcid->ps.path, path)) { - *pdcid = dcid; - return 0; - } + *pdcid = ngtcp2_dcidtr_find_bound_dcid(&conn->dcid.dtr, path); + if (*pdcid) { + return 0; } if (conn->dcid.current.cid.datalen == 0) { - ndcid = ngtcp2_ringbuf_push_back(&conn->dcid.bound.rb); - ngtcp2_cid_zero(&cid); - ngtcp2_dcid_init(ndcid, ++conn->dcid.zerolen_seq, &cid, NULL); - ngtcp2_dcid_set_path(ndcid, path); - - *pdcid = ndcid; + *pdcid = ngtcp2_dcidtr_bind_zerolen_dcid(&conn->dcid.dtr, path); return 0; } - if (ngtcp2_ringbuf_len(&conn->dcid.unused.rb) == 0) { + if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { return NGTCP2_ERR_CONN_ID_BLOCKED; } - if (ngtcp2_ringbuf_full(&conn->dcid.bound.rb)) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, 0); - rv = conn_retire_dcid(conn, dcid, ts); - if (rv != 0) { - return rv; - } - } - - dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); - ndcid = ngtcp2_ringbuf_push_back(&conn->dcid.bound.rb); - - ngtcp2_dcid_copy(ndcid, dcid); - ndcid->bound_ts = ts; - ngtcp2_dcid_set_path(ndcid, path); - - ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); - - *pdcid = ndcid; - - return 0; + return ngtcp2_dcidtr_bind_dcid(&conn->dcid.dtr, pdcid, path, ts, + dcidtr_on_retire, conn); } static int conn_start_pmtud(ngtcp2_conn *conn) { @@ -4773,17 +4524,17 @@ static int conn_stop_pv(ngtcp2_conn *conn, ngtcp2_tstamp ts) { } if (pv->dcid.cid.datalen && pv->dcid.seq != conn->dcid.current.seq) { - rv = conn_retire_dcid(conn, &pv->dcid, ts); + rv = conn_retire_active_dcid(conn, &pv->dcid, ts); if (rv != 0) { goto fin; } } - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && pv->fallback_dcid.cid.datalen && pv->fallback_dcid.seq != conn->dcid.current.seq && pv->fallback_dcid.seq != pv->dcid.seq) { - rv = conn_retire_dcid(conn, &pv->fallback_dcid, ts); + rv = conn_retire_active_dcid(conn, &pv->fallback_dcid, ts); if (rv != 0) { goto fin; } @@ -4874,7 +4625,7 @@ static int conn_on_path_validation_failed(ngtcp2_conn *conn, ngtcp2_pv *pv, } } - if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) { + if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) { ngtcp2_dcid_copy(&conn->dcid.current, &pv->fallback_dcid); conn_reset_congestion_state(conn, ts); } @@ -5024,7 +4775,7 @@ static ngtcp2_ssize conn_write_path_response(ngtcp2_conn *conn, dcid = &pv->dcid; break; } - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && ngtcp2_path_eq(&pv->fallback_dcid.ps.path, &pcent->ps.path)) { dcid = &pv->fallback_dcid; break; @@ -5377,8 +5128,15 @@ static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr, */ static void assign_recved_ack_delay_unscaled(ngtcp2_ack *fr, uint64_t ack_delay_exponent) { - fr->ack_delay_unscaled = - fr->ack_delay * (1ULL << ack_delay_exponent) * NGTCP2_MICROSECONDS; + const ngtcp2_tstamp max_ack_delay = ((1 << 14) - 1) * NGTCP2_MILLISECONDS; + uint64_t exp = (1ULL << ack_delay_exponent) * NGTCP2_MICROSECONDS; + + if (fr->ack_delay > max_ack_delay / exp) { + fr->ack_delay_unscaled = max_ack_delay; + return; + } + + fr->ack_delay_unscaled = fr->ack_delay * exp; } /* @@ -5482,6 +5240,17 @@ static void conn_recv_max_data(ngtcp2_conn *conn, const ngtcp2_max_data *fr) { conn->tx.max_offset = ngtcp2_max_uint64(conn->tx.max_offset, fr->max_data); } +/* + * should_buffer_1rtt_pkt returns nonzero if 1RTT packet |pkt| of + * length |pktlen| should be buffered. + */ +static int should_buffer_1rtt_pkt(const uint8_t *pkt, size_t pktlen) { + /* A packet starting with 21 bytes zeros are most likely padding + bytes. */ + return pktlen >= NGTCP2_MIN_QUIC_PKTLEN && + (pkt[0] != 0 || memcmp(pkt, pkt + 1, NGTCP2_MIN_QUIC_PKTLEN - 1) != 0); +} + /* * conn_buffer_pkt buffers |pkt| of length |pktlen|, chaining it from * |*ppc|. @@ -5786,15 +5555,52 @@ static void conn_reset_congestion_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { conn->hs_pktns->tx.last_pkt_num + 1); } ngtcp2_rtb_reset_cc_state(&conn->pktns.rtb, conn->pktns.tx.last_pkt_num + 1); - ngtcp2_rst_init(&conn->rst); + ngtcp2_rst_reset(&conn->rst); conn->tx.pacing.next_ts = UINT64_MAX; + conn->tx.pacing.compensation = 0; } -static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr, - ngtcp2_tstamp ts) { +/* + * conn_server_preferred_addr_migration returns nonzero if + * |local_addr| equals to one of the preferred addresses. + */ +static int conn_server_preferred_addr_migration(const ngtcp2_conn *conn, + const ngtcp2_addr *local_addr) { + const ngtcp2_preferred_addr *paddr; + + assert(conn->server); + + if (!conn->local.transport_params.preferred_addr_present) { + return 0; + } + + paddr = &conn->local.transport_params.preferred_addr; + + switch (local_addr->addr->sa_family) { + case NGTCP2_AF_INET: + if (!paddr->ipv4_present) { + return 0; + } + + return ngtcp2_sockaddr_eq((const ngtcp2_sockaddr *)&paddr->ipv4, + local_addr->addr); + case NGTCP2_AF_INET6: + if (!paddr->ipv6_present) { + return 0; + } + + return ngtcp2_sockaddr_eq((const ngtcp2_sockaddr *)&paddr->ipv6, + local_addr->addr); + } + + return 0; +} + +static int conn_recv_path_response(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, + ngtcp2_path_response *fr, ngtcp2_tstamp ts) { int rv; - ngtcp2_pv *pv = conn->pv, *npv; + ngtcp2_pv *pv = conn->pv, *npv = NULL; uint8_t ent_flags; if (!pv) { @@ -5809,18 +5615,26 @@ static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr, } if (!(pv->flags & NGTCP2_PV_FLAG_DONT_CARE)) { - if (pv->dcid.seq != conn->dcid.current.seq) { - assert(!conn->server); - assert(conn->dcid.current.cid.datalen); - - rv = conn_retire_dcid(conn, &conn->dcid.current, ts); - if (rv != 0) { - return rv; + if (pv->dcid.seq != conn->dcid.current.seq || + !ngtcp2_path_eq(&pv->dcid.ps.path, &conn->dcid.current.ps.path)) { + if (conn->dcid.current.cid.datalen && + pv->dcid.seq != conn->dcid.current.seq) { + rv = conn_retire_active_dcid(conn, &conn->dcid.current, ts); + if (rv != 0) { + return rv; + } } + ngtcp2_dcid_copy(&conn->dcid.current, &pv->dcid); conn_reset_congestion_state(conn, ts); conn_reset_ecn_validation_state(conn); + + if (conn->server && conn->rx.preferred_addr.pkt_num == -1 && + conn_server_preferred_addr_migration( + conn, &conn->dcid.current.ps.path.local)) { + conn->rx.preferred_addr.pkt_num = hd->pkt_num; + } } assert(ngtcp2_path_eq(&pv->dcid.ps.path, &conn->dcid.current.ps.path)); @@ -5847,46 +5661,45 @@ static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr, } } - if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) { - if (ent_flags & NGTCP2_PV_ENTRY_FLAG_UNDERSIZED) { - assert(conn->server); - - /* Validate path again */ - rv = ngtcp2_pv_new(&npv, &pv->dcid, conn_compute_pv_timeout(conn), - NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE, &conn->log, - conn->mem); - if (rv != 0) { - return rv; - } + if (ent_flags & NGTCP2_PV_ENTRY_FLAG_UNDERSIZED) { + assert(conn->server); - npv->dcid.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED; - ngtcp2_dcid_copy(&npv->fallback_dcid, &pv->fallback_dcid); - npv->fallback_pto = pv->fallback_pto; - } else { - rv = ngtcp2_pv_new(&npv, &pv->fallback_dcid, - conn_compute_pv_timeout_pto(conn, pv->fallback_pto), - NGTCP2_PV_FLAG_DONT_CARE, &conn->log, conn->mem); - if (rv != 0) { - return rv; - } + /* Validate path again */ + rv = ngtcp2_pv_new(&npv, &pv->dcid, conn_compute_pv_timeout(conn), + NGTCP2_PV_FLAG_NONE, &conn->log, conn->mem); + if (rv != 0) { + return rv; } - /* Unset the flag bit so that conn_stop_pv does not retire - DCID. */ - pv->flags &= (uint8_t)~NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE; + npv->dcid.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED; - rv = conn_stop_pv(conn, ts); + if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) { + ngtcp2_pv_set_fallback(npv, &pv->fallback_dcid, pv->fallback_pto); + } + } else if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) { + rv = ngtcp2_pv_new(&npv, &pv->fallback_dcid, + conn_compute_pv_timeout_pto(conn, pv->fallback_pto), + NGTCP2_PV_FLAG_DONT_CARE, &conn->log, conn->mem); if (rv != 0) { - ngtcp2_pv_del(npv); return rv; } + } - conn->pv = npv; + if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) { + /* Unset the flag bit so that conn_stop_pv does not retire + DCID. */ + pv->flags &= (uint8_t)~NGTCP2_PV_FLAG_FALLBACK_PRESENT; + } - return 0; + rv = conn_stop_pv(conn, ts); + if (rv != 0) { + ngtcp2_pv_del(npv); + return rv; } - return conn_stop_pv(conn, ts); + conn->pv = npv; + + return 0; } /* @@ -5899,12 +5712,24 @@ static int pktns_pkt_num_is_duplicate(ngtcp2_pktns *pktns, int64_t pkt_num) { /* * pktns_commit_recv_pkt_num marks packet number |pkt_num| as - * received. + * received. It stores |pkt_num| and its reception timestamp |ts| in + * order to send its ACK. It also increase ECN counts from |pi|. + * |require_ack| is nonzero if the received packet is ack-eliciting. + * + * It returns 0 if it succeeds, or one of the following negative error + * codes: + * + * NGTCP2_ERR_NOMEM + * Out of memory + * NGTCP2_ERR_PROTO + * Same packet number has already been added. */ static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num, - int ack_eliciting, ngtcp2_tstamp ts) { - int rv; + const ngtcp2_pkt_info *pi, int require_ack, + ngtcp2_tstamp ts) { + ngtcp2_acktr *acktr = &pktns->acktr; ngtcp2_range r; + int rv; rv = ngtcp2_gaptr_push(&pktns->rx.pngap, (uint64_t)pkt_num, 1); if (rv != 0) { @@ -5915,7 +5740,7 @@ static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num, ngtcp2_gaptr_drop_first_gap(&pktns->rx.pngap); } - if (ack_eliciting) { + if (require_ack) { if (pktns->rx.max_ack_eliciting_pkt_num != -1) { if (pkt_num < pktns->rx.max_ack_eliciting_pkt_num) { ngtcp2_acktr_immediate_ack(&pktns->acktr); @@ -5934,9 +5759,12 @@ static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num, } } - if (pktns->rx.max_pkt_num < pkt_num) { - pktns->rx.max_pkt_num = pkt_num; - pktns->rx.max_pkt_ts = ts; + ngtcp2_acktr_increase_ecn_counts(acktr, pi); + + rv = ngtcp2_acktr_add(acktr, pkt_num, require_ack, ts); + if (rv != 0) { + assert(rv != NGTCP2_ERR_INVALID_ARGUMENT); + return rv; } return 0; @@ -5954,21 +5782,6 @@ static int verify_token(const uint8_t *token, size_t tokenlen, return NGTCP2_ERR_PROTO; } -static void pktns_increase_ecn_counts(ngtcp2_pktns *pktns, - const ngtcp2_pkt_info *pi) { - switch (pi->ecn & NGTCP2_ECN_MASK) { - case NGTCP2_ECN_ECT_0: - ++pktns->rx.ecn.ect0; - break; - case NGTCP2_ECN_ECT_1: - ++pktns->rx.ecn.ect1; - break; - case NGTCP2_ECN_CE: - ++pktns->rx.ecn.ce; - break; - } -} - /* * vneg_available_versions_includes returns nonzero if * |available_versions| of length |available_versionslen| includes @@ -6111,14 +5924,11 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, int invalid_reserved_bits = 0; size_t num_ack_processed = 0; - if (pktlen == 0) { - return 0; - } - if (!(pkt[0] & NGTCP2_HEADER_FORM_BIT)) { - if (conn->state == NGTCP2_CS_SERVER_INITIAL) { - /* Ignore 1RTT packet unless server's first Handshake packet has - been transmitted. */ + /* Ignore 1RTT packet unless server's first Handshake packet has + been transmitted. */ + if (conn->state == NGTCP2_CS_SERVER_INITIAL || + !should_buffer_1rtt_pkt(pkt, pktlen)) { return (ngtcp2_ssize)pktlen; } @@ -6432,8 +6242,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, payload = pkt + hdpktlen; payloadlen = hd.len - hd.pkt_numlen; - hd.pkt_num = - ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, hd.pkt_numlen); + hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->acktr.max_pkt_num, hd.pkt_num, + hd.pkt_numlen); if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); @@ -6623,20 +6433,13 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_qlog_pkt_received_end(&conn->qlog, &hd, pktlen); - rv = pktns_commit_recv_pkt_num(pktns, hd.pkt_num, require_ack, pkt_ts); + rv = pktns_commit_recv_pkt_num(pktns, hd.pkt_num, pi, require_ack, pkt_ts); if (rv != 0) { return rv; } - pktns_increase_ecn_counts(pktns, pi); - /* Initial and Handshake are always acknowledged without delay. No need to call ngtcp2_acktr_immediate_ack(). */ - rv = - ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, pkt_ts); - if (rv != 0) { - return rv; - } conn_restart_timer_on_read(conn, ts); @@ -6710,7 +6513,7 @@ static ngtcp2_ssize conn_recv_handshake_cpkt(ngtcp2_conn *conn, and the current connection state might wrongly discard valid packet and prevent the handshake from completing. */ - if (conn->in_pktns && conn->in_pktns->rx.max_pkt_num == -1) { + if (conn->in_pktns && conn->in_pktns->acktr.max_pkt_num == -1) { return NGTCP2_ERR_DROP_CONN; } @@ -7516,9 +7319,8 @@ static int conn_recv_stop_sending(ngtcp2_conn *conn, static int check_stateless_reset(const ngtcp2_dcid *dcid, const ngtcp2_path *path, const ngtcp2_pkt_stateless_reset *sr) { - return ngtcp2_path_eq(&dcid->ps.path, path) && - ngtcp2_dcid_verify_stateless_reset_token( - dcid, sr->stateless_reset_token) == 0; + return ngtcp2_dcid_verify_stateless_reset_token( + dcid, path, sr->stateless_reset_token) == 0; } /* @@ -7540,11 +7342,9 @@ static int check_stateless_reset(const ngtcp2_dcid *dcid, */ static int conn_on_stateless_reset(ngtcp2_conn *conn, const ngtcp2_path *path, const uint8_t *payload, size_t payloadlen) { - int rv = 1; + int rv; ngtcp2_pv *pv = conn->pv; - ngtcp2_dcid *dcid; ngtcp2_pkt_stateless_reset sr; - size_t len, i; rv = ngtcp2_pkt_decode_stateless_reset(&sr, payload, payloadlen); if (rv != 0) { @@ -7553,28 +7353,12 @@ static int conn_on_stateless_reset(ngtcp2_conn *conn, const ngtcp2_path *path, if (!check_stateless_reset(&conn->dcid.current, path, &sr) && (!pv || (!check_stateless_reset(&pv->dcid, path, &sr) && - (!(pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) || + (!(pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) || !check_stateless_reset(&pv->fallback_dcid, path, &sr))))) { - len = ngtcp2_ringbuf_len(&conn->dcid.retired.rb); - for (i = 0; i < len; ++i) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.retired.rb, i); - if (check_stateless_reset(dcid, path, &sr)) { - break; - } - } - - if (i == len) { - len = ngtcp2_ringbuf_len(&conn->dcid.bound.rb); - for (i = 0; i < len; ++i) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, i); - if (check_stateless_reset(dcid, path, &sr)) { - break; - } - } - - if (i == len) { - return NGTCP2_ERR_INVALID_ARGUMENT; - } + rv = ngtcp2_dcidtr_verify_stateless_reset(&conn->dcid.dtr, path, + sr.stateless_reset_token); + if (rv != 0) { + return rv; } } @@ -7624,42 +7408,6 @@ static int conn_recv_max_streams(ngtcp2_conn *conn, return 0; } -static int conn_retire_dcid_prior_to(ngtcp2_conn *conn, ngtcp2_ringbuf *rb, - uint64_t retire_prior_to) { - size_t i; - ngtcp2_dcid *dcid, *last; - int rv; - - for (i = 0; i < ngtcp2_ringbuf_len(rb);) { - dcid = ngtcp2_ringbuf_get(rb, i); - if (dcid->seq >= retire_prior_to) { - ++i; - continue; - } - - rv = conn_retire_dcid_seq(conn, dcid->seq); - if (rv != 0) { - return rv; - } - - if (i == 0) { - ngtcp2_ringbuf_pop_front(rb); - continue; - } - - if (i == ngtcp2_ringbuf_len(rb) - 1) { - ngtcp2_ringbuf_pop_back(rb); - break; - } - - last = ngtcp2_ringbuf_get(rb, ngtcp2_ringbuf_len(rb) - 1); - ngtcp2_dcid_copy(dcid, last); - ngtcp2_ringbuf_pop_back(rb); - } - - return 0; -} - /* * conn_recv_new_connection_id processes the incoming * NEW_CONNECTION_ID frame |fr|. @@ -7673,8 +7421,7 @@ static int conn_retire_dcid_prior_to(ngtcp2_conn *conn, ngtcp2_ringbuf *rb, */ static int conn_recv_new_connection_id(ngtcp2_conn *conn, const ngtcp2_new_connection_id *fr) { - size_t i, len; - ngtcp2_dcid *dcid; + size_t len; ngtcp2_pv *pv = conn->pv; int rv; int found = 0; @@ -7693,60 +7440,32 @@ static int conn_recv_new_connection_id(ngtcp2_conn *conn, if (rv != 0) { return rv; } - if (ngtcp2_cid_eq(&conn->dcid.current.cid, &fr->cid)) { - found = 1; - } - - if (pv) { - rv = ngtcp2_dcid_verify_uniqueness(&pv->dcid, fr->seq, &fr->cid, - fr->stateless_reset_token); - if (rv != 0) { - return rv; - } - if (ngtcp2_cid_eq(&pv->dcid.cid, &fr->cid)) { - found = 1; - } + if (ngtcp2_cid_eq(&conn->dcid.current.cid, &fr->cid)) { + found = 1; } - len = ngtcp2_ringbuf_len(&conn->dcid.bound.rb); - - for (i = 0; i < len; ++i) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, i); - rv = ngtcp2_dcid_verify_uniqueness(dcid, fr->seq, &fr->cid, + if (pv) { + rv = ngtcp2_dcid_verify_uniqueness(&pv->dcid, fr->seq, &fr->cid, fr->stateless_reset_token); if (rv != 0) { - return NGTCP2_ERR_PROTO; + return rv; } - if (ngtcp2_cid_eq(&dcid->cid, &fr->cid)) { + if (ngtcp2_cid_eq(&pv->dcid.cid, &fr->cid)) { found = 1; } } - len = ngtcp2_ringbuf_len(&conn->dcid.unused.rb); - - for (i = 0; i < len; ++i) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, i); - rv = ngtcp2_dcid_verify_uniqueness(dcid, fr->seq, &fr->cid, - fr->stateless_reset_token); - if (rv != 0) { - return NGTCP2_ERR_PROTO; - } - if (ngtcp2_cid_eq(&dcid->cid, &fr->cid)) { - found = 1; - } + rv = ngtcp2_dcidtr_verify_token_uniqueness( + &conn->dcid.dtr, &found, fr->seq, &fr->cid, fr->stateless_reset_token); + if (rv != 0) { + return rv; } if (conn->dcid.retire_prior_to < fr->retire_prior_to) { conn->dcid.retire_prior_to = fr->retire_prior_to; - rv = conn_retire_dcid_prior_to(conn, &conn->dcid.bound.rb, - fr->retire_prior_to); - if (rv != 0) { - return rv; - } - - rv = conn_retire_dcid_prior_to(conn, &conn->dcid.unused.rb, - conn->dcid.retire_prior_to); + rv = ngtcp2_dcidtr_retire_inactive_dcid_prior_to( + &conn->dcid.dtr, fr->retire_prior_to, dcidtr_on_retire, conn); if (rv != 0) { return rv; } @@ -7759,7 +7478,16 @@ static int conn_recv_new_connection_id(ngtcp2_conn *conn, For example, a peer might send seq = 50000 and retire_prior_to = 50000. Then send NEW_CONNECTION_ID frames with seq < 50000. */ - return conn_retire_dcid_seq(conn, fr->seq); + if (ngtcp2_dcidtr_check_retired_seq_tracked(&conn->dcid.dtr, fr->seq)) { + return 0; + } + + rv = ngtcp2_dcidtr_track_retired_seq(&conn->dcid.dtr, fr->seq); + if (rv != 0) { + return rv; + } + + return conn_enqueue_retire_connection_id(conn, fr->seq); } if (found) { @@ -7779,7 +7507,7 @@ static int conn_recv_new_connection_id(ngtcp2_conn *conn, ngtcp2_gaptr_drop_first_gap(&conn->dcid.seqgap); } - len = ngtcp2_ringbuf_len(&conn->dcid.unused.rb); + len = ngtcp2_dcidtr_inactive_len(&conn->dcid.dtr); if (conn->dcid.current.seq >= conn->dcid.retire_prior_to) { ++extra_dcid; @@ -7789,7 +7517,7 @@ static int conn_recv_new_connection_id(ngtcp2_conn *conn, pv->dcid.seq >= conn->dcid.retire_prior_to) { ++extra_dcid; } - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && pv->fallback_dcid.seq != conn->dcid.current.seq && pv->fallback_dcid.seq >= conn->dcid.retire_prior_to) { ++extra_dcid; @@ -7801,13 +7529,13 @@ static int conn_recv_new_connection_id(ngtcp2_conn *conn, return NGTCP2_ERR_CONNECTION_ID_LIMIT; } - if (len >= NGTCP2_MAX_DCID_POOL_SIZE) { + if (len >= NGTCP2_DCIDTR_MAX_UNUSED_DCID_SIZE) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "too many connection ID"); return 0; } - dcid = ngtcp2_ringbuf_push_back(&conn->dcid.unused.rb); - ngtcp2_dcid_init(dcid, fr->seq, &fr->cid, fr->stateless_reset_token); + ngtcp2_dcidtr_push_unused(&conn->dcid.dtr, fr->seq, &fr->cid, + fr->stateless_reset_token); return 0; } @@ -7827,32 +7555,32 @@ static int conn_recv_new_connection_id(ngtcp2_conn *conn, static int conn_post_process_recv_new_connection_id(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ngtcp2_pv *pv = conn->pv; - ngtcp2_dcid *dcid; + ngtcp2_dcid dcid; int rv; if (conn->dcid.current.seq < conn->dcid.retire_prior_to) { - if (ngtcp2_ringbuf_len(&conn->dcid.unused.rb) == 0) { + if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { return 0; } - rv = conn_retire_dcid(conn, &conn->dcid.current, ts); + rv = conn_retire_active_dcid(conn, &conn->dcid.current, ts); if (rv != 0) { return rv; } - dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); + ngtcp2_dcidtr_pop_unused_cid_token(&conn->dcid.dtr, &dcid); + if (pv) { if (conn->dcid.current.seq == pv->dcid.seq) { - ngtcp2_dcid_copy_cid_token(&pv->dcid, dcid); + ngtcp2_dcid_copy_cid_token(&pv->dcid, &dcid); } - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && conn->dcid.current.seq == pv->fallback_dcid.seq) { - ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, dcid); + ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, &dcid); } } - ngtcp2_dcid_copy_cid_token(&conn->dcid.current, dcid); - ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); + ngtcp2_dcid_copy_cid_token(&conn->dcid.current, &dcid); rv = conn_call_activate_dcid(conn, &conn->dcid.current); if (rv != 0) { @@ -7862,54 +7590,52 @@ static int conn_post_process_recv_new_connection_id(ngtcp2_conn *conn, if (pv) { if (pv->dcid.seq < conn->dcid.retire_prior_to) { - if (ngtcp2_ringbuf_len(&conn->dcid.unused.rb)) { - rv = conn_retire_dcid(conn, &pv->dcid, ts); - if (rv != 0) { - return rv; - } - - dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); - - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && - pv->dcid.seq == pv->fallback_dcid.seq) { - ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, dcid); - } - - ngtcp2_dcid_copy_cid_token(&pv->dcid, dcid); - ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); - - rv = conn_call_activate_dcid(conn, &pv->dcid); - if (rv != 0) { - return rv; - } - } else { + if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PTV, "path migration is aborted because connection ID is" "retired and no unused connection ID is available"); return conn_abort_pv(conn, ts); } - } - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && - pv->fallback_dcid.seq < conn->dcid.retire_prior_to) { - if (ngtcp2_ringbuf_len(&conn->dcid.unused.rb)) { - rv = conn_retire_dcid(conn, &pv->fallback_dcid, ts); - if (rv != 0) { - return rv; - } - dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); - ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, dcid); - ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); + rv = conn_retire_active_dcid(conn, &pv->dcid, ts); + if (rv != 0) { + return rv; + } - rv = conn_call_activate_dcid(conn, &pv->fallback_dcid); - if (rv != 0) { - return rv; - } - } else { + ngtcp2_dcidtr_pop_unused_cid_token(&conn->dcid.dtr, &dcid); + + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && + pv->dcid.seq == pv->fallback_dcid.seq) { + ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, &dcid); + } + + ngtcp2_dcid_copy_cid_token(&pv->dcid, &dcid); + + rv = conn_call_activate_dcid(conn, &pv->dcid); + if (rv != 0) { + return rv; + } + } + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && + pv->fallback_dcid.seq < conn->dcid.retire_prior_to) { + if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { /* Now we have no fallback dcid. */ return conn_abort_pv(conn, ts); } + + rv = conn_retire_active_dcid(conn, &pv->fallback_dcid, ts); + if (rv != 0) { + return rv; + } + + ngtcp2_dcidtr_pop_unused_cid_token(&conn->dcid.dtr, &dcid); + ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, &dcid); + + rv = conn_call_activate_dcid(conn, &pv->fallback_dcid); + if (rv != 0) { + return rv; + } } } @@ -8185,9 +7911,9 @@ static int conn_select_preferred_addr(ngtcp2_conn *conn) { ngtcp2_path_storage ps; int rv; ngtcp2_pv *pv; - ngtcp2_dcid *dcid; + ngtcp2_dcid dcid; - if (ngtcp2_ringbuf_len(&conn->dcid.unused.rb) == 0) { + if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { return 0; } @@ -8199,24 +7925,22 @@ static int conn_select_preferred_addr(ngtcp2_conn *conn) { return rv; } - if (ps.path.remote.addrlen == 0 || + if (ngtcp2_addr_empty(&ps.path.remote) || ngtcp2_addr_eq(&conn->dcid.current.ps.path.remote, &ps.path.remote)) { return 0; } assert(conn->pv == NULL); - dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); - ngtcp2_dcid_set_path(dcid, &ps.path); + ngtcp2_dcidtr_pop_unused(&conn->dcid.dtr, &dcid); + ngtcp2_dcid_set_path(&dcid, &ps.path); - rv = ngtcp2_pv_new(&pv, dcid, conn_compute_pv_timeout(conn), + rv = ngtcp2_pv_new(&pv, &dcid, conn_compute_pv_timeout(conn), NGTCP2_PV_FLAG_PREFERRED_ADDR, &conn->log, conn->mem); if (rv != 0) { - /* TODO Call ngtcp2_dcid_free here if it is introduced */ return rv; } - ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); conn->pv = pv; return conn_call_activate_dcid(conn, &pv->dcid); @@ -8250,7 +7974,7 @@ static int conn_recv_handshake_done(ngtcp2_conn *conn, ngtcp2_tstamp ts) { conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED | NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED; - conn->pktns.rtb.persistent_congestion_start_ts = ts; + conn->handshake_confirmed_ts = ts; ngtcp2_conn_discard_handshake_state(conn, ts); @@ -8443,18 +8167,18 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, size_t dgramlen, int new_cid_used, ngtcp2_tstamp ts) { - ngtcp2_dcid dcid, *bound_dcid, *last; + ngtcp2_dcid dcid; ngtcp2_pv *pv; int rv; ngtcp2_duration pto; int require_new_cid; int local_addr_eq; + int pref_addr_migration; uint32_t remote_addr_cmp; - size_t len, i; assert(conn->server); - if (conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && + if (conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && ngtcp2_path_eq(&conn->pv->fallback_dcid.ps.path, path)) { /* If new path equals fallback path, that means connection migrated back to the original path. Fallback path is @@ -8478,9 +8202,11 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, } remote_addr_cmp = - ngtcp2_addr_compare(&conn->dcid.current.ps.path.remote, &path->remote); + ngtcp2_addr_cmp(&conn->dcid.current.ps.path.remote, &path->remote); local_addr_eq = ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local); + pref_addr_migration = + !local_addr_eq && conn_server_preferred_addr_migration(conn, &path->local); /* * When to change DCID? RFC 9002 section 9.5 says: @@ -8504,44 +8230,25 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "non-probing packet was received from new remote address"); - len = ngtcp2_ringbuf_len(&conn->dcid.bound.rb); + if (ngtcp2_dcidtr_pop_bound_dcid(&conn->dcid.dtr, &dcid, path) == 0) { + ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, + "Found DCID which has already been bound to the new path"); - for (i = 0; i < len; ++i) { - bound_dcid = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, i); - if (ngtcp2_path_eq(&bound_dcid->ps.path, path)) { - ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_CON, - "Found DCID which has already been bound to the new path"); - - ngtcp2_dcid_copy(&dcid, bound_dcid); - if (i == 0) { - ngtcp2_ringbuf_pop_front(&conn->dcid.bound.rb); - } else if (i == ngtcp2_ringbuf_len(&conn->dcid.bound.rb) - 1) { - ngtcp2_ringbuf_pop_back(&conn->dcid.bound.rb); - } else { - last = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, len - 1); - ngtcp2_dcid_copy(bound_dcid, last); - ngtcp2_ringbuf_pop_back(&conn->dcid.bound.rb); - } - require_new_cid = 0; + require_new_cid = 0; - if (dcid.cid.datalen) { - rv = conn_call_activate_dcid(conn, &dcid); - if (rv != 0) { - return rv; - } + if (dcid.cid.datalen) { + rv = conn_call_activate_dcid(conn, &dcid); + if (rv != 0) { + return rv; } - break; } - } - - if (i == len) { + } else { if (require_new_cid) { - if (ngtcp2_ringbuf_len(&conn->dcid.unused.rb) == 0) { + if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { return NGTCP2_ERR_CONN_ID_BLOCKED; } - ngtcp2_dcid_copy(&dcid, ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0)); - ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); + + ngtcp2_dcidtr_pop_unused(&conn->dcid.dtr, &dcid); rv = conn_call_activate_dcid(conn, &dcid); if (rv != 0) { @@ -8564,32 +8271,33 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, pto = conn_compute_pto(conn, &conn->pktns); rv = ngtcp2_pv_new(&pv, &dcid, conn_compute_pv_timeout_pto(conn, pto), - NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE, &conn->log, conn->mem); + NGTCP2_PV_FLAG_NONE, &conn->log, conn->mem); if (rv != 0) { return rv; } - if (conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE)) { - ngtcp2_dcid_copy(&pv->fallback_dcid, &conn->pv->fallback_dcid); - pv->fallback_pto = conn->pv->fallback_pto; + if (conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT)) { + ngtcp2_pv_set_fallback(pv, &conn->pv->fallback_dcid, + conn->pv->fallback_pto); /* Unset the flag bit so that conn_stop_pv does not retire DCID. */ - conn->pv->flags &= (uint8_t)~NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE; - } else { - ngtcp2_dcid_copy(&pv->fallback_dcid, &conn->dcid.current); - pv->fallback_pto = pto; + conn->pv->flags &= (uint8_t)~NGTCP2_PV_FLAG_FALLBACK_PRESENT; + } else if (!pref_addr_migration) { + ngtcp2_pv_set_fallback(pv, &conn->dcid.current, pto); } - ngtcp2_dcid_copy(&conn->dcid.current, &dcid); + if (!pref_addr_migration) { + ngtcp2_dcid_copy(&conn->dcid.current, &dcid); - if (!local_addr_eq || (remote_addr_cmp & (NGTCP2_ADDR_COMPARE_FLAG_ADDR | - NGTCP2_ADDR_COMPARE_FLAG_FAMILY))) { - conn_reset_congestion_state(conn, ts); - } + if (!local_addr_eq || (remote_addr_cmp & (NGTCP2_ADDR_CMP_FLAG_ADDR | + NGTCP2_ADDR_CMP_FLAG_FAMILY))) { + conn_reset_congestion_state(conn, ts); + } - conn_reset_ecn_validation_state(conn); + conn_reset_ecn_validation_state(conn); - ngtcp2_conn_stop_pmtud(conn); + ngtcp2_conn_stop_pmtud(conn); + } if (conn->pv) { ngtcp2_log_info( @@ -8634,7 +8342,7 @@ static int conn_recv_pkt_from_new_path(ngtcp2_conn *conn, return 0; } - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && ngtcp2_path_eq(&pv->fallback_dcid.ps.path, path)) { pv->fallback_dcid.bytes_recv += dgramlen; return 0; @@ -8650,7 +8358,6 @@ static int conn_recv_pkt_from_new_path(ngtcp2_conn *conn, return rv; } - ngtcp2_dcid_set_path(bound_dcid, path); bound_dcid->bytes_recv += dgramlen; return 0; @@ -8763,20 +8470,13 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, ngtcp2_qlog_pkt_received_end(&conn->qlog, hd, pktlen); - rv = pktns_commit_recv_pkt_num(pktns, hd->pkt_num, require_ack, pkt_ts); + rv = pktns_commit_recv_pkt_num(pktns, hd->pkt_num, pi, require_ack, pkt_ts); if (rv != 0) { return rv; } - pktns_increase_ecn_counts(pktns, pi); - /* Initial and Handshake are always acknowledged without delay. No need to call ngtcp2_acktr_immediate_ack(). */ - rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd->pkt_num, require_ack, - pkt_ts); - if (rv != 0) { - return rv; - } conn_restart_timer_on_read(conn, ts); @@ -8794,8 +8494,6 @@ static int conn_allow_path_change_under_disable_active_migration(ngtcp2_conn *conn, const ngtcp2_path *path) { uint32_t remote_addr_cmp; - const ngtcp2_preferred_addr *paddr; - ngtcp2_addr addr; assert(conn->server); assert(conn->local.transport_params.disable_active_migration); @@ -8804,40 +8502,15 @@ conn_allow_path_change_under_disable_active_migration(ngtcp2_conn *conn, (NAT rebinding). */ if (ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local)) { remote_addr_cmp = - ngtcp2_addr_compare(&conn->dcid.current.ps.path.remote, &path->remote); + ngtcp2_addr_cmp(&conn->dcid.current.ps.path.remote, &path->remote); - return (remote_addr_cmp | NGTCP2_ADDR_COMPARE_FLAG_PORT) == - NGTCP2_ADDR_COMPARE_FLAG_PORT; + return (remote_addr_cmp | NGTCP2_ADDR_CMP_FLAG_PORT) == + NGTCP2_ADDR_CMP_FLAG_PORT; } /* If local address changes, it must be one of the preferred addresses. */ - - if (!conn->local.transport_params.preferred_addr_present) { - return 0; - } - - paddr = &conn->local.transport_params.preferred_addr; - - if (paddr->ipv4_present) { - ngtcp2_addr_init(&addr, (const ngtcp2_sockaddr *)&paddr->ipv4, - sizeof(paddr->ipv4)); - - if (ngtcp2_addr_eq(&addr, &path->local)) { - return 1; - } - } - - if (paddr->ipv6_present) { - ngtcp2_addr_init(&addr, (const ngtcp2_sockaddr *)&paddr->ipv6, - sizeof(paddr->ipv6)); - - if (ngtcp2_addr_eq(&addr, &path->local)) { - return 1; - } - } - - return 0; + return conn_server_preferred_addr_migration(conn, &path->local); } /* @@ -8904,13 +8577,28 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, int path_challenge_recved = 0; size_t num_ack_processed = 0; - if (conn->server && conn->local.transport_params.disable_active_migration && - !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) && - !conn_allow_path_change_under_disable_active_migration(conn, path)) { - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, - "packet is discarded because active migration is disabled"); + if (conn->server) { + if (conn->local.transport_params.disable_active_migration && + !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) && + !conn_allow_path_change_under_disable_active_migration(conn, path)) { + ngtcp2_log_info( + &conn->log, NGTCP2_LOG_EVENT_PKT, + "packet is discarded because local active migration is disabled"); - return NGTCP2_ERR_DISCARD_PKT; + return NGTCP2_ERR_DISCARD_PKT; + } + + assert(conn->remote.transport_params); + + if (conn->remote.transport_params->disable_active_migration && + !ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local) && + !conn_server_preferred_addr_migration(conn, &path->local)) { + ngtcp2_log_info( + &conn->log, NGTCP2_LOG_EVENT_PKT, + "packet is discarded because remote active migration is disabled"); + + return NGTCP2_ERR_DISCARD_PKT; + } } if (pkt[0] & NGTCP2_HEADER_FORM_BIT) { @@ -9035,8 +8723,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, payload = pkt + hdpktlen; payloadlen = pktlen - hdpktlen; - hd.pkt_num = - ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, hd.pkt_numlen); + hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->acktr.max_pkt_num, hd.pkt_num, + hd.pkt_numlen); if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); @@ -9046,6 +8734,19 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_log_rx_pkt_hd(&conn->log, &hd); if (hd.type == NGTCP2_PKT_1RTT) { + if (conn->server && conn->rx.preferred_addr.pkt_num != -1 && + conn->rx.preferred_addr.pkt_num < hd.pkt_num && + ngtcp2_sockaddr_eq((const ngtcp2_sockaddr *)&conn->hs_local_addr, + path->local.addr)) { + ngtcp2_log_info( + &conn->log, NGTCP2_LOG_EVENT_PKT, + "pkt=%" PRId64 + " is discarded because it was received on handshake local " + "address after preferred address migration", + hd.pkt_num); + return NGTCP2_ERR_DISCARD_PKT; + } + key_phase_bit_changed = conn_key_phase_changed(conn, &hd); } @@ -9067,7 +8768,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } else { force_decrypt_failure = 1; } - } else if (pktns->rx.max_pkt_num < hd.pkt_num) { + } else if (pktns->acktr.max_pkt_num < hd.pkt_num) { assert(ckm->pkt_num < hd.pkt_num); if (!conn->crypto.key_update.new_rx_ckm) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, @@ -9336,7 +9037,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, path_challenge_recved = 1; break; case NGTCP2_FRAME_PATH_RESPONSE: - rv = conn_recv_path_response(conn, &fr->path_response, ts); + rv = conn_recv_path_response(conn, &hd, &fr->path_response, ts); if (rv != 0) { return rv; } @@ -9426,7 +9127,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (conn->server && hd.type == NGTCP2_PKT_1RTT && !ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { - if (non_probing_pkt && pktns->rx.max_pkt_num < hd.pkt_num && + if (non_probing_pkt && pktns->acktr.max_pkt_num < hd.pkt_num && !conn_path_validation_in_progress(conn, path)) { rv = conn_recv_non_probing_pkt_on_new_path(conn, path, dgramlen, new_cid_used, ts); @@ -9470,25 +9171,17 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } } - rv = pktns_commit_recv_pkt_num(pktns, hd.pkt_num, require_ack, pkt_ts); + rv = pktns_commit_recv_pkt_num(pktns, hd.pkt_num, pi, require_ack, pkt_ts); if (rv != 0) { return rv; } - pktns_increase_ecn_counts(pktns, pi); - if (require_ack && (++pktns->acktr.rx_npkt >= conn->local.settings.ack_thresh || (pi->ecn & NGTCP2_ECN_MASK) == NGTCP2_ECN_CE)) { ngtcp2_acktr_immediate_ack(&pktns->acktr); } - rv = - ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, pkt_ts); - if (rv != 0) { - return rv; - } - conn_restart_timer_on_read(conn, ts); ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); @@ -9721,24 +9414,6 @@ static int conn_recv_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path, return 0; } -/* - * conn_is_retired_path returns nonzero if |path| is included in - * retired path list. - */ -static int conn_is_retired_path(ngtcp2_conn *conn, const ngtcp2_path *path) { - size_t i, len = ngtcp2_ringbuf_len(&conn->dcid.retired.rb); - ngtcp2_dcid *dcid; - - for (i = 0; i < len; ++i) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.retired.rb, i); - if (ngtcp2_path_eq(&dcid->ps.path, path)) { - return 1; - } - } - - return 0; -} - /* * conn_enqueue_handshake_done enqueues HANDSHAKE_DONE frame for * transmission. @@ -9875,7 +9550,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, } } - if (conn->hs_pktns->rx.max_pkt_num != -1) { + if (conn->hs_pktns->acktr.max_pkt_num != -1) { ngtcp2_conn_discard_initial_state(conn, ts); } @@ -9956,7 +9631,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, } } - conn->pktns.rtb.persistent_congestion_start_ts = ts; + conn->handshake_confirmed_ts = ts; /* Re-arm loss detection timer here after handshake has been confirmed. */ @@ -9996,7 +9671,7 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, /* client does not expect a packet from unknown path. */ if (!conn->server && !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) && (!conn->pv || !ngtcp2_path_eq(&conn->pv->dcid.ps.path, path)) && - !conn_is_retired_path(conn, path)) { + !ngtcp2_dcidtr_check_path_retired(&conn->dcid.dtr, path)) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "ignore packet from unknown path"); return 0; @@ -10172,7 +9847,6 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, ngtcp2_ssize res = 0, nwrite = 0, early_spktlen = 0; size_t origlen = destlen; uint64_t pending_early_datalen; - ngtcp2_dcid *dcid; ngtcp2_preferred_addr *paddr; switch (conn->state) { @@ -10290,11 +9964,11 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, assert(conn->remote.transport_params); if (conn->remote.transport_params->preferred_addr_present) { - assert(!ngtcp2_ringbuf_full(&conn->dcid.unused.rb)); + assert(!ngtcp2_dcidtr_unused_full(&conn->dcid.dtr)); paddr = &conn->remote.transport_params->preferred_addr; - dcid = ngtcp2_ringbuf_push_back(&conn->dcid.unused.rb); - ngtcp2_dcid_init(dcid, 1, &paddr->cid, paddr->stateless_reset_token); + ngtcp2_dcidtr_push_unused(&conn->dcid.dtr, 1, &paddr->cid, + paddr->stateless_reset_token); rv = ngtcp2_gaptr_push(&conn->dcid.seqgap, 1, 1); if (rv != 0) { @@ -10519,20 +10193,6 @@ int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn) { (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED); } -int ngtcp2_conn_sched_ack(ngtcp2_conn *conn, ngtcp2_acktr *acktr, - int64_t pkt_num, int active_ack, ngtcp2_tstamp ts) { - int rv; - (void)conn; - - rv = ngtcp2_acktr_add(acktr, pkt_num, active_ack, ts); - if (rv != 0) { - assert(rv != NGTCP2_ERR_INVALID_ARGUMENT); - return rv; - } - - return 0; -} - int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt, size_t pktlen) { ngtcp2_ssize nread; ngtcp2_pkt_hd hd, *p; @@ -10904,68 +10564,14 @@ int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { return conn_initiate_key_update(conn, ts); } -/* - * conn_retire_stale_bound_dcid retires stale destination connection - * ID in conn->dcid.bound to keep some unused destination connection - * IDs available. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -static int conn_retire_stale_bound_dcid(ngtcp2_conn *conn, - ngtcp2_duration timeout, - ngtcp2_tstamp ts) { - size_t i; - ngtcp2_dcid *dcid, *last; - int rv; - - for (i = 0; i < ngtcp2_ringbuf_len(&conn->dcid.bound.rb);) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, i); - - assert(dcid->cid.datalen); - - if (ngtcp2_tstamp_not_elapsed(dcid->bound_ts, timeout, ts)) { - ++i; - continue; - } - - rv = conn_retire_dcid_seq(conn, dcid->seq); - if (rv != 0) { - return rv; - } - - if (i == 0) { - ngtcp2_ringbuf_pop_front(&conn->dcid.bound.rb); - continue; - } - - if (i == ngtcp2_ringbuf_len(&conn->dcid.bound.rb) - 1) { - ngtcp2_ringbuf_pop_back(&conn->dcid.bound.rb); - break; - } - - last = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, - ngtcp2_ringbuf_len(&conn->dcid.bound.rb) - 1); - ngtcp2_dcid_copy(dcid, last); - ngtcp2_ringbuf_pop_back(&conn->dcid.bound.rb); - } - - return 0; -} - ngtcp2_tstamp ngtcp2_conn_loss_detection_expiry(ngtcp2_conn *conn) { return conn->cstat.loss_detection_timer; } ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { - ngtcp2_tstamp res = UINT64_MAX; + ngtcp2_tstamp res = UINT64_MAX, ts; ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); ngtcp2_scid *scid; - ngtcp2_dcid *dcid; - size_t i, len; if (conn->pv) { res = ngtcp2_pv_next_expiry(conn->pv); @@ -10982,20 +10588,15 @@ ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { } } - if (ngtcp2_ringbuf_len(&conn->dcid.retired.rb)) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.retired.rb, 0); - res = ngtcp2_min_uint64(res, dcid->retired_ts + pto); + ts = ngtcp2_dcidtr_earliest_retired_ts(&conn->dcid.dtr); + if (ts != UINT64_MAX) { + res = ngtcp2_min_uint64(res, ts + pto); } if (conn->dcid.current.cid.datalen) { - len = ngtcp2_ringbuf_len(&conn->dcid.bound.rb); - for (i = 0; i < len; ++i) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, i); - - assert(dcid->cid.datalen); - assert(dcid->bound_ts != UINT64_MAX); - - res = ngtcp2_min_uint64(res, dcid->bound_ts + 3 * pto); + ts = ngtcp2_dcidtr_earliest_bound_ts(&conn->dcid.dtr); + if (ts != UINT64_MAX) { + res = ngtcp2_min_uint64(res, ts + 3 * pto); } } @@ -11081,7 +10682,8 @@ int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts) { } if (conn->dcid.current.cid.datalen) { - rv = conn_retire_stale_bound_dcid(conn, 3 * pto, ts); + rv = ngtcp2_dcidtr_retire_stale_bound_dcid(&conn->dcid.dtr, 3 * pto, ts, + dcidtr_on_retire, conn); if (rv != 0) { return rv; } @@ -11578,7 +11180,8 @@ int ngtcp2_conn_set_local_transport_params_versioned( assert(conn->server); assert(params->active_connection_id_limit >= NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT); - assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE); + assert(params->active_connection_id_limit <= + NGTCP2_DCIDTR_MAX_UNUSED_DCID_SIZE); if (conn->hs_pktns == NULL || conn->hs_pktns->crypto.tx.ckm) { return NGTCP2_ERR_INVALID_STATE; @@ -11739,8 +11342,7 @@ static ngtcp2_ssize conn_write_vmsg_wrapper(ngtcp2_conn *conn, if (cstat->bytes_in_flight >= cstat->cwnd) { conn->rst.is_cwnd_limited = 1; - } else if (conn->rst.app_limited == 0 && - (cstat->cwnd >= cstat->ssthresh || + } else if ((cstat->cwnd >= cstat->ssthresh || cstat->bytes_in_flight * 2 < cstat->cwnd) && nwrite == 0 && conn_pacing_pkt_tx_allowed(conn, ts) && (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) { @@ -12930,7 +12532,7 @@ static void conn_get_loss_time_and_pktns(ngtcp2_conn *conn, static ngtcp2_tstamp conn_get_earliest_pto_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts) { - ngtcp2_pktns *ns[] = {conn->in_pktns, conn->hs_pktns, &conn->pktns}; + ngtcp2_pktns *const ns[] = {conn->in_pktns, conn->hs_pktns, &conn->pktns}; size_t i; ngtcp2_tstamp earliest_ts = UINT64_MAX, t; ngtcp2_conn_stat *cstat = &conn->cstat; @@ -13249,18 +12851,22 @@ static size_t conn_get_num_active_dcid(ngtcp2_conn *conn) { size_t n = 1; /* for conn->dcid.current */ ngtcp2_pv *pv = conn->pv; + if (conn->dcid.current.cid.datalen == 0) { + return n; + } + if (pv) { if (pv->dcid.seq != conn->dcid.current.seq) { ++n; } - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && pv->fallback_dcid.seq != conn->dcid.current.seq && pv->fallback_dcid.seq != pv->dcid.seq) { ++n; } } - n += ngtcp2_ringbuf_len(&conn->dcid.retired.rb); + n += ngtcp2_dcidtr_retired_len(&conn->dcid.dtr); return n; } @@ -13293,12 +12899,16 @@ size_t ngtcp2_conn_get_active_dcid(ngtcp2_conn *conn, ngtcp2_cid_token *dest) { copy_dcid_to_cid_token(dest, &conn->dcid.current); ++dest; + if (conn->dcid.current.cid.datalen == 0) { + return 1; + } + if (pv) { if (pv->dcid.seq != conn->dcid.current.seq) { copy_dcid_to_cid_token(dest, &pv->dcid); ++dest; } - if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) && + if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_PRESENT) && pv->fallback_dcid.seq != conn->dcid.current.seq && pv->fallback_dcid.seq != pv->dcid.seq) { copy_dcid_to_cid_token(dest, &pv->fallback_dcid); @@ -13306,9 +12916,9 @@ size_t ngtcp2_conn_get_active_dcid(ngtcp2_conn *conn, ngtcp2_cid_token *dest) { } } - len = ngtcp2_ringbuf_len(&conn->dcid.retired.rb); + len = ngtcp2_ringbuf_len(&conn->dcid.dtr.retired.rb); for (i = 0; i < len; ++i) { - dcid = ngtcp2_ringbuf_get(&conn->dcid.retired.rb, i); + dcid = ngtcp2_ringbuf_get(&conn->dcid.dtr.retired.rb, i); copy_dcid_to_cid_token(dest, dcid); ++dest; } @@ -13353,7 +12963,7 @@ static int conn_initiate_migration_precheck(ngtcp2_conn *conn, return NGTCP2_ERR_INVALID_STATE; } - if (ngtcp2_ringbuf_len(&conn->dcid.unused.rb) == 0) { + if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { return NGTCP2_ERR_CONN_ID_BLOCKED; } @@ -13368,7 +12978,7 @@ int ngtcp2_conn_initiate_immediate_migration(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_tstamp ts) { int rv; - ngtcp2_dcid *dcid; + ngtcp2_dcid dcid; ngtcp2_pv *pv; assert(!conn->server); @@ -13389,16 +12999,15 @@ int ngtcp2_conn_initiate_immediate_migration(ngtcp2_conn *conn, } } - rv = conn_retire_dcid(conn, &conn->dcid.current, ts); + rv = conn_retire_active_dcid(conn, &conn->dcid.current, ts); if (rv != 0) { return rv; } - dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); - ngtcp2_dcid_set_path(dcid, path); + ngtcp2_dcidtr_pop_unused(&conn->dcid.dtr, &dcid); + ngtcp2_dcid_set_path(&dcid, path); - ngtcp2_dcid_copy(&conn->dcid.current, dcid); - ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); + ngtcp2_dcid_copy(&conn->dcid.current, &dcid); conn_reset_congestion_state(conn, ts); conn_reset_ecn_validation_state(conn); @@ -13407,7 +13016,7 @@ int ngtcp2_conn_initiate_immediate_migration(ngtcp2_conn *conn, connection should be closed if this path validation failed. The current design allows an application to continue, by migrating into yet another path. */ - rv = ngtcp2_pv_new(&pv, dcid, conn_compute_pv_timeout(conn), + rv = ngtcp2_pv_new(&pv, &dcid, conn_compute_pv_timeout(conn), NGTCP2_PV_FLAG_NONE, &conn->log, conn->mem); if (rv != 0) { return rv; @@ -13421,7 +13030,7 @@ int ngtcp2_conn_initiate_immediate_migration(ngtcp2_conn *conn, int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_tstamp ts) { int rv; - ngtcp2_dcid *dcid; + ngtcp2_dcid dcid; ngtcp2_pv *pv; assert(!conn->server); @@ -13440,16 +13049,15 @@ int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path, } } - dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0); - ngtcp2_dcid_set_path(dcid, path); + ngtcp2_dcidtr_pop_unused(&conn->dcid.dtr, &dcid); + ngtcp2_dcid_set_path(&dcid, path); - rv = ngtcp2_pv_new(&pv, dcid, conn_compute_pv_timeout(conn), + rv = ngtcp2_pv_new(&pv, &dcid, conn_compute_pv_timeout(conn), NGTCP2_PV_FLAG_NONE, &conn->log, conn->mem); if (rv != 0) { return rv; } - ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb); conn->pv = pv; return conn_call_activate_dcid(conn, &pv->dcid); @@ -13487,7 +13095,7 @@ uint64_t ngtcp2_conn_get_streams_uni_left(ngtcp2_conn *conn) { uint64_t ngtcp2_conn_get_cwnd_left(ngtcp2_conn *conn) { uint64_t bytes_in_flight = conn->cstat.bytes_in_flight; - uint64_t cwnd = conn_get_cwnd(conn); + uint64_t cwnd = conn->cstat.cwnd; if (cwnd > bytes_in_flight) { return cwnd - bytes_in_flight; @@ -13630,7 +13238,7 @@ int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, int64_t stream_id, void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ngtcp2_duration pacing_interval; - ngtcp2_duration wait; + ngtcp2_duration wait, d; conn_update_timestamp(conn, ts); @@ -13651,6 +13259,12 @@ void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) { wait = (ngtcp2_duration)(conn->tx.pacing.pktlen * pacing_interval); + if (conn->tx.pacing.compensation >= NGTCP2_MILLISECONDS) { + d = ngtcp2_min_uint64(wait, conn->tx.pacing.compensation); + wait -= d; + conn->tx.pacing.compensation -= d; + } + conn->tx.pacing.next_ts = ts + wait; conn->tx.pacing.pktlen = 0; } @@ -13659,48 +13273,6 @@ size_t ngtcp2_conn_get_send_quantum(ngtcp2_conn *conn) { return conn->cstat.send_quantum; } -int ngtcp2_conn_track_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { - if (conn->dcid.retire_unacked.len >= - ngtcp2_arraylen(conn->dcid.retire_unacked.seqs)) { - return NGTCP2_ERR_CONNECTION_ID_LIMIT; - } - - conn->dcid.retire_unacked.seqs[conn->dcid.retire_unacked.len++] = seq; - - return 0; -} - -void ngtcp2_conn_untrack_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { - size_t i; - - for (i = 0; i < conn->dcid.retire_unacked.len; ++i) { - if (conn->dcid.retire_unacked.seqs[i] != seq) { - continue; - } - - if (i != conn->dcid.retire_unacked.len - 1) { - conn->dcid.retire_unacked.seqs[i] = - conn->dcid.retire_unacked.seqs[conn->dcid.retire_unacked.len - 1]; - } - - --conn->dcid.retire_unacked.len; - - return; - } -} - -int ngtcp2_conn_check_retired_dcid_tracked(ngtcp2_conn *conn, uint64_t seq) { - size_t i; - - for (i = 0; i < conn->dcid.retire_unacked.len; ++i) { - if (conn->dcid.retire_unacked.seqs[i] == seq) { - return 1; - } - } - - return 0; -} - size_t ngtcp2_conn_get_stream_loss_count(ngtcp2_conn *conn, int64_t stream_id) { ngtcp2_strm *strm = ngtcp2_conn_find_stream(conn, stream_id); @@ -13737,8 +13309,7 @@ ngtcp2_ssize ngtcp2_pkt_write_connection_close( int rv; ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, NGTCP2_PKT_INITIAL, dcid, - scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1, version, - /* len = */ 0); + scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1, version); ngtcp2_vec_init(&ckm.secret, NULL, 0); ngtcp2_vec_init(&ckm.iv, iv, 12); @@ -13767,6 +13338,7 @@ ngtcp2_ssize ngtcp2_pkt_write_connection_close( fr.type = NGTCP2_FRAME_CONNECTION_CLOSE; fr.connection_close.error_code = error_code; + fr.connection_close.frame_type = 0; fr.connection_close.reasonlen = reasonlen; fr.connection_close.reason = (uint8_t *)reason; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h index 55073fcc828d73..0ba8d6efcc6ac1 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h @@ -51,6 +51,7 @@ #include "ngtcp2_qlog.h" #include "ngtcp2_rst.h" #include "ngtcp2_conn_stat.h" +#include "ngtcp2_dcidtr.h" typedef enum { /* Client specific handshake states */ @@ -78,18 +79,6 @@ typedef enum { accept. */ #define NGTCP2_MAX_RETRIES 3 -/* NGTCP2_MAX_BOUND_DCID_POOL_SIZE is the maximum number of - destination connection ID which have been bound to a particular - path, but not yet used as primary path and path validation is not - performed from the local endpoint. */ -#define NGTCP2_MAX_BOUND_DCID_POOL_SIZE 4 -/* NGTCP2_MAX_DCID_POOL_SIZE is the maximum number of destination - connection ID the remote endpoint provides to store. It must be - the power of 2. */ -#define NGTCP2_MAX_DCID_POOL_SIZE 8 -/* NGTCP2_MAX_DCID_RETIRED_SIZE is the maximum number of retired DCID - kept to catch in-flight packet on retired path. */ -#define NGTCP2_MAX_DCID_RETIRED_SIZE 2 /* NGTCP2_MAX_SCID_POOL_SIZE is the maximum number of source connection ID the local endpoint provides to the remote endpoint. The chosen value was described in old draft. Now a remote endpoint @@ -239,11 +228,6 @@ typedef struct ngtcp2_pktns { /* pngap tracks received packet number in order to suppress duplicated packet number. */ ngtcp2_gaptr pngap; - /* max_pkt_num is the largest packet number received so far. */ - int64_t max_pkt_num; - /* max_pkt_ts is the timestamp when max_pkt_num packet is - received. */ - ngtcp2_tstamp max_pkt_ts; /* max_ack_eliciting_pkt_num is the largest ack-eliciting packet number received so far. */ int64_t max_ack_eliciting_pkt_num; @@ -268,21 +252,6 @@ typedef struct ngtcp2_pktns { * ngtcp2_pktns. */ ngtcp2_pkt_chain *buffed_pkts; - - struct { - /* ect0, ect1, and ce are the number of QUIC packets received - with those markings. */ - size_t ect0; - size_t ect1; - size_t ce; - struct { - /* ect0, ect1, ce are the ECN counts received in the latest - ACK frame. */ - uint64_t ect0; - uint64_t ect1; - uint64_t ce; - } ack; - } ecn; } rx; struct { @@ -336,12 +305,6 @@ typedef struct ngtcp2_early_transport_params { uint64_t max_datagram_frame_size; } ngtcp2_early_transport_params; -ngtcp2_static_ringbuf_def(dcid_bound, NGTCP2_MAX_BOUND_DCID_POOL_SIZE, - sizeof(ngtcp2_dcid)) -ngtcp2_static_ringbuf_def(dcid_unused, NGTCP2_MAX_DCID_POOL_SIZE, - sizeof(ngtcp2_dcid)) -ngtcp2_static_ringbuf_def(dcid_retired, NGTCP2_MAX_DCID_RETIRED_SIZE, - sizeof(ngtcp2_dcid)) ngtcp2_static_ringbuf_def(path_challenge, 4, sizeof(ngtcp2_path_challenge_entry)) @@ -366,6 +329,8 @@ struct ngtcp2_conn { records it in order to verify retry_source_connection_id transport parameter. Server does not use this field. */ ngtcp2_cid retry_scid; + /* hs_local_addr is a local address used during handshake. */ + ngtcp2_sockaddr_union hs_local_addr; ngtcp2_pktns *in_pktns; ngtcp2_pktns *hs_pktns; ngtcp2_pktns pktns; @@ -373,31 +338,13 @@ struct ngtcp2_conn { struct { /* current is the current destination connection ID. */ ngtcp2_dcid current; - /* bound is a set of destination connection IDs which are bound to - particular paths. These paths are not validated yet. */ - ngtcp2_static_ringbuf_dcid_bound bound; - /* unused is a set of unused CID received from peer. */ - ngtcp2_static_ringbuf_dcid_unused unused; - /* retired is a set of CID retired by local endpoint. Keep them - in 3*PTO to catch packets in flight along the old path. */ - ngtcp2_static_ringbuf_dcid_retired retired; + ngtcp2_dcidtr dtr; /* seqgap tracks received sequence numbers in order to ignore retransmitted duplicated NEW_CONNECTION_ID frame. */ ngtcp2_gaptr seqgap; /* retire_prior_to is the largest retire_prior_to received so far. */ uint64_t retire_prior_to; - struct { - /* seqs contains sequence number of Connection ID whose - retirement is not acknowledged by the remote endpoint yet. */ - uint64_t seqs[NGTCP2_MAX_DCID_POOL_SIZE * 2]; - /* len is the number of sequence numbers that seq contains. */ - size_t len; - } retire_unacked; - /* zerolen_seq is a pseudo sequence number of zero-length - Destination Connection ID in order to distinguish between - them. */ - uint64_t zerolen_seq; } dcid; struct { @@ -421,11 +368,6 @@ struct ngtcp2_conn { struct { /* strmq contains ngtcp2_strm which has frames to send. */ ngtcp2_pq strmq; - /* ack is ACK frame. The underlying buffer is reused. */ - ngtcp2_frame *ack; - /* max_ack_ranges is the number of additional ngtcp2_ack_range - which ack can contain. */ - size_t max_ack_ranges; /* offset is the offset the local endpoint has sent to the remote endpoint. */ uint64_t offset; @@ -458,6 +400,15 @@ struct ngtcp2_conn { /* next_ts is the time to send next packet. It is UINT64_MAX if packet pacing is disabled or expired.*/ ngtcp2_tstamp next_ts; + /* compensation is the amount of time that a local endpoint + waits too long for pacing. This happens because there is an + overhead before start writing packets after pacing timer + expires. If multiple QUIC connections are handled by a + single thread, which is typical use case for event loop based + servers, each processing of QUIC connection adds overhead, + for example, TLS handshake, and packet encryption/decryption, + etc. */ + ngtcp2_duration compensation; } pacing; } tx; @@ -478,6 +429,12 @@ struct ngtcp2_conn { ngtcp2_static_ringbuf_path_challenge path_challenge; /* ccerr is the received connection close error. */ ngtcp2_ccerr ccerr; + + struct { + /* pkt_num is the lowest incoming packet number of the packet + that server verified preferred address usage of client. */ + int64_t pkt_num; + } preferred_addr; } rx; struct { @@ -671,6 +628,9 @@ struct ngtcp2_conn { const ngtcp2_mem *mem; /* idle_ts is the time instant when idle timer started. */ ngtcp2_tstamp idle_ts; + /* handshake_confirmed_ts is the time instant when handshake is + confirmed. For server, it is confirmed when completed. */ + ngtcp2_tstamp handshake_confirmed_ts; void *user_data; uint32_t client_chosen_version; uint32_t negotiated_version; @@ -724,21 +684,6 @@ typedef struct ngtcp2_vmsg { }; } ngtcp2_vmsg; -/* - * ngtcp2_conn_sched_ack stores packet number |pkt_num| and its - * reception timestamp |ts| in order to send its ACK. - * - * It returns 0 if it succeeds, or one of the following negative error - * codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory - * NGTCP2_ERR_PROTO - * Same packet number has already been added. - */ -int ngtcp2_conn_sched_ack(ngtcp2_conn *conn, ngtcp2_acktr *acktr, - int64_t pkt_num, int active_ack, ngtcp2_tstamp ts); - /* * ngtcp2_conn_find_stream returns a stream whose stream ID is * |stream_id|. If no such stream is found, it returns NULL. @@ -1137,28 +1082,6 @@ int ngtcp2_conn_set_remote_transport_params( int ngtcp2_conn_set_0rtt_remote_transport_params( ngtcp2_conn *conn, const ngtcp2_transport_params *params); -/* - * ngtcp2_conn_create_ack_frame creates ACK frame, and assigns its - * pointer to |*pfr| if there are any received packets to acknowledge. - * If there are no packets to acknowledge, this function returns 0, - * and |*pfr| is untouched. The caller is advised to set |*pfr| to - * NULL before calling this function, and check it after this function - * returns. - * - * Call ngtcp2_acktr_commit_ack after a created ACK frame is - * successfully serialized into a packet. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, - ngtcp2_pktns *pktns, uint8_t type, - ngtcp2_tstamp ts, ngtcp2_duration ack_delay, - uint64_t ack_delay_exponent); - /* * ngtcp2_conn_discard_initial_state discards state for Initial packet * number space. diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.c new file mode 100644 index 00000000000000..8a8d7733797176 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.c @@ -0,0 +1,497 @@ +/* + * ngtcp2 + * + * Copyright (c) 2025 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ngtcp2_dcidtr.h" + +#include + +#include "ngtcp2_tstamp.h" +#include "ngtcp2_macro.h" + +void ngtcp2_dcidtr_init(ngtcp2_dcidtr *dtr) { + ngtcp2_static_ringbuf_dcid_unused_init(&dtr->unused); + ngtcp2_static_ringbuf_dcid_bound_init(&dtr->bound); + ngtcp2_static_ringbuf_dcid_retired_init(&dtr->retired); + + dtr->retire_unacked.len = 0; +} + +int ngtcp2_dcidtr_track_retired_seq(ngtcp2_dcidtr *dtr, uint64_t seq) { + if (dtr->retire_unacked.len >= ngtcp2_arraylen(dtr->retire_unacked.seqs)) { + return NGTCP2_ERR_CONNECTION_ID_LIMIT; + } + + dtr->retire_unacked.seqs[dtr->retire_unacked.len++] = seq; + + return 0; +} + +void ngtcp2_dcidtr_untrack_retired_seq(ngtcp2_dcidtr *dtr, uint64_t seq) { + size_t i; + + for (i = 0; i < dtr->retire_unacked.len; ++i) { + if (dtr->retire_unacked.seqs[i] != seq) { + continue; + } + + if (i != dtr->retire_unacked.len - 1) { + dtr->retire_unacked.seqs[i] = + dtr->retire_unacked.seqs[dtr->retire_unacked.len - 1]; + } + + --dtr->retire_unacked.len; + + return; + } +} + +int ngtcp2_dcidtr_check_retired_seq_tracked(const ngtcp2_dcidtr *dtr, + uint64_t seq) { + size_t i; + + for (i = 0; i < dtr->retire_unacked.len; ++i) { + if (dtr->retire_unacked.seqs[i] == seq) { + return 1; + } + } + + return 0; +} + +static int dcidtr_on_retire(ngtcp2_dcidtr *dtr, const ngtcp2_dcid *dcid, + ngtcp2_dcidtr_cb on_retire, void *user_data) { + int rv; + + if (ngtcp2_dcidtr_check_retired_seq_tracked(dtr, dcid->seq)) { + return 0; + } + + rv = ngtcp2_dcidtr_track_retired_seq(dtr, dcid->seq); + if (rv != 0) { + return rv; + } + + if (!on_retire) { + return 0; + } + + return on_retire(dcid, user_data); +} + +ngtcp2_dcid *ngtcp2_dcidtr_find_bound_dcid(const ngtcp2_dcidtr *dtr, + const ngtcp2_path *path) { + ngtcp2_dcid *dcid; + const ngtcp2_ringbuf *rb = &dtr->bound.rb; + size_t i, len = ngtcp2_ringbuf_len(rb); + + for (i = 0; i < len; ++i) { + dcid = ngtcp2_ringbuf_get(rb, i); + + if (ngtcp2_path_eq(&dcid->ps.path, path)) { + return dcid; + } + } + + return NULL; +} + +ngtcp2_dcid *ngtcp2_dcidtr_bind_zerolen_dcid(ngtcp2_dcidtr *dtr, + const ngtcp2_path *path) { + ngtcp2_dcid *dcid = ngtcp2_ringbuf_push_back(&dtr->bound.rb); + ngtcp2_cid cid; + + ngtcp2_cid_zero(&cid); + ngtcp2_dcid_init(dcid, 0, &cid, NULL); + ngtcp2_dcid_set_path(dcid, path); + + return dcid; +} + +int ngtcp2_dcidtr_bind_dcid(ngtcp2_dcidtr *dtr, ngtcp2_dcid **pdest, + const ngtcp2_path *path, ngtcp2_tstamp ts, + ngtcp2_dcidtr_cb on_retire, void *user_data) { + const ngtcp2_dcid *src; + ngtcp2_dcid *dest; + int rv; + + if (ngtcp2_ringbuf_full(&dtr->bound.rb)) { + rv = dcidtr_on_retire(dtr, ngtcp2_ringbuf_get(&dtr->bound.rb, 0), on_retire, + user_data); + if (rv != 0) { + return rv; + } + } + + src = ngtcp2_ringbuf_get(&dtr->unused.rb, 0); + dest = ngtcp2_ringbuf_push_back(&dtr->bound.rb); + + ngtcp2_dcid_copy(dest, src); + dest->bound_ts = ts; + ngtcp2_dcid_set_path(dest, path); + + ngtcp2_ringbuf_pop_front(&dtr->unused.rb); + + *pdest = dest; + + return 0; +} + +static int verify_stateless_reset(const ngtcp2_ringbuf *rb, + const ngtcp2_path *path, + const uint8_t *token) { + const ngtcp2_dcid *dcid; + size_t i, len = ngtcp2_ringbuf_len(rb); + + for (i = 0; i < len; ++i) { + dcid = ngtcp2_ringbuf_get(rb, i); + if (ngtcp2_dcid_verify_stateless_reset_token(dcid, path, token) == 0) { + return 0; + } + } + + return NGTCP2_ERR_INVALID_ARGUMENT; +} + +int ngtcp2_dcidtr_verify_stateless_reset(const ngtcp2_dcidtr *dtr, + const ngtcp2_path *path, + const uint8_t *token) { + int rv; + + rv = verify_stateless_reset(&dtr->retired.rb, path, token); + if (rv == 0) { + return 0; + } + + return verify_stateless_reset(&dtr->bound.rb, path, token); +} + +static int verify_token_uniqueness(const ngtcp2_ringbuf *rb, int *pfound, + uint64_t seq, const ngtcp2_cid *cid, + const uint8_t *token) { + const ngtcp2_dcid *dcid; + size_t i, len = ngtcp2_ringbuf_len(rb); + int rv; + + for (i = 0; i < len; ++i) { + dcid = ngtcp2_ringbuf_get(rb, i); + rv = ngtcp2_dcid_verify_uniqueness(dcid, seq, cid, token); + if (rv != 0) { + return NGTCP2_ERR_PROTO; + } + + if (ngtcp2_cid_eq(&dcid->cid, cid)) { + *pfound = 1; + } + } + + return 0; +} + +int ngtcp2_dcidtr_verify_token_uniqueness(const ngtcp2_dcidtr *dtr, int *pfound, + uint64_t seq, const ngtcp2_cid *cid, + const uint8_t *token) { + int rv; + + rv = verify_token_uniqueness(&dtr->bound.rb, pfound, seq, cid, token); + if (rv != 0) { + return rv; + } + + return verify_token_uniqueness(&dtr->unused.rb, pfound, seq, cid, token); +} + +static void remove_dcid_at(ngtcp2_ringbuf *rb, size_t at) { + const ngtcp2_dcid *src; + ngtcp2_dcid *dest; + + if (at == 0) { + ngtcp2_ringbuf_pop_front(rb); + return; + } + + if (at == ngtcp2_ringbuf_len(rb) - 1) { + ngtcp2_ringbuf_pop_back(rb); + return; + } + + src = ngtcp2_ringbuf_get(rb, ngtcp2_ringbuf_len(rb) - 1); + dest = ngtcp2_ringbuf_get(rb, at); + + ngtcp2_dcid_copy(dest, src); + ngtcp2_ringbuf_pop_back(rb); +} + +static int dcidtr_retire_dcid_prior_to(ngtcp2_dcidtr *dtr, ngtcp2_ringbuf *rb, + uint64_t seq, ngtcp2_dcidtr_cb on_retire, + void *user_data) { + size_t i; + const ngtcp2_dcid *dcid; + int rv; + + for (i = 0; i < ngtcp2_ringbuf_len(rb);) { + dcid = ngtcp2_ringbuf_get(rb, i); + if (dcid->seq >= seq) { + ++i; + continue; + } + + rv = dcidtr_on_retire(dtr, dcid, on_retire, user_data); + if (rv != 0) { + return rv; + } + + remove_dcid_at(rb, i); + } + + return 0; +} + +int ngtcp2_dcidtr_retire_inactive_dcid_prior_to(ngtcp2_dcidtr *dtr, + uint64_t seq, + ngtcp2_dcidtr_cb on_retire, + void *user_data) { + int rv; + + rv = + dcidtr_retire_dcid_prior_to(dtr, &dtr->bound.rb, seq, on_retire, user_data); + if (rv != 0) { + return rv; + } + + return dcidtr_retire_dcid_prior_to(dtr, &dtr->unused.rb, seq, on_retire, + user_data); +} + +int ngtcp2_dcidtr_retire_active_dcid(ngtcp2_dcidtr *dtr, + const ngtcp2_dcid *dcid, ngtcp2_tstamp ts, + ngtcp2_dcidtr_cb on_deactivate, + void *user_data) { + ngtcp2_ringbuf *rb = &dtr->retired.rb; + const ngtcp2_dcid *stale_dcid; + ngtcp2_dcid *dest; + int rv; + + assert(dcid->cid.datalen); + + if (ngtcp2_ringbuf_full(rb)) { + stale_dcid = ngtcp2_ringbuf_get(rb, 0); + rv = on_deactivate(stale_dcid, user_data); + if (rv != 0) { + return rv; + } + } + + dest = ngtcp2_ringbuf_push_back(rb); + ngtcp2_dcid_copy(dest, dcid); + dest->retired_ts = ts; + + return dcidtr_on_retire(dtr, dest, NULL, NULL); +} + +int ngtcp2_dcidtr_remove_stale_retired_dcid(ngtcp2_dcidtr *dtr, + ngtcp2_duration timeout, + ngtcp2_tstamp ts, + ngtcp2_dcidtr_cb on_deactivate, + void *user_data) { + ngtcp2_ringbuf *rb = &dtr->retired.rb; + const ngtcp2_dcid *dcid; + int rv; + + for (; ngtcp2_ringbuf_len(rb);) { + dcid = ngtcp2_ringbuf_get(rb, 0); + if (ngtcp2_tstamp_not_elapsed(dcid->retired_ts, timeout, ts)) { + break; + } + + rv = on_deactivate(dcid, user_data); + if (rv != 0) { + return rv; + } + + ngtcp2_ringbuf_pop_front(rb); + } + + return 0; +} + +int ngtcp2_dcidtr_pop_bound_dcid(ngtcp2_dcidtr *dtr, ngtcp2_dcid *dest, + const ngtcp2_path *path) { + const ngtcp2_dcid *src; + ngtcp2_ringbuf *rb = &dtr->bound.rb; + size_t len = ngtcp2_ringbuf_len(rb); + size_t i; + + for (i = 0; i < len; ++i) { + src = ngtcp2_ringbuf_get(rb, i); + if (ngtcp2_path_eq(&src->ps.path, path)) { + ngtcp2_dcid_copy(dest, src); + remove_dcid_at(rb, i); + + return 0; + } + } + + return NGTCP2_ERR_INVALID_ARGUMENT; +} + +int ngtcp2_dcidtr_retire_stale_bound_dcid(ngtcp2_dcidtr *dtr, + ngtcp2_duration timeout, + ngtcp2_tstamp ts, + ngtcp2_dcidtr_cb on_retire, + void *user_data) { + ngtcp2_ringbuf *rb = &dtr->bound.rb; + size_t i; + const ngtcp2_dcid *dcid; + int rv; + + for (i = 0; i < ngtcp2_ringbuf_len(rb);) { + dcid = ngtcp2_ringbuf_get(rb, i); + + assert(dcid->cid.datalen); + + if (ngtcp2_tstamp_not_elapsed(dcid->bound_ts, timeout, ts)) { + ++i; + continue; + } + + rv = dcidtr_on_retire(dtr, dcid, on_retire, user_data); + if (rv != 0) { + return rv; + } + + remove_dcid_at(rb, i); + } + + return 0; +} + +ngtcp2_tstamp ngtcp2_dcidtr_earliest_bound_ts(const ngtcp2_dcidtr *dtr) { + const ngtcp2_ringbuf *rb = &dtr->bound.rb; + size_t i, len = ngtcp2_ringbuf_len(rb); + ngtcp2_tstamp res = UINT64_MAX; + const ngtcp2_dcid *dcid; + + for (i = 0; i < len; ++i) { + dcid = ngtcp2_ringbuf_get(rb, i); + + assert(dcid->cid.datalen); + assert(dcid->bound_ts != UINT64_MAX); + + res = ngtcp2_min_uint64(res, dcid->bound_ts); + } + + return res; +} + +ngtcp2_tstamp ngtcp2_dcidtr_earliest_retired_ts(const ngtcp2_dcidtr *dtr) { + const ngtcp2_ringbuf *rb = &dtr->retired.rb; + const ngtcp2_dcid *dcid; + + if (ngtcp2_ringbuf_len(rb) == 0) { + return UINT64_MAX; + } + + dcid = ngtcp2_ringbuf_get(rb, 0); + + return dcid->retired_ts; +} + +void ngtcp2_dcidtr_push_unused(ngtcp2_dcidtr *dtr, uint64_t seq, + const ngtcp2_cid *cid, const uint8_t *token) { + ngtcp2_dcid *dcid = ngtcp2_ringbuf_push_back(&dtr->unused.rb); + + ngtcp2_dcid_init(dcid, seq, cid, token); +} + +void ngtcp2_dcidtr_pop_unused_cid_token(ngtcp2_dcidtr *dtr, ngtcp2_dcid *dest) { + ngtcp2_ringbuf *rb = &dtr->unused.rb; + const ngtcp2_dcid *src; + + assert(ngtcp2_ringbuf_len(rb)); + + src = ngtcp2_ringbuf_get(rb, 0); + + dest->flags = NGTCP2_DCID_FLAG_NONE; + ngtcp2_dcid_copy_cid_token(dest, src); + + ngtcp2_ringbuf_pop_front(rb); +} + +void ngtcp2_dcidtr_pop_unused(ngtcp2_dcidtr *dtr, ngtcp2_dcid *dest) { + ngtcp2_ringbuf *rb = &dtr->unused.rb; + const ngtcp2_dcid *src; + + assert(ngtcp2_ringbuf_len(rb)); + + src = ngtcp2_ringbuf_get(rb, 0); + + ngtcp2_dcid_copy(dest, src); + + ngtcp2_ringbuf_pop_front(rb); +} + +int ngtcp2_dcidtr_check_path_retired(const ngtcp2_dcidtr *dtr, + const ngtcp2_path *path) { + const ngtcp2_ringbuf *rb = &dtr->retired.rb; + size_t i, len = ngtcp2_ringbuf_len(rb); + const ngtcp2_dcid *dcid; + + for (i = 0; i < len; ++i) { + dcid = ngtcp2_ringbuf_get(rb, i); + if (ngtcp2_path_eq(&dcid->ps.path, path)) { + return 1; + } + } + + return 0; +} + +size_t ngtcp2_dcidtr_unused_len(const ngtcp2_dcidtr *dtr) { + return ngtcp2_ringbuf_len(&dtr->unused.rb); +} + +size_t ngtcp2_dcidtr_bound_len(const ngtcp2_dcidtr *dtr) { + return ngtcp2_ringbuf_len(&dtr->bound.rb); +} + +size_t ngtcp2_dcidtr_retired_len(const ngtcp2_dcidtr *dtr) { + return ngtcp2_ringbuf_len(&dtr->retired.rb); +} + +size_t ngtcp2_dcidtr_inactive_len(const ngtcp2_dcidtr *dtr) { + return ngtcp2_ringbuf_len(&dtr->unused.rb) + + ngtcp2_ringbuf_len(&dtr->bound.rb); +} + +int ngtcp2_dcidtr_unused_full(const ngtcp2_dcidtr *dtr) { + return ngtcp2_ringbuf_full(&dtr->unused.rb); +} + +int ngtcp2_dcidtr_unused_empty(const ngtcp2_dcidtr *dtr) { + return ngtcp2_ringbuf_len(&dtr->unused.rb) == 0; +} + +int ngtcp2_dcidtr_bound_full(const ngtcp2_dcidtr *dtr) { + return ngtcp2_ringbuf_full(&dtr->bound.rb); +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.h new file mode 100644 index 00000000000000..17942389b814d1 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_dcidtr.h @@ -0,0 +1,343 @@ +/* + * ngtcp2 + * + * Copyright (c) 2025 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef NGTCP2_DCIDTR_H +#define NGTCP2_DCIDTR_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* defined(HAVE_CONFIG_H) */ + +#include + +#include "ngtcp2_cid.h" +#include "ngtcp2_ringbuf.h" + +/* NGTCP2_DCIDTR_MAX_BOUND_DCID_SIZE is the maximum number of + Destination Connection ID which has been bound to a particular + path, but not yet used as primary path, and path validation is not + performed from the local endpoint. It must be the power of 2. */ +#define NGTCP2_DCIDTR_MAX_BOUND_DCID_SIZE 4 +/* NGTCP2_DCIDTR_MAX_UNUSED_DCID_SIZE is the maximum number of + Destination Connection ID the remote endpoint provides to store. + It must be the power of 2. */ +#define NGTCP2_DCIDTR_MAX_UNUSED_DCID_SIZE 8 +/* NGTCP2_DCIDTR_MAX_RETIRED_DCID_SIZE is the maximum number of + retired Destination Connection ID kept to catch in-flight packet on + a retired path. It must be the power of 2. */ +#define NGTCP2_DCIDTR_MAX_RETIRED_DCID_SIZE 2 + +ngtcp2_static_ringbuf_def(dcid_bound, NGTCP2_DCIDTR_MAX_BOUND_DCID_SIZE, + sizeof(ngtcp2_dcid)) +ngtcp2_static_ringbuf_def(dcid_unused, NGTCP2_DCIDTR_MAX_UNUSED_DCID_SIZE, + sizeof(ngtcp2_dcid)) +ngtcp2_static_ringbuf_def(dcid_retired, NGTCP2_DCIDTR_MAX_RETIRED_DCID_SIZE, + sizeof(ngtcp2_dcid)) + +/* + * ngtcp2_dcidtr stores unused, bound, and retired Destination + * Connection IDs. + */ +typedef struct ngtcp2_dcidtr { + /* unused is a set of unused Destination Connection ID received from + a remote endpoint. They are considered inactive. */ + ngtcp2_static_ringbuf_dcid_unused unused; + /* bound is a set of Destination Connection IDs which are bound to + particular paths. These paths are not validated yet. They are + considered inactive. */ + ngtcp2_static_ringbuf_dcid_bound bound; + /* retired is a set of Destination Connection ID retired by local + endpoint. Keep them in 3*PTO to catch packets in flight along + the old path. They are considered active. */ + ngtcp2_static_ringbuf_dcid_retired retired; + struct { + /* seqs contains sequence number of Destination Connection ID + whose retirement is not acknowledged by the remote endpoint + yet. */ + uint64_t seqs[NGTCP2_DCIDTR_MAX_UNUSED_DCID_SIZE * 2]; + /* len is the number of sequence numbers that seq contains. */ + size_t len; + } retire_unacked; +} ngtcp2_dcidtr; + +typedef int (*ngtcp2_dcidtr_cb)(const ngtcp2_dcid *dcid, void *user_data); + +/* + * ngtcp2_dcidtr_init initializes |dtr|. + */ +void ngtcp2_dcidtr_init(ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_track_retired_seq tracks the sequence number |seq| of + * unacknowledged retiring Destination Connection ID. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_CONNECTION_ID_LIMIT + * The number of unacknowledged retirement exceeds the limit. + */ +int ngtcp2_dcidtr_track_retired_seq(ngtcp2_dcidtr *dtr, uint64_t seq); + +/* + * ngtcp2_dcidtr_untrack_retired_seq deletes the sequence number |seq| + * of unacknowledged retiring Destination Connection ID. It is fine + * if such sequence number is not found. + */ +void ngtcp2_dcidtr_untrack_retired_seq(ngtcp2_dcidtr *dtr, uint64_t seq); + +/* + * ngtcp2_dcidtr_check_retired_seq_tracked returns nonzero if |seq| + * has already been tracked. + */ +int ngtcp2_dcidtr_check_retired_seq_tracked(const ngtcp2_dcidtr *dtr, + uint64_t seq); + +/* + * ngtcp2_dcidtr_find_bound_dcid returns the pointer to ngtcp2_dcid + * that bound to |path|. It returns NULL if there is no such + * ngtcp2_dcid. + */ +ngtcp2_dcid *ngtcp2_dcidtr_find_bound_dcid(const ngtcp2_dcidtr *dtr, + const ngtcp2_path *path); + +/* + * ngtcp2_dcidtr_bind_zerolen_dcid binds zero-length Destination + * Connection ID to |path|, and returns the pointer to the bound + * ngtcp2_dcid. + */ +ngtcp2_dcid *ngtcp2_dcidtr_bind_zerolen_dcid(ngtcp2_dcidtr *dtr, + const ngtcp2_path *path); + +/* + * ngtcp2_dcidtr_bind_dcid binds non-zero Destination Connection ID to + * |path|. |ts| is the current timestamp. The buffer space of bound + * Destination Connection ID is limited. If it is full, the earliest + * one is removed. |on_retire|, if specified, is called for the + * removed ngtcp2_dcid with |user_data|. This function assigns the + * pointer to bound ngtcp2_dcid to |*pdest|. + * + * This function returns 0 if it succeeds, or negative error code that + * |on_retire| returns. + */ +int ngtcp2_dcidtr_bind_dcid(ngtcp2_dcidtr *dtr, ngtcp2_dcid **pdest, + const ngtcp2_path *path, ngtcp2_tstamp ts, + ngtcp2_dcidtr_cb on_retire, void *user_data); + +/* + * ngtcp2_dcidtr_verify_stateless_reset verifies the stateless reset + * token |token| received from |path|. It returns 0 if it succeeds, + * or one of the following negative error codes: + * + * NGTCP2_ERR_INVALID_ARGUMENT + * There is no Destination Connection ID that matches the given + * |path| and |token|. + */ +int ngtcp2_dcidtr_verify_stateless_reset(const ngtcp2_dcidtr *dtr, + const ngtcp2_path *path, + const uint8_t *token); + +/* + * ngtcp2_dcidtr_verify_token_uniqueness verifies that the uniqueness + * of the combination of |seq|, |cid|, and |token| against the exiting + * Destination Connection IDs. That is: + * + * - If they do not share the same seq, then their Connection IDs must + * be different. + * + * - If they share the same seq, then their Connection IDs and tokens + * must be the same. + * + * If this function succeeds, and there is Destination Connection ID + * which shares |seq|, |cid|, and |token|, |*pfound| is set to + * nonzero. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_PROTO + * The given combination of values does not satisfy the above + * conditions. + */ +int ngtcp2_dcidtr_verify_token_uniqueness(const ngtcp2_dcidtr *dtr, int *pfound, + uint64_t seq, const ngtcp2_cid *cid, + const uint8_t *token); + +/* + * ngtcp2_dcidtr_retire_inactive_dcid_prior_to retires inactive + * Destination Connection IDs (unused or bound) whose seq is less than + * |seq|. For each retired ngtcp2_dcid, |on_retire|, if specified, is + * called with |user_data|. + * + * This function returns 0 if it succeeds, or negative error code that + * |on_retire| returns. + */ +int ngtcp2_dcidtr_retire_inactive_dcid_prior_to(ngtcp2_dcidtr *dtr, + uint64_t seq, + ngtcp2_dcidtr_cb on_retire, + void *user_data); + +/* + * ngtcp2_dcidtr_retire_active_dcid adds an active |dcid| to the + * retired Destination Connection ID buffer. The buffer space of + * retired Destination Connection ID is limited. If it is full, the + * earliest one is removed. |on_deactivate| is called for the removed + * ngtcp2_dcid with |user_data|. + * + * This function returns 0 if it succeeds, or negative error code that + * |on_deactivate| returns. + */ +int ngtcp2_dcidtr_retire_active_dcid(ngtcp2_dcidtr *dtr, + const ngtcp2_dcid *dcid, ngtcp2_tstamp ts, + ngtcp2_dcidtr_cb on_deactivate, + void *user_data); + +/* + * ngtcp2_dcidtr_retire_stale_bound_dcid retires stale bound + * Destination Connection ID. For each retired ngtcp2_dcid, + * |on_retire|, if specified, is called with |user_data|. + */ +int ngtcp2_dcidtr_retire_stale_bound_dcid(ngtcp2_dcidtr *dtr, + ngtcp2_duration timeout, + ngtcp2_tstamp ts, + ngtcp2_dcidtr_cb on_retire, + void *user_data); + +/* + * ngtcp2_dcidtr_remove_stale_retired_dcid removes stale retired + * Destination Connection ID. For each removed ngtcp2_dcid, + * |on_deactivate| is called with |user_data|. + * + * This function returns 0 if it succeeds, or negative error code that + * |on_deactivate| returns. + */ +int ngtcp2_dcidtr_remove_stale_retired_dcid(ngtcp2_dcidtr *dtr, + ngtcp2_duration timeout, + ngtcp2_tstamp ts, + ngtcp2_dcidtr_cb on_deactivate, + void *user_data); + +/* + * ngtcp2_dcidtr_pop_bound_dcid removes Destination Connection ID that + * is bound to |path|, and copies it into the object pointed by + * |dest|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_INVALID_ARGUMENT + * No ngtcp2_dcid bound to |path| found. + */ +int ngtcp2_dcidtr_pop_bound_dcid(ngtcp2_dcidtr *dtr, ngtcp2_dcid *dest, + const ngtcp2_path *path); + +/* + * ngtcp2_dcidtr_earliest_bound_ts returns earliest timestamp when a + * Destination Connection ID is bound. If there is no bound + * Destination Connection ID, this function returns UINT64_MAX. + */ +ngtcp2_tstamp ngtcp2_dcidtr_earliest_bound_ts(const ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_earliest_retired_ts returns earliest timestamp when a + * Destination Connection ID is retired. If there is no retired + * Destination Connection ID, this function returns UINT64_MAX. + */ +ngtcp2_tstamp ngtcp2_dcidtr_earliest_retired_ts(const ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_push_unused adds new Destination Connection ID to the + * unused buffer. |seq| is its sequence number, |cid| is its + * Connection ID, and |token| is its stateless reset token. If the + * buffer space is full, the earliest ngtcp2_dcid is removed. + */ +void ngtcp2_dcidtr_push_unused(ngtcp2_dcidtr *dtr, uint64_t seq, + const ngtcp2_cid *cid, const uint8_t *token); + +/* + * ngtcp2_dcidtr_pop_unused_cid_token removes an unused Destination + * Connection ID, and copies it into the object pointed by |dcid| with + * ngtcp2_dcid_copy_cid_token. This function assumes that there is at + * least one unused Destination Connection ID. + */ +void ngtcp2_dcidtr_pop_unused_cid_token(ngtcp2_dcidtr *dtr, ngtcp2_dcid *dcid); + +/* + * ngtcp2_dcidtr_pop_unused removes an unused Destination Connection + * ID, and copies it into the object pointed by |dcid| with + * ngtcp2_dcid_copy. This function assumes that there is at least one + * unused Destination Connection ID. + */ +void ngtcp2_dcidtr_pop_unused(ngtcp2_dcidtr *dtr, ngtcp2_dcid *dcid); + +/* + * ngtcp2_dcidtr_check_path_retired returns nonzero if |path| is + * included in retired Destination Connection IDs. + */ +int ngtcp2_dcidtr_check_path_retired(const ngtcp2_dcidtr *dtr, + const ngtcp2_path *path); + +/* + * ngtcp2_dcidtr_unused_len returns the number of unused Destination + * Connection ID. + */ +size_t ngtcp2_dcidtr_unused_len(const ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_bound_len returns the number of bound Destination + * Connection ID. + */ +size_t ngtcp2_dcidtr_bound_len(const ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_retired_len returns the number of retired Destination + * Connection ID. + */ +size_t ngtcp2_dcidtr_retired_len(const ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_inactive_len returns the number of unused and bound + * Destination Connection ID. + */ +size_t ngtcp2_dcidtr_inactive_len(const ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_unused_full returns nonzero if the buffer of unused + * Destination Connection ID is full. + */ +int ngtcp2_dcidtr_unused_full(const ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_unused_empty returns nonzero if the buffer of unused + * Destination Connection ID is empty. + */ +int ngtcp2_dcidtr_unused_empty(const ngtcp2_dcidtr *dtr); + +/* + * ngtcp2_dcidtr_bound_full returns nonzero if the buffer of bound + * Destination Connection ID is full. + */ +int ngtcp2_dcidtr_bound_full(const ngtcp2_dcidtr *dtr); + +#endif /* NGTCP2_DCIDTR_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c index 6a8a22c3f0d010..0f6b06a788d174 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c @@ -29,17 +29,6 @@ ngtcp2_objalloc_def(frame_chain, ngtcp2_frame_chain, oplent) -int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem) { - *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain)); - if (*pfrc == NULL) { - return NGTCP2_ERR_NOMEM; - } - - ngtcp2_frame_chain_init(*pfrc); - - return 0; -} - int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc, ngtcp2_objalloc *objalloc) { *pfrc = ngtcp2_objalloc_frame_chain_get(objalloc); @@ -83,13 +72,13 @@ int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc, size_t tokenlen, ngtcp2_objalloc *objalloc, const ngtcp2_mem *mem) { - size_t avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token); int rv; uint8_t *p; ngtcp2_frame *fr; - if (tokenlen > avail) { - rv = ngtcp2_frame_chain_extralen_new(pfrc, tokenlen - avail, mem); + if (tokenlen > NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES) { + rv = ngtcp2_frame_chain_extralen_new( + pfrc, tokenlen - NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES, mem); } else { rv = ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); } @@ -144,8 +133,7 @@ void ngtcp2_frame_chain_objalloc_del(ngtcp2_frame_chain *frc, break; case NGTCP2_FRAME_NEW_TOKEN: - if (frc->fr.new_token.tokenlen > - sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token)) { + if (frc->fr.new_token.tokenlen > NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES) { ngtcp2_frame_chain_del(frc, mem); return; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h index e5b6779c0f03c2..e7b33632529cd4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h @@ -95,28 +95,15 @@ int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b, #define NGTCP2_MAX_STREAM_DATACNT 256 /* - * ngtcp2_frame_chain_new allocates ngtcp2_frame_chain object and - * assigns its pointer to |*pfrc|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem); - -/* - * ngtcp2_frame_chain_objalloc_new behaves like - * ngtcp2_frame_chain_new, but it uses |objalloc| to allocate the object. + * ngtcp2_frame_chain_objalloc_new allocates ngtcp2_frame_chain using + * |objalloc|. */ int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc, ngtcp2_objalloc *objalloc); /* - * ngtcp2_frame_chain_extralen_new works like ngtcp2_frame_chain_new, - * but it allocates extra memory |extralen| in order to extend - * ngtcp2_frame. + * ngtcp2_frame_chain_extralen_new allocates ngtcp2_frame_chain + * followed by |extralen| bytes. */ int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen, const ngtcp2_mem *mem); @@ -134,12 +121,18 @@ int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen, #define NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES \ (NGTCP2_FRAME_CHAIN_STREAM_AVAIL / sizeof(ngtcp2_vec) + 1) +/* NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES is the length of a token that + changes allocation method. If the length is more than this value, + ngtcp2_frame_chain is allocated without ngtcp2_objalloc. + Otherwise, it is allocated using ngtcp2_objalloc. */ +#define NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES \ + (sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token)) + /* - * ngtcp2_frame_chain_stream_datacnt_objalloc_new works like - * ngtcp2_frame_chain_new, but it allocates enough data to store - * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_stream - * object. If no additional space is required, in other words, - * |datacnt| <= NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES, + * ngtcp2_frame_chain_stream_datacnt_objalloc_new allocates enough + * data to store additional |datacnt| - 1 ngtcp2_vec object after + * ngtcp2_stream object. If no additional space is required, in other + * words, |datacnt| <= NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES, * ngtcp2_frame_chain_objalloc_new is called internally. Otherwise, * ngtcp2_frame_chain_extralen_new is used and objalloc is not used. * Therefore, it is important to call ngtcp2_frame_chain_objalloc_del @@ -150,6 +143,13 @@ int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, ngtcp2_objalloc *objalloc, const ngtcp2_mem *mem); +/* + * ngtcp2_frame_chain_new_token_objalloc_new allocates enough space to + * store the given token. If |tokenlen| <= + * NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES, ngtcp2_frame_chain_objalloc_new + * is called internally. Otherwise, ngtcp2_frame_chain_extralen_new + * is used, and objalloc is not used. + */ int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc, const uint8_t *token, size_t tokenlen, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c index 3bfa398480c382..d04b9634c20528 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c @@ -35,7 +35,9 @@ void ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem) { } static int gaptr_gap_init(ngtcp2_gaptr *gaptr) { - ngtcp2_range range = {0, UINT64_MAX}; + ngtcp2_range range = { + .end = UINT64_MAX, + }; return ngtcp2_ksl_insert(&gaptr->gap, NULL, &range, NULL); } @@ -50,7 +52,11 @@ void ngtcp2_gaptr_free(ngtcp2_gaptr *gaptr) { int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, uint64_t datalen) { int rv; - ngtcp2_range k, m, l, r, q = {offset, offset + datalen}; + ngtcp2_range k, m, l, r; + ngtcp2_range q = { + .begin = offset, + .end = offset + datalen, + }; ngtcp2_ksl_it it; if (ngtcp2_ksl_len(&gaptr->gap) == 0) { @@ -110,11 +116,16 @@ uint64_t ngtcp2_gaptr_first_gap_offset(const ngtcp2_gaptr *gaptr) { ngtcp2_range ngtcp2_gaptr_get_first_gap_after(const ngtcp2_gaptr *gaptr, uint64_t offset) { - ngtcp2_range q = {offset, offset + 1}; + ngtcp2_range q = { + .begin = offset, + .end = offset + 1, + }; ngtcp2_ksl_it it; if (ngtcp2_ksl_len(&gaptr->gap) == 0) { - ngtcp2_range r = {0, UINT64_MAX}; + ngtcp2_range r = { + .end = UINT64_MAX, + }; return r; } @@ -128,7 +139,10 @@ ngtcp2_range ngtcp2_gaptr_get_first_gap_after(const ngtcp2_gaptr *gaptr, int ngtcp2_gaptr_is_pushed(const ngtcp2_gaptr *gaptr, uint64_t offset, uint64_t datalen) { - ngtcp2_range q = {offset, offset + datalen}; + ngtcp2_range q = { + .begin = offset, + .end = offset + datalen, + }; ngtcp2_ksl_it it; ngtcp2_range m; @@ -138,6 +152,9 @@ int ngtcp2_gaptr_is_pushed(const ngtcp2_gaptr *gaptr, uint64_t offset, it = ngtcp2_ksl_lower_bound_search(&gaptr->gap, &q, ngtcp2_ksl_range_exclusive_search); + + assert(!ngtcp2_ksl_it_end(&it)); + m = ngtcp2_range_intersect(&q, (ngtcp2_range *)ngtcp2_ksl_it_key(&it)); return ngtcp2_range_len(&m) == 0; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c index 5e74f647241816..22c131a1ac677c 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c @@ -33,7 +33,7 @@ #include "ngtcp2_mem.h" #include "ngtcp2_range.h" -static ngtcp2_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}}; +static ngtcp2_ksl_blk null_blk; ngtcp2_objalloc_def(ksl_blk, ngtcp2_ksl_blk, oplent) diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c index 0b66fceac6c993..5e4726e63ff7ef 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c @@ -119,7 +119,11 @@ void ngtcp2_map_print_distance(const ngtcp2_map *map) { static int insert(ngtcp2_map_bucket *table, size_t hashbits, ngtcp2_map_key_type key, void *data) { size_t idx = hash(key, hashbits); - ngtcp2_map_bucket b = {0, key, data}, *bkt; + ngtcp2_map_bucket b = { + .key = key, + .data = data, + }; + ngtcp2_map_bucket *bkt; size_t mask = (1u << hashbits) - 1; for (;;) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c index d30e1f986e97d3..48f430f474f126 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c @@ -51,8 +51,12 @@ static void *default_realloc(void *ptr, size_t size, void *user_data) { return realloc(ptr, size); } -static const ngtcp2_mem mem_default = {NULL, default_malloc, default_free, - default_calloc, default_realloc}; +static const ngtcp2_mem mem_default = { + .malloc = default_malloc, + .free = default_free, + .calloc = default_calloc, + .realloc = default_realloc, +}; const ngtcp2_mem *ngtcp2_mem_default(void) { return &mem_default; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c index 5c82e1bd503f98..d78978492ca8e7 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c @@ -145,8 +145,7 @@ int ngtcp2_pkt_decode_version_cid(ngtcp2_version_cid *dest, const uint8_t *data, void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, - int64_t pkt_num, size_t pkt_numlen, uint32_t version, - size_t len) { + int64_t pkt_num, size_t pkt_numlen, uint32_t version) { hd->flags = flags; hd->type = type; @@ -167,7 +166,7 @@ void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type, hd->tokenlen = 0; hd->pkt_numlen = pkt_numlen; hd->version = version; - hd->len = len; + hd->len = 0; } ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, @@ -2285,8 +2284,7 @@ ngtcp2_ssize ngtcp2_pkt_write_retry( } ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, NGTCP2_PKT_RETRY, dcid, - scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1, version, - /* len = */ 0); + scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1, version); pseudo_retrylen = ngtcp2_pkt_encode_pseudo_retry(pseudo_retry, sizeof(pseudo_retry), &hd, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h index 86ebecef7bc870..756076e7a7f258 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h @@ -57,6 +57,10 @@ #define NGTCP2_STREAM_LEN_BIT 0x02 #define NGTCP2_STREAM_OFF_BIT 0x04 +/* NGTCP2_MIN_QUIC_PKTLEN is the minimum length of a valid QUIC + packet. */ +#define NGTCP2_MIN_QUIC_PKTLEN 21 + /* NGTCP2_STREAM_OVERHEAD is the maximum number of bytes required other than payload for STREAM frame. That is from type field to the beginning of the payload. */ @@ -407,13 +411,11 @@ void ngtcp2_pkt_chain_del(ngtcp2_pkt_chain *pc, const ngtcp2_mem *mem); * |dcid| and/or |scid| is NULL, Destination Connection ID and/or * Source Connection ID of |hd| is empty respectively. |pkt_numlen| * is the number of bytes used to encode |pkt_num| and either 1, 2, or - * 4. |version| is QUIC version for long header. |len| is the length - * field of Initial, 0RTT, and Handshake packets. + * 4. |version| is QUIC version for long header. */ void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, - int64_t pkt_num, size_t pkt_numlen, uint32_t version, - size_t len); + int64_t pkt_num, size_t pkt_numlen, uint32_t version); /* * ngtcp2_pkt_encode_hd_long encodes |hd| as QUIC long header into diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c index 19e3e3e36aa5e6..162bed00156755 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c @@ -161,19 +161,3 @@ void ngtcp2_pq_remove(ngtcp2_pq *pq, ngtcp2_pq_entry *item) { int ngtcp2_pq_empty(const ngtcp2_pq *pq) { return pq->length == 0; } size_t ngtcp2_pq_size(const ngtcp2_pq *pq) { return pq->length; } - -int ngtcp2_pq_each(const ngtcp2_pq *pq, ngtcp2_pq_item_cb fun, void *arg) { - size_t i; - - if (pq->length == 0) { - return 0; - } - - for (i = 0; i < pq->length; ++i) { - if ((*fun)(pq->q[i], arg)) { - return 1; - } - } - - return 0; -} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h index 84961c9143978c..aa195a9f7baee3 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h @@ -109,17 +109,6 @@ int ngtcp2_pq_empty(const ngtcp2_pq *pq); */ size_t ngtcp2_pq_size(const ngtcp2_pq *pq); -typedef int (*ngtcp2_pq_item_cb)(ngtcp2_pq_entry *item, void *arg); - -/* - * ngtcp2_pq_each applies |fun| to each item in |pq|. The |arg| is - * passed as arg parameter to callback function. This function must - * not change the ordering key. If the return value from callback is - * nonzero, this function returns 1 immediately without iterating - * remaining items. Otherwise this function returns 0. - */ -int ngtcp2_pq_each(const ngtcp2_pq *pq, ngtcp2_pq_item_cb fun, void *arg); - /* * ngtcp2_pq_remove removes |item| from |pq|. |pq| must contain * |item| otherwise the behavior is undefined. diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c index e4fee94eb558d3..471f84c76440fe 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c @@ -170,3 +170,10 @@ void ngtcp2_pv_cancel_expired_timer(ngtcp2_pv *pv, ngtcp2_tstamp ts) { pv->flags |= NGTCP2_PV_FLAG_CANCEL_TIMER; } + +void ngtcp2_pv_set_fallback(ngtcp2_pv *pv, const ngtcp2_dcid *dcid, + ngtcp2_duration pto) { + pv->flags |= NGTCP2_PV_FLAG_FALLBACK_PRESENT; + ngtcp2_dcid_copy(&pv->fallback_dcid, dcid); + pv->fallback_pto = pto; +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h index e9573da497bee4..2d07e41648db2e 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h @@ -71,11 +71,13 @@ void ngtcp2_pv_entry_init(ngtcp2_pv_entry *pvent, const uint8_t *data, /* NGTCP2_PV_FLAG_CANCEL_TIMER indicates that the expiry timer is cancelled. */ #define NGTCP2_PV_FLAG_CANCEL_TIMER 0x02u -/* NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE indicates that fallback DCID is - available in ngtcp2_pv. If path validation fails, fallback to the - fallback DCID. If path validation succeeds, fallback DCID is - retired if it does not equal to the current DCID. */ -#define NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE 0x04u +/* NGTCP2_PV_FLAG_FALLBACK_PRESENT indicates that a fallback + Destination Connection ID and PTO are available in ngtcp2_pv. If + path validation fails, then fallback to them. If path validation + succeeds, the fallback Destination Connection ID is retired if it + is not zero length, and does not equal to the current Destination + Connection ID. */ +#define NGTCP2_PV_FLAG_FALLBACK_PRESENT 0x04u /* NGTCP2_PV_FLAG_PREFERRED_ADDR indicates that client is migrating to server's preferred address. This flag is only used by client. */ #define NGTCP2_PV_FLAG_PREFERRED_ADDR 0x10u @@ -191,4 +193,10 @@ ngtcp2_tstamp ngtcp2_pv_next_expiry(ngtcp2_pv *pv); */ void ngtcp2_pv_cancel_expired_timer(ngtcp2_pv *pv, ngtcp2_tstamp ts); +/* + * ngtcp2_pv_set_fallback sets |dcid| and |pto| as fallback. + */ +void ngtcp2_pv_set_fallback(ngtcp2_pv *pv, const ngtcp2_dcid *dcid, + ngtcp2_duration pto); + #endif /* !defined(NGTCP2_PV_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c index 7bbefc0175c595..e89891532936e8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c @@ -32,7 +32,7 @@ void ngtcp2_range_init(ngtcp2_range *r, uint64_t begin, uint64_t end) { ngtcp2_range ngtcp2_range_intersect(const ngtcp2_range *a, const ngtcp2_range *b) { - ngtcp2_range r = {0, 0}; + ngtcp2_range r = {0}; uint64_t begin = ngtcp2_max_uint64(a->begin, b->begin); uint64_t end = ngtcp2_min_uint64(a->end, b->end); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c index 41446739bf699d..353afca4d48fb5 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c @@ -122,4 +122,6 @@ void *ngtcp2_ringbuf_get(const ngtcp2_ringbuf *rb, size_t offset) { return &rb->buf[offset * rb->size]; } -int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb) { return rb->len == rb->mask + 1; } +int ngtcp2_ringbuf_full(const ngtcp2_ringbuf *rb) { + return rb->len == rb->mask + 1; +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h index 6953ea6278f88d..d490524805b1e9 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h @@ -113,7 +113,7 @@ void *ngtcp2_ringbuf_get(const ngtcp2_ringbuf *rb, size_t offset); #define ngtcp2_ringbuf_len(RB) ((RB)->len) /* ngtcp2_ringbuf_full returns nonzero if |rb| is full. */ -int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb); +int ngtcp2_ringbuf_full(const ngtcp2_ringbuf *rb); /* ngtcp2_static_ringbuf_def defines ngtcp2_ringbuf struct wrapper which uses a statically allocated buffer. ngtcp2_ringbuf_free diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c index ce6c2113ddf1ce..853f1d650eaf54 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c @@ -122,7 +122,10 @@ static int rob_write_data(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, size_t n; int rv; ngtcp2_rob_data *d; - ngtcp2_range range = {offset, offset + len}; + ngtcp2_range range = { + .begin = offset, + .end = offset + len, + }; ngtcp2_ksl_it it; for (it = ngtcp2_ksl_lower_bound_search(&rob->dataksl, &range, @@ -163,7 +166,11 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, size_t datalen) { int rv; ngtcp2_rob_gap *g; - ngtcp2_range m, l, r, q = {offset, offset + datalen}; + ngtcp2_range m, l, r; + ngtcp2_range q = { + .begin = offset, + .end = offset + datalen, + }; ngtcp2_ksl_it it; it = ngtcp2_ksl_lower_bound_search(&rob->gapksl, &q, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c index 89c89acdc265a2..181691f3e69401 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c @@ -46,6 +46,11 @@ void ngtcp2_rs_init(ngtcp2_rs *rs) { } void ngtcp2_rst_init(ngtcp2_rst *rst) { + rst->last_seq = -1; + ngtcp2_rst_reset(rst); +} + +void ngtcp2_rst_reset(ngtcp2_rst *rst) { ngtcp2_rs_init(&rst->rs); rst->delivered = 0; rst->delivered_ts = 0; @@ -53,7 +58,7 @@ void ngtcp2_rst_init(ngtcp2_rst *rst) { rst->app_limited = 0; rst->is_cwnd_limited = 0; rst->lost = 0; - rst->last_seq = -1; + rst->valid_after_seq = rst->last_seq; } void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, @@ -108,6 +113,10 @@ void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent, ngtcp2_tstamp ts) { ngtcp2_rs *rs = &rst->rs; + if (ent->rst.end_seq <= rst->valid_after_seq) { + return; + } + rst->delivered += ent->pktlen; rst->delivered_ts = ts; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h index 95616eee97d99f..c2580306cc59fe 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h @@ -73,11 +73,17 @@ typedef struct ngtcp2_rst { across all packet number spaces, we can replace this with a packet number. */ int64_t last_seq; + /* valid_after_seq is the sequence number, and ignore a packet if + the sequence number of the packet is less than or equal to this + number. */ + int64_t valid_after_seq; int is_cwnd_limited; } ngtcp2_rst; void ngtcp2_rst_init(ngtcp2_rst *rst); +void ngtcp2_rst_reset(ngtcp2_rst *rst); + void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, const ngtcp2_conn_stat *cstat); void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c index 090355f5dbc938..f7a7f5724b7ac3 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -101,7 +101,6 @@ void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_rst *rst, ngtcp2_cc *cc, rtb->probe_pkt_left = 0; rtb->cc_pkt_num = cc_pkt_num; rtb->cc_bytes_in_flight = 0; - rtb->persistent_congestion_start_ts = UINT64_MAX; rtb->num_lost_pkts = 0; rtb->num_lost_pmtud_pkts = 0; } @@ -672,8 +671,8 @@ static int process_acked_pkt(ngtcp2_rtb_entry *ent, ngtcp2_conn *conn, break; case NGTCP2_FRAME_RETIRE_CONNECTION_ID: - ngtcp2_conn_untrack_retired_dcid_seq(conn, - frc->fr.retire_connection_id.seq); + ngtcp2_dcidtr_untrack_retired_seq(&conn->dcid.dtr, + frc->fr.retire_connection_id.seq); break; case NGTCP2_FRAME_NEW_CONNECTION_ID: assert(conn->scid.num_in_flight); @@ -734,11 +733,11 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, if ((ecn_acked && fr->type == NGTCP2_FRAME_ACK) || (fr->type == NGTCP2_FRAME_ACK_ECN && - (pktns->rx.ecn.ack.ect0 > fr->ecn.ect0 || - pktns->rx.ecn.ack.ect1 > fr->ecn.ect1 || - pktns->rx.ecn.ack.ce > fr->ecn.ce || - (fr->ecn.ect0 - pktns->rx.ecn.ack.ect0) + - (fr->ecn.ce - pktns->rx.ecn.ack.ce) < + (pktns->acktr.ecn.ack.ect0 > fr->ecn.ect0 || + pktns->acktr.ecn.ack.ect1 > fr->ecn.ect1 || + pktns->acktr.ecn.ack.ce > fr->ecn.ce || + (fr->ecn.ect0 - pktns->acktr.ecn.ack.ect0) + + (fr->ecn.ce - pktns->acktr.ecn.ack.ce) < ecn_acked || fr->ecn.ect0 > pktns->tx.ecn.ect0 || fr->ecn.ect1))) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, @@ -755,13 +754,13 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, if (fr->type == NGTCP2_FRAME_ACK_ECN) { if (cc->congestion_event && largest_pkt_sent_ts != UINT64_MAX && - fr->ecn.ce > pktns->rx.ecn.ack.ce) { + fr->ecn.ce > pktns->acktr.ecn.ack.ce) { cc->congestion_event(cc, cstat, largest_pkt_sent_ts, 0, ts); } - pktns->rx.ecn.ack.ect0 = fr->ecn.ect0; - pktns->rx.ecn.ack.ect1 = fr->ecn.ect1; - pktns->rx.ecn.ack.ce = fr->ecn.ce; + pktns->acktr.ecn.ack.ect0 = fr->ecn.ect0; + pktns->acktr.ecn.ack.ect1 = fr->ecn.ect1; + pktns->acktr.ecn.ack.ce = fr->ecn.ce; } } @@ -1052,7 +1051,7 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, max_ack_delay) * NGTCP2_PERSISTENT_CONGESTION_THRESHOLD; - start_ts = ngtcp2_max_uint64(rtb->persistent_congestion_start_ts, + start_ts = ngtcp2_max_uint64(conn->handshake_confirmed_ts, cstat->first_rtt_sample_ts); for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h index 2ef772b2e14f4b..3a9397eac5bb6f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h @@ -184,10 +184,6 @@ typedef struct ngtcp2_rtb { count a packet whose packet number is greater than or equals to cc_pkt_num. */ uint64_t cc_bytes_in_flight; - /* persistent_congestion_start_ts is the time when persistent - congestion evaluation is started. It happens roughly after - handshake is confirmed. */ - ngtcp2_tstamp persistent_congestion_start_ts; /* num_lost_pkts is the number entries in ents which has NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED flag set. */ size_t num_lost_pkts; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.c index dda59c48858185..ca517532e3a695 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.c @@ -410,7 +410,7 @@ static int decode_varint(uint64_t *pdest, const uint8_t **pp, } len = ngtcp2_get_uvarintlen(p); - if ((uint64_t)(end - p) < len) { + if ((size_t)(end - p) < len) { return -1; } @@ -530,8 +530,11 @@ int ngtcp2_transport_params_decode_versioned(int transport_params_version, params->active_connection_id_limit = NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; - p = data; - end = data + datalen; + p = end = data; + + if (datalen) { + end += datalen; + } for (; (size_t)(end - p) >= 2;) { if (decode_varint(¶m_type, &p, end) != 0) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c index 0b9c92d47d7d88..dbca8691d64888 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c @@ -35,33 +35,6 @@ ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len) { return vec; } -int ngtcp2_vec_new(ngtcp2_vec **pvec, const uint8_t *data, size_t datalen, - const ngtcp2_mem *mem) { - size_t len; - uint8_t *p; - - len = sizeof(ngtcp2_vec) + datalen; - - *pvec = ngtcp2_mem_malloc(mem, len); - if (*pvec == NULL) { - return NGTCP2_ERR_NOMEM; - } - - p = (uint8_t *)(*pvec) + sizeof(ngtcp2_vec); - (*pvec)->base = p; - (*pvec)->len = datalen; - - if (datalen) { - /* p = */ ngtcp2_cpymem(p, data, datalen); - } - - return 0; -} - -void ngtcp2_vec_del(ngtcp2_vec *vec, const ngtcp2_mem *mem) { - ngtcp2_mem_free(mem, vec); -} - uint64_t ngtcp2_vec_len(const ngtcp2_vec *vec, size_t n) { size_t i; size_t res = 0; @@ -225,13 +198,14 @@ size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t dstcnt, continue; } - dst[j] = src[i]; - - if (dst[j].len > left) { + if (src[i].len > left) { + dst[j].base = src[i].base; dst[j].len = left; + return j + 1; } + dst[j] = src[i]; left -= dst[j].len; ++i; ++j; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h index f7611efcb7d6ce..55e735d164edcb 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h @@ -46,22 +46,6 @@ */ ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len); -/* - * ngtcp2_vec_new allocates and initializes |*pvec| with given |data| - * of length |datalen|. This function allocates memory for |*pvec| - * and the given data with a single allocation, and the contents - * pointed by |data| is copied into the allocated memory space. To - * free the allocated memory, call ngtcp2_vec_del. - */ -int ngtcp2_vec_new(ngtcp2_vec **pvec, const uint8_t *data, size_t datalen, - const ngtcp2_mem *mem); - -/* - * ngtcp2_vec_del frees the memory allocated by |vec| which is - * allocated and initialized by ngtcp2_vec_new. - */ -void ngtcp2_vec_del(ngtcp2_vec *vec, const ngtcp2_mem *mem); - /* * ngtcp2_vec_len returns the sum of length in |vec| of |n| elements. */