summaryrefslogtreecommitdiffstats
path: root/src/contrib/libngtcp2/ngtcp2
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-14 16:17:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-14 16:17:58 +0000
commita04a7c41c9327144cc11ffd030c0efc2a4f85534 (patch)
tree812fe9d19c0c90324f80b838b1b1e2976a416999 /src/contrib/libngtcp2/ngtcp2
parentAdding upstream version 3.3.5. (diff)
downloadknot-a04a7c41c9327144cc11ffd030c0efc2a4f85534.tar.xz
knot-a04a7c41c9327144cc11ffd030c0efc2a4f85534.zip
Adding upstream version 3.3.6.upstream/3.3.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/contrib/libngtcp2/ngtcp2')
-rw-r--r--src/contrib/libngtcp2/ngtcp2/crypto/shared.c33
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c34
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h15
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c40
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c2
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c591
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h31
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c66
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c819
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h44
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h36
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c18
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h5
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c43
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h9
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c43
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h28
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c2
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h5
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c8
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c9
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c91
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h73
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h3
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c886
-rw-r--r--src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.h (renamed from src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.h)53
-rw-r--r--src/contrib/libngtcp2/ngtcp2/ngtcp2.h62
-rw-r--r--src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h2
-rw-r--r--src/contrib/libngtcp2/ngtcp2/version.h4
29 files changed, 1677 insertions, 1378 deletions
diff --git a/src/contrib/libngtcp2/ngtcp2/crypto/shared.c b/src/contrib/libngtcp2/ngtcp2/crypto/shared.c
index 162094a..604cb96 100644
--- a/src/contrib/libngtcp2/ngtcp2/crypto/shared.c
+++ b/src/contrib/libngtcp2/ngtcp2/crypto/shared.c
@@ -923,10 +923,11 @@ ngtcp2_ssize ngtcp2_crypto_generate_retry_token(
uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version,
const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen,
const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts) {
- uint8_t plaintext[NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN];
+ uint8_t
+ plaintext[/* cid len = */ 1 + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)];
uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN];
- uint8_t key[32];
- uint8_t iv[32];
+ uint8_t key[16];
+ uint8_t iv[12];
size_t keylen;
size_t ivlen;
ngtcp2_crypto_aead aead;
@@ -962,8 +963,8 @@ ngtcp2_ssize ngtcp2_crypto_generate_retry_token(
keylen = ngtcp2_crypto_aead_keylen(&aead);
ivlen = ngtcp2_crypto_aead_noncelen(&aead);
- assert(sizeof(key) >= keylen);
- assert(sizeof(iv) >= ivlen);
+ assert(sizeof(key) == keylen);
+ assert(sizeof(iv) == ivlen);
if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen,
rand_data, sizeof(rand_data),
@@ -1005,8 +1006,8 @@ int ngtcp2_crypto_verify_retry_token(
const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts) {
uint8_t
plaintext[/* cid len = */ 1 + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)];
- uint8_t key[32];
- uint8_t iv[32];
+ uint8_t key[16];
+ uint8_t iv[12];
size_t keylen;
size_t ivlen;
ngtcp2_crypto_aead_ctx aead_ctx;
@@ -1039,6 +1040,9 @@ int ngtcp2_crypto_verify_retry_token(
keylen = ngtcp2_crypto_aead_keylen(&aead);
ivlen = ngtcp2_crypto_aead_noncelen(&aead);
+ assert(sizeof(key) == keylen);
+ assert(sizeof(iv) == ivlen);
+
if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen,
rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN,
retry_token_info_prefix,
@@ -1114,8 +1118,8 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token(
ngtcp2_tstamp ts) {
uint8_t plaintext[sizeof(ngtcp2_tstamp)];
uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN];
- uint8_t key[32];
- uint8_t iv[32];
+ uint8_t key[16];
+ uint8_t iv[12];
size_t keylen;
size_t ivlen;
ngtcp2_crypto_aead aead;
@@ -1144,8 +1148,8 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token(
keylen = ngtcp2_crypto_aead_keylen(&aead);
ivlen = ngtcp2_crypto_aead_noncelen(&aead);
- assert(sizeof(key) >= keylen);
- assert(sizeof(iv) >= ivlen);
+ assert(sizeof(key) == keylen);
+ assert(sizeof(iv) == ivlen);
if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen,
rand_data, sizeof(rand_data),
@@ -1186,8 +1190,8 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen,
ngtcp2_duration timeout,
ngtcp2_tstamp ts) {
uint8_t plaintext[sizeof(ngtcp2_tstamp)];
- uint8_t key[32];
- uint8_t iv[32];
+ uint8_t key[16];
+ uint8_t iv[12];
size_t keylen;
size_t ivlen;
ngtcp2_crypto_aead_ctx aead_ctx;
@@ -1217,6 +1221,9 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen,
keylen = ngtcp2_crypto_aead_keylen(&aead);
ivlen = ngtcp2_crypto_aead_noncelen(&aead);
+ assert(sizeof(key) == keylen);
+ assert(sizeof(iv) == ivlen);
+
if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen,
rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN,
regular_token_info_prefix,
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c
index d4778d6..3ed581f 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c
@@ -60,31 +60,18 @@ static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
return *(int64_t *)lhs > *(int64_t *)rhs;
}
-int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
- const ngtcp2_mem *mem) {
- int rv;
-
+void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
+ const ngtcp2_mem *mem) {
ngtcp2_objalloc_acktr_entry_init(&acktr->objalloc, 32, mem);
- rv = ngtcp2_ringbuf_init(&acktr->acks, 32, sizeof(ngtcp2_acktr_ack_entry),
- mem);
- if (rv != 0) {
- goto fail_acks_init;
- }
+ ngtcp2_static_ringbuf_acks_init(&acktr->acks);
ngtcp2_ksl_init(&acktr->ents, greater, sizeof(int64_t), mem);
acktr->log = log;
- acktr->mem = mem;
acktr->flags = NGTCP2_ACKTR_FLAG_NONE;
acktr->first_unacked_ts = UINT64_MAX;
acktr->rx_npkt = 0;
-
- return 0;
-
-fail_acks_init:
- ngtcp2_objalloc_free(&acktr->objalloc);
- return rv;
}
void ngtcp2_acktr_free(ngtcp2_acktr *acktr) {
@@ -105,8 +92,6 @@ void ngtcp2_acktr_free(ngtcp2_acktr *acktr) {
ngtcp2_ksl_free(&acktr->ents);
- ngtcp2_ringbuf_free(&acktr->acks);
-
ngtcp2_objalloc_free(&acktr->objalloc);
}
@@ -225,7 +210,7 @@ int ngtcp2_acktr_empty(ngtcp2_acktr *acktr) {
ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr,
int64_t pkt_num,
int64_t largest_ack) {
- ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks);
+ ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks.rb);
ent->largest_ack = largest_ack;
ent->pkt_num = pkt_num;
@@ -266,8 +251,10 @@ static void acktr_on_ack(ngtcp2_acktr *acktr, ngtcp2_ringbuf *rb,
ngtcp2_ksl_it_prev(&it);
ent = ngtcp2_ksl_it_get(&it);
- if (ent->pkt_num > ack_ent->largest_ack &&
- ack_ent->largest_ack >= ent->pkt_num - (int64_t)(ent->len - 1)) {
+
+ assert(ent->pkt_num > ack_ent->largest_ack);
+
+ if (ack_ent->largest_ack >= ent->pkt_num - (int64_t)(ent->len - 1)) {
ent->len = (size_t)(ent->pkt_num - ack_ent->largest_ack);
}
}
@@ -279,7 +266,7 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) {
ngtcp2_acktr_ack_entry *ent;
int64_t largest_ack = fr->largest_ack, min_ack;
size_t i, j;
- ngtcp2_ringbuf *rb = &acktr->acks;
+ ngtcp2_ringbuf *rb = &acktr->acks.rb;
size_t nacks = ngtcp2_ringbuf_len(rb);
/* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
@@ -306,8 +293,7 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) {
for (;;) {
if (ent->pkt_num > largest_ack) {
- ++j;
- if (j == nacks) {
+ if (++j == nacks) {
return;
}
ent = ngtcp2_ringbuf_get(rb, j);
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h
index 809fb69..0cbb490 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h
@@ -108,17 +108,18 @@ typedef struct ngtcp2_acktr_ack_entry {
expired and canceled. */
#define NGTCP2_ACKTR_FLAG_CANCEL_TIMER 0x0100u
+ngtcp2_static_ringbuf_def(acks, 32, sizeof(ngtcp2_acktr_ack_entry));
+
/*
* ngtcp2_acktr tracks received packets which we have to send ack.
*/
typedef struct ngtcp2_acktr {
ngtcp2_objalloc objalloc;
- ngtcp2_ringbuf acks;
+ ngtcp2_static_ringbuf_acks acks;
/* ents includes ngtcp2_acktr_entry sorted by decreasing order of
packet number. */
ngtcp2_ksl ents;
ngtcp2_log *log;
- const ngtcp2_mem *mem;
/* flags is bitwise OR of zero, or more of NGTCP2_ACKTR_FLAG_*. */
uint16_t flags;
/* first_unacked_ts is timestamp when ngtcp2_acktr_entry is added
@@ -131,15 +132,9 @@ typedef struct ngtcp2_acktr {
/*
* ngtcp2_acktr_init initializes |acktr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
*/
-int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
- const ngtcp2_mem *mem);
+void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
+ const ngtcp2_mem *mem);
/*
* ngtcp2_acktr_free frees resources allocated for |acktr|. It frees
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c
index 27c4667..ebc6f48 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c
@@ -558,11 +558,12 @@ static void bbr_init_lower_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) {
}
static void bbr_loss_lower_bounds(ngtcp2_cc_bbr *bbr) {
- bbr->bw_lo = ngtcp2_max(bbr->bw_latest, bbr->bw_lo * NGTCP2_BBR_BETA_NUMER /
- NGTCP2_BBR_BETA_DENOM);
- bbr->inflight_lo = ngtcp2_max(bbr->inflight_latest,
- bbr->inflight_lo * NGTCP2_BBR_BETA_NUMER /
- NGTCP2_BBR_BETA_DENOM);
+ bbr->bw_lo =
+ ngtcp2_max_uint64(bbr->bw_latest, bbr->bw_lo * NGTCP2_BBR_BETA_NUMER /
+ NGTCP2_BBR_BETA_DENOM);
+ bbr->inflight_lo = ngtcp2_max_uint64(
+ bbr->inflight_latest,
+ bbr->inflight_lo * NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM);
}
static void bbr_bound_bw_for_model(ngtcp2_cc_bbr *bbr) {
@@ -801,13 +802,13 @@ static uint64_t bbr_inflight_with_headroom(ngtcp2_cc_bbr *bbr,
return UINT64_MAX;
}
- headroom = ngtcp2_max(cstat->max_tx_udp_payload_size,
- bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER /
- NGTCP2_BBR_HEADROOM_DENOM);
+ headroom = ngtcp2_max_uint64(cstat->max_tx_udp_payload_size,
+ bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER /
+ NGTCP2_BBR_HEADROOM_DENOM);
mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size);
if (bbr->inflight_hi > headroom) {
- return ngtcp2_max(bbr->inflight_hi - headroom, mpcwnd);
+ return ngtcp2_max_uint64(bbr->inflight_hi - headroom, mpcwnd);
}
return mpcwnd;
@@ -818,8 +819,8 @@ static void bbr_raise_inflight_hi_slope(ngtcp2_cc_bbr *bbr,
uint64_t growth_this_round = cstat->max_tx_udp_payload_size
<< bbr->bw_probe_up_rounds;
- bbr->bw_probe_up_rounds = ngtcp2_min(bbr->bw_probe_up_rounds + 1, 30);
- bbr->probe_up_cnt = ngtcp2_max(cstat->cwnd / growth_this_round, 1) *
+ 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;
}
@@ -946,7 +947,7 @@ static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr,
bbr->bw_probe_samples = 0;
if (!rs->is_app_limited) {
- bbr->inflight_hi = ngtcp2_max(
+ bbr->inflight_hi = ngtcp2_max_uint64(
rs->tx_in_flight, bbr_target_inflight(bbr, cstat) *
NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM);
}
@@ -1154,8 +1155,8 @@ static uint64_t bbr_quantization_budget(ngtcp2_cc_bbr *bbr,
bbr_update_offload_budget(bbr, cstat);
inflight = ngtcp2_max(inflight, bbr->offload_budget);
- inflight =
- ngtcp2_max(inflight, min_pipe_cwnd(cstat->max_tx_udp_payload_size));
+ inflight = ngtcp2_max_uint64(inflight,
+ min_pipe_cwnd(cstat->max_tx_udp_payload_size));
if (bbr->state == NGTCP2_BBR_STATE_PROBE_BW_UP) {
inflight += 2 * cstat->max_tx_udp_payload_size;
@@ -1198,15 +1199,16 @@ static void bbr_modulate_cwnd_for_recovery(ngtcp2_cc_bbr *bbr,
if (ack->bytes_lost > 0) {
if (cstat->cwnd > ack->bytes_lost) {
cstat->cwnd -= ack->bytes_lost;
- cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_tx_udp_payload_size);
+ cstat->cwnd =
+ ngtcp2_max_uint64(cstat->cwnd, 2 * cstat->max_tx_udp_payload_size);
} else {
cstat->cwnd = 2 * cstat->max_tx_udp_payload_size;
}
}
if (bbr->packet_conservation) {
- cstat->cwnd =
- ngtcp2_max(cstat->cwnd, cstat->bytes_in_flight + ack->bytes_delivered);
+ cstat->cwnd = ngtcp2_max_uint64(cstat->cwnd, cstat->bytes_in_flight +
+ ack->bytes_delivered);
}
}
@@ -1400,8 +1402,8 @@ static void bbr_cc_on_persistent_congestion(ngtcp2_cc *cc,
bbr_save_cwnd(bbr, cstat);
cstat->cwnd = cstat->bytes_in_flight + cstat->max_tx_udp_payload_size;
- cstat->cwnd =
- ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size));
+ cstat->cwnd = ngtcp2_max_uint64(
+ cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size));
}
static void bbr_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c
index 9ad37fb..bade016 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c
@@ -41,7 +41,7 @@
uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) {
uint64_t n = 2 * max_udp_payload_size;
n = ngtcp2_max(n, 14720);
- return ngtcp2_min(10 * max_udp_payload_size, n);
+ return ngtcp2_min_uint64(10 * max_udp_payload_size, n);
}
ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c
index c8caf47..a8e8874 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c
@@ -37,7 +37,8 @@
#include "ngtcp2_rcvry.h"
#include "ngtcp2_unreachable.h"
#include "ngtcp2_net.h"
-#include "ngtcp2_conversion.h"
+#include "ngtcp2_transport_params.h"
+#include "ngtcp2_settings.h"
#include "ngtcp2_tstamp.h"
#include "ngtcp2_frame_chain.h"
@@ -663,13 +664,11 @@ static int conn_call_recv_tx_key(ngtcp2_conn *conn,
return 0;
}
-static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id,
- ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num,
- ngtcp2_log *log, ngtcp2_qlog *qlog,
- ngtcp2_objalloc *rtb_entry_objalloc,
- ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) {
- int rv;
-
+static void pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id,
+ ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num,
+ ngtcp2_log *log, ngtcp2_qlog *qlog,
+ ngtcp2_objalloc *rtb_entry_objalloc,
+ ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) {
memset(pktns, 0, sizeof(*pktns));
ngtcp2_gaptr_init(&pktns->rx.pngap, mem);
@@ -679,10 +678,7 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id,
pktns->rx.max_pkt_num = -1;
pktns->rx.max_ack_eliciting_pkt_num = -1;
- rv = ngtcp2_acktr_init(&pktns->acktr, log, mem);
- if (rv != 0) {
- goto fail_acktr_init;
- }
+ ngtcp2_acktr_init(&pktns->acktr, log, mem);
ngtcp2_strm_init(&pktns->crypto.strm, 0, NGTCP2_STRM_FLAG_NONE, 0, 0, NULL,
frc_objalloc, mem);
@@ -690,13 +686,6 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id,
ngtcp2_rtb_init(&pktns->rtb, pktns_id, &pktns->crypto.strm, rst, cc,
initial_pkt_num, log, qlog, rtb_entry_objalloc, frc_objalloc,
mem);
-
- return 0;
-
-fail_acktr_init:
- ngtcp2_gaptr_free(&pktns->rx.pngap);
-
- return rv;
}
static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id,
@@ -704,20 +693,15 @@ static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id,
ngtcp2_log *log, ngtcp2_qlog *qlog,
ngtcp2_objalloc *rtb_entry_objalloc,
ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) {
- int rv;
-
*ppktns = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pktns));
if (*ppktns == NULL) {
return NGTCP2_ERR_NOMEM;
}
- rv = pktns_init(*ppktns, pktns_id, rst, cc, initial_pkt_num, log, qlog,
- rtb_entry_objalloc, frc_objalloc, mem);
- if (rv != 0) {
- ngtcp2_mem_free(mem, *ppktns);
- }
+ pktns_init(*ppktns, pktns_id, rst, cc, initial_pkt_num, log, qlog,
+ rtb_entry_objalloc, frc_objalloc, mem);
- return rv;
+ return 0;
}
static int cycle_less(const ngtcp2_pq_entry *lhs, const ngtcp2_pq_entry *rhs) {
@@ -803,8 +787,9 @@ static void conn_reset_conn_stat_cc(ngtcp2_conn *conn,
cstat->first_rtt_sample_ts = UINT64_MAX;
cstat->pto_count = 0;
cstat->loss_detection_timer = UINT64_MAX;
- cstat->cwnd =
- ngtcp2_cc_compute_initcwnd(conn->local.settings.max_tx_udp_payload_size);
+ cstat->max_tx_udp_payload_size =
+ ngtcp2_conn_get_path_max_tx_udp_payload_size(conn);
+ cstat->cwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size);
cstat->ssthresh = UINT64_MAX;
cstat->congestion_recovery_start_ts = UINT64_MAX;
cstat->bytes_in_flight = 0;
@@ -847,7 +832,7 @@ static void delete_scid(ngtcp2_ksl *scids, const ngtcp2_mem *mem) {
static ngtcp2_duration compute_pto(ngtcp2_duration smoothed_rtt,
ngtcp2_duration rttvar,
ngtcp2_duration max_ack_delay) {
- ngtcp2_duration var = ngtcp2_max(4 * rttvar, NGTCP2_GRANULARITY);
+ ngtcp2_duration var = ngtcp2_max_uint64(4 * rttvar, NGTCP2_GRANULARITY);
return smoothed_rtt + var + max_ack_delay;
}
@@ -1007,28 +992,15 @@ static void conn_reset_ecn_validation_state(ngtcp2_conn *conn) {
static uint8_t server_default_available_versions[] = {0, 0, 0, 1};
/*
- * available_versions_new allocates new buffer, and writes |versions|
- * of length |versionslen| in network byte order, suitable for sending
- * in available_versions field of version_information QUIC transport
- * parameter. The pointer to the allocated buffer is assigned to
- * |*pbuf|.
- *
- * This function returns 0 if it succeeds, or one of the negative
- * error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
+ * available_versions_init writes |versions| of length |versionslen|
+ * in network byte order to the buffer pointed by |buf|, suitable for
+ * sending in available_versions field of version_information QUIC
+ * transport parameter. This function returns the pointer to the one
+ * beyond the last byte written.
*/
-static int available_versions_new(uint8_t **pbuf, const uint32_t *versions,
- size_t versionslen, const ngtcp2_mem *mem) {
+static void *available_versions_init(void *buf, const uint32_t *versions,
+ size_t versionslen) {
size_t i;
- uint8_t *buf = ngtcp2_mem_malloc(mem, sizeof(uint32_t) * versionslen);
-
- if (buf == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- *pbuf = buf;
for (i = 0; i < versionslen; ++i) {
buf = ngtcp2_put_uint32be(buf, versions[i]);
@@ -1055,6 +1027,16 @@ conn_set_local_transport_params(ngtcp2_conn *conn,
p->version_info_present = 1;
}
+static size_t buflen_align(size_t buflen) {
+ return (buflen + 0x7) & (size_t)~0x7;
+}
+
+static void *buf_align(void *buf) {
+ return (void *)((uintptr_t)((uint8_t *)buf + 0x7) & (uintptr_t)~0x7);
+}
+
+static void *buf_advance(void *buf, size_t n) { return (uint8_t *)buf + n; }
+
static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
const ngtcp2_cid *scid, const ngtcp2_path *path,
uint32_t client_chosen_version, int callbacks_version,
@@ -1065,14 +1047,18 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
const ngtcp2_mem *mem, void *user_data, int server) {
int rv;
ngtcp2_scid *scident;
- uint8_t *buf;
+ void *buf, *tokenbuf;
+ size_t buflen;
uint8_t fixed_bit_byte;
size_t i;
uint32_t *preferred_versions;
+ ngtcp2_settings settingsbuf;
ngtcp2_transport_params paramsbuf;
(void)callbacks_version;
(void)settings_version;
+ settings = ngtcp2_settings_convert_to_latest(&settingsbuf, settings_version,
+ settings);
params = ngtcp2_transport_params_convert_to_latest(
&paramsbuf, transport_params_version, params);
@@ -1111,16 +1097,54 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
assert(callbacks->get_path_challenge_data);
assert(!server || !ngtcp2_is_reserved_version(client_chosen_version));
+ for (i = 0; i < settings->pmtud_probeslen; ++i) {
+ assert(settings->pmtud_probes[i] > NGTCP2_MAX_UDP_PAYLOAD_SIZE);
+ }
+
if (mem == NULL) {
mem = ngtcp2_mem_default();
}
- *pconn = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_conn));
- if (*pconn == NULL) {
- rv = NGTCP2_ERR_NOMEM;
- goto fail_conn;
+ buflen = sizeof(ngtcp2_conn);
+ if (settings->qlog_write) {
+ buflen = buflen_align(buflen);
+ buflen += NGTCP2_QLOG_BUFLEN;
+ }
+
+ if (settings->pmtud_probeslen) {
+ buflen = buflen_align(buflen);
+ buflen += sizeof(settings->pmtud_probes[0]) * settings->pmtud_probeslen;
+ }
+
+ if (settings->preferred_versionslen) {
+ buflen = buflen_align(buflen);
+ buflen += sizeof(settings->preferred_versions[0]) *
+ settings->preferred_versionslen;
+ }
+
+ if (settings->available_versionslen) {
+ buflen = buflen_align(buflen);
+ buflen += sizeof(settings->available_versions[0]) *
+ settings->available_versionslen;
+ } else if (server) {
+ if (settings->preferred_versionslen) {
+ buflen = buflen_align(buflen);
+ buflen += sizeof(settings->preferred_versions[0]) *
+ settings->preferred_versionslen;
+ }
+ } else if (!ngtcp2_is_reserved_version(client_chosen_version)) {
+ buflen = buflen_align(buflen);
+ buflen += sizeof(client_chosen_version);
}
+ buf = ngtcp2_mem_calloc(mem, 1, buflen);
+ if (buf == NULL) {
+ return NGTCP2_ERR_NOMEM;
+ }
+
+ *pconn = buf;
+ buf = buf_advance(buf, sizeof(ngtcp2_conn));
+
(*pconn)->server = server;
ngtcp2_objalloc_frame_chain_init(&(*pconn)->frc_objalloc, 64, mem);
@@ -1154,36 +1178,47 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
ngtcp2_qlog_init(&(*pconn)->qlog, settings->qlog_write, settings->initial_ts,
user_data);
if ((*pconn)->qlog.write) {
- buf = ngtcp2_mem_malloc(mem, NGTCP2_QLOG_BUFLEN);
- if (buf == NULL) {
- rv = NGTCP2_ERR_NOMEM;
- goto fail_qlog_buf;
- }
+ buf = buf_align(buf);
ngtcp2_buf_init(&(*pconn)->qlog.buf, buf, NGTCP2_QLOG_BUFLEN);
+ buf = buf_advance(buf, NGTCP2_QLOG_BUFLEN);
}
(*pconn)->local.settings = *settings;
if (settings->tokenlen) {
- buf = ngtcp2_mem_malloc(mem, settings->tokenlen);
- if (buf == NULL) {
+ tokenbuf = ngtcp2_mem_malloc(mem, settings->tokenlen);
+ if (tokenbuf == NULL) {
rv = NGTCP2_ERR_NOMEM;
goto fail_token;
}
- memcpy(buf, settings->token, settings->tokenlen);
- (*pconn)->local.settings.token = buf;
+ memcpy(tokenbuf, settings->token, settings->tokenlen);
+ (*pconn)->local.settings.token = tokenbuf;
} else {
(*pconn)->local.settings.token = NULL;
}
+ if (settings->pmtud_probeslen) {
+ (*pconn)->local.settings.pmtud_probes = buf_align(buf);
+ buf = ngtcp2_cpymem((uint16_t *)(*pconn)->local.settings.pmtud_probes,
+ settings->pmtud_probes,
+ sizeof(settings->pmtud_probes[0]) *
+ settings->pmtud_probeslen);
+ }
+
if (!(*pconn)->local.settings.original_version) {
(*pconn)->local.settings.original_version = client_chosen_version;
}
+ ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL);
+ ngtcp2_dcid_set_path(&(*pconn)->dcid.current, path);
+
+ rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1);
+ if (rv != 0) {
+ goto fail_seqgap_push;
+ }
+
conn_reset_conn_stat(*pconn, &(*pconn)->cstat);
(*pconn)->cstat.initial_rtt = settings->initial_rtt;
- (*pconn)->cstat.max_tx_udp_payload_size =
- (*pconn)->local.settings.max_tx_udp_payload_size;
ngtcp2_rst_init(&(*pconn)->rst);
@@ -1224,13 +1259,10 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
goto fail_hs_pktns_init;
}
- rv = pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APPLICATION, &(*pconn)->rst,
- &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log,
- &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc,
- &(*pconn)->frc_objalloc, mem);
- if (rv != 0) {
- goto fail_pktns_init;
- }
+ pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APPLICATION, &(*pconn)->rst,
+ &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log,
+ &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc,
+ &(*pconn)->frc_objalloc, mem);
scident = ngtcp2_mem_malloc(mem, sizeof(*scident));
if (scident == NULL) {
@@ -1249,14 +1281,6 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
scident = NULL;
- ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL);
- ngtcp2_dcid_set_path(&(*pconn)->dcid.current, path);
-
- rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1);
- if (rv != 0) {
- goto fail_seqgap_push;
- }
-
if (settings->preferred_versionslen) {
if (!server && !ngtcp2_is_reserved_version(client_chosen_version)) {
for (i = 0; i < settings->preferred_versionslen; ++i) {
@@ -1268,12 +1292,9 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
assert(i < settings->preferred_versionslen);
}
- preferred_versions = ngtcp2_mem_malloc(
- mem, sizeof(uint32_t) * settings->preferred_versionslen);
- if (preferred_versions == NULL) {
- rv = NGTCP2_ERR_NOMEM;
- goto fail_preferred_versions;
- }
+ preferred_versions = buf_align(buf);
+ buf = buf_advance(preferred_versions, sizeof(preferred_versions[0]) *
+ settings->preferred_versionslen);
for (i = 0; i < settings->preferred_versionslen; ++i) {
assert(ngtcp2_is_supported_version(settings->preferred_versions[i]));
@@ -1304,39 +1325,33 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
ngtcp2_is_supported_version(settings->available_versions[i]));
}
- rv = available_versions_new(&buf, settings->available_versions,
- settings->available_versionslen, mem);
- if (rv != 0) {
- goto fail_available_versions;
- }
-
- (*pconn)->vneg.available_versions = buf;
+ (*pconn)->vneg.available_versions = buf_align(buf);
(*pconn)->vneg.available_versionslen =
sizeof(uint32_t) * settings->available_versionslen;
+
+ buf = available_versions_init((*pconn)->vneg.available_versions,
+ settings->available_versions,
+ settings->available_versionslen);
} else if (server) {
if (settings->preferred_versionslen) {
- rv = available_versions_new(&buf, settings->preferred_versions,
- settings->preferred_versionslen, mem);
- if (rv != 0) {
- goto fail_available_versions;
- }
-
- (*pconn)->vneg.available_versions = buf;
+ (*pconn)->vneg.available_versions = buf_align(buf);
(*pconn)->vneg.available_versionslen =
sizeof(uint32_t) * settings->preferred_versionslen;
+
+ buf = available_versions_init((*pconn)->vneg.available_versions,
+ settings->preferred_versions,
+ settings->preferred_versionslen);
} else {
(*pconn)->vneg.available_versions = server_default_available_versions;
(*pconn)->vneg.available_versionslen =
sizeof(server_default_available_versions);
}
- } else if (!server && !ngtcp2_is_reserved_version(client_chosen_version)) {
- rv = available_versions_new(&buf, &client_chosen_version, 1, mem);
- if (rv != 0) {
- goto fail_available_versions;
- }
-
- (*pconn)->vneg.available_versions = buf;
+ } else if (!ngtcp2_is_reserved_version(client_chosen_version)) {
+ (*pconn)->vneg.available_versions = buf_align(buf);
(*pconn)->vneg.available_versionslen = sizeof(uint32_t);
+
+ buf = available_versions_init((*pconn)->vneg.available_versions,
+ &client_chosen_version, 1);
}
(*pconn)->local.settings.available_versions = NULL;
@@ -1377,34 +1392,19 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
return 0;
-fail_available_versions:
- ngtcp2_mem_free(mem, (*pconn)->vneg.preferred_versions);
-fail_preferred_versions:
-fail_seqgap_push:
fail_scid_set_insert:
ngtcp2_mem_free(mem, scident);
fail_scident:
- pktns_free(&(*pconn)->pktns, mem);
-fail_pktns_init:
pktns_del((*pconn)->hs_pktns, mem);
fail_hs_pktns_init:
pktns_del((*pconn)->in_pktns, mem);
fail_in_pktns_init:
+ ngtcp2_gaptr_free(&(*pconn)->dcid.seqgap);
+fail_seqgap_push:
ngtcp2_mem_free(mem, (uint8_t *)(*pconn)->local.settings.token);
fail_token:
- ngtcp2_mem_free(mem, (*pconn)->qlog.buf.begin);
-fail_qlog_buf:
- ngtcp2_idtr_free(&(*pconn)->remote.uni.idtr);
- ngtcp2_idtr_free(&(*pconn)->remote.bidi.idtr);
- ngtcp2_map_free(&(*pconn)->strms);
- delete_scid(&(*pconn)->scid.set, mem);
- ngtcp2_ksl_free(&(*pconn)->scid.set);
- ngtcp2_gaptr_free(&(*pconn)->dcid.seqgap);
- ngtcp2_objalloc_free(&(*pconn)->strm_objalloc);
- ngtcp2_objalloc_free(&(*pconn)->rtb_entry_objalloc);
- ngtcp2_objalloc_free(&(*pconn)->frc_objalloc);
ngtcp2_mem_free(mem, *pconn);
-fail_conn:
+
return rv;
}
@@ -1471,8 +1471,8 @@ int ngtcp2_conn_server_new_versioned(
* credits are considered.
*/
static uint64_t conn_fc_credits(ngtcp2_conn *conn, ngtcp2_strm *strm) {
- return ngtcp2_min(strm->tx.max_offset - strm->tx.offset,
- conn->tx.max_offset - conn->tx.offset);
+ return ngtcp2_min_uint64(strm->tx.max_offset - strm->tx.offset,
+ conn->tx.max_offset - conn->tx.offset);
}
/*
@@ -1582,11 +1582,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) {
conn_vneg_crypto_free(conn);
- ngtcp2_mem_free(conn->mem, conn->vneg.preferred_versions);
- if (conn->vneg.available_versions != server_default_available_versions) {
- ngtcp2_mem_free(conn->mem, conn->vneg.available_versions);
- }
-
ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_buf.base);
ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_hp_buf.base);
ngtcp2_mem_free(conn->mem, (uint8_t *)conn->local.settings.token);
@@ -1600,8 +1595,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) {
pktns_del(conn->hs_pktns, conn->mem);
pktns_del(conn->in_pktns, conn->mem);
- ngtcp2_mem_free(conn->mem, conn->qlog.buf.begin);
-
ngtcp2_pmtud_del(conn->pmtud);
ngtcp2_pv_del(conn->pv);
@@ -1665,8 +1658,8 @@ static int conn_ensure_ack_ranges(ngtcp2_conn *conn, size_t n) {
* ACK.
*/
static ngtcp2_duration conn_compute_ack_delay(ngtcp2_conn *conn) {
- return ngtcp2_min(conn->local.transport_params.max_ack_delay,
- conn->cstat.smoothed_rtt / 8);
+ return ngtcp2_min_uint64(conn->local.transport_params.max_ack_delay,
+ conn->cstat.smoothed_rtt / 8);
}
int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr,
@@ -2021,12 +2014,13 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left,
return 0;
}
- if (conn->hs_pktns->crypto.tx.ckm &&
- (conn->hs_pktns->rtb.probe_pkt_left ||
- !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm) ||
- !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) {
- /* If we have something to send in Handshake packet, then add
- PADDING in Handshake packet. */
+ if ((conn->hs_pktns->crypto.tx.ckm &&
+ (conn->hs_pktns->rtb.probe_pkt_left ||
+ !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm) ||
+ !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) ||
+ conn->pktns.crypto.tx.ckm) {
+ /* If we have something to send in Handshake or 1RTT packet,
+ then add PADDING in that packet. */
min_payloadlen = NGTCP2_MIN_COALESCED_PAYLOADLEN;
} else {
return 1;
@@ -2195,9 +2189,10 @@ static uint8_t conn_pkt_flags_short(ngtcp2_conn *conn) {
/*
* conn_write_handshake_pkt writes handshake packet in the buffer
- * pointed by |dest| whose length is |destlen|. |type| specifies long
- * packet type. It should be either NGTCP2_PKT_INITIAL or
- * NGTCP2_PKT_HANDSHAKE_PKT.
+ * pointed by |dest| whose length is |destlen|. |dgram_offset| is the
+ * offset in UDP datagram payload where this QUIC packet is positioned
+ * at. |type| specifies long packet type. It should be either
+ * NGTCP2_PKT_INITIAL or NGTCP2_PKT_HANDSHAKE_PKT.
*
* |write_datalen| is the minimum length of application data ready to
* send in subsequent 0RTT packet.
@@ -2212,8 +2207,9 @@ static uint8_t conn_pkt_flags_short(ngtcp2_conn *conn) {
*/
static ngtcp2_ssize
conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest,
- size_t destlen, uint8_t type, uint8_t flags,
- uint64_t write_datalen, ngtcp2_tstamp ts) {
+ size_t destlen, size_t dgram_offset, uint8_t type,
+ uint8_t flags, uint64_t write_datalen,
+ ngtcp2_tstamp ts) {
int rv;
ngtcp2_ppe ppe;
ngtcp2_pkt_hd hd;
@@ -2282,7 +2278,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest,
hd.tokenlen = conn->local.settings.tokenlen;
}
- ngtcp2_ppe_init(&ppe, dest, destlen, &cc);
+ ngtcp2_ppe_init(&ppe, dest, destlen, dgram_offset, &cc);
rv = ngtcp2_ppe_encode_hd(&ppe, &hd);
if (rv != 0) {
@@ -2433,7 +2429,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest,
(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) != 0,
require_padding)) {
lfr.type = NGTCP2_FRAME_PADDING;
- lfr.padding.len = ngtcp2_ppe_padding(&ppe);
+ lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe);
} else if (pkt_empty) {
return 0;
} else {
@@ -2602,11 +2598,7 @@ static void conn_discard_pktns(ngtcp2_conn *conn, ngtcp2_pktns **ppktns,
ngtcp2_conn_set_loss_detection_timer(conn, ts);
}
-/*
- * conn_discard_initial_state discards state for Initial packet number
- * space.
- */
-static void conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
+void ngtcp2_conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
if (!conn->in_pktns) {
return;
}
@@ -2622,11 +2614,7 @@ static void conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
memset(&conn->vneg.tx, 0, sizeof(conn->vneg.tx));
}
-/*
- * conn_discard_handshake_state discards state for Handshake packet
- * number space.
- */
-static void conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
+void ngtcp2_conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
if (!conn->hs_pktns) {
return;
}
@@ -2694,7 +2682,7 @@ static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn,
res += nwrite;
if (!conn->server && nwrite) {
- conn_discard_initial_state(conn, ts);
+ ngtcp2_conn_discard_initial_state(conn, ts);
}
}
@@ -2725,9 +2713,9 @@ static ngtcp2_ssize conn_write_client_initial(ngtcp2_conn *conn,
return rv;
}
- return conn_write_handshake_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL,
- NGTCP2_WRITE_PKT_FLAG_NONE, early_datalen,
- ts);
+ return conn_write_handshake_pkt(
+ conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL,
+ NGTCP2_WRITE_PKT_FLAG_NONE, early_datalen, ts);
}
/*
@@ -2807,10 +2795,10 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn,
conn->hs_pktns->rtb.probe_pkt_left)) {
/* Discard Initial state here so that Handshake packet is not
padded. */
- conn_discard_initial_state(conn, ts);
+ ngtcp2_conn_discard_initial_state(conn, ts);
} else if (conn->in_pktns) {
nwrite =
- conn_write_handshake_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL,
+ conn_write_handshake_pkt(conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL,
NGTCP2_WRITE_PKT_FLAG_NONE, write_datalen, ts);
if (nwrite < 0) {
assert(nwrite != NGTCP2_ERR_NOBUF);
@@ -2837,10 +2825,10 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn,
dest += nwrite;
destlen -= (size_t)nwrite;
- if (destlen) {
- /* We might have already added padding to Initial, but in that
- case, we should have destlen == 0 and no Handshake packet
- will be written. */
+ /* If initial packet size is at least
+ NGTCP2_MAX_UDP_PAYLOAD_SIZE, no extra padding is needed in a
+ subsequent packet. */
+ if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE) {
if (conn->server) {
it = ngtcp2_rtb_head(&conn->in_pktns->rtb);
if (!ngtcp2_ksl_it_end(&it)) {
@@ -2856,8 +2844,9 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn,
}
}
- nwrite = conn_write_handshake_pkt(
- conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, wflags, write_datalen, ts);
+ nwrite =
+ conn_write_handshake_pkt(conn, pi, dest, destlen, (size_t)res,
+ NGTCP2_PKT_HANDSHAKE, wflags, write_datalen, ts);
if (nwrite < 0) {
assert(nwrite != NGTCP2_ERR_NOBUF);
return nwrite;
@@ -2869,7 +2858,7 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn,
/* We don't need to send further Initial packet if we have
Handshake key and sent something with it. So discard initial
state here. */
- conn_discard_initial_state(conn, ts);
+ ngtcp2_conn_discard_initial_state(conn, ts);
}
return res;
@@ -3097,7 +3086,8 @@ static int conn_remove_retired_connection_id(ngtcp2_conn *conn,
* this endpoint sends.
*/
static size_t conn_min_short_pktlen(ngtcp2_conn *conn) {
- return conn->dcid.current.cid.datalen + NGTCP2_MIN_PKT_EXPANDLEN;
+ return ngtcp2_max(conn->dcid.current.cid.datalen, conn->oscid.datalen) +
+ NGTCP2_MIN_PKT_EXPANDLEN;
}
/*
@@ -3155,8 +3145,10 @@ static void conn_reset_ppe_pending(ngtcp2_conn *conn) {
/*
* conn_write_pkt writes a protected packet in the buffer pointed by
- * |dest| whose length if |destlen|. |type| specifies the type of
- * packet. It can be NGTCP2_PKT_1RTT or NGTCP2_PKT_0RTT.
+ * |dest| whose length if |destlen|. |dgram_offset| is the offset in
+ * UDP datagram payload where this QUIC packet is positioned at.
+ * |type| specifies the type of packet. It can be NGTCP2_PKT_1RTT or
+ * NGTCP2_PKT_0RTT.
*
* This function can send new stream data. In order to send stream
* data, specify the underlying stream and parameters to
@@ -3183,8 +3175,9 @@ static void conn_reset_ppe_pending(ngtcp2_conn *conn) {
*/
static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
uint8_t *dest, size_t destlen,
- ngtcp2_vmsg *vmsg, uint8_t type,
- uint8_t flags, ngtcp2_tstamp ts) {
+ size_t dgram_offset, ngtcp2_vmsg *vmsg,
+ uint8_t type, uint8_t flags,
+ ngtcp2_tstamp ts) {
int rv = 0;
ngtcp2_crypto_cc *cc = &conn->pkt.cc;
ngtcp2_ppe *ppe = &conn->pkt.ppe;
@@ -3369,7 +3362,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
pktns->tx.last_pkt_num + 1,
pktns_select_pkt_numlen(pktns), version, 0);
- ngtcp2_ppe_init(ppe, dest, destlen, cc);
+ ngtcp2_ppe_init(ppe, dest, destlen, dgram_offset, cc);
rv = ngtcp2_ppe_encode_hd(ppe, hd);
if (rv != 0) {
@@ -3944,6 +3937,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
vmsg->stream.strm->tx.offset += ndatalen;
conn->tx.offset += ndatalen;
+ vmsg->stream.strm->flags |= NGTCP2_STRM_FLAG_ANY_SENT;
if (fin) {
ngtcp2_strm_shutdown(vmsg->stream.strm, NGTCP2_STRM_FLAG_SHUT_WR);
@@ -4166,10 +4160,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
/* TODO Push STREAM frame back to ngtcp2_strm if there is an error
before ngtcp2_rtb_entry is safely created and added. */
- if (require_padding ||
- /* Making full sized packet will help GSO a bit */
- ngtcp2_ppe_left(ppe) < 10) {
- lfr.padding.len = ngtcp2_ppe_padding(ppe);
+ if (require_padding) {
+ lfr.padding.len = ngtcp2_ppe_dgram_padding(ppe);
} else if (type == NGTCP2_PKT_1RTT) {
lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen);
} else {
@@ -4332,7 +4324,7 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt(
pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns),
version, 0);
- ngtcp2_ppe_init(&ppe, dest, destlen, &cc);
+ ngtcp2_ppe_init(&ppe, dest, destlen, 0, &cc);
rv = ngtcp2_ppe_encode_hd(&ppe, &hd);
if (rv != 0) {
@@ -4354,14 +4346,16 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt(
}
lfr.type = NGTCP2_FRAME_PADDING;
- if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) {
- lfr.padding.len = ngtcp2_ppe_padding(&ppe);
+ if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL) {
+ lfr.padding.len = ngtcp2_ppe_dgram_padding_size(&ppe, destlen);
+ } else if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) {
+ lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe);
} else {
switch (fr->type) {
case NGTCP2_FRAME_PATH_CHALLENGE:
case NGTCP2_FRAME_PATH_RESPONSE:
if (!conn->server || destlen >= NGTCP2_MAX_UDP_PAYLOAD_SIZE) {
- lfr.padding.len = ngtcp2_ppe_padding(&ppe);
+ lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe);
} else {
lfr.padding.len = 0;
}
@@ -4522,6 +4516,10 @@ static int conn_retire_dcid_seq(ngtcp2_conn *conn, uint64_t seq) {
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;
@@ -4664,7 +4662,9 @@ static int conn_start_pmtud(ngtcp2_conn *conn) {
rv = ngtcp2_pmtud_new(&conn->pmtud, conn->dcid.current.max_udp_payload_size,
hard_max_udp_payload_size,
- conn->pktns.tx.last_pkt_num + 1, conn->mem);
+ conn->pktns.tx.last_pkt_num + 1,
+ conn->local.settings.pmtud_probes,
+ conn->local.settings.pmtud_probeslen, conn->mem);
if (rv != 0) {
return rv;
}
@@ -4716,7 +4716,7 @@ static ngtcp2_ssize conn_write_pmtud_probe(ngtcp2_conn *conn,
nwrite = ngtcp2_conn_write_single_frame_pkt(
conn, pi, dest, probelen, NGTCP2_PKT_1RTT,
- NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING, &conn->dcid.current.cid, &lfr,
+ NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL, &conn->dcid.current.cid, &lfr,
NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING |
NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING |
NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE,
@@ -6833,6 +6833,12 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm,
return rv;
}
+ /* ngtcp2_conn_shutdown_stream_read from a callback will free
+ strm->rx.rob. */
+ if (!strm->rx.rob) {
+ return 0;
+ }
+
ngtcp2_rob_pop(strm->rx.rob, rx_offset - datalen, datalen);
}
}
@@ -8221,7 +8227,7 @@ static int conn_recv_handshake_done(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
conn->pktns.rtb.persistent_congestion_start_ts = ts;
- conn_discard_handshake_state(conn, ts);
+ ngtcp2_conn_discard_handshake_state(conn, ts);
assert(conn->remote.transport_params);
@@ -8550,13 +8556,13 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn,
pv->fallback_pto = pto;
}
+ 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);
}
- ngtcp2_dcid_copy(&conn->dcid.current, &dcid);
-
conn_reset_ecn_validation_state(conn);
ngtcp2_conn_stop_pmtud(conn);
@@ -9822,7 +9828,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn,
}
if (conn->hs_pktns->rx.max_pkt_num != -1) {
- conn_discard_initial_state(conn, ts);
+ ngtcp2_conn_discard_initial_state(conn, ts);
}
if (!conn_is_tls_handshake_completed(conn)) {
@@ -9888,7 +9894,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn,
return rv;
}
- conn_discard_handshake_state(conn, ts);
+ ngtcp2_conn_discard_handshake_state(conn, ts);
rv = conn_enqueue_handshake_done(conn);
if (rv != 0) {
@@ -9936,7 +9942,7 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path,
pktlen);
if (pktlen == 0) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
+ return 0;
}
/* client does not expect a packet from unknown path. */
@@ -10035,13 +10041,12 @@ static int conn_check_pkt_num_exhausted(ngtcp2_conn *conn) {
* conn_retransmit_retry_early retransmits 0RTT packet after Retry is
* received from server.
*/
-static ngtcp2_ssize conn_retransmit_retry_early(ngtcp2_conn *conn,
- ngtcp2_pkt_info *pi,
- uint8_t *dest, size_t destlen,
- uint8_t flags,
- ngtcp2_tstamp ts) {
- return conn_write_pkt(conn, pi, dest, destlen, NULL, NGTCP2_PKT_0RTT, flags,
- ts);
+static ngtcp2_ssize
+conn_retransmit_retry_early(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
+ uint8_t *dest, size_t destlen, size_t dgram_offset,
+ uint8_t flags, ngtcp2_tstamp ts) {
+ return conn_write_pkt(conn, pi, dest, destlen, dgram_offset, NULL,
+ NGTCP2_PKT_0RTT, flags, ts);
}
/*
@@ -10137,7 +10142,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
}
} else {
nwrite = conn_write_handshake_pkt(
- conn, pi, dest, destlen, NGTCP2_PKT_INITIAL,
+ conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL,
NGTCP2_WRITE_PKT_FLAG_NONE, write_datalen, ts);
if (nwrite < 0) {
return nwrite;
@@ -10146,7 +10151,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
if (pending_early_datalen) {
early_spktlen = conn_retransmit_retry_early(
- conn, pi, dest + nwrite, destlen - (size_t)nwrite,
+ conn, pi, dest + nwrite, destlen - (size_t)nwrite, (size_t)nwrite,
nwrite ? NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING
: NGTCP2_WRITE_PKT_FLAG_NONE,
ts);
@@ -10186,8 +10191,9 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi,
if (!conn_is_tls_handshake_completed(conn)) {
if (!(conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED)) {
- nwrite = conn_retransmit_retry_early(conn, pi, dest, destlen,
- NGTCP2_WRITE_PKT_FLAG_NONE, ts);
+ nwrite =
+ conn_retransmit_retry_early(conn, pi, dest, destlen, (size_t)res,
+ NGTCP2_WRITE_PKT_FLAG_NONE, ts);
if (nwrite < 0) {
return nwrite;
}
@@ -10363,8 +10369,8 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn,
datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt);
send_stream = conn_retry_early_payloadlen(conn) == 0;
if (send_stream) {
- write_datalen = ngtcp2_min(datalen + NGTCP2_STREAM_OVERHEAD,
- NGTCP2_MIN_COALESCED_PAYLOADLEN);
+ write_datalen = ngtcp2_min_uint64(datalen + NGTCP2_STREAM_OVERHEAD,
+ NGTCP2_MIN_COALESCED_PAYLOADLEN);
if (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_MORE) {
wflags |= NGTCP2_WRITE_PKT_FLAG_MORE;
@@ -10428,8 +10434,8 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn,
return spktlen;
}
- early_spktlen = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_0RTT,
- wflags, ts);
+ early_spktlen = conn_write_pkt(conn, pi, dest, destlen, (size_t)spktlen, vmsg,
+ NGTCP2_PKT_0RTT, wflags, ts);
if (early_spktlen < 0) {
switch (early_spktlen) {
case NGTCP2_ERR_STREAM_DATA_BLOCKED:
@@ -10905,7 +10911,7 @@ ngtcp2_tstamp ngtcp2_conn_loss_detection_expiry(ngtcp2_conn *conn) {
}
ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) {
- ngtcp2_tstamp res = UINT64_MAX, t;
+ ngtcp2_tstamp res = UINT64_MAX;
ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns);
ngtcp2_scid *scid;
ngtcp2_dcid *dcid;
@@ -10922,15 +10928,13 @@ ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) {
if (!ngtcp2_pq_empty(&conn->scid.used)) {
scid = ngtcp2_struct_of(ngtcp2_pq_top(&conn->scid.used), ngtcp2_scid, pe);
if (scid->retired_ts != UINT64_MAX) {
- t = scid->retired_ts + pto;
- res = ngtcp2_min(res, t);
+ res = ngtcp2_min_uint64(res, scid->retired_ts + pto);
}
}
if (ngtcp2_ringbuf_len(&conn->dcid.retired.rb)) {
dcid = ngtcp2_ringbuf_get(&conn->dcid.retired.rb, 0);
- t = dcid->retired_ts + pto;
- res = ngtcp2_min(res, t);
+ res = ngtcp2_min_uint64(res, dcid->retired_ts + pto);
}
if (conn->dcid.current.cid.datalen) {
@@ -10941,15 +10945,13 @@ ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) {
assert(dcid->cid.datalen);
assert(dcid->bound_ts != UINT64_MAX);
- t = dcid->bound_ts + 3 * pto;
- res = ngtcp2_min(res, t);
+ res = ngtcp2_min_uint64(res, dcid->bound_ts + 3 * pto);
}
}
if (conn->server && conn->early.ckm &&
conn->early.discard_started_ts != UINT64_MAX) {
- t = conn->early.discard_started_ts + 3 * pto;
- res = ngtcp2_min(res, t);
+ res = ngtcp2_min_uint64(res, conn->early.discard_started_ts + 3 * pto);
}
return res;
@@ -10978,19 +10980,13 @@ static ngtcp2_tstamp conn_handshake_expiry(ngtcp2_conn *conn) {
}
ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn) {
- ngtcp2_tstamp t1 = ngtcp2_conn_loss_detection_expiry(conn);
- ngtcp2_tstamp t2 = ngtcp2_conn_ack_delay_expiry(conn);
- ngtcp2_tstamp t3 = ngtcp2_conn_internal_expiry(conn);
- ngtcp2_tstamp t4 = ngtcp2_conn_lost_pkt_expiry(conn);
- ngtcp2_tstamp t5 = conn_keep_alive_expiry(conn);
- ngtcp2_tstamp t6 = conn_handshake_expiry(conn);
- ngtcp2_tstamp t7 = ngtcp2_conn_get_idle_expiry(conn);
- ngtcp2_tstamp res = ngtcp2_min(t1, t2);
- res = ngtcp2_min(res, t3);
- res = ngtcp2_min(res, t4);
- res = ngtcp2_min(res, t5);
- res = ngtcp2_min(res, t6);
- res = ngtcp2_min(res, t7);
+ ngtcp2_tstamp res = ngtcp2_min_uint64(ngtcp2_conn_loss_detection_expiry(conn),
+ ngtcp2_conn_ack_delay_expiry(conn));
+ res = ngtcp2_min_uint64(res, ngtcp2_conn_internal_expiry(conn));
+ res = ngtcp2_min_uint64(res, ngtcp2_conn_lost_pkt_expiry(conn));
+ res = ngtcp2_min_uint64(res, conn_keep_alive_expiry(conn));
+ res = ngtcp2_min_uint64(res, conn_handshake_expiry(conn));
+ res = ngtcp2_min_uint64(res, ngtcp2_conn_get_idle_expiry(conn));
return ngtcp2_min(res, conn->tx.pacing.next_ts);
}
@@ -11734,19 +11730,24 @@ ngtcp2_ssize ngtcp2_conn_writev_stream_versioned(
return NGTCP2_ERR_INVALID_ARGUMENT;
}
- if ((uint64_t)datalen > NGTCP2_MAX_VARINT - strm->tx.offset ||
- (uint64_t)datalen > NGTCP2_MAX_VARINT - conn->tx.offset) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
+ if (datalen == 0 && !(flags & NGTCP2_WRITE_STREAM_FLAG_FIN) &&
+ (strm->flags & NGTCP2_STRM_FLAG_ANY_SENT)) {
+ pvmsg = NULL;
+ } else {
+ if ((uint64_t)datalen > NGTCP2_MAX_VARINT - strm->tx.offset ||
+ (uint64_t)datalen > NGTCP2_MAX_VARINT - conn->tx.offset) {
+ return NGTCP2_ERR_INVALID_ARGUMENT;
+ }
- vmsg.type = NGTCP2_VMSG_TYPE_STREAM;
- vmsg.stream.strm = strm;
- vmsg.stream.flags = flags;
- vmsg.stream.data = datav;
- vmsg.stream.datacnt = datavcnt;
- vmsg.stream.pdatalen = pdatalen;
+ vmsg.type = NGTCP2_VMSG_TYPE_STREAM;
+ vmsg.stream.strm = strm;
+ vmsg.stream.flags = flags;
+ vmsg.stream.data = datav;
+ vmsg.stream.datacnt = datavcnt;
+ vmsg.stream.pdatalen = pdatalen;
- pvmsg = &vmsg;
+ pvmsg = &vmsg;
+ }
} else {
pvmsg = NULL;
}
@@ -11867,10 +11868,9 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
assert(dest[0] & NGTCP2_HEADER_FORM_BIT);
assert(conn->negotiated_version);
- if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) ==
- NGTCP2_PKT_INITIAL) {
- /* We have added padding already, but in that case, there is no
- space left to write 1RTT packet. */
+ if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE &&
+ ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) ==
+ NGTCP2_PKT_INITIAL) {
wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
}
@@ -11931,14 +11931,12 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
dest += nwrite;
destlen -= (size_t)nwrite;
- if (conn->in_pktns && nwrite > 0) {
+ if (res < NGTCP2_MAX_UDP_PAYLOAD_SIZE && conn->in_pktns && nwrite > 0) {
it = ngtcp2_rtb_head(&conn->in_pktns->rtb);
if (!ngtcp2_ksl_it_end(&it)) {
rtbent = ngtcp2_ksl_it_get(&it);
if (rtbent->hd.pkt_num != prev_in_pkt_num &&
(rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) {
- /* We have added padding already, but in that case, there
- is no space left to write 1RTT packet. */
wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
}
}
@@ -12004,8 +12002,8 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
}
/* dest and destlen have already been adjusted in ppe in the first
run. They are adjusted for probe packet later. */
- nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT,
- wflags, ts);
+ nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg,
+ NGTCP2_PKT_1RTT, wflags, ts);
goto fin;
} else {
conn->pkt.require_padding =
@@ -12100,14 +12098,14 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
"transmit probe pkt left=%zu",
conn->pktns.rtb.probe_pkt_left);
- nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT,
- wflags, ts);
+ nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg,
+ NGTCP2_PKT_1RTT, wflags, ts);
goto fin;
}
- nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT,
- wflags, ts);
+ nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg,
+ NGTCP2_PKT_1RTT, wflags, ts);
if (nwrite) {
assert(nwrite != NGTCP2_ERR_NOBUF);
goto fin;
@@ -12326,12 +12324,9 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt(
destlen -= (size_t)nwrite;
}
- if (conn->state != NGTCP2_CS_POST_HANDSHAKE) {
- assert(res);
-
- if (!conn->server || !conn->pktns.crypto.tx.ckm) {
- return res;
- }
+ if (conn->state != NGTCP2_CS_POST_HANDSHAKE &&
+ (!conn->server || !conn->pktns.crypto.tx.ckm)) {
+ return res;
}
assert(conn->pktns.crypto.tx.ckm);
@@ -12393,6 +12388,16 @@ void ngtcp2_ccerr_set_liberr(ngtcp2_ccerr *ccerr, int liberr,
reasonlen);
return;
+ case NGTCP2_ERR_DROP_CONN:
+ ccerr_init(ccerr, NGTCP2_CCERR_TYPE_DROP_CONN, NGTCP2_NO_ERROR, reason,
+ reasonlen);
+
+ return;
+ case NGTCP2_ERR_RETRY:
+ ccerr_init(ccerr, NGTCP2_CCERR_TYPE_RETRY, NGTCP2_NO_ERROR, reason,
+ reasonlen);
+
+ return;
};
ngtcp2_ccerr_set_transport_error(
@@ -13597,20 +13602,11 @@ size_t ngtcp2_conn_get_send_quantum(ngtcp2_conn *conn) {
}
int ngtcp2_conn_track_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) {
- size_t i;
-
if (conn->dcid.retire_unacked.len >=
ngtcp2_arraylen(conn->dcid.retire_unacked.seqs)) {
return NGTCP2_ERR_CONNECTION_ID_LIMIT;
}
- /* Make sure that we do not have a duplicate */
- for (i = 0; i < conn->dcid.retire_unacked.len; ++i) {
- if (conn->dcid.retire_unacked.seqs[i] == seq) {
- ngtcp2_unreachable();
- }
- }
-
conn->dcid.retire_unacked.seqs[conn->dcid.retire_unacked.len++] = seq;
return 0;
@@ -13635,6 +13631,18 @@ void ngtcp2_conn_untrack_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) {
}
}
+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);
@@ -13652,45 +13660,6 @@ void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent,
memcpy(pcent->data, data, sizeof(pcent->data));
}
-void ngtcp2_settings_default_versioned(int settings_version,
- ngtcp2_settings *settings) {
- (void)settings_version;
-
- memset(settings, 0, sizeof(*settings));
- settings->cc_algo = NGTCP2_CC_ALGO_CUBIC;
- settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT;
- settings->ack_thresh = 2;
- settings->max_tx_udp_payload_size = 1500 - 48;
- settings->handshake_timeout = UINT64_MAX;
-}
-
-void ngtcp2_transport_params_default_versioned(
- int transport_params_version, ngtcp2_transport_params *params) {
- size_t len;
-
- switch (transport_params_version) {
- case NGTCP2_TRANSPORT_PARAMS_VERSION:
- len = sizeof(*params);
-
- break;
- default:
- ngtcp2_unreachable();
- }
-
- memset(params, 0, len);
-
- switch (transport_params_version) {
- case NGTCP2_TRANSPORT_PARAMS_VERSION:
- params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE;
- params->active_connection_id_limit =
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
- params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
- params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
-
- break;
- }
-}
-
/* The functions prefixed with ngtcp2_pkt_ are usually put inside
ngtcp2_pkt.c. This function uses encryption construct and uses
test data defined only in ngtcp2_conn_test.c, so it is written
@@ -13726,7 +13695,7 @@ ngtcp2_ssize ngtcp2_pkt_write_connection_close(
cc.encrypt = encrypt;
cc.hp_mask = hp_mask;
- ngtcp2_ppe_init(&ppe, dest, destlen, &cc);
+ ngtcp2_ppe_init(&ppe, dest, destlen, 0, &cc);
rv = ngtcp2_ppe_encode_hd(&ppe, &hd);
if (rv != 0) {
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h
index 4ed6787..1172816 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h
@@ -65,9 +65,6 @@ typedef enum {
NGTCP2_CS_DRAINING,
} ngtcp2_conn_state;
-/* NGTCP2_MAX_STREAMS is the maximum number of streams. */
-#define NGTCP2_MAX_STREAMS (1LL << 60)
-
/* NGTCP2_MAX_NUM_BUFFED_RX_PKTS is the maximum number of buffered
reordered packets. */
#define NGTCP2_MAX_NUM_BUFFED_RX_PKTS 4
@@ -121,12 +118,18 @@ typedef enum {
/* NGTCP2_WRITE_PKT_FLAG_NONE indicates that no flag is set. */
#define NGTCP2_WRITE_PKT_FLAG_NONE 0x00u
/* NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING indicates that packet other
- than Initial packet should be padded. Initial packet might be
- padded based on QUIC requirement regardless of this flag. */
+ than Initial packet should be padded so that UDP datagram payload
+ is at least NGTCP2_MAX_UDP_PAYLOAD_SIZE bytes. Initial packet
+ might be padded based on QUIC requirement regardless of this
+ flag. */
#define NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING 0x01u
/* NGTCP2_WRITE_PKT_FLAG_MORE indicates that more frames might come
and it should be encoded into the current packet. */
#define NGTCP2_WRITE_PKT_FLAG_MORE 0x02u
+/* NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL is just like
+ NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING, but it requests to add
+ padding to the full UDP datagram payload size. */
+#define NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL 0x04u
/*
* ngtcp2_max_frame is defined so that it covers the largest ACK
@@ -974,6 +977,12 @@ int ngtcp2_conn_track_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq);
void ngtcp2_conn_untrack_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq);
/*
+ * ngtcp2_conn_check_retired_dcid_tracked returns nonzero if |seq| has
+ * already been tracked.
+ */
+int ngtcp2_conn_check_retired_dcid_tracked(ngtcp2_conn *conn, uint64_t seq);
+
+/*
* ngtcp2_conn_server_negotiate_version negotiates QUIC version. It
* is compatible version negotiation. It returns the negotiated QUIC
* version. This function must not be called by client.
@@ -1156,4 +1165,16 @@ int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr,
ngtcp2_tstamp ts, ngtcp2_duration ack_delay,
uint64_t ack_delay_exponent);
+/*
+ * ngtcp2_conn_discard_initial_state discards state for Initial packet
+ * number space.
+ */
+void ngtcp2_conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts);
+
+/*
+ * ngtcp2_conn_discard_handshake_state discards state for Handshake
+ * packet number space.
+ */
+void ngtcp2_conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts);
+
#endif /* NGTCP2_CONN_H */
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c
deleted file mode 100644
index eb85687..0000000
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2023 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_conversion.h"
-
-#include <string.h>
-#include <assert.h>
-
-static void transport_params_copy(int transport_params_version,
- ngtcp2_transport_params *dest,
- const ngtcp2_transport_params *src) {
- assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION);
-
- switch (transport_params_version) {
- case NGTCP2_TRANSPORT_PARAMS_V1:
- memcpy(dest, src,
- offsetof(ngtcp2_transport_params, version_info_present) +
- sizeof(src->version_info_present));
-
- break;
- }
-}
-
-const ngtcp2_transport_params *
-ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest,
- int transport_params_version,
- const ngtcp2_transport_params *src) {
- if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) {
- return src;
- }
-
- ngtcp2_transport_params_default(dest);
-
- transport_params_copy(transport_params_version, dest, src);
-
- return dest;
-}
-
-void ngtcp2_transport_params_convert_to_old(
- int transport_params_version, ngtcp2_transport_params *dest,
- const ngtcp2_transport_params *src) {
- assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION);
-
- transport_params_copy(transport_params_version, dest, src);
-}
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c
index 0a3ecf6..9f61791 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c
@@ -27,11 +27,7 @@
#include <string.h>
#include <assert.h>
-#include "ngtcp2_str.h"
-#include "ngtcp2_conv.h"
-#include "ngtcp2_conn.h"
#include "ngtcp2_net.h"
-#include "ngtcp2_conversion.h"
int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
size_t secretlen,
@@ -85,6 +81,16 @@ void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem) {
return;
}
+ if (ckm->secret.len) {
+#ifdef WIN32
+ SecureZeroMemory(ckm->secret.base, ckm->secret.len);
+#elif defined(HAVE_EXPLICIT_BZERO)
+ explicit_bzero(ckm->secret.base, ckm->secret.len);
+#elif defined(HAVE_MEMSET_S)
+ memset_s(ckm->secret.base, ckm->secret.len, 0, ckm->secret.len);
+#endif /* HAVE_MEMSET_S */
+ }
+
ngtcp2_mem_free(mem, ckm);
}
@@ -102,808 +108,3 @@ void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen,
dest[ivlen - 8 + i] ^= ((uint8_t *)&n)[i];
}
}
-
-/*
- * varint_paramlen returns the length of a single transport parameter
- * which has variable integer in its parameter.
- */
-static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) {
- size_t valuelen = ngtcp2_put_uvarintlen(param);
- return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(valuelen) + valuelen;
-}
-
-/*
- * write_varint_param writes parameter |id| of the given |value| in
- * varint encoding. It returns p + the number of bytes written.
- */
-static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id,
- uint64_t value) {
- p = ngtcp2_put_uvarint(p, id);
- p = ngtcp2_put_uvarint(p, ngtcp2_put_uvarintlen(value));
- return ngtcp2_put_uvarint(p, value);
-}
-
-/*
- * zero_paramlen returns the length of a single transport parameter
- * which has zero length value in its parameter.
- */
-static size_t zero_paramlen(ngtcp2_transport_param_id id) {
- return ngtcp2_put_uvarintlen(id) + 1;
-}
-
-/*
- * write_zero_param writes parameter |id| that has zero length value.
- * It returns p + the number of bytes written.
- */
-static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) {
- p = ngtcp2_put_uvarint(p, id);
- *p++ = 0;
-
- return p;
-}
-
-/*
- * cid_paramlen returns the length of a single transport parameter
- * which has |cid| as value.
- */
-static size_t cid_paramlen(ngtcp2_transport_param_id id,
- const ngtcp2_cid *cid) {
- return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(cid->datalen) +
- cid->datalen;
-}
-
-/*
- * write_cid_param writes parameter |id| of the given |cid|. It
- * returns p + the number of bytes written.
- */
-static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id,
- const ngtcp2_cid *cid) {
- assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN);
- assert(cid->datalen <= NGTCP2_MAX_CIDLEN);
-
- p = ngtcp2_put_uvarint(p, id);
- p = ngtcp2_put_uvarint(p, cid->datalen);
- if (cid->datalen) {
- p = ngtcp2_cpymem(p, cid->data, cid->datalen);
- }
- return p;
-}
-
-static const uint8_t empty_address[16];
-
-ngtcp2_ssize ngtcp2_transport_params_encode_versioned(
- uint8_t *dest, size_t destlen, int transport_params_version,
- const ngtcp2_transport_params *params) {
- uint8_t *p;
- size_t len = 0;
- /* For some reason, gcc 7.3.0 requires this initialization. */
- size_t preferred_addrlen = 0;
- size_t version_infolen = 0;
- const ngtcp2_sockaddr_in *sa_in;
- const ngtcp2_sockaddr_in6 *sa_in6;
- ngtcp2_transport_params paramsbuf;
-
- params = ngtcp2_transport_params_convert_to_latest(
- &paramsbuf, transport_params_version, params);
-
- if (params->original_dcid_present) {
- len +=
- cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
- &params->original_dcid);
- }
-
- if (params->stateless_reset_token_present) {
- len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) +
- ngtcp2_put_uvarintlen(NGTCP2_STATELESS_RESET_TOKENLEN) +
- NGTCP2_STATELESS_RESET_TOKENLEN;
- }
-
- if (params->preferred_addr_present) {
- assert(params->preferred_addr.cid.datalen >= NGTCP2_MIN_CIDLEN);
- assert(params->preferred_addr.cid.datalen <= NGTCP2_MAX_CIDLEN);
- preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ +
- 16 /* ipv6Address */ + 2 /* ipv6Port */
- + 1 + params->preferred_addr.cid.datalen /* CID */ +
- NGTCP2_STATELESS_RESET_TOKENLEN;
- len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) +
- ngtcp2_put_uvarintlen(preferred_addrlen) + preferred_addrlen;
- }
- if (params->retry_scid_present) {
- len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
- &params->retry_scid);
- }
-
- if (params->initial_scid_present) {
- len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
- &params->initial_scid);
- }
-
- if (params->initial_max_stream_data_bidi_local) {
- len += varint_paramlen(
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
- params->initial_max_stream_data_bidi_local);
- }
- if (params->initial_max_stream_data_bidi_remote) {
- len += varint_paramlen(
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
- params->initial_max_stream_data_bidi_remote);
- }
- if (params->initial_max_stream_data_uni) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
- params->initial_max_stream_data_uni);
- }
- if (params->initial_max_data) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
- params->initial_max_data);
- }
- if (params->initial_max_streams_bidi) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
- params->initial_max_streams_bidi);
- }
- if (params->initial_max_streams_uni) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
- params->initial_max_streams_uni);
- }
- if (params->max_udp_payload_size !=
- NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
- params->max_udp_payload_size);
- }
- if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
- params->ack_delay_exponent);
- }
- if (params->disable_active_migration) {
- len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
- }
- if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
- params->max_ack_delay / NGTCP2_MILLISECONDS);
- }
- if (params->max_idle_timeout) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
- params->max_idle_timeout / NGTCP2_MILLISECONDS);
- }
- if (params->active_connection_id_limit &&
- params->active_connection_id_limit !=
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
- params->active_connection_id_limit);
- }
- if (params->max_datagram_frame_size) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
- params->max_datagram_frame_size);
- }
- if (params->grease_quic_bit) {
- len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT);
- }
- if (params->version_info_present) {
- version_infolen =
- sizeof(uint32_t) + params->version_info.available_versionslen;
- len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION) +
- ngtcp2_put_uvarintlen(version_infolen) + version_infolen;
- }
-
- if (dest == NULL && destlen == 0) {
- return (ngtcp2_ssize)len;
- }
-
- if (destlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = dest;
-
- if (params->original_dcid_present) {
- p = write_cid_param(
- p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
- &params->original_dcid);
- }
-
- if (params->stateless_reset_token_present) {
- p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN);
- p = ngtcp2_put_uvarint(p, sizeof(params->stateless_reset_token));
- p = ngtcp2_cpymem(p, params->stateless_reset_token,
- sizeof(params->stateless_reset_token));
- }
-
- if (params->preferred_addr_present) {
- p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS);
- p = ngtcp2_put_uvarint(p, preferred_addrlen);
-
- if (params->preferred_addr.ipv4_present) {
- sa_in = &params->preferred_addr.ipv4;
- p = ngtcp2_cpymem(p, &sa_in->sin_addr, sizeof(sa_in->sin_addr));
- p = ngtcp2_put_uint16(p, sa_in->sin_port);
- } else {
- p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in->sin_addr));
- p = ngtcp2_put_uint16(p, 0);
- }
-
- if (params->preferred_addr.ipv6_present) {
- sa_in6 = &params->preferred_addr.ipv6;
- p = ngtcp2_cpymem(p, &sa_in6->sin6_addr, sizeof(sa_in6->sin6_addr));
- p = ngtcp2_put_uint16(p, sa_in6->sin6_port);
- } else {
- p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in6->sin6_addr));
- p = ngtcp2_put_uint16(p, 0);
- }
-
- *p++ = (uint8_t)params->preferred_addr.cid.datalen;
- if (params->preferred_addr.cid.datalen) {
- p = ngtcp2_cpymem(p, params->preferred_addr.cid.data,
- params->preferred_addr.cid.datalen);
- }
- p = ngtcp2_cpymem(p, params->preferred_addr.stateless_reset_token,
- sizeof(params->preferred_addr.stateless_reset_token));
- }
-
- if (params->retry_scid_present) {
- p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
- &params->retry_scid);
- }
-
- if (params->initial_scid_present) {
- p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
- &params->initial_scid);
- }
-
- if (params->initial_max_stream_data_bidi_local) {
- p = write_varint_param(
- p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
- params->initial_max_stream_data_bidi_local);
- }
-
- if (params->initial_max_stream_data_bidi_remote) {
- p = write_varint_param(
- p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
- params->initial_max_stream_data_bidi_remote);
- }
-
- if (params->initial_max_stream_data_uni) {
- p = write_varint_param(p,
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
- params->initial_max_stream_data_uni);
- }
-
- if (params->initial_max_data) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
- params->initial_max_data);
- }
-
- if (params->initial_max_streams_bidi) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
- params->initial_max_streams_bidi);
- }
-
- if (params->initial_max_streams_uni) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
- params->initial_max_streams_uni);
- }
-
- if (params->max_udp_payload_size !=
- NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
- params->max_udp_payload_size);
- }
-
- if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
- params->ack_delay_exponent);
- }
-
- if (params->disable_active_migration) {
- p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
- }
-
- if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
- params->max_ack_delay / NGTCP2_MILLISECONDS);
- }
-
- if (params->max_idle_timeout) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
- params->max_idle_timeout / NGTCP2_MILLISECONDS);
- }
-
- if (params->active_connection_id_limit &&
- params->active_connection_id_limit !=
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
- params->active_connection_id_limit);
- }
-
- if (params->max_datagram_frame_size) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
- params->max_datagram_frame_size);
- }
-
- if (params->grease_quic_bit) {
- p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT);
- }
-
- if (params->version_info_present) {
- p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION);
- p = ngtcp2_put_uvarint(p, version_infolen);
- p = ngtcp2_put_uint32be(p, params->version_info.chosen_version);
- if (params->version_info.available_versionslen) {
- p = ngtcp2_cpymem(p, params->version_info.available_versions,
- params->version_info.available_versionslen);
- }
- }
-
- assert((size_t)(p - dest) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-/*
- * decode_varint decodes a single varint from the buffer pointed by
- * |*pp| of length |end - *pp|. If it decodes an integer
- * successfully, it stores the integer in |*pdest|, increment |*pp| by
- * the number of bytes read from |*pp|, and returns 0. Otherwise it
- * returns -1.
- */
-static int decode_varint(uint64_t *pdest, const uint8_t **pp,
- const uint8_t *end) {
- const uint8_t *p = *pp;
- size_t len;
-
- if (p == end) {
- return -1;
- }
-
- len = ngtcp2_get_uvarintlen(p);
- if ((uint64_t)(end - p) < len) {
- return -1;
- }
-
- *pp = ngtcp2_get_uvarint(pdest, p);
-
- return 0;
-}
-
-/*
- * decode_varint_param decodes length prefixed value from the buffer
- * pointed by |*pp| of length |end - *pp|. The length and value are
- * encoded in varint form. If it decodes a value successfully, it
- * stores the value in |*pdest|, increment |*pp| by the number of
- * bytes read from |*pp|, and returns 0. Otherwise it returns -1.
- */
-static int decode_varint_param(uint64_t *pdest, const uint8_t **pp,
- const uint8_t *end) {
- const uint8_t *p = *pp;
- uint64_t valuelen;
-
- if (decode_varint(&valuelen, &p, end) != 0) {
- return -1;
- }
-
- if (p == end) {
- return -1;
- }
-
- if ((uint64_t)(end - p) < valuelen) {
- return -1;
- }
-
- if (ngtcp2_get_uvarintlen(p) != valuelen) {
- return -1;
- }
-
- *pp = ngtcp2_get_uvarint(pdest, p);
-
- return 0;
-}
-
-/*
- * decode_zero_param decodes zero length value from the buffer pointed
- * by |*pp| of length |end - *pp|. The length is encoded in varint
- * form. If it decodes zero length value successfully, it increments
- * |*pp| by 1, and returns 0. Otherwise it returns -1.
- */
-static int decode_zero_param(const uint8_t **pp, const uint8_t *end) {
- if (*pp == end || **pp != 0) {
- return -1;
- }
-
- ++*pp;
-
- return 0;
-}
-
-/*
- * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer
- * pointed by |*pp| of length |end - *pp|. The length is encoded in
- * varint form. If it decodes a value successfully, it stores the
- * value in |*pdest|, increment |*pp| by the number of read from
- * |*pp|, and returns the number of bytes read. Otherwise it returns
- * the one of the negative error code:
- *
- * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM
- * Could not decode Connection ID.
- */
-static int decode_cid_param(ngtcp2_cid *pdest, const uint8_t **pp,
- const uint8_t *end) {
- const uint8_t *p = *pp;
- uint64_t valuelen;
-
- if (decode_varint(&valuelen, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) ||
- valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- ngtcp2_cid_init(pdest, p, (size_t)valuelen);
-
- p += valuelen;
-
- *pp = p;
-
- return 0;
-}
-
-int ngtcp2_transport_params_decode_versioned(int transport_params_version,
- ngtcp2_transport_params *dest,
- const uint8_t *data,
- size_t datalen) {
- const uint8_t *p, *end, *lend;
- size_t len;
- uint64_t param_type;
- uint64_t valuelen;
- int rv;
- ngtcp2_sockaddr_in *sa_in;
- ngtcp2_sockaddr_in6 *sa_in6;
- uint32_t version;
- ngtcp2_transport_params *params, paramsbuf;
-
- if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) {
- params = dest;
- } else {
- params = &paramsbuf;
- }
-
- /* Set default values */
- memset(params, 0, sizeof(*params));
- params->original_dcid_present = 0;
- params->initial_scid_present = 0;
- params->initial_max_streams_bidi = 0;
- params->initial_max_streams_uni = 0;
- params->initial_max_stream_data_bidi_local = 0;
- params->initial_max_stream_data_bidi_remote = 0;
- params->initial_max_stream_data_uni = 0;
- params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE;
- params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
- params->stateless_reset_token_present = 0;
- params->preferred_addr_present = 0;
- params->disable_active_migration = 0;
- params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
- params->max_idle_timeout = 0;
- params->active_connection_id_limit =
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
- params->retry_scid_present = 0;
- params->max_datagram_frame_size = 0;
- memset(&params->retry_scid, 0, sizeof(params->retry_scid));
- memset(&params->initial_scid, 0, sizeof(params->initial_scid));
- memset(&params->original_dcid, 0, sizeof(params->original_dcid));
- params->version_info_present = 0;
-
- p = data;
- end = data + datalen;
-
- for (; (size_t)(end - p) >= 2;) {
- if (decode_varint(&param_type, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- switch (param_type) {
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
- if (decode_varint_param(&params->initial_max_stream_data_bidi_local, &p,
- end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
- if (decode_varint_param(&params->initial_max_stream_data_bidi_remote, &p,
- end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI:
- if (decode_varint_param(&params->initial_max_stream_data_uni, &p, end) !=
- 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA:
- if (decode_varint_param(&params->initial_max_data, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI:
- if (decode_varint_param(&params->initial_max_streams_bidi, &p, end) !=
- 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI:
- if (decode_varint_param(&params->initial_max_streams_uni, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT:
- if (decode_varint_param(&params->max_idle_timeout, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- params->max_idle_timeout *= NGTCP2_MILLISECONDS;
- break;
- case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE:
- if (decode_varint_param(&params->max_udp_payload_size, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN:
- if (decode_varint(&valuelen, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if ((size_t)valuelen != sizeof(params->stateless_reset_token)) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- p = ngtcp2_get_bytes(params->stateless_reset_token, p,
- sizeof(params->stateless_reset_token));
- params->stateless_reset_token_present = 1;
-
- break;
- case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT:
- if (decode_varint_param(&params->ack_delay_exponent, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (params->ack_delay_exponent > 20) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS:
- if (decode_varint(&valuelen, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if ((size_t)(end - p) < valuelen) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ +
- 2 /* ipv6Port */
- + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN;
- if (valuelen < len) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- sa_in = &params->preferred_addr.ipv4;
-
- p = ngtcp2_get_bytes(&sa_in->sin_addr, p, sizeof(sa_in->sin_addr));
- p = ngtcp2_get_uint16be(&sa_in->sin_port, p);
-
- if (sa_in->sin_port || memcmp(empty_address, &sa_in->sin_addr,
- sizeof(sa_in->sin_addr)) != 0) {
- sa_in->sin_family = NGTCP2_AF_INET;
- params->preferred_addr.ipv4_present = 1;
- }
-
- sa_in6 = &params->preferred_addr.ipv6;
-
- p = ngtcp2_get_bytes(&sa_in6->sin6_addr, p, sizeof(sa_in6->sin6_addr));
- p = ngtcp2_get_uint16be(&sa_in6->sin6_port, p);
-
- if (sa_in6->sin6_port || memcmp(empty_address, &sa_in6->sin6_addr,
- sizeof(sa_in6->sin6_addr)) != 0) {
- sa_in6->sin6_family = NGTCP2_AF_INET6;
- params->preferred_addr.ipv6_present = 1;
- }
-
- /* cid */
- params->preferred_addr.cid.datalen = *p++;
- len += params->preferred_addr.cid.datalen;
- if (valuelen != len ||
- params->preferred_addr.cid.datalen > NGTCP2_MAX_CIDLEN ||
- params->preferred_addr.cid.datalen < NGTCP2_MIN_CIDLEN) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (params->preferred_addr.cid.datalen) {
- p = ngtcp2_get_bytes(params->preferred_addr.cid.data, p,
- params->preferred_addr.cid.datalen);
- }
-
- /* stateless reset token */
- p = ngtcp2_get_bytes(
- params->preferred_addr.stateless_reset_token, p,
- sizeof(params->preferred_addr.stateless_reset_token));
- params->preferred_addr_present = 1;
- break;
- case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION:
- if (decode_zero_param(&p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- params->disable_active_migration = 1;
- break;
- case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID:
- rv = decode_cid_param(&params->original_dcid, &p, end);
- if (rv != 0) {
- return rv;
- }
- params->original_dcid_present = 1;
- break;
- case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID:
- rv = decode_cid_param(&params->retry_scid, &p, end);
- if (rv != 0) {
- return rv;
- }
- params->retry_scid_present = 1;
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID:
- rv = decode_cid_param(&params->initial_scid, &p, end);
- if (rv != 0) {
- return rv;
- }
- params->initial_scid_present = 1;
- break;
- case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY:
- if (decode_varint_param(&params->max_ack_delay, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (params->max_ack_delay >= 16384) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- params->max_ack_delay *= NGTCP2_MILLISECONDS;
- break;
- case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT:
- if (decode_varint_param(&params->active_connection_id_limit, &p, end) !=
- 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE:
- if (decode_varint_param(&params->max_datagram_frame_size, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- break;
- case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT:
- if (decode_zero_param(&p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- params->grease_quic_bit = 1;
- break;
- case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION:
- if (decode_varint(&valuelen, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if ((size_t)(end - p) < valuelen) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p = ngtcp2_get_uint32(&params->version_info.chosen_version, p);
- if (params->version_info.chosen_version == 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (valuelen > sizeof(uint32_t)) {
- params->version_info.available_versions = (uint8_t *)p;
- params->version_info.available_versionslen =
- (size_t)valuelen - sizeof(uint32_t);
-
- for (lend = p + (valuelen - sizeof(uint32_t)); p != lend;) {
- p = ngtcp2_get_uint32(&version, p);
- if (version == 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- }
- }
- params->version_info_present = 1;
- break;
- default:
- /* Ignore unknown parameter */
- if (decode_varint(&valuelen, &p, end) != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if ((size_t)(end - p) < valuelen) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += valuelen;
- break;
- }
- }
-
- if (end - p != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- if (transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION) {
- ngtcp2_transport_params_convert_to_old(transport_params_version, dest,
- params);
- }
-
- return 0;
-}
-
-static int transport_params_copy_new(ngtcp2_transport_params **pdest,
- const ngtcp2_transport_params *src,
- const ngtcp2_mem *mem) {
- size_t len = sizeof(**pdest);
- ngtcp2_transport_params *dest;
- uint8_t *p;
-
- if (src->version_info_present) {
- len += src->version_info.available_versionslen;
- }
-
- dest = ngtcp2_mem_malloc(mem, len);
- if (dest == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- *dest = *src;
-
- if (src->version_info_present && src->version_info.available_versionslen) {
- p = (uint8_t *)dest + sizeof(*dest);
- memcpy(p, src->version_info.available_versions,
- src->version_info.available_versionslen);
- dest->version_info.available_versions = p;
- }
-
- *pdest = dest;
-
- return 0;
-}
-
-int ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams,
- const uint8_t *data, size_t datalen,
- const ngtcp2_mem *mem) {
- int rv;
- ngtcp2_transport_params params;
-
- rv = ngtcp2_transport_params_decode(&params, data, datalen);
- if (rv < 0) {
- return rv;
- }
-
- if (mem == NULL) {
- mem = ngtcp2_mem_default();
- }
-
- return transport_params_copy_new(pparams, &params, mem);
-}
-
-void ngtcp2_transport_params_del(ngtcp2_transport_params *params,
- const ngtcp2_mem *mem) {
- if (params == NULL) {
- return;
- }
-
- if (mem == NULL) {
- mem = ngtcp2_mem_default();
- }
-
- ngtcp2_mem_free(mem, params);
-}
-
-int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest,
- const ngtcp2_transport_params *src,
- const ngtcp2_mem *mem) {
- if (src == NULL) {
- *pdest = NULL;
- return 0;
- }
-
- return transport_params_copy_new(pdest, src, mem);
-}
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h
index b78429b..c561723 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h
@@ -41,33 +41,6 @@
/* NGTCP2_MAX_AEAD_OVERHEAD is expected maximum AEAD overhead. */
#define NGTCP2_MAX_AEAD_OVERHEAD 16
-/* ngtcp2_transport_param_id is the registry of QUIC transport
- parameter ID. */
-typedef uint64_t ngtcp2_transport_param_id;
-
-#define NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID 0x00
-#define NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT 0x01
-#define NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN 0x02
-#define NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE 0x03
-#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA 0x04
-#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05
-#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06
-#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI 0x07
-#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI 0x08
-#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI 0x09
-#define NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT 0x0a
-#define NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY 0x0b
-#define NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION 0x0c
-#define NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS 0x0d
-#define NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT 0x0e
-#define NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID 0x0f
-#define NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID 0x10
-/* https://datatracker.ietf.org/doc/html/rfc9221 */
-#define NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE 0x20
-#define NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT 0x2ab2
-/* https://datatracker.ietf.org/doc/html/rfc9368 */
-#define NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION 0x11
-
/* NGTCP2_CRYPTO_KM_FLAG_NONE indicates that no flag is set. */
#define NGTCP2_CRYPTO_KM_FLAG_NONE 0x00u
/* NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE is set if key phase bit is
@@ -127,21 +100,4 @@ typedef struct ngtcp2_crypto_cc {
void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen,
int64_t pkt_num);
-/*
- * ngtcp2_transport_params_copy_new makes a copy of |src|, and assigns
- * it to |*pdest|. If |src| is NULL, NULL is assigned to |*pdest|.
- *
- * Caller is responsible to call ngtcp2_transport_params_del to free
- * the memory assigned to |*pdest|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest,
- const ngtcp2_transport_params *src,
- const ngtcp2_mem *mem);
-
#endif /* NGTCP2_CRYPTO_H */
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h
index 28d3461..8974c86 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h
@@ -55,4 +55,40 @@
*/
#define ngtcp2_arraylen(A) (sizeof(A) / sizeof(A[0]))
+/*
+ * ngtcp2_max variants but they are inline functions. The
+ * intermediate values are stored in parameters so that they are
+ * evaluated just once.
+ */
+#define ngtcp2_max_def(SUFFIX, T) \
+ static inline T ngtcp2_max_##SUFFIX(T a, T b) { return a < b ? b : a; }
+
+ngtcp2_max_def(int8, int8_t);
+ngtcp2_max_def(int16, int16_t);
+ngtcp2_max_def(int32, int32_t);
+ngtcp2_max_def(int64, int64_t);
+ngtcp2_max_def(uint8, uint8_t);
+ngtcp2_max_def(uint16, uint16_t);
+ngtcp2_max_def(uint32, uint32_t);
+ngtcp2_max_def(uint64, uint64_t);
+ngtcp2_max_def(size, size_t);
+
+/*
+ * ngtcp2_min variants but they are inline functions. The
+ * intermediate values are stored in parameters so that they are
+ * evaluated just once.
+ */
+#define ngtcp2_min_def(SUFFIX, T) \
+ static inline T ngtcp2_min_##SUFFIX(T a, T b) { return a < b ? a : b; }
+
+ngtcp2_min_def(int8, int8_t);
+ngtcp2_min_def(int16, int16_t);
+ngtcp2_min_def(int32, int32_t);
+ngtcp2_min_def(int64, int64_t);
+ngtcp2_min_def(uint8, uint8_t);
+ngtcp2_min_def(uint16, uint16_t);
+ngtcp2_min_def(uint32, uint32_t);
+ngtcp2_min_def(uint64, uint64_t);
+ngtcp2_min_def(size, size_t);
+
#endif /* NGTCP2_MACRO_H */
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c
index 1687ff2..f4ceb32 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c
@@ -2208,7 +2208,7 @@ ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen,
p = dest;
- randlen = ngtcp2_min(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen);
+ randlen = ngtcp2_min_size(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen);
p = ngtcp2_cpymem(p, rand, randlen);
p = ngtcp2_cpymem(p, stateless_reset_token, NGTCP2_STATELESS_RESET_TOKENLEN);
@@ -2384,21 +2384,21 @@ size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset,
#if SIZE_MAX > UINT32_MAX
len = ngtcp2_min(len, 4611686018427387903lu);
#endif /* SIZE_MAX > UINT32_MAX */
- return (size_t)ngtcp2_min(len, (uint64_t)(left - 8));
+ return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 8));
}
if (left > 4 + 16383 && len > 16383) {
len = ngtcp2_min(len, 1073741823);
- return (size_t)ngtcp2_min(len, (uint64_t)(left - 4));
+ return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 4));
}
if (left > 2 + 63 && len > 63) {
len = ngtcp2_min(len, 16383);
- return (size_t)ngtcp2_min(len, (uint64_t)(left - 2));
+ return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 2));
}
len = ngtcp2_min(len, 63);
- return (size_t)ngtcp2_min(len, (uint64_t)(left - 1));
+ return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 1));
}
size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
@@ -2416,21 +2416,21 @@ size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
#if SIZE_MAX > UINT32_MAX
len = ngtcp2_min(len, 4611686018427387903lu);
#endif /* SIZE_MAX > UINT32_MAX */
- return ngtcp2_min(len, left - 8);
+ return ngtcp2_min_size(len, left - 8);
}
if (left > 4 + 16383 && len > 16383) {
len = ngtcp2_min(len, 1073741823);
- return ngtcp2_min(len, left - 4);
+ return ngtcp2_min_size(len, left - 4);
}
if (left > 2 + 63 && len > 63) {
len = ngtcp2_min(len, 16383);
- return ngtcp2_min(len, left - 2);
+ return ngtcp2_min_size(len, left - 2);
}
len = ngtcp2_min(len, 63);
- return ngtcp2_min(len, left - 1);
+ return ngtcp2_min_size(len, left - 1);
}
size_t ngtcp2_pkt_datagram_framelen(size_t len) {
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h
index feec4d3..5f2e448 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h
@@ -95,9 +95,8 @@
/* NGTCP2_MAX_PKT_NUM is the maximum packet number. */
#define NGTCP2_MAX_PKT_NUM ((int64_t)((1ll << 62) - 1))
-/* NGTCP2_MIN_PKT_EXPANDLEN is the minimum packet size expansion in
- addition to the minimum DCID length to hide/trigger Stateless
- Reset. */
+/* NGTCP2_MIN_PKT_EXPANDLEN is the minimum packet size expansion to
+ hide/trigger Stateless Reset. */
#define NGTCP2_MIN_PKT_EXPANDLEN 22
/* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c
index 771ef5e..6010e42 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c
@@ -33,7 +33,7 @@
for each probe. */
#define NGTCP2_PMTUD_PROBE_NUM_MAX 3
-static size_t mtu_probes[] = {
+static uint16_t pmtud_default_probes[] = {
1454 - 48, /* The well known MTU used by a domestic optic fiber
service in Japan. */
1390 - 48, /* Typical Tunneled MTU */
@@ -41,10 +41,9 @@ static size_t mtu_probes[] = {
1492 - 48, /* PPPoE */
};
-#define NGTCP2_MTU_PROBESLEN ngtcp2_arraylen(mtu_probes)
-
int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size,
size_t hard_max_udp_payload_size, int64_t tx_pkt_num,
+ const uint16_t *probes, size_t probeslen,
const ngtcp2_mem *mem) {
ngtcp2_pmtud *pmtud = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pmtud));
@@ -61,11 +60,19 @@ int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size,
pmtud->hard_max_udp_payload_size = hard_max_udp_payload_size;
pmtud->min_fail_udp_payload_size = SIZE_MAX;
- for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) {
- if (mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) {
+ if (probeslen) {
+ pmtud->probes = probes;
+ pmtud->probeslen = probeslen;
+ } else {
+ pmtud->probes = pmtud_default_probes;
+ pmtud->probeslen = ngtcp2_arraylen(pmtud_default_probes);
+ }
+
+ for (; pmtud->mtu_idx < pmtud->probeslen; ++pmtud->mtu_idx) {
+ if (pmtud->probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) {
continue;
}
- if (mtu_probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) {
+ if (pmtud->probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) {
break;
}
}
@@ -84,9 +91,9 @@ void ngtcp2_pmtud_del(ngtcp2_pmtud *pmtud) {
}
size_t ngtcp2_pmtud_probelen(ngtcp2_pmtud *pmtud) {
- assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN);
+ assert(pmtud->mtu_idx < pmtud->probeslen);
- return mtu_probes[pmtud->mtu_idx];
+ return pmtud->probes[pmtud->mtu_idx];
}
void ngtcp2_pmtud_probe_sent(ngtcp2_pmtud *pmtud, ngtcp2_duration pto,
@@ -107,19 +114,19 @@ int ngtcp2_pmtud_require_probe(ngtcp2_pmtud *pmtud) {
}
static void pmtud_next_probe(ngtcp2_pmtud *pmtud) {
- assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN);
+ assert(pmtud->mtu_idx < pmtud->probeslen);
++pmtud->mtu_idx;
pmtud->num_pkts_sent = 0;
pmtud->expiry = UINT64_MAX;
- for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) {
- if (mtu_probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size ||
- mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) {
+ for (; pmtud->mtu_idx < pmtud->probeslen; ++pmtud->mtu_idx) {
+ if (pmtud->probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size ||
+ pmtud->probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) {
continue;
}
- if (mtu_probes[pmtud->mtu_idx] < pmtud->min_fail_udp_payload_size) {
+ if (pmtud->probes[pmtud->mtu_idx] < pmtud->min_fail_udp_payload_size) {
break;
}
}
@@ -129,9 +136,9 @@ void ngtcp2_pmtud_probe_success(ngtcp2_pmtud *pmtud, size_t payloadlen) {
pmtud->max_udp_payload_size =
ngtcp2_max(pmtud->max_udp_payload_size, payloadlen);
- assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN);
+ assert(pmtud->mtu_idx < pmtud->probeslen);
- if (mtu_probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) {
+ if (pmtud->probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) {
return;
}
@@ -149,12 +156,12 @@ void ngtcp2_pmtud_handle_expiry(ngtcp2_pmtud *pmtud, ngtcp2_tstamp ts) {
return;
}
- pmtud->min_fail_udp_payload_size =
- ngtcp2_min(pmtud->min_fail_udp_payload_size, mtu_probes[pmtud->mtu_idx]);
+ pmtud->min_fail_udp_payload_size = ngtcp2_min_size(
+ pmtud->min_fail_udp_payload_size, pmtud->probes[pmtud->mtu_idx]);
pmtud_next_probe(pmtud);
}
int ngtcp2_pmtud_finished(ngtcp2_pmtud *pmtud) {
- return pmtud->mtu_idx >= NGTCP2_MTU_PROBESLEN;
+ return pmtud->mtu_idx >= pmtud->probeslen;
}
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h
index 6b2e691..59876d5 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h
@@ -58,6 +58,10 @@ typedef struct ngtcp2_pmtud {
/* min_fail_udp_payload_size is the minimum UDP payload size that is
known to fail. */
size_t min_fail_udp_payload_size;
+ /* probes is the array of UDP datagram payload size to probe. */
+ const uint16_t *probes;
+ /* probeslen is the number of probes pointed by probes. */
+ size_t probeslen;
} ngtcp2_pmtud;
/*
@@ -70,6 +74,10 @@ typedef struct ngtcp2_pmtud {
* larger than or equal to all UDP payload probe candidates.
* Therefore, call ngtcp2_pmtud_finished to check this situation.
*
+ * The array pointed by |pmtud_probes| of length |pmtud_probeslen|
+ * specifies UDP datagram payload size to probe. If |pmtud_probeslen|
+ * is zero, the default probes are used.
+ *
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
@@ -78,6 +86,7 @@ typedef struct ngtcp2_pmtud {
*/
int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size,
size_t hard_max_udp_payload_size, int64_t tx_pkt_num,
+ const uint16_t *pmtud_probes, size_t pmtud_probeslen,
const ngtcp2_mem *mem);
/*
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c
index f7c122b..34363d0 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c
@@ -29,11 +29,13 @@
#include "ngtcp2_str.h"
#include "ngtcp2_conv.h"
+#include "ngtcp2_macro.h"
void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen,
- ngtcp2_crypto_cc *cc) {
+ size_t dgram_offset, ngtcp2_crypto_cc *cc) {
ngtcp2_buf_init(&ppe->buf, out, outlen);
+ ppe->dgram_offset = dgram_offset;
ppe->hdlen = 0;
ppe->len_offset = 0;
ppe->pkt_num_offset = 0;
@@ -180,20 +182,6 @@ size_t ngtcp2_ppe_pktlen(ngtcp2_ppe *ppe) {
return ngtcp2_buf_len(&ppe->buf) + cc->aead.max_overhead;
}
-size_t ngtcp2_ppe_padding(ngtcp2_ppe *ppe) {
- ngtcp2_crypto_cc *cc = ppe->cc;
- ngtcp2_buf *buf = &ppe->buf;
- size_t len;
-
- assert(ngtcp2_buf_left(buf) >= cc->aead.max_overhead);
-
- len = ngtcp2_buf_left(buf) - cc->aead.max_overhead;
- memset(buf->last, 0, len);
- buf->last += len;
-
- return len;
-}
-
size_t ngtcp2_ppe_padding_hp_sample(ngtcp2_ppe *ppe) {
ngtcp2_crypto_cc *cc = ppe->cc;
ngtcp2_buf *buf = &ppe->buf;
@@ -220,6 +208,8 @@ size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n) {
size_t pktlen = ngtcp2_buf_len(buf) + cc->aead.max_overhead;
size_t len;
+ n = ngtcp2_min_size(n, ngtcp2_buf_cap(buf));
+
if (pktlen >= n) {
return 0;
}
@@ -230,6 +220,29 @@ size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n) {
return len;
}
+size_t ngtcp2_ppe_dgram_padding(ngtcp2_ppe *ppe) {
+ return ngtcp2_ppe_dgram_padding_size(ppe, NGTCP2_MAX_UDP_PAYLOAD_SIZE);
+}
+
+size_t ngtcp2_ppe_dgram_padding_size(ngtcp2_ppe *ppe, size_t n) {
+ ngtcp2_crypto_cc *cc = ppe->cc;
+ ngtcp2_buf *buf = &ppe->buf;
+ size_t dgramlen =
+ ppe->dgram_offset + ngtcp2_buf_len(buf) + cc->aead.max_overhead;
+ size_t len;
+
+ n = ngtcp2_min_size(n, ppe->dgram_offset + ngtcp2_buf_cap(buf));
+
+ if (dgramlen >= n) {
+ return 0;
+ }
+
+ len = n - dgramlen;
+ buf->last = ngtcp2_setmem(buf->last, 0, len);
+
+ return len;
+}
+
int ngtcp2_ppe_ensure_hp_sample(ngtcp2_ppe *ppe) {
ngtcp2_buf *buf = &ppe->buf;
return ngtcp2_buf_left(buf) >= (4 - ppe->pkt_numlen) + NGTCP2_HP_SAMPLELEN;
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h
index 2a069ef..2f9275c 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h
@@ -41,6 +41,9 @@
typedef struct ngtcp2_ppe {
ngtcp2_buf buf;
ngtcp2_crypto_cc *cc;
+ /* dgram_offset is the offset in UDP datagram payload that this QUIC
+ packet is positioned at. */
+ size_t dgram_offset;
/* hdlen is the number of bytes for packet header written in buf. */
size_t hdlen;
/* len_offset is the offset to Length field. */
@@ -61,7 +64,7 @@ typedef struct ngtcp2_ppe {
* ngtcp2_ppe_init initializes |ppe| with the given buffer.
*/
void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen,
- ngtcp2_crypto_cc *cc);
+ size_t dgram_offset, ngtcp2_crypto_cc *cc);
/*
* ngtcp2_ppe_encode_hd encodes |hd|.
@@ -110,13 +113,26 @@ size_t ngtcp2_ppe_left(ngtcp2_ppe *ppe);
*/
size_t ngtcp2_ppe_pktlen(ngtcp2_ppe *ppe);
-/**
- * @function
+/*
+ * ngtcp2_ppe_dgram_padding is equivalent to call
+ * ngtcp2_ppe_dgram_padding_size(ppe, NGTCP2_MAX_UDP_PAYLOAD_SIZE).
+ * This function should be called just before calling
+ * ngtcp2_ppe_final().
+ *
+ * This function returns the number of bytes padded.
+ */
+size_t ngtcp2_ppe_dgram_padding(ngtcp2_ppe *ppe);
+
+/*
+ * ngtcp2_ppe_dgram_padding_size adds PADDING frame so that the size
+ * of a UDP datagram payload is at least |n| bytes long. If it is
+ * unable to add PADDING in that way, this function still adds PADDING
+ * frame as much as possible. This function should be called just
+ * before calling ngtcp2_ppe_final().
*
- * `ngtcp2_ppe_padding` encodes PADDING frames to the end of the
- * buffer. This function returns the number of bytes padded.
+ * This function returns the number of bytes added as padding.
*/
-size_t ngtcp2_ppe_padding(ngtcp2_ppe *ppe);
+size_t ngtcp2_ppe_dgram_padding_size(ngtcp2_ppe *ppe, size_t n);
/*
* ngtcp2_ppe_padding_hp_sample adds PADDING frame if the current
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c
index 5e1003d..96cde8f 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c
@@ -69,7 +69,7 @@ int ngtcp2_pq_push(ngtcp2_pq *pq, ngtcp2_pq_entry *item) {
void *nq;
size_t ncapacity;
- ncapacity = ngtcp2_max(4, (pq->capacity * 2));
+ ncapacity = ngtcp2_max_size(4, pq->capacity * 2);
nq = ngtcp2_mem_realloc(pq->mem, pq->q,
ncapacity * sizeof(ngtcp2_pq_entry *));
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h
index b28a882..205ac62 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h
@@ -115,9 +115,8 @@ void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset);
int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb);
/* ngtcp2_static_ringbuf_def defines ngtcp2_ringbuf struct wrapper
- which uses a statically allocated buffer that is suitable for a
- usage that does not change buffer size with ngtcp2_ringbuf_resize.
- ngtcp2_ringbuf_free should never be called for rb field. */
+ which uses a statically allocated buffer. ngtcp2_ringbuf_free
+ should never be called for rb field. */
#define ngtcp2_static_ringbuf_def(NAME, NMEMB, SIZE) \
typedef struct ngtcp2_static_ringbuf_##NAME { \
ngtcp2_ringbuf rb; \
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c
index 5cac383..4fa3b83 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c
@@ -149,7 +149,8 @@ static int rob_write_data(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
}
}
- n = (size_t)ngtcp2_min((uint64_t)len, d->range.begin + rob->chunk - offset);
+ n = (size_t)ngtcp2_min_uint64((uint64_t)len,
+ d->range.begin + rob->chunk - offset);
memcpy(d->begin + (offset - d->range.begin), data, n);
offset += n;
data += n;
@@ -278,8 +279,9 @@ size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest,
*pdest = d->begin + (offset - d->range.begin);
- return (size_t)(ngtcp2_min(g->range.begin, d->range.begin + rob->chunk) -
- offset);
+ return (
+ size_t)(ngtcp2_min_uint64(g->range.begin, d->range.begin + rob->chunk) -
+ offset);
}
void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len) {
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c
index 5ebdce7..89a0cb5 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c
@@ -53,7 +53,6 @@ static void rtb_entry_init(ngtcp2_rtb_entry *ent, const ngtcp2_pkt_hd *hd,
ent->lost_ts = UINT64_MAX;
ent->pktlen = pktlen;
ent->flags = flags;
- ent->next = NULL;
}
int ngtcp2_rtb_entry_objalloc_new(ngtcp2_rtb_entry **pent,
@@ -581,7 +580,8 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
ngtcp2_pmtud_probe_success(conn->pmtud, ent->pktlen);
conn->dcid.current.max_udp_payload_size =
- ngtcp2_max(conn->dcid.current.max_udp_payload_size, ent->pktlen);
+ conn->cstat.max_tx_udp_payload_size =
+ ngtcp2_max(conn->dcid.current.max_udp_payload_size, ent->pktlen);
if (ngtcp2_pmtud_finished(conn->pmtud)) {
ngtcp2_conn_stop_pmtud(conn);
@@ -971,7 +971,7 @@ static int rtb_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat,
if (loss_time == UINT64_MAX) {
loss_time = ent->ts + loss_delay;
} else {
- loss_time = ngtcp2_min(loss_time, ent->ts + loss_delay);
+ loss_time = ngtcp2_min_uint64(loss_time, ent->ts + loss_delay);
}
cstat->loss_time[rtb->pktns_id] = loss_time;
@@ -1049,7 +1049,8 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost,
congestion_period =
(cstat->smoothed_rtt +
- ngtcp2_max(4 * cstat->rttvar, NGTCP2_GRANULARITY) + max_ack_delay) *
+ ngtcp2_max_uint64(4 * cstat->rttvar, NGTCP2_GRANULARITY) +
+ max_ack_delay) *
NGTCP2_PERSISTENT_CONGESTION_THRESHOLD;
start_ts = ngtcp2_max(rtb->persistent_congestion_start_ts,
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c
new file mode 100644
index 0000000..77a68bd
--- /dev/null
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c
@@ -0,0 +1,91 @@
+/*
+ * ngtcp2
+ *
+ * Copyright (c) 2024 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_settings.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include "ngtcp2_unreachable.h"
+
+void ngtcp2_settings_default_versioned(int settings_version,
+ ngtcp2_settings *settings) {
+ size_t len = ngtcp2_settingslen_version(settings_version);
+
+ memset(settings, 0, len);
+
+ switch (settings_version) {
+ case NGTCP2_SETTINGS_VERSION:
+ case NGTCP2_SETTINGS_V1:
+ settings->cc_algo = NGTCP2_CC_ALGO_CUBIC;
+ settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT;
+ settings->ack_thresh = 2;
+ settings->max_tx_udp_payload_size = 1500 - 48;
+ settings->handshake_timeout = UINT64_MAX;
+
+ break;
+ }
+}
+
+static void settings_copy(ngtcp2_settings *dest, const ngtcp2_settings *src,
+ int settings_version) {
+ assert(settings_version != NGTCP2_SETTINGS_VERSION);
+
+ memcpy(dest, src, ngtcp2_settingslen_version(settings_version));
+}
+
+const ngtcp2_settings *
+ngtcp2_settings_convert_to_latest(ngtcp2_settings *dest, int settings_version,
+ const ngtcp2_settings *src) {
+ if (settings_version == NGTCP2_SETTINGS_VERSION) {
+ return src;
+ }
+
+ ngtcp2_settings_default(dest);
+
+ settings_copy(dest, src, settings_version);
+
+ return dest;
+}
+
+void ngtcp2_settings_convert_to_old(int settings_version, ngtcp2_settings *dest,
+ const ngtcp2_settings *src) {
+ assert(settings_version != NGTCP2_SETTINGS_VERSION);
+
+ settings_copy(dest, src, settings_version);
+}
+
+size_t ngtcp2_settingslen_version(int settings_version) {
+ ngtcp2_settings settings;
+
+ switch (settings_version) {
+ case NGTCP2_SETTINGS_VERSION:
+ return sizeof(settings);
+ case NGTCP2_SETTINGS_V1:
+ return offsetof(ngtcp2_settings, initial_pkt_num) +
+ sizeof(settings.initial_pkt_num);
+ default:
+ ngtcp2_unreachable();
+ }
+}
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h
new file mode 100644
index 0000000..8a8ddc2
--- /dev/null
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h
@@ -0,0 +1,73 @@
+/*
+ * ngtcp2
+ *
+ * Copyright (c) 2024 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_SETTINGS_H
+#define NGTCP2_SETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <ngtcp2/ngtcp2.h>
+
+/*
+ * ngtcp2_settings_convert_to_latest converts |src| of version
+ * |settings_version| to the latest version NGTCP2_SETTINGS_VERSION.
+ *
+ * |dest| must point to the latest version. |src| may be the older
+ * version, and if so, it may have fewer fields. Accessing those
+ * fields causes undefined behavior.
+ *
+ * If |settings_version| == NGTCP2_SETTINGS_VERSION, no conversion is
+ * made, and |src| is returned. Otherwise, first |dest| is
+ * initialized via ngtcp2_settings_default, and then all valid fields
+ * in |src| are copied into |dest|. Finally, |dest| is returned.
+ */
+const ngtcp2_settings *
+ngtcp2_settings_convert_to_latest(ngtcp2_settings *dest, int settings_version,
+ const ngtcp2_settings *src);
+
+/*
+ * ngtcp2_settings_convert_to_old converts |src| of the latest version
+ * to |dest| of version |settings_version|.
+ *
+ * |settings_version| must not be the latest version
+ * NGTCP2_SETTINGS_VERSION.
+ *
+ * |dest| points to the older version, and it may have fewer fields.
+ * Accessing those fields causes undefined behavior.
+ *
+ * This function copies all valid fields in version |settings_version|
+ * from |src| to |dest|.
+ */
+void ngtcp2_settings_convert_to_old(int settings_version, ngtcp2_settings *dest,
+ const ngtcp2_settings *src);
+
+/*
+ * ngtcp2_settingslen_version returns the effective length of
+ * ngtcp2_settings at the version |settings_version|.
+ */
+size_t ngtcp2_settingslen_version(int settings_version);
+
+#endif /* NGTCP2_SETTINGS_H */
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h
index 385302a..e396b24 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h
@@ -86,6 +86,9 @@ typedef struct ngtcp2_frame_chain ngtcp2_frame_chain;
received from the remote endpoint. In this case,
NGTCP2_STRM_FLAG_SHUT_WR is also set. */
#define NGTCP2_STRM_FLAG_STOP_SENDING_RECVED 0x800u
+/* NGTCP2_STRM_FLAG_ANY_SENT indicates that any STREAM frame,
+ including empty one, has been sent. */
+#define NGTCP2_STRM_FLAG_ANY_SENT 0x1000u
typedef struct ngtcp2_strm ngtcp2_strm;
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c
new file mode 100644
index 0000000..5a2b346
--- /dev/null
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c
@@ -0,0 +1,886 @@
+/*
+ * ngtcp2
+ *
+ * Copyright (c) 2023 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_transport_params.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include "ngtcp2_conv.h"
+#include "ngtcp2_str.h"
+#include "ngtcp2_mem.h"
+#include "ngtcp2_unreachable.h"
+
+void ngtcp2_transport_params_default_versioned(
+ int transport_params_version, ngtcp2_transport_params *params) {
+ size_t len;
+
+ switch (transport_params_version) {
+ case NGTCP2_TRANSPORT_PARAMS_VERSION:
+ len = sizeof(*params);
+
+ break;
+ default:
+ ngtcp2_unreachable();
+ }
+
+ memset(params, 0, len);
+
+ switch (transport_params_version) {
+ case NGTCP2_TRANSPORT_PARAMS_VERSION:
+ params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE;
+ params->active_connection_id_limit =
+ NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
+ params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
+ params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
+
+ break;
+ }
+}
+
+/*
+ * varint_paramlen returns the length of a single transport parameter
+ * which has variable integer in its parameter.
+ */
+static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) {
+ size_t valuelen = ngtcp2_put_uvarintlen(param);
+ return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(valuelen) + valuelen;
+}
+
+/*
+ * write_varint_param writes parameter |id| of the given |value| in
+ * varint encoding. It returns p + the number of bytes written.
+ */
+static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id,
+ uint64_t value) {
+ p = ngtcp2_put_uvarint(p, id);
+ p = ngtcp2_put_uvarint(p, ngtcp2_put_uvarintlen(value));
+ return ngtcp2_put_uvarint(p, value);
+}
+
+/*
+ * zero_paramlen returns the length of a single transport parameter
+ * which has zero length value in its parameter.
+ */
+static size_t zero_paramlen(ngtcp2_transport_param_id id) {
+ return ngtcp2_put_uvarintlen(id) + 1;
+}
+
+/*
+ * write_zero_param writes parameter |id| that has zero length value.
+ * It returns p + the number of bytes written.
+ */
+static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) {
+ p = ngtcp2_put_uvarint(p, id);
+ *p++ = 0;
+
+ return p;
+}
+
+/*
+ * cid_paramlen returns the length of a single transport parameter
+ * which has |cid| as value.
+ */
+static size_t cid_paramlen(ngtcp2_transport_param_id id,
+ const ngtcp2_cid *cid) {
+ return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(cid->datalen) +
+ cid->datalen;
+}
+
+/*
+ * write_cid_param writes parameter |id| of the given |cid|. It
+ * returns p + the number of bytes written.
+ */
+static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id,
+ const ngtcp2_cid *cid) {
+ assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN);
+ assert(cid->datalen <= NGTCP2_MAX_CIDLEN);
+
+ p = ngtcp2_put_uvarint(p, id);
+ p = ngtcp2_put_uvarint(p, cid->datalen);
+ if (cid->datalen) {
+ p = ngtcp2_cpymem(p, cid->data, cid->datalen);
+ }
+ return p;
+}
+
+static const uint8_t empty_address[16];
+
+ngtcp2_ssize ngtcp2_transport_params_encode_versioned(
+ uint8_t *dest, size_t destlen, int transport_params_version,
+ const ngtcp2_transport_params *params) {
+ uint8_t *p;
+ size_t len = 0;
+ /* For some reason, gcc 7.3.0 requires this initialization. */
+ size_t preferred_addrlen = 0;
+ size_t version_infolen = 0;
+ const ngtcp2_sockaddr_in *sa_in;
+ const ngtcp2_sockaddr_in6 *sa_in6;
+ ngtcp2_transport_params paramsbuf;
+
+ params = ngtcp2_transport_params_convert_to_latest(
+ &paramsbuf, transport_params_version, params);
+
+ if (params->original_dcid_present) {
+ len +=
+ cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
+ &params->original_dcid);
+ }
+
+ if (params->stateless_reset_token_present) {
+ len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) +
+ ngtcp2_put_uvarintlen(NGTCP2_STATELESS_RESET_TOKENLEN) +
+ NGTCP2_STATELESS_RESET_TOKENLEN;
+ }
+
+ if (params->preferred_addr_present) {
+ assert(params->preferred_addr.cid.datalen >= NGTCP2_MIN_CIDLEN);
+ assert(params->preferred_addr.cid.datalen <= NGTCP2_MAX_CIDLEN);
+ preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ +
+ 16 /* ipv6Address */ + 2 /* ipv6Port */
+ + 1 + params->preferred_addr.cid.datalen /* CID */ +
+ NGTCP2_STATELESS_RESET_TOKENLEN;
+ len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) +
+ ngtcp2_put_uvarintlen(preferred_addrlen) + preferred_addrlen;
+ }
+ if (params->retry_scid_present) {
+ len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
+ &params->retry_scid);
+ }
+
+ if (params->initial_scid_present) {
+ len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
+ &params->initial_scid);
+ }
+
+ if (params->initial_max_stream_data_bidi_local) {
+ len += varint_paramlen(
+ NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
+ params->initial_max_stream_data_bidi_local);
+ }
+ if (params->initial_max_stream_data_bidi_remote) {
+ len += varint_paramlen(
+ NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
+ params->initial_max_stream_data_bidi_remote);
+ }
+ if (params->initial_max_stream_data_uni) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
+ params->initial_max_stream_data_uni);
+ }
+ if (params->initial_max_data) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
+ params->initial_max_data);
+ }
+ if (params->initial_max_streams_bidi) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
+ params->initial_max_streams_bidi);
+ }
+ if (params->initial_max_streams_uni) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
+ params->initial_max_streams_uni);
+ }
+ if (params->max_udp_payload_size !=
+ NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
+ params->max_udp_payload_size);
+ }
+ if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
+ params->ack_delay_exponent);
+ }
+ if (params->disable_active_migration) {
+ len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
+ }
+ if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
+ params->max_ack_delay / NGTCP2_MILLISECONDS);
+ }
+ if (params->max_idle_timeout) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
+ params->max_idle_timeout / NGTCP2_MILLISECONDS);
+ }
+ if (params->active_connection_id_limit &&
+ params->active_connection_id_limit !=
+ NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
+ params->active_connection_id_limit);
+ }
+ if (params->max_datagram_frame_size) {
+ len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
+ params->max_datagram_frame_size);
+ }
+ if (params->grease_quic_bit) {
+ len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT);
+ }
+ if (params->version_info_present) {
+ version_infolen =
+ sizeof(uint32_t) + params->version_info.available_versionslen;
+ len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION) +
+ ngtcp2_put_uvarintlen(version_infolen) + version_infolen;
+ }
+
+ if (dest == NULL && destlen == 0) {
+ return (ngtcp2_ssize)len;
+ }
+
+ if (destlen < len) {
+ return NGTCP2_ERR_NOBUF;
+ }
+
+ p = dest;
+
+ if (params->original_dcid_present) {
+ p = write_cid_param(
+ p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
+ &params->original_dcid);
+ }
+
+ if (params->stateless_reset_token_present) {
+ p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN);
+ p = ngtcp2_put_uvarint(p, sizeof(params->stateless_reset_token));
+ p = ngtcp2_cpymem(p, params->stateless_reset_token,
+ sizeof(params->stateless_reset_token));
+ }
+
+ if (params->preferred_addr_present) {
+ p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS);
+ p = ngtcp2_put_uvarint(p, preferred_addrlen);
+
+ if (params->preferred_addr.ipv4_present) {
+ sa_in = &params->preferred_addr.ipv4;
+ p = ngtcp2_cpymem(p, &sa_in->sin_addr, sizeof(sa_in->sin_addr));
+ p = ngtcp2_put_uint16(p, sa_in->sin_port);
+ } else {
+ p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in->sin_addr));
+ p = ngtcp2_put_uint16(p, 0);
+ }
+
+ if (params->preferred_addr.ipv6_present) {
+ sa_in6 = &params->preferred_addr.ipv6;
+ p = ngtcp2_cpymem(p, &sa_in6->sin6_addr, sizeof(sa_in6->sin6_addr));
+ p = ngtcp2_put_uint16(p, sa_in6->sin6_port);
+ } else {
+ p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in6->sin6_addr));
+ p = ngtcp2_put_uint16(p, 0);
+ }
+
+ *p++ = (uint8_t)params->preferred_addr.cid.datalen;
+ if (params->preferred_addr.cid.datalen) {
+ p = ngtcp2_cpymem(p, params->preferred_addr.cid.data,
+ params->preferred_addr.cid.datalen);
+ }
+ p = ngtcp2_cpymem(p, params->preferred_addr.stateless_reset_token,
+ sizeof(params->preferred_addr.stateless_reset_token));
+ }
+
+ if (params->retry_scid_present) {
+ p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
+ &params->retry_scid);
+ }
+
+ if (params->initial_scid_present) {
+ p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
+ &params->initial_scid);
+ }
+
+ if (params->initial_max_stream_data_bidi_local) {
+ p = write_varint_param(
+ p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
+ params->initial_max_stream_data_bidi_local);
+ }
+
+ if (params->initial_max_stream_data_bidi_remote) {
+ p = write_varint_param(
+ p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
+ params->initial_max_stream_data_bidi_remote);
+ }
+
+ if (params->initial_max_stream_data_uni) {
+ p = write_varint_param(p,
+ NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
+ params->initial_max_stream_data_uni);
+ }
+
+ if (params->initial_max_data) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
+ params->initial_max_data);
+ }
+
+ if (params->initial_max_streams_bidi) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
+ params->initial_max_streams_bidi);
+ }
+
+ if (params->initial_max_streams_uni) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
+ params->initial_max_streams_uni);
+ }
+
+ if (params->max_udp_payload_size !=
+ NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
+ params->max_udp_payload_size);
+ }
+
+ if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
+ params->ack_delay_exponent);
+ }
+
+ if (params->disable_active_migration) {
+ p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
+ }
+
+ if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
+ params->max_ack_delay / NGTCP2_MILLISECONDS);
+ }
+
+ if (params->max_idle_timeout) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
+ params->max_idle_timeout / NGTCP2_MILLISECONDS);
+ }
+
+ if (params->active_connection_id_limit &&
+ params->active_connection_id_limit !=
+ NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
+ params->active_connection_id_limit);
+ }
+
+ if (params->max_datagram_frame_size) {
+ p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
+ params->max_datagram_frame_size);
+ }
+
+ if (params->grease_quic_bit) {
+ p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT);
+ }
+
+ if (params->version_info_present) {
+ p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION);
+ p = ngtcp2_put_uvarint(p, version_infolen);
+ p = ngtcp2_put_uint32be(p, params->version_info.chosen_version);
+ if (params->version_info.available_versionslen) {
+ p = ngtcp2_cpymem(p, params->version_info.available_versions,
+ params->version_info.available_versionslen);
+ }
+ }
+
+ assert((size_t)(p - dest) == len);
+
+ return (ngtcp2_ssize)len;
+}
+
+/*
+ * decode_varint decodes a single varint from the buffer pointed by
+ * |*pp| of length |end - *pp|. If it decodes an integer
+ * successfully, it stores the integer in |*pdest|, increment |*pp| by
+ * the number of bytes read from |*pp|, and returns 0. Otherwise it
+ * returns -1.
+ */
+static int decode_varint(uint64_t *pdest, const uint8_t **pp,
+ const uint8_t *end) {
+ const uint8_t *p = *pp;
+ size_t len;
+
+ if (p == end) {
+ return -1;
+ }
+
+ len = ngtcp2_get_uvarintlen(p);
+ if ((uint64_t)(end - p) < len) {
+ return -1;
+ }
+
+ *pp = ngtcp2_get_uvarint(pdest, p);
+
+ return 0;
+}
+
+/*
+ * decode_varint_param decodes length prefixed value from the buffer
+ * pointed by |*pp| of length |end - *pp|. The length and value are
+ * encoded in varint form. If it decodes a value successfully, it
+ * stores the value in |*pdest|, increment |*pp| by the number of
+ * bytes read from |*pp|, and returns 0. Otherwise it returns -1.
+ */
+static int decode_varint_param(uint64_t *pdest, const uint8_t **pp,
+ const uint8_t *end) {
+ const uint8_t *p = *pp;
+ uint64_t valuelen;
+
+ if (decode_varint(&valuelen, &p, end) != 0) {
+ return -1;
+ }
+
+ if (p == end) {
+ return -1;
+ }
+
+ if ((uint64_t)(end - p) < valuelen) {
+ return -1;
+ }
+
+ if (ngtcp2_get_uvarintlen(p) != valuelen) {
+ return -1;
+ }
+
+ *pp = ngtcp2_get_uvarint(pdest, p);
+
+ return 0;
+}
+
+/*
+ * decode_zero_param decodes zero length value from the buffer pointed
+ * by |*pp| of length |end - *pp|. The length is encoded in varint
+ * form. If it decodes zero length value successfully, it increments
+ * |*pp| by 1, and returns 0. Otherwise it returns -1.
+ */
+static int decode_zero_param(const uint8_t **pp, const uint8_t *end) {
+ if (*pp == end || **pp != 0) {
+ return -1;
+ }
+
+ ++*pp;
+
+ return 0;
+}
+
+/*
+ * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer
+ * pointed by |*pp| of length |end - *pp|. The length is encoded in
+ * varint form. If it decodes a value successfully, it stores the
+ * value in |*pdest|, increment |*pp| by the number of read from
+ * |*pp|, and returns the number of bytes read. Otherwise it returns
+ * the one of the negative error code:
+ *
+ * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM
+ * Could not decode Connection ID.
+ */
+static int decode_cid_param(ngtcp2_cid *pdest, const uint8_t **pp,
+ const uint8_t *end) {
+ const uint8_t *p = *pp;
+ uint64_t valuelen;
+
+ if (decode_varint(&valuelen, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+
+ if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) ||
+ valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+
+ ngtcp2_cid_init(pdest, p, (size_t)valuelen);
+
+ p += valuelen;
+
+ *pp = p;
+
+ return 0;
+}
+
+int ngtcp2_transport_params_decode_versioned(int transport_params_version,
+ ngtcp2_transport_params *dest,
+ const uint8_t *data,
+ size_t datalen) {
+ const uint8_t *p, *end, *lend;
+ size_t len;
+ uint64_t param_type;
+ uint64_t valuelen;
+ int rv;
+ ngtcp2_sockaddr_in *sa_in;
+ ngtcp2_sockaddr_in6 *sa_in6;
+ uint32_t version;
+ ngtcp2_transport_params *params, paramsbuf;
+
+ if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) {
+ params = dest;
+ } else {
+ params = &paramsbuf;
+ }
+
+ /* Set default values */
+ memset(params, 0, sizeof(*params));
+ params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE;
+ params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
+ params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
+ params->active_connection_id_limit =
+ NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
+
+ p = data;
+ end = data + datalen;
+
+ for (; (size_t)(end - p) >= 2;) {
+ if (decode_varint(&param_type, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+
+ switch (param_type) {
+ case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
+ if (decode_varint_param(&params->initial_max_stream_data_bidi_local, &p,
+ end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
+ if (decode_varint_param(&params->initial_max_stream_data_bidi_remote, &p,
+ end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI:
+ if (decode_varint_param(&params->initial_max_stream_data_uni, &p, end) !=
+ 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA:
+ if (decode_varint_param(&params->initial_max_data, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI:
+ if (decode_varint_param(&params->initial_max_streams_bidi, &p, end) !=
+ 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI:
+ if (decode_varint_param(&params->initial_max_streams_uni, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT:
+ if (decode_varint_param(&params->max_idle_timeout, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ params->max_idle_timeout *= NGTCP2_MILLISECONDS;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE:
+ if (decode_varint_param(&params->max_udp_payload_size, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN:
+ if (decode_varint(&valuelen, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if ((size_t)valuelen != sizeof(params->stateless_reset_token)) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+
+ p = ngtcp2_get_bytes(params->stateless_reset_token, p,
+ sizeof(params->stateless_reset_token));
+ params->stateless_reset_token_present = 1;
+
+ break;
+ case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT:
+ if (decode_varint_param(&params->ack_delay_exponent, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if (params->ack_delay_exponent > 20) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS:
+ if (decode_varint(&valuelen, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if ((size_t)(end - p) < valuelen) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ +
+ 2 /* ipv6Port */
+ + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN;
+ if (valuelen < len) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+
+ sa_in = &params->preferred_addr.ipv4;
+
+ p = ngtcp2_get_bytes(&sa_in->sin_addr, p, sizeof(sa_in->sin_addr));
+ p = ngtcp2_get_uint16be(&sa_in->sin_port, p);
+
+ if (sa_in->sin_port || memcmp(empty_address, &sa_in->sin_addr,
+ sizeof(sa_in->sin_addr)) != 0) {
+ sa_in->sin_family = NGTCP2_AF_INET;
+ params->preferred_addr.ipv4_present = 1;
+ }
+
+ sa_in6 = &params->preferred_addr.ipv6;
+
+ p = ngtcp2_get_bytes(&sa_in6->sin6_addr, p, sizeof(sa_in6->sin6_addr));
+ p = ngtcp2_get_uint16be(&sa_in6->sin6_port, p);
+
+ if (sa_in6->sin6_port || memcmp(empty_address, &sa_in6->sin6_addr,
+ sizeof(sa_in6->sin6_addr)) != 0) {
+ sa_in6->sin6_family = NGTCP2_AF_INET6;
+ params->preferred_addr.ipv6_present = 1;
+ }
+
+ /* cid */
+ params->preferred_addr.cid.datalen = *p++;
+ len += params->preferred_addr.cid.datalen;
+ if (valuelen != len ||
+ params->preferred_addr.cid.datalen > NGTCP2_MAX_CIDLEN ||
+ params->preferred_addr.cid.datalen < NGTCP2_MIN_CIDLEN) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if (params->preferred_addr.cid.datalen) {
+ p = ngtcp2_get_bytes(params->preferred_addr.cid.data, p,
+ params->preferred_addr.cid.datalen);
+ }
+
+ /* stateless reset token */
+ p = ngtcp2_get_bytes(
+ params->preferred_addr.stateless_reset_token, p,
+ sizeof(params->preferred_addr.stateless_reset_token));
+ params->preferred_addr_present = 1;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION:
+ if (decode_zero_param(&p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ params->disable_active_migration = 1;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID:
+ rv = decode_cid_param(&params->original_dcid, &p, end);
+ if (rv != 0) {
+ return rv;
+ }
+ params->original_dcid_present = 1;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID:
+ rv = decode_cid_param(&params->retry_scid, &p, end);
+ if (rv != 0) {
+ return rv;
+ }
+ params->retry_scid_present = 1;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID:
+ rv = decode_cid_param(&params->initial_scid, &p, end);
+ if (rv != 0) {
+ return rv;
+ }
+ params->initial_scid_present = 1;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY:
+ if (decode_varint_param(&params->max_ack_delay, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if (params->max_ack_delay >= 16384) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ params->max_ack_delay *= NGTCP2_MILLISECONDS;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT:
+ if (decode_varint_param(&params->active_connection_id_limit, &p, end) !=
+ 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE:
+ if (decode_varint_param(&params->max_datagram_frame_size, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ break;
+ case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT:
+ if (decode_zero_param(&p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ params->grease_quic_bit = 1;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION:
+ if (decode_varint(&valuelen, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if ((size_t)(end - p) < valuelen) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ p = ngtcp2_get_uint32(&params->version_info.chosen_version, p);
+ if (params->version_info.chosen_version == 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if (valuelen > sizeof(uint32_t)) {
+ params->version_info.available_versions = (uint8_t *)p;
+ params->version_info.available_versionslen =
+ (size_t)valuelen - sizeof(uint32_t);
+
+ for (lend = p + (valuelen - sizeof(uint32_t)); p != lend;) {
+ p = ngtcp2_get_uint32(&version, p);
+ if (version == 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ }
+ }
+ params->version_info_present = 1;
+ break;
+ default:
+ /* Ignore unknown parameter */
+ if (decode_varint(&valuelen, &p, end) != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ if ((size_t)(end - p) < valuelen) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+ p += valuelen;
+ break;
+ }
+ }
+
+ if (end - p != 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+
+ if (transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION) {
+ ngtcp2_transport_params_convert_to_old(transport_params_version, dest,
+ params);
+ }
+
+ return 0;
+}
+
+static int transport_params_copy_new(ngtcp2_transport_params **pdest,
+ const ngtcp2_transport_params *src,
+ const ngtcp2_mem *mem) {
+ size_t len = sizeof(**pdest);
+ ngtcp2_transport_params *dest;
+ uint8_t *p;
+
+ if (src->version_info_present) {
+ len += src->version_info.available_versionslen;
+ }
+
+ dest = ngtcp2_mem_malloc(mem, len);
+ if (dest == NULL) {
+ return NGTCP2_ERR_NOMEM;
+ }
+
+ *dest = *src;
+
+ if (src->version_info_present && src->version_info.available_versionslen) {
+ p = (uint8_t *)dest + sizeof(*dest);
+ memcpy(p, src->version_info.available_versions,
+ src->version_info.available_versionslen);
+ dest->version_info.available_versions = p;
+ }
+
+ *pdest = dest;
+
+ return 0;
+}
+
+int ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams,
+ const uint8_t *data, size_t datalen,
+ const ngtcp2_mem *mem) {
+ int rv;
+ ngtcp2_transport_params params;
+
+ rv = ngtcp2_transport_params_decode(&params, data, datalen);
+ if (rv < 0) {
+ return rv;
+ }
+
+ if (mem == NULL) {
+ mem = ngtcp2_mem_default();
+ }
+
+ return transport_params_copy_new(pparams, &params, mem);
+}
+
+void ngtcp2_transport_params_del(ngtcp2_transport_params *params,
+ const ngtcp2_mem *mem) {
+ if (params == NULL) {
+ return;
+ }
+
+ if (mem == NULL) {
+ mem = ngtcp2_mem_default();
+ }
+
+ ngtcp2_mem_free(mem, params);
+}
+
+int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest,
+ const ngtcp2_transport_params *src,
+ const ngtcp2_mem *mem) {
+ if (src == NULL) {
+ *pdest = NULL;
+ return 0;
+ }
+
+ return transport_params_copy_new(pdest, src, mem);
+}
+
+static void transport_params_copy(ngtcp2_transport_params *dest,
+ const ngtcp2_transport_params *src,
+ int transport_params_version) {
+ assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION);
+
+ switch (transport_params_version) {
+ case NGTCP2_TRANSPORT_PARAMS_V1:
+ memcpy(dest, src,
+ offsetof(ngtcp2_transport_params, version_info_present) +
+ sizeof(src->version_info_present));
+
+ break;
+ }
+}
+
+const ngtcp2_transport_params *
+ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest,
+ int transport_params_version,
+ const ngtcp2_transport_params *src) {
+ if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) {
+ return src;
+ }
+
+ ngtcp2_transport_params_default(dest);
+
+ transport_params_copy(dest, src, transport_params_version);
+
+ return dest;
+}
+
+void ngtcp2_transport_params_convert_to_old(
+ int transport_params_version, ngtcp2_transport_params *dest,
+ const ngtcp2_transport_params *src) {
+ assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION);
+
+ transport_params_copy(dest, src, transport_params_version);
+}
diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.h
index 3457a8f..9b0acb8 100644
--- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.h
+++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.h
@@ -22,8 +22,8 @@
* 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_CONVERSION_H
-#define NGTCP2_CONVERSION_H
+#ifndef NGTCP2_TRANSPORT_PARAMS_H
+#define NGTCP2_TRANSPORT_PARAMS_H
#ifdef HAVE_CONFIG_H
# include <config.h>
@@ -31,6 +31,53 @@
#include <ngtcp2/ngtcp2.h>
+/* ngtcp2_transport_param_id is the registry of QUIC transport
+ parameter ID. */
+typedef uint64_t ngtcp2_transport_param_id;
+
+#define NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID 0x00
+#define NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT 0x01
+#define NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN 0x02
+#define NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE 0x03
+#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA 0x04
+#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05
+#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06
+#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI 0x07
+#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI 0x08
+#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI 0x09
+#define NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT 0x0a
+#define NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY 0x0b
+#define NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION 0x0c
+#define NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS 0x0d
+#define NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT 0x0e
+#define NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID 0x0f
+#define NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID 0x10
+/* https://datatracker.ietf.org/doc/html/rfc9221 */
+#define NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE 0x20
+#define NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT 0x2ab2
+/* https://datatracker.ietf.org/doc/html/rfc9368 */
+#define NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION 0x11
+
+/* NGTCP2_MAX_STREAMS is the maximum number of streams. */
+#define NGTCP2_MAX_STREAMS (1LL << 60)
+
+/*
+ * ngtcp2_transport_params_copy_new makes a copy of |src|, and assigns
+ * it to |*pdest|. If |src| is NULL, NULL is assigned to |*pdest|.
+ *
+ * Caller is responsible to call ngtcp2_transport_params_del to free
+ * the memory assigned to |*pdest|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGTCP2_ERR_NOMEM
+ * Out of memory.
+ */
+int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest,
+ const ngtcp2_transport_params *src,
+ const ngtcp2_mem *mem);
+
/*
* ngtcp2_transport_params_convert_to_latest converts |src| of version
* |transport_params_version| to the latest version
@@ -68,4 +115,4 @@ void ngtcp2_transport_params_convert_to_old(int transport_params_version,
ngtcp2_transport_params *dest,
const ngtcp2_transport_params *src);
-#endif /* NGTCP2_CONVERSION_H */
+#endif /* NGTCP2_TRANSPORT_PARAMS_H */
diff --git a/src/contrib/libngtcp2/ngtcp2/ngtcp2.h b/src/contrib/libngtcp2/ngtcp2/ngtcp2.h
index 72c8142..0b49853 100644
--- a/src/contrib/libngtcp2/ngtcp2/ngtcp2.h
+++ b/src/contrib/libngtcp2/ngtcp2/ngtcp2.h
@@ -1689,7 +1689,8 @@ typedef enum ngtcp2_token_type {
} ngtcp2_token_type;
#define NGTCP2_SETTINGS_V1 1
-#define NGTCP2_SETTINGS_VERSION NGTCP2_SETTINGS_V1
+#define NGTCP2_SETTINGS_V2 2
+#define NGTCP2_SETTINGS_VERSION NGTCP2_SETTINGS_V2
/**
* @struct
@@ -1723,8 +1724,7 @@ typedef struct ngtcp2_settings {
ngtcp2_printf log_printf;
/**
* :member:`max_tx_udp_payload_size` is the maximum size of UDP
- * datagram payload that the local endpoint transmits. It is used
- * by congestion controller to compute congestion window.
+ * datagram payload that the local endpoint transmits.
*/
size_t max_tx_udp_payload_size;
/**
@@ -1877,6 +1877,24 @@ typedef struct ngtcp2_settings {
* number space. It must be in range [0, INT32_MAX], inclusive.
*/
uint32_t initial_pkt_num;
+ /* The following fields have been added since NGTCP2_SETTINGS_V2. */
+ /**
+ * :member:`pmtud_probes` is the array of UDP datagram payload size
+ * to probe during Path MTU Discovery. The discovery is done in the
+ * order appeared in this array. The size must be strictly larger
+ * than 1200, otherwise the behavior is undefined. The maximum
+ * value in this array should be set to
+ * :member:`max_tx_udp_payload_size`. If this field is not set, the
+ * predefined PMTUD probes are made. This field has been available
+ * since v1.4.0.
+ */
+ const uint16_t *pmtud_probes;
+ /**
+ * :member:`pmtud_probeslen` is the number of elements that are
+ * contained in the array pointed by :member:`pmtud_probes`. This
+ * field has been available since v1.4.0.
+ */
+ size_t pmtud_probeslen;
} ngtcp2_settings;
/**
@@ -4388,7 +4406,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned(
* handshake as well.
*
* |destlen| should be at least
- * :member:`ngtcp2_settings.max_tx_udp_payload_size`.
+ * :member:`ngtcp2_settings.max_tx_udp_payload_size`. It must be at
+ * least :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`.
*
* Specifying -1 to |stream_id| means no new stream data to send.
*
@@ -4418,8 +4437,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned(
* In that case, |*pdatalen| would be -1 if |pdatalen| is not
* ``NULL``.
*
- * If |flags| & :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` is nonzero, and
- * 0 length STREAM frame is successfully serialized, |*pdatalen| would
+ * Empty data is treated specially, and it is only accepted if no
+ * data, including the empty data, is submitted to a stream or
+ * :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` is set in |flags|. If 0
+ * length STREAM frame is successfully serialized, |*pdatalen| would
* be 0.
*
* The number of data encoded in STREAM frame is stored in |*pdatalen|
@@ -4573,7 +4594,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_datagram_versioned(
* as well.
*
* |destlen| should be at least
- * :member:`ngtcp2_settings.max_tx_udp_payload_size`.
+ * :member:`ngtcp2_settings.max_tx_udp_payload_size`. It must be at
+ * least :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`.
*
* For |path| and |pi| parameters, refer to
* `ngtcp2_conn_writev_stream`.
@@ -5193,7 +5215,19 @@ typedef enum ngtcp2_ccerr_type {
* transport error, and it indicates that connection is closed
* because of idle timeout.
*/
- NGTCP2_CCERR_TYPE_IDLE_CLOSE
+ NGTCP2_CCERR_TYPE_IDLE_CLOSE,
+ /**
+ * :enum:`NGTCP2_CCERR_TYPE_DROP_CONN` is a special case of QUIC
+ * transport error, and it indicates that connection should be
+ * dropped without sending a CONNECTION_CLOSE frame.
+ */
+ NGTCP2_CCERR_TYPE_DROP_CONN,
+ /**
+ * :enum:`NGTCP2_CCERR_TYPE_RETRY` is a special case of QUIC
+ * transport error, and it indicates that RETRY packet should be
+ * sent to a client.
+ */
+ NGTCP2_CCERR_TYPE_RETRY
} ngtcp2_ccerr_type;
/**
@@ -5284,6 +5318,18 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_transport_error(ngtcp2_ccerr *ccerr,
* :member:`ccerr->error_code <ngtcp2_ccerr.error_code>` to
* :macro:`NGTCP2_NO_ERROR`.
*
+ * If |liberr| is :macro:`NGTCP2_ERR_DROP_CONN`, :member:`ccerr->type
+ * <ngtcp2_ccerr.type>` is set to
+ * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_DROP_CONN`, and
+ * :member:`ccerr->error_code <ngtcp2_ccerr.error_code>` to
+ * :macro:`NGTCP2_NO_ERROR`.
+ *
+ * If |liberr| is :macro:`NGTCP2_ERR_RETRY`, :member:`ccerr->type
+ * <ngtcp2_ccerr.type>` is set to
+ * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_RETRY`, and
+ * :member:`ccerr->error_type <ngtcp2_ccerr.error_code>` to
+ * :macro:`NGTCP2_NO_ERROR`.
+ *
* Otherwise, :member:`ccerr->type <ngtcp2_ccerr.type>` is set to
* :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_TRANSPORT`, and
* :member:`ccerr->error_code <ngtcp2_ccerr.error_code>` is set to an
diff --git a/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h b/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h
index 06427d7..9f909bf 100644
--- a/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h
+++ b/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h
@@ -540,7 +540,7 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token(
* `ngtcp2_crypto_generate_retry_token` or
* `ngtcp2_crypto_generate_regular_token`.
*/
-#define NGTCP2_CRYPTO_TOKEN_RAND_DATALEN 32
+#define NGTCP2_CRYPTO_TOKEN_RAND_DATALEN 16
/**
* @macro
diff --git a/src/contrib/libngtcp2/ngtcp2/version.h b/src/contrib/libngtcp2/ngtcp2/version.h
index 801c6cb..9eb076d 100644
--- a/src/contrib/libngtcp2/ngtcp2/version.h
+++ b/src/contrib/libngtcp2/ngtcp2/version.h
@@ -36,7 +36,7 @@
*
* Version number of the ngtcp2 library release.
*/
-#define NGTCP2_VERSION "1.3.0"
+#define NGTCP2_VERSION "1.5.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 0x010300
+#define NGTCP2_VERSION_NUM 0x010500
#endif /* VERSION_H */