From: Daniel Salzman Date: Sun, 23 Nov 2025 15:59:21 +0000 (+0100) Subject: libngtcp2: update embedded library to v1.18.0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5873a7d2e6ed374dec6ffc39ffceb558a8b4a72;p=thirdparty%2Fknot-dns.git libngtcp2: update embedded library to v1.18.0 --- diff --git a/src/contrib/libngtcp2/ngtcp2/crypto/shared.c b/src/contrib/libngtcp2/ngtcp2/crypto/shared.c index 98cd4de7e8..062efb45e9 100644 --- a/src/contrib/libngtcp2/ngtcp2/crypto/shared.c +++ b/src/contrib/libngtcp2/ngtcp2/crypto/shared.c @@ -461,7 +461,9 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, if (ngtcp2_conn_is_server(conn) && crypto_set_local_transport_params(conn, tls) != 0) { - goto fail; + /* Just return -1 because aead_ctx and hp_ctx are now owned by + conn. */ + return -1; } break; @@ -1305,13 +1307,22 @@ static size_t crypto_generate_regular_token_aad(uint8_t *dest, return addrlen; } +/* NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN is the maximum length of + opaque data embedded in a regular token. */ +#define NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN 256 + +/* NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN is the maximum length + of plaintext included in a regular token. */ +#define NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN \ + (sizeof(ngtcp2_tstamp) + NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN) + static const uint8_t regular_token_info_prefix[] = "regular_token"; -ngtcp2_ssize ngtcp2_crypto_generate_regular_token( +static ngtcp2_ssize crypto_generate_regular_token( uint8_t *token, const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, - ngtcp2_tstamp ts) { - uint8_t plaintext[sizeof(ngtcp2_tstamp)]; + const void *data, size_t datalen, ngtcp2_tstamp ts) { + uint8_t plaintext[NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN]; uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN]; uint8_t key[16]; uint8_t iv[12]; @@ -1328,9 +1339,18 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token( int rv; (void)remote_addrlen; + if (datalen > NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN) { + return -1; + } + memcpy(p, &ts_be, sizeof(ts_be)); p += sizeof(ts_be); + if (datalen) { + memcpy(p, data, datalen); + p += datalen; + } + plaintextlen = (size_t)(p - plaintext); if (ngtcp2_crypto_random(rand_data, sizeof(rand_data)) != 0) { @@ -1378,13 +1398,11 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token( return p - token; } -int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, - const uint8_t *secret, size_t secretlen, - const ngtcp2_sockaddr *remote_addr, - ngtcp2_socklen remote_addrlen, - ngtcp2_duration timeout, - ngtcp2_tstamp ts) { - uint8_t plaintext[sizeof(ngtcp2_tstamp)]; +static ngtcp2_ssize crypto_verify_regular_token( + void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts) { + uint8_t plaintext[NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN]; uint8_t key[16]; uint8_t iv[12]; size_t keylen; @@ -1397,13 +1415,14 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, const uint8_t *rand_data; const uint8_t *ciphertext; size_t ciphertextlen; + size_t datalen; int rv; ngtcp2_tstamp gen_ts; (void)remote_addrlen; - if (tokenlen != NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN || + if (tokenlen < NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN || token[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR) { - return -1; + return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN; } rand_data = token + tokenlen - NGTCP2_CRYPTO_TOKEN_RAND_DATALEN; @@ -1413,6 +1432,10 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, ngtcp2_crypto_aead_aes_128_gcm(&aead); ngtcp2_crypto_md_sha256(&md); + if (ciphertextlen > sizeof(plaintext) + aead.max_overhead) { + return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN; + } + keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); @@ -1423,13 +1446,13 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN, regular_token_info_prefix, sizeof(regular_token_info_prefix) - 1) != 0) { - return -1; + return NGTCP2_CRYPTO_ERR_INTERNAL; } aadlen = crypto_generate_regular_token_aad(aad, remote_addr); if (ngtcp2_crypto_aead_ctx_decrypt_init(&aead_ctx, &aead, key, ivlen) != 0) { - return -1; + return NGTCP2_CRYPTO_ERR_INTERNAL; } rv = ngtcp2_crypto_decrypt(plaintext, &aead, &aead_ctx, ciphertext, @@ -1438,19 +1461,74 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, ngtcp2_crypto_aead_ctx_free(&aead_ctx); if (rv != 0) { - return -1; + return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN; } memcpy(&gen_ts, plaintext, sizeof(gen_ts)); gen_ts = ngtcp2_ntohl64(gen_ts); if (gen_ts + timeout <= ts) { + return NGTCP2_CRYPTO_ERR_VERIFY_TOKEN; + } + + if (max_datalen == 0) { + return 0; + } + + datalen = ciphertextlen - aead.max_overhead - sizeof(gen_ts); + if (datalen > max_datalen) { + return 0; + } + + memcpy(data, plaintext + sizeof(gen_ts), datalen); + + return (ngtcp2_ssize)datalen; +} + +ngtcp2_ssize ngtcp2_crypto_generate_regular_token( + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + ngtcp2_tstamp ts) { + return crypto_generate_regular_token(token, secret, secretlen, remote_addr, + remote_addrlen, NULL, 0, ts); +} + +int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, + ngtcp2_duration timeout, + ngtcp2_tstamp ts) { + ngtcp2_ssize datalen = + crypto_verify_regular_token(NULL, 0, token, tokenlen, secret, secretlen, + remote_addr, remote_addrlen, timeout, ts); + + if (datalen < 0) { return -1; } + assert(0 == datalen); + return 0; } +ngtcp2_ssize ngtcp2_crypto_generate_regular_token2( + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const void *data, size_t datalen, ngtcp2_tstamp ts) { + return crypto_generate_regular_token(token, secret, secretlen, remote_addr, + remote_addrlen, data, datalen, ts); +} + +ngtcp2_ssize ngtcp2_crypto_verify_regular_token2( + void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts) { + return crypto_verify_regular_token(data, max_datalen, token, tokenlen, secret, + secretlen, remote_addr, remote_addrlen, + timeout, ts); +} + ngtcp2_ssize ngtcp2_crypto_write_connection_close( uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, uint64_t error_code, const uint8_t *reason, diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c index 59bc621ef4..0781f082e7 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c @@ -34,9 +34,11 @@ ngtcp2_objalloc_def(acktr_entry, ngtcp2_acktr_entry, oplent) static void acktr_entry_init(ngtcp2_acktr_entry *ent, int64_t pkt_num, ngtcp2_tstamp tstamp) { - ent->pkt_num = pkt_num; - ent->len = 1; - ent->tstamp = tstamp; + *ent = (ngtcp2_acktr_entry){ + .pkt_num = pkt_num, + .len = 1, + .tstamp = tstamp, + }; } int ngtcp2_acktr_entry_objalloc_new(ngtcp2_acktr_entry **ent, int64_t pkt_num, @@ -219,8 +221,10 @@ ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr, int64_t largest_ack) { ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks.rb); - ent->largest_ack = largest_ack; - ent->pkt_num = pkt_num; + *ent = (ngtcp2_acktr_ack_entry){ + .largest_ack = largest_ack, + .pkt_num = pkt_num, + }; return ent; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c index a028a8a8f4..58694e3836 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_addr.c @@ -31,8 +31,11 @@ ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const ngtcp2_sockaddr *addr, ngtcp2_socklen addrlen) { - dest->addrlen = addrlen; - dest->addr = (ngtcp2_sockaddr *)addr; + *dest = (ngtcp2_addr){ + .addr = (ngtcp2_sockaddr *)addr, + .addrlen = addrlen, + }; + return dest; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c index 62e6b2f125..babf35bfdb 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c @@ -1097,13 +1097,8 @@ static void bbr_check_probe_rtt_done(ngtcp2_cc_bbr *bbr, static void bbr_mark_connection_app_limited(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - uint64_t app_limited = bbr->rst->delivered + cstat->bytes_in_flight; - - if (app_limited) { - bbr->rst->app_limited = app_limited; - } else { - bbr->rst->app_limited = cstat->max_tx_udp_payload_size; - } + bbr->rst->app_limited = + ngtcp2_max_uint64(bbr->rst->delivered + cstat->bytes_in_flight, 1); } static void bbr_exit_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts) { diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_buf.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_buf.c index bf4273f816..083a766281 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_buf.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_buf.c @@ -26,8 +26,12 @@ #include "ngtcp2_mem.h" void ngtcp2_buf_init(ngtcp2_buf *buf, uint8_t *begin, size_t len) { - buf->begin = buf->pos = buf->last = begin; - buf->end = begin + len; + *buf = (ngtcp2_buf){ + .begin = begin, + .end = begin + len, + .pos = begin, + .last = begin, + }; } void ngtcp2_buf_reset(ngtcp2_buf *buf) { buf->pos = buf->last = buf->begin; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c index f8e420ed7d..73dfde6904 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c @@ -261,7 +261,6 @@ uint64_t ngtcp2_cbrt(uint64_t n) { y <<= 1; b = 3 * y * (y + 1) + 1; if (n >= b) { - n -= b; y++; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h index 010a1c3541..a19e90b1d0 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.h @@ -184,20 +184,12 @@ typedef void (*ngtcp2_cc_on_ack_recv)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, * @functypedef * * :type:`ngtcp2_cc_on_pkt_sent` is a callback function which is - * called when an ack-eliciting packet is sent. + * called when an ack-eliciting packet is sent. The lost, + * tx_in_flight, and is_app_limited fields in |pkt| are set to 0. */ typedef void (*ngtcp2_cc_on_pkt_sent)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt); -/** - * @functypedef - * - * :type:`ngtcp2_cc_new_rtt_sample` is a callback function which is - * called when new RTT sample is obtained. - */ -typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - /** * @functypedef * @@ -207,28 +199,6 @@ typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, typedef void (*ngtcp2_cc_reset)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -/** - * @enum - * - * :type:`ngtcp2_cc_event_type` defines congestion control events. - */ -typedef enum ngtcp2_cc_event_type { - /** - * :enum:`NGTCP2_CC_EVENT_TX_START` occurs when ack-eliciting packet - * is sent and no other ack-eliciting packet is present. - */ - NGTCP2_CC_EVENT_TYPE_TX_START -} ngtcp2_cc_event_type; - -/** - * @functypedef - * - * :type:`ngtcp2_cc_event` is a callback function which is called when - * a specific event happens. - */ -typedef void (*ngtcp2_cc_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_cc_event_type event, ngtcp2_tstamp ts); - /** * @struct * @@ -275,21 +245,11 @@ typedef struct ngtcp2_cc { * ack-eliciting packet is sent. */ ngtcp2_cc_on_pkt_sent on_pkt_sent; - /** - * :member:`new_rtt_sample` is a callback function which is called - * when new RTT sample is obtained. - */ - ngtcp2_cc_new_rtt_sample new_rtt_sample; /** * :member:`reset` is a callback function which is called when * congestion control state must be reset. */ ngtcp2_cc_reset reset; - /** - * :member:`event` is a callback function which is called when a - * specific event happens. - */ - ngtcp2_cc_event event; } ngtcp2_cc; /* diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cid.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cid.c index acbee78aaf..42a4827664 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cid.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cid.c @@ -58,11 +58,13 @@ int ngtcp2_cid_less(const ngtcp2_cid *lhs, const ngtcp2_cid *rhs) { int ngtcp2_cid_empty(const ngtcp2_cid *cid) { return cid->datalen == 0; } void ngtcp2_scid_init(ngtcp2_scid *scid, uint64_t seq, const ngtcp2_cid *cid) { - scid->pe.index = NGTCP2_PQ_BAD_INDEX; - scid->seq = seq; - scid->cid = *cid; - scid->retired_ts = UINT64_MAX; - scid->flags = NGTCP2_SCID_FLAG_NONE; + *scid = (ngtcp2_scid){ + .pe.index = NGTCP2_PQ_BAD_INDEX, + .seq = seq, + .cid = *cid, + .retired_ts = UINT64_MAX, + .flags = NGTCP2_SCID_FLAG_NONE, + }; } void ngtcp2_scid_copy(ngtcp2_scid *dest, const ngtcp2_scid *src) { diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c index b1a9840c6e..827cacd535 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -697,8 +697,10 @@ static int conn_call_recv_tx_key(ngtcp2_conn *conn, return 0; } -// pktns_init initializes |pktns|. It assumes that the object pointed -// by |pktns| is zero-cleared. +/* + * pktns_init initializes |pktns|. It assumes that the object pointed + * by |pktns| is zero-cleared. + */ 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, @@ -1525,6 +1527,8 @@ fail_seqgap_push: fail_token: ngtcp2_mem_free(mem, *pconn); + *pconn = NULL; + return rv; } @@ -1552,6 +1556,8 @@ int ngtcp2_conn_client_new_versioned( rv = ngtcp2_conn_commit_local_transport_params(*pconn); if (rv != 0) { ngtcp2_conn_del(*pconn); + *pconn = NULL; + return rv; } @@ -1809,8 +1815,18 @@ static int conn_ppe_write_frame(ngtcp2_conn *conn, ngtcp2_ppe *ppe, static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_rtb_entry *ent) { ngtcp2_rtb *rtb = &pktns->rtb; + ngtcp2_cc_pkt cc_pkt; int rv; + if ((ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) && + conn->cc.on_pkt_sent) { + conn->cc.on_pkt_sent( + &conn->cc, &conn->cstat, + ngtcp2_cc_pkt_init(&cc_pkt, ent->hd.pkt_num, ent->pktlen, pktns->id, + ent->ts, /* lost = */ 0, + /* tx_in_flight = */ 0, /* is_app_limited = */ 0)); + } + /* This function implements OnPacketSent, but it handles only non-ACK-only packet. */ rv = ngtcp2_rtb_add(rtb, ent, &conn->cstat); @@ -2015,6 +2031,12 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, return 1; } + /* We might send Handshake packet even if exceeding CWND. In that + case, we do not write non-probe 1RTT packet. */ + if (conn_cwnd_is_zero(conn) && conn->pktns.rtb.probe_pkt_left == 0) { + return 1; + } + min_payloadlen = NGTCP2_MIN_COALESCED_PAYLOADLEN; } @@ -2194,12 +2216,15 @@ static int conn_cut_crypto_frame(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc, } /* ngtcp2_frame_chain for the removed data */ - removed_frc->fr.stream.type = NGTCP2_FRAME_CRYPTO; - removed_frc->fr.stream.offset = (*pfrc)->fr.stream.offset + offset; - removed_frc->fr.stream.datacnt = 1; - removed_frc->fr.stream.data[0] = (ngtcp2_vec){ - .base = data->base + offset, - .len = removed_data->len, + removed_frc->fr.stream = (ngtcp2_stream){ + .type = NGTCP2_FRAME_CRYPTO, + .offset = (*pfrc)->fr.stream.offset + offset, + .datacnt = 1, + .data[0] = + { + .base = data->base + offset, + .len = removed_data->len, + }, }; rv = ngtcp2_strm_streamfrq_push(crypto_strm, removed_frc); @@ -2249,12 +2274,15 @@ static int conn_cut_crypto_frame(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc, return rv; } - left_frc->fr.stream.type = NGTCP2_FRAME_CRYPTO; - left_frc->fr.stream.offset = (*pfrc)->fr.stream.offset; - left_frc->fr.stream.datacnt = 1; - left_frc->fr.stream.data[0] = (ngtcp2_vec){ - .base = data[0].base, - .len = offset, + left_frc->fr.stream = (ngtcp2_stream){ + .type = NGTCP2_FRAME_CRYPTO, + .offset = (*pfrc)->fr.stream.offset, + .datacnt = 1, + .data[0] = + { + .base = data[0].base, + .len = offset, + }, }; left_frc->next = right_frc; @@ -3078,21 +3106,16 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, dest += nwrite; destlen -= (size_t)nwrite; - /* 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)) { - rtbent = ngtcp2_ksl_it_get(&it); - if (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { - wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; - } + if (conn->server) { + it = ngtcp2_rtb_head(&conn->in_pktns->rtb); + if (!ngtcp2_ksl_it_end(&it)) { + rtbent = ngtcp2_ksl_it_get(&it); + if (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { + wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } - } else { - wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } + } else { + wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } } } @@ -3457,7 +3480,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, size_t min_pktlen = conn_min_pktlen(conn); int min_padded = 0; int padded = 0; - ngtcp2_cc_pkt cc_pkt; uint64_t crypto_offset; uint64_t stream_offset; ngtcp2_ssize num_reclaimed; @@ -3573,8 +3595,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, conn->tx.last_max_data_ts = ts; - nfrc->fr.type = NGTCP2_FRAME_MAX_DATA; - nfrc->fr.max_data.max_data = conn->rx.unsent_max_offset + delta; + nfrc->fr.max_data = (ngtcp2_max_data){ + .type = NGTCP2_FRAME_MAX_DATA, + .max_data = conn->rx.unsent_max_offset + delta, + }; nfrc->next = pktns->tx.frq; pktns->tx.frq = nfrc; @@ -3817,11 +3841,12 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_RESET_STREAM; - nfrc->fr.reset_stream.stream_id = strm->stream_id; - nfrc->fr.reset_stream.app_error_code = - strm->tx.reset_stream_app_error_code; - nfrc->fr.reset_stream.final_size = strm->tx.offset; + nfrc->fr.reset_stream = (ngtcp2_reset_stream){ + .type = NGTCP2_FRAME_RESET_STREAM, + .stream_id = strm->stream_id, + .app_error_code = strm->tx.reset_stream_app_error_code, + .final_size = strm->tx.offset, + }; *pfrc = nfrc; strm->flags &= ~NGTCP2_STRM_FLAG_SEND_RESET_STREAM; @@ -3860,10 +3885,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_STOP_SENDING; - nfrc->fr.stop_sending.stream_id = strm->stream_id; - nfrc->fr.stop_sending.app_error_code = - strm->tx.stop_sending_app_error_code; + nfrc->fr.stop_sending = (ngtcp2_stop_sending){ + .type = NGTCP2_FRAME_STOP_SENDING, + .stream_id = strm->stream_id, + .app_error_code = strm->tx.stop_sending_app_error_code, + }; *pfrc = nfrc; strm->flags &= ~NGTCP2_STRM_FLAG_SEND_STOP_SENDING; @@ -3891,9 +3917,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED; - nfrc->fr.stream_data_blocked.stream_id = strm->stream_id; - nfrc->fr.stream_data_blocked.offset = strm->tx.max_offset; + nfrc->fr.stream_data_blocked = (ngtcp2_stream_data_blocked){ + .type = NGTCP2_FRAME_STREAM_DATA_BLOCKED, + .stream_id = strm->stream_id, + .offset = strm->tx.max_offset, + }; *pfrc = nfrc; strm->tx.last_blocked_offset = strm->tx.max_offset; @@ -3945,10 +3973,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, strm->tx.last_max_stream_data_ts = ts; - nfrc->fr.type = NGTCP2_FRAME_MAX_STREAM_DATA; - nfrc->fr.max_stream_data.stream_id = strm->stream_id; - nfrc->fr.max_stream_data.max_stream_data = - strm->rx.unsent_max_offset + delta; + nfrc->fr.max_stream_data = (ngtcp2_max_stream_data){ + .type = NGTCP2_FRAME_MAX_STREAM_DATA, + .stream_id = strm->stream_id, + .max_stream_data = strm->rx.unsent_max_offset + delta, + }; *pfrc = nfrc; strm->rx.max_offset = strm->rx.unsent_max_offset = @@ -4044,8 +4073,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, assert(ngtcp2_err_is_fatal(rv)); return rv; } - nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_BIDI; - nfrc->fr.max_streams.max_streams = conn->remote.bidi.unsent_max_streams; + nfrc->fr.max_streams = (ngtcp2_max_streams){ + .type = NGTCP2_FRAME_MAX_STREAMS_BIDI, + .max_streams = conn->remote.bidi.unsent_max_streams, + }; *pfrc = nfrc; conn->remote.bidi.max_streams = conn->remote.bidi.unsent_max_streams; @@ -4076,8 +4107,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, assert(ngtcp2_err_is_fatal(rv)); return rv; } - nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_UNI; - nfrc->fr.max_streams.max_streams = conn->remote.uni.unsent_max_streams; + nfrc->fr.max_streams = (ngtcp2_max_streams){ + .type = NGTCP2_FRAME_MAX_STREAMS_UNI, + .max_streams = conn->remote.uni.unsent_max_streams, + }; *pfrc = nfrc; conn->remote.uni.max_streams = conn->remote.uni.unsent_max_streams; @@ -4198,8 +4231,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_DATA_BLOCKED; - nfrc->fr.data_blocked.offset = conn->tx.offset; + nfrc->fr.data_blocked = (ngtcp2_data_blocked){ + .type = NGTCP2_FRAME_DATA_BLOCKED, + .offset = conn->tx.offset, + }; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { @@ -4230,9 +4265,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED; - nfrc->fr.stream_data_blocked.stream_id = strm->stream_id; - nfrc->fr.stream_data_blocked.offset = strm->tx.max_offset; + nfrc->fr.stream_data_blocked = (ngtcp2_stream_data_blocked){ + .type = NGTCP2_FRAME_STREAM_DATA_BLOCKED, + .stream_id = strm->stream_id, + .offset = strm->tx.max_offset, + }; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { @@ -4390,7 +4427,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING; } pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; - pkt_empty = 0; } } else if (pktns->tx.non_ack_pkt_start_ts == UINT64_MAX) { pktns->tx.non_ack_pkt_start_ts = ts; @@ -4452,12 +4488,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, *pfrc = NULL; } - if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) && - pktns->rtb.num_ack_eliciting == 0 && conn->cc.event) { - conn->cc.event(&conn->cc, &conn->cstat, NGTCP2_CC_EVENT_TYPE_TX_START, - ts); - } - rv = conn_on_pkt_sent(conn, pktns, ent); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); @@ -4466,18 +4496,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - if (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { - if (conn->cc.on_pkt_sent) { - conn->cc.on_pkt_sent( - &conn->cc, &conn->cstat, - ngtcp2_cc_pkt_init(&cc_pkt, hd->pkt_num, (size_t)nwrite, - NGTCP2_PKTNS_ID_APPLICATION, ts, ent->rst.lost, - ent->rst.tx_in_flight, ent->rst.is_app_limited)); - } - - if (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE) { - conn_restart_timer_on_write(conn, ts); - } + if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) && + (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE)) { + conn_restart_timer_on_write(conn, ts); } } else if (pi && conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) { conn_handle_tx_ecn(conn, pi, NULL, pktns, hd, ts); @@ -4652,6 +4673,13 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( padded = 0; } + break; + case NGTCP2_FRAME_CONNECTION_CLOSE: + case NGTCP2_FRAME_CONNECTION_CLOSE_APP: + /* Clear padded so that we never store the terminal packet in + ngtcp2_rtb. */ + padded = 0; + break; } @@ -4778,8 +4806,10 @@ static int conn_enqueue_retire_connection_id(ngtcp2_conn *conn, uint64_t seq) { return rv; } - nfrc->fr.type = NGTCP2_FRAME_RETIRE_CONNECTION_ID; - nfrc->fr.retire_connection_id.seq = seq; + nfrc->fr.retire_connection_id = (ngtcp2_retire_connection_id){ + .type = NGTCP2_FRAME_RETIRE_CONNECTION_ID, + .seq = seq, + }; nfrc->next = pktns->tx.frq; pktns->tx.frq = nfrc; @@ -5415,7 +5445,7 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, ngtcp2_pktns *in_pktns = conn->in_pktns; ngtcp2_rtb *rtb = &conn->pktns.rtb; ngtcp2_rtb *in_rtb; - uint8_t cidbuf[sizeof(retry.odcid.data) * 2 + 1]; + char cidbuf[sizeof(retry.odcid.data) * 2 + 1]; uint8_t *token; if (!in_pktns || (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY)) { @@ -5440,9 +5470,9 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, return rv; } - ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_PKT, "odcid=0x%s", - (const char *)ngtcp2_encode_hex(cidbuf, retry.odcid.data, - retry.odcid.datalen)); + ngtcp2_log_infof( + &conn->log, NGTCP2_LOG_EVENT_PKT, "odcid=0x%s", + ngtcp2_encode_hex_cstr(cidbuf, retry.odcid.data, retry.odcid.datalen)); if (retry.tokenlen == 0) { return NGTCP2_ERR_PROTO; @@ -8742,7 +8772,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, ngtcp2_pv *pv = NULL; int rv; ngtcp2_duration pto; - int require_new_cid; int local_addr_eq; int pref_addr_migration; uint32_t remote_addr_cmp; @@ -8800,9 +8829,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, * continue to use the current connection ID with the new remote * address while still sending from the same local address. */ - require_new_cid = conn->dcid.current.cid.datalen && - ((new_cid_used && remote_addr_cmp) || !local_addr_eq); - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "non-probing packet was received from new remote address"); @@ -8810,8 +8836,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "Found DCID which has already been bound to the new path"); - require_new_cid = 0; - if (dcid.cid.datalen) { rv = conn_call_activate_dcid(conn, &dcid); if (rv != 0) { @@ -8819,7 +8843,9 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, } } } else { - if (require_new_cid) { + if (conn->dcid.current.cid.datalen && + ((new_cid_used && remote_addr_cmp) || !local_addr_eq)) { + /* New DCID is required. */ if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { return NGTCP2_ERR_CONN_ID_BLOCKED; } @@ -10592,8 +10618,6 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } res += nwrite; - dest += nwrite; - destlen -= (size_t)nwrite; } if (res == 0) { @@ -10603,8 +10627,6 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } res += nwrite; - dest += nwrite; - origlen -= (size_t)nwrite; } return res; @@ -10840,6 +10862,9 @@ int ngtcp2_conn_install_initial_key( rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL, 0, NULL, tx_iv, ivlen, conn->mem); if (rv != 0) { + ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, conn->mem); + pktns->crypto.rx.ckm = NULL; + return rv; } @@ -10890,6 +10915,9 @@ int ngtcp2_conn_install_vneg_initial_key( rv = ngtcp2_crypto_km_new(&conn->vneg.tx.ckm, NULL, 0, NULL, tx_iv, ivlen, conn->mem); if (rv != 0) { + ngtcp2_crypto_km_del(conn->vneg.rx.ckm, conn->mem); + conn->vneg.rx.ckm = NULL; + return rv; } @@ -10958,21 +10986,27 @@ int ngtcp2_conn_install_tx_handshake_key( if (conn->server) { rv = ngtcp2_conn_commit_local_transport_params(conn); if (rv != 0) { - return rv; + goto fail; } } rv = conn_call_recv_tx_key(conn, NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE); if (rv != 0) { - ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem); - pktns->crypto.tx.ckm = NULL; - - memset(&pktns->crypto.tx.hp_ctx, 0, sizeof(pktns->crypto.tx.hp_ctx)); - - return rv; + goto fail; } return 0; + +fail: + /* If this function fails, aead_ctx and hp_ctx are still owned by + the caller. Delete the install key to remove the any reference + to them. */ + ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem); + pktns->crypto.tx.ckm = NULL; + + memset(&pktns->crypto.tx.hp_ctx, 0, sizeof(pktns->crypto.tx.hp_ctx)); + + return rv; } int ngtcp2_conn_install_0rtt_key(ngtcp2_conn *conn, @@ -11924,11 +11958,8 @@ conn_write_vmsg_wrapper(ngtcp2_conn *conn, ngtcp2_path *path, packet is produced, if it is set, we are sure that we are not app-limited. */ !(conn->flags & NGTCP2_CONN_FLAG_AGGREGATE_PKTS)) { - conn->rst.app_limited = conn->rst.delivered + cstat->bytes_in_flight; - - if (conn->rst.app_limited == 0) { - conn->rst.app_limited = cstat->max_tx_udp_payload_size; - } + conn->rst.app_limited = + ngtcp2_max_uint64(conn->rst.delivered + cstat->bytes_in_flight, 1); } return nwrite; @@ -12111,27 +12142,29 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, conn_client_write_handshake(conn, pi, dest, destlen, wflags, vmsg, ts); /* We might be unable to write a packet because of depletion of congestion window budget, perhaps due to packet loss that - shrinks the window drastically. */ - if (nwrite <= 0) { + shrinks the window drastically. Then continue if we are in + post-handshake. There, we might be able to write packets + exceeding CWND to avoid deadlock. */ + if (nwrite < 0) { return nwrite; } if (conn->state != NGTCP2_CS_POST_HANDSHAKE) { return nwrite; } - assert(nwrite); - assert(dest[0] & NGTCP2_HEADER_FORM_BIT); - assert(conn->negotiated_version); + if (nwrite) { + assert(dest[0] & NGTCP2_HEADER_FORM_BIT); + assert(conn->negotiated_version); - if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE && - ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == + if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == NGTCP2_PKT_INITIAL) { - wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; - } + wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; + } - res = nwrite; - dest += nwrite; - destlen -= (size_t)nwrite; + res = nwrite; + dest += nwrite; + destlen -= (size_t)nwrite; + } /* Break here so that we can coalesces 1RTT packet. */ break; case NGTCP2_CS_SERVER_INITIAL: @@ -12186,7 +12219,7 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, dest += nwrite; destlen -= (size_t)nwrite; - if (res < NGTCP2_MAX_UDP_PAYLOAD_SIZE && conn->in_pktns && nwrite > 0) { + if (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); @@ -12333,9 +12366,22 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, return nwrite; } if (nwrite > 0) { + /* This makes 1RTT packet padded. If 1RTT packet is not going + to be sent, packet is already padded. */ + if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == + NGTCP2_PKT_INITIAL) { + wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; + } + res = nwrite; dest += nwrite; destlen -= (size_t)nwrite; + + /* We only exceed CWND to avoid deadlock. Do no write 1RTT + packet if CWND is depleted. */ + if (conn_cwnd_is_zero(conn) && conn->pktns.rtb.probe_pkt_left == 0) { + goto fin; + } } else if (destlen == 0) { res = conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts); if (res) { @@ -12402,11 +12448,12 @@ conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, ngtcp2_frame fr; uint8_t flags = NGTCP2_WRITE_PKT_FLAG_NONE; - fr.type = NGTCP2_FRAME_CONNECTION_CLOSE; - fr.connection_close.error_code = error_code; - fr.connection_close.frame_type = 0; - fr.connection_close.reasonlen = reasonlen; - fr.connection_close.reason = (uint8_t *)reason; + fr.connection_close = (ngtcp2_connection_close){ + .type = NGTCP2_FRAME_CONNECTION_CLOSE, + .error_code = error_code, + .reasonlen = reasonlen, + .reason = (uint8_t *)reason, + }; if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) && pkt_type != NGTCP2_PKT_INITIAL) { @@ -12581,11 +12628,12 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( assert(conn->pktns.crypto.tx.ckm); - fr.type = NGTCP2_FRAME_CONNECTION_CLOSE_APP; - fr.connection_close.error_code = app_error_code; - fr.connection_close.frame_type = 0; - fr.connection_close.reasonlen = reasonlen; - fr.connection_close.reason = (uint8_t *)reason; + fr.connection_close = (ngtcp2_connection_close){ + .type = NGTCP2_FRAME_CONNECTION_CLOSE_APP, + .error_code = app_error_code, + .reasonlen = reasonlen, + .reason = (uint8_t *)reason, + }; nwrite = ngtcp2_conn_write_single_frame_pkt( conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE, @@ -12609,11 +12657,12 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( static void ccerr_init(ngtcp2_ccerr *ccerr, ngtcp2_ccerr_type type, uint64_t error_code, const uint8_t *reason, size_t reasonlen) { - ccerr->type = type; - ccerr->error_code = error_code; - ccerr->frame_type = 0; - ccerr->reason = (uint8_t *)reason; - ccerr->reasonlen = reasonlen; + *ccerr = (ngtcp2_ccerr){ + .type = type, + .error_code = error_code, + .reason = (uint8_t *)reason, + .reasonlen = reasonlen, + }; } void ngtcp2_ccerr_default(ngtcp2_ccerr *ccerr) { @@ -13029,8 +13078,8 @@ int ngtcp2_conn_get_tls_early_data_rejected(ngtcp2_conn *conn) { return (conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED) != 0; } -int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, - ngtcp2_duration ack_delay, ngtcp2_tstamp ts) { +void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, + ngtcp2_duration ack_delay, ngtcp2_tstamp ts) { ngtcp2_conn_stat *cstat = &conn->cstat; assert(rtt > 0); @@ -13057,7 +13106,7 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, " min_rtt=%" PRIu64 " ack_delay=%" PRIu64, rtt / NGTCP2_MILLISECONDS, cstat->min_rtt / NGTCP2_MILLISECONDS, ack_delay / NGTCP2_MILLISECONDS); - return NGTCP2_ERR_INVALID_ARGUMENT; + return; } cstat->latest_rtt = rtt; @@ -13082,8 +13131,6 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, cstat->min_rtt / NGTCP2_MILLISECONDS, cstat->smoothed_rtt / NGTCP2_MILLISECONDS, cstat->rttvar / NGTCP2_MILLISECONDS, ack_delay / NGTCP2_MILLISECONDS); - - return 0; } void ngtcp2_conn_get_conn_info_versioned(ngtcp2_conn *conn, @@ -13314,7 +13361,6 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn, const uint8_t *data, const size_t datalen) { ngtcp2_pktns *pktns; ngtcp2_frame_chain *frc; - ngtcp2_stream *fr; int rv; if (datalen == 0) { @@ -13347,16 +13393,16 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn, return rv; } - fr = &frc->fr.stream; - - fr->type = NGTCP2_FRAME_CRYPTO; - fr->flags = 0; - fr->fin = 0; - fr->stream_id = 0; - fr->offset = pktns->crypto.tx.offset; - fr->datacnt = 1; - fr->data[0].len = datalen; - fr->data[0].base = (uint8_t *)data; + frc->fr.stream = (ngtcp2_stream){ + .type = NGTCP2_FRAME_CRYPTO, + .offset = pktns->crypto.tx.offset, + .datacnt = 1, + .data[0] = + { + .base = (uint8_t *)data, + .len = datalen, + }, + }; rv = ngtcp2_strm_streamfrq_push(&pktns->crypto.strm, frc); if (rv != 0) { diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h index 30a44e7266..8cda85edbf 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h @@ -768,15 +768,9 @@ int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm); * ack_delay included in ACK frame. |ack_delay| is actually tainted * (sent by peer), so don't assume that |ack_delay| is always smaller * than, or equals to |rtt|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_INVALID_ARGUMENT - * RTT sample is ignored. */ -int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, - ngtcp2_duration ack_delay, ngtcp2_tstamp ts); +void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, + ngtcp2_duration ack_delay, ngtcp2_tstamp ts); void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts); diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c index 1f74e8c583..078568fde3 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c @@ -65,15 +65,21 @@ int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen, } p = (uint8_t *)(*pckm) + sizeof(ngtcp2_crypto_km); - (*pckm)->secret.base = p; - (*pckm)->secret.len = secretlen; - p += secretlen; - (*pckm)->iv.base = p; - (*pckm)->iv.len = ivlen; - (*pckm)->aead_ctx.native_handle = NULL; - (*pckm)->pkt_num = -1; - (*pckm)->use_count = 0; - (*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE; + + **pckm = (ngtcp2_crypto_km){ + .secret = + { + .base = p, + .len = secretlen, + }, + .iv = + { + .base = p + secretlen, + .len = ivlen, + }, + .pkt_num = -1, + .flags = NGTCP2_CRYPTO_KM_FLAG_NONE, + }; return 0; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.c index 22c131a1ac..25e803efbb 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.c @@ -37,33 +37,31 @@ static ngtcp2_ksl_blk null_blk; ngtcp2_objalloc_def(ksl_blk, ngtcp2_ksl_blk, oplent) -static size_t ksl_nodelen(size_t keylen) { - assert(keylen >= sizeof(uint64_t)); - - return (sizeof(ngtcp2_ksl_node) + keylen - sizeof(uint64_t) + 0x7u) & - ~(uintptr_t)0x7u; -} - -static size_t ksl_blklen(size_t nodelen) { - return sizeof(ngtcp2_ksl_blk) + nodelen * NGTCP2_KSL_MAX_NBLK - +static size_t ksl_blklen(size_t aligned_keylen) { + return sizeof(ngtcp2_ksl_blk) + NGTCP2_KSL_MAX_NBLK * aligned_keylen - sizeof(uint64_t); } /* - * ksl_node_set_key sets |key| to |node|. + * ksl_set_nth_key sets |key| to |n|th node under |blk|. */ -static void ksl_node_set_key(ngtcp2_ksl *ksl, ngtcp2_ksl_node *node, - const void *key) { - memcpy(node->key, key, ksl->keylen); +static void ksl_set_nth_key(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, + size_t n, const ngtcp2_ksl_key *key) { + memcpy(blk->keys + n * ksl->aligned_keylen, key, ksl->keylen); } void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, ngtcp2_ksl_search search, size_t keylen, const ngtcp2_mem *mem) { - size_t nodelen = ksl_nodelen(keylen); + size_t aligned_keylen; + + assert(keylen >= sizeof(uint64_t)); + + aligned_keylen = (keylen + 0x7u) & ~0x7u; ngtcp2_objalloc_init(&ksl->blkalloc, - (ksl_blklen(nodelen) + 0xfu) & ~(uintptr_t)0xfu, mem); + (ksl_blklen(aligned_keylen) + 0xfu) & ~(uintptr_t)0xfu, + mem); ksl->head = NULL; ksl->front = ksl->back = NULL; @@ -71,12 +69,12 @@ void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, ksl->search = search; ksl->n = 0; ksl->keylen = keylen; - ksl->nodelen = nodelen; + ksl->aligned_keylen = aligned_keylen; } static ngtcp2_ksl_blk *ksl_blk_objalloc_new(ngtcp2_ksl *ksl) { return ngtcp2_objalloc_ksl_blk_len_get(&ksl->blkalloc, - ksl_blklen(ksl->nodelen)); + ksl_blklen(ksl->aligned_keylen)); } static void ksl_blk_objalloc_del(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { @@ -109,7 +107,7 @@ static void ksl_free_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { if (!blk->leaf) { for (i = 0; i < blk->n; ++i) { - ksl_free_blk(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk); + ksl_free_blk(ksl, blk->nodes[i].blk); } } @@ -160,8 +158,10 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { rblk->n = blk->n / 2; blk->n -= rblk->n; - memcpy(rblk->nodes, blk->nodes + ksl->nodelen * blk->n, - ksl->nodelen * rblk->n); + memcpy(rblk->nodes, blk->nodes + blk->n, rblk->n * sizeof(ngtcp2_ksl_node)); + + memcpy(rblk->keys, blk->keys + blk->n * ksl->aligned_keylen, + rblk->n * ksl->aligned_keylen); assert(blk->n >= NGTCP2_KSL_MIN_NBLK); assert(rblk->n >= NGTCP2_KSL_MIN_NBLK); @@ -181,25 +181,25 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { * Out of memory. */ static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { - ngtcp2_ksl_node *node; - ngtcp2_ksl_blk *lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk, *rblk; + ngtcp2_ksl_blk *lblk = blk->nodes[i].blk, *rblk; rblk = ksl_split_blk(ksl, lblk); if (rblk == NULL) { return NGTCP2_ERR_NOMEM; } - memmove(blk->nodes + (i + 2) * ksl->nodelen, - blk->nodes + (i + 1) * ksl->nodelen, - ksl->nodelen * (blk->n - (i + 1))); + memmove(blk->nodes + (i + 2), blk->nodes + (i + 1), + (blk->n - (i + 1)) * sizeof(ngtcp2_ksl_node)); - node = ngtcp2_ksl_nth_node(ksl, blk, i + 1); - node->blk = rblk; + memmove(blk->keys + (i + 2) * ksl->aligned_keylen, + blk->keys + (i + 1) * ksl->aligned_keylen, + (blk->n - (i + 1)) * ksl->aligned_keylen); + + blk->nodes[i + 1].blk = rblk; ++blk->n; - ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i + 1, ngtcp2_ksl_nth_key(ksl, rblk, rblk->n - 1)); - node = ngtcp2_ksl_nth_node(ksl, blk, i); - ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); return 0; } @@ -216,7 +216,6 @@ static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { */ static int ksl_split_head(ngtcp2_ksl *ksl) { ngtcp2_ksl_blk *rblk = NULL, *lblk, *nhead = NULL; - ngtcp2_ksl_node *node; rblk = ksl_split_blk(ksl, ksl->head); if (rblk == NULL) { @@ -236,13 +235,11 @@ static int ksl_split_head(ngtcp2_ksl *ksl) { nhead->n = 2; nhead->leaf = 0; - node = ngtcp2_ksl_nth_node(ksl, nhead, 0); - ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); - node->blk = lblk; + ksl_set_nth_key(ksl, nhead, 0, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); + nhead->nodes[0].blk = lblk; - node = ngtcp2_ksl_nth_node(ksl, nhead, 1); - ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key); - node->blk = rblk; + ksl_set_nth_key(ksl, nhead, 1, ngtcp2_ksl_nth_key(ksl, rblk, rblk->n - 1)); + nhead->nodes[1].blk = rblk; ksl->head = nhead; @@ -257,16 +254,17 @@ static int ksl_split_head(ngtcp2_ksl *ksl) { */ static void ksl_insert_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i, const ngtcp2_ksl_key *key, void *data) { - ngtcp2_ksl_node *node; - assert(blk->n < NGTCP2_KSL_MAX_NBLK); - memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen, - ksl->nodelen * (blk->n - i)); + memmove(blk->nodes + (i + 1), blk->nodes + i, + (blk->n - i) * sizeof(ngtcp2_ksl_node)); + + memmove(blk->keys + (i + 1) * ksl->aligned_keylen, + blk->keys + i * ksl->aligned_keylen, + (blk->n - i) * ksl->aligned_keylen); - node = ngtcp2_ksl_nth_node(ksl, blk, i); - ksl_node_set_key(ksl, node, key); - node->data = data; + ksl_set_nth_key(ksl, blk, i, key); + blk->nodes[i].data = data; ++blk->n; } @@ -298,8 +296,7 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, i = ksl->search(ksl, blk, key); if (blk->leaf) { - if (i < blk->n && - !ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) { + if (i < blk->n && !ksl->compar(key, ngtcp2_ksl_nth_key(ksl, blk, i))) { if (it) { *it = ngtcp2_ksl_end(ksl); } @@ -320,17 +317,17 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, if (i == blk->n) { /* This insertion extends the largest key in this subtree. */ for (; !blk->leaf;) { - node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1); + node = &blk->nodes[blk->n - 1]; if (node->blk->n == NGTCP2_KSL_MAX_NBLK) { rv = ksl_split_node(ksl, blk, blk->n - 1); if (rv != 0) { return rv; } - node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1); + node = &blk->nodes[blk->n - 1]; } - ksl_node_set_key(ksl, node, key); + ksl_set_nth_key(ksl, blk, blk->n - 1, key); blk = node->blk; } @@ -344,7 +341,7 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, return 0; } - node = ngtcp2_ksl_nth_node(ksl, blk, i); + node = &blk->nodes[i]; if (node->blk->n == NGTCP2_KSL_MAX_NBLK) { rv = ksl_split_node(ksl, blk, i); @@ -352,11 +349,11 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, return rv; } - if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) { - node = ngtcp2_ksl_nth_node(ksl, blk, i + 1); + if (ksl->compar(ngtcp2_ksl_nth_key(ksl, blk, i), key)) { + node = &blk->nodes[i + 1]; - if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) { - ksl_node_set_key(ksl, node, key); + if (ksl->compar(ngtcp2_ksl_nth_key(ksl, blk, i + 1), key)) { + ksl_set_nth_key(ksl, blk, i + 1, key); } } } @@ -370,8 +367,12 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, * |i|. */ static void ksl_remove_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { - memmove(blk->nodes + i * ksl->nodelen, blk->nodes + (i + 1) * ksl->nodelen, - ksl->nodelen * (blk->n - (i + 1))); + memmove(blk->nodes + i, blk->nodes + (i + 1), + (blk->n - (i + 1)) * sizeof(ngtcp2_ksl_node)); + + memmove(blk->keys + i * ksl->aligned_keylen, + blk->keys + (i + 1) * ksl->aligned_keylen, + (blk->n - (i + 1)) * ksl->aligned_keylen); --blk->n; } @@ -393,15 +394,17 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, assert(i + 1 < blk->n); - lnode = ngtcp2_ksl_nth_node(ksl, blk, i); + lnode = &blk->nodes[i]; lblk = lnode->blk; - rblk = ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk; + rblk = blk->nodes[i + 1].blk; assert(lblk->n + rblk->n < NGTCP2_KSL_MAX_NBLK); - memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes, - ksl->nodelen * rblk->n); + memcpy(lblk->nodes + lblk->n, rblk->nodes, rblk->n * sizeof(ngtcp2_ksl_node)); + + memcpy(lblk->keys + lblk->n * ksl->aligned_keylen, rblk->keys, + rblk->n * ksl->aligned_keylen); lblk->n += rblk->n; lblk->next = rblk->next; @@ -419,8 +422,7 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, ksl->head = lblk; } else { ksl_remove_node(ksl, blk, i + 1); - ksl_node_set_key(ksl, lnode, - ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); } return lblk; @@ -438,8 +440,8 @@ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { assert(i > 0); - lnode = ngtcp2_ksl_nth_node(ksl, blk, i - 1); - rnode = ngtcp2_ksl_nth_node(ksl, blk, i); + lnode = &blk->nodes[i - 1]; + rnode = &blk->nodes[i]; lblk = lnode->blk; rblk = rnode->blk; @@ -453,15 +455,20 @@ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { assert(lblk->n <= NGTCP2_KSL_MAX_NBLK - n); assert(rblk->n >= NGTCP2_KSL_MIN_NBLK + n); - memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes, ksl->nodelen * n); + memcpy(lblk->nodes + lblk->n, rblk->nodes, n * sizeof(ngtcp2_ksl_node)); + + memcpy(lblk->keys + lblk->n * ksl->aligned_keylen, rblk->keys, + n * ksl->aligned_keylen); lblk->n += (uint32_t)n; rblk->n -= (uint32_t)n; - ksl_node_set_key(ksl, lnode, - ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i - 1, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); + + memmove(rblk->nodes, rblk->nodes + n, rblk->n * sizeof(ngtcp2_ksl_node)); - memmove(rblk->nodes, rblk->nodes + ksl->nodelen * n, ksl->nodelen * rblk->n); + memmove(rblk->keys, rblk->keys + n * ksl->aligned_keylen, + rblk->n * ksl->aligned_keylen); } /* @@ -476,8 +483,8 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { assert(i < blk->n - 1); - lnode = ngtcp2_ksl_nth_node(ksl, blk, i); - rnode = ngtcp2_ksl_nth_node(ksl, blk, i + 1); + lnode = &blk->nodes[i]; + rnode = &blk->nodes[i + 1]; lblk = lnode->blk; rblk = rnode->blk; @@ -491,15 +498,20 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { assert(lblk->n >= NGTCP2_KSL_MIN_NBLK + n); assert(rblk->n <= NGTCP2_KSL_MAX_NBLK - n); - memmove(rblk->nodes + ksl->nodelen * n, rblk->nodes, ksl->nodelen * rblk->n); + memmove(rblk->nodes + n, rblk->nodes, rblk->n * sizeof(ngtcp2_ksl_node)); + + memmove(rblk->keys + n * ksl->aligned_keylen, rblk->keys, + rblk->n * ksl->aligned_keylen); rblk->n += (uint32_t)n; lblk->n -= (uint32_t)n; - memcpy(rblk->nodes, lblk->nodes + ksl->nodelen * lblk->n, ksl->nodelen * n); + memcpy(rblk->nodes, lblk->nodes + lblk->n, n * sizeof(ngtcp2_ksl_node)); - ksl_node_set_key(ksl, lnode, - ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); + memcpy(rblk->keys, lblk->keys + lblk->n * ksl->aligned_keylen, + n * ksl->aligned_keylen); + + ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); } /* @@ -548,8 +560,8 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, } if (!blk->leaf && blk->n == 2 && - ngtcp2_ksl_nth_node(ksl, blk, 0)->blk->n == NGTCP2_KSL_MIN_NBLK && - ngtcp2_ksl_nth_node(ksl, blk, 1)->blk->n == NGTCP2_KSL_MIN_NBLK) { + blk->nodes[0].blk->n == NGTCP2_KSL_MIN_NBLK && + blk->nodes[1].blk->n == NGTCP2_KSL_MIN_NBLK) { blk = ksl_merge_node(ksl, blk, 0); } @@ -565,7 +577,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, } if (blk->leaf) { - if (ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) { + if (ksl->compar(key, ngtcp2_ksl_nth_key(ksl, blk, i))) { if (it) { *it = ngtcp2_ksl_end(ksl); } @@ -587,7 +599,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, return 0; } - node = ngtcp2_ksl_nth_node(ksl, blk, i); + node = &blk->nodes[i]; if (node->blk->n > NGTCP2_KSL_MIN_NBLK) { blk = node->blk; @@ -596,16 +608,14 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, assert(node->blk->n == NGTCP2_KSL_MIN_NBLK); - if (i + 1 < blk->n && - ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk->n > NGTCP2_KSL_MIN_NBLK) { + if (i + 1 < blk->n && blk->nodes[i + 1].blk->n > NGTCP2_KSL_MIN_NBLK) { ksl_shift_left(ksl, blk, i + 1); blk = node->blk; continue; } - if (i > 0 && - ngtcp2_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGTCP2_KSL_MIN_NBLK) { + if (i > 0 && blk->nodes[i - 1].blk->n > NGTCP2_KSL_MIN_NBLK) { ksl_shift_right(ksl, blk, i - 1); blk = node->blk; @@ -657,7 +667,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_search(const ngtcp2_ksl *ksl, if (i == blk->n) { /* This happens if descendant has smaller key. Fast forward to find last node in this subtree. */ - for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk) + for (; !blk->leaf; blk = blk->nodes[blk->n - 1].blk) ; if (blk->next) { @@ -672,7 +682,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_search(const ngtcp2_ksl *ksl, return it; } - blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk; + blk = blk->nodes[i].blk; } } @@ -680,6 +690,7 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, const ngtcp2_ksl_key *new_key) { ngtcp2_ksl_blk *blk = ksl->head; ngtcp2_ksl_node *node; + const ngtcp2_ksl_key *node_key; size_t i; assert(ksl->head); @@ -688,18 +699,19 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, i = ksl->search(ksl, blk, old_key); assert(i < blk->n); - node = ngtcp2_ksl_nth_node(ksl, blk, i); + node = &blk->nodes[i]; + node_key = ngtcp2_ksl_nth_key(ksl, blk, i); if (blk->leaf) { - assert(key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key)); - ksl_node_set_key(ksl, node, new_key); + assert(key_equal(ksl->compar, node_key, old_key)); + ksl_set_nth_key(ksl, blk, i, new_key); return; } - if (key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key) || - ksl->compar((ngtcp2_ksl_key *)node->key, new_key)) { - ksl_node_set_key(ksl, node, new_key); + if (key_equal(ksl->compar, node_key, old_key) || + ksl->compar(node_key, new_key)) { + ksl_set_nth_key(ksl, blk, i, new_key); } blk = node->blk; @@ -727,14 +739,12 @@ void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) { static void ksl_print(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) { size_t i; - ngtcp2_ksl_node *node; fprintf(stderr, "LV=%zu n=%u\n", level, blk->n); if (blk->leaf) { for (i = 0; i < blk->n; ++i) { - node = ngtcp2_ksl_nth_node(ksl, blk, i); - fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key); + fprintf(stderr, " %" PRId64, *(int64_t *)ngtcp2_ksl_nth_key(ksl, blk, i)); } fprintf(stderr, "\n"); @@ -743,7 +753,7 @@ static void ksl_print(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, } for (i = 0; i < blk->n; ++i) { - ksl_print(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk, level + 1); + ksl_print(ksl, blk->nodes[i].blk, level + 1); } } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.h index d5c3f61d2a..32f754c459 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ksl.h @@ -55,22 +55,13 @@ typedef struct ngtcp2_ksl_blk ngtcp2_ksl_blk; /* * ngtcp2_ksl_node is a node which contains either ngtcp2_ksl_blk or * opaque data. If a node is an internal node, it contains - * ngtcp2_ksl_blk. Otherwise, it has data. The key is stored at the - * location starting at key. + * ngtcp2_ksl_blk. Otherwise, it has data. */ struct ngtcp2_ksl_node { union { ngtcp2_ksl_blk *blk; void *data; }; - union { - uint64_t align; - /* key is a buffer to include key associated to this node. - Because the length of key is unknown until ngtcp2_ksl_init is - called, the actual buffer will be allocated after this - field. */ - uint8_t key[1]; - }; }; /* @@ -88,14 +79,14 @@ struct ngtcp2_ksl_blk { uint32_t n; /* leaf is nonzero if this block contains leaf nodes. */ uint32_t leaf; + ngtcp2_ksl_node nodes[NGTCP2_KSL_MAX_NBLK]; union { uint64_t align; - /* nodes is a buffer to contain NGTCP2_KSL_MAX_NBLK - ngtcp2_ksl_node objects. Because ngtcp2_ksl_node object is - allocated along with the additional variable length key - storage, the size of buffer is unknown until ngtcp2_ksl_init is - called. */ - uint8_t nodes[1]; + /* keys is a buffer to include NGTCP2_KSL_MAX_NBLK keys. + Because the length of key is unknown until ngtcp2_ksl_init + is called, the actual buffer will be allocated after this + field. */ + uint8_t keys[1]; }; }; @@ -131,11 +122,10 @@ typedef size_t (*ngtcp2_ksl_search)(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, static size_t ksl_##NAME##_search( \ const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, const ngtcp2_ksl_key *key) { \ size_t i; \ - ngtcp2_ksl_node *node; \ + uint8_t *node_key; \ \ - for (i = 0, node = (ngtcp2_ksl_node *)(void *)blk->nodes; \ - i < blk->n && COMPAR((ngtcp2_ksl_key *)node->key, key); ++i, \ - node = (ngtcp2_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen)) \ + for (i = 0, node_key = blk->keys; i < blk->n && COMPAR(node_key, key); \ + ++i, node_key += ksl->aligned_keylen) \ ; \ \ return i; \ @@ -169,9 +159,7 @@ struct ngtcp2_ksl { size_t n; /* keylen is the size of key */ size_t keylen; - /* nodelen is the actual size of ngtcp2_ksl_node including key - storage. */ - size_t nodelen; + size_t aligned_keylen; }; /* @@ -290,12 +278,11 @@ size_t ngtcp2_ksl_len(const ngtcp2_ksl *ksl); void ngtcp2_ksl_clear(ngtcp2_ksl *ksl); /* - * ngtcp2_ksl_nth_node returns the |n|th node under |blk|. + * ngtcp2_ksl_nth_key returns the |n|th key under |blk|. */ -static inline ngtcp2_ksl_node *ngtcp2_ksl_nth_node(const ngtcp2_ksl *ksl, - const ngtcp2_ksl_blk *blk, - size_t n) { - return (ngtcp2_ksl_node *)(void *)(blk->nodes + ksl->nodelen * n); +static inline const ngtcp2_ksl_key * +ngtcp2_ksl_nth_key(const ngtcp2_ksl *ksl, const ngtcp2_ksl_blk *blk, size_t n) { + return blk->keys + n * ksl->aligned_keylen; } #ifndef WIN32 @@ -319,7 +306,7 @@ void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl, * ngtcp2_ksl_it_end(it) returns nonzero. */ static inline void *ngtcp2_ksl_it_get(const ngtcp2_ksl_it *it) { - return ngtcp2_ksl_nth_node(it->ksl, it->blk, it->i)->data; + return it->blk->nodes[it->i].data; } /* @@ -361,8 +348,8 @@ int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it); * It is undefined to call this function when ngtcp2_ksl_it_end(it) * returns nonzero. */ -static inline ngtcp2_ksl_key *ngtcp2_ksl_it_key(const ngtcp2_ksl_it *it) { - return (ngtcp2_ksl_key *)ngtcp2_ksl_nth_node(it->ksl, it->blk, it->i)->key; +static inline const ngtcp2_ksl_key *ngtcp2_ksl_it_key(const ngtcp2_ksl_it *it) { + return ngtcp2_ksl_nth_key(it->ksl, it->blk, it->i); } /* diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.c index 5c31f44a73..d11e24455a 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.c @@ -42,7 +42,7 @@ void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid, ngtcp2_printf log_printf, ngtcp2_tstamp ts, void *user_data) { if (scid) { - ngtcp2_encode_hex(log->scid, scid->data, scid->datalen); + ngtcp2_encode_hex_cstr(log->scid, scid->data, scid->datalen); } else { log->scid[0] = '\0'; } @@ -267,7 +267,7 @@ static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, fr->type == NGTCP2_FRAME_CONNECTION_CLOSE ? strerrorcode(fr->error_code) : strapperrorcode(fr->error_code), fr->error_code, fr->frame_type, fr->reasonlen, - ngtcp2_encode_printable_ascii(reason, fr->reason, reasonlen)); + ngtcp2_encode_printable_ascii_cstr(reason, fr->reason, reasonlen)); } static void log_fr_max_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -335,8 +335,8 @@ static void log_fr_streams_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_new_connection_id *fr, const char *dir) { - uint8_t buf[sizeof(fr->stateless_reset_token) * 2 + 1]; - uint8_t cid[sizeof(fr->cid.data) * 2 + 1]; + char buf[sizeof(fr->stateless_reset_token) * 2 + 1]; + char cid[sizeof(fr->cid.data) * 2 + 1]; ngtcp2_log_infof_raw( log, NGTCP2_LOG_EVENT_FRM, @@ -344,10 +344,10 @@ static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, " cid=0x%s retire_prior_to=%" PRIu64 " stateless_reset_token=0x%s", NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->seq, - (const char *)ngtcp2_encode_hex(cid, fr->cid.data, fr->cid.datalen), + ngtcp2_encode_hex_cstr(cid, fr->cid.data, fr->cid.datalen), fr->retire_prior_to, - (const char *)ngtcp2_encode_hex(buf, fr->stateless_reset_token, - sizeof(fr->stateless_reset_token))); + ngtcp2_encode_hex_cstr(buf, fr->stateless_reset_token, + sizeof(fr->stateless_reset_token))); } static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -364,25 +364,25 @@ static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, static void log_fr_path_challenge(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_path_challenge *fr, const char *dir) { - uint8_t buf[sizeof(fr->data) * 2 + 1]; + char buf[sizeof(fr->data) * 2 + 1]; - ngtcp2_log_infof_raw( - log, NGTCP2_LOG_EVENT_FRM, - NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64 ") data=0x%s", - NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, - (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64 + ") data=0x%s", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, + ngtcp2_encode_hex_cstr(buf, fr->data, sizeof(fr->data))); } static void log_fr_path_response(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_path_response *fr, const char *dir) { - uint8_t buf[sizeof(fr->data) * 2 + 1]; + char buf[sizeof(fr->data) * 2 + 1]; - ngtcp2_log_infof_raw( - log, NGTCP2_LOG_EVENT_FRM, - NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64 ") data=0x%s", - NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, - (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64 + ") data=0x%s", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, + ngtcp2_encode_hex_cstr(buf, fr->data, sizeof(fr->data))); } static void log_fr_crypto(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -398,21 +398,21 @@ static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_new_token *fr, const char *dir) { /* Show at most first 64 bytes of token. If token is longer than 64 bytes, log first 64 bytes and then append "*" */ - uint8_t buf[128 + 1 + 1]; - uint8_t *p; + char buf[128 + 1 + 1]; + char *p; if (fr->tokenlen > 64) { - p = ngtcp2_encode_hex(buf, fr->token, 64); + p = ngtcp2_encode_hex_cstr(buf, fr->token, 64); p[128] = '*'; p[129] = '\0'; } else { - p = ngtcp2_encode_hex(buf, fr->token, fr->tokenlen); + p = ngtcp2_encode_hex_cstr(buf, fr->token, fr->tokenlen); } ngtcp2_log_infof_raw( log, NGTCP2_LOG_EVENT_FRM, NGTCP2_LOG_PKT " NEW_TOKEN(0x%02" PRIx64 ") token=0x%s len=%zu", - NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, (const char *)p, fr->tokenlen); + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, p, fr->tokenlen); } static void log_fr_retire_connection_id(ngtcp2_log *log, @@ -550,7 +550,7 @@ void ngtcp2_log_rx_vn(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, } void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) { - uint8_t buf[sizeof(sr->stateless_reset_token) * 2 + 1]; + char buf[sizeof(sr->stateless_reset_token) * 2 + 1]; ngtcp2_pkt_hd shd; ngtcp2_pkt_hd *hd = &shd; @@ -565,16 +565,16 @@ void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) { ngtcp2_log_infof_raw( log, NGTCP2_LOG_EVENT_PKT, NGTCP2_LOG_PKT " token=0x%s randlen=%zu", NGTCP2_LOG_PKT_HD_FIELDS("rx"), - (const char *)ngtcp2_encode_hex(buf, sr->stateless_reset_token, - sizeof(sr->stateless_reset_token)), + ngtcp2_encode_hex_cstr(buf, sr->stateless_reset_token, + sizeof(sr->stateless_reset_token)), sr->randlen); } void ngtcp2_log_remote_tp(ngtcp2_log *log, const ngtcp2_transport_params *params) { - uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1]; - uint8_t addr[16 * 2 + 7 + 1]; - uint8_t cid[NGTCP2_MAX_CIDLEN * 2 + 1]; + char token[NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1]; + char addr[16 * 2 + 7 + 1]; + char cid[NGTCP2_MAX_CIDLEN * 2 + 1]; size_t i; const ngtcp2_sockaddr_in *sa_in; const ngtcp2_sockaddr_in6 *sa_in6; @@ -588,18 +588,18 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, if (params->stateless_reset_token_present) { ngtcp2_log_infof_raw( log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " stateless_reset_token=0x%s", - (const char *)ngtcp2_encode_hex(token, params->stateless_reset_token, - sizeof(params->stateless_reset_token))); + ngtcp2_encode_hex_cstr(token, params->stateless_reset_token, + sizeof(params->stateless_reset_token))); } if (params->preferred_addr_present) { if (params->preferred_addr.ipv4_present) { sa_in = ¶ms->preferred_addr.ipv4; - ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, - NGTCP2_LOG_TP " preferred_address.ipv4_addr=%s", - (const char *)ngtcp2_encode_ipv4( - addr, (const uint8_t *)&sa_in->sin_addr)); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " preferred_address.ipv4_addr=%s", + ngtcp2_encode_ipv4_cstr(addr, (const uint8_t *)&sa_in->sin_addr)); ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " preferred_address.ipv4_port=%u", ngtcp2_ntohs(sa_in->sin_port)); @@ -608,10 +608,10 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, if (params->preferred_addr.ipv6_present) { sa_in6 = ¶ms->preferred_addr.ipv6; - ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, - NGTCP2_LOG_TP " preferred_address.ipv6_addr=%s", - (const char *)ngtcp2_encode_ipv6( - addr, (const uint8_t *)&sa_in6->sin6_addr)); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " preferred_address.ipv6_addr=%s", + ngtcp2_encode_ipv6_cstr(addr, (const uint8_t *)&sa_in6->sin6_addr)); ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " preferred_address.ipv6_port=%u", ngtcp2_ntohs(sa_in6->sin6_port)); @@ -619,38 +619,36 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, ngtcp2_log_infof_raw( log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " preferred_address.cid=0x%s", - (const char *)ngtcp2_encode_hex(cid, params->preferred_addr.cid.data, - params->preferred_addr.cid.datalen)); + ngtcp2_encode_hex_cstr(cid, params->preferred_addr.cid.data, + params->preferred_addr.cid.datalen)); ngtcp2_log_infof_raw( log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s", - (const char *)ngtcp2_encode_hex( + ngtcp2_encode_hex_cstr( token, params->preferred_addr.stateless_reset_token, sizeof(params->preferred_addr.stateless_reset_token))); } if (params->original_dcid_present) { - ngtcp2_log_infof_raw( - log, NGTCP2_LOG_EVENT_CRY, - NGTCP2_LOG_TP " original_destination_connection_id=0x%s", - (const char *)ngtcp2_encode_hex(cid, params->original_dcid.data, - params->original_dcid.datalen)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP + " original_destination_connection_id=0x%s", + ngtcp2_encode_hex_cstr(cid, params->original_dcid.data, + params->original_dcid.datalen)); } if (params->retry_scid_present) { - ngtcp2_log_infof_raw( - log, NGTCP2_LOG_EVENT_CRY, - NGTCP2_LOG_TP " retry_source_connection_id=0x%s", - (const char *)ngtcp2_encode_hex(cid, params->retry_scid.data, - params->retry_scid.datalen)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " retry_source_connection_id=0x%s", + ngtcp2_encode_hex_cstr(cid, params->retry_scid.data, + params->retry_scid.datalen)); } if (params->initial_scid_present) { - ngtcp2_log_infof_raw( - log, NGTCP2_LOG_EVENT_CRY, - NGTCP2_LOG_TP " initial_source_connection_id=0x%s", - (const char *)ngtcp2_encode_hex(cid, params->initial_scid.data, - params->initial_scid.datalen)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " initial_source_connection_id=0x%s", + ngtcp2_encode_hex_cstr(cid, params->initial_scid.data, + params->initial_scid.datalen)); } ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, @@ -732,8 +730,8 @@ void ngtcp2_log_pkt_lost(ngtcp2_log *log, int64_t pkt_num, uint8_t type, static void log_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const char *dir) { - uint8_t dcid[sizeof(hd->dcid.data) * 2 + 1]; - uint8_t scid[sizeof(hd->scid.data) * 2 + 1]; + char dcid[sizeof(hd->dcid.data) * 2 + 1]; + char scid[sizeof(hd->scid.data) * 2 + 1]; if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_PKT)) { return; @@ -743,15 +741,15 @@ static void log_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, ngtcp2_log_infof( log, NGTCP2_LOG_EVENT_PKT, "%s pkn=%" PRId64 " dcid=0x%s type=%s k=%d", dir, hd->pkt_num, - (const char *)ngtcp2_encode_hex(dcid, hd->dcid.data, hd->dcid.datalen), + ngtcp2_encode_hex_cstr(dcid, hd->dcid.data, hd->dcid.datalen), strpkttype(hd), (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) != 0); } else { ngtcp2_log_infof( log, NGTCP2_LOG_EVENT_PKT, "%s pkn=%" PRId64 " dcid=0x%s scid=0x%s version=0x%08x type=%s len=%zu", dir, hd->pkt_num, - (const char *)ngtcp2_encode_hex(dcid, hd->dcid.data, hd->dcid.datalen), - (const char *)ngtcp2_encode_hex(scid, hd->scid.data, hd->scid.datalen), + ngtcp2_encode_hex_cstr(dcid, hd->dcid.data, hd->dcid.datalen), + ngtcp2_encode_hex_cstr(scid, hd->scid.data, hd->scid.datalen), hd->version, strpkttype(hd), hd->len); } } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.h index 707cd3089e..fabd5908e0 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_log.h @@ -49,7 +49,7 @@ typedef struct ngtcp2_log { log_pritnf. */ void *user_data; /* scid is SCID encoded as NULL-terminated hex string. */ - uint8_t scid[NGTCP2_MAX_CIDLEN * 2 + 1]; + char scid[NGTCP2_MAX_CIDLEN * 2 + 1]; } ngtcp2_log; /** diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.c index 246c779f29..6b332f6b58 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.c @@ -34,11 +34,10 @@ #define NGTCP2_INITIAL_HASHBITS 4 void ngtcp2_map_init(ngtcp2_map *map, uint64_t seed, const ngtcp2_mem *mem) { - map->mem = mem; - map->hashbits = 0; - map->table = NULL; - map->seed = seed; - map->size = 0; + *map = (ngtcp2_map){ + .mem = mem, + .seed = seed, + }; } void ngtcp2_map_free(ngtcp2_map *map) { @@ -46,30 +45,27 @@ void ngtcp2_map_free(ngtcp2_map *map) { return; } - ngtcp2_mem_free(map->mem, map->table); + ngtcp2_mem_free(map->mem, map->keys); } int ngtcp2_map_each(const ngtcp2_map *map, int (*func)(void *data, void *ptr), void *ptr) { int rv; size_t i; - ngtcp2_map_bucket *bkt; size_t tablelen; if (map->size == 0) { return 0; } - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - - if (bkt->data == NULL) { + if (map->psl[i] == 0) { continue; } - rv = func(bkt->data, ptr); + rv = func(map->data[i], ptr); if (rv != 0) { return rv; } @@ -78,176 +74,228 @@ int ngtcp2_map_each(const ngtcp2_map *map, int (*func)(void *data, void *ptr), return 0; } -static size_t map_hash(const ngtcp2_map *map, ngtcp2_map_key_type key) { - /* hasher from - https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs - We do not perform finalization here because we use top bits - anyway. */ - key += map->seed; - key *= 0xf1357aea2e62a9c5ull; - return (size_t)((key * 11400714819323198485llu) >> (64 - map->hashbits)); -} - -static void map_bucket_swap(ngtcp2_map_bucket *a, ngtcp2_map_bucket *b) { - ngtcp2_map_bucket c = *a; +/* Hasher from + https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs + to maximize the output's sensitivity to all input bits. */ +#define NGTCP2_MAP_HASHER 0xf1357aea2e62a9c5ull +/* 64-bit Fibonacci hashing constant, Golden Ratio constant, to get + the high bits with the good distribution. */ +#define NGTCP2_MAP_FIBO 0x9e3779b97f4a7c15ull - *a = *b; - *b = c; +static size_t map_index(const ngtcp2_map *map, ngtcp2_map_key_type key) { + key += map->seed; + key *= NGTCP2_MAP_HASHER; + return (size_t)((key * NGTCP2_MAP_FIBO) >> (64 - map->hashbits)); } #ifndef WIN32 void ngtcp2_map_print_distance(const ngtcp2_map *map) { size_t i; size_t idx; - ngtcp2_map_bucket *bkt; size_t tablelen; if (map->size == 0) { return; } - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - - if (bkt->data == NULL) { + if (map->psl[i] == 0) { fprintf(stderr, "@%zu \n", i); continue; } - idx = map_hash(map, bkt->key); - fprintf(stderr, "@%zu hash=%zu key=%" PRIu64 " base=%zu distance=%u\n", i, - map_hash(map, bkt->key), bkt->key, idx, bkt->psl); + idx = map_index(map, map->keys[i]); + fprintf(stderr, "@%zu key=%" PRIu64 " base=%zu distance=%u\n", i, + map->keys[i], idx, map->psl[i] - 1); } } #endif /* !defined(WIN32) */ -static int map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data) { - size_t idx = map_hash(map, key); - ngtcp2_map_bucket b = { - .key = key, - .data = data, - }; - ngtcp2_map_bucket *bkt; - size_t mask = (1u << map->hashbits) - 1; +static void map_set_entry(ngtcp2_map *map, size_t idx, ngtcp2_map_key_type key, + void *data, size_t psl) { + map->keys[idx] = key; + map->data[idx] = data; + map->psl[idx] = (uint8_t)psl; +} + +#define NGTCP2_SWAP(TYPE, A, B) \ + do { \ + TYPE t = (TYPE) * (A); \ + \ + *(A) = *(B); \ + *(B) = t; \ + } while (0) + +/* + * map_insert inserts |key| and |data| to |map|, and returns the index + * where the pair is stored if it succeeds. Otherwise, it returns one + * of the following negative error codes: + * + * NGTCP2_ERR_INVALID_ARGUMENT + * The another data associated to |key| is already present. + */ +static ngtcp2_ssize map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, + void *data) { + size_t idx = map_index(map, key); + size_t mask = ((size_t)1 << map->hashbits) - 1; + size_t psl = 1; + size_t kpsl; for (;;) { - bkt = &map->table[idx]; + kpsl = map->psl[idx]; - if (bkt->data == NULL) { - *bkt = b; + if (kpsl == 0) { + map_set_entry(map, idx, key, data, psl); ++map->size; - return 0; + + return (ngtcp2_ssize)idx; } - if (b.psl > bkt->psl) { - map_bucket_swap(bkt, &b); - } else if (bkt->key == key) { - /* TODO This check is just a waste after first swap or if this - function is called from map_resize. That said, there is no - difference with or without this conditional in performance - wise. */ + if (psl > kpsl) { + NGTCP2_SWAP(ngtcp2_map_key_type, &key, &map->keys[idx]); + NGTCP2_SWAP(void *, &data, &map->data[idx]); + NGTCP2_SWAP(uint8_t, &psl, &map->psl[idx]); + } else if (map->keys[idx] == key) { + /* This check ensures that no duplicate keys are inserted. But + it is just a waste after first swap or if this function is + called from map_resize. That said, there is no difference + with or without this conditional in performance wise. */ return NGTCP2_ERR_INVALID_ARGUMENT; } - ++b.psl; + ++psl; idx = (idx + 1) & mask; } } +/* NGTCP2_MAP_MAX_HASHBITS is the maximum number of bits used for hash + table. The theoretical limit of the maximum number of keys that + can be stored is 1 << NGTCP2_MAP_MAX_HASHBITS. */ +#define NGTCP2_MAP_MAX_HASHBITS (sizeof(size_t) * 8 - 1) + static int map_resize(ngtcp2_map *map, size_t new_hashbits) { size_t i; - ngtcp2_map_bucket *bkt; size_t tablelen; - int rv; + ngtcp2_ssize idx; ngtcp2_map new_map = { - .table = ngtcp2_mem_calloc(map->mem, 1u << new_hashbits, - sizeof(ngtcp2_map_bucket)), .mem = map->mem, .seed = map->seed, .hashbits = new_hashbits, }; - (void)rv; + void *buf; + (void)idx; - if (new_map.table == NULL) { + if (new_hashbits > NGTCP2_MAP_MAX_HASHBITS) { return NGTCP2_ERR_NOMEM; } + tablelen = (size_t)1 << new_hashbits; + + buf = ngtcp2_mem_calloc(map->mem, tablelen, + sizeof(ngtcp2_map_key_type) + sizeof(void *) + + sizeof(uint8_t)); + if (buf == NULL) { + return NGTCP2_ERR_NOMEM; + } + + new_map.keys = buf; + new_map.data = + (void *)((uint8_t *)new_map.keys + tablelen * sizeof(ngtcp2_map_key_type)); + new_map.psl = (uint8_t *)new_map.data + tablelen * sizeof(void *); + if (map->size) { - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - if (bkt->data == NULL) { + if (map->psl[i] == 0) { continue; } - rv = map_insert(&new_map, bkt->key, bkt->data); + idx = map_insert(&new_map, map->keys[i], map->data[i]); - assert(0 == rv); + /* map_insert must not fail because all keys are unique during + resize. */ + assert(idx >= 0); } } - ngtcp2_mem_free(map->mem, map->table); - map->table = new_map.table; + ngtcp2_mem_free(map->mem, map->keys); + map->keys = new_map.keys; + map->data = new_map.data; + map->psl = new_map.psl; map->hashbits = new_hashbits; return 0; } +/* NGTCP2_MAX_PSL_RESIZE_THRESH is the maximum psl threshold. If + reached, resize the table. */ +#define NGTCP2_MAX_PSL_RESIZE_THRESH 128 + int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data) { int rv; + size_t tablelen; + ngtcp2_ssize idx; assert(data); - /* Load factor is 7/8 */ - /* Under the very initial condition, that is map->size == 0 and - map->hashbits == 0, 8 > 7 still holds nicely. */ - if ((map->size + 1) * 8 > (1u << map->hashbits) * 7) { - if (map->hashbits) { - rv = map_resize(map, map->hashbits + 1); - if (rv != 0) { - return rv; - } - } else { - rv = map_resize(map, NGTCP2_INITIAL_HASHBITS); - if (rv != 0) { - return rv; - } + /* tablelen is incorrect if map->hashbits == 0 which leads to + tablelen = 1, but it is only used to check the load factor, and + it works in this special case. */ + tablelen = (size_t)1 << map->hashbits; + + /* Load factor is 7 / 8. Because tablelen is power of 2, (tablelen + - (tablelen >> 3)) computes tablelen * 7 / 8. */ + if (map->size + 1 >= (tablelen - (tablelen >> 3))) { + rv = map_resize(map, map->hashbits ? map->hashbits + 1 + : NGTCP2_INITIAL_HASHBITS); + if (rv != 0) { + return rv; } + + idx = map_insert(map, key, data); + if (idx < 0) { + return (int)idx; + } + + return 0; } - rv = map_insert(map, key, data); - if (rv != 0) { - return rv; + idx = map_insert(map, key, data); + if (idx < 0) { + return (int)idx; } - return 0; + /* Resize if psl reaches really large value which is almost + improbable, but just in case. */ + if (map->psl[idx] - 1 < NGTCP2_MAX_PSL_RESIZE_THRESH) { + return 0; + } + + return map_resize(map, map->hashbits + 1); } void *ngtcp2_map_find(const ngtcp2_map *map, ngtcp2_map_key_type key) { size_t idx; - ngtcp2_map_bucket *bkt; - size_t psl = 0; + size_t psl = 1; size_t mask; if (map->size == 0) { return NULL; } - idx = map_hash(map, key); - mask = (1u << map->hashbits) - 1; + idx = map_index(map, key); + mask = ((size_t)1 << map->hashbits) - 1; for (;;) { - bkt = &map->table[idx]; - - if (bkt->data == NULL || psl > bkt->psl) { + if (psl > map->psl[idx]) { return NULL; } - if (bkt->key == key) { - return bkt->data; + if (map->keys[idx] == key) { + return map->data[idx]; } ++psl; @@ -257,38 +305,36 @@ void *ngtcp2_map_find(const ngtcp2_map *map, ngtcp2_map_key_type key) { int ngtcp2_map_remove(ngtcp2_map *map, ngtcp2_map_key_type key) { size_t idx; - ngtcp2_map_bucket *b, *bkt; - size_t psl = 0; + size_t dest; + size_t psl = 1, kpsl; size_t mask; if (map->size == 0) { return NGTCP2_ERR_INVALID_ARGUMENT; } - idx = map_hash(map, key); - mask = (1u << map->hashbits) - 1; + idx = map_index(map, key); + mask = ((size_t)1 << map->hashbits) - 1; for (;;) { - bkt = &map->table[idx]; - - if (bkt->data == NULL || psl > bkt->psl) { + if (psl > map->psl[idx]) { return NGTCP2_ERR_INVALID_ARGUMENT; } - if (bkt->key == key) { - b = bkt; + if (map->keys[idx] == key) { + dest = idx; idx = (idx + 1) & mask; for (;;) { - bkt = &map->table[idx]; - if (bkt->data == NULL || bkt->psl == 0) { - b->data = NULL; + kpsl = map->psl[idx]; + if (kpsl <= 1) { + map->psl[dest] = 0; break; } - --bkt->psl; - *b = *bkt; - b = bkt; + map_set_entry(map, dest, map->keys[idx], map->data[idx], kpsl - 1); + + dest = idx; idx = (idx + 1) & mask; } @@ -308,7 +354,7 @@ void ngtcp2_map_clear(ngtcp2_map *map) { return; } - memset(map->table, 0, sizeof(*map->table) * (1u << map->hashbits)); + memset(map->psl, 0, sizeof(*map->psl) * ((size_t)1 << map->hashbits)); map->size = 0; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.h index 0c1a76552a..1afe3167e6 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_map.h @@ -38,14 +38,13 @@ typedef uint64_t ngtcp2_map_key_type; -typedef struct ngtcp2_map_bucket { - uint32_t psl; - ngtcp2_map_key_type key; - void *data; -} ngtcp2_map_bucket; - typedef struct ngtcp2_map { - ngtcp2_map_bucket *table; + ngtcp2_map_key_type *keys; + void **data; + /* psl is the Probe Sequence Length. 0 has special meaning that the + element is not stored at i-th position if psl[i] == 0. Because + of this, the actual psl value is psl[i] - 1 if psl[i] > 0. */ + uint8_t *psl; const ngtcp2_mem *mem; uint64_t seed; size_t size; diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.c index 8323873003..c9636a8db9 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.c @@ -28,12 +28,6 @@ #include "ngtcp2_addr.h" -void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local, - const ngtcp2_addr *remote) { - path->local = *local; - path->remote = *remote; -} - void ngtcp2_path_copy(ngtcp2_path *dest, const ngtcp2_path *src) { ngtcp2_addr_copy(&dest->local, &src->local); ngtcp2_addr_copy(&dest->remote, &src->remote); diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.h index a708378db3..9d4205cee2 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_path.h @@ -31,14 +31,6 @@ #include -/* - * ngtcp2_path_init initializes |path| with the given addresses. Note - * that the buffer pointed by local->addr and remote->addr are not - * copied. Their pointer values are assigned instead. - */ -void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local, - const ngtcp2_addr *remote); - /* * ngtcp2_path_storage_init2 initializes |ps| using |path| as initial * data. diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pcg.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pcg.c index 9d0eb57e0d..c8490467e4 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pcg.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pcg.c @@ -66,7 +66,7 @@ void ngtcp2_pcg32_init(ngtcp2_pcg32 *pcg, uint64_t seed) { } static uint32_t pcg_rotr_32(uint32_t value, unsigned int rot) { - return (value >> rot) | (value << ((-rot) & 31)); + return (value >> rot) | (value << ((32 - rot) & 31)); } static uint32_t pcg_output_xsh_rr_64_32(uint64_t state) { diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c index d63dc932e1..db9ecf8313 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c @@ -918,7 +918,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( return NGTCP2_ERR_FRAME_ENCODING; } - p = ngtcp2_get_uvarint(&vi, p); + ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1053,6 +1053,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_ping_frame(ngtcp2_ping *dest, (void)payload; (void)payloadlen; + assert(payloadlen > 0); + dest->type = NGTCP2_FRAME_PING; return 1; } @@ -1321,7 +1323,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_stream *dest, return NGTCP2_ERR_FRAME_ENCODING; } - p = ngtcp2_get_uvarint(&vi, p); + ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1428,6 +1430,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done *dest, (void)payload; (void)payloadlen; + assert(payloadlen > 0); + dest->type = NGTCP2_FRAME_HANDSHAKE_DONE; return 1; } @@ -1442,9 +1446,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest, size_t n; uint64_t vi; - if (payloadlen < len) { - return NGTCP2_ERR_FRAME_ENCODING; - } + assert(payloadlen > 0); type = payload[0]; diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_qlog.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_qlog.c index 19667e17db..b8a94b7c95 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_qlog.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_qlog.c @@ -55,15 +55,9 @@ static uint8_t *write_string_impl(uint8_t *p, const uint8_t *data, #define write_string(DEST, S) \ write_string_impl((DEST), (const uint8_t *)(S), sizeof(S) - 1) -#define NGTCP2_LOWER_XDIGITS "0123456789abcdef" - static uint8_t *write_hex(uint8_t *p, const uint8_t *data, size_t datalen) { - const uint8_t *b = data, *end = data + datalen; *p++ = '"'; - for (; b != end; ++b) { - *p++ = (uint8_t)NGTCP2_LOWER_XDIGITS[*b >> 4]; - *p++ = (uint8_t)NGTCP2_LOWER_XDIGITS[*b & 0xf]; - } + p = ngtcp2_encode_hex(p, data, datalen); *p++ = '"'; return p; } @@ -72,31 +66,12 @@ static uint8_t *write_cid(uint8_t *p, const ngtcp2_cid *cid) { return write_hex(p, cid->data, cid->datalen); } -static uint8_t *write_number(uint8_t *p, uint64_t n) { - size_t nlen = 0; - uint64_t t; - uint8_t *res; - - if (n == 0) { - *p++ = '0'; - return p; - } - for (t = n; t; t /= 10, ++nlen) - ; - p += nlen; - res = p; - for (; n; n /= 10) { - *--p = (uint8_t)((n % 10) + '0'); - } - return res; -} - static uint8_t *write_tstamp(uint8_t *p, ngtcp2_tstamp ts) { - return write_number(p, ts / NGTCP2_MILLISECONDS); + return ngtcp2_encode_uint(p, ts / NGTCP2_MILLISECONDS); } static uint8_t *write_duration(uint8_t *p, ngtcp2_duration duration) { - return write_number(p, duration / NGTCP2_MILLISECONDS); + return ngtcp2_encode_uint(p, duration / NGTCP2_MILLISECONDS); } static uint8_t *write_bool(uint8_t *p, int b) { @@ -132,7 +107,7 @@ static uint8_t *write_pair_number_impl(uint8_t *p, const uint8_t *name, size_t namelen, uint64_t value) { p = write_string_impl(p, name, namelen); *p++ = ':'; - return write_number(p, value); + return ngtcp2_encode_uint(p, value); } #define write_pair_number(DEST, NAME, VALUE) \ @@ -338,10 +313,10 @@ static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) { min_ack = fr->largest_ack - (int64_t)fr->first_ack_range; *p++ = '['; - p = write_number(p, (uint64_t)min_ack); + p = ngtcp2_encode_uint(p, (uint64_t)min_ack); if (largest_ack != min_ack) { *p++ = ','; - p = write_number(p, (uint64_t)largest_ack); + p = ngtcp2_encode_uint(p, (uint64_t)largest_ack); } *p++ = ']'; @@ -351,10 +326,10 @@ static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) { min_ack = largest_ack - (int64_t)range->len; *p++ = ','; *p++ = '['; - p = write_number(p, (uint64_t)min_ack); + p = ngtcp2_encode_uint(p, (uint64_t)min_ack); if (largest_ack != min_ack) { *p++ = ','; - p = write_number(p, (uint64_t)largest_ack); + p = ngtcp2_encode_uint(p, (uint64_t)largest_ack); } *p++ = ']'; } @@ -736,7 +711,7 @@ static void qlog_pkt_write_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, p = write_verbatim(p, "],\"header\":"); p = write_pkt_hd(p, hd); p = write_verbatim(p, ",\"raw\":{\"length\":"); - p = write_number(p, pktlen); + p = ngtcp2_encode_uint(p, pktlen); p = write_verbatim(p, "}}}\n"); qlog->buf.last = p; diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c index ef1938ea63..20eae1d881 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c @@ -36,8 +36,13 @@ int ngtcp2_rob_gap_new(ngtcp2_rob_gap **pg, uint64_t begin, uint64_t end, return NGTCP2_ERR_NOMEM; } - (*pg)->range.begin = begin; - (*pg)->range.end = end; + **pg = (ngtcp2_rob_gap){ + .range = + { + .begin = begin, + .end = end, + }, + }; return 0; } @@ -53,9 +58,14 @@ int ngtcp2_rob_data_new(ngtcp2_rob_data **pd, uint64_t offset, size_t chunk, return NGTCP2_ERR_NOMEM; } - (*pd)->range.begin = offset; - (*pd)->range.end = offset + chunk; - (*pd)->begin = (uint8_t *)(*pd) + sizeof(ngtcp2_rob_data); + **pd = (ngtcp2_rob_data){ + .range = + { + .begin = offset, + .end = offset + chunk, + }, + .begin = (uint8_t *)(*pd) + sizeof(ngtcp2_rob_data), + }; return 0; } @@ -254,9 +264,11 @@ void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) { } if (offset < g->range.end) { - ngtcp2_range r = {offset, g->range.end}; - - ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r); + ngtcp2_ksl_update_key(&rob->gapksl, &g->range, + &(ngtcp2_range){ + .begin = offset, + .end = g->range.end, + }); g->range.begin = offset; break; diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c index 77247108ec..89b395cd95 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.c @@ -32,16 +32,11 @@ #include "ngtcp2_conn_stat.h" void ngtcp2_rs_init(ngtcp2_rs *rs) { - rs->interval = UINT64_MAX; - rs->delivered = 0; - rs->prior_delivered = 0; - rs->prior_ts = UINT64_MAX; - rs->tx_in_flight = 0; - rs->lost = 0; - rs->send_elapsed = 0; - rs->ack_elapsed = 0; - rs->last_end_seq = -1; - rs->is_app_limited = 0; + *rs = (ngtcp2_rs){ + .interval = UINT64_MAX, + .prior_ts = UINT64_MAX, + .last_end_seq = -1, + }; } void ngtcp2_rst_init(ngtcp2_rst *rst) { diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c index 5908fcc5c5..ae68d93e95 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -531,9 +531,10 @@ static void rtb_remove(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it, int rv; (void)rv; + rtb_on_remove(rtb, ent, cstat); + rv = ngtcp2_ksl_remove_hint(&rtb->ents, it, it, &ent->hd.pkt_num); assert(0 == rv); - rtb_on_remove(rtb, ent, cstat); assert(ent->next == NULL); @@ -895,11 +896,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, cc_ack.rtt = ngtcp2_max_uint64(pkt_ts - cc_ack.largest_pkt_sent_ts, NGTCP2_NANOSECONDS); - rv = ngtcp2_conn_update_rtt(conn, cc_ack.rtt, fr->ack_delay_unscaled, ts); - if (rv == 0 && cc->new_rtt_sample && - rtb->largest_acked_tx_pkt_num >= rtb->cc_pkt_num) { - cc->new_rtt_sample(cc, cstat, ts); - } + ngtcp2_conn_update_rtt(conn, cc_ack.rtt, fr->ack_delay_unscaled, ts); } if (conn) { @@ -1193,12 +1190,12 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_cc_ack *cc_ack, int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - ngtcp2_cc_ack cc_ack = { - .largest_pkt_sent_ts = UINT64_MAX, - .rtt = UINT64_MAX, - }; - - return rtb_detect_lost_pkt(rtb, &cc_ack, conn, pktns, cstat, ts); + return rtb_detect_lost_pkt(rtb, + &(ngtcp2_cc_ack){ + .largest_pkt_sent_ts = UINT64_MAX, + .rtt = UINT64_MAX, + }, + conn, pktns, cstat, ts); } void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n) { @@ -1251,8 +1248,9 @@ void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_ksl_it_prev(&it); ent = ngtcp2_ksl_it_get(&it); - if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED) || - ts - ent->lost_ts < timeout) { + assert(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED); + + if (ts - ent->lost_ts < timeout) { return; } @@ -1412,12 +1410,19 @@ int ngtcp2_rtb_reclaim_on_retry(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_log_infof(rtb->log, NGTCP2_LOG_EVENT_LDC, "pkn=%" PRId64 " has already been reclaimed on PTO", ent->hd.pkt_num); + + ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, + rtb->frc_objalloc, rtb->mem); + continue; } if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) && (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_DATAGRAM) || !conn->callbacks.lost_datagram)) { + ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, + rtb->frc_objalloc, rtb->mem); + continue; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h index caa0fb58c5..28b91d8d36 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h @@ -33,10 +33,10 @@ /* NGTCP2_DEFAULT_GLITCH_RATELIM_BURST is the maximum number of tokens in glitch rate limiter. It is also the initial value. */ -#define NGTCP2_DEFAULT_GLITCH_RATELIM_BURST 1000 +#define NGTCP2_DEFAULT_GLITCH_RATELIM_BURST 4000 /* NGTCP2_DEFAULT_GLITCH_RATELIM_RATE is the rate of tokens generated per second for glitch rate limiter. */ -#define NGTCP2_DEFAULT_GLITCH_RATELIM_RATE 33 +#define NGTCP2_DEFAULT_GLITCH_RATELIM_RATE 132 /* * ngtcp2_settings_convert_to_latest converts |src| of version diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c index a61636d188..01f2706043 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c @@ -54,13 +54,19 @@ uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len) { *p++ = (uint8_t)LOWER_XDIGITS[data[i] & 0xf]; } + return p; +} + +char *ngtcp2_encode_hex_cstr(char *dest, const uint8_t *data, size_t len) { + uint8_t *p = ngtcp2_encode_hex((uint8_t *)dest, data, len); + *p = '\0'; return dest; } -char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data, - size_t len) { +char *ngtcp2_encode_printable_ascii_cstr(char *dest, const uint8_t *data, + size_t len) { size_t i; char *p = dest; uint8_t c; @@ -79,40 +85,15 @@ char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data, return dest; } -/* - * write_uint writes |n| to the buffer pointed by |p| in decimal - * representation. It returns |p| plus the number of bytes written. - * The function assumes that the buffer has enough capacity to contain - * a string. - */ -static uint8_t *write_uint(uint8_t *p, uint64_t n) { - size_t nlen = 0; - uint64_t t; - uint8_t *res; - - if (n == 0) { - *p++ = '0'; - return p; - } - for (t = n; t; t /= 10, ++nlen) - ; - p += nlen; - res = p; - for (; n; n /= 10) { - *--p = (uint8_t)((n % 10) + '0'); - } - return res; -} - -uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr) { +char *ngtcp2_encode_ipv4_cstr(char *dest, const uint8_t *addr) { size_t i; - uint8_t *p = dest; + char *p = dest; - p = write_uint(p, addr[0]); + p = (char *)ngtcp2_encode_uint((uint8_t *)p, addr[0]); for (i = 1; i < 4; ++i) { *p++ = '.'; - p = write_uint(p, addr[i]); + p = (char *)ngtcp2_encode_uint((uint8_t *)p, addr[i]); } *p = '\0'; @@ -125,9 +106,9 @@ uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr) { * length |len| to |dest| in hex string. Any leading zeros are * suppressed. It returns |dest| plus the number of bytes written. */ -static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) { +static char *write_hex_zsup(char *dest, const uint8_t *data, size_t len) { size_t i; - uint8_t *p = dest; + char *p = dest; uint8_t d; for (i = 0; i < len; ++i) { @@ -139,7 +120,7 @@ static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) { d &= 0xf; if (d) { - *p++ = (uint8_t)LOWER_XDIGITS[d]; + *p++ = LOWER_XDIGITS[d]; ++i; break; } @@ -152,19 +133,19 @@ static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) { for (; i < len; ++i) { d = data[i]; - *p++ = (uint8_t)LOWER_XDIGITS[d >> 4]; - *p++ = (uint8_t)LOWER_XDIGITS[d & 0xf]; + *p++ = LOWER_XDIGITS[d >> 4]; + *p++ = LOWER_XDIGITS[d & 0xf]; } return p; } -uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr) { +char *ngtcp2_encode_ipv6_cstr(char *dest, const uint8_t *addr) { uint16_t blks[8]; size_t i; size_t zlen, zoff; size_t max_zlen = 0, max_zoff = 8; - uint8_t *p = dest; + char *p = dest; for (i = 0; i < 16; i += sizeof(uint16_t)) { /* Copy in network byte order. */ @@ -231,3 +212,124 @@ int ngtcp2_cmemeq(const uint8_t *a, const uint8_t *b, size_t n) { return rv == 0; } + +/* countl_zero counts the number of leading zeros in |x|. It is + undefined if |x| is 0. */ +static int countl_zero(uint64_t x) { +#ifdef __GNUC__ + return __builtin_clzll(x); +#else /* !defined(__GNUC__) */ + /* This is the same implementation of Go's LeadingZeros64 in + math/bits package. */ + static const uint8_t len8tab[] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + }; + int n = 0; + + if (x >= 1ull << 32) { + x >>= 32; + n += 32; + } + + if (x >= 1 << 16) { + x >>= 16; + n += 16; + } + + if (x >= 1 << 8) { + x >>= 8; + n += 8; + } + + return 64 - (n + len8tab[x]); +#endif /* !defined(__GNUC__) */ +} + +/* + * count_digit returns the minimum number of digits to represent |x| + * in base 10. + * + * credit: + * https://lemire.me/blog/2025/01/07/counting-the-digits-of-64-bit-integers/ + */ +static size_t count_digit(uint64_t x) { + static const uint64_t count_digit_tbl[] = { + 9ull, + 99ull, + 999ull, + 9999ull, + 99999ull, + 999999ull, + 9999999ull, + 99999999ull, + 999999999ull, + 9999999999ull, + 99999999999ull, + 999999999999ull, + 9999999999999ull, + 99999999999999ull, + 999999999999999ull, + 9999999999999999ull, + 99999999999999999ull, + 999999999999999999ull, + 9999999999999999999ull, + }; + size_t y = (size_t)(19 * (63 - countl_zero(x | 1)) >> 6); + + y += x > count_digit_tbl[y]; + + return y + 1; +} + +uint8_t *ngtcp2_encode_uint(uint8_t *dest, uint64_t n) { + static const uint8_t uint_digits[] = + "00010203040506070809101112131415161718192021222324252627282930313233343536" + "37383940414243444546474849505152535455565758596061626364656667686970717273" + "7475767778798081828384858687888990919293949596979899"; + uint8_t *p; + const uint8_t *tp; + + if (n < 10) { + *dest++ = (uint8_t)('0' + n); + return dest; + } + + if (n < 100) { + tp = &uint_digits[n * 2]; + *dest++ = *tp++; + *dest++ = *tp; + return dest; + } + + dest += count_digit(n); + p = dest; + + for (; n >= 100; n /= 100) { + p -= 2; + tp = &uint_digits[(n % 100) * 2]; + p[0] = *tp++; + p[1] = *tp; + } + + if (n < 10) { + *--p = (uint8_t)('0' + n); + return dest; + } + + p -= 2; + tp = &uint_digits[n * 2]; + p[0] = *tp++; + p[1] = *tp; + + return dest; +} diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h index f970c153e8..051053d75b 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h @@ -46,24 +46,31 @@ uint8_t *ngtcp2_setmem(uint8_t *dest, uint8_t b, size_t n); const void *ngtcp2_get_bytes(void *dest, const void *src, size_t n); /* - * ngtcp2_encode_hex encodes |data| of length |len| in hex string. It - * writes additional NULL bytes at the end of the buffer. The buffer - * pointed by |dest| must have at least |len| * 2 + 1 bytes space. - * This function returns |dest|. + * ngtcp2_encode_hex encodes |data| of length |len| in hex string. + * The buffer pointed by |dest| must have at least |len| * 2 bytes + * space. This function returns |dest| + |len| * 2. */ uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len); /* - * ngtcp2_encode_ipv4 encodes binary form IPv4 address stored in + * ngtcp2_encode_hex_cstr encodes |data| of length |len| in hex + * string. It writes additional NULL bytes at the end of the buffer. + * The buffer pointed by |dest| must have at least |len| * 2 + 1 bytes + * space. This function returns |dest|. + */ +char *ngtcp2_encode_hex_cstr(char *dest, const uint8_t *data, size_t len); + +/* + * ngtcp2_encode_ipv4_cstr encodes binary form IPv4 address stored in * |addr| to human readable text form in the buffer pointed by |dest|. * The capacity of buffer must have enough length to store a text form * plus a terminating NULL byte. The resulting text form ends with * NULL byte. The function returns |dest|. */ -uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr); +char *ngtcp2_encode_ipv4_cstr(char *dest, const uint8_t *addr); /* - * ngtcp2_encode_ipv6 encodes binary form IPv6 address stored in + * ngtcp2_encode_ipv6_cstr encodes binary form IPv6 address stored in * |addr| to human readable text form in the buffer pointed by |dest|. * The capacity of buffer must have enough length to store a text form * plus a terminating NULL byte. The resulting text form ends with @@ -72,7 +79,7 @@ uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr); * https://tools.ietf.org/html/rfc5952#section-4. The function * returns |dest|. */ -uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr); +char *ngtcp2_encode_ipv6_cstr(char *dest, const uint8_t *addr); /* * ngtcp2_encode_printable_ascii encodes |data| of length |len| in @@ -81,8 +88,8 @@ uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr); * writes additional NULL bytes at the end of the buffer. |dest| must * have at least |len| + 1 bytes. This function returns |dest|. */ -char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data, - size_t len); +char *ngtcp2_encode_printable_ascii_cstr(char *dest, const uint8_t *data, + size_t len); /* * ngtcp2_cmemeq returns nonzero if the first |n| bytes of the buffers @@ -91,4 +98,12 @@ char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data, */ int ngtcp2_cmemeq(const uint8_t *a, const uint8_t *b, size_t n); +/* + * ngtcp2_encode_uint encodes |n| as a decimal integer to the buffer + * pointed by |dest|. This function assumes that the buffer contains + * the sufficient capacity to write the number. This function returns + * the pointer to the buffer past the last byte written. + */ +uint8_t *ngtcp2_encode_uint(uint8_t *dest, uint64_t n); + #endif /* !defined(NGTCP2_STR_H) */ diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c index faa4177132..26871aa0a2 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c @@ -36,30 +36,27 @@ void ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags, uint64_t max_rx_offset, uint64_t max_tx_offset, void *stream_user_data, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { - strm->pe.index = NGTCP2_PQ_BAD_INDEX; - strm->cycle = 0; - strm->frc_objalloc = frc_objalloc; - strm->tx.acked_offset = NULL; - strm->tx.cont_acked_offset = 0; - strm->tx.streamfrq = NULL; - strm->tx.offset = 0; - strm->tx.max_offset = max_tx_offset; - strm->tx.last_blocked_offset = UINT64_MAX; - strm->tx.last_max_stream_data_ts = UINT64_MAX; - strm->tx.loss_count = 0; - strm->tx.last_lost_pkt_num = -1; - strm->tx.stop_sending_app_error_code = 0; - strm->tx.reset_stream_app_error_code = 0; - strm->rx.rob = NULL; - strm->rx.cont_offset = 0; - strm->rx.last_offset = 0; - strm->rx.max_offset = strm->rx.unsent_max_offset = strm->rx.window = - max_rx_offset; - strm->mem = mem; - strm->stream_id = stream_id; - strm->stream_user_data = stream_user_data; - strm->flags = flags; - strm->app_error_code = 0; + *strm = (ngtcp2_strm){ + .pe.index = NGTCP2_PQ_BAD_INDEX, + .frc_objalloc = frc_objalloc, + .tx = + { + .max_offset = max_tx_offset, + .last_blocked_offset = UINT64_MAX, + .last_max_stream_data_ts = UINT64_MAX, + .last_lost_pkt_num = -1, + }, + .rx = + { + .max_offset = max_rx_offset, + .unsent_max_offset = max_rx_offset, + .window = max_rx_offset, + }, + .mem = mem, + .stream_id = stream_id, + .stream_user_data = stream_user_data, + .flags = flags, + }; } void ngtcp2_strm_free(ngtcp2_strm *strm) { @@ -120,7 +117,7 @@ uint64_t ngtcp2_strm_rx_offset(const ngtcp2_strm *strm) { /* strm_rob_heavily_fragmented returns nonzero if the number of gaps in |rob| exceeds the limit. */ static int strm_rob_heavily_fragmented(const ngtcp2_rob *rob) { - return ngtcp2_ksl_len(&rob->gapksl) >= 1000; + return ngtcp2_ksl_len(&rob->gapksl) >= 4000; } ngtcp2_ssize ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data, @@ -694,12 +691,11 @@ int ngtcp2_strm_is_all_tx_data_fin_acked(const ngtcp2_strm *strm) { ngtcp2_range ngtcp2_strm_get_unacked_range_after(const ngtcp2_strm *strm, uint64_t offset) { - ngtcp2_range gap; - if (strm->tx.acked_offset == NULL) { - gap.begin = strm->tx.cont_acked_offset; - gap.end = UINT64_MAX; - return gap; + return (ngtcp2_range){ + .begin = strm->tx.cont_acked_offset, + .end = UINT64_MAX, + }; } return ngtcp2_gaptr_get_first_gap_after(strm->tx.acked_offset, offset); @@ -754,7 +750,7 @@ int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len) { return rv; } - if (ngtcp2_ksl_len(&strm->tx.acked_offset->gap) >= 1000) { + if (ngtcp2_ksl_len(&strm->tx.acked_offset->gap) >= 4000) { return NGTCP2_ERR_INTERNAL; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.c index ada027b909..537599f6c1 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_vec.c @@ -30,8 +30,11 @@ #include "ngtcp2_str.h" ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len) { - vec->base = (uint8_t *)base; - vec->len = len; + *vec = (ngtcp2_vec){ + .base = (uint8_t *)base, + .len = len, + }; + return vec; } @@ -158,8 +161,10 @@ size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, } else if (*pdstcnt == maxcnt) { break; } else { - dst[*pdstcnt].len = left; - dst[*pdstcnt].base = b->base; + dst[*pdstcnt] = (ngtcp2_vec){ + .base = b->base, + .len = left, + }; ++*pdstcnt; } @@ -199,8 +204,10 @@ size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t dstcnt, } if (src[i].len > left) { - dst[j].base = src[i].base; - dst[j].len = left; + dst[j] = (ngtcp2_vec){ + .base = src[i].base, + .len = left, + }; return j + 1; } diff --git a/src/contrib/libngtcp2/ngtcp2/ngtcp2.h b/src/contrib/libngtcp2/ngtcp2/ngtcp2.h index 5634c9c751..a89e9d8184 100644 --- a/src/contrib/libngtcp2/ngtcp2/ngtcp2.h +++ b/src/contrib/libngtcp2/ngtcp2/ngtcp2.h @@ -5579,7 +5579,9 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr, * |destlen| could be shorten by some factors (e.g., server side * amplification limit). This function returns * :macro:`NGTCP2_ERR_NOBUF` if the resulting buffer is too small even - * if the given buffer has enough space. + * if the given buffer has enough space. This can happen if sending a + * packet would exceed a transmission limit (e.g., for amplification + * attack protection). * * This function must not be called from inside the callback * functions. @@ -5594,7 +5596,8 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr, * :macro:`NGTCP2_ERR_NOMEM` * Out of memory * :macro:`NGTCP2_ERR_NOBUF` - * Buffer is too small + * Buffer is too small or packet would exceed the transmission + * limit (e.g., for amplification attack protection). * :macro:`NGTCP2_ERR_INVALID_STATE` * The current state does not allow sending CONNECTION_CLOSE * frame. @@ -5916,9 +5919,9 @@ NGTCP2_EXTERN void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps); * * :member:`handshake_timeout ` = * ``UINT64_MAX`` * * :member:`glitch_ratelim_burst - * ` = 1000 + * ` = 4000 * * :member:`glitch_ratelim_rate - * ` = 33 + * ` = 132 */ NGTCP2_EXTERN void ngtcp2_settings_default_versioned(int settings_version, ngtcp2_settings *settings); diff --git a/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h b/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h index 003ec6b4c3..c2099d2495 100644 --- a/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h +++ b/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h @@ -627,7 +627,10 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( * @macro * * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` is the maximum length - * of a token generated by `ngtcp2_crypto_generate_regular_token`. + * of a token generated by `ngtcp2_crypto_generate_regular_token`. + * `ngtcp2_crypto_generate_regular_token2` generates a token of length + * at most :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` bytes + the + * length of the provided opaque data. */ #define NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN \ (/* magic = */ 1 + sizeof(ngtcp2_tstamp) + /* aead tag = */ 16 + \ @@ -787,6 +790,77 @@ NGTCP2_EXTERN int ngtcp2_crypto_verify_regular_token( size_t secretlen, const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts); +/** + * @function + * + * `ngtcp2_crypto_generate_regular_token2` generates a token in the + * buffer pointed by |token| that is sent with NEW_TOKEN frame. The + * buffer pointed by |token| must have at least + * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` + |datalen| bytes long. + * The successfully generated token starts with + * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR`. |secret| of length + * |secretlen| is a keying material to generate keys to encrypt the + * token. |remote_addr| of length |remote_addrlen| is an address of + * client. |ts| is the timestamp when the token is generated. |data| + * of length |datalen| is an opaque data embedded in the token. + * |datalen| must be less than or equal to 256. + * + * Calling this function with |datalen| = 0 is equivalent to calling + * `ngtcp2_crypto_generate_regular_token`. + * + * To get the opaque data after successful verification, use + * `ngtcp2_crypto_verify_regular_token2`. + * `ngtcp2_crypto_verify_regular_token` can verify the token with + * |datalen| > 0, but it discards the opaque data. + * + * This function returns the length of generated token if it succeeds, + * or -1. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_regular_token2( + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const void *data, size_t datalen, ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_crypto_verify_regular_token2` verifies a regular token + * stored in the buffer pointed by |token| of length |tokenlen|. + * |secret| of length |secretlen| is a keying material to generate + * keys to decrypt the token. |remote_addr| of length + * |remote_addrlen| is an address of client. |timeout| is the period + * during which the token is valid. |ts| is the current timestamp. + * |data| is the pointer to the buffer of length at least + * |max_datalen| bytes. If the token is verified successfully, the + * opaque data embedded in the token is copied to the buffer pointed + * by |data|. + * + * If |tokenlen| is less than + * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN`, this function returns + * :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN`. + * + * If the length of opaque data is larger than |max_datalen|, the + * verification still succeeds, but nothing is written to the buffer + * pointed by |data|, and this function returns 0. In other words, + * the opaque data is discarded. + * + * This function returns the number of the opaque data written to the + * buffer pointed by |data| if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN` + * A token is badly formatted; or verifying the integrity + * protection failed. + * :macro:`NGTCP2_CRYPTO_ERR_VERIFY_TOKEN` + * A token validity has expired. + * :macro:`NGTCP2_CRYPTO_ERR_INTERNAL` + * Internal error occurred. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_verify_regular_token2( + void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts); + /** * @function * diff --git a/src/contrib/libngtcp2/ngtcp2/version.h b/src/contrib/libngtcp2/ngtcp2/version.h index 3ff1ebac97..3e60b39d5d 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.17.0" +#define NGTCP2_VERSION "1.18.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 0x011100 +#define NGTCP2_VERSION_NUM 0x011200 #endif /* !defined(NGTCP2_VERSION_H) */