aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2025-03-10 19:42:22 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2025-03-10 19:56:23 +0300
commitfc6cd7d48282fba73b60215b3fd31fc0a8825982 (patch)
treebcb36b06098e700fd726b6b19c89e6fae7d429e2
parent21c1cc59ef7d0910313ef39ca737c78380ef3ec3 (diff)
downloadydb-fc6cd7d48282fba73b60215b3fd31fc0a8825982.tar.gz
Update contrib/libs/ngtcp2 to 1.11.0
commit_hash:3beea54841aa142a4af33f802d5bdb7d6010b68d
-rw-r--r--contrib/libs/ngtcp2/.yandex_meta/devtools.copyrights.report12
-rw-r--r--contrib/libs/ngtcp2/.yandex_meta/devtools.licenses.report4
-rw-r--r--contrib/libs/ngtcp2/.yandex_meta/licenses.list.txt4
-rw-r--r--contrib/libs/ngtcp2/.yandex_meta/override.nix4
-rw-r--r--contrib/libs/ngtcp2/README.rst10
-rw-r--r--contrib/libs/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h4
-rw-r--r--contrib/libs/ngtcp2/lib/includes/ngtcp2/ngtcp2.h8
-rw-r--r--contrib/libs/ngtcp2/lib/includes/ngtcp2/version.h4
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_acktr.c114
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_acktr.h44
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_addr.c23
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_addr.h30
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_bbr.c79
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_bbr.h1
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_cc.c6
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_cid.c4
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_cid.h13
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_conn.c1288
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_conn.h121
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_dcidtr.c497
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_dcidtr.h343
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_frame_chain.c20
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_frame_chain.h44
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_gaptr.c27
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_ksl.c2
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_map.c6
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_mem.c8
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_pkt.c8
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_pkt.h10
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_pq.c16
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_pq.h11
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_pv.c7
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_pv.h18
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_range.c2
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_ringbuf.c4
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_ringbuf.h2
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_rob.c11
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_rst.c11
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_rst.h6
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_rtb.c25
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_rtb.h4
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_transport_params.c9
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_vec.c34
-rw-r--r--contrib/libs/ngtcp2/lib/ngtcp2_vec.h16
-rw-r--r--contrib/libs/ngtcp2/ya.make5
45 files changed, 1722 insertions, 1197 deletions
diff --git a/contrib/libs/ngtcp2/.yandex_meta/devtools.copyrights.report b/contrib/libs/ngtcp2/.yandex_meta/devtools.copyrights.report
index 05464e0456..5199463198 100644
--- a/contrib/libs/ngtcp2/.yandex_meta/devtools.copyrights.report
+++ b/contrib/libs/ngtcp2/.yandex_meta/devtools.copyrights.report
@@ -219,6 +219,18 @@ BELONGS ya.make
lib/ngtcp2_pq.c [4:5]
lib/ngtcp2_pq.h [4:5]
+KEEP COPYRIGHT_SERVICE_LABEL d6540bc8665ef99ad871e3a0a3847f50
+BELONGS ya.make
+ License text:
+ * Copyright (c) 2025 ngtcp2 contributors
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ lib/ngtcp2_dcidtr.c [4:4]
+ lib/ngtcp2_dcidtr.h [4:4]
+
KEEP COPYRIGHT_SERVICE_LABEL d8ca50c11a8cd311a31e6462c4b42555
BELONGS ya.make
License text:
diff --git a/contrib/libs/ngtcp2/.yandex_meta/devtools.licenses.report b/contrib/libs/ngtcp2/.yandex_meta/devtools.licenses.report
index 09b80ceac3..ccf2fd0140 100644
--- a/contrib/libs/ngtcp2/.yandex_meta/devtools.licenses.report
+++ b/contrib/libs/ngtcp2/.yandex_meta/devtools.licenses.report
@@ -87,7 +87,7 @@ BELONGS ya.make
KEEP MIT a3a8f7feced3937b87cd090ba748e24b
BELONGS ya.make
-FILE_INCLUDE AUTHORS found in files: crypto/includes/ngtcp2/ngtcp2_crypto.h at line 20, crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h at line 20, crypto/quictls/quictls.c at line 20, crypto/shared.c at line 20, crypto/shared.h at line 20, lib/includes/ngtcp2/ngtcp2.h at line 21, lib/includes/ngtcp2/version.h at line 20, lib/ngtcp2_acktr.c at line 20, lib/ngtcp2_acktr.h at line 20, lib/ngtcp2_addr.c at line 20, lib/ngtcp2_addr.h at line 20, lib/ngtcp2_balloc.c at line 20, lib/ngtcp2_balloc.h at line 20, lib/ngtcp2_bbr.c at line 20, lib/ngtcp2_bbr.h at line 20, lib/ngtcp2_buf.c at line 20, lib/ngtcp2_buf.h at line 20, lib/ngtcp2_cc.c at line 20, lib/ngtcp2_cc.h at line 20, lib/ngtcp2_cid.c at line 20, lib/ngtcp2_cid.h at line 20, lib/ngtcp2_conn.c at line 20, lib/ngtcp2_conn.h at line 20, lib/ngtcp2_conn_stat.h at line 20, lib/ngtcp2_conv.c at line 20, lib/ngtcp2_conv.h at line 20, lib/ngtcp2_crypto.c at line 20, lib/ngtcp2_crypto.h at line 20, lib/ngtcp2_err.c at line 20, lib/ngtcp2_err.h at line 20, lib/ngtcp2_frame_chain.c at line 20, lib/ngtcp2_frame_chain.h at line 20, lib/ngtcp2_gaptr.c at line 20, lib/ngtcp2_gaptr.h at line 20, lib/ngtcp2_idtr.c at line 20, lib/ngtcp2_idtr.h at line 20, lib/ngtcp2_ksl.c at line 20, lib/ngtcp2_ksl.h at line 20, lib/ngtcp2_log.c at line 20, lib/ngtcp2_log.h at line 20, lib/ngtcp2_macro.h at line 20, lib/ngtcp2_map.c at line 21, lib/ngtcp2_map.h at line 21, lib/ngtcp2_mem.c at line 21, lib/ngtcp2_mem.h at line 21, lib/ngtcp2_net.h at line 20, lib/ngtcp2_objalloc.c at line 20, lib/ngtcp2_objalloc.h at line 20, lib/ngtcp2_opl.c at line 20, lib/ngtcp2_opl.h at line 20, lib/ngtcp2_path.c at line 20, lib/ngtcp2_path.h at line 20, lib/ngtcp2_pkt.c at line 20, lib/ngtcp2_pkt.h at line 20, lib/ngtcp2_pktns_id.h at line 20, lib/ngtcp2_pmtud.c at line 20, lib/ngtcp2_pmtud.h at line 20, lib/ngtcp2_ppe.c at line 20, lib/ngtcp2_ppe.h at line 20, lib/ngtcp2_pq.c at line 21, lib/ngtcp2_pq.h at line 21, lib/ngtcp2_pv.c at line 20, lib/ngtcp2_pv.h at line 20, lib/ngtcp2_qlog.c at line 20, lib/ngtcp2_qlog.h at line 20, lib/ngtcp2_range.c at line 20, lib/ngtcp2_range.h at line 20, lib/ngtcp2_rcvry.h at line 20, lib/ngtcp2_ringbuf.c at line 20, lib/ngtcp2_ringbuf.h at line 20, lib/ngtcp2_rob.c at line 20, lib/ngtcp2_rob.h at line 20, lib/ngtcp2_rst.c at line 20, lib/ngtcp2_rst.h at line 20, lib/ngtcp2_rtb.c at line 20, lib/ngtcp2_rtb.h at line 20, lib/ngtcp2_settings.c at line 20, lib/ngtcp2_settings.h at line 20, lib/ngtcp2_str.c at line 20, lib/ngtcp2_str.h at line 20, lib/ngtcp2_strm.c at line 20, lib/ngtcp2_strm.h at line 20, lib/ngtcp2_transport_params.c at line 20, lib/ngtcp2_transport_params.h at line 20, lib/ngtcp2_tstamp.h at line 20, lib/ngtcp2_unreachable.c at line 20, lib/ngtcp2_unreachable.h at line 20, lib/ngtcp2_vec.c at line 20, lib/ngtcp2_vec.h at line 20, lib/ngtcp2_version.c at line 20, lib/ngtcp2_window_filter.c at line 20, lib/ngtcp2_window_filter.h at line 20
+FILE_INCLUDE AUTHORS found in files: crypto/includes/ngtcp2/ngtcp2_crypto.h at line 20, crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h at line 20, crypto/quictls/quictls.c at line 20, crypto/shared.c at line 20, crypto/shared.h at line 20, lib/includes/ngtcp2/ngtcp2.h at line 21, lib/includes/ngtcp2/version.h at line 20, lib/ngtcp2_acktr.c at line 20, lib/ngtcp2_acktr.h at line 20, lib/ngtcp2_addr.c at line 20, lib/ngtcp2_addr.h at line 20, lib/ngtcp2_balloc.c at line 20, lib/ngtcp2_balloc.h at line 20, lib/ngtcp2_bbr.c at line 20, lib/ngtcp2_bbr.h at line 20, lib/ngtcp2_buf.c at line 20, lib/ngtcp2_buf.h at line 20, lib/ngtcp2_cc.c at line 20, lib/ngtcp2_cc.h at line 20, lib/ngtcp2_cid.c at line 20, lib/ngtcp2_cid.h at line 20, lib/ngtcp2_conn.c at line 20, lib/ngtcp2_conn.h at line 20, lib/ngtcp2_conn_stat.h at line 20, lib/ngtcp2_conv.c at line 20, lib/ngtcp2_conv.h at line 20, lib/ngtcp2_crypto.c at line 20, lib/ngtcp2_crypto.h at line 20, lib/ngtcp2_dcidtr.c at line 20, lib/ngtcp2_dcidtr.h at line 20, lib/ngtcp2_err.c at line 20, lib/ngtcp2_err.h at line 20, lib/ngtcp2_frame_chain.c at line 20, lib/ngtcp2_frame_chain.h at line 20, lib/ngtcp2_gaptr.c at line 20, lib/ngtcp2_gaptr.h at line 20, lib/ngtcp2_idtr.c at line 20, lib/ngtcp2_idtr.h at line 20, lib/ngtcp2_ksl.c at line 20, lib/ngtcp2_ksl.h at line 20, lib/ngtcp2_log.c at line 20, lib/ngtcp2_log.h at line 20, lib/ngtcp2_macro.h at line 20, lib/ngtcp2_map.c at line 21, lib/ngtcp2_map.h at line 21, lib/ngtcp2_mem.c at line 21, lib/ngtcp2_mem.h at line 21, lib/ngtcp2_net.h at line 20, lib/ngtcp2_objalloc.c at line 20, lib/ngtcp2_objalloc.h at line 20, lib/ngtcp2_opl.c at line 20, lib/ngtcp2_opl.h at line 20, lib/ngtcp2_path.c at line 20, lib/ngtcp2_path.h at line 20, lib/ngtcp2_pkt.c at line 20, lib/ngtcp2_pkt.h at line 20, lib/ngtcp2_pktns_id.h at line 20, lib/ngtcp2_pmtud.c at line 20, lib/ngtcp2_pmtud.h at line 20, lib/ngtcp2_ppe.c at line 20, lib/ngtcp2_ppe.h at line 20, lib/ngtcp2_pq.c at line 21, lib/ngtcp2_pq.h at line 21, lib/ngtcp2_pv.c at line 20, lib/ngtcp2_pv.h at line 20, lib/ngtcp2_qlog.c at line 20, lib/ngtcp2_qlog.h at line 20, lib/ngtcp2_range.c at line 20, lib/ngtcp2_range.h at line 20, lib/ngtcp2_rcvry.h at line 20, lib/ngtcp2_ringbuf.c at line 20, lib/ngtcp2_ringbuf.h at line 20, lib/ngtcp2_rob.c at line 20, lib/ngtcp2_rob.h at line 20, lib/ngtcp2_rst.c at line 20, lib/ngtcp2_rst.h at line 20, lib/ngtcp2_rtb.c at line 20, lib/ngtcp2_rtb.h at line 20, lib/ngtcp2_settings.c at line 20, lib/ngtcp2_settings.h at line 20, lib/ngtcp2_str.c at line 20, lib/ngtcp2_str.h at line 20, lib/ngtcp2_strm.c at line 20, lib/ngtcp2_strm.h at line 20, lib/ngtcp2_transport_params.c at line 20, lib/ngtcp2_transport_params.h at line 20, lib/ngtcp2_tstamp.h at line 20, lib/ngtcp2_unreachable.c at line 20, lib/ngtcp2_unreachable.h at line 20, lib/ngtcp2_vec.c at line 20, lib/ngtcp2_vec.h at line 20, lib/ngtcp2_version.c at line 20, lib/ngtcp2_window_filter.c at line 20, lib/ngtcp2_window_filter.h at line 20
Note: matched license text is too long. Read it in the source files.
Scancode info:
Original SPDX id: MIT
@@ -123,6 +123,8 @@ FILE_INCLUDE AUTHORS found in files: crypto/includes/ngtcp2/ngtcp2_crypto.h at l
lib/ngtcp2_conv.h [6:23]
lib/ngtcp2_crypto.c [6:23]
lib/ngtcp2_crypto.h [6:23]
+ lib/ngtcp2_dcidtr.c [6:23]
+ lib/ngtcp2_dcidtr.h [6:23]
lib/ngtcp2_err.c [6:23]
lib/ngtcp2_err.h [6:23]
lib/ngtcp2_frame_chain.c [6:23]
diff --git a/contrib/libs/ngtcp2/.yandex_meta/licenses.list.txt b/contrib/libs/ngtcp2/.yandex_meta/licenses.list.txt
index 849335d337..de5f02b01d 100644
--- a/contrib/libs/ngtcp2/.yandex_meta/licenses.list.txt
+++ b/contrib/libs/ngtcp2/.yandex_meta/licenses.list.txt
@@ -56,6 +56,10 @@ Software Foundation, Inc.
====================COPYRIGHT====================
+ * Copyright (c) 2025 ngtcp2 contributors
+
+
+====================COPYRIGHT====================
Copyright (c) 2016 ngtcp2 contributors
diff --git a/contrib/libs/ngtcp2/.yandex_meta/override.nix b/contrib/libs/ngtcp2/.yandex_meta/override.nix
index 780296e02a..c78b13139d 100644
--- a/contrib/libs/ngtcp2/.yandex_meta/override.nix
+++ b/contrib/libs/ngtcp2/.yandex_meta/override.nix
@@ -1,9 +1,9 @@
pkgs: attrs: with pkgs; rec {
- version = "1.10.0";
+ version = "1.11.0";
src = fetchurl {
url = "https://github.com/ngtcp2/ngtcp2/releases/download/v${version}/ngtcp2-${version}.tar.xz";
- hash = "sha256-T43B1hlXIF0Bw9aqbxyWx7K6wf7qcf2vly2G219kZd8=";
+ hash = "sha256-OCwVv2a2MPJgIWMbJbfrH+rELGfB1oJhidYQkd+qTQk=";
};
patches = [];
diff --git a/contrib/libs/ngtcp2/README.rst b/contrib/libs/ngtcp2/README.rst
index a3de8f7cb3..af9ad18219 100644
--- a/contrib/libs/ngtcp2/README.rst
+++ b/contrib/libs/ngtcp2/README.rst
@@ -61,9 +61,9 @@ directory require at least one of the following TLS backends:
- `quictls
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1w+quic>`_
- GnuTLS >= 3.7.5
-- BoringSSL (commit c361e279402ec359834b7eaa7d737462d02675e1);
+- BoringSSL (commit 294ab9730c570213b496cfc2fc14b3c0bfcd4bcc);
or aws-lc >= 1.39.0
-- Picotls (commit 402544bb65b35c3231a8912f25919de7e7922659)
+- Picotls (commit bbcdbe6dc31ec5d4b72a7beece4daf58098bad42)
- wolfSSL >= 5.5.0
- LibreSSL >= v3.9.2
@@ -81,7 +81,7 @@ Build with wolfSSL
.. code-block:: shell
- $ git clone --depth 1 -b v5.7.4-stable https://github.com/wolfSSL/wolfssl
+ $ git clone --depth 1 -b v5.7.6-stable https://github.com/wolfSSL/wolfssl
$ cd wolfssl
$ autoreconf -i
$ # For wolfSSL < v5.6.6, append --enable-quic.
@@ -114,7 +114,7 @@ Build with BoringSSL
$ git clone https://boringssl.googlesource.com/boringssl
$ cd boringssl
- $ git checkout c361e279402ec359834b7eaa7d737462d02675e1
+ $ git checkout 294ab9730c570213b496cfc2fc14b3c0bfcd4bcc
$ cmake -B build -DCMAKE_POSITION_INDEPENDENT_CODE=ON
$ make -j$(nproc) -C build
$ cd ..
@@ -141,7 +141,7 @@ Build with aws-lc
.. code-block:: shell
- $ git clone --depth 1 -b v1.41.1 https://github.com/aws/aws-lc
+ $ git clone --depth 1 -b v1.46.1 https://github.com/aws/aws-lc
$ cd aws-lc
$ cmake -B build -DDISABLE_GO=ON
$ make -j$(nproc) -C build
diff --git a/contrib/libs/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h b/contrib/libs/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
index 68093d18b7..4eaf615bd3 100644
--- a/contrib/libs/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/includes/ngtcp2/ngtcp2.h b/contrib/libs/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
index 2abeb8f1cd..bb4a252c0a 100644
--- a/contrib/libs/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/includes/ngtcp2/version.h b/contrib/libs/ngtcp2/lib/includes/ngtcp2/version.h
index 20c4ac24d2..bb983f5cf4 100644
--- a/contrib/libs/ngtcp2/lib/includes/ngtcp2/version.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_acktr.c b/contrib/libs/ngtcp2/lib/ngtcp2_acktr.c
index 0e5bfe069e..776dc0c2c3 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_acktr.c
+++ b/contrib/libs/ngtcp2/lib/ngtcp2_acktr.c
@@ -25,6 +25,7 @@
#include "ngtcp2_acktr.h"
#include <assert.h>
+#include <string.h>
#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/contrib/libs/ngtcp2/lib/ngtcp2_acktr.h b/contrib/libs/ngtcp2/lib/ngtcp2_acktr.h
index 16aee42f27..cf75a774db 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_acktr.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_addr.c b/contrib/libs/ngtcp2/lib/ngtcp2_addr.c
index f389abe76d..1fb273d494 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_addr.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_addr.h b/contrib/libs/ngtcp2/lib/ngtcp2_addr.h
index 65ee7cd9f3..c2224f85cd 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_addr.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_bbr.c b/contrib/libs/ngtcp2/lib/ngtcp2_bbr.c
index 8777ca4c8a..a20f04521e 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_bbr.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_bbr.h b/contrib/libs/ngtcp2/lib/ngtcp2_bbr.h
index f266ec5d71..74eb2d640b 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_bbr.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_cc.c b/contrib/libs/ngtcp2/lib/ngtcp2_cc.c
index 1ff59f315c..508a5d9ec1 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_cc.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_cid.c b/contrib/libs/ngtcp2/lib/ngtcp2_cid.c
index 181850cfcb..8bff06c0c1 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_cid.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_cid.h b/contrib/libs/ngtcp2/lib/ngtcp2_cid.h
index 6372ef113d..c6ab16831a 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_cid.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_conn.c b/contrib/libs/ngtcp2/lib/ngtcp2_conn.c
index 765e4a877e..59eb90f6ea 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_conn.c
+++ b/contrib/libs/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);
@@ -1626,40 +1629,6 @@ void ngtcp2_conn_del(ngtcp2_conn *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
@@ -1895,21 +1746,12 @@ static size_t pktns_select_pkt_numlen(ngtcp2_pktns *pktns) {
}
/*
- * 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;
}
/*
@@ -5483,6 +5241,17 @@ static void conn_recv_max_data(ngtcp2_conn *conn, const ngtcp2_max_data *fr) {
}
/*
+ * 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;
@@ -7708,45 +7455,17 @@ static int conn_recv_new_connection_id(ngtcp2_conn *conn,
}
}
- 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,
- fr->stateless_reset_token);
- if (rv != 0) {
- return NGTCP2_ERR_PROTO;
- }
- if (ngtcp2_cid_eq(&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);
@@ -9722,24 +9415,6 @@ static int conn_recv_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path,
}
/*
- * 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/contrib/libs/ngtcp2/lib/ngtcp2_conn.h b/contrib/libs/ngtcp2/lib/ngtcp2_conn.h
index 55073fcc82..0ba8d6efcc 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_conn.h
+++ b/contrib/libs/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;
@@ -725,21 +685,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.
*/
@@ -1138,28 +1083,6 @@ 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/contrib/libs/ngtcp2/lib/ngtcp2_dcidtr.c b/contrib/libs/ngtcp2/lib/ngtcp2_dcidtr.c
new file mode 100644
index 0000000000..8a8d773379
--- /dev/null
+++ b/contrib/libs/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 <assert.h>
+
+#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/contrib/libs/ngtcp2/lib/ngtcp2_dcidtr.h b/contrib/libs/ngtcp2/lib/ngtcp2_dcidtr.h
new file mode 100644
index 0000000000..17942389b8
--- /dev/null
+++ b/contrib/libs/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 <config.h>
+#endif /* defined(HAVE_CONFIG_H) */
+
+#include <ngtcp2/ngtcp2.h>
+
+#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/contrib/libs/ngtcp2/lib/ngtcp2_frame_chain.c b/contrib/libs/ngtcp2/lib/ngtcp2_frame_chain.c
index 6a8a22c3f0..0f6b06a788 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_frame_chain.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_frame_chain.h b/contrib/libs/ngtcp2/lib/ngtcp2_frame_chain.h
index e5b6779c0f..e7b3363252 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_frame_chain.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_gaptr.c b/contrib/libs/ngtcp2/lib/ngtcp2_gaptr.c
index 3bfa398480..d04b9634c2 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_gaptr.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_ksl.c b/contrib/libs/ngtcp2/lib/ngtcp2_ksl.c
index 5e74f64724..22c131a1ac 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_ksl.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_map.c b/contrib/libs/ngtcp2/lib/ngtcp2_map.c
index 0b66fceac6..5e4726e63f 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_map.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_mem.c b/contrib/libs/ngtcp2/lib/ngtcp2_mem.c
index d30e1f986e..48f430f474 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_mem.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_pkt.c b/contrib/libs/ngtcp2/lib/ngtcp2_pkt.c
index 5c82e1bd50..d78978492c 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_pkt.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_pkt.h b/contrib/libs/ngtcp2/lib/ngtcp2_pkt.h
index 86ebecef7b..756076e7a7 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_pkt.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_pq.c b/contrib/libs/ngtcp2/lib/ngtcp2_pq.c
index 19e3e3e36a..162bed0015 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_pq.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_pq.h b/contrib/libs/ngtcp2/lib/ngtcp2_pq.h
index 84961c9143..aa195a9f7b 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_pq.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_pv.c b/contrib/libs/ngtcp2/lib/ngtcp2_pv.c
index e4fee94eb5..471f84c764 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_pv.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_pv.h b/contrib/libs/ngtcp2/lib/ngtcp2_pv.h
index e9573da497..2d07e41648 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_pv.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_range.c b/contrib/libs/ngtcp2/lib/ngtcp2_range.c
index 7bbefc0175..e898915329 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_range.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_ringbuf.c b/contrib/libs/ngtcp2/lib/ngtcp2_ringbuf.c
index 41446739bf..353afca4d4 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_ringbuf.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_ringbuf.h b/contrib/libs/ngtcp2/lib/ngtcp2_ringbuf.h
index 6953ea6278..d490524805 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_ringbuf.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_rob.c b/contrib/libs/ngtcp2/lib/ngtcp2_rob.c
index ce6c2113dd..853f1d650e 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_rob.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_rst.c b/contrib/libs/ngtcp2/lib/ngtcp2_rst.c
index 89c89acdc2..181691f3e6 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_rst.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_rst.h b/contrib/libs/ngtcp2/lib/ngtcp2_rst.h
index 95616eee97..c2580306cc 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_rst.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_rtb.c b/contrib/libs/ngtcp2/lib/ngtcp2_rtb.c
index 090355f5db..f7a7f5724b 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_rtb.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_rtb.h b/contrib/libs/ngtcp2/lib/ngtcp2_rtb.h
index 2ef772b2e1..3a9397eac5 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_rtb.h
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_transport_params.c b/contrib/libs/ngtcp2/lib/ngtcp2_transport_params.c
index dda59c4885..ca517532e3 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_transport_params.c
+++ b/contrib/libs/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(&param_type, &p, end) != 0) {
diff --git a/contrib/libs/ngtcp2/lib/ngtcp2_vec.c b/contrib/libs/ngtcp2/lib/ngtcp2_vec.c
index 0b9c92d47d..dbca8691d6 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_vec.c
+++ b/contrib/libs/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/contrib/libs/ngtcp2/lib/ngtcp2_vec.h b/contrib/libs/ngtcp2/lib/ngtcp2_vec.h
index f7611efcb7..55e735d164 100644
--- a/contrib/libs/ngtcp2/lib/ngtcp2_vec.h
+++ b/contrib/libs/ngtcp2/lib/ngtcp2_vec.h
@@ -47,22 +47,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.
*/
uint64_t ngtcp2_vec_len(const ngtcp2_vec *vec, size_t n);
diff --git a/contrib/libs/ngtcp2/ya.make b/contrib/libs/ngtcp2/ya.make
index 8e51e5aa3e..e81fc5ee20 100644
--- a/contrib/libs/ngtcp2/ya.make
+++ b/contrib/libs/ngtcp2/ya.make
@@ -2,9 +2,9 @@
LIBRARY()
-VERSION(1.10.0)
+VERSION(1.11.0)
-ORIGINAL_SOURCE(https://github.com/ngtcp2/ngtcp2/releases/download/v1.10.0/ngtcp2-1.10.0.tar.xz)
+ORIGINAL_SOURCE(https://github.com/ngtcp2/ngtcp2/releases/download/v1.11.0/ngtcp2-1.11.0.tar.xz)
LICENSE(
BSD-3-Clause AND
@@ -48,6 +48,7 @@ SRCS(
lib/ngtcp2_conn.c
lib/ngtcp2_conv.c
lib/ngtcp2_crypto.c
+ lib/ngtcp2_dcidtr.c
lib/ngtcp2_err.c
lib/ngtcp2_frame_chain.c
lib/ngtcp2_gaptr.c