From 96e846de8965b97a8b34e22bebaa8a55ecc8f252 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Mon, 25 Nov 2024 20:01:52 -0500 Subject: [PATCH] deps: update ngtcp2 to 1.9.0 PR-URL: https://github.com/nodejs/node/pull/55975 Reviewed-By: Luigi Pinca Reviewed-By: Rafael Gonzaga Reviewed-By: Richard Lau --- deps/ngtcp2/ngtcp2.gyp | 3 +- .../ngtcp2/crypto/boringssl/boringssl.c | 41 +- .../crypto/includes/ngtcp2/ngtcp2_crypto.h | 219 ++- .../includes/ngtcp2/ngtcp2_crypto_boringssl.h | 10 +- .../includes/ngtcp2/ngtcp2_crypto_picotls.h | 18 +- .../includes/ngtcp2/ngtcp2_crypto_quictls.h | 10 +- .../includes/ngtcp2/ngtcp2_crypto_wolfssl.h | 10 +- deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c | 10 +- deps/ngtcp2/ngtcp2/crypto/quictls/quictls.c | 97 +- deps/ngtcp2/ngtcp2/crypto/shared.c | 404 +++-- deps/ngtcp2/ngtcp2/crypto/shared.h | 24 +- deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c | 43 +- .../ngtcp2/lib/includes/ngtcp2/ngtcp2.h | 332 ++-- .../ngtcp2/lib/includes/ngtcp2/version.h | 10 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c | 58 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h | 29 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c | 10 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.h | 11 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c | 375 ++-- deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h | 15 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c | 542 +++--- deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h | 105 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c | 22 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h | 59 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c | 1548 +++++++++-------- deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h | 79 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h | 9 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c | 151 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h | 70 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.c | 66 - deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c | 831 +-------- deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h | 65 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_err.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c | 19 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h | 27 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c | 42 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.h | 20 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.c | 19 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.h | 35 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c | 271 +-- deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h | 158 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c | 258 ++- deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h | 35 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c | 220 +-- deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h | 66 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.h | 8 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h | 48 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h | 26 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_opl.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c | 191 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h | 128 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pktns_id.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c | 55 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.h | 13 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c | 79 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h | 59 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c | 53 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h | 69 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c | 2 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h | 6 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c | 56 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.h | 10 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c | 6 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_range.h | 6 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rcvry.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c | 34 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h | 26 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c | 45 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h | 28 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c | 35 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h | 18 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c | 322 ++-- deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h | 78 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.c | 91 + deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h | 73 + deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c | 125 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h | 73 +- .../ngtcp2/lib/ngtcp2_transport_params.c | 886 ++++++++++ ...conversion.h => ngtcp2_transport_params.h} | 55 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_tstamp.h | 4 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.c | 19 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.h | 12 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c | 9 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h | 30 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_version.c | 2 +- deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.h | 4 +- 92 files changed, 4936 insertions(+), 4334 deletions(-) delete mode 100644 deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.c create mode 100644 deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.c create mode 100644 deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h create mode 100644 deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.c rename deps/ngtcp2/ngtcp2/lib/{ngtcp2_conversion.h => ngtcp2_transport_params.h} (55%) diff --git a/deps/ngtcp2/ngtcp2.gyp b/deps/ngtcp2/ngtcp2.gyp index 0f2929b75478f1..68013580874b09 100644 --- a/deps/ngtcp2/ngtcp2.gyp +++ b/deps/ngtcp2/ngtcp2.gyp @@ -13,7 +13,6 @@ 'ngtcp2/lib/ngtcp2_cid.c', 'ngtcp2/lib/ngtcp2_conn.c', 'ngtcp2/lib/ngtcp2_conv.c', - 'ngtcp2/lib/ngtcp2_conversion.c', 'ngtcp2/lib/ngtcp2_crypto.c', 'ngtcp2/lib/ngtcp2_err.c', 'ngtcp2/lib/ngtcp2_frame_chain.c', @@ -37,8 +36,10 @@ 'ngtcp2/lib/ngtcp2_rob.c', 'ngtcp2/lib/ngtcp2_rst.c', 'ngtcp2/lib/ngtcp2_rtb.c', + 'ngtcp2/lib/ngtcp2_settings.c', 'ngtcp2/lib/ngtcp2_str.c', 'ngtcp2/lib/ngtcp2_strm.c', + 'ngtcp2/lib/ngtcp2_transport_params.c', 'ngtcp2/lib/ngtcp2_unreachable.c', 'ngtcp2/lib/ngtcp2_vec.c', 'ngtcp2/lib/ngtcp2_version.c', diff --git a/deps/ngtcp2/ngtcp2/crypto/boringssl/boringssl.c b/deps/ngtcp2/ngtcp2/crypto/boringssl/boringssl.c index 50b89110e36ff7..283063f738e2af 100644 --- a/deps/ngtcp2/ngtcp2/crypto/boringssl/boringssl.c +++ b/deps/ngtcp2/ngtcp2/crypto/boringssl/boringssl.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include @@ -52,15 +52,15 @@ typedef struct ngtcp2_crypto_boringssl_cipher { } ngtcp2_crypto_boringssl_cipher; static ngtcp2_crypto_boringssl_cipher crypto_cipher_aes_128 = { - NGTCP2_CRYPTO_BORINGSSL_CIPHER_TYPE_AES_128, + NGTCP2_CRYPTO_BORINGSSL_CIPHER_TYPE_AES_128, }; static ngtcp2_crypto_boringssl_cipher crypto_cipher_aes_256 = { - NGTCP2_CRYPTO_BORINGSSL_CIPHER_TYPE_AES_256, + NGTCP2_CRYPTO_BORINGSSL_CIPHER_TYPE_AES_256, }; static ngtcp2_crypto_boringssl_cipher crypto_cipher_chacha20 = { - NGTCP2_CRYPTO_BORINGSSL_CIPHER_TYPE_CHACHA20, + NGTCP2_CRYPTO_BORINGSSL_CIPHER_TYPE_CHACHA20, }; ngtcp2_crypto_aead *ngtcp2_crypto_aead_aes_128_gcm(ngtcp2_crypto_aead *aead) { @@ -175,7 +175,7 @@ static ngtcp2_crypto_ctx *crypto_ctx_cipher_id(ngtcp2_crypto_ctx *ctx, ctx->hp.native_handle = (void *)crypto_cipher_id_get_hp(cipher_id); ctx->max_encryption = crypto_cipher_id_get_aead_max_encryption(cipher_id); ctx->max_decryption_failure = - crypto_cipher_id_get_aead_max_decryption_failure(cipher_id); + crypto_cipher_id_get_aead_max_decryption_failure(cipher_id); return ctx; } @@ -413,12 +413,12 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, AES_ecb_encrypt(sample, dest, &ctx->aes_key, 1); return 0; case NGTCP2_CRYPTO_BORINGSSL_CIPHER_TYPE_CHACHA20: -#if defined(WORDS_BIGENDIAN) +#ifdef WORDS_BIGENDIAN counter = (uint32_t)sample[0] + (uint32_t)(sample[1] << 8) + (uint32_t)(sample[2] << 16) + (uint32_t)(sample[3] << 24); -#else /* !WORDS_BIGENDIAN */ +#else /* !defined(WORDS_BIGENDIAN) */ memcpy(&counter, sample, sizeof(counter)); -#endif /* !WORDS_BIGENDIAN */ +#endif /* !defined(WORDS_BIGENDIAN) */ CRYPTO_chacha_20(dest, PLAINTEXT, sizeof(PLAINTEXT) - 1, ctx->key, sample + sizeof(counter), counter); return 0; @@ -429,17 +429,16 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, } int ngtcp2_crypto_read_write_crypto_data( - ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, - const uint8_t *data, size_t datalen) { + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + const uint8_t *data, size_t datalen) { SSL *ssl = ngtcp2_conn_get_tls_native_handle(conn); int rv; int err; if (SSL_provide_quic_data( - ssl, - ngtcp2_crypto_boringssl_from_ngtcp2_encryption_level( - encryption_level), - data, datalen) != 1) { + ssl, + ngtcp2_crypto_boringssl_from_ngtcp2_encryption_level(encryption_level), + data, datalen) != 1) { return -1; } @@ -522,7 +521,7 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf, } ngtcp2_encryption_level ngtcp2_crypto_boringssl_from_ssl_encryption_level( - enum ssl_encryption_level_t ssl_level) { + enum ssl_encryption_level_t ssl_level) { switch (ssl_level) { case ssl_encryption_initial: return NGTCP2_ENCRYPTION_LEVEL_INITIAL; @@ -540,7 +539,7 @@ ngtcp2_encryption_level ngtcp2_crypto_boringssl_from_ssl_encryption_level( enum ssl_encryption_level_t ngtcp2_crypto_boringssl_from_ngtcp2_encryption_level( - ngtcp2_encryption_level encryption_level) { + ngtcp2_encryption_level encryption_level) { switch (encryption_level) { case NGTCP2_ENCRYPTION_LEVEL_INITIAL: return ssl_encryption_initial; @@ -582,7 +581,7 @@ static int set_read_secret(SSL *ssl, enum ssl_encryption_level_t bssl_level, ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); ngtcp2_encryption_level level = - ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); + ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); (void)cipher; if (ngtcp2_crypto_derive_and_install_rx_key(conn, NULL, NULL, NULL, level, @@ -599,7 +598,7 @@ static int set_write_secret(SSL *ssl, enum ssl_encryption_level_t bssl_level, ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); ngtcp2_encryption_level level = - ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); + ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); (void)cipher; if (ngtcp2_crypto_derive_and_install_tx_key(conn, NULL, NULL, NULL, level, @@ -615,7 +614,7 @@ static int add_handshake_data(SSL *ssl, enum ssl_encryption_level_t bssl_level, ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); ngtcp2_encryption_level level = - ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); + ngtcp2_crypto_boringssl_from_ssl_encryption_level(bssl_level); int rv; rv = ngtcp2_conn_submit_crypto_data(conn, level, data, datalen); @@ -644,8 +643,8 @@ static int send_alert(SSL *ssl, enum ssl_encryption_level_t bssl_level, } static SSL_QUIC_METHOD quic_method = { - set_read_secret, set_write_secret, add_handshake_data, - flush_flight, send_alert, + set_read_secret, set_write_secret, add_handshake_data, + flush_flight, send_alert, }; static void crypto_boringssl_configure_context(SSL_CTX *ssl_ctx) { diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h index 06427d7a7cac70..68093d18b71b14 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h @@ -29,14 +29,45 @@ #ifdef __cplusplus extern "C" { -#endif +#endif /* defined(__cplusplus) */ #ifdef WIN32 # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN -# endif +# endif /* !defined(WIN32_LEAN_AND_MEAN) */ # include -#endif /* WIN32 */ +#endif /* defined(WIN32) */ + +/** + * @macrosection + * + * ngtcp2 crypto library error codes + */ + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_ERR_INTERNAL` indicates an internal error. + */ +#define NGTCP2_CRYPTO_ERR_INTERNAL -201 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN` indicates that a token + * is unreadable because it is not correctly formatted; or verifying + * the integrity protection failed. + */ +#define NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN -202 + +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_ERR_VERIFY_TOKEN` indicates that a token does + * not probe the client address; or the token validity has expired; or + * it contains invalid Connection ID. + */ +#define NGTCP2_CRYPTO_ERR_VERIFY_TOKEN -203 /** * @function @@ -135,12 +166,9 @@ ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, * * This function returns 0 if it succeeds, or -1. */ -NGTCP2_EXTERN int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, - const ngtcp2_crypto_md *md, - const uint8_t *secret, - size_t secretlen, - const uint8_t *info, - size_t infolen); +NGTCP2_EXTERN int ngtcp2_crypto_hkdf_expand( + uint8_t *dest, size_t destlen, const ngtcp2_crypto_md *md, + const uint8_t *secret, size_t secretlen, const uint8_t *info, size_t infolen); /** * @function @@ -318,8 +346,8 @@ ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp, * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_rx_key( - ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp, - ngtcp2_encryption_level level, const uint8_t *secret, size_t secretlen); + ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp, + ngtcp2_encryption_level level, const uint8_t *secret, size_t secretlen); /** * @function @@ -365,8 +393,8 @@ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_rx_key( * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_tx_key( - ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp, - ngtcp2_encryption_level level, const uint8_t *secret, size_t secretlen); + ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp, + ngtcp2_encryption_level level, const uint8_t *secret, size_t secretlen); /** * @function @@ -405,11 +433,11 @@ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_tx_key( * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int ngtcp2_crypto_update_key( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv, - ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv, - const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, - size_t secretlen); + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv, + ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv, + const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, + size_t secretlen); /** * @function @@ -422,11 +450,11 @@ NGTCP2_EXTERN int ngtcp2_crypto_update_key( * :macro:`NGTCP2_ERR_CALLBACK_FAILURE`. */ NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, - ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv, - const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, - size_t secretlen, void *user_data); + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, + ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv, + const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, + size_t secretlen, void *user_data); /** * @function @@ -514,8 +542,8 @@ ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, * codes. */ NGTCP2_EXTERN int ngtcp2_crypto_recv_crypto_data_cb( - ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, - uint64_t offset, const uint8_t *data, size_t datalen, void *user_data); + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, uint64_t offset, + const uint8_t *data, size_t datalen, void *user_data); /** * @function @@ -529,8 +557,8 @@ NGTCP2_EXTERN int ngtcp2_crypto_recv_crypto_data_cb( * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( - uint8_t *token, const uint8_t *secret, size_t secretlen, - const ngtcp2_cid *cid); + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_cid *cid); /** * @macro @@ -540,7 +568,7 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( * `ngtcp2_crypto_generate_retry_token` or * `ngtcp2_crypto_generate_regular_token`. */ -#define NGTCP2_CRYPTO_TOKEN_RAND_DATALEN 32 +#define NGTCP2_CRYPTO_TOKEN_RAND_DATALEN 16 /** * @macro @@ -550,6 +578,14 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( */ #define NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY 0xb6 +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2` is the magic byte for + * Retry token generated by `ngtcp2_crypto_generate_retry_token2`. + */ +#define NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2 0xb7 + /** * @macro * @@ -569,6 +605,17 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( sizeof(ngtcp2_tstamp) + /* aead tag = */ 16 + \ NGTCP2_CRYPTO_TOKEN_RAND_DATALEN) +/** + * @macro + * + * :macro:`NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN2` is the maximum length of + * a token generated by `ngtcp2_crypto_generate_retry_token2`. + */ +#define NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN2 \ + (/* magic = */ 1 + sizeof(ngtcp2_sockaddr_union) + /* cid len = */ 1 + \ + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp) + /* aead tag = */ 16 + \ + NGTCP2_CRYPTO_TOKEN_RAND_DATALEN) + /** * @macro * @@ -595,13 +642,15 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( * is a Destination Connection ID in Initial packet sent by client. * |ts| is the timestamp when the token is generated. * + * See also `ngtcp2_crypto_generate_retry_token2`. + * * This function returns the length of generated token if it succeeds, * or -1. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_retry_token( - uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version, - const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, - const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts); + uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts); /** * @function @@ -622,10 +671,76 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_retry_token( * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int ngtcp2_crypto_verify_retry_token( - ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen, - const uint8_t *secret, size_t secretlen, uint32_t version, - const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, - const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts); + ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_crypto_generate_retry_token2` generates a token in the + * buffer pointed by |token| that is sent with Retry packet. The + * buffer pointed by |token| must have at least + * :macro:`NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN2` bytes long. The + * successfully generated token starts with + * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2`. |secret| of length + * |secretlen| is a keying material to generate keys to encrypt the + * token. |version| is QUIC version. |remote_addr| of length + * |remote_addrlen| is an address of client. |retry_scid| is a Source + * Connection ID chosen by server, and set in Retry packet. |odcid| + * is a Destination Connection ID in Initial packet sent by client. + * |ts| is the timestamp when the token is generated. + * + * Use this function instead of `ngtcp2_crypto_generate_retry_token` + * if more detailed error handling is required when verifying the + * token. `ngtcp2_crypto_verify_retry_token2` must be used to verify + * the token. + * + * This function returns the length of generated token if it succeeds, + * or -1. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_retry_token2( + uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_crypto_verify_retry_token2` verifies Retry 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. |version| is QUIC version of the Initial packet that + * contains this token. |remote_addr| of length |remote_addrlen| is + * an address of client. |dcid| is a Destination Connection ID in + * Initial packet sent by client. |timeout| is the period during + * which the token is valid. |ts| is the current timestamp. When + * validation succeeds, the extracted Destination Connection ID (which + * is the Destination Connection ID in Initial packet sent by client + * that triggered Retry packet) is stored in the buffer pointed by + * |odcid|. + * + * The token must be generated by + * `ngtcp2_crypto_generate_retry_token2`. + * + * This function returns 0 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 does not probe the client address; or the token + * validity has expired; or it contains invalid Connection ID. + * :macro:`NGTCP2_CRYPTO_ERR_INTERNAL` + * Internal error occurred. + */ +NGTCP2_EXTERN int ngtcp2_crypto_verify_retry_token2( + ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts); /** * @function @@ -644,9 +759,9 @@ NGTCP2_EXTERN int ngtcp2_crypto_verify_retry_token( * or -1. */ NGTCP2_EXTERN 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); + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + ngtcp2_tstamp ts); /** * @function @@ -661,9 +776,9 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_regular_token( * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN 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); + 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 @@ -685,9 +800,9 @@ NGTCP2_EXTERN int ngtcp2_crypto_verify_regular_token( * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN 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, - size_t reasonlen); + 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, + size_t reasonlen); /** * @function @@ -705,9 +820,9 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_write_connection_close( * This function returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_write_retry( - uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, - const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token, - size_t tokenlen); + uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token, + size_t tokenlen); /** * @function @@ -759,7 +874,7 @@ ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx *aead_ctx); * :member:`ngtcp2_callbacks.delete_crypto_aead_ctx` field. */ NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_aead_ctx_cb( - ngtcp2_conn *conn, ngtcp2_crypto_aead_ctx *aead_ctx, void *user_data); + ngtcp2_conn *conn, ngtcp2_crypto_aead_ctx *aead_ctx, void *user_data); /** * @function @@ -771,7 +886,7 @@ NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_aead_ctx_cb( * :member:`ngtcp2_callbacks.delete_crypto_cipher_ctx` field. */ NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_cipher_ctx_cb( - ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data); + ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data); /** * @function @@ -813,7 +928,7 @@ typedef struct ngtcp2_crypto_conn_ref ngtcp2_crypto_conn_ref; * must return non-NULL :type:`ngtcp2_conn` object. */ typedef ngtcp2_conn *(*ngtcp2_crypto_get_conn)( - ngtcp2_crypto_conn_ref *conn_ref); + ngtcp2_crypto_conn_ref *conn_ref); /** * @struct @@ -836,6 +951,6 @@ typedef struct ngtcp2_crypto_conn_ref { #ifdef __cplusplus } -#endif +#endif /* defined(__cplusplus) */ -#endif /* NGTCP2_CRYPTO_H */ +#endif /* !defined(NGTCP2_CRYPTO_H) */ diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h index 43a3c36f03a382..89b26f0bc0e346 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h @@ -31,7 +31,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif /* defined(__cplusplus) */ /** * @function @@ -42,7 +42,7 @@ extern "C" { */ NGTCP2_EXTERN ngtcp2_encryption_level ngtcp2_crypto_boringssl_from_ssl_encryption_level( - enum ssl_encryption_level_t ssl_level); + enum ssl_encryption_level_t ssl_level); /** * @function @@ -53,7 +53,7 @@ ngtcp2_crypto_boringssl_from_ssl_encryption_level( */ NGTCP2_EXTERN enum ssl_encryption_level_t ngtcp2_crypto_boringssl_from_ngtcp2_encryption_level( - ngtcp2_encryption_level encryption_level); + ngtcp2_encryption_level encryption_level); /** * @function @@ -99,6 +99,6 @@ ngtcp2_crypto_boringssl_configure_client_context(SSL_CTX *ssl_ctx); #ifdef __cplusplus } -#endif +#endif /* defined(__cplusplus) */ -#endif /* NGTCP2_CRYPTO_BORINGSSL_H */ +#endif /* !defined(NGTCP2_CRYPTO_BORINGSSL_H) */ diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h index 61020bb3a8f376..d3f2f978e79923 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h @@ -31,7 +31,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif /* defined(__cplusplus) */ /** * @struct @@ -79,7 +79,7 @@ ngtcp2_crypto_picotls_from_epoch(size_t epoch); * Picotls backend. */ NGTCP2_EXTERN size_t ngtcp2_crypto_picotls_from_ngtcp2_encryption_level( - ngtcp2_encryption_level encryption_level); + ngtcp2_encryption_level encryption_level); /** * @function @@ -160,7 +160,7 @@ ngtcp2_crypto_picotls_configure_client_context(ptls_context_t *ctx); * It returns 0 if it succeeds, or -1. */ NGTCP2_EXTERN int ngtcp2_crypto_picotls_configure_server_session( - ngtcp2_crypto_picotls_ctx *cptls); + ngtcp2_crypto_picotls_ctx *cptls); /** * @function @@ -224,8 +224,8 @@ ngtcp2_crypto_picotls_deconfigure_session(ngtcp2_crypto_picotls_ctx *cptls); * :macro:`NGTCP2_TLSEXT_QUIC_TRANSPORT_PARAMETERS_V1`. */ NGTCP2_EXTERN int ngtcp2_crypto_picotls_collect_extension( - ptls_t *ptls, struct st_ptls_handshake_properties_t *properties, - uint16_t type); + ptls_t *ptls, struct st_ptls_handshake_properties_t *properties, + uint16_t type); /** * @function @@ -236,11 +236,11 @@ NGTCP2_EXTERN int ngtcp2_crypto_picotls_collect_extension( * extensions are ignored. */ NGTCP2_EXTERN int ngtcp2_crypto_picotls_collected_extensions( - ptls_t *ptls, struct st_ptls_handshake_properties_t *properties, - ptls_raw_extension_t *extensions); + ptls_t *ptls, struct st_ptls_handshake_properties_t *properties, + ptls_raw_extension_t *extensions); #ifdef __cplusplus } -#endif +#endif /* defined(__cplusplus) */ -#endif /* NGTCP2_CRYPTO_PICOTLS_H */ +#endif /* !defined(NGTCP2_CRYPTO_PICOTLS_H) */ diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h index b25c13b81c8b18..22e3eda0c4160a 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_quictls.h @@ -31,7 +31,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif /* defined(__cplusplus) */ /** * @macrosection @@ -70,7 +70,7 @@ extern "C" { */ NGTCP2_EXTERN ngtcp2_encryption_level ngtcp2_crypto_quictls_from_ossl_encryption_level( - OSSL_ENCRYPTION_LEVEL ossl_level); + OSSL_ENCRYPTION_LEVEL ossl_level); /** * @function @@ -81,7 +81,7 @@ ngtcp2_crypto_quictls_from_ossl_encryption_level( */ NGTCP2_EXTERN OSSL_ENCRYPTION_LEVEL ngtcp2_crypto_quictls_from_ngtcp2_encryption_level( - ngtcp2_encryption_level encryption_level); + ngtcp2_encryption_level encryption_level); /** * @function @@ -142,6 +142,6 @@ NGTCP2_EXTERN int ngtcp2_crypto_quictls_init(void); #ifdef __cplusplus } -#endif +#endif /* defined(__cplusplus) */ -#endif /* NGTCP2_CRYPTO_QUICTLS_H */ +#endif /* !defined(NGTCP2_CRYPTO_QUICTLS_H) */ diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h index e1d621adce94d8..e95056de5926a9 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h @@ -33,7 +33,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif /* defined(__cplusplus) */ /** * @function @@ -44,7 +44,7 @@ extern "C" { */ NGTCP2_EXTERN ngtcp2_encryption_level ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level( - WOLFSSL_ENCRYPTION_LEVEL wolfssl_level); + WOLFSSL_ENCRYPTION_LEVEL wolfssl_level); /** * @function @@ -55,7 +55,7 @@ ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level( */ NGTCP2_EXTERN WOLFSSL_ENCRYPTION_LEVEL ngtcp2_crypto_wolfssl_from_ngtcp2_encryption_level( - ngtcp2_encryption_level encryption_level); + ngtcp2_encryption_level encryption_level); /** * @function @@ -101,6 +101,6 @@ ngtcp2_crypto_wolfssl_configure_client_context(WOLFSSL_CTX *ssl_ctx); #ifdef __cplusplus } -#endif +#endif /* defined(__cplusplus) */ -#endif /* NGTCP2_CRYPTO_WOLFSSL_H */ +#endif /* !defined(NGTCP2_CRYPTO_WOLFSSL_H) */ diff --git a/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c b/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c index 35bfb7b2f8fa19..c3f14f5d444bac 100644 --- a/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c +++ b/deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include @@ -79,7 +79,7 @@ crypto_cipher_suite_get_aead_max_encryption(ptls_cipher_suite_t *cs) { if (cs->aead == &ptls_openssl_chacha20poly1305) { return NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305; } -#endif /* PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 */ +#endif /* defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305) */ return 0; } @@ -95,7 +95,7 @@ crypto_cipher_suite_get_aead_max_decryption_failure(ptls_cipher_suite_t *cs) { if (cs->aead == &ptls_openssl_chacha20poly1305) { return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305; } -#endif /* PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 */ +#endif /* defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305) */ return 0; } @@ -114,7 +114,7 @@ crypto_cipher_suite_get_hp(ptls_cipher_suite_t *cs) { if (cs->aead == &ptls_openssl_chacha20poly1305) { return &ptls_openssl_chacha20; } -#endif /* PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 */ +#endif /* defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305) */ return NULL; } @@ -124,7 +124,7 @@ static int supported_cipher_suite(ptls_cipher_suite_t *cs) { cs->aead == &ptls_openssl_aes256gcm #ifdef PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 || cs->aead == &ptls_openssl_chacha20poly1305 -#endif /* PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 */ +#endif /* defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305) */ ; } diff --git a/deps/ngtcp2/ngtcp2/crypto/quictls/quictls.c b/deps/ngtcp2/ngtcp2/crypto/quictls/quictls.c index 330ca687b44666..592e5a86535356 100644 --- a/deps/ngtcp2/ngtcp2/crypto/quictls/quictls.c +++ b/deps/ngtcp2/ngtcp2/crypto/quictls/quictls.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -339,7 +339,7 @@ static ngtcp2_crypto_ctx *crypto_ctx_cipher_id(ngtcp2_crypto_ctx *ctx, ctx->hp.native_handle = (void *)crypto_cipher_id_get_hp(cipher_id); ctx->max_encryption = crypto_cipher_id_get_aead_max_encryption(cipher_id); ctx->max_decryption_failure = - crypto_cipher_id_get_aead_max_decryption_failure(cipher_id); + crypto_cipher_id_get_aead_max_decryption_failure(cipher_id); return ctx; } @@ -527,14 +527,14 @@ int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf); int mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; OSSL_PARAM params[] = { - OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode), - OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, - (char *)EVP_MD_get0_name(prf), 0), - OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)secret, - secretlen), - OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, (void *)salt, - saltlen), - OSSL_PARAM_construct_end(), + OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode), + OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, + (char *)EVP_MD_get0_name(prf), 0), + OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)secret, + secretlen), + OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, (void *)salt, + saltlen), + OSSL_PARAM_construct_end(), }; int rv = 0; @@ -584,14 +584,14 @@ int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf); int mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; OSSL_PARAM params[] = { - OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode), - OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, - (char *)EVP_MD_get0_name(prf), 0), - OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)secret, - secretlen), - OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, (void *)info, - infolen), - OSSL_PARAM_construct_end(), + OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode), + OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, + (char *)EVP_MD_get0_name(prf), 0), + OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)secret, + secretlen), + OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, (void *)info, + infolen), + OSSL_PARAM_construct_end(), }; int rv = 0; @@ -639,15 +639,15 @@ int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen, EVP_KDF *kdf = crypto_kdf_hkdf(); EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf); OSSL_PARAM params[] = { - OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, - (char *)EVP_MD_get0_name(prf), 0), - OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)secret, - secretlen), - OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, (void *)salt, - saltlen), - OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, (void *)info, - infolen), - OSSL_PARAM_construct_end(), + OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, + (char *)EVP_MD_get0_name(prf), 0), + OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)secret, + secretlen), + OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, (void *)salt, + saltlen), + OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, (void *)info, + infolen), + OSSL_PARAM_construct_end(), }; int rv = 0; @@ -672,7 +672,7 @@ int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen, if (EVP_PKEY_derive_init(pctx) != 1 || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) != - 1 || + 1 || EVP_PKEY_CTX_set_hkdf_md(pctx, prf) != 1 || EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, (int)saltlen) != 1 || EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, (int)secretlen) != 1 || @@ -699,9 +699,9 @@ int ngtcp2_crypto_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead, int len; #if OPENSSL_VERSION_NUMBER >= 0x30000000L OSSL_PARAM params[] = { - OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, - dest + plaintextlen, taglen), - OSSL_PARAM_construct_end(), + OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, + dest + plaintextlen, taglen), + OSSL_PARAM_construct_end(), }; #endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */ @@ -794,16 +794,16 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, } int ngtcp2_crypto_read_write_crypto_data( - ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, - const uint8_t *data, size_t datalen) { + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + const uint8_t *data, size_t datalen) { SSL *ssl = ngtcp2_conn_get_tls_native_handle(conn); int rv; int err; if (SSL_provide_quic_data( - ssl, - ngtcp2_crypto_quictls_from_ngtcp2_encryption_level(encryption_level), - data, datalen) != 1) { + ssl, + ngtcp2_crypto_quictls_from_ngtcp2_encryption_level(encryption_level), + data, datalen) != 1) { return -1; } @@ -874,7 +874,7 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf, } ngtcp2_encryption_level ngtcp2_crypto_quictls_from_ossl_encryption_level( - OSSL_ENCRYPTION_LEVEL ossl_level) { + OSSL_ENCRYPTION_LEVEL ossl_level) { switch (ossl_level) { case ssl_encryption_initial: return NGTCP2_ENCRYPTION_LEVEL_INITIAL; @@ -892,7 +892,7 @@ ngtcp2_encryption_level ngtcp2_crypto_quictls_from_ossl_encryption_level( OSSL_ENCRYPTION_LEVEL ngtcp2_crypto_quictls_from_ngtcp2_encryption_level( - ngtcp2_encryption_level encryption_level) { + ngtcp2_encryption_level encryption_level) { switch (encryption_level) { case NGTCP2_ENCRYPTION_LEVEL_INITIAL: return ssl_encryption_initial; @@ -934,7 +934,7 @@ static int set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); ngtcp2_encryption_level level = - ngtcp2_crypto_quictls_from_ossl_encryption_level(ossl_level); + ngtcp2_crypto_quictls_from_ossl_encryption_level(ossl_level); if (rx_secret && ngtcp2_crypto_derive_and_install_rx_key(conn, NULL, NULL, NULL, level, @@ -956,7 +956,7 @@ static int add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); ngtcp2_encryption_level level = - ngtcp2_crypto_quictls_from_ossl_encryption_level(ossl_level); + ngtcp2_crypto_quictls_from_ossl_encryption_level(ossl_level); int rv; rv = ngtcp2_conn_submit_crypto_data(conn, level, data, datalen); @@ -973,8 +973,7 @@ static int flush_flight(SSL *ssl) { return 1; } -static int send_alert(SSL *ssl, enum ssl_encryption_level_t level, - uint8_t alert) { +static int send_alert(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, uint8_t alert) { ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); (void)level; @@ -985,14 +984,14 @@ static int send_alert(SSL *ssl, enum ssl_encryption_level_t level, } static SSL_QUIC_METHOD quic_method = { - set_encryption_secrets, - add_handshake_data, - flush_flight, - send_alert, + set_encryption_secrets, + add_handshake_data, + flush_flight, + send_alert, #ifdef LIBRESSL_VERSION_NUMBER - NULL, - NULL, -#endif /* LIBRESSL_VERSION_NUMBER */ + NULL, + NULL, +#endif /* defined(LIBRESSL_VERSION_NUMBER) */ }; static void crypto_quictls_configure_context(SSL_CTX *ssl_ctx) { diff --git a/deps/ngtcp2/ngtcp2/crypto/shared.c b/deps/ngtcp2/ngtcp2/crypto/shared.c index 162094a375cb8b..98cd4de7e8097d 100644 --- a/deps/ngtcp2/ngtcp2/crypto/shared.c +++ b/deps/ngtcp2/ngtcp2/crypto/shared.c @@ -27,9 +27,9 @@ #ifdef WIN32 # include # include -#else +#elif defined(HAVE_NETINET_IN_H) # include -#endif +#endif /* defined(HAVE_NETINET_IN_H) */ #include #include @@ -110,13 +110,11 @@ int ngtcp2_crypto_derive_initial_secrets(uint8_t *rx_secret, uint8_t *tx_secret, } if (ngtcp2_crypto_hkdf_expand_label( - client_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, &ctx.md, - initial_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, CLABEL, - sizeof(CLABEL) - 1) != 0 || + client_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, &ctx.md, initial_secret, + NGTCP2_CRYPTO_INITIAL_SECRETLEN, CLABEL, sizeof(CLABEL) - 1) != 0 || ngtcp2_crypto_hkdf_expand_label( - server_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, &ctx.md, - initial_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, SLABEL, - sizeof(SLABEL) - 1) != 0) { + server_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, &ctx.md, initial_secret, + NGTCP2_CRYPTO_INITIAL_SECRETLEN, SLABEL, sizeof(SLABEL) - 1) != 0) { return -1; } @@ -125,13 +123,13 @@ int ngtcp2_crypto_derive_initial_secrets(uint8_t *rx_secret, uint8_t *tx_secret, size_t ngtcp2_crypto_packet_protection_ivlen(const ngtcp2_crypto_aead *aead) { size_t noncelen = ngtcp2_crypto_aead_noncelen(aead); - return ngtcp2_max(8, noncelen); + return ngtcp2_max_size(8, noncelen); } int ngtcp2_crypto_derive_packet_protection_key( - uint8_t *key, uint8_t *iv, uint8_t *hp_key, uint32_t version, - const ngtcp2_crypto_aead *aead, const ngtcp2_crypto_md *md, - const uint8_t *secret, size_t secretlen) { + uint8_t *key, uint8_t *iv, uint8_t *hp_key, uint32_t version, + const ngtcp2_crypto_aead *aead, const ngtcp2_crypto_md *md, + const uint8_t *secret, size_t secretlen) { static const uint8_t KEY_LABEL_V1[] = "quic key"; static const uint8_t IV_LABEL_V1[] = "quic iv"; static const uint8_t HP_KEY_LABEL_V1[] = "quic hp"; @@ -305,8 +303,8 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key, } break; case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: - rv = ngtcp2_conn_install_rx_handshake_key(conn, &aead_ctx, iv, ivlen, - &hp_ctx); + rv = + ngtcp2_conn_install_rx_handshake_key(conn, &aead_ctx, iv, ivlen, &hp_ctx); if (rv != 0) { goto fail; } @@ -455,8 +453,8 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, } break; case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: - rv = ngtcp2_conn_install_tx_handshake_key(conn, &aead_ctx, iv, ivlen, - &hp_ctx); + rv = + ngtcp2_conn_install_tx_handshake_key(conn, &aead_ctx, iv, ivlen, &hp_ctx); if (rv != 0) { goto fail; } @@ -489,10 +487,10 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, } int ngtcp2_crypto_derive_and_install_initial_key( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, - uint8_t *rx_hp_key, uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp_key, - uint32_t version, const ngtcp2_cid *client_dcid) { + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, uint8_t *rx_hp_key, + uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp_key, uint32_t version, + const ngtcp2_cid *client_dcid) { uint8_t rx_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; uint8_t tx_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; uint8_t initial_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; @@ -548,21 +546,20 @@ int ngtcp2_crypto_derive_and_install_initial_key( ngtcp2_conn_set_initial_crypto_ctx(conn, &ctx); if (ngtcp2_crypto_derive_initial_secrets( - rx_secret, tx_secret, initial_secret, version, client_dcid, - server ? NGTCP2_CRYPTO_SIDE_SERVER : NGTCP2_CRYPTO_SIDE_CLIENT) != - 0) { + rx_secret, tx_secret, initial_secret, version, client_dcid, + server ? NGTCP2_CRYPTO_SIDE_SERVER : NGTCP2_CRYPTO_SIDE_CLIENT) != 0) { return -1; } if (ngtcp2_crypto_derive_packet_protection_key( - rx_key, rx_iv, rx_hp_key, version, &ctx.aead, &ctx.md, rx_secret, - NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { + rx_key, rx_iv, rx_hp_key, version, &ctx.aead, &ctx.md, rx_secret, + NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { return -1; } if (ngtcp2_crypto_derive_packet_protection_key( - tx_key, tx_iv, tx_hp_key, version, &ctx.aead, &ctx.md, tx_secret, - NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { + tx_key, tx_iv, tx_hp_key, version, &ctx.aead, &ctx.md, tx_secret, + NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { return -1; } @@ -631,10 +628,10 @@ int ngtcp2_crypto_derive_and_install_initial_key( } int ngtcp2_crypto_derive_and_install_vneg_initial_key( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, - uint8_t *rx_hp_key, uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp_key, - uint32_t version, const ngtcp2_cid *client_dcid) { + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, uint8_t *rx_hp_key, + uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp_key, uint32_t version, + const ngtcp2_cid *client_dcid) { uint8_t rx_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; uint8_t tx_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; uint8_t initial_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; @@ -682,21 +679,20 @@ int ngtcp2_crypto_derive_and_install_vneg_initial_key( } if (ngtcp2_crypto_derive_initial_secrets( - rx_secret, tx_secret, initial_secret, version, client_dcid, - server ? NGTCP2_CRYPTO_SIDE_SERVER : NGTCP2_CRYPTO_SIDE_CLIENT) != - 0) { + rx_secret, tx_secret, initial_secret, version, client_dcid, + server ? NGTCP2_CRYPTO_SIDE_SERVER : NGTCP2_CRYPTO_SIDE_CLIENT) != 0) { return -1; } if (ngtcp2_crypto_derive_packet_protection_key( - rx_key, rx_iv, rx_hp_key, version, &ctx->aead, &ctx->md, rx_secret, - NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { + rx_key, rx_iv, rx_hp_key, version, &ctx->aead, &ctx->md, rx_secret, + NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { return -1; } if (ngtcp2_crypto_derive_packet_protection_key( - tx_key, tx_iv, tx_hp_key, version, &ctx->aead, &ctx->md, tx_secret, - NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { + tx_key, tx_iv, tx_hp_key, version, &ctx->aead, &ctx->md, tx_secret, + NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { return -1; } @@ -721,8 +717,8 @@ int ngtcp2_crypto_derive_and_install_vneg_initial_key( } rv = ngtcp2_conn_install_vneg_initial_key( - conn, version, &rx_aead_ctx, rx_iv, &rx_hp_ctx, &tx_aead_ctx, tx_iv, - &tx_hp_ctx, NGTCP2_CRYPTO_INITIAL_IVLEN); + conn, version, &rx_aead_ctx, rx_iv, &rx_hp_ctx, &tx_aead_ctx, tx_iv, + &tx_hp_ctx, NGTCP2_CRYPTO_INITIAL_IVLEN); if (rv != 0) { goto fail; } @@ -739,11 +735,11 @@ int ngtcp2_crypto_derive_and_install_vneg_initial_key( } int ngtcp2_crypto_update_key( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv, - ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv, - const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, - size_t secretlen) { + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv, + ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv, + const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, + size_t secretlen) { const ngtcp2_crypto_ctx *ctx = ngtcp2_conn_get_crypto_ctx(conn); const ngtcp2_crypto_aead *aead = &ctx->aead; const ngtcp2_crypto_md *md = &ctx->md; @@ -756,7 +752,7 @@ int ngtcp2_crypto_update_key( } if (ngtcp2_crypto_derive_packet_protection_key( - rx_key, rx_iv, NULL, version, aead, md, rx_secret, secretlen) != 0) { + rx_key, rx_iv, NULL, version, aead, md, rx_secret, secretlen) != 0) { return -1; } @@ -766,7 +762,7 @@ int ngtcp2_crypto_update_key( } if (ngtcp2_crypto_derive_packet_protection_key( - tx_key, tx_iv, NULL, version, aead, md, tx_secret, secretlen) != 0) { + tx_key, tx_iv, NULL, version, aead, md, tx_secret, secretlen) != 0) { return -1; } @@ -819,20 +815,19 @@ int ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp, } int ngtcp2_crypto_update_key_cb( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, - ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv, - const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, - size_t secretlen, void *user_data) { + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, + ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv, + const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, + size_t secretlen, void *user_data) { uint8_t rx_key[64]; uint8_t tx_key[64]; (void)conn; (void)user_data; - if (ngtcp2_crypto_update_key(conn, rx_secret, tx_secret, rx_aead_ctx, rx_key, - rx_iv, tx_aead_ctx, tx_key, tx_iv, - current_rx_secret, current_tx_secret, - secretlen) != 0) { + if (ngtcp2_crypto_update_key( + conn, rx_secret, tx_secret, rx_aead_ctx, rx_key, rx_iv, tx_aead_ctx, + tx_key, tx_iv, current_rx_secret, current_tx_secret, secretlen) != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } return 0; @@ -920,13 +915,14 @@ static size_t crypto_generate_retry_token_aad(uint8_t *dest, uint32_t version, static const uint8_t retry_token_info_prefix[] = "retry_token"; ngtcp2_ssize ngtcp2_crypto_generate_retry_token( - uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version, - const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, - const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts) { - uint8_t plaintext[NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN]; + uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts) { + uint8_t + plaintext[/* cid len = */ 1 + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)]; uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN]; - uint8_t key[32]; - uint8_t iv[32]; + uint8_t key[16]; + uint8_t iv[12]; size_t keylen; size_t ivlen; ngtcp2_crypto_aead aead; @@ -934,7 +930,7 @@ ngtcp2_ssize ngtcp2_crypto_generate_retry_token( ngtcp2_crypto_aead_ctx aead_ctx; size_t plaintextlen; uint8_t - aad[sizeof(version) + sizeof(ngtcp2_sockaddr_union) + NGTCP2_MAX_CIDLEN]; + aad[sizeof(version) + sizeof(ngtcp2_sockaddr_union) + NGTCP2_MAX_CIDLEN]; size_t aadlen; uint8_t *p = plaintext; ngtcp2_tstamp ts_be = ngtcp2_htonl64(ts); @@ -962,8 +958,8 @@ ngtcp2_ssize ngtcp2_crypto_generate_retry_token( keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); - assert(sizeof(key) >= keylen); - assert(sizeof(iv) >= ivlen); + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, rand_data, sizeof(rand_data), @@ -999,21 +995,21 @@ ngtcp2_ssize ngtcp2_crypto_generate_retry_token( } int ngtcp2_crypto_verify_retry_token( - ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen, - const uint8_t *secret, size_t secretlen, uint32_t version, - const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, - const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts) { + ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts) { uint8_t - plaintext[/* cid len = */ 1 + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)]; - uint8_t key[32]; - uint8_t iv[32]; + plaintext[/* cid len = */ 1 + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)]; + uint8_t key[16]; + uint8_t iv[12]; size_t keylen; size_t ivlen; ngtcp2_crypto_aead_ctx aead_ctx; ngtcp2_crypto_aead aead; ngtcp2_crypto_md md; uint8_t - aad[sizeof(version) + sizeof(ngtcp2_sockaddr_union) + NGTCP2_MAX_CIDLEN]; + aad[sizeof(version) + sizeof(ngtcp2_sockaddr_union) + NGTCP2_MAX_CIDLEN]; size_t aadlen; const uint8_t *rand_data; const uint8_t *ciphertext; @@ -1039,6 +1035,9 @@ int ngtcp2_crypto_verify_retry_token( keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); + if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN, retry_token_info_prefix, @@ -1081,6 +1080,206 @@ int ngtcp2_crypto_verify_retry_token( return 0; } +static size_t crypto_generate_retry_token_aad2(uint8_t *dest, uint32_t version, + const ngtcp2_cid *retry_scid) { + uint8_t *p = dest; + + version = ngtcp2_htonl(version); + memcpy(p, &version, sizeof(version)); + p += sizeof(version); + memcpy(p, retry_scid->data, retry_scid->datalen); + p += retry_scid->datalen; + + return (size_t)(p - dest); +} + +static const uint8_t retry_token_info_prefix2[] = "retry_token2"; + +ngtcp2_ssize ngtcp2_crypto_generate_retry_token2( + uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts) { + uint8_t plaintext[sizeof(ngtcp2_sockaddr_union) + /* cid len = */ 1 + + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)]; + uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN]; + uint8_t key[16]; + uint8_t iv[12]; + size_t keylen; + size_t ivlen; + ngtcp2_crypto_aead aead; + ngtcp2_crypto_md md; + ngtcp2_crypto_aead_ctx aead_ctx; + uint8_t aad[sizeof(version) + NGTCP2_MAX_CIDLEN]; + size_t aadlen; + uint8_t *p = plaintext; + ngtcp2_tstamp ts_be = ngtcp2_htonl64(ts); + int rv; + + assert((size_t)remote_addrlen <= sizeof(ngtcp2_sockaddr_union)); + + memset(plaintext, 0, sizeof(plaintext)); + + memcpy(p, remote_addr, (size_t)remote_addrlen); + p += sizeof(ngtcp2_sockaddr_union); + *p++ = (uint8_t)odcid->datalen; + memcpy(p, odcid->data, odcid->datalen); + p += NGTCP2_MAX_CIDLEN; + memcpy(p, &ts_be, sizeof(ts_be)); + + assert((size_t)(p + sizeof(ts_be) - plaintext) == sizeof(plaintext)); + + if (ngtcp2_crypto_random(rand_data, sizeof(rand_data)) != 0) { + return -1; + } + + ngtcp2_crypto_aead_aes_128_gcm(&aead); + ngtcp2_crypto_md_sha256(&md); + + keylen = ngtcp2_crypto_aead_keylen(&aead); + ivlen = ngtcp2_crypto_aead_noncelen(&aead); + + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); + + if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, + rand_data, sizeof(rand_data), + retry_token_info_prefix2, + sizeof(retry_token_info_prefix2) - 1) != 0) { + return -1; + } + + aadlen = crypto_generate_retry_token_aad2(aad, version, retry_scid); + + p = token; + *p++ = NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2; + + if (ngtcp2_crypto_aead_ctx_encrypt_init(&aead_ctx, &aead, key, ivlen) != 0) { + return -1; + } + + rv = ngtcp2_crypto_encrypt(p, &aead, &aead_ctx, plaintext, sizeof(plaintext), + iv, ivlen, aad, aadlen); + + ngtcp2_crypto_aead_ctx_free(&aead_ctx); + + if (rv != 0) { + return -1; + } + + p += sizeof(plaintext) + aead.max_overhead; + memcpy(p, rand_data, sizeof(rand_data)); + p += sizeof(rand_data); + + return p - token; +} + +int ngtcp2_crypto_verify_retry_token2( + ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, uint32_t version, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts) { + uint8_t plaintext[sizeof(ngtcp2_sockaddr_union) + /* cid len = */ 1 + + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)]; + uint8_t key[16]; + uint8_t iv[12]; + size_t keylen; + size_t ivlen; + ngtcp2_crypto_aead_ctx aead_ctx; + ngtcp2_crypto_aead aead; + ngtcp2_crypto_md md; + uint8_t aad[sizeof(version) + NGTCP2_MAX_CIDLEN]; + size_t aadlen; + const uint8_t *rand_data; + const uint8_t *ciphertext; + size_t ciphertextlen; + size_t cil; + int rv; + ngtcp2_tstamp gen_ts; + ngtcp2_sockaddr_union addr; + size_t addrlen; + uint8_t *p; + + assert((size_t)remote_addrlen <= sizeof(ngtcp2_sockaddr_union)); + + if (tokenlen != NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN2 || + token[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2) { + return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN; + } + + rand_data = token + tokenlen - NGTCP2_CRYPTO_TOKEN_RAND_DATALEN; + ciphertext = token + 1; + ciphertextlen = (size_t)(rand_data - ciphertext); + + ngtcp2_crypto_aead_aes_128_gcm(&aead); + ngtcp2_crypto_md_sha256(&md); + + keylen = ngtcp2_crypto_aead_keylen(&aead); + ivlen = ngtcp2_crypto_aead_noncelen(&aead); + + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); + + if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, + rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN, + retry_token_info_prefix2, + sizeof(retry_token_info_prefix2) - 1) != 0) { + return NGTCP2_CRYPTO_ERR_INTERNAL; + } + + aadlen = crypto_generate_retry_token_aad2(aad, version, dcid); + + if (ngtcp2_crypto_aead_ctx_decrypt_init(&aead_ctx, &aead, key, ivlen) != 0) { + return NGTCP2_CRYPTO_ERR_INTERNAL; + } + + rv = ngtcp2_crypto_decrypt(plaintext, &aead, &aead_ctx, ciphertext, + ciphertextlen, iv, ivlen, aad, aadlen); + + ngtcp2_crypto_aead_ctx_free(&aead_ctx); + + if (rv != 0) { + return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN; + } + + p = plaintext; + + memcpy(&addr, p, sizeof(addr)); + + switch (addr.sa.sa_family) { + case NGTCP2_AF_INET: + addrlen = sizeof(ngtcp2_sockaddr_in); + break; + case NGTCP2_AF_INET6: + addrlen = sizeof(ngtcp2_sockaddr_in6); + break; + default: + return NGTCP2_CRYPTO_ERR_VERIFY_TOKEN; + } + + if (addrlen != (size_t)remote_addrlen || + memcmp(&addr, remote_addr, addrlen) != 0) { + return NGTCP2_CRYPTO_ERR_VERIFY_TOKEN; + } + + p += sizeof(addr); + cil = *p++; + + if (cil != 0 && (cil < NGTCP2_MIN_CIDLEN || cil > NGTCP2_MAX_CIDLEN)) { + return NGTCP2_CRYPTO_ERR_VERIFY_TOKEN; + } + + memcpy(&gen_ts, p + NGTCP2_MAX_CIDLEN, sizeof(gen_ts)); + + gen_ts = ngtcp2_ntohl64(gen_ts); + if (gen_ts + timeout <= ts) { + return NGTCP2_CRYPTO_ERR_VERIFY_TOKEN; + } + + ngtcp2_cid_init(odcid, p, cil); + + return 0; +} + static size_t crypto_generate_regular_token_aad(uint8_t *dest, const ngtcp2_sockaddr *sa) { const uint8_t *addr; @@ -1093,7 +1292,7 @@ static size_t crypto_generate_regular_token_aad(uint8_t *dest, break; case NGTCP2_AF_INET6: addr = - (const uint8_t *)&((const ngtcp2_sockaddr_in6 *)(void *)sa)->sin6_addr; + (const uint8_t *)&((const ngtcp2_sockaddr_in6 *)(void *)sa)->sin6_addr; addrlen = sizeof(((const ngtcp2_sockaddr_in6 *)(void *)sa)->sin6_addr); break; default: @@ -1109,13 +1308,13 @@ static size_t crypto_generate_regular_token_aad(uint8_t *dest, static const uint8_t regular_token_info_prefix[] = "regular_token"; 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) { + 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)]; uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN]; - uint8_t key[32]; - uint8_t iv[32]; + uint8_t key[16]; + uint8_t iv[12]; size_t keylen; size_t ivlen; ngtcp2_crypto_aead aead; @@ -1144,8 +1343,8 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token( keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); - assert(sizeof(key) >= keylen); - assert(sizeof(iv) >= ivlen); + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, rand_data, sizeof(rand_data), @@ -1186,8 +1385,8 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, ngtcp2_duration timeout, ngtcp2_tstamp ts) { uint8_t plaintext[sizeof(ngtcp2_tstamp)]; - uint8_t key[32]; - uint8_t iv[32]; + uint8_t key[16]; + uint8_t iv[12]; size_t keylen; size_t ivlen; ngtcp2_crypto_aead_ctx aead_ctx; @@ -1217,6 +1416,9 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); + if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN, regular_token_info_prefix, @@ -1250,9 +1452,9 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, } 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, - size_t reasonlen) { + 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, + size_t reasonlen) { uint8_t rx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; uint8_t tx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; uint8_t initial_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; @@ -1273,8 +1475,8 @@ ngtcp2_ssize ngtcp2_crypto_write_connection_close( } if (ngtcp2_crypto_derive_packet_protection_key( - tx_key, tx_iv, tx_hp_key, version, &ctx.aead, &ctx.md, tx_secret, - NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { + tx_key, tx_iv, tx_hp_key, version, &ctx.aead, &ctx.md, tx_secret, + NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) { return -1; } @@ -1290,9 +1492,9 @@ ngtcp2_ssize ngtcp2_crypto_write_connection_close( } spktlen = ngtcp2_pkt_write_connection_close( - dest, destlen, version, dcid, scid, error_code, reason, reasonlen, - ngtcp2_crypto_encrypt_cb, &ctx.aead, &aead_ctx, tx_iv, - ngtcp2_crypto_hp_mask_cb, &ctx.hp, &hp_ctx); + dest, destlen, version, dcid, scid, error_code, reason, reasonlen, + ngtcp2_crypto_encrypt_cb, &ctx.aead, &aead_ctx, tx_iv, + ngtcp2_crypto_hp_mask_cb, &ctx.hp, &hp_ctx); if (spktlen < 0) { spktlen = -1; } @@ -1352,8 +1554,8 @@ int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn, void *user_data) { (void)user_data; if (ngtcp2_crypto_derive_and_install_initial_key( - conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - ngtcp2_conn_get_client_chosen_version(conn), dcid) != 0) { + conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + ngtcp2_conn_get_client_chosen_version(conn), dcid) != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -1362,7 +1564,7 @@ int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn, void *user_data) { } if (ngtcp2_crypto_read_write_crypto_data( - conn, NGTCP2_ENCRYPTION_LEVEL_INITIAL, NULL, 0) != 0) { + conn, NGTCP2_ENCRYPTION_LEVEL_INITIAL, NULL, 0) != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -1374,8 +1576,8 @@ int ngtcp2_crypto_recv_retry_cb(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, (void)user_data; if (ngtcp2_crypto_derive_and_install_initial_key( - conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - ngtcp2_conn_get_client_chosen_version(conn), &hd->scid) != 0) { + conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + ngtcp2_conn_get_client_chosen_version(conn), &hd->scid) != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -1388,8 +1590,8 @@ int ngtcp2_crypto_recv_client_initial_cb(ngtcp2_conn *conn, (void)user_data; if (ngtcp2_crypto_derive_and_install_initial_key( - conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - ngtcp2_conn_get_client_chosen_version(conn), dcid) != 0) { + conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + ngtcp2_conn_get_client_chosen_version(conn), dcid) != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -1402,8 +1604,8 @@ int ngtcp2_crypto_version_negotiation_cb(ngtcp2_conn *conn, uint32_t version, (void)user_data; if (ngtcp2_crypto_derive_and_install_vneg_initial_key( - conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, version, - client_dcid) != 0) { + conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, version, + client_dcid) != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -1420,7 +1622,7 @@ void ngtcp2_crypto_delete_crypto_aead_ctx_cb(ngtcp2_conn *conn, } void ngtcp2_crypto_delete_crypto_cipher_ctx_cb( - ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data) { + ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data) { (void)conn; (void)user_data; diff --git a/deps/ngtcp2/ngtcp2/crypto/shared.h b/deps/ngtcp2/ngtcp2/crypto/shared.h index d69fd21212d7d2..34158d3d02dbc0 100644 --- a/deps/ngtcp2/ngtcp2/crypto/shared.h +++ b/deps/ngtcp2/ngtcp2/crypto/shared.h @@ -22,12 +22,12 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef NGTCP2_SHARED_H -#define NGTCP2_SHARED_H +#ifndef SHARED_H +#define SHARED_H #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -286,10 +286,10 @@ int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls); * This function returns 0 if it succeeds, or -1. */ int ngtcp2_crypto_derive_and_install_initial_key( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, uint8_t *rx_hp, - uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp, uint32_t version, - const ngtcp2_cid *client_dcid); + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, uint8_t *rx_hp, + uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp, uint32_t version, + const ngtcp2_cid *client_dcid); /** * @function @@ -337,10 +337,10 @@ int ngtcp2_crypto_derive_and_install_initial_key( * This function returns 0 if it succeeds, or -1. */ int ngtcp2_crypto_derive_and_install_vneg_initial_key( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, uint8_t *rx_hp, - uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp, uint32_t version, - const ngtcp2_cid *client_dcid); + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, uint8_t *rx_hp, + uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp, uint32_t version, + const ngtcp2_cid *client_dcid); /** * @function @@ -394,4 +394,4 @@ int ngtcp2_crypto_hkdf_expand_label(uint8_t *dest, size_t destlen, const uint8_t *secret, size_t secretlen, const uint8_t *label, size_t labellen); -#endif /* NGTCP2_SHARED_H */ +#endif /* !defined(SHARED_H) */ diff --git a/deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c b/deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c index 2b7b5321863915..bc9d9d84a862c5 100644 --- a/deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c +++ b/deps/ngtcp2/ngtcp2/crypto/wolfssl/wolfssl.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -39,9 +39,9 @@ #define PRINTF_DEBUG 0 #if PRINTF_DEBUG # define DEBUG_MSG(...) fprintf(stderr, __VA_ARGS__) -#else +#else /* !PRINTF_DEBUG */ # define DEBUG_MSG(...) (void)0 -#endif +#endif /* !PRINTF_DEBUG */ ngtcp2_crypto_aead *ngtcp2_crypto_aead_aes_128_gcm(ngtcp2_crypto_aead *aead) { return ngtcp2_crypto_aead_init(aead, (void *)wolfSSL_EVP_aes_128_gcm()); @@ -65,7 +65,7 @@ ngtcp2_crypto_aead *ngtcp2_crypto_aead_init(ngtcp2_crypto_aead *aead, void *aead_native_handle) { aead->native_handle = aead_native_handle; aead->max_overhead = wolfSSL_quic_get_aead_tag_len( - (const WOLFSSL_EVP_CIPHER *)(aead_native_handle)); + (const WOLFSSL_EVP_CIPHER *)(aead_native_handle)); return aead; } @@ -124,7 +124,7 @@ ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, ctx->hp.native_handle = (void *)wolfSSL_quic_get_hp(ssl); ctx->max_encryption = crypto_aead_get_aead_max_encryption(aead); ctx->max_decryption_failure = - crypto_aead_get_aead_max_decryption_failure(aead); + crypto_aead_get_aead_max_decryption_failure(aead); return ctx; } @@ -203,7 +203,7 @@ int ngtcp2_crypto_cipher_ctx_encrypt_init(ngtcp2_crypto_cipher_ctx *cipher_ctx, WOLFSSL_EVP_CIPHER_CTX *actx; actx = - wolfSSL_quic_crypt_new(cipher->native_handle, key, NULL, /* encrypt */ 1); + wolfSSL_quic_crypt_new(cipher->native_handle, key, NULL, /* encrypt */ 1); if (actx == NULL) { return -1; } @@ -279,7 +279,6 @@ int ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead, if (wolfSSL_quic_aead_decrypt(dest, aead_ctx->native_handle, ciphertext, ciphertextlen, nonce, aad, aadlen) != WOLFSSL_SUCCESS) { - DEBUG_MSG("WOLFSSL: decrypt FAILED\n"); return -1; } @@ -296,11 +295,11 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, (void)hp; if (wolfSSL_EVP_EncryptInit_ex(actx, NULL, NULL, NULL, sample) != - WOLFSSL_SUCCESS || + WOLFSSL_SUCCESS || wolfSSL_EVP_CipherUpdate(actx, dest, &len, PLAINTEXT, sizeof(PLAINTEXT) - 1) != WOLFSSL_SUCCESS || wolfSSL_EVP_EncryptFinal_ex(actx, dest + sizeof(PLAINTEXT) - 1, &len) != - WOLFSSL_SUCCESS) { + WOLFSSL_SUCCESS) { DEBUG_MSG("WOLFSSL: hp_mask FAILED\n"); return -1; } @@ -309,11 +308,11 @@ int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, } int ngtcp2_crypto_read_write_crypto_data( - ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, - const uint8_t *data, size_t datalen) { + ngtcp2_conn *conn, ngtcp2_encryption_level encryption_level, + const uint8_t *data, size_t datalen) { WOLFSSL *ssl = ngtcp2_conn_get_tls_native_handle(conn); WOLFSSL_ENCRYPTION_LEVEL level = - ngtcp2_crypto_wolfssl_from_ngtcp2_encryption_level(encryption_level); + ngtcp2_crypto_wolfssl_from_ngtcp2_encryption_level(encryption_level); int rv; int err; @@ -397,7 +396,7 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf, } ngtcp2_encryption_level ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level( - WOLFSSL_ENCRYPTION_LEVEL wolfssl_level) { + WOLFSSL_ENCRYPTION_LEVEL wolfssl_level) { switch (wolfssl_level) { case wolfssl_encryption_initial: return NGTCP2_ENCRYPTION_LEVEL_INITIAL; @@ -415,7 +414,7 @@ ngtcp2_encryption_level ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level( WOLFSSL_ENCRYPTION_LEVEL ngtcp2_crypto_wolfssl_from_ngtcp2_encryption_level( - ngtcp2_encryption_level encryption_level) { + ngtcp2_encryption_level encryption_level) { switch (encryption_level) { case NGTCP2_ENCRYPTION_LEVEL_INITIAL: return wolfssl_encryption_initial; @@ -458,7 +457,7 @@ static int set_encryption_secrets(WOLFSSL *ssl, ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); ngtcp2_encryption_level level = - ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level(wolfssl_level); + ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level(wolfssl_level); DEBUG_MSG("WOLFSSL: set encryption secrets, level=%d, rxlen=%lu, txlen=%lu\n", wolfssl_level, rx_secret ? secretlen : 0, @@ -484,7 +483,7 @@ static int add_handshake_data(WOLFSSL *ssl, ngtcp2_crypto_conn_ref *conn_ref = SSL_get_app_data(ssl); ngtcp2_conn *conn = conn_ref->get_conn(conn_ref); ngtcp2_encryption_level level = - ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level(wolfssl_level); + ngtcp2_crypto_wolfssl_from_wolfssl_encryption_level(wolfssl_level); int rv; DEBUG_MSG("WOLFSSL: add handshake data, level=%d len=%lu\n", wolfssl_level, @@ -516,10 +515,10 @@ static int send_alert(WOLFSSL *ssl, enum wolfssl_encryption_level_t level, } static WOLFSSL_QUIC_METHOD quic_method = { - set_encryption_secrets, - add_handshake_data, - flush_flight, - send_alert, + set_encryption_secrets, + add_handshake_data, + flush_flight, + send_alert, }; static void crypto_wolfssl_configure_context(WOLFSSL_CTX *ssl_ctx) { @@ -532,7 +531,7 @@ int ngtcp2_crypto_wolfssl_configure_server_context(WOLFSSL_CTX *ssl_ctx) { crypto_wolfssl_configure_context(ssl_ctx); #if PRINTF_DEBUG wolfSSL_Debugging_ON(); -#endif +#endif /* PRINTF_DEBUG */ return 0; } @@ -541,6 +540,6 @@ int ngtcp2_crypto_wolfssl_configure_client_context(WOLFSSL_CTX *ssl_ctx) { wolfSSL_CTX_UseSessionTicket(ssl_ctx); #if PRINTF_DEBUG wolfSSL_Debugging_ON(); -#endif +#endif /* PRINTF_DEBUG */ return 0; } diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h index 72c8142a5a5aa7..acc79be6e0b375 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h @@ -30,12 +30,12 @@ libcurl) */ #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) # define WIN32 -#endif +#endif /* (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) */ #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable : 4324) -#endif +#endif /* defined(_MSC_VER) */ #include #if defined(_MSC_VER) && (_MSC_VER < 1800) @@ -43,9 +43,9 @@ compliant. See compiler macros and version number in https://sourceforge.net/p/predef/wiki/Compilers/ */ # include -#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ +#else /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */ # include -#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ +#endif /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */ #include #include #include @@ -54,13 +54,13 @@ # ifdef WIN32 # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN -# endif /* WIN32_LEAN_AND_MEAN */ +# endif /* !defined(WIN32_LEAN_AND_MEAN) */ # include -# else /* !WIN32 */ +# else /* !defined(WIN32) */ # include # include -# endif /* !WIN32 */ -#endif /* NGTCP2_USE_GENERIC_SOCKADDR */ +# endif /* !defined(WIN32) */ +#endif /* !defined(NGTCP2_USE_GENERIC_SOCKADDR) */ #include @@ -69,26 +69,26 @@ #elif defined(WIN32) # ifdef BUILDING_NGTCP2 # define NGTCP2_EXTERN __declspec(dllexport) -# else /* !BUILDING_NGTCP2 */ +# else /* !defined(BUILDING_NGTCP2) */ # define NGTCP2_EXTERN __declspec(dllimport) -# endif /* !BUILDING_NGTCP2 */ -#else /* !defined(WIN32) */ +# endif /* !defined(BUILDING_NGTCP2) */ +#else /* !(defined(NGTCP2_STATICLIB) || defined(WIN32)) */ # ifdef BUILDING_NGTCP2 # define NGTCP2_EXTERN __attribute__((visibility("default"))) -# else /* !BUILDING_NGTCP2 */ +# else /* !defined(BUILDING_NGTCP2) */ # define NGTCP2_EXTERN -# endif /* !BUILDING_NGTCP2 */ -#endif /* !defined(WIN32) */ +# endif /* !defined(BUILDING_NGTCP2) */ +#endif /* !(defined(NGTCP2_STATICLIB) || defined(WIN32)) */ #ifdef _MSC_VER # define NGTCP2_ALIGN(N) __declspec(align(N)) -#else /* !_MSC_VER */ +#else /* !defined(_MSC_VER) */ # define NGTCP2_ALIGN(N) __attribute__((aligned(N))) -#endif /* !_MSC_VER */ +#endif /* !defined(_MSC_VER) */ #ifdef __cplusplus extern "C" { -#endif +#endif /* defined(__cplusplus) */ /** * @typedef @@ -1229,11 +1229,11 @@ typedef struct ngtcp2_pkt_stateless_reset { #ifdef NGTCP2_USE_GENERIC_SOCKADDR # ifndef NGTCP2_AF_INET # error NGTCP2_AF_INET must be defined -# endif /* !NGTCP2_AF_INET */ +# endif /* !defined(NGTCP2_AF_INET) */ # ifndef NGTCP2_AF_INET6 # error NGTCP2_AF_INET6 must be defined -# endif /* !NGTCP2_AF_INET6 */ +# endif /* !defined(NGTCP2_AF_INET6) */ typedef unsigned short int ngtcp2_sa_family; typedef uint16_t ngtcp2_in_port; @@ -1267,7 +1267,7 @@ typedef struct ngtcp2_sockaddr_in6 { } ngtcp2_sockaddr_in6; typedef uint32_t ngtcp2_socklen; -#else /* !NGTCP2_USE_GENERIC_SOCKADDR */ +#else /* !defined(NGTCP2_USE_GENERIC_SOCKADDR) */ # define NGTCP2_AF_INET AF_INET # define NGTCP2_AF_INET6 AF_INET6 @@ -1303,7 +1303,7 @@ typedef struct sockaddr_in6 ngtcp2_sockaddr_in6; * uint32_t. */ typedef socklen_t ngtcp2_socklen; -#endif /* !NGTCP2_USE_GENERIC_SOCKADDR */ +#endif /* !defined(NGTCP2_USE_GENERIC_SOCKADDR) */ /** * @struct @@ -1689,7 +1689,8 @@ typedef enum ngtcp2_token_type { } ngtcp2_token_type; #define NGTCP2_SETTINGS_V1 1 -#define NGTCP2_SETTINGS_VERSION NGTCP2_SETTINGS_V1 +#define NGTCP2_SETTINGS_V2 2 +#define NGTCP2_SETTINGS_VERSION NGTCP2_SETTINGS_V2 /** * @struct @@ -1723,8 +1724,7 @@ typedef struct ngtcp2_settings { ngtcp2_printf log_printf; /** * :member:`max_tx_udp_payload_size` is the maximum size of UDP - * datagram payload that the local endpoint transmits. It is used - * by congestion controller to compute congestion window. + * datagram payload that the local endpoint transmits. */ size_t max_tx_udp_payload_size; /** @@ -1777,6 +1777,13 @@ typedef struct ngtcp2_settings { * or :member:`ngtcp2_transport_params.initial_max_stream_data_uni`, * depending on the type of stream. The window size is scaled up to * the value specified in this field. + * + * Please note that the auto-tuning is done per stream. Even if the + * previous stream gets larger window as a result of auto-tuning, + * the new stream still starts with the initial value set in + * transport parameters. This might become a bottleneck if + * congestion window of a remote server is wide open. If this + * causes an issue, do not enable auto-tuning. */ uint64_t max_stream_window; /** @@ -1873,10 +1880,29 @@ typedef struct ngtcp2_settings { */ uint8_t no_pmtud; /** - * :member:`pkt_num` is the initial packet number for each packet - * number space. It must be in range [0, INT32_MAX], inclusive. + * :member:`initial_pkt_num` is the initial packet number for each + * packet number space. It must be in range [0, INT32_MAX], + * inclusive. */ uint32_t initial_pkt_num; + /* The following fields have been added since NGTCP2_SETTINGS_V2. */ + /** + * :member:`pmtud_probes` is the array of UDP datagram payload size + * to probe during Path MTU Discovery. The discovery is done in the + * order appeared in this array. The size must be strictly larger + * than 1200, otherwise the behavior is undefined. The maximum + * value in this array should be set to + * :member:`max_tx_udp_payload_size`. If this field is not set, the + * predefined PMTUD probes are made. This field has been available + * since v1.4.0. + */ + const uint16_t *pmtud_probes; + /** + * :member:`pmtud_probeslen` is the number of elements that are + * contained in the array pointed by :member:`pmtud_probes`. This + * field has been available since v1.4.0. + */ + size_t pmtud_probeslen; } ngtcp2_settings; /** @@ -2080,8 +2106,8 @@ typedef struct ngtcp2_crypto_ctx { * Buffer is too small. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_transport_params_encode_versioned( - uint8_t *dest, size_t destlen, int transport_params_version, - const ngtcp2_transport_params *params); + uint8_t *dest, size_t destlen, int transport_params_version, + const ngtcp2_transport_params *params); /** * @function @@ -2324,8 +2350,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd *dest, * :macro:`NGTCP2_MIN_STATELESS_RESET_RANDLEN`. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_stateless_reset( - uint8_t *dest, size_t destlen, const uint8_t *stateless_reset_token, - const uint8_t *rand, size_t randlen); + uint8_t *dest, size_t destlen, const uint8_t *stateless_reset_token, + const uint8_t *rand, size_t randlen); /** * @function @@ -2347,9 +2373,9 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_stateless_reset( * Buffer is too small. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_version_negotiation( - uint8_t *dest, size_t destlen, uint8_t unused_random, const uint8_t *dcid, - size_t dcidlen, const uint8_t *scid, size_t scidlen, const uint32_t *sv, - size_t nsv); + uint8_t *dest, size_t destlen, uint8_t unused_random, const uint8_t *dcid, + size_t dcidlen, const uint8_t *scid, size_t scidlen, const uint32_t *sv, + size_t nsv); /** * @struct @@ -2770,8 +2796,8 @@ typedef int (*ngtcp2_stream_reset)(ngtcp2_conn *conn, int64_t stream_id, * call return immediately. */ typedef int (*ngtcp2_acked_stream_data_offset)( - ngtcp2_conn *conn, int64_t stream_id, uint64_t offset, uint64_t datalen, - void *user_data, void *stream_user_data); + ngtcp2_conn *conn, int64_t stream_id, uint64_t offset, uint64_t datalen, + void *user_data, void *stream_user_data); /** * @functypedef @@ -2893,11 +2919,11 @@ typedef int (*ngtcp2_remove_connection_id)(ngtcp2_conn *conn, * immediately. */ typedef int (*ngtcp2_update_key)( - ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, - ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, - ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv, - const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, - size_t secretlen, void *user_data); + ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, + ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, + ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv, + const uint8_t *current_rx_secret, const uint8_t *current_tx_secret, + size_t secretlen, void *user_data); /** * @macrosection @@ -3024,8 +3050,8 @@ typedef enum ngtcp2_connection_id_status_type { * immediately. */ typedef int (*ngtcp2_connection_id_status)( - ngtcp2_conn *conn, ngtcp2_connection_id_status_type type, uint64_t seq, - const ngtcp2_cid *cid, const uint8_t *token, void *user_data); + ngtcp2_conn *conn, ngtcp2_connection_id_status_type type, uint64_t seq, + const ngtcp2_cid *cid, const uint8_t *token, void *user_data); /** * @functypedef @@ -3064,7 +3090,7 @@ typedef void (*ngtcp2_delete_crypto_aead_ctx)(ngtcp2_conn *conn, * `. */ typedef void (*ngtcp2_delete_crypto_cipher_ctx)( - ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data); + ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data); /** * @macrosection @@ -3510,12 +3536,12 @@ typedef struct ngtcp2_callbacks { * Callback function failed. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_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, - size_t reasonlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead, - const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, - ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp, - const ngtcp2_crypto_cipher_ctx *hp_ctx); + 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, + size_t reasonlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, + ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp, + const ngtcp2_crypto_cipher_ctx *hp_ctx); /** * @function @@ -3542,10 +3568,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_connection_close( * :macro:`NGTCP2_MIN_INITIAL_DCIDLEN`. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_retry( - uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, - const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token, - size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead, - const ngtcp2_crypto_aead_ctx *aead_ctx); + uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token, + size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx); /** * @function @@ -3594,12 +3620,12 @@ NGTCP2_EXTERN int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt, * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_client_new_versioned( - ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, - const ngtcp2_path *path, uint32_t client_chosen_version, - int callbacks_version, const ngtcp2_callbacks *callbacks, - int settings_version, const ngtcp2_settings *settings, - int transport_params_version, const ngtcp2_transport_params *params, - const ngtcp2_mem *mem, void *user_data); + ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, + const ngtcp2_path *path, uint32_t client_chosen_version, + int callbacks_version, const ngtcp2_callbacks *callbacks, + int settings_version, const ngtcp2_settings *settings, + int transport_params_version, const ngtcp2_transport_params *params, + const ngtcp2_mem *mem, void *user_data); /** * @function @@ -3629,12 +3655,12 @@ NGTCP2_EXTERN int ngtcp2_conn_client_new_versioned( * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_server_new_versioned( - ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, - const ngtcp2_path *path, uint32_t client_chosen_version, - int callbacks_version, const ngtcp2_callbacks *callbacks, - int settings_version, const ngtcp2_settings *settings, - int transport_params_version, const ngtcp2_transport_params *params, - const ngtcp2_mem *mem, void *user_data); + ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, + const ngtcp2_path *path, uint32_t client_chosen_version, + int callbacks_version, const ngtcp2_callbacks *callbacks, + int settings_version, const ngtcp2_settings *settings, + int transport_params_version, const ngtcp2_transport_params *params, + const ngtcp2_mem *mem, void *user_data); /** * @function @@ -3698,8 +3724,8 @@ ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, * and :macro:`NGTCP2_WRITE_STREAM_FLAG_NONE` as flags. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_pkt_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_tstamp ts); /** * @function @@ -3755,10 +3781,10 @@ NGTCP2_EXTERN int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn); * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_install_initial_key( - ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *rx_aead_ctx, - const uint8_t *rx_iv, const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, - const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, - const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen); + ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *rx_aead_ctx, + const uint8_t *rx_iv, const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, + const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, + const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen); /** * @function @@ -3790,11 +3816,11 @@ NGTCP2_EXTERN int ngtcp2_conn_install_initial_key( * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_install_vneg_initial_key( - ngtcp2_conn *conn, uint32_t version, - const ngtcp2_crypto_aead_ctx *rx_aead_ctx, const uint8_t *rx_iv, - const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, - const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, - const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen); + ngtcp2_conn *conn, uint32_t version, + const ngtcp2_crypto_aead_ctx *rx_aead_ctx, const uint8_t *rx_iv, + const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, + const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, + const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen); /** * @function @@ -3821,8 +3847,8 @@ NGTCP2_EXTERN int ngtcp2_conn_install_vneg_initial_key( * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_install_rx_handshake_key( - ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, - const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx); + ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, + size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx); /** * @function @@ -3849,8 +3875,8 @@ NGTCP2_EXTERN int ngtcp2_conn_install_rx_handshake_key( * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_install_tx_handshake_key( - ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, - const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx); + ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, + size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx); /** * @function @@ -3876,8 +3902,8 @@ NGTCP2_EXTERN int ngtcp2_conn_install_tx_handshake_key( * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_install_0rtt_key( - ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, - const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx); + ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, + size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx); /** * @function @@ -3906,9 +3932,9 @@ NGTCP2_EXTERN int ngtcp2_conn_install_0rtt_key( * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_install_rx_key( - ngtcp2_conn *conn, const uint8_t *secret, size_t secretlen, - const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen, - const ngtcp2_crypto_cipher_ctx *hp_ctx); + ngtcp2_conn *conn, const uint8_t *secret, size_t secretlen, + const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen, + const ngtcp2_crypto_cipher_ctx *hp_ctx); /** * @function @@ -3937,9 +3963,9 @@ NGTCP2_EXTERN int ngtcp2_conn_install_rx_key( * Out of memory. */ NGTCP2_EXTERN int ngtcp2_conn_install_tx_key( - ngtcp2_conn *conn, const uint8_t *secret, size_t secretlen, - const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen, - const ngtcp2_crypto_cipher_ctx *hp_ctx); + ngtcp2_conn *conn, const uint8_t *secret, size_t secretlen, + const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen, + const ngtcp2_crypto_cipher_ctx *hp_ctx); /** * @function @@ -4063,7 +4089,7 @@ NGTCP2_EXTERN ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn); * User callback failed */ NGTCP2_EXTERN int ngtcp2_conn_decode_and_set_remote_transport_params( - ngtcp2_conn *conn, const uint8_t *data, size_t datalen); + ngtcp2_conn *conn, const uint8_t *data, size_t datalen); /** * @function @@ -4148,7 +4174,7 @@ ngtcp2_ssize ngtcp2_conn_encode_0rtt_transport_params(ngtcp2_conn *conn, * The input is malformed. */ NGTCP2_EXTERN int ngtcp2_conn_decode_and_set_0rtt_transport_params( - ngtcp2_conn *conn, const uint8_t *data, size_t datalen); + ngtcp2_conn *conn, const uint8_t *data, size_t datalen); /** * @function @@ -4168,8 +4194,8 @@ NGTCP2_EXTERN int ngtcp2_conn_decode_and_set_0rtt_transport_params( * `ngtcp2_conn_install_tx_handshake_key` has been called. */ NGTCP2_EXTERN int ngtcp2_conn_set_local_transport_params_versioned( - ngtcp2_conn *conn, int transport_params_version, - const ngtcp2_transport_params *params); + ngtcp2_conn *conn, int transport_params_version, + const ngtcp2_transport_params *params); /** * @function @@ -4193,7 +4219,7 @@ ngtcp2_conn_get_local_transport_params(ngtcp2_conn *conn); * Buffer is too small. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_encode_local_transport_params( - ngtcp2_conn *conn, uint8_t *dest, size_t destlen); + ngtcp2_conn *conn, uint8_t *dest, size_t destlen); /** * @function @@ -4374,10 +4400,10 @@ NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, * conveniently accepts a single buffer. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen, - uint32_t flags, int64_t stream_id, const uint8_t *data, size_t datalen, - ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen, + uint32_t flags, int64_t stream_id, const uint8_t *data, size_t datalen, + ngtcp2_tstamp ts); /** * @function @@ -4388,7 +4414,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * handshake as well. * * |destlen| should be at least - * :member:`ngtcp2_settings.max_tx_udp_payload_size`. + * :member:`ngtcp2_settings.max_tx_udp_payload_size`. It must be at + * least :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`. * * Specifying -1 to |stream_id| means no new stream data to send. * @@ -4418,8 +4445,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * In that case, |*pdatalen| would be -1 if |pdatalen| is not * ``NULL``. * - * If |flags| & :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` is nonzero, and - * 0 length STREAM frame is successfully serialized, |*pdatalen| would + * Empty data is treated specially, and it is only accepted if no + * data, including the empty data, is submitted to a stream or + * :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` is set in |flags|. If 0 + * length STREAM frame is successfully serialized, |*pdatalen| would * be 0. * * The number of data encoded in STREAM frame is stored in |*pdatalen| @@ -4525,10 +4554,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * sending it makes QUIC connection enter the closing state. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen, - uint32_t flags, int64_t stream_id, const ngtcp2_vec *datav, size_t datavcnt, - ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen, + uint32_t flags, int64_t stream_id, const ngtcp2_vec *datav, size_t datavcnt, + ngtcp2_tstamp ts); /** * @macrosection @@ -4559,10 +4588,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( * conveniently accepts a single buffer. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_datagram_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, - uint32_t flags, uint64_t dgram_id, const uint8_t *data, size_t datalen, - ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, + uint32_t flags, uint64_t dgram_id, const uint8_t *data, size_t datalen, + ngtcp2_tstamp ts); /** * @function @@ -4573,7 +4602,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_datagram_versioned( * as well. * * |destlen| should be at least - * :member:`ngtcp2_settings.max_tx_udp_payload_size`. + * :member:`ngtcp2_settings.max_tx_udp_payload_size`. It must be at + * least :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`. * * For |path| and |pi| parameters, refer to * `ngtcp2_conn_writev_stream`. @@ -4655,10 +4685,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_datagram_versioned( * sending it makes QUIC connection enter the closing state. */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_datagram_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, - uint32_t flags, uint64_t dgram_id, const ngtcp2_vec *datav, size_t datavcnt, - ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, + uint32_t flags, uint64_t dgram_id, const ngtcp2_vec *datav, size_t datavcnt, + ngtcp2_tstamp ts); /** * @function @@ -4992,7 +5022,7 @@ ngtcp2_conn_get_path_max_tx_udp_payload_size(ngtcp2_conn *conn); * Out of memory */ NGTCP2_EXTERN int ngtcp2_conn_initiate_immediate_migration( - ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_tstamp ts); + ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_tstamp ts); /** * @function @@ -5193,7 +5223,19 @@ typedef enum ngtcp2_ccerr_type { * transport error, and it indicates that connection is closed * because of idle timeout. */ - NGTCP2_CCERR_TYPE_IDLE_CLOSE + NGTCP2_CCERR_TYPE_IDLE_CLOSE, + /** + * :enum:`NGTCP2_CCERR_TYPE_DROP_CONN` is a special case of QUIC + * transport error, and it indicates that connection should be + * dropped without sending a CONNECTION_CLOSE frame. + */ + NGTCP2_CCERR_TYPE_DROP_CONN, + /** + * :enum:`NGTCP2_CCERR_TYPE_RETRY` is a special case of QUIC + * transport error, and it indicates that RETRY packet should be + * sent to a client. + */ + NGTCP2_CCERR_TYPE_RETRY } ngtcp2_ccerr_type; /** @@ -5284,6 +5326,18 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_transport_error(ngtcp2_ccerr *ccerr, * :member:`ccerr->error_code ` to * :macro:`NGTCP2_NO_ERROR`. * + * If |liberr| is :macro:`NGTCP2_ERR_DROP_CONN`, :member:`ccerr->type + * ` is set to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_DROP_CONN`, and + * :member:`ccerr->error_code ` to + * :macro:`NGTCP2_NO_ERROR`. + * + * If |liberr| is :macro:`NGTCP2_ERR_RETRY`, :member:`ccerr->type + * ` is set to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_RETRY`, and + * :member:`ccerr->error_type ` to + * :macro:`NGTCP2_NO_ERROR`. + * * Otherwise, :member:`ccerr->type ` is set to * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_TRANSPORT`, and * :member:`ccerr->error_code ` is set to an @@ -5380,9 +5434,9 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr, * User callback failed */ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_connection_close_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, - const ngtcp2_ccerr *ccerr, ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, const ngtcp2_ccerr *ccerr, + ngtcp2_tstamp ts); /** * @function @@ -5734,8 +5788,8 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, #define ngtcp2_conn_write_stream(CONN, PATH, PI, DEST, DESTLEN, PDATALEN, \ FLAGS, STREAM_ID, DATA, DATALEN, TS) \ ngtcp2_conn_write_stream_versioned( \ - (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ - (PDATALEN), (FLAGS), (STREAM_ID), (DATA), (DATALEN), (TS)) + (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ + (PDATALEN), (FLAGS), (STREAM_ID), (DATA), (DATALEN), (TS)) /* * `ngtcp2_conn_writev_stream` is a wrapper around @@ -5745,8 +5799,8 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, #define ngtcp2_conn_writev_stream(CONN, PATH, PI, DEST, DESTLEN, PDATALEN, \ FLAGS, STREAM_ID, DATAV, DATAVCNT, TS) \ ngtcp2_conn_writev_stream_versioned( \ - (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ - (PDATALEN), (FLAGS), (STREAM_ID), (DATAV), (DATAVCNT), (TS)) + (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ + (PDATALEN), (FLAGS), (STREAM_ID), (DATAV), (DATAVCNT), (TS)) /* * `ngtcp2_conn_write_datagram` is a wrapper around @@ -5756,8 +5810,8 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, #define ngtcp2_conn_write_datagram(CONN, PATH, PI, DEST, DESTLEN, PACCEPTED, \ FLAGS, DGRAM_ID, DATA, DATALEN, TS) \ ngtcp2_conn_write_datagram_versioned( \ - (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ - (PACCEPTED), (FLAGS), (DGRAM_ID), (DATA), (DATALEN), (TS)) + (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ + (PACCEPTED), (FLAGS), (DGRAM_ID), (DATA), (DATALEN), (TS)) /* * `ngtcp2_conn_writev_datagram` is a wrapper around @@ -5767,8 +5821,8 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, #define ngtcp2_conn_writev_datagram(CONN, PATH, PI, DEST, DESTLEN, PACCEPTED, \ FLAGS, DGRAM_ID, DATAV, DATAVCNT, TS) \ ngtcp2_conn_writev_datagram_versioned( \ - (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ - (PACCEPTED), (FLAGS), (DGRAM_ID), (DATAV), (DATAVCNT), (TS)) + (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ + (PACCEPTED), (FLAGS), (DGRAM_ID), (DATAV), (DATAVCNT), (TS)) /* * `ngtcp2_conn_write_connection_close` is a wrapper around @@ -5778,8 +5832,8 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, #define ngtcp2_conn_write_connection_close(CONN, PATH, PI, DEST, DESTLEN, \ CCERR, TS) \ ngtcp2_conn_write_connection_close_versioned( \ - (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), \ - (CCERR), (TS)) + (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (DEST), (DESTLEN), (CCERR), \ + (TS)) /* * `ngtcp2_transport_params_encode` is a wrapper around @@ -5788,7 +5842,7 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, */ #define ngtcp2_transport_params_encode(DEST, DESTLEN, PARAMS) \ ngtcp2_transport_params_encode_versioned( \ - (DEST), (DESTLEN), NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS)) + (DEST), (DESTLEN), NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS)) /* * `ngtcp2_transport_params_decode` is a wrapper around @@ -5807,9 +5861,9 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, #define ngtcp2_conn_client_new(PCONN, DCID, SCID, PATH, VERSION, CALLBACKS, \ SETTINGS, PARAMS, MEM, USER_DATA) \ ngtcp2_conn_client_new_versioned( \ - (PCONN), (DCID), (SCID), (PATH), (VERSION), NGTCP2_CALLBACKS_VERSION, \ - (CALLBACKS), NGTCP2_SETTINGS_VERSION, (SETTINGS), \ - NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS), (MEM), (USER_DATA)) + (PCONN), (DCID), (SCID), (PATH), (VERSION), NGTCP2_CALLBACKS_VERSION, \ + (CALLBACKS), NGTCP2_SETTINGS_VERSION, (SETTINGS), \ + NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS), (MEM), (USER_DATA)) /* * `ngtcp2_conn_server_new` is a wrapper around @@ -5819,9 +5873,9 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, #define ngtcp2_conn_server_new(PCONN, DCID, SCID, PATH, VERSION, CALLBACKS, \ SETTINGS, PARAMS, MEM, USER_DATA) \ ngtcp2_conn_server_new_versioned( \ - (PCONN), (DCID), (SCID), (PATH), (VERSION), NGTCP2_CALLBACKS_VERSION, \ - (CALLBACKS), NGTCP2_SETTINGS_VERSION, (SETTINGS), \ - NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS), (MEM), (USER_DATA)) + (PCONN), (DCID), (SCID), (PATH), (VERSION), NGTCP2_CALLBACKS_VERSION, \ + (CALLBACKS), NGTCP2_SETTINGS_VERSION, (SETTINGS), \ + NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS), (MEM), (USER_DATA)) /* * `ngtcp2_conn_set_local_transport_params` is a wrapper around @@ -5830,7 +5884,7 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, */ #define ngtcp2_conn_set_local_transport_params(CONN, PARAMS) \ ngtcp2_conn_set_local_transport_params_versioned( \ - (CONN), NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS)) + (CONN), NGTCP2_TRANSPORT_PARAMS_VERSION, (PARAMS)) /* * `ngtcp2_transport_params_default` is a wrapper around @@ -5859,10 +5913,10 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, #ifdef _MSC_VER # pragma warning(pop) -#endif +#endif /* defined(_MSC_VER) */ #ifdef __cplusplus } -#endif +#endif /* defined(__cplusplus) */ -#endif /* NGTCP2_H */ +#endif /* !defined(NGTCP2_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h index 801c6cb2681386..15bf36ded2bc77 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h @@ -22,8 +22,8 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef VERSION_H -#define VERSION_H +#ifndef NGTCP2_VERSION_H +#define NGTCP2_VERSION_H /** * @macrosection @@ -36,7 +36,7 @@ * * Version number of the ngtcp2 library release. */ -#define NGTCP2_VERSION "1.3.0" +#define NGTCP2_VERSION "1.9.0" /** * @macro @@ -46,6 +46,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGTCP2_VERSION_NUM 0x010300 +#define NGTCP2_VERSION_NUM 0x010900 -#endif /* VERSION_H */ +#endif /* !defined(NGTCP2_VERSION_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c index d4778d66accf31..0e5bfe069e9fab 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c @@ -29,7 +29,7 @@ #include "ngtcp2_macro.h" #include "ngtcp2_tstamp.h" -ngtcp2_objalloc_def(acktr_entry, ngtcp2_acktr_entry, oplent); +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) { @@ -56,41 +56,26 @@ void ngtcp2_acktr_entry_objalloc_del(ngtcp2_acktr_entry *ent, ngtcp2_objalloc_acktr_entry_release(objalloc, ent); } -static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { - return *(int64_t *)lhs > *(int64_t *)rhs; -} - -int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, - const ngtcp2_mem *mem) { - int rv; +void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, + const ngtcp2_mem *mem) { + ngtcp2_objalloc_acktr_entry_init(&acktr->objalloc, NGTCP2_ACKTR_MAX_ENT + 1, + mem); - ngtcp2_objalloc_acktr_entry_init(&acktr->objalloc, 32, mem); + ngtcp2_static_ringbuf_acks_init(&acktr->acks); - rv = ngtcp2_ringbuf_init(&acktr->acks, 32, sizeof(ngtcp2_acktr_ack_entry), - mem); - if (rv != 0) { - goto fail_acks_init; - } - - ngtcp2_ksl_init(&acktr->ents, greater, sizeof(int64_t), mem); + ngtcp2_ksl_init(&acktr->ents, ngtcp2_ksl_int64_greater, + ngtcp2_ksl_int64_greater_search, sizeof(int64_t), mem); acktr->log = log; - acktr->mem = mem; acktr->flags = NGTCP2_ACKTR_FLAG_NONE; acktr->first_unacked_ts = UINT64_MAX; acktr->rx_npkt = 0; - - return 0; - -fail_acks_init: - ngtcp2_objalloc_free(&acktr->objalloc); - return rv; } void ngtcp2_acktr_free(ngtcp2_acktr *acktr) { #ifdef NOMEMPOOL ngtcp2_ksl_it it; -#endif /* NOMEMPOOL */ +#endif /* defined(NOMEMPOOL) */ if (acktr == NULL) { return; @@ -101,12 +86,10 @@ void ngtcp2_acktr_free(ngtcp2_acktr *acktr) { ngtcp2_ksl_it_next(&it)) { ngtcp2_acktr_entry_objalloc_del(ngtcp2_ksl_it_get(&it), &acktr->objalloc); } -#endif /* NOMEMPOOL */ +#endif /* defined(NOMEMPOOL) */ ngtcp2_ksl_free(&acktr->ents); - ngtcp2_ringbuf_free(&acktr->acks); - ngtcp2_objalloc_free(&acktr->objalloc); } @@ -213,11 +196,11 @@ void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent) { } } -ngtcp2_ksl_it ngtcp2_acktr_get(ngtcp2_acktr *acktr) { +ngtcp2_ksl_it ngtcp2_acktr_get(const ngtcp2_acktr *acktr) { return ngtcp2_ksl_begin(&acktr->ents); } -int ngtcp2_acktr_empty(ngtcp2_acktr *acktr) { +int ngtcp2_acktr_empty(const ngtcp2_acktr *acktr) { ngtcp2_ksl_it it = ngtcp2_ksl_begin(&acktr->ents); return ngtcp2_ksl_it_end(&it); } @@ -225,7 +208,7 @@ int ngtcp2_acktr_empty(ngtcp2_acktr *acktr) { ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr, int64_t pkt_num, int64_t largest_ack) { - ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks); + ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks.rb); ent->largest_ack = largest_ack; ent->pkt_num = pkt_num; @@ -266,8 +249,10 @@ static void acktr_on_ack(ngtcp2_acktr *acktr, ngtcp2_ringbuf *rb, ngtcp2_ksl_it_prev(&it); ent = ngtcp2_ksl_it_get(&it); - if (ent->pkt_num > ack_ent->largest_ack && - ack_ent->largest_ack >= ent->pkt_num - (int64_t)(ent->len - 1)) { + + assert(ent->pkt_num > ack_ent->largest_ack); + + if (ack_ent->largest_ack + (int64_t)ent->len > ent->pkt_num) { ent->len = (size_t)(ent->pkt_num - ack_ent->largest_ack); } } @@ -279,7 +264,7 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) { ngtcp2_acktr_ack_entry *ent; int64_t largest_ack = fr->largest_ack, min_ack; size_t i, j; - ngtcp2_ringbuf *rb = &acktr->acks; + ngtcp2_ringbuf *rb = &acktr->acks.rb; size_t nacks = ngtcp2_ringbuf_len(rb); /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */ @@ -295,7 +280,7 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) { min_ack = largest_ack - (int64_t)fr->first_ack_range; - if (min_ack <= ent->pkt_num && ent->pkt_num <= largest_ack) { + if (min_ack <= ent->pkt_num) { acktr_on_ack(acktr, rb, j); return; } @@ -306,8 +291,7 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) { for (;;) { if (ent->pkt_num > largest_ack) { - ++j; - if (j == nacks) { + if (++j == nacks) { return; } ent = ngtcp2_ringbuf_get(rb, j); @@ -330,7 +314,7 @@ void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr) { acktr->rx_npkt = 0; } -int ngtcp2_acktr_require_active_ack(ngtcp2_acktr *acktr, +int ngtcp2_acktr_require_active_ack(const ngtcp2_acktr *acktr, ngtcp2_duration max_ack_delay, ngtcp2_tstamp ts) { return ngtcp2_tstamp_elapsed(acktr->first_unacked_ts, max_ack_delay, ts); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h index 809fb692adc3c8..16aee42f275f67 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -39,7 +39,7 @@ /* NGTCP2_ACKTR_MAX_ENT is the maximum number of ngtcp2_acktr_entry which ngtcp2_acktr stores. */ -#define NGTCP2_ACKTR_MAX_ENT 1024 +#define NGTCP2_ACKTR_MAX_ENT (NGTCP2_MAX_ACK_RANGES + 1) typedef struct ngtcp2_log ngtcp2_log; @@ -65,7 +65,7 @@ typedef struct ngtcp2_acktr_entry { }; } ngtcp2_acktr_entry; -ngtcp2_objalloc_decl(acktr_entry, ngtcp2_acktr_entry, oplent); +ngtcp2_objalloc_decl(acktr_entry, ngtcp2_acktr_entry, oplent) /* * ngtcp2_acktr_entry_objalloc_new allocates memory for ent, and @@ -108,17 +108,18 @@ typedef struct ngtcp2_acktr_ack_entry { expired and canceled. */ #define NGTCP2_ACKTR_FLAG_CANCEL_TIMER 0x0100u +ngtcp2_static_ringbuf_def(acks, 32, sizeof(ngtcp2_acktr_ack_entry)) + /* * ngtcp2_acktr tracks received packets which we have to send ack. */ typedef struct ngtcp2_acktr { ngtcp2_objalloc objalloc; - ngtcp2_ringbuf acks; + ngtcp2_static_ringbuf_acks acks; /* ents includes ngtcp2_acktr_entry sorted by decreasing order of packet number. */ ngtcp2_ksl ents; ngtcp2_log *log; - const ngtcp2_mem *mem; /* flags is bitwise OR of zero, or more of NGTCP2_ACKTR_FLAG_*. */ uint16_t flags; /* first_unacked_ts is timestamp when ngtcp2_acktr_entry is added @@ -131,15 +132,9 @@ typedef struct ngtcp2_acktr { /* * ngtcp2_acktr_init initializes |acktr|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. */ -int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, - const ngtcp2_mem *mem); +void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, + const ngtcp2_mem *mem); /* * ngtcp2_acktr_free frees resources allocated for |acktr|. It frees @@ -174,13 +169,13 @@ void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent); * has the largest packet number to be acked. If there is no entry, * returned value satisfies ngtcp2_ksl_it_end(&it) != 0. */ -ngtcp2_ksl_it ngtcp2_acktr_get(ngtcp2_acktr *acktr); +ngtcp2_ksl_it ngtcp2_acktr_get(const ngtcp2_acktr *acktr); /* * ngtcp2_acktr_empty returns nonzero if it has no packet to * acknowledge. */ -int ngtcp2_acktr_empty(ngtcp2_acktr *acktr); +int ngtcp2_acktr_empty(const ngtcp2_acktr *acktr); /* * ngtcp2_acktr_add_ack records outgoing ACK frame whose largest @@ -208,7 +203,7 @@ void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr); * ngtcp2_acktr_require_active_ack returns nonzero if ACK frame should * be generated actively. */ -int ngtcp2_acktr_require_active_ack(ngtcp2_acktr *acktr, +int ngtcp2_acktr_require_active_ack(const ngtcp2_acktr *acktr, ngtcp2_duration max_ack_delay, ngtcp2_tstamp ts); @@ -218,4 +213,4 @@ int ngtcp2_acktr_require_active_ack(ngtcp2_acktr *acktr, */ void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr); -#endif /* NGTCP2_ACKTR_H */ +#endif /* !defined(NGTCP2_ACKTR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h index 8e3a9f591d9977..65ee7cd9f3006b 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -68,4 +68,4 @@ uint32_t ngtcp2_addr_compare(const ngtcp2_addr *a, const ngtcp2_addr *b); */ int ngtcp2_addr_empty(const ngtcp2_addr *addr); -#endif /* NGTCP2_ADDR_H */ +#endif /* !defined(NGTCP2_ADDR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c index 5cc39ee3b03da4..4a6797689fcc01 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c @@ -66,7 +66,7 @@ int ngtcp2_balloc_get(ngtcp2_balloc *balloc, void **pbuf, size_t n) { if (ngtcp2_buf_left(&balloc->buf) < n) { p = ngtcp2_mem_malloc(balloc->mem, - sizeof(ngtcp2_memblock_hd) + 0x10u + balloc->blklen); + sizeof(ngtcp2_memblock_hd) + 0x8u + balloc->blklen); if (p == NULL) { return NGTCP2_ERR_NOMEM; } @@ -75,10 +75,10 @@ int ngtcp2_balloc_get(ngtcp2_balloc *balloc, void **pbuf, size_t n) { hd->next = balloc->head; balloc->head = hd; ngtcp2_buf_init( - &balloc->buf, - (uint8_t *)(((uintptr_t)p + sizeof(ngtcp2_memblock_hd) + 0xfu) & - ~(uintptr_t)0xfu), - balloc->blklen); + &balloc->buf, + (uint8_t *)(((uintptr_t)p + sizeof(ngtcp2_memblock_hd) + 0xfu) & + ~(uintptr_t)0xfu), + balloc->blklen); } assert(((uintptr_t)balloc->buf.last & 0xfu) == 0); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.h index 1fb16325d9953d..c0e2a3f7562968 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -39,7 +39,10 @@ typedef struct ngtcp2_memblock_hd ngtcp2_memblock_hd; * ngtcp2_memblock_hd is the header of memory block. */ struct ngtcp2_memblock_hd { - ngtcp2_memblock_hd *next; + union { + ngtcp2_memblock_hd *next; + uint64_t pad; + }; }; /* @@ -60,7 +63,7 @@ typedef struct ngtcp2_balloc { /* * ngtcp2_balloc_init initializes |balloc| with |blklen| which is the - * size of memory block. + * size of memory block. |blklen| must be divisible by 16. */ void ngtcp2_balloc_init(ngtcp2_balloc *balloc, size_t blklen, const ngtcp2_mem *mem); @@ -88,4 +91,4 @@ int ngtcp2_balloc_get(ngtcp2_balloc *balloc, void **pbuf, size_t n); */ void ngtcp2_balloc_clear(ngtcp2_balloc *balloc); -#endif /* NGTCP2_BALLOC_H */ +#endif /* !defined(NGTCP2_BALLOC_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c index 27c4667c03924a..8777ca4c8a1632 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c @@ -39,8 +39,9 @@ #define NGTCP2_BBR_EXTRA_ACKED_FILTERLEN 10 #define NGTCP2_BBR_STARTUP_PACING_GAIN_H 277 +#define NGTCP2_BBR_DRAIN_PACING_GAIN_H 35 -#define NGTCP2_BBR_STARTUP_CWND_GAIN_H 200 +#define NGTCP2_BBR_DEFAULT_CWND_GAIN_H 200 #define NGTCP2_BBR_PROBE_RTT_CWND_GAIN_H 50 @@ -72,7 +73,7 @@ static void bbr_reset_lower_bounds(ngtcp2_cc_bbr *bbr); static void bbr_init_round_counting(ngtcp2_cc_bbr *bbr); -static void bbr_init_full_pipe(ngtcp2_cc_bbr *bbr); +static void bbr_reset_full_bw(ngtcp2_cc_bbr *bbr); static void bbr_init_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); @@ -84,8 +85,7 @@ static void bbr_set_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); static void bbr_enter_startup(ngtcp2_cc_bbr *bbr); -static void bbr_check_startup_done(ngtcp2_cc_bbr *bbr, - const ngtcp2_cc_ack *ack); +static void bbr_check_startup_done(ngtcp2_cc_bbr *bbr); static void bbr_update_on_ack(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); @@ -148,16 +148,17 @@ static void bbr_start_probe_bw_cruise(ngtcp2_cc_bbr *bbr); static void bbr_start_probe_bw_refill(ngtcp2_cc_bbr *bbr); -static void bbr_start_probe_bw_up(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); +static void bbr_start_probe_bw_up(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); static void bbr_update_probe_bw_cycle_phase(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); -static int bbr_check_time_to_cruise(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); +static int bbr_is_time_to_cruise(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); + +static int bbr_is_time_to_go_down(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); static int bbr_has_elapsed_in_phase(ngtcp2_cc_bbr *bbr, ngtcp2_duration interval, ngtcp2_tstamp ts); @@ -175,9 +176,8 @@ static void bbr_probe_inflight_hi_upward(ngtcp2_cc_bbr *bbr, static void bbr_adapt_upper_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); -static int bbr_check_time_to_probe_bw(ngtcp2_cc_bbr *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); +static int bbr_is_time_to_probe_bw(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts); static void bbr_pick_probe_wait(ngtcp2_cc_bbr *bbr); @@ -197,6 +197,8 @@ static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_rs *rs, ngtcp2_tstamp ts); +static void bbr_note_loss(ngtcp2_cc_bbr *bbr); + static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); @@ -227,15 +229,14 @@ static void bbr_handle_restart_from_idle(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -static uint64_t bbr_bdp_multiple(ngtcp2_cc_bbr *bbr, uint64_t bw, - uint64_t gain_h); +static uint64_t bbr_bdp_multiple(ngtcp2_cc_bbr *bbr, uint64_t gain_h); static uint64_t bbr_quantization_budget(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, uint64_t inflight); static uint64_t bbr_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - uint64_t bw, uint64_t gain_h); + uint64_t gain_h); static void bbr_update_max_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); @@ -247,10 +248,6 @@ static uint64_t min_pipe_cwnd(size_t max_udp_payload_size); static void bbr_advance_max_bw_filter(ngtcp2_cc_bbr *bbr); -static void bbr_modulate_cwnd_for_recovery(ngtcp2_cc_bbr *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack); - static void bbr_save_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); static void bbr_restore_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); @@ -272,7 +269,7 @@ static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_time); static void bbr_handle_recovery(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); + const ngtcp2_cc_ack *ack); static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, ngtcp2_tstamp initial_ts) { @@ -289,11 +286,12 @@ static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, bbr->idle_restart = 0; bbr->extra_acked_interval_start = initial_ts; bbr->extra_acked_delivered = 0; + bbr->full_bw_reached = 0; bbr_reset_congestion_signals(bbr); bbr_reset_lower_bounds(bbr); bbr_init_round_counting(bbr); - bbr_init_full_pipe(bbr); + bbr_reset_full_bw(bbr); bbr_init_pacing_rate(bbr, cstat); bbr_enter_startup(bbr); @@ -326,23 +324,17 @@ static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, bbr->bw_probe_up_acks = 0; bbr->inflight_hi = UINT64_MAX; - bbr->bw_hi = UINT64_MAX; bbr->probe_rtt_expired = 0; bbr->probe_rtt_min_delay = UINT64_MAX; bbr->probe_rtt_min_stamp = initial_ts; bbr->in_loss_recovery = 0; - bbr->packet_conservation = 0; + bbr->round_count_at_recovery = UINT64_MAX; bbr->max_inflight = 0; bbr->congestion_recovery_start_ts = UINT64_MAX; - bbr->congestion_recovery_next_round_delivered = 0; - - bbr->prior_inflight_lo = 0; - bbr->prior_inflight_hi = 0; - bbr->prior_bw_lo = 0; } static void bbr_reset_congestion_signals(ngtcp2_cc_bbr *bbr) { @@ -362,48 +354,53 @@ static void bbr_init_round_counting(ngtcp2_cc_bbr *bbr) { bbr->round_count = 0; } -static void bbr_init_full_pipe(ngtcp2_cc_bbr *bbr) { - bbr->filled_pipe = 0; +static void bbr_reset_full_bw(ngtcp2_cc_bbr *bbr) { bbr->full_bw = 0; bbr->full_bw_count = 0; + bbr->full_bw_now = 0; } -static void bbr_check_startup_full_bandwidth(ngtcp2_cc_bbr *bbr) { - if (bbr->filled_pipe || !bbr->round_start || bbr->rst->rs.is_app_limited) { +static void bbr_check_full_bw_reached(ngtcp2_cc_bbr *bbr, + ngtcp2_conn_stat *cstat) { + if (bbr->full_bw_now || bbr->rst->rs.is_app_limited) { return; } - if (bbr->max_bw * 100 >= bbr->full_bw * 125) { - bbr->full_bw = bbr->max_bw; - bbr->full_bw_count = 0; - } - - ++bbr->full_bw_count; - - if (bbr->full_bw_count >= 3) { - bbr->filled_pipe = 1; + if (cstat->delivery_rate_sec * 100 >= bbr->full_bw * 125) { + bbr_reset_full_bw(bbr); + bbr->full_bw = cstat->delivery_rate_sec; - ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, - "bbr filled pipe, full_bw=%" PRIu64, bbr->full_bw); + return; } -} -static void bbr_check_startup_high_loss(ngtcp2_cc_bbr *bbr, - const ngtcp2_cc_ack *ack) { - if (bbr->filled_pipe || !bbr->round_start || bbr->rst->rs.is_app_limited) { + if (!bbr->round_start) { return; } - if (bbr->loss_events_in_round <= 3) { + ++bbr->full_bw_count; + + bbr->full_bw_now = bbr->full_bw_count >= 3; + if (!bbr->full_bw_now) { return; } - /* loss_thresh = 2% */ - if (bbr->bytes_lost_in_round * 100 <= ack->prior_bytes_in_flight * 2) { + bbr->full_bw_reached = 1; + + ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, + "bbr reached full bandwidth, full_bw=%" PRIu64, bbr->full_bw); +} + +static void bbr_check_startup_high_loss(ngtcp2_cc_bbr *bbr) { + if (bbr->full_bw_reached || bbr->loss_events_in_round <= 6 || + (bbr->in_loss_recovery && + bbr->round_count <= bbr->round_count_at_recovery) || + !is_inflight_too_high(&bbr->rst->rs)) { return; } - bbr->filled_pipe = 1; + bbr->full_bw_reached = 1; + bbr->inflight_hi = ngtcp2_max_uint64(bbr_bdp_multiple(bbr, bbr->cwnd_gain_h), + bbr->inflight_latest); } static void bbr_init_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { @@ -423,7 +420,7 @@ static void bbr_set_pacing_rate_with_gain(ngtcp2_cc_bbr *bbr, interval = NGTCP2_SECONDS * 100 * 100 / pacing_gain_h / bbr->bw / (100 - NGTCP2_BBR_PACING_MARGIN_PERCENT); - if (bbr->filled_pipe || interval < cstat->pacing_interval) { + if (bbr->full_bw_reached || interval < cstat->pacing_interval) { cstat->pacing_interval = interval; } } @@ -437,15 +434,13 @@ static void bbr_enter_startup(ngtcp2_cc_bbr *bbr) { bbr->state = NGTCP2_BBR_STATE_STARTUP; bbr->pacing_gain_h = NGTCP2_BBR_STARTUP_PACING_GAIN_H; - bbr->cwnd_gain_h = NGTCP2_BBR_STARTUP_CWND_GAIN_H; + bbr->cwnd_gain_h = NGTCP2_BBR_DEFAULT_CWND_GAIN_H; } -static void bbr_check_startup_done(ngtcp2_cc_bbr *bbr, - const ngtcp2_cc_ack *ack) { - bbr_check_startup_full_bandwidth(bbr); - bbr_check_startup_high_loss(bbr, ack); +static void bbr_check_startup_done(ngtcp2_cc_bbr *bbr) { + bbr_check_startup_high_loss(bbr); - if (bbr->state == NGTCP2_BBR_STATE_STARTUP && bbr->filled_pipe) { + if (bbr->state == NGTCP2_BBR_STATE_STARTUP && bbr->full_bw_reached) { bbr_enter_drain(bbr); } } @@ -468,7 +463,8 @@ static void bbr_update_model_and_state(ngtcp2_cc_bbr *bbr, bbr_update_latest_delivery_signals(bbr, cstat); bbr_update_congestion_signals(bbr, cstat, ack); bbr_update_ack_aggregation(bbr, cstat, ack, ts); - bbr_check_startup_done(bbr, ack); + bbr_check_full_bw_reached(bbr, cstat); + bbr_check_startup_done(bbr); bbr_check_drain(bbr, cstat, ts); bbr_update_probe_bw_cycle_phase(bbr, cstat, ack, ts); bbr_update_min_rtt(bbr, ack, ts); @@ -493,9 +489,9 @@ static void bbr_update_on_loss(ngtcp2_cc_bbr *cc, ngtcp2_conn_stat *cstat, static void bbr_update_latest_delivery_signals(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { bbr->loss_round_start = 0; - bbr->bw_latest = ngtcp2_max(bbr->bw_latest, cstat->delivery_rate_sec); + bbr->bw_latest = ngtcp2_max_uint64(bbr->bw_latest, cstat->delivery_rate_sec); bbr->inflight_latest = - ngtcp2_max(bbr->inflight_latest, bbr->rst->rs.delivered); + ngtcp2_max_uint64(bbr->inflight_latest, bbr->rst->rs.delivered); if (bbr->rst->rs.prior_delivered >= bbr->loss_round_delivered) { bbr->loss_round_delivered = bbr->rst->delivered; @@ -519,11 +515,6 @@ static void bbr_update_congestion_signals(ngtcp2_cc_bbr *bbr, if (ack->bytes_lost) { bbr->bytes_lost_in_round += ack->bytes_lost; ++bbr->loss_events_in_round; - - if (!bbr->loss_in_round) { - bbr->loss_in_round = 1; - bbr->loss_round_delivered = bbr->rst->delivered; - } } if (!bbr->loss_round_start) { @@ -558,16 +549,15 @@ static void bbr_init_lower_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { } static void bbr_loss_lower_bounds(ngtcp2_cc_bbr *bbr) { - bbr->bw_lo = ngtcp2_max(bbr->bw_latest, bbr->bw_lo * NGTCP2_BBR_BETA_NUMER / - NGTCP2_BBR_BETA_DENOM); - bbr->inflight_lo = ngtcp2_max(bbr->inflight_latest, - bbr->inflight_lo * NGTCP2_BBR_BETA_NUMER / - NGTCP2_BBR_BETA_DENOM); + bbr->bw_lo = ngtcp2_max_uint64( + bbr->bw_latest, bbr->bw_lo * NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM); + bbr->inflight_lo = ngtcp2_max_uint64( + bbr->inflight_latest, + bbr->inflight_lo * NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM); } static void bbr_bound_bw_for_model(ngtcp2_cc_bbr *bbr) { - bbr->bw = ngtcp2_min(bbr->max_bw, bbr->bw_lo); - bbr->bw = ngtcp2_min(bbr->bw, bbr->bw_hi); + bbr->bw = ngtcp2_min_uint64(bbr->max_bw, bbr->bw_lo); } static void bbr_update_max_bw(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, @@ -633,7 +623,13 @@ static void bbr_update_ack_aggregation(ngtcp2_cc_bbr *bbr, bbr->extra_acked_delivered += ack->bytes_delivered; extra = bbr->extra_acked_delivered - expected_delivered; - extra = ngtcp2_min(extra, cstat->cwnd); + extra = ngtcp2_min_uint64(extra, cstat->cwnd); + + if (bbr->full_bw_reached) { + bbr->extra_acked_filter.window_length = NGTCP2_BBR_EXTRA_ACKED_FILTERLEN; + } else { + bbr->extra_acked_filter.window_length = 1; + } ngtcp2_window_filter_update(&bbr->extra_acked_filter, extra, bbr->round_count); @@ -645,14 +641,14 @@ static void bbr_enter_drain(ngtcp2_cc_bbr *bbr) { ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, "bbr enter Drain"); bbr->state = NGTCP2_BBR_STATE_DRAIN; - bbr->pacing_gain_h = 100 * 100 / NGTCP2_BBR_STARTUP_CWND_GAIN_H; - bbr->cwnd_gain_h = NGTCP2_BBR_STARTUP_CWND_GAIN_H; + bbr->pacing_gain_h = NGTCP2_BBR_DRAIN_PACING_GAIN_H; + bbr->cwnd_gain_h = NGTCP2_BBR_DEFAULT_CWND_GAIN_H; } static void bbr_check_drain(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { if (bbr->state == NGTCP2_BBR_STATE_DRAIN && - cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, bbr->bw, 100)) { + cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, 100)) { bbr_enter_probe_bw(bbr, ts); } } @@ -677,7 +673,7 @@ static void bbr_start_probe_bw_down(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts) { bbr->state = NGTCP2_BBR_STATE_PROBE_BW_DOWN; bbr->pacing_gain_h = 90; - bbr->cwnd_gain_h = 200; + bbr->cwnd_gain_h = NGTCP2_BBR_DEFAULT_CWND_GAIN_H; } static void bbr_start_probe_bw_cruise(ngtcp2_cc_bbr *bbr) { @@ -686,7 +682,7 @@ static void bbr_start_probe_bw_cruise(ngtcp2_cc_bbr *bbr) { bbr->state = NGTCP2_BBR_STATE_PROBE_BW_CRUISE; bbr->pacing_gain_h = 100; - bbr->cwnd_gain_h = 200; + bbr->cwnd_gain_h = NGTCP2_BBR_DEFAULT_CWND_GAIN_H; } static void bbr_start_probe_bw_refill(ngtcp2_cc_bbr *bbr) { @@ -703,18 +699,18 @@ static void bbr_start_probe_bw_refill(ngtcp2_cc_bbr *bbr) { bbr->state = NGTCP2_BBR_STATE_PROBE_BW_REFILL; bbr->pacing_gain_h = 100; - bbr->cwnd_gain_h = 200; + bbr->cwnd_gain_h = NGTCP2_BBR_DEFAULT_CWND_GAIN_H; } -static void bbr_start_probe_bw_up(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { +static void bbr_start_probe_bw_up(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, "bbr start ProbeBW_UP"); bbr->ack_phase = NGTCP2_BBR_ACK_PHASE_ACKS_PROBE_STARTING; bbr_start_round(bbr); + bbr_reset_full_bw(bbr); - bbr->cycle_stamp = ts; + bbr->full_bw = cstat->delivery_rate_sec; bbr->state = NGTCP2_BBR_STATE_PROBE_BW_UP; bbr->pacing_gain_h = 125; bbr->cwnd_gain_h = 225; @@ -726,7 +722,7 @@ static void bbr_update_probe_bw_cycle_phase(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - if (!bbr->filled_pipe) { + if (!bbr->full_bw_reached) { return; } @@ -738,17 +734,17 @@ static void bbr_update_probe_bw_cycle_phase(ngtcp2_cc_bbr *bbr, switch (bbr->state) { case NGTCP2_BBR_STATE_PROBE_BW_DOWN: - if (bbr_check_time_to_probe_bw(bbr, cstat, ts)) { + if (bbr_is_time_to_probe_bw(bbr, cstat, ts)) { return; } - if (bbr_check_time_to_cruise(bbr, cstat, ts)) { + if (bbr_is_time_to_cruise(bbr, cstat, ts)) { bbr_start_probe_bw_cruise(bbr); } break; case NGTCP2_BBR_STATE_PROBE_BW_CRUISE: - if (bbr_check_time_to_probe_bw(bbr, cstat, ts)) { + if (bbr_is_time_to_probe_bw(bbr, cstat, ts)) { return; } @@ -756,13 +752,12 @@ static void bbr_update_probe_bw_cycle_phase(ngtcp2_cc_bbr *bbr, case NGTCP2_BBR_STATE_PROBE_BW_REFILL: if (bbr->round_start) { bbr->bw_probe_samples = 1; - bbr_start_probe_bw_up(bbr, cstat, ts); + bbr_start_probe_bw_up(bbr, cstat); } break; case NGTCP2_BBR_STATE_PROBE_BW_UP: - if (bbr_has_elapsed_in_phase(bbr, bbr->min_rtt, ts) && - cstat->bytes_in_flight > bbr_inflight(bbr, cstat, bbr->max_bw, 125)) { + if (bbr_is_time_to_go_down(bbr, cstat)) { bbr_start_probe_bw_down(bbr, ts); } @@ -772,15 +767,26 @@ static void bbr_update_probe_bw_cycle_phase(ngtcp2_cc_bbr *bbr, } } -static int bbr_check_time_to_cruise(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { +static int bbr_is_time_to_cruise(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { (void)ts; if (cstat->bytes_in_flight > bbr_inflight_with_headroom(bbr, cstat)) { return 0; } - if (cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, bbr->max_bw, 100)) { + if (cstat->bytes_in_flight <= bbr_inflight(bbr, cstat, 100)) { + return 1; + } + + return 0; +} + +static int bbr_is_time_to_go_down(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { + if (bbr->rst->is_cwnd_limited && cstat->cwnd >= bbr->inflight_hi) { + bbr_reset_full_bw(bbr); + bbr->full_bw = cstat->delivery_rate_sec; + } else if (bbr->full_bw_now) { return 1; } @@ -801,13 +807,13 @@ static uint64_t bbr_inflight_with_headroom(ngtcp2_cc_bbr *bbr, return UINT64_MAX; } - headroom = ngtcp2_max(cstat->max_tx_udp_payload_size, - bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER / - NGTCP2_BBR_HEADROOM_DENOM); + headroom = ngtcp2_max_uint64(cstat->max_tx_udp_payload_size, + bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER / + NGTCP2_BBR_HEADROOM_DENOM); mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); if (bbr->inflight_hi > headroom) { - return ngtcp2_max(bbr->inflight_hi - headroom, mpcwnd); + return ngtcp2_max_uint64(bbr->inflight_hi - headroom, mpcwnd); } return mpcwnd; @@ -818,8 +824,8 @@ static void bbr_raise_inflight_hi_slope(ngtcp2_cc_bbr *bbr, uint64_t growth_this_round = cstat->max_tx_udp_payload_size << bbr->bw_probe_up_rounds; - bbr->bw_probe_up_rounds = ngtcp2_min(bbr->bw_probe_up_rounds + 1, 30); - bbr->probe_up_cnt = ngtcp2_max(cstat->cwnd / growth_this_round, 1) * + bbr->bw_probe_up_rounds = ngtcp2_min_size(bbr->bw_probe_up_rounds + 1, 30); + bbr->probe_up_cnt = ngtcp2_max_uint64(cstat->cwnd / growth_this_round, 1) * cstat->max_tx_udp_payload_size; } @@ -860,8 +866,7 @@ static void bbr_adapt_upper_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, } if (!bbr_check_inflight_too_high(bbr, cstat, ts)) { - /* bbr->bw_hi never be updated */ - if (bbr->inflight_hi == UINT64_MAX /* || bbr->bw_hi == UINT64_MAX */) { + if (bbr->inflight_hi == UINT64_MAX) { return; } @@ -869,19 +874,14 @@ static void bbr_adapt_upper_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, bbr->inflight_hi = bbr->rst->rs.tx_in_flight; } - if (cstat->delivery_rate_sec > bbr->bw_hi) { - bbr->bw_hi = cstat->delivery_rate_sec; - } - if (bbr->state == NGTCP2_BBR_STATE_PROBE_BW_UP) { bbr_probe_inflight_hi_upward(bbr, cstat, ack); } } } -static int bbr_check_time_to_probe_bw(ngtcp2_cc_bbr *bbr, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { +static int bbr_is_time_to_probe_bw(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { if (bbr_has_elapsed_in_phase(bbr, bbr->bw_probe_wait, ts) || bbr_is_reno_coexistence_probe_time(bbr, cstat)) { bbr_start_probe_bw_refill(bbr); @@ -902,22 +902,22 @@ static void bbr_pick_probe_wait(ngtcp2_cc_bbr *bbr) { bbr->rand(&rand, 1, &bbr->rand_ctx); bbr->bw_probe_wait = - 2 * NGTCP2_SECONDS + (ngtcp2_tstamp)(NGTCP2_SECONDS * rand / 255); + 2 * NGTCP2_SECONDS + (ngtcp2_tstamp)(NGTCP2_SECONDS * rand / 255); } static int bbr_is_reno_coexistence_probe_time(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { uint64_t reno_rounds = - bbr_target_inflight(bbr, cstat) / cstat->max_tx_udp_payload_size; + bbr_target_inflight(bbr, cstat) / cstat->max_tx_udp_payload_size; - return bbr->rounds_since_bw_probe >= ngtcp2_min(reno_rounds, 63); + return bbr->rounds_since_bw_probe >= ngtcp2_min_uint64(reno_rounds, 63); } static uint64_t bbr_target_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - uint64_t bdp = bbr_inflight(bbr, cstat, bbr->bw, 100); + uint64_t bdp = bbr_bdp_multiple(bbr, bbr->cwnd_gain_h); - return ngtcp2_min(bdp, cstat->cwnd); + return ngtcp2_min_uint64(bdp, cstat->cwnd); } static int bbr_check_inflight_too_high(ngtcp2_cc_bbr *bbr, @@ -946,9 +946,9 @@ static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, bbr->bw_probe_samples = 0; if (!rs->is_app_limited) { - bbr->inflight_hi = ngtcp2_max( - rs->tx_in_flight, bbr_target_inflight(bbr, cstat) * - NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM); + bbr->inflight_hi = ngtcp2_max_uint64( + rs->tx_in_flight, bbr_target_inflight(bbr, cstat) * + NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM); } if (bbr->state == NGTCP2_BBR_STATE_PROBE_BW_UP) { @@ -956,10 +956,21 @@ static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, } } +static void bbr_note_loss(ngtcp2_cc_bbr *bbr) { + if (bbr->loss_in_round) { + return; + } + + bbr->loss_in_round = 1; + bbr->loss_round_delivered = bbr->rst->delivered; +} + static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { ngtcp2_rs rs = {0}; + bbr_note_loss(bbr); + if (!bbr->bw_probe_samples) { return; } @@ -1007,7 +1018,7 @@ static void bbr_update_min_rtt(ngtcp2_cc_bbr *bbr, const ngtcp2_cc_ack *ack, int min_rtt_expired; bbr->probe_rtt_expired = - ts > bbr->probe_rtt_min_stamp + NGTCP2_BBR_PROBE_RTT_INTERVAL; + ts > bbr->probe_rtt_min_stamp + NGTCP2_BBR_PROBE_RTT_INTERVAL; if (ack->rtt != UINT64_MAX && (ack->rtt < bbr->probe_rtt_min_delay || bbr->probe_rtt_expired)) { @@ -1106,7 +1117,7 @@ static void bbr_mark_connection_app_limited(ngtcp2_cc_bbr *bbr, static void bbr_exit_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts) { bbr_reset_lower_bounds(bbr); - if (bbr->filled_pipe) { + if (bbr->full_bw_reached) { bbr_start_probe_bw_down(bbr, ts); bbr_start_probe_bw_cruise(bbr); } else { @@ -1131,15 +1142,14 @@ static void bbr_handle_restart_from_idle(ngtcp2_cc_bbr *bbr, } } -static uint64_t bbr_bdp_multiple(ngtcp2_cc_bbr *bbr, uint64_t bw, - uint64_t gain_h) { +static uint64_t bbr_bdp_multiple(ngtcp2_cc_bbr *bbr, uint64_t gain_h) { uint64_t bdp; if (bbr->min_rtt == UINT64_MAX) { return bbr->initial_cwnd; } - bdp = bw * bbr->min_rtt / NGTCP2_SECONDS; + bdp = ngtcp2_max_uint64(bbr->bw * bbr->min_rtt / NGTCP2_SECONDS, 1); return (uint64_t)(bdp * gain_h / 100); } @@ -1153,9 +1163,9 @@ static uint64_t bbr_quantization_budget(ngtcp2_cc_bbr *bbr, uint64_t inflight) { bbr_update_offload_budget(bbr, cstat); - inflight = ngtcp2_max(inflight, bbr->offload_budget); + inflight = ngtcp2_max_uint64(inflight, bbr->offload_budget); inflight = - ngtcp2_max(inflight, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); + ngtcp2_max_uint64(inflight, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); if (bbr->state == NGTCP2_BBR_STATE_PROBE_BW_UP) { inflight += 2 * cstat->max_tx_udp_payload_size; @@ -1165,8 +1175,8 @@ static uint64_t bbr_quantization_budget(ngtcp2_cc_bbr *bbr, } static uint64_t bbr_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - uint64_t bw, uint64_t gain_h) { - uint64_t inflight = bbr_bdp_multiple(bbr, bw, gain_h); + uint64_t gain_h) { + uint64_t inflight = bbr_bdp_multiple(bbr, gain_h); return bbr_quantization_budget(bbr, cstat, inflight); } @@ -1178,8 +1188,7 @@ static void bbr_update_max_inflight(ngtcp2_cc_bbr *bbr, /* Not documented */ /* bbr_update_aggregation_budget(bbr); */ - inflight = - bbr_bdp_multiple(bbr, bbr->bw, bbr->cwnd_gain_h) + bbr->extra_acked; + inflight = bbr_bdp_multiple(bbr, bbr->cwnd_gain_h) + bbr->extra_acked; bbr->max_inflight = bbr_quantization_budget(bbr, cstat, inflight); } @@ -1192,44 +1201,26 @@ static void bbr_advance_max_bw_filter(ngtcp2_cc_bbr *bbr) { ++bbr->cycle_count; } -static void bbr_modulate_cwnd_for_recovery(ngtcp2_cc_bbr *bbr, - ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack) { - if (ack->bytes_lost > 0) { - if (cstat->cwnd > ack->bytes_lost) { - cstat->cwnd -= ack->bytes_lost; - cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_tx_udp_payload_size); - } else { - cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; - } - } - - if (bbr->packet_conservation) { - cstat->cwnd = - ngtcp2_max(cstat->cwnd, cstat->bytes_in_flight + ack->bytes_delivered); - } -} - static void bbr_save_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { if (!bbr->in_loss_recovery && bbr->state != NGTCP2_BBR_STATE_PROBE_RTT) { bbr->prior_cwnd = cstat->cwnd; return; } - bbr->prior_cwnd = ngtcp2_max(bbr->prior_cwnd, cstat->cwnd); + bbr->prior_cwnd = ngtcp2_max_uint64(bbr->prior_cwnd, cstat->cwnd); } static void bbr_restore_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - cstat->cwnd = ngtcp2_max(cstat->cwnd, bbr->prior_cwnd); + cstat->cwnd = ngtcp2_max_uint64(cstat->cwnd, bbr->prior_cwnd); } static uint64_t bbr_probe_rtt_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { uint64_t probe_rtt_cwnd = - bbr_bdp_multiple(bbr, bbr->bw, NGTCP2_BBR_PROBE_RTT_CWND_GAIN_H); + bbr_bdp_multiple(bbr, NGTCP2_BBR_PROBE_RTT_CWND_GAIN_H); uint64_t mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); - return ngtcp2_max(probe_rtt_cwnd, mpcwnd); + return ngtcp2_max_uint64(probe_rtt_cwnd, mpcwnd); } static void bbr_bound_cwnd_for_probe_rtt(ngtcp2_cc_bbr *bbr, @@ -1239,7 +1230,7 @@ static void bbr_bound_cwnd_for_probe_rtt(ngtcp2_cc_bbr *bbr, if (bbr->state == NGTCP2_BBR_STATE_PROBE_RTT) { probe_rtt_cwnd = bbr_probe_rtt_cwnd(bbr, cstat); - cstat->cwnd = ngtcp2_min(cstat->cwnd, probe_rtt_cwnd); + cstat->cwnd = ngtcp2_min_uint64(cstat->cwnd, probe_rtt_cwnd); } } @@ -1248,21 +1239,18 @@ static void bbr_set_cwnd(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, uint64_t mpcwnd; bbr_update_max_inflight(bbr, cstat); - bbr_modulate_cwnd_for_recovery(bbr, cstat, ack); - - if (!bbr->packet_conservation) { - if (bbr->filled_pipe) { - cstat->cwnd += ack->bytes_delivered; - cstat->cwnd = ngtcp2_min(cstat->cwnd, bbr->max_inflight); - } else if (cstat->cwnd < bbr->max_inflight || - bbr->rst->delivered < bbr->initial_cwnd) { - cstat->cwnd += ack->bytes_delivered; - } - mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); - cstat->cwnd = ngtcp2_max(cstat->cwnd, mpcwnd); + if (bbr->full_bw_reached) { + cstat->cwnd += ack->bytes_delivered; + cstat->cwnd = ngtcp2_min_uint64(cstat->cwnd, bbr->max_inflight); + } else if (cstat->cwnd < bbr->max_inflight || + bbr->rst->delivered < bbr->initial_cwnd) { + cstat->cwnd += ack->bytes_delivered; } + mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); + cstat->cwnd = ngtcp2_max_uint64(cstat->cwnd, mpcwnd); + bbr_bound_cwnd_for_probe_rtt(bbr, cstat); bbr_bound_cwnd_for_model(bbr, cstat); } @@ -1280,30 +1268,23 @@ static void bbr_bound_cwnd_for_model(ngtcp2_cc_bbr *bbr, cap = bbr_inflight_with_headroom(bbr, cstat); } - cap = ngtcp2_min(cap, bbr->inflight_lo); - cap = ngtcp2_max(cap, mpcwnd); + cap = ngtcp2_min_uint64(cap, bbr->inflight_lo); + cap = ngtcp2_max_uint64(cap, mpcwnd); - cstat->cwnd = ngtcp2_min(cstat->cwnd, cap); + cstat->cwnd = ngtcp2_min_uint64(cstat->cwnd, cap); } static void bbr_set_send_quantum(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - size_t floor, send_quantum; + size_t send_quantum = 64 * 1024; (void)bbr; - if (cstat->pacing_interval > (NGTCP2_SECONDS * 8 * 10 / 12) >> 20) { - floor = cstat->max_tx_udp_payload_size; - } else { - floor = 2 * cstat->max_tx_udp_payload_size; - } - if (cstat->pacing_interval) { - send_quantum = (size_t)(NGTCP2_MILLISECONDS / cstat->pacing_interval); - send_quantum = ngtcp2_min(send_quantum, 64 * 1024); - } else { - send_quantum = 64 * 1024; + send_quantum = ngtcp2_min_size( + send_quantum, (size_t)(NGTCP2_MILLISECONDS / cstat->pacing_interval)); } - cstat->send_quantum = ngtcp2_max(send_quantum, floor); + cstat->send_quantum = + ngtcp2_max_size(send_quantum, 2 * cstat->max_tx_udp_payload_size); } static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, @@ -1313,16 +1294,12 @@ static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, } static void bbr_handle_recovery(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { + const ngtcp2_cc_ack *ack) { if (bbr->in_loss_recovery) { - if (ts - cstat->congestion_recovery_start_ts >= cstat->smoothed_rtt) { - bbr->packet_conservation = 0; - } - if (ack->largest_pkt_sent_ts != UINT64_MAX && !in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { bbr->in_loss_recovery = 0; - bbr->packet_conservation = 0; + bbr->round_count_at_recovery = UINT64_MAX; bbr_restore_cwnd(bbr, cstat); } @@ -1331,18 +1308,15 @@ static void bbr_handle_recovery(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, if (bbr->congestion_recovery_start_ts != UINT64_MAX) { bbr->in_loss_recovery = 1; + bbr->round_count_at_recovery = + bbr->round_start ? bbr->round_count : bbr->round_count + 1; bbr_save_cwnd(bbr, cstat); cstat->cwnd = - cstat->bytes_in_flight + - ngtcp2_max(ack->bytes_delivered, cstat->max_tx_udp_payload_size); + cstat->bytes_in_flight + + ngtcp2_max_uint64(ack->bytes_delivered, cstat->max_tx_udp_payload_size); cstat->congestion_recovery_start_ts = bbr->congestion_recovery_start_ts; bbr->congestion_recovery_start_ts = UINT64_MAX; - bbr->packet_conservation = 1; - bbr->congestion_recovery_next_round_delivered = bbr->rst->delivered; - bbr->prior_inflight_hi = bbr->inflight_hi; - bbr->prior_inflight_lo = bbr->inflight_lo; - bbr->prior_bw_lo = bbr->bw_lo; } } @@ -1350,12 +1324,18 @@ static void bbr_cc_on_pkt_lost(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + if (bbr->state == NGTCP2_BBR_STATE_STARTUP) { + return; + } + bbr_update_on_loss(bbr, cstat, pkt, ts); } static void bbr_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_ts, ngtcp2_tstamp ts) { + ngtcp2_tstamp sent_ts, uint64_t bytes_lost, + ngtcp2_tstamp ts) { ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); + (void)bytes_lost; if (bbr->in_loss_recovery || bbr->congestion_recovery_start_ts != UINT64_MAX || @@ -1377,13 +1357,8 @@ static void bbr_cc_on_spurious_congestion(ngtcp2_cc *cc, if (bbr->in_loss_recovery) { bbr->in_loss_recovery = 0; - bbr->packet_conservation = 0; + bbr->round_count_at_recovery = UINT64_MAX; bbr_restore_cwnd(bbr, cstat); - bbr->full_bw_count = 0; - bbr->loss_in_round = 0; - bbr->inflight_lo = ngtcp2_max(bbr->inflight_lo, bbr->prior_inflight_lo); - bbr->inflight_hi = ngtcp2_max(bbr->inflight_hi, bbr->prior_inflight_hi); - bbr->bw_lo = ngtcp2_max(bbr->bw_lo, bbr->prior_bw_lo); } } @@ -1396,19 +1371,19 @@ static void bbr_cc_on_persistent_congestion(ngtcp2_cc *cc, cstat->congestion_recovery_start_ts = UINT64_MAX; bbr->congestion_recovery_start_ts = UINT64_MAX; bbr->in_loss_recovery = 0; - bbr->packet_conservation = 0; + bbr->round_count_at_recovery = UINT64_MAX; bbr_save_cwnd(bbr, cstat); cstat->cwnd = cstat->bytes_in_flight + cstat->max_tx_udp_payload_size; - cstat->cwnd = - ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); + cstat->cwnd = ngtcp2_max_uint64( + cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); } static void bbr_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); - bbr_handle_recovery(bbr, cstat, ack, ts); + bbr_handle_recovery(bbr, cstat, ack); bbr_update_on_ack(bbr, cstat, ack, ts); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h index 0017be35010e66..f266ec5d71e4e4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -95,9 +95,10 @@ typedef struct ngtcp2_cc_bbr { uint64_t round_count; /* Full pipe */ - int filled_pipe; uint64_t full_bw; size_t full_bw_count; + int full_bw_reached; + int full_bw_now; /* Pacing rate */ uint64_t pacing_gain_h; @@ -123,19 +124,13 @@ typedef struct ngtcp2_cc_bbr { size_t bw_probe_up_rounds; uint64_t bw_probe_up_acks; uint64_t inflight_hi; - uint64_t bw_hi; int probe_rtt_expired; ngtcp2_duration probe_rtt_min_delay; ngtcp2_tstamp probe_rtt_min_stamp; int in_loss_recovery; - int packet_conservation; + uint64_t round_count_at_recovery; uint64_t max_inflight; ngtcp2_tstamp congestion_recovery_start_ts; - uint64_t congestion_recovery_next_round_delivered; - - uint64_t prior_inflight_lo; - uint64_t prior_inflight_hi; - uint64_t prior_bw_lo; } ngtcp2_cc_bbr; void ngtcp2_cc_bbr_init(ngtcp2_cc_bbr *bbr, ngtcp2_log *log, @@ -143,4 +138,4 @@ void ngtcp2_cc_bbr_init(ngtcp2_cc_bbr *bbr, ngtcp2_log *log, ngtcp2_tstamp initial_ts, ngtcp2_rand rand, const ngtcp2_rand_ctx *rand_ctx); -#endif /* NGTCP2_BBR_H */ +#endif /* !defined(NGTCP2_BBR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h index 85b5f4ddf0464a..e87adb119916ca 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -105,4 +105,4 @@ int ngtcp2_buf_chain_new(ngtcp2_buf_chain **pbufchain, size_t len, */ void ngtcp2_buf_chain_del(ngtcp2_buf_chain *bufchain, const ngtcp2_mem *mem); -#endif /* NGTCP2_BUF_H */ +#endif /* !defined(NGTCP2_BUF_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c index 9ad37fbdb6395a..1ff59f315c5b66 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c @@ -32,16 +32,13 @@ #include "ngtcp2_mem.h" #include "ngtcp2_rcvry.h" #include "ngtcp2_conn_stat.h" +#include "ngtcp2_rst.h" #include "ngtcp2_unreachable.h" -/* NGTCP2_CC_DELIVERY_RATE_SEC_FILTERLEN is the window length of - delivery rate filter driven by ACK clocking. */ -#define NGTCP2_CC_DELIVERY_RATE_SEC_FILTERLEN 10 - uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) { uint64_t n = 2 * max_udp_payload_size; - n = ngtcp2_max(n, 14720); - return ngtcp2_min(10 * max_udp_payload_size, n); + n = ngtcp2_max_uint64(n, 14720); + return ngtcp2_min_uint64(10 * max_udp_payload_size, n); } ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, @@ -59,13 +56,7 @@ ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, return pkt; } -static void reno_cc_reset(ngtcp2_cc_reno *reno) { - ngtcp2_window_filter_init(&reno->delivery_rate_sec_filter, - NGTCP2_CC_DELIVERY_RATE_SEC_FILTERLEN); - reno->ack_count = 0; - reno->target_cwnd = 0; - reno->pending_add = 0; -} +static void reno_cc_reset(ngtcp2_cc_reno *reno) { reno->pending_add = 0; } void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log) { memset(reno, 0, sizeof(*reno)); @@ -74,8 +65,7 @@ void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log) { reno->cc.on_pkt_acked = ngtcp2_cc_reno_cc_on_pkt_acked; reno->cc.congestion_event = ngtcp2_cc_reno_cc_congestion_event; reno->cc.on_persistent_congestion = - ngtcp2_cc_reno_cc_on_persistent_congestion; - reno->cc.on_ack_recv = ngtcp2_cc_reno_cc_on_ack_recv; + ngtcp2_cc_reno_cc_on_persistent_congestion; reno->cc.reset = ngtcp2_cc_reno_cc_reset; reno_cc_reset(reno); @@ -94,11 +84,7 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, uint64_t m; (void)ts; - if (in_congestion_recovery(cstat, pkt->sent_ts)) { - return; - } - - if (reno->target_cwnd && reno->target_cwnd < cstat->cwnd) { + if (in_congestion_recovery(cstat, pkt->sent_ts) || pkt->is_app_limited) { return; } @@ -118,9 +104,10 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - ngtcp2_tstamp ts) { + uint64_t bytes_lost, ngtcp2_tstamp ts) { ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); uint64_t min_cwnd; + (void)bytes_lost; if (in_congestion_recovery(cstat, sent_ts)) { return; @@ -129,7 +116,7 @@ void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cstat->congestion_recovery_start_ts = ts; cstat->cwnd >>= NGTCP2_LOSS_REDUCTION_FACTOR_BITS; min_cwnd = 2 * cstat->max_tx_udp_payload_size; - cstat->cwnd = ngtcp2_max(cstat->cwnd, min_cwnd); + cstat->cwnd = ngtcp2_max_uint64(cstat->cwnd, min_cwnd); cstat->ssthresh = cstat->cwnd; reno->pending_add = 0; @@ -149,35 +136,6 @@ void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc, cstat->congestion_recovery_start_ts = UINT64_MAX; } -void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { - ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); - uint64_t target_cwnd, initcwnd; - uint64_t max_delivery_rate_sec; - (void)ack; - (void)ts; - - ++reno->ack_count; - - ngtcp2_window_filter_update(&reno->delivery_rate_sec_filter, - cstat->delivery_rate_sec, reno->ack_count); - - max_delivery_rate_sec = - ngtcp2_window_filter_get_best(&reno->delivery_rate_sec_filter); - - if (cstat->min_rtt != UINT64_MAX && max_delivery_rate_sec) { - target_cwnd = max_delivery_rate_sec * cstat->smoothed_rtt / NGTCP2_SECONDS; - initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size); - reno->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100; - - ngtcp2_log_info(reno->cc.log, NGTCP2_LOG_EVENT_CCA, - "target_cwnd=%" PRIu64 " max_delivery_rate_sec=%" PRIu64 - " smoothed_rtt=%" PRIu64, - reno->target_cwnd, max_delivery_rate_sec, - cstat->smoothed_rtt); - } -} - void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); @@ -187,45 +145,49 @@ void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, reno_cc_reset(reno); } +static void cubic_vars_reset(ngtcp2_cubic_vars *v) { + v->cwnd_prior = 0; + v->w_max = 0; + v->k = 0; + v->epoch_start = UINT64_MAX; + v->w_est = 0; + + v->state = NGTCP2_CUBIC_STATE_INITIAL; + v->app_limited_start_ts = UINT64_MAX; + v->app_limited_duration = 0; + v->pending_bytes_delivered = 0; + v->pending_est_bytes_delivered = 0; +} + static void cubic_cc_reset(ngtcp2_cc_cubic *cubic) { - ngtcp2_window_filter_init(&cubic->delivery_rate_sec_filter, - NGTCP2_CC_DELIVERY_RATE_SEC_FILTERLEN); - cubic->ack_count = 0; - cubic->target_cwnd = 0; - cubic->w_last_max = 0; - cubic->w_tcp = 0; - cubic->origin_point = 0; - cubic->epoch_start = UINT64_MAX; - cubic->k = 0; - - cubic->prior.cwnd = 0; - cubic->prior.ssthresh = 0; - cubic->prior.w_last_max = 0; - cubic->prior.w_tcp = 0; - cubic->prior.origin_point = 0; - cubic->prior.epoch_start = UINT64_MAX; - cubic->prior.k = 0; - - cubic->rtt_sample_count = 0; - cubic->current_round_min_rtt = UINT64_MAX; - cubic->last_round_min_rtt = UINT64_MAX; - cubic->window_end = -1; + cubic_vars_reset(&cubic->current); + cubic_vars_reset(&cubic->undo.v); + cubic->undo.cwnd = 0; + cubic->undo.ssthresh = 0; + + cubic->hs.current_round_min_rtt = UINT64_MAX; + cubic->hs.last_round_min_rtt = UINT64_MAX; + cubic->hs.curr_rtt = UINT64_MAX; + cubic->hs.rtt_sample_count = 0; + cubic->hs.css_baseline_min_rtt = UINT64_MAX; + cubic->hs.css_round = 0; + + cubic->next_round_delivered = 0; } -void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cubic, ngtcp2_log *log) { +void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cubic, ngtcp2_log *log, + ngtcp2_rst *rst) { memset(cubic, 0, sizeof(*cubic)); cubic->cc.log = log; - cubic->cc.on_pkt_acked = ngtcp2_cc_cubic_cc_on_pkt_acked; + cubic->cc.on_ack_recv = ngtcp2_cc_cubic_cc_on_ack_recv; cubic->cc.congestion_event = ngtcp2_cc_cubic_cc_congestion_event; cubic->cc.on_spurious_congestion = ngtcp2_cc_cubic_cc_on_spurious_congestion; cubic->cc.on_persistent_congestion = - ngtcp2_cc_cubic_cc_on_persistent_congestion; - cubic->cc.on_ack_recv = ngtcp2_cc_cubic_cc_on_ack_recv; - cubic->cc.on_pkt_sent = ngtcp2_cc_cubic_cc_on_pkt_sent; - cubic->cc.new_rtt_sample = ngtcp2_cc_cubic_cc_new_rtt_sample; + ngtcp2_cc_cubic_cc_on_persistent_congestion; cubic->cc.reset = ngtcp2_cc_cubic_cc_reset; - cubic->cc.event = ngtcp2_cc_cubic_cc_event; + + cubic->rst = rst; cubic_cc_reset(cubic); } @@ -254,191 +216,250 @@ uint64_t ngtcp2_cbrt(uint64_t n) { return y; } -/* HyStart++ constants */ -#define NGTCP2_HS_MIN_SSTHRESH 16 +/* RFC 9406 HyStart++ constants */ +#define NGTCP2_HS_MIN_RTT_THRESH (4 * NGTCP2_MILLISECONDS) +#define NGTCP2_HS_MAX_RTT_THRESH (16 * NGTCP2_MILLISECONDS) +#define NGTCP2_HS_MIN_RTT_DIVISOR 8 #define NGTCP2_HS_N_RTT_SAMPLE 8 -#define NGTCP2_HS_MIN_ETA (4 * NGTCP2_MILLISECONDS) -#define NGTCP2_HS_MAX_ETA (16 * NGTCP2_MILLISECONDS) +#define NGTCP2_HS_CSS_GROWTH_DIVISOR 4 +#define NGTCP2_HS_CSS_ROUNDS 5 + +static uint64_t cubic_cc_compute_w_cubic(ngtcp2_cc_cubic *cubic, + const ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { + ngtcp2_duration t = ts - cubic->current.epoch_start; + uint64_t delta; + uint64_t tx = (t << 10) / NGTCP2_SECONDS; + uint64_t kx = (cubic->current.k << 10) / NGTCP2_SECONDS; + uint64_t time_delta; + + if (tx < kx) { + return UINT64_MAX; + } + + time_delta = tx - kx; + + delta = cstat->max_tx_udp_payload_size * + ((((time_delta * time_delta) >> 10) * time_delta) >> 10) * 4 / 10; -void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, - ngtcp2_tstamp ts) { + return cubic->current.w_max + (delta >> 10); +} + +void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts) { ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); - ngtcp2_duration t, eta; - uint64_t target, cwnd_thres; - uint64_t tx, kx, time_delta, delta; - uint64_t add, tcp_add; - uint64_t m; + uint64_t w_cubic, w_cubic_next, target, m; + ngtcp2_duration rtt_thresh; + int round_start; - if (pkt->pktns_id == NGTCP2_PKTNS_ID_APPLICATION && cubic->window_end != -1 && - cubic->window_end <= pkt->pkt_num) { - cubic->window_end = -1; + if (in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { + return; } - if (in_congestion_recovery(cstat, pkt->sent_ts)) { + if (cubic->current.state == NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE) { + if (cubic->rst->rs.is_app_limited && !cubic->rst->is_cwnd_limited) { + if (cubic->current.app_limited_start_ts == UINT64_MAX) { + cubic->current.app_limited_start_ts = ts; + } + + return; + } + + if (cubic->current.app_limited_start_ts != UINT64_MAX) { + cubic->current.app_limited_duration += + ts - cubic->current.app_limited_start_ts; + cubic->current.app_limited_start_ts = UINT64_MAX; + } + } else if (cubic->rst->rs.is_app_limited && !cubic->rst->is_cwnd_limited) { return; } + round_start = ack->pkt_delivered >= cubic->next_round_delivered; + if (round_start) { + cubic->next_round_delivered = cubic->rst->delivered; + + cubic->rst->is_cwnd_limited = 0; + } + if (cstat->cwnd < cstat->ssthresh) { /* slow-start */ - if (cubic->target_cwnd == 0 || cubic->target_cwnd > cstat->cwnd) { - cstat->cwnd += pkt->pktlen; + if (cubic->hs.css_round) { + cstat->cwnd += ack->bytes_delivered / NGTCP2_HS_CSS_GROWTH_DIVISOR; + } else { + cstat->cwnd += ack->bytes_delivered; } ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64, - pkt->pkt_num, cstat->cwnd); + "%" PRIu64 " bytes acked, slow start cwnd=%" PRIu64, + ack->bytes_delivered, cstat->cwnd); + + if (round_start) { + cubic->hs.last_round_min_rtt = cubic->hs.current_round_min_rtt; + cubic->hs.current_round_min_rtt = UINT64_MAX; + cubic->hs.rtt_sample_count = 0; - if (cubic->last_round_min_rtt != UINT64_MAX && - cubic->current_round_min_rtt != UINT64_MAX && - cstat->cwnd >= - NGTCP2_HS_MIN_SSTHRESH * cstat->max_tx_udp_payload_size && - cubic->rtt_sample_count >= NGTCP2_HS_N_RTT_SAMPLE) { - eta = cubic->last_round_min_rtt / 8; - - if (eta < NGTCP2_HS_MIN_ETA) { - eta = NGTCP2_HS_MIN_ETA; - } else if (eta > NGTCP2_HS_MAX_ETA) { - eta = NGTCP2_HS_MAX_ETA; + if (cubic->hs.css_round) { + ++cubic->hs.css_round; } + } + + cubic->hs.current_round_min_rtt = + ngtcp2_min_uint64(cubic->hs.current_round_min_rtt, ack->rtt); + ++cubic->hs.rtt_sample_count; - if (cubic->current_round_min_rtt >= cubic->last_round_min_rtt + eta) { + if (cubic->hs.css_round) { + if (cubic->hs.current_round_min_rtt < cubic->hs.css_baseline_min_rtt) { + cubic->hs.css_baseline_min_rtt = UINT64_MAX; + cubic->hs.css_round = 0; + return; + } + + if (cubic->hs.css_round >= NGTCP2_HS_CSS_ROUNDS) { ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "HyStart++ exit slow start"); - cubic->w_last_max = cstat->cwnd; cstat->ssthresh = cstat->cwnd; } - } - - return; - } - /* congestion avoidance */ - - if (cubic->epoch_start == UINT64_MAX) { - cubic->epoch_start = ts; - if (cstat->cwnd < cubic->w_last_max) { - cubic->k = ngtcp2_cbrt((cubic->w_last_max - cstat->cwnd) * 10 / 4 / - cstat->max_tx_udp_payload_size); - cubic->origin_point = cubic->w_last_max; - } else { - cubic->k = 0; - cubic->origin_point = cstat->cwnd; + return; } - cubic->w_tcp = cstat->cwnd; - - ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "cubic-ca epoch_start=%" PRIu64 " k=%" PRIu64 - " origin_point=%" PRIu64, - cubic->epoch_start, cubic->k, cubic->origin_point); + if (cubic->hs.rtt_sample_count >= NGTCP2_HS_N_RTT_SAMPLE && + cubic->hs.current_round_min_rtt != UINT64_MAX && + cubic->hs.last_round_min_rtt != UINT64_MAX) { + rtt_thresh = + ngtcp2_max_uint64(NGTCP2_HS_MIN_RTT_THRESH, + ngtcp2_min_uint64(cubic->hs.last_round_min_rtt / + NGTCP2_HS_MIN_RTT_DIVISOR, + NGTCP2_HS_MAX_RTT_THRESH)); + + if (cubic->hs.current_round_min_rtt >= + cubic->hs.last_round_min_rtt + rtt_thresh) { + cubic->hs.css_baseline_min_rtt = cubic->hs.current_round_min_rtt; + cubic->hs.css_round = 1; + } + } - cubic->pending_add = 0; - cubic->pending_w_add = 0; + return; } - t = ts - cubic->epoch_start; - - tx = (t << 10) / NGTCP2_SECONDS; - kx = (cubic->k << 10); + /* congestion avoidance */ - if (tx > kx) { - time_delta = tx - kx; - } else { - time_delta = kx - tx; + switch (cubic->current.state) { + case NGTCP2_CUBIC_STATE_INITIAL: + m = cstat->max_tx_udp_payload_size * ack->bytes_delivered + + cubic->current.pending_bytes_delivered; + cstat->cwnd += m / cstat->cwnd; + cubic->current.pending_bytes_delivered = m % cstat->cwnd; + return; + case NGTCP2_CUBIC_STATE_RECOVERY: + cubic->current.state = NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE; + cubic->current.epoch_start = ts; + break; + default: + break; } - delta = cstat->max_tx_udp_payload_size * - ((((time_delta * time_delta) >> 10) * time_delta) >> 10) * 4 / 10; - delta >>= 10; - - if (tx > kx) { - target = cubic->origin_point + delta; - } else { - target = cubic->origin_point - delta; - } + w_cubic = cubic_cc_compute_w_cubic(cubic, cstat, + ts - cubic->current.app_limited_duration); + w_cubic_next = cubic_cc_compute_w_cubic( + cubic, cstat, + ts - cubic->current.app_limited_duration + cstat->smoothed_rtt); - cwnd_thres = - (target * (((t + cstat->smoothed_rtt) << 10) / NGTCP2_SECONDS)) >> 10; - if (cwnd_thres < cstat->cwnd) { + if (w_cubic_next == UINT64_MAX || w_cubic_next < cstat->cwnd) { target = cstat->cwnd; - } else if (2 * cwnd_thres > 3 * cstat->cwnd) { + } else if (2 * w_cubic_next > 3 * cstat->cwnd) { target = cstat->cwnd * 3 / 2; } else { - target = cwnd_thres; + target = w_cubic_next; } - if (target > cstat->cwnd) { - m = cubic->pending_add + - cstat->max_tx_udp_payload_size * (target - cstat->cwnd); - add = m / cstat->cwnd; - cubic->pending_add = m % cstat->cwnd; - } else { - m = cubic->pending_add + cstat->max_tx_udp_payload_size; - add = m / (100 * cstat->cwnd); - cubic->pending_add = m % (100 * cstat->cwnd); - } - - m = cubic->pending_w_add + cstat->max_tx_udp_payload_size * pkt->pktlen; - - cubic->w_tcp += m / cstat->cwnd; - cubic->pending_w_add = m % cstat->cwnd; + m = ack->bytes_delivered * cstat->max_tx_udp_payload_size + + cubic->current.pending_est_bytes_delivered; + cubic->current.pending_est_bytes_delivered = m % cstat->cwnd; - if (cubic->w_tcp > cstat->cwnd) { - tcp_add = cstat->max_tx_udp_payload_size * (cubic->w_tcp - cstat->cwnd) / - cstat->cwnd; - if (tcp_add > add) { - add = tcp_add; - } + if (cubic->current.w_est < cubic->current.cwnd_prior) { + cubic->current.w_est += m * 9 / 17 / cstat->cwnd; + } else { + cubic->current.w_est += m / cstat->cwnd; } - if (cubic->target_cwnd == 0 || cubic->target_cwnd > cstat->cwnd) { - cstat->cwnd += add; + if (w_cubic == UINT64_MAX || cubic->current.w_est > w_cubic) { + cstat->cwnd = cubic->current.w_est; + } else { + m = (target - cstat->cwnd) * cstat->max_tx_udp_payload_size + + cubic->current.pending_bytes_delivered; + cstat->cwnd += m / cstat->cwnd; + cubic->current.pending_bytes_delivered = m % cstat->cwnd; } ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "pkn=%" PRId64 " acked, cubic-ca cwnd=%" PRIu64 " t=%" PRIu64 - " k=%" PRIi64 " time_delta=%" PRIu64 " delta=%" PRIu64 - " target=%" PRIu64 " w_tcp=%" PRIu64, - pkt->pkt_num, cstat->cwnd, t, cubic->k, time_delta >> 4, - delta, target, cubic->w_tcp); + "%" PRIu64 " bytes acked, cubic-ca cwnd=%" PRIu64 + " k=%" PRIi64 " target=%" PRIu64 " w_est=%" PRIu64, + ack->bytes_delivered, cstat->cwnd, cubic->current.k, target, + cubic->current.w_est); } void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, + uint64_t bytes_lost, ngtcp2_tstamp ts) { ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); - uint64_t min_cwnd; + uint64_t flight_size; if (in_congestion_recovery(cstat, sent_ts)) { return; } - if (cubic->prior.cwnd < cstat->cwnd) { - cubic->prior.cwnd = cstat->cwnd; - cubic->prior.ssthresh = cstat->ssthresh; - cubic->prior.w_last_max = cubic->w_last_max; - cubic->prior.w_tcp = cubic->w_tcp; - cubic->prior.origin_point = cubic->origin_point; - cubic->prior.epoch_start = cubic->epoch_start; - cubic->prior.k = cubic->k; + if (cubic->undo.cwnd < cstat->cwnd) { + cubic->undo.v = cubic->current; + cubic->undo.cwnd = cstat->cwnd; + cubic->undo.ssthresh = cstat->ssthresh; } cstat->congestion_recovery_start_ts = ts; - cubic->epoch_start = UINT64_MAX; - if (cstat->cwnd < cubic->w_last_max) { - cubic->w_last_max = cstat->cwnd * 17 / 10 / 2; + cubic->current.state = NGTCP2_CUBIC_STATE_RECOVERY; + cubic->current.epoch_start = UINT64_MAX; + cubic->current.app_limited_start_ts = UINT64_MAX; + cubic->current.app_limited_duration = 0; + cubic->current.pending_bytes_delivered = 0; + cubic->current.pending_est_bytes_delivered = 0; + + if (cstat->cwnd < cubic->current.w_max) { + cubic->current.w_max = cstat->cwnd * 17 / 20; } else { - cubic->w_last_max = cstat->cwnd; + cubic->current.w_max = cstat->cwnd; } - min_cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->ssthresh = cstat->cwnd * 7 / 10; - cstat->ssthresh = ngtcp2_max(cstat->ssthresh, min_cwnd); + + if (cubic->rst->rs.delivered * 2 < cstat->cwnd) { + flight_size = cstat->bytes_in_flight + bytes_lost; + cstat->ssthresh = ngtcp2_min_uint64( + cstat->ssthresh, + ngtcp2_max_uint64(cubic->rst->rs.delivered, flight_size) * 7 / 10); + } + + cstat->ssthresh = + ngtcp2_max_uint64(cstat->ssthresh, 2 * cstat->max_tx_udp_payload_size); + + cubic->current.cwnd_prior = cstat->cwnd; cstat->cwnd = cstat->ssthresh; + cubic->current.w_est = cstat->cwnd; + + if (cstat->cwnd < cubic->current.w_max) { + cubic->current.k = + ngtcp2_cbrt(((cubic->current.w_max - cstat->cwnd) << 10) * 10 / 4 / + cstat->max_tx_udp_payload_size) * + NGTCP2_SECONDS; + cubic->current.k >>= 10; + } else { + cubic->current.k = 0; + } + ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, "reduce cwnd because of packet loss cwnd=%" PRIu64, cstat->cwnd); @@ -450,101 +471,34 @@ void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *cc, ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); (void)ts; - if (cstat->cwnd >= cubic->prior.cwnd) { - return; - } - - cstat->congestion_recovery_start_ts = UINT64_MAX; - - cstat->cwnd = cubic->prior.cwnd; - cstat->ssthresh = cubic->prior.ssthresh; - cubic->w_last_max = cubic->prior.w_last_max; - cubic->w_tcp = cubic->prior.w_tcp; - cubic->origin_point = cubic->prior.origin_point; - cubic->epoch_start = cubic->prior.epoch_start; - cubic->k = cubic->prior.k; - - cubic->prior.cwnd = 0; - cubic->prior.ssthresh = 0; - cubic->prior.w_last_max = 0; - cubic->prior.w_tcp = 0; - cubic->prior.origin_point = 0; - cubic->prior.epoch_start = UINT64_MAX; - cubic->prior.k = 0; - - ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "spurious congestion is detected and congestion state is " - "restored cwnd=%" PRIu64, - cstat->cwnd); -} - -void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc, - ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { - (void)cc; - (void)ts; - - cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->congestion_recovery_start_ts = UINT64_MAX; -} - -void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, - ngtcp2_tstamp ts) { - ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); - uint64_t target_cwnd, initcwnd; - uint64_t max_delivery_rate_sec; - (void)ack; - (void)ts; - - ++cubic->ack_count; - - ngtcp2_window_filter_update(&cubic->delivery_rate_sec_filter, - cstat->delivery_rate_sec, cubic->ack_count); - max_delivery_rate_sec = - ngtcp2_window_filter_get_best(&cubic->delivery_rate_sec_filter); - - if (cstat->min_rtt != UINT64_MAX && max_delivery_rate_sec) { - target_cwnd = max_delivery_rate_sec * cstat->smoothed_rtt / NGTCP2_SECONDS; - initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size); - cubic->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100; + if (cstat->cwnd < cubic->undo.cwnd) { + cubic->current = cubic->undo.v; + cstat->cwnd = cubic->undo.cwnd; + cstat->ssthresh = cubic->undo.ssthresh; ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "target_cwnd=%" PRIu64 " max_delivery_rate_sec=%" PRIu64 - " smoothed_rtt=%" PRIu64, - cubic->target_cwnd, max_delivery_rate_sec, - cstat->smoothed_rtt); + "spurious congestion is detected and congestion state is " + "restored cwnd=%" PRIu64, + cstat->cwnd); } -} - -void ngtcp2_cc_cubic_cc_on_pkt_sent(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt) { - ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); - (void)cstat; - if (pkt->pktns_id != NGTCP2_PKTNS_ID_APPLICATION || cubic->window_end != -1) { - return; - } - - cubic->window_end = pkt->pkt_num; - cubic->last_round_min_rtt = cubic->current_round_min_rtt; - cubic->current_round_min_rtt = UINT64_MAX; - cubic->rtt_sample_count = 0; + cubic_vars_reset(&cubic->undo.v); + cubic->undo.cwnd = 0; + cubic->undo.ssthresh = 0; } -void ngtcp2_cc_cubic_cc_new_rtt_sample(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts) { +void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc, + ngtcp2_conn_stat *cstat, + ngtcp2_tstamp ts) { ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); (void)ts; - if (cubic->window_end == -1) { - return; - } + cubic_cc_reset(cubic); - cubic->current_round_min_rtt = - ngtcp2_min(cubic->current_round_min_rtt, cstat->latest_rtt); - ++cubic->rtt_sample_count; + cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; + cstat->congestion_recovery_start_ts = UINT64_MAX; } void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, @@ -555,23 +509,3 @@ void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cubic_cc_reset(cubic); } - -void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_cc_event_type event, ngtcp2_tstamp ts) { - ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); - ngtcp2_tstamp last_ts; - - if (event != NGTCP2_CC_EVENT_TYPE_TX_START || - cubic->epoch_start == UINT64_MAX) { - return; - } - - last_ts = cstat->last_tx_pkt_ts[NGTCP2_PKTNS_ID_APPLICATION]; - if (last_ts == UINT64_MAX || last_ts <= cubic->epoch_start) { - return; - } - - assert(ts >= last_ts); - - cubic->epoch_start += ts - last_ts; -} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h index 524bcdb7e4bf86..e3c363a51bb85a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h @@ -27,18 +27,18 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include "ngtcp2_pktns_id.h" -#include "ngtcp2_window_filter.h" #define NGTCP2_LOSS_REDUCTION_FACTOR_BITS 1 #define NGTCP2_PERSISTENT_CONGESTION_THRESHOLD 3 typedef struct ngtcp2_log ngtcp2_log; typedef struct ngtcp2_conn_stat ngtcp2_conn_stat; +typedef struct ngtcp2_rst ngtcp2_rst; /** * @struct @@ -144,10 +144,12 @@ typedef void (*ngtcp2_cc_on_pkt_lost)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, * * :type:`ngtcp2_cc_congestion_event` is a callback function which is * called when congestion event happens (e.g., when packet is lost). + * |bytes_lost| is the number of bytes lost in this congestion event. */ typedef void (*ngtcp2_cc_congestion_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, + uint64_t bytes_lost, ngtcp2_tstamp ts); /** @@ -305,9 +307,6 @@ ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, /* ngtcp2_cc_reno is the RENO congestion controller. */ typedef struct ngtcp2_cc_reno { ngtcp2_cc cc; - ngtcp2_window_filter delivery_rate_sec_filter; - uint64_t ack_count; - uint64_t target_cwnd; uint64_t pending_add; } ngtcp2_cc_reno; @@ -318,59 +317,81 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - ngtcp2_tstamp ts); + uint64_t bytes_lost, ngtcp2_tstamp ts); void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); - void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); +typedef enum ngtcp2_cubic_state { + /* NGTCP2_CUBIC_STATE_INITIAL is the state where CUBIC is in slow + start phase, or congestion avoidance phase before congestion + events occur. */ + NGTCP2_CUBIC_STATE_INITIAL, + /* NGTCP2_CUBIC_STATE_RECOVERY is the state that a connection is in + recovery period. */ + NGTCP2_CUBIC_STATE_RECOVERY, + /* NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE is the state where CUBIC + is in congestion avoidance phase after recovery period ends. */ + NGTCP2_CUBIC_STATE_CONGESTION_AVOIDANCE, +} ngtcp2_cubic_state; + +typedef struct ngtcp2_cubic_vars { + uint64_t cwnd_prior; + uint64_t w_max; + ngtcp2_duration k; + ngtcp2_tstamp epoch_start; + uint64_t w_est; + + ngtcp2_cubic_state state; + /* app_limited_start_ts is the timestamp where app limited period + started. */ + ngtcp2_tstamp app_limited_start_ts; + /* app_limited_duration is the cumulative duration where a + connection is under app limited when ACK is received. */ + ngtcp2_duration app_limited_duration; + uint64_t pending_bytes_delivered; + uint64_t pending_est_bytes_delivered; +} ngtcp2_cubic_vars; + /* ngtcp2_cc_cubic is CUBIC congestion controller. */ typedef struct ngtcp2_cc_cubic { ngtcp2_cc cc; - ngtcp2_window_filter delivery_rate_sec_filter; - uint64_t ack_count; - uint64_t target_cwnd; - uint64_t w_last_max; - uint64_t w_tcp; - uint64_t origin_point; - ngtcp2_tstamp epoch_start; - uint64_t k; - /* prior stores the congestion state when a congestion event occurs + ngtcp2_rst *rst; + /* current is a set of variables that are currently in effect. */ + ngtcp2_cubic_vars current; + /* undo stores the congestion state when a congestion event occurs in order to restore the state when it turns out that the event is spurious. */ struct { + ngtcp2_cubic_vars v; uint64_t cwnd; uint64_t ssthresh; - uint64_t w_last_max; - uint64_t w_tcp; - uint64_t origin_point; - ngtcp2_tstamp epoch_start; - uint64_t k; - } prior; + } undo; /* HyStart++ variables */ - size_t rtt_sample_count; - uint64_t current_round_min_rtt; - uint64_t last_round_min_rtt; - int64_t window_end; - uint64_t pending_add; - uint64_t pending_w_add; + struct { + ngtcp2_duration current_round_min_rtt; + ngtcp2_duration last_round_min_rtt; + ngtcp2_duration curr_rtt; + size_t rtt_sample_count; + ngtcp2_duration css_baseline_min_rtt; + size_t css_round; + } hs; + uint64_t next_round_delivered; } ngtcp2_cc_cubic; -void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cc, ngtcp2_log *log); +void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cc, ngtcp2_log *log, + ngtcp2_rst *rst); -void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt, - ngtcp2_tstamp ts); +void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - ngtcp2_tstamp ts); + uint64_t bytes_lost, ngtcp2_tstamp ts); void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, @@ -380,21 +401,9 @@ void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); - -void ngtcp2_cc_cubic_cc_on_pkt_sent(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - const ngtcp2_cc_pkt *pkt); - -void ngtcp2_cc_cubic_cc_new_rtt_sample(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_cc_event_type event, ngtcp2_tstamp ts); - uint64_t ngtcp2_cbrt(uint64_t n); -#endif /* NGTCP2_CC_H */ +#endif /* !defined(NGTCP2_CC_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c index f3b92b569ec928..181850cfcbc87a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c @@ -36,6 +36,7 @@ void ngtcp2_cid_init(ngtcp2_cid *cid, const uint8_t *data, size_t datalen) { assert(datalen <= NGTCP2_MAX_CIDLEN); cid->datalen = datalen; + if (datalen) { ngtcp2_cpymem(cid->data, data, datalen); } @@ -74,12 +75,14 @@ void ngtcp2_dcid_init(ngtcp2_dcid *dcid, uint64_t seq, const ngtcp2_cid *cid, const uint8_t *token) { dcid->seq = seq; dcid->cid = *cid; + if (token) { memcpy(dcid->token, token, NGTCP2_STATELESS_RESET_TOKENLEN); dcid->flags = NGTCP2_DCID_FLAG_TOKEN_PRESENT; } else { dcid->flags = NGTCP2_DCID_FLAG_NONE; } + ngtcp2_path_storage_zero(&dcid->ps); dcid->retired_ts = UINT64_MAX; dcid->bound_ts = UINT64_MAX; @@ -115,6 +118,7 @@ void ngtcp2_dcid_copy(ngtcp2_dcid *dest, const ngtcp2_dcid *src) { void ngtcp2_dcid_copy_cid_token(ngtcp2_dcid *dest, const ngtcp2_dcid *src) { dest->seq = src->seq; dest->cid = src->cid; + if (src->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) { dest->flags |= NGTCP2_DCID_FLAG_TOKEN_PRESENT; memcpy(dest->token, src->token, NGTCP2_STATELESS_RESET_TOKENLEN); @@ -123,15 +127,14 @@ void ngtcp2_dcid_copy_cid_token(ngtcp2_dcid *dest, const ngtcp2_dcid *src) { } } -int ngtcp2_dcid_verify_uniqueness(ngtcp2_dcid *dcid, uint64_t seq, +int ngtcp2_dcid_verify_uniqueness(const ngtcp2_dcid *dcid, uint64_t seq, const ngtcp2_cid *cid, const uint8_t *token) { if (dcid->seq == seq) { return ngtcp2_cid_eq(&dcid->cid, cid) && - (dcid->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) && - memcmp(dcid->token, token, - NGTCP2_STATELESS_RESET_TOKENLEN) == 0 - ? 0 - : NGTCP2_ERR_PROTO; + (dcid->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) && + memcmp(dcid->token, token, NGTCP2_STATELESS_RESET_TOKENLEN) == 0 + ? 0 + : NGTCP2_ERR_PROTO; } return !ngtcp2_cid_eq(&dcid->cid, cid) ? 0 : NGTCP2_ERR_PROTO; @@ -140,8 +143,7 @@ int ngtcp2_dcid_verify_uniqueness(ngtcp2_dcid *dcid, uint64_t seq, int ngtcp2_dcid_verify_stateless_reset_token(const ngtcp2_dcid *dcid, const uint8_t *token) { return (dcid->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) && - ngtcp2_cmemeq(dcid->token, token, - NGTCP2_STATELESS_RESET_TOKENLEN) - ? 0 - : NGTCP2_ERR_INVALID_ARGUMENT; + ngtcp2_cmemeq(dcid->token, token, NGTCP2_STATELESS_RESET_TOKENLEN) + ? 0 + : NGTCP2_ERR_INVALID_ARGUMENT; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h index 0b37441178c72a..6372ef113d6454 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -37,20 +37,20 @@ /* NGTCP2_SCID_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_SCID_FLAG_NONE 0x00u /* NGTCP2_SCID_FLAG_USED indicates that a local endpoint observed that - a remote endpoint uses a particular Connection ID. */ + a remote endpoint uses this particular Connection ID. */ #define NGTCP2_SCID_FLAG_USED 0x01u -/* NGTCP2_SCID_FLAG_RETIRED indicates that a particular Connection ID - is retired. */ +/* NGTCP2_SCID_FLAG_RETIRED indicates that this particular Connection + ID is retired. */ #define NGTCP2_SCID_FLAG_RETIRED 0x02u typedef struct ngtcp2_scid { ngtcp2_pq_entry pe; - /* seq is the sequence number associated to the CID. */ + /* seq is the sequence number associated to the Connection ID. */ uint64_t seq; /* cid is a connection ID */ ngtcp2_cid cid; - /* retired_ts is the timestamp when peer tells that this CID is - retired. */ + /* retired_ts is the timestamp when a remote endpoint tells that + this Connection ID is retired. */ ngtcp2_tstamp retired_ts; /* flags is the bitwise OR of zero or more of NGTCP2_SCID_FLAG_*. */ uint8_t flags; @@ -66,33 +66,33 @@ typedef struct ngtcp2_scid { #define NGTCP2_DCID_FLAG_TOKEN_PRESENT 0x02u typedef struct ngtcp2_dcid { - /* seq is the sequence number associated to the CID. */ + /* seq is the sequence number associated to the Connection ID. */ uint64_t seq; - /* cid is a connection ID */ + /* cid is a Connection ID */ ngtcp2_cid cid; /* path is a path which cid is bound to. The addresses are zero length if cid has not been bound to a particular path yet. */ ngtcp2_path_storage ps; - /* retired_ts is the timestamp when peer tells that this CID is + /* retired_ts is the timestamp when this Connection ID is retired. */ ngtcp2_tstamp retired_ts; - /* bound_ts is the timestamp when this connection ID is bound to a - particular path. It is only assigned when a connection ID is - used just for sending PATH_RESPONSE and is not zero-length. */ + /* bound_ts is the timestamp when this Connection ID is bound to a + particular path. It is only assigned when a Connection ID is + used just for sending PATH_RESPONSE, and is not zero-length. */ ngtcp2_tstamp bound_ts; /* bytes_sent is the number of bytes sent to an associated path. */ uint64_t bytes_sent; /* bytes_recv is the number of bytes received from an associated path. */ uint64_t bytes_recv; - /* max_udp_payload_size is the maximum size of UDP payload that is - allowed to send to this path. */ + /* max_udp_payload_size is the maximum size of UDP datagram payload + that is allowed to be sent to this path. */ size_t max_udp_payload_size; /* flags is bitwise OR of zero or more of NGTCP2_DCID_FLAG_*. */ uint8_t flags; - /* token is a stateless reset token associated to this CID. - Actually, the stateless reset token is tied to the connection, - not to the particular connection ID. */ + /* token is a stateless reset token received along with this + Connection ID. The stateless reset token is tied to the + connection, not to the particular Connection ID. */ uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN]; } ngtcp2_dcid; @@ -106,7 +106,7 @@ void ngtcp2_cid_zero(ngtcp2_cid *cid); int ngtcp2_cid_less(const ngtcp2_cid *lhs, const ngtcp2_cid *rhs); /* - * ngtcp2_cid_empty returns nonzero if |cid| includes empty connection + * ngtcp2_cid_empty returns nonzero if |cid| includes empty Connection * ID. */ int ngtcp2_cid_empty(const ngtcp2_cid *cid); @@ -123,7 +123,7 @@ void ngtcp2_scid_copy(ngtcp2_scid *dest, const ngtcp2_scid *src); /* * ngtcp2_dcid_init initializes |dcid| with the given parameters. If - * |token| is NULL, the function fills dcid->token it with 0. |token| + * |token| is NULL, the function fills dcid->token with 0. |token| * must be NGTCP2_STATELESS_RESET_TOKENLEN bytes long. */ void ngtcp2_dcid_init(ngtcp2_dcid *dcid, uint64_t seq, const ngtcp2_cid *cid, @@ -131,14 +131,14 @@ void ngtcp2_dcid_init(ngtcp2_dcid *dcid, uint64_t seq, const ngtcp2_cid *cid, /* * ngtcp2_dcid_set_token sets |token| to |dcid|. |token| must not be - * NULL and must be NGTCP2_STATELESS_RESET_TOKENLEN bytes long. + * NULL, and must be NGTCP2_STATELESS_RESET_TOKENLEN bytes long. */ void ngtcp2_dcid_set_token(ngtcp2_dcid *dcid, const uint8_t *token); /* * ngtcp2_dcid_set_path sets |path| to |dcid|. It sets - * max_udp_payload_size to the minimum UDP payload size supported - * by the IP protocol version. + * max_udp_payload_size to the minimum UDP datagram payload size + * supported by the IP protocol version. */ void ngtcp2_dcid_set_path(ngtcp2_dcid *dcid, const ngtcp2_path *path); @@ -149,7 +149,7 @@ void ngtcp2_dcid_copy(ngtcp2_dcid *dest, const ngtcp2_dcid *src); /* * ngtcp2_dcid_copy_cid_token behaves like ngtcp2_dcid_copy, but it - * only copies cid, seq, and path. + * only copies cid, seq, and token. */ void ngtcp2_dcid_copy_cid_token(ngtcp2_dcid *dest, const ngtcp2_dcid *src); @@ -157,14 +157,15 @@ void ngtcp2_dcid_copy_cid_token(ngtcp2_dcid *dest, const ngtcp2_dcid *src); * ngtcp2_dcid_verify_uniqueness verifies uniqueness of (|seq|, |cid|, * |token|) tuple against |dcid|. */ -int ngtcp2_dcid_verify_uniqueness(ngtcp2_dcid *dcid, uint64_t seq, +int ngtcp2_dcid_verify_uniqueness(const ngtcp2_dcid *dcid, uint64_t seq, const ngtcp2_cid *cid, const uint8_t *token); /* * ngtcp2_dcid_verify_stateless_reset_token verifies stateless reset - * token |token| against the one included in |dcid|. This function - * returns 0 if the verification succeeds, or one of the following - * negative error codes: + * token |token| against the one included in |dcid|. Tokens are + * compared in constant time. This function returns 0 if the + * verification succeeds, or one of the following negative error + * codes: * * NGTCP2_ERR_INVALID_ARGUMENT * Tokens do not match; or |dcid| does not contain a token. @@ -172,4 +173,4 @@ int ngtcp2_dcid_verify_uniqueness(ngtcp2_dcid *dcid, uint64_t seq, int ngtcp2_dcid_verify_stateless_reset_token(const ngtcp2_dcid *dcid, const uint8_t *token); -#endif /* NGTCP2_CID_H */ +#endif /* !defined(NGTCP2_CID_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c index c8caf47ea76232..0f67ac09bf33b9 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -37,7 +37,8 @@ #include "ngtcp2_rcvry.h" #include "ngtcp2_unreachable.h" #include "ngtcp2_net.h" -#include "ngtcp2_conversion.h" +#include "ngtcp2_transport_params.h" +#include "ngtcp2_settings.h" #include "ngtcp2_tstamp.h" #include "ngtcp2_frame_chain.h" @@ -50,8 +51,12 @@ /* NGTCP2_MIN_COALESCED_PAYLOADLEN is the minimum length of QUIC packet payload that should be coalesced to a long packet. */ #define NGTCP2_MIN_COALESCED_PAYLOADLEN 128 +/* NGTCP2_MAX_ACK_PER_PKT is the maximum number of ACK frame per an + incoming QUIC packet to process. ACK frames that exceed this limit + are not processed. */ +#define NGTCP2_MAX_ACK_PER_PKT 1 -ngtcp2_objalloc_def(strm, ngtcp2_strm, oplent); +ngtcp2_objalloc_def(strm, ngtcp2_strm, oplent) /* * conn_local_stream returns nonzero if |stream_id| indicates that it @@ -323,8 +328,8 @@ static int conn_call_select_preferred_addr(ngtcp2_conn *conn, assert(conn->remote.transport_params->preferred_addr_present); rv = conn->callbacks.select_preferred_addr( - conn, dest, &conn->remote.transport_params->preferred_addr, - conn->user_data); + conn, dest, &conn->remote.transport_params->preferred_addr, + conn->user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -377,7 +382,7 @@ static int conn_call_extend_max_stream_data(ngtcp2_conn *conn, } rv = conn->callbacks.extend_max_stream_data( - conn, stream_id, datalen, conn->user_data, strm->stream_user_data); + conn, stream_id, datalen, conn->user_data, strm->stream_user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -395,9 +400,9 @@ static int conn_call_dcid_status(ngtcp2_conn *conn, } rv = conn->callbacks.dcid_status( - conn, type, dcid->seq, &dcid->cid, - (dcid->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) ? dcid->token : NULL, - conn->user_data); + conn, type, dcid->seq, &dcid->cid, + (dcid->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) ? dcid->token : NULL, + conn->user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -413,7 +418,7 @@ static int conn_call_activate_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid) { static int conn_call_deactivate_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid) { return conn_call_dcid_status( - conn, NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE, dcid); + conn, NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE, dcid); } static int conn_call_stream_stop_sending(ngtcp2_conn *conn, int64_t stream_id, @@ -587,8 +592,8 @@ static int conn_call_recv_datagram(ngtcp2_conn *conn, flags |= NGTCP2_DATAGRAM_FLAG_0RTT; } - rv = conn->callbacks.recv_datagram(conn, flags, data, datalen, - conn->user_data); + rv = + conn->callbacks.recv_datagram(conn, flags, data, datalen, conn->user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -607,8 +612,8 @@ conn_call_update_key(ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, assert(conn->callbacks.update_key); rv = conn->callbacks.update_key( - conn, rx_secret, tx_secret, rx_aead_ctx, rx_iv, tx_aead_ctx, tx_iv, - current_rx_secret, current_tx_secret, secretlen, conn->user_data); + conn, rx_secret, tx_secret, rx_aead_ctx, rx_iv, tx_aead_ctx, tx_iv, + current_rx_secret, current_tx_secret, secretlen, conn->user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -623,7 +628,7 @@ static int conn_call_version_negotiation(ngtcp2_conn *conn, uint32_t version, assert(conn->callbacks.version_negotiation); rv = - conn->callbacks.version_negotiation(conn, version, dcid, conn->user_data); + conn->callbacks.version_negotiation(conn, version, dcid, conn->user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -663,13 +668,11 @@ static int conn_call_recv_tx_key(ngtcp2_conn *conn, return 0; } -static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, - ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num, - ngtcp2_log *log, ngtcp2_qlog *qlog, - ngtcp2_objalloc *rtb_entry_objalloc, - ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { - int rv; - +static void pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, + ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num, + ngtcp2_log *log, ngtcp2_qlog *qlog, + ngtcp2_objalloc *rtb_entry_objalloc, + ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { memset(pktns, 0, sizeof(*pktns)); ngtcp2_gaptr_init(&pktns->rx.pngap, mem); @@ -678,25 +681,15 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; pktns->rx.max_pkt_num = -1; pktns->rx.max_ack_eliciting_pkt_num = -1; + pktns->id = pktns_id; - rv = ngtcp2_acktr_init(&pktns->acktr, log, mem); - if (rv != 0) { - goto fail_acktr_init; - } + ngtcp2_acktr_init(&pktns->acktr, log, mem); ngtcp2_strm_init(&pktns->crypto.strm, 0, NGTCP2_STRM_FLAG_NONE, 0, 0, NULL, frc_objalloc, mem); - ngtcp2_rtb_init(&pktns->rtb, pktns_id, &pktns->crypto.strm, rst, cc, - initial_pkt_num, log, qlog, rtb_entry_objalloc, frc_objalloc, - mem); - - return 0; - -fail_acktr_init: - ngtcp2_gaptr_free(&pktns->rx.pngap); - - return rv; + ngtcp2_rtb_init(&pktns->rtb, rst, cc, initial_pkt_num, log, qlog, + rtb_entry_objalloc, frc_objalloc, mem); } static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id, @@ -704,20 +697,15 @@ static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id, ngtcp2_log *log, ngtcp2_qlog *qlog, ngtcp2_objalloc *rtb_entry_objalloc, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { - int rv; - *ppktns = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pktns)); if (*ppktns == NULL) { return NGTCP2_ERR_NOMEM; } - rv = pktns_init(*ppktns, pktns_id, rst, cc, initial_pkt_num, log, qlog, - rtb_entry_objalloc, frc_objalloc, mem); - if (rv != 0) { - ngtcp2_mem_free(mem, *ppktns); - } + pktns_init(*ppktns, pktns_id, rst, cc, initial_pkt_num, log, qlog, + rtb_entry_objalloc, frc_objalloc, mem); - return rv; + return 0; } static int cycle_less(const ngtcp2_pq_entry *lhs, const ngtcp2_pq_entry *rhs) { @@ -783,6 +771,8 @@ static int cid_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { return ngtcp2_cid_less(lhs, rhs); } +ngtcp2_ksl_search_def(cid_less, cid_less) + static int retired_ts_less(const ngtcp2_pq_entry *lhs, const ngtcp2_pq_entry *rhs) { const ngtcp2_scid *a = ngtcp2_struct_of(lhs, ngtcp2_scid, pe); @@ -803,8 +793,9 @@ static void conn_reset_conn_stat_cc(ngtcp2_conn *conn, cstat->first_rtt_sample_ts = UINT64_MAX; cstat->pto_count = 0; cstat->loss_detection_timer = UINT64_MAX; - cstat->cwnd = - ngtcp2_cc_compute_initcwnd(conn->local.settings.max_tx_udp_payload_size); + cstat->max_tx_udp_payload_size = + ngtcp2_conn_get_path_max_tx_udp_payload_size(conn); + cstat->cwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size); cstat->ssthresh = UINT64_MAX; cstat->congestion_recovery_start_ts = UINT64_MAX; cstat->bytes_in_flight = 0; @@ -847,7 +838,7 @@ static void delete_scid(ngtcp2_ksl *scids, const ngtcp2_mem *mem) { static ngtcp2_duration compute_pto(ngtcp2_duration smoothed_rtt, ngtcp2_duration rttvar, ngtcp2_duration max_ack_delay) { - ngtcp2_duration var = ngtcp2_max(4 * rttvar, NGTCP2_GRANULARITY); + ngtcp2_duration var = ngtcp2_max_uint64(4 * rttvar, NGTCP2_GRANULARITY); return smoothed_rtt + var + max_ack_delay; } @@ -859,7 +850,7 @@ static ngtcp2_duration conn_compute_initial_pto(ngtcp2_conn *conn, ngtcp2_duration initial_rtt = conn->local.settings.initial_rtt; ngtcp2_duration max_ack_delay; - if (pktns->rtb.pktns_id == NGTCP2_PKTNS_ID_APPLICATION && + if (pktns->id == NGTCP2_PKTNS_ID_APPLICATION && conn->remote.transport_params) { max_ack_delay = conn->remote.transport_params->max_ack_delay; } else { @@ -876,7 +867,7 @@ static ngtcp2_duration conn_compute_pto(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat = &conn->cstat; ngtcp2_duration max_ack_delay; - if (pktns->rtb.pktns_id == NGTCP2_PKTNS_ID_APPLICATION && + if (pktns->id == NGTCP2_PKTNS_ID_APPLICATION && conn->remote.transport_params) { max_ack_delay = conn->remote.transport_params->max_ack_delay; } else { @@ -898,7 +889,7 @@ static ngtcp2_duration conn_compute_pv_timeout_pto(ngtcp2_conn *conn, ngtcp2_duration pto) { ngtcp2_duration initial_pto = conn_compute_initial_pto(conn, &conn->pktns); - return 3 * ngtcp2_max(pto, initial_pto); + return 3 * ngtcp2_max_uint64(pto, initial_pto); } /* @@ -1007,28 +998,15 @@ static void conn_reset_ecn_validation_state(ngtcp2_conn *conn) { static uint8_t server_default_available_versions[] = {0, 0, 0, 1}; /* - * available_versions_new allocates new buffer, and writes |versions| - * of length |versionslen| in network byte order, suitable for sending - * in available_versions field of version_information QUIC transport - * parameter. The pointer to the allocated buffer is assigned to - * |*pbuf|. - * - * This function returns 0 if it succeeds, or one of the negative - * error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. + * available_versions_init writes |versions| of length |versionslen| + * in network byte order to the buffer pointed by |buf|, suitable for + * sending in available_versions field of version_information QUIC + * transport parameter. This function returns the pointer to the one + * beyond the last byte written. */ -static int available_versions_new(uint8_t **pbuf, const uint32_t *versions, - size_t versionslen, const ngtcp2_mem *mem) { +static void *available_versions_init(void *buf, const uint32_t *versions, + size_t versionslen) { size_t i; - uint8_t *buf = ngtcp2_mem_malloc(mem, sizeof(uint32_t) * versionslen); - - if (buf == NULL) { - return NGTCP2_ERR_NOMEM; - } - - *pbuf = buf; for (i = 0; i < versionslen; ++i) { buf = ngtcp2_put_uint32be(buf, versions[i]); @@ -1055,6 +1033,16 @@ conn_set_local_transport_params(ngtcp2_conn *conn, p->version_info_present = 1; } +static size_t buflen_align(size_t buflen) { + return (buflen + 0x7) & (size_t)~0x7; +} + +static void *buf_align(void *buf) { + return (void *)((uintptr_t)((uint8_t *)buf + 0x7) & (uintptr_t)~0x7); +} + +static void *buf_advance(void *buf, size_t n) { return (uint8_t *)buf + n; } + static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, const ngtcp2_path *path, uint32_t client_chosen_version, int callbacks_version, @@ -1065,16 +1053,20 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_mem *mem, void *user_data, int server) { int rv; ngtcp2_scid *scident; - uint8_t *buf; + void *buf, *tokenbuf; + size_t buflen; uint8_t fixed_bit_byte; size_t i; uint32_t *preferred_versions; + ngtcp2_settings settingsbuf; ngtcp2_transport_params paramsbuf; (void)callbacks_version; (void)settings_version; + settings = + ngtcp2_settings_convert_to_latest(&settingsbuf, settings_version, settings); params = ngtcp2_transport_params_convert_to_latest( - ¶msbuf, transport_params_version, params); + ¶msbuf, transport_params_version, params); assert(settings->max_window <= NGTCP2_MAX_VARINT); assert(settings->max_stream_window <= NGTCP2_MAX_VARINT); @@ -1111,21 +1103,59 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, assert(callbacks->get_path_challenge_data); assert(!server || !ngtcp2_is_reserved_version(client_chosen_version)); + for (i = 0; i < settings->pmtud_probeslen; ++i) { + assert(settings->pmtud_probes[i] > NGTCP2_MAX_UDP_PAYLOAD_SIZE); + } + if (mem == NULL) { mem = ngtcp2_mem_default(); } - *pconn = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_conn)); - if (*pconn == NULL) { - rv = NGTCP2_ERR_NOMEM; - goto fail_conn; + buflen = sizeof(ngtcp2_conn); + if (settings->qlog_write) { + buflen = buflen_align(buflen); + buflen += NGTCP2_QLOG_BUFLEN; + } + + if (settings->pmtud_probeslen) { + buflen = buflen_align(buflen); + buflen += sizeof(settings->pmtud_probes[0]) * settings->pmtud_probeslen; } + if (settings->preferred_versionslen) { + buflen = buflen_align(buflen); + buflen += + sizeof(settings->preferred_versions[0]) * settings->preferred_versionslen; + } + + if (settings->available_versionslen) { + buflen = buflen_align(buflen); + buflen += + sizeof(settings->available_versions[0]) * settings->available_versionslen; + } else if (server) { + if (settings->preferred_versionslen) { + buflen = buflen_align(buflen); + buflen += sizeof(settings->preferred_versions[0]) * + settings->preferred_versionslen; + } + } else if (!ngtcp2_is_reserved_version(client_chosen_version)) { + buflen = buflen_align(buflen); + buflen += sizeof(client_chosen_version); + } + + buf = ngtcp2_mem_calloc(mem, 1, buflen); + if (buf == NULL) { + return NGTCP2_ERR_NOMEM; + } + + *pconn = buf; + buf = buf_advance(buf, sizeof(ngtcp2_conn)); + (*pconn)->server = server; - ngtcp2_objalloc_frame_chain_init(&(*pconn)->frc_objalloc, 64, mem); - ngtcp2_objalloc_rtb_entry_init(&(*pconn)->rtb_entry_objalloc, 64, mem); - ngtcp2_objalloc_strm_init(&(*pconn)->strm_objalloc, 64, mem); + ngtcp2_objalloc_frame_chain_init(&(*pconn)->frc_objalloc, 16, mem); + ngtcp2_objalloc_rtb_entry_init(&(*pconn)->rtb_entry_objalloc, 16, mem); + ngtcp2_objalloc_strm_init(&(*pconn)->strm_objalloc, 16, mem); ngtcp2_static_ringbuf_dcid_bound_init(&(*pconn)->dcid.bound); @@ -1135,7 +1165,8 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_gaptr_init(&(*pconn)->dcid.seqgap, mem); - ngtcp2_ksl_init(&(*pconn)->scid.set, cid_less, sizeof(ngtcp2_cid), mem); + ngtcp2_ksl_init(&(*pconn)->scid.set, cid_less, ksl_cid_less_search, + sizeof(ngtcp2_cid), mem); ngtcp2_pq_init(&(*pconn)->scid.used, retired_ts_less, mem); @@ -1143,9 +1174,9 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_pq_init(&(*pconn)->tx.strmq, cycle_less, mem); - ngtcp2_idtr_init(&(*pconn)->remote.bidi.idtr, !server, mem); + ngtcp2_idtr_init(&(*pconn)->remote.bidi.idtr, mem); - ngtcp2_idtr_init(&(*pconn)->remote.uni.idtr, !server, mem); + ngtcp2_idtr_init(&(*pconn)->remote.uni.idtr, mem); ngtcp2_static_ringbuf_path_challenge_init(&(*pconn)->rx.path_challenge); @@ -1154,36 +1185,46 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_qlog_init(&(*pconn)->qlog, settings->qlog_write, settings->initial_ts, user_data); if ((*pconn)->qlog.write) { - buf = ngtcp2_mem_malloc(mem, NGTCP2_QLOG_BUFLEN); - if (buf == NULL) { - rv = NGTCP2_ERR_NOMEM; - goto fail_qlog_buf; - } + buf = buf_align(buf); ngtcp2_buf_init(&(*pconn)->qlog.buf, buf, NGTCP2_QLOG_BUFLEN); + buf = buf_advance(buf, NGTCP2_QLOG_BUFLEN); } (*pconn)->local.settings = *settings; if (settings->tokenlen) { - buf = ngtcp2_mem_malloc(mem, settings->tokenlen); - if (buf == NULL) { + tokenbuf = ngtcp2_mem_malloc(mem, settings->tokenlen); + if (tokenbuf == NULL) { rv = NGTCP2_ERR_NOMEM; goto fail_token; } - memcpy(buf, settings->token, settings->tokenlen); - (*pconn)->local.settings.token = buf; + memcpy(tokenbuf, settings->token, settings->tokenlen); + (*pconn)->local.settings.token = tokenbuf; } else { (*pconn)->local.settings.token = NULL; } + if (settings->pmtud_probeslen) { + (*pconn)->local.settings.pmtud_probes = buf_align(buf); + buf = ngtcp2_cpymem( + (uint16_t *)(*pconn)->local.settings.pmtud_probes, settings->pmtud_probes, + sizeof(settings->pmtud_probes[0]) * settings->pmtud_probeslen); + } + if (!(*pconn)->local.settings.original_version) { (*pconn)->local.settings.original_version = client_chosen_version; } + ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL); + ngtcp2_dcid_set_path(&(*pconn)->dcid.current, path); + + rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1); + if (rv != 0) { + goto fail_seqgap_push; + } + conn_reset_conn_stat(*pconn, &(*pconn)->cstat); (*pconn)->cstat.initial_rtt = settings->initial_rtt; - (*pconn)->cstat.max_tx_udp_payload_size = - (*pconn)->local.settings.max_tx_udp_payload_size; ngtcp2_rst_init(&(*pconn)->rst); @@ -1195,7 +1236,7 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, break; case NGTCP2_CC_ALGO_CUBIC: - ngtcp2_cc_cubic_init(&(*pconn)->cubic, &(*pconn)->log); + ngtcp2_cc_cubic_init(&(*pconn)->cubic, &(*pconn)->log, &(*pconn)->rst); break; case NGTCP2_CC_ALGO_BBR: @@ -1224,13 +1265,10 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, goto fail_hs_pktns_init; } - rv = pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APPLICATION, &(*pconn)->rst, - &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log, - &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc, - &(*pconn)->frc_objalloc, mem); - if (rv != 0) { - goto fail_pktns_init; - } + pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APPLICATION, &(*pconn)->rst, + &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log, + &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc, + &(*pconn)->frc_objalloc, mem); scident = ngtcp2_mem_malloc(mem, sizeof(*scident)); if (scident == NULL) { @@ -1249,14 +1287,6 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, scident = NULL; - ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL); - ngtcp2_dcid_set_path(&(*pconn)->dcid.current, path); - - rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1); - if (rv != 0) { - goto fail_seqgap_push; - } - if (settings->preferred_versionslen) { if (!server && !ngtcp2_is_reserved_version(client_chosen_version)) { for (i = 0; i < settings->preferred_versionslen; ++i) { @@ -1268,12 +1298,9 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, assert(i < settings->preferred_versionslen); } - preferred_versions = ngtcp2_mem_malloc( - mem, sizeof(uint32_t) * settings->preferred_versionslen); - if (preferred_versions == NULL) { - rv = NGTCP2_ERR_NOMEM; - goto fail_preferred_versions; - } + preferred_versions = buf_align(buf); + buf = buf_advance(preferred_versions, sizeof(preferred_versions[0]) * + settings->preferred_versionslen); for (i = 0; i < settings->preferred_versionslen; ++i) { assert(ngtcp2_is_supported_version(settings->preferred_versions[i])); @@ -1304,39 +1331,33 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_is_supported_version(settings->available_versions[i])); } - rv = available_versions_new(&buf, settings->available_versions, - settings->available_versionslen, mem); - if (rv != 0) { - goto fail_available_versions; - } - - (*pconn)->vneg.available_versions = buf; + (*pconn)->vneg.available_versions = buf_align(buf); (*pconn)->vneg.available_versionslen = - sizeof(uint32_t) * settings->available_versionslen; + sizeof(uint32_t) * settings->available_versionslen; + + buf = available_versions_init((*pconn)->vneg.available_versions, + settings->available_versions, + settings->available_versionslen); } else if (server) { if (settings->preferred_versionslen) { - rv = available_versions_new(&buf, settings->preferred_versions, - settings->preferred_versionslen, mem); - if (rv != 0) { - goto fail_available_versions; - } - - (*pconn)->vneg.available_versions = buf; + (*pconn)->vneg.available_versions = buf_align(buf); (*pconn)->vneg.available_versionslen = - sizeof(uint32_t) * settings->preferred_versionslen; + sizeof(uint32_t) * settings->preferred_versionslen; + + buf = available_versions_init((*pconn)->vneg.available_versions, + settings->preferred_versions, + settings->preferred_versionslen); } else { (*pconn)->vneg.available_versions = server_default_available_versions; (*pconn)->vneg.available_versionslen = - sizeof(server_default_available_versions); + sizeof(server_default_available_versions); } - } else if (!server && !ngtcp2_is_reserved_version(client_chosen_version)) { - rv = available_versions_new(&buf, &client_chosen_version, 1, mem); - if (rv != 0) { - goto fail_available_versions; - } - - (*pconn)->vneg.available_versions = buf; + } else if (!ngtcp2_is_reserved_version(client_chosen_version)) { + (*pconn)->vneg.available_versions = buf_align(buf); (*pconn)->vneg.available_versionslen = sizeof(uint32_t); + + buf = available_versions_init((*pconn)->vneg.available_versions, + &client_chosen_version, 1); } (*pconn)->local.settings.available_versions = NULL; @@ -1367,54 +1388,39 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, conn_reset_ecn_validation_state(*pconn); - ngtcp2_qlog_start( - &(*pconn)->qlog, - server ? ((*pconn)->local.transport_params.retry_scid_present - ? &(*pconn)->local.transport_params.retry_scid - : &(*pconn)->local.transport_params.original_dcid) - : dcid, - server); + ngtcp2_qlog_start(&(*pconn)->qlog, + server + ? ((*pconn)->local.transport_params.retry_scid_present + ? &(*pconn)->local.transport_params.retry_scid + : &(*pconn)->local.transport_params.original_dcid) + : dcid, + server); return 0; -fail_available_versions: - ngtcp2_mem_free(mem, (*pconn)->vneg.preferred_versions); -fail_preferred_versions: -fail_seqgap_push: fail_scid_set_insert: ngtcp2_mem_free(mem, scident); fail_scident: - pktns_free(&(*pconn)->pktns, mem); -fail_pktns_init: pktns_del((*pconn)->hs_pktns, mem); fail_hs_pktns_init: pktns_del((*pconn)->in_pktns, mem); fail_in_pktns_init: + ngtcp2_gaptr_free(&(*pconn)->dcid.seqgap); +fail_seqgap_push: ngtcp2_mem_free(mem, (uint8_t *)(*pconn)->local.settings.token); fail_token: - ngtcp2_mem_free(mem, (*pconn)->qlog.buf.begin); -fail_qlog_buf: - ngtcp2_idtr_free(&(*pconn)->remote.uni.idtr); - ngtcp2_idtr_free(&(*pconn)->remote.bidi.idtr); - ngtcp2_map_free(&(*pconn)->strms); - delete_scid(&(*pconn)->scid.set, mem); - ngtcp2_ksl_free(&(*pconn)->scid.set); - ngtcp2_gaptr_free(&(*pconn)->dcid.seqgap); - ngtcp2_objalloc_free(&(*pconn)->strm_objalloc); - ngtcp2_objalloc_free(&(*pconn)->rtb_entry_objalloc); - ngtcp2_objalloc_free(&(*pconn)->frc_objalloc); ngtcp2_mem_free(mem, *pconn); -fail_conn: + return rv; } int ngtcp2_conn_client_new_versioned( - ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, - const ngtcp2_path *path, uint32_t client_chosen_version, - int callbacks_version, const ngtcp2_callbacks *callbacks, - int settings_version, const ngtcp2_settings *settings, - int transport_params_version, const ngtcp2_transport_params *params, - const ngtcp2_mem *mem, void *user_data) { + ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, + const ngtcp2_path *path, uint32_t client_chosen_version, + int callbacks_version, const ngtcp2_callbacks *callbacks, + int settings_version, const ngtcp2_settings *settings, + int transport_params_version, const ngtcp2_transport_params *params, + const ngtcp2_mem *mem, void *user_data) { int rv; rv = conn_new(pconn, dcid, scid, path, client_chosen_version, @@ -1438,12 +1444,12 @@ int ngtcp2_conn_client_new_versioned( } int ngtcp2_conn_server_new_versioned( - ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, - const ngtcp2_path *path, uint32_t client_chosen_version, - int callbacks_version, const ngtcp2_callbacks *callbacks, - int settings_version, const ngtcp2_settings *settings, - int transport_params_version, const ngtcp2_transport_params *params, - const ngtcp2_mem *mem, void *user_data) { + ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, + const ngtcp2_path *path, uint32_t client_chosen_version, + int callbacks_version, const ngtcp2_callbacks *callbacks, + int settings_version, const ngtcp2_settings *settings, + int transport_params_version, const ngtcp2_transport_params *params, + const ngtcp2_mem *mem, void *user_data) { int rv; rv = conn_new(pconn, dcid, scid, path, client_chosen_version, @@ -1471,8 +1477,8 @@ int ngtcp2_conn_server_new_versioned( * credits are considered. */ static uint64_t conn_fc_credits(ngtcp2_conn *conn, ngtcp2_strm *strm) { - return ngtcp2_min(strm->tx.max_offset - strm->tx.offset, - conn->tx.max_offset - conn->tx.offset); + return ngtcp2_min_uint64(strm->tx.max_offset - strm->tx.offset, + conn->tx.max_offset - conn->tx.offset); } /* @@ -1483,7 +1489,7 @@ static uint64_t conn_fc_credits(ngtcp2_conn *conn, ngtcp2_strm *strm) { static uint64_t conn_enforce_flow_control(ngtcp2_conn *conn, ngtcp2_strm *strm, uint64_t len) { uint64_t fc_credits = conn_fc_credits(conn, strm); - return ngtcp2_min(len, fc_credits); + return ngtcp2_min_uint64(len, fc_credits); } static int delete_strms_each(void *data, void *ptr) { @@ -1525,15 +1531,15 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { if (conn->crypto.key_update.old_rx_ckm) { conn_call_delete_crypto_aead_ctx( - conn, &conn->crypto.key_update.old_rx_ckm->aead_ctx); + conn, &conn->crypto.key_update.old_rx_ckm->aead_ctx); } if (conn->crypto.key_update.new_rx_ckm) { conn_call_delete_crypto_aead_ctx( - conn, &conn->crypto.key_update.new_rx_ckm->aead_ctx); + conn, &conn->crypto.key_update.new_rx_ckm->aead_ctx); } if (conn->crypto.key_update.new_tx_ckm) { conn_call_delete_crypto_aead_ctx( - conn, &conn->crypto.key_update.new_tx_ckm->aead_ctx); + conn, &conn->crypto.key_update.new_tx_ckm->aead_ctx); } if (conn->pktns.crypto.rx.ckm) { @@ -1551,26 +1557,26 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { if (conn->hs_pktns) { if (conn->hs_pktns->crypto.rx.ckm) { conn_call_delete_crypto_aead_ctx( - conn, &conn->hs_pktns->crypto.rx.ckm->aead_ctx); + conn, &conn->hs_pktns->crypto.rx.ckm->aead_ctx); } conn_call_delete_crypto_cipher_ctx(conn, &conn->hs_pktns->crypto.rx.hp_ctx); if (conn->hs_pktns->crypto.tx.ckm) { conn_call_delete_crypto_aead_ctx( - conn, &conn->hs_pktns->crypto.tx.ckm->aead_ctx); + conn, &conn->hs_pktns->crypto.tx.ckm->aead_ctx); } conn_call_delete_crypto_cipher_ctx(conn, &conn->hs_pktns->crypto.tx.hp_ctx); } if (conn->in_pktns) { if (conn->in_pktns->crypto.rx.ckm) { conn_call_delete_crypto_aead_ctx( - conn, &conn->in_pktns->crypto.rx.ckm->aead_ctx); + conn, &conn->in_pktns->crypto.rx.ckm->aead_ctx); } conn_call_delete_crypto_cipher_ctx(conn, &conn->in_pktns->crypto.rx.hp_ctx); if (conn->in_pktns->crypto.tx.ckm) { conn_call_delete_crypto_aead_ctx( - conn, &conn->in_pktns->crypto.tx.ckm->aead_ctx); + conn, &conn->in_pktns->crypto.tx.ckm->aead_ctx); } conn_call_delete_crypto_cipher_ctx(conn, &conn->in_pktns->crypto.tx.hp_ctx); } @@ -1582,11 +1588,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { conn_vneg_crypto_free(conn); - ngtcp2_mem_free(conn->mem, conn->vneg.preferred_versions); - if (conn->vneg.available_versions != server_default_available_versions) { - ngtcp2_mem_free(conn->mem, conn->vneg.available_versions); - } - ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_buf.base); ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_hp_buf.base); ngtcp2_mem_free(conn->mem, (uint8_t *)conn->local.settings.token); @@ -1600,8 +1601,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { pktns_del(conn->hs_pktns, conn->mem); pktns_del(conn->in_pktns, conn->mem); - ngtcp2_mem_free(conn->mem, conn->qlog.buf.begin); - ngtcp2_pmtud_del(conn->pmtud); ngtcp2_pv_del(conn->pv); @@ -1611,7 +1610,7 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { ngtcp2_idtr_free(&conn->remote.bidi.idtr); ngtcp2_mem_free(conn->mem, conn->tx.ack); ngtcp2_pq_free(&conn->tx.strmq); - ngtcp2_map_each_free(&conn->strms, delete_strms_each, (void *)conn); + ngtcp2_map_each(&conn->strms, delete_strms_each, (void *)conn); ngtcp2_map_free(&conn->strms); ngtcp2_pq_free(&conn->scid.used); @@ -1665,8 +1664,9 @@ static int conn_ensure_ack_ranges(ngtcp2_conn *conn, size_t n) { * ACK. */ static ngtcp2_duration conn_compute_ack_delay(ngtcp2_conn *conn) { - return ngtcp2_min(conn->local.transport_params.max_ack_delay, - conn->cstat.smoothed_rtt / 8); + return ngtcp2_min_uint64( + conn->local.transport_params.max_ack_delay, + ngtcp2_max_uint64(conn->cstat.smoothed_rtt / 8, NGTCP2_NANOSECONDS)); } int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, @@ -1702,8 +1702,8 @@ int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, if (conn->tx.ack == NULL) { conn->tx.ack = ngtcp2_mem_malloc( - conn->mem, - sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_range) * initial_max_ack_ranges); + conn->mem, + sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_range) * initial_max_ack_ranges); if (conn->tx.ack == NULL) { return NGTCP2_ERR_NOMEM; } @@ -1844,8 +1844,9 @@ static int conn_ppe_write_frame(ngtcp2_conn *conn, ngtcp2_ppe *ppe, * NGTCP2_ERR_NOMEM * Out of memory */ -static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_rtb *rtb, +static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_rtb_entry *ent) { + ngtcp2_rtb *rtb = &pktns->rtb; int rv; /* This function implements OnPacketSent, but it handles only @@ -1856,7 +1857,7 @@ static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_rtb *rtb, } if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { - conn->cstat.last_tx_pkt_ts[rtb->pktns_id] = ent->ts; + conn->cstat.last_tx_pkt_ts[pktns->id] = ent->ts; } ngtcp2_conn_set_loss_detection_timer(conn, ent->ts); @@ -1898,8 +1899,8 @@ static size_t pktns_select_pkt_numlen(ngtcp2_pktns *pktns) { */ static uint64_t conn_get_cwnd(ngtcp2_conn *conn) { return conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) - ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_tx_udp_payload_size) - : conn->cstat.cwnd; + ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_tx_udp_payload_size) + : conn->cstat.cwnd; } /* @@ -1947,7 +1948,7 @@ static uint64_t conn_retry_early_payloadlen(ngtcp2_conn *conn) { /* Take the min because in conn_should_pad_pkt we take max in order to deal with unbreakable DATAGRAM. */ - return ngtcp2_min(len, NGTCP2_MIN_COALESCED_PAYLOADLEN); + return ngtcp2_min_uint64(len, NGTCP2_MIN_COALESCED_PAYLOADLEN); } return 0; @@ -2021,12 +2022,13 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, return 0; } - if (conn->hs_pktns->crypto.tx.ckm && - (conn->hs_pktns->rtb.probe_pkt_left || - !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm) || - !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) { - /* If we have something to send in Handshake packet, then add - PADDING in Handshake packet. */ + if ((conn->hs_pktns->crypto.tx.ckm && + (conn->hs_pktns->rtb.probe_pkt_left || + !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm) || + !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) || + conn->pktns.crypto.tx.ckm) { + /* If we have something to send in Handshake or 1RTT packet, + then add PADDING in that packet. */ min_payloadlen = NGTCP2_MIN_COALESCED_PAYLOADLEN; } else { return 1; @@ -2044,7 +2046,7 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, PADDING in that packet. Take maximum in case that write_datalen includes DATAGRAM which cannot be split. */ min_payloadlen = - ngtcp2_max(write_datalen, NGTCP2_MIN_COALESCED_PAYLOADLEN); + ngtcp2_max_uint64(write_datalen, NGTCP2_MIN_COALESCED_PAYLOADLEN); } else { return 1; } @@ -2067,8 +2069,8 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, return left < /* TODO Assuming that pkt_num is encoded in 1 byte. */ NGTCP2_MIN_LONG_HEADERLEN + conn->dcid.current.cid.datalen + - conn->oscid.datalen + NGTCP2_PKT_LENGTHLEN - 1 + min_payloadlen + - NGTCP2_MAX_AEAD_OVERHEAD; + conn->oscid.datalen + NGTCP2_PKT_LENGTHLEN - 1 + min_payloadlen + + NGTCP2_MAX_AEAD_OVERHEAD; } static void conn_restart_timer_on_write(ngtcp2_conn *conn, ngtcp2_tstamp ts) { @@ -2189,15 +2191,18 @@ static uint8_t conn_pkt_flags_long(ngtcp2_conn *conn) { static uint8_t conn_pkt_flags_short(ngtcp2_conn *conn) { return (uint8_t)(conn_pkt_flags(conn) | ((conn->pktns.crypto.tx.ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE) - ? NGTCP2_PKT_FLAG_KEY_PHASE - : NGTCP2_PKT_FLAG_NONE)); + ? NGTCP2_PKT_FLAG_KEY_PHASE + : NGTCP2_PKT_FLAG_NONE)); } +static size_t conn_min_pktlen(ngtcp2_conn *conn); + /* * conn_write_handshake_pkt writes handshake packet in the buffer - * pointed by |dest| whose length is |destlen|. |type| specifies long - * packet type. It should be either NGTCP2_PKT_INITIAL or - * NGTCP2_PKT_HANDSHAKE_PKT. + * pointed by |dest| whose length is |destlen|. |dgram_offset| is the + * offset in UDP datagram payload where this QUIC packet is positioned + * at. |type| specifies long packet type. It should be either + * NGTCP2_PKT_INITIAL or NGTCP2_PKT_HANDSHAKE_PKT. * * |write_datalen| is the minimum length of application data ready to * send in subsequent 0RTT packet. @@ -2212,8 +2217,9 @@ static uint8_t conn_pkt_flags_short(ngtcp2_conn *conn) { */ static ngtcp2_ssize conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, - size_t destlen, uint8_t type, uint8_t flags, - uint64_t write_datalen, ngtcp2_tstamp ts) { + size_t destlen, size_t dgram_offset, uint8_t type, + uint8_t flags, uint64_t write_datalen, + ngtcp2_tstamp ts) { int rv; ngtcp2_ppe ppe; ngtcp2_pkt_hd hd; @@ -2228,6 +2234,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, uint16_t rtb_entry_flags = NGTCP2_RTB_ENTRY_FLAG_NONE; int require_padding = (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) != 0; int pkt_empty = 1; + int min_padded = 0; int padded = 0; int hd_logged = 0; uint64_t crypto_offset; @@ -2271,10 +2278,9 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, cc.encrypt = conn->callbacks.encrypt; cc.hp_mask = conn->callbacks.hp_mask; - ngtcp2_pkt_hd_init(&hd, conn_pkt_flags_long(conn), type, - &conn->dcid.current.cid, &conn->oscid, - pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), - version, 0); + ngtcp2_pkt_hd_init( + &hd, conn_pkt_flags_long(conn), type, &conn->dcid.current.cid, &conn->oscid, + pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), version, 0); if (!conn->server && type == NGTCP2_PKT_INITIAL && conn->local.settings.tokenlen) { @@ -2282,7 +2288,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, hd.tokenlen = conn->local.settings.tokenlen; } - ngtcp2_ppe_init(&ppe, dest, destlen, &cc); + ngtcp2_ppe_init(&ppe, dest, destlen, dgram_offset, &cc); rv = ngtcp2_ppe_encode_hd(&ppe, &hd); if (rv != 0) { @@ -2395,7 +2401,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, assert(rv == NGTCP2_ERR_NOBUF); } else { rtb_entry_flags |= - NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | NGTCP2_RTB_ENTRY_FLAG_PROBE; + NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | NGTCP2_RTB_ENTRY_FLAG_PROBE; pkt_empty = 0; } } @@ -2412,6 +2418,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, } else { rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_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; @@ -2429,20 +2436,24 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, /* If we cannot write another packet, then we need to add padding to Initial here. */ if (conn_should_pad_pkt( - conn, type, ngtcp2_ppe_left(&ppe), write_datalen, - (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) != 0, - require_padding)) { + conn, type, ngtcp2_ppe_left(&ppe), write_datalen, + (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) != 0, + require_padding)) { lfr.type = NGTCP2_FRAME_PADDING; - lfr.padding.len = ngtcp2_ppe_padding(&ppe); + lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); } else if (pkt_empty) { return 0; } else { lfr.type = NGTCP2_FRAME_PADDING; - lfr.padding.len = ngtcp2_ppe_padding_hp_sample(&ppe); + lfr.padding.len = ngtcp2_ppe_padding_size(&ppe, conn_min_pktlen(conn)); + min_padded = 1; } if (lfr.padding.len) { - padded = 1; + if (!min_padded || + (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { + padded = 1; + } ngtcp2_log_tx_fr(&conn->log, &hd, &lfr); ngtcp2_qlog_write_frame(&conn->qlog, &lfr); } @@ -2461,16 +2472,16 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, conn_handle_tx_ecn(conn, pi, &rtb_entry_flags, pktns, &hd, ts); } - rv = ngtcp2_rtb_entry_objalloc_new(&rtbent, &hd, frq, ts, (size_t)spktlen, - rtb_entry_flags, - &conn->rtb_entry_objalloc); + rv = + ngtcp2_rtb_entry_objalloc_new(&rtbent, &hd, frq, ts, (size_t)spktlen, + rtb_entry_flags, &conn->rtb_entry_objalloc); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_list_objalloc_del(frq, &conn->frc_objalloc, conn->mem); return rv; } - rv = conn_on_pkt_sent(conn, &pktns->rtb, rtbent); + rv = conn_on_pkt_sent(conn, pktns, rtbent); if (rv != 0) { ngtcp2_rtb_entry_objalloc_del(rtbent, &conn->rtb_entry_objalloc, &conn->frc_objalloc, conn->mem); @@ -2565,8 +2576,8 @@ static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } spktlen = ngtcp2_conn_write_single_frame_pkt( - conn, pi, dest, destlen, type, NGTCP2_WRITE_PKT_FLAG_NONE, - &conn->dcid.current.cid, ackfr, NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); + conn, pi, dest, destlen, type, NGTCP2_WRITE_PKT_FLAG_NONE, + &conn->dcid.current.cid, ackfr, NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); if (spktlen <= 0) { return spktlen; @@ -2588,8 +2599,8 @@ static void conn_discard_pktns(ngtcp2_conn *conn, ngtcp2_pktns **ppktns, conn->cstat.bytes_in_flight -= bytes_in_flight; conn->cstat.pto_count = 0; - conn->cstat.last_tx_pkt_ts[pktns->rtb.pktns_id] = UINT64_MAX; - conn->cstat.loss_time[pktns->rtb.pktns_id] = UINT64_MAX; + conn->cstat.last_tx_pkt_ts[pktns->id] = UINT64_MAX; + conn->cstat.loss_time[pktns->id] = UINT64_MAX; conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.rx.ckm->aead_ctx); conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.rx.hp_ctx); @@ -2602,11 +2613,7 @@ static void conn_discard_pktns(ngtcp2_conn *conn, ngtcp2_pktns **ppktns, ngtcp2_conn_set_loss_detection_timer(conn, ts); } -/* - * conn_discard_initial_state discards state for Initial packet number - * space. - */ -static void conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { +void ngtcp2_conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (!conn->in_pktns) { return; } @@ -2622,11 +2629,7 @@ static void conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { memset(&conn->vneg.tx, 0, sizeof(conn->vneg.tx)); } -/* - * conn_discard_handshake_state discards state for Handshake packet - * number space. - */ -static void conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { +void ngtcp2_conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (!conn->hs_pktns) { return; } @@ -2672,7 +2675,7 @@ static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn, to send ACK is give server RTT measurement early. */ if (conn->server && conn->in_pktns) { nwrite = - conn_write_ack_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, ts); + conn_write_ack_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, ts); if (nwrite < 0) { assert(nwrite != NGTCP2_ERR_NOBUF); return nwrite; @@ -2685,7 +2688,7 @@ static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn, if (conn->hs_pktns->crypto.tx.ckm) { nwrite = - conn_write_ack_pkt(conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, ts); + conn_write_ack_pkt(conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, ts); if (nwrite < 0) { assert(nwrite != NGTCP2_ERR_NOBUF); return nwrite; @@ -2694,7 +2697,7 @@ static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn, res += nwrite; if (!conn->server && nwrite) { - conn_discard_initial_state(conn, ts); + ngtcp2_conn_discard_initial_state(conn, ts); } } @@ -2725,9 +2728,9 @@ static ngtcp2_ssize conn_write_client_initial(ngtcp2_conn *conn, return rv; } - return conn_write_handshake_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, - NGTCP2_WRITE_PKT_FLAG_NONE, early_datalen, - ts); + return conn_write_handshake_pkt( + conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL, NGTCP2_WRITE_PKT_FLAG_NONE, + early_datalen, ts); } /* @@ -2807,11 +2810,11 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, conn->hs_pktns->rtb.probe_pkt_left)) { /* Discard Initial state here so that Handshake packet is not padded. */ - conn_discard_initial_state(conn, ts); + ngtcp2_conn_discard_initial_state(conn, ts); } else if (conn->in_pktns) { nwrite = - conn_write_handshake_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, - NGTCP2_WRITE_PKT_FLAG_NONE, write_datalen, ts); + conn_write_handshake_pkt(conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL, + NGTCP2_WRITE_PKT_FLAG_NONE, write_datalen, ts); if (nwrite < 0) { assert(nwrite != NGTCP2_ERR_NOBUF); return nwrite; @@ -2823,11 +2826,11 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, !ngtcp2_strm_streamfrq_empty(&conn->in_pktns->crypto.strm))) { if (cstat->loss_detection_timer != UINT64_MAX && conn_server_tx_left(conn, &conn->dcid.current) < - NGTCP2_MAX_UDP_PAYLOAD_SIZE) { + NGTCP2_MAX_UDP_PAYLOAD_SIZE) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_LDC, - "loss detection timer canceled due to amplification limit"); - cstat->loss_detection_timer = UINT64_MAX; + &conn->log, NGTCP2_LOG_EVENT_LDC, + "loss detection timer canceled due to amplification limit"); + ngtcp2_conn_cancel_loss_detection_timer(conn); } return 0; @@ -2837,10 +2840,10 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, dest += nwrite; destlen -= (size_t)nwrite; - if (destlen) { - /* We might have already added padding to Initial, but in that - case, we should have destlen == 0 and no Handshake packet - will be written. */ + /* If initial packet size is at least + NGTCP2_MAX_UDP_PAYLOAD_SIZE, no extra padding is needed in a + subsequent packet. */ + if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE) { if (conn->server) { it = ngtcp2_rtb_head(&conn->in_pktns->rtb); if (!ngtcp2_ksl_it_end(&it)) { @@ -2856,8 +2859,9 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, } } - nwrite = conn_write_handshake_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, wflags, write_datalen, ts); + nwrite = + conn_write_handshake_pkt(conn, pi, dest, destlen, (size_t)res, + NGTCP2_PKT_HANDSHAKE, wflags, write_datalen, ts); if (nwrite < 0) { assert(nwrite != NGTCP2_ERR_NOBUF); return nwrite; @@ -2869,7 +2873,7 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, /* We don't need to send further Initial packet if we have Handshake key and sent something with it. So discard initial state here. */ - conn_discard_initial_state(conn, ts); + ngtcp2_conn_discard_initial_state(conn, ts); } return res; @@ -2905,7 +2909,7 @@ static int conn_should_send_max_stream_data(ngtcp2_conn *conn, uint64_t inc = strm->rx.unsent_max_offset - strm->rx.max_offset; (void)conn; - return strm->rx.window < 2 * inc; + return strm->rx.window < 4 * inc; } /* @@ -2915,7 +2919,7 @@ static int conn_should_send_max_stream_data(ngtcp2_conn *conn, static int conn_should_send_max_data(ngtcp2_conn *conn) { uint64_t inc = conn->rx.unsent_max_offset - conn->rx.max_offset; - return conn->rx.window < 2 * inc; + return conn->rx.window < 4 * inc; } /* @@ -2948,9 +2952,9 @@ static size_t conn_required_num_new_connection_id(ngtcp2_conn *conn) { n = conn->remote.transport_params->active_connection_id_limit + conn->scid.num_retired; - n = ngtcp2_min(NGTCP2_MAX_SCID_POOL_SIZE, n) - len; + n = ngtcp2_min_uint64(NGTCP2_MAX_SCID_POOL_SIZE, n) - len; - return (size_t)ngtcp2_min(lim, n); + return (size_t)ngtcp2_min_uint64(lim, n); } /* @@ -3093,11 +3097,12 @@ static int conn_remove_retired_connection_id(ngtcp2_conn *conn, } /* - * conn_min_short_pktlen returns the minimum length of Short packet - * this endpoint sends. + * conn_min_pktlen returns the minimum length of packet this endpoint + * sends. It may underestimate the length because this does not take + * into account header protection sample. */ -static size_t conn_min_short_pktlen(ngtcp2_conn *conn) { - return conn->dcid.current.cid.datalen + NGTCP2_MIN_PKT_EXPANDLEN; +static size_t conn_min_pktlen(ngtcp2_conn *conn) { + return conn->oscid.datalen + NGTCP2_MIN_PKT_EXPANDLEN; } /* @@ -3155,8 +3160,10 @@ static void conn_reset_ppe_pending(ngtcp2_conn *conn) { /* * conn_write_pkt writes a protected packet in the buffer pointed by - * |dest| whose length if |destlen|. |type| specifies the type of - * packet. It can be NGTCP2_PKT_1RTT or NGTCP2_PKT_0RTT. + * |dest| whose length if |destlen|. |dgram_offset| is the offset in + * UDP datagram payload where this QUIC packet is positioned at. + * |type| specifies the type of packet. It can be NGTCP2_PKT_1RTT or + * NGTCP2_PKT_0RTT. * * This function can send new stream data. In order to send stream * data, specify the underlying stream and parameters to @@ -3183,8 +3190,9 @@ static void conn_reset_ppe_pending(ngtcp2_conn *conn) { */ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, - ngtcp2_vmsg *vmsg, uint8_t type, - uint8_t flags, ngtcp2_tstamp ts) { + size_t dgram_offset, ngtcp2_vmsg *vmsg, + uint8_t type, uint8_t flags, + ngtcp2_tstamp ts) { int rv = 0; ngtcp2_crypto_cc *cc = &conn->pkt.cc; ngtcp2_ppe *ppe = &conn->pkt.ppe; @@ -3211,7 +3219,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, int require_padding = (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) != 0; int write_more = (flags & NGTCP2_WRITE_PKT_FLAG_MORE) != 0; int ppe_pending = (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING) != 0; - size_t min_pktlen = conn_min_short_pktlen(conn); + size_t min_pktlen = conn_min_pktlen(conn); + int min_padded = 0; int padded = 0; ngtcp2_cc_pkt cc_pkt; uint64_t crypto_offset; @@ -3311,7 +3320,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (conn->local.settings.max_window && conn->tx.last_max_data_ts != UINT64_MAX && ts - conn->tx.last_max_data_ts < - NGTCP2_FLOW_WINDOW_RTT_FACTOR * cstat->smoothed_rtt && + NGTCP2_FLOW_WINDOW_RTT_FACTOR * cstat->smoothed_rtt && conn->local.settings.max_window > conn->rx.window) { target_max_data = NGTCP2_FLOW_WINDOW_SCALING_FACTOR * conn->rx.window; if (target_max_data > conn->local.settings.max_window) { @@ -3336,7 +3345,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, pktns->tx.frq = nfrc; conn->rx.max_offset = conn->rx.unsent_max_offset = - nfrc->fr.max_data.max_data; + nfrc->fr.max_data.max_data; } if (stream_blocked && conn_should_send_max_data(conn)) { @@ -3369,7 +3378,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), version, 0); - ngtcp2_ppe_init(ppe, dest, destlen, cc); + ngtcp2_ppe_init(ppe, dest, destlen, dgram_offset, cc); rv = ngtcp2_ppe_encode_hd(ppe, hd); if (rv != 0) { @@ -3407,8 +3416,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } rv = ngtcp2_conn_create_ack_frame( - conn, &ackfr, pktns, type, ts, conn_compute_ack_delay(conn), - conn->local.transport_params.ack_delay_exponent); + conn, &ackfr, pktns, type, ts, conn_compute_ack_delay(conn), + conn->local.transport_params.ack_delay_exponent); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); return rv; @@ -3422,10 +3431,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, ngtcp2_acktr_commit_ack(&pktns->acktr); ngtcp2_acktr_add_ack(&pktns->acktr, hd->pkt_num, ackfr->ack.largest_ack); - if (type == NGTCP2_PKT_1RTT) { - conn_handle_unconfirmed_key_update_from_remote( - conn, ackfr->ack.largest_ack, ts); - } + assert(NGTCP2_PKT_1RTT == type); + conn_handle_unconfirmed_key_update_from_remote( + conn, ackfr->ack.largest_ack, ts); pkt_empty = 0; } } @@ -3443,7 +3451,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, switch ((*pfrc)->fr.type) { case NGTCP2_FRAME_RESET_STREAM: strm = - ngtcp2_conn_find_stream(conn, (*pfrc)->fr.reset_stream.stream_id); + ngtcp2_conn_find_stream(conn, (*pfrc)->fr.reset_stream.stream_id); if (strm == NULL || !ngtcp2_strm_require_retransmit_reset_stream(strm)) { frc = *pfrc; @@ -3454,7 +3462,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, break; case NGTCP2_FRAME_STOP_SENDING: strm = - ngtcp2_conn_find_stream(conn, (*pfrc)->fr.stop_sending.stream_id); + ngtcp2_conn_find_stream(conn, (*pfrc)->fr.stop_sending.stream_id); if (strm == NULL || !ngtcp2_strm_require_retransmit_stop_sending(strm)) { frc = *pfrc; @@ -3484,10 +3492,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } break; case NGTCP2_FRAME_MAX_STREAM_DATA: - strm = ngtcp2_conn_find_stream(conn, - (*pfrc)->fr.max_stream_data.stream_id); + strm = + ngtcp2_conn_find_stream(conn, (*pfrc)->fr.max_stream_data.stream_id); if (strm == NULL || !ngtcp2_strm_require_retransmit_max_stream_data( - strm, &(*pfrc)->fr.max_stream_data)) { + strm, &(*pfrc)->fr.max_stream_data)) { frc = *pfrc; *pfrc = (*pfrc)->next; ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); @@ -3504,9 +3512,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, break; case NGTCP2_FRAME_STREAM_DATA_BLOCKED: strm = ngtcp2_conn_find_stream( - conn, (*pfrc)->fr.stream_data_blocked.stream_id); + conn, (*pfrc)->fr.stream_data_blocked.stream_id); if (strm == NULL || !ngtcp2_strm_require_retransmit_stream_data_blocked( - strm, &(*pfrc)->fr.stream_data_blocked)) { + strm, &(*pfrc)->fr.stream_data_blocked)) { frc = *pfrc; *pfrc = (*pfrc)->next; ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); @@ -3543,7 +3551,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, left = ngtcp2_ppe_left(ppe); crypto_offset = - ngtcp2_strm_streamfrq_unacked_offset(&pktns->crypto.strm); + ngtcp2_strm_streamfrq_unacked_offset(&pktns->crypto.strm); if (crypto_offset == (uint64_t)-1) { ngtcp2_strm_streamfrq_clear(&pktns->crypto.strm); break; @@ -3593,14 +3601,14 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, 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; + strm->tx.reset_stream_app_error_code; nfrc->fr.reset_stream.final_size = strm->tx.offset; *pfrc = nfrc; strm->flags &= ~NGTCP2_STRM_FLAG_SEND_RESET_STREAM; rv = - conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); + conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { assert(NGTCP2_ERR_NOBUF == rv); @@ -3620,8 +3628,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, strm->flags &= ~NGTCP2_STRM_FLAG_SEND_STOP_SENDING; } else { rv = conn_call_stream_stop_sending( - conn, strm->stream_id, strm->tx.stop_sending_app_error_code, - strm->stream_user_data); + conn, strm->stream_id, strm->tx.stop_sending_app_error_code, + strm->stream_user_data); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); @@ -3636,13 +3644,13 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, 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; + strm->tx.stop_sending_app_error_code; *pfrc = nfrc; strm->flags &= ~NGTCP2_STRM_FLAG_SEND_STOP_SENDING; - rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, - &nfrc->fr); + rv = + conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { assert(NGTCP2_ERR_NOBUF == rv); @@ -3672,7 +3680,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, strm->tx.last_blocked_offset = strm->tx.max_offset; rv = - conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); + conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { assert(NGTCP2_ERR_NOBUF == rv); @@ -3698,10 +3706,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (conn->local.settings.max_stream_window && strm->tx.last_max_stream_data_ts != UINT64_MAX && ts - strm->tx.last_max_stream_data_ts < - NGTCP2_FLOW_WINDOW_RTT_FACTOR * cstat->smoothed_rtt && + NGTCP2_FLOW_WINDOW_RTT_FACTOR * cstat->smoothed_rtt && conn->local.settings.max_stream_window > strm->rx.window) { target_max_data = - NGTCP2_FLOW_WINDOW_SCALING_FACTOR * strm->rx.window; + NGTCP2_FLOW_WINDOW_SCALING_FACTOR * strm->rx.window; if (target_max_data > conn->local.settings.max_stream_window) { target_max_data = conn->local.settings.max_stream_window; } @@ -3721,14 +3729,14 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, 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; + strm->rx.unsent_max_offset + delta; *pfrc = nfrc; strm->rx.max_offset = strm->rx.unsent_max_offset = - nfrc->fr.max_stream_data.max_stream_data; + nfrc->fr.max_stream_data.max_stream_data; rv = - conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); + conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { assert(NGTCP2_ERR_NOBUF == rv); break; @@ -3806,7 +3814,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (*pfrc == NULL && conn->remote.bidi.unsent_max_streams > conn->remote.bidi.max_streams) { rv = conn_call_extend_max_remote_streams_bidi( - conn, conn->remote.bidi.unsent_max_streams); + conn, conn->remote.bidi.unsent_max_streams); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); return rv; @@ -3838,7 +3846,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (*pfrc == NULL && conn->remote.uni.unsent_max_streams > conn->remote.uni.max_streams) { rv = conn_call_extend_max_remote_streams_uni( - conn, conn->remote.uni.unsent_max_streams); + conn, conn->remote.uni.unsent_max_streams); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); return rv; @@ -3901,8 +3909,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (*pfrc == NULL && send_stream && (ndatalen = ngtcp2_pkt_stream_max_datalen( - vmsg->stream.strm->stream_id, vmsg->stream.strm->tx.offset, ndatalen, - left)) != (size_t)-1 && + vmsg->stream.strm->stream_id, vmsg->stream.strm->tx.offset, ndatalen, + left)) != (size_t)-1 && (ndatalen || datalen == 0)) { datacnt = ngtcp2_vec_copy_at_most(data, NGTCP2_MAX_STREAM_DATACNT, vmsg->stream.data, vmsg->stream.datacnt, @@ -3912,7 +3920,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, assert((datacnt == 0 && datalen == 0) || (datacnt && datalen)); rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( - &nfrc, datacnt, &conn->frc_objalloc, conn->mem); + &nfrc, datacnt, &conn->frc_objalloc, conn->mem); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); return rv; @@ -3944,6 +3952,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, vmsg->stream.strm->tx.offset += ndatalen; conn->tx.offset += ndatalen; + vmsg->stream.strm->flags |= NGTCP2_STRM_FLAG_ANY_SENT; if (fin) { ngtcp2_strm_shutdown(vmsg->stream.strm, NGTCP2_STRM_FLAG_SHUT_WR); @@ -4095,7 +4104,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } keep_alive_expired = - type == NGTCP2_PKT_1RTT && conn_keep_alive_expired(conn, ts); + type == NGTCP2_PKT_1RTT && conn_keep_alive_expired(conn, ts); if (conn->pktns.rtb.probe_pkt_left == 0 && !keep_alive_expired && !require_padding) { @@ -4154,8 +4163,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING; if (conn->pktns.rtb.probe_pkt_left) { rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_PROBE; + } else { + 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; @@ -4166,19 +4178,19 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, /* TODO Push STREAM frame back to ngtcp2_strm if there is an error before ngtcp2_rtb_entry is safely created and added. */ - if (require_padding || - /* Making full sized packet will help GSO a bit */ - ngtcp2_ppe_left(ppe) < 10) { - lfr.padding.len = ngtcp2_ppe_padding(ppe); - } else if (type == NGTCP2_PKT_1RTT) { - lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen); + if (require_padding) { + lfr.padding.len = ngtcp2_ppe_dgram_padding(ppe); } else { - lfr.padding.len = ngtcp2_ppe_padding_hp_sample(ppe); + lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen); + min_padded = 1; } if (lfr.padding.len) { + if (!min_padded || + (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { + padded = 1; + } lfr.type = NGTCP2_FRAME_PADDING; - padded = 1; ngtcp2_log_tx_fr(&conn->log, hd, &lfr); ngtcp2_qlog_write_frame(&conn->qlog, &lfr); } @@ -4200,11 +4212,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, conn_handle_tx_ecn(conn, pi, &rtb_entry_flags, pktns, hd, ts); } - rv = ngtcp2_rtb_entry_objalloc_new(&ent, hd, NULL, ts, (size_t)nwrite, - rtb_entry_flags, - &conn->rtb_entry_objalloc); + rv = + ngtcp2_rtb_entry_objalloc_new(&ent, hd, NULL, ts, (size_t)nwrite, + rtb_entry_flags, &conn->rtb_entry_objalloc); if (rv != 0) { - assert(ngtcp2_err_is_fatal((int)nwrite)); + assert(ngtcp2_err_is_fatal(rv)); return rv; } @@ -4220,7 +4232,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, ts); } - rv = conn_on_pkt_sent(conn, &pktns->rtb, ent); + rv = conn_on_pkt_sent(conn, pktns, ent); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); ngtcp2_rtb_entry_objalloc_del(ent, &conn->rtb_entry_objalloc, @@ -4231,10 +4243,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, 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)); + &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) { @@ -4269,9 +4281,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( - ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, - uint8_t type, uint8_t flags, const ngtcp2_cid *dcid, ngtcp2_frame *fr, - uint16_t rtb_entry_flags, const ngtcp2_path *path, ngtcp2_tstamp ts) { + ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, + uint8_t type, uint8_t flags, const ngtcp2_cid *dcid, ngtcp2_frame *fr, + uint16_t rtb_entry_flags, const ngtcp2_path *path, ngtcp2_tstamp ts) { int rv; ngtcp2_ppe ppe; ngtcp2_pkt_hd hd; @@ -4332,7 +4344,7 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), version, 0); - ngtcp2_ppe_init(&ppe, dest, destlen, &cc); + ngtcp2_ppe_init(&ppe, dest, destlen, 0, &cc); rv = ngtcp2_ppe_encode_hd(&ppe, &hd); if (rv != 0) { @@ -4354,25 +4366,22 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( } lfr.type = NGTCP2_FRAME_PADDING; - if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) { - lfr.padding.len = ngtcp2_ppe_padding(&ppe); + if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL) { + lfr.padding.len = ngtcp2_ppe_dgram_padding_size(&ppe, destlen); + } else if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) { + lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); } else { switch (fr->type) { case NGTCP2_FRAME_PATH_CHALLENGE: case NGTCP2_FRAME_PATH_RESPONSE: if (!conn->server || destlen >= NGTCP2_MAX_UDP_PAYLOAD_SIZE) { - lfr.padding.len = ngtcp2_ppe_padding(&ppe); + lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); } else { lfr.padding.len = 0; } break; default: - if (type == NGTCP2_PKT_1RTT) { - lfr.padding.len = - ngtcp2_ppe_padding_size(&ppe, conn_min_short_pktlen(conn)); - } else { - lfr.padding.len = ngtcp2_ppe_padding_hp_sample(&ppe); - } + lfr.padding.len = ngtcp2_ppe_padding_size(&ppe, conn_min_pktlen(conn)); } } if (lfr.padding.len) { @@ -4402,6 +4411,12 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( conn_handle_unconfirmed_key_update_from_remote(conn, fr->ack.largest_ack, ts); } + + if (!(flags & (NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL | + NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING))) { + padded = 0; + } + break; } @@ -4412,14 +4427,14 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( conn_handle_tx_ecn(conn, pi, &rtb_entry_flags, pktns, &hd, ts); } - rv = ngtcp2_rtb_entry_objalloc_new(&rtbent, &hd, NULL, ts, (size_t)nwrite, - rtb_entry_flags, - &conn->rtb_entry_objalloc); + rv = + ngtcp2_rtb_entry_objalloc_new(&rtbent, &hd, NULL, ts, (size_t)nwrite, + rtb_entry_flags, &conn->rtb_entry_objalloc); if (rv != 0) { return rv; } - rv = conn_on_pkt_sent(conn, &pktns->rtb, rtbent); + rv = conn_on_pkt_sent(conn, pktns, rtbent); if (rv != 0) { ngtcp2_rtb_entry_objalloc_del(rtbent, &conn->rtb_entry_objalloc, &conn->frc_objalloc, conn->mem); @@ -4522,6 +4537,10 @@ static int conn_retire_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { ngtcp2_frame_chain *nfrc; int rv; + if (ngtcp2_conn_check_retired_dcid_tracked(conn, seq)) { + return 0; + } + rv = ngtcp2_conn_track_retired_dcid_seq(conn, seq); if (rv != 0) { return rv; @@ -4658,13 +4677,15 @@ static int conn_start_pmtud(ngtcp2_conn *conn) { assert(conn->remote.transport_params->max_udp_payload_size >= NGTCP2_MAX_UDP_PAYLOAD_SIZE); - hard_max_udp_payload_size = (size_t)ngtcp2_min( - conn->remote.transport_params->max_udp_payload_size, - (uint64_t)conn->local.settings.max_tx_udp_payload_size); + hard_max_udp_payload_size = (size_t)ngtcp2_min_uint64( + conn->remote.transport_params->max_udp_payload_size, + (uint64_t)conn->local.settings.max_tx_udp_payload_size); - rv = ngtcp2_pmtud_new(&conn->pmtud, conn->dcid.current.max_udp_payload_size, - hard_max_udp_payload_size, - conn->pktns.tx.last_pkt_num + 1, conn->mem); + rv = + ngtcp2_pmtud_new(&conn->pmtud, conn->dcid.current.max_udp_payload_size, + hard_max_udp_payload_size, conn->pktns.tx.last_pkt_num + 1, + conn->local.settings.pmtud_probes, + conn->local.settings.pmtud_probeslen, conn->mem); if (rv != 0) { return rv; } @@ -4715,12 +4736,11 @@ static ngtcp2_ssize conn_write_pmtud_probe(ngtcp2_conn *conn, lfr.type = NGTCP2_FRAME_PING; nwrite = ngtcp2_conn_write_single_frame_pkt( - conn, pi, dest, probelen, NGTCP2_PKT_1RTT, - NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING, &conn->dcid.current.cid, &lfr, - NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | - NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | - NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE, - NULL, ts); + conn, pi, dest, probelen, NGTCP2_PKT_1RTT, + NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL, &conn->dcid.current.cid, &lfr, + NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | + NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE, + NULL, ts); if (nwrite < 0) { return nwrite; } @@ -4813,19 +4833,19 @@ static size_t conn_shape_udp_payload(ngtcp2_conn *conn, const ngtcp2_dcid *dcid, assert(conn->remote.transport_params->max_udp_payload_size >= NGTCP2_MAX_UDP_PAYLOAD_SIZE); - payloadlen = - (size_t)ngtcp2_min((uint64_t)payloadlen, - conn->remote.transport_params->max_udp_payload_size); + payloadlen = (size_t)ngtcp2_min_uint64( + (uint64_t)payloadlen, + conn->remote.transport_params->max_udp_payload_size); } payloadlen = - ngtcp2_min(payloadlen, conn->local.settings.max_tx_udp_payload_size); + ngtcp2_min_size(payloadlen, conn->local.settings.max_tx_udp_payload_size); if (conn->local.settings.no_tx_udp_payload_size_shaping) { return payloadlen; } - return ngtcp2_min(payloadlen, dcid->max_udp_payload_size); + return ngtcp2_min_size(payloadlen, dcid->max_udp_payload_size); } static void conn_reset_congestion_state(ngtcp2_conn *conn, ngtcp2_tstamp ts); @@ -4920,15 +4940,15 @@ static ngtcp2_ssize conn_write_path_challenge(ngtcp2_conn *conn, initial_pto = conn_compute_initial_pto(conn, &conn->pktns); timeout = conn_compute_pto(conn, &conn->pktns); - timeout = ngtcp2_max(timeout, initial_pto); + timeout = ngtcp2_max_uint64(timeout, initial_pto); expiry = ts + timeout * (1ULL << pv->round); - destlen = ngtcp2_min(destlen, NGTCP2_MAX_UDP_PAYLOAD_SIZE); + destlen = ngtcp2_min_size(destlen, NGTCP2_MAX_UDP_PAYLOAD_SIZE); if (conn->server) { if (!(pv->dcid.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) { tx_left = conn_server_tx_left(conn, &pv->dcid); - destlen = (size_t)ngtcp2_min((uint64_t)destlen, tx_left); + destlen = (size_t)ngtcp2_min_uint64((uint64_t)destlen, tx_left); if (destlen == 0) { return 0; } @@ -4946,10 +4966,10 @@ static ngtcp2_ssize conn_write_path_challenge(ngtcp2_conn *conn, ngtcp2_pv_add_entry(pv, lfr.path_challenge.data, expiry, flags, ts); nwrite = ngtcp2_conn_write_single_frame_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE, - &pv->dcid.cid, &lfr, - NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING, - &pv->dcid.ps.path, ts); + conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE, + &pv->dcid.cid, &lfr, + NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING, + &pv->dcid.ps.path, ts); if (nwrite <= 0) { return nwrite; } @@ -5039,11 +5059,11 @@ static ngtcp2_ssize conn_write_path_response(ngtcp2_conn *conn, } } - destlen = ngtcp2_min(destlen, NGTCP2_MAX_UDP_PAYLOAD_SIZE); + destlen = ngtcp2_min_size(destlen, NGTCP2_MAX_UDP_PAYLOAD_SIZE); if (conn->server && !(dcid->flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) { tx_left = conn_server_tx_left(conn, dcid); - destlen = (size_t)ngtcp2_min((uint64_t)destlen, tx_left); + destlen = (size_t)ngtcp2_min_uint64((uint64_t)destlen, tx_left); if (destlen == 0) { return 0; } @@ -5053,9 +5073,8 @@ static ngtcp2_ssize conn_write_path_response(ngtcp2_conn *conn, memcpy(lfr.path_response.data, pcent->data, sizeof(lfr.path_response.data)); nwrite = ngtcp2_conn_write_single_frame_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE, - &dcid->cid, &lfr, NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING, &pcent->ps.path, - ts); + conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE, + &dcid->cid, &lfr, NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING, &pcent->ps.path, ts); if (nwrite <= 0) { return nwrite; } @@ -5077,10 +5096,10 @@ ngtcp2_ssize ngtcp2_conn_write_pkt_versioned(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_tstamp ts) { return ngtcp2_conn_writev_stream_versioned( - conn, path, pkt_info_version, pi, dest, destlen, - /* pdatalen = */ NULL, NGTCP2_WRITE_STREAM_FLAG_NONE, - /* stream_id = */ -1, - /* datav = */ NULL, /* datavcnt = */ 0, ts); + conn, path, pkt_info_version, pi, dest, destlen, + /* pdatalen = */ NULL, NGTCP2_WRITE_STREAM_FLAG_NONE, + /* stream_id = */ -1, + /* datav = */ NULL, /* datavcnt = */ 0, ts); } /* @@ -5225,8 +5244,8 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, retry.odcid = conn->dcid.current.cid; rv = ngtcp2_pkt_verify_retry_tag( - conn->client_chosen_version, &retry, pkt, pktlen, conn->callbacks.encrypt, - &conn->crypto.retry_aead, &conn->crypto.retry_aead_ctx); + conn->client_chosen_version, &retry, pkt, pktlen, conn->callbacks.encrypt, + &conn->crypto.retry_aead, &conn->crypto.retry_aead_ctx); if (rv != 0) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "unable to verify Retry packet integrity"); @@ -5334,8 +5353,8 @@ static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr, ngtcp2_acktr_recv_ack(&pktns->acktr, fr); - num_acked = ngtcp2_rtb_recv_ack(&pktns->rtb, fr, &conn->cstat, conn, pktns, - pkt_ts, ts); + num_acked = + ngtcp2_rtb_recv_ack(&pktns->rtb, fr, &conn->cstat, conn, pktns, pkt_ts, ts); if (num_acked < 0) { assert(ngtcp2_err_is_fatal((int)num_acked)); return (int)num_acked; @@ -5351,7 +5370,7 @@ static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr, (conn->server || (conn->flags & NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED))) { /* Reset PTO count but no less than 2 to avoid frequent probe packet transmission. */ - cstat->pto_count = ngtcp2_min(cstat->pto_count, 2); + cstat->pto_count = ngtcp2_min_size(cstat->pto_count, 2); } ngtcp2_conn_set_loss_detection_timer(conn, ts); @@ -5366,7 +5385,7 @@ static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr, static void assign_recved_ack_delay_unscaled(ngtcp2_ack *fr, uint64_t ack_delay_exponent) { fr->ack_delay_unscaled = - fr->ack_delay * (1ULL << ack_delay_exponent) * NGTCP2_MICROSECONDS; + fr->ack_delay * (1ULL << ack_delay_exponent) * NGTCP2_MICROSECONDS; } /* @@ -5467,7 +5486,7 @@ static int conn_recv_max_stream_data(ngtcp2_conn *conn, * conn_recv_max_data processes received MAX_DATA frame |fr|. */ static void conn_recv_max_data(ngtcp2_conn *conn, const ngtcp2_max_data *fr) { - conn->tx.max_offset = ngtcp2_max(conn->tx.max_offset, fr->max_data); + conn->tx.max_offset = ngtcp2_max_uint64(conn->tx.max_offset, fr->max_data); } /* @@ -5496,7 +5515,7 @@ static int conn_buffer_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns, } rv = - ngtcp2_pkt_chain_new(&pc, path, pi, pkt, pktlen, dgramlen, ts, conn->mem); + ngtcp2_pkt_chain_new(&pc, path, pi, pkt, pktlen, dgramlen, ts, conn->mem); if (rv != 0) { return rv; } @@ -5695,8 +5714,8 @@ conn_emit_pending_crypto_data(ngtcp2_conn *conn, offset = rx_offset; rx_offset += datalen; - rv = conn_call_recv_crypto_data(conn, encryption_level, offset, data, - datalen); + rv = + conn_call_recv_crypto_data(conn, encryption_level, offset, data, datalen); if (rv != 0) { return rv; } @@ -5735,7 +5754,7 @@ static int conn_recv_connection_close(ngtcp2_conn *conn, } } - ccerr->reasonlen = ngtcp2_min(fr->reasonlen, NGTCP2_CCERR_MAX_REASONLEN); + ccerr->reasonlen = ngtcp2_min_size(fr->reasonlen, NGTCP2_CCERR_MAX_REASONLEN); ngtcp2_cpymem((uint8_t *)ccerr->reason, fr->reason, ccerr->reasonlen); return 0; @@ -5907,9 +5926,9 @@ static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num, if (pktns->rx.max_ack_eliciting_pkt_num != -1) { if (pkt_num < pktns->rx.max_ack_eliciting_pkt_num) { ngtcp2_acktr_immediate_ack(&pktns->acktr); - } else if (pkt_num > pktns->rx.max_ack_eliciting_pkt_num) { + } else if (pkt_num != pktns->rx.max_ack_eliciting_pkt_num + 1) { r = ngtcp2_gaptr_get_first_gap_after( - &pktns->rx.pngap, (uint64_t)pktns->rx.max_ack_eliciting_pkt_num); + &pktns->rx.pngap, (uint64_t)pktns->rx.max_ack_eliciting_pkt_num); if (r.begin < (uint64_t)pkt_num) { ngtcp2_acktr_immediate_ack(&pktns->acktr); @@ -5977,7 +5996,7 @@ static int vneg_available_versions_includes(const uint8_t *available_versions, } for (i = 0; i < available_versionslen; i += sizeof(uint32_t)) { - available_versions = ngtcp2_get_uint32(&v, available_versions); + available_versions = ngtcp2_get_uint32be(&v, available_versions); if (version == v) { return 1; @@ -6097,6 +6116,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_strm *crypto; ngtcp2_encryption_level encryption_level; int invalid_reserved_bits = 0; + size_t num_ack_processed = 0; if (pktlen == 0) { return 0; @@ -6116,8 +6136,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "buffering 1RTT packet len=%zu", pktlen); - rv = conn_buffer_pkt(conn, &conn->pktns, path, pi, pkt, pktlen, dgramlen, - ts); + rv = + conn_buffer_pkt(conn, &conn->pktns, path, pi, pkt, pktlen, dgramlen, ts); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); return rv; @@ -6158,8 +6178,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, "packet was ignored because of mismatched SCID"); return NGTCP2_ERR_DISCARD_PKT; } - rv = conn_on_version_negotiation(conn, &hd, pkt + hdpktlen, - pktlen - hdpktlen); + rv = + conn_on_version_negotiation(conn, &hd, pkt + hdpktlen, pktlen - hdpktlen); if (rv != 0) { if (ngtcp2_err_is_fatal(rv)) { return rv; @@ -6250,7 +6270,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_ssize nread2; /* TODO Avoid to parse header twice. */ nread2 = - conn_recv_pkt(conn, path, pi, pkt, pktlen, dgramlen, pkt_ts, ts); + conn_recv_pkt(conn, path, pi, pkt, pktlen, dgramlen, pkt_ts, ts); if (nread2 < 0) { return nread2; } @@ -6275,8 +6295,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, case NGTCP2_PKT_INITIAL: if (!conn->in_pktns) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_PKT, - "Initial packet is discarded because keys have been discarded"); + &conn->log, NGTCP2_LOG_EVENT_PKT, + "Initial packet is discarded because keys have been discarded"); return (ngtcp2_ssize)pktlen; } @@ -6285,10 +6305,10 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (conn->server) { if (dgramlen < NGTCP2_MAX_UDP_PAYLOAD_SIZE) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_PKT, - "Initial packet was ignored because it is included in UDP datagram " - "less than %zu bytes: %zu bytes", - NGTCP2_MAX_UDP_PAYLOAD_SIZE, dgramlen); + &conn->log, NGTCP2_LOG_EVENT_PKT, + "Initial packet was ignored because it is included in UDP datagram " + "less than %zu bytes: %zu bytes", + NGTCP2_MAX_UDP_PAYLOAD_SIZE, dgramlen); return NGTCP2_ERR_DISCARD_PKT; } if (conn->local.settings.tokenlen) { @@ -6329,10 +6349,9 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, /* Install new Initial keys using QUIC version = hd.version */ rv = conn_call_version_negotiation( - conn, hd.version, - (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) - ? &conn->dcid.current.cid - : &conn->rcid); + conn, hd.version, + (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) ? &conn->dcid.current.cid + : &conn->rcid); if (rv != 0) { return rv; } @@ -6364,8 +6383,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (!conn->hs_pktns->crypto.rx.ckm) { if (conn->server) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_PKT, - "Handshake packet at this point is unexpected and discarded"); + &conn->log, NGTCP2_LOG_EVENT_PKT, + "Handshake packet at this point is unexpected and discarded"); return (ngtcp2_ssize)pktlen; } ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, @@ -6420,8 +6439,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, payload = pkt + hdpktlen; payloadlen = hd.len - hd.pkt_numlen; - hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, - hd.pkt_numlen); + hd.pkt_num = + ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, hd.pkt_numlen); if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); @@ -6550,6 +6569,9 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, switch (fr->type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: + if (num_ack_processed >= NGTCP2_MAX_ACK_PER_PKT) { + break; + } if (!conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) { conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED; } @@ -6557,6 +6579,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (rv != 0) { return rv; } + ++num_ack_processed; break; case NGTCP2_FRAME_PADDING: break; @@ -6609,8 +6632,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, /* Initial and Handshake are always acknowledged without delay. No need to call ngtcp2_acktr_immediate_ack(). */ - rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, - pkt_ts); + rv = + ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, pkt_ts); if (rv != 0) { return rv; } @@ -6661,7 +6684,7 @@ static ngtcp2_ssize conn_recv_handshake_cpkt(ngtcp2_conn *conn, while (pktlen) { nread = - conn_recv_handshake_pkt(conn, path, pi, pkt, pktlen, dgramlen, ts, ts); + conn_recv_handshake_pkt(conn, path, pi, pkt, pktlen, dgramlen, ts, ts); if (nread < 0) { if (ngtcp2_err_is_fatal((int)nread)) { return nread; @@ -6673,7 +6696,7 @@ static ngtcp2_ssize conn_recv_handshake_cpkt(ngtcp2_conn *conn, if ((pkt[0] & NGTCP2_HEADER_FORM_BIT) && pktlen > 4) { /* Not a Version Negotiation packet */ - ngtcp2_get_uint32(&version, &pkt[1]); + ngtcp2_get_uint32be(&version, &pkt[1]); if (ngtcp2_pkt_get_type_long(version, pkt[0]) == NGTCP2_PKT_INITIAL) { if (conn->server) { if (is_unrecoverable_error((int)nread)) { @@ -6738,14 +6761,14 @@ int ngtcp2_conn_init_stream(ngtcp2_conn *conn, ngtcp2_strm *strm, if (bidi_stream(stream_id)) { if (local_stream) { max_rx_offset = - conn->local.transport_params.initial_max_stream_data_bidi_local; + conn->local.transport_params.initial_max_stream_data_bidi_local; max_tx_offset = - conn->remote.transport_params->initial_max_stream_data_bidi_remote; + conn->remote.transport_params->initial_max_stream_data_bidi_remote; } else { max_rx_offset = - conn->local.transport_params.initial_max_stream_data_bidi_remote; + conn->local.transport_params.initial_max_stream_data_bidi_remote; max_tx_offset = - conn->remote.transport_params->initial_max_stream_data_bidi_local; + conn->remote.transport_params->initial_max_stream_data_bidi_local; } } else if (local_stream) { max_rx_offset = 0; @@ -6759,8 +6782,8 @@ int ngtcp2_conn_init_stream(ngtcp2_conn *conn, ngtcp2_strm *strm, max_tx_offset, stream_user_data, &conn->frc_objalloc, conn->mem); - rv = ngtcp2_map_insert(&conn->strms, (ngtcp2_map_key_type)strm->stream_id, - strm); + rv = + ngtcp2_map_insert(&conn->strms, (ngtcp2_map_key_type)strm->stream_id, strm); if (rv != 0) { assert(rv != NGTCP2_ERR_INVALID_ARGUMENT); goto fail; @@ -6833,6 +6856,12 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, return rv; } + /* ngtcp2_conn_shutdown_stream_read from a callback will free + strm->rx.rob. */ + if (!strm->rx.rob) { + return 0; + } + ngtcp2_rob_pop(strm->rx.rob, rx_offset - datalen, datalen); } } @@ -6901,7 +6930,8 @@ static int conn_recv_crypto(ngtcp2_conn *conn, return 0; } - crypto->rx.last_offset = ngtcp2_max(crypto->rx.last_offset, fr_end_offset); + crypto->rx.last_offset = + ngtcp2_max_uint64(crypto->rx.last_offset, fr_end_offset); /* TODO Before dispatching incoming data to TLS stack, make sure that previous data in previous encryption level has been @@ -6917,14 +6947,14 @@ static int conn_recv_crypto(ngtcp2_conn *conn, rx_offset += datalen; ngtcp2_strm_update_rx_offset(crypto, rx_offset); - rv = conn_call_recv_crypto_data(conn, encryption_level, offset, data, - datalen); + rv = + conn_call_recv_crypto_data(conn, encryption_level, offset, data, datalen); if (rv != 0) { return rv; } - rv = conn_emit_pending_crypto_data(conn, encryption_level, crypto, - rx_offset); + rv = + conn_emit_pending_crypto_data(conn, encryption_level, crypto, rx_offset); if (rv != 0) { return rv; } @@ -7100,7 +7130,8 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { return NGTCP2_ERR_FINAL_SIZE; } - strm->rx.last_offset = ngtcp2_max(strm->rx.last_offset, fr_end_offset); + strm->rx.last_offset = + ngtcp2_max_uint64(strm->rx.last_offset, fr_end_offset); if (fr_end_offset <= rx_offset) { return 0; @@ -7220,9 +7251,9 @@ handle_max_remote_streams_extension(uint64_t *punsent_max_remote_streams, size_t n) { if ( #if SIZE_MAX > UINT32_MAX - NGTCP2_MAX_STREAMS < n || + NGTCP2_MAX_STREAMS < n || #endif /* SIZE_MAX > UINT32_MAX */ - *punsent_max_remote_streams > (uint64_t)(NGTCP2_MAX_STREAMS - n)) { + *punsent_max_remote_streams > (uint64_t)(NGTCP2_MAX_STREAMS - n)) { *punsent_max_remote_streams = NGTCP2_MAX_STREAMS; } else { *punsent_max_remote_streams += n; @@ -7360,7 +7391,7 @@ static int conn_recv_reset_stream(ngtcp2_conn *conn, which are not passed to application. */ if (!(strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING)) { ngtcp2_conn_extend_max_offset(conn, strm->rx.last_offset - - ngtcp2_strm_rx_offset(strm)); + ngtcp2_strm_rx_offset(strm)); } conn->rx.offset += datalen; @@ -7368,7 +7399,7 @@ static int conn_recv_reset_stream(ngtcp2_conn *conn, strm->rx.last_offset = fr->final_size; strm->flags |= - NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_RESET_STREAM_RECVED; + NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_RESET_STREAM_RECVED; ngtcp2_strm_set_app_error_code(strm, fr->app_error_code); @@ -7471,7 +7502,7 @@ static int conn_recv_stop_sending(ngtcp2_conn *conn, } strm->flags |= - NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_STOP_SENDING_RECVED; + NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_STOP_SENDING_RECVED; ngtcp2_strm_streamfrq_clear(strm); @@ -7487,7 +7518,7 @@ static int check_stateless_reset(const ngtcp2_dcid *dcid, const ngtcp2_pkt_stateless_reset *sr) { return ngtcp2_path_eq(&dcid->ps.path, path) && ngtcp2_dcid_verify_stateless_reset_token( - dcid, sr->stateless_reset_token) == 0; + dcid, sr->stateless_reset_token) == 0; } /* @@ -7576,7 +7607,7 @@ static int conn_recv_max_streams(ngtcp2_conn *conn, return NGTCP2_ERR_FRAME_ENCODING; } - n = ngtcp2_min(fr->max_streams, NGTCP2_MAX_STREAMS); + n = ngtcp2_min_uint64(fr->max_streams, NGTCP2_MAX_STREAMS); if (fr->type == NGTCP2_FRAME_MAX_STREAMS_BIDI) { if (conn->local.bidi.max_streams < n) { @@ -8221,7 +8252,7 @@ static int conn_recv_handshake_done(ngtcp2_conn *conn, ngtcp2_tstamp ts) { conn->pktns.rtb.persistent_congestion_start_ts = ts; - conn_discard_handshake_state(conn, ts); + ngtcp2_conn_discard_handshake_state(conn, ts); assert(conn->remote.transport_params); @@ -8323,9 +8354,9 @@ static int conn_prepare_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { new_tx_ckm = conn->crypto.key_update.new_tx_ckm; rv = conn_call_update_key( - conn, new_rx_ckm->secret.base, new_tx_ckm->secret.base, &rx_aead_ctx, - new_rx_ckm->iv.base, &tx_aead_ctx, new_tx_ckm->iv.base, - rx_ckm->secret.base, tx_ckm->secret.base, secretlen); + conn, new_rx_ckm->secret.base, new_tx_ckm->secret.base, &rx_aead_ctx, + new_rx_ckm->iv.base, &tx_aead_ctx, new_tx_ckm->iv.base, rx_ckm->secret.base, + tx_ckm->secret.base, secretlen); if (rv != 0) { return rv; } @@ -8340,7 +8371,7 @@ static int conn_prepare_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (conn->crypto.key_update.old_rx_ckm) { conn_call_delete_crypto_aead_ctx( - conn, &conn->crypto.key_update.old_rx_ckm->aead_ctx); + conn, &conn->crypto.key_update.old_rx_ckm->aead_ctx); ngtcp2_crypto_km_del(conn->crypto.key_update.old_rx_ckm, conn->mem); conn->crypto.key_update.old_rx_ckm = NULL; } @@ -8412,7 +8443,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, size_t dgramlen, int new_cid_used, ngtcp2_tstamp ts) { - ngtcp2_dcid dcid, *bound_dcid, *last; ngtcp2_pv *pv; int rv; @@ -8448,9 +8478,9 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, } remote_addr_cmp = - ngtcp2_addr_compare(&conn->dcid.current.ps.path.remote, &path->remote); + ngtcp2_addr_compare(&conn->dcid.current.ps.path.remote, &path->remote); local_addr_eq = - ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local); + ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local); /* * When to change DCID? RFC 9002 section 9.5 says: @@ -8480,8 +8510,8 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, bound_dcid = ngtcp2_ringbuf_get(&conn->dcid.bound.rb, i); if (ngtcp2_path_eq(&bound_dcid->ps.path, path)) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_CON, - "Found DCID which has already been bound to the new path"); + &conn->log, NGTCP2_LOG_EVENT_CON, + "Found DCID which has already been bound to the new path"); ngtcp2_dcid_copy(&dcid, bound_dcid); if (i == 0) { @@ -8550,21 +8580,21 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, pv->fallback_pto = pto; } + ngtcp2_dcid_copy(&conn->dcid.current, &dcid); + if (!local_addr_eq || (remote_addr_cmp & (NGTCP2_ADDR_COMPARE_FLAG_ADDR | NGTCP2_ADDR_COMPARE_FLAG_FAMILY))) { conn_reset_congestion_state(conn, ts); } - ngtcp2_dcid_copy(&conn->dcid.current, &dcid); - conn_reset_ecn_validation_state(conn); ngtcp2_conn_stop_pmtud(conn); if (conn->pv) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_PTV, - "path migration is aborted because new migration has started"); + &conn->log, NGTCP2_LOG_EVENT_PTV, + "path migration is aborted because new migration has started"); rv = conn_abort_pv(conn, ts); if (rv != 0) { return rv; @@ -8658,6 +8688,7 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, int rv; int require_ack = 0; ngtcp2_pktns *pktns; + size_t num_ack_processed = 0; assert(hd->type == NGTCP2_PKT_HANDSHAKE); @@ -8692,6 +8723,9 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, switch (fr->type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: + if (num_ack_processed >= NGTCP2_MAX_ACK_PER_PKT) { + break; + } if (!conn->server) { conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED; } @@ -8699,6 +8733,7 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, if (rv != 0) { return rv; } + ++num_ack_processed; break; case NGTCP2_FRAME_PADDING: break; @@ -8762,7 +8797,7 @@ conn_allow_path_change_under_disable_active_migration(ngtcp2_conn *conn, (NAT rebinding). */ if (ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local)) { remote_addr_cmp = - ngtcp2_addr_compare(&conn->dcid.current.ps.path.remote, &path->remote); + ngtcp2_addr_compare(&conn->dcid.current.ps.path.remote, &path->remote); return (remote_addr_cmp | NGTCP2_ADDR_COMPARE_FLAG_PORT) == NGTCP2_ADDR_COMPARE_FLAG_PORT; @@ -8860,6 +8895,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, int recv_ncid = 0; int new_cid_used = 0; int path_challenge_recved = 0; + size_t num_ack_processed = 0; if (conn->server && conn->local.transport_params.disable_active_migration && !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) && @@ -8992,8 +9028,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, payload = pkt + hdpktlen; payloadlen = pktlen - hdpktlen; - hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, - hd.pkt_numlen); + hd.pkt_num = + ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, hd.pkt_numlen); if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); @@ -9057,7 +9093,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (hd.type == NGTCP2_PKT_1RTT && ++conn->crypto.decryption_failure_count >= - pktns->crypto.ctx.max_decryption_failure) { + pktns->crypto.ctx.max_decryption_failure) { return NGTCP2_ERR_AEAD_LIMIT_REACHED; } @@ -9163,7 +9199,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } assert(conn->remote.transport_params); assign_recved_ack_delay_unscaled( - &fr->ack, conn->remote.transport_params->ack_delay_exponent); + &fr->ack, conn->remote.transport_params->ack_delay_exponent); break; } @@ -9210,6 +9246,9 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, switch (fr->type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: + if (num_ack_processed >= NGTCP2_MAX_ACK_PER_PKT) { + break; + } if (!conn->server) { conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED; } @@ -9218,6 +9257,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return rv; } non_probing_pkt = 1; + ++num_ack_processed; break; case NGTCP2_FRAME_STREAM: rv = conn_recv_stream(conn, &fr->stream); @@ -9429,8 +9469,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_acktr_immediate_ack(&pktns->acktr); } - rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, - pkt_ts); + rv = + ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, pkt_ts); if (rv != 0) { return rv; } @@ -9602,8 +9642,8 @@ static int conn_handshake_completed(ngtcp2_conn *conn) { } } if (conn->local.uni.max_streams > 0) { - rv = conn_call_extend_max_local_streams_uni(conn, - conn->local.uni.max_streams); + rv = + conn_call_extend_max_local_streams_uni(conn, conn->local.uni.max_streams); if (rv != 0) { return rv; } @@ -9822,7 +9862,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, } if (conn->hs_pktns->rx.max_pkt_num != -1) { - conn_discard_initial_state(conn, ts); + ngtcp2_conn_discard_initial_state(conn, ts); } if (!conn_is_tls_handshake_completed(conn)) { @@ -9888,7 +9928,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, return rv; } - conn_discard_handshake_state(conn, ts); + ngtcp2_conn_discard_handshake_state(conn, ts); rv = conn_enqueue_handshake_done(conn); if (rv != 0) { @@ -9936,7 +9976,7 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, pktlen); if (pktlen == 0) { - return NGTCP2_ERR_INVALID_ARGUMENT; + return 0; } /* client does not expect a packet from unknown path. */ @@ -10035,13 +10075,12 @@ static int conn_check_pkt_num_exhausted(ngtcp2_conn *conn) { * conn_retransmit_retry_early retransmits 0RTT packet after Retry is * received from server. */ -static ngtcp2_ssize conn_retransmit_retry_early(ngtcp2_conn *conn, - ngtcp2_pkt_info *pi, - uint8_t *dest, size_t destlen, - uint8_t flags, - ngtcp2_tstamp ts) { - return conn_write_pkt(conn, pi, dest, destlen, NULL, NGTCP2_PKT_0RTT, flags, - ts); +static ngtcp2_ssize +conn_retransmit_retry_early(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, + uint8_t *dest, size_t destlen, size_t dgram_offset, + uint8_t flags, ngtcp2_tstamp ts) { + return conn_write_pkt(conn, pi, dest, destlen, dgram_offset, NULL, + NGTCP2_PKT_0RTT, flags, ts); } /* @@ -10067,21 +10106,21 @@ static int conn_validate_early_transport_params_limits(ngtcp2_conn *conn) { assert(params); if (conn->early.transport_params.active_connection_id_limit > - params->active_connection_id_limit || + params->active_connection_id_limit || conn->early.transport_params.initial_max_data > - params->initial_max_data || + params->initial_max_data || conn->early.transport_params.initial_max_stream_data_bidi_local > - params->initial_max_stream_data_bidi_local || + params->initial_max_stream_data_bidi_local || conn->early.transport_params.initial_max_stream_data_bidi_remote > - params->initial_max_stream_data_bidi_remote || + params->initial_max_stream_data_bidi_remote || conn->early.transport_params.initial_max_stream_data_uni > - params->initial_max_stream_data_uni || + params->initial_max_stream_data_uni || conn->early.transport_params.initial_max_streams_bidi > - params->initial_max_streams_bidi || + params->initial_max_streams_bidi || conn->early.transport_params.initial_max_streams_uni > - params->initial_max_streams_uni || + params->initial_max_streams_uni || conn->early.transport_params.max_datagram_frame_size > - params->max_datagram_frame_size) { + params->max_datagram_frame_size) { return NGTCP2_ERR_PROTO; } @@ -10131,14 +10170,14 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (!(conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY)) { nwrite = - conn_write_client_initial(conn, pi, dest, destlen, write_datalen, ts); + conn_write_client_initial(conn, pi, dest, destlen, write_datalen, ts); if (nwrite <= 0) { return nwrite; } } else { - nwrite = conn_write_handshake_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, - NGTCP2_WRITE_PKT_FLAG_NONE, write_datalen, ts); + nwrite = + conn_write_handshake_pkt(conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL, + NGTCP2_WRITE_PKT_FLAG_NONE, write_datalen, ts); if (nwrite < 0) { return nwrite; } @@ -10146,10 +10185,10 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (pending_early_datalen) { early_spktlen = conn_retransmit_retry_early( - conn, pi, dest + nwrite, destlen - (size_t)nwrite, - nwrite ? NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING - : NGTCP2_WRITE_PKT_FLAG_NONE, - ts); + conn, pi, dest + nwrite, destlen - (size_t)nwrite, (size_t)nwrite, + nwrite ? NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING + : NGTCP2_WRITE_PKT_FLAG_NONE, + ts); if (early_spktlen < 0) { assert(ngtcp2_err_is_fatal((int)early_spktlen)); @@ -10163,6 +10202,8 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return res; case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE: + pending_early_datalen = 0; + if (!conn_handshake_probe_left(conn) && conn_cwnd_is_zero(conn)) { destlen = 0; } else { @@ -10174,7 +10215,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } nwrite = - conn_write_handshake_pkts(conn, pi, dest, destlen, write_datalen, ts); + conn_write_handshake_pkts(conn, pi, dest, destlen, write_datalen, ts); if (nwrite < 0) { return nwrite; } @@ -10185,9 +10226,10 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } if (!conn_is_tls_handshake_completed(conn)) { - if (!(conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED)) { - nwrite = conn_retransmit_retry_early(conn, pi, dest, destlen, - NGTCP2_WRITE_PKT_FLAG_NONE, ts); + if (pending_early_datalen && + !(conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED)) { + nwrite = conn_retransmit_retry_early( + conn, pi, dest, destlen, (size_t)res, NGTCP2_WRITE_PKT_FLAG_NONE, ts); if (nwrite < 0) { return nwrite; } @@ -10250,8 +10292,8 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, assert(conn->dcid.current.seq == 0); assert(!(conn->dcid.current.flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT)); ngtcp2_dcid_set_token( - &conn->dcid.current, - conn->remote.transport_params->stateless_reset_token); + &conn->dcid.current, + conn->remote.transport_params->stateless_reset_token); } rv = conn_call_activate_dcid(conn, &conn->dcid.current); @@ -10271,7 +10313,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return res; case NGTCP2_CS_SERVER_INITIAL: nwrite = - conn_write_handshake_pkts(conn, pi, dest, destlen, write_datalen, ts); + conn_write_handshake_pkts(conn, pi, dest, destlen, write_datalen, ts); if (nwrite < 0) { return nwrite; } @@ -10284,7 +10326,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, case NGTCP2_CS_SERVER_WAIT_HANDSHAKE: if (conn_handshake_probe_left(conn) || !conn_cwnd_is_zero(conn)) { nwrite = - conn_write_handshake_pkts(conn, pi, dest, destlen, write_datalen, ts); + conn_write_handshake_pkts(conn, pi, dest, destlen, write_datalen, ts); if (nwrite < 0) { return nwrite; } @@ -10363,8 +10405,8 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt); send_stream = conn_retry_early_payloadlen(conn) == 0; if (send_stream) { - write_datalen = ngtcp2_min(datalen + NGTCP2_STREAM_OVERHEAD, - NGTCP2_MIN_COALESCED_PAYLOADLEN); + write_datalen = ngtcp2_min_uint64(datalen + NGTCP2_STREAM_OVERHEAD, + NGTCP2_MIN_COALESCED_PAYLOADLEN); if (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_MORE) { wflags |= NGTCP2_WRITE_PKT_FLAG_MORE; @@ -10428,8 +10470,8 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, return spktlen; } - early_spktlen = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_0RTT, - wflags, ts); + early_spktlen = conn_write_pkt(conn, pi, dest, destlen, (size_t)spktlen, vmsg, + NGTCP2_PKT_0RTT, wflags, ts); if (early_spktlen < 0) { switch (early_spktlen) { case NGTCP2_ERR_STREAM_DATA_BLOCKED: @@ -10520,10 +10562,10 @@ int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt, size_t pktlen) { } int ngtcp2_conn_install_initial_key( - ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *rx_aead_ctx, - const uint8_t *rx_iv, const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, - const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, - const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen) { + ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *rx_aead_ctx, + const uint8_t *rx_iv, const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, + const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, + const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen) { ngtcp2_pktns *pktns = conn->in_pktns; int rv; @@ -10571,11 +10613,11 @@ int ngtcp2_conn_install_initial_key( } int ngtcp2_conn_install_vneg_initial_key( - ngtcp2_conn *conn, uint32_t version, - const ngtcp2_crypto_aead_ctx *rx_aead_ctx, const uint8_t *rx_iv, - const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, - const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, - const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen) { + ngtcp2_conn *conn, uint32_t version, + const ngtcp2_crypto_aead_ctx *rx_aead_ctx, const uint8_t *rx_iv, + const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, + const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, + const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen) { int rv; assert(ivlen >= 8); @@ -10622,8 +10664,8 @@ int ngtcp2_conn_install_vneg_initial_key( } int ngtcp2_conn_install_rx_handshake_key( - ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, - const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx) { + ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, + size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx) { ngtcp2_pktns *pktns = conn->hs_pktns; int rv; @@ -10654,8 +10696,8 @@ int ngtcp2_conn_install_rx_handshake_key( } int ngtcp2_conn_install_tx_handshake_key( - ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, - const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx) { + ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, + size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx) { ngtcp2_pktns *pktns = conn->hs_pktns; int rv; @@ -10905,7 +10947,7 @@ ngtcp2_tstamp ngtcp2_conn_loss_detection_expiry(ngtcp2_conn *conn) { } ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { - ngtcp2_tstamp res = UINT64_MAX, t; + ngtcp2_tstamp res = UINT64_MAX; ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); ngtcp2_scid *scid; ngtcp2_dcid *dcid; @@ -10916,21 +10958,19 @@ ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { } if (conn->pmtud) { - res = ngtcp2_min(res, conn->pmtud->expiry); + res = ngtcp2_min_uint64(res, conn->pmtud->expiry); } if (!ngtcp2_pq_empty(&conn->scid.used)) { scid = ngtcp2_struct_of(ngtcp2_pq_top(&conn->scid.used), ngtcp2_scid, pe); if (scid->retired_ts != UINT64_MAX) { - t = scid->retired_ts + pto; - res = ngtcp2_min(res, t); + res = ngtcp2_min_uint64(res, scid->retired_ts + pto); } } if (ngtcp2_ringbuf_len(&conn->dcid.retired.rb)) { dcid = ngtcp2_ringbuf_get(&conn->dcid.retired.rb, 0); - t = dcid->retired_ts + pto; - res = ngtcp2_min(res, t); + res = ngtcp2_min_uint64(res, dcid->retired_ts + pto); } if (conn->dcid.current.cid.datalen) { @@ -10941,15 +10981,13 @@ ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { assert(dcid->cid.datalen); assert(dcid->bound_ts != UINT64_MAX); - t = dcid->bound_ts + 3 * pto; - res = ngtcp2_min(res, t); + res = ngtcp2_min_uint64(res, dcid->bound_ts + 3 * pto); } } if (conn->server && conn->early.ckm && conn->early.discard_started_ts != UINT64_MAX) { - t = conn->early.discard_started_ts + 3 * pto; - res = ngtcp2_min(res, t); + res = ngtcp2_min_uint64(res, conn->early.discard_started_ts + 3 * pto); } return res; @@ -10969,7 +11007,7 @@ static ngtcp2_tstamp conn_handshake_expiry(ngtcp2_conn *conn) { if (conn_is_tls_handshake_completed(conn) || conn->local.settings.handshake_timeout == UINT64_MAX || conn->local.settings.initial_ts >= - UINT64_MAX - conn->local.settings.handshake_timeout) { + UINT64_MAX - conn->local.settings.handshake_timeout) { return UINT64_MAX; } @@ -10978,20 +11016,14 @@ static ngtcp2_tstamp conn_handshake_expiry(ngtcp2_conn *conn) { } ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn) { - ngtcp2_tstamp t1 = ngtcp2_conn_loss_detection_expiry(conn); - ngtcp2_tstamp t2 = ngtcp2_conn_ack_delay_expiry(conn); - ngtcp2_tstamp t3 = ngtcp2_conn_internal_expiry(conn); - ngtcp2_tstamp t4 = ngtcp2_conn_lost_pkt_expiry(conn); - ngtcp2_tstamp t5 = conn_keep_alive_expiry(conn); - ngtcp2_tstamp t6 = conn_handshake_expiry(conn); - ngtcp2_tstamp t7 = ngtcp2_conn_get_idle_expiry(conn); - ngtcp2_tstamp res = ngtcp2_min(t1, t2); - res = ngtcp2_min(res, t3); - res = ngtcp2_min(res, t4); - res = ngtcp2_min(res, t5); - res = ngtcp2_min(res, t6); - res = ngtcp2_min(res, t7); - return ngtcp2_min(res, conn->tx.pacing.next_ts); + ngtcp2_tstamp res = ngtcp2_min_uint64(ngtcp2_conn_loss_detection_expiry(conn), + ngtcp2_conn_ack_delay_expiry(conn)); + res = ngtcp2_min_uint64(res, ngtcp2_conn_internal_expiry(conn)); + res = ngtcp2_min_uint64(res, ngtcp2_conn_lost_pkt_expiry(conn)); + res = ngtcp2_min_uint64(res, conn_keep_alive_expiry(conn)); + res = ngtcp2_min_uint64(res, conn_handshake_expiry(conn)); + res = ngtcp2_min_uint64(res, ngtcp2_conn_get_idle_expiry(conn)); + return ngtcp2_min_uint64(res, conn->tx.pacing.next_ts); } int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts) { @@ -11089,7 +11121,7 @@ ngtcp2_tstamp ngtcp2_conn_lost_pkt_expiry(ngtcp2_conn *conn) { ts = ngtcp2_rtb_lost_pkt_ts(&conn->in_pktns->rtb); if (ts != UINT64_MAX) { ts += conn_compute_pto(conn, conn->in_pktns); - res = ngtcp2_min(res, ts); + res = ngtcp2_min_uint64(res, ts); } } @@ -11097,14 +11129,14 @@ ngtcp2_tstamp ngtcp2_conn_lost_pkt_expiry(ngtcp2_conn *conn) { ts = ngtcp2_rtb_lost_pkt_ts(&conn->hs_pktns->rtb); if (ts != UINT64_MAX) { ts += conn_compute_pto(conn, conn->hs_pktns); - res = ngtcp2_min(res, ts); + res = ngtcp2_min_uint64(res, ts); } } ts = ngtcp2_rtb_lost_pkt_ts(&conn->pktns.rtb); if (ts != UINT64_MAX) { ts += conn_compute_pto(conn, &conn->pktns); - res = ngtcp2_min(res, ts); + res = ngtcp2_min_uint64(res, ts); } return res; @@ -11153,7 +11185,7 @@ static uint32_t select_preferred_version(const uint32_t *preferred_versions, } for (j = 0, p = available_versions; j < available_versionslen; j += sizeof(uint32_t)) { - p = ngtcp2_get_uint32(&v, p); + p = ngtcp2_get_uint32be(&v, p); if (preferred_versions[i] == v) { return v; @@ -11266,13 +11298,13 @@ ngtcp2_conn_server_negotiate_version(ngtcp2_conn *conn, assert(conn->client_chosen_version == version_info->chosen_version); return select_preferred_version( - conn->vneg.preferred_versions, conn->vneg.preferred_versionslen, - version_info->chosen_version, version_info->available_versions, - version_info->available_versionslen, version_info->chosen_version); + conn->vneg.preferred_versions, conn->vneg.preferred_versionslen, + version_info->chosen_version, version_info->available_versions, + version_info->available_versionslen, version_info->chosen_version); } int ngtcp2_conn_set_remote_transport_params( - ngtcp2_conn *conn, const ngtcp2_transport_params *params) { + ngtcp2_conn *conn, const ngtcp2_transport_params *params) { int rv; /* We expect this function is called once per QUIC connection, but @@ -11315,9 +11347,9 @@ int ngtcp2_conn_set_remote_transport_params( if (params->version_info_present) { if (!vneg_available_versions_includes( - params->version_info.available_versions, - params->version_info.available_versionslen, - params->version_info.chosen_version)) { + params->version_info.available_versions, + params->version_info.available_versionslen, + params->version_info.chosen_version)) { return NGTCP2_ERR_TRANSPORT_PARAM; } @@ -11326,7 +11358,7 @@ int ngtcp2_conn_set_remote_transport_params( } conn->negotiated_version = - ngtcp2_conn_server_negotiate_version(conn, ¶ms->version_info); + ngtcp2_conn_server_negotiate_version(conn, ¶ms->version_info); if (conn->negotiated_version != conn->client_chosen_version) { rv = conn_call_version_negotiation(conn, conn->negotiated_version, &conn->rcid); @@ -11339,7 +11371,7 @@ int ngtcp2_conn_set_remote_transport_params( } conn->local.transport_params.version_info.chosen_version = - conn->negotiated_version; + conn->negotiated_version; ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "the negotiated version is 0x%08x", @@ -11372,7 +11404,7 @@ int ngtcp2_conn_set_remote_transport_params( assert(!conn->remote.pending_transport_params); rv = ngtcp2_transport_params_copy_new( - &conn->remote.pending_transport_params, params, conn->mem); + &conn->remote.pending_transport_params, params, conn->mem); if (rv != 0) { return rv; } @@ -11424,9 +11456,9 @@ ngtcp2_ssize ngtcp2_conn_encode_0rtt_transport_params(ngtcp2_conn *conn, params.initial_max_streams_bidi = src->initial_max_streams_bidi; params.initial_max_streams_uni = src->initial_max_streams_uni; params.initial_max_stream_data_bidi_local = - src->initial_max_stream_data_bidi_local; + src->initial_max_stream_data_bidi_local; params.initial_max_stream_data_bidi_remote = - src->initial_max_stream_data_bidi_remote; + src->initial_max_stream_data_bidi_remote; params.initial_max_stream_data_uni = src->initial_max_stream_data_uni; params.initial_max_data = src->initial_max_data; params.active_connection_id_limit = src->active_connection_id_limit; @@ -11456,7 +11488,7 @@ int ngtcp2_conn_decode_and_set_0rtt_transport_params(ngtcp2_conn *conn, } int ngtcp2_conn_set_0rtt_remote_transport_params( - ngtcp2_conn *conn, const ngtcp2_transport_params *params) { + ngtcp2_conn *conn, const ngtcp2_transport_params *params) { ngtcp2_transport_params *p; assert(!conn->server); @@ -11475,41 +11507,41 @@ int ngtcp2_conn_set_0rtt_remote_transport_params( p->initial_max_streams_bidi = params->initial_max_streams_bidi; p->initial_max_streams_uni = params->initial_max_streams_uni; p->initial_max_stream_data_bidi_local = - params->initial_max_stream_data_bidi_local; + params->initial_max_stream_data_bidi_local; p->initial_max_stream_data_bidi_remote = - params->initial_max_stream_data_bidi_remote; + params->initial_max_stream_data_bidi_remote; p->initial_max_stream_data_uni = params->initial_max_stream_data_uni; p->initial_max_data = params->initial_max_data; /* we might hit garbage, then set the sane default. */ p->active_connection_id_limit = - ngtcp2_max(NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT, - params->active_connection_id_limit); + ngtcp2_max_uint64(NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT, + params->active_connection_id_limit); p->max_datagram_frame_size = params->max_datagram_frame_size; /* we might hit garbage, then set the sane default. */ if (params->max_udp_payload_size) { - p->max_udp_payload_size = - ngtcp2_max(NGTCP2_MAX_UDP_PAYLOAD_SIZE, params->max_udp_payload_size); + p->max_udp_payload_size = ngtcp2_max_uint64(NGTCP2_MAX_UDP_PAYLOAD_SIZE, + params->max_udp_payload_size); } /* These parameters are treated specially. If server accepts early data, it must not set values for these parameters that are smaller than these remembered values. */ conn->early.transport_params.initial_max_streams_bidi = - params->initial_max_streams_bidi; + params->initial_max_streams_bidi; conn->early.transport_params.initial_max_streams_uni = - params->initial_max_streams_uni; + params->initial_max_streams_uni; conn->early.transport_params.initial_max_stream_data_bidi_local = - params->initial_max_stream_data_bidi_local; + params->initial_max_stream_data_bidi_local; conn->early.transport_params.initial_max_stream_data_bidi_remote = - params->initial_max_stream_data_bidi_remote; + params->initial_max_stream_data_bidi_remote; conn->early.transport_params.initial_max_stream_data_uni = - params->initial_max_stream_data_uni; + params->initial_max_stream_data_uni; conn->early.transport_params.initial_max_data = params->initial_max_data; conn->early.transport_params.active_connection_id_limit = - params->active_connection_id_limit; + params->active_connection_id_limit; conn->early.transport_params.max_datagram_frame_size = - params->max_datagram_frame_size; + params->max_datagram_frame_size; conn_sync_stream_id_limit(conn); @@ -11522,12 +11554,12 @@ int ngtcp2_conn_set_0rtt_remote_transport_params( } int ngtcp2_conn_set_local_transport_params_versioned( - ngtcp2_conn *conn, int transport_params_version, - const ngtcp2_transport_params *params) { + ngtcp2_conn *conn, int transport_params_version, + const ngtcp2_transport_params *params) { ngtcp2_transport_params paramsbuf; params = ngtcp2_transport_params_convert_to_latest( - ¶msbuf, transport_params_version, params); + ¶msbuf, transport_params_version, params); assert(conn->server); assert(params->active_connection_id_limit >= @@ -11576,7 +11608,7 @@ int ngtcp2_conn_commit_local_transport_params(ngtcp2_conn *conn) { } conn->rx.window = conn->rx.unsent_max_offset = conn->rx.max_offset = - params->initial_max_data; + params->initial_max_data; conn->remote.bidi.unsent_max_streams = params->initial_max_streams_bidi; conn->remote.bidi.max_streams = params->initial_max_streams_bidi; conn->remote.uni.unsent_max_streams = params->initial_max_streams_uni; @@ -11662,10 +11694,10 @@ ngtcp2_strm *ngtcp2_conn_find_stream(ngtcp2_conn *conn, int64_t stream_id) { } ngtcp2_ssize ngtcp2_conn_write_stream_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen, - uint32_t flags, int64_t stream_id, const uint8_t *data, size_t datalen, - ngtcp2_tstamp ts) { + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen, + uint32_t flags, int64_t stream_id, const uint8_t *data, size_t datalen, + ngtcp2_tstamp ts) { ngtcp2_vec datav; datav.len = datalen; @@ -11693,9 +11725,10 @@ static ngtcp2_ssize conn_write_vmsg_wrapper(ngtcp2_conn *conn, if (cstat->bytes_in_flight >= cstat->cwnd) { conn->rst.is_cwnd_limited = 1; - } - - if (nwrite == 0 && cstat->bytes_in_flight < cstat->cwnd) { + } else if ((cstat->cwnd >= cstat->ssthresh || + cstat->bytes_in_flight * 2 < cstat->cwnd) && + nwrite == 0 && conn_pacing_pkt_tx_allowed(conn, ts) && + (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) { conn->rst.app_limited = conn->rst.delivered + cstat->bytes_in_flight; if (conn->rst.app_limited == 0) { @@ -11707,10 +11740,10 @@ static ngtcp2_ssize conn_write_vmsg_wrapper(ngtcp2_conn *conn, } ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen, - uint32_t flags, int64_t stream_id, const ngtcp2_vec *datav, size_t datavcnt, - ngtcp2_tstamp ts) { + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen, + uint32_t flags, int64_t stream_id, const ngtcp2_vec *datav, size_t datavcnt, + ngtcp2_tstamp ts) { ngtcp2_vmsg vmsg, *pvmsg; ngtcp2_strm *strm; int64_t datalen; @@ -11734,19 +11767,24 @@ ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( return NGTCP2_ERR_INVALID_ARGUMENT; } - if ((uint64_t)datalen > NGTCP2_MAX_VARINT - strm->tx.offset || - (uint64_t)datalen > NGTCP2_MAX_VARINT - conn->tx.offset) { - return NGTCP2_ERR_INVALID_ARGUMENT; - } + if (datalen == 0 && !(flags & NGTCP2_WRITE_STREAM_FLAG_FIN) && + (strm->flags & NGTCP2_STRM_FLAG_ANY_SENT)) { + pvmsg = NULL; + } else { + if ((uint64_t)datalen > NGTCP2_MAX_VARINT - strm->tx.offset || + (uint64_t)datalen > NGTCP2_MAX_VARINT - conn->tx.offset) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } - vmsg.type = NGTCP2_VMSG_TYPE_STREAM; - vmsg.stream.strm = strm; - vmsg.stream.flags = flags; - vmsg.stream.data = datav; - vmsg.stream.datacnt = datavcnt; - vmsg.stream.pdatalen = pdatalen; + vmsg.type = NGTCP2_VMSG_TYPE_STREAM; + vmsg.stream.strm = strm; + vmsg.stream.flags = flags; + vmsg.stream.data = datav; + vmsg.stream.datacnt = datavcnt; + vmsg.stream.pdatalen = pdatalen; - pvmsg = &vmsg; + pvmsg = &vmsg; + } } else { pvmsg = NULL; } @@ -11756,10 +11794,10 @@ ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( } ngtcp2_ssize ngtcp2_conn_write_datagram_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, - uint32_t flags, uint64_t dgram_id, const uint8_t *data, size_t datalen, - ngtcp2_tstamp ts) { + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, + uint32_t flags, uint64_t dgram_id, const uint8_t *data, size_t datalen, + ngtcp2_tstamp ts) { ngtcp2_vec datav; datav.len = datalen; @@ -11771,10 +11809,10 @@ ngtcp2_ssize ngtcp2_conn_write_datagram_versioned( } ngtcp2_ssize ngtcp2_conn_writev_datagram_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, - uint32_t flags, uint64_t dgram_id, const ngtcp2_vec *datav, size_t datavcnt, - ngtcp2_tstamp ts) { + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, int *paccepted, + uint32_t flags, uint64_t dgram_id, const ngtcp2_vec *datav, size_t datavcnt, + ngtcp2_tstamp ts) { ngtcp2_vmsg vmsg; int64_t datalen; @@ -11837,7 +11875,7 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, } origlen = destlen = - conn_shape_udp_payload(conn, &conn->dcid.current, destlen); + conn_shape_udp_payload(conn, &conn->dcid.current, destlen); if (!ppe_pending && pi) { pi->ecn = NGTCP2_ECN_NOT_ECT; @@ -11867,10 +11905,9 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, assert(dest[0] & NGTCP2_HEADER_FORM_BIT); assert(conn->negotiated_version); - if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == - NGTCP2_PKT_INITIAL) { - /* We have added padding already, but in that case, there is no - space left to write 1RTT packet. */ + if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE && + ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == + NGTCP2_PKT_INITIAL) { wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } @@ -11890,7 +11927,7 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, return 0; } - origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left); + origlen = (size_t)ngtcp2_min_uint64((uint64_t)origlen, server_tx_left); } return conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts); @@ -11902,15 +11939,15 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, if (server_tx_left == 0) { if (cstat->loss_detection_timer != UINT64_MAX) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_LDC, - "loss detection timer canceled due to amplification limit"); - cstat->loss_detection_timer = UINT64_MAX; + &conn->log, NGTCP2_LOG_EVENT_LDC, + "loss detection timer canceled due to amplification limit"); + ngtcp2_conn_cancel_loss_detection_timer(conn); } return 0; } - destlen = (size_t)ngtcp2_min((uint64_t)destlen, server_tx_left); + destlen = (size_t)ngtcp2_min_uint64((uint64_t)destlen, server_tx_left); } if (conn->in_pktns) { @@ -11931,14 +11968,12 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, dest += nwrite; destlen -= (size_t)nwrite; - if (conn->in_pktns && nwrite > 0) { + if (res < NGTCP2_MAX_UDP_PAYLOAD_SIZE && conn->in_pktns && nwrite > 0) { it = ngtcp2_rtb_head(&conn->in_pktns->rtb); if (!ngtcp2_ksl_it_end(&it)) { rtbent = ngtcp2_ksl_it_get(&it); if (rtbent->hd.pkt_num != prev_in_pkt_num && (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { - /* We have added padding already, but in that case, there - is no space left to write 1RTT packet. */ wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } } @@ -11959,7 +11994,7 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, return 0; } - origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left); + origlen = (size_t)ngtcp2_min_uint64((uint64_t)origlen, server_tx_left); } return conn_write_ack_pkt(conn, pi, dest, origlen, NGTCP2_PKT_1RTT, ts); @@ -12004,12 +12039,12 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, } /* dest and destlen have already been adjusted in ppe in the first run. They are adjusted for probe packet later. */ - nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT, - wflags, ts); + nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg, + NGTCP2_PKT_1RTT, wflags, ts); goto fin; } else { conn->pkt.require_padding = - (wflags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING); + (wflags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING); if (conn->state == NGTCP2_CS_POST_HANDSHAKE) { rv = conn_prepare_key_update(conn, ts); @@ -12023,14 +12058,14 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, } else { if (res == 0) { nwrite = - conn_write_path_response(conn, path, pi, dest, origdestlen, ts); + conn_write_path_response(conn, path, pi, dest, origdestlen, ts); if (nwrite) { goto fin; } if (conn->pv) { nwrite = - conn_write_path_challenge(conn, path, pi, dest, origdestlen, ts); + conn_write_path_challenge(conn, path, pi, dest, origdestlen, ts); if (nwrite) { goto fin; } @@ -12051,15 +12086,15 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, if (conn->server && !(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED)) { server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); - origlen = (size_t)ngtcp2_min((uint64_t)origlen, server_tx_left); - destlen = (size_t)ngtcp2_min((uint64_t)destlen, server_tx_left); + origlen = (size_t)ngtcp2_min_uint64((uint64_t)origlen, server_tx_left); + destlen = (size_t)ngtcp2_min_uint64((uint64_t)destlen, server_tx_left); if (server_tx_left == 0 && conn->cstat.loss_detection_timer != UINT64_MAX) { ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_LDC, - "loss detection timer canceled due to amplification limit"); - conn->cstat.loss_detection_timer = UINT64_MAX; + &conn->log, NGTCP2_LOG_EVENT_LDC, + "loss detection timer canceled due to amplification limit"); + ngtcp2_conn_cancel_loss_detection_timer(conn); } } } @@ -12100,14 +12135,14 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, "transmit probe pkt left=%zu", conn->pktns.rtb.probe_pkt_left); - nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT, - wflags, ts); + nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg, + NGTCP2_PKT_1RTT, wflags, ts); goto fin; } - nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT, - wflags, ts); + nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg, + NGTCP2_PKT_1RTT, wflags, ts); if (nwrite) { assert(nwrite != NGTCP2_ERR_NOBUF); goto fin; @@ -12162,9 +12197,8 @@ conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, pkt_type != NGTCP2_PKT_INITIAL) { if (in_pktns && conn->server) { nwrite = ngtcp2_conn_write_single_frame_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, - NGTCP2_WRITE_PKT_FLAG_NONE, &conn->dcid.current.cid, &fr, - NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); + conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, NGTCP2_WRITE_PKT_FLAG_NONE, + &conn->dcid.current.cid, &fr, NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); if (nwrite < 0) { return nwrite; } @@ -12177,9 +12211,9 @@ conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (pkt_type != NGTCP2_PKT_HANDSHAKE && hs_pktns && hs_pktns->crypto.tx.ckm) { nwrite = ngtcp2_conn_write_single_frame_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, - NGTCP2_WRITE_PKT_FLAG_NONE, &conn->dcid.current.cid, &fr, - NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); + conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, + NGTCP2_WRITE_PKT_FLAG_NONE, &conn->dcid.current.cid, &fr, + NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); if (nwrite < 0) { return nwrite; } @@ -12195,8 +12229,8 @@ conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } nwrite = ngtcp2_conn_write_single_frame_pkt( - conn, pi, dest, destlen, pkt_type, flags, &conn->dcid.current.cid, &fr, - NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); + conn, pi, dest, destlen, pkt_type, flags, &conn->dcid.current.cid, &fr, + NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); if (nwrite < 0) { return nwrite; @@ -12212,9 +12246,9 @@ conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } ngtcp2_ssize ngtcp2_conn_write_connection_close_pkt( - ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, - size_t destlen, uint64_t error_code, const uint8_t *reason, - size_t reasonlen, ngtcp2_tstamp ts) { + ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, + size_t destlen, uint64_t error_code, const uint8_t *reason, size_t reasonlen, + ngtcp2_tstamp ts) { ngtcp2_pktns *in_pktns = conn->in_pktns; ngtcp2_pktns *hs_pktns = conn->hs_pktns; uint8_t pkt_type; @@ -12247,7 +12281,7 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close_pkt( if (conn->server) { server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); - destlen = (size_t)ngtcp2_min((uint64_t)destlen, server_tx_left); + destlen = (size_t)ngtcp2_min_uint64((uint64_t)destlen, server_tx_left); } if (conn->state == NGTCP2_CS_POST_HANDSHAKE || @@ -12275,9 +12309,9 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close_pkt( } ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( - ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, - size_t destlen, uint64_t app_error_code, const uint8_t *reason, - size_t reasonlen, ngtcp2_tstamp ts) { + ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, + size_t destlen, uint64_t app_error_code, const uint8_t *reason, + size_t reasonlen, ngtcp2_tstamp ts) { ngtcp2_ssize nwrite; ngtcp2_ssize res = 0; ngtcp2_frame fr; @@ -12309,15 +12343,14 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( if (conn->server) { server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); - destlen = (size_t)ngtcp2_min((uint64_t)destlen, server_tx_left); + destlen = (size_t)ngtcp2_min_uint64((uint64_t)destlen, server_tx_left); } if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)) { - nwrite = conn_write_connection_close(conn, pi, dest, destlen, - conn->hs_pktns->crypto.tx.ckm - ? NGTCP2_PKT_HANDSHAKE - : NGTCP2_PKT_INITIAL, - NGTCP2_APPLICATION_ERROR, NULL, 0, ts); + nwrite = conn_write_connection_close( + conn, pi, dest, destlen, + conn->hs_pktns->crypto.tx.ckm ? NGTCP2_PKT_HANDSHAKE : NGTCP2_PKT_INITIAL, + NGTCP2_APPLICATION_ERROR, NULL, 0, ts); if (nwrite < 0) { return nwrite; } @@ -12326,12 +12359,9 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( destlen -= (size_t)nwrite; } - if (conn->state != NGTCP2_CS_POST_HANDSHAKE) { - assert(res); - - if (!conn->server || !conn->pktns.crypto.tx.ckm) { - return res; - } + if (conn->state != NGTCP2_CS_POST_HANDSHAKE && + (!conn->server || !conn->pktns.crypto.tx.ckm)) { + return res; } assert(conn->pktns.crypto.tx.ckm); @@ -12343,8 +12373,8 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( fr.connection_close.reason = (uint8_t *)reason; nwrite = ngtcp2_conn_write_single_frame_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE, - &conn->dcid.current.cid, &fr, NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); + conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE, + &conn->dcid.current.cid, &fr, NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); if (nwrite < 0) { return nwrite; @@ -12392,12 +12422,22 @@ void ngtcp2_ccerr_set_liberr(ngtcp2_ccerr *ccerr, int liberr, ccerr_init(ccerr, NGTCP2_CCERR_TYPE_IDLE_CLOSE, NGTCP2_NO_ERROR, reason, reasonlen); + return; + case NGTCP2_ERR_DROP_CONN: + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_DROP_CONN, NGTCP2_NO_ERROR, reason, + reasonlen); + + return; + case NGTCP2_ERR_RETRY: + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_RETRY, NGTCP2_NO_ERROR, reason, + reasonlen); + return; }; ngtcp2_ccerr_set_transport_error( - ccerr, ngtcp2_err_infer_quic_transport_error_code(liberr), reason, - reasonlen); + ccerr, ngtcp2_err_infer_quic_transport_error_code(liberr), reason, + reasonlen); } void ngtcp2_ccerr_set_tls_alert(ngtcp2_ccerr *ccerr, uint8_t tls_alert, @@ -12415,9 +12455,9 @@ void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr, } ngtcp2_ssize ngtcp2_conn_write_connection_close_versioned( - ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, - ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, - const ngtcp2_ccerr *ccerr, ngtcp2_tstamp ts) { + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, const ngtcp2_ccerr *ccerr, + ngtcp2_tstamp ts) { (void)pkt_info_version; conn_update_timestamp(conn, ts); @@ -12425,12 +12465,12 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close_versioned( switch (ccerr->type) { case NGTCP2_CCERR_TYPE_TRANSPORT: return ngtcp2_conn_write_connection_close_pkt( - conn, path, pi, dest, destlen, ccerr->error_code, ccerr->reason, - ccerr->reasonlen, ts); + conn, path, pi, dest, destlen, ccerr->error_code, ccerr->reason, + ccerr->reasonlen, ts); case NGTCP2_CCERR_TYPE_APPLICATION: return ngtcp2_conn_write_application_close_pkt( - conn, path, pi, dest, destlen, ccerr->error_code, ccerr->reason, - ccerr->reasonlen, ts); + conn, path, pi, dest, destlen, ccerr->error_code, ccerr->reason, + ccerr->reasonlen, ts); default: return 0; } @@ -12471,7 +12511,7 @@ int ngtcp2_conn_close_stream(ngtcp2_conn *conn, ngtcp2_strm *strm) { int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm) { if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RDWR) == - NGTCP2_STRM_FLAG_SHUT_RDWR && + NGTCP2_STRM_FLAG_SHUT_RDWR && ((strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_RECVED) || ngtcp2_strm_rx_offset(strm) == strm->rx.last_offset) && (((strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM) && @@ -12537,7 +12577,7 @@ static int conn_shutdown_stream_read(ngtcp2_conn *conn, ngtcp2_strm *strm, which are not passed to application. */ if (!(strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_RECVED)) { ngtcp2_conn_extend_max_offset(conn, strm->rx.last_offset - - ngtcp2_strm_rx_offset(strm)); + ngtcp2_strm_rx_offset(strm)); } strm->flags |= NGTCP2_STRM_FLAG_STOP_SENDING; @@ -12720,20 +12760,20 @@ static void conn_discard_early_data_state(ngtcp2_conn *conn) { ngtcp2_rtb_remove_early_data(&conn->pktns.rtb, &conn->cstat); - ngtcp2_map_each_free(&conn->strms, delete_strms_pq_each, conn); + ngtcp2_map_each(&conn->strms, delete_strms_pq_each, conn); ngtcp2_map_clear(&conn->strms); conn->tx.offset = 0; conn->tx.last_blocked_offset = UINT64_MAX; conn->rx.unsent_max_offset = conn->rx.max_offset = - conn->local.transport_params.initial_max_data; + conn->local.transport_params.initial_max_data; conn->remote.bidi.unsent_max_streams = conn->remote.bidi.max_streams = - conn->local.transport_params.initial_max_streams_bidi; + conn->local.transport_params.initial_max_streams_bidi; conn->remote.uni.unsent_max_streams = conn->remote.uni.max_streams = - conn->local.transport_params.initial_max_streams_uni; + conn->local.transport_params.initial_max_streams_uni; if (conn->server) { conn->local.bidi.next_stream_id = 1; @@ -12778,6 +12818,8 @@ int 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); + if (cstat->min_rtt == UINT64_MAX) { cstat->latest_rtt = rtt; cstat->min_rtt = rtt; @@ -12788,43 +12830,43 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, if (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) { assert(conn->remote.transport_params); - ack_delay = - ngtcp2_min(ack_delay, conn->remote.transport_params->max_ack_delay); + ack_delay = ngtcp2_min_uint64( + ack_delay, conn->remote.transport_params->max_ack_delay); } else if (ack_delay > 0 && rtt >= cstat->min_rtt && rtt < cstat->min_rtt + ack_delay) { /* Ignore RTT sample if adjusting ack_delay causes the sample less than min_rtt before handshake confirmation. */ ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_LDC, - "ignore rtt sample because ack_delay is too large latest_rtt=%" PRIu64 - " min_rtt=%" PRIu64 " ack_delay=%" PRIu64, - rtt / NGTCP2_MILLISECONDS, cstat->min_rtt / NGTCP2_MILLISECONDS, - ack_delay / NGTCP2_MILLISECONDS); + &conn->log, NGTCP2_LOG_EVENT_LDC, + "ignore rtt sample because ack_delay is too large latest_rtt=%" PRIu64 + " min_rtt=%" PRIu64 " ack_delay=%" PRIu64, + rtt / NGTCP2_MILLISECONDS, cstat->min_rtt / NGTCP2_MILLISECONDS, + ack_delay / NGTCP2_MILLISECONDS); return NGTCP2_ERR_INVALID_ARGUMENT; } cstat->latest_rtt = rtt; - cstat->min_rtt = ngtcp2_min(cstat->min_rtt, rtt); + cstat->min_rtt = ngtcp2_min_uint64(cstat->min_rtt, rtt); if (rtt >= cstat->min_rtt + ack_delay) { rtt -= ack_delay; } cstat->rttvar = (cstat->rttvar * 3 + (cstat->smoothed_rtt < rtt - ? rtt - cstat->smoothed_rtt - : cstat->smoothed_rtt - rtt)) / + ? rtt - cstat->smoothed_rtt + : cstat->smoothed_rtt - rtt)) / 4; cstat->smoothed_rtt = (cstat->smoothed_rtt * 7 + rtt) / 8; } ngtcp2_log_info( - &conn->log, NGTCP2_LOG_EVENT_LDC, - "latest_rtt=%" PRIu64 " min_rtt=%" PRIu64 " smoothed_rtt=%" PRIu64 - " rttvar=%" PRIu64 " ack_delay=%" PRIu64, - cstat->latest_rtt / NGTCP2_MILLISECONDS, - cstat->min_rtt / NGTCP2_MILLISECONDS, - cstat->smoothed_rtt / NGTCP2_MILLISECONDS, - cstat->rttvar / NGTCP2_MILLISECONDS, ack_delay / NGTCP2_MILLISECONDS); + &conn->log, NGTCP2_LOG_EVENT_LDC, + "latest_rtt=%" PRIu64 " min_rtt=%" PRIu64 " smoothed_rtt=%" PRIu64 + " rttvar=%" PRIu64 " ack_delay=%" PRIu64, + cstat->latest_rtt / NGTCP2_MILLISECONDS, + cstat->min_rtt / NGTCP2_MILLISECONDS, + cstat->smoothed_rtt / NGTCP2_MILLISECONDS, + cstat->rttvar / NGTCP2_MILLISECONDS, ack_delay / NGTCP2_MILLISECONDS); return 0; } @@ -12879,8 +12921,8 @@ static ngtcp2_tstamp conn_get_earliest_pto_expiry(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat = &conn->cstat; ngtcp2_tstamp *times = cstat->last_tx_pkt_ts; ngtcp2_duration duration = - compute_pto(cstat->smoothed_rtt, cstat->rttvar, /* max_ack_delay = */ 0) * - (1ULL << cstat->pto_count); + compute_pto(cstat->smoothed_rtt, cstat->rttvar, /* max_ack_delay = */ 0) * + (1ULL << cstat->pto_count); for (i = NGTCP2_PKTNS_ID_INITIAL; i < NGTCP2_PKTNS_ID_MAX; ++i) { if (ns[i] == NULL || ns[i]->rtb.num_pto_eliciting == 0 || @@ -12939,8 +12981,7 @@ void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (cstat->loss_detection_timer != UINT64_MAX) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "loss detection timer canceled"); - cstat->loss_detection_timer = UINT64_MAX; - cstat->pto_count = 0; + ngtcp2_conn_cancel_loss_detection_timer(conn); } return; } @@ -12948,13 +12989,20 @@ void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { cstat->loss_detection_timer = conn_get_earliest_pto_expiry(conn, ts); timeout = - cstat->loss_detection_timer > ts ? cstat->loss_detection_timer - ts : 0; + cstat->loss_detection_timer > ts ? cstat->loss_detection_timer - ts : 0; ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "loss_detection_timer=%" PRIu64 " timeout=%" PRIu64, cstat->loss_detection_timer, timeout / NGTCP2_MILLISECONDS); } +void ngtcp2_conn_cancel_loss_detection_timer(ngtcp2_conn *conn) { + ngtcp2_conn_stat *cstat = &conn->cstat; + + cstat->loss_detection_timer = UINT64_MAX; + cstat->pto_count = 0; +} + int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ngtcp2_conn_stat *cstat = &conn->cstat; int rv; @@ -12966,8 +13014,7 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { switch (conn->state) { case NGTCP2_CS_CLOSING: case NGTCP2_CS_DRAINING: - cstat->loss_detection_timer = UINT64_MAX; - cstat->pto_count = 0; + ngtcp2_conn_cancel_loss_detection_timer(conn); return 0; default: break; @@ -13042,7 +13089,8 @@ static int conn_buffer_crypto_data(ngtcp2_conn *conn, const uint8_t **pdata, } if (!*pbufchain) { - rv = ngtcp2_buf_chain_new(pbufchain, ngtcp2_max(1024, datalen), conn->mem); + rv = ngtcp2_buf_chain_new(pbufchain, ngtcp2_max_size(1024, datalen), + conn->mem); if (rv != 0) { return rv; } @@ -13125,7 +13173,7 @@ int ngtcp2_conn_submit_new_token(ngtcp2_conn *conn, const uint8_t *token, assert(tokenlen); rv = ngtcp2_frame_chain_new_token_objalloc_new( - &nfrc, token, tokenlen, &conn->frc_objalloc, conn->mem); + &nfrc, token, tokenlen, &conn->frc_objalloc, conn->mem); if (rv != 0) { return rv; } @@ -13208,7 +13256,7 @@ static void copy_dcid_to_cid_token(ngtcp2_cid_token *dest, dest->cid = src->cid; ngtcp2_path_storage_init2(&dest->ps, &src->ps.path); if ((dest->token_present = - (src->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) != 0)) { + (src->flags & NGTCP2_DCID_FLAG_TOKEN_PRESENT) != 0)) { memcpy(dest->token, src->token, NGTCP2_STATELESS_RESET_TOKENLEN); } } @@ -13411,8 +13459,8 @@ uint64_t ngtcp2_conn_get_streams_bidi_left(ngtcp2_conn *conn) { uint64_t n = ngtcp2_ord_stream_id(conn->local.bidi.next_stream_id); return n > conn->local.bidi.max_streams - ? 0 - : conn->local.bidi.max_streams - n + 1; + ? 0 + : conn->local.bidi.max_streams - n + 1; } uint64_t ngtcp2_conn_get_streams_uni_left(ngtcp2_conn *conn) { @@ -13444,7 +13492,7 @@ ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) { conn->remote.transport_params->max_idle_timeout == 0 || (conn->local.transport_params.max_idle_timeout && conn->local.transport_params.max_idle_timeout < - conn->remote.transport_params->max_idle_timeout)) { + conn->remote.transport_params->max_idle_timeout)) { idle_timeout = conn->local.transport_params.max_idle_timeout; } else { idle_timeout = conn->remote.transport_params->max_idle_timeout; @@ -13455,10 +13503,10 @@ ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) { } trpto = 3 * conn_compute_pto(conn, conn_is_tls_handshake_completed(conn) - ? &conn->pktns - : conn->hs_pktns); + ? &conn->pktns + : conn->hs_pktns); - idle_timeout = ngtcp2_max(idle_timeout, trpto); + idle_timeout = ngtcp2_max_uint64(idle_timeout, trpto); if (conn->idle_ts >= UINT64_MAX - idle_timeout) { return UINT64_MAX; @@ -13469,8 +13517,8 @@ ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) { ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn) { return conn_compute_pto(conn, conn_is_tls_handshake_completed(conn) - ? &conn->pktns - : conn->hs_pktns); + ? &conn->pktns + : conn->hs_pktns); } void ngtcp2_conn_set_initial_crypto_ctx(ngtcp2_conn *conn, @@ -13581,8 +13629,8 @@ void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) { /* 1.25 is the under-utilization avoidance factor described in https://datatracker.ietf.org/doc/html/rfc9002#section-7.7 */ pacing_interval = (conn->cstat.first_rtt_sample_ts == UINT64_MAX - ? NGTCP2_MILLISECONDS - : conn->cstat.smoothed_rtt) * + ? NGTCP2_MILLISECONDS + : conn->cstat.smoothed_rtt) * 100 / 125 / conn->cstat.cwnd; } @@ -13597,20 +13645,11 @@ size_t ngtcp2_conn_get_send_quantum(ngtcp2_conn *conn) { } int ngtcp2_conn_track_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { - size_t i; - if (conn->dcid.retire_unacked.len >= ngtcp2_arraylen(conn->dcid.retire_unacked.seqs)) { return NGTCP2_ERR_CONNECTION_ID_LIMIT; } - /* Make sure that we do not have a duplicate */ - for (i = 0; i < conn->dcid.retire_unacked.len; ++i) { - if (conn->dcid.retire_unacked.seqs[i] == seq) { - ngtcp2_unreachable(); - } - } - conn->dcid.retire_unacked.seqs[conn->dcid.retire_unacked.len++] = seq; return 0; @@ -13626,7 +13665,7 @@ void ngtcp2_conn_untrack_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { if (i != conn->dcid.retire_unacked.len - 1) { conn->dcid.retire_unacked.seqs[i] = - conn->dcid.retire_unacked.seqs[conn->dcid.retire_unacked.len - 1]; + conn->dcid.retire_unacked.seqs[conn->dcid.retire_unacked.len - 1]; } --conn->dcid.retire_unacked.len; @@ -13635,6 +13674,18 @@ void ngtcp2_conn_untrack_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { } } +int ngtcp2_conn_check_retired_dcid_tracked(ngtcp2_conn *conn, uint64_t seq) { + size_t i; + + for (i = 0; i < conn->dcid.retire_unacked.len; ++i) { + if (conn->dcid.retire_unacked.seqs[i] == seq) { + return 1; + } + } + + return 0; +} + size_t ngtcp2_conn_get_stream_loss_count(ngtcp2_conn *conn, int64_t stream_id) { ngtcp2_strm *strm = ngtcp2_conn_find_stream(conn, stream_id); @@ -13652,56 +13703,17 @@ void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent, memcpy(pcent->data, data, sizeof(pcent->data)); } -void ngtcp2_settings_default_versioned(int settings_version, - ngtcp2_settings *settings) { - (void)settings_version; - - memset(settings, 0, sizeof(*settings)); - settings->cc_algo = NGTCP2_CC_ALGO_CUBIC; - settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT; - settings->ack_thresh = 2; - settings->max_tx_udp_payload_size = 1500 - 48; - settings->handshake_timeout = UINT64_MAX; -} - -void ngtcp2_transport_params_default_versioned( - int transport_params_version, ngtcp2_transport_params *params) { - size_t len; - - switch (transport_params_version) { - case NGTCP2_TRANSPORT_PARAMS_VERSION: - len = sizeof(*params); - - break; - default: - ngtcp2_unreachable(); - } - - memset(params, 0, len); - - switch (transport_params_version) { - case NGTCP2_TRANSPORT_PARAMS_VERSION: - params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; - params->active_connection_id_limit = - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; - params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; - params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; - - break; - } -} - /* The functions prefixed with ngtcp2_pkt_ are usually put inside ngtcp2_pkt.c. This function uses encryption construct and uses test data defined only in ngtcp2_conn_test.c, so it is written here. */ ngtcp2_ssize ngtcp2_pkt_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, - size_t reasonlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead, - const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, - ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp, - const ngtcp2_crypto_cipher_ctx *hp_ctx) { + 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, + size_t reasonlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, + ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp, + const ngtcp2_crypto_cipher_ctx *hp_ctx) { ngtcp2_pkt_hd hd; ngtcp2_crypto_km ckm; ngtcp2_crypto_cc cc; @@ -13726,7 +13738,7 @@ ngtcp2_ssize ngtcp2_pkt_write_connection_close( cc.encrypt = encrypt; cc.hp_mask = hp_mask; - ngtcp2_ppe_init(&ppe, dest, destlen, &cc); + ngtcp2_ppe_init(&ppe, dest, destlen, 0, &cc); rv = ngtcp2_ppe_encode_hd(&ppe, &hd); if (rv != 0) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h index 4ed67876bc3749..55073fcc828d73 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -65,9 +65,6 @@ typedef enum { NGTCP2_CS_DRAINING, } ngtcp2_conn_state; -/* NGTCP2_MAX_STREAMS is the maximum number of streams. */ -#define NGTCP2_MAX_STREAMS (1LL << 60) - /* NGTCP2_MAX_NUM_BUFFED_RX_PKTS is the maximum number of buffered reordered packets. */ #define NGTCP2_MAX_NUM_BUFFED_RX_PKTS 4 @@ -77,15 +74,6 @@ typedef enum { unreceived data. */ #define NGTCP2_MAX_REORDERED_CRYPTO_DATA 65536 -/* NGTCP2_MAX_RX_INITIAL_CRYPTO_DATA is the maximum offset of received - crypto stream in Initial packet. We set this hard limit here - because crypto stream is unbounded. */ -#define NGTCP2_MAX_RX_INITIAL_CRYPTO_DATA 65536 -/* NGTCP2_MAX_RX_HANDSHAKE_CRYPTO_DATA is the maximum offset of - received crypto stream in Handshake packet. We set this hard limit - here because crypto stream is unbounded. */ -#define NGTCP2_MAX_RX_HANDSHAKE_CRYPTO_DATA 65536 - /* NGTCP2_MAX_RETRIES is the number of Retry packet which client can accept. */ #define NGTCP2_MAX_RETRIES 3 @@ -121,12 +109,18 @@ typedef enum { /* NGTCP2_WRITE_PKT_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_WRITE_PKT_FLAG_NONE 0x00u /* NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING indicates that packet other - than Initial packet should be padded. Initial packet might be - padded based on QUIC requirement regardless of this flag. */ + than Initial packet should be padded so that UDP datagram payload + is at least NGTCP2_MAX_UDP_PAYLOAD_SIZE bytes. Initial packet + might be padded based on QUIC requirement regardless of this + flag. */ #define NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING 0x01u /* NGTCP2_WRITE_PKT_FLAG_MORE indicates that more frames might come and it should be encoded into the current packet. */ #define NGTCP2_WRITE_PKT_FLAG_MORE 0x02u +/* NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL is just like + NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING, but it requests to add + padding to the full UDP datagram payload size. */ +#define NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL 0x04u /* * ngtcp2_max_frame is defined so that it covers the largest ACK @@ -319,6 +313,7 @@ typedef struct ngtcp2_pktns { ngtcp2_acktr acktr; ngtcp2_rtb rtb; + ngtcp2_pktns_id id; } ngtcp2_pktns; typedef enum ngtcp2_ecn_state { @@ -342,15 +337,15 @@ typedef struct ngtcp2_early_transport_params { } ngtcp2_early_transport_params; ngtcp2_static_ringbuf_def(dcid_bound, NGTCP2_MAX_BOUND_DCID_POOL_SIZE, - sizeof(ngtcp2_dcid)); + sizeof(ngtcp2_dcid)) ngtcp2_static_ringbuf_def(dcid_unused, NGTCP2_MAX_DCID_POOL_SIZE, - sizeof(ngtcp2_dcid)); + sizeof(ngtcp2_dcid)) ngtcp2_static_ringbuf_def(dcid_retired, NGTCP2_MAX_DCID_RETIRED_SIZE, - sizeof(ngtcp2_dcid)); + sizeof(ngtcp2_dcid)) ngtcp2_static_ringbuf_def(path_challenge, 4, - sizeof(ngtcp2_path_challenge_entry)); + sizeof(ngtcp2_path_challenge_entry)) -ngtcp2_objalloc_decl(strm, ngtcp2_strm, oplent); +ngtcp2_objalloc_decl(strm, ngtcp2_strm, oplent) struct ngtcp2_conn { ngtcp2_objalloc frc_objalloc; @@ -813,6 +808,8 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts); +void ngtcp2_conn_cancel_loss_detection_timer(ngtcp2_conn *conn); + int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts); /* @@ -878,9 +875,9 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, * User-defined callback function failed. */ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( - ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, - uint8_t type, uint8_t flags, const ngtcp2_cid *dcid, ngtcp2_frame *fr, - uint16_t rtb_entry_flags, const ngtcp2_path *path, ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, + uint8_t type, uint8_t flags, const ngtcp2_cid *dcid, ngtcp2_frame *fr, + uint16_t rtb_entry_flags, const ngtcp2_path *path, ngtcp2_tstamp ts); /* * ngtcp2_conn_commit_local_transport_params commits the local @@ -973,6 +970,12 @@ int ngtcp2_conn_track_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq); */ void ngtcp2_conn_untrack_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq); +/* + * ngtcp2_conn_check_retired_dcid_tracked returns nonzero if |seq| has + * already been tracked. + */ +int ngtcp2_conn_check_retired_dcid_tracked(ngtcp2_conn *conn, uint64_t seq); + /* * ngtcp2_conn_server_negotiate_version negotiates QUIC version. It * is compatible version negotiation. It returns the negotiated QUIC @@ -1020,9 +1023,9 @@ ngtcp2_conn_server_negotiate_version(ngtcp2_conn *conn, * User callback failed */ ngtcp2_ssize ngtcp2_conn_write_connection_close_pkt( - ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, - size_t destlen, uint64_t error_code, const uint8_t *reason, - size_t reasonlen, ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, + size_t destlen, uint64_t error_code, const uint8_t *reason, size_t reasonlen, + ngtcp2_tstamp ts); /** * @function @@ -1066,9 +1069,9 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close_pkt( * User callback failed */ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( - ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, - size_t destlen, uint64_t app_error_code, const uint8_t *reason, - size_t reasonlen, ngtcp2_tstamp ts); + ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, + size_t destlen, uint64_t app_error_code, const uint8_t *reason, + size_t reasonlen, ngtcp2_tstamp ts); int ngtcp2_conn_start_pmtud(ngtcp2_conn *conn); @@ -1093,7 +1096,7 @@ void ngtcp2_conn_stop_pmtud(ngtcp2_conn *conn); * Out of memory. */ int ngtcp2_conn_set_remote_transport_params( - ngtcp2_conn *conn, const ngtcp2_transport_params *params); + ngtcp2_conn *conn, const ngtcp2_transport_params *params); /** * @function @@ -1132,7 +1135,7 @@ int ngtcp2_conn_set_remote_transport_params( * Out of memory. */ int ngtcp2_conn_set_0rtt_remote_transport_params( - ngtcp2_conn *conn, const ngtcp2_transport_params *params); + ngtcp2_conn *conn, const ngtcp2_transport_params *params); /* * ngtcp2_conn_create_ack_frame creates ACK frame, and assigns its @@ -1156,4 +1159,16 @@ int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, ngtcp2_tstamp ts, ngtcp2_duration ack_delay, uint64_t ack_delay_exponent); -#endif /* NGTCP2_CONN_H */ +/* + * ngtcp2_conn_discard_initial_state discards state for Initial packet + * number space. + */ +void ngtcp2_conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts); + +/* + * ngtcp2_conn_discard_handshake_state discards state for Handshake + * packet number space. + */ +void ngtcp2_conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts); + +#endif /* !defined(NGTCP2_CONN_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h index 1a93867aab3cae..ad2b7329f48df2 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -105,8 +105,9 @@ typedef struct ngtcp2_conn_stat { uint64_t bytes_in_flight; /** * :member:`max_tx_udp_payload_size` is the maximum size of UDP - * datagram payload that this endpoint transmits. It is used by - * congestion controller to compute congestion window. + * datagram payload that this endpoint transmits to the current + * path. It is used by congestion controller to compute congestion + * window. */ size_t max_tx_udp_payload_size; /** @@ -129,4 +130,4 @@ typedef struct ngtcp2_conn_stat { size_t send_quantum; } ngtcp2_conn_stat; -#endif /* NGTCP2_CONN_STAT_H */ +#endif /* !defined(NGTCP2_CONN_STAT_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c index 336721772b4e4c..6528011cc0edf4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c @@ -32,47 +32,37 @@ #include "ngtcp2_net.h" #include "ngtcp2_unreachable.h" -const uint8_t *ngtcp2_get_uint64(uint64_t *dest, const uint8_t *p) { - uint64_t n; - memcpy(&n, p, sizeof(n)); - *dest = ngtcp2_ntohl64(n); - return p + sizeof(n); -} - -const uint8_t *ngtcp2_get_uint48(uint64_t *dest, const uint8_t *p) { - uint64_t n = 0; - memcpy(((uint8_t *)&n) + 2, p, 6); - *dest = ngtcp2_ntohl64(n); - return p + 6; +const uint8_t *ngtcp2_get_uint64be(uint64_t *dest, const uint8_t *p) { + memcpy(dest, p, sizeof(*dest)); + *dest = ngtcp2_ntohl64(*dest); + return p + sizeof(*dest); } -const uint8_t *ngtcp2_get_uint32(uint32_t *dest, const uint8_t *p) { - uint32_t n; - memcpy(&n, p, sizeof(n)); - *dest = ngtcp2_ntohl(n); - return p + sizeof(n); +const uint8_t *ngtcp2_get_uint32be(uint32_t *dest, const uint8_t *p) { + memcpy(dest, p, sizeof(*dest)); + *dest = ngtcp2_ntohl(*dest); + return p + sizeof(*dest); } -const uint8_t *ngtcp2_get_uint24(uint32_t *dest, const uint8_t *p) { - uint32_t n = 0; - memcpy(((uint8_t *)&n) + 1, p, 3); - *dest = ngtcp2_ntohl(n); +const uint8_t *ngtcp2_get_uint24be(uint32_t *dest, const uint8_t *p) { + *dest = 0; + memcpy(((uint8_t *)dest) + 1, p, 3); + *dest = ngtcp2_ntohl(*dest); return p + 3; } -const uint8_t *ngtcp2_get_uint16(uint16_t *dest, const uint8_t *p) { - uint16_t n; - memcpy(&n, p, sizeof(n)); - *dest = ngtcp2_ntohs(n); - return p + sizeof(n); +const uint8_t *ngtcp2_get_uint16be(uint16_t *dest, const uint8_t *p) { + memcpy(dest, p, sizeof(*dest)); + *dest = ngtcp2_ntohs(*dest); + return p + sizeof(*dest); } -const uint8_t *ngtcp2_get_uint16be(uint16_t *dest, const uint8_t *p) { +const uint8_t *ngtcp2_get_uint16(uint16_t *dest, const uint8_t *p) { memcpy(dest, p, sizeof(*dest)); return p + sizeof(*dest); } -static uint64_t get_uvarint(size_t *plen, const uint8_t *p) { +static const uint8_t *get_uvarint(uint64_t *dest, const uint8_t *p) { union { uint8_t n8; uint16_t n16; @@ -80,42 +70,39 @@ static uint64_t get_uvarint(size_t *plen, const uint8_t *p) { uint64_t n64; } n; - *plen = (size_t)(1u << (*p >> 6)); - - switch (*plen) { + switch (*p >> 6) { + case 0: + *dest = *p++; + return p; case 1: - return *p; - case 2: memcpy(&n, p, 2); n.n8 &= 0x3f; - return ngtcp2_ntohs(n.n16); - case 4: + *dest = ngtcp2_ntohs(n.n16); + + return p + 2; + case 2: memcpy(&n, p, 4); n.n8 &= 0x3f; - return ngtcp2_ntohl(n.n32); - case 8: + *dest = ngtcp2_ntohl(n.n32); + + return p + 4; + case 3: memcpy(&n, p, 8); n.n8 &= 0x3f; - return ngtcp2_ntohl64(n.n64); + *dest = ngtcp2_ntohl64(n.n64); + + return p + 8; default: ngtcp2_unreachable(); } } const uint8_t *ngtcp2_get_uvarint(uint64_t *dest, const uint8_t *p) { - size_t len; - - *dest = get_uvarint(&len, p); - - return p + len; + return get_uvarint(dest, p); } const uint8_t *ngtcp2_get_varint(int64_t *dest, const uint8_t *p) { - size_t len; - - *dest = (int64_t)get_uvarint(&len, p); - - return p + len; + return get_uvarint((uint64_t *)dest, p); } int64_t ngtcp2_get_pkt_num(const uint8_t *p, size_t pkt_numlen) { @@ -126,13 +113,13 @@ int64_t ngtcp2_get_pkt_num(const uint8_t *p, size_t pkt_numlen) { case 1: return *p; case 2: - ngtcp2_get_uint16(&s, p); + ngtcp2_get_uint16be(&s, p); return (int64_t)s; case 3: - ngtcp2_get_uint24(&l, p); + ngtcp2_get_uint24be(&l, p); return (int64_t)l; case 4: - ngtcp2_get_uint32(&l, p); + ngtcp2_get_uint32be(&l, p); return (int64_t)l; default: ngtcp2_unreachable(); @@ -144,11 +131,6 @@ uint8_t *ngtcp2_put_uint64be(uint8_t *p, uint64_t n) { return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n)); } -uint8_t *ngtcp2_put_uint48be(uint8_t *p, uint64_t n) { - n = ngtcp2_htonl64(n); - return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 2, 6); -} - uint8_t *ngtcp2_put_uint32be(uint8_t *p, uint32_t n) { n = ngtcp2_htonl(n); return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n)); @@ -207,14 +189,11 @@ uint8_t *ngtcp2_put_pkt_num(uint8_t *p, int64_t pkt_num, size_t len) { *p++ = (uint8_t)pkt_num; return p; case 2: - ngtcp2_put_uint16be(p, (uint16_t)pkt_num); - return p + 2; + return ngtcp2_put_uint16be(p, (uint16_t)pkt_num); case 3: - ngtcp2_put_uint24be(p, (uint32_t)pkt_num); - return p + 3; + return ngtcp2_put_uint24be(p, (uint32_t)pkt_num); case 4: - ngtcp2_put_uint32be(p, (uint32_t)pkt_num); - return p + 4; + return ngtcp2_put_uint32be(p, (uint32_t)pkt_num); default: ngtcp2_unreachable(); } @@ -238,54 +217,6 @@ size_t ngtcp2_put_uvarintlen(uint64_t n) { return 8; } -int64_t ngtcp2_nth_server_bidi_id(uint64_t n) { - if (n == 0) { - return 0; - } - - if ((NGTCP2_MAX_VARINT >> 2) < n - 1) { - return NGTCP2_MAX_SERVER_STREAM_ID_BIDI; - } - - return (int64_t)(((n - 1) << 2) | 0x01); -} - -int64_t ngtcp2_nth_client_bidi_id(uint64_t n) { - if (n == 0) { - return 0; - } - - if ((NGTCP2_MAX_VARINT >> 2) < n - 1) { - return NGTCP2_MAX_CLIENT_STREAM_ID_BIDI; - } - - return (int64_t)((n - 1) << 2); -} - -int64_t ngtcp2_nth_server_uni_id(uint64_t n) { - if (n == 0) { - return 0; - } - - if ((NGTCP2_MAX_VARINT >> 2) < n - 1) { - return NGTCP2_MAX_SERVER_STREAM_ID_UNI; - } - - return (int64_t)(((n - 1) << 2) | 0x03); -} - -int64_t ngtcp2_nth_client_uni_id(uint64_t n) { - if (n == 0) { - return 0; - } - - if ((NGTCP2_MAX_VARINT >> 2) < n - 1) { - return NGTCP2_MAX_CLIENT_STREAM_ID_UNI; - } - - return (int64_t)(((n - 1) << 2) | 0x02); -} - uint64_t ngtcp2_ord_stream_id(int64_t stream_id) { return (uint64_t)(stream_id >> 2) + 1; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h index ef089a971a37f1..ad924683b8dc10 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.h @@ -27,51 +27,44 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include /* - * ngtcp2_get_uint64 reads 8 bytes from |p| as 64 bits unsigned + * ngtcp2_get_uint64be reads 8 bytes from |p| as 64 bits unsigned * integer encoded as network byte order, and stores it in the buffer * pointed by |dest| in host byte order. It returns |p| + 8. */ -const uint8_t *ngtcp2_get_uint64(uint64_t *dest, const uint8_t *p); +const uint8_t *ngtcp2_get_uint64be(uint64_t *dest, const uint8_t *p); /* - * ngtcp2_get_uint48 reads 6 bytes from |p| as 48 bits unsigned - * integer encoded as network byte order, and stores it in the buffer - * pointed by |dest| in host byte order. It returns |p| + 6. - */ -const uint8_t *ngtcp2_get_uint48(uint64_t *dest, const uint8_t *p); - -/* - * ngtcp2_get_uint32 reads 4 bytes from |p| as 32 bits unsigned + * ngtcp2_get_uint32be reads 4 bytes from |p| as 32 bits unsigned * integer encoded as network byte order, and stores it in the buffer * pointed by |dest| in host byte order. It returns |p| + 4. */ -const uint8_t *ngtcp2_get_uint32(uint32_t *dest, const uint8_t *p); +const uint8_t *ngtcp2_get_uint32be(uint32_t *dest, const uint8_t *p); /* - * ngtcp2_get_uint24 reads 3 bytes from |p| as 24 bits unsigned + * ngtcp2_get_uint24be reads 3 bytes from |p| as 24 bits unsigned * integer encoded as network byte order, and stores it in the buffer * pointed by |dest| in host byte order. It returns |p| + 3. */ -const uint8_t *ngtcp2_get_uint24(uint32_t *dest, const uint8_t *p); +const uint8_t *ngtcp2_get_uint24be(uint32_t *dest, const uint8_t *p); /* - * ngtcp2_get_uint16 reads 2 bytes from |p| as 16 bits unsigned + * ngtcp2_get_uint16be reads 2 bytes from |p| as 16 bits unsigned * integer encoded as network byte order, and stores it in the buffer * pointed by |dest| in host byte order. It returns |p| + 2. */ -const uint8_t *ngtcp2_get_uint16(uint16_t *dest, const uint8_t *p); +const uint8_t *ngtcp2_get_uint16be(uint16_t *dest, const uint8_t *p); /* - * ngtcp2_get_uint16be reads 2 bytes from |p| as 16 bits unsigned + * ngtcp2_get_uint16 reads 2 bytes from |p| as 16 bits unsigned * integer encoded as network byte order, and stores it in the buffer * pointed by |dest| as is. It returns |p| + 2. */ -const uint8_t *ngtcp2_get_uint16be(uint16_t *dest, const uint8_t *p); +const uint8_t *ngtcp2_get_uint16(uint16_t *dest, const uint8_t *p); /* * ngtcp2_get_uvarint reads variable-length unsigned integer from |p|, @@ -102,13 +95,6 @@ int64_t ngtcp2_get_pkt_num(const uint8_t *p, size_t pkt_numlen); */ uint8_t *ngtcp2_put_uint64be(uint8_t *p, uint64_t n); -/* - * ngtcp2_put_uint48be writes |n| in host byte order in |p| in network - * byte order. It writes only least significant 48 bits. It returns - * the one beyond of the last written position. - */ -uint8_t *ngtcp2_put_uint48be(uint8_t *p, uint64_t n); - /* * ngtcp2_put_uint32be writes |n| in host byte order in |p| in network * byte order. It returns the one beyond of the last written @@ -168,41 +154,9 @@ size_t ngtcp2_get_uvarintlen(const uint8_t *p); */ size_t ngtcp2_put_uvarintlen(uint64_t n); -/* - * ngtcp2_nth_server_bidi_id returns |n|-th server bidirectional - * stream ID. If |n| is 0, it returns 0. If the |n|-th stream ID is - * larger than NGTCP2_MAX_SERVER_STREAM_ID_BIDI, this function returns - * NGTCP2_MAX_SERVER_STREAM_ID_BIDI. - */ -int64_t ngtcp2_nth_server_bidi_id(uint64_t n); - -/* - * ngtcp2_nth_client_bidi_id returns |n|-th client bidirectional - * stream ID. If |n| is 0, it returns 0. If the |n|-th stream ID is - * larger than NGTCP2_MAX_CLIENT_STREAM_ID_BIDI, this function returns - * NGTCP2_MAX_CLIENT_STREAM_ID_BIDI. - */ -int64_t ngtcp2_nth_client_bidi_id(uint64_t n); - -/* - * ngtcp2_nth_server_uni_id returns |n|-th server unidirectional - * stream ID. If |n| is 0, it returns 0. If the |n|-th stream ID is - * larger than NGTCP2_MAX_SERVER_STREAM_ID_UNI, this function returns - * NGTCP2_MAX_SERVER_STREAM_ID_UNI. - */ -int64_t ngtcp2_nth_server_uni_id(uint64_t n); - -/* - * ngtcp2_nth_client_uni_id returns |n|-th client unidirectional - * stream ID. If |n| is 0, it returns 0. If the |n|-th stream ID is - * larger than NGTCP2_MAX_CLIENT_STREAM_ID_UNI, this function returns - * NGTCP2_MAX_CLIENT_STREAM_ID_UNI. - */ -int64_t ngtcp2_nth_client_uni_id(uint64_t n); - /* * ngtcp2_ord_stream_id returns the ordinal number of |stream_id|. */ uint64_t ngtcp2_ord_stream_id(int64_t stream_id); -#endif /* NGTCP2_CONV_H */ +#endif /* !defined(NGTCP2_CONV_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.c deleted file mode 100644 index eb85687a068449..00000000000000 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * ngtcp2 - * - * Copyright (c) 2023 ngtcp2 contributors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ngtcp2_conversion.h" - -#include -#include - -static void transport_params_copy(int transport_params_version, - ngtcp2_transport_params *dest, - const ngtcp2_transport_params *src) { - assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); - - switch (transport_params_version) { - case NGTCP2_TRANSPORT_PARAMS_V1: - memcpy(dest, src, - offsetof(ngtcp2_transport_params, version_info_present) + - sizeof(src->version_info_present)); - - break; - } -} - -const ngtcp2_transport_params * -ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest, - int transport_params_version, - const ngtcp2_transport_params *src) { - if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { - return src; - } - - ngtcp2_transport_params_default(dest); - - transport_params_copy(transport_params_version, dest, src); - - return dest; -} - -void ngtcp2_transport_params_convert_to_old( - int transport_params_version, ngtcp2_transport_params *dest, - const ngtcp2_transport_params *src) { - assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); - - transport_params_copy(transport_params_version, dest, src); -} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c index 0a3ecf6a2440cb..1f74e8c58397b1 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c @@ -27,11 +27,7 @@ #include #include -#include "ngtcp2_str.h" -#include "ngtcp2_conv.h" -#include "ngtcp2_conn.h" #include "ngtcp2_net.h" -#include "ngtcp2_conversion.h" int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret, size_t secretlen, @@ -46,9 +42,11 @@ int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret, if (secretlen) { memcpy((*pckm)->secret.base, secret, secretlen); } + if (aead_ctx) { (*pckm)->aead_ctx = *aead_ctx; } + memcpy((*pckm)->iv.base, iv, ivlen); return 0; @@ -85,825 +83,30 @@ void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem) { return; } + if (ckm->secret.len) { +#ifdef WIN32 + SecureZeroMemory(ckm->secret.base, ckm->secret.len); +#elif defined(HAVE_EXPLICIT_BZERO) + explicit_bzero(ckm->secret.base, ckm->secret.len); +#elif defined(HAVE_MEMSET_S) + memset_s(ckm->secret.base, ckm->secret.len, 0, ckm->secret.len); +#endif /* defined(HAVE_MEMSET_S) */ + } + ngtcp2_mem_free(mem, ckm); } void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen, int64_t pkt_num) { - size_t i; uint64_t n; - assert(ivlen >= 8); + assert(ivlen >= sizeof(n)); memcpy(dest, iv, ivlen); - n = ngtcp2_htonl64((uint64_t)pkt_num); - - for (i = 0; i < 8; ++i) { - dest[ivlen - 8 + i] ^= ((uint8_t *)&n)[i]; - } -} - -/* - * varint_paramlen returns the length of a single transport parameter - * which has variable integer in its parameter. - */ -static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) { - size_t valuelen = ngtcp2_put_uvarintlen(param); - return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(valuelen) + valuelen; -} - -/* - * write_varint_param writes parameter |id| of the given |value| in - * varint encoding. It returns p + the number of bytes written. - */ -static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id, - uint64_t value) { - p = ngtcp2_put_uvarint(p, id); - p = ngtcp2_put_uvarint(p, ngtcp2_put_uvarintlen(value)); - return ngtcp2_put_uvarint(p, value); -} - -/* - * zero_paramlen returns the length of a single transport parameter - * which has zero length value in its parameter. - */ -static size_t zero_paramlen(ngtcp2_transport_param_id id) { - return ngtcp2_put_uvarintlen(id) + 1; -} - -/* - * write_zero_param writes parameter |id| that has zero length value. - * It returns p + the number of bytes written. - */ -static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) { - p = ngtcp2_put_uvarint(p, id); - *p++ = 0; - - return p; -} - -/* - * cid_paramlen returns the length of a single transport parameter - * which has |cid| as value. - */ -static size_t cid_paramlen(ngtcp2_transport_param_id id, - const ngtcp2_cid *cid) { - return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(cid->datalen) + - cid->datalen; -} - -/* - * write_cid_param writes parameter |id| of the given |cid|. It - * returns p + the number of bytes written. - */ -static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id, - const ngtcp2_cid *cid) { - assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN); - assert(cid->datalen <= NGTCP2_MAX_CIDLEN); - - p = ngtcp2_put_uvarint(p, id); - p = ngtcp2_put_uvarint(p, cid->datalen); - if (cid->datalen) { - p = ngtcp2_cpymem(p, cid->data, cid->datalen); - } - return p; -} - -static const uint8_t empty_address[16]; - -ngtcp2_ssize ngtcp2_transport_params_encode_versioned( - uint8_t *dest, size_t destlen, int transport_params_version, - const ngtcp2_transport_params *params) { - uint8_t *p; - size_t len = 0; - /* For some reason, gcc 7.3.0 requires this initialization. */ - size_t preferred_addrlen = 0; - size_t version_infolen = 0; - const ngtcp2_sockaddr_in *sa_in; - const ngtcp2_sockaddr_in6 *sa_in6; - ngtcp2_transport_params paramsbuf; - - params = ngtcp2_transport_params_convert_to_latest( - ¶msbuf, transport_params_version, params); - - if (params->original_dcid_present) { - len += - cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, - ¶ms->original_dcid); - } - - if (params->stateless_reset_token_present) { - len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) + - ngtcp2_put_uvarintlen(NGTCP2_STATELESS_RESET_TOKENLEN) + - NGTCP2_STATELESS_RESET_TOKENLEN; - } - - if (params->preferred_addr_present) { - assert(params->preferred_addr.cid.datalen >= NGTCP2_MIN_CIDLEN); - assert(params->preferred_addr.cid.datalen <= NGTCP2_MAX_CIDLEN); - preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ + - 16 /* ipv6Address */ + 2 /* ipv6Port */ - + 1 + params->preferred_addr.cid.datalen /* CID */ + - NGTCP2_STATELESS_RESET_TOKENLEN; - len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) + - ngtcp2_put_uvarintlen(preferred_addrlen) + preferred_addrlen; - } - if (params->retry_scid_present) { - len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, - ¶ms->retry_scid); - } - - if (params->initial_scid_present) { - len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, - ¶ms->initial_scid); - } - - if (params->initial_max_stream_data_bidi_local) { - len += varint_paramlen( - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, - params->initial_max_stream_data_bidi_local); - } - if (params->initial_max_stream_data_bidi_remote) { - len += varint_paramlen( - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, - params->initial_max_stream_data_bidi_remote); - } - if (params->initial_max_stream_data_uni) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI, - params->initial_max_stream_data_uni); - } - if (params->initial_max_data) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA, - params->initial_max_data); - } - if (params->initial_max_streams_bidi) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI, - params->initial_max_streams_bidi); - } - if (params->initial_max_streams_uni) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, - params->initial_max_streams_uni); - } - if (params->max_udp_payload_size != - NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, - params->max_udp_payload_size); - } - if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, - params->ack_delay_exponent); - } - if (params->disable_active_migration) { - len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); - } - if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, - params->max_ack_delay / NGTCP2_MILLISECONDS); - } - if (params->max_idle_timeout) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT, - params->max_idle_timeout / NGTCP2_MILLISECONDS); - } - if (params->active_connection_id_limit && - params->active_connection_id_limit != - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT, - params->active_connection_id_limit); - } - if (params->max_datagram_frame_size) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE, - params->max_datagram_frame_size); - } - if (params->grease_quic_bit) { - len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); - } - if (params->version_info_present) { - version_infolen = - sizeof(uint32_t) + params->version_info.available_versionslen; - len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION) + - ngtcp2_put_uvarintlen(version_infolen) + version_infolen; - } - - if (dest == NULL && destlen == 0) { - return (ngtcp2_ssize)len; - } - - if (destlen < len) { - return NGTCP2_ERR_NOBUF; - } - - p = dest; - - if (params->original_dcid_present) { - p = write_cid_param( - p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, - ¶ms->original_dcid); - } - - if (params->stateless_reset_token_present) { - p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN); - p = ngtcp2_put_uvarint(p, sizeof(params->stateless_reset_token)); - p = ngtcp2_cpymem(p, params->stateless_reset_token, - sizeof(params->stateless_reset_token)); - } - - if (params->preferred_addr_present) { - p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS); - p = ngtcp2_put_uvarint(p, preferred_addrlen); - - if (params->preferred_addr.ipv4_present) { - sa_in = ¶ms->preferred_addr.ipv4; - p = ngtcp2_cpymem(p, &sa_in->sin_addr, sizeof(sa_in->sin_addr)); - p = ngtcp2_put_uint16(p, sa_in->sin_port); - } else { - p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in->sin_addr)); - p = ngtcp2_put_uint16(p, 0); - } - - if (params->preferred_addr.ipv6_present) { - sa_in6 = ¶ms->preferred_addr.ipv6; - p = ngtcp2_cpymem(p, &sa_in6->sin6_addr, sizeof(sa_in6->sin6_addr)); - p = ngtcp2_put_uint16(p, sa_in6->sin6_port); - } else { - p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in6->sin6_addr)); - p = ngtcp2_put_uint16(p, 0); - } - - *p++ = (uint8_t)params->preferred_addr.cid.datalen; - if (params->preferred_addr.cid.datalen) { - p = ngtcp2_cpymem(p, params->preferred_addr.cid.data, - params->preferred_addr.cid.datalen); - } - p = ngtcp2_cpymem(p, params->preferred_addr.stateless_reset_token, - sizeof(params->preferred_addr.stateless_reset_token)); - } - - if (params->retry_scid_present) { - p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, - ¶ms->retry_scid); - } - - if (params->initial_scid_present) { - p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, - ¶ms->initial_scid); - } - - if (params->initial_max_stream_data_bidi_local) { - p = write_varint_param( - p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, - params->initial_max_stream_data_bidi_local); - } - - if (params->initial_max_stream_data_bidi_remote) { - p = write_varint_param( - p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, - params->initial_max_stream_data_bidi_remote); - } - - if (params->initial_max_stream_data_uni) { - p = write_varint_param(p, - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI, - params->initial_max_stream_data_uni); - } - - if (params->initial_max_data) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA, - params->initial_max_data); - } - - if (params->initial_max_streams_bidi) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI, - params->initial_max_streams_bidi); - } - - if (params->initial_max_streams_uni) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, - params->initial_max_streams_uni); - } - - if (params->max_udp_payload_size != - NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, - params->max_udp_payload_size); - } - - if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, - params->ack_delay_exponent); - } - - if (params->disable_active_migration) { - p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); - } - - if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, - params->max_ack_delay / NGTCP2_MILLISECONDS); - } - - if (params->max_idle_timeout) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT, - params->max_idle_timeout / NGTCP2_MILLISECONDS); - } - - if (params->active_connection_id_limit && - params->active_connection_id_limit != - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT, - params->active_connection_id_limit); - } - - if (params->max_datagram_frame_size) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE, - params->max_datagram_frame_size); - } - - if (params->grease_quic_bit) { - p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); - } - - if (params->version_info_present) { - p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION); - p = ngtcp2_put_uvarint(p, version_infolen); - p = ngtcp2_put_uint32be(p, params->version_info.chosen_version); - if (params->version_info.available_versionslen) { - p = ngtcp2_cpymem(p, params->version_info.available_versions, - params->version_info.available_versionslen); - } - } - - assert((size_t)(p - dest) == len); - - return (ngtcp2_ssize)len; -} - -/* - * decode_varint decodes a single varint from the buffer pointed by - * |*pp| of length |end - *pp|. If it decodes an integer - * successfully, it stores the integer in |*pdest|, increment |*pp| by - * the number of bytes read from |*pp|, and returns 0. Otherwise it - * returns -1. - */ -static int decode_varint(uint64_t *pdest, const uint8_t **pp, - const uint8_t *end) { - const uint8_t *p = *pp; - size_t len; - - if (p == end) { - return -1; - } - - len = ngtcp2_get_uvarintlen(p); - if ((uint64_t)(end - p) < len) { - return -1; - } - - *pp = ngtcp2_get_uvarint(pdest, p); - - return 0; -} - -/* - * decode_varint_param decodes length prefixed value from the buffer - * pointed by |*pp| of length |end - *pp|. The length and value are - * encoded in varint form. If it decodes a value successfully, it - * stores the value in |*pdest|, increment |*pp| by the number of - * bytes read from |*pp|, and returns 0. Otherwise it returns -1. - */ -static int decode_varint_param(uint64_t *pdest, const uint8_t **pp, - const uint8_t *end) { - const uint8_t *p = *pp; - uint64_t valuelen; - - if (decode_varint(&valuelen, &p, end) != 0) { - return -1; - } - - if (p == end) { - return -1; - } - - if ((uint64_t)(end - p) < valuelen) { - return -1; - } - - if (ngtcp2_get_uvarintlen(p) != valuelen) { - return -1; - } - - *pp = ngtcp2_get_uvarint(pdest, p); - - return 0; -} - -/* - * decode_zero_param decodes zero length value from the buffer pointed - * by |*pp| of length |end - *pp|. The length is encoded in varint - * form. If it decodes zero length value successfully, it increments - * |*pp| by 1, and returns 0. Otherwise it returns -1. - */ -static int decode_zero_param(const uint8_t **pp, const uint8_t *end) { - if (*pp == end || **pp != 0) { - return -1; - } - - ++*pp; - - return 0; -} - -/* - * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer - * pointed by |*pp| of length |end - *pp|. The length is encoded in - * varint form. If it decodes a value successfully, it stores the - * value in |*pdest|, increment |*pp| by the number of read from - * |*pp|, and returns the number of bytes read. Otherwise it returns - * the one of the negative error code: - * - * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM - * Could not decode Connection ID. - */ -static int decode_cid_param(ngtcp2_cid *pdest, const uint8_t **pp, - const uint8_t *end) { - const uint8_t *p = *pp; - uint64_t valuelen; - - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) || - valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - ngtcp2_cid_init(pdest, p, (size_t)valuelen); - - p += valuelen; - - *pp = p; - - return 0; -} - -int ngtcp2_transport_params_decode_versioned(int transport_params_version, - ngtcp2_transport_params *dest, - const uint8_t *data, - size_t datalen) { - const uint8_t *p, *end, *lend; - size_t len; - uint64_t param_type; - uint64_t valuelen; - int rv; - ngtcp2_sockaddr_in *sa_in; - ngtcp2_sockaddr_in6 *sa_in6; - uint32_t version; - ngtcp2_transport_params *params, paramsbuf; - if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { - params = dest; - } else { - params = ¶msbuf; - } - - /* Set default values */ - memset(params, 0, sizeof(*params)); - params->original_dcid_present = 0; - params->initial_scid_present = 0; - params->initial_max_streams_bidi = 0; - params->initial_max_streams_uni = 0; - params->initial_max_stream_data_bidi_local = 0; - params->initial_max_stream_data_bidi_remote = 0; - params->initial_max_stream_data_uni = 0; - params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; - params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; - params->stateless_reset_token_present = 0; - params->preferred_addr_present = 0; - params->disable_active_migration = 0; - params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; - params->max_idle_timeout = 0; - params->active_connection_id_limit = - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; - params->retry_scid_present = 0; - params->max_datagram_frame_size = 0; - memset(¶ms->retry_scid, 0, sizeof(params->retry_scid)); - memset(¶ms->initial_scid, 0, sizeof(params->initial_scid)); - memset(¶ms->original_dcid, 0, sizeof(params->original_dcid)); - params->version_info_present = 0; - - p = data; - end = data + datalen; - - for (; (size_t)(end - p) >= 2;) { - if (decode_varint(¶m_type, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - switch (param_type) { - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: - if (decode_varint_param(¶ms->initial_max_stream_data_bidi_local, &p, - end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: - if (decode_varint_param(¶ms->initial_max_stream_data_bidi_remote, &p, - end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI: - if (decode_varint_param(¶ms->initial_max_stream_data_uni, &p, end) != - 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA: - if (decode_varint_param(¶ms->initial_max_data, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI: - if (decode_varint_param(¶ms->initial_max_streams_bidi, &p, end) != - 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI: - if (decode_varint_param(¶ms->initial_max_streams_uni, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT: - if (decode_varint_param(¶ms->max_idle_timeout, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - params->max_idle_timeout *= NGTCP2_MILLISECONDS; - break; - case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE: - if (decode_varint_param(¶ms->max_udp_payload_size, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN: - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)valuelen != sizeof(params->stateless_reset_token)) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - p = ngtcp2_get_bytes(params->stateless_reset_token, p, - sizeof(params->stateless_reset_token)); - params->stateless_reset_token_present = 1; - - break; - case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT: - if (decode_varint_param(¶ms->ack_delay_exponent, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->ack_delay_exponent > 20) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS: - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)(end - p) < valuelen) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ + - 2 /* ipv6Port */ - + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN; - if (valuelen < len) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - sa_in = ¶ms->preferred_addr.ipv4; - - p = ngtcp2_get_bytes(&sa_in->sin_addr, p, sizeof(sa_in->sin_addr)); - p = ngtcp2_get_uint16be(&sa_in->sin_port, p); - - if (sa_in->sin_port || memcmp(empty_address, &sa_in->sin_addr, - sizeof(sa_in->sin_addr)) != 0) { - sa_in->sin_family = NGTCP2_AF_INET; - params->preferred_addr.ipv4_present = 1; - } - - sa_in6 = ¶ms->preferred_addr.ipv6; - - p = ngtcp2_get_bytes(&sa_in6->sin6_addr, p, sizeof(sa_in6->sin6_addr)); - p = ngtcp2_get_uint16be(&sa_in6->sin6_port, p); - - if (sa_in6->sin6_port || memcmp(empty_address, &sa_in6->sin6_addr, - sizeof(sa_in6->sin6_addr)) != 0) { - sa_in6->sin6_family = NGTCP2_AF_INET6; - params->preferred_addr.ipv6_present = 1; - } - - /* cid */ - params->preferred_addr.cid.datalen = *p++; - len += params->preferred_addr.cid.datalen; - if (valuelen != len || - params->preferred_addr.cid.datalen > NGTCP2_MAX_CIDLEN || - params->preferred_addr.cid.datalen < NGTCP2_MIN_CIDLEN) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->preferred_addr.cid.datalen) { - p = ngtcp2_get_bytes(params->preferred_addr.cid.data, p, - params->preferred_addr.cid.datalen); - } - - /* stateless reset token */ - p = ngtcp2_get_bytes( - params->preferred_addr.stateless_reset_token, p, - sizeof(params->preferred_addr.stateless_reset_token)); - params->preferred_addr_present = 1; - break; - case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION: - if (decode_zero_param(&p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - params->disable_active_migration = 1; - break; - case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID: - rv = decode_cid_param(¶ms->original_dcid, &p, end); - if (rv != 0) { - return rv; - } - params->original_dcid_present = 1; - break; - case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID: - rv = decode_cid_param(¶ms->retry_scid, &p, end); - if (rv != 0) { - return rv; - } - params->retry_scid_present = 1; - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID: - rv = decode_cid_param(¶ms->initial_scid, &p, end); - if (rv != 0) { - return rv; - } - params->initial_scid_present = 1; - break; - case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY: - if (decode_varint_param(¶ms->max_ack_delay, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->max_ack_delay >= 16384) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - params->max_ack_delay *= NGTCP2_MILLISECONDS; - break; - case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT: - if (decode_varint_param(¶ms->active_connection_id_limit, &p, end) != - 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE: - if (decode_varint_param(¶ms->max_datagram_frame_size, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT: - if (decode_zero_param(&p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - params->grease_quic_bit = 1; - break; - case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION: - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)(end - p) < valuelen) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - p = ngtcp2_get_uint32(¶ms->version_info.chosen_version, p); - if (params->version_info.chosen_version == 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (valuelen > sizeof(uint32_t)) { - params->version_info.available_versions = (uint8_t *)p; - params->version_info.available_versionslen = - (size_t)valuelen - sizeof(uint32_t); - - for (lend = p + (valuelen - sizeof(uint32_t)); p != lend;) { - p = ngtcp2_get_uint32(&version, p); - if (version == 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - } - } - params->version_info_present = 1; - break; - default: - /* Ignore unknown parameter */ - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)(end - p) < valuelen) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - p += valuelen; - break; - } - } - - if (end - p != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - if (transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION) { - ngtcp2_transport_params_convert_to_old(transport_params_version, dest, - params); - } - - return 0; -} - -static int transport_params_copy_new(ngtcp2_transport_params **pdest, - const ngtcp2_transport_params *src, - const ngtcp2_mem *mem) { - size_t len = sizeof(**pdest); - ngtcp2_transport_params *dest; - uint8_t *p; - - if (src->version_info_present) { - len += src->version_info.available_versionslen; - } - - dest = ngtcp2_mem_malloc(mem, len); - if (dest == NULL) { - return NGTCP2_ERR_NOMEM; - } - - *dest = *src; - - if (src->version_info_present && src->version_info.available_versionslen) { - p = (uint8_t *)dest + sizeof(*dest); - memcpy(p, src->version_info.available_versions, - src->version_info.available_versionslen); - dest->version_info.available_versions = p; - } - - *pdest = dest; - - return 0; -} - -int ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams, - const uint8_t *data, size_t datalen, - const ngtcp2_mem *mem) { - int rv; - ngtcp2_transport_params params; - - rv = ngtcp2_transport_params_decode(¶ms, data, datalen); - if (rv < 0) { - return rv; - } - - if (mem == NULL) { - mem = ngtcp2_mem_default(); - } - - return transport_params_copy_new(pparams, ¶ms, mem); -} - -void ngtcp2_transport_params_del(ngtcp2_transport_params *params, - const ngtcp2_mem *mem) { - if (params == NULL) { - return; - } - - if (mem == NULL) { - mem = ngtcp2_mem_default(); - } - - ngtcp2_mem_free(mem, params); -} - -int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest, - const ngtcp2_transport_params *src, - const ngtcp2_mem *mem) { - if (src == NULL) { - *pdest = NULL; - return 0; - } + dest += ivlen - sizeof(n); - return transport_params_copy_new(pdest, src, mem); + memcpy(&n, dest, sizeof(n)); + n ^= ngtcp2_htonl64((uint64_t)pkt_num); + memcpy(dest, &n, sizeof(n)); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h index b78429bb38f582..ca6d494846f324 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -38,36 +38,9 @@ bytes. */ #define NGTCP2_INITIAL_AEAD_OVERHEAD 16 -/* NGTCP2_MAX_AEAD_OVERHEAD is expected maximum AEAD overhead. */ +/* NGTCP2_MAX_AEAD_OVERHEAD is the maximum AEAD overhead. */ #define NGTCP2_MAX_AEAD_OVERHEAD 16 -/* ngtcp2_transport_param_id is the registry of QUIC transport - parameter ID. */ -typedef uint64_t ngtcp2_transport_param_id; - -#define NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID 0x00 -#define NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT 0x01 -#define NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN 0x02 -#define NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE 0x03 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA 0x04 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI 0x07 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI 0x08 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI 0x09 -#define NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT 0x0a -#define NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY 0x0b -#define NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION 0x0c -#define NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS 0x0d -#define NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT 0x0e -#define NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID 0x0f -#define NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID 0x10 -/* https://datatracker.ietf.org/doc/html/rfc9221 */ -#define NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE 0x20 -#define NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT 0x2ab2 -/* https://datatracker.ietf.org/doc/html/rfc9368 */ -#define NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION 0x11 - /* NGTCP2_CRYPTO_KM_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_CRYPTO_KM_FLAG_NONE 0x00u /* NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE is set if key phase bit is @@ -83,8 +56,7 @@ typedef struct ngtcp2_crypto_km { a packet. For decryption key, it is the lowest packet number of a packet which can be decrypted with this keying material. */ int64_t pkt_num; - /* use_count is the number of encryption applied with this key. - This field is only used for tx key. */ + /* use_count is the number of encryption applied with this key. */ uint64_t use_count; /* flags is the bitwise OR of zero or more of NGTCP2_CRYPTO_KM_FLAG_*. */ @@ -92,12 +64,12 @@ typedef struct ngtcp2_crypto_km { } ngtcp2_crypto_km; /* - * ngtcp2_crypto_km_new creates new ngtcp2_crypto_km object and + * ngtcp2_crypto_km_new creates new ngtcp2_crypto_km object, and * assigns its pointer to |*pckm|. The |secret| of length - * |secretlen|, the |key| of length |keylen| and the |iv| of length - * |ivlen| are copied to |*pckm|. If |secretlen| == 0, the function - * assumes no secret is given which is acceptable. The sole reason to - * store secret is update keys. Only 1RTT key can be updated. + * |secretlen|, |aead_ctx|, and the |iv| of length |ivlen| are copied + * to |*pckm|. If |secretlen| == 0, the function assumes no secret is + * given which is acceptable. The sole reason to store secret is + * update keys. Only 1RTT key can be updated. */ int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret, size_t secretlen, @@ -107,7 +79,7 @@ int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret, /* * ngtcp2_crypto_km_nocopy_new is similar to ngtcp2_crypto_km_new, but - * it does not copy secret, key and IV. + * it does not copy secret, aead context, and IV. */ int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen, size_t ivlen, const ngtcp2_mem *mem); @@ -127,21 +99,4 @@ typedef struct ngtcp2_crypto_cc { void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen, int64_t pkt_num); -/* - * ngtcp2_transport_params_copy_new makes a copy of |src|, and assigns - * it to |*pdest|. If |src| is NULL, NULL is assigned to |*pdest|. - * - * Caller is responsible to call ngtcp2_transport_params_del to free - * the memory assigned to |*pdest|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest, - const ngtcp2_transport_params *src, - const ngtcp2_mem *mem); - -#endif /* NGTCP2_CRYPTO_H */ +#endif /* !defined(NGTCP2_CRYPTO_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_err.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_err.h index 9229f5425a63cf..44527b11bdec47 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_err.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_err.h @@ -27,8 +27,8 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include -#endif /* NGTCP2_ERR_H */ +#endif /* !defined(NGTCP2_ERR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c index 41c2a6a755cc8a..6a8a22c3f0d010 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c @@ -27,7 +27,7 @@ #include #include -ngtcp2_objalloc_def(frame_chain, ngtcp2_frame_chain, oplent); +ngtcp2_objalloc_def(frame_chain, ngtcp2_frame_chain, oplent) int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem) { *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain)); @@ -68,14 +68,11 @@ int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, size_t datacnt, ngtcp2_objalloc *objalloc, const ngtcp2_mem *mem) { - size_t need, avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream); - - if (datacnt > 1) { - need = sizeof(ngtcp2_vec) * (datacnt - 1); - - if (need > avail) { - return ngtcp2_frame_chain_extralen_new(pfrc, need - avail, mem); - } + if (datacnt > NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES) { + return ngtcp2_frame_chain_extralen_new(pfrc, + sizeof(ngtcp2_vec) * (datacnt - 1) - + NGTCP2_FRAME_CHAIN_STREAM_AVAIL, + mem); } return ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); @@ -139,9 +136,7 @@ void ngtcp2_frame_chain_objalloc_del(ngtcp2_frame_chain *frc, switch (frc->fr.type) { case NGTCP2_FRAME_CRYPTO: case NGTCP2_FRAME_STREAM: - if (frc->fr.stream.datacnt && - sizeof(ngtcp2_vec) * (frc->fr.stream.datacnt - 1) > - sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream)) { + if (frc->fr.stream.datacnt > NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES) { ngtcp2_frame_chain_del(frc, mem); return; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h index 656fa5b799450e..e5b6779c0f03c2 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -74,7 +74,7 @@ struct ngtcp2_frame_chain { }; }; -ngtcp2_objalloc_decl(frame_chain, ngtcp2_frame_chain, oplent); +ngtcp2_objalloc_decl(frame_chain, ngtcp2_frame_chain, oplent) /* * ngtcp2_bind_frame_chains binds two frame chains |a| and |b| using @@ -121,12 +121,29 @@ int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc, int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen, const ngtcp2_mem *mem); +/* NGTCP2_FRAME_CHAIN_STREAM_AVAIL is the number of additional bytes + available after ngtcp2_stream when it is embedded in + ngtcp2_frame. */ +#define NGTCP2_FRAME_CHAIN_STREAM_AVAIL \ + (sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream)) + +/* NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES is the number of datacnt + that changes allocation method. If datacnt is more than this + value, ngtcp2_frame_chain is allocated without ngtcp2_objalloc. + Otherwise, it is allocated using ngtcp2_objalloc. */ +#define NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES \ + (NGTCP2_FRAME_CHAIN_STREAM_AVAIL / sizeof(ngtcp2_vec) + 1) + /* * ngtcp2_frame_chain_stream_datacnt_objalloc_new works like * ngtcp2_frame_chain_new, but it allocates enough data to store * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_stream - * object. If no additional space is required, - * ngtcp2_frame_chain_objalloc_new is called internally. + * object. If no additional space is required, in other words, + * |datacnt| <= NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES, + * ngtcp2_frame_chain_objalloc_new is called internally. Otherwise, + * ngtcp2_frame_chain_extralen_new is used and objalloc is not used. + * Therefore, it is important to call ngtcp2_frame_chain_objalloc_del + * without changing datacnt field. */ int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, size_t datacnt, @@ -168,4 +185,4 @@ void ngtcp2_frame_chain_list_objalloc_del(ngtcp2_frame_chain *frc, ngtcp2_objalloc *objalloc, const ngtcp2_mem *mem); -#endif /* NGTCP2_FRAME_CHAIN_H */ +#endif /* !defined(NGTCP2_FRAME_CHAIN_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c index 87c23898e8207d..3bfa398480c382 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c @@ -28,22 +28,16 @@ #include void ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem) { - ngtcp2_ksl_init(&gaptr->gap, ngtcp2_ksl_range_compar, sizeof(ngtcp2_range), - mem); + ngtcp2_ksl_init(&gaptr->gap, ngtcp2_ksl_range_compar, ngtcp2_ksl_range_search, + sizeof(ngtcp2_range), mem); gaptr->mem = mem; } static int gaptr_gap_init(ngtcp2_gaptr *gaptr) { ngtcp2_range range = {0, UINT64_MAX}; - int rv; - - rv = ngtcp2_ksl_insert(&gaptr->gap, NULL, &range, NULL); - if (rv != 0) { - return rv; - } - return 0; + return ngtcp2_ksl_insert(&gaptr->gap, NULL, &range, NULL); } void ngtcp2_gaptr_free(ngtcp2_gaptr *gaptr) { @@ -66,8 +60,8 @@ int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, uint64_t datalen) { } } - it = ngtcp2_ksl_lower_bound_compar(&gaptr->gap, &q, - ngtcp2_ksl_range_exclusive_compar); + it = ngtcp2_ksl_lower_bound_search(&gaptr->gap, &q, + ngtcp2_ksl_range_exclusive_search); for (; !ngtcp2_ksl_it_end(&it);) { k = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it); @@ -80,7 +74,9 @@ int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, uint64_t datalen) { ngtcp2_ksl_remove_hint(&gaptr->gap, &it, &it, &k); continue; } + ngtcp2_range_cut(&l, &r, &k, &m); + if (ngtcp2_range_len(&l)) { ngtcp2_ksl_update_key(&gaptr->gap, &k, &l); @@ -93,26 +89,26 @@ int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, uint64_t datalen) { } else if (ngtcp2_range_len(&r)) { ngtcp2_ksl_update_key(&gaptr->gap, &k, &r); } + ngtcp2_ksl_it_next(&it); } + return 0; } -uint64_t ngtcp2_gaptr_first_gap_offset(ngtcp2_gaptr *gaptr) { +uint64_t ngtcp2_gaptr_first_gap_offset(const ngtcp2_gaptr *gaptr) { ngtcp2_ksl_it it; - ngtcp2_range r; if (ngtcp2_ksl_len(&gaptr->gap) == 0) { return 0; } it = ngtcp2_ksl_begin(&gaptr->gap); - r = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it); - return r.begin; + return ((ngtcp2_range *)ngtcp2_ksl_it_key(&it))->begin; } -ngtcp2_range ngtcp2_gaptr_get_first_gap_after(ngtcp2_gaptr *gaptr, +ngtcp2_range ngtcp2_gaptr_get_first_gap_after(const ngtcp2_gaptr *gaptr, uint64_t offset) { ngtcp2_range q = {offset, offset + 1}; ngtcp2_ksl_it it; @@ -122,29 +118,27 @@ ngtcp2_range ngtcp2_gaptr_get_first_gap_after(ngtcp2_gaptr *gaptr, return r; } - it = ngtcp2_ksl_lower_bound_compar(&gaptr->gap, &q, - ngtcp2_ksl_range_exclusive_compar); + it = ngtcp2_ksl_lower_bound_search(&gaptr->gap, &q, + ngtcp2_ksl_range_exclusive_search); assert(!ngtcp2_ksl_it_end(&it)); return *(ngtcp2_range *)ngtcp2_ksl_it_key(&it); } -int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset, +int ngtcp2_gaptr_is_pushed(const ngtcp2_gaptr *gaptr, uint64_t offset, uint64_t datalen) { ngtcp2_range q = {offset, offset + datalen}; ngtcp2_ksl_it it; - ngtcp2_range k; ngtcp2_range m; if (ngtcp2_ksl_len(&gaptr->gap) == 0) { return 0; } - it = ngtcp2_ksl_lower_bound_compar(&gaptr->gap, &q, - ngtcp2_ksl_range_exclusive_compar); - k = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it); - m = ngtcp2_range_intersect(&q, &k); + it = ngtcp2_ksl_lower_bound_search(&gaptr->gap, &q, + ngtcp2_ksl_range_exclusive_search); + m = ngtcp2_range_intersect(&q, (ngtcp2_range *)ngtcp2_ksl_it_key(&it)); return ngtcp2_range_len(&m) == 0; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.h index 0f100a81c4286c..3120676cf849d4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -39,8 +39,9 @@ * ngtcp2_gaptr maintains the gap in the range [0, UINT64_MAX). */ typedef struct ngtcp2_gaptr { - /* gap maintains the range of offset which is not received - yet. Initially, its range is [0, UINT64_MAX). */ + /* gap maintains the range of offset which is not pushed + yet. Initially, its range is [0, UINT64_MAX). "gap" is the range + that is not pushed yet. */ ngtcp2_ksl gap; /* mem is custom memory allocator */ const ngtcp2_mem *mem; @@ -57,8 +58,7 @@ void ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem); void ngtcp2_gaptr_free(ngtcp2_gaptr *gaptr); /* - * ngtcp2_gaptr_push adds new data of length |datalen| at the stream - * offset |offset|. + * ngtcp2_gaptr_push pushes the range [offset, offset + datalen). * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -72,20 +72,20 @@ int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, uint64_t datalen); * ngtcp2_gaptr_first_gap_offset returns the offset to the first gap. * If there is no gap, it returns UINT64_MAX. */ -uint64_t ngtcp2_gaptr_first_gap_offset(ngtcp2_gaptr *gaptr); +uint64_t ngtcp2_gaptr_first_gap_offset(const ngtcp2_gaptr *gaptr); /* * ngtcp2_gaptr_get_first_gap_after returns the first gap which - * overlaps or comes after |offset|. + * includes or comes after |offset|. */ -ngtcp2_range ngtcp2_gaptr_get_first_gap_after(ngtcp2_gaptr *gaptr, +ngtcp2_range ngtcp2_gaptr_get_first_gap_after(const ngtcp2_gaptr *gaptr, uint64_t offset); /* * ngtcp2_gaptr_is_pushed returns nonzero if range [offset, offset + * datalen) is completely pushed into this object. */ -int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset, +int ngtcp2_gaptr_is_pushed(const ngtcp2_gaptr *gaptr, uint64_t offset, uint64_t datalen); /* @@ -95,4 +95,4 @@ int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset, */ void ngtcp2_gaptr_drop_first_gap(ngtcp2_gaptr *gaptr); -#endif /* NGTCP2_GAPTR_H */ +#endif /* !defined(NGTCP2_GAPTR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.c index d9880227690faf..2cf9d3cbfd1393 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.c @@ -26,10 +26,8 @@ #include -void ngtcp2_idtr_init(ngtcp2_idtr *idtr, int server, const ngtcp2_mem *mem) { +void ngtcp2_idtr_init(ngtcp2_idtr *idtr, const ngtcp2_mem *mem) { ngtcp2_gaptr_init(&idtr->gap, mem); - - idtr->server = server; } void ngtcp2_idtr_free(ngtcp2_idtr *idtr) { @@ -41,8 +39,7 @@ void ngtcp2_idtr_free(ngtcp2_idtr *idtr) { } /* - * id_from_stream_id translates |stream_id| to id space used by - * ngtcp2_idtr. + * id_from_stream_id translates |stream_id| to an internal ID. */ static uint64_t id_from_stream_id(int64_t stream_id) { return (uint64_t)(stream_id >> 2); @@ -51,9 +48,6 @@ static uint64_t id_from_stream_id(int64_t stream_id) { int ngtcp2_idtr_open(ngtcp2_idtr *idtr, int64_t stream_id) { uint64_t q; - assert((idtr->server && (stream_id % 2)) || - (!idtr->server && (stream_id % 2)) == 0); - q = id_from_stream_id(stream_id); if (ngtcp2_gaptr_is_pushed(&idtr->gap, q, 1)) { @@ -63,17 +57,10 @@ int ngtcp2_idtr_open(ngtcp2_idtr *idtr, int64_t stream_id) { return ngtcp2_gaptr_push(&idtr->gap, q, 1); } -int ngtcp2_idtr_is_open(ngtcp2_idtr *idtr, int64_t stream_id) { +int ngtcp2_idtr_is_open(const ngtcp2_idtr *idtr, int64_t stream_id) { uint64_t q; - assert((idtr->server && (stream_id % 2)) || - (!idtr->server && (stream_id % 2)) == 0); - q = id_from_stream_id(stream_id); return ngtcp2_gaptr_is_pushed(&idtr->gap, q, 1); } - -uint64_t ngtcp2_idtr_first_gap(ngtcp2_idtr *idtr) { - return ngtcp2_gaptr_first_gap_offset(&idtr->gap); -} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.h index edb8c68c8db9b5..0671f5ed91a5cd 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_idtr.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -38,21 +38,17 @@ * ngtcp2_idtr tracks the usage of stream ID. */ typedef struct ngtcp2_idtr { - /* gap maintains the range of ID which is not used yet. Initially, - its range is [0, UINT64_MAX). */ + /* gap maintains the range of an internal ID which is not used yet. + Initially, its range is [0, UINT64_MAX). The internal ID and + stream ID are in the different number spaces. See + id_from_stream_id to convert a stream ID to an internal ID. */ ngtcp2_gaptr gap; - /* server is nonzero if this object records server initiated stream - ID. */ - int server; } ngtcp2_idtr; /* * ngtcp2_idtr_init initializes |idtr|. - * - * If this object records server initiated ID (even number), set - * |server| to nonzero. */ -void ngtcp2_idtr_init(ngtcp2_idtr *idtr, int server, const ngtcp2_mem *mem); +void ngtcp2_idtr_init(ngtcp2_idtr *idtr, const ngtcp2_mem *mem); /* * ngtcp2_idtr_free frees resources allocated for |idtr|. @@ -60,30 +56,21 @@ void ngtcp2_idtr_init(ngtcp2_idtr *idtr, int server, const ngtcp2_mem *mem); void ngtcp2_idtr_free(ngtcp2_idtr *idtr); /* - * ngtcp2_idtr_open claims that |stream_id| is in used. + * ngtcp2_idtr_open claims that |stream_id| is in use. * * It returns 0 if it succeeds, or one of the following negative error * codes: * * NGTCP2_ERR_STREAM_IN_USE - * ID has already been used. + * |stream_id| has already been used. * NGTCP2_ERR_NOMEM * Out of memory. */ int ngtcp2_idtr_open(ngtcp2_idtr *idtr, int64_t stream_id); /* - * ngtcp2_idtr_open tells whether ID |stream_id| is in used or not. - * - * It returns nonzero if |stream_id| is used. - */ -int ngtcp2_idtr_is_open(ngtcp2_idtr *idtr, int64_t stream_id); - -/* - * ngtcp2_idtr_first_gap returns the first id of first gap. If there - * is no gap, it returns UINT64_MAX. The returned id is an id space - * used in this object internally, and not stream ID. + * ngtcp2_idtr_open returns nonzero if |stream_id| is in use. */ -uint64_t ngtcp2_idtr_first_gap(ngtcp2_idtr *idtr); +int ngtcp2_idtr_is_open(const ngtcp2_idtr *idtr, int64_t stream_id); -#endif /* NGTCP2_IDTR_H */ +#endif /* !defined(NGTCP2_IDTR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c index 0ccc048b5b16b1..5e74f647241816 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c @@ -35,11 +35,13 @@ static ngtcp2_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}}; -ngtcp2_objalloc_def(ksl_blk, ngtcp2_ksl_blk, oplent); +ngtcp2_objalloc_def(ksl_blk, ngtcp2_ksl_blk, oplent) static size_t ksl_nodelen(size_t keylen) { - return (sizeof(ngtcp2_ksl_node) + keylen - sizeof(uint64_t) + 0xfu) & - ~(uintptr_t)0xfu; + 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) { @@ -55,20 +57,21 @@ static void ksl_node_set_key(ngtcp2_ksl *ksl, ngtcp2_ksl_node *node, memcpy(node->key, key, ksl->keylen); } -void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, size_t 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); ngtcp2_objalloc_init(&ksl->blkalloc, - ((ksl_blklen(nodelen) + 0xfu) & ~(uintptr_t)0xfu) * 8, - mem); + (ksl_blklen(nodelen) + 0xfu) & ~(uintptr_t)0xfu, mem); ksl->head = NULL; ksl->front = ksl->back = NULL; ksl->compar = compar; + ksl->search = search; + ksl->n = 0; ksl->keylen = keylen; ksl->nodelen = nodelen; - ksl->n = 0; } static ngtcp2_ksl_blk *ksl_blk_objalloc_new(ngtcp2_ksl *ksl) { @@ -82,6 +85,7 @@ static void ksl_blk_objalloc_del(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { static int ksl_head_init(ngtcp2_ksl *ksl) { ngtcp2_ksl_blk *head = ksl_blk_objalloc_new(ksl); + if (!head) { return NGTCP2_ERR_NOMEM; } @@ -111,7 +115,7 @@ static void ksl_free_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { ksl_blk_objalloc_del(ksl, blk); } -#endif /* NOMEMPOOL */ +#endif /* defined(NOMEMPOOL) */ void ngtcp2_ksl_free(ngtcp2_ksl *ksl) { if (!ksl || !ksl->head) { @@ -120,7 +124,7 @@ void ngtcp2_ksl_free(ngtcp2_ksl *ksl) { #ifdef NOMEMPOOL ksl_free_blk(ksl, ksl->head); -#endif /* NOMEMPOOL */ +#endif /* defined(NOMEMPOOL) */ ngtcp2_objalloc_free(&ksl->blkalloc); } @@ -143,21 +147,22 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { rblk->next = blk->next; blk->next = rblk; + if (rblk->next) { rblk->next->prev = rblk; } else if (ksl->back == blk) { ksl->back = rblk; } + rblk->prev = blk; rblk->leaf = blk->leaf; rblk->n = blk->n / 2; + blk->n -= rblk->n; - memcpy(rblk->nodes, blk->nodes + ksl->nodelen * (blk->n - rblk->n), + memcpy(rblk->nodes, blk->nodes + ksl->nodelen * blk->n, ksl->nodelen * rblk->n); - blk->n -= rblk->n; - assert(blk->n >= NGTCP2_KSL_MIN_NBLK); assert(rblk->n >= NGTCP2_KSL_MIN_NBLK); @@ -173,7 +178,7 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { * codes: * * NGTCP2_ERR_NOMEM - * Out of memory. + * Out of memory. */ static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { ngtcp2_ksl_node *node; @@ -207,7 +212,7 @@ static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { * codes: * * NGTCP2_ERR_NOMEM - * Out of memory. + * Out of memory. */ static int ksl_split_head(ngtcp2_ksl *ksl) { ngtcp2_ksl_blk *rblk = NULL, *lblk, *nhead = NULL; @@ -221,10 +226,12 @@ static int ksl_split_head(ngtcp2_ksl *ksl) { lblk = ksl->head; nhead = ksl_blk_objalloc_new(ksl); + if (nhead == NULL) { ksl_blk_objalloc_del(ksl, rblk); return NGTCP2_ERR_NOMEM; } + nhead->next = nhead->prev = NULL; nhead->n = 2; nhead->leaf = 0; @@ -243,9 +250,9 @@ static int ksl_split_head(ngtcp2_ksl *ksl) { } /* - * insert_node inserts a node whose key is |key| with the associated - * |data| at the index of |i|. This function assumes that the number - * of nodes contained by |blk| is strictly less than + * ksl_insert_node inserts a node whose key is |key| with the + * associated |data| at the index of |i|. This function assumes that + * the number of nodes contained by |blk| is strictly less than * NGTCP2_KSL_MAX_NBLK. */ static void ksl_insert_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i, @@ -264,19 +271,6 @@ static void ksl_insert_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i, ++blk->n; } -static size_t ksl_bsearch(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, - const ngtcp2_ksl_key *key, ngtcp2_ksl_compar compar) { - size_t i; - ngtcp2_ksl_node *node; - - 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)) - ; - - return i; -} - int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, const ngtcp2_ksl_key *key, void *data) { ngtcp2_ksl_blk *blk; @@ -291,18 +285,17 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, } } - blk = ksl->head; - - if (blk->n == NGTCP2_KSL_MAX_NBLK) { + if (ksl->head->n == NGTCP2_KSL_MAX_NBLK) { rv = ksl_split_head(ksl); if (rv != 0) { return rv; } - blk = ksl->head; } + blk = ksl->head; + for (;;) { - i = ksl_bsearch(ksl, blk, key, ksl->compar); + i = ksl->search(ksl, blk, key); if (blk->leaf) { if (i < blk->n && @@ -310,13 +303,17 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, if (it) { *it = ngtcp2_ksl_end(ksl); } + return NGTCP2_ERR_INVALID_ARGUMENT; } + ksl_insert_node(ksl, blk, i, key, data); ++ksl->n; + if (it) { ngtcp2_ksl_it_init(it, ksl, blk, i); } + return 0; } @@ -329,16 +326,21 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, if (rv != 0) { return rv; } + node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1); } + ksl_node_set_key(ksl, node, key); blk = node->blk; } + ksl_insert_node(ksl, blk, blk->n, key, data); ++ksl->n; + if (it) { ngtcp2_ksl_it_init(it, ksl, blk, blk->n - 1); } + return 0; } @@ -349,8 +351,10 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, if (rv != 0) { 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_key *)node->key, key)) { ksl_node_set_key(ksl, node, key); } @@ -376,19 +380,22 @@ static void ksl_remove_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { * ksl_merge_node merges 2 nodes which are the nodes at the index of * |i| and |i + 1|. * - * If |blk| is the direct descendant of head (root) block and the head - * block contains just 2 nodes, the merged block becomes head block, - * which decreases the height of |ksl| by 1. + * If |blk| is the head (root) block and it contains just 2 nodes + * before merging nodes, the merged block becomes head block, which + * decreases the height of |ksl| by 1. * * This function returns the pointer to the merged block. */ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { + ngtcp2_ksl_node *lnode; ngtcp2_ksl_blk *lblk, *rblk; assert(i + 1 < blk->n); - lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk; + lnode = ngtcp2_ksl_nth_node(ksl, blk, i); + + lblk = lnode->blk; rblk = ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk; assert(lblk->n + rblk->n < NGTCP2_KSL_MAX_NBLK); @@ -398,6 +405,7 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, lblk->n += rblk->n; lblk->next = rblk->next; + if (lblk->next) { lblk->next->prev = lblk; } else if (ksl->back == rblk) { @@ -411,7 +419,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, ngtcp2_ksl_nth_node(ksl, blk, i), + ksl_node_set_key(ksl, lnode, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); } @@ -425,6 +433,7 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, */ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { ngtcp2_ksl_node *lnode, *rnode; + ngtcp2_ksl_blk *lblk, *rblk; size_t n; assert(i > 0); @@ -432,35 +441,37 @@ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { lnode = ngtcp2_ksl_nth_node(ksl, blk, i - 1); rnode = ngtcp2_ksl_nth_node(ksl, blk, i); - assert(lnode->blk->n < NGTCP2_KSL_MAX_NBLK); - assert(rnode->blk->n > NGTCP2_KSL_MIN_NBLK); + lblk = lnode->blk; + rblk = rnode->blk; + + assert(lblk->n < NGTCP2_KSL_MAX_NBLK); + assert(rblk->n > NGTCP2_KSL_MIN_NBLK); - n = (lnode->blk->n + rnode->blk->n + 1) / 2 - lnode->blk->n; + n = (lblk->n + rblk->n + 1) / 2 - lblk->n; assert(n > 0); - assert(lnode->blk->n <= NGTCP2_KSL_MAX_NBLK - n); - assert(rnode->blk->n >= NGTCP2_KSL_MIN_NBLK + n); + assert(lblk->n <= NGTCP2_KSL_MAX_NBLK - n); + assert(rblk->n >= NGTCP2_KSL_MIN_NBLK + n); - memcpy(lnode->blk->nodes + ksl->nodelen * lnode->blk->n, rnode->blk->nodes, - ksl->nodelen * n); + memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes, ksl->nodelen * n); - lnode->blk->n += (uint32_t)n; - rnode->blk->n -= (uint32_t)n; + lblk->n += (uint32_t)n; + rblk->n -= (uint32_t)n; - ksl_node_set_key( - ksl, lnode, ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key); + ksl_node_set_key(ksl, lnode, + ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); - memmove(rnode->blk->nodes, rnode->blk->nodes + ksl->nodelen * n, - ksl->nodelen * rnode->blk->n); + memmove(rblk->nodes, rblk->nodes + ksl->nodelen * n, ksl->nodelen * rblk->n); } /* * ksl_shift_right moves the last nodes in blk->nodes[i]->blk->nodes * to blk->nodes[i + 1]->blk->nodes in a manner that they have the - * same amount of nodes as much as possible.. + * same amount of nodes as much as possible. */ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { ngtcp2_ksl_node *lnode, *rnode; + ngtcp2_ksl_blk *lblk, *rblk; size_t n; assert(i < blk->n - 1); @@ -468,26 +479,27 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { lnode = ngtcp2_ksl_nth_node(ksl, blk, i); rnode = ngtcp2_ksl_nth_node(ksl, blk, i + 1); - assert(lnode->blk->n > NGTCP2_KSL_MIN_NBLK); - assert(rnode->blk->n < NGTCP2_KSL_MAX_NBLK); + lblk = lnode->blk; + rblk = rnode->blk; - n = (lnode->blk->n + rnode->blk->n + 1) / 2 - rnode->blk->n; + assert(lblk->n > NGTCP2_KSL_MIN_NBLK); + assert(rblk->n < NGTCP2_KSL_MAX_NBLK); + + n = (lblk->n + rblk->n + 1) / 2 - rblk->n; assert(n > 0); - assert(lnode->blk->n >= NGTCP2_KSL_MIN_NBLK + n); - assert(rnode->blk->n <= NGTCP2_KSL_MAX_NBLK - n); + assert(lblk->n >= NGTCP2_KSL_MIN_NBLK + n); + assert(rblk->n <= NGTCP2_KSL_MAX_NBLK - n); - memmove(rnode->blk->nodes + ksl->nodelen * n, rnode->blk->nodes, - ksl->nodelen * rnode->blk->n); + memmove(rblk->nodes + ksl->nodelen * n, rblk->nodes, ksl->nodelen * rblk->n); - rnode->blk->n += (uint32_t)n; - lnode->blk->n -= (uint32_t)n; + rblk->n += (uint32_t)n; + lblk->n -= (uint32_t)n; - memcpy(rnode->blk->nodes, lnode->blk->nodes + ksl->nodelen * lnode->blk->n, - ksl->nodelen * n); + memcpy(rblk->nodes, lblk->nodes + ksl->nodelen * lblk->n, ksl->nodelen * n); - ksl_node_set_key( - ksl, lnode, ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key); + ksl_node_set_key(ksl, lnode, + ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); } /* @@ -531,23 +543,24 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, ngtcp2_ksl_node *node; size_t i; - if (!ksl->head) { + if (!blk) { return NGTCP2_ERR_INVALID_ARGUMENT; } 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 = ksl_merge_node(ksl, ksl->head, 0); + blk = ksl_merge_node(ksl, blk, 0); } for (;;) { - i = ksl_bsearch(ksl, blk, key, ksl->compar); + i = ksl->search(ksl, blk, key); if (i == blk->n) { if (it) { *it = ngtcp2_ksl_end(ksl); } + return NGTCP2_ERR_INVALID_ARGUMENT; } @@ -556,10 +569,13 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, if (it) { *it = ngtcp2_ksl_end(ksl); } + return NGTCP2_ERR_INVALID_ARGUMENT; } + ksl_remove_node(ksl, blk, i); --ksl->n; + if (it) { if (blk->n == i && blk->next) { ngtcp2_ksl_it_init(it, ksl, blk->next, 0); @@ -567,6 +583,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, ngtcp2_ksl_it_init(it, ksl, blk, i); } } + return 0; } @@ -583,6 +600,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk->n > NGTCP2_KSL_MIN_NBLK) { ksl_shift_left(ksl, blk, i + 1); blk = node->blk; + continue; } @@ -590,6 +608,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, ngtcp2_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGTCP2_KSL_MIN_NBLK) { ksl_shift_right(ksl, blk, i - 1); blk = node->blk; + continue; } @@ -604,50 +623,14 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, } } -ngtcp2_ksl_it ngtcp2_ksl_lower_bound(ngtcp2_ksl *ksl, +ngtcp2_ksl_it ngtcp2_ksl_lower_bound(const ngtcp2_ksl *ksl, const ngtcp2_ksl_key *key) { - ngtcp2_ksl_blk *blk = ksl->head; - ngtcp2_ksl_it it; - size_t i; - - if (!blk) { - ngtcp2_ksl_it_init(&it, ksl, &null_blk, 0); - return it; - } - - for (;;) { - i = ksl_bsearch(ksl, blk, key, ksl->compar); - - if (blk->leaf) { - if (i == blk->n && blk->next) { - blk = blk->next; - i = 0; - } - ngtcp2_ksl_it_init(&it, ksl, blk, i); - return it; - } - - 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) - ; - if (blk->next) { - blk = blk->next; - i = 0; - } else { - i = blk->n; - } - ngtcp2_ksl_it_init(&it, ksl, blk, i); - return it; - } - blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk; - } + return ngtcp2_ksl_lower_bound_search(ksl, key, ksl->search); } -ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl, +ngtcp2_ksl_it ngtcp2_ksl_lower_bound_search(const ngtcp2_ksl *ksl, const ngtcp2_ksl_key *key, - ngtcp2_ksl_compar compar) { + ngtcp2_ksl_search search) { ngtcp2_ksl_blk *blk = ksl->head; ngtcp2_ksl_it it; size_t i; @@ -658,14 +641,16 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl, } for (;;) { - i = ksl_bsearch(ksl, blk, key, compar); + i = search(ksl, blk, key); if (blk->leaf) { if (i == blk->n && blk->next) { blk = blk->next; i = 0; } + ngtcp2_ksl_it_init(&it, ksl, blk, i); + return it; } @@ -674,15 +659,19 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl, find last node in this subtree. */ for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk) ; + if (blk->next) { blk = blk->next; i = 0; } else { i = blk->n; } + ngtcp2_ksl_it_init(&it, ksl, blk, i); + return it; } + blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk; } } @@ -696,7 +685,7 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, assert(ksl->head); for (;;) { - i = ksl_bsearch(ksl, blk, old_key, ksl->compar); + i = ksl->search(ksl, blk, old_key); assert(i < blk->n); node = ngtcp2_ksl_nth_node(ksl, blk, i); @@ -704,6 +693,7 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, if (blk->leaf) { assert(key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key)); ksl_node_set_key(ksl, node, new_key); + return; } @@ -716,7 +706,7 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, } } -size_t ngtcp2_ksl_len(ngtcp2_ksl *ksl) { return ksl->n; } +size_t ngtcp2_ksl_len(const ngtcp2_ksl *ksl) { return ksl->n; } void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) { if (!ksl->head) { @@ -725,7 +715,7 @@ void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) { #ifdef NOMEMPOOL ksl_free_blk(ksl, ksl->head); -#endif /* NOMEMPOOL */ +#endif /* defined(NOMEMPOOL) */ ksl->front = ksl->back = ksl->head = NULL; ksl->n = 0; @@ -734,7 +724,8 @@ void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) { } #ifndef WIN32 -static void ksl_print(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) { +static void ksl_print(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, + size_t level) { size_t i; ngtcp2_ksl_node *node; @@ -745,7 +736,9 @@ static void ksl_print(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) { node = ngtcp2_ksl_nth_node(ksl, blk, i); fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key); } + fprintf(stderr, "\n"); + return; } @@ -754,14 +747,14 @@ static void ksl_print(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) { } } -void ngtcp2_ksl_print(ngtcp2_ksl *ksl) { +void ngtcp2_ksl_print(const ngtcp2_ksl *ksl) { if (!ksl->head) { return; } ksl_print(ksl, ksl->head, 0); } -#endif /* !WIN32 */ +#endif /* !defined(WIN32) */ ngtcp2_ksl_it ngtcp2_ksl_begin(const ngtcp2_ksl *ksl) { ngtcp2_ksl_it it; @@ -815,9 +808,49 @@ int ngtcp2_ksl_range_compar(const ngtcp2_ksl_key *lhs, return a->begin < b->begin; } +ngtcp2_ksl_search_def(range, ngtcp2_ksl_range_compar) + +size_t ngtcp2_ksl_range_search(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key) { + return ksl_range_search(ksl, blk, key); +} + int ngtcp2_ksl_range_exclusive_compar(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { const ngtcp2_range *a = lhs, *b = rhs; - return a->begin < b->begin && - !(ngtcp2_max(a->begin, b->begin) < ngtcp2_min(a->end, b->end)); + return a->begin < b->begin && !(ngtcp2_max_uint64(a->begin, b->begin) < + ngtcp2_min_uint64(a->end, b->end)); +} + +ngtcp2_ksl_search_def(range_exclusive, ngtcp2_ksl_range_exclusive_compar) + +size_t ngtcp2_ksl_range_exclusive_search(const ngtcp2_ksl *ksl, + ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key) { + return ksl_range_exclusive_search(ksl, blk, key); +} + +int ngtcp2_ksl_uint64_less(const ngtcp2_ksl_key *lhs, + const ngtcp2_ksl_key *rhs) { + return *(uint64_t *)lhs < *(uint64_t *)rhs; +} + +ngtcp2_ksl_search_def(uint64_less, ngtcp2_ksl_uint64_less) + +size_t ngtcp2_ksl_uint64_less_search(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key) { + return ksl_uint64_less_search(ksl, blk, key); +} + +int ngtcp2_ksl_int64_greater(const ngtcp2_ksl_key *lhs, + const ngtcp2_ksl_key *rhs) { + return *(int64_t *)lhs > *(int64_t *)rhs; +} + +ngtcp2_ksl_search_def(int64_greater, ngtcp2_ksl_int64_greater) + +size_t ngtcp2_ksl_int64_greater_search(const ngtcp2_ksl *ksl, + ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key) { + return ksl_int64_greater_search(ksl, blk, key); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h index 7e08f15cdae6e8..de78bcb8070f53 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -35,16 +35,12 @@ #include "ngtcp2_objalloc.h" -/* - * Skip List using single key instead of range. - */ - #define NGTCP2_KSL_DEGR 16 /* NGTCP2_KSL_MAX_NBLK is the maximum number of nodes which a single block can contain. */ #define NGTCP2_KSL_MAX_NBLK (2 * NGTCP2_KSL_DEGR - 1) /* NGTCP2_KSL_MIN_NBLK is the minimum number of nodes which a single - block other than root must contains. */ + block other than root must contain. */ #define NGTCP2_KSL_MIN_NBLK (NGTCP2_KSL_DEGR - 1) /* @@ -85,7 +81,8 @@ struct ngtcp2_ksl_blk { struct { /* next points to the next block if leaf field is nonzero. */ ngtcp2_ksl_blk *next; - /* prev points to the previous block if leaf field is nonzero. */ + /* prev points to the previous block if leaf field is + nonzero. */ ngtcp2_ksl_blk *prev; /* n is the number of nodes this object contains in nodes. */ uint32_t n; @@ -106,7 +103,7 @@ struct ngtcp2_ksl_blk { }; }; -ngtcp2_objalloc_decl(ksl_blk, ngtcp2_ksl_blk, oplent); +ngtcp2_objalloc_decl(ksl_blk, ngtcp2_ksl_blk, oplent) /* * ngtcp2_ksl_compar is a function type which returns nonzero if key @@ -117,10 +114,37 @@ typedef int (*ngtcp2_ksl_compar)(const ngtcp2_ksl_key *lhs, typedef struct ngtcp2_ksl ngtcp2_ksl; +/* + * ngtcp2_ksl_search is a function to search for the first element in + * |blk|->nodes which is not ordered before |key|. It returns the + * index of such element. It returns |blk|->n if there is no such + * element. + */ +typedef size_t (*ngtcp2_ksl_search)(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key); + +/* + * ngtcp2_ksl_search_def is a macro to implement ngtcp2_ksl_search + * with COMPAR which is supposed to be ngtcp2_ksl_compar. + */ +#define ngtcp2_ksl_search_def(NAME, COMPAR) \ + 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; \ + \ + 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)) \ + ; \ + \ + return i; \ + } + typedef struct ngtcp2_ksl_it ngtcp2_ksl_it; /* - * ngtcp2_ksl_it is a forward iterator to iterate nodes. + * ngtcp2_ksl_it is a bidirectional iterator to iterate nodes. */ struct ngtcp2_ksl_it { const ngtcp2_ksl *ksl; @@ -140,6 +164,8 @@ struct ngtcp2_ksl { /* back points to the last leaf block. */ ngtcp2_ksl_blk *back; ngtcp2_ksl_compar compar; + ngtcp2_ksl_search search; + /* n is the number of elements stored. */ size_t n; /* keylen is the size of key */ size_t keylen; @@ -150,9 +176,12 @@ struct ngtcp2_ksl { /* * ngtcp2_ksl_init initializes |ksl|. |compar| specifies compare - * function. |keylen| is the length of key. + * function. |search| is a search function which must use |compar|. + * |keylen| is the length of key and must be at least + * sizeof(uint64_t). */ -void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, size_t keylen, +void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, + ngtcp2_ksl_search search, size_t keylen, const ngtcp2_mem *mem); /* @@ -165,15 +194,15 @@ void ngtcp2_ksl_free(ngtcp2_ksl *ksl); /* * ngtcp2_ksl_insert inserts |key| with its associated |data|. On * successful insertion, the iterator points to the inserted node is - * stored in |*it|. + * stored in |*it| if |it| is not NULL. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * NGTCP2_ERR_NOMEM - * Out of memory. + * Out of memory. * NGTCP2_ERR_INVALID_ARGUMENT - * |key| already exists. + * |key| already exists. */ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, const ngtcp2_ksl_key *key, void *data); @@ -184,13 +213,14 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, * This function assigns the iterator to |*it|, which points to the * node which is located at the right next of the removed node if |it| * is not NULL. If |key| is not found, no deletion takes place and - * the return value of ngtcp2_ksl_end(ksl) is assigned to |*it|. + * the return value of ngtcp2_ksl_end(ksl) is assigned to |*it| if + * |it| is not NULL. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * NGTCP2_ERR_INVALID_ARGUMENT - * |key| does not exist. + * |key| does not exist. */ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, const ngtcp2_ksl_key *key); @@ -213,16 +243,16 @@ int ngtcp2_ksl_remove_hint(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, * node, it returns the iterator which satisfies ngtcp2_ksl_it_end(it) * != 0. */ -ngtcp2_ksl_it ngtcp2_ksl_lower_bound(ngtcp2_ksl *ksl, +ngtcp2_ksl_it ngtcp2_ksl_lower_bound(const ngtcp2_ksl *ksl, const ngtcp2_ksl_key *key); /* - * ngtcp2_ksl_lower_bound_compar works like ngtcp2_ksl_lower_bound, - * but it takes custom function |compar| to do lower bound search. + * ngtcp2_ksl_lower_bound_search works like ngtcp2_ksl_lower_bound, + * but it takes custom function |search| to do lower bound search. */ -ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl, +ngtcp2_ksl_it ngtcp2_ksl_lower_bound_search(const ngtcp2_ksl *ksl, const ngtcp2_ksl_key *key, - ngtcp2_ksl_compar compar); + ngtcp2_ksl_search search); /* * ngtcp2_ksl_update_key replaces the key of nodes which has |old_key| @@ -235,7 +265,8 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, /* * ngtcp2_ksl_begin returns the iterator which points to the first * node. If there is no node in |ksl|, it returns the iterator which - * satisfies ngtcp2_ksl_it_end(it) != 0. + * satisfies both ngtcp2_ksl_it_begin(it) != 0 and + * ngtcp2_ksl_it_end(it) != 0. */ ngtcp2_ksl_it ngtcp2_ksl_begin(const ngtcp2_ksl *ksl); @@ -243,14 +274,15 @@ ngtcp2_ksl_it ngtcp2_ksl_begin(const ngtcp2_ksl *ksl); * ngtcp2_ksl_end returns the iterator which points to the node * following the last node. The returned object satisfies * ngtcp2_ksl_it_end(). If there is no node in |ksl|, it returns the - * iterator which satisfies ngtcp2_ksl_it_begin(it) != 0. + * iterator which satisfies ngtcp2_ksl_it_begin(it) != 0 and + * ngtcp2_ksl_it_end(it) != 0. */ ngtcp2_ksl_it ngtcp2_ksl_end(const ngtcp2_ksl *ksl); /* * ngtcp2_ksl_len returns the number of elements stored in |ksl|. */ -size_t ngtcp2_ksl_len(ngtcp2_ksl *ksl); +size_t ngtcp2_ksl_len(const ngtcp2_ksl *ksl); /* * ngtcp2_ksl_clear removes all elements stored in |ksl|. @@ -269,8 +301,8 @@ void ngtcp2_ksl_clear(ngtcp2_ksl *ksl); * that the key is of type int64_t. This function should be used for * the debugging purpose only. */ -void ngtcp2_ksl_print(ngtcp2_ksl *ksl); -#endif /* !WIN32 */ +void ngtcp2_ksl_print(const ngtcp2_ksl *ksl); +#endif /* !defined(WIN32) */ /* * ngtcp2_ksl_it_init initializes |it|. @@ -293,8 +325,8 @@ void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl, */ #define ngtcp2_ksl_it_next(IT) \ (++(IT)->i == (IT)->blk->n && (IT)->blk->next \ - ? ((IT)->blk = (IT)->blk->next, (IT)->i = 0) \ - : 0) + ? ((IT)->blk = (IT)->blk->next, (IT)->i = 0) \ + : 0) /* * ngtcp2_ksl_it_prev moves backward the iterator by one. It is @@ -304,16 +336,16 @@ void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl, void ngtcp2_ksl_it_prev(ngtcp2_ksl_it *it); /* - * ngtcp2_ksl_it_end returns nonzero if |it| points to the beyond the - * last node. + * ngtcp2_ksl_it_end returns nonzero if |it| points to the one beyond + * the last node. */ #define ngtcp2_ksl_it_end(IT) \ ((IT)->blk->n == (IT)->i && (IT)->blk->next == NULL) /* * ngtcp2_ksl_it_begin returns nonzero if |it| points to the first - * node. |it| might satisfy both ngtcp2_ksl_it_begin(&it) and - * ngtcp2_ksl_it_end(&it) if the skip list has no node. + * node. |it| might satisfy both ngtcp2_ksl_it_begin(it) != 0 and + * ngtcp2_ksl_it_end(it) != 0 if the skip list has no node. */ int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it); @@ -327,21 +359,67 @@ int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it); /* * ngtcp2_ksl_range_compar is an implementation of ngtcp2_ksl_compar. - * lhs->ptr and rhs->ptr must point to ngtcp2_range object and the - * function returns nonzero if (const ngtcp2_range *)(lhs->ptr)->begin - * < (const ngtcp2_range *)(rhs->ptr)->begin. + * |lhs| and |rhs| must point to ngtcp2_range object, and the function + * returns nonzero if ((const ngtcp2_range *)lhs)->begin < ((const + * ngtcp2_range *)rhs)->begin. */ int ngtcp2_ksl_range_compar(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs); +/* + * ngtcp2_ksl_range_search is an implementation of ngtcp2_ksl_search + * that uses ngtcp2_ksl_range_compar. + */ +size_t ngtcp2_ksl_range_search(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key); + /* * ngtcp2_ksl_range_exclusive_compar is an implementation of - * ngtcp2_ksl_compar. lhs->ptr and rhs->ptr must point to - * ngtcp2_range object and the function returns nonzero if (const - * ngtcp2_range *)(lhs->ptr)->begin < (const ngtcp2_range - * *)(rhs->ptr)->begin and the 2 ranges do not intersect. + * ngtcp2_ksl_compar. |lhs| and |rhs| must point to ngtcp2_range + * object, and the function returns nonzero if ((const ngtcp2_range + * *)lhs)->begin < ((const ngtcp2_range *)rhs)->begin, and the 2 + * ranges do not intersect. */ int ngtcp2_ksl_range_exclusive_compar(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs); -#endif /* NGTCP2_KSL_H */ +/* + * ngtcp2_ksl_range_exclusive_search is an implementation of + * ngtcp2_ksl_search that uses ngtcp2_ksl_range_exclusive_compar. + */ +size_t ngtcp2_ksl_range_exclusive_search(const ngtcp2_ksl *ksl, + ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key); + +/* + * ngtcp2_ksl_uint64_less is an implementation of ngtcp2_ksl_compar. + * |lhs| and |rhs| must point to uint64_t objects, and the function + * returns nonzero if *(uint64_t *)|lhs| < *(uint64_t *)|rhs|. + */ +int ngtcp2_ksl_uint64_less(const ngtcp2_ksl_key *lhs, + const ngtcp2_ksl_key *rhs); + +/* + * ngtcp2_ksl_uint64_less_search is an implementation of + * ngtcp2_ksl_search that uses ngtcp2_ksl_uint64_less. + */ +size_t ngtcp2_ksl_uint64_less_search(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key); + +/* + * ngtcp2_ksl_int64_greater is an implementation of ngtcp2_ksl_compar. + * |lhs| and |rhs| must point to int64_t objects, and the function + * returns nonzero if *(int64_t *)|lhs| > *(int64_t *)|rhs|. + */ +int ngtcp2_ksl_int64_greater(const ngtcp2_ksl_key *lhs, + const ngtcp2_ksl_key *rhs); + +/* + * ngtcp2_ksl_int64_greater_search is an implementation of + * ngtcp2_ksl_search that uses ngtcp2_ksl_int64_greater. + */ +size_t ngtcp2_ksl_int64_greater_search(const ngtcp2_ksl *ksl, + ngtcp2_ksl_blk *blk, + const ngtcp2_ksl_key *key); + +#endif /* !defined(NGTCP2_KSL_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c index 93922a29c319f4..fc4eb443517d40 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c @@ -27,7 +27,7 @@ #include #ifdef HAVE_UNISTD_H # include -#endif +#endif /* defined(HAVE_UNISTD_H) */ #include #include @@ -99,11 +99,11 @@ void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid, #define NGTCP2_LOG_FRM_HD_FIELDS(DIR) \ timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "frm", \ - (DIR), hd->pkt_num, strpkttype(hd) + (DIR), hd->pkt_num, strpkttype(hd) #define NGTCP2_LOG_PKT_HD_FIELDS(DIR) \ timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "pkt", \ - (DIR), hd->pkt_num, strpkttype(hd) + (DIR), hd->pkt_num, strpkttype(hd) #define NGTCP2_LOG_TP_HD_FIELDS \ timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "cry" @@ -223,12 +223,12 @@ static uint64_t timestamp_cast(uint64_t ns) { return ns / NGTCP2_MILLISECONDS; } static void log_fr_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stream *fr, const char *dir) { log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 - " fin=%d offset=%" PRIu64 " len=%" PRIu64 " uni=%d"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type | fr->flags, fr->stream_id, - fr->fin, fr->offset, ngtcp2_vec_len(fr->data, fr->datacnt), - (fr->stream_id & 0x2) != 0); + log->user_data, + (NGTCP2_LOG_PKT " STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 + " fin=%d offset=%" PRIu64 " len=%" PRIu64 " uni=%d"), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type | fr->flags, fr->stream_id, fr->fin, + fr->offset, ngtcp2_vec_len(fr->data, fr->datacnt), + (fr->stream_id & 0x2) != 0); } static void log_fr_ack(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -236,13 +236,12 @@ static void log_fr_ack(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, int64_t largest_ack, min_ack; size_t i; - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") largest_ack=%" PRId64 - " ack_delay=%" PRIu64 "(%" PRIu64 - ") ack_range_count=%zu"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->largest_ack, - fr->ack_delay_unscaled / NGTCP2_MILLISECONDS, fr->ack_delay, - fr->rangecnt); + log->log_printf( + log->user_data, + (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") largest_ack=%" PRId64 + " ack_delay=%" PRIu64 "(%" PRIu64 ") ack_range_count=%zu"), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->largest_ack, + fr->ack_delay_unscaled / NGTCP2_MILLISECONDS, fr->ack_delay, fr->rangecnt); largest_ack = fr->largest_ack; min_ack = fr->largest_ack - (int64_t)fr->first_ack_range; @@ -285,38 +284,37 @@ static void log_fr_reset_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_reset_stream *fr, const char *dir) { log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " RESET_STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 - " app_error_code=%s(0x%" PRIx64 ") final_size=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, - strapperrorcode(fr->app_error_code), fr->app_error_code, fr->final_size); + log->user_data, + (NGTCP2_LOG_PKT " RESET_STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 + " app_error_code=%s(0x%" PRIx64 ") final_size=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, + strapperrorcode(fr->app_error_code), fr->app_error_code, fr->final_size); } static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_connection_close *fr, const char *dir) { char reason[256]; - size_t reasonlen = ngtcp2_min(sizeof(reason) - 1, fr->reasonlen); + size_t reasonlen = ngtcp2_min_size(sizeof(reason) - 1, fr->reasonlen); - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " CONNECTION_CLOSE(0x%02" PRIx64 - ") error_code=%s(0x%" PRIx64 ") " - "frame_type=%" PRIx64 - " reason_len=%zu reason=[%s]"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, - 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)); + log->log_printf( + log->user_data, + (NGTCP2_LOG_PKT " CONNECTION_CLOSE(0x%02" PRIx64 + ") error_code=%s(0x%" PRIx64 ") " + "frame_type=%" PRIx64 " reason_len=%zu reason=[%s]"), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, + 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)); } static void log_fr_max_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_max_data *fr, const char *dir) { log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " MAX_DATA(0x%02" PRIx64 ") max_data=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_data); + log->user_data, + (NGTCP2_LOG_PKT " MAX_DATA(0x%02" PRIx64 ") max_data=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_data); } static void log_fr_max_stream_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -333,9 +331,9 @@ static void log_fr_max_stream_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, static void log_fr_max_streams(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_max_streams *fr, const char *dir) { log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " MAX_STREAMS(0x%02" PRIx64 ") max_streams=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); + log->user_data, + (NGTCP2_LOG_PKT " MAX_STREAMS(0x%02" PRIx64 ") max_streams=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); } static void log_fr_ping(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -348,9 +346,9 @@ static void log_fr_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_data_blocked *fr, const char *dir) { log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " DATA_BLOCKED(0x%02" PRIx64 ") offset=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset); + log->user_data, + (NGTCP2_LOG_PKT " DATA_BLOCKED(0x%02" PRIx64 ") offset=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset); } static void log_fr_stream_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -367,9 +365,9 @@ static void log_fr_streams_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_streams_blocked *fr, const char *dir) { log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " STREAMS_BLOCKED(0x%02" PRIx64 ") max_streams=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); + log->user_data, + (NGTCP2_LOG_PKT " STREAMS_BLOCKED(0x%02" PRIx64 ") max_streams=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); } static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -379,15 +377,15 @@ static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, uint8_t cid[sizeof(fr->cid.data) * 2 + 1]; log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " NEW_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64 - " cid=0x%s retire_prior_to=%" PRIu64 - " stateless_reset_token=0x%s"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq, - (const char *)ngtcp2_encode_hex(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))); + log->user_data, + (NGTCP2_LOG_PKT " NEW_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64 + " cid=0x%s retire_prior_to=%" PRIu64 + " stateless_reset_token=0x%s"), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq, + (const char *)ngtcp2_encode_hex(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))); } static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -406,10 +404,10 @@ static void log_fr_path_challenge(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, uint8_t buf[sizeof(fr->data) * 2 + 1]; log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64 ") data=0x%s"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, - (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); + log->user_data, + (NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64 ") data=0x%s"), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, + (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); } static void log_fr_path_response(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -418,19 +416,19 @@ static void log_fr_path_response(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, uint8_t buf[sizeof(fr->data) * 2 + 1]; log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64 ") data=0x%s"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, - (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); + log->user_data, + (NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64 ") data=0x%s"), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, + (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); } static void log_fr_crypto(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stream *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " CRYPTO(0x%02" PRIx64 ") offset=%" PRIu64 - " len=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset, - ngtcp2_vec_len(fr->data, fr->datacnt)); + log->log_printf( + log->user_data, + (NGTCP2_LOG_PKT " CRYPTO(0x%02" PRIx64 ") offset=%" PRIu64 " len=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset, + ngtcp2_vec_len(fr->data, fr->datacnt)); } static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -448,9 +446,9 @@ static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, p = ngtcp2_encode_hex(buf, fr->token, fr->tokenlen); } log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " NEW_TOKEN(0x%02" PRIx64 ") token=0x%s len=%zu"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)p, fr->tokenlen); + log->user_data, + (NGTCP2_LOG_PKT " NEW_TOKEN(0x%02" PRIx64 ") token=0x%s len=%zu"), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)p, fr->tokenlen); } static void log_fr_retire_connection_id(ngtcp2_log *log, @@ -458,9 +456,9 @@ static void log_fr_retire_connection_id(ngtcp2_log *log, const ngtcp2_retire_connection_id *fr, const char *dir) { log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " RETIRE_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq); + log->user_data, + (NGTCP2_LOG_PKT " RETIRE_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64), + NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq); } static void log_fr_handshake_done(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, @@ -601,11 +599,11 @@ void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) { shd.type = NGTCP2_PKT_STATELESS_RESET; log->log_printf( - log->user_data, (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)), - sr->randlen); + log->user_data, (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)), + sr->randlen); } void ngtcp2_log_remote_tp(ngtcp2_log *log, @@ -625,10 +623,10 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, if (params->stateless_reset_token_present) { log->log_printf( - log->user_data, (NGTCP2_LOG_TP " stateless_reset_token=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(token, params->stateless_reset_token, - sizeof(params->stateless_reset_token))); + log->user_data, (NGTCP2_LOG_TP " stateless_reset_token=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(token, params->stateless_reset_token, + sizeof(params->stateless_reset_token))); } if (params->preferred_addr_present) { @@ -639,7 +637,7 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, (NGTCP2_LOG_TP " preferred_address.ipv4_addr=%s"), NGTCP2_LOG_TP_HD_FIELDS, (const char *)ngtcp2_encode_ipv4( - addr, (const uint8_t *)&sa_in->sin_addr)); + addr, (const uint8_t *)&sa_in->sin_addr)); log->log_printf(log->user_data, (NGTCP2_LOG_TP " preferred_address.ipv4_port=%u"), NGTCP2_LOG_TP_HD_FIELDS, ngtcp2_ntohs(sa_in->sin_port)); @@ -652,59 +650,59 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, (NGTCP2_LOG_TP " preferred_address.ipv6_addr=%s"), NGTCP2_LOG_TP_HD_FIELDS, (const char *)ngtcp2_encode_ipv6( - addr, (const uint8_t *)&sa_in6->sin6_addr)); + addr, (const uint8_t *)&sa_in6->sin6_addr)); log->log_printf(log->user_data, (NGTCP2_LOG_TP " preferred_address.ipv6_port=%u"), NGTCP2_LOG_TP_HD_FIELDS, ngtcp2_ntohs(sa_in6->sin6_port)); } log->log_printf( - log->user_data, (NGTCP2_LOG_TP " preferred_address.cid=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->preferred_addr.cid.data, - params->preferred_addr.cid.datalen)); + log->user_data, (NGTCP2_LOG_TP " preferred_address.cid=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(cid, params->preferred_addr.cid.data, + params->preferred_addr.cid.datalen)); log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex( - token, params->preferred_addr.stateless_reset_token, - sizeof(params->preferred_addr.stateless_reset_token))); + log->user_data, + (NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex( + token, params->preferred_addr.stateless_reset_token, + sizeof(params->preferred_addr.stateless_reset_token))); } if (params->original_dcid_present) { log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " original_destination_connection_id=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->original_dcid.data, - params->original_dcid.datalen)); + log->user_data, + (NGTCP2_LOG_TP " original_destination_connection_id=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(cid, params->original_dcid.data, + params->original_dcid.datalen)); } if (params->retry_scid_present) { log->log_printf( - log->user_data, (NGTCP2_LOG_TP " retry_source_connection_id=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->retry_scid.data, - params->retry_scid.datalen)); + log->user_data, (NGTCP2_LOG_TP " retry_source_connection_id=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(cid, params->retry_scid.data, + params->retry_scid.datalen)); } if (params->initial_scid_present) { log->log_printf( - log->user_data, (NGTCP2_LOG_TP " initial_source_connection_id=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->initial_scid.data, - params->initial_scid.datalen)); + log->user_data, (NGTCP2_LOG_TP " initial_source_connection_id=0x%s"), + NGTCP2_LOG_TP_HD_FIELDS, + (const char *)ngtcp2_encode_hex(cid, params->initial_scid.data, + params->initial_scid.datalen)); } log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " initial_max_stream_data_bidi_local=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_bidi_local); + log->user_data, + (NGTCP2_LOG_TP " initial_max_stream_data_bidi_local=%" PRIu64), + NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_bidi_local); log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " initial_max_stream_data_bidi_remote=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_bidi_remote); + log->user_data, + (NGTCP2_LOG_TP " initial_max_stream_data_bidi_remote=%" PRIu64), + NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_bidi_remote); log->log_printf(log->user_data, (NGTCP2_LOG_TP " initial_max_stream_data_uni=%" PRIu64), NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_uni); @@ -742,21 +740,21 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, if (params->version_info_present) { log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " version_information.chosen_version=0x%08x"), - NGTCP2_LOG_TP_HD_FIELDS, params->version_info.chosen_version); + log->user_data, + (NGTCP2_LOG_TP " version_information.chosen_version=0x%08x"), + NGTCP2_LOG_TP_HD_FIELDS, params->version_info.chosen_version); assert(!(params->version_info.available_versionslen & 0x3)); for (i = 0, p = params->version_info.available_versions; i < params->version_info.available_versionslen; i += sizeof(uint32_t)) { - p = ngtcp2_get_uint32(&version, p); + p = ngtcp2_get_uint32be(&version, p); log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " version_information.available_versions[%zu]=0x%08x"), - NGTCP2_LOG_TP_HD_FIELDS, i >> 2, version); + log->user_data, + (NGTCP2_LOG_TP " version_information.available_versions[%zu]=0x%08x"), + NGTCP2_LOG_TP_HD_FIELDS, i >> 2, version); } } } @@ -783,18 +781,18 @@ static void log_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, if (hd->type == NGTCP2_PKT_1RTT) { ngtcp2_log_info( - 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), - strpkttype(hd), (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) != 0); + 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), + strpkttype(hd), (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) != 0); } else { ngtcp2_log_info( - 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), - hd->version, strpkttype(hd), hd->len); + 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), + hd->version, strpkttype(hd), hd->len); } } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h index 1280ce04d6385a..13fb81a72e1d51 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -129,4 +129,4 @@ void ngtcp2_log_tx_cancel(ngtcp2_log *log, const ngtcp2_pkt_hd *hd); void ngtcp2_log_info(ngtcp2_log *log, ngtcp2_log_event ev, const char *fmt, ...); -#endif /* NGTCP2_LOG_H */ +#endif /* !defined(NGTCP2_LOG_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h index 28d3461bef9238..dfe5e0aed220f8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_macro.h @@ -27,17 +27,14 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include -#define ngtcp2_min(A, B) ((A) < (B) ? (A) : (B)) -#define ngtcp2_max(A, B) ((A) > (B) ? (A) : (B)) - #define ngtcp2_struct_of(ptr, type, member) \ - ((type *)(void *)((char *)(ptr)-offsetof(type, member))) + ((type *)(void *)((char *)(ptr) - offsetof(type, member))) /* ngtcp2_list_insert inserts |T| before |*PD|. The contract is that this is singly linked list, and the next element is pointed by next @@ -55,4 +52,30 @@ */ #define ngtcp2_arraylen(A) (sizeof(A) / sizeof(A[0])) -#endif /* NGTCP2_MACRO_H */ +#define ngtcp2_max_def(SUFFIX, T) \ + static inline T ngtcp2_max_##SUFFIX(T a, T b) { return a < b ? b : a; } + +ngtcp2_max_def(int8, int8_t) +ngtcp2_max_def(int16, int16_t) +ngtcp2_max_def(int32, int32_t) +ngtcp2_max_def(int64, int64_t) +ngtcp2_max_def(uint8, uint8_t) +ngtcp2_max_def(uint16, uint16_t) +ngtcp2_max_def(uint32, uint32_t) +ngtcp2_max_def(uint64, uint64_t) +ngtcp2_max_def(size, size_t) + +#define ngtcp2_min_def(SUFFIX, T) \ + static inline T ngtcp2_min_##SUFFIX(T a, T b) { return a < b ? a : b; } + +ngtcp2_min_def(int8, int8_t) +ngtcp2_min_def(int16, int16_t) +ngtcp2_min_def(int32, int32_t) +ngtcp2_min_def(int64, int64_t) +ngtcp2_min_def(uint8, uint8_t) +ngtcp2_min_def(uint16, uint16_t) +ngtcp2_min_def(uint32, uint32_t) +ngtcp2_min_def(uint64, uint64_t) +ngtcp2_min_def(size, size_t) + +#endif /* !defined(NGTCP2_MACRO_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c index 33e9fcc018b5db..9eb102f16b32e2 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c @@ -35,8 +35,7 @@ void ngtcp2_map_init(ngtcp2_map *map, const ngtcp2_mem *mem) { map->mem = mem; - map->tablelen = 0; - map->tablelenbits = 0; + map->hashbits = 0; map->table = NULL; map->size = 0; } @@ -49,33 +48,20 @@ void ngtcp2_map_free(ngtcp2_map *map) { ngtcp2_mem_free(map->mem, map->table); } -void ngtcp2_map_each_free(ngtcp2_map *map, int (*func)(void *data, void *ptr), - void *ptr) { - uint32_t i; - ngtcp2_map_bucket *bkt; - - for (i = 0; i < map->tablelen; ++i) { - bkt = &map->table[i]; - - if (bkt->data == NULL) { - continue; - } - - func(bkt->data, ptr); - } -} - -int ngtcp2_map_each(ngtcp2_map *map, int (*func)(void *data, void *ptr), +int ngtcp2_map_each(const ngtcp2_map *map, int (*func)(void *data, void *ptr), void *ptr) { int rv; - uint32_t i; + size_t i; ngtcp2_map_bucket *bkt; + size_t tablelen; if (map->size == 0) { return 0; } - for (i = 0; i < map->tablelen; ++i) { + tablelen = 1u << map->hashbits; + + for (i = 0; i < tablelen; ++i) { bkt = &map->table[i]; if (bkt->data == NULL) { @@ -91,82 +77,61 @@ int ngtcp2_map_each(ngtcp2_map *map, int (*func)(void *data, void *ptr), return 0; } -static uint32_t hash(ngtcp2_map_key_type key) { - return (uint32_t)((key * 11400714819323198485llu) >> 32); -} - -static size_t h2idx(uint32_t hash, uint32_t bits) { - return hash >> (32 - bits); -} - -static size_t distance(uint32_t tablelen, uint32_t tablelenbits, - ngtcp2_map_bucket *bkt, size_t idx) { - return (idx - h2idx(bkt->hash, tablelenbits)) & (tablelen - 1); +static size_t hash(ngtcp2_map_key_type key, size_t bits) { + return (size_t)((key * 11400714819323198485llu) >> (64 - bits)); } -static void map_bucket_swap(ngtcp2_map_bucket *bkt, uint32_t *phash, - ngtcp2_map_key_type *pkey, void **pdata) { - uint32_t h = bkt->hash; - ngtcp2_map_key_type key = bkt->key; - void *data = bkt->data; - - bkt->hash = *phash; - bkt->key = *pkey; - bkt->data = *pdata; +static void map_bucket_swap(ngtcp2_map_bucket *a, ngtcp2_map_bucket *b) { + ngtcp2_map_bucket c = *a; - *phash = h; - *pkey = key; - *pdata = data; -} - -static void map_bucket_set_data(ngtcp2_map_bucket *bkt, uint32_t hash, - ngtcp2_map_key_type key, void *data) { - bkt->hash = hash; - bkt->key = key; - bkt->data = data; + *a = *b; + *b = c; } #ifndef WIN32 -void ngtcp2_map_print_distance(ngtcp2_map *map) { - uint32_t i; +void ngtcp2_map_print_distance(const ngtcp2_map *map) { + size_t i; size_t idx; ngtcp2_map_bucket *bkt; + size_t tablelen; - for (i = 0; i < map->tablelen; ++i) { + if (map->size == 0) { + return; + } + + tablelen = 1u << map->hashbits; + + for (i = 0; i < tablelen; ++i) { bkt = &map->table[i]; if (bkt->data == NULL) { - fprintf(stderr, "@%u \n", i); + fprintf(stderr, "@%zu \n", i); continue; } - idx = h2idx(bkt->hash, map->tablelenbits); - fprintf(stderr, "@%u hash=%08x key=%" PRIu64 " base=%zu distance=%zu\n", i, - bkt->hash, bkt->key, idx, - distance(map->tablelen, map->tablelenbits, bkt, idx)); + idx = hash(bkt->key, map->hashbits); + fprintf(stderr, "@%zu hash=%zu key=%" PRIu64 " base=%zu distance=%u\n", i, + hash(bkt->key, map->hashbits), bkt->key, idx, bkt->psl); } } -#endif /* !WIN32 */ +#endif /* !defined(WIN32) */ -static int insert(ngtcp2_map_bucket *table, uint32_t tablelen, - uint32_t tablelenbits, uint32_t hash, ngtcp2_map_key_type key, - void *data) { - size_t idx = h2idx(hash, tablelenbits); - size_t d = 0, dd; - ngtcp2_map_bucket *bkt; +static int insert(ngtcp2_map_bucket *table, size_t hashbits, + ngtcp2_map_key_type key, void *data) { + size_t idx = hash(key, hashbits); + ngtcp2_map_bucket b = {0, key, data}, *bkt; + size_t mask = (1u << hashbits) - 1; for (;;) { bkt = &table[idx]; if (bkt->data == NULL) { - map_bucket_set_data(bkt, hash, key, data); + *bkt = b; return 0; } - dd = distance(tablelen, tablelenbits, bkt, idx); - if (d > dd) { - map_bucket_swap(bkt, &hash, &key, &data); - d = dd; + 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 @@ -175,41 +140,42 @@ static int insert(ngtcp2_map_bucket *table, uint32_t tablelen, return NGTCP2_ERR_INVALID_ARGUMENT; } - ++d; - idx = (idx + 1) & (tablelen - 1); + ++b.psl; + idx = (idx + 1) & mask; } } -/* new_tablelen must be power of 2 and new_tablelen == (1 << - new_tablelenbits) must hold. */ -static int map_resize(ngtcp2_map *map, uint32_t new_tablelen, - uint32_t new_tablelenbits) { - uint32_t i; +static int map_resize(ngtcp2_map *map, size_t new_hashbits) { + size_t i; ngtcp2_map_bucket *new_table; ngtcp2_map_bucket *bkt; + size_t tablelen; int rv; (void)rv; new_table = - ngtcp2_mem_calloc(map->mem, new_tablelen, sizeof(ngtcp2_map_bucket)); + ngtcp2_mem_calloc(map->mem, 1u << new_hashbits, sizeof(ngtcp2_map_bucket)); if (new_table == NULL) { return NGTCP2_ERR_NOMEM; } - for (i = 0; i < map->tablelen; ++i) { - bkt = &map->table[i]; - if (bkt->data == NULL) { - continue; - } - rv = insert(new_table, new_tablelen, new_tablelenbits, bkt->hash, bkt->key, - bkt->data); + if (map->size) { + tablelen = 1u << map->hashbits; - assert(0 == rv); + for (i = 0; i < tablelen; ++i) { + bkt = &map->table[i]; + if (bkt->data == NULL) { + continue; + } + + rv = insert(new_table, new_hashbits, bkt->key, bkt->data); + + assert(0 == rv); + } } ngtcp2_mem_free(map->mem, map->table); - map->tablelen = new_tablelen; - map->tablelenbits = new_tablelenbits; + map->hashbits = new_hashbits; map->table = new_table; return 0; @@ -221,48 +187,49 @@ int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data) { assert(data); /* Load factor is 0.75 */ - if ((map->size + 1) * 4 > map->tablelen * 3) { - if (map->tablelen) { - rv = map_resize(map, map->tablelen * 2, map->tablelenbits + 1); + /* Under the very initial condition, that is map->size == 0 and + map->hashbits == 0, 4 > 3 still holds nicely. */ + if ((map->size + 1) * 4 > (1u << map->hashbits) * 3) { + if (map->hashbits) { + rv = map_resize(map, map->hashbits + 1); if (rv != 0) { return rv; } } else { - rv = map_resize(map, 1 << NGTCP2_INITIAL_TABLE_LENBITS, - NGTCP2_INITIAL_TABLE_LENBITS); + rv = map_resize(map, NGTCP2_INITIAL_TABLE_LENBITS); if (rv != 0) { return rv; } } } - rv = insert(map->table, map->tablelen, map->tablelenbits, hash(key), key, - data); + rv = insert(map->table, map->hashbits, key, data); if (rv != 0) { return rv; } + ++map->size; + return 0; } -void *ngtcp2_map_find(ngtcp2_map *map, ngtcp2_map_key_type key) { - uint32_t h; +void *ngtcp2_map_find(const ngtcp2_map *map, ngtcp2_map_key_type key) { size_t idx; ngtcp2_map_bucket *bkt; - size_t d = 0; + size_t psl = 0; + size_t mask; if (map->size == 0) { return NULL; } - h = hash(key); - idx = h2idx(h, map->tablelenbits); + idx = hash(key, map->hashbits); + mask = (1u << map->hashbits) - 1; for (;;) { bkt = &map->table[idx]; - if (bkt->data == NULL || - d > distance(map->tablelen, map->tablelenbits, bkt, idx)) { + if (bkt->data == NULL || psl > bkt->psl) { return NULL; } @@ -270,50 +237,47 @@ void *ngtcp2_map_find(ngtcp2_map *map, ngtcp2_map_key_type key) { return bkt->data; } - ++d; - idx = (idx + 1) & (map->tablelen - 1); + ++psl; + idx = (idx + 1) & mask; } } int ngtcp2_map_remove(ngtcp2_map *map, ngtcp2_map_key_type key) { - uint32_t h; - size_t idx, didx; - ngtcp2_map_bucket *bkt; - size_t d = 0; + size_t idx; + ngtcp2_map_bucket *b, *bkt; + size_t psl = 0; + size_t mask; if (map->size == 0) { return NGTCP2_ERR_INVALID_ARGUMENT; } - h = hash(key); - idx = h2idx(h, map->tablelenbits); + idx = hash(key, map->hashbits); + mask = (1u << map->hashbits) - 1; for (;;) { bkt = &map->table[idx]; - if (bkt->data == NULL || - d > distance(map->tablelen, map->tablelenbits, bkt, idx)) { + if (bkt->data == NULL || psl > bkt->psl) { return NGTCP2_ERR_INVALID_ARGUMENT; } if (bkt->key == key) { - map_bucket_set_data(bkt, 0, 0, NULL); - - didx = idx; - idx = (idx + 1) & (map->tablelen - 1); + b = bkt; + idx = (idx + 1) & mask; for (;;) { bkt = &map->table[idx]; - if (bkt->data == NULL || - distance(map->tablelen, map->tablelenbits, bkt, idx) == 0) { + if (bkt->data == NULL || bkt->psl == 0) { + b->data = NULL; break; } - map->table[didx] = *bkt; - map_bucket_set_data(bkt, 0, 0, NULL); - didx = idx; + --bkt->psl; + *b = *bkt; + b = bkt; - idx = (idx + 1) & (map->tablelen - 1); + idx = (idx + 1) & mask; } --map->size; @@ -321,18 +285,18 @@ int ngtcp2_map_remove(ngtcp2_map *map, ngtcp2_map_key_type key) { return 0; } - ++d; - idx = (idx + 1) & (map->tablelen - 1); + ++psl; + idx = (idx + 1) & mask; } } void ngtcp2_map_clear(ngtcp2_map *map) { - if (map->tablelen == 0) { + if (map->size == 0) { return; } - memset(map->table, 0, sizeof(*map->table) * map->tablelen); + memset(map->table, 0, sizeof(*map->table) * (1u << map->hashbits)); map->size = 0; } -size_t ngtcp2_map_size(ngtcp2_map *map) { return map->size; } +size_t ngtcp2_map_size(const ngtcp2_map *map) { return map->size; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h index d05b1657489e45..9d882fb20088d8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h @@ -28,7 +28,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -39,7 +39,7 @@ typedef uint64_t ngtcp2_map_key_type; typedef struct ngtcp2_map_bucket { - uint32_t hash; + uint32_t psl; ngtcp2_map_key_type key; void *data; } ngtcp2_map_bucket; @@ -48,33 +48,24 @@ typedef struct ngtcp2_map { ngtcp2_map_bucket *table; const ngtcp2_mem *mem; size_t size; - uint32_t tablelen; - uint32_t tablelenbits; + size_t hashbits; } ngtcp2_map; /* - * Initializes the map |map|. + * ngtcp2_map_init initializes the map |map|. */ void ngtcp2_map_init(ngtcp2_map *map, const ngtcp2_mem *mem); /* - * Deallocates any resources allocated for |map|. The stored entries - * are not freed by this function. Use ngtcp2_map_each_free() to free - * each entries. + * ngtcp2_map_free deallocates any resources allocated for |map|. The + * stored entries are not freed by this function. Use + * ngtcp2_map_each() to free each entry. */ void ngtcp2_map_free(ngtcp2_map *map); /* - * Deallocates each entries using |func| function and any resources - * allocated for |map|. The |func| function is responsible for freeing - * given the |data| object. The |ptr| will be passed to the |func| as - * send argument. The return value of the |func| will be ignored. - */ -void ngtcp2_map_each_free(ngtcp2_map *map, int (*func)(void *data, void *ptr), - void *ptr); - -/* - * Inserts the new |data| with the |key| to the map |map|. + * ngtcp2_map_insert inserts the new |data| with the |key| to the map + * |map|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -82,57 +73,56 @@ void ngtcp2_map_each_free(ngtcp2_map *map, int (*func)(void *data, void *ptr), * NGTCP2_ERR_INVALID_ARGUMENT * The item associated by |key| already exists. * NGTCP2_ERR_NOMEM - * Out of memory + * Out of memory */ int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data); /* - * Returns the data associated by the key |key|. If there is no such - * data, this function returns NULL. + * ngtcp2_map_find returns the entry associated by the key |key|. If + * there is no such entry, this function returns NULL. */ -void *ngtcp2_map_find(ngtcp2_map *map, ngtcp2_map_key_type key); +void *ngtcp2_map_find(const ngtcp2_map *map, ngtcp2_map_key_type key); /* - * Removes the data associated by the key |key| from the |map|. The - * removed data is not freed by this function. + * ngtcp2_map_remove removes the entry associated by the key |key| + * from the |map|. The removed entry is not freed by this function. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * NGTCP2_ERR_INVALID_ARGUMENT - * The data associated by |key| does not exist. + * The entry associated by |key| does not exist. */ int ngtcp2_map_remove(ngtcp2_map *map, ngtcp2_map_key_type key); /* - * Removes all entries from |map|. + * ngtcp2_map_clear removes all entries from |map|. The removed entry + * is not freed by this function. */ void ngtcp2_map_clear(ngtcp2_map *map); /* - * Returns the number of items stored in the map |map|. + * ngtcp2_map_size returns the number of items stored in the map + * |map|. */ -size_t ngtcp2_map_size(ngtcp2_map *map); +size_t ngtcp2_map_size(const ngtcp2_map *map); /* - * Applies the function |func| to each data in the |map| with the - * optional user supplied pointer |ptr|. + * ngtcp2_map_each applies the function |func| to each entry in the + * |map| with the optional user supplied pointer |ptr|. * * If the |func| returns 0, this function calls the |func| with the - * next data. If the |func| returns nonzero, it will not call the + * next entry. If the |func| returns nonzero, it will not call the * |func| for further entries and return the return value of the * |func| immediately. Thus, this function returns 0 if all the * invocations of the |func| return 0, or nonzero value which the last * invocation of |func| returns. - * - * Don't use this function to free each data. Use - * ngtcp2_map_each_free() instead. */ -int ngtcp2_map_each(ngtcp2_map *map, int (*func)(void *data, void *ptr), +int ngtcp2_map_each(const ngtcp2_map *map, int (*func)(void *data, void *ptr), void *ptr); #ifndef WIN32 -void ngtcp2_map_print_distance(ngtcp2_map *map); -#endif /* !WIN32 */ +void ngtcp2_map_print_distance(const ngtcp2_map *map); +#endif /* !defined(WIN32) */ -#endif /* NGTCP2_MAP_H */ +#endif /* !defined(NGTCP2_MAP_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c index bcce0b5cdfcf02..d30e1f986e97d3 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.c @@ -72,7 +72,7 @@ void *ngtcp2_mem_calloc(const ngtcp2_mem *mem, size_t nmemb, size_t size) { void *ngtcp2_mem_realloc(const ngtcp2_mem *mem, void *ptr, size_t size) { return mem->realloc(ptr, size, mem->user_data); } -#else /* MEMDEBUG */ +#else /* defined(MEMDEBUG) */ void *ngtcp2_mem_malloc_debug(const ngtcp2_mem *mem, size_t size, const char *func, const char *file, size_t line) { void *nptr = mem->malloc(size, mem->user_data); @@ -110,4 +110,4 @@ void *ngtcp2_mem_realloc_debug(const ngtcp2_mem *mem, void *ptr, size_t size, return nptr; } -#endif /* MEMDEBUG */ +#endif /* defined(MEMDEBUG) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.h index c99b6c59726891..9f818752125523 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_mem.h @@ -28,7 +28,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -42,7 +42,7 @@ void ngtcp2_mem_free(const ngtcp2_mem *mem, void *ptr); void *ngtcp2_mem_calloc(const ngtcp2_mem *mem, size_t nmemb, size_t size); void *ngtcp2_mem_realloc(const ngtcp2_mem *mem, void *ptr, size_t size); -#else /* MEMDEBUG */ +#else /* defined(MEMDEBUG) */ void *ngtcp2_mem_malloc_debug(const ngtcp2_mem *mem, size_t size, const char *func, const char *file, size_t line); @@ -67,6 +67,6 @@ void *ngtcp2_mem_realloc_debug(const ngtcp2_mem *mem, void *ptr, size_t size, # define ngtcp2_mem_realloc(MEM, PTR, SIZE) \ ngtcp2_mem_realloc_debug((MEM), (PTR), (SIZE), __func__, __FILE__, __LINE__) -#endif /* MEMDEBUG */ +#endif /* defined(MEMDEBUG) */ -#endif /* NGTCP2_MEM_H */ +#endif /* !defined(NGTCP2_MEM_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h index 4a2c4041d4d170..103a2fb2d80714 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_net.h @@ -30,70 +30,68 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #ifdef HAVE_ARPA_INET_H # include -#endif /* HAVE_ARPA_INET_H */ +#endif /* defined(HAVE_ARPA_INET_H) */ #ifdef HAVE_NETINET_IN_H # include -#endif /* HAVE_NETINET_IN_H */ +#endif /* defined(HAVE_NETINET_IN_H) */ #ifdef HAVE_BYTESWAP_H # include -#endif /* HAVE_BYTESWAP_H */ +#endif /* defined(HAVE_BYTESWAP_H) */ #ifdef HAVE_ENDIAN_H # include -#endif /* HAVE_ENDIAN_H */ +#endif /* defined(HAVE_ENDIAN_H) */ #ifdef HAVE_SYS_ENDIAN_H # include -#endif /* HAVE_SYS_ENDIAN_H */ +#endif /* defined(HAVE_SYS_ENDIAN_H) */ -#if defined(__APPLE__) +#ifdef __APPLE__ # include -#endif // __APPLE__ +#endif /* defined(__APPLE__) */ #include -#if defined(HAVE_BE64TOH) || \ - (defined(HAVE_DECL_BE64TOH) && HAVE_DECL_BE64TOH > 0) +#if HAVE_DECL_BE64TOH # define ngtcp2_ntohl64(N) be64toh(N) # define ngtcp2_htonl64(N) htobe64(N) -#else /* !HAVE_BE64TOH */ -# if defined(WORDS_BIGENDIAN) +#else /* !HAVE_DECL_BE64TOH */ +# ifdef WORDS_BIGENDIAN # define ngtcp2_ntohl64(N) (N) # define ngtcp2_htonl64(N) (N) -# else /* !WORDS_BIGENDIAN */ -# if defined(HAVE_BSWAP_64) || \ - (defined(HAVE_DECL_BSWAP_64) && HAVE_DECL_BSWAP_64 > 0) +# else /* !defined(WORDS_BIGENDIAN) */ +# if HAVE_DECL_BSWAP_64 # define ngtcp2_bswap64 bswap_64 # elif defined(WIN32) # define ngtcp2_bswap64 _byteswap_uint64 # elif defined(__APPLE__) # define ngtcp2_bswap64 OSSwapInt64 -# else /* !HAVE_BSWAP_64 && !WIN32 && !__APPLE__ */ +# else /* !(HAVE_DECL_BSWAP_64 || defined(WIN32) || defined(__APPLE__)) */ # define ngtcp2_bswap64(N) \ ((uint64_t)(ngtcp2_ntohl((uint32_t)(N))) << 32 | \ ngtcp2_ntohl((uint32_t)((N) >> 32))) -# endif /* !HAVE_BSWAP_64 && !WIN32 && !__APPLE__ */ +# endif /* !(HAVE_DECL_BSWAP_64 || defined(WIN32) || defined(__APPLE__)) */ # define ngtcp2_ntohl64(N) ngtcp2_bswap64(N) # define ngtcp2_htonl64(N) ngtcp2_bswap64(N) -# endif /* !WORDS_BIGENDIAN */ -#endif /* !HAVE_BE64TOH */ +# endif /* !defined(WORDS_BIGENDIAN) */ +#endif /* !HAVE_DECL_BE64TOH */ -#if defined(WIN32) +#ifdef WIN32 /* Windows requires ws2_32 library for ntonl family functions. We define inline functions for those function so that we don't have dependency on that lib. */ # ifdef _MSC_VER # define STIN static __inline -# else +# else /* !defined(_MSC_VER) */ # define STIN static inline -# endif +# endif /* !defined(_MSC_VER) */ STIN uint32_t ngtcp2_htonl(uint32_t hostlong) { uint32_t res; @@ -131,13 +129,13 @@ STIN uint16_t ngtcp2_ntohs(uint16_t netshort) { return res; } -#else /* !WIN32 */ +#else /* !defined(WIN32) */ # define ngtcp2_htonl htonl # define ngtcp2_htons htons # define ngtcp2_ntohl ntohl # define ngtcp2_ntohs ntohs -#endif /* !WIN32 */ +#endif /* !defined(WIN32) */ -#endif /* NGTCP2_NET_H */ +#endif /* !defined(NGTCP2_NET_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h index ea73e788317681..cf23de7b2b7f20 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_objalloc.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -67,9 +67,9 @@ void ngtcp2_objalloc_clear(ngtcp2_objalloc *objalloc); #ifndef NOMEMPOOL # define ngtcp2_objalloc_decl(NAME, TYPE, OPLENTFIELD) \ inline static void ngtcp2_objalloc_##NAME##_init( \ - ngtcp2_objalloc *objalloc, size_t nmemb, const ngtcp2_mem *mem) { \ + ngtcp2_objalloc *objalloc, size_t nmemb, const ngtcp2_mem *mem) { \ ngtcp2_objalloc_init( \ - objalloc, ((sizeof(TYPE) + 0xfu) & ~(uintptr_t)0xfu) * nmemb, mem); \ + objalloc, ((sizeof(TYPE) + 0xfu) & ~(uintptr_t)0xfu) * nmemb, mem); \ } \ \ TYPE *ngtcp2_objalloc_##NAME##_get(ngtcp2_objalloc *objalloc); \ @@ -78,7 +78,7 @@ void ngtcp2_objalloc_clear(ngtcp2_objalloc *objalloc); size_t len); \ \ inline static void ngtcp2_objalloc_##NAME##_release( \ - ngtcp2_objalloc *objalloc, TYPE *obj) { \ + ngtcp2_objalloc *objalloc, TYPE *obj) { \ ngtcp2_opl_push(&objalloc->opl, &obj->OPLENTFIELD); \ } @@ -90,7 +90,7 @@ void ngtcp2_objalloc_clear(ngtcp2_objalloc *objalloc); \ if (!oplent) { \ rv = \ - ngtcp2_balloc_get(&objalloc->balloc, (void **)&obj, sizeof(TYPE)); \ + ngtcp2_balloc_get(&objalloc->balloc, (void **)&obj, sizeof(TYPE)); \ if (rv != 0) { \ return NULL; \ } \ @@ -118,30 +118,30 @@ void ngtcp2_objalloc_clear(ngtcp2_objalloc *objalloc); \ return ngtcp2_struct_of(oplent, TYPE, OPLENTFIELD); \ } -#else /* NOMEMPOOL */ +#else /* defined(NOMEMPOOL) */ # define ngtcp2_objalloc_decl(NAME, TYPE, OPLENTFIELD) \ inline static void ngtcp2_objalloc_##NAME##_init( \ - ngtcp2_objalloc *objalloc, size_t nmemb, const ngtcp2_mem *mem) { \ + ngtcp2_objalloc *objalloc, size_t nmemb, const ngtcp2_mem *mem) { \ ngtcp2_objalloc_init( \ - objalloc, ((sizeof(TYPE) + 0xfu) & ~(uintptr_t)0xfu) * nmemb, mem); \ + objalloc, ((sizeof(TYPE) + 0xfu) & ~(uintptr_t)0xfu) * nmemb, mem); \ } \ \ inline static TYPE *ngtcp2_objalloc_##NAME##_get( \ - ngtcp2_objalloc *objalloc) { \ + ngtcp2_objalloc *objalloc) { \ return ngtcp2_mem_malloc(objalloc->balloc.mem, sizeof(TYPE)); \ } \ \ inline static TYPE *ngtcp2_objalloc_##NAME##_len_get( \ - ngtcp2_objalloc *objalloc, size_t len) { \ + ngtcp2_objalloc *objalloc, size_t len) { \ return ngtcp2_mem_malloc(objalloc->balloc.mem, len); \ } \ \ inline static void ngtcp2_objalloc_##NAME##_release( \ - ngtcp2_objalloc *objalloc, TYPE *obj) { \ + ngtcp2_objalloc *objalloc, TYPE *obj) { \ ngtcp2_mem_free(objalloc->balloc.mem, obj); \ } # define ngtcp2_objalloc_def(NAME, TYPE, OPLENTFIELD) -#endif /* NOMEMPOOL */ +#endif /* defined(NOMEMPOOL) */ -#endif /* NGTCP2_OBJALLOC_H */ +#endif /* !defined(NGTCP2_OBJALLOC_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_opl.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_opl.h index 714aa366304f0d..f2df3f6dccd45e 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_opl.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_opl.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -62,4 +62,4 @@ ngtcp2_opl_entry *ngtcp2_opl_pop(ngtcp2_opl *opl); void ngtcp2_opl_clear(ngtcp2_opl *opl); -#endif /* NGTCP2_OPL_H */ +#endif /* !defined(NGTCP2_OPL_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h index 0c360e936231c8..a708378db32fbb 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -46,4 +46,4 @@ void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local, void ngtcp2_path_storage_init2(ngtcp2_path_storage *ps, const ngtcp2_path *path); -#endif /* NGTCP2_PATH_H */ +#endif /* !defined(NGTCP2_PATH_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c index 1687ff254d94c7..5c82e1bd503f98 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c @@ -83,16 +83,19 @@ int ngtcp2_pkt_decode_version_cid(ngtcp2_version_cid *dest, const uint8_t *data, dcidlen = data[5]; len += dcidlen; + if (datalen < len) { return NGTCP2_ERR_INVALID_ARGUMENT; } + scidlen = data[5 + 1 + dcidlen]; len += scidlen; + if (datalen < len) { return NGTCP2_ERR_INVALID_ARGUMENT; } - ngtcp2_get_uint32(&version, &data[1]); + ngtcp2_get_uint32be(&version, &data[1]); supported_version = ngtcp2_is_supported_version(version); @@ -120,6 +123,7 @@ int ngtcp2_pkt_decode_version_cid(ngtcp2_version_cid *dest, const uint8_t *data, if (!supported_version) { return NGTCP2_ERR_VERSION_NEGOTIATION; } + return 0; } @@ -145,16 +149,19 @@ void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type, size_t len) { hd->flags = flags; hd->type = type; + if (dcid) { hd->dcid = *dcid; } else { ngtcp2_cid_zero(&hd->dcid); } + if (scid) { hd->scid = *scid; } else { ngtcp2_cid_zero(&hd->scid); } + hd->pkt_num = pkt_num; hd->token = NULL; hd->tokenlen = 0; @@ -170,10 +177,11 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, size_t dcil, scil; const uint8_t *p; size_t len = 0; - size_t n; size_t ntokenlen = 0; const uint8_t *token = NULL; size_t tokenlen = 0; + size_t nlonglen = 0; + size_t longlen = 0; uint64_t vi; uint8_t flags = NGTCP2_PKT_FLAG_LONG_FORM; @@ -185,7 +193,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, return NGTCP2_ERR_INVALID_ARGUMENT; } - ngtcp2_get_uint32(&version, &pkt[1]); + ngtcp2_get_uint32be(&version, &pkt[1]); if (version == 0) { type = NGTCP2_PKT_VERSION_NEGOTIATION; @@ -227,6 +235,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, p = &pkt[5]; dcil = *p; + if (dcil > NGTCP2_MAX_CIDLEN) { /* QUIC v1 implementation never expect to receive CID length more than NGTCP2_MAX_CIDLEN. */ @@ -240,9 +249,11 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, p += 1 + dcil; scil = *p; + if (scil > NGTCP2_MAX_CIDLEN) { return NGTCP2_ERR_INVALID_ARGUMENT; } + len += scil; if (pktlen < len) { @@ -264,6 +275,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, if (pktlen - len < vi) { return NGTCP2_ERR_INVALID_ARGUMENT; } + tokenlen = (size_t)vi; len += tokenlen; @@ -285,12 +297,21 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, } /* Length */ - n = ngtcp2_get_uvarintlen(p); - len += n - 1; + nlonglen = ngtcp2_get_uvarintlen(p); + len += nlonglen - 1; if (pktlen < len) { return NGTCP2_ERR_INVALID_ARGUMENT; } + + ngtcp2_get_uvarint(&vi, p); +#if SIZE_MAX > UINT32_MAX + if (vi > SIZE_MAX) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } +#endif /* SIZE_MAX > UINT32_MAX */ + + longlen = (size_t)vi; } dest->flags = flags; @@ -309,24 +330,11 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt, dest->tokenlen = tokenlen; p += ntokenlen + tokenlen; - switch (type) { - case NGTCP2_PKT_RETRY: - dest->len = 0; - break; - default: - if (!(flags & NGTCP2_PKT_FLAG_LONG_FORM)) { - assert(type == NGTCP2_PKT_VERSION_NEGOTIATION); - /* Version Negotiation is not a long header packet. */ - dest->len = 0; - break; - } + dest->len = longlen; - p = ngtcp2_get_uvarint(&vi, p); - if (vi > SIZE_MAX) { - return NGTCP2_ERR_INVALID_ARGUMENT; - } - dest->len = (size_t)vi; - } +#ifndef NDEBUG + p += nlonglen; +#endif /* !defined(NDEBUG) */ assert((size_t)(p - pkt) == len); @@ -401,6 +409,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen, *p = (uint8_t)(NGTCP2_HEADER_FORM_BIT | (ngtcp2_pkt_versioned_type(hd->version, hd->type) << 4) | (uint8_t)(hd->pkt_numlen - 1)); + if (!(hd->flags & NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR)) { *p |= NGTCP2_FIXED_BIT_MASK; } @@ -409,16 +418,20 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen, p = ngtcp2_put_uint32be(p, hd->version); *p++ = (uint8_t)hd->dcid.datalen; + if (hd->dcid.datalen) { p = ngtcp2_cpymem(p, hd->dcid.data, hd->dcid.datalen); } + *p++ = (uint8_t)hd->scid.datalen; + if (hd->scid.datalen) { p = ngtcp2_cpymem(p, hd->scid.data, hd->scid.datalen); } if (hd->type == NGTCP2_PKT_INITIAL) { p = ngtcp2_put_uvarint(p, hd->tokenlen); + if (hd->tokenlen) { p = ngtcp2_cpymem(p, hd->token, hd->tokenlen); } @@ -446,9 +459,11 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen, p = out; *p = (uint8_t)(hd->pkt_numlen - 1); + if (!(hd->flags & NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR)) { *p |= NGTCP2_FIXED_BIT_MASK; } + if (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) { *p |= NGTCP2_SHORT_KEY_PHASE_BIT; } @@ -503,7 +518,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, payloadlen); case NGTCP2_FRAME_STREAM_DATA_BLOCKED: return ngtcp2_pkt_decode_stream_data_blocked_frame( - &dest->stream_data_blocked, payload, payloadlen); + &dest->stream_data_blocked, payload, payloadlen); case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI: case NGTCP2_FRAME_STREAMS_BLOCKED_UNI: return ngtcp2_pkt_decode_streams_blocked_frame(&dest->streams_blocked, @@ -530,7 +545,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, payloadlen); case NGTCP2_FRAME_RETIRE_CONNECTION_ID: return ngtcp2_pkt_decode_retire_connection_id_frame( - &dest->retire_connection_id, payload, payloadlen); + &dest->retire_connection_id, payload, payloadlen); case NGTCP2_FRAME_HANDSHAKE_DONE: return ngtcp2_pkt_decode_handshake_done_frame(&dest->handshake_done, payload, payloadlen); @@ -613,6 +628,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest, if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } + datalen = (size_t)vi; len += datalen; } else { @@ -752,7 +768,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, } /* TODO We might not decode all ranges. It could be very large. */ - max_rangecnt = ngtcp2_min(NGTCP2_MAX_ACK_RANGES, rangecnt); + max_rangecnt = ngtcp2_min_size(NGTCP2_MAX_ACK_RANGES, rangecnt); p = payload + 1; @@ -770,7 +786,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, p = ngtcp2_get_uvarint(&range->gap, p); p = ngtcp2_get_uvarint(&range->len, p); } - for (i = max_rangecnt; i < rangecnt; ++i) { + + for (; i < rangecnt; ++i) { p += ngtcp2_get_uvarintlen(p); p += ngtcp2_get_uvarintlen(p); } @@ -820,18 +837,23 @@ ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest, n = ngtcp2_get_uvarintlen(p); len += n - 1; + if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } + p += n; n = ngtcp2_get_uvarintlen(p); len += n - 1; + if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } + p += n; n = ngtcp2_get_uvarintlen(p); len += n - 1; + if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -849,7 +871,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest, } ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( - ngtcp2_connection_close *dest, const uint8_t *payload, size_t payloadlen) { + ngtcp2_connection_close *dest, const uint8_t *payload, size_t payloadlen) { size_t len = 1 + 1 + 1; const uint8_t *p; size_t reasonlen; @@ -868,6 +890,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( n = ngtcp2_get_uvarintlen(p); len += n - 1; + if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -879,6 +902,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( n = ngtcp2_get_uvarintlen(p); len += n - 1; + if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -888,6 +912,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( nreasonlen = ngtcp2_get_uvarintlen(p); len += nreasonlen - 1; + if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -896,6 +921,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } + reasonlen = (size_t)vi; len += reasonlen; @@ -903,13 +929,16 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( dest->type = type; p = ngtcp2_get_uvarint(&dest->error_code, p); + if (type == NGTCP2_FRAME_CONNECTION_CLOSE) { p = ngtcp2_get_uvarint(&dest->frame_type, p); } else { dest->frame_type = 0; } + dest->reasonlen = reasonlen; p += nreasonlen; + if (reasonlen == 0) { dest->reason = NULL; } else { @@ -951,7 +980,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data *dest, } ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame( - ngtcp2_max_stream_data *dest, const uint8_t *payload, size_t payloadlen) { + ngtcp2_max_stream_data *dest, const uint8_t *payload, size_t payloadlen) { size_t len = 1 + 1 + 1; const uint8_t *p; size_t n; @@ -1055,10 +1084,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked *dest, return (ngtcp2_ssize)len; } -ngtcp2_ssize -ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest, - const uint8_t *payload, - size_t payloadlen) { +ngtcp2_ssize ngtcp2_pkt_decode_stream_data_blocked_frame( + ngtcp2_stream_data_blocked *dest, const uint8_t *payload, size_t payloadlen) { size_t len = 1 + 1 + 1; const uint8_t *p; size_t n; @@ -1097,7 +1124,7 @@ ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest, } ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame( - ngtcp2_streams_blocked *dest, const uint8_t *payload, size_t payloadlen) { + ngtcp2_streams_blocked *dest, const uint8_t *payload, size_t payloadlen) { size_t len = 1 + 1; const uint8_t *p; size_t n; @@ -1124,7 +1151,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame( } ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame( - ngtcp2_new_connection_id *dest, const uint8_t *payload, size_t payloadlen) { + ngtcp2_new_connection_id *dest, const uint8_t *payload, size_t payloadlen) { size_t len = 1 + 1 + 1 + 1 + 16; const uint8_t *p; size_t n; @@ -1138,6 +1165,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame( n = ngtcp2_get_uvarintlen(p); len += n - 1; + if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1146,6 +1174,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame( n = ngtcp2_get_uvarintlen(p); len += n - 1; + if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1197,6 +1226,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest, if (payloadlen < len) { return NGTCP2_ERR_FRAME_ENCODING; } + p += n; n = ngtcp2_get_uvarintlen(p); len += n - 1; @@ -1307,6 +1337,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_stream *dest, p = ngtcp2_get_uvarint(&dest->offset, p); dest->data[0].len = datalen; p += ndatalen; + if (dest->data[0].len) { dest->data[0].base = (uint8_t *)p; p += dest->data[0].len; @@ -1347,6 +1378,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest, if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } + datalen = (size_t)vi; len += datalen; @@ -1442,6 +1474,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest, datalen = (size_t)vi; len += datalen; + break; default: ngtcp2_unreachable(); @@ -1496,7 +1529,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen, return ngtcp2_pkt_encode_data_blocked_frame(out, outlen, &fr->data_blocked); case NGTCP2_FRAME_STREAM_DATA_BLOCKED: return ngtcp2_pkt_encode_stream_data_blocked_frame( - out, outlen, &fr->stream_data_blocked); + out, outlen, &fr->stream_data_blocked); case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI: case NGTCP2_FRAME_STREAMS_BLOCKED_UNI: return ngtcp2_pkt_encode_streams_blocked_frame(out, outlen, @@ -1518,7 +1551,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen, return ngtcp2_pkt_encode_new_token_frame(out, outlen, &fr->new_token); case NGTCP2_FRAME_RETIRE_CONNECTION_ID: return ngtcp2_pkt_encode_retire_connection_id_frame( - out, outlen, &fr->retire_connection_id); + out, outlen, &fr->retire_connection_id); case NGTCP2_FRAME_HANDSHAKE_DONE: return ngtcp2_pkt_encode_handshake_done_frame(out, outlen, &fr->handshake_done); @@ -1586,7 +1619,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen, } ngtcp2_ssize ngtcp2_pkt_encode_ack_frame(uint8_t *out, size_t outlen, - ngtcp2_ack *fr) { + const ngtcp2_ack *fr) { size_t len = 1 + ngtcp2_put_uvarintlen((uint64_t)fr->largest_ack) + ngtcp2_put_uvarintlen(fr->ack_delay) + ngtcp2_put_uvarintlen(fr->rangecnt) + @@ -1676,8 +1709,8 @@ ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen, const ngtcp2_connection_close *fr) { size_t len = 1 + ngtcp2_put_uvarintlen(fr->error_code) + (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE - ? ngtcp2_put_uvarintlen(fr->frame_type) - : 0) + + ? ngtcp2_put_uvarintlen(fr->frame_type) + : 0) + ngtcp2_put_uvarintlen(fr->reasonlen) + fr->reasonlen; uint8_t *p; @@ -1689,10 +1722,13 @@ ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen, *p++ = (uint8_t)fr->type; p = ngtcp2_put_uvarint(p, fr->error_code); + if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) { p = ngtcp2_put_uvarint(p, fr->frame_type); } + p = ngtcp2_put_uvarint(p, fr->reasonlen); + if (fr->reasonlen) { p = ngtcp2_cpymem(p, fr->reason, fr->reasonlen); } @@ -1796,7 +1832,7 @@ ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen, } ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame( - uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr) { + uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr) { size_t len = 1 + ngtcp2_put_uvarintlen((uint64_t)fr->stream_id) + ngtcp2_put_uvarintlen(fr->offset); uint8_t *p; @@ -1986,7 +2022,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen, } ngtcp2_ssize ngtcp2_pkt_encode_retire_connection_id_frame( - uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr) { + uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr) { size_t len = 1 + ngtcp2_put_uvarintlen(fr->seq); uint8_t *p; @@ -2023,9 +2059,9 @@ ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen, const ngtcp2_datagram *fr) { uint64_t datalen = ngtcp2_vec_len(fr->data, fr->datacnt); uint64_t len = - 1 + - (fr->type == NGTCP2_FRAME_DATAGRAM ? 0 : ngtcp2_put_uvarintlen(datalen)) + - datalen; + 1 + + (fr->type == NGTCP2_FRAME_DATAGRAM ? 0 : ngtcp2_put_uvarintlen(datalen)) + + datalen; uint8_t *p; size_t i; @@ -2039,6 +2075,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen, p = out; *p++ = (uint8_t)fr->type; + if (fr->type == NGTCP2_FRAME_DATAGRAM_LEN) { p = ngtcp2_put_uvarint(p, datalen); } @@ -2055,9 +2092,9 @@ ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen, } ngtcp2_ssize ngtcp2_pkt_write_version_negotiation( - uint8_t *dest, size_t destlen, uint8_t unused_random, const uint8_t *dcid, - size_t dcidlen, const uint8_t *scid, size_t scidlen, const uint32_t *sv, - size_t nsv) { + uint8_t *dest, size_t destlen, uint8_t unused_random, const uint8_t *dcid, + size_t dcidlen, const uint8_t *scid, size_t scidlen, const uint32_t *sv, + size_t nsv) { size_t len = 1 + 4 + 1 + dcidlen + 1 + scidlen + nsv * 4; uint8_t *p; size_t i; @@ -2074,10 +2111,13 @@ ngtcp2_ssize ngtcp2_pkt_write_version_negotiation( *p++ = 0xc0 | unused_random; p = ngtcp2_put_uint32be(p, 0); *p++ = (uint8_t)dcidlen; + if (dcidlen) { p = ngtcp2_cpymem(p, dcid, dcidlen); } + *p++ = (uint8_t)scidlen; + if (scidlen) { p = ngtcp2_cpymem(p, scid, scidlen); } @@ -2099,7 +2139,7 @@ size_t ngtcp2_pkt_decode_version_negotiation(uint32_t *dest, assert((payloadlen % sizeof(uint32_t)) == 0); for (; payload != end;) { - payload = ngtcp2_get_uint32(dest++, payload); + payload = ngtcp2_get_uint32be(dest++, payload); } return payloadlen / sizeof(uint32_t); @@ -2150,13 +2190,15 @@ int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num, assert(cand <= (int64_t)NGTCP2_MAX_VARINT - win); return cand + win; } + if (cand > expected + hwin && cand >= win) { return cand - win; } + return cand; } -int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr, int64_t min_pkt_num) { +int ngtcp2_pkt_validate_ack(const ngtcp2_ack *fr, int64_t min_pkt_num) { int64_t largest_ack = fr->largest_ack; size_t i; @@ -2208,7 +2250,7 @@ ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen, p = dest; - randlen = ngtcp2_min(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen); + randlen = ngtcp2_min_size(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen); p = ngtcp2_cpymem(p, rand, randlen); p = ngtcp2_cpymem(p, stateless_reset_token, NGTCP2_STATELESS_RESET_TOKENLEN); @@ -2218,10 +2260,10 @@ ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen, } ngtcp2_ssize ngtcp2_pkt_write_retry( - uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, - const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token, - size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead, - const ngtcp2_crypto_aead_ctx *aead_ctx) { + uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token, + size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead, + const ngtcp2_crypto_aead_ctx *aead_ctx) { ngtcp2_pkt_hd hd; uint8_t pseudo_retry[1500]; ngtcp2_ssize pseudo_retrylen; @@ -2247,8 +2289,8 @@ ngtcp2_ssize ngtcp2_pkt_write_retry( /* len = */ 0); pseudo_retrylen = - ngtcp2_pkt_encode_pseudo_retry(pseudo_retry, sizeof(pseudo_retry), &hd, - /* unused = */ 0, odcid, token, tokenlen); + ngtcp2_pkt_encode_pseudo_retry(pseudo_retry, sizeof(pseudo_retry), &hd, + /* unused = */ 0, odcid, token, tokenlen); if (pseudo_retrylen < 0) { return pseudo_retrylen; } @@ -2285,8 +2327,8 @@ ngtcp2_ssize ngtcp2_pkt_write_retry( } ngtcp2_ssize ngtcp2_pkt_encode_pseudo_retry( - uint8_t *dest, size_t destlen, const ngtcp2_pkt_hd *hd, uint8_t unused, - const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen) { + uint8_t *dest, size_t destlen, const ngtcp2_pkt_hd *hd, uint8_t unused, + const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen) { uint8_t *p = dest; ngtcp2_ssize nwrite; @@ -2382,23 +2424,23 @@ size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset, if (left > 8 + 1073741823 && len > 1073741823) { #if SIZE_MAX > UINT32_MAX - len = ngtcp2_min(len, 4611686018427387903lu); + len = ngtcp2_min_uint64(len, 4611686018427387903lu); #endif /* SIZE_MAX > UINT32_MAX */ - return (size_t)ngtcp2_min(len, (uint64_t)(left - 8)); + return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 8)); } if (left > 4 + 16383 && len > 16383) { - len = ngtcp2_min(len, 1073741823); - return (size_t)ngtcp2_min(len, (uint64_t)(left - 4)); + len = ngtcp2_min_uint64(len, 1073741823); + return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 4)); } if (left > 2 + 63 && len > 63) { - len = ngtcp2_min(len, 16383); - return (size_t)ngtcp2_min(len, (uint64_t)(left - 2)); + len = ngtcp2_min_uint64(len, 16383); + return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 2)); } - len = ngtcp2_min(len, 63); - return (size_t)ngtcp2_min(len, (uint64_t)(left - 1)); + len = ngtcp2_min_uint64(len, 63); + return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 1)); } size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) { @@ -2414,23 +2456,23 @@ size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) { if (left > 8 + 1073741823 && len > 1073741823) { #if SIZE_MAX > UINT32_MAX - len = ngtcp2_min(len, 4611686018427387903lu); + len = ngtcp2_min_size(len, 4611686018427387903lu); #endif /* SIZE_MAX > UINT32_MAX */ - return ngtcp2_min(len, left - 8); + return ngtcp2_min_size(len, left - 8); } if (left > 4 + 16383 && len > 16383) { - len = ngtcp2_min(len, 1073741823); - return ngtcp2_min(len, left - 4); + len = ngtcp2_min_size(len, 1073741823); + return ngtcp2_min_size(len, left - 4); } if (left > 2 + 63 && len > 63) { - len = ngtcp2_min(len, 16383); - return ngtcp2_min(len, left - 2); + len = ngtcp2_min_size(len, 16383); + return ngtcp2_min_size(len, left - 2); } - len = ngtcp2_min(len, 63); - return ngtcp2_min(len, left - 1); + len = ngtcp2_min_size(len, 63); + return ngtcp2_min_size(len, left - 1); } size_t ngtcp2_pkt_datagram_framelen(size_t len) { @@ -2528,5 +2570,6 @@ int ngtcp2_pkt_verify_reserved_bits(uint8_t c) { if (c & NGTCP2_HEADER_FORM_BIT) { return (c & NGTCP2_LONG_RESERVED_BIT_MASK) == 0 ? 0 : NGTCP2_ERR_PROTO; } + return (c & NGTCP2_SHORT_RESERVED_BIT_MASK) == 0 ? 0 : NGTCP2_ERR_PROTO; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h index feec4d32c97bdd..86ebecef7bc870 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -41,7 +41,6 @@ #define NGTCP2_LONG_RESERVED_BIT_MASK 0x0c /* Short header specific macros */ -#define NGTCP2_SHORT_SPIN_BIT_MASK 0x20 #define NGTCP2_SHORT_RESERVED_BIT_MASK 0x18 #define NGTCP2_SHORT_KEY_PHASE_BIT 0x04 @@ -53,6 +52,7 @@ LENGTH<1> + PKN<1> */ #define NGTCP2_MIN_LONG_HEADERLEN (1 + 4 + 1 + 1 + 1 + 1) +/* STREAM frame specific macros */ #define NGTCP2_STREAM_FIN_BIT 0x01 #define NGTCP2_STREAM_LEN_BIT 0x02 #define NGTCP2_STREAM_OFF_BIT 0x04 @@ -72,9 +72,6 @@ the beginning of the payload. */ #define NGTCP2_DATAGRAM_OVERHEAD (1 + 8) -/* NGTCP2_MIN_FRAME_PAYLOADLEN is the minimum frame payload length. */ -#define NGTCP2_MIN_FRAME_PAYLOADLEN 16 - /* NGTCP2_MAX_SERVER_STREAM_ID_BIDI is the maximum bidirectional server stream ID. */ #define NGTCP2_MAX_SERVER_STREAM_ID_BIDI ((int64_t)0x3ffffffffffffffdll) @@ -95,16 +92,15 @@ /* NGTCP2_MAX_PKT_NUM is the maximum packet number. */ #define NGTCP2_MAX_PKT_NUM ((int64_t)((1ll << 62) - 1)) -/* NGTCP2_MIN_PKT_EXPANDLEN is the minimum packet size expansion in - addition to the minimum DCID length to hide/trigger Stateless - Reset. */ +/* NGTCP2_MIN_PKT_EXPANDLEN is the minimum packet size expansion to + hide/trigger Stateless Reset. */ #define NGTCP2_MIN_PKT_EXPANDLEN 22 /* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */ #define NGTCP2_RETRY_TAGLEN 16 -/* NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE is the maximum UDP payload size - that this library can write. */ +/* NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE is the maximum UDP datagram + payload size that this library can write. */ #define NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE ((1 << 24) - 1) /* NGTCP2_PKT_LENGTHLEN is the number of bytes that is occupied by @@ -357,6 +353,11 @@ typedef union ngtcp2_frame { ngtcp2_retire_connection_id retire_connection_id; ngtcp2_handshake_done handshake_done; ngtcp2_datagram datagram; + /* Extend ngtcp2_frame so that ngtcp2_stream has at least additional + 3 ngtcp2_vec, totaling 4 slots, which can store HEADERS header, + HEADERS payload, DATA header, and DATA payload in the standard + sized ngtcp2_frame_chain. */ + uint8_t pad[sizeof(ngtcp2_stream) + sizeof(ngtcp2_vec) * 3]; } ngtcp2_frame; typedef struct ngtcp2_pkt_chain ngtcp2_pkt_chain; @@ -371,7 +372,7 @@ struct ngtcp2_pkt_chain { uint8_t *pkt; /* pktlen is length of a QUIC packet. */ size_t pktlen; - /* dgramlen is length of UDP datagram that a QUIC packet is + /* dgramlen is length of UDP datagram payload that a QUIC packet is included. */ size_t dgramlen; ngtcp2_tstamp ts; @@ -403,11 +404,11 @@ void ngtcp2_pkt_chain_del(ngtcp2_pkt_chain *pc, const ngtcp2_mem *mem); /* * ngtcp2_pkt_hd_init initializes |hd| with the given values. If - * |dcid| and/or |scid| is NULL, DCID and SCID of |hd| is empty - * respectively. |pkt_numlen| is the number of bytes used to encode - * |pkt_num| and either 1, 2, or 4. |version| is QUIC version for - * long header. |len| is the length field of Initial, 0RTT, and - * Handshake packets. + * |dcid| and/or |scid| is NULL, Destination Connection ID and/or + * Source Connection ID of |hd| is empty respectively. |pkt_numlen| + * is the number of bytes used to encode |pkt_num| and either 1, 2, or + * 4. |version| is QUIC version for long header. |len| is the length + * field of Initial, 0RTT, and Handshake packets. */ void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, @@ -417,8 +418,8 @@ void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type, /* * ngtcp2_pkt_encode_hd_long encodes |hd| as QUIC long header into * |out| which has length |outlen|. It returns the number of bytes - * written into |outlen| if it succeeds, or one of the following - * negative error codes: + * written into |out| if it succeeds, or one of the following negative + * error codes: * * NGTCP2_ERR_NOBUF * Buffer is too short @@ -429,8 +430,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen, /* * ngtcp2_pkt_encode_hd_short encodes |hd| as QUIC short header into * |out| which has length |outlen|. It returns the number of bytes - * written into |outlen| if it succeeds, or one of the following - * negative error codes: + * written into |out| if it succeeds, or one of the following negative + * error codes: * * NGTCP2_ERR_NOBUF * Buffer is too short @@ -457,7 +458,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, /** * @function * - * `ngtcp2_pkt_encode_frame` encodes a frame |fm| into the buffer + * `ngtcp2_pkt_encode_frame` encodes a frame |fr| into the buffer * pointed by |out| of length |outlen|. * * This function returns the number of bytes written to the buffer, or @@ -543,7 +544,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest, /* * ngtcp2_pkt_decode_padding_frame decodes contiguous PADDING frames * from |payload| of length |payloadlen|. It continues to parse - * frames as long as the frame type is PADDING. This finishes when it + * frames as long as the frame type is PADDING. It finishes when it * encounters the frame type which is not PADDING, or all input data * is read. The first byte (payload[0]) must be NGTCP2_FRAME_PADDING. * This function returns the exact number of bytes read to decode @@ -573,7 +574,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest, * ngtcp2_pkt_decode_connection_close_frame decodes CONNECTION_CLOSE * frame from |payload| of length |payloadlen|. The result is stored * in the object pointed by |dest|. CONNECTION_CLOSE frame must start - * at payload[0]. This function finishes it decodes one + * at payload[0]. This function finishes when it decodes one * CONNECTION_CLOSE frame, and returns the exact number of bytes read * to decode a frame if it succeeds, or one of the following negative * error codes: @@ -582,7 +583,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest, * Payload is too short to include CONNECTION_CLOSE frame. */ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( - ngtcp2_connection_close *dest, const uint8_t *payload, size_t payloadlen); + ngtcp2_connection_close *dest, const uint8_t *payload, size_t payloadlen); /* * ngtcp2_pkt_decode_max_data_frame decodes MAX_DATA frame from @@ -612,7 +613,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data *dest, * Payload is too short to include MAX_STREAM_DATA frame. */ ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame( - ngtcp2_max_stream_data *dest, const uint8_t *payload, size_t payloadlen); + ngtcp2_max_stream_data *dest, const uint8_t *payload, size_t payloadlen); /* * ngtcp2_pkt_decode_max_streams_frame decodes MAX_STREAMS frame from @@ -668,10 +669,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked *dest, * NGTCP2_ERR_FRAME_ENCODING * Payload is too short to include STREAM_DATA_BLOCKED frame. */ -ngtcp2_ssize -ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest, - const uint8_t *payload, - size_t payloadlen); +ngtcp2_ssize ngtcp2_pkt_decode_stream_data_blocked_frame( + ngtcp2_stream_data_blocked *dest, const uint8_t *payload, size_t payloadlen); /* * ngtcp2_pkt_decode_streams_blocked_frame decodes STREAMS_BLOCKED @@ -686,7 +685,7 @@ ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest, * Payload is too short to include STREAMS_BLOCKED frame. */ ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame( - ngtcp2_streams_blocked *dest, const uint8_t *payload, size_t payloadlen); + ngtcp2_streams_blocked *dest, const uint8_t *payload, size_t payloadlen); /* * ngtcp2_pkt_decode_new_connection_id_frame decodes NEW_CONNECTION_ID @@ -699,11 +698,11 @@ ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame( * * NGTCP2_ERR_FRAME_ENCODING * Payload is too short to include NEW_CONNECTION_ID frame; or the - * length of CID is strictly less than NGTCP2_MIN_CIDLEN or - * greater than NGTCP2_MAX_CIDLEN. + * length of Connection ID is strictly less than NGTCP2_MIN_CIDLEN + * or greater than NGTCP2_MAX_CIDLEN. */ ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame( - ngtcp2_new_connection_id *dest, const uint8_t *payload, size_t payloadlen); + ngtcp2_new_connection_id *dest, const uint8_t *payload, size_t payloadlen); /* * ngtcp2_pkt_decode_stop_sending_frame decodes STOP_SENDING frame @@ -784,20 +783,19 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest, size_t payloadlen); /* - * ngtcp2_pkt_decode_retire_connection_id_frame decodes RETIRE_CONNECTION_ID - * frame from |payload| of length |payloadlen|. The result is stored in the - * object pointed by |dest|. RETIRE_CONNECTION_ID frame must start at - * payload[0]. This function finishes when it decodes one RETIRE_CONNECTION_ID - * frame, and returns the exact number of bytes read to decode a frame - * if it succeeds, or one of the following negative error codes: + * ngtcp2_pkt_decode_retire_connection_id_frame decodes + * RETIRE_CONNECTION_ID frame from |payload| of length |payloadlen|. + * The result is stored in the object pointed by |dest|. + * RETIRE_CONNECTION_ID frame must start at payload[0]. This function + * finishes when it decodes one RETIRE_CONNECTION_ID frame, and + * returns the exact number of bytes read to decode a frame if it + * succeeds, or one of the following negative error codes: * * NGTCP2_ERR_FRAME_ENCODING * Payload is too short to include RETIRE_CONNECTION_ID frame. */ -ngtcp2_ssize -ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id *dest, - const uint8_t *payload, - size_t payloadlen); +ngtcp2_ssize ngtcp2_pkt_decode_retire_connection_id_frame( + ngtcp2_retire_connection_id *dest, const uint8_t *payload, size_t payloadlen); /* * ngtcp2_pkt_decode_handshake_done_frame decodes HANDSHAKE_DONE frame @@ -846,9 +844,6 @@ ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen, * ngtcp2_pkt_encode_ack_frame encodes ACK frame |fr| into the buffer * pointed by |out| of length |outlen|. * - * This function assigns & - * ~NGTCP2_FRAME_ACK to fr->flags. - * * This function returns the number of bytes written if it succeeds, * or one of the following negative error codes: * @@ -856,7 +851,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen, * Buffer does not have enough capacity to write a frame. */ ngtcp2_ssize ngtcp2_pkt_encode_ack_frame(uint8_t *out, size_t outlen, - ngtcp2_ack *fr); + const ngtcp2_ack *fr); /* * ngtcp2_pkt_encode_padding_frame encodes PADDING frame |fr| into the @@ -980,7 +975,7 @@ ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen, * Buffer does not have enough capacity to write a frame. */ ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame( - uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr); + uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr); /* * ngtcp2_pkt_encode_streams_blocked_frame encodes STREAMS_BLOCKED @@ -1079,8 +1074,9 @@ ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen, const ngtcp2_new_token *fr); /* - * ngtcp2_pkt_encode_retire_connection_id_frame encodes RETIRE_CONNECTION_ID - * frame |fr| into the buffer pointed by |out| of length |outlen|. + * ngtcp2_pkt_encode_retire_connection_id_frame encodes + * RETIRE_CONNECTION_ID frame |fr| into the buffer pointed by |out| of + * length |outlen|. * * This function returns the number of bytes written if it succeeds, * or one of the following negative error codes: @@ -1089,7 +1085,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen, * Buffer does not have enough capacity to write a frame. */ ngtcp2_ssize ngtcp2_pkt_encode_retire_connection_id_frame( - uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr); + uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr); /* * ngtcp2_pkt_encode_handshake_done_frame encodes HANDSHAKE_DONE frame @@ -1119,7 +1115,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen, const ngtcp2_datagram *fr); /* - * ngtcp2_pkt_adjust_pkt_num find the full 64 bits packet number for + * ngtcp2_pkt_adjust_pkt_num finds the full 62 bits packet number for * |pkt_num|, which is encoded in |pkt_numlen| bytes. The * |max_pkt_num| is the highest successfully authenticated packet * number. @@ -1128,10 +1124,10 @@ int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num, size_t pkt_numlen); /* - * ngtcp2_pkt_validate_ack checks that ack is malformed or not. - * |min_pkt_num| is the minimum packet number that an endpoint sends. - * It is an error to receive acknowledgements for a packet less than - * |min_pkt_num|. + * ngtcp2_pkt_validate_ack verifies whether |fr| is malformed or not. + * |min_pkt_num| is the minimum packet number that a local endpoint + * sends. It is an error to receive acknowledgements for a packet + * less than |min_pkt_num|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -1141,13 +1137,13 @@ int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num, * NGTCP2_ERR_PROTO * |fr| contains a packet number less than |min_pkt_num|. */ -int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr, int64_t min_pkt_num); +int ngtcp2_pkt_validate_ack(const ngtcp2_ack *fr, int64_t min_pkt_num); /* * ngtcp2_pkt_stream_max_datalen returns the maximum number of bytes * which can be sent for stream denoted by |stream_id|. |offset| is - * an offset of within the stream. |len| is the estimated number of - * bytes to be sent. |left| is the size of buffer. If |left| is too + * an offset within the stream. |len| is the estimated number of + * bytes to send. |left| is the size of buffer. If |left| is too * small to write STREAM frame, this function returns (size_t)-1. */ size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset, @@ -1155,10 +1151,10 @@ size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset, /* * ngtcp2_pkt_crypto_max_datalen returns the maximum number of bytes - * which can be sent for crypto stream. |offset| is an offset of - * within the crypto stream. |len| is the estimated number of bytes - * to be sent. |left| is the size of buffer. If |left| is too small - * to write CRYPTO frame, this function returns (size_t)-1. + * which can be sent for crypto stream. |offset| is an offset within + * the crypto stream. |len| is the estimated number of bytes to send. + * |left| is the size of buffer. If |left| is too small to write + * CRYPTO frame, this function returns (size_t)-1. */ size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left); @@ -1191,8 +1187,8 @@ int ngtcp2_pkt_verify_reserved_bits(uint8_t c); * Buffer is too short. */ ngtcp2_ssize ngtcp2_pkt_encode_pseudo_retry( - uint8_t *dest, size_t destlen, const ngtcp2_pkt_hd *hd, uint8_t unused, - const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen); + uint8_t *dest, size_t destlen, const ngtcp2_pkt_hd *hd, uint8_t unused, + const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen); /* * ngtcp2_pkt_verify_retry_tag verifies Retry packet. The buffer @@ -1229,4 +1225,4 @@ uint8_t ngtcp2_pkt_versioned_type(uint32_t version, uint32_t pkt_type); */ uint8_t ngtcp2_pkt_get_type_long(uint32_t version, uint8_t c); -#endif /* NGTCP2_PKT_H */ +#endif /* !defined(NGTCP2_PKT_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pktns_id.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pktns_id.h index 66b0ee9e6c13cf..9cf8444d32d7eb 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pktns_id.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pktns_id.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -59,4 +59,4 @@ typedef enum ngtcp2_pktns_id { NGTCP2_PKTNS_ID_MAX } ngtcp2_pktns_id; -#endif /* NGTCP2_PKTNS_ID_H */ +#endif /* !defined(NGTCP2_PKTNS_ID_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c index 771ef5e026d12d..ebd113f6746217 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.c @@ -33,18 +33,17 @@ for each probe. */ #define NGTCP2_PMTUD_PROBE_NUM_MAX 3 -static size_t mtu_probes[] = { - 1454 - 48, /* The well known MTU used by a domestic optic fiber - service in Japan. */ - 1390 - 48, /* Typical Tunneled MTU */ - 1280 - 48, /* IPv6 minimum MTU */ - 1492 - 48, /* PPPoE */ +static uint16_t pmtud_default_probes[] = { + 1454 - 48, /* The well known MTU used by a domestic optic fiber + service in Japan. */ + 1390 - 48, /* Typical Tunneled MTU */ + 1280 - 48, /* IPv6 minimum MTU */ + 1492 - 48, /* PPPoE */ }; -#define NGTCP2_MTU_PROBESLEN ngtcp2_arraylen(mtu_probes) - int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, size_t hard_max_udp_payload_size, int64_t tx_pkt_num, + const uint16_t *probes, size_t probeslen, const ngtcp2_mem *mem) { ngtcp2_pmtud *pmtud = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pmtud)); @@ -61,11 +60,19 @@ int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, pmtud->hard_max_udp_payload_size = hard_max_udp_payload_size; pmtud->min_fail_udp_payload_size = SIZE_MAX; - for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) { - if (mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { + if (probeslen) { + pmtud->probes = probes; + pmtud->probeslen = probeslen; + } else { + pmtud->probes = pmtud_default_probes; + pmtud->probeslen = ngtcp2_arraylen(pmtud_default_probes); + } + + for (; pmtud->mtu_idx < pmtud->probeslen; ++pmtud->mtu_idx) { + if (pmtud->probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { continue; } - if (mtu_probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { + if (pmtud->probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { break; } } @@ -84,9 +91,9 @@ void ngtcp2_pmtud_del(ngtcp2_pmtud *pmtud) { } size_t ngtcp2_pmtud_probelen(ngtcp2_pmtud *pmtud) { - assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); + assert(pmtud->mtu_idx < pmtud->probeslen); - return mtu_probes[pmtud->mtu_idx]; + return pmtud->probes[pmtud->mtu_idx]; } void ngtcp2_pmtud_probe_sent(ngtcp2_pmtud *pmtud, ngtcp2_duration pto, @@ -107,19 +114,19 @@ int ngtcp2_pmtud_require_probe(ngtcp2_pmtud *pmtud) { } static void pmtud_next_probe(ngtcp2_pmtud *pmtud) { - assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); + assert(pmtud->mtu_idx < pmtud->probeslen); ++pmtud->mtu_idx; pmtud->num_pkts_sent = 0; pmtud->expiry = UINT64_MAX; - for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) { - if (mtu_probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size || - mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { + for (; pmtud->mtu_idx < pmtud->probeslen; ++pmtud->mtu_idx) { + if (pmtud->probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size || + pmtud->probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { continue; } - if (mtu_probes[pmtud->mtu_idx] < pmtud->min_fail_udp_payload_size) { + if (pmtud->probes[pmtud->mtu_idx] < pmtud->min_fail_udp_payload_size) { break; } } @@ -127,11 +134,11 @@ static void pmtud_next_probe(ngtcp2_pmtud *pmtud) { void ngtcp2_pmtud_probe_success(ngtcp2_pmtud *pmtud, size_t payloadlen) { pmtud->max_udp_payload_size = - ngtcp2_max(pmtud->max_udp_payload_size, payloadlen); + ngtcp2_max_size(pmtud->max_udp_payload_size, payloadlen); - assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); + assert(pmtud->mtu_idx < pmtud->probeslen); - if (mtu_probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { + if (pmtud->probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { return; } @@ -149,12 +156,12 @@ void ngtcp2_pmtud_handle_expiry(ngtcp2_pmtud *pmtud, ngtcp2_tstamp ts) { return; } - pmtud->min_fail_udp_payload_size = - ngtcp2_min(pmtud->min_fail_udp_payload_size, mtu_probes[pmtud->mtu_idx]); + pmtud->min_fail_udp_payload_size = ngtcp2_min_size( + pmtud->min_fail_udp_payload_size, pmtud->probes[pmtud->mtu_idx]); pmtud_next_probe(pmtud); } int ngtcp2_pmtud_finished(ngtcp2_pmtud *pmtud) { - return pmtud->mtu_idx >= NGTCP2_MTU_PROBESLEN; + return pmtud->mtu_idx >= pmtud->probeslen; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.h index 6b2e691cfc793a..53fc6a538292e0 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pmtud.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -58,6 +58,10 @@ typedef struct ngtcp2_pmtud { /* min_fail_udp_payload_size is the minimum UDP payload size that is known to fail. */ size_t min_fail_udp_payload_size; + /* probes is the array of UDP datagram payload size to probe. */ + const uint16_t *probes; + /* probeslen is the number of probes pointed by probes. */ + size_t probeslen; } ngtcp2_pmtud; /* @@ -70,6 +74,10 @@ typedef struct ngtcp2_pmtud { * larger than or equal to all UDP payload probe candidates. * Therefore, call ngtcp2_pmtud_finished to check this situation. * + * The array pointed by |pmtud_probes| of length |pmtud_probeslen| + * specifies UDP datagram payload size to probe. If |pmtud_probeslen| + * is zero, the default probes are used. + * * This function returns 0 if it succeeds, or one of the following * negative error codes: * @@ -78,6 +86,7 @@ typedef struct ngtcp2_pmtud { */ int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, size_t hard_max_udp_payload_size, int64_t tx_pkt_num, + const uint16_t *pmtud_probes, size_t pmtud_probeslen, const ngtcp2_mem *mem); /* @@ -120,4 +129,4 @@ void ngtcp2_pmtud_handle_expiry(ngtcp2_pmtud *pmtud, ngtcp2_tstamp ts); */ int ngtcp2_pmtud_finished(ngtcp2_pmtud *pmtud); -#endif /* NGTCP2_PMTUD_H */ +#endif /* !defined(NGTCP2_PMTUD_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c index f7c122b1ab406b..13ef2b24908905 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.c @@ -29,11 +29,13 @@ #include "ngtcp2_str.h" #include "ngtcp2_conv.h" +#include "ngtcp2_macro.h" void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen, - ngtcp2_crypto_cc *cc) { + size_t dgram_offset, ngtcp2_crypto_cc *cc) { ngtcp2_buf_init(&ppe->buf, out, outlen); + ppe->dgram_offset = dgram_offset; ppe->hdlen = 0; ppe->len_offset = 0; ppe->pkt_num_offset = 0; @@ -53,17 +55,22 @@ int ngtcp2_ppe_encode_hd(ngtcp2_ppe *ppe, const ngtcp2_pkt_hd *hd) { if (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM) { ppe->len_offset = 1 + 4 + 1 + hd->dcid.datalen + 1 + hd->scid.datalen; + if (hd->type == NGTCP2_PKT_INITIAL) { ppe->len_offset += ngtcp2_put_uvarintlen(hd->tokenlen) + hd->tokenlen; } + ppe->pkt_num_offset = ppe->len_offset + NGTCP2_PKT_LENGTHLEN; + rv = ngtcp2_pkt_encode_hd_long( - buf->last, ngtcp2_buf_left(buf) - cc->aead.max_overhead, hd); + buf->last, ngtcp2_buf_left(buf) - cc->aead.max_overhead, hd); } else { ppe->pkt_num_offset = 1 + hd->dcid.datalen; + rv = ngtcp2_pkt_encode_hd_short( - buf->last, ngtcp2_buf_left(buf) - cc->aead.max_overhead, hd); + buf->last, ngtcp2_buf_left(buf) - cc->aead.max_overhead, hd); } + if (rv < 0) { return (int)rv; } @@ -72,7 +79,6 @@ int ngtcp2_ppe_encode_hd(ngtcp2_ppe *ppe, const ngtcp2_pkt_hd *hd) { ppe->pkt_numlen = hd->pkt_numlen; ppe->hdlen = (size_t)rv; - ppe->pkt_num = hd->pkt_num; return 0; @@ -88,7 +94,7 @@ int ngtcp2_ppe_encode_frame(ngtcp2_ppe *ppe, ngtcp2_frame *fr) { } rv = ngtcp2_pkt_encode_frame( - buf->last, ngtcp2_buf_left(buf) - cc->aead.max_overhead, fr); + buf->last, ngtcp2_buf_left(buf) - cc->aead.max_overhead, fr); if (rv < 0) { return (int)rv; } @@ -121,8 +127,8 @@ ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) { if (ppe->len_offset) { ngtcp2_put_uvarint30( - buf->begin + ppe->len_offset, - (uint16_t)(payloadlen + ppe->pkt_numlen + cc->aead.max_overhead)); + buf->begin + ppe->len_offset, + (uint16_t)(payloadlen + ppe->pkt_numlen + cc->aead.max_overhead)); } ngtcp2_crypto_create_nonce(ppe->nonce, cc->ckm->iv.base, cc->ckm->iv.len, @@ -136,7 +142,7 @@ ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) { buf->last = payload + payloadlen + cc->aead.max_overhead; - /* TODO Check that we have enough space to get sample */ + /* Make sure that we have enough space to get sample */ assert(ppe_sample_offset(ppe) + NGTCP2_HP_SAMPLELEN <= ngtcp2_buf_len(buf)); rv = cc->hp_mask(mask, &cc->hp, &cc->hp_ctx, @@ -164,7 +170,7 @@ ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) { return (ngtcp2_ssize)ngtcp2_buf_len(buf); } -size_t ngtcp2_ppe_left(ngtcp2_ppe *ppe) { +size_t ngtcp2_ppe_left(const ngtcp2_ppe *ppe) { ngtcp2_crypto_cc *cc = ppe->cc; if (ngtcp2_buf_left(&ppe->buf) < cc->aead.max_overhead) { @@ -174,57 +180,57 @@ size_t ngtcp2_ppe_left(ngtcp2_ppe *ppe) { return ngtcp2_buf_left(&ppe->buf) - cc->aead.max_overhead; } -size_t ngtcp2_ppe_pktlen(ngtcp2_ppe *ppe) { +size_t ngtcp2_ppe_pktlen(const ngtcp2_ppe *ppe) { ngtcp2_crypto_cc *cc = ppe->cc; return ngtcp2_buf_len(&ppe->buf) + cc->aead.max_overhead; } -size_t ngtcp2_ppe_padding(ngtcp2_ppe *ppe) { - ngtcp2_crypto_cc *cc = ppe->cc; - ngtcp2_buf *buf = &ppe->buf; - size_t len; - - assert(ngtcp2_buf_left(buf) >= cc->aead.max_overhead); - - len = ngtcp2_buf_left(buf) - cc->aead.max_overhead; - memset(buf->last, 0, len); - buf->last += len; - - return len; -} - -size_t ngtcp2_ppe_padding_hp_sample(ngtcp2_ppe *ppe) { +size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n) { ngtcp2_crypto_cc *cc = ppe->cc; ngtcp2_buf *buf = &ppe->buf; - size_t max_samplelen; + size_t pktlen = ngtcp2_buf_len(buf) + cc->aead.max_overhead; size_t len = 0; + size_t max_samplelen; - assert(cc->aead.max_overhead); + n = ngtcp2_min_size(n, ngtcp2_buf_cap(buf)); + if (pktlen < n) { + len = n - pktlen; + } + /* Ensure header protection sample */ max_samplelen = - ngtcp2_buf_len(buf) + cc->aead.max_overhead - ppe_sample_offset(ppe); + ngtcp2_buf_len(buf) + cc->aead.max_overhead - ppe_sample_offset(ppe); + if (max_samplelen < NGTCP2_HP_SAMPLELEN) { - len = NGTCP2_HP_SAMPLELEN - max_samplelen; - assert(ngtcp2_ppe_left(ppe) >= len); - memset(buf->last, 0, len); - buf->last += len; + len = ngtcp2_max_size(len, NGTCP2_HP_SAMPLELEN - max_samplelen); } + assert(ngtcp2_buf_left(buf) >= len + cc->aead.max_overhead); + + buf->last = ngtcp2_setmem(buf->last, 0, len); + return len; } -size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n) { +size_t ngtcp2_ppe_dgram_padding(ngtcp2_ppe *ppe) { + return ngtcp2_ppe_dgram_padding_size(ppe, NGTCP2_MAX_UDP_PAYLOAD_SIZE); +} + +size_t ngtcp2_ppe_dgram_padding_size(ngtcp2_ppe *ppe, size_t n) { ngtcp2_crypto_cc *cc = ppe->cc; ngtcp2_buf *buf = &ppe->buf; - size_t pktlen = ngtcp2_buf_len(buf) + cc->aead.max_overhead; + size_t dgramlen = + ppe->dgram_offset + ngtcp2_buf_len(buf) + cc->aead.max_overhead; size_t len; - if (pktlen >= n) { + n = ngtcp2_min_size(n, ppe->dgram_offset + ngtcp2_buf_cap(buf)); + + if (dgramlen >= n) { return 0; } - len = n - pktlen; + len = n - dgramlen; buf->last = ngtcp2_setmem(buf->last, 0, len); return len; @@ -232,5 +238,6 @@ size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n) { int ngtcp2_ppe_ensure_hp_sample(ngtcp2_ppe *ppe) { ngtcp2_buf *buf = &ppe->buf; + return ngtcp2_buf_left(buf) >= (4 - ppe->pkt_numlen) + NGTCP2_HP_SAMPLELEN; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h index 2a069ef33451ab..660b1482b56671 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ppe.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -36,11 +36,17 @@ #include "ngtcp2_crypto.h" /* - * ngtcp2_ppe is the Protected Packet Encoder. + * ngtcp2_ppe is the QUIC Packet Encoder. */ typedef struct ngtcp2_ppe { + /* buf is the buffer where a QUIC packet is written. */ ngtcp2_buf buf; + /* cc is the encryption context that includes callback functions to + encrypt a QUIC packet, and AEAD cipher, etc. */ ngtcp2_crypto_cc *cc; + /* dgram_offset is the offset in UDP datagram payload that this QUIC + packet is positioned at. */ + size_t dgram_offset; /* hdlen is the number of bytes for packet header written in buf. */ size_t hdlen; /* len_offset is the offset to Length field. */ @@ -53,7 +59,7 @@ typedef struct ngtcp2_ppe { /* pkt_num is the packet number written in buf. */ int64_t pkt_num; /* nonce is the buffer to store nonce. It should be equal or longer - than then length of IV. */ + than the length of IV. */ uint8_t nonce[32]; } ngtcp2_ppe; @@ -61,7 +67,7 @@ typedef struct ngtcp2_ppe { * ngtcp2_ppe_init initializes |ppe| with the given buffer. */ void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen, - ngtcp2_crypto_cc *cc); + size_t dgram_offset, ngtcp2_crypto_cc *cc); /* * ngtcp2_ppe_encode_hd encodes |hd|. @@ -86,7 +92,7 @@ int ngtcp2_ppe_encode_hd(ngtcp2_ppe *ppe, const ngtcp2_pkt_hd *hd); int ngtcp2_ppe_encode_frame(ngtcp2_ppe *ppe, ngtcp2_frame *fr); /* - * ngtcp2_ppe_final encrypts QUIC packet payload. If |**ppkt| is not + * ngtcp2_ppe_final encrypts QUIC packet payload. If |ppkt| is not * NULL, the pointer to the packet is assigned to it. * * This function returns the length of QUIC packet, including header, @@ -102,39 +108,46 @@ ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt); * ngtcp2_ppe_left returns the number of bytes left to write * additional frames. This does not count AEAD overhead. */ -size_t ngtcp2_ppe_left(ngtcp2_ppe *ppe); +size_t ngtcp2_ppe_left(const ngtcp2_ppe *ppe); /* * ngtcp2_ppe_pktlen returns the provisional packet length. It * includes AEAD overhead. */ -size_t ngtcp2_ppe_pktlen(ngtcp2_ppe *ppe); +size_t ngtcp2_ppe_pktlen(const ngtcp2_ppe *ppe); -/** - * @function +/* + * ngtcp2_ppe_dgram_padding is equivalent to call + * ngtcp2_ppe_dgram_padding_size(ppe, NGTCP2_MAX_UDP_PAYLOAD_SIZE). + * This function should be called just before calling + * ngtcp2_ppe_final(). * - * `ngtcp2_ppe_padding` encodes PADDING frames to the end of the - * buffer. This function returns the number of bytes padded. + * This function returns the number of bytes padded. */ -size_t ngtcp2_ppe_padding(ngtcp2_ppe *ppe); +size_t ngtcp2_ppe_dgram_padding(ngtcp2_ppe *ppe); /* - * ngtcp2_ppe_padding_hp_sample adds PADDING frame if the current - * payload does not have enough space for header protection sample. - * This function should be called just before calling - * ngtcp2_ppe_final(). + * ngtcp2_ppe_dgram_padding_size adds PADDING frame so that the size + * of a UDP datagram payload is at least |n| bytes long. If it is + * unable to add PADDING in that way, this function still adds PADDING + * frame as much as possible. This function should be called just + * before calling ngtcp2_ppe_final(). * * This function returns the number of bytes added as padding. */ -size_t ngtcp2_ppe_padding_hp_sample(ngtcp2_ppe *ppe); +size_t ngtcp2_ppe_dgram_padding_size(ngtcp2_ppe *ppe, size_t n); /* * ngtcp2_ppe_padding_size adds PADDING frame so that the size of QUIC - * packet is at least |n| bytes long. If it is unable to add PADDING - * in that way, this function still adds PADDING frame as much as - * possible. This function should be called just before calling - * ngtcp2_ppe_final(). For Short packet, this function should be - * called instead of ngtcp2_ppe_padding_hp_sample. + * packet is at least |n| bytes long and the current payload has + * enough space for header protection sample. If it is unable to add + * PADDING at least |n| bytes, this function still adds PADDING frames + * as much as possible. This function also adds PADDING frames so + * that the minimum padding requirement of header protection is met. + * Those padding may be larger than |n| bytes. It is recommended to + * make sure that ngtcp2_ppe_ensure_hp_sample succeeds after writing + * QUIC packet header. This function should be called just before + * calling ngtcp2_ppe_final(). * * This function returns the number of bytes added as padding. */ @@ -147,4 +160,4 @@ size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n); */ int ngtcp2_ppe_ensure_hp_sample(ngtcp2_ppe *ppe); -#endif /* NGTCP2_PPE_H */ +#endif /* !defined(NGTCP2_PPE_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c index 5e1003d7942e53..19e3e3e36aa5e6 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.c @@ -29,17 +29,20 @@ #include "ngtcp2_macro.h" -void ngtcp2_pq_init(ngtcp2_pq *pq, ngtcp2_less less, const ngtcp2_mem *mem) { - pq->mem = mem; - pq->capacity = 0; +void ngtcp2_pq_init(ngtcp2_pq *pq, ngtcp2_pq_less less, const ngtcp2_mem *mem) { pq->q = NULL; + pq->mem = mem; pq->length = 0; + pq->capacity = 0; pq->less = less; } void ngtcp2_pq_free(ngtcp2_pq *pq) { + if (!pq) { + return; + } + ngtcp2_mem_free(pq->mem, pq->q); - pq->q = NULL; } static void swap(ngtcp2_pq *pq, size_t i, size_t j) { @@ -54,11 +57,13 @@ static void swap(ngtcp2_pq *pq, size_t i, size_t j) { static void bubble_up(ngtcp2_pq *pq, size_t index) { size_t parent; - while (index != 0) { + + while (index) { parent = (index - 1) / 2; if (!pq->less(pq->q[index], pq->q[parent])) { return; } + swap(pq, parent, index); index = parent; } @@ -69,56 +74,64 @@ int ngtcp2_pq_push(ngtcp2_pq *pq, ngtcp2_pq_entry *item) { void *nq; size_t ncapacity; - ncapacity = ngtcp2_max(4, (pq->capacity * 2)); + ncapacity = ngtcp2_max_size(4, pq->capacity * 2); - nq = ngtcp2_mem_realloc(pq->mem, pq->q, - ncapacity * sizeof(ngtcp2_pq_entry *)); + nq = + ngtcp2_mem_realloc(pq->mem, pq->q, ncapacity * sizeof(ngtcp2_pq_entry *)); if (nq == NULL) { return NGTCP2_ERR_NOMEM; } + pq->capacity = ncapacity; pq->q = nq; } + pq->q[pq->length] = item; item->index = pq->length; ++pq->length; - bubble_up(pq, pq->length - 1); + bubble_up(pq, item->index); + return 0; } -ngtcp2_pq_entry *ngtcp2_pq_top(ngtcp2_pq *pq) { +ngtcp2_pq_entry *ngtcp2_pq_top(const ngtcp2_pq *pq) { assert(pq->length); return pq->q[0]; } static void bubble_down(ngtcp2_pq *pq, size_t index) { size_t i, j, minindex; + for (;;) { j = index * 2 + 1; minindex = index; + for (i = 0; i < 2; ++i, ++j) { if (j >= pq->length) { break; } + if (pq->less(pq->q[j], pq->q[minindex])) { minindex = j; } } + if (minindex == index) { return; } + swap(pq, index, minindex); index = minindex; } } void ngtcp2_pq_pop(ngtcp2_pq *pq) { - if (pq->length > 0) { - pq->q[0] = pq->q[pq->length - 1]; - pq->q[0]->index = 0; - --pq->length; - bubble_down(pq, 0); - } + assert(pq->length); + + pq->q[0] = pq->q[pq->length - 1]; + pq->q[0]->index = 0; + --pq->length; + bubble_down(pq, 0); } void ngtcp2_pq_remove(ngtcp2_pq *pq, ngtcp2_pq_entry *item) { @@ -145,20 +158,22 @@ void ngtcp2_pq_remove(ngtcp2_pq *pq, ngtcp2_pq_entry *item) { } } -int ngtcp2_pq_empty(ngtcp2_pq *pq) { return pq->length == 0; } +int ngtcp2_pq_empty(const ngtcp2_pq *pq) { return pq->length == 0; } -size_t ngtcp2_pq_size(ngtcp2_pq *pq) { return pq->length; } +size_t ngtcp2_pq_size(const ngtcp2_pq *pq) { return pq->length; } -int ngtcp2_pq_each(ngtcp2_pq *pq, ngtcp2_pq_item_cb fun, void *arg) { +int ngtcp2_pq_each(const ngtcp2_pq *pq, ngtcp2_pq_item_cb fun, void *arg) { size_t i; if (pq->length == 0) { return 0; } + for (i = 0; i < pq->length; ++i) { if ((*fun)(pq->q[i], arg)) { return 1; } } + return 0; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h index 484c8f21f75de2..84961c9143978c 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pq.h @@ -28,7 +28,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -45,37 +45,39 @@ typedef struct ngtcp2_pq_entry { size_t index; } ngtcp2_pq_entry; -/* "less" function, return nonzero if |lhs| is less than |rhs|. */ -typedef int (*ngtcp2_less)(const ngtcp2_pq_entry *lhs, - const ngtcp2_pq_entry *rhs); +/* ngtcp2_pq_less is a "less" function, that returns nonzero if |lhs| + is considered to be less than |rhs|. */ +typedef int (*ngtcp2_pq_less)(const ngtcp2_pq_entry *lhs, + const ngtcp2_pq_entry *rhs); typedef struct ngtcp2_pq { - /* The pointer to the pointer to the item stored */ + /* q is a pointer to an array that stores the items. */ ngtcp2_pq_entry **q; - /* Memory allocator */ + /* mem is a memory allocator. */ const ngtcp2_mem *mem; - /* The number of items stored */ + /* length is the number of items stored. */ size_t length; - /* The maximum number of items this pq can store. This is - automatically extended when length is reached to this value. */ + /* capacity is the maximum number of items this queue can store. + This is automatically extended when length is reached to this + limit. */ size_t capacity; - /* The less function between items */ - ngtcp2_less less; + /* less is the less function to compare items. */ + ngtcp2_pq_less less; } ngtcp2_pq; /* - * Initializes priority queue |pq| with compare function |cmp|. + * ngtcp2_pq_init initializes |pq| with compare function |cmp|. */ -void ngtcp2_pq_init(ngtcp2_pq *pq, ngtcp2_less less, const ngtcp2_mem *mem); +void ngtcp2_pq_init(ngtcp2_pq *pq, ngtcp2_pq_less less, const ngtcp2_mem *mem); /* - * Deallocates any resources allocated for |pq|. The stored items are - * not freed by this function. + * ngtcp2_pq_free deallocates any resources allocated for |pq|. The + * stored items are not freed by this function. */ void ngtcp2_pq_free(ngtcp2_pq *pq); /* - * Adds |item| to the priority queue |pq|. + * ngtcp2_pq_push adds |item| to |pq|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -86,41 +88,42 @@ void ngtcp2_pq_free(ngtcp2_pq *pq); int ngtcp2_pq_push(ngtcp2_pq *pq, ngtcp2_pq_entry *item); /* - * Returns item at the top of the queue |pq|. It is undefined if the - * queue is empty. + * ngtcp2_pq_top returns item at the top of |pq|. It is undefined if + * |pq| is empty. */ -ngtcp2_pq_entry *ngtcp2_pq_top(ngtcp2_pq *pq); +ngtcp2_pq_entry *ngtcp2_pq_top(const ngtcp2_pq *pq); /* - * Pops item at the top of the queue |pq|. The popped item is not - * freed by this function. + * ngtcp2_pq_pop pops item at the top of |pq|. The popped item is not + * freed by this function. It is undefined if |pq| is empty. */ void ngtcp2_pq_pop(ngtcp2_pq *pq); /* - * Returns nonzero if the queue |pq| is empty. + * ngtcp2_pq_empty returns nonzero if |pq| is empty. */ -int ngtcp2_pq_empty(ngtcp2_pq *pq); +int ngtcp2_pq_empty(const ngtcp2_pq *pq); /* - * Returns the number of items in the queue |pq|. + * ngtcp2_pq_size returns the number of items |pq| contains. */ -size_t ngtcp2_pq_size(ngtcp2_pq *pq); +size_t ngtcp2_pq_size(const ngtcp2_pq *pq); typedef int (*ngtcp2_pq_item_cb)(ngtcp2_pq_entry *item, void *arg); /* - * Applies |fun| to each item in |pq|. The |arg| is passed as arg - * parameter to callback function. This function must not change the - * ordering key. If the return value from callback is nonzero, this - * function returns 1 immediately without iterating remaining items. - * Otherwise this function returns 0. + * ngtcp2_pq_each applies |fun| to each item in |pq|. The |arg| is + * passed as arg parameter to callback function. This function must + * not change the ordering key. If the return value from callback is + * nonzero, this function returns 1 immediately without iterating + * remaining items. Otherwise this function returns 0. */ -int ngtcp2_pq_each(ngtcp2_pq *pq, ngtcp2_pq_item_cb fun, void *arg); +int ngtcp2_pq_each(const ngtcp2_pq *pq, ngtcp2_pq_item_cb fun, void *arg); /* - * Removes |item| from priority queue. + * ngtcp2_pq_remove removes |item| from |pq|. |pq| must contain + * |item| otherwise the behavior is undefined. */ void ngtcp2_pq_remove(ngtcp2_pq *pq, ngtcp2_pq_entry *item); -#endif /* NGTCP2_PQ_H */ +#endif /* !defined(NGTCP2_PQ_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c index 314e005293c279..e4fee94eb558d3 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.c @@ -143,7 +143,7 @@ int ngtcp2_pv_validation_timed_out(ngtcp2_pv *pv, ngtcp2_tstamp ts) { ent = ngtcp2_ringbuf_get(&pv->ents.rb, ngtcp2_ringbuf_len(&pv->ents.rb) - 1); t = pv->started_ts + pv->timeout; - t = ngtcp2_max(t, ent->expiry); + t = ngtcp2_max_uint64(t, ent->expiry); return t <= ts; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h index c9da15248a3e2b..e9573da497bee4 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pv.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -83,7 +83,7 @@ void ngtcp2_pv_entry_init(ngtcp2_pv_entry *pvent, const uint8_t *data, typedef struct ngtcp2_pv ngtcp2_pv; ngtcp2_static_ringbuf_def(pv_ents, NGTCP2_PV_MAX_ENTRIES, - sizeof(ngtcp2_pv_entry)); + sizeof(ngtcp2_pv_entry)) /* * ngtcp2_pv is the context of a single path validation. */ @@ -191,4 +191,4 @@ ngtcp2_tstamp ngtcp2_pv_next_expiry(ngtcp2_pv *pv); */ void ngtcp2_pv_cancel_expired_timer(ngtcp2_pv *pv, ngtcp2_tstamp ts); -#endif /* NGTCP2_PV_H */ +#endif /* !defined(NGTCP2_PV_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c index 27675347794b2a..c0f920746a4dff 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c @@ -184,13 +184,12 @@ static uint8_t *write_pair_cid_impl(uint8_t *p, const uint8_t *name, write_pair_cid_impl((DEST), (const uint8_t *)(NAME), sizeof(NAME) - 1, \ (VALUE)) -#define ngtcp2_make_vec_lit(S) \ - { (uint8_t *)(S), sizeof((S)) - 1 } +#define ngtcp2_make_vec_lit(S) {(uint8_t *)(S), sizeof((S)) - 1} static uint8_t *write_common_fields(uint8_t *p, const ngtcp2_cid *odcid) { p = write_verbatim( - p, "\"common_fields\":{\"protocol_type\":[\"QUIC\"],\"time_format\":" - "\"relative\",\"reference_time\":0,\"group_id\":"); + p, "\"common_fields\":{\"protocol_type\":[\"QUIC\"],\"time_format\":" + "\"relative\",\"reference_time\":0,\"group_id\":"); p = write_cid(p, odcid); *p++ = '}'; return p; @@ -198,7 +197,7 @@ static uint8_t *write_common_fields(uint8_t *p, const ngtcp2_cid *odcid) { static uint8_t *write_trace(uint8_t *p, int server, const ngtcp2_cid *odcid) { p = write_verbatim( - p, "\"trace\":{\"vantage_point\":{\"name\":\"ngtcp2\",\"type\":"); + p, "\"trace\":{\"vantage_point\":{\"name\":\"ngtcp2\",\"type\":"); if (server) { p = write_string(p, "server"); } else { @@ -219,7 +218,7 @@ void ngtcp2_qlog_start(ngtcp2_qlog *qlog, const ngtcp2_cid *odcid, int server) { } p = write_verbatim( - p, "\x1e{\"qlog_format\":\"JSON-SEQ\",\"qlog_version\":\"0.3\","); + p, "\x1e{\"qlog_format\":\"JSON-SEQ\",\"qlog_version\":\"0.3\","); p = write_trace(p, server, odcid); p = write_verbatim(p, "}\n"); @@ -243,9 +242,9 @@ static ngtcp2_vec vec_pkt_type_0rtt = ngtcp2_make_vec_lit("0RTT"); static ngtcp2_vec vec_pkt_type_1rtt = ngtcp2_make_vec_lit("1RTT"); static ngtcp2_vec vec_pkt_type_retry = ngtcp2_make_vec_lit("retry"); static ngtcp2_vec vec_pkt_type_version_negotiation = - ngtcp2_make_vec_lit("version_negotiation"); + ngtcp2_make_vec_lit("version_negotiation"); static ngtcp2_vec vec_pkt_type_stateless_reset = - ngtcp2_make_vec_lit("stateless_reset"); + ngtcp2_make_vec_lit("stateless_reset"); static ngtcp2_vec vec_pkt_type_unknown = ngtcp2_make_vec_lit("unknown"); static const ngtcp2_vec *qlog_pkt_type(const ngtcp2_pkt_hd *hd) { @@ -638,8 +637,8 @@ write_connection_close_frame(uint8_t *p, const ngtcp2_connection_close *fr) { */ #define NGTCP2_QLOG_CONNECTION_CLOSE_FRAME_OVERHEAD 131 - p = write_verbatim(p, - "{\"frame_type\":\"connection_close\",\"error_space\":"); + p = + write_verbatim(p, "{\"frame_type\":\"connection_close\",\"error_space\":"); if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) { p = write_string(p, "transport"); } else { @@ -772,10 +771,10 @@ void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) { case NGTCP2_FRAME_ACK_ECN: if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_ACK_FRAME_BASE_OVERHEAD + - (size_t)(fr->type == NGTCP2_FRAME_ACK_ECN - ? NGTCP2_QLOG_ACK_FRAME_ECN_OVERHEAD - : 0) + - NGTCP2_QLOG_ACK_FRAME_RANGE_OVERHEAD * (1 + fr->ack.rangecnt) + 1) { + (size_t)(fr->type == NGTCP2_FRAME_ACK_ECN + ? NGTCP2_QLOG_ACK_FRAME_ECN_OVERHEAD + : 0) + + NGTCP2_QLOG_ACK_FRAME_RANGE_OVERHEAD * (1 + fr->ack.rangecnt) + 1) { return; } p = write_ack_frame(p, &fr->ack); @@ -934,8 +933,8 @@ void ngtcp2_qlog_pkt_sent_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, } void ngtcp2_qlog_parameters_set_transport_params( - ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server, - ngtcp2_qlog_side side) { + ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server, + ngtcp2_qlog_side side) { uint8_t buf[1024]; uint8_t *p = buf; const ngtcp2_preferred_addr *paddr; @@ -950,7 +949,7 @@ void ngtcp2_qlog_parameters_set_transport_params( *p++ = '{'; p = qlog_write_time(qlog, p); p = write_verbatim( - p, ",\"name\":\"transport:parameters_set\",\"data\":{\"owner\":"); + p, ",\"name\":\"transport:parameters_set\",\"data\":{\"owner\":"); if (side == NGTCP2_QLOG_SIDE_LOCAL) { p = write_string(p, "local"); @@ -982,8 +981,8 @@ void ngtcp2_qlog_parameters_set_transport_params( *p++ = ','; p = write_pair_duration(p, "max_idle_timeout", params->max_idle_timeout); *p++ = ','; - p = write_pair_number(p, "max_udp_payload_size", - params->max_udp_payload_size); + p = + write_pair_number(p, "max_udp_payload_size", params->max_udp_payload_size); *p++ = ','; p = write_pair_number(p, "ack_delay_exponent", params->ack_delay_exponent); *p++ = ','; @@ -1106,7 +1105,7 @@ void ngtcp2_qlog_pkt_lost(ngtcp2_qlog *qlog, ngtcp2_rtb_entry *ent) { *p++ = '{'; p = qlog_write_time(qlog, p); p = write_verbatim( - p, ",\"name\":\"recovery:packet_lost\",\"data\":{\"header\":"); + p, ",\"name\":\"recovery:packet_lost\",\"data\":{\"header\":"); hd.type = ent->hd.type; hd.flags = ent->hd.flags; @@ -1134,13 +1133,11 @@ void ngtcp2_qlog_retry_pkt_received(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, *buf.last++ = '{'; buf.last = qlog_write_time(qlog, buf.last); buf.last = write_verbatim( - buf.last, - ",\"name\":\"transport:packet_received\",\"data\":{\"header\":"); + buf.last, ",\"name\":\"transport:packet_received\",\"data\":{\"header\":"); - if (ngtcp2_buf_left(&buf) < - NGTCP2_QLOG_PKT_HD_OVERHEAD + hd->tokenlen * 2 + - sizeof(",\"retry_token\":{\"data\":\"\"}}}\n") - 1 + - retry->tokenlen * 2) { + if (ngtcp2_buf_left(&buf) < NGTCP2_QLOG_PKT_HD_OVERHEAD + hd->tokenlen * 2 + + sizeof(",\"retry_token\":{\"data\":\"\"}}}\n") - + 1 + retry->tokenlen * 2) { return; } @@ -1154,7 +1151,7 @@ void ngtcp2_qlog_retry_pkt_received(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, } void ngtcp2_qlog_stateless_reset_pkt_received( - ngtcp2_qlog *qlog, const ngtcp2_pkt_stateless_reset *sr) { + ngtcp2_qlog *qlog, const ngtcp2_pkt_stateless_reset *sr) { uint8_t buf[256]; uint8_t *p = buf; ngtcp2_pkt_hd hd = {0}; @@ -1169,7 +1166,7 @@ void ngtcp2_qlog_stateless_reset_pkt_received( *p++ = '{'; p = qlog_write_time(qlog, p); p = write_verbatim( - p, ",\"name\":\"transport:packet_received\",\"data\":{\"header\":"); + p, ",\"name\":\"transport:packet_received\",\"data\":{\"header\":"); p = write_pkt_hd(p, &hd); *p++ = ','; p = write_pair_hex(p, "stateless_reset_token", sr->stateless_reset_token, @@ -1199,8 +1196,7 @@ void ngtcp2_qlog_version_negotiation_pkt_received(ngtcp2_qlog *qlog, *buf.last++ = '{'; buf.last = qlog_write_time(qlog, buf.last); buf.last = write_verbatim( - buf.last, - ",\"name\":\"transport:packet_received\",\"data\":{\"header\":"); + buf.last, ",\"name\":\"transport:packet_received\",\"data\":{\"header\":"); buf.last = write_pkt_hd(buf.last, hd); buf.last = write_verbatim(buf.last, ",\"supported_versions\":["); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.h index b9107c0e5c031a..d2a5f1038c0f42 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -120,8 +120,8 @@ void ngtcp2_qlog_pkt_sent_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, * "local", otherwise "remote". */ void ngtcp2_qlog_parameters_set_transport_params( - ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server, - ngtcp2_qlog_side side); + ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server, + ngtcp2_qlog_side side); /* * ngtcp2_qlog_metrics_updated writes metrics_updated event of @@ -147,7 +147,7 @@ void ngtcp2_qlog_retry_pkt_received(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, * event for a received Stateless Reset packet. */ void ngtcp2_qlog_stateless_reset_pkt_received( - ngtcp2_qlog *qlog, const ngtcp2_pkt_stateless_reset *sr); + ngtcp2_qlog *qlog, const ngtcp2_pkt_stateless_reset *sr); /* * ngtcp2_qlog_version_negotiation_pkt_received writes packet_received @@ -158,4 +158,4 @@ void ngtcp2_qlog_version_negotiation_pkt_received(ngtcp2_qlog *qlog, const uint32_t *sv, size_t nsv); -#endif /* NGTCP2_QLOG_H */ +#endif /* !defined(NGTCP2_QLOG_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c index 9379496b7d4b53..7bbefc0175c595 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c @@ -33,11 +33,13 @@ void ngtcp2_range_init(ngtcp2_range *r, uint64_t begin, uint64_t end) { ngtcp2_range ngtcp2_range_intersect(const ngtcp2_range *a, const ngtcp2_range *b) { ngtcp2_range r = {0, 0}; - uint64_t begin = ngtcp2_max(a->begin, b->begin); - uint64_t end = ngtcp2_min(a->end, b->end); + uint64_t begin = ngtcp2_max_uint64(a->begin, b->begin); + uint64_t end = ngtcp2_min_uint64(a->end, b->end); + if (begin < end) { ngtcp2_range_init(&r, begin, end); } + return r; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.h index a776c4ec4768ce..22cd2951859ef1 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -58,7 +58,7 @@ uint64_t ngtcp2_range_len(const ngtcp2_range *r); /* * ngtcp2_range_eq returns nonzero if |a| equals |b|, such that - * a->begin == b->begin, and a->end == b->end hold. + * a->begin == b->begin and a->end == b->end hold. */ int ngtcp2_range_eq(const ngtcp2_range *a, const ngtcp2_range *b); @@ -77,4 +77,4 @@ void ngtcp2_range_cut(ngtcp2_range *left, ngtcp2_range *right, */ int ngtcp2_range_not_after(const ngtcp2_range *a, const ngtcp2_range *b); -#endif /* NGTCP2_RANGE_H */ +#endif /* !defined(NGTCP2_RANGE_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rcvry.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rcvry.h index 4cb40882192a77..e6321061b59cd1 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rcvry.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rcvry.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -37,4 +37,4 @@ /* NGTCP2_GRANULARITY is kGranularity described in RFC 9002. */ #define NGTCP2_GRANULARITY NGTCP2_MILLISECONDS -#endif /* NGTCP2_RCVRY_H */ +#endif /* !defined(NGTCP2_RCVRY_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c index ecfdeb63b3485b..41446739bf699d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c @@ -27,24 +27,29 @@ #include #ifdef WIN32 # include -#endif +#endif /* defined(WIN32) */ #include "ngtcp2_macro.h" -#if defined(_MSC_VER) && _MSC_VER < 1941 && !defined(__clang__) && \ - (defined(_M_ARM) || defined(_M_ARM64)) -static unsigned int __popcnt(unsigned int x) { - unsigned int c = 0; - for (; x; ++c) { - x &= x - 1; - } - return c; +#ifndef NDEBUG +static int ispow2(size_t n) { +# if defined(_MSC_VER) && !defined(__clang__) && \ + (defined(_M_ARM) || (defined(_M_ARM64) && _MSC_VER < 1941)) + return n && !(n & (n - 1)); +# elif defined(WIN32) + return 1 == __popcnt((unsigned int)n); +# else /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \ + (defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */ + return 1 == __builtin_popcount((unsigned int)n); +# endif /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \ + (defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */ } -#endif +#endif /* !defined(NDEBUG) */ int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size, const ngtcp2_mem *mem) { uint8_t *buf = ngtcp2_mem_malloc(mem, nmemb * size); + if (buf == NULL) { return NGTCP2_ERR_NOMEM; } @@ -56,11 +61,7 @@ int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size, void ngtcp2_ringbuf_buf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size, uint8_t *buf, const ngtcp2_mem *mem) { -#ifdef WIN32 - assert(1 == __popcnt((unsigned int)nmemb)); -#else - assert(1 == __builtin_popcount((unsigned int)nmemb)); -#endif + assert(ispow2(nmemb)); rb->buf = buf; rb->mem = mem; @@ -114,9 +115,10 @@ void ngtcp2_ringbuf_resize(ngtcp2_ringbuf *rb, size_t len) { rb->len = len; } -void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset) { +void *ngtcp2_ringbuf_get(const ngtcp2_ringbuf *rb, size_t offset) { assert(offset < rb->len); offset = (rb->first + offset) & rb->mask; + return &rb->buf[offset * rb->size]; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h index b28a882c4bae84..6953ea6278f88d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -51,7 +51,7 @@ typedef struct ngtcp2_ringbuf { /* * ngtcp2_ringbuf_init initializes |rb|. |nmemb| is the number of * elements that can be stored in this buffer. |size| is the size of - * each element. |size| must be power of 2. + * each element. |nmemb| must be power of 2. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -64,7 +64,7 @@ int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size, /* * ngtcp2_ringbuf_buf_init initializes |rb| with given buffer and - * size. + * size. Same restrictions are applied as ngtcp2_ringbuf_init. */ void ngtcp2_ringbuf_buf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size, uint8_t *buf, const ngtcp2_mem *mem); @@ -79,15 +79,16 @@ void ngtcp2_ringbuf_free(ngtcp2_ringbuf *rb); the buffer backward, and returns the pointer to the element. Caller can store data to the buffer pointed by the returned pointer. If this action exceeds the capacity of the ring buffer, - the last element is silently overwritten, and rb->len remains - unchanged. */ + this function returns the pointer to the last element, and rb->len + remains unchanged. */ void *ngtcp2_ringbuf_push_front(ngtcp2_ringbuf *rb); /* ngtcp2_ringbuf_push_back moves the offset to the last element in the buffer forward, and returns the pointer to the element. Caller can store data to the buffer pointed by the returned pointer. If - this action exceeds the capacity of the ring buffer, the first - element is silently overwritten, and rb->len remains unchanged. */ + this action exceeds the capacity of the ring buffer, this function + returns the pointer to the first element, and rb->len remains + unchanged. */ void *ngtcp2_ringbuf_push_back(ngtcp2_ringbuf *rb); /* @@ -106,7 +107,7 @@ void ngtcp2_ringbuf_resize(ngtcp2_ringbuf *rb, size_t len); /* ngtcp2_ringbuf_get returns the pointer to the element at |offset|. */ -void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset); +void *ngtcp2_ringbuf_get(const ngtcp2_ringbuf *rb, size_t offset); /* ngtcp2_ringbuf_len returns the number of elements stored. */ #define ngtcp2_ringbuf_len(RB) ((RB)->len) @@ -115,9 +116,8 @@ void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset); int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb); /* ngtcp2_static_ringbuf_def defines ngtcp2_ringbuf struct wrapper - which uses a statically allocated buffer that is suitable for a - usage that does not change buffer size with ngtcp2_ringbuf_resize. - ngtcp2_ringbuf_free should never be called for rb field. */ + which uses a statically allocated buffer. ngtcp2_ringbuf_free + should never be called for rb field. */ #define ngtcp2_static_ringbuf_def(NAME, NMEMB, SIZE) \ typedef struct ngtcp2_static_ringbuf_##NAME { \ ngtcp2_ringbuf rb; \ @@ -125,8 +125,8 @@ int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb); } ngtcp2_static_ringbuf_##NAME; \ \ static inline void ngtcp2_static_ringbuf_##NAME##_init( \ - ngtcp2_static_ringbuf_##NAME *srb) { \ + ngtcp2_static_ringbuf_##NAME *srb) { \ ngtcp2_ringbuf_buf_init(&srb->rb, (NMEMB), (SIZE), srb->buf, NULL); \ } -#endif /* NGTCP2_RINGBUF_H */ +#endif /* !defined(NGTCP2_RINGBUF_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c index 5cac383f7bb166..ce6c2113ddf1ce 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c @@ -56,7 +56,6 @@ int ngtcp2_rob_data_new(ngtcp2_rob_data **pd, uint64_t offset, size_t chunk, (*pd)->range.begin = offset; (*pd)->range.end = offset + chunk; (*pd)->begin = (uint8_t *)(*pd) + sizeof(ngtcp2_rob_data); - (*pd)->end = (*pd)->begin + chunk; return 0; } @@ -69,8 +68,8 @@ int ngtcp2_rob_init(ngtcp2_rob *rob, size_t chunk, const ngtcp2_mem *mem) { int rv; ngtcp2_rob_gap *g; - ngtcp2_ksl_init(&rob->gapksl, ngtcp2_ksl_range_compar, sizeof(ngtcp2_range), - mem); + ngtcp2_ksl_init(&rob->gapksl, ngtcp2_ksl_range_compar, + ngtcp2_ksl_range_search, sizeof(ngtcp2_range), mem); rv = ngtcp2_rob_gap_new(&g, 0, UINT64_MAX, mem); if (rv != 0) { @@ -82,8 +81,8 @@ int ngtcp2_rob_init(ngtcp2_rob *rob, size_t chunk, const ngtcp2_mem *mem) { goto fail_gapksl_ksl_insert; } - ngtcp2_ksl_init(&rob->dataksl, ngtcp2_ksl_range_compar, sizeof(ngtcp2_range), - mem); + ngtcp2_ksl_init(&rob->dataksl, ngtcp2_ksl_range_compar, + ngtcp2_ksl_range_search, sizeof(ngtcp2_range), mem); rob->chunk = chunk; rob->mem = mem; @@ -126,8 +125,8 @@ static int rob_write_data(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, ngtcp2_range range = {offset, offset + len}; ngtcp2_ksl_it it; - for (it = ngtcp2_ksl_lower_bound_compar(&rob->dataksl, &range, - ngtcp2_ksl_range_exclusive_compar); + for (it = ngtcp2_ksl_lower_bound_search(&rob->dataksl, &range, + ngtcp2_ksl_range_exclusive_search); len; ngtcp2_ksl_it_next(&it)) { if (ngtcp2_ksl_it_end(&it)) { d = NULL; @@ -149,7 +148,8 @@ static int rob_write_data(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, } } - n = (size_t)ngtcp2_min((uint64_t)len, d->range.begin + rob->chunk - offset); + n = (size_t)ngtcp2_min_uint64((uint64_t)len, + d->range.begin + rob->chunk - offset); memcpy(d->begin + (offset - d->range.begin), data, n); offset += n; data += n; @@ -166,8 +166,8 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, ngtcp2_range m, l, r, q = {offset, offset + datalen}; ngtcp2_ksl_it it; - it = ngtcp2_ksl_lower_bound_compar(&rob->gapksl, &q, - ngtcp2_ksl_range_exclusive_compar); + it = ngtcp2_ksl_lower_bound_search(&rob->gapksl, &q, + ngtcp2_ksl_range_exclusive_search); for (; !ngtcp2_ksl_it_end(&it);) { g = ngtcp2_ksl_it_get(&it); @@ -176,9 +176,11 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, if (!ngtcp2_range_len(&m)) { break; } + if (ngtcp2_range_eq(&g->range, &m)) { ngtcp2_ksl_remove_hint(&rob->gapksl, &it, &it, &g->range); ngtcp2_rob_gap_del(g, rob->mem); + rv = rob_write_data(rob, m.begin, data + (m.begin - offset), (size_t)ngtcp2_range_len(&m)); if (rv != 0) { @@ -187,17 +189,21 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, continue; } + ngtcp2_range_cut(&l, &r, &g->range, &m); + if (ngtcp2_range_len(&l)) { ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &l); g->range = l; if (ngtcp2_range_len(&r)) { ngtcp2_rob_gap *ng; + rv = ngtcp2_rob_gap_new(&ng, r.begin, r.end, rob->mem); if (rv != 0) { return rv; } + rv = ngtcp2_ksl_insert(&rob->gapksl, &it, &ng->range, ng); if (rv != 0) { ngtcp2_rob_gap_del(ng, rob->mem); @@ -208,13 +214,16 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r); g->range = r; } + rv = rob_write_data(rob, m.begin, data + (m.begin - offset), (size_t)ngtcp2_range_len(&m)); if (rv != 0) { return rv; } + ngtcp2_ksl_it_next(&it); } + return 0; } @@ -230,12 +239,16 @@ void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) { if (offset <= g->range.begin) { break; } + if (offset < g->range.end) { ngtcp2_range r = {offset, g->range.end}; + ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r); g->range.begin = offset; + break; } + ngtcp2_ksl_remove_hint(&rob->gapksl, &it, &it, &g->range); ngtcp2_rob_gap_del(g, rob->mem); } @@ -247,12 +260,13 @@ void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) { if (offset < d->range.begin + rob->chunk) { return; } + ngtcp2_ksl_remove_hint(&rob->dataksl, &it, &it, &d->range); ngtcp2_rob_data_del(d, rob->mem); } } -size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest, +size_t ngtcp2_rob_data_at(const ngtcp2_rob *rob, const uint8_t **pdest, uint64_t offset) { ngtcp2_rob_gap *g; ngtcp2_rob_data *d; @@ -278,8 +292,9 @@ size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest, *pdest = d->begin + (offset - d->range.begin); - return (size_t)(ngtcp2_min(g->range.begin, d->range.begin + rob->chunk) - - offset); + return ( + size_t)(ngtcp2_min_uint64(g->range.begin, d->range.begin + rob->chunk) - + offset); } void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len) { @@ -299,7 +314,7 @@ void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len) { ngtcp2_rob_data_del(d, rob->mem); } -uint64_t ngtcp2_rob_first_gap_offset(ngtcp2_rob *rob) { +uint64_t ngtcp2_rob_first_gap_offset(const ngtcp2_rob *rob) { ngtcp2_ksl_it it = ngtcp2_ksl_begin(&rob->gapksl); ngtcp2_rob_gap *g; @@ -312,6 +327,6 @@ uint64_t ngtcp2_rob_first_gap_offset(ngtcp2_rob *rob) { return g->range.begin; } -int ngtcp2_rob_data_buffered(ngtcp2_rob *rob) { +int ngtcp2_rob_data_buffered(const ngtcp2_rob *rob) { return ngtcp2_ksl_len(&rob->dataksl) != 0; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h index 6518d56c539185..d53b5160b10230 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -70,12 +70,10 @@ void ngtcp2_rob_gap_del(ngtcp2_rob_gap *g, const ngtcp2_mem *mem); * ngtcp2_rob_data holds the buffered stream data. */ typedef struct ngtcp2_rob_data { - /* range is the range of this gap. */ + /* range is the range of this data. */ ngtcp2_range range; /* begin points to the buffer. */ uint8_t *begin; - /* end points to the one beyond of the last byte of the buffer */ - uint8_t *end; } ngtcp2_rob_data; /* @@ -110,8 +108,8 @@ typedef struct ngtcp2_rob { /* gapksl maintains the range of offset which is not received yet. Initially, its range is [0, UINT64_MAX). */ ngtcp2_ksl gapksl; - /* dataksl maintains the list of buffers which store received data - ordered by stream offset. */ + /* dataksl maintains the buffers which store received out-of-order + data ordered by stream offset. */ ngtcp2_ksl dataksl; /* mem is custom memory allocator */ const ngtcp2_mem *mem; @@ -137,8 +135,8 @@ int ngtcp2_rob_init(ngtcp2_rob *rob, size_t chunk, const ngtcp2_mem *mem); void ngtcp2_rob_free(ngtcp2_rob *rob); /* - * ngtcp2_rob_push adds new data of length |datalen| at the stream - * offset |offset|. + * ngtcp2_rob_push adds new data pointed by |data| of length |datalen| + * at the stream offset |offset|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -151,7 +149,8 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, /* * ngtcp2_rob_remove_prefix removes gap up to |offset|, exclusive. It - * also removes data buffer if it is completely included in |offset|. + * also removes buffered data if it is completely included in + * |offset|. */ void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset); @@ -159,9 +158,10 @@ void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset); * ngtcp2_rob_data_at stores the pointer to the buffer of stream * offset |offset| to |*pdest| if it is available, and returns the * valid length of available data. If no data is available, it - * returns 0. + * returns 0. This function only returns the data before the first + * gap. It returns 0 even if data is available after the first gap. */ -size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest, +size_t ngtcp2_rob_data_at(const ngtcp2_rob *rob, const uint8_t **pdest, uint64_t offset); /* @@ -181,11 +181,11 @@ void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len); * ngtcp2_rob_first_gap_offset returns the offset to the first gap. * If there is no gap, it returns UINT64_MAX. */ -uint64_t ngtcp2_rob_first_gap_offset(ngtcp2_rob *rob); +uint64_t ngtcp2_rob_first_gap_offset(const ngtcp2_rob *rob); /* * ngtcp2_rob_data_buffered returns nonzero if any data is buffered. */ -int ngtcp2_rob_data_buffered(ngtcp2_rob *rob); +int ngtcp2_rob_data_buffered(const ngtcp2_rob *rob); -#endif /* NGTCP2_ROB_H */ +#endif /* !defined(NGTCP2_ROB_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c index b8587e3e9dbac8..89c89acdc265a2 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c @@ -35,26 +35,25 @@ void ngtcp2_rs_init(ngtcp2_rs *rs) { rs->interval = UINT64_MAX; rs->delivered = 0; rs->prior_delivered = 0; - rs->prior_ts = 0; + rs->prior_ts = UINT64_MAX; rs->tx_in_flight = 0; rs->lost = 0; rs->prior_lost = 0; rs->send_elapsed = 0; rs->ack_elapsed = 0; + rs->last_end_seq = -1; rs->is_app_limited = 0; } void ngtcp2_rst_init(ngtcp2_rst *rst) { ngtcp2_rs_init(&rst->rs); - ngtcp2_window_filter_init(&rst->wf, 12); rst->delivered = 0; rst->delivered_ts = 0; rst->first_sent_ts = 0; rst->app_limited = 0; - rst->next_round_delivered = 0; - rst->round_count = 0; rst->is_cwnd_limited = 0; rst->lost = 0; + rst->last_seq = -1; } void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, @@ -68,27 +67,21 @@ void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, ent->rst.is_app_limited = rst->app_limited != 0; ent->rst.tx_in_flight = cstat->bytes_in_flight + ent->pktlen; ent->rst.lost = rst->lost; + ent->rst.end_seq = ++rst->last_seq; } -void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, - uint64_t pkt_delivered) { +void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) { ngtcp2_rs *rs = &rst->rs; - uint64_t rate; if (rst->app_limited && rst->delivered > rst->app_limited) { rst->app_limited = 0; } - if (pkt_delivered >= rst->next_round_delivered) { - rst->next_round_delivered = pkt_delivered; - ++rst->round_count; - } - - if (rs->prior_ts == 0) { + if (rs->prior_ts == UINT64_MAX) { return; } - rs->interval = ngtcp2_max(rs->send_elapsed, rs->ack_elapsed); + rs->interval = ngtcp2_max_uint64(rs->send_elapsed, rs->ack_elapsed); rs->delivered = rst->delivered - rs->prior_delivered; rs->lost = rst->lost - rs->prior_lost; @@ -102,12 +95,13 @@ void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, return; } - rate = rs->delivered * NGTCP2_SECONDS / rs->interval; + cstat->delivery_rate_sec = rs->delivered * NGTCP2_SECONDS / rs->interval; +} - if (rate > ngtcp2_window_filter_get_best(&rst->wf) || !rst->app_limited) { - ngtcp2_window_filter_update(&rst->wf, rate, rst->round_count); - cstat->delivery_rate_sec = ngtcp2_window_filter_get_best(&rst->wf); - } +static int rst_is_newest_pkt(const ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent, + const ngtcp2_rs *rs) { + return ent->ts > rst->first_sent_ts || + (ent->ts == rst->first_sent_ts && ent->rst.end_seq > rs->last_end_seq); } void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent, @@ -117,7 +111,7 @@ void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent, rst->delivered += ent->pktlen; rst->delivered_ts = ts; - if (ent->rst.delivered > rs->prior_delivered) { + if (rs->prior_ts == UINT64_MAX || rst_is_newest_pkt(rst, ent, rs)) { rs->prior_delivered = ent->rst.delivered; rs->prior_ts = ent->rst.delivered_ts; rs->is_app_limited = ent->rst.is_app_limited; @@ -125,6 +119,7 @@ void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent, rs->ack_elapsed = rst->delivered_ts - ent->rst.delivered_ts; rs->tx_in_flight = ent->rst.tx_in_flight; rs->prior_lost = ent->rst.lost; + rs->last_end_seq = ent->rst.end_seq; rst->first_sent_ts = ent->ts; } } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h index c9e1e161b7766f..95616eee97d99f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -51,6 +51,7 @@ typedef struct ngtcp2_rs { uint64_t prior_lost; ngtcp2_duration send_elapsed; ngtcp2_duration ack_elapsed; + int64_t last_end_seq; int is_app_limited; } ngtcp2_rs; @@ -58,18 +59,20 @@ void ngtcp2_rs_init(ngtcp2_rs *rs); /* * ngtcp2_rst implements delivery rate estimation described in - * https://tools.ietf.org/html/draft-cheng-iccrg-delivery-rate-estimation-00 + * https://ietf-wg-ccwg.github.io/draft-cardwell-ccwg-bbr/draft-cardwell-ccwg-bbr.html */ typedef struct ngtcp2_rst { ngtcp2_rs rs; - ngtcp2_window_filter wf; uint64_t delivered; ngtcp2_tstamp delivered_ts; ngtcp2_tstamp first_sent_ts; uint64_t app_limited; - uint64_t next_round_delivered; - uint64_t round_count; uint64_t lost; + /* last_seq is the sequence number of packets across all packet + number spaces. If we would adopt single packet number sequence + across all packet number spaces, we can replace this with a + packet number. */ + int64_t last_seq; int is_cwnd_limited; } ngtcp2_rst; @@ -77,10 +80,9 @@ void ngtcp2_rst_init(ngtcp2_rst *rst); void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, const ngtcp2_conn_stat *cstat); -void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat, - uint64_t pkt_delivered); +void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat); void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent, ngtcp2_tstamp ts); void ngtcp2_rst_update_app_limited(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat); -#endif /* NGTCP2_RST_H */ +#endif /* !defined(NGTCP2_RST_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c index 5ebdce7d0e2715..4d417186e15854 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -38,7 +38,7 @@ #include "ngtcp2_tstamp.h" #include "ngtcp2_frame_chain.h" -ngtcp2_objalloc_def(rtb_entry, ngtcp2_rtb_entry, oplent); +ngtcp2_objalloc_def(rtb_entry, ngtcp2_rtb_entry, oplent) static void rtb_entry_init(ngtcp2_rtb_entry *ent, const ngtcp2_pkt_hd *hd, ngtcp2_frame_chain *frc, ngtcp2_tstamp ts, @@ -53,7 +53,6 @@ static void rtb_entry_init(ngtcp2_rtb_entry *ent, const ngtcp2_pkt_hd *hd, ent->lost_ts = UINT64_MAX; ent->pktlen = pktlen; ent->flags = flags; - ent->next = NULL; } int ngtcp2_rtb_entry_objalloc_new(ngtcp2_rtb_entry **pent, @@ -82,19 +81,14 @@ void ngtcp2_rtb_entry_objalloc_del(ngtcp2_rtb_entry *ent, ngtcp2_objalloc_rtb_entry_release(objalloc, ent); } -static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { - return *(int64_t *)lhs > *(int64_t *)rhs; -} - -void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id, - ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc, +void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t cc_pkt_num, ngtcp2_log *log, ngtcp2_qlog *qlog, ngtcp2_objalloc *rtb_entry_objalloc, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { rtb->rtb_entry_objalloc = rtb_entry_objalloc; rtb->frc_objalloc = frc_objalloc; - ngtcp2_ksl_init(&rtb->ents, greater, sizeof(int64_t), mem); - rtb->crypto = crypto; + ngtcp2_ksl_init(&rtb->ents, ngtcp2_ksl_int64_greater, + ngtcp2_ksl_int64_greater_search, sizeof(int64_t), mem); rtb->rst = rst; rtb->cc = cc; rtb->log = log; @@ -105,7 +99,6 @@ void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id, rtb->num_retransmittable = 0; rtb->num_pto_eliciting = 0; rtb->probe_pkt_left = 0; - rtb->pktns_id = pktns_id; rtb->cc_pkt_num = cc_pkt_num; rtb->cc_bytes_in_flight = 0; rtb->persistent_congestion_start_ts = UINT64_MAX; @@ -145,9 +138,11 @@ static void rtb_on_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { ++rtb->num_ack_eliciting; } + if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) { ++rtb->num_retransmittable; } + if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING) { ++rtb->num_pto_eliciting; } @@ -209,10 +204,10 @@ static size_t rtb_on_remove(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, #define NGTCP2_RECLAIM_FLAG_ON_LOSS 0x01u /* - * rtb_reclaim_frame queues unacknowledged frames included in |ent| - * for retransmission. The re-queued frames are not deleted from - * |ent|. It returns the number of frames queued. |flags| is bitwise - * OR of 0 or more of NGTCP2_RECLAIM_FLAG_*. + * rtb_reclaim_frame copies and queues frames included in |ent| for + * retransmission. The frames are not deleted from |ent|. It returns + * the number of frames queued. |flags| is bitwise OR of 0 or more of + * NGTCP2_RECLAIM_FLAG_*. */ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, ngtcp2_conn *conn, ngtcp2_pktns *pktns, @@ -229,11 +224,13 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, /* TODO Reconsider the order of pfrc */ for (frc = ent->frc; frc; frc = frc->next) { fr = &frc->fr; + /* Check that a late ACK acknowledged this frame. */ if (frc->binder && (frc->binder->flags & NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK)) { continue; } + switch (frc->fr.type) { case NGTCP2_FRAME_STREAM: strm = ngtcp2_conn_find_stream(conn, fr->stream.stream_id); @@ -244,14 +241,15 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, gap = ngtcp2_strm_get_unacked_range_after(strm, fr->stream.offset); range.begin = fr->stream.offset; - range.end = fr->stream.offset + - ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt); + range.end = + fr->stream.offset + ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt); range = ngtcp2_range_intersect(&range, &gap); + if (ngtcp2_range_len(&range) == 0) { if (!fr->stream.fin) { /* 0 length STREAM frame with offset == 0 must be - retransmitted if no non-empty data is sent to this stream - and no data in this stream is acknowledged. */ + retransmitted if no non-empty data are sent to this + stream, and no data in this stream are acknowledged. */ if (fr->stream.offset != 0 || fr->stream.datacnt != 0 || strm->tx.offset || (strm->flags & NGTCP2_STRM_FLAG_ANY_ACKED)) { continue; @@ -268,7 +266,7 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, } rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( - &nfrc, fr->stream.datacnt, rtb->frc_objalloc, rtb->mem); + &nfrc, fr->stream.datacnt, rtb->frc_objalloc, rtb->mem); if (rv != 0) { return rv; } @@ -282,8 +280,10 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, ngtcp2_frame_chain_objalloc_del(nfrc, rtb->frc_objalloc, rtb->mem); return rv; } + if (!ngtcp2_strm_is_tx_queued(strm)) { strm->cycle = ngtcp2_conn_tx_strmq_first_cycle(conn); + rv = ngtcp2_conn_tx_strmq_push(conn, strm); if (rv != 0) { return rv; @@ -294,20 +294,22 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, continue; case NGTCP2_FRAME_CRYPTO: - /* Don't resend CRYPTO frame if the whole region it contains has - been acknowledged */ - gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, fr->stream.offset); + /* Do not resend CRYPTO frame if the whole region it contains + has been acknowledged */ + gap = ngtcp2_strm_get_unacked_range_after(&pktns->crypto.strm, + fr->stream.offset); range.begin = fr->stream.offset; - range.end = fr->stream.offset + - ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt); + range.end = + fr->stream.offset + ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt); range = ngtcp2_range_intersect(&range, &gap); + if (ngtcp2_range_len(&range) == 0) { continue; } rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( - &nfrc, fr->stream.datacnt, rtb->frc_objalloc, rtb->mem); + &nfrc, fr->stream.datacnt, rtb->frc_objalloc, rtb->mem); if (rv != 0) { return rv; } @@ -328,8 +330,8 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, continue; case NGTCP2_FRAME_NEW_TOKEN: rv = ngtcp2_frame_chain_new_token_objalloc_new( - &nfrc, fr->new_token.token, fr->new_token.tokenlen, rtb->frc_objalloc, - rtb->mem); + &nfrc, fr->new_token.token, fr->new_token.tokenlen, rtb->frc_objalloc, + rtb->mem); if (rv != 0) { return rv; } @@ -366,7 +368,7 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, case NGTCP2_FRAME_MAX_STREAM_DATA: strm = ngtcp2_conn_find_stream(conn, fr->max_stream_data.stream_id); if (strm == NULL || !ngtcp2_strm_require_retransmit_max_stream_data( - strm, &fr->max_stream_data)) { + strm, &fr->max_stream_data)) { continue; } @@ -374,7 +376,7 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, case NGTCP2_FRAME_STREAM_DATA_BLOCKED: strm = ngtcp2_conn_find_stream(conn, fr->stream_data_blocked.stream_id); if (strm == NULL || !ngtcp2_strm_require_retransmit_stream_data_blocked( - strm, &fr->stream_data_blocked)) { + strm, &fr->stream_data_blocked)) { continue; } @@ -423,6 +425,7 @@ static int conn_process_lost_datagram(ngtcp2_conn *conn, if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } + break; } } @@ -430,10 +433,9 @@ static int conn_process_lost_datagram(ngtcp2_conn *conn, return 0; } -static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it, - ngtcp2_rtb_entry *ent, ngtcp2_conn_stat *cstat, - ngtcp2_conn *conn, ngtcp2_pktns *pktns, - ngtcp2_tstamp ts) { +static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, + ngtcp2_conn_stat *cstat, ngtcp2_conn *conn, + ngtcp2_pktns *pktns, ngtcp2_tstamp ts) { int rv; ngtcp2_ssize reclaimed; ngtcp2_cc *cc = rtb->cc; @@ -451,7 +453,7 @@ static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it, } else if (rtb->cc->on_pkt_lost) { cc->on_pkt_lost(cc, cstat, ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen, - rtb->pktns_id, ent->ts, ent->rst.lost, + pktns->id, ent->ts, ent->rst.lost, ent->rst.tx_in_flight, ent->rst.is_app_limited), ts); @@ -463,34 +465,25 @@ static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it, ent->hd.pkt_num); assert(!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED)); assert(UINT64_MAX == ent->lost_ts); - - ent->flags |= NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED; - ent->lost_ts = ts; - - ++rtb->num_lost_pkts; - - ngtcp2_ksl_it_next(it); - - return 0; - } - - if (conn->callbacks.lost_datagram && - (ent->flags & NGTCP2_RTB_ENTRY_FLAG_DATAGRAM)) { - rv = conn_process_lost_datagram(conn, ent); - if (rv != 0) { - return rv; + } else { + if (conn->callbacks.lost_datagram && + (ent->flags & NGTCP2_RTB_ENTRY_FLAG_DATAGRAM)) { + rv = conn_process_lost_datagram(conn, ent); + if (rv != 0) { + return rv; + } } - } - if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) { - assert(ent->frc); - assert(!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED)); - assert(UINT64_MAX == ent->lost_ts); + if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) { + assert(ent->frc); + assert(!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED)); + assert(UINT64_MAX == ent->lost_ts); - reclaimed = + reclaimed = rtb_reclaim_frame(rtb, NGTCP2_RECLAIM_FLAG_ON_LOSS, conn, pktns, ent); - if (reclaimed < 0) { - return (int)reclaimed; + if (reclaimed < 0) { + return (int)reclaimed; + } } } @@ -499,8 +492,6 @@ static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it, ++rtb->num_lost_pkts; - ngtcp2_ksl_it_next(it); - return 0; } @@ -518,7 +509,7 @@ int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, return 0; } -ngtcp2_ksl_it ngtcp2_rtb_head(ngtcp2_rtb *rtb) { +ngtcp2_ksl_it ngtcp2_rtb_head(const ngtcp2_rtb *rtb) { return ngtcp2_ksl_begin(&rtb->ents); } @@ -566,22 +557,24 @@ static void conn_ack_crypto_data(ngtcp2_conn *conn, ngtcp2_pktns *pktns, return; } -static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, - ngtcp2_conn *conn) { +static int process_acked_pkt(ngtcp2_rtb_entry *ent, ngtcp2_conn *conn, + ngtcp2_pktns *pktns) { ngtcp2_frame_chain *frc; uint64_t prev_stream_offset, stream_offset; ngtcp2_strm *strm; int rv; uint64_t datalen; - ngtcp2_strm *crypto = rtb->crypto; - ngtcp2_pktns *pktns = NULL; + ngtcp2_strm *crypto = &pktns->crypto.strm; if ((ent->flags & NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE) && conn->pmtud && conn->pmtud->tx_pkt_num <= ent->hd.pkt_num) { ngtcp2_pmtud_probe_success(conn->pmtud, ent->pktlen); - conn->dcid.current.max_udp_payload_size = - ngtcp2_max(conn->dcid.current.max_udp_payload_size, ent->pktlen); + if (conn->dcid.current.max_udp_payload_size < ent->pktlen) { + conn->dcid.current.max_udp_payload_size = ent->pktlen; + conn->cstat.max_tx_udp_payload_size = + ngtcp2_conn_get_path_max_tx_udp_payload_size(conn); + } if (ngtcp2_pmtud_finished(conn->pmtud)) { ngtcp2_conn_stop_pmtud(conn); @@ -611,23 +604,25 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, } prev_stream_offset = ngtcp2_strm_get_acked_offset(strm); + rv = ngtcp2_strm_ack_data( - strm, frc->fr.stream.offset, - ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt)); + strm, frc->fr.stream.offset, + ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt)); if (rv != 0) { return rv; } if (conn->callbacks.acked_stream_data_offset) { stream_offset = ngtcp2_strm_get_acked_offset(strm); + datalen = stream_offset - prev_stream_offset; if (datalen == 0 && !frc->fr.stream.fin) { break; } rv = conn->callbacks.acked_stream_data_offset( - conn, strm->stream_id, prev_stream_offset, datalen, conn->user_data, - strm->stream_user_data); + conn, strm->stream_id, prev_stream_offset, datalen, conn->user_data, + strm->stream_user_data); if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -637,36 +632,25 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, if (rv != 0) { return rv; } + break; case NGTCP2_FRAME_CRYPTO: prev_stream_offset = ngtcp2_strm_get_acked_offset(crypto); + rv = ngtcp2_strm_ack_data( - crypto, frc->fr.stream.offset, - ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt)); + crypto, frc->fr.stream.offset, + ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt)); if (rv != 0) { return rv; } stream_offset = ngtcp2_strm_get_acked_offset(crypto); + datalen = stream_offset - prev_stream_offset; if (datalen == 0) { break; } - switch (rtb->pktns_id) { - case NGTCP2_PKTNS_ID_INITIAL: - pktns = conn->in_pktns; - break; - case NGTCP2_PKTNS_ID_HANDSHAKE: - pktns = conn->hs_pktns; - break; - case NGTCP2_PKTNS_ID_APPLICATION: - pktns = &conn->pktns; - break; - default: - ngtcp2_unreachable(); - } - conn_ack_crypto_data(conn, pktns, datalen); break; @@ -675,11 +659,14 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, if (strm == NULL) { break; } + strm->flags |= NGTCP2_STRM_FLAG_RESET_STREAM_ACKED; + rv = ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm); if (rv != 0) { return rv; } + break; case NGTCP2_FRAME_RETIRE_CONNECTION_ID: ngtcp2_conn_untrack_retired_dcid_seq(conn, @@ -702,14 +689,17 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, if (rv != 0) { return NGTCP2_ERR_CALLBACK_FAILURE; } + break; } } + return 0; } static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, - ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { + ngtcp2_conn_stat *cstat, const ngtcp2_pktns *pktns, + ngtcp2_tstamp ts) { ngtcp2_cc *cc = rtb->cc; ngtcp2_cc_pkt pkt; @@ -718,7 +708,7 @@ static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, if (cc->on_pkt_acked) { cc->on_pkt_acked(cc, cstat, ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen, - rtb->pktns_id, ent->ts, ent->rst.lost, + pktns->id, ent->ts, ent->rst.lost, ent->rst.tx_in_flight, ent->rst.is_app_limited), ts); @@ -745,12 +735,13 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, pktns->rx.ecn.ack.ect1 > fr->ecn.ect1 || pktns->rx.ecn.ack.ce > fr->ecn.ce || (fr->ecn.ect0 - pktns->rx.ecn.ack.ect0) + - (fr->ecn.ce - pktns->rx.ecn.ack.ce) < - ecn_acked || + (fr->ecn.ce - pktns->rx.ecn.ack.ce) < + ecn_acked || fr->ecn.ect0 > pktns->tx.ecn.ect0 || fr->ecn.ect1))) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "path is not ECN capable"); conn->tx.ecn.state = NGTCP2_ECN_STATE_FAILED; + return; } @@ -762,7 +753,7 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, if (fr->type == NGTCP2_FRAME_ACK_ECN) { if (cc->congestion_event && largest_pkt_sent_ts != UINT64_MAX && fr->ecn.ce > pktns->rx.ecn.ack.ce) { - cc->congestion_event(cc, cstat, largest_pkt_sent_ts, ts); + cc->congestion_event(cc, cstat, largest_pkt_sent_ts, 0, ts); } pktns->rx.ecn.ack.ect0 = fr->ecn.ect0; @@ -784,7 +775,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, size_t i; int rv; ngtcp2_ksl_it it; - ngtcp2_ssize num_acked = 0; + size_t num_acked = 0; ngtcp2_tstamp largest_pkt_sent_ts = UINT64_MAX; int64_t pkt_num; ngtcp2_cc *cc = rtb->cc; @@ -820,6 +811,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, largest_pkt_sent_ts, ts); } + return 0; } @@ -848,7 +840,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ++num_acked; } - for (i = 0; i < fr->rangecnt;) { + for (i = 0; i < fr->rangecnt; ++i) { largest_ack = min_ack - (int64_t)fr->ranges[i].gap - 2; min_ack = largest_ack - (int64_t)fr->ranges[i].len; @@ -862,6 +854,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, if (pkt_num < min_ack) { break; } + ent = ngtcp2_ksl_it_get(&it); if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { @@ -871,12 +864,11 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, rtb_remove(rtb, &it, &acked_ent, ent, cstat); ++num_acked; } - - ++i; } if (largest_pkt_sent_ts != UINT64_MAX && ack_eliciting_pkt_acked) { - cc_ack.rtt = pkt_ts - largest_pkt_sent_ts; + cc_ack.rtt = + ngtcp2_max_uint64(pkt_ts - 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) { @@ -891,7 +883,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ++ecn_acked; } - rv = rtb_process_acked_pkt(rtb, ent, conn); + rv = process_acked_pkt(ent, conn, pktns); if (rv != 0) { goto fail; } @@ -903,7 +895,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, cc_ack.pkt_delivered = ent->rst.delivered; } - rtb_on_pkt_acked(rtb, ent, cstat, ts); + rtb_on_pkt_acked(rtb, ent, cstat, pktns, ts); acked_ent = ent->next; ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, rtb->frc_objalloc, rtb->mem); @@ -916,7 +908,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, } else { /* For unit tests */ for (ent = acked_ent; ent; ent = acked_ent) { - rtb_on_pkt_acked(rtb, ent, cstat, ts); + rtb_on_pkt_acked(rtb, ent, cstat, pktns, ts); acked_ent = ent->next; ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, rtb->frc_objalloc, rtb->mem); @@ -924,27 +916,29 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, } if (rtb->cc->on_spurious_congestion && num_lost_pkts && - rtb->num_lost_pkts - rtb->num_lost_pmtud_pkts == 0) { + rtb->num_lost_pkts == rtb->num_lost_pmtud_pkts) { rtb->cc->on_spurious_congestion(cc, cstat, ts); } - ngtcp2_rst_on_ack_recv(rtb->rst, cstat, cc_ack.pkt_delivered); + if (num_acked) { + ngtcp2_rst_on_ack_recv(rtb->rst, cstat); - if (conn && num_acked > 0) { - rv = rtb_detect_lost_pkt(rtb, &cc_ack.bytes_lost, conn, pktns, cstat, ts); - if (rv != 0) { - return rv; + if (conn) { + rv = rtb_detect_lost_pkt(rtb, &cc_ack.bytes_lost, conn, pktns, cstat, ts); + if (rv != 0) { + return rv; + } } } rtb->rst->lost += cc_ack.bytes_lost; cc_ack.largest_pkt_sent_ts = largest_pkt_sent_ts; - if (cc->on_ack_recv) { + if (num_acked && cc->on_ack_recv) { cc->on_ack_recv(cc, cstat, &cc_ack, ts); } - return num_acked; + return (ngtcp2_ssize)num_acked; fail: for (ent = acked_ent; ent; ent = acked_ent) { @@ -958,7 +952,8 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, static int rtb_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat, const ngtcp2_rtb_entry *ent, ngtcp2_duration loss_delay, - size_t pkt_thres, ngtcp2_tstamp ts) { + size_t pkt_thres, const ngtcp2_pktns *pktns, + ngtcp2_tstamp ts) { ngtcp2_tstamp loss_time; if (ngtcp2_tstamp_elapsed(ent->ts, loss_delay, ts) || @@ -966,27 +961,27 @@ static int rtb_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat, return 1; } - loss_time = cstat->loss_time[rtb->pktns_id]; + loss_time = cstat->loss_time[pktns->id]; if (loss_time == UINT64_MAX) { loss_time = ent->ts + loss_delay; } else { - loss_time = ngtcp2_min(loss_time, ent->ts + loss_delay); + loss_time = ngtcp2_min_uint64(loss_time, ent->ts + loss_delay); } - cstat->loss_time[rtb->pktns_id] = loss_time; + cstat->loss_time[pktns->id] = loss_time; return 0; } /* - * rtb_compute_pkt_loss_delay computes loss delay. + * compute_pkt_loss_delay computes loss delay. */ static ngtcp2_duration compute_pkt_loss_delay(const ngtcp2_conn_stat *cstat) { /* 9/8 is kTimeThreshold */ ngtcp2_duration loss_delay = - ngtcp2_max(cstat->latest_rtt, cstat->smoothed_rtt) * 9 / 8; - return ngtcp2_max(loss_delay, NGTCP2_GRANULARITY); + ngtcp2_max_uint64(cstat->latest_rtt, cstat->smoothed_rtt) * 9 / 8; + return ngtcp2_max_uint64(loss_delay, NGTCP2_GRANULARITY); } /* @@ -999,9 +994,9 @@ static int conn_all_ecn_pkt_lost(ngtcp2_conn *conn) { ngtcp2_pktns *pktns = &conn->pktns; return (!in_pktns || in_pktns->tx.ecn.validation_pkt_sent == - in_pktns->tx.ecn.validation_pkt_lost) && + in_pktns->tx.ecn.validation_pkt_lost) && (!hs_pktns || hs_pktns->tx.ecn.validation_pkt_sent == - hs_pktns->tx.ecn.validation_pkt_lost) && + hs_pktns->tx.ecn.validation_pkt_lost) && pktns->tx.ecn.validation_pkt_sent == pktns->tx.ecn.validation_pkt_lost; } @@ -1017,16 +1012,16 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, ngtcp2_cc *cc = rtb->cc; int rv; uint64_t pkt_thres = - rtb->cc_bytes_in_flight / cstat->max_tx_udp_payload_size / 2; + rtb->cc_bytes_in_flight / cstat->max_tx_udp_payload_size / 2; size_t ecn_pkt_lost = 0; ngtcp2_tstamp start_ts; ngtcp2_duration pto = ngtcp2_conn_compute_pto(conn, pktns); uint64_t bytes_lost = 0; ngtcp2_duration max_ack_delay; - pkt_thres = ngtcp2_max(pkt_thres, NGTCP2_PKT_THRESHOLD); - pkt_thres = ngtcp2_min(pkt_thres, 256); - cstat->loss_time[rtb->pktns_id] = UINT64_MAX; + pkt_thres = ngtcp2_max_uint64(pkt_thres, NGTCP2_PKT_THRESHOLD); + pkt_thres = ngtcp2_min_uint64(pkt_thres, 256); + cstat->loss_time[pktns->id] = UINT64_MAX; loss_delay = compute_pkt_loss_delay(cstat); it = ngtcp2_ksl_lower_bound(&rtb->ents, &rtb->largest_acked_tx_pkt_num); @@ -1037,25 +1032,27 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, break; } - if (rtb_pkt_lost(rtb, cstat, ent, loss_delay, (size_t)pkt_thres, ts)) { + if (rtb_pkt_lost(rtb, cstat, ent, loss_delay, (size_t)pkt_thres, pktns, + ts)) { /* All entries from ent are considered to be lost. */ latest_ts = oldest_ts = ent->ts; /* +1 to pick this packet for persistent congestion in the following loop. */ last_lost_pkt_num = ent->hd.pkt_num + 1; max_ack_delay = conn->remote.transport_params - ? conn->remote.transport_params->max_ack_delay - : 0; + ? conn->remote.transport_params->max_ack_delay + : 0; congestion_period = - (cstat->smoothed_rtt + - ngtcp2_max(4 * cstat->rttvar, NGTCP2_GRANULARITY) + max_ack_delay) * - NGTCP2_PERSISTENT_CONGESTION_THRESHOLD; + (cstat->smoothed_rtt + + ngtcp2_max_uint64(4 * cstat->rttvar, NGTCP2_GRANULARITY) + + max_ack_delay) * + NGTCP2_PERSISTENT_CONGESTION_THRESHOLD; - start_ts = ngtcp2_max(rtb->persistent_congestion_start_ts, - cstat->first_rtt_sample_ts); + start_ts = ngtcp2_max_uint64(rtb->persistent_congestion_start_ts, + cstat->first_rtt_sample_ts); - for (; !ngtcp2_ksl_it_end(&it);) { + for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) { ent = ngtcp2_ksl_it_get(&it); if (last_lost_pkt_num == ent->hd.pkt_num + 1 && ent->ts >= start_ts) { @@ -1066,12 +1063,12 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, } if ((ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED)) { - if (rtb->pktns_id != NGTCP2_PKTNS_ID_APPLICATION || + if (pktns->id != NGTCP2_PKTNS_ID_APPLICATION || last_lost_pkt_num == -1 || latest_ts - oldest_ts >= congestion_period) { break; } - ngtcp2_ksl_it_next(&it); + continue; } @@ -1081,7 +1078,7 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, } bytes_lost += rtb_on_remove(rtb, ent, cstat); - rv = rtb_on_pkt_lost(rtb, &it, ent, cstat, conn, pktns, ts); + rv = rtb_on_pkt_lost(rtb, ent, cstat, conn, pktns, ts); if (rv != 0) { return rv; } @@ -1098,13 +1095,16 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, if (conn->tx.ecn.validation_start_ts == UINT64_MAX) { break; } + if (ts - conn->tx.ecn.validation_start_ts < 3 * pto) { pktns->tx.ecn.validation_pkt_lost += ecn_pkt_lost; assert(pktns->tx.ecn.validation_pkt_sent >= pktns->tx.ecn.validation_pkt_lost); break; } + conn->tx.ecn.state = NGTCP2_ECN_STATE_UNKNOWN; + /* fall through */ case NGTCP2_ECN_STATE_UNKNOWN: pktns->tx.ecn.validation_pkt_lost += ecn_pkt_lost; @@ -1119,7 +1119,7 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, } if (cc->congestion_event) { - cc->congestion_event(cc, cstat, latest_ts, ts); + cc->congestion_event(cc, cstat, latest_ts, bytes_lost, ts); } loss_window = latest_ts - oldest_ts; @@ -1130,23 +1130,22 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, * persistent congestion there, then it is a lot easier to just * not enable it during handshake. */ - if (rtb->pktns_id == NGTCP2_PKTNS_ID_APPLICATION && loss_window > 0) { - if (loss_window >= congestion_period) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, - "persistent congestion loss_window=%" PRIu64 - " congestion_period=%" PRIu64, - loss_window, congestion_period); - - /* Reset min_rtt, srtt, and rttvar here. Next new RTT - sample will be used to recalculate these values. */ - cstat->min_rtt = UINT64_MAX; - cstat->smoothed_rtt = conn->local.settings.initial_rtt; - cstat->rttvar = conn->local.settings.initial_rtt / 2; - cstat->first_rtt_sample_ts = UINT64_MAX; - - if (cc->on_persistent_congestion) { - cc->on_persistent_congestion(cc, cstat, ts); - } + if (pktns->id == NGTCP2_PKTNS_ID_APPLICATION && loss_window && + loss_window >= congestion_period) { + ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, + "persistent congestion loss_window=%" PRIu64 + " congestion_period=%" PRIu64, + loss_window, congestion_period); + + /* Reset min_rtt, srtt, and rttvar here. Next new RTT + sample will be used to recalculate these values. */ + cstat->min_rtt = UINT64_MAX; + cstat->smoothed_rtt = conn->local.settings.initial_rtt; + cstat->rttvar = conn->local.settings.initial_rtt / 2; + cstat->first_rtt_sample_ts = UINT64_MAX; + + if (cc->on_persistent_congestion) { + cc->on_persistent_congestion(cc, cstat, ts); } } @@ -1243,7 +1242,7 @@ void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_duration pto, } } -ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(ngtcp2_rtb *rtb) { +ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(const ngtcp2_rtb *rtb) { ngtcp2_ksl_it it; ngtcp2_rtb_entry *ent; @@ -1338,11 +1337,13 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_frame_chain_objalloc_del(frc, rtb->frc_objalloc, rtb->mem); break; } + rv = ngtcp2_strm_streamfrq_push(strm, frc); if (rv != 0) { ngtcp2_frame_chain_objalloc_del(frc, rtb->frc_objalloc, rtb->mem); return rv; } + if (!ngtcp2_strm_is_tx_queued(strm)) { strm->cycle = ngtcp2_conn_tx_strmq_first_cycle(conn); rv = ngtcp2_conn_tx_strmq_push(conn, strm); @@ -1350,6 +1351,7 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, return rv; } } + break; case NGTCP2_FRAME_CRYPTO: frc = *pfrc; @@ -1363,6 +1365,7 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_frame_chain_objalloc_del(frc, rtb->frc_objalloc, rtb->mem); return rv; } + break; case NGTCP2_FRAME_DATAGRAM: case NGTCP2_FRAME_DATAGRAM_LEN: @@ -1379,6 +1382,7 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, *pfrc = (*pfrc)->next; ngtcp2_frame_chain_objalloc_del(frc, rtb->frc_objalloc, rtb->mem); + break; default: pfrc = &(*pfrc)->next; @@ -1408,8 +1412,10 @@ int ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_conn *conn, assert(0 == rv); rv = rtb_on_pkt_lost_resched_move(rtb, conn, pktns, ent); + ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, rtb->frc_objalloc, rtb->mem); + if (rv != 0) { return rv; } @@ -1443,7 +1449,7 @@ void ngtcp2_rtb_remove_early_data(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat) { } } -int ngtcp2_rtb_empty(ngtcp2_rtb *rtb) { +int ngtcp2_rtb_empty(const ngtcp2_rtb *rtb) { return ngtcp2_ksl_len(&rtb->ents) == 0; } @@ -1460,7 +1466,7 @@ ngtcp2_ssize ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb *rtb, ngtcp2_conn *conn, size_t atmost = num_pkts; it = ngtcp2_ksl_end(&rtb->ents); - for (; !ngtcp2_ksl_it_begin(&it) && num_pkts >= 1;) { + for (; !ngtcp2_ksl_it_begin(&it) && num_pkts;) { ngtcp2_ksl_it_prev(&it); ent = ngtcp2_ksl_it_get(&it); @@ -1473,13 +1479,13 @@ ngtcp2_ssize ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb *rtb, ngtcp2_conn *conn, assert(ent->frc); reclaimed = - rtb_reclaim_frame(rtb, NGTCP2_RECLAIM_FLAG_NONE, conn, pktns, ent); + rtb_reclaim_frame(rtb, NGTCP2_RECLAIM_FLAG_NONE, conn, pktns, ent); if (reclaimed < 0) { return reclaimed; } - /* Mark reclaimed even if reclaimed == 0 so that we can skip it in - the next run. */ + /* Mark ent reclaimed even if reclaimed == 0 so that we can skip + it in the next run. */ ent->flags |= NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED; assert(rtb->num_retransmittable); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h index a1ff208b19eac7..2ef772b2e14f4b 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -85,7 +85,7 @@ typedef struct ngtcp2_rtb_entry ngtcp2_rtb_entry; /* * ngtcp2_rtb_entry is an object stored in ngtcp2_rtb. It corresponds - * to the one packet which is waiting for its ACK. + * to the one packet which is waiting for its acknowledgement. */ struct ngtcp2_rtb_entry { union { @@ -98,10 +98,11 @@ struct ngtcp2_rtb_entry { uint8_t flags; } hd; ngtcp2_frame_chain *frc; - /* ts is the time point when a packet included in this entry is sent - to a peer. */ + /* ts is the time point when a packet included in this entry is + sent to a remote endpoint. */ ngtcp2_tstamp ts; - /* lost_ts is the time when this entry is marked lost. */ + /* lost_ts is the time when this entry is declared to be + lost. */ ngtcp2_tstamp lost_ts; /* pktlen is the length of QUIC packet */ size_t pktlen; @@ -111,6 +112,7 @@ struct ngtcp2_rtb_entry { ngtcp2_tstamp first_sent_ts; uint64_t tx_in_flight; uint64_t lost; + int64_t end_seq; int is_app_limited; } rst; /* flags is bitwise-OR of zero or more of @@ -122,11 +124,11 @@ struct ngtcp2_rtb_entry { }; }; -ngtcp2_objalloc_decl(rtb_entry, ngtcp2_rtb_entry, oplent); +ngtcp2_objalloc_decl(rtb_entry, ngtcp2_rtb_entry, oplent) /* - * ngtcp2_rtb_entry_new allocates ngtcp2_rtb_entry object, and assigns - * its pointer to |*pent|. + * ngtcp2_rtb_entry_objalloc_new allocates ngtcp2_rtb_entry object via + * |objalloc|, and assigns its pointer to |*pent|. */ int ngtcp2_rtb_entry_objalloc_new(ngtcp2_rtb_entry **pent, const ngtcp2_pkt_hd *hd, @@ -145,7 +147,7 @@ void ngtcp2_rtb_entry_objalloc_del(ngtcp2_rtb_entry *ent, const ngtcp2_mem *mem); /* - * ngtcp2_rtb tracks sent packets, and its ACK timeout for + * ngtcp2_rtb tracks sent packets, and its acknowledgement timeout for * retransmission. */ typedef struct ngtcp2_rtb { @@ -154,34 +156,33 @@ typedef struct ngtcp2_rtb { /* ents includes ngtcp2_rtb_entry sorted by decreasing order of packet number. */ ngtcp2_ksl ents; - /* crypto is CRYPTO stream. */ - ngtcp2_strm *crypto; ngtcp2_rst *rst; ngtcp2_cc *cc; ngtcp2_log *log; ngtcp2_qlog *qlog; const ngtcp2_mem *mem; /* largest_acked_tx_pkt_num is the largest packet number - acknowledged by the peer. */ + acknowledged by a remote endpoint. */ int64_t largest_acked_tx_pkt_num; - /* num_ack_eliciting is the number of ACK eliciting entries. */ + /* num_ack_eliciting is the number of ACK eliciting entries in + ents. */ size_t num_ack_eliciting; /* num_retransmittable is the number of packets which contain frames - that must be retransmitted on loss. */ + that must be retransmitted on loss in ents. */ size_t num_retransmittable; /* num_pto_eliciting is the number of packets that elicit PTO probe - packets. */ + packets in ents. */ size_t num_pto_eliciting; /* probe_pkt_left is the number of probe packet to send */ size_t probe_pkt_left; - /* pktns_id is the identifier of packet number space. */ - ngtcp2_pktns_id pktns_id; /* cc_pkt_num is the smallest packet number that is contributed to ngtcp2_conn_stat.bytes_in_flight. */ int64_t cc_pkt_num; /* cc_bytes_in_flight is the number of in-flight bytes that is contributed to ngtcp2_conn_stat.bytes_in_flight. It only - includes the bytes after congestion state is reset. */ + includes the bytes after congestion state is reset, that is only + count a packet whose packet number is greater than or equals to + cc_pkt_num. */ uint64_t cc_bytes_in_flight; /* persistent_congestion_start_ts is the time when persistent congestion evaluation is started. It happens roughly after @@ -199,8 +200,7 @@ typedef struct ngtcp2_rtb { /* * ngtcp2_rtb_init initializes |rtb|. */ -void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id, - ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc, +void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t cc_pkt_num, ngtcp2_log *log, ngtcp2_qlog *qlog, ngtcp2_objalloc *rtb_entry_objalloc, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem); @@ -227,13 +227,13 @@ int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, * which has the largest packet number. If there is no entry, * returned value satisfies ngtcp2_ksl_it_end(&it) != 0. */ -ngtcp2_ksl_it ngtcp2_rtb_head(ngtcp2_rtb *rtb); +ngtcp2_ksl_it ngtcp2_rtb_head(const ngtcp2_rtb *rtb); /* - * ngtcp2_rtb_recv_ack removes acked ngtcp2_rtb_entry from |rtb|. - * |pkt_num| is a packet number which includes |fr|. |pkt_ts| is the - * timestamp when packet is received. |ts| should be the current - * time. Usually they are the same, but for buffered packets, + * ngtcp2_rtb_recv_ack removes an acknowledged ngtcp2_rtb_entry from + * |rtb|. |pkt_num| is a packet number which includes |fr|. |pkt_ts| + * is the timestamp when packet is received. |ts| should be the + * current time. Usually they are the same, but for buffered packets, * |pkt_ts| would be earlier than |ts|. * * This function returns the number of newly acknowledged packets if @@ -252,7 +252,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, /* * ngtcp2_rtb_detect_lost_pkt detects lost packets and prepends the * frames contained them to |*pfrc|. Even when this function fails, - * some frames might be prepended to |*pfrc| and the caller should + * some frames might be prepended to |*pfrc|, and the caller should * handle them. */ int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn, @@ -266,16 +266,16 @@ void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_duration pto, ngtcp2_tstamp ts); /* - * ngtcp2_rtb_lost_pkt_ts returns the earliest time when the still - * retained packet was lost. It returns UINT64_MAX if no such packet - * exists. + * ngtcp2_rtb_lost_pkt_ts returns the timestamp when an oldest lost + * packet tracked by |rtb| was declared lost. It returns UINT64_MAX + * if no such packet exists. */ -ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(ngtcp2_rtb *rtb); +ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(const ngtcp2_rtb *rtb); /* - * ngtcp2_rtb_remove_all removes all packets from |rtb| and prepends + * ngtcp2_rtb_remove_all removes all packets from |rtb|, and prepends * all frames to |*pfrc|. Even when this function fails, some frames - * might be prepended to |*pfrc| and the caller should handle them. + * might be prepended to |*pfrc|, and the caller should handle them. */ int ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat); @@ -286,9 +286,9 @@ int ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_conn *conn, void ngtcp2_rtb_remove_early_data(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat); /* - * ngtcp2_rtb_empty returns nonzero if |rtb| have no entry. + * ngtcp2_rtb_empty returns nonzero if |rtb| has no entry. */ -int ngtcp2_rtb_empty(ngtcp2_rtb *rtb); +int ngtcp2_rtb_empty(const ngtcp2_rtb *rtb); /* * ngtcp2_rtb_reset_cc_state resets congestion state in |rtb|. @@ -298,15 +298,15 @@ int ngtcp2_rtb_empty(ngtcp2_rtb *rtb); void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num); /* - * ngtcp2_rtb_remove_expired_lost_pkt ensures that the number of lost - * packets at most |n|. + * ngtcp2_rtb_remove_excessive_lost_pkt ensures that the number of + * lost packets is at most |n|. */ void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n); /* * ngtcp2_rtb_reclaim_on_pto reclaims up to |num_pkts| packets which - * are in-flight and not marked lost to send them in PTO probe. The - * reclaimed frames are chained to |*pfrc|. + * are in-flight and not marked lost. The reclaimed frames may be + * sent in a PTO probe packet. * * This function returns the number of packets reclaimed if it * succeeds, or one of the following negative error codes: @@ -317,4 +317,4 @@ void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n); ngtcp2_ssize ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_pktns *pktns, size_t num_pkts); -#endif /* NGTCP2_RTB_H */ +#endif /* !defined(NGTCP2_RTB_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.c new file mode 100644 index 00000000000000..77a68bd112e3b2 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.c @@ -0,0 +1,91 @@ +/* + * ngtcp2 + * + * Copyright (c) 2024 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ngtcp2_settings.h" + +#include +#include + +#include "ngtcp2_unreachable.h" + +void ngtcp2_settings_default_versioned(int settings_version, + ngtcp2_settings *settings) { + size_t len = ngtcp2_settingslen_version(settings_version); + + memset(settings, 0, len); + + switch (settings_version) { + case NGTCP2_SETTINGS_VERSION: + case NGTCP2_SETTINGS_V1: + settings->cc_algo = NGTCP2_CC_ALGO_CUBIC; + settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT; + settings->ack_thresh = 2; + settings->max_tx_udp_payload_size = 1500 - 48; + settings->handshake_timeout = UINT64_MAX; + + break; + } +} + +static void settings_copy(ngtcp2_settings *dest, const ngtcp2_settings *src, + int settings_version) { + assert(settings_version != NGTCP2_SETTINGS_VERSION); + + memcpy(dest, src, ngtcp2_settingslen_version(settings_version)); +} + +const ngtcp2_settings * +ngtcp2_settings_convert_to_latest(ngtcp2_settings *dest, int settings_version, + const ngtcp2_settings *src) { + if (settings_version == NGTCP2_SETTINGS_VERSION) { + return src; + } + + ngtcp2_settings_default(dest); + + settings_copy(dest, src, settings_version); + + return dest; +} + +void ngtcp2_settings_convert_to_old(int settings_version, ngtcp2_settings *dest, + const ngtcp2_settings *src) { + assert(settings_version != NGTCP2_SETTINGS_VERSION); + + settings_copy(dest, src, settings_version); +} + +size_t ngtcp2_settingslen_version(int settings_version) { + ngtcp2_settings settings; + + switch (settings_version) { + case NGTCP2_SETTINGS_VERSION: + return sizeof(settings); + case NGTCP2_SETTINGS_V1: + return offsetof(ngtcp2_settings, initial_pkt_num) + + sizeof(settings.initial_pkt_num); + default: + ngtcp2_unreachable(); + } +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h new file mode 100644 index 00000000000000..80466d43e47a7a --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h @@ -0,0 +1,73 @@ +/* + * ngtcp2 + * + * Copyright (c) 2024 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef NGTCP2_SETTINGS_H +#define NGTCP2_SETTINGS_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* defined(HAVE_CONFIG_H) */ + +#include + +/* + * ngtcp2_settings_convert_to_latest converts |src| of version + * |settings_version| to the latest version NGTCP2_SETTINGS_VERSION. + * + * |dest| must point to the latest version. |src| may be the older + * version, and if so, it may have fewer fields. Accessing those + * fields causes undefined behavior. + * + * If |settings_version| == NGTCP2_SETTINGS_VERSION, no conversion is + * made, and |src| is returned. Otherwise, first |dest| is + * initialized via ngtcp2_settings_default, and then all valid fields + * in |src| are copied into |dest|. Finally, |dest| is returned. + */ +const ngtcp2_settings * +ngtcp2_settings_convert_to_latest(ngtcp2_settings *dest, int settings_version, + const ngtcp2_settings *src); + +/* + * ngtcp2_settings_convert_to_old converts |src| of the latest version + * to |dest| of version |settings_version|. + * + * |settings_version| must not be the latest version + * NGTCP2_SETTINGS_VERSION. + * + * |dest| points to the older version, and it may have fewer fields. + * Accessing those fields causes undefined behavior. + * + * This function copies all valid fields in version |settings_version| + * from |src| to |dest|. + */ +void ngtcp2_settings_convert_to_old(int settings_version, ngtcp2_settings *dest, + const ngtcp2_settings *src); + +/* + * ngtcp2_settingslen_version returns the effective length of + * ngtcp2_settings at the version |settings_version|. + */ +size_t ngtcp2_settingslen_version(int settings_version); + +#endif /* !defined(NGTCP2_SETTINGS_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h index deb75e356d70d4..f970c153e805a8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -91,4 +91,4 @@ 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); -#endif /* NGTCP2_STR_H */ +#endif /* !defined(NGTCP2_STR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c index c00e86fa8c1afa..8ea969c4addbdc 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c @@ -32,16 +32,13 @@ #include "ngtcp2_vec.h" #include "ngtcp2_frame_chain.h" -static int offset_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { - return *(int64_t *)lhs < *(int64_t *)rhs; -} - 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->frc_objalloc = frc_objalloc; + 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; @@ -56,13 +53,12 @@ void ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags, 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->flags = flags; strm->stream_user_data = stream_user_data; - strm->rx.window = strm->rx.max_offset = strm->rx.unsent_max_offset = - max_rx_offset; - strm->pe.index = NGTCP2_PQ_BAD_INDEX; - strm->mem = mem; + strm->flags = flags; strm->app_error_code = 0; } @@ -114,7 +110,7 @@ static int strm_rob_init(ngtcp2_strm *strm) { return 0; } -uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm) { +uint64_t ngtcp2_strm_rx_offset(const ngtcp2_strm *strm) { if (strm->rx.rob == NULL) { return strm->rx.cont_offset; } @@ -123,7 +119,7 @@ uint64_t ngtcp2_strm_rx_offset(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(ngtcp2_rob *rob) { +static int strm_rob_heavily_fragmented(const ngtcp2_rob *rob) { return ngtcp2_ksl_len(&rob->gapksl) >= 5000; } @@ -180,7 +176,8 @@ static int strm_streamfrq_init(ngtcp2_strm *strm) { return NGTCP2_ERR_NOMEM; } - ngtcp2_ksl_init(streamfrq, offset_less, sizeof(uint64_t), strm->mem); + ngtcp2_ksl_init(streamfrq, ngtcp2_ksl_uint64_less, + ngtcp2_ksl_uint64_less_search, sizeof(uint64_t), strm->mem); strm->tx.streamfrq = streamfrq; @@ -271,6 +268,7 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, } ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); + continue; } @@ -306,11 +304,12 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, fr->data[0].len -= (size_t)base_offset; *pfrc = frc; + return 0; } rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( - &nfrc, fr->datacnt - end_idx, strm->frc_objalloc, strm->mem); + &nfrc, fr->datacnt - end_idx, strm->frc_objalloc, strm->mem); if (rv != 0) { ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); return rv; @@ -336,6 +335,7 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem); ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); + return rv; } @@ -350,14 +350,17 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, fr->fin = 0; fr->offset = offset + base_offset; fr->datacnt = end_idx - idx; + if (end_base_offset) { assert(fr->data[fr->datacnt - 1].len > end_base_offset); fr->data[fr->datacnt - 1].len = (size_t)end_base_offset; } + fr->data[0].base += base_offset; fr->data[0].len -= (size_t)base_offset; *pfrc = frc; + return 0; } @@ -367,7 +370,7 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, size_t left) { ngtcp2_stream *fr, *nfr; - ngtcp2_frame_chain *frc, *nfrc; + ngtcp2_frame_chain *frc, *nfrc, *sfrc; int rv; size_t nmerged; uint64_t datalen; @@ -385,6 +388,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, if (rv != 0) { return rv; } + if (frc == NULL) { *pfrc = NULL; return 0; @@ -401,7 +405,9 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); return rv; } + *pfrc = NULL; + return 0; } @@ -410,13 +416,13 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, acnt = fr->datacnt; bcnt = 0; - ngtcp2_vec_split(a, &acnt, b, &bcnt, left, NGTCP2_MAX_STREAM_DATACNT); + ngtcp2_vec_split(b, &bcnt, a, &acnt, left, NGTCP2_MAX_STREAM_DATACNT); assert(acnt > 0); assert(bcnt > 0); rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( - &nfrc, bcnt, strm->frc_objalloc, strm->mem); + &nfrc, bcnt, strm->frc_objalloc, strm->mem); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); @@ -437,11 +443,12 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem); ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); + return rv; } rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( - &nfrc, acnt, strm->frc_objalloc, strm->mem); + &nfrc, acnt, strm->frc_objalloc, strm->mem); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); @@ -491,7 +498,9 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, break; } - nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left, + bcnt = nfr->datacnt; + + nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &bcnt, left, NGTCP2_MAX_STREAM_DATACNT); if (nmerged == 0) { rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc); @@ -499,27 +508,56 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, assert(ngtcp2_err_is_fatal(rv)); ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem); ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); + return rv; } + break; } datalen += nmerged; left -= nmerged; - if (nfr->datacnt == 0) { + if (bcnt == 0) { fr->fin = nfr->fin; ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem); continue; } - nfr->offset += nmerged; + if (nfr->datacnt <= NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES || + bcnt > NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES) { + nfr->offset += nmerged; + nfr->datacnt = bcnt; + + rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc); + if (rv != 0) { + ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem); + ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); + return rv; + } + } else { + rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( + &sfrc, bcnt, strm->frc_objalloc, strm->mem); + if (rv != 0) { + ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem); + ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); + return rv; + } + + sfrc->fr.stream = nfrc->fr.stream; + sfrc->fr.stream.offset += nmerged; + sfrc->fr.stream.datacnt = bcnt; + ngtcp2_vec_copy(sfrc->fr.stream.data, nfrc->fr.stream.data, bcnt); - rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc); - if (rv != 0) { ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem); - ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); - return rv; + + rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &sfrc->fr.stream.offset, + sfrc); + if (rv != 0) { + ngtcp2_frame_chain_objalloc_del(sfrc, strm->frc_objalloc, strm->mem); + ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); + return rv; + } } break; @@ -531,13 +569,14 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, } *pfrc = frc; + return 0; } assert(acnt > fr->datacnt); rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( - &nfrc, acnt, strm->frc_objalloc, strm->mem); + &nfrc, acnt, strm->frc_objalloc, strm->mem); if (rv != 0) { ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); return rv; @@ -555,7 +594,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, return 0; } -uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm) { +uint64_t ngtcp2_strm_streamfrq_unacked_offset(const ngtcp2_strm *strm) { ngtcp2_frame_chain *frc; ngtcp2_stream *fr; ngtcp2_range gap; @@ -577,9 +616,11 @@ uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm) { if (gap.begin <= fr->offset) { return fr->offset; } + if (gap.begin < fr->offset + datalen) { return gap.begin; } + if (fr->offset + datalen == gap.begin && fr->fin && !(strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED)) { return fr->offset + datalen; @@ -589,17 +630,18 @@ uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm) { return (uint64_t)-1; } -ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(ngtcp2_strm *strm) { +ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(const ngtcp2_strm *strm) { ngtcp2_ksl_it it; assert(strm->tx.streamfrq); assert(ngtcp2_ksl_len(strm->tx.streamfrq)); it = ngtcp2_ksl_begin(strm->tx.streamfrq); + return ngtcp2_ksl_it_get(&it); } -int ngtcp2_strm_streamfrq_empty(ngtcp2_strm *strm) { +int ngtcp2_strm_streamfrq_empty(const ngtcp2_strm *strm) { return strm->tx.streamfrq == NULL || ngtcp2_ksl_len(strm->tx.streamfrq) == 0; } @@ -616,14 +658,15 @@ void ngtcp2_strm_streamfrq_clear(ngtcp2_strm *strm) { frc = ngtcp2_ksl_it_get(&it); ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem); } + ngtcp2_ksl_clear(strm->tx.streamfrq); } -int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm) { +int ngtcp2_strm_is_tx_queued(const ngtcp2_strm *strm) { return strm->pe.index != NGTCP2_PQ_BAD_INDEX; } -int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm) { +int ngtcp2_strm_is_all_tx_data_acked(const ngtcp2_strm *strm) { if (strm->tx.acked_offset == NULL) { return strm->tx.cont_acked_offset == strm->tx.offset; } @@ -632,12 +675,12 @@ int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm) { strm->tx.offset; } -int ngtcp2_strm_is_all_tx_data_fin_acked(ngtcp2_strm *strm) { +int ngtcp2_strm_is_all_tx_data_fin_acked(const ngtcp2_strm *strm) { return (strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED) && ngtcp2_strm_is_all_tx_data_acked(strm); } -ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm, +ngtcp2_range ngtcp2_strm_get_unacked_range_after(const ngtcp2_strm *strm, uint64_t offset) { ngtcp2_range gap; @@ -650,7 +693,7 @@ ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm, return ngtcp2_gaptr_get_first_gap_after(strm->tx.acked_offset, offset); } -uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm) { +uint64_t ngtcp2_strm_get_acked_offset(const ngtcp2_strm *strm) { if (strm->tx.acked_offset == NULL) { return strm->tx.cont_acked_offset; } @@ -660,7 +703,7 @@ uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm) { static int strm_acked_offset_init(ngtcp2_strm *strm) { ngtcp2_gaptr *acked_offset = - ngtcp2_mem_malloc(strm->mem, sizeof(*acked_offset)); + ngtcp2_mem_malloc(strm->mem, sizeof(*acked_offset)); if (acked_offset == NULL) { return NGTCP2_ERR_NOMEM; @@ -688,7 +731,7 @@ int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len) { } rv = - ngtcp2_gaptr_push(strm->tx.acked_offset, 0, strm->tx.cont_acked_offset); + ngtcp2_gaptr_push(strm->tx.acked_offset, 0, strm->tx.cont_acked_offset); if (rv != 0) { return rv; } @@ -709,24 +752,24 @@ void ngtcp2_strm_set_app_error_code(ngtcp2_strm *strm, strm->app_error_code = app_error_code; } -int ngtcp2_strm_require_retransmit_reset_stream(ngtcp2_strm *strm) { +int ngtcp2_strm_require_retransmit_reset_stream(const ngtcp2_strm *strm) { return !ngtcp2_strm_is_all_tx_data_fin_acked(strm); } -int ngtcp2_strm_require_retransmit_stop_sending(ngtcp2_strm *strm) { +int ngtcp2_strm_require_retransmit_stop_sending(const ngtcp2_strm *strm) { return !(strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) || ngtcp2_strm_rx_offset(strm) != strm->rx.last_offset; } -int ngtcp2_strm_require_retransmit_max_stream_data(ngtcp2_strm *strm, - ngtcp2_max_stream_data *fr) { +int ngtcp2_strm_require_retransmit_max_stream_data( + const ngtcp2_strm *strm, const ngtcp2_max_stream_data *fr) { return fr->max_stream_data == strm->rx.max_offset && !(strm->flags & (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_STOP_SENDING)); } int ngtcp2_strm_require_retransmit_stream_data_blocked( - ngtcp2_strm *strm, ngtcp2_stream_data_blocked *fr) { + const ngtcp2_strm *strm, const ngtcp2_stream_data_blocked *fr) { return fr->offset == strm->tx.max_offset && !(strm->flags & NGTCP2_STRM_FLAG_SHUT_WR); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h index 385302a5eafa9f..c72f8b9dc89aca 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -86,6 +86,9 @@ typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; received from the remote endpoint. In this case, NGTCP2_STRM_FLAG_SHUT_WR is also set. */ #define NGTCP2_STRM_FLAG_STOP_SENDING_RECVED 0x800u +/* NGTCP2_STRM_FLAG_ANY_SENT indicates that any STREAM frame, + including empty one, has been sent. */ +#define NGTCP2_STRM_FLAG_ANY_SENT 0x1000u typedef struct ngtcp2_strm ngtcp2_strm; @@ -105,13 +108,13 @@ struct ngtcp2_strm { acked_offset is used instead. */ uint64_t cont_acked_offset; /* streamfrq contains STREAM or CRYPTO frame for - retransmission. The flow control credits have been paid - when they are transmitted first time. There are no + retransmission. The flow control credits have already been + paid when they are transmitted first time. There are no restriction regarding flow control for retransmission. */ ngtcp2_ksl *streamfrq; - /* offset is the next offset of outgoing data. In other words, it - is the number of bytes sent in this stream without - duplication. */ + /* offset is the next offset of new outgoing data. In other + words, it is the number of bytes sent in this stream + without duplication. */ uint64_t offset; /* max_tx_offset is the maximum offset that local endpoint can send for this stream. */ @@ -200,7 +203,7 @@ void ngtcp2_strm_free(ngtcp2_strm *strm); * ngtcp2_strm_rx_offset returns the minimum offset of stream data * which is not received yet. */ -uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm); +uint64_t ngtcp2_strm_rx_offset(const ngtcp2_strm *strm); /* * ngtcp2_strm_recv_reordering handles reordered data. @@ -215,8 +218,8 @@ int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data, size_t datalen, uint64_t offset); /* - * ngtcp2_strm_update_rx_offset tells that data up to offset bytes are - * received in order. + * ngtcp2_strm_update_rx_offset tells that data up to |offset| bytes + * are received in order. */ void ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset); @@ -227,13 +230,14 @@ void ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset); void ngtcp2_strm_discard_reordered_data(ngtcp2_strm *strm); /* - * ngtcp2_strm_shutdown shutdowns |strm|. |flags| should be - * NGTCP2_STRM_FLAG_SHUT_RD, and/or NGTCP2_STRM_FLAG_SHUT_WR. + * ngtcp2_strm_shutdown shutdowns |strm|. |flags| should be one of + * NGTCP2_STRM_FLAG_SHUT_RD, NGTCP2_STRM_FLAG_SHUT_WR, and + * NGTCP2_STRM_FLAG_SHUT_RDWR. */ void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags); /* - * ngtcp2_strm_streamfrq_push pushes |frc| to streamfrq for + * ngtcp2_strm_streamfrq_push pushes |frc| to strm->tx.streamfrq for * retransmission. * * This function returns 0 if it succeeds, or one of the following @@ -245,11 +249,12 @@ void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags); int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc); /* - * ngtcp2_strm_streamfrq_pop pops the first ngtcp2_frame_chain and - * assigns it to |*pfrc|. This function splits into or merges several - * ngtcp2_frame_chain objects so that the returned ngtcp2_frame_chain - * has at most |left| data length. If there is no frames to send, - * this function returns 0 and |*pfrc| is NULL. + * ngtcp2_strm_streamfrq_pop assigns a ngtcp2_frame_chain that only + * contains unacknowledged stream data with smallest offset to |*pfrc| + * for retransmission. The assigned ngtcp2_frame_chain has stream + * data at most |left| bytes. strm->tx.streamfrq is adjusted to + * exclude the portion of data included in it. If there is no stream + * data to send, this function returns 0 and |*pfrc| is NULL. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -264,18 +269,18 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, * ngtcp2_strm_streamfrq_unacked_offset returns the smallest offset of * unacknowledged stream data held in strm->tx.streamfrq. */ -uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm); +uint64_t ngtcp2_strm_streamfrq_unacked_offset(const ngtcp2_strm *strm); /* * ngtcp2_strm_streamfrq_top returns the first ngtcp2_frame_chain. * The queue must not be empty. */ -ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(ngtcp2_strm *strm); +ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(const ngtcp2_strm *strm); /* * ngtcp2_strm_streamfrq_empty returns nonzero if streamfrq is empty. */ -int ngtcp2_strm_streamfrq_empty(ngtcp2_strm *strm); +int ngtcp2_strm_streamfrq_empty(const ngtcp2_strm *strm); /* * ngtcp2_strm_streamfrq_clear removes all frames from streamfrq. @@ -285,26 +290,26 @@ void ngtcp2_strm_streamfrq_clear(ngtcp2_strm *strm); /* * ngtcp2_strm_is_tx_queued returns nonzero if |strm| is queued. */ -int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm); +int ngtcp2_strm_is_tx_queued(const ngtcp2_strm *strm); /* * ngtcp2_strm_is_all_tx_data_acked returns nonzero if all outgoing * data for |strm| which have sent so far have been acknowledged. */ -int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm); +int ngtcp2_strm_is_all_tx_data_acked(const ngtcp2_strm *strm); /* * ngtcp2_strm_is_all_tx_data_fin_acked behaves like * ngtcp2_strm_is_all_tx_data_acked, but it also requires that STREAM * frame with fin bit set is acknowledged. */ -int ngtcp2_strm_is_all_tx_data_fin_acked(ngtcp2_strm *strm); +int ngtcp2_strm_is_all_tx_data_fin_acked(const ngtcp2_strm *strm); /* * ngtcp2_strm_get_unacked_range_after returns the range that is not - * acknowledged yet and intersects or comes after |offset|. + * acknowledged yet and includes or comes after |offset|. */ -ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm, +ngtcp2_range ngtcp2_strm_get_unacked_range_after(const ngtcp2_strm *strm, uint64_t offset); /* @@ -312,11 +317,11 @@ ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm, * this offset have been acknowledged by a remote endpoint. It * returns 0 if no data is acknowledged. */ -uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm); +uint64_t ngtcp2_strm_get_acked_offset(const ngtcp2_strm *strm); /* - * ngtcp2_strm_ack_data tells |strm| that the data [offset, - * offset+len) is acknowledged by a remote endpoint. + * ngtcp2_strm_ack_data tells |strm| that the data [|offset|, |offset| + * + |len|) is acknowledged by a remote endpoint. */ int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len); @@ -331,26 +336,26 @@ void ngtcp2_strm_set_app_error_code(ngtcp2_strm *strm, uint64_t app_error_code); * ngtcp2_strm_require_retransmit_reset_stream returns nonzero if * RESET_STREAM frame should be retransmitted. */ -int ngtcp2_strm_require_retransmit_reset_stream(ngtcp2_strm *strm); +int ngtcp2_strm_require_retransmit_reset_stream(const ngtcp2_strm *strm); /* * ngtcp2_strm_require_retransmit_stop_sending returns nonzero if * STOP_SENDING frame should be retransmitted. */ -int ngtcp2_strm_require_retransmit_stop_sending(ngtcp2_strm *strm); +int ngtcp2_strm_require_retransmit_stop_sending(const ngtcp2_strm *strm); /* * ngtcp2_strm_require_retransmit_max_stream_data returns nonzero if * MAX_STREAM_DATA frame should be retransmitted. */ -int ngtcp2_strm_require_retransmit_max_stream_data(ngtcp2_strm *strm, - ngtcp2_max_stream_data *fr); +int ngtcp2_strm_require_retransmit_max_stream_data( + const ngtcp2_strm *strm, const ngtcp2_max_stream_data *fr); /* * ngtcp2_strm_require_retransmit_stream_data_blocked returns nonzero * if STREAM_DATA_BLOCKED frame frame should be retransmitted. */ int ngtcp2_strm_require_retransmit_stream_data_blocked( - ngtcp2_strm *strm, ngtcp2_stream_data_blocked *fr); + const ngtcp2_strm *strm, const ngtcp2_stream_data_blocked *fr); -#endif /* NGTCP2_STRM_H */ +#endif /* !defined(NGTCP2_STRM_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.c new file mode 100644 index 00000000000000..dda59c48858185 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.c @@ -0,0 +1,886 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ngtcp2_transport_params.h" + +#include +#include + +#include "ngtcp2_conv.h" +#include "ngtcp2_str.h" +#include "ngtcp2_mem.h" +#include "ngtcp2_unreachable.h" + +void ngtcp2_transport_params_default_versioned( + int transport_params_version, ngtcp2_transport_params *params) { + size_t len; + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_VERSION: + len = sizeof(*params); + + break; + default: + ngtcp2_unreachable(); + } + + memset(params, 0, len); + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_VERSION: + params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; + params->active_connection_id_limit = + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; + params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; + params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; + + break; + } +} + +/* + * varint_paramlen returns the length of a single transport parameter + * which has variable integer in its parameter. + */ +static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) { + size_t valuelen = ngtcp2_put_uvarintlen(param); + return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(valuelen) + valuelen; +} + +/* + * write_varint_param writes parameter |id| of the given |value| in + * varint encoding. It returns p + the number of bytes written. + */ +static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id, + uint64_t value) { + p = ngtcp2_put_uvarint(p, id); + p = ngtcp2_put_uvarint(p, ngtcp2_put_uvarintlen(value)); + return ngtcp2_put_uvarint(p, value); +} + +/* + * zero_paramlen returns the length of a single transport parameter + * which has zero length value in its parameter. + */ +static size_t zero_paramlen(ngtcp2_transport_param_id id) { + return ngtcp2_put_uvarintlen(id) + 1; +} + +/* + * write_zero_param writes parameter |id| that has zero length value. + * It returns p + the number of bytes written. + */ +static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) { + p = ngtcp2_put_uvarint(p, id); + *p++ = 0; + + return p; +} + +/* + * cid_paramlen returns the length of a single transport parameter + * which has |cid| as value. + */ +static size_t cid_paramlen(ngtcp2_transport_param_id id, + const ngtcp2_cid *cid) { + return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(cid->datalen) + + cid->datalen; +} + +/* + * write_cid_param writes parameter |id| of the given |cid|. It + * returns p + the number of bytes written. + */ +static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id, + const ngtcp2_cid *cid) { + assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN); + assert(cid->datalen <= NGTCP2_MAX_CIDLEN); + + p = ngtcp2_put_uvarint(p, id); + p = ngtcp2_put_uvarint(p, cid->datalen); + if (cid->datalen) { + p = ngtcp2_cpymem(p, cid->data, cid->datalen); + } + return p; +} + +static const uint8_t empty_address[16]; + +ngtcp2_ssize ngtcp2_transport_params_encode_versioned( + uint8_t *dest, size_t destlen, int transport_params_version, + const ngtcp2_transport_params *params) { + uint8_t *p; + size_t len = 0; + /* For some reason, gcc 7.3.0 requires this initialization. */ + size_t preferred_addrlen = 0; + size_t version_infolen = 0; + const ngtcp2_sockaddr_in *sa_in; + const ngtcp2_sockaddr_in6 *sa_in6; + ngtcp2_transport_params paramsbuf; + + params = ngtcp2_transport_params_convert_to_latest( + ¶msbuf, transport_params_version, params); + + if (params->original_dcid_present) { + len += + cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, + ¶ms->original_dcid); + } + + if (params->stateless_reset_token_present) { + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) + + ngtcp2_put_uvarintlen(NGTCP2_STATELESS_RESET_TOKENLEN) + + NGTCP2_STATELESS_RESET_TOKENLEN; + } + + if (params->preferred_addr_present) { + assert(params->preferred_addr.cid.datalen >= NGTCP2_MIN_CIDLEN); + assert(params->preferred_addr.cid.datalen <= NGTCP2_MAX_CIDLEN); + preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ + + 16 /* ipv6Address */ + 2 /* ipv6Port */ + + 1 + params->preferred_addr.cid.datalen /* CID */ + + NGTCP2_STATELESS_RESET_TOKENLEN; + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) + + ngtcp2_put_uvarintlen(preferred_addrlen) + preferred_addrlen; + } + if (params->retry_scid_present) { + len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, + ¶ms->retry_scid); + } + + if (params->initial_scid_present) { + len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, + ¶ms->initial_scid); + } + + if (params->initial_max_stream_data_bidi_local) { + len += + varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, + params->initial_max_stream_data_bidi_local); + } + if (params->initial_max_stream_data_bidi_remote) { + len += varint_paramlen( + NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, + params->initial_max_stream_data_bidi_remote); + } + if (params->initial_max_stream_data_uni) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI, + params->initial_max_stream_data_uni); + } + if (params->initial_max_data) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA, + params->initial_max_data); + } + if (params->initial_max_streams_bidi) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI, + params->initial_max_streams_bidi); + } + if (params->initial_max_streams_uni) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, + params->initial_max_streams_uni); + } + if (params->max_udp_payload_size != + NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, + params->max_udp_payload_size); + } + if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, + params->ack_delay_exponent); + } + if (params->disable_active_migration) { + len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); + } + if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, + params->max_ack_delay / NGTCP2_MILLISECONDS); + } + if (params->max_idle_timeout) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT, + params->max_idle_timeout / NGTCP2_MILLISECONDS); + } + if (params->active_connection_id_limit && + params->active_connection_id_limit != + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT, + params->active_connection_id_limit); + } + if (params->max_datagram_frame_size) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE, + params->max_datagram_frame_size); + } + if (params->grease_quic_bit) { + len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); + } + if (params->version_info_present) { + version_infolen = + sizeof(uint32_t) + params->version_info.available_versionslen; + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION) + + ngtcp2_put_uvarintlen(version_infolen) + version_infolen; + } + + if (dest == NULL && destlen == 0) { + return (ngtcp2_ssize)len; + } + + if (destlen < len) { + return NGTCP2_ERR_NOBUF; + } + + p = dest; + + if (params->original_dcid_present) { + p = write_cid_param( + p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, + ¶ms->original_dcid); + } + + if (params->stateless_reset_token_present) { + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN); + p = ngtcp2_put_uvarint(p, sizeof(params->stateless_reset_token)); + p = ngtcp2_cpymem(p, params->stateless_reset_token, + sizeof(params->stateless_reset_token)); + } + + if (params->preferred_addr_present) { + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS); + p = ngtcp2_put_uvarint(p, preferred_addrlen); + + if (params->preferred_addr.ipv4_present) { + sa_in = ¶ms->preferred_addr.ipv4; + p = ngtcp2_cpymem(p, &sa_in->sin_addr, sizeof(sa_in->sin_addr)); + p = ngtcp2_put_uint16(p, sa_in->sin_port); + } else { + p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in->sin_addr)); + p = ngtcp2_put_uint16(p, 0); + } + + if (params->preferred_addr.ipv6_present) { + sa_in6 = ¶ms->preferred_addr.ipv6; + p = ngtcp2_cpymem(p, &sa_in6->sin6_addr, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_put_uint16(p, sa_in6->sin6_port); + } else { + p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_put_uint16(p, 0); + } + + *p++ = (uint8_t)params->preferred_addr.cid.datalen; + if (params->preferred_addr.cid.datalen) { + p = ngtcp2_cpymem(p, params->preferred_addr.cid.data, + params->preferred_addr.cid.datalen); + } + p = ngtcp2_cpymem(p, params->preferred_addr.stateless_reset_token, + sizeof(params->preferred_addr.stateless_reset_token)); + } + + if (params->retry_scid_present) { + p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, + ¶ms->retry_scid); + } + + if (params->initial_scid_present) { + p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, + ¶ms->initial_scid); + } + + if (params->initial_max_stream_data_bidi_local) { + p = write_varint_param( + p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, + params->initial_max_stream_data_bidi_local); + } + + if (params->initial_max_stream_data_bidi_remote) { + p = write_varint_param( + p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, + params->initial_max_stream_data_bidi_remote); + } + + if (params->initial_max_stream_data_uni) { + p = + write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI, + params->initial_max_stream_data_uni); + } + + if (params->initial_max_data) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA, + params->initial_max_data); + } + + if (params->initial_max_streams_bidi) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI, + params->initial_max_streams_bidi); + } + + if (params->initial_max_streams_uni) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, + params->initial_max_streams_uni); + } + + if (params->max_udp_payload_size != + NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, + params->max_udp_payload_size); + } + + if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, + params->ack_delay_exponent); + } + + if (params->disable_active_migration) { + p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); + } + + if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, + params->max_ack_delay / NGTCP2_MILLISECONDS); + } + + if (params->max_idle_timeout) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT, + params->max_idle_timeout / NGTCP2_MILLISECONDS); + } + + if (params->active_connection_id_limit && + params->active_connection_id_limit != + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT, + params->active_connection_id_limit); + } + + if (params->max_datagram_frame_size) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE, + params->max_datagram_frame_size); + } + + if (params->grease_quic_bit) { + p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); + } + + if (params->version_info_present) { + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION); + p = ngtcp2_put_uvarint(p, version_infolen); + p = ngtcp2_put_uint32be(p, params->version_info.chosen_version); + if (params->version_info.available_versionslen) { + p = ngtcp2_cpymem(p, params->version_info.available_versions, + params->version_info.available_versionslen); + } + } + + assert((size_t)(p - dest) == len); + + return (ngtcp2_ssize)len; +} + +/* + * decode_varint decodes a single varint from the buffer pointed by + * |*pp| of length |end - *pp|. If it decodes an integer + * successfully, it stores the integer in |*pdest|, increment |*pp| by + * the number of bytes read from |*pp|, and returns 0. Otherwise it + * returns -1. + */ +static int decode_varint(uint64_t *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; + size_t len; + + if (p == end) { + return -1; + } + + len = ngtcp2_get_uvarintlen(p); + if ((uint64_t)(end - p) < len) { + return -1; + } + + *pp = ngtcp2_get_uvarint(pdest, p); + + return 0; +} + +/* + * decode_varint_param decodes length prefixed value from the buffer + * pointed by |*pp| of length |end - *pp|. The length and value are + * encoded in varint form. If it decodes a value successfully, it + * stores the value in |*pdest|, increment |*pp| by the number of + * bytes read from |*pp|, and returns 0. Otherwise it returns -1. + */ +static int decode_varint_param(uint64_t *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; + uint64_t valuelen; + + if (decode_varint(&valuelen, &p, end) != 0) { + return -1; + } + + if (p == end) { + return -1; + } + + if ((uint64_t)(end - p) < valuelen) { + return -1; + } + + if (ngtcp2_get_uvarintlen(p) != valuelen) { + return -1; + } + + *pp = ngtcp2_get_uvarint(pdest, p); + + return 0; +} + +/* + * decode_zero_param decodes zero length value from the buffer pointed + * by |*pp| of length |end - *pp|. The length is encoded in varint + * form. If it decodes zero length value successfully, it increments + * |*pp| by 1, and returns 0. Otherwise it returns -1. + */ +static int decode_zero_param(const uint8_t **pp, const uint8_t *end) { + if (*pp == end || **pp != 0) { + return -1; + } + + ++*pp; + + return 0; +} + +/* + * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer + * pointed by |*pp| of length |end - *pp|. The length is encoded in + * varint form. If it decodes a value successfully, it stores the + * value in |*pdest|, increment |*pp| by the number of read from + * |*pp|, and returns the number of bytes read. Otherwise it returns + * the one of the negative error code: + * + * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM + * Could not decode Connection ID. + */ +static int decode_cid_param(ngtcp2_cid *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; + uint64_t valuelen; + + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) || + valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + ngtcp2_cid_init(pdest, p, (size_t)valuelen); + + p += valuelen; + + *pp = p; + + return 0; +} + +int ngtcp2_transport_params_decode_versioned(int transport_params_version, + ngtcp2_transport_params *dest, + const uint8_t *data, + size_t datalen) { + const uint8_t *p, *end, *lend; + size_t len; + uint64_t param_type; + uint64_t valuelen; + int rv; + ngtcp2_sockaddr_in *sa_in; + ngtcp2_sockaddr_in6 *sa_in6; + uint32_t version; + ngtcp2_transport_params *params, paramsbuf; + + if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { + params = dest; + } else { + params = ¶msbuf; + } + + /* Set default values */ + memset(params, 0, sizeof(*params)); + params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; + params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; + params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; + params->active_connection_id_limit = + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; + + p = data; + end = data + datalen; + + for (; (size_t)(end - p) >= 2;) { + if (decode_varint(¶m_type, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + switch (param_type) { + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: + if (decode_varint_param(¶ms->initial_max_stream_data_bidi_local, &p, + end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: + if (decode_varint_param(¶ms->initial_max_stream_data_bidi_remote, &p, + end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI: + if (decode_varint_param(¶ms->initial_max_stream_data_uni, &p, end) != + 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA: + if (decode_varint_param(¶ms->initial_max_data, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI: + if (decode_varint_param(¶ms->initial_max_streams_bidi, &p, end) != + 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI: + if (decode_varint_param(¶ms->initial_max_streams_uni, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT: + if (decode_varint_param(¶ms->max_idle_timeout, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + params->max_idle_timeout *= NGTCP2_MILLISECONDS; + break; + case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE: + if (decode_varint_param(¶ms->max_udp_payload_size, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN: + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)valuelen != sizeof(params->stateless_reset_token)) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + p = ngtcp2_get_bytes(params->stateless_reset_token, p, + sizeof(params->stateless_reset_token)); + params->stateless_reset_token_present = 1; + + break; + case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT: + if (decode_varint_param(¶ms->ack_delay_exponent, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->ack_delay_exponent > 20) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS: + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ + + 2 /* ipv6Port */ + + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN; + if (valuelen < len) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + sa_in = ¶ms->preferred_addr.ipv4; + + p = ngtcp2_get_bytes(&sa_in->sin_addr, p, sizeof(sa_in->sin_addr)); + p = ngtcp2_get_uint16(&sa_in->sin_port, p); + + if (sa_in->sin_port || memcmp(empty_address, &sa_in->sin_addr, + sizeof(sa_in->sin_addr)) != 0) { + sa_in->sin_family = NGTCP2_AF_INET; + params->preferred_addr.ipv4_present = 1; + } + + sa_in6 = ¶ms->preferred_addr.ipv6; + + p = ngtcp2_get_bytes(&sa_in6->sin6_addr, p, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_get_uint16(&sa_in6->sin6_port, p); + + if (sa_in6->sin6_port || memcmp(empty_address, &sa_in6->sin6_addr, + sizeof(sa_in6->sin6_addr)) != 0) { + sa_in6->sin6_family = NGTCP2_AF_INET6; + params->preferred_addr.ipv6_present = 1; + } + + /* cid */ + params->preferred_addr.cid.datalen = *p++; + len += params->preferred_addr.cid.datalen; + if (valuelen != len || + params->preferred_addr.cid.datalen > NGTCP2_MAX_CIDLEN || + params->preferred_addr.cid.datalen < NGTCP2_MIN_CIDLEN) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->preferred_addr.cid.datalen) { + p = ngtcp2_get_bytes(params->preferred_addr.cid.data, p, + params->preferred_addr.cid.datalen); + } + + /* stateless reset token */ + p = + ngtcp2_get_bytes(params->preferred_addr.stateless_reset_token, p, + sizeof(params->preferred_addr.stateless_reset_token)); + params->preferred_addr_present = 1; + break; + case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION: + if (decode_zero_param(&p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + params->disable_active_migration = 1; + break; + case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID: + rv = decode_cid_param(¶ms->original_dcid, &p, end); + if (rv != 0) { + return rv; + } + params->original_dcid_present = 1; + break; + case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID: + rv = decode_cid_param(¶ms->retry_scid, &p, end); + if (rv != 0) { + return rv; + } + params->retry_scid_present = 1; + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID: + rv = decode_cid_param(¶ms->initial_scid, &p, end); + if (rv != 0) { + return rv; + } + params->initial_scid_present = 1; + break; + case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY: + if (decode_varint_param(¶ms->max_ack_delay, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->max_ack_delay >= 16384) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + params->max_ack_delay *= NGTCP2_MILLISECONDS; + break; + case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT: + if (decode_varint_param(¶ms->active_connection_id_limit, &p, end) != + 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE: + if (decode_varint_param(¶ms->max_datagram_frame_size, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT: + if (decode_zero_param(&p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + params->grease_quic_bit = 1; + break; + case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION: + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + p = ngtcp2_get_uint32be(¶ms->version_info.chosen_version, p); + if (params->version_info.chosen_version == 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (valuelen > sizeof(uint32_t)) { + params->version_info.available_versions = (uint8_t *)p; + params->version_info.available_versionslen = + (size_t)valuelen - sizeof(uint32_t); + + for (lend = p + (valuelen - sizeof(uint32_t)); p != lend;) { + p = ngtcp2_get_uint32be(&version, p); + if (version == 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + } + } + params->version_info_present = 1; + break; + default: + /* Ignore unknown parameter */ + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + p += valuelen; + break; + } + } + + if (end - p != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + if (transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION) { + ngtcp2_transport_params_convert_to_old(transport_params_version, dest, + params); + } + + return 0; +} + +static int transport_params_copy_new(ngtcp2_transport_params **pdest, + const ngtcp2_transport_params *src, + const ngtcp2_mem *mem) { + size_t len = sizeof(**pdest); + ngtcp2_transport_params *dest; + uint8_t *p; + + if (src->version_info_present) { + len += src->version_info.available_versionslen; + } + + dest = ngtcp2_mem_malloc(mem, len); + if (dest == NULL) { + return NGTCP2_ERR_NOMEM; + } + + *dest = *src; + + if (src->version_info_present && src->version_info.available_versionslen) { + p = (uint8_t *)dest + sizeof(*dest); + memcpy(p, src->version_info.available_versions, + src->version_info.available_versionslen); + dest->version_info.available_versions = p; + } + + *pdest = dest; + + return 0; +} + +int ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams, + const uint8_t *data, size_t datalen, + const ngtcp2_mem *mem) { + int rv; + ngtcp2_transport_params params; + + rv = ngtcp2_transport_params_decode(¶ms, data, datalen); + if (rv < 0) { + return rv; + } + + if (mem == NULL) { + mem = ngtcp2_mem_default(); + } + + return transport_params_copy_new(pparams, ¶ms, mem); +} + +void ngtcp2_transport_params_del(ngtcp2_transport_params *params, + const ngtcp2_mem *mem) { + if (params == NULL) { + return; + } + + if (mem == NULL) { + mem = ngtcp2_mem_default(); + } + + ngtcp2_mem_free(mem, params); +} + +int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest, + const ngtcp2_transport_params *src, + const ngtcp2_mem *mem) { + if (src == NULL) { + *pdest = NULL; + return 0; + } + + return transport_params_copy_new(pdest, src, mem); +} + +static void transport_params_copy(ngtcp2_transport_params *dest, + const ngtcp2_transport_params *src, + int transport_params_version) { + assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_V1: + memcpy(dest, src, + offsetof(ngtcp2_transport_params, version_info_present) + + sizeof(src->version_info_present)); + + break; + } +} + +const ngtcp2_transport_params * +ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest, + int transport_params_version, + const ngtcp2_transport_params *src) { + if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { + return src; + } + + ngtcp2_transport_params_default(dest); + + transport_params_copy(dest, src, transport_params_version); + + return dest; +} + +void ngtcp2_transport_params_convert_to_old( + int transport_params_version, ngtcp2_transport_params *dest, + const ngtcp2_transport_params *src) { + assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); + + transport_params_copy(dest, src, transport_params_version); +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.h similarity index 55% rename from deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.h rename to deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.h index 3457a8f2053aba..c077f06a9dd717 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conversion.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_transport_params.h @@ -22,15 +22,62 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef NGTCP2_CONVERSION_H -#define NGTCP2_CONVERSION_H +#ifndef NGTCP2_TRANSPORT_PARAMS_H +#define NGTCP2_TRANSPORT_PARAMS_H #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include +/* ngtcp2_transport_param_id is the registry of QUIC transport + parameter ID. */ +typedef uint64_t ngtcp2_transport_param_id; + +#define NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID 0x00 +#define NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT 0x01 +#define NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN 0x02 +#define NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE 0x03 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA 0x04 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI 0x07 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI 0x08 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI 0x09 +#define NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT 0x0a +#define NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY 0x0b +#define NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION 0x0c +#define NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS 0x0d +#define NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT 0x0e +#define NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID 0x0f +#define NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID 0x10 +/* https://datatracker.ietf.org/doc/html/rfc9221 */ +#define NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE 0x20 +#define NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT 0x2ab2 +/* https://datatracker.ietf.org/doc/html/rfc9368 */ +#define NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION 0x11 + +/* NGTCP2_MAX_STREAMS is the maximum number of streams. */ +#define NGTCP2_MAX_STREAMS (1LL << 60) + +/* + * ngtcp2_transport_params_copy_new makes a copy of |src|, and assigns + * it to |*pdest|. If |src| is NULL, NULL is assigned to |*pdest|. + * + * Caller is responsible to call ngtcp2_transport_params_del to free + * the memory assigned to |*pdest|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_NOMEM + * Out of memory. + */ +int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest, + const ngtcp2_transport_params *src, + const ngtcp2_mem *mem); + /* * ngtcp2_transport_params_convert_to_latest converts |src| of version * |transport_params_version| to the latest version @@ -68,4 +115,4 @@ void ngtcp2_transport_params_convert_to_old(int transport_params_version, ngtcp2_transport_params *dest, const ngtcp2_transport_params *src); -#endif /* NGTCP2_CONVERSION_H */ +#endif /* !defined(NGTCP2_TRANSPORT_PARAMS_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_tstamp.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_tstamp.h index 9a210a320dc1ca..2b1bb51d87edc6 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_tstamp.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_tstamp.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -65,4 +65,4 @@ static inline int ngtcp2_tstamp_not_elapsed(ngtcp2_tstamp base, return base != UINT64_MAX && (base >= UINT64_MAX - d || base + d > ts); } -#endif /* NGTCP2_TSTAMP_H */ +#endif /* !defined(NGTCP2_TSTAMP_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.c index 7c7d9ae78e914d..5ab1db72cc5384 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.c @@ -26,20 +26,22 @@ #include #include +#include #ifdef HAVE_UNISTD_H +# define NGTCP2_UNREACHABLE_LOG # include -#endif /* HAVE_UNISTD_H */ -#include -#ifdef WIN32 +#elif defined(WIN32) +# define NGTCP2_UNREACHABLE_LOG # include -#endif /* WIN32 */ +#endif /* defined(WIN32) */ void ngtcp2_unreachable_fail(const char *file, int line, const char *func) { +#ifdef NGTCP2_UNREACHABLE_LOG char *buf; size_t buflen; int rv; -#define NGTCP2_UNREACHABLE_TEMPLATE "%s:%d %s: Unreachable.\n" +# define NGTCP2_UNREACHABLE_TEMPLATE "%s:%d %s: Unreachable.\n" rv = snprintf(NULL, 0, NGTCP2_UNREACHABLE_TEMPLATE, file, line, func); if (rv < 0) { @@ -58,14 +60,15 @@ void ngtcp2_unreachable_fail(const char *file, int line, const char *func) { abort(); } -#ifndef WIN32 +# ifndef WIN32 while (write(STDERR_FILENO, buf, (size_t)rv) == -1 && errno == EINTR) ; -#else /* WIN32 */ +# else /* defined(WIN32) */ _write(_fileno(stderr), buf, (unsigned int)rv); -#endif /* WIN32 */ +# endif /* defined(WIN32) */ free(buf); +#endif /* defined(NGTCP2_UNREACHABLE_LOG) */ abort(); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.h index a5276fd505463f..ca7123865279f9 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_unreachable.h @@ -27,26 +27,26 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #ifdef __FILE_NAME__ # define NGTCP2_FILE_NAME __FILE_NAME__ -#else /* !__FILE_NAME__ */ +#else /* !defined(__FILE_NAME__) */ # define NGTCP2_FILE_NAME "(file)" -#endif /* !__FILE_NAME__ */ +#endif /* !defined(__FILE_NAME__) */ #define ngtcp2_unreachable() \ ngtcp2_unreachable_fail(NGTCP2_FILE_NAME, __LINE__, __func__) #ifdef _MSC_VER __declspec(noreturn) -#endif /* _MSC_VER */ +#endif /* defined(_MSC_VER) */ void ngtcp2_unreachable_fail(const char *file, int line, const char *func) #ifndef _MSC_VER __attribute__((noreturn)) -#endif /* !_MSC_VER */ +#endif /* !defined(_MSC_VER) */ ; -#endif /* NGTCP2_UNREACHABLE_H */ +#endif /* !defined(NGTCP2_UNREACHABLE_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c index dbc7b668042695..0b9c92d47d7d88 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c @@ -50,6 +50,7 @@ int ngtcp2_vec_new(ngtcp2_vec **pvec, const uint8_t *data, size_t datalen, p = (uint8_t *)(*pvec) + sizeof(ngtcp2_vec); (*pvec)->base = p; (*pvec)->len = datalen; + if (datalen) { /* p = */ ngtcp2_cpymem(p, data, datalen); } @@ -89,8 +90,8 @@ int64_t ngtcp2_vec_len_varint(const ngtcp2_vec *vec, size_t n) { return (int64_t)res; } -ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *src, size_t *psrccnt, ngtcp2_vec *dst, - size_t *pdstcnt, size_t left, size_t maxcnt) { +ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, + size_t *psrccnt, size_t left, size_t maxcnt) { size_t i; size_t srccnt = *psrccnt; size_t nmove; @@ -203,6 +204,7 @@ size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, } else { dst[(*pdstcnt)++] = *b; } + left -= b->len; } @@ -222,11 +224,14 @@ size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t dstcnt, ++i; continue; } + dst[j] = src[i]; + if (dst[j].len > left) { dst[j].len = left; return j + 1; } + left -= dst[j].len; ++i; ++j; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h index a39c4392fd2627..f7611efcb7d6ce 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -74,19 +74,21 @@ uint64_t ngtcp2_vec_len(const ngtcp2_vec *vec, size_t n); int64_t ngtcp2_vec_len_varint(const ngtcp2_vec *vec, size_t n); /* - * ngtcp2_vec_split splits |src| to |dst| so that the sum of the - * length in |src| does not exceed |left| bytes. The |maxcnt| is the - * maximum number of elements which |dst| array can contain. The - * caller must set |*psrccnt| to the number of elements of |src|. - * Similarly, the caller must set |*pdstcnt| to the number of elements - * of |dst|. The split does not necessarily occur at the boundary of - * ngtcp2_vec object. After split has done, this function updates - * |*psrccnt| and |*pdstcnt|. This function returns the number of - * bytes moved from |src| to |dst|. If split cannot be made because - * doing so exceeds |maxcnt|, this function returns -1. + * ngtcp2_vec_split splits |src| at the data position where + * ngtcp2_vec_len(|src|) does not exceed |left| bytes. The removed + * vectors are moved to |dst|. The existing elements in |dst| are + * moved forward to make up a space. The |maxcnt| is the maximum + * number of elements which |dst| array can contain. The caller must + * set |*psrccnt| to the number of elements of |src|. Similarly, the + * caller must set |*pdstcnt| to the number of elements of |dst|. The + * split does not necessarily occur at the boundary of ngtcp2_vec + * object. After split has done, this function updates |*psrccnt| and + * |*pdstcnt|. This function returns the number of bytes moved from + * |src| to |dst|. If split cannot be made because doing so exceeds + * |maxcnt|, this function returns -1. */ -ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *src, size_t *psrccnt, ngtcp2_vec *dst, - size_t *pdstcnt, size_t left, size_t maxcnt); +ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, + size_t *psrccnt, size_t left, size_t maxcnt); /* * ngtcp2_vec_merge merges |src| into |dst| by moving at most |left| @@ -117,4 +119,4 @@ size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t dstcnt, */ void ngtcp2_vec_copy(ngtcp2_vec *dst, const ngtcp2_vec *src, size_t cnt); -#endif /* NGTCP2_VEC_H */ +#endif /* !defined(NGTCP2_VEC_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_version.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_version.c index b31162c3ebe0d7..d2557e9ef8a580 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_version.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_version.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.h index 50415f10b8c37b..c90a9fdb9078da 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_window_filter.h @@ -37,7 +37,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -62,4 +62,4 @@ void ngtcp2_window_filter_reset(ngtcp2_window_filter *wf, uint64_t new_sample, uint64_t ngtcp2_window_filter_get_best(ngtcp2_window_filter *wf); -#endif /* NGTCP2_WINDOW_FILTER_H */ +#endif /* !defined(NGTCP2_WINDOW_FILTER_H) */