Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2020-06-23 04:04:28 +0300
committerJames M Snell <jasnell@gmail.com>2020-06-24 22:32:49 +0300
commit6b27d07779f95c5d079d4dd4103cc6c9116c1bc6 (patch)
tree67a3cad0415ffdc52673eb2db82be250b391593f /deps
parenta2b1b92e30e98f05808f86ec49899669b8511d0f (diff)
deps: update ngtcp2
PR-URL: https://github.com/nodejs/node/pull/34033 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Diffstat (limited to 'deps')
-rw-r--r--deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h199
-rw-r--r--deps/ngtcp2/crypto/openssl/openssl.c56
-rw-r--r--deps/ngtcp2/crypto/shared.c251
-rw-r--r--deps/ngtcp2/crypto/shared.h96
-rw-r--r--deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h606
-rw-r--r--deps/ngtcp2/lib/includes/ngtcp2/version.h4
-rw-r--r--deps/ngtcp2/lib/includes/ngtcp2/version.h.in45
-rw-r--r--deps/ngtcp2/lib/ngtcp2_acktr.c45
-rw-r--r--deps/ngtcp2/lib/ngtcp2_acktr.h6
-rw-r--r--deps/ngtcp2/lib/ngtcp2_cc.c483
-rw-r--r--deps/ngtcp2/lib/ngtcp2_cc.h117
-rw-r--r--deps/ngtcp2/lib/ngtcp2_conn.c2206
-rw-r--r--deps/ngtcp2/lib/ngtcp2_conn.h137
-rw-r--r--deps/ngtcp2/lib/ngtcp2_crypto.c173
-rw-r--r--deps/ngtcp2/lib/ngtcp2_crypto.h6
-rw-r--r--deps/ngtcp2/lib/ngtcp2_err.c2
-rw-r--r--deps/ngtcp2/lib/ngtcp2_gaptr.c34
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ksl.c177
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ksl.h33
-rw-r--r--deps/ngtcp2/lib/ngtcp2_log.c93
-rw-r--r--deps/ngtcp2/lib/ngtcp2_log.h19
-rw-r--r--deps/ngtcp2/lib/ngtcp2_net.h91
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pipeack.c155
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pipeack.h89
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pkt.c110
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pkt.h17
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ppe.c2
-rw-r--r--deps/ngtcp2/lib/ngtcp2_psl.c621
-rw-r--r--deps/ngtcp2/lib/ngtcp2_psl.h231
-rw-r--r--deps/ngtcp2/lib/ngtcp2_qlog.c61
-rw-r--r--deps/ngtcp2/lib/ngtcp2_qlog.h11
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rcvry.h2
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rob.c48
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rst.c34
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rst.h16
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rtb.c249
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rtb.h52
-rw-r--r--deps/ngtcp2/lib/ngtcp2_strm.c24
-rw-r--r--deps/ngtcp2/ngtcp2.gyp10
39 files changed, 3269 insertions, 3342 deletions
diff --git a/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h b/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
index d405e0d1336..3197c5dcb86 100644
--- a/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
+++ b/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
@@ -175,7 +175,7 @@ ngtcp2_crypto_packet_protection_ivlen(const ngtcp2_crypto_aead *aead);
/**
* @function
*
- * `ngtcp2_crypto_derive_packet_protection_key` dervies packet
+ * `ngtcp2_crypto_derive_packet_protection_key` derives packet
* protection key. This function writes packet protection key into
* the buffer pointed by |key|. |key| must point to the buffer which
* is at least ngtcp2_crypto_aead_keylen(aead) bytes long. This
@@ -237,7 +237,7 @@ ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
* `ngtcp2_crypto_decrypt` decrypts |ciphertext| of length
* |ciphertextlen| and writes the plaintext into the buffer pointed by
* |dest|. The length of plaintext is ciphertextlen -
- * ngtcp2_crypto_aead_taglen(aead) bytes log. |dest| must have enough
+ * ngtcp2_crypto_aead_taglen(aead) bytes long. |dest| must have enough
* capacity to store the plaintext. It is allowed to specify the same
* value to |dest| and |ciphertext|.
*
@@ -298,32 +298,17 @@ NGTCP2_EXTERN int ngtcp2_crypto_hp_mask_cb(uint8_t *dest,
/**
* @function
*
- * `ngtcp2_crypto_derive_and_install_key` derives the rx and tx keys
- * from |rx_secret| and |tx_secret| respectively and installs new keys
- * to |conn|.
+ * `ngtcp2_crypto_derive_and_install_rx_key` derives the rx keys from
+ * |secret| and installs new keys to |conn|.
+ *
+ * If |key| is not NULL, the derived packet protection key for
+ * decryption is written to the buffer pointed by |key|. If |iv| is
+ * not NULL, the derived packet protection IV for decryption is
+ * written to the buffer pointed by |iv|. If |hp| is not NULL, the
+ * derived header protection key for decryption is written to the
+ * buffer pointed by |hp|.
*
- * If |rx_key| is not NULL, the derived packet protection key for
- * decryption is written to the buffer pointed by |rx_key|. If
- * |rx_iv| is not NULL, the derived packet protection IV for
- * decryption is written to the buffer pointed by |rx_iv|. If |rx_hp|
- * is not NULL, the derived header protection key for decryption is
- * written to the buffer pointed by |rx_hp|.
- *
- * If |tx_key| is not NULL, the derived packet protection key for
- * encryption is written to the buffer pointed by |tx_key|. If
- * |tx_iv| is not NULL, the derived packet protection IV for
- * encryption is written to the buffer pointed by |tx_iv|. If |tx_hp|
- * is not NULL, the derived header protection key for encryption is
- * written to the buffer pointed by |tx_hp|.
- *
- * |level| specifies the encryption level. If |level| is
- * NGTCP2_CRYPTO_LEVEL_EARLY, and if |side| is
- * NGTCP2_CRYPTO_SIDE_CLIENT, |rx_secret| must be NULL. If |level| is
- * NGTCP2_CRYPTO_LEVEL_EARLY, and if |side| is
- * NGTCP2_CRYPTO_SIDE_SERVER, |tx_secret| must be NULL. Otherwise,
- * |rx_secret| and |tx_secret| must not be NULL.
- *
- * |secretlen| specifies the length of |rx_secret| and |tx_secret|.
+ * |secretlen| specifies the length of |secret|.
*
* The length of packet protection key and header protection key is
* ngtcp2_crypto_aead(ctx->aead), and the length of packet protection
@@ -337,71 +322,48 @@ NGTCP2_EXTERN int ngtcp2_crypto_hp_mask_cb(uint8_t *dest,
* It also calls `ngtcp2_conn_set_aead_overhead` to set AEAD tag
* length.
*
- * If |level| is NGTCP2_CRYPTO_LEVEL_APP, this function retrieves a
- * remote QUIC transport parameters extension from |tls| and sets it
- * to |conn|.
- *
* This function returns 0 if it succeeds, or -1.
*/
-NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_key(
- ngtcp2_conn *conn, void *tls, uint8_t *rx_key, uint8_t *rx_iv,
- uint8_t *rx_hp, uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp,
- ngtcp2_crypto_level level, const uint8_t *rx_secret,
- const uint8_t *tx_secret, size_t secretlen, ngtcp2_crypto_side side);
+NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_rx_key(
+ ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp,
+ ngtcp2_crypto_level level, const uint8_t *secret, size_t secretlen);
/**
* @function
*
- * `ngtcp2_crypto_derive_and_install_initial_key` derives initial
- * keying materials and installs keys to |conn|.
- *
- * If |rx_secret| is not NULL, the secret for decryption is written to
- * the buffer pointed by |rx_secret|. The length of secret is 32
- * bytes, and |rx_secret| must point to the buffer which has enough
- * capacity.
- *
- * If |tx_secret| is not NULL, the secret for encryption is written to
- * the buffer pointed by |tx_secret|. The length of secret is 32
- * bytes, and |tx_secret| must point to the buffer which has enough
- * capacity.
- *
- * If |initial_secret| is not NULL, the initial secret is written to
- * the buffer pointed by |initial_secret|. The length of secret is 32
- * bytes, and |initial_secret| must point to the buffer which has
- * enough capacity.
- *
- * |client_dcid| is the destination connection ID in first Initial
- * packet of client.
- *
- * If |rx_key| is not NULL, the derived packet protection key for
- * decryption is written to the buffer pointed by |rx_key|. If
- * |rx_iv| is not NULL, the derived packet protection IV for
- * decryption is written to the buffer pointed by |rx_iv|. If |rx_hp|
- * is not NULL, the derived header protection key for decryption is
- * written to the buffer pointed by |rx_hp|.
- *
- * If |tx_key| is not NULL, the derived packet protection key for
- * encryption is written to the buffer pointed by |tx_key|. If
- * |tx_iv| is not NULL, the derived packet protection IV for
- * encryption is written to the buffer pointed by |tx_iv|. If |tx_hp|
- * is not NULL, the derived header protection key for encryption is
- * written to the buffer pointed by |tx_hp|.
- *
- * The length of packet protection key and header protection key is 16
- * bytes long. The length of packet protection IV is 12 bytes long.
- *
- * This function calls `ngtcp2_conn_set_initial_crypto_ctx` to set
- * initial AEAD and message digest algorithm. After the successful
- * call of this function, application can use
- * `ngtcp2_conn_get_initial_crypto_ctx` to get the object.
+ * `ngtcp2_crypto_derive_and_install_tx_key` derives the tx keys from
+ * |secret| and installs new keys to |conn|.
+ *
+ * If |key| is not NULL, the derived packet protection key for
+ * encryption is written to the buffer pointed by |key|. If |iv| is
+ * not NULL, the derived packet protection IV for encryption is
+ * written to the buffer pointed by |iv|. If |hp| is not NULL, the
+ * derived header protection key for encryption is written to the
+ * buffer pointed by |hp|.
+ *
+ * |secretlen| specifies the length of |secret|.
+ *
+ * The length of packet protection key and header protection key is
+ * ngtcp2_crypto_aead(ctx->aead), and the length of packet protection
+ * IV is ngtcp2_crypto_packet_protection_ivlen(ctx->aead) where ctx
+ * can be obtained by `ngtcp2_crypto_ctx_tls`.
+ *
+ * In the first call of this function, it calls
+ * `ngtcp2_conn_set_crypto_ctx` to set negotiated AEAD and message
+ * digest algorithm. After the successful call of this function,
+ * application can use `ngtcp2_conn_get_crypto_ctx` to get the object.
+ * It also calls `ngtcp2_conn_set_aead_overhead` to set AEAD tag
+ * length.
+ *
+ * If |level| is NGTCP2_CRYPTO_LEVEL_APP, this function retrieves a
+ * remote QUIC transport parameters extension from |tls| and sets it
+ * to |conn|.
*
* This function returns 0 if it succeeds, or -1.
*/
-NGTCP2_EXTERN 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,
- const ngtcp2_cid *client_dcid, ngtcp2_crypto_side side);
+NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_tx_key(
+ ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp,
+ ngtcp2_crypto_level level, const uint8_t *secret, size_t secretlen);
/**
* @function
@@ -461,6 +423,54 @@ NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb(
/**
* @function
*
+ * `ngtcp2_crypto_client_initial_cb` installs initial secrets and
+ * encryption keys and sets QUIC transport parameters.
+ *
+ * This function can be directly passed to client_initial field in
+ * ngtcp2_callbacks. It is only used by client.
+ *
+ * This function returns 0 if it succeeds, or
+ * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
+ */
+NGTCP2_EXTERN int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn,
+ void *user_data);
+
+/**
+ * @function
+ *
+ * `ngtcp2_crypto_recv_retry_cb` re-installs initial secrets in
+ * response to incoming Retry packet.
+ *
+ * This function can be directly passed to recv_retry field in
+ * ngtcp2_callbacks. It is only used by client.
+ *
+ * This function returns 0 if it succeeds, or
+ * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
+ */
+NGTCP2_EXTERN int ngtcp2_crypto_recv_retry_cb(ngtcp2_conn *conn,
+ const ngtcp2_pkt_hd *hd,
+ void *user_data);
+
+/**
+ * @function
+ *
+ * `ngtcp2_crypto_recv_client_initial_cb` installs initial secrets in
+ * response to an incoming Initial packet from client, and sets QUIC
+ * transport parameters.
+ *
+ * This function can be directly passed to recv_client_initial field
+ * in ngtcp2_callbacks. It is only used by server.
+ *
+ * This function returns 0 if it succeeds, or
+ * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
+ */
+NGTCP2_EXTERN int ngtcp2_crypto_recv_client_initial_cb(ngtcp2_conn *conn,
+ const ngtcp2_cid *dcid,
+ void *user_data);
+
+/**
+ * @function
+ *
* `ngtcp2_crypto_read_write_crypto_data` reads CRYPTO data |data| of
* length |datalen| in encryption level |crypto_level| and may feed
* outgoing CRYPTO data to |conn|. This function can drive handshake.
@@ -468,10 +478,6 @@ NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb(
* allowed to call this function with datalen == 0. In this case, no
* additional read operation is done.
*
- * |tls| points to a implementation dependent TLS session object. If
- * libngtcp2_crypto_openssl is linked, |tls| must be a pointer to SSL
- * object.
- *
* This function returns 0 if it succeeds, or a negative error code.
* The generic error code is -1 if a specific error code is not
* suitable. The error codes less than -10000 are specific to
@@ -479,30 +485,13 @@ NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb(
* defined in ngtcp2_crypto_openssl.h.
*/
NGTCP2_EXTERN int
-ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, void *tls,
+ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn,
ngtcp2_crypto_level crypto_level,
const uint8_t *data, size_t datalen);
/**
* @function
*
- * `ngtcp2_crypto_set_remote_transport_params` retrieves a remote QUIC
- * transport parameters from |tls| and sets it to |conn| using
- * `ngtcp2_conn_set_remote_transport_params`.
- *
- * |tls| points to a implementation dependent TLS session object. If
- * libngtcp2_crypto_openssl is linked, |tls| must be a pointer to SSL
- * object.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int
-ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls,
- ngtcp2_crypto_side side);
-
-/**
- * @function
- *
* `ngtcp2_crypto_generate_stateless_reset_token` generates a
* stateless reset token using HKDF extraction with |md| using the
* given |cid| and static key |secret| as input. The token will be
diff --git a/deps/ngtcp2/crypto/openssl/openssl.c b/deps/ngtcp2/crypto/openssl/openssl.c
index 5e6a8493074..60e7250eae9 100644
--- a/deps/ngtcp2/crypto/openssl/openssl.c
+++ b/deps/ngtcp2/crypto/openssl/openssl.c
@@ -35,10 +35,14 @@
#include <openssl/evp.h>
#include <openssl/kdf.h>
+#include "shared.h"
+
ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx) {
ctx->aead.native_handle = (void *)EVP_aes_128_gcm();
ctx->md.native_handle = (void *)EVP_sha256();
ctx->hp.native_handle = (void *)EVP_aes_128_ctr();
+ ctx->max_encryption = 0;
+ ctx->max_decryption_failure = 0;
return ctx;
}
@@ -62,6 +66,34 @@ static const EVP_CIPHER *crypto_ssl_get_aead(SSL *ssl) {
}
}
+static uint64_t crypto_ssl_get_aead_max_encryption(SSL *ssl) {
+ switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
+ case TLS1_3_CK_AES_128_GCM_SHA256:
+ case TLS1_3_CK_AES_256_GCM_SHA384:
+ return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM;
+ case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
+ return NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305;
+ case TLS1_3_CK_AES_128_CCM_SHA256:
+ return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_CCM;
+ default:
+ return 0;
+ }
+}
+
+static uint64_t crypto_ssl_get_aead_max_decryption_failure(SSL *ssl) {
+ switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
+ case TLS1_3_CK_AES_128_GCM_SHA256:
+ case TLS1_3_CK_AES_256_GCM_SHA384:
+ return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM;
+ case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
+ return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305;
+ case TLS1_3_CK_AES_128_CCM_SHA256:
+ return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_CCM;
+ default:
+ return 0;
+ }
+}
+
static const EVP_CIPHER *crypto_ssl_get_hp(SSL *ssl) {
switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
case TLS1_3_CK_AES_128_GCM_SHA256:
@@ -95,6 +127,8 @@ ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx,
ctx->aead.native_handle = (void *)crypto_ssl_get_aead(ssl);
ctx->md.native_handle = (void *)crypto_ssl_get_md(ssl);
ctx->hp.native_handle = (void *)crypto_ssl_get_hp(ssl);
+ ctx->max_encryption = crypto_ssl_get_aead_max_encryption(ssl);
+ ctx->max_decryption_failure = crypto_ssl_get_aead_max_decryption_failure(ssl);
return ctx;
}
@@ -313,10 +347,10 @@ from_ngtcp2_level(ngtcp2_crypto_level crypto_level) {
}
}
-int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, void *tls,
+int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn,
ngtcp2_crypto_level crypto_level,
const uint8_t *data, size_t datalen) {
- SSL *ssl = tls;
+ SSL *ssl = ngtcp2_conn_get_tls_native_handle(conn);
int rv;
int err;
@@ -365,13 +399,12 @@ int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, void *tls,
return 0;
}
-int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls,
- ngtcp2_crypto_side side) {
+int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls) {
SSL *ssl = tls;
ngtcp2_transport_params_type exttype =
- side == NGTCP2_CRYPTO_SIDE_CLIENT
- ? NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS
- : NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO;
+ ngtcp2_conn_is_server(conn)
+ ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO
+ : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS;
const uint8_t *tp;
size_t tplen;
ngtcp2_transport_params params;
@@ -393,3 +426,12 @@ int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls,
return 0;
}
+
+int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf,
+ size_t len) {
+ if (SSL_set_quic_transport_params(tls, buf, len) != 1) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/deps/ngtcp2/crypto/shared.c b/deps/ngtcp2/crypto/shared.c
index 6304e59639d..bea088e85f3 100644
--- a/deps/ngtcp2/crypto/shared.c
+++ b/deps/ngtcp2/crypto/shared.c
@@ -145,37 +145,32 @@ int ngtcp2_crypto_update_traffic_secret(uint8_t *dest,
return 0;
}
-int ngtcp2_crypto_derive_and_install_key(
- ngtcp2_conn *conn, void *tls, 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,
- ngtcp2_crypto_level level, const uint8_t *rx_secret,
- const uint8_t *tx_secret, size_t secretlen, ngtcp2_crypto_side side) {
+int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key,
+ uint8_t *iv, uint8_t *hp_key,
+ ngtcp2_crypto_level level,
+ const uint8_t *secret,
+ size_t secretlen) {
const ngtcp2_crypto_ctx *ctx;
const ngtcp2_crypto_aead *aead;
const ngtcp2_crypto_md *md;
- uint8_t rx_keybuf[64], rx_ivbuf[64], rx_hp_keybuf[64];
- uint8_t tx_keybuf[64], tx_ivbuf[64], tx_hp_keybuf[64];
+ void *tls = ngtcp2_conn_get_tls_native_handle(conn);
+ uint8_t keybuf[64], ivbuf[64], hp_keybuf[64];
size_t keylen;
size_t ivlen;
int rv;
- if (!rx_key) {
- rx_key = rx_keybuf;
- }
- if (!rx_iv) {
- rx_iv = rx_ivbuf;
- }
- if (!rx_hp_key) {
- rx_hp_key = rx_hp_keybuf;
+ if (level == NGTCP2_CRYPTO_LEVEL_EARLY && !ngtcp2_conn_is_server(conn)) {
+ return 0;
}
- if (!tx_key) {
- tx_key = tx_keybuf;
+
+ if (!key) {
+ key = keybuf;
}
- if (!tx_iv) {
- tx_iv = tx_ivbuf;
+ if (!iv) {
+ iv = ivbuf;
}
- if (!tx_hp_key) {
- tx_hp_key = tx_hp_keybuf;
+ if (!hp_key) {
+ hp_key = hp_keybuf;
}
ctx = ngtcp2_conn_get_crypto_ctx(conn);
@@ -193,50 +188,119 @@ int ngtcp2_crypto_derive_and_install_key(
keylen = ngtcp2_crypto_aead_keylen(aead);
ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
- if ((level != NGTCP2_CRYPTO_LEVEL_EARLY ||
- side == NGTCP2_CRYPTO_SIDE_SERVER) &&
- ngtcp2_crypto_derive_packet_protection_key(
- rx_key, rx_iv, rx_hp_key, aead, md, rx_secret, secretlen) != 0) {
- return -1;
- }
-
- if ((level != NGTCP2_CRYPTO_LEVEL_EARLY ||
- side == NGTCP2_CRYPTO_SIDE_CLIENT) &&
- ngtcp2_crypto_derive_packet_protection_key(
- tx_key, tx_iv, tx_hp_key, aead, md, tx_secret, secretlen) != 0) {
+ if (ngtcp2_crypto_derive_packet_protection_key(key, iv, hp_key, aead, md,
+ secret, secretlen) != 0) {
return -1;
}
switch (level) {
case NGTCP2_CRYPTO_LEVEL_EARLY:
- if (side == NGTCP2_CRYPTO_SIDE_CLIENT) {
- rv = ngtcp2_conn_install_early_key(conn, tx_key, tx_iv, tx_hp_key, keylen,
- ivlen);
- } else {
- rv = ngtcp2_conn_install_early_key(conn, rx_key, rx_iv, rx_hp_key, keylen,
- ivlen);
- }
+ rv = ngtcp2_conn_install_early_key(conn, key, iv, hp_key, keylen, ivlen);
if (rv != 0) {
return -1;
}
break;
case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
- rv = ngtcp2_conn_install_handshake_key(conn, rx_key, rx_iv, rx_hp_key,
- tx_key, tx_iv, tx_hp_key, keylen,
- ivlen);
+ rv = ngtcp2_conn_install_rx_handshake_key(conn, key, iv, hp_key, keylen,
+ ivlen);
if (rv != 0) {
return -1;
}
break;
case NGTCP2_CRYPTO_LEVEL_APP:
- rv = ngtcp2_crypto_set_remote_transport_params(conn, tls, side);
+ if (!ngtcp2_conn_is_server(conn)) {
+ rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
+ if (rv != 0) {
+ return -1;
+ }
+ }
+
+ rv = ngtcp2_conn_install_rx_key(conn, secret, key, iv, hp_key, secretlen,
+ keylen, ivlen);
if (rv != 0) {
return -1;
}
- rv = ngtcp2_conn_install_key(conn, rx_secret, tx_secret, rx_key, rx_iv,
- rx_hp_key, tx_key, tx_iv, tx_hp_key, secretlen,
- keylen, ivlen);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key,
+ uint8_t *iv, uint8_t *hp_key,
+ ngtcp2_crypto_level level,
+ const uint8_t *secret,
+ size_t secretlen) {
+ const ngtcp2_crypto_ctx *ctx;
+ const ngtcp2_crypto_aead *aead;
+ const ngtcp2_crypto_md *md;
+ void *tls = ngtcp2_conn_get_tls_native_handle(conn);
+ uint8_t keybuf[64], ivbuf[64], hp_keybuf[64];
+ size_t keylen;
+ size_t ivlen;
+ int rv;
+
+ if (level == NGTCP2_CRYPTO_LEVEL_EARLY && ngtcp2_conn_is_server(conn)) {
+ return 0;
+ }
+
+ if (!key) {
+ key = keybuf;
+ }
+ if (!iv) {
+ iv = ivbuf;
+ }
+ if (!hp_key) {
+ hp_key = hp_keybuf;
+ }
+
+ ctx = ngtcp2_conn_get_crypto_ctx(conn);
+
+ if (!ctx->aead.native_handle) {
+ ngtcp2_crypto_ctx cctx;
+ ngtcp2_crypto_ctx_tls(&cctx, tls);
+ ngtcp2_conn_set_aead_overhead(conn, ngtcp2_crypto_aead_taglen(&cctx.aead));
+ ngtcp2_conn_set_crypto_ctx(conn, &cctx);
+ ctx = ngtcp2_conn_get_crypto_ctx(conn);
+ }
+
+ aead = &ctx->aead;
+ md = &ctx->md;
+ keylen = ngtcp2_crypto_aead_keylen(aead);
+ ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
+
+ if (ngtcp2_crypto_derive_packet_protection_key(key, iv, hp_key, aead, md,
+ secret, secretlen) != 0) {
+ return -1;
+ }
+
+ switch (level) {
+ case NGTCP2_CRYPTO_LEVEL_EARLY:
+ rv = ngtcp2_conn_install_early_key(conn, key, iv, hp_key, keylen, ivlen);
+ if (rv != 0) {
+ return -1;
+ }
+ break;
+ case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
+ if (ngtcp2_conn_is_server(conn)) {
+ rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
+ if (rv != 0) {
+ return -1;
+ }
+ }
+
+ rv = ngtcp2_conn_install_tx_handshake_key(conn, key, iv, hp_key, keylen,
+ ivlen);
+ if (rv != 0) {
+ return -1;
+ }
+ break;
+ case NGTCP2_CRYPTO_LEVEL_APP:
+ rv = ngtcp2_conn_install_tx_key(conn, secret, key, iv, hp_key, secretlen,
+ keylen, ivlen);
if (rv != 0) {
return -1;
}
@@ -253,7 +317,7 @@ 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,
- const ngtcp2_cid *client_dcid, ngtcp2_crypto_side side) {
+ 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];
@@ -300,8 +364,10 @@ 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,
- client_dcid, side) != 0) {
+ if (ngtcp2_crypto_derive_initial_secrets(
+ rx_secret, tx_secret, initial_secret, client_dcid,
+ ngtcp2_conn_is_server(conn) ? NGTCP2_CRYPTO_SIDE_SERVER
+ : NGTCP2_CRYPTO_SIDE_CLIENT) != 0) {
return -1;
}
@@ -486,3 +552,90 @@ ngtcp2_ssize ngtcp2_crypto_write_retry(uint8_t *dest, size_t destlen,
return spktlen;
}
+
+/*
+ * crypto_set_local_transport_params gets local QUIC transport
+ * parameters from |conn| and sets it to |tls|.
+ *
+ * This function returns 0 if it succeeds, or -1.
+ */
+static int crypto_set_local_transport_params(ngtcp2_conn *conn, void *tls) {
+ ngtcp2_transport_params_type exttype =
+ ngtcp2_conn_is_server(conn)
+ ? NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS
+ : NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO;
+ ngtcp2_transport_params params;
+ ngtcp2_ssize nwrite;
+ uint8_t buf[256];
+
+ ngtcp2_conn_get_local_transport_params(conn, &params);
+
+ nwrite = ngtcp2_encode_transport_params(buf, sizeof(buf), exttype, &params);
+ if (nwrite < 0) {
+ return -1;
+ }
+
+ if (ngtcp2_crypto_set_local_transport_params(tls, buf, (size_t)nwrite) != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * crypto_setup_initial_crypto establishes the initial secrets and
+ * encryption keys, and prepares local QUIC transport parameters.
+ */
+static int crypto_setup_initial_crypto(ngtcp2_conn *conn,
+ const ngtcp2_cid *dcid) {
+ void *tls = ngtcp2_conn_get_tls_native_handle(conn);
+
+ if (ngtcp2_crypto_derive_and_install_initial_key(conn, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ dcid) != 0) {
+ return -1;
+ }
+
+ return crypto_set_local_transport_params(conn, tls);
+}
+
+int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn, void *user_data) {
+ const ngtcp2_cid *dcid = ngtcp2_conn_get_dcid(conn);
+ (void)user_data;
+
+ if (crypto_setup_initial_crypto(conn, dcid) != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ if (ngtcp2_crypto_read_write_crypto_data(conn, NGTCP2_CRYPTO_LEVEL_INITIAL,
+ NULL, 0) != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+int ngtcp2_crypto_recv_retry_cb(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
+ void *user_data) {
+ (void)user_data;
+
+ if (ngtcp2_crypto_derive_and_install_initial_key(conn, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ &hd->scid) != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+int ngtcp2_crypto_recv_client_initial_cb(ngtcp2_conn *conn,
+ const ngtcp2_cid *dcid,
+ void *user_data) {
+ (void)user_data;
+
+ if (crypto_setup_initial_crypto(conn, dcid) != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
diff --git a/deps/ngtcp2/crypto/shared.h b/deps/ngtcp2/crypto/shared.h
index 87f3d8928f0..a904f6994fb 100644
--- a/deps/ngtcp2/crypto/shared.h
+++ b/deps/ngtcp2/crypto/shared.h
@@ -31,6 +31,16 @@
#include <ngtcp2/ngtcp2_crypto.h>
+/* Maximum key usage (encryption) limits */
+#define NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM (23726566ULL)
+#define NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305 (1ULL << 62)
+#define NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_CCM (1ULL << 23)
+
+/* Maximum authentication failure (decryption) limits */
+#define NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM (1ULL << 36)
+#define NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305 (1ULL << 36)
+#define NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_CCM (11863283ULL)
+
/**
* @function
*
@@ -69,4 +79,90 @@ int ngtcp2_crypto_update_traffic_secret(uint8_t *dest,
const uint8_t *secret,
size_t secretlen);
+/**
+ * @function
+ *
+ * `ngtcp2_crypto_set_local_transport_params` sets QUIC transport
+ * parameter, which is encoded in wire format and stored in the buffer
+ * pointed by |buf| of length |len|, to the native handle |tls|.
+ *
+ * |tls| points to a implementation dependent TLS session object. If
+ * libngtcp2_crypto_openssl is linked, |tls| must be a pointer to SSL
+ * object.
+ *
+ * This function returns 0 if it succeeds, or -1.
+ */
+int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf,
+ size_t len);
+
+/**
+ * @function
+ *
+ * `ngtcp2_crypto_set_remote_transport_params` retrieves a remote QUIC
+ * transport parameters from |tls| and sets it to |conn| using
+ * `ngtcp2_conn_set_remote_transport_params`.
+ *
+ * |tls| points to a implementation dependent TLS session object. If
+ * libngtcp2_crypto_openssl is linked, |tls| must be a pointer to SSL
+ * object.
+ *
+ * This function returns 0 if it succeeds, or -1.
+ */
+int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls);
+
+
+/**
+ * @function
+ *
+ * `ngtcp2_crypto_derive_and_install_initial_key` derives initial
+ * keying materials and installs keys to |conn|.
+ *
+ * If |rx_secret| is not NULL, the secret for decryption is written to
+ * the buffer pointed by |rx_secret|. The length of secret is 32
+ * bytes, and |rx_secret| must point to the buffer which has enough
+ * capacity.
+ *
+ * If |tx_secret| is not NULL, the secret for encryption is written to
+ * the buffer pointed by |tx_secret|. The length of secret is 32
+ * bytes, and |tx_secret| must point to the buffer which has enough
+ * capacity.
+ *
+ * If |initial_secret| is not NULL, the initial secret is written to
+ * the buffer pointed by |initial_secret|. The length of secret is 32
+ * bytes, and |initial_secret| must point to the buffer which has
+ * enough capacity.
+ *
+ * |client_dcid| is the destination connection ID in first Initial
+ * packet of client.
+ *
+ * If |rx_key| is not NULL, the derived packet protection key for
+ * decryption is written to the buffer pointed by |rx_key|. If
+ * |rx_iv| is not NULL, the derived packet protection IV for
+ * decryption is written to the buffer pointed by |rx_iv|. If |rx_hp|
+ * is not NULL, the derived header protection key for decryption is
+ * written to the buffer pointed by |rx_hp|.
+ *
+ * If |tx_key| is not NULL, the derived packet protection key for
+ * encryption is written to the buffer pointed by |tx_key|. If
+ * |tx_iv| is not NULL, the derived packet protection IV for
+ * encryption is written to the buffer pointed by |tx_iv|. If |tx_hp|
+ * is not NULL, the derived header protection key for encryption is
+ * written to the buffer pointed by |tx_hp|.
+ *
+ * The length of packet protection key and header protection key is 16
+ * bytes long. The length of packet protection IV is 12 bytes long.
+ *
+ * This function calls `ngtcp2_conn_set_initial_crypto_ctx` to set
+ * initial AEAD and message digest algorithm. After the successful
+ * call of this function, application can use
+ * `ngtcp2_conn_get_initial_crypto_ctx` to get the object.
+ *
+ * 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,
+ const ngtcp2_cid *client_dcid);
+
#endif /* NGTCP2_SHARED_H */
diff --git a/deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h b/deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
index a2f7d67a5ce..29cf3e54250 100644
--- a/deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
+++ b/deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
@@ -159,16 +159,11 @@ typedef struct ngtcp2_mem {
} ngtcp2_mem;
/* NGTCP2_PROTO_VER is the supported QUIC protocol version. */
-#define NGTCP2_PROTO_VER 0xff00001bu
+#define NGTCP2_PROTO_VER 0xff00001du
/* NGTCP2_PROTO_VER_MAX is the highest QUIC version the library
supports. */
#define NGTCP2_PROTO_VER_MAX NGTCP2_PROTO_VER
-/* NGTCP2_ALPN_H3 is a serialized form of HTTP/3 ALPN protocol
- identifier this library supports. Notice that the first byte is
- the length of the following protocol identifier. */
-#define NGTCP2_ALPN_H3 "\x5h3-27"
-
#define NGTCP2_MAX_PKTLEN_IPV4 1252
#define NGTCP2_MAX_PKTLEN_IPV6 1232
@@ -176,6 +171,11 @@ typedef struct ngtcp2_mem {
packet sent by client which contains its first Initial packet. */
#define NGTCP2_MIN_INITIAL_PKTLEN 1200
+/* NGTCP2_DEFAULT_MAX_PKTLEN is the default maximum size of UDP
+ datagram payload that this endpoint transmits. It is used by
+ congestion controller to compute congestion window. */
+#define NGTCP2_DEFAULT_MAX_PKTLEN 1200
+
/* NGTCP2_STATELESS_RESET_TOKENLEN is the length of Stateless Reset
Token. */
#define NGTCP2_STATELESS_RESET_TOKENLEN 16
@@ -187,8 +187,8 @@ typedef struct ngtcp2_mem {
/* NGTCP2_INITIAL_SALT is a salt value which is used to derive initial
secret. */
#define NGTCP2_INITIAL_SALT \
- "\xc3\xee\xf7\x12\xc7\x2e\xbb\x5a\x11\xa7\xd2\x43\x2b\xb4\x63\x65\xbe\xf9" \
- "\xf5\x02"
+ "\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97\x86\xf1\x9c\x61\x11\xe0\x43\x90" \
+ "\xa8\x99"
/* NGTCP2_HP_MASKLEN is the length of header protection mask. */
#define NGTCP2_HP_MASKLEN 5
@@ -250,6 +250,7 @@ typedef enum ngtcp2_lib_error {
NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED = -239,
NGTCP2_ERR_WRITE_STREAM_MORE = -240,
NGTCP2_ERR_RETRY = -241,
+ NGTCP2_ERR_DROP_CONN = -242,
NGTCP2_ERR_FATAL = -500,
NGTCP2_ERR_NOMEM = -501,
NGTCP2_ERR_CALLBACK_FAILURE = -502,
@@ -280,7 +281,7 @@ typedef enum ngtcp2_pkt_type {
/* QUIC transport error code. */
#define NGTCP2_NO_ERROR 0x0u
#define NGTCP2_INTERNAL_ERROR 0x1u
-#define NGTCP2_SERVER_BUSY 0x2u
+#define NGTCP2_CONNECTION_REFUSED 0x2u
#define NGTCP2_FLOW_CONTROL_ERROR 0x3u
#define NGTCP2_STREAM_LIMIT_ERROR 0x4u
#define NGTCP2_STREAM_STATE_ERROR 0x5u
@@ -290,6 +291,7 @@ typedef enum ngtcp2_pkt_type {
#define NGTCP2_CONNECTION_ID_LIMIT_ERROR 0x9u
#define NGTCP2_PROTOCOL_VIOLATION 0xau
#define NGTCP2_INVALID_TOKEN 0xbu
+#define NGTCP2_APPLICATION_ERROR 0xcu
#define NGTCP2_CRYPTO_BUFFER_EXCEEDED 0xdu
#define NGTCP2_KEY_UPDATE_ERROR 0xeu
#define NGTCP2_CRYPTO_ERROR 0x100u
@@ -304,13 +306,12 @@ typedef enum ngtcp2_path_validation_result {
} ngtcp2_path_validation_result;
/*
- * ngtcp2_tstamp is a timestamp with NGTCP2_DURATION_TICK resolution.
+ * ngtcp2_tstamp is a timestamp with nanosecond resolution.
*/
typedef uint64_t ngtcp2_tstamp;
/*
- * ngtcp2_duration is a period of time in NGTCP2_DURATION_TICK
- * resolution.
+ * ngtcp2_duration is a period of time in nanosecond resolution.
*/
typedef uint64_t ngtcp2_duration;
@@ -319,6 +320,11 @@ typedef uint64_t ngtcp2_duration;
/* NGTCP2_MIN_CIDLEN is the minimum length of Connection ID. */
#define NGTCP2_MIN_CIDLEN 1
+/* NGTCP2_MIN_INITIAL_DCIDLEN is the minimum length of Destination
+ Connection ID in Client Initial packet if it does not bear token
+ from Retry packet. */
+#define NGTCP2_MIN_INITIAL_DCIDLEN 8
+
/**
* @struct
*
@@ -358,8 +364,7 @@ typedef struct ngtcp2_pkt_hd {
ngtcp2_cid dcid;
ngtcp2_cid scid;
int64_t pkt_num;
- uint8_t *token;
- size_t tokenlen;
+ ngtcp2_vec token;
/**
* pkt_numlen is the number of bytes spent to encode pkt_num.
*/
@@ -380,25 +385,15 @@ typedef struct ngtcp2_pkt_stateless_reset {
size_t randlen;
} ngtcp2_pkt_stateless_reset;
-/* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */
-#define NGTCP2_RETRY_TAGLEN 16
-
-typedef struct ngtcp2_pkt_retry {
- ngtcp2_cid odcid;
- const uint8_t *token;
- size_t tokenlen;
- uint8_t tag[NGTCP2_RETRY_TAGLEN];
-} ngtcp2_pkt_retry;
-
#if defined(__cplusplus) && __cplusplus >= 201103L
-typedef enum ngtcp2_transport_param_id : uint16_t {
+typedef enum ngtcp2_transport_param_id : int {
#else
typedef enum ngtcp2_transport_param_id {
#endif
- NGTCP2_TRANSPORT_PARAM_ORIGINAL_CONNECTION_ID = 0x0000,
+ NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID = 0x0000,
NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT = 0x0001,
NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN = 0x0002,
- NGTCP2_TRANSPORT_PARAM_MAX_PACKET_SIZE = 0x0003,
+ NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE = 0x0003,
NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA = 0x0004,
NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL = 0x0005,
NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE = 0x0006,
@@ -410,7 +405,8 @@ typedef enum ngtcp2_transport_param_id {
NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION = 0x000c,
NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS = 0x000d,
NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT = 0x000e,
- NGTCP2_TRANSPORT_PARAM_ID_MAX = UINT16_MAX
+ NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID = 0x000f,
+ NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID = 0x0010
} ngtcp2_transport_param_id;
#if defined(__cplusplus) && __cplusplus >= 201103L
@@ -440,7 +436,11 @@ typedef enum ngtcp2_rand_ctx {
NGTCP2_RAND_CTX_PATH_CHALLENGE
} ngtcp2_rand_ctx;
-#define NGTCP2_MAX_PKT_SIZE 65527
+/*
+ * NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE is the default value of
+ * max_udp_payload_size transport parameter.
+ */
+#define NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE 65527
/**
* @macro
@@ -486,11 +486,28 @@ typedef struct ngtcp2_preferred_addr {
typedef struct ngtcp2_transport_params {
ngtcp2_preferred_addr preferred_address;
- /* original_connection_id is the client initial connection ID.
- Server must specify this field and set
- original_connection_id_present to nonzero if it sent Retry
- packet. */
- ngtcp2_cid original_connection_id;
+ /* original_dcid is the Destination Connection ID field from the
+ first Initial packet from client. Server must specify this
+ field. If application specifies retry_scid_present to nonzero,
+ then it must also specify this field. It is expected that
+ application knows the original Destination Connection ID, for
+ example, by including it in retry token. Otherwise, application
+ should not specify this field. */
+ ngtcp2_cid original_dcid;
+ /* initial_scid is the Source Connection ID field from the first
+ Initial packet the endpoint sends. Application should not
+ specify this field. */
+ ngtcp2_cid initial_scid;
+ /* retry_scid is the Source Connection ID field from Retry packet.
+ Only server uses this field. If server application received
+ Initial packet with retry token from client and server verified
+ its token, server application must set Destination Connection ID
+ field from the Initial packet to this field and set
+ retry_scid_present to nonzero. Server application must verify
+ that the Destination Connection ID from Initial packet was sent
+ in Retry packet by, for example, including the Connection ID in a
+ token, or including it in AAD when encrypting a token. */
+ ngtcp2_cid retry_scid;
/* initial_max_stream_data_bidi_local is the size of flow control
window of locally initiated stream. This is the number of bytes
that the remote endpoint can send and the local endpoint must
@@ -517,7 +534,7 @@ typedef struct ngtcp2_transport_params {
/* max_idle_timeout is a duration during which sender allows
quiescent. */
ngtcp2_duration max_idle_timeout;
- uint64_t max_packet_size;
+ uint64_t max_udp_payload_size;
/* active_connection_id_limit is the maximum number of Connection ID
that sender can store. */
uint64_t active_connection_id_limit;
@@ -525,11 +542,138 @@ typedef struct ngtcp2_transport_params {
ngtcp2_duration max_ack_delay;
uint8_t stateless_reset_token_present;
uint8_t disable_active_migration;
- uint8_t original_connection_id_present;
+ uint8_t retry_scid_present;
uint8_t preferred_address_present;
uint8_t stateless_reset_token[NGTCP2_STATELESS_RESET_TOKENLEN];
} ngtcp2_transport_params;
+typedef struct ngtcp2_log ngtcp2_log;
+
+typedef enum ngtcp2_pktns_id {
+ /* NGTCP2_PKTNS_ID_INITIAL is the Initial packet number space. */
+ NGTCP2_PKTNS_ID_INITIAL,
+ /* NGTCP2_PKTNS_ID_INITIAL is the Handshake packet number space. */
+ NGTCP2_PKTNS_ID_HANDSHAKE,
+ /* NGTCP2_PKTNS_ID_INITIAL is the Application data packet number
+ space. */
+ NGTCP2_PKTNS_ID_APP,
+ /* NGTCP2_PKTNS_ID_MAX is defined to get the number of packet number
+ spaces. */
+ NGTCP2_PKTNS_ID_MAX
+} ngtcp2_pktns_id;
+
+/**
+ * @struct
+ *
+ * ngtcp2_conn_stat holds various connection statistics, and computed
+ * data for recovery and congestion controller.
+ */
+typedef struct ngtcp2_conn_stat {
+ ngtcp2_duration latest_rtt;
+ ngtcp2_duration min_rtt;
+ ngtcp2_duration smoothed_rtt;
+ ngtcp2_duration rttvar;
+ size_t pto_count;
+ ngtcp2_tstamp loss_detection_timer;
+ /* last_tx_pkt_ts corresponds to
+ time_of_last_sent_ack_eliciting_packet in
+ draft-ietf-quic-recovery-25. */
+ ngtcp2_tstamp last_tx_pkt_ts[NGTCP2_PKTNS_ID_MAX];
+ ngtcp2_tstamp loss_time[NGTCP2_PKTNS_ID_MAX];
+ uint64_t cwnd;
+ uint64_t ssthresh;
+ ngtcp2_tstamp congestion_recovery_start_ts;
+ uint64_t bytes_in_flight;
+ /* max_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. */
+ size_t max_udp_payload_size;
+ /* bytes_sent is the number of bytes sent in this particular
+ connection. It only includes data written by
+ `ngtcp2_conn_writev_stream()` .*/
+ uint64_t bytes_sent;
+ /* bytes_recv is the number of bytes received in this particular
+ connection, including discarded packets. */
+ uint64_t bytes_recv;
+ /* delivery_rate_sec is the current sending rate measured per
+ second. */
+ uint64_t delivery_rate_sec;
+ /* recv_rate_sec is the current receiving rate of application data
+ measured in per second. */
+ uint64_t recv_rate_sec;
+} ngtcp2_conn_stat;
+
+typedef enum ngtcp2_cc_algo {
+ NGTCP2_CC_ALGO_RENO = 0x00,
+ NGTCP2_CC_ALGO_CUBIC = 0x01,
+ NGTCP2_CC_ALGO_CUSTOM = 0xff
+} ngtcp2_cc_algo;
+
+typedef struct ngtcp2_cc_base {
+ ngtcp2_log *log;
+} ngtcp2_cc_base;
+
+/* ngtcp2_cc_pkt is a convenient structure to include acked/lost/sent
+ packet. */
+typedef struct {
+ /* pkt_num is the packet number */
+ int64_t pkt_num;
+ /* pktlen is the length of packet. */
+ size_t pktlen;
+ /* pktns_id is the ID of packet number space which this packet
+ belongs to. */
+ ngtcp2_pktns_id pktns_id;
+ /* ts_sent is the timestamp when packet is sent. */
+ ngtcp2_tstamp ts_sent;
+} ngtcp2_cc_pkt;
+
+typedef struct ngtcp2_cc ngtcp2_cc;
+
+typedef void (*ngtcp2_cc_on_pkt_acked)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
+ const ngtcp2_cc_pkt *pkt,
+ ngtcp2_tstamp ts);
+
+typedef void (*ngtcp2_cc_congestion_event)(ngtcp2_cc *cc,
+ ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts_sent,
+ ngtcp2_tstamp ts);
+
+typedef void (*ngtcp2_cc_on_persistent_congestion)(ngtcp2_cc *cc,
+ ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts);
+
+typedef void (*ngtcp2_cc_on_ack_recv)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts);
+
+typedef void (*ngtcp2_cc_on_pkt_sent)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
+ const ngtcp2_cc_pkt *pkt);
+
+typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts);
+
+typedef void (*ngtcp2_cc_reset)(ngtcp2_cc *cc);
+
+typedef enum ngtcp2_cc_event_type {
+ /* NGTCP2_CC_EVENT_TX_START occurs when ack-eliciting packet is sent
+ and no other ack-eliciting packet is present. */
+ NGTCP2_CC_EVENT_TYPE_TX_START
+} ngtcp2_cc_event_type;
+
+typedef void (*ngtcp2_cc_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
+ ngtcp2_cc_event_type event, ngtcp2_tstamp ts);
+
+typedef struct ngtcp2_cc {
+ ngtcp2_cc_base *ccb;
+ ngtcp2_cc_on_pkt_acked on_pkt_acked;
+ ngtcp2_cc_congestion_event congestion_event;
+ ngtcp2_cc_on_persistent_congestion on_persistent_congestion;
+ ngtcp2_cc_on_ack_recv on_ack_recv;
+ ngtcp2_cc_on_pkt_sent on_pkt_sent;
+ ngtcp2_cc_new_rtt_sample new_rtt_sample;
+ ngtcp2_cc_reset reset;
+ ngtcp2_cc_event event;
+} ngtcp2_cc;
+
/* user_data is the same object passed to ngtcp2_conn_client_new or
ngtcp2_conn_server_new. */
typedef void (*ngtcp2_printf)(void *user_data, const char *format, ...);
@@ -539,7 +683,8 @@ typedef void (*ngtcp2_qlog_write)(void *user_data, const void *data,
typedef struct ngtcp2_qlog_settings {
/* odcid is Original Destination Connection ID sent by client. It
- is used as group_id and ODCID fields. */
+ is used as group_id and ODCID fields. Client ignores this field
+ and uses dcid parameter passed to `ngtcp2_conn_client_new()`. */
ngtcp2_cid odcid;
/* write is a callback function to write qlog. Setting NULL
disables qlog. */
@@ -550,57 +695,43 @@ typedef struct ngtcp2_settings {
/* transport_params is the QUIC transport parameters to send. */
ngtcp2_transport_params transport_params;
ngtcp2_qlog_settings qlog;
+ ngtcp2_cc_algo cc_algo;
+ ngtcp2_cc *cc;
/* initial_ts is an initial timestamp given to the library. */
ngtcp2_tstamp initial_ts;
/* log_printf is a function that the library uses to write logs.
NULL means no logging output. */
ngtcp2_printf log_printf;
- /* token is a token received in Client Initial packet and
- successfully validated. Only server application may specify this
- field. Server then verifies that all Client Initial packets have
- this token. `ngtcp2_conn_server_new` makes a copy of token. */
+ /* max_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. If it is set to 0, it
+ defaults to NGTCP2_DEFAULT_MAX_PKTLEN. */
+ size_t max_udp_payload_size;
+ /**
+ * token is a token from Retry packet or NEW_TOKEN frame.
+ *
+ * Server sets this field if it received the token in Client Initial
+ * packet and successfully validated.
+ *
+ * Client sets this field if it intends to send token in its Initial
+ * packet.
+ *
+ * `ngtcp2_conn_server_new` and `ngtcp2_conn_client_new` make a copy
+ * of token.
+ */
ngtcp2_vec token;
} ngtcp2_settings;
/**
* @struct
*
- * ngtcp2_rcvry_stat holds various statistics, and computed data for
- * recovery from packet loss.
- *
- * Everything is NGTCP2_DURATION_TICK resolution.
- */
-typedef struct ngtcp2_rcvry_stat {
- ngtcp2_duration latest_rtt;
- ngtcp2_duration min_rtt;
- ngtcp2_duration smoothed_rtt;
- ngtcp2_duration rttvar;
- size_t pto_count;
- ngtcp2_tstamp loss_detection_timer;
- /* last_tx_pkt_ts corresponds to
- time_of_last_sent_ack_eliciting_packet in
- draft-ietf-quic-recovery-25. It is indexed by
- ngtcp2_crypto_level. No last_tx_pkt_ts for 0RTT packet. */
- ngtcp2_tstamp last_tx_pkt_ts[3];
-} ngtcp2_rcvry_stat;
-
-typedef struct ngtcp2_cc_stat {
- uint64_t cwnd;
- uint64_t ssthresh;
- ngtcp2_tstamp congestion_recovery_start_ts;
- uint64_t bytes_in_flight;
-} ngtcp2_cc_stat;
-
-/**
- * @struct
- *
* ngtcp2_addr is the endpoint address.
*/
typedef struct ngtcp2_addr {
/* addrlen is the length of addr. */
size_t addrlen;
/* addr points to the buffer which contains endpoint address. It is
- opaque to the ngtcp2 library. */
+ opaque to the ngtcp2 library. It must not be NULL. */
uint8_t *addr;
/* user_data is an arbitrary data and opaque to the library. */
void *user_data;
@@ -680,6 +811,12 @@ typedef struct ngtcp2_crypto_ctx {
ngtcp2_crypto_aead aead;
ngtcp2_crypto_md md;
ngtcp2_crypto_cipher hp;
+ /* max_encryption is the number of encryption which this key can be
+ used with. */
+ uint64_t max_encryption;
+ /* max_decryption_failure is the number of decryption failure with
+ this key. */
+ uint64_t max_decryption_failure;
} ngtcp2_crypto_ctx;
/**
@@ -1055,7 +1192,6 @@ typedef int (*ngtcp2_recv_version_negotiation)(ngtcp2_conn *conn,
* immediately.
*/
typedef int (*ngtcp2_recv_retry)(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
- const ngtcp2_pkt_retry *retry,
void *user_data);
/**
@@ -1132,22 +1268,45 @@ typedef int (*ngtcp2_hp_mask)(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
const uint8_t *hp_key, const uint8_t *sample);
/**
+ * @enum
+ *
+ * ngtcp2_stream_data_flag defines the properties of the data emitted
+ * via :type:`ngtcp2_recv_stream_data` callback function.
+ */
+typedef enum ngtcp2_stream_data_flag {
+ NGTCP2_STREAM_DATA_FLAG_NONE = 0x00,
+ /**
+ * NGTCP2_STREAM_DATA_FLAG_FIN indicates that this chunk of data is
+ * final piece of an incoming stream.
+ */
+ NGTCP2_STREAM_DATA_FLAG_FIN = 0x01,
+ /**
+ * NGTCP2_STREAM_DATA_FLAG_0RTT indicates that this chunk of data
+ * contains data received in 0RTT packet and the handshake has not
+ * completed yet, which means that the data might be replayed.
+ */
+ NGTCP2_STREAM_DATA_FLAG_0RTT = 0x02
+} ngtcp2_stream_data_flag;
+
+/**
* @functypedef
*
* :type:`ngtcp2_recv_stream_data` is invoked when stream data is
- * received. The stream is specified by |stream_id|. If |fin| is
- * nonzero, this portion of the data is the last data in this stream.
- * |offset| is the offset where this data begins. The library ensures
- * that data is passed to the application in the non-decreasing order
- * of |offset|. The data is passed as |data| of length |datalen|.
- * |datalen| may be 0 if and only if |fin| is nonzero.
+ * received. The stream is specified by |stream_id|. |flags| is the
+ * bitwise-OR of zero or more of ngtcp2_stream_data_flag. If |flags|
+ * & :enum:`NGTCP2_STREAM_DATA_FLAG_FIN` is nonzero, this portion of
+ * the data is the last data in this stream. |offset| is the offset
+ * where this data begins. The library ensures that data is passed to
+ * the application in the non-decreasing order of |offset|. The data
+ * is passed as |data| of length |datalen|. |datalen| may be 0 if and
+ * only if |fin| is nonzero.
*
* The callback function must return 0 if it succeeds, or
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the library return
* immediately.
*/
-typedef int (*ngtcp2_recv_stream_data)(ngtcp2_conn *conn, int64_t stream_id,
- int fin, uint64_t offset,
+typedef int (*ngtcp2_recv_stream_data)(ngtcp2_conn *conn, uint32_t flags,
+ int64_t stream_id, uint64_t offset,
const uint8_t *data, size_t datalen,
void *user_data, void *stream_user_data);
@@ -1215,11 +1374,9 @@ typedef int (*ngtcp2_stream_reset)(ngtcp2_conn *conn, int64_t stream_id,
* Returning :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library
* call return immediately.
*/
-typedef int (*ngtcp2_acked_stream_data_offset)(ngtcp2_conn *conn,
- int64_t stream_id,
- uint64_t offset, size_t datalen,
- void *user_data,
- void *stream_user_data);
+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);
/**
* @functypedef
@@ -1238,7 +1395,7 @@ typedef int (*ngtcp2_acked_stream_data_offset)(ngtcp2_conn *conn,
*/
typedef int (*ngtcp2_acked_crypto_offset)(ngtcp2_conn *conn,
ngtcp2_crypto_level crypto_level,
- uint64_t offset, size_t datalen,
+ uint64_t offset, uint64_t datalen,
void *user_data);
/**
@@ -1436,6 +1593,21 @@ typedef int (*ngtcp2_connection_id_status)(ngtcp2_conn *conn, int type,
const uint8_t *token,
void *user_data);
+/**
+ * @functypedef
+ *
+ * :type:`ngtcp2_recv_new_token` is a callback function which is
+ * called when new token is received from server.
+ *
+ * |token| is the received token.
+ *
+ * The callback function must return 0 if it succeeds. Returning
+ * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
+ * immediately.
+ */
+typedef int (*ngtcp2_recv_new_token)(ngtcp2_conn *conn, const ngtcp2_vec *token,
+ void *user_data);
+
typedef struct ngtcp2_conn_callbacks {
/**
* client_initial is a callback function which is invoked when
@@ -1617,6 +1789,11 @@ typedef struct ngtcp2_conn_callbacks {
* handshake confirmation for server.
*/
ngtcp2_handshake_confirmed handshake_confirmed;
+ /**
+ * recv_new_token is a callback function which is invoked when new
+ * token is received from server. This field is ignored by server.
+ */
+ ngtcp2_recv_new_token recv_new_token;
} ngtcp2_conn_callbacks;
/**
@@ -1764,7 +1941,10 @@ NGTCP2_EXTERN void ngtcp2_conn_del(ngtcp2_conn *conn);
* connection using `ngtcp2_conn_del`. It is undefined to call the
* other library functions. If :enum:`NGTCP2_ERR_RETRY` is returned,
* application must be a server and it must perform address validation
- * by sending Retry packet and close the connection.
+ * by sending Retry packet and close the connection. If
+ * :enum:`NGTCP2_ERR_DROP_CONN` is returned, server application must
+ * drop the connection silently (without sending any CONNECTION_CLOSE
+ * frame) and discard connection state.
*/
NGTCP2_EXTERN int ngtcp2_conn_read_pkt(ngtcp2_conn *conn,
const ngtcp2_path *path,
@@ -1828,13 +2008,11 @@ NGTCP2_EXTERN int ngtcp2_conn_install_initial_key(
/**
* @function
*
- * `ngtcp2_conn_install_handshake_key` installs packet protection
- * keying materials for Handshake packets. |rx_key| of length
- * |keylen|, IV |rx_iv| of length |rx_ivlen|, and packet header
- * protection key |rx_hp_key| of length |keylen| to decrypt incoming
- * Handshake packets. Similarly, |tx_key|, |tx_iv| and |tx_hp_key|
- * are for encrypt outgoing packets and are the same length with the
- * rx counterpart.
+ * `ngtcp2_conn_install_rx_handshake_key` installs packet protection
+ * keying materials for decrypting incoming Handshake packets. |key|
+ * of length |keylen|, IV |iv| of length |ivlen|, and packet header
+ * protection key |hp_key| of length |keylen| to decrypt incoming
+ * Handshake packets.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@@ -1842,10 +2020,30 @@ NGTCP2_EXTERN int ngtcp2_conn_install_initial_key(
* :enum:`NGTCP2_ERR_NOMEM`
* Out of memory.
*/
-NGTCP2_EXTERN int ngtcp2_conn_install_handshake_key(
- ngtcp2_conn *conn, const uint8_t *rx_key, const uint8_t *rx_iv,
- const uint8_t *rx_hp_key, const uint8_t *tx_key, const uint8_t *tx_iv,
- const uint8_t *tx_hp_key, size_t keylen, size_t ivlen);
+NGTCP2_EXTERN int
+ngtcp2_conn_install_rx_handshake_key(ngtcp2_conn *conn, const uint8_t *key,
+ const uint8_t *iv, const uint8_t *hp_key,
+ size_t keylen, size_t ivlen);
+
+/**
+ * @function
+ *
+ * `ngtcp2_conn_install_tx_handshake_key` installs packet protection
+ * keying materials for encrypting outgoing Handshake packets. |key|
+ * of length |keylen|, IV |iv| of length |ivlen|, and packet header
+ * protection key |hp_key| of length |keylen| to encrypt outgoing
+ * Handshake packets.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGTCP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGTCP2_EXTERN int
+ngtcp2_conn_install_tx_handshake_key(ngtcp2_conn *conn, const uint8_t *key,
+ const uint8_t *iv, const uint8_t *hp_key,
+ size_t keylen, size_t ivlen);
/**
* @function
@@ -1890,14 +2088,34 @@ NGTCP2_EXTERN int ngtcp2_conn_install_early_key(ngtcp2_conn *conn,
/**
* @function
*
- * `ngtcp2_conn_install_key` installs packet protection keying
- * materials for Short packets. |rx_secret| of length |secretlen| is
- * the decryption secret. |rx_key| of length |keylen|, IV |rx_iv| of
- * length |rx_ivlen|, and packet header protection key |rx_hp_key| of
- * length |keylen| to decrypt incoming Short packets. Similarly,
- * |tx_secret| of length |secretlen| is the encryption secret.
- * |tx_key|, |tx_iv| and |tx_hp_key| are used to encrypt outgoing
- * packets and are the same length with the rx counterpart.
+ * `ngtcp2_conn_install_rx_key` installs packet protection keying
+ * materials for decrypting Short packets. |secret| of length
+ * |secretlen| is the decryption secret which is used to derive keying
+ * materials passed to this function. |key| of length |keylen|, IV
+ * |iv| of length |ivlen|, and packet header protection key |hp_key|
+ * of length |keylen| to decrypt incoming Short packets.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGTCP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGTCP2_EXTERN int
+ngtcp2_conn_install_rx_key(ngtcp2_conn *conn, const uint8_t *secret,
+ const uint8_t *key, const uint8_t *iv,
+ const uint8_t *hp_key, size_t secretlen,
+ size_t keylen, size_t ivlen);
+
+/**
+ * @function
+ *
+ * `ngtcp2_conn_install_tx_key` installs packet protection keying
+ * materials for encrypting Short packets. |secret| of length
+ * |secretlen| is the encryption secret which is used to derive keying
+ * materials passed to this function. |key| of length |keylen|, IV
+ * |iv| of length |ivlen|, and packet header protection key |hp_key|
+ * of length |keylen| to encrypt outgoing Short packets.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@@ -1905,11 +2123,11 @@ NGTCP2_EXTERN int ngtcp2_conn_install_early_key(ngtcp2_conn *conn,
* :enum:`NGTCP2_ERR_NOMEM`
* Out of memory.
*/
-NGTCP2_EXTERN int ngtcp2_conn_install_key(
- ngtcp2_conn *conn, const uint8_t *rx_secret, const uint8_t *tx_secret,
- const uint8_t *rx_key, const uint8_t *rx_iv, const uint8_t *rx_hp_key,
- const uint8_t *tx_key, const uint8_t *tx_iv, const uint8_t *tx_hp_key,
- size_t secretlen, size_t keylen, size_t ivlen);
+NGTCP2_EXTERN int
+ngtcp2_conn_install_tx_key(ngtcp2_conn *conn, const uint8_t *secret,
+ const uint8_t *key, const uint8_t *iv,
+ const uint8_t *hp_key, size_t secretlen,
+ size_t keylen, size_t ivlen);
/**
* @function
@@ -1986,7 +2204,7 @@ NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn);
/**
* @function
*
- * `ngtcp2_conn_handle_expiry` handles expired timer. It do nothing
+ * `ngtcp2_conn_handle_expiry` handles expired timer. It does nothing
* if timer is not expired.
*/
NGTCP2_EXTERN int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn,
@@ -2194,7 +2412,12 @@ typedef enum ngtcp2_write_stream_flag {
* NGTCP2_WRITE_STREAM_FLAG_MORE indicates that more stream data may
* come and should be coalesced into the same packet if possible.
*/
- NGTCP2_WRITE_STREAM_FLAG_MORE = 0x01
+ NGTCP2_WRITE_STREAM_FLAG_MORE = 0x01,
+ /**
+ * NGTCP2_WRITE_STREAM_FLAG_FIN indicates that the passed data is
+ * the final part of a stream.
+ */
+ NGTCP2_WRITE_STREAM_FLAG_FIN = 0x02
} ngtcp2_write_stream_flag;
/**
@@ -2206,7 +2429,7 @@ typedef enum ngtcp2_write_stream_flag {
*/
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
ngtcp2_conn *conn, ngtcp2_path *path, uint8_t *dest, size_t destlen,
- ngtcp2_ssize *pdatalen, uint32_t flags, int64_t stream_id, int fin,
+ ngtcp2_ssize *pdatalen, uint32_t flags, int64_t stream_id,
const uint8_t *data, size_t datalen, ngtcp2_tstamp ts);
/**
@@ -2226,15 +2449,16 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
* nothing is written to |dest|.
*
* If the all given data is encoded as STREAM frame in |dest|, and if
- * |fin| is nonzero, fin flag is set in outgoing STREAM frame.
- * Otherwise, fin flag in STREAM frame is not set.
+ * |flags| & NGTCP2_WRITE_STREAM_FLAG_FIN is nonzero, fin flag is set
+ * to outgoing STREAM frame. Otherwise, fin flag in STREAM frame is
+ * not set.
*
* This packet may contain frames other than STREAM frame. The packet
* might not contain STREAM frame if other frames occupy the packet.
* In that case, |*pdatalen| would be -1 if |pdatalen| is not NULL.
*
- * If |fin| is nonzero, and 0 length STREAM frame is successfully
- * serialized, |*pdatalen| would be 0.
+ * If |flags| & NGTCP2_WRITE_STREAM_FLAG_FIN is nonzero, and 0 length
+ * STREAM frame is successfully serialized, |*pdatalen| would be 0.
*
* The number of data encoded in STREAM frame is stored in |*pdatalen|
* if it is not NULL. The caller must keep the portion of data
@@ -2257,14 +2481,15 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
* - The function returns the written length of packet just like
* without :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE`. This is because
* packet is nearly full and the library decided to make a complete
- * packet.
+ * packet. In this case, |*pdatalen| == -1 is asserted.
*
- * - The function returns :enum:`NGTCP2_ERR_WRITE_STREAM_MORE`. This
- * indicates that application can call this function with different
- * stream data to pack them into the same packet. Application has
- * to specify the same |conn|, |path|, |dest|, |destlen|,
- * |pdatalen|, and |ts| parameters, otherwise the behaviour is
- * undefined. The application can change |flags|.
+ * - The function returns :enum:`NGTCP2_ERR_WRITE_STREAM_MORE`. In
+ * this case, |*pdatalen| >= 0 is asserted. This indicates that
+ * application can call this function with different stream data to
+ * pack them into the same packet. Application has to specify the
+ * same |conn|, |path|, |dest|, |destlen|, |pdatalen|, and |ts|
+ * parameters, otherwise the behaviour is undefined. The
+ * application can change |flags|.
*
* - The function returns :enum:`NGTCP2_ERR_STREAM_DATA_BLOCKED` which
* indicates that stream is blocked because of flow control.
@@ -2278,7 +2503,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
* `ngtcp2_conn_write_application_close` to handle error from this
* function). Just keep calling `ngtcp2_conn_writev_stream` or
* `ngtcp2_conn_write_pkt` until it returns a positive number (which
- * indicates a complete packet is ready).
+ * indicates a complete packet is ready). If |*pdatalen| >= 0, the
+ * function always return :enum:`NGTCP2_ERR_WRITE_STREAM_MORE`.
*
* This function returns 0 if it cannot write any frame because buffer
* is too small, or packet is congestion limited. Application should
@@ -2316,7 +2542,7 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
*/
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream(
ngtcp2_conn *conn, ngtcp2_path *path, uint8_t *dest, size_t destlen,
- ngtcp2_ssize *pdatalen, uint32_t flags, int64_t stream_id, int fin,
+ ngtcp2_ssize *pdatalen, uint32_t flags, int64_t stream_id,
const ngtcp2_vec *datav, size_t datavcnt, ngtcp2_tstamp ts);
/**
@@ -2419,7 +2645,7 @@ NGTCP2_EXTERN int ngtcp2_conn_is_in_draining_period(ngtcp2_conn *conn);
*/
NGTCP2_EXTERN int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn,
int64_t stream_id,
- size_t datalen);
+ uint64_t datalen);
/**
* @function
@@ -2428,7 +2654,7 @@ NGTCP2_EXTERN int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn,
* |datalen|.
*/
NGTCP2_EXTERN void ngtcp2_conn_extend_max_offset(ngtcp2_conn *conn,
- size_t datalen);
+ uint64_t datalen);
/**
* @function
@@ -2462,15 +2688,6 @@ NGTCP2_EXTERN void ngtcp2_conn_extend_max_streams_uni(ngtcp2_conn *conn,
/**
* @function
*
- * `ngtcp2_conn_get_bytes_in_flight` returns the number of bytes which
- * is the sum of outgoing QUIC packet length in flight. This does not
- * include a packet which only includes ACK frames.
- */
-NGTCP2_EXTERN size_t ngtcp2_conn_get_bytes_in_flight(ngtcp2_conn *conn);
-
-/**
- * @function
- *
* `ngtcp2_conn_get_dcid` returns the non-NULL pointer to destination
* connection ID. If no destination connection ID is present, the
* return value is not ``NULL``, and its datalen field is 0.
@@ -2554,19 +2771,11 @@ NGTCP2_EXTERN int ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn);
/**
* @function
*
- * `ngtcp2_conn_get_rcvry_stat` returns a pointer to the object which
- * stores recovery information.
- */
-NGTCP2_EXTERN const ngtcp2_rcvry_stat *
-ngtcp2_conn_get_rcvry_stat(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_cc_stat` returns a pointer to the object which
- * stores congestion controller information.
+ * `ngtcp2_conn_get_conn_stat` assigns connection statistics data to
+ * |*cstat|.
*/
-NGTCP2_EXTERN const ngtcp2_cc_stat *ngtcp2_conn_get_cc_stat(ngtcp2_conn *conn);
+NGTCP2_EXTERN void ngtcp2_conn_get_conn_stat(ngtcp2_conn *conn,
+ ngtcp2_conn_stat *cstat);
/**
* @function
@@ -2610,6 +2819,26 @@ ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn,
/**
* @function
*
+ * `ngtcp2_conn_submit_new_token` submits address validation token.
+ * It is sent in NEW_TOKEN frame. Only server can call this function.
+ * |tokenlen| must not be 0.
+ *
+ * This function makes a copy of the buffer pointed by |token| of
+ * length |tokenlen|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGTCP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGTCP2_EXTERN int ngtcp2_conn_submit_new_token(ngtcp2_conn *conn,
+ const uint8_t *token,
+ size_t tokenlen);
+
+/**
+ * @function
+ *
* `ngtcp2_conn_set_local_addr` sets local endpoint address |addr| to
* |conn|.
*/
@@ -2676,6 +2905,24 @@ NGTCP2_EXTERN uint64_t ngtcp2_conn_get_max_data_left(ngtcp2_conn *conn);
/**
* @function
*
+ * `ngtcp2_conn_get_streams_bidi_left` returns the number of
+ * bidirectional streams which the local endpoint can open without
+ * violating stream concurrency limit.
+ */
+NGTCP2_EXTERN uint64_t ngtcp2_conn_get_streams_bidi_left(ngtcp2_conn *conn);
+
+/**
+ * @function
+ *
+ * `ngtcp2_conn_get_streams_uni_left` returns the number of
+ * unidirectional streams which the local endpoint can open without
+ * violating stream concurrency limit.
+ */
+NGTCP2_EXTERN uint64_t ngtcp2_conn_get_streams_uni_left(ngtcp2_conn *conn);
+
+/**
+ * @function
+ *
* `ngtcp2_conn_set_initial_crypto_ctx` sets |ctx| for Initial packet
* encryption. The passed data will be passed to
* :type:`ngtcp2_encrypt`, :type:`ngtcp2_decrypt` and
@@ -2709,6 +2956,24 @@ NGTCP2_EXTERN void ngtcp2_conn_set_crypto_ctx(ngtcp2_conn *conn,
/**
* @function
*
+ * `ngtcp2_conn_get_tls_native_handle` returns TLS native handle set by
+ * `ngtcp2_conn_set_tls_native_handle()`.
+ */
+NGTCP2_EXTERN void *ngtcp2_conn_get_tls_native_handle(ngtcp2_conn *conn);
+
+/**
+ * @function
+ *
+ * `ngtcp2_conn_set_tls_native_handle` sets TLS native handle
+ * |tls_native_handle| to |conn|. Internally, it is used as an opaque
+ * pointer.
+ */
+NGTCP2_EXTERN void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn,
+ void *tls_native_handle);
+
+/**
+ * @function
+ *
* `ngtcp2_conn_set_retry_aead` sets |aead| for Retry integrity tag
* verification. It must be AEAD_AES_128_GCM. This function must be
* called if |conn| is initialized as client. Server does not verify
@@ -2763,6 +3028,14 @@ NGTCP2_EXTERN int ngtcp2_conn_is_local_stream(ngtcp2_conn *conn,
/**
* @function
*
+ * `ngtcp2_conn_is_server` returns nonzero if |conn| is initialized as
+ * server.
+ */
+NGTCP2_EXTERN int ngtcp2_conn_is_server(ngtcp2_conn *conn);
+
+/**
+ * @function
+ *
* `ngtcp2_strerror` returns the text representation of |liberr|.
*/
NGTCP2_EXTERN const char *ngtcp2_strerror(int liberr);
@@ -2818,9 +3091,12 @@ NGTCP2_EXTERN void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps);
* values. First this function fills |settings| with 0 and set the
* default value to the following fields:
*
- * * max_packet_size = NGTCP2_MAX_PKT_SIZE
- * * ack_delay_component = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT
- * * max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY
+ * * cc_algo = NGTCP2_CC_ALGO_CUBIC
+ * * transport_params.max_udp_payload_size = NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE
+ * * transport_params.ack_delay_component = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT
+ * * transport_params.max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY
+ * * transport_params.active_connection_id_limit =
+ * NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT
*/
NGTCP2_EXTERN void ngtcp2_settings_default(ngtcp2_settings *settings);
@@ -2882,6 +3158,30 @@ NGTCP2_EXTERN ngtcp2_info *ngtcp2_version(int least_version);
*/
NGTCP2_EXTERN int ngtcp2_is_bidi_stream(int64_t stream_id);
+typedef enum {
+ NGTCP2_LOG_EVENT_NONE,
+ /* connection (catch-all) event */
+ NGTCP2_LOG_EVENT_CON,
+ /* packet event */
+ NGTCP2_LOG_EVENT_PKT,
+ /* frame event */
+ NGTCP2_LOG_EVENT_FRM,
+ /* recovery event */
+ NGTCP2_LOG_EVENT_RCV,
+ /* crypto event */
+ NGTCP2_LOG_EVENT_CRY,
+ /* path validation event */
+ NGTCP2_LOG_EVENT_PTV,
+} ngtcp2_log_event;
+
+/**
+ * @function
+ *
+ * `ngtcp2_log_info` writes info level log.
+ */
+NGTCP2_EXTERN void ngtcp2_log_info(ngtcp2_log *log, ngtcp2_log_event ev,
+ const char *fmt, ...);
+
#ifdef __cplusplus
}
#endif
diff --git a/deps/ngtcp2/lib/includes/ngtcp2/version.h b/deps/ngtcp2/lib/includes/ngtcp2/version.h
index 85850725bfa..3782959c286 100644
--- a/deps/ngtcp2/lib/includes/ngtcp2/version.h
+++ b/deps/ngtcp2/lib/includes/ngtcp2/version.h
@@ -30,7 +30,7 @@
*
* Version number of the ngtcp2 library release.
*/
-#define NGTCP2_VERSION "0.1.90"
+#define NGTCP2_VERSION "0.1.0-DEV"
/**
* @macro
@@ -40,6 +40,6 @@
* number, 8 bits for minor and 8 bits for patch. Version 1.2.3
* becomes 0x010203.
*/
-#define NGTCP2_VERSION_NUM 0x00015a
+#define NGTCP2_VERSION_NUM 0x000100
#endif /* VERSION_H */
diff --git a/deps/ngtcp2/lib/includes/ngtcp2/version.h.in b/deps/ngtcp2/lib/includes/ngtcp2/version.h.in
deleted file mode 100644
index fc7459636dd..00000000000
--- a/deps/ngtcp2/lib/includes/ngtcp2/version.h.in
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2016 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 VERSION_H
-#define VERSION_H
-
-/**
- * @macro
- *
- * Version number of the ngtcp2 library release.
- */
-#define NGTCP2_VERSION "@PACKAGE_VERSION@"
-
-/**
- * @macro
- *
- * Numerical representation of the version number of the ngtcp2
- * library release. This is a 24 bit number with 8 bits for major
- * number, 8 bits for minor and 8 bits for patch. Version 1.2.3
- * becomes 0x010203.
- */
-#define NGTCP2_VERSION_NUM @PACKAGE_VERSION_NUM@
-
-#endif /* VERSION_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_acktr.c b/deps/ngtcp2/lib/ngtcp2_acktr.c
index e27d05c787d..85113716b1c 100644
--- a/deps/ngtcp2/lib/ngtcp2_acktr.c
+++ b/deps/ngtcp2/lib/ngtcp2_acktr.c
@@ -45,7 +45,7 @@ void ngtcp2_acktr_entry_del(ngtcp2_acktr_entry *ent, const ngtcp2_mem *mem) {
}
static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return *lhs->i > *rhs->i;
+ return *(int64_t *)lhs > *(int64_t *)rhs;
}
int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
@@ -95,11 +95,9 @@ int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
ngtcp2_acktr_entry *ent, *prev_ent, *delent;
int rv;
int added = 0;
- ngtcp2_ksl_key key, old_key;
if (ngtcp2_ksl_len(&acktr->ents)) {
- it = ngtcp2_ksl_lower_bound(&acktr->ents,
- ngtcp2_ksl_key_ptr(&key, &pkt_num));
+ it = ngtcp2_ksl_lower_bound(&acktr->ents, &pkt_num);
if (ngtcp2_ksl_it_end(&it)) {
ngtcp2_ksl_it_prev(&it);
ent = ngtcp2_ksl_it_get(&it);
@@ -117,9 +115,7 @@ int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
if (ngtcp2_ksl_it_begin(&it)) {
if (ent->pkt_num + 1 == pkt_num) {
- ngtcp2_ksl_update_key(&acktr->ents,
- ngtcp2_ksl_key_ptr(&key, &ent->pkt_num),
- ngtcp2_ksl_key_ptr(&old_key, &pkt_num));
+ ngtcp2_ksl_update_key(&acktr->ents, &ent->pkt_num, &pkt_num);
ent->pkt_num = pkt_num;
ent->tstamp = ts;
++ent->len;
@@ -134,14 +130,11 @@ int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
if (ent->pkt_num + 1 == pkt_num) {
if (prev_ent->pkt_num == pkt_num + (int64_t)prev_ent->len) {
prev_ent->len += ent->len + 1;
- ngtcp2_ksl_remove(&acktr->ents, NULL,
- ngtcp2_ksl_key_ptr(&key, &ent->pkt_num));
+ ngtcp2_ksl_remove(&acktr->ents, NULL, &ent->pkt_num);
ngtcp2_acktr_entry_del(ent, acktr->mem);
added = 1;
} else {
- ngtcp2_ksl_update_key(&acktr->ents,
- ngtcp2_ksl_key_ptr(&key, &ent->pkt_num),
- ngtcp2_ksl_key_ptr(&old_key, &pkt_num));
+ ngtcp2_ksl_update_key(&acktr->ents, &ent->pkt_num, &pkt_num);
ent->pkt_num = pkt_num;
ent->tstamp = ts;
++ent->len;
@@ -160,8 +153,7 @@ int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
if (rv != 0) {
return rv;
}
- rv = ngtcp2_ksl_insert(&acktr->ents, NULL,
- ngtcp2_ksl_key_ptr(&key, &ent->pkt_num), ent);
+ rv = ngtcp2_ksl_insert(&acktr->ents, NULL, &ent->pkt_num, ent);
if (rv != 0) {
ngtcp2_acktr_entry_del(ent, acktr->mem);
return rv;
@@ -179,8 +171,7 @@ int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
it = ngtcp2_ksl_end(&acktr->ents);
ngtcp2_ksl_it_prev(&it);
delent = ngtcp2_ksl_it_get(&it);
- ngtcp2_ksl_remove(&acktr->ents, NULL,
- ngtcp2_ksl_key_ptr(&key, &delent->pkt_num));
+ ngtcp2_ksl_remove(&acktr->ents, NULL, &delent->pkt_num);
ngtcp2_acktr_entry_del(delent, acktr->mem);
}
@@ -189,16 +180,13 @@ int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent) {
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
- it = ngtcp2_ksl_lower_bound(&acktr->ents,
- ngtcp2_ksl_key_ptr(&key, &ent->pkt_num));
- assert(*ngtcp2_ksl_it_key(&it).i == (int64_t)ent->pkt_num);
+ it = ngtcp2_ksl_lower_bound(&acktr->ents, &ent->pkt_num);
+ assert(*(int64_t *)ngtcp2_ksl_it_key(&it) == (int64_t)ent->pkt_num);
for (; !ngtcp2_ksl_it_end(&it);) {
ent = ngtcp2_ksl_it_get(&it);
- ngtcp2_ksl_remove(&acktr->ents, &it,
- ngtcp2_ksl_key_ptr(&key, &ent->pkt_num));
+ ngtcp2_ksl_remove(&acktr->ents, &it, &ent->pkt_num);
ngtcp2_acktr_entry_del(ent, acktr->mem);
}
}
@@ -207,6 +195,11 @@ ngtcp2_ksl_it ngtcp2_acktr_get(ngtcp2_acktr *acktr) {
return ngtcp2_ksl_begin(&acktr->ents);
}
+int ngtcp2_acktr_empty(ngtcp2_acktr *acktr) {
+ ngtcp2_ksl_it it = ngtcp2_ksl_begin(&acktr->ents);
+ return ngtcp2_ksl_it_end(&it);
+}
+
ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr,
int64_t pkt_num,
int64_t largest_ack) {
@@ -224,9 +217,7 @@ ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr,
*/
static void acktr_remove(ngtcp2_acktr *acktr, ngtcp2_ksl_it *it,
ngtcp2_acktr_entry *ent) {
- ngtcp2_ksl_key key;
-
- ngtcp2_ksl_remove(&acktr->ents, it, ngtcp2_ksl_key_ptr(&key, &ent->pkt_num));
+ ngtcp2_ksl_remove(&acktr->ents, it, &ent->pkt_num);
ngtcp2_acktr_entry_del(ent, acktr->mem);
}
@@ -235,15 +226,13 @@ static void acktr_on_ack(ngtcp2_acktr *acktr, ngtcp2_ringbuf *rb,
ngtcp2_acktr_ack_entry *ack_ent;
ngtcp2_acktr_entry *ent;
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
assert(ngtcp2_ringbuf_len(rb));
ack_ent = ngtcp2_ringbuf_get(rb, ack_ent_offset);
/* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
- it = ngtcp2_ksl_lower_bound(&acktr->ents,
- ngtcp2_ksl_key_ptr(&key, &ack_ent->largest_ack));
+ it = ngtcp2_ksl_lower_bound(&acktr->ents, &ack_ent->largest_ack);
for (; !ngtcp2_ksl_it_end(&it);) {
ent = ngtcp2_ksl_it_get(&it);
acktr_remove(acktr, &it, ent);
diff --git a/deps/ngtcp2/lib/ngtcp2_acktr.h b/deps/ngtcp2/lib/ngtcp2_acktr.h
index 0efd2156ac9..38c1ebe2cfd 100644
--- a/deps/ngtcp2/lib/ngtcp2_acktr.h
+++ b/deps/ngtcp2/lib/ngtcp2_acktr.h
@@ -177,6 +177,12 @@ void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent);
ngtcp2_ksl_it ngtcp2_acktr_get(ngtcp2_acktr *acktr);
/*
+ * ngtcp2_acktr_empty returns nonzero if it has no packet to
+ * acknowledge.
+ */
+int ngtcp2_acktr_empty(ngtcp2_acktr *acktr);
+
+/*
* ngtcp2_acktr_add_ack records outgoing ACK frame whose largest
* acknowledged packet number is |largest_ack|. |pkt_num| is the
* packet number of a packet in which ACK frame is included. This
diff --git a/deps/ngtcp2/lib/ngtcp2_cc.c b/deps/ngtcp2/lib/ngtcp2_cc.c
index 02864bffa0e..9c61a5e9564 100644
--- a/deps/ngtcp2/lib/ngtcp2_cc.c
+++ b/deps/ngtcp2/lib/ngtcp2_cc.c
@@ -23,115 +23,472 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "ngtcp2_cc.h"
+
+#include <assert.h>
+
#include "ngtcp2_log.h"
#include "ngtcp2_macro.h"
-#include "ngtcp2_rst.h"
+#include "ngtcp2_mem.h"
+#include "ngtcp2_rcvry.h"
+
+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);
+}
ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
- size_t pktlen, ngtcp2_tstamp ts_sent) {
+ size_t pktlen, ngtcp2_pktns_id pktns_id,
+ ngtcp2_tstamp ts_sent) {
pkt->pkt_num = pkt_num;
pkt->pktlen = pktlen;
+ pkt->pktns_id = pktns_id;
pkt->ts_sent = ts_sent;
return pkt;
}
-void ngtcp2_default_cc_init(ngtcp2_default_cc *cc, ngtcp2_cc_stat *ccs,
- ngtcp2_rst *rst, ngtcp2_log *log) {
- cc->log = log;
- cc->ccs = ccs;
- cc->rst = rst;
- cc->max_delivery_rate = 0.;
- cc->min_rtt = 0;
- cc->min_rtt_ts = 0;
+static void reno_cc_reset(ngtcp2_reno_cc *cc) {
+ cc->max_delivery_rate_sec = 0;
cc->target_cwnd = 0;
}
-void ngtcp2_default_cc_free(ngtcp2_default_cc *cc) { (void)cc; }
+void ngtcp2_reno_cc_init(ngtcp2_reno_cc *cc, ngtcp2_log *log) {
+ cc->ccb.log = log;
+ reno_cc_reset(cc);
+}
+
+void ngtcp2_reno_cc_free(ngtcp2_reno_cc *cc) { (void)cc; }
+
+int ngtcp2_cc_reno_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
+ const ngtcp2_mem *mem) {
+ ngtcp2_reno_cc *reno_cc;
+
+ reno_cc = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_reno_cc));
+ if (reno_cc == NULL) {
+ return NGTCP2_ERR_NOMEM;
+ }
-static int default_cc_in_congestion_recovery(ngtcp2_default_cc *cc,
- ngtcp2_tstamp sent_time) {
- return sent_time <= cc->ccs->congestion_recovery_start_ts;
+ ngtcp2_reno_cc_init(reno_cc, log);
+
+ cc->ccb = &reno_cc->ccb;
+ cc->on_pkt_acked = ngtcp2_cc_reno_cc_on_pkt_acked;
+ cc->congestion_event = ngtcp2_cc_reno_cc_congestion_event;
+ cc->on_persistent_congestion = ngtcp2_cc_reno_cc_on_persistent_congestion;
+ cc->on_ack_recv = ngtcp2_cc_reno_cc_on_ack_recv;
+ cc->reset = ngtcp2_cc_reno_cc_reset;
+
+ return 0;
}
-void ngtcp2_default_cc_on_pkt_acked(ngtcp2_default_cc *cc,
- const ngtcp2_cc_pkt *pkt) {
- ngtcp2_cc_stat *ccs = cc->ccs;
+void ngtcp2_cc_reno_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) {
+ ngtcp2_reno_cc *reno_cc = ngtcp2_struct_of(cc->ccb, ngtcp2_reno_cc, ccb);
+
+ ngtcp2_reno_cc_free(reno_cc);
+ ngtcp2_mem_free(mem, reno_cc);
+}
+
+static int in_congestion_recovery(const ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp sent_time) {
+ return sent_time <= cstat->congestion_recovery_start_ts;
+}
+
+void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
+ const ngtcp2_cc_pkt *pkt,
+ ngtcp2_tstamp ts) {
+ ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb);
+ (void)ts;
- if (default_cc_in_congestion_recovery(cc, pkt->ts_sent)) {
+ if (in_congestion_recovery(cstat, pkt->ts_sent)) {
return;
}
- if (cc->target_cwnd && ccs->cwnd >= cc->target_cwnd) {
+ if (cc->target_cwnd && cc->target_cwnd < cstat->cwnd) {
return;
}
- if (ccs->cwnd < ccs->ssthresh) {
- ccs->cwnd += pkt->pktlen;
- ngtcp2_log_info(cc->log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64 " acked, slow start cwnd=%lu", pkt->pkt_num,
- ccs->cwnd);
+ if (cstat->cwnd < cstat->ssthresh) {
+ cstat->cwnd += pkt->pktlen;
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64,
+ pkt->pkt_num, cstat->cwnd);
return;
}
- ccs->cwnd += NGTCP2_MAX_DGRAM_SIZE * pkt->pktlen / ccs->cwnd;
+ cstat->cwnd += cstat->max_udp_payload_size * pkt->pktlen / cstat->cwnd;
}
-void ngtcp2_default_cc_congestion_event(ngtcp2_default_cc *cc,
+void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
ngtcp2_tstamp ts_sent,
ngtcp2_tstamp ts) {
- ngtcp2_cc_stat *ccs = cc->ccs;
+ ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb);
+ uint64_t min_cwnd;
- if (default_cc_in_congestion_recovery(cc, ts_sent)) {
+ if (in_congestion_recovery(cstat, ts_sent)) {
return;
}
- ccs->congestion_recovery_start_ts = ts;
- ccs->cwnd >>= NGTCP2_LOSS_REDUCTION_FACTOR_BITS;
- ccs->cwnd = ngtcp2_max(ccs->cwnd, NGTCP2_MIN_CWND);
- ccs->ssthresh = ccs->cwnd;
- ngtcp2_log_info(cc->log, NGTCP2_LOG_EVENT_RCV,
- "reduce cwnd because of packet loss cwnd=%lu", ccs->cwnd);
-}
+ cstat->congestion_recovery_start_ts = ts;
+ cstat->cwnd >>= NGTCP2_LOSS_REDUCTION_FACTOR_BITS;
+ min_cwnd = 2 * cstat->max_udp_payload_size;
+ cstat->cwnd = ngtcp2_max(cstat->cwnd, min_cwnd);
+ cstat->ssthresh = cstat->cwnd;
-void ngtcp2_default_cc_handle_persistent_congestion(ngtcp2_default_cc *cc,
- ngtcp2_duration loss_window,
- ngtcp2_duration pto) {
- ngtcp2_cc_stat *ccs = cc->ccs;
- ngtcp2_duration congestion_period =
- pto * NGTCP2_PERSISTENT_CONGESTION_THRESHOLD;
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "reduce cwnd because of packet loss cwnd=%" PRIu64,
+ cstat->cwnd);
+}
- if (loss_window >= congestion_period) {
- ngtcp2_log_info(cc->log, NGTCP2_LOG_EVENT_RCV,
- "persistent congestion loss_window=%" PRIu64
- " congestion_period=%" PRIu64,
- loss_window, congestion_period);
+void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *ccx,
+ ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts) {
+ (void)ccx;
+ (void)ts;
- ccs->cwnd = NGTCP2_MIN_CWND;
- }
+ cstat->cwnd = 2 * cstat->max_udp_payload_size;
}
-void ngtcp2_default_cc_on_ack_recv(ngtcp2_default_cc *cc,
- ngtcp2_duration latest_rtt,
+void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
ngtcp2_tstamp ts) {
+ ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb);
+ uint64_t target_cwnd, initcwnd;
+ (void)ts;
+
+ /* TODO Use sliding window for min rtt measurement */
/* TODO Use sliding window */
- if (latest_rtt && (cc->min_rtt == 0 || cc->min_rtt > latest_rtt)) {
- cc->min_rtt = latest_rtt;
- cc->min_rtt_ts = ts;
+ cc->max_delivery_rate_sec =
+ ngtcp2_max(cc->max_delivery_rate_sec, cstat->delivery_rate_sec);
+
+ if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) {
+ target_cwnd = cc->max_delivery_rate_sec * cstat->min_rtt / NGTCP2_SECONDS;
+ initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_udp_payload_size);
+ cc->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100;
+
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "target_cwnd=%" PRIu64 " max_delivery_rate_sec=%" PRIu64
+ " min_rtt=%" PRIu64,
+ cc->target_cwnd, cc->max_delivery_rate_sec, cstat->min_rtt);
}
+}
+
+void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *ccx) {
+ ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb);
+ reno_cc_reset(cc);
+}
+
+static void cubic_cc_reset(ngtcp2_cubic_cc *cc) {
+ cc->max_delivery_rate_sec = 0;
+ cc->target_cwnd = 0;
+ cc->w_last_max = 0;
+ cc->w_tcp = 0;
+ cc->origin_point = 0;
+ cc->epoch_start = UINT64_MAX;
+ cc->k = 0;
+
+ cc->rtt_sample_count = 0;
+ cc->current_round_min_rtt = UINT64_MAX;
+ cc->last_round_min_rtt = UINT64_MAX;
+ cc->window_end = -1;
+}
+
+void ngtcp2_cubic_cc_init(ngtcp2_cubic_cc *cc, ngtcp2_log *log) {
+ cc->ccb.log = log;
+ cubic_cc_reset(cc);
+}
+
+void ngtcp2_cubic_cc_free(ngtcp2_cubic_cc *cc) { (void)cc; }
+
+int ngtcp2_cc_cubic_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
+ const ngtcp2_mem *mem) {
+ ngtcp2_cubic_cc *cubic_cc;
+
+ cubic_cc = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_cubic_cc));
+ if (cubic_cc == NULL) {
+ return NGTCP2_ERR_NOMEM;
+ }
+
+ ngtcp2_cubic_cc_init(cubic_cc, log);
+
+ cc->ccb = &cubic_cc->ccb;
+ cc->on_pkt_acked = ngtcp2_cc_cubic_cc_on_pkt_acked;
+ cc->congestion_event = ngtcp2_cc_cubic_cc_congestion_event;
+ cc->on_persistent_congestion = ngtcp2_cc_cubic_cc_on_persistent_congestion;
+ cc->on_ack_recv = ngtcp2_cc_cubic_cc_on_ack_recv;
+ cc->on_pkt_sent = ngtcp2_cc_cubic_cc_on_pkt_sent;
+ cc->new_rtt_sample = ngtcp2_cc_cubic_cc_new_rtt_sample;
+ cc->reset = ngtcp2_cc_cubic_cc_reset;
+ cc->event = ngtcp2_cc_cubic_cc_event;
+
+ return 0;
+}
+
+void ngtcp2_cc_cubic_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) {
+ ngtcp2_cubic_cc *cubic_cc = ngtcp2_struct_of(cc->ccb, ngtcp2_cubic_cc, ccb);
+
+ ngtcp2_cubic_cc_free(cubic_cc);
+ ngtcp2_mem_free(mem, cubic_cc);
+}
+
+static uint64_t ngtcp2_cbrt(uint64_t n) {
+ int d;
+ uint64_t a;
+ int i;
+
+ if (n == 0) {
+ return 0;
+ }
+
+ d = __builtin_clzll(n);
+ a = 1ULL << ((64 - d) / 3 + 1);
+
+ for (i = 0; a * a * a > n; ++i) {
+ a = (2 * a + n / a / a) / 3;
+ }
+ return a;
+}
+
+/* HyStart++ constants */
+#define NGTCP2_HS_MIN_SSTHRESH 16
+#define NGTCP2_HS_N_RTT_SAMPLE 8
+#define NGTCP2_HS_MIN_ETA (4 * NGTCP2_MILLISECONDS)
+#define NGTCP2_HS_MAX_ETA (16 * NGTCP2_MILLISECONDS)
+
+void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
+ const ngtcp2_cc_pkt *pkt,
+ ngtcp2_tstamp ts) {
+ ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
+ ngtcp2_duration t, min_rtt, eta;
+ uint64_t target;
+ uint64_t tx, kx, time_delta, delta;
+ uint64_t add, tcp_add;
+
+ if (pkt->pktns_id == NGTCP2_PKTNS_ID_APP && cc->window_end != -1 &&
+ cc->window_end <= pkt->pkt_num) {
+ cc->window_end = -1;
+ }
+
+ if (in_congestion_recovery(cstat, pkt->ts_sent)) {
+ return;
+ }
+
+ if (cc->target_cwnd && cc->target_cwnd < cstat->cwnd) {
+ return;
+ }
+
+ if (cstat->cwnd < cstat->ssthresh) {
+ /* slow-start */
+ cstat->cwnd += pkt->pktlen;
+
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64,
+ pkt->pkt_num, cstat->cwnd);
+
+ if (cc->last_round_min_rtt != UINT64_MAX &&
+ cc->current_round_min_rtt != UINT64_MAX &&
+ cstat->cwnd >= NGTCP2_HS_MIN_SSTHRESH * cstat->max_udp_payload_size &&
+ cc->rtt_sample_count >= NGTCP2_HS_N_RTT_SAMPLE) {
+ eta = cc->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 (cc->current_round_min_rtt >= cc->last_round_min_rtt + eta) {
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "HyStart++ exit slow start");
+ cc->w_last_max = cstat->cwnd;
+ cstat->ssthresh = cstat->cwnd;
+ }
+ }
+
+ return;
+ }
+
+ /* congestion avoidance */
+
+ if (cc->epoch_start == UINT64_MAX) {
+ cc->epoch_start = ts;
+ if (cstat->cwnd < cc->w_last_max) {
+ cc->k = ngtcp2_cbrt((cc->w_last_max - cstat->cwnd) * 10 / 4 /
+ cstat->max_udp_payload_size);
+ cc->origin_point = cc->w_last_max;
+ } else {
+ cc->k = 0;
+ cc->origin_point = cstat->cwnd;
+ }
+
+ cc->w_tcp = cstat->cwnd;
+
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "cubic-ca epoch_start=%" PRIu64 " k=%" PRIu64
+ " origin_point=%" PRIu64,
+ cc->epoch_start, cc->k, cc->origin_point);
+ }
+
+ min_rtt = cstat->min_rtt == UINT64_MAX ? NGTCP2_DEFAULT_INITIAL_RTT
+ : cstat->min_rtt;
+
+ t = ts + min_rtt - cc->epoch_start;
+
+ tx = (t << 4) / NGTCP2_SECONDS;
+ kx = (cc->k << 4);
+
+ if (tx > kx) {
+ time_delta = tx - kx;
+ } else {
+ time_delta = kx - tx;
+ }
+
+ delta = cstat->max_udp_payload_size *
+ ((((time_delta * time_delta) >> 4) * time_delta) >> 8) * 4 / 10;
+
+ if (tx > kx) {
+ target = cc->origin_point + delta;
+ } else {
+ target = cc->origin_point - delta;
+ }
+
+ if (target > cstat->cwnd) {
+ add = cstat->max_udp_payload_size * (target - cstat->cwnd) / cstat->cwnd;
+ } else {
+ /* TODO too small, no increment at all */
+ add = cstat->max_udp_payload_size / (100 * cstat->cwnd);
+ }
+
+ cc->w_tcp += cstat->max_udp_payload_size * pkt->pktlen * 9 / 17 / cstat->cwnd;
+
+ if (cc->w_tcp > cstat->cwnd) {
+ tcp_add =
+ cstat->max_udp_payload_size * (cc->w_tcp - cstat->cwnd) / cstat->cwnd;
+ if (tcp_add > add) {
+ add = tcp_add;
+ }
+ }
+
+ cstat->cwnd += add;
+
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "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, cc->k, time_delta >> 4, delta,
+ target, cc->w_tcp);
+}
+
+void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *ccx,
+ ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts_sent,
+ ngtcp2_tstamp ts) {
+ ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
+ uint64_t min_cwnd;
+
+ if (in_congestion_recovery(cstat, ts_sent)) {
+ return;
+ }
+
+ cstat->congestion_recovery_start_ts = ts;
+
+ cc->epoch_start = UINT64_MAX;
+ if (cstat->cwnd < cc->w_last_max) {
+ cc->w_last_max = cstat->cwnd * 17 / 10 / 2;
+ } else {
+ cc->w_last_max = cstat->cwnd;
+ }
+
+ min_cwnd = 2 * cstat->max_udp_payload_size;
+ cstat->ssthresh = cstat->cwnd * 7 / 10;
+ cstat->ssthresh = ngtcp2_max(cstat->ssthresh, min_cwnd);
+ cstat->cwnd = cstat->ssthresh;
+
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "reduce cwnd because of packet loss cwnd=%" PRIu64,
+ cstat->cwnd);
+}
+
+void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *ccx,
+ ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts) {
+ (void)ccx;
+ (void)ts;
+
+ cstat->cwnd = 2 * cstat->max_udp_payload_size;
+}
+
+void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts) {
+ ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
+ uint64_t target_cwnd, initcwnd;
+ (void)ts;
+
+ /* TODO Use sliding window for min rtt measurement */
/* TODO Use sliding window */
- cc->max_delivery_rate =
- ngtcp2_max(cc->max_delivery_rate, cc->rst->rs.delivery_rate);
+ cc->max_delivery_rate_sec =
+ ngtcp2_max(cc->max_delivery_rate_sec, cstat->delivery_rate_sec);
+
+ if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) {
+ target_cwnd = cc->max_delivery_rate_sec * cstat->min_rtt / NGTCP2_SECONDS;
+ initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_udp_payload_size);
+ cc->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100;
+
+ ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
+ "target_cwnd=%" PRIu64 " max_delivery_rate_sec=%" PRIu64
+ " min_rtt=%" PRIu64,
+ cc->target_cwnd, cc->max_delivery_rate_sec, cstat->min_rtt);
+ }
+}
+
+void ngtcp2_cc_cubic_cc_on_pkt_sent(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
+ const ngtcp2_cc_pkt *pkt) {
+ ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
+ (void)cstat;
+
+ if (pkt->pktns_id != NGTCP2_PKTNS_ID_APP || cc->window_end != -1) {
+ return;
+ }
- if (cc->min_rtt && cc->max_delivery_rate > 1e-9) {
- uint64_t target_cwnd =
- (uint64_t)(2.89 * cc->max_delivery_rate * (double)cc->min_rtt);
- cc->target_cwnd = ngtcp2_max(NGTCP2_MIN_CWND, target_cwnd);
+ cc->window_end = pkt->pkt_num;
+ cc->last_round_min_rtt = cc->current_round_min_rtt;
+ cc->current_round_min_rtt = UINT64_MAX;
+ cc->rtt_sample_count = 0;
+}
+
+void ngtcp2_cc_cubic_cc_new_rtt_sample(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts) {
+ ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
+ (void)ts;
+
+ if (cc->window_end == -1) {
+ return;
+ }
+
+ cc->current_round_min_rtt =
+ ngtcp2_min(cc->current_round_min_rtt, cstat->latest_rtt);
+ ++cc->rtt_sample_count;
+}
+
+void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *ccx) {
+ ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
+ cubic_cc_reset(cc);
+}
+
+void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
+ ngtcp2_cc_event_type event, ngtcp2_tstamp ts) {
+ ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
+ ngtcp2_tstamp last_ts;
+
+ if (event != NGTCP2_CC_EVENT_TYPE_TX_START || cc->epoch_start == UINT64_MAX) {
+ return;
+ }
- ngtcp2_log_info(cc->log, NGTCP2_LOG_EVENT_RCV,
- "target_cwnd=%lu max_delivery_rate=%.02f min_rtt=%lu",
- cc->target_cwnd, cc->max_delivery_rate * 1000000000,
- cc->min_rtt);
+ last_ts = cstat->last_tx_pkt_ts[NGTCP2_PKTNS_ID_APP];
+ if (last_ts == UINT64_MAX || last_ts <= cc->epoch_start) {
+ return;
}
+
+ assert(ts >= last_ts);
+
+ cc->epoch_start += ts - last_ts;
}
diff --git a/deps/ngtcp2/lib/ngtcp2_cc.h b/deps/ngtcp2/lib/ngtcp2_cc.h
index 33f2815c78f..c3886a6e6b4 100644
--- a/deps/ngtcp2/lib/ngtcp2_cc.h
+++ b/deps/ngtcp2/lib/ngtcp2_cc.h
@@ -31,62 +31,105 @@
#include <ngtcp2/ngtcp2.h>
-#define NGTCP2_MAX_DGRAM_SIZE 1200
-#define NGTCP2_MIN_CWND (2 * NGTCP2_MAX_DGRAM_SIZE)
#define NGTCP2_LOSS_REDUCTION_FACTOR_BITS 1
#define NGTCP2_PERSISTENT_CONGESTION_THRESHOLD 3
struct ngtcp2_log;
typedef struct ngtcp2_log ngtcp2_log;
-struct ngtcp2_rst;
-typedef struct ngtcp2_rst ngtcp2_rst;
-
-/* ngtcp2_cc_pkt is a convenient structure to include acked/lost/sent
- packet. */
-typedef struct {
- /* pkt_num is the packet number */
- int64_t pkt_num;
- /* pktlen is the length of packet. */
- size_t pktlen;
- /* ts_sent is the timestamp when packet is sent. */
- ngtcp2_tstamp ts_sent;
-} ngtcp2_cc_pkt;
+/*
+ * ngtcp2_cc_compute_initcwnd computes initial cwnd.
+ */
+uint64_t ngtcp2_cc_compute_initcwnd(size_t max_packet_size);
ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
- size_t pktlen, ngtcp2_tstamp ts_sent);
-
-/* ngtcp2_default_cc is the default congestion controller. */
-struct ngtcp2_default_cc {
- ngtcp2_log *log;
- ngtcp2_cc_stat *ccs;
- ngtcp2_rst *rst;
- double max_delivery_rate;
- ngtcp2_duration min_rtt;
- ngtcp2_tstamp min_rtt_ts;
+ size_t pktlen, ngtcp2_pktns_id pktns_id,
+ ngtcp2_tstamp ts_sent);
+
+/* ngtcp2_reno_cc is the RENO congestion controller. */
+struct ngtcp2_reno_cc {
+ ngtcp2_cc_base ccb;
+ uint64_t max_delivery_rate_sec;
uint64_t target_cwnd;
};
-typedef struct ngtcp2_default_cc ngtcp2_default_cc;
+typedef struct ngtcp2_reno_cc ngtcp2_reno_cc;
-void ngtcp2_default_cc_init(ngtcp2_default_cc *cc, ngtcp2_cc_stat *ccs,
- ngtcp2_rst *rst, ngtcp2_log *log);
+int ngtcp2_cc_reno_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
+ const ngtcp2_mem *mem);
-void ngtcp2_default_cc_free(ngtcp2_default_cc *cc);
+void ngtcp2_cc_reno_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem);
-void ngtcp2_default_cc_on_pkt_acked(ngtcp2_default_cc *cc,
- const ngtcp2_cc_pkt *pkt);
+void ngtcp2_reno_cc_init(ngtcp2_reno_cc *cc, ngtcp2_log *log);
+
+void ngtcp2_reno_cc_free(ngtcp2_reno_cc *cc);
-void ngtcp2_default_cc_congestion_event(ngtcp2_default_cc *cc,
+void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
+ const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts);
+
+void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
ngtcp2_tstamp ts_sent,
ngtcp2_tstamp ts);
-void ngtcp2_default_cc_handle_persistent_congestion(ngtcp2_default_cc *cc,
- ngtcp2_duration loss_window,
- ngtcp2_duration pto);
+void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc,
+ ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts);
-void ngtcp2_default_cc_on_ack_recv(ngtcp2_default_cc *cc,
- ngtcp2_duration latest_rtt,
+void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
ngtcp2_tstamp ts);
+void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc);
+
+/* ngtcp2_cubic_cc is CUBIC congestion controller. */
+typedef struct ngtcp2_cubic_cc {
+ ngtcp2_cc_base ccb;
+ uint64_t max_delivery_rate_sec;
+ uint64_t target_cwnd;
+ uint64_t w_last_max;
+ uint64_t w_tcp;
+ uint64_t origin_point;
+ ngtcp2_tstamp epoch_start;
+ uint64_t k;
+ /* HyStart++ variables */
+ size_t rtt_sample_count;
+ uint64_t current_round_min_rtt;
+ uint64_t last_round_min_rtt;
+ int64_t window_end;
+} ngtcp2_cubic_cc;
+
+int ngtcp2_cc_cubic_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
+ const ngtcp2_mem *mem);
+
+void ngtcp2_cc_cubic_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem);
+
+void ngtcp2_cubic_cc_init(ngtcp2_cubic_cc *cc, ngtcp2_log *log);
+
+void ngtcp2_cubic_cc_free(ngtcp2_cubic_cc *cc);
+
+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_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
+ ngtcp2_tstamp ts_sent,
+ ngtcp2_tstamp ts);
+
+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,
+ 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);
+
+void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
+ ngtcp2_cc_event_type event, ngtcp2_tstamp ts);
+
#endif /* NGTCP2_CC_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_conn.c b/deps/ngtcp2/lib/ngtcp2_conn.c
index eca7f04ca33..41e5f4d915e 100644
--- a/deps/ngtcp2/lib/ngtcp2_conn.c
+++ b/deps/ngtcp2/lib/ngtcp2_conn.c
@@ -81,7 +81,7 @@ static int conn_call_handshake_completed(ngtcp2_conn *conn) {
}
static int conn_call_recv_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm,
- int fin, uint64_t offset,
+ uint32_t flags, uint64_t offset,
const uint8_t *data, size_t datalen) {
int rv;
@@ -89,7 +89,7 @@ static int conn_call_recv_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm,
return 0;
}
- rv = conn->callbacks.recv_stream_data(conn, strm->stream_id, fin, offset,
+ rv = conn->callbacks.recv_stream_data(conn, flags, strm->stream_id, offset,
data, datalen, conn->user_data,
strm->stream_user_data);
if (rv != 0) {
@@ -361,11 +361,11 @@ static int conn_call_deactivate_dcid(ngtcp2_conn *conn,
static int crypto_offset_less(const ngtcp2_ksl_key *lhs,
const ngtcp2_ksl_key *rhs) {
- return *lhs->i < *rhs->i;
+ return *(int64_t *)lhs < *(int64_t *)rhs;
}
-static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_crypto_level crypto_level,
- ngtcp2_rst *rst, ngtcp2_default_cc *cc, ngtcp2_log *log,
+static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id,
+ ngtcp2_rst *rst, ngtcp2_cc *cc, ngtcp2_log *log,
ngtcp2_qlog *qlog, const ngtcp2_mem *mem) {
int rv;
@@ -396,7 +396,7 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_crypto_level crypto_level,
goto fail_tx_frq_init;
}
- ngtcp2_rtb_init(&pktns->rtb, crypto_level, &pktns->crypto.strm, rst, cc, log,
+ ngtcp2_rtb_init(&pktns->rtb, pktns_id, &pktns->crypto.strm, rst, cc, log,
qlog, mem);
return 0;
@@ -411,8 +411,8 @@ fail_acktr_init:
return rv;
}
-static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_crypto_level crypto_level,
- ngtcp2_rst *rst, ngtcp2_default_cc *cc, ngtcp2_log *log,
+static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id,
+ ngtcp2_rst *rst, ngtcp2_cc *cc, ngtcp2_log *log,
ngtcp2_qlog *qlog, const ngtcp2_mem *mem) {
int rv;
@@ -421,7 +421,7 @@ static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_crypto_level crypto_level,
return NGTCP2_ERR_NOMEM;
}
- rv = pktns_init(*ppktns, crypto_level, rst, cc, log, qlog, mem);
+ rv = pktns_init(*ppktns, pktns_id, rst, cc, log, qlog, mem);
if (rv != 0) {
ngtcp2_mem_free(mem, *ppktns);
}
@@ -487,8 +487,22 @@ static void pktns_del(ngtcp2_pktns *pktns, const ngtcp2_mem *mem) {
ngtcp2_mem_free(mem, pktns);
}
+static void cc_del(ngtcp2_cc *cc, ngtcp2_cc_algo cc_algo,
+ const ngtcp2_mem *mem) {
+ switch (cc_algo) {
+ case NGTCP2_CC_ALGO_RENO:
+ ngtcp2_cc_reno_cc_free(cc, mem);
+ break;
+ case NGTCP2_CC_ALGO_CUBIC:
+ ngtcp2_cc_cubic_cc_free(cc, mem);
+ break;
+ default:
+ break;
+ }
+}
+
static int cid_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return ngtcp2_cid_less(lhs->ptr, rhs->ptr);
+ return ngtcp2_cid_less(lhs, rhs);
}
static int ts_retired_less(const ngtcp2_pq_entry *lhs,
@@ -499,18 +513,68 @@ static int ts_retired_less(const ngtcp2_pq_entry *lhs,
return a->ts_retired < b->ts_retired;
}
-static void rcvry_stat_reset(ngtcp2_rcvry_stat *rcs) {
- memset(rcs, 0, sizeof(*rcs));
- rcs->min_rtt = UINT64_MAX;
+static void conn_reset_conn_stat(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat) {
+ cstat->latest_rtt = 0;
+ cstat->min_rtt = UINT64_MAX;
+ cstat->smoothed_rtt = NGTCP2_DEFAULT_INITIAL_RTT;
+ cstat->rttvar = NGTCP2_DEFAULT_INITIAL_RTT / 2;
+ cstat->pto_count = 0;
+ cstat->loss_detection_timer = 0;
// Initializes them with UINT64_MAX.
- memset(rcs->last_tx_pkt_ts, 0xff, sizeof(rcs->last_tx_pkt_ts));
+ memset(cstat->loss_time, 0xff, sizeof(cstat->loss_time));
+ cstat->cwnd =
+ ngtcp2_cc_compute_initcwnd(conn->local.settings.max_udp_payload_size);
+ cstat->ssthresh = UINT64_MAX;
+ cstat->congestion_recovery_start_ts = 0;
+ cstat->bytes_in_flight = 0;
+ cstat->max_udp_payload_size = conn->local.settings.max_udp_payload_size;
+ cstat->delivery_rate_sec = 0;
+ cstat->recv_rate_sec = 0;
+}
+
+static void conn_reset_rx_rate(ngtcp2_conn *conn) {
+ conn->rx.rate.start_ts = UINT64_MAX;
+ conn->rx.rate.received = 0;
}
-static void cc_stat_reset(ngtcp2_cc_stat *ccs) {
- memset(ccs, 0, sizeof(*ccs));
- ccs->cwnd = ngtcp2_min(10 * NGTCP2_MAX_DGRAM_SIZE,
- ngtcp2_max(2 * NGTCP2_MAX_DGRAM_SIZE, 14720));
- ccs->ssthresh = UINT64_MAX;
+static void conn_update_recv_rate(ngtcp2_conn *conn, size_t datalen,
+ ngtcp2_tstamp ts) {
+ uint64_t bps;
+ ngtcp2_duration window;
+
+ conn->rx.rate.received += datalen;
+
+ if (conn->rx.rate.start_ts == UINT64_MAX) {
+ conn->rx.rate.start_ts = ts;
+ return;
+ }
+
+ assert(conn->cstat.min_rtt);
+
+ window = conn->cstat.min_rtt == UINT64_MAX ? NGTCP2_DEFAULT_INITIAL_RTT
+ : conn->cstat.min_rtt * 2;
+
+ if (window > ts - conn->rx.rate.start_ts) {
+ return;
+ }
+
+ bps = conn->rx.rate.received * NGTCP2_SECONDS / (ts - conn->rx.rate.start_ts);
+
+ if (conn->cstat.recv_rate_sec == 0) {
+ conn->cstat.recv_rate_sec = bps;
+ } else {
+ conn->cstat.recv_rate_sec = (conn->cstat.recv_rate_sec * 3 + bps) / 4;
+ }
+
+ conn_reset_rx_rate(conn);
+
+ if (conn->cstat.min_rtt != UINT64_MAX) {
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
+ "recv_rate_sec=%" PRIu64 " bytes/min_rtt=%" PRIu64,
+ conn->cstat.recv_rate_sec,
+ conn->cstat.recv_rate_sec * conn->cstat.min_rtt /
+ NGTCP2_SECONDS);
+ }
}
static void delete_scid(ngtcp2_ksl *scids, const ngtcp2_mem *mem) {
@@ -529,7 +593,6 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
void *user_data, int server) {
int rv;
ngtcp2_scid *scident;
- ngtcp2_ksl_key key;
const ngtcp2_transport_params *params = &settings->transport_params;
uint8_t *buf;
@@ -600,34 +663,9 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
ngtcp2_buf_init(&(*pconn)->qlog.buf, buf, NGTCP2_QLOG_BUFLEN);
}
- ngtcp2_rst_init(&(*pconn)->rst);
-
- ngtcp2_default_cc_init(&(*pconn)->cc, &(*pconn)->ccs, &(*pconn)->rst,
- &(*pconn)->log);
-
- rv = pktns_new(&(*pconn)->in_pktns, NGTCP2_CRYPTO_LEVEL_INITIAL,
- &(*pconn)->rst, &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog,
- mem);
- if (rv != 0) {
- goto fail_in_pktns_init;
- }
-
- rv = pktns_new(&(*pconn)->hs_pktns, NGTCP2_CRYPTO_LEVEL_HANDSHAKE,
- &(*pconn)->rst, &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog,
- mem);
- if (rv != 0) {
- goto fail_hs_pktns_init;
- }
-
- rv = pktns_init(&(*pconn)->pktns, NGTCP2_CRYPTO_LEVEL_APP, &(*pconn)->rst,
- &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem);
- if (rv != 0) {
- goto fail_pktns_init;
- }
-
(*pconn)->local.settings = *settings;
- if (server && settings->token.len) {
+ if (settings->token.len) {
buf = ngtcp2_mem_malloc(mem, settings->token.len);
if (buf == NULL) {
goto fail_token;
@@ -644,6 +682,64 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
}
+ (*pconn)->local.settings.transport_params.initial_scid = *scid;
+
+ if (scid->datalen == 0) {
+ (*pconn)->local.settings.transport_params.preferred_address_present = 0;
+ }
+
+ if (settings->max_udp_payload_size == 0) {
+ (*pconn)->local.settings.max_udp_payload_size = NGTCP2_DEFAULT_MAX_PKTLEN;
+ }
+
+ conn_reset_conn_stat(*pconn, &(*pconn)->cstat);
+
+ ngtcp2_rst_init(&(*pconn)->rst);
+
+ (*pconn)->cc_algo = settings->cc_algo;
+
+ switch (settings->cc_algo) {
+ case NGTCP2_CC_ALGO_RENO:
+ rv = ngtcp2_cc_reno_cc_init(&(*pconn)->cc, &(*pconn)->log, mem);
+ if (rv != 0) {
+ goto fail_cc_init;
+ }
+ break;
+ case NGTCP2_CC_ALGO_CUBIC:
+ rv = ngtcp2_cc_cubic_cc_init(&(*pconn)->cc, &(*pconn)->log, mem);
+ if (rv != 0) {
+ goto fail_cc_init;
+ }
+ break;
+ case NGTCP2_CC_ALGO_CUSTOM:
+ assert(settings->cc);
+ (*pconn)->cc = *settings->cc;
+ (*pconn)->cc.ccb->log = &(*pconn)->log;
+ break;
+ default:
+ assert(0);
+ }
+
+ conn_reset_rx_rate(*pconn);
+
+ rv = pktns_new(&(*pconn)->in_pktns, NGTCP2_PKTNS_ID_INITIAL, &(*pconn)->rst,
+ &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem);
+ if (rv != 0) {
+ goto fail_in_pktns_init;
+ }
+
+ rv = pktns_new(&(*pconn)->hs_pktns, NGTCP2_PKTNS_ID_HANDSHAKE, &(*pconn)->rst,
+ &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem);
+ if (rv != 0) {
+ goto fail_hs_pktns_init;
+ }
+
+ rv = pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APP, &(*pconn)->rst,
+ &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem);
+ if (rv != 0) {
+ goto fail_pktns_init;
+ }
+
scident = ngtcp2_mem_malloc(mem, sizeof(*scident));
if (scident == NULL) {
rv = NGTCP2_ERR_NOMEM;
@@ -655,8 +751,7 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
? params->stateless_reset_token
: NULL);
- rv = ngtcp2_ksl_insert(&(*pconn)->scid.set, NULL,
- ngtcp2_ksl_key_ptr(&key, &scident->cid), scident);
+ rv = ngtcp2_ksl_insert(&(*pconn)->scid.set, NULL, &scident->cid, scident);
if (rv != 0) {
goto fail_scid_set_insert;
}
@@ -673,8 +768,7 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
ngtcp2_scid_init(scident, 1, &params->preferred_address.cid,
params->preferred_address.stateless_reset_token);
- rv = ngtcp2_ksl_insert(&(*pconn)->scid.set, NULL,
- ngtcp2_ksl_key_ptr(&key, &scident->cid), scident);
+ rv = ngtcp2_ksl_insert(&(*pconn)->scid.set, NULL, &scident->cid, scident);
if (rv != 0) {
goto fail_scid_set_insert;
}
@@ -701,12 +795,11 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
(*pconn)->idle_ts = settings->initial_ts;
(*pconn)->crypto.key_update.confirmed_ts = UINT64_MAX;
- rcvry_stat_reset(&(*pconn)->rcs);
- cc_stat_reset(&(*pconn)->ccs);
-
- ngtcp2_qlog_start(&(*pconn)->qlog, &settings->qlog.odcid, server);
+ ngtcp2_qlog_start(&(*pconn)->qlog, server ? &settings->qlog.odcid : dcid,
+ server);
ngtcp2_qlog_parameters_set_transport_params(
&(*pconn)->qlog, &(*pconn)->local.settings.transport_params,
+ (*pconn)->server,
/* local = */ 1);
return 0;
@@ -722,7 +815,8 @@ fail_pktns_init:
fail_hs_pktns_init:
pktns_del((*pconn)->in_pktns, mem);
fail_in_pktns_init:
- ngtcp2_default_cc_free(&(*pconn)->cc);
+ cc_del(&(*pconn)->cc, settings->cc_algo, mem);
+fail_cc_init:
ngtcp2_mem_free(mem, (*pconn)->qlog.buf.begin);
fail_qlog_buf:
ngtcp2_ringbuf_free(&(*pconn)->rx.path_challenge);
@@ -790,6 +884,11 @@ int ngtcp2_conn_server_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
params->active_connection_id_limit = 0;
}
+ if ((*pconn)->local.settings.token.len) {
+ /* Usage of token lifts amplification limit */
+ (*pconn)->flags |= NGTCP2_CONN_FLAG_SADDR_VERIFIED;
+ }
+
return 0;
}
@@ -798,7 +897,7 @@ int ngtcp2_conn_server_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
* the given stream. Both connection and stream level flow control
* credits are considered.
*/
-static size_t conn_fc_credits(ngtcp2_conn *conn, ngtcp2_strm *strm) {
+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);
}
@@ -810,8 +909,8 @@ static size_t conn_fc_credits(ngtcp2_conn *conn, ngtcp2_strm *strm) {
*/
static size_t conn_enforce_flow_control(ngtcp2_conn *conn, ngtcp2_strm *strm,
size_t len) {
- size_t fc_credits = conn_fc_credits(conn, strm);
- return ngtcp2_min(len, fc_credits);
+ uint64_t fc_credits = conn_fc_credits(conn, strm);
+ return (size_t)ngtcp2_min((uint64_t)len, fc_credits);
}
static int delete_strms_each(ngtcp2_map_entry *ent, void *ptr) {
@@ -831,7 +930,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) {
ngtcp2_qlog_end(&conn->qlog);
- ngtcp2_mem_free(conn->mem, conn->token.begin);
ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_buf.base);
ngtcp2_mem_free(conn->mem, conn->local.settings.token.base);
@@ -845,7 +943,7 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) {
pktns_del(conn->hs_pktns, conn->mem);
pktns_del(conn->in_pktns, conn->mem);
- ngtcp2_default_cc_free(&conn->cc);
+ cc_del(&conn->cc, conn->cc_algo, conn->mem);
ngtcp2_mem_free(conn->mem, conn->qlog.buf.begin);
@@ -908,14 +1006,8 @@ static int conn_ensure_ack_blks(ngtcp2_conn *conn, size_t n) {
* ACK.
*/
static ngtcp2_duration conn_compute_ack_delay(ngtcp2_conn *conn) {
- ngtcp2_duration initial_delay =
- conn->local.settings.transport_params.max_ack_delay;
-
- if (conn->rcs.smoothed_rtt == 0) {
- return initial_delay;
- }
-
- return ngtcp2_min(initial_delay, conn->rcs.smoothed_rtt / 8);
+ return ngtcp2_min(conn->local.settings.transport_params.max_ack_delay,
+ conn->cstat.smoothed_rtt / 8);
}
/*
@@ -1090,15 +1182,17 @@ static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_rtb *rtb,
/* This function implements OnPacketSent, but it handles only
non-ACK-only packet. */
- rv = ngtcp2_rtb_add(rtb, ent);
+ rv = ngtcp2_rtb_add(rtb, ent, &conn->cstat);
if (rv != 0) {
return rv;
}
if (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
- conn->rcs.last_tx_pkt_ts[rtb->crypto_level] = ent->ts;
+ conn->cstat.last_tx_pkt_ts[rtb->pktns_id] = ent->ts;
+ /* I think pseudo code is wrong; timer should be set when
+ ack-eliciting packet is sent. */
+ ngtcp2_conn_set_loss_detection_timer(conn, ent->ts);
}
- ngtcp2_conn_set_loss_detection_timer(conn, ent->ts);
return 0;
}
@@ -1133,22 +1227,17 @@ static size_t pktns_select_pkt_numlen(ngtcp2_pktns *pktns) {
}
/*
- * conn_cwnd_left returns the number of bytes the local endpoint can
- * sent at this time.
+ * conn_cwnd_is_zero returns nonzero if the number of bytes the local
+ * endpoint can sent at this time is zero.
*/
-static uint64_t conn_cwnd_left(ngtcp2_conn *conn) {
- uint64_t bytes_in_flight = ngtcp2_conn_get_bytes_in_flight(conn);
+static uint64_t conn_cwnd_is_zero(ngtcp2_conn *conn) {
+ uint64_t bytes_in_flight = conn->cstat.bytes_in_flight;
uint64_t cwnd =
conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE)
- ? NGTCP2_MIN_CWND
- : conn->ccs.cwnd;
+ ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_udp_payload_size)
+ : conn->cstat.cwnd;
- /* We might send more than bytes_in_flight if probe packets are
- involved. */
- if (bytes_in_flight >= cwnd) {
- return 0;
- }
- return cwnd - bytes_in_flight;
+ return bytes_in_flight >= cwnd;
}
/*
@@ -1196,14 +1285,13 @@ static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
ngtcp2_crypto *fr, *nfr;
uint64_t offset, end_offset;
size_t idx, end_idx;
- size_t base_offset, end_base_offset;
+ uint64_t base_offset, end_base_offset;
ngtcp2_ksl_it gapit;
ngtcp2_range gap;
ngtcp2_rtb *rtb = &pktns->rtb;
ngtcp2_vec *v;
int rv;
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
*pfrc = NULL;
@@ -1211,8 +1299,7 @@ static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
frc = ngtcp2_ksl_it_get(&it);
fr = &frc->fr.crypto;
- ngtcp2_ksl_remove(&pktns->crypto.tx.frq, &it,
- ngtcp2_ksl_key_ptr(&key, &fr->offset));
+ ngtcp2_ksl_remove(&pktns->crypto.tx.frq, &it, &fr->offset);
idx = 0;
offset = fr->offset;
@@ -1220,7 +1307,7 @@ static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
gapit =
ngtcp2_gaptr_get_first_gap_after(&rtb->crypto->tx.acked_offset, offset);
- gap = *(ngtcp2_range *)ngtcp2_ksl_it_key(&gapit).ptr;
+ gap = *(ngtcp2_range *)ngtcp2_ksl_it_key(&gapit);
if (gap.begin < offset) {
gap.begin = offset;
}
@@ -1269,7 +1356,7 @@ static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
fr->offset = offset + base_offset;
fr->datacnt = end_idx - idx;
fr->data[0].base += base_offset;
- fr->data[0].len -= base_offset;
+ fr->data[0].len -= (size_t)base_offset;
*pfrc = frc;
return 0;
@@ -1291,10 +1378,9 @@ static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
nfr->offset = end_offset + end_base_offset;
nfr->datacnt = fr->datacnt - end_idx;
nfr->data[0].base += end_base_offset;
- nfr->data[0].len -= end_base_offset;
+ nfr->data[0].len -= (size_t)end_base_offset;
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- ngtcp2_ksl_key_ptr(&key, &nfr->offset), nfrc);
+ rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));
ngtcp2_frame_chain_del(nfrc, conn->mem);
@@ -1314,10 +1400,10 @@ static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
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 = end_base_offset;
+ fr->data[fr->datacnt - 1].len = (size_t)end_base_offset;
}
fr->data[0].base += base_offset;
- fr->data[0].len -= base_offset;
+ fr->data[0].len -= (size_t)base_offset;
*pfrc = frc;
return 0;
@@ -1336,7 +1422,6 @@ static int conn_cryptofrq_pop(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc,
ngtcp2_vec b[NGTCP2_MAX_CRYPTO_DATACNT];
size_t acnt, bcnt;
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
rv = conn_cryptofrq_unacked_pop(conn, pktns, &frc);
if (rv != 0) {
@@ -1373,8 +1458,7 @@ static int conn_cryptofrq_pop(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc,
nfr->datacnt = bcnt;
ngtcp2_vec_copy(nfr->data, b, bcnt);
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- ngtcp2_ksl_key_ptr(&key, &nfr->offset), nfrc);
+ rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));
ngtcp2_frame_chain_del(nfrc, conn->mem);
@@ -1431,8 +1515,7 @@ static int conn_cryptofrq_pop(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc,
nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left,
NGTCP2_MAX_CRYPTO_DATACNT);
if (nmerged == 0) {
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- ngtcp2_ksl_key_ptr(&key, &nfr->offset), nfrc);
+ rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));
ngtcp2_frame_chain_del(nfrc, conn->mem);
@@ -1452,8 +1535,7 @@ static int conn_cryptofrq_pop(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc,
nfr->offset += nmerged;
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- ngtcp2_ksl_key_ptr(&key, &nfr->offset), nfrc);
+ rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc);
if (rv != 0) {
ngtcp2_frame_chain_del(nfrc, conn->mem);
ngtcp2_frame_chain_del(frc, conn->mem);
@@ -1508,13 +1590,11 @@ static int conn_cryptofrq_pop(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc,
*/
static int conn_verify_dcid(ngtcp2_conn *conn, int *pnew_cid_used,
const ngtcp2_pkt_hd *hd) {
- ngtcp2_ksl_key key;
ngtcp2_ksl_it it;
ngtcp2_scid *scid;
int rv;
- it = ngtcp2_ksl_lower_bound(&conn->scid.set,
- ngtcp2_ksl_key_ptr(&key, &hd->dcid));
+ it = ngtcp2_ksl_lower_bound(&conn->scid.set, &hd->dcid);
if (ngtcp2_ksl_it_end(&it)) {
return NGTCP2_ERR_INVALID_ARGUMENT;
}
@@ -1554,14 +1634,28 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left,
size_t early_datalen) {
size_t min_payloadlen;
- if (conn->server || type != NGTCP2_PKT_INITIAL) {
+ if (conn->server) {
return 0;
}
- if (!conn->early.ckm || early_datalen == 0) {
+ if (type == NGTCP2_PKT_HANDSHAKE) {
+ return conn->in_pktns != NULL;
+ }
+
+ if (conn->hs_pktns->crypto.tx.ckm &&
+ (conn->hs_pktns->rtb.probe_pkt_left ||
+ ngtcp2_ksl_len(&conn->hs_pktns->crypto.tx.frq) ||
+ !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) {
+ /* If we have something to send in Handshake packet, then add
+ PADDING in Handshake packet. */
+ min_payloadlen = 128;
+ } else if (!conn->early.ckm || early_datalen == 0) {
return 1;
+ } else {
+ /* If we have something to send in 0RTT packet, then add PADDING
+ in 0RTT packet. */
+ min_payloadlen = ngtcp2_min(early_datalen, 128);
}
- min_payloadlen = ngtcp2_min(early_datalen, 128);
return left <
/* TODO Assuming that pkt_num is encoded in 1 byte. */
@@ -1646,9 +1740,9 @@ static ngtcp2_ssize conn_write_handshake_pkt(ngtcp2_conn *conn, uint8_t *dest,
pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns),
conn->version, 0);
- if (type == NGTCP2_PKT_INITIAL && ngtcp2_buf_len(&conn->token)) {
- hd.token = conn->token.pos;
- hd.tokenlen = ngtcp2_buf_len(&conn->token);
+ if (!conn->server && type == NGTCP2_PKT_INITIAL &&
+ conn->local.settings.token.len) {
+ hd.token = conn->local.settings.token;
}
ngtcp2_ppe_init(&ppe, dest, destlen, &cc);
@@ -1663,6 +1757,25 @@ static ngtcp2_ssize conn_write_handshake_pkt(ngtcp2_conn *conn, uint8_t *dest,
return 0;
}
+ rv = conn_create_ack_frame(conn, &ackfr, &pktns->acktr, type, ts,
+ /* ack_delay = */ 0,
+ NGTCP2_DEFAULT_ACK_DELAY_EXPONENT);
+ if (rv != 0) {
+ ngtcp2_frame_chain_list_del(frq, conn->mem);
+ return rv;
+ }
+
+ if (ackfr) {
+ rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, ackfr);
+ if (rv != 0) {
+ assert(NGTCP2_ERR_NOBUF == rv);
+ } else {
+ ngtcp2_acktr_commit_ack(&pktns->acktr);
+ ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, ackfr->ack.largest_ack);
+ pkt_empty = 0;
+ }
+ }
+
for (; ngtcp2_ksl_len(&pktns->crypto.tx.frq);) {
left = ngtcp2_ppe_left(&ppe);
left = ngtcp2_pkt_crypto_max_datalen(
@@ -1696,25 +1809,6 @@ static ngtcp2_ssize conn_write_handshake_pkt(ngtcp2_conn *conn, uint8_t *dest,
NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_CRYPTO_PKT;
}
- rv = conn_create_ack_frame(conn, &ackfr, &pktns->acktr, type, ts,
- /* ack_delay = */ 0,
- NGTCP2_DEFAULT_ACK_DELAY_EXPONENT);
- if (rv != 0) {
- ngtcp2_frame_chain_list_del(frq, conn->mem);
- return rv;
- }
-
- if (ackfr) {
- rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, ackfr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- } else {
- ngtcp2_acktr_commit_ack(&pktns->acktr);
- ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, ackfr->ack.largest_ack);
- pkt_empty = 0;
- }
- }
-
/* Don't send any PING frame if client Initial has not been
acknowledged yet. */
if (!(rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
@@ -1809,7 +1903,7 @@ static ngtcp2_ssize conn_write_handshake_pkt(ngtcp2_conn *conn, uint8_t *dest,
--pktns->rtb.probe_pkt_left;
}
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->rcs, &conn->ccs);
+ ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
++pktns->tx.last_pkt_num;
@@ -1882,6 +1976,50 @@ static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, uint8_t *dest,
NGTCP2_RTB_FLAG_NONE, ts);
}
+static void conn_discard_pktns(ngtcp2_conn *conn, ngtcp2_pktns **ppktns,
+ ngtcp2_tstamp ts) {
+ ngtcp2_pktns *pktns = *ppktns;
+ uint64_t bytes_in_flight;
+
+ bytes_in_flight = pktns->rtb.cc_bytes_in_flight;
+
+ assert(conn->cstat.bytes_in_flight >= bytes_in_flight);
+
+ 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;
+
+ pktns_del(pktns, conn->mem);
+ *ppktns = NULL;
+
+ 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) {
+ if (!conn->in_pktns) {
+ return;
+ }
+
+ conn_discard_pktns(conn, &conn->in_pktns, ts);
+}
+
+/*
+ * conn_discard_handshake_state discards state for Handshake packet
+ * number space.
+ */
+static void conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
+ if (!conn->hs_pktns) {
+ return;
+ }
+
+ conn_discard_pktns(conn, &conn->hs_pktns, ts);
+}
+
/*
* conn_write_handshake_ack_pkts writes packets which contain ACK
* frame only. This function writes at most 2 packets for each
@@ -1892,9 +2030,12 @@ static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn,
ngtcp2_tstamp ts) {
ngtcp2_ssize res = 0, nwrite = 0;
- /* Actullay client never send ACK for server Initial. This is
+ /* In the most cases, client sends ACK in conn_write_handshake_pkt.
+ This function is only called when it is CWND limited. It is not
+ required for client to send ACK for server Initial. This is
because once it gets server Initial, it gets Handshake tx key and
- discards Initial key. */
+ discards Initial key. The only good reason to send ACK is give
+ server RTT measurement early. */
if (conn->server && conn->in_pktns) {
nwrite = conn_write_ack_pkt(conn, dest, destlen, NGTCP2_PKT_INITIAL, ts);
if (nwrite < 0) {
@@ -1913,7 +2054,12 @@ static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn,
assert(nwrite != NGTCP2_ERR_NOBUF);
return nwrite;
}
+
res += nwrite;
+
+ if (!conn->server && nwrite) {
+ conn_discard_initial_state(conn, ts);
+ }
}
return res;
@@ -1967,21 +2113,24 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, uint8_t *dest,
ngtcp2_ssize nwrite;
ngtcp2_ssize res = 0;
- nwrite = conn_write_handshake_pkt(conn, dest, destlen, NGTCP2_PKT_INITIAL,
- early_datalen, ts);
- if (nwrite < 0) {
- assert(nwrite != NGTCP2_ERR_NOBUF);
- return nwrite;
- }
+ if (!conn->server && conn->hs_pktns->crypto.tx.ckm &&
+ !ngtcp2_acktr_empty(&conn->hs_pktns->acktr)) {
+ /* Discard Initial state here so that Handshake packet is not
+ padded. */
+ conn_discard_initial_state(conn, ts);
+ } else {
+ nwrite = conn_write_handshake_pkt(conn, dest, destlen, NGTCP2_PKT_INITIAL,
+ early_datalen, ts);
+ if (nwrite < 0) {
+ assert(nwrite != NGTCP2_ERR_NOBUF);
+ return nwrite;
+ }
- if (!conn->server && nwrite) {
- return nwrite;
+ res += nwrite;
+ dest += nwrite;
+ destlen -= (size_t)nwrite;
}
- res += nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
-
nwrite = conn_write_handshake_pkt(conn, dest, destlen, NGTCP2_PKT_HANDSHAKE,
0, ts);
if (nwrite < 0) {
@@ -1991,34 +2140,11 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, uint8_t *dest,
res += nwrite;
- return res;
-}
-
-static ngtcp2_ssize conn_write_server_handshake(ngtcp2_conn *conn,
- uint8_t *dest, size_t destlen,
- ngtcp2_tstamp ts) {
- ngtcp2_ssize nwrite;
- ngtcp2_ssize res = 0;
-
- nwrite = conn_write_handshake_pkts(conn, dest, destlen, 0, ts);
- if (nwrite < 0) {
- assert(nwrite != NGTCP2_ERR_NOBUF);
- return nwrite;
- }
-
- res += nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
-
- /* Acknowledge 0-RTT packet here. */
- if (conn->pktns.crypto.tx.ckm) {
- nwrite = conn_write_ack_pkt(conn, dest, destlen, NGTCP2_PKT_SHORT, ts);
- if (nwrite < 0) {
- assert(nwrite != NGTCP2_ERR_NOBUF);
- return nwrite;
- }
-
- res += nwrite;
+ if (!conn->server && conn->hs_pktns->crypto.tx.ckm && nwrite) {
+ /* 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);
}
return res;
@@ -2055,8 +2181,12 @@ static int conn_should_send_max_stream_data(ngtcp2_conn *conn,
ngtcp2_strm *strm) {
uint64_t win = conn_initial_stream_rx_offset(conn, strm->stream_id);
uint64_t inc = strm->rx.unsent_max_offset - strm->rx.max_offset;
+ ngtcp2_conn_stat *cstat = &conn->cstat;
- return win < 2 * inc || inc >= 10 * NGTCP2_MAX_DGRAM_SIZE;
+ return win < 2 * inc ||
+ (cstat->min_rtt != UINT64_MAX &&
+ 2 * cstat->recv_rate_sec * cstat->min_rtt / NGTCP2_SECONDS >
+ win - inc);
}
/*
@@ -2065,9 +2195,12 @@ 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;
+ ngtcp2_conn_stat *cstat = &conn->cstat;
return conn->local.settings.transport_params.initial_max_data < 2 * inc ||
- inc >= 10 * NGTCP2_MAX_DGRAM_SIZE;
+ (cstat->min_rtt != UINT64_MAX &&
+ 2 * cstat->recv_rate_sec * cstat->min_rtt / NGTCP2_SECONDS >
+ conn->local.settings.transport_params.initial_max_data - inc);
}
/*
@@ -2076,7 +2209,8 @@ static int conn_should_send_max_data(ngtcp2_conn *conn) {
* remote endpoint.
*/
static size_t conn_required_num_new_connection_id(ngtcp2_conn *conn) {
- size_t n, len = ngtcp2_ksl_len(&conn->scid.set);
+ uint64_t n;
+ size_t len = ngtcp2_ksl_len(&conn->scid.set);
if (len >= NGTCP2_MAX_SCID_POOL_SIZE) {
return 0;
@@ -2088,7 +2222,7 @@ 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;
- return ngtcp2_min(NGTCP2_MAX_SCID_POOL_SIZE, n) - len;
+ return (size_t)ngtcp2_min(NGTCP2_MAX_SCID_POOL_SIZE, n) - len;
}
/*
@@ -2113,7 +2247,6 @@ static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) {
ngtcp2_frame_chain *nfrc;
ngtcp2_pktns *pktns = &conn->pktns;
ngtcp2_scid *scid;
- ngtcp2_ksl_key key;
ngtcp2_ksl_it it;
for (i = 0; i < need; ++i) {
@@ -2127,10 +2260,9 @@ static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) {
}
/* Assert uniqueness */
- it =
- ngtcp2_ksl_lower_bound(&conn->scid.set, ngtcp2_ksl_key_ptr(&key, &cid));
+ it = ngtcp2_ksl_lower_bound(&conn->scid.set, &cid);
if (!ngtcp2_ksl_it_end(&it) &&
- ngtcp2_cid_eq(ngtcp2_ksl_it_key(&it).ptr, &cid)) {
+ ngtcp2_cid_eq(ngtcp2_ksl_it_key(&it), &cid)) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -2143,8 +2275,7 @@ static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) {
ngtcp2_scid_init(scid, seq, &cid, token);
- rv = ngtcp2_ksl_insert(&conn->scid.set, NULL,
- ngtcp2_ksl_key_ptr(&key, &scid->cid), scid);
+ rv = ngtcp2_ksl_insert(&conn->scid.set, NULL, &scid->cid, scid);
if (rv != 0) {
ngtcp2_mem_free(conn->mem, scid);
return rv;
@@ -2171,21 +2302,22 @@ static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) {
/*
* conn_compute_pto computes the current PTO.
*/
-static ngtcp2_duration conn_compute_pto(ngtcp2_conn *conn) {
- ngtcp2_rcvry_stat *rcs = &conn->rcs;
- ngtcp2_duration var = ngtcp2_max(4 * rcs->rttvar, NGTCP2_GRANULARITY);
+static ngtcp2_duration conn_compute_pto(ngtcp2_conn *conn,
+ ngtcp2_pktns *pktns) {
+ ngtcp2_conn_stat *cstat = &conn->cstat;
+ ngtcp2_duration var = ngtcp2_max(4 * cstat->rttvar, NGTCP2_GRANULARITY);
ngtcp2_duration max_ack_delay =
- (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)
+ pktns->rtb.pktns_id == NGTCP2_PKTNS_ID_APP
? conn->remote.transport_params.max_ack_delay
- : NGTCP2_DEFAULT_MAX_ACK_DELAY;
- return rcs->smoothed_rtt + var + max_ack_delay;
+ : 0;
+ return cstat->smoothed_rtt + var + max_ack_delay;
}
/*
* conn_remove_retired_connection_id removes the already retired
- * connection ID. It waits RTT * 2 before actually removing a
- * connection ID after it receives RETIRE_CONNECTION_ID from peer to
- * catch reordered packets.
+ * connection ID. It waits PTO before actually removing a connection
+ * ID after it receives RETIRE_CONNECTION_ID from peer to catch
+ * reordered packets.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@@ -2197,9 +2329,8 @@ static ngtcp2_duration conn_compute_pto(ngtcp2_conn *conn) {
*/
static int conn_remove_retired_connection_id(ngtcp2_conn *conn,
ngtcp2_tstamp ts) {
- ngtcp2_duration timeout = conn_compute_pto(conn);
+ ngtcp2_duration timeout = conn_compute_pto(conn, &conn->pktns);
ngtcp2_scid *scid;
- ngtcp2_ksl_key key;
ngtcp2_dcid *dcid;
int rv;
@@ -2217,8 +2348,7 @@ static int conn_remove_retired_connection_id(ngtcp2_conn *conn,
return rv;
}
- ngtcp2_ksl_remove(&conn->scid.set, NULL,
- ngtcp2_ksl_key_ptr(&key, &scid->cid));
+ ngtcp2_ksl_remove(&conn->scid.set, NULL, &scid->cid);
ngtcp2_pq_pop(&conn->scid.used);
ngtcp2_mem_free(conn->mem, scid);
@@ -2322,6 +2452,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
size_t min_pktlen = conn_min_short_pktlen(conn);
int padded = 0;
int credit_expanded = 0;
+ ngtcp2_cc_pkt cc_pkt;
/* Return 0 if destlen is less than minimum packet length which can
trigger Stateless Reset */
@@ -2517,11 +2648,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
break;
}
- if ((*pfrc)->fr.type == NGTCP2_FRAME_RETIRE_CONNECTION_ID) {
- assert(conn->dcid.num_retire_queued);
- --conn->dcid.num_retire_queued;
- }
-
pkt_empty = 0;
rtb_entry_flags |= NGTCP2_RTB_FLAG_ACK_ELICITING;
pfrc = &(*pfrc)->next;
@@ -2789,25 +2915,27 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
if (pkt_empty) {
assert(rv == 0 || NGTCP2_ERR_NOBUF == rv);
- if (rv == 0 && stream_blocked) {
+ if (rv == 0 && stream_blocked && ngtcp2_conn_get_max_data_left(conn)) {
return NGTCP2_ERR_STREAM_DATA_BLOCKED;
}
- return 0;
- }
- if (stream_more) {
+ if (conn->pktns.rtb.probe_pkt_left == 0) {
+ return 0;
+ }
+ } else if (stream_more) {
conn->pkt.pfrc = pfrc;
conn->pkt.pkt_empty = pkt_empty;
conn->pkt.rtb_entry_flags = rtb_entry_flags;
conn->pkt.hd_logged = hd_logged;
conn->flags |= NGTCP2_CONN_FLAG_PPE_PENDING;
- if (stream_blocked) {
- return NGTCP2_ERR_STREAM_DATA_BLOCKED;
- }
if (send_stream) {
return NGTCP2_ERR_WRITE_STREAM_MORE;
}
+
+ if (ngtcp2_conn_get_max_data_left(conn) && stream_blocked) {
+ return NGTCP2_ERR_STREAM_DATA_BLOCKED;
+ }
}
if (!(rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING)) {
@@ -2818,8 +2946,13 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr);
if (rv != 0) {
assert(rv == NGTCP2_ERR_NOBUF);
+ /* TODO If buffer is too small, PING cannot be written if
+ packet is still empty. */
} else {
rtb_entry_flags |= NGTCP2_RTB_FLAG_ACK_ELICITING;
+ if (pktns->rtb.probe_pkt_left) {
+ rtb_entry_flags |= NGTCP2_RTB_FLAG_PROBE;
+ }
pktns->tx.num_non_ack_pkt = 0;
}
} else {
@@ -2852,6 +2985,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
return nwrite;
}
+ ++cc->ckm->use_count;
+
ngtcp2_qlog_pkt_sent_end(&conn->qlog, hd, (size_t)nwrite);
if ((rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) || padded) {
@@ -2868,6 +3003,12 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
*pfrc = NULL;
}
+ if ((rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
+ pktns->rtb.num_ack_eliciting == 0 && conn->cc.event) {
+ conn->cc.event(&conn->cc, &conn->cstat, NGTCP2_CC_EVENT_TYPE_TX_START,
+ ts);
+ }
+
rv = conn_on_pkt_sent(conn, &pktns->rtb, ent);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));
@@ -2875,15 +3016,31 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
return rv;
}
- if ((rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
- (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE)) {
- conn_restart_timer_on_write(conn, ts);
+ if (rtb_entry_flags & NGTCP2_RTB_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_APP, ts));
+ }
+
+ if (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE) {
+ conn_restart_timer_on_write(conn, ts);
+ }
}
}
conn->flags &= (uint16_t)~NGTCP2_CONN_FLAG_PPE_PENDING;
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->rcs, &conn->ccs);
+ if (pktns->rtb.probe_pkt_left &&
+ (rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING)) {
+ --pktns->rtb.probe_pkt_left;
+
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "probe pkt size=%td",
+ nwrite);
+ }
+
+ ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
++pktns->tx.last_pkt_num;
@@ -2905,7 +3062,6 @@ ngtcp2_conn_write_single_frame_pkt(ngtcp2_conn *conn, uint8_t *dest,
uint8_t flags;
ngtcp2_rtb_entry *rtbent;
int padded = 0;
- size_t pktlen;
switch (type) {
case NGTCP2_PKT_INITIAL:
@@ -2971,15 +3127,6 @@ ngtcp2_conn_write_single_frame_pkt(ngtcp2_conn *conn, uint8_t *dest,
lfr.padding.len = ngtcp2_ppe_padding_hp_sample(&ppe);
}
if (lfr.padding.len) {
- if (fr->type == NGTCP2_FRAME_ACK) {
- /* If PADDING is added, the packet suddenly gets CWND
- limited. */
- pktlen = ngtcp2_ppe_pktlen(&ppe);
- if (pktlen > conn_cwnd_left(conn)) {
- return 0;
- }
- }
-
padded = 1;
ngtcp2_log_tx_fr(&conn->log, &hd, &lfr);
ngtcp2_qlog_write_frame(&conn->qlog, &lfr);
@@ -2990,6 +3137,8 @@ ngtcp2_conn_write_single_frame_pkt(ngtcp2_conn *conn, uint8_t *dest,
return nwrite;
}
+ ++cc.ckm->use_count;
+
ngtcp2_qlog_pkt_sent_end(&conn->qlog, &hd, (size_t)nwrite);
/* Do this when we are sure that there is no error. */
@@ -3017,7 +3166,7 @@ ngtcp2_conn_write_single_frame_pkt(ngtcp2_conn *conn, uint8_t *dest,
}
}
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->rcs, &conn->ccs);
+ ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
++pktns->tx.last_pkt_num;
@@ -3048,194 +3197,6 @@ static void conn_process_early_rtb(ngtcp2_conn *conn) {
}
/*
- * conn_write_probe_ping writes probe packet containing PING frame
- * (and optionally ACK frame) to the buffer pointed by |dest| of
- * length |destlen|. Probe packet is always Short packet. This
- * function might return 0 if it cannot write packet (e.g., |destlen|
- * is too small).
- *
- * This function returns the number of bytes written to |dest|, or one
- * of the following negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static ngtcp2_ssize conn_write_probe_ping(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, ngtcp2_tstamp ts) {
- ngtcp2_ppe ppe;
- ngtcp2_pkt_hd hd;
- ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_crypto_cc cc;
- ngtcp2_frame_chain *frc = NULL;
- ngtcp2_rtb_entry *ent;
- ngtcp2_frame *ackfr = NULL, lfr;
- int rv;
- ngtcp2_ssize nwrite;
-
- assert(pktns->crypto.tx.ckm);
-
- cc.aead_overhead = conn->crypto.aead_overhead;
- cc.encrypt = conn->callbacks.encrypt;
- cc.hp_mask = conn->callbacks.hp_mask;
- cc.aead = pktns->crypto.ctx.aead;
- cc.hp = pktns->crypto.ctx.hp;
- cc.ckm = pktns->crypto.tx.ckm;
- cc.hp_key = pktns->crypto.tx.hp_key;
-
- ngtcp2_pkt_hd_init(
- &hd,
- (pktns->crypto.tx.ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE)
- ? NGTCP2_PKT_FLAG_KEY_PHASE
- : NGTCP2_PKT_FLAG_NONE,
- NGTCP2_PKT_SHORT, &conn->dcid.current.cid, NULL,
- pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), conn->version,
- 0);
-
- ngtcp2_ppe_init(&ppe, dest, destlen, &cc);
-
- rv = ngtcp2_ppe_encode_hd(&ppe, &hd);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- return 0;
- }
-
- if (!ngtcp2_ppe_ensure_hp_sample(&ppe)) {
- return 0;
- }
-
- ngtcp2_log_tx_pkt_hd(&conn->log, &hd);
- ngtcp2_qlog_pkt_sent_start(&conn->qlog, &hd);
-
- rv = ngtcp2_frame_chain_new(&frc, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- frc->fr.type = NGTCP2_FRAME_PING;
-
- rv = conn_ppe_write_frame(conn, &ppe, &hd, &frc->fr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- rv = 0;
- goto fail;
- }
-
- rv = conn_create_ack_frame(
- conn, &ackfr, &pktns->acktr, NGTCP2_PKT_SHORT, ts,
- conn_compute_ack_delay(conn),
- conn->local.settings.transport_params.ack_delay_exponent);
- if (rv != 0) {
- goto fail;
- }
-
- if (ackfr) {
- rv = conn_ppe_write_frame(conn, &ppe, &hd, ackfr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- } else {
- ngtcp2_acktr_commit_ack(&pktns->acktr);
- ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, ackfr->ack.largest_ack);
- }
- }
-
- lfr.type = NGTCP2_FRAME_PADDING;
- lfr.padding.len = ngtcp2_ppe_padding_size(&ppe, conn_min_short_pktlen(conn));
- if (lfr.padding.len) {
- ngtcp2_log_tx_fr(&conn->log, &hd, &lfr);
- ngtcp2_qlog_write_frame(&conn->qlog, &lfr);
- }
-
- nwrite = ngtcp2_ppe_final(&ppe, NULL);
- if (nwrite < 0) {
- rv = (int)nwrite;
- goto fail;
- }
-
- ngtcp2_qlog_pkt_sent_end(&conn->qlog, &hd, (size_t)nwrite);
-
- rv = ngtcp2_rtb_entry_new(
- &ent, &hd, frc, ts, (size_t)nwrite,
- NGTCP2_RTB_FLAG_PROBE | NGTCP2_RTB_FLAG_ACK_ELICITING, conn->mem);
- if (rv != 0) {
- goto fail;
- }
-
- rv = conn_on_pkt_sent(conn, &pktns->rtb, ent);
- if (rv != 0) {
- ngtcp2_rtb_entry_del(ent, conn->mem);
- return rv;
- }
-
- if (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE) {
- conn_restart_timer_on_write(conn, ts);
- }
-
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->rcs, &conn->ccs);
-
- ++pktns->tx.last_pkt_num;
-
- return nwrite;
-
-fail:
- ngtcp2_frame_chain_del(frc, conn->mem);
-
- return rv;
-}
-
-/*
- * conn_write_probe_pkt writes a QUIC Short packet as probe packet.
- * The packet is written to the buffer pointed by |dest| of length
- * |destlen|. This function can send new stream data. In order to
- * send stream data, specify the underlying stream to |strm|. If
- * |fin| is set to nonzero, it signals that the given data is the
- * final portion of the stream. |datav| vector of length |datavcnt|
- * specify stream data to send. If no stream data to send, set |strm|
- * to NULL. The number of bytes sent to the stream is assigned to
- * |*pdatalen|. If 0 length STREAM data is sent, 0 is assigned to
- * |*pdatalen|. The caller should initialize |*pdatalen| to -1.
- *
- * This function returns the number of bytes written to the buffer
- * pointed by |dest|, or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_STREAM_DATA_BLOCKED
- * Stream data could not be written because of flow control.
- */
-static ngtcp2_ssize conn_write_probe_pkt(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, ngtcp2_ssize *pdatalen,
- ngtcp2_strm *strm, int fin,
- const ngtcp2_vec *datav,
- size_t datavcnt, ngtcp2_tstamp ts) {
- ngtcp2_ssize nwrite;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "transmit probe pkt left=%zu",
- conn->pktns.rtb.probe_pkt_left);
-
- /* a probe packet is not blocked by cwnd. */
- nwrite = conn_write_pkt(conn, dest, destlen, pdatalen, NGTCP2_PKT_SHORT, strm,
- fin, datav, datavcnt, NGTCP2_WRITE_PKT_FLAG_NONE, ts);
- if (nwrite == 0 || nwrite == NGTCP2_ERR_STREAM_DATA_BLOCKED) {
- nwrite = conn_write_probe_ping(conn, dest, destlen, ts);
- }
- if (nwrite <= 0) {
- return nwrite;
- }
-
- --conn->pktns.rtb.probe_pkt_left;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "probe pkt size=%td",
- nwrite);
-
- return nwrite;
-}
-
-/*
* conn_handshake_remnants_left returns nonzero if there may be
* handshake packets the local endpoint has to send, including new
* packets and lost ones.
@@ -3245,9 +3206,9 @@ static int conn_handshake_remnants_left(ngtcp2_conn *conn) {
ngtcp2_pktns *hs_pktns = conn->hs_pktns;
return !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) ||
- (in_pktns && (ngtcp2_rtb_num_ack_eliciting(&in_pktns->rtb) ||
+ (in_pktns && (in_pktns->rtb.num_ack_eliciting ||
ngtcp2_ksl_len(&in_pktns->crypto.tx.frq))) ||
- (hs_pktns && (ngtcp2_rtb_num_ack_eliciting(&hs_pktns->rtb) ||
+ (hs_pktns && (hs_pktns->rtb.num_ack_eliciting ||
ngtcp2_ksl_len(&hs_pktns->crypto.tx.frq)));
}
@@ -3450,11 +3411,11 @@ static ngtcp2_ssize conn_write_path_challenge(ngtcp2_conn *conn,
ngtcp2_ssize ngtcp2_conn_write_pkt(ngtcp2_conn *conn, ngtcp2_path *path,
uint8_t *dest, size_t destlen,
ngtcp2_tstamp ts) {
- return ngtcp2_conn_writev_stream(
- conn, path, dest, destlen,
- /* pdatalen = */ NULL, NGTCP2_WRITE_STREAM_FLAG_NONE,
- /* stream_id = */ -1,
- /* fin = */ 0, /* datav = */ NULL, /* datavcnt = */ 0, ts);
+ return ngtcp2_conn_writev_stream(conn, path, dest, destlen,
+ /* pdatalen = */ NULL,
+ NGTCP2_WRITE_STREAM_FLAG_NONE,
+ /* stream_id = */ -1,
+ /* datav = */ NULL, /* datavcnt = */ 0, ts);
}
/*
@@ -3481,6 +3442,7 @@ static int conn_on_version_negotiation(ngtcp2_conn *conn,
uint32_t *p;
int rv = 0;
size_t nsv;
+ size_t i;
if (payloadlen % sizeof(uint32_t)) {
return NGTCP2_ERR_INVALID_ARGUMENT;
@@ -3495,28 +3457,41 @@ static int conn_on_version_negotiation(ngtcp2_conn *conn,
p = sv;
}
- /* TODO Just move to the terminal state for now in order not to send
- CONNECTION_CLOSE frame. */
- conn->state = NGTCP2_CS_DRAINING;
-
nsv = ngtcp2_pkt_decode_version_negotiation(p, payload, payloadlen);
ngtcp2_log_rx_vn(&conn->log, hd, p, nsv);
+ for (i = 0; i < nsv; ++i) {
+ if (p[i] == conn->version) {
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
+ "ignore Version Negotiation because it contains version "
+ "selected by client");
+
+ rv = NGTCP2_ERR_INVALID_ARGUMENT;
+ goto fin;
+ }
+ }
+
if (conn->callbacks.recv_version_negotiation) {
rv = conn->callbacks.recv_version_negotiation(conn, hd, p, nsv,
conn->user_data);
+ if (rv != 0) {
+ rv = NGTCP2_ERR_CALLBACK_FAILURE;
+ }
}
- if (p != sv) {
- ngtcp2_mem_free(conn->mem, p);
+ if (rv == 0) {
+ /* TODO Just move to the terminal state for now in order not to
+ send CONNECTION_CLOSE frame. */
+ conn->state = NGTCP2_CS_DRAINING;
}
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
+fin:
+ if (p != sv) {
+ ngtcp2_mem_free(conn->mem, p);
}
- return 0;
+ return rv;
}
static uint64_t conn_tx_strmq_first_cycle(ngtcp2_conn *conn) {
@@ -3546,7 +3521,6 @@ static int conn_resched_frames(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
ngtcp2_frame_chain *frc;
ngtcp2_stream *sfr;
ngtcp2_strm *strm;
- ngtcp2_ksl_key key;
int rv;
if (*pfrc == NULL) {
@@ -3587,8 +3561,7 @@ static int conn_resched_frames(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
frc->next = NULL;
rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- ngtcp2_ksl_key_ptr(&key, &frc->fr.crypto.offset),
- frc);
+ &frc->fr.crypto.offset, frc);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));
ngtcp2_frame_chain_del(frc, conn->mem);
@@ -3628,17 +3601,19 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
size_t hdpktlen, const uint8_t *pkt, size_t pktlen) {
int rv;
ngtcp2_pkt_retry retry;
- uint8_t *p;
ngtcp2_pktns *in_pktns = conn->in_pktns;
ngtcp2_rtb *rtb = &conn->pktns.rtb;
- ngtcp2_rtb *in_rtb = &in_pktns->rtb;
+ ngtcp2_rtb *in_rtb;
uint8_t cidbuf[sizeof(retry.odcid.data) * 2 + 1];
ngtcp2_frame_chain *frc = NULL;
+ ngtcp2_vec *token;
- if (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) {
+ if (!in_pktns || conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) {
return 0;
}
+ in_rtb = &in_pktns->rtb;
+
rv = ngtcp2_pkt_decode_retry(&retry, pkt + hdpktlen, pktlen - hdpktlen);
if (rv != 0) {
return rv;
@@ -3658,7 +3633,7 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
(const char *)ngtcp2_encode_hex(cidbuf, retry.odcid.data,
retry.odcid.datalen));
- if (retry.tokenlen == 0) {
+ if (retry.token.len == 0) {
return NGTCP2_ERR_PROTO;
}
@@ -3669,12 +3644,13 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
/* DCID must be updated before invoking callback because client
generates new initial keys there. */
conn->dcid.current.cid = hd->scid;
+ conn->retry_scid = hd->scid;
conn->flags |= NGTCP2_CONN_FLAG_RECV_RETRY;
assert(conn->callbacks.recv_retry);
- rv = conn->callbacks.recv_retry(conn, hd, &retry, conn->user_data);
+ rv = conn->callbacks.recv_retry(conn, hd, conn->user_data);
if (rv != 0) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -3683,7 +3659,7 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
/* Just freeing memory is dangerous because we might free twice. */
- ngtcp2_rtb_remove_all(rtb, &frc);
+ ngtcp2_rtb_remove_all(rtb, &frc, &conn->cstat);
rv = conn_resched_frames(conn, &conn->pktns, &frc);
if (rv != 0) {
@@ -3693,7 +3669,7 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
}
frc = NULL;
- ngtcp2_rtb_remove_all(in_rtb, &frc);
+ ngtcp2_rtb_remove_all(in_rtb, &frc, &conn->cstat);
rv = conn_resched_frames(conn, in_pktns, &frc);
if (rv != 0) {
@@ -3702,17 +3678,19 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
return rv;
}
- assert(conn->token.begin == NULL);
+ token = &conn->local.settings.token;
- p = ngtcp2_mem_malloc(conn->mem, retry.tokenlen);
- if (p == NULL) {
+ ngtcp2_mem_free(conn->mem, token->base);
+ token->base = NULL;
+ token->len = 0;
+
+ token->base = ngtcp2_mem_malloc(conn->mem, retry.token.len);
+ if (token->base == NULL) {
return NGTCP2_ERR_NOMEM;
}
- ngtcp2_buf_init(&conn->token, p, retry.tokenlen);
+ token->len = retry.token.len;
- ngtcp2_cpymem(conn->token.begin, retry.token, retry.tokenlen);
- conn->token.pos = conn->token.begin;
- conn->token.last = conn->token.pos + retry.tokenlen;
+ ngtcp2_cpymem(token->base, retry.token.base, retry.token.len);
conn_reset_congestion_state(conn);
@@ -3720,12 +3698,12 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
}
int ngtcp2_conn_detect_lost_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
- ngtcp2_rcvry_stat *rcs, ngtcp2_tstamp ts) {
+ ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) {
ngtcp2_frame_chain *frc = NULL;
int rv;
- ngtcp2_duration pto = conn_compute_pto(conn);
+ ngtcp2_duration pto = conn_compute_pto(conn, pktns);
- ngtcp2_rtb_detect_lost_pkt(&pktns->rtb, &frc, rcs, pto, ts);
+ ngtcp2_rtb_detect_lost_pkt(&pktns->rtb, &frc, cstat, pto, ts);
rv = conn_resched_frames(conn, pktns, &frc);
if (rv != 0) {
@@ -3758,8 +3736,8 @@ static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr,
ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) {
int rv;
ngtcp2_frame_chain *frc = NULL;
- ngtcp2_rcvry_stat *rcs = &conn->rcs;
ngtcp2_ssize num_acked;
+ ngtcp2_conn_stat *cstat = &conn->cstat;
if (pktns->tx.last_pkt_num < fr->largest_ack) {
return NGTCP2_ERR_PROTO;
@@ -3772,7 +3750,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, pkt_ts, ts);
+ num_acked =
+ ngtcp2_rtb_recv_ack(&pktns->rtb, fr, &conn->cstat, conn, pkt_ts, ts);
if (num_acked < 0) {
/* TODO assert this */
assert(ngtcp2_err_is_fatal((int)num_acked));
@@ -3784,14 +3763,20 @@ static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr,
return 0;
}
- rv = ngtcp2_conn_detect_lost_pkt(conn, pktns, &conn->rcs, ts);
+ rv = ngtcp2_conn_detect_lost_pkt(conn, pktns, &conn->cstat, ts);
if (rv != 0) {
return rv;
}
- rcs->pto_count = 0;
pktns->rtb.probe_pkt_left = 0;
+ if (cstat->pto_count &&
+ (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);
+ }
+
ngtcp2_conn_set_loss_detection_timer(conn, ts);
return 0;
@@ -4144,13 +4129,18 @@ static void conn_recv_path_challenge(ngtcp2_conn *conn,
* conn_reset_congestion_state resets congestion state.
*/
static void conn_reset_congestion_state(ngtcp2_conn *conn) {
- rcvry_stat_reset(&conn->rcs);
- cc_stat_reset(&conn->ccs);
+ conn_reset_conn_stat(conn, &conn->cstat);
+
+ conn_reset_rx_rate(conn);
+
+ conn->cc.reset(&conn->cc);
if (conn->hs_pktns) {
- conn->hs_pktns->rtb.cc_pkt_num = conn->hs_pktns->tx.last_pkt_num + 1;
+ ngtcp2_rtb_reset_cc_state(&conn->hs_pktns->rtb,
+ conn->hs_pktns->tx.last_pkt_num + 1);
}
- conn->pktns.rtb.cc_pkt_num = conn->pktns.tx.last_pkt_num + 1;
+ ngtcp2_rtb_reset_cc_state(&conn->pktns.rtb, conn->pktns.tx.last_pkt_num + 1);
+ ngtcp2_rst_init(&conn->rst);
}
static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr,
@@ -4223,7 +4213,6 @@ static int pktns_pkt_num_is_duplicate(ngtcp2_pktns *pktns, int64_t pkt_num) {
static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num) {
int rv;
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
ngtcp2_range range;
if (pktns->rx.max_pkt_num + 1 != pkt_num) {
@@ -4240,59 +4229,20 @@ static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num) {
if (ngtcp2_ksl_len(&pktns->rx.pngap.gap) > 256) {
it = ngtcp2_ksl_begin(&pktns->rx.pngap.gap);
- range = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it).ptr;
- ngtcp2_ksl_remove(&pktns->rx.pngap.gap, NULL,
- ngtcp2_ksl_key_ptr(&key, &range));
+ range = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
+ ngtcp2_ksl_remove(&pktns->rx.pngap.gap, NULL, &range);
}
return 0;
}
-static void conn_discard_pktns(ngtcp2_conn *conn, ngtcp2_pktns *pktns) {
- uint64_t bytes_in_flight;
-
- bytes_in_flight = ngtcp2_rtb_get_bytes_in_flight(&pktns->rtb);
-
- assert(conn->ccs.bytes_in_flight >= bytes_in_flight);
-
- conn->ccs.bytes_in_flight -= bytes_in_flight;
-
- pktns_del(pktns, conn->mem);
-}
-
-/*
- * conn_discard_initial_state discards state for Initial packet number
- * space.
- */
-static void conn_discard_initial_state(ngtcp2_conn *conn) {
- if (!conn->in_pktns) {
- return;
- }
-
- conn_discard_pktns(conn, conn->in_pktns);
- conn->in_pktns = NULL;
-}
-
-/*
- * conn_discard_handshake_state discards state for Handshake packet
- * number space.
- */
-static void conn_discard_handshake_state(ngtcp2_conn *conn) {
- if (!conn->hs_pktns) {
- return;
- }
-
- conn_discard_pktns(conn, conn->hs_pktns);
- conn->hs_pktns = NULL;
-}
-
/*
* verify_token verifies |hd| contains |token| in its token field. It
* returns 0 if it succeeds, or NGTCP2_ERR_PROTO.
*/
static int verify_token(const ngtcp2_vec *token, const ngtcp2_pkt_hd *hd) {
- if (token->len == hd->tokenlen &&
- ngtcp2_cmemeq(token->base, hd->token, token->len)) {
+ if (token->len == hd->token.len &&
+ ngtcp2_cmemeq(token->base, hd->token.base, token->len)) {
return 0;
}
return NGTCP2_ERR_PROTO;
@@ -4412,12 +4362,7 @@ static ngtcp2_ssize conn_recv_handshake_pkt(ngtcp2_conn *conn,
return NGTCP2_ERR_DISCARD_PKT;
}
- /* TODO Do not change state here? */
- rv = conn_verify_dcid(conn, NULL, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
+ if (!ngtcp2_cid_eq(&conn->oscid, &hd.dcid)) {
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
"packet was ignored because of mismatched DCID");
return NGTCP2_ERR_DISCARD_PKT;
@@ -4534,12 +4479,18 @@ static ngtcp2_ssize conn_recv_handshake_pkt(ngtcp2_conn *conn,
}
}
if ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) == 0) {
+ /* Set rcid here so that it is available to callback. If this
+ packet is discarded later in this function and no packet is
+ processed in this connection attempt so far, connection
+ will be dropped. */
+ conn->rcid = hd.dcid;
+
rv = conn_call_recv_client_initial(conn, &hd.dcid);
if (rv != 0) {
return rv;
}
}
- } else if (hd.tokenlen != 0) {
+ } else if (hd.token.len != 0) {
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
"packet was ignored because token is not empty");
return NGTCP2_ERR_DISCARD_PKT;
@@ -4697,12 +4648,9 @@ static ngtcp2_ssize conn_recv_handshake_pkt(ngtcp2_conn *conn,
if (hd.type == NGTCP2_PKT_INITIAL &&
!(conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED)) {
conn->flags |= NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED;
- if (conn->server) {
- conn->rcid = hd.dcid;
- } else {
+ if (!conn->server) {
conn->dcid.current.cid = hd.scid;
}
- conn->odcid = hd.scid;
}
ngtcp2_qlog_pkt_received_start(&conn->qlog, &hd);
@@ -4726,13 +4674,13 @@ static ngtcp2_ssize conn_recv_handshake_pkt(ngtcp2_conn *conn,
switch (fr->type) {
case NGTCP2_FRAME_ACK:
case NGTCP2_FRAME_ACK_ECN:
+ if (!conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) {
+ conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
+ }
rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts);
if (rv != 0) {
return rv;
}
- if (!conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) {
- conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
- }
break;
case NGTCP2_FRAME_PADDING:
break;
@@ -4781,7 +4729,7 @@ static ngtcp2_ssize conn_recv_handshake_pkt(ngtcp2_conn *conn,
conn_restart_timer_on_read(conn, ts);
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->rcs, &conn->ccs);
+ ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
return conn->state == NGTCP2_CS_DRAINING ? NGTCP2_ERR_DRAINING
: (ngtcp2_ssize)pktlen;
@@ -4801,7 +4749,7 @@ static int conn_recv_handshake_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path,
ngtcp2_tstamp ts) {
ngtcp2_ssize nread;
- conn->hs_recved += pktlen;
+ conn->cstat.bytes_recv += pktlen;
while (pktlen) {
nread = conn_recv_handshake_pkt(conn, path, pkt, pktlen, ts, ts);
@@ -4810,19 +4758,41 @@ static int conn_recv_handshake_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path,
return (int)nread;
}
- switch (nread) {
- case NGTCP2_ERR_DISCARD_PKT:
- return 0;
- case NGTCP2_ERR_DRAINING:
+ if (nread == NGTCP2_ERR_DRAINING) {
return NGTCP2_ERR_DRAINING;
}
- if (nread != NGTCP2_ERR_CRYPTO && (pkt[0] & NGTCP2_HEADER_FORM_BIT) &&
+ if ((pkt[0] & NGTCP2_HEADER_FORM_BIT) &&
/* Not a Version Negotiation packet */
pktlen > 4 && ngtcp2_get_uint32(&pkt[1]) > 0 &&
ngtcp2_pkt_get_type_long(pkt[0]) == NGTCP2_PKT_INITIAL) {
- break;
+ if (conn->server) {
+ /* If server discards first Initial, then drop connection
+ state. This is because SCID in packet might be corrupted
+ and the current connection state might wrongly discard
+ valid packet and prevent the handshake from
+ completing. */
+ if (conn->in_pktns && conn->in_pktns->rx.max_pkt_num == -1) {
+ /* If this is crypto related error, then return normally
+ in order to send CONNECTION_CLOSE with TLS alert (e.g.,
+ no_application_protocol). */
+ if (nread == NGTCP2_ERR_CRYPTO) {
+ return (int)nread;
+ }
+ return NGTCP2_ERR_DROP_CONN;
+ }
+ } else if (nread == NGTCP2_ERR_CRYPTO) {
+ /* If client gets crypto error from TLS stack, it is
+ unrecoverable, therefore drop connection. */
+ return (int)nread;
+ }
+ return 0;
}
+
+ if (nread == NGTCP2_ERR_DISCARD_PKT) {
+ return 0;
+ }
+
return (int)nread;
}
@@ -4913,6 +4883,8 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm,
const uint8_t *data;
int rv;
uint64_t offset;
+ uint32_t sdflags;
+ int handshake_completed = conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED;
for (;;) {
/* Stop calling callback if application has called
@@ -4931,10 +4903,16 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm,
offset = rx_offset;
rx_offset += datalen;
- rv = conn_call_recv_stream_data(conn, strm,
- (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) &&
- rx_offset == strm->rx.last_offset,
- offset, data, datalen);
+ sdflags = NGTCP2_STREAM_DATA_FLAG_NONE;
+ if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) &&
+ rx_offset == strm->rx.last_offset) {
+ sdflags |= NGTCP2_STREAM_DATA_FLAG_FIN;
+ }
+ if (!handshake_completed) {
+ sdflags |= NGTCP2_STREAM_DATA_FLAG_0RTT;
+ }
+
+ rv = conn_call_recv_stream_data(conn, strm, sdflags, offset, data, datalen);
if (rv != 0) {
return rv;
}
@@ -4943,6 +4921,8 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm,
}
}
+static int conn_on_crypto_timeout(ngtcp2_conn *conn, ngtcp2_pktns *pktns);
+
/*
* conn_recv_crypto is called when CRYPTO frame |fr| is received.
* |rx_offset_base| is the offset in the entire TLS handshake stream.
@@ -4984,6 +4964,29 @@ static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
rx_offset = ngtcp2_strm_rx_offset(crypto);
if (fr_end_offset <= rx_offset) {
+ if (conn->server && crypto_level == NGTCP2_CRYPTO_LEVEL_INITIAL) {
+ /* recovery draft: Speeding Up Handshake Completion
+
+ When a server receives an Initial packet containing duplicate
+ CRYPTO data, it can assume the client did not receive all of
+ the server's CRYPTO data sent in Initial packets, or the
+ client's estimated RTT is too small. ... To speed up
+ handshake completion under these conditions, an endpoint MAY
+ send a packet containing unacknowledged CRYPTO data earlier
+ than the PTO expiry, subject to address validation limits;
+ ... */
+ rv = conn_on_crypto_timeout(conn, conn->in_pktns);
+ if (rv != 0) {
+ return rv;
+ }
+ conn->in_pktns->rtb.probe_pkt_left = 1;
+
+ rv = conn_on_crypto_timeout(conn, conn->hs_pktns);
+ if (rv != 0) {
+ return rv;
+ }
+ conn->hs_pktns->rtb.probe_pkt_left = 1;
+ }
return 0;
}
@@ -4995,7 +4998,7 @@ static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
error because key is generated after consuming all data in the
previous encryption level. */
if (fr->offset <= rx_offset) {
- size_t ncut = rx_offset - fr->offset;
+ size_t ncut = (size_t)(rx_offset - fr->offset);
const uint8_t *data = fr->data[0].base + ncut;
size_t datalen = fr->data[0].len - ncut;
uint64_t offset = rx_offset;
@@ -5032,7 +5035,7 @@ static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
* conn_max_data_violated returns nonzero if receiving |datalen|
* violates connection flow control on local endpoint.
*/
-static int conn_max_data_violated(ngtcp2_conn *conn, size_t datalen) {
+static int conn_max_data_violated(ngtcp2_conn *conn, uint64_t datalen) {
return conn->rx.max_offset - conn->rx.offset < datalen;
}
@@ -5060,7 +5063,8 @@ static int conn_max_data_violated(ngtcp2_conn *conn, size_t datalen) {
* STREAM frame has strictly larger end offset than it is
* permitted.
*/
-static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) {
+static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr,
+ ngtcp2_tstamp ts) {
int rv;
ngtcp2_strm *strm;
ngtcp2_idtr *idtr;
@@ -5068,6 +5072,7 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) {
int local_stream;
int bidi;
size_t datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
+ uint32_t sdflags = NGTCP2_STREAM_DATA_FLAG_NONE;
local_stream = conn_local_stream(conn, fr->stream_id);
bidi = bidi_stream(fr->stream_id);
@@ -5139,7 +5144,7 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) {
}
if (strm->rx.last_offset < fr_end_offset) {
- size_t len = fr_end_offset - strm->rx.last_offset;
+ uint64_t len = fr_end_offset - strm->rx.last_offset;
if (conn_max_data_violated(conn, len)) {
return NGTCP2_ERR_FLOW_CONTROL;
@@ -5179,15 +5184,6 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) {
return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm,
strm->app_error_code);
}
-
- if (fr_end_offset == rx_offset) {
- rv = conn_call_recv_stream_data(conn, strm, 1, rx_offset, NULL, 0);
- if (rv != 0) {
- return rv;
- }
- return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm,
- NGTCP2_NO_ERROR);
- }
}
} else {
if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) &&
@@ -5207,8 +5203,10 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) {
}
}
+ conn_update_recv_rate(conn, fr_end_offset - fr->offset, ts);
+
if (fr->offset <= rx_offset) {
- size_t ncut = rx_offset - fr->offset;
+ size_t ncut = (size_t)(rx_offset - fr->offset);
uint64_t offset = rx_offset;
const uint8_t *data;
int fin;
@@ -5231,7 +5229,14 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) {
rx_offset == strm->rx.last_offset;
if (fin || datalen) {
- rv = conn_call_recv_stream_data(conn, strm, fin, offset, data, datalen);
+ if (fin) {
+ sdflags |= NGTCP2_STREAM_DATA_FLAG_FIN;
+ }
+ if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
+ sdflags |= NGTCP2_STREAM_DATA_FLAG_0RTT;
+ }
+ rv = conn_call_recv_stream_data(conn, strm, sdflags, offset, data,
+ datalen);
if (rv != 0) {
return rv;
}
@@ -5323,7 +5328,13 @@ static int conn_stop_sending(ngtcp2_conn *conn, ngtcp2_strm *strm,
static void
handle_max_remote_streams_extension(uint64_t *punsent_max_remote_streams,
size_t n) {
- if (*punsent_max_remote_streams < NGTCP2_MAX_STREAMS - n) {
+ if (
+#if SIZE_MAX > UINT32_MAX
+ NGTCP2_MAX_STREAMS < n ||
+#endif /* SIZE_MAX > UINT32_MAX */
+ *punsent_max_remote_streams > (uint64_t)(NGTCP2_MAX_STREAMS - n)) {
+ *punsent_max_remote_streams = NGTCP2_MAX_STREAMS;
+ } else {
*punsent_max_remote_streams += n;
}
}
@@ -5991,16 +6002,29 @@ static int conn_recv_retire_connection_id(ngtcp2_conn *conn,
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
- * NGTCP2_ERR_FRAME_ENCODING:
+ * NGTCP2_ERR_FRAME_ENCODING
* Token is empty
+ * NGTCP2_ERR_PROTO:
+ * Server received NEW_TOKEN.
*/
static int conn_recv_new_token(ngtcp2_conn *conn, const ngtcp2_new_token *fr) {
- (void)conn;
+ int rv;
+
+ if (conn->server) {
+ return NGTCP2_ERR_PROTO;
+ }
- if (fr->tokenlen == 0) {
+ if (fr->token.len == 0) {
return NGTCP2_ERR_FRAME_ENCODING;
}
- /* TODO Not implemented yet*/
+
+ if (conn->callbacks.recv_new_token) {
+ rv = conn->callbacks.recv_new_token(conn, &fr->token, conn->user_data);
+ if (rv != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+
return 0;
}
@@ -6044,7 +6068,7 @@ static int conn_select_preferred_addr(ngtcp2_conn *conn) {
assert(conn->pv == NULL);
dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0);
- timeout = conn_compute_pto(conn);
+ timeout = 3 * conn_compute_pto(conn, &conn->pktns);
timeout =
ngtcp2_max(timeout, (ngtcp2_duration)(6ULL * NGTCP2_DEFAULT_INITIAL_RTT));
@@ -6078,7 +6102,7 @@ static int conn_select_preferred_addr(ngtcp2_conn *conn) {
* NGTCP2_ERR_CALLBACK_FAILURE
* User-defined callback function failed.
*/
-static int conn_recv_handshake_done(ngtcp2_conn *conn) {
+static int conn_recv_handshake_done(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
int rv;
if (conn->server) {
@@ -6089,9 +6113,10 @@ static int conn_recv_handshake_done(ngtcp2_conn *conn) {
return 0;
}
- conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED;
+ conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED |
+ NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
- conn_discard_handshake_state(conn);
+ conn_discard_handshake_state(conn, ts);
if (conn->callbacks.handshake_confirmed) {
rv = conn->callbacks.handshake_confirmed(conn, conn->user_data);
@@ -6100,6 +6125,10 @@ static int conn_recv_handshake_done(ngtcp2_conn *conn) {
}
}
+ /* Re-arm loss detection timer after handshake has been
+ confirmed. */
+ ngtcp2_conn_set_loss_detection_timer(conn, ts);
+
return 0;
}
@@ -6120,13 +6149,19 @@ static int conn_key_phase_changed(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd) {
static int conn_prepare_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
int rv;
ngtcp2_tstamp confirmed_ts = conn->crypto.key_update.confirmed_ts;
- ngtcp2_duration pto = conn_compute_pto(conn);
+ ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns);
ngtcp2_pktns *pktns = &conn->pktns;
ngtcp2_crypto_km *rx_ckm = pktns->crypto.rx.ckm;
ngtcp2_crypto_km *tx_ckm = pktns->crypto.tx.ckm;
ngtcp2_crypto_km *new_rx_ckm, *new_tx_ckm;
size_t secretlen, keylen, ivlen;
+ if ((conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) &&
+ (tx_ckm->use_count >= pktns->crypto.ctx.max_encryption ||
+ rx_ckm->use_count >= pktns->crypto.ctx.max_decryption_failure)) {
+ ngtcp2_conn_initiate_key_update(conn, ts);
+ }
+
if ((conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) ||
(confirmed_ts != UINT64_MAX && confirmed_ts + pto > ts)) {
return 0;
@@ -6282,7 +6317,7 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn,
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
"non-probing packet was received from new remote address");
- timeout = conn_compute_pto(conn);
+ timeout = 3 * conn_compute_pto(conn, &conn->pktns);
timeout =
ngtcp2_max(timeout, (ngtcp2_duration)(6ULL * NGTCP2_DEFAULT_INITIAL_RTT));
@@ -6396,13 +6431,13 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
switch (fr->type) {
case NGTCP2_FRAME_ACK:
case NGTCP2_FRAME_ACK_ECN:
+ if (!conn->server) {
+ conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
+ }
rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts);
if (rv != 0) {
return rv;
}
- if (!conn->server) {
- conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
- }
break;
case NGTCP2_FRAME_PADDING:
break;
@@ -6438,7 +6473,7 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
conn_restart_timer_on_read(conn, ts);
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->rcs, &conn->ccs);
+ ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
return 0;
}
@@ -6522,7 +6557,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
/* Quoted from spec: if subsequent packets of those types include
a different Source Connection ID, they MUST be discarded. */
- if (!ngtcp2_cid_eq(&conn->odcid, &hd.scid)) {
+ if (!ngtcp2_cid_eq(&conn->dcid.current.cid, &hd.scid)) {
ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
"packet was ignored because of mismatched SCID");
@@ -6610,48 +6645,6 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
- if (hd.flags & NGTCP2_PKT_FLAG_LONG_FORM) {
- switch (hd.type) {
- case NGTCP2_PKT_HANDSHAKE:
- rv = conn_verify_dcid(conn, NULL, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
- break;
- case NGTCP2_PKT_0RTT:
- if (!ngtcp2_cid_eq(&conn->rcid, &hd.dcid)) {
- rv = conn_verify_dcid(conn, NULL, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
- }
- break;
- default:
- /* Unreachable */
- assert(0);
- }
- } else {
- rv = conn_verify_dcid(conn, &new_cid_used, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
- }
-
if (hd.type == NGTCP2_PKT_SHORT) {
key_phase_bit_changed = conn_key_phase_changed(conn, &hd);
}
@@ -6705,6 +6698,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
assert(NGTCP2_ERR_TLS_DECRYPT == nwrite);
+ ++ckm->use_count;
+
if (hd.flags & NGTCP2_PKT_FLAG_LONG_FORM) {
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
"could not decrypt packet payload");
@@ -6739,15 +6734,53 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
}
if (hd.flags & NGTCP2_PKT_FLAG_LONG_FORM) {
- if (hd.type == NGTCP2_PKT_HANDSHAKE) {
+ switch (hd.type) {
+ case NGTCP2_PKT_HANDSHAKE:
+ rv = conn_verify_dcid(conn, NULL, &hd);
+ if (rv != 0) {
+ if (ngtcp2_err_is_fatal(rv)) {
+ return rv;
+ }
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
+ "packet was ignored because of mismatched DCID");
+ return NGTCP2_ERR_DISCARD_PKT;
+ }
+
rv = conn_recv_delayed_handshake_pkt(conn, &hd, pktlen, payload,
payloadlen, pkt_ts, ts);
if (rv < 0) {
return (ngtcp2_ssize)rv;
}
+
return (ngtcp2_ssize)pktlen;
+ case NGTCP2_PKT_0RTT:
+ if (!ngtcp2_cid_eq(&conn->rcid, &hd.dcid)) {
+ rv = conn_verify_dcid(conn, NULL, &hd);
+ if (rv != 0) {
+ if (ngtcp2_err_is_fatal(rv)) {
+ return rv;
+ }
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
+ "packet was ignored because of mismatched DCID");
+ return NGTCP2_ERR_DISCARD_PKT;
+ }
+ }
+ break;
+ default:
+ /* Unreachable */
+ assert(0);
}
} else {
+ rv = conn_verify_dcid(conn, &new_cid_used, &hd);
+ if (rv != 0) {
+ if (ngtcp2_err_is_fatal(rv)) {
+ return rv;
+ }
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
+ "packet was ignored because of mismatched DCID");
+ return NGTCP2_ERR_DISCARD_PKT;
+ }
+
conn->flags |= NGTCP2_CONN_FLAG_RECV_PROTECTED_PKT;
}
@@ -6792,6 +6825,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
case NGTCP2_FRAME_PATH_CHALLENGE:
case NGTCP2_FRAME_PATH_RESPONSE:
+ case NGTCP2_FRAME_CONNECTION_CLOSE:
+ case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
break;
default:
return NGTCP2_ERR_PROTO;
@@ -6812,17 +6847,17 @@ 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 (!conn->server) {
+ conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
+ }
rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts);
if (rv != 0) {
return rv;
}
- if (!conn->server) {
- conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
- }
non_probing_pkt = 1;
break;
case NGTCP2_FRAME_STREAM:
- rv = conn_recv_stream(conn, &fr->stream);
+ rv = conn_recv_stream(conn, &fr->stream, ts);
if (rv != 0) {
return rv;
}
@@ -6908,7 +6943,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
non_probing_pkt = 1;
break;
case NGTCP2_FRAME_HANDSHAKE_DONE:
- rv = conn_recv_handshake_done(conn);
+ rv = conn_recv_handshake_done(conn, ts);
if (rv != 0) {
return rv;
}
@@ -6975,7 +7010,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
conn_restart_timer_on_read(conn, ts);
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->rcs, &conn->ccs);
+ ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
return conn->state == NGTCP2_CS_DRAINING ? NGTCP2_ERR_DRAINING
: (ngtcp2_ssize)pktlen;
@@ -7122,6 +7157,8 @@ static int conn_recv_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path,
const uint8_t *origpkt = pkt;
size_t origpktlen = pktlen;
+ conn->cstat.bytes_recv += pktlen;
+
while (pktlen) {
nread = conn_recv_pkt(conn, path, pkt, pktlen, ts, ts);
if (nread < 0) {
@@ -7174,79 +7211,6 @@ static int conn_is_retired_path(ngtcp2_conn *conn, const ngtcp2_path *path) {
return 0;
}
-int ngtcp2_conn_read_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen, ngtcp2_tstamp ts) {
- int rv = 0;
-
- conn->log.last_ts = ts;
- conn->qlog.last_ts = ts;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "recv packet len=%zu",
- pktlen);
-
- if (pktlen == 0) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- /* client does not expect a packet from unknown path. */
- if (!conn->server && !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) &&
- (!conn->pv || !ngtcp2_path_eq(&conn->pv->dcid.ps.path, path)) &&
- !conn_is_retired_path(conn, path)) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "ignore packet from unknown path");
- return 0;
- }
-
- switch (conn->state) {
- case NGTCP2_CS_CLIENT_INITIAL:
- case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
- case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED:
- case NGTCP2_CS_SERVER_INITIAL:
- case NGTCP2_CS_SERVER_WAIT_HANDSHAKE:
- case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED:
- return ngtcp2_conn_read_handshake(conn, path, pkt, pktlen, ts);
- case NGTCP2_CS_CLOSING:
- return NGTCP2_ERR_CLOSING;
- case NGTCP2_CS_DRAINING:
- return NGTCP2_ERR_DRAINING;
- case NGTCP2_CS_POST_HANDSHAKE:
- rv = conn_prepare_key_update(conn, ts);
- if (rv != 0) {
- return rv;
- }
- return conn_recv_cpkt(conn, path, pkt, pktlen, ts);
- default:
- assert(0);
- }
-}
-
-/*
- * conn_check_pkt_num_exhausted returns nonzero if packet number is
- * exhausted in at least one of packet number space.
- */
-static int conn_check_pkt_num_exhausted(ngtcp2_conn *conn) {
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_pktns *hs_pktns = conn->hs_pktns;
-
- return (in_pktns && in_pktns->tx.last_pkt_num == NGTCP2_MAX_PKT_NUM) ||
- (hs_pktns && hs_pktns->tx.last_pkt_num == NGTCP2_MAX_PKT_NUM) ||
- conn->pktns.tx.last_pkt_num == NGTCP2_MAX_PKT_NUM;
-}
-
-/*
- * conn_server_hs_tx_left returns the maximum number of bytes that
- * server is allowed to send during handshake.
- */
-static size_t conn_server_hs_tx_left(ngtcp2_conn *conn) {
- if (conn->flags & NGTCP2_CONN_FLAG_SADDR_VERIFIED) {
- return SIZE_MAX;
- }
- /* From QUIC spec: Prior to validating the client address, servers
- MUST NOT send more than three times as many bytes as the number
- of bytes they have received. */
- return conn->hs_recved * 3 - conn->hs_sent;
-}
-
/*
* conn_enqueue_handshake_done enqueues HANDSHAKE_DONE frame for
* transmission.
@@ -7270,7 +7234,17 @@ static int conn_enqueue_handshake_done(ngtcp2_conn *conn) {
return 0;
}
-int ngtcp2_conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
+/**
+ * @function
+ *
+ * `conn_read_handshake` performs QUIC cryptographic handshake by
+ * reading given data. |pkt| points to the buffer to read and
+ * |pktlen| is the length of the buffer. |path| is the network path.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes: (TBD).
+ */
+static int conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
const uint8_t *pkt, size_t pktlen,
ngtcp2_tstamp ts) {
int rv;
@@ -7297,8 +7271,6 @@ int ngtcp2_conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
if (rv != 0) {
return rv;
}
-
- conn_discard_initial_state(conn);
}
return 0;
@@ -7358,10 +7330,32 @@ int ngtcp2_conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
}
if (conn->hs_pktns->rx.max_pkt_num != -1) {
- conn_discard_initial_state(conn);
+ conn_discard_initial_state(conn, ts);
}
if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
+ /* If server hits amplification limit, it cancels loss detection
+ timer. If server receives a packet from client, the limit is
+ increased and server can send more. If server has
+ ack-eliciting Initial or Handshake packets, it should resend
+ it if timer fired but timer is not armed in this case. So
+ instead of resending Initial/Handshake packets, if server has
+ 1RTT data to send, it might send them and then might hit
+ amplification limit again until it hits stream data limit.
+ Initial/Handshake data is not resent. In order to avoid this
+ situation, try to arm loss detection and check the expiry
+ here so that on next write call, we can resend
+ Initial/Handshake first. */
+ if (!conn->cstat.loss_detection_timer) {
+ ngtcp2_conn_set_loss_detection_timer(conn, ts);
+ if (ngtcp2_conn_loss_detection_expiry(conn) <= ts) {
+ rv = ngtcp2_conn_on_loss_detection_timer(conn, ts);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ }
+
return 0;
}
@@ -7369,8 +7363,6 @@ int ngtcp2_conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
}
- conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED;
-
rv = conn_handshake_completed(conn);
if (rv != 0) {
return rv;
@@ -7387,13 +7379,17 @@ int ngtcp2_conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
return rv;
}
- conn_discard_handshake_state(conn);
+ conn_discard_handshake_state(conn, ts);
rv = conn_enqueue_handshake_done(conn);
if (rv != 0) {
return rv;
}
+ /* Re-arm loss detection timer here after handshake has been
+ confirmed. */
+ ngtcp2_conn_set_loss_detection_timer(conn, ts);
+
return 0;
case NGTCP2_CS_CLOSING:
return NGTCP2_ERR_CLOSING;
@@ -7404,6 +7400,81 @@ int ngtcp2_conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
}
}
+int ngtcp2_conn_read_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
+ const uint8_t *pkt, size_t pktlen, ngtcp2_tstamp ts) {
+ int rv = 0;
+
+ conn->log.last_ts = ts;
+ conn->qlog.last_ts = ts;
+
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "recv packet len=%zu",
+ pktlen);
+
+ if (pktlen == 0) {
+ return NGTCP2_ERR_INVALID_ARGUMENT;
+ }
+
+ /* client does not expect a packet from unknown path. */
+ if (!conn->server && !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) &&
+ (!conn->pv || !ngtcp2_path_eq(&conn->pv->dcid.ps.path, path)) &&
+ !conn_is_retired_path(conn, path)) {
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
+ "ignore packet from unknown path");
+ return 0;
+ }
+
+ switch (conn->state) {
+ case NGTCP2_CS_CLIENT_INITIAL:
+ case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
+ case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED:
+ case NGTCP2_CS_SERVER_INITIAL:
+ case NGTCP2_CS_SERVER_WAIT_HANDSHAKE:
+ case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED:
+ return conn_read_handshake(conn, path, pkt, pktlen, ts);
+ case NGTCP2_CS_CLOSING:
+ return NGTCP2_ERR_CLOSING;
+ case NGTCP2_CS_DRAINING:
+ return NGTCP2_ERR_DRAINING;
+ case NGTCP2_CS_POST_HANDSHAKE:
+ rv = conn_prepare_key_update(conn, ts);
+ if (rv != 0) {
+ return rv;
+ }
+ return conn_recv_cpkt(conn, path, pkt, pktlen, ts);
+ default:
+ assert(0);
+ }
+}
+
+/*
+ * conn_check_pkt_num_exhausted returns nonzero if packet number is
+ * exhausted in at least one of packet number space.
+ */
+static int conn_check_pkt_num_exhausted(ngtcp2_conn *conn) {
+ ngtcp2_pktns *in_pktns = conn->in_pktns;
+ ngtcp2_pktns *hs_pktns = conn->hs_pktns;
+
+ return (in_pktns && in_pktns->tx.last_pkt_num == NGTCP2_MAX_PKT_NUM) ||
+ (hs_pktns && hs_pktns->tx.last_pkt_num == NGTCP2_MAX_PKT_NUM) ||
+ conn->pktns.tx.last_pkt_num == NGTCP2_MAX_PKT_NUM;
+}
+
+/*
+ * conn_server_hs_tx_left returns the maximum number of bytes that
+ * server is allowed to send during handshake.
+ */
+static size_t conn_server_hs_tx_left(ngtcp2_conn *conn) {
+ if (conn->flags & NGTCP2_CONN_FLAG_SADDR_VERIFIED) {
+ return SIZE_MAX;
+ }
+ /* From QUIC spec: Prior to validating the client address, servers
+ MUST NOT send more than three times as many bytes as the number
+ of bytes they have received. */
+ assert(conn->cstat.bytes_recv * 3 >= conn->cstat.bytes_sent);
+
+ return conn->cstat.bytes_recv * 3 - conn->cstat.bytes_sent;
+}
+
/*
* conn_retransmit_retry_early retransmits 0RTT packet after Retry is
* received from server.
@@ -7416,6 +7487,16 @@ static ngtcp2_ssize conn_retransmit_retry_early(ngtcp2_conn *conn,
}
/*
+ * conn_handshake_probe_left returns nonzero if there are probe
+ * packets to be sent for Initial or Handshake packet number space
+ * left.
+ */
+static int conn_handshake_probe_left(ngtcp2_conn *conn) {
+ return (conn->in_pktns && conn->in_pktns->rtb.probe_pkt_left) ||
+ conn->hs_pktns->rtb.probe_pkt_left;
+}
+
+/*
* conn_write_handshake writes QUIC handshake packets to the buffer
* pointed by |dest| of length |destlen|. |early_datalen| specifies
* the expected length of early data to send. Specify 0 to
@@ -7443,17 +7524,13 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
ngtcp2_tstamp ts) {
int rv;
ngtcp2_ssize res = 0, nwrite = 0, early_spktlen = 0;
- uint64_t cwnd;
size_t origlen = destlen;
size_t server_hs_tx_left;
- ngtcp2_rcvry_stat *rcs = &conn->rcs;
+ ngtcp2_conn_stat *cstat = &conn->cstat;
size_t pending_early_datalen;
ngtcp2_dcid *dcid;
ngtcp2_preferred_addr *paddr;
- cwnd = conn_cwnd_left(conn);
- destlen = ngtcp2_min(destlen, cwnd);
-
switch (conn->state) {
case NGTCP2_CS_CLIENT_INITIAL:
pending_early_datalen = conn_retry_early_payloadlen(conn);
@@ -7487,32 +7564,32 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
conn->state = NGTCP2_CS_CLIENT_WAIT_HANDSHAKE;
- return nwrite + early_spktlen;
+ res = nwrite + early_spktlen;
+ cstat->bytes_sent += (size_t)res;
+
+ return res;
case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
- if ((conn->in_pktns && conn->in_pktns->rtb.probe_pkt_left) ||
- conn->hs_pktns->rtb.probe_pkt_left) {
- nwrite = conn_write_handshake_pkts(conn, dest, origlen, 0, ts);
- if (nwrite) {
- return nwrite;
+ if (!conn_handshake_probe_left(conn) && conn_cwnd_is_zero(conn)) {
+ destlen = 0;
+ } else {
+ if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) {
+ pending_early_datalen = conn_retry_early_payloadlen(conn);
+ if (pending_early_datalen) {
+ early_datalen = pending_early_datalen;
+ }
}
- }
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) {
- pending_early_datalen = conn_retry_early_payloadlen(conn);
- if (pending_early_datalen) {
- early_datalen = pending_early_datalen;
+ nwrite =
+ conn_write_handshake_pkts(conn, dest, destlen, early_datalen, ts);
+ if (nwrite < 0) {
+ return nwrite;
}
- }
- nwrite = conn_write_handshake_pkts(conn, dest, destlen, early_datalen, ts);
- if (nwrite < 0) {
- return nwrite;
+ res += nwrite;
+ dest += nwrite;
+ destlen -= (size_t)nwrite;
}
- res += nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
-
if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
nwrite = conn_retransmit_retry_early(conn, dest, destlen, ts);
if (nwrite < 0) {
@@ -7528,6 +7605,9 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
}
res = nwrite;
}
+
+ cstat->bytes_sent += (size_t)res;
+
return res;
}
@@ -7576,16 +7656,19 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
}
}
+ cstat->bytes_sent += (size_t)res;
+
return res;
case NGTCP2_CS_SERVER_INITIAL:
- nwrite = conn_write_server_handshake(conn, dest, destlen, ts);
+ nwrite = conn_write_handshake_pkts(conn, dest, destlen,
+ /* early_datalen = */ 0, ts);
if (nwrite < 0) {
return nwrite;
}
if (nwrite) {
conn->state = NGTCP2_CS_SERVER_WAIT_HANDSHAKE;
- conn->hs_sent += (size_t)nwrite;
+ cstat->bytes_sent += (size_t)nwrite;
}
return nwrite;
@@ -7593,56 +7676,39 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
server_hs_tx_left = conn_server_hs_tx_left(conn);
if (server_hs_tx_left == 0) {
- if (rcs->loss_detection_timer) {
+ if (cstat->loss_detection_timer) {
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
"loss detection timer canceled");
- rcs->loss_detection_timer = 0;
+ cstat->loss_detection_timer = 0;
+ cstat->pto_count = 0;
}
return 0;
}
- destlen = ngtcp2_min(destlen, server_hs_tx_left);
- origlen = ngtcp2_min(origlen, server_hs_tx_left);
-
- if ((conn->in_pktns && conn->in_pktns->rtb.probe_pkt_left) ||
- conn->hs_pktns->rtb.probe_pkt_left) {
- nwrite = conn_write_handshake_pkts(conn, dest, origlen, 0, ts);
+ if (conn_handshake_probe_left(conn) || !conn_cwnd_is_zero(conn)) {
+ nwrite = conn_write_handshake_pkts(conn, dest, destlen,
+ /* early_datalen = */ 0, ts);
if (nwrite < 0) {
return nwrite;
}
- /* Coalesce packets, because server might send Initial as
- probe, and Handshake as non-probe. */
res += nwrite;
dest += nwrite;
- if (destlen <= (size_t)nwrite) {
- goto server_wait_handshake_done;
- }
destlen -= (size_t)nwrite;
- origlen -= (size_t)nwrite;
- }
-
- nwrite = conn_write_server_handshake(conn, dest, destlen, ts);
- if (nwrite < 0) {
- return nwrite;
}
- /* TODO Write 1RTT ACK packet if we have received 0RTT packet */
-
- res += nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- origlen -= (size_t)nwrite;
+ if (res == 0) {
+ nwrite = conn_write_handshake_ack_pkts(conn, dest, origlen, ts);
+ if (nwrite < 0) {
+ return nwrite;
+ }
- nwrite = conn_write_handshake_ack_pkts(conn, dest, origlen, ts);
- if (nwrite < 0) {
- return nwrite;
+ res += nwrite;
+ dest += nwrite;
+ origlen -= (size_t)nwrite;
}
- res += nwrite;
-
- server_wait_handshake_done:
- conn->hs_sent += (size_t)res;
+ cstat->bytes_sent += (size_t)res;
return res;
}
@@ -7656,19 +7722,37 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
}
}
-ngtcp2_ssize ngtcp2_conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, ngtcp2_tstamp ts) {
- return conn_write_handshake(conn, dest, destlen, 0, ts);
-}
-
-ngtcp2_ssize ngtcp2_conn_client_write_handshake(
- ngtcp2_conn *conn, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen,
- uint32_t flags, int64_t stream_id, int fin, const ngtcp2_vec *datav,
- size_t datavcnt, ngtcp2_tstamp ts) {
+/**
+ * @function
+ *
+ * `conn_client_write_handshake` writes client side handshake data and
+ * 0RTT packet.
+ *
+ * |stream_id|, |fin|, |datav|, and |datavcnt| are stream identifier
+ * to which 0-RTT data is sent, whether it is a last data chunk in
+ * this stream, a vector of 0-RTT data, and its number of elements
+ * respectively. If there is no 0RTT data to send, pass negative
+ * integer to |stream_id|. The amount of 0RTT data sent is assigned
+ * to |*pdatalen|. If no data is sent, -1 is assigned. Note that 0
+ * length STREAM frame is allowed in QUIC, so 0 might be assigned to
+ * |*pdatalen|.
+ *
+ * This function returns 0 if it cannot write any frame because buffer
+ * is too small, or packet is congestion limited. Application should
+ * keep reading and wait for congestion window to grow.
+ *
+ * This function returns the number of bytes written to the buffer
+ * pointed by |dest| if it succeeds, or one of the following negative
+ * error codes: (TBD).
+ */
+static ngtcp2_ssize
+conn_client_write_handshake(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
+ ngtcp2_ssize *pdatalen, uint32_t flags,
+ int64_t stream_id, int fin, const ngtcp2_vec *datav,
+ size_t datavcnt, ngtcp2_tstamp ts) {
ngtcp2_strm *strm = NULL;
int send_stream = 0;
ngtcp2_ssize spktlen, early_spktlen;
- uint64_t cwnd;
int was_client_initial;
size_t datalen = ngtcp2_vec_len(datav, datavcnt);
size_t early_datalen = 0;
@@ -7696,10 +7780,11 @@ ngtcp2_ssize ngtcp2_conn_client_write_handshake(
(datalen > 0 && (strm->tx.max_offset - strm->tx.offset) &&
(conn->tx.max_offset - conn->tx.offset)));
if (send_stream) {
+ early_datalen = (size_t)ngtcp2_min((uint64_t)datalen,
+ strm->tx.max_offset - strm->tx.offset);
early_datalen =
- ngtcp2_min(datalen, strm->tx.max_offset - strm->tx.offset);
- early_datalen =
- ngtcp2_min(early_datalen, conn->tx.max_offset - conn->tx.offset) +
+ (size_t)ngtcp2_min((uint64_t)early_datalen,
+ conn->tx.max_offset - conn->tx.offset) +
NGTCP2_STREAM_OVERHEAD;
if (flags & NGTCP2_WRITE_STREAM_FLAG_MORE) {
@@ -7736,11 +7821,12 @@ ngtcp2_ssize ngtcp2_conn_client_write_handshake(
wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
}
- cwnd = conn_cwnd_left(conn);
-
dest += spktlen;
destlen -= (size_t)spktlen;
- destlen = ngtcp2_min(destlen, cwnd);
+
+ if (conn_cwnd_is_zero(conn)) {
+ return spktlen;
+ }
early_spktlen = conn_write_pkt(conn, dest, destlen, pdatalen, NGTCP2_PKT_0RTT,
strm, fin, datav, datavcnt, wflags, ts);
@@ -7757,11 +7843,16 @@ ngtcp2_ssize ngtcp2_conn_client_write_handshake(
return early_spktlen;
}
+ conn->cstat.bytes_sent += (size_t)early_spktlen;
+
return spktlen + early_spktlen;
}
void ngtcp2_conn_handshake_completed(ngtcp2_conn *conn) {
conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED;
+ if (conn->server) {
+ conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED;
+ }
}
int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn) {
@@ -7807,7 +7898,7 @@ int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt, size_t pktlen) {
if (pktlen < NGTCP2_MIN_INITIAL_PKTLEN) {
return -1;
}
- if (p->tokenlen == 0 && p->dcid.datalen < 8) {
+ if (p->token.len == 0 && p->dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN) {
return -1;
}
break;
@@ -7885,37 +7976,44 @@ int ngtcp2_conn_install_initial_key(ngtcp2_conn *conn, const uint8_t *rx_key,
return ngtcp2_vec_new(&pktns->crypto.tx.hp_key, tx_hp_key, keylen, conn->mem);
}
-int ngtcp2_conn_install_handshake_key(
- ngtcp2_conn *conn, const uint8_t *rx_key, const uint8_t *rx_iv,
- const uint8_t *rx_hp_key, const uint8_t *tx_key, const uint8_t *tx_iv,
- const uint8_t *tx_hp_key, size_t keylen, size_t ivlen) {
+int ngtcp2_conn_install_rx_handshake_key(ngtcp2_conn *conn, const uint8_t *key,
+ const uint8_t *iv,
+ const uint8_t *hp_key, size_t keylen,
+ size_t ivlen) {
ngtcp2_pktns *pktns = conn->hs_pktns;
int rv;
assert(pktns);
assert(!pktns->crypto.rx.hp_key);
assert(!pktns->crypto.rx.ckm);
- assert(!pktns->crypto.tx.hp_key);
- assert(!pktns->crypto.tx.ckm);
- rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, NULL, 0, rx_key, keylen,
- rx_iv, ivlen, conn->mem);
+ rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, NULL, 0, key, keylen, iv,
+ ivlen, conn->mem);
if (rv != 0) {
return rv;
}
- rv = ngtcp2_vec_new(&pktns->crypto.rx.hp_key, rx_hp_key, keylen, conn->mem);
- if (rv != 0) {
- return rv;
- }
+ return ngtcp2_vec_new(&pktns->crypto.rx.hp_key, hp_key, keylen, conn->mem);
+}
- rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL, 0, tx_key, keylen,
- tx_iv, ivlen, conn->mem);
+int ngtcp2_conn_install_tx_handshake_key(ngtcp2_conn *conn, const uint8_t *key,
+ const uint8_t *iv,
+ const uint8_t *hp_key, size_t keylen,
+ size_t ivlen) {
+ ngtcp2_pktns *pktns = conn->hs_pktns;
+ int rv;
+
+ assert(pktns);
+ assert(!pktns->crypto.tx.hp_key);
+ assert(!pktns->crypto.tx.ckm);
+
+ rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL, 0, key, keylen, iv,
+ ivlen, conn->mem);
if (rv != 0) {
return rv;
}
- return ngtcp2_vec_new(&pktns->crypto.tx.hp_key, tx_hp_key, keylen, conn->mem);
+ return ngtcp2_vec_new(&pktns->crypto.tx.hp_key, hp_key, keylen, conn->mem);
}
int ngtcp2_conn_install_early_key(ngtcp2_conn *conn, const uint8_t *key,
@@ -7935,38 +8033,47 @@ int ngtcp2_conn_install_early_key(ngtcp2_conn *conn, const uint8_t *key,
return ngtcp2_vec_new(&conn->early.hp_key, hp_key, keylen, conn->mem);
}
-int ngtcp2_conn_install_key(ngtcp2_conn *conn, const uint8_t *rx_secret,
- const uint8_t *tx_secret, const uint8_t *rx_key,
- const uint8_t *rx_iv, const uint8_t *rx_hp_key,
- const uint8_t *tx_key, const uint8_t *tx_iv,
- const uint8_t *tx_hp_key, size_t secretlen,
- size_t keylen, size_t ivlen) {
+int ngtcp2_conn_install_rx_key(ngtcp2_conn *conn, const uint8_t *secret,
+ const uint8_t *key, const uint8_t *iv,
+ const uint8_t *hp_key, size_t secretlen,
+ size_t keylen, size_t ivlen) {
ngtcp2_pktns *pktns = &conn->pktns;
int rv;
assert(!pktns->crypto.rx.hp_key);
assert(!pktns->crypto.rx.ckm);
- assert(!pktns->crypto.tx.hp_key);
- assert(!pktns->crypto.tx.ckm);
- rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, rx_secret, secretlen, rx_key,
- keylen, rx_iv, ivlen, conn->mem);
+ rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, secret, secretlen, key,
+ keylen, iv, ivlen, conn->mem);
if (rv != 0) {
return rv;
}
- rv = ngtcp2_vec_new(&pktns->crypto.rx.hp_key, rx_hp_key, keylen, conn->mem);
+ rv = ngtcp2_vec_new(&pktns->crypto.rx.hp_key, hp_key, keylen, conn->mem);
if (rv != 0) {
return rv;
}
- rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, tx_secret, secretlen, tx_key,
- keylen, tx_iv, ivlen, conn->mem);
+ return 0;
+}
+
+int ngtcp2_conn_install_tx_key(ngtcp2_conn *conn, const uint8_t *secret,
+ const uint8_t *key, const uint8_t *iv,
+ const uint8_t *hp_key, size_t secretlen,
+ size_t keylen, size_t ivlen) {
+ ngtcp2_pktns *pktns = &conn->pktns;
+ int rv;
+
+ assert(!pktns->crypto.tx.hp_key);
+ assert(!pktns->crypto.tx.ckm);
+
+ rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, secret, secretlen, key,
+ keylen, iv, ivlen, conn->mem);
if (rv != 0) {
return rv;
}
- rv = ngtcp2_vec_new(&pktns->crypto.tx.hp_key, tx_hp_key, keylen, conn->mem);
+ rv = ngtcp2_vec_new(&pktns->crypto.tx.hp_key, hp_key, keylen, conn->mem);
if (rv != 0) {
return rv;
}
@@ -7980,7 +8087,7 @@ int ngtcp2_conn_install_key(ngtcp2_conn *conn, const uint8_t *rx_secret,
int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
ngtcp2_tstamp confirmed_ts = conn->crypto.key_update.confirmed_ts;
- ngtcp2_duration pto = conn_compute_pto(conn);
+ ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns);
assert(conn->state == NGTCP2_CS_POST_HANDSHAKE);
@@ -7998,15 +8105,15 @@ int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
}
ngtcp2_tstamp ngtcp2_conn_loss_detection_expiry(ngtcp2_conn *conn) {
- if (conn->rcs.loss_detection_timer) {
- return conn->rcs.loss_detection_timer;
+ if (conn->cstat.loss_detection_timer) {
+ return conn->cstat.loss_detection_timer;
}
return UINT64_MAX;
}
ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) {
ngtcp2_tstamp res = UINT64_MAX;
- ngtcp2_duration pto = conn_compute_pto(conn);
+ ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns);
ngtcp2_scid *scid;
ngtcp2_dcid *dcid;
@@ -8088,20 +8195,33 @@ void ngtcp2_conn_cancel_expired_ack_delay_timer(ngtcp2_conn *conn,
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
+ * NGTCP2_ERR_PROTO
+ * Validation against either of original_dcid and retry_scid is
+ * failed.
* NGTCP2_ERR_TRANSPORT_PARAM
- * Transport parameters are invalid.
+ * params contains preferred address but server chose zero-length
+ * connection ID.
*/
static int
conn_client_validate_transport_params(ngtcp2_conn *conn,
const ngtcp2_transport_params *params) {
+ if (!ngtcp2_cid_eq(&conn->rcid, &params->original_dcid)) {
+ return NGTCP2_ERR_TRANSPORT_PARAM;
+ }
+
if (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) {
- if (!params->original_connection_id_present) {
+ if (!params->retry_scid_present) {
return NGTCP2_ERR_TRANSPORT_PARAM;
}
- if (!ngtcp2_cid_eq(&conn->rcid, &params->original_connection_id)) {
+ if (!ngtcp2_cid_eq(&conn->retry_scid, &params->retry_scid)) {
return NGTCP2_ERR_TRANSPORT_PARAM;
}
- } else if (params->original_connection_id_present) {
+ } else if (params->retry_scid_present) {
+ return NGTCP2_ERR_TRANSPORT_PARAM;
+ }
+
+ if (params->preferred_address_present &&
+ conn->dcid.current.cid.datalen == 0) {
return NGTCP2_ERR_TRANSPORT_PARAM;
}
@@ -8121,6 +8241,13 @@ int ngtcp2_conn_set_remote_transport_params(
return NGTCP2_ERR_TRANSPORT_PARAM;
}
+ /* We assume that conn->dcid.current.cid is still the initial one.
+ This requires that transport parameter must be fed into
+ ngtcp2_conn as early as possible. */
+ if (!ngtcp2_cid_eq(&conn->dcid.current.cid, &params->initial_scid)) {
+ return NGTCP2_ERR_TRANSPORT_PARAM;
+ }
+
if (!conn->server) {
rv = conn_client_validate_transport_params(conn, params);
if (rv != 0) {
@@ -8134,10 +8261,10 @@ int ngtcp2_conn_set_remote_transport_params(
: NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS,
params);
- ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, params,
+ ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, params, conn->server,
/* local = */ 0);
- if (conn->pktns.crypto.rx.ckm) {
+ if (conn->pktns.crypto.tx.ckm) {
conn->remote.transport_params = *params;
conn_sync_stream_id_limit(conn);
conn->tx.max_offset = conn->remote.transport_params.initial_max_data;
@@ -8180,13 +8307,21 @@ void ngtcp2_conn_set_early_remote_transport_params(
conn->tx.max_offset = p->initial_max_data;
- ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, p,
+ ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, p, conn->server,
/* local = */ 0);
}
void ngtcp2_conn_get_local_transport_params(ngtcp2_conn *conn,
ngtcp2_transport_params *params) {
*params = conn->local.settings.transport_params;
+
+ /* If params->retry_scid_present is set by application then it
+ should also specify original_dcid because the destination
+ connection ID from client after Retry is not what we want
+ here. */
+ if (conn->server && !params->retry_scid_present) {
+ params->original_dcid = conn->rcid;
+ }
}
int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn, int64_t *pstream_id,
@@ -8194,8 +8329,7 @@ int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn, int64_t *pstream_id,
int rv;
ngtcp2_strm *strm;
- if (ngtcp2_ord_stream_id(conn->local.bidi.next_stream_id) >
- conn->local.bidi.max_streams) {
+ if (ngtcp2_conn_get_streams_bidi_left(conn) == 0) {
return NGTCP2_ERR_STREAM_ID_BLOCKED;
}
@@ -8222,8 +8356,7 @@ int ngtcp2_conn_open_uni_stream(ngtcp2_conn *conn, int64_t *pstream_id,
int rv;
ngtcp2_strm *strm;
- if (ngtcp2_ord_stream_id(conn->local.uni.next_stream_id) >
- conn->local.uni.max_streams) {
+ if (ngtcp2_conn_get_streams_uni_left(conn) == 0) {
return NGTCP2_ERR_STREAM_ID_BLOCKED;
}
@@ -8260,33 +8393,33 @@ ngtcp2_strm *ngtcp2_conn_find_stream(ngtcp2_conn *conn, int64_t stream_id) {
ngtcp2_ssize ngtcp2_conn_write_stream(ngtcp2_conn *conn, ngtcp2_path *path,
uint8_t *dest, size_t destlen,
ngtcp2_ssize *pdatalen, uint32_t flags,
- int64_t stream_id, int fin,
- const uint8_t *data, size_t datalen,
- ngtcp2_tstamp ts) {
+ int64_t stream_id, const uint8_t *data,
+ size_t datalen, ngtcp2_tstamp ts) {
ngtcp2_vec datav;
datav.len = datalen;
datav.base = (uint8_t *)data;
return ngtcp2_conn_writev_stream(conn, path, dest, destlen, pdatalen, flags,
- stream_id, fin, &datav, 1, ts);
+ stream_id, &datav, 1, ts);
}
ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
uint8_t *dest, size_t destlen,
ngtcp2_ssize *pdatalen, uint32_t flags,
- int64_t stream_id, int fin,
+ int64_t stream_id,
const ngtcp2_vec *datav, size_t datavcnt,
ngtcp2_tstamp ts) {
ngtcp2_strm *strm = NULL;
ngtcp2_ssize nwrite;
- uint64_t cwnd;
ngtcp2_pktns *pktns = &conn->pktns;
size_t origlen = destlen;
int rv;
uint8_t wflags = NGTCP2_WRITE_PKT_FLAG_NONE;
int ppe_pending = (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING) != 0;
ngtcp2_ssize res = 0;
+ size_t server_hs_tx_left;
+ int fin = flags & NGTCP2_WRITE_STREAM_FLAG_FIN;
conn->log.last_ts = ts;
conn->qlog.last_ts = ts;
@@ -8303,9 +8436,8 @@ ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
case NGTCP2_CS_CLIENT_INITIAL:
case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED:
- nwrite =
- ngtcp2_conn_client_write_handshake(conn, dest, destlen, pdatalen, flags,
- stream_id, fin, datav, datavcnt, ts);
+ nwrite = conn_client_write_handshake(conn, dest, destlen, pdatalen, flags,
+ stream_id, fin, datav, datavcnt, ts);
if (nwrite < 0 || conn->state != NGTCP2_CS_POST_HANDSHAKE) {
return nwrite;
}
@@ -8318,14 +8450,27 @@ ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
case NGTCP2_CS_SERVER_WAIT_HANDSHAKE:
case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED:
if (!ppe_pending) {
- nwrite = ngtcp2_conn_write_handshake(conn, dest, destlen, ts);
- if (nwrite) {
+ server_hs_tx_left = conn_server_hs_tx_left(conn);
+ destlen = ngtcp2_min(destlen, server_hs_tx_left);
+
+ nwrite = conn_write_handshake(conn, dest, destlen, 0, ts);
+ if (nwrite < 0) {
return nwrite;
}
+
+ if (conn->flags & NGTCP2_CONN_FLAG_SADDR_VERIFIED) {
+ destlen = origlen;
+ } else {
+ origlen = destlen;
+ }
+
+ res = nwrite;
+ dest += nwrite;
+ destlen -= (size_t)nwrite;
}
if (conn->state != NGTCP2_CS_POST_HANDSHAKE &&
conn->pktns.crypto.tx.ckm == NULL) {
- return 0;
+ return res;
}
break;
case NGTCP2_CS_POST_HANDSHAKE:
@@ -8344,13 +8489,6 @@ ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
return NGTCP2_ERR_PKT_NUM_EXHAUSTED;
}
- if (conn->state == NGTCP2_CS_POST_HANDSHAKE) {
- rv = conn_prepare_key_update(conn, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
rv = conn_remove_retired_connection_id(conn, ts);
if (rv != 0) {
return rv;
@@ -8371,9 +8509,6 @@ ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
}
}
- cwnd = conn_cwnd_left(conn);
- destlen = ngtcp2_min(destlen, cwnd);
-
if (ppe_pending) {
res = conn->pkt.hs_spktlen;
conn->pkt.hs_spktlen = 0;
@@ -8382,40 +8517,49 @@ ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
nwrite = conn_write_pkt(conn, dest, destlen, pdatalen, NGTCP2_PKT_SHORT,
strm, fin, datav, datavcnt, wflags, ts);
goto fin;
- }
+ } else {
+ if (conn->state == NGTCP2_CS_POST_HANDSHAKE) {
+ rv = conn_prepare_key_update(conn, ts);
+ if (rv != 0) {
+ return rv;
+ }
+ }
- if (conn->pv) {
- nwrite = conn_write_path_challenge(conn, path, dest, origlen, ts);
- if (nwrite) {
- goto fin;
+ if (!conn->pktns.rtb.probe_pkt_left && conn_cwnd_is_zero(conn)) {
+ destlen = 0;
+ } else if (conn->pv) {
+ nwrite = conn_write_path_challenge(conn, path, dest, destlen, ts);
+ if (nwrite) {
+ goto fin;
+ }
}
}
if (res == 0) {
if (conn_handshake_remnants_left(conn)) {
- if ((conn->in_pktns && conn->in_pktns->rtb.probe_pkt_left) ||
- conn->hs_pktns->rtb.probe_pkt_left) {
- nwrite = conn_write_handshake_pkts(conn, dest, origlen, 0, ts);
- if (nwrite) {
- return nwrite;
- }
- } else {
- nwrite = conn_write_handshake_pkts(conn, dest, destlen, 0, ts);
- if (nwrite < 0) {
- return nwrite;
- }
- if (nwrite > 0) {
- res = nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- }
+ if (conn_handshake_probe_left(conn)) {
+ destlen = origlen;
+ }
+ nwrite = conn_write_handshake_pkts(conn, dest, destlen, 0, ts);
+ if (nwrite < 0) {
+ return nwrite;
+ }
+ if (nwrite > 0) {
+ res = nwrite;
+ dest += nwrite;
+ destlen -= (size_t)nwrite;
}
}
}
if (conn->pktns.rtb.probe_pkt_left) {
- nwrite = conn_write_probe_pkt(conn, dest, origlen, pdatalen, strm, fin,
- datav, datavcnt, ts);
+ ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
+ "transmit probe pkt left=%zu",
+ conn->pktns.rtb.probe_pkt_left);
+
+ nwrite = conn_write_pkt(conn, dest, destlen, pdatalen, NGTCP2_PKT_SHORT,
+ strm, fin, datav, datavcnt, wflags, ts);
+
goto fin;
}
@@ -8427,13 +8571,14 @@ ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
}
if (res == 0) {
- return conn_write_ack_pkt(conn, dest, origlen, NGTCP2_PKT_SHORT, ts);
+ nwrite = conn_write_ack_pkt(conn, dest, origlen, NGTCP2_PKT_SHORT, ts);
}
fin:
conn->pkt.hs_spktlen = 0;
if (nwrite >= 0) {
+ conn->cstat.bytes_sent += (size_t)nwrite;
return res + nwrite;
}
/* NGTCP2_CONN_FLAG_PPE_PENDING is set in conn_write_pkt above.
@@ -8455,8 +8600,6 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close(ngtcp2_conn *conn,
ngtcp2_ssize res = 0, nwrite;
ngtcp2_frame fr;
uint8_t pkt_type;
- int bundle = 0;
- uint8_t bundle_pkt_type;
conn->log.last_ts = ts;
conn->qlog.last_ts = ts;
@@ -8466,6 +8609,7 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close(ngtcp2_conn *conn,
}
switch (conn->state) {
+ case NGTCP2_CS_CLIENT_INITIAL:
case NGTCP2_CS_CLOSING:
case NGTCP2_CS_DRAINING:
return NGTCP2_ERR_INVALID_STATE;
@@ -8495,29 +8639,39 @@ ngtcp2_ssize ngtcp2_conn_write_connection_close(ngtcp2_conn *conn,
return NGTCP2_ERR_INVALID_STATE;
}
- if (conn->server && pkt_type == NGTCP2_PKT_HANDSHAKE && in_pktns) {
- bundle = 1;
- bundle_pkt_type = NGTCP2_PKT_INITIAL;
- } else if (pkt_type == NGTCP2_PKT_SHORT && hs_pktns &&
- !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)) {
- bundle = 1;
- bundle_pkt_type = NGTCP2_PKT_HANDSHAKE;
- }
+ if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) &&
+ pkt_type != NGTCP2_PKT_INITIAL) {
+ if (in_pktns && conn->server) {
+ nwrite = ngtcp2_conn_write_single_frame_pkt(
+ conn, dest, destlen, NGTCP2_PKT_INITIAL, &conn->dcid.current.cid, &fr,
+ NGTCP2_RTB_FLAG_NONE, ts);
+ if (nwrite < 0) {
+ return nwrite;
+ }
- if (bundle) {
- nwrite = ngtcp2_conn_write_single_frame_pkt(
- conn, dest, destlen, bundle_pkt_type, &conn->dcid.current.cid, &fr,
- NGTCP2_RTB_FLAG_NONE, ts);
- if (nwrite < 0) {
- return nwrite;
+ dest += nwrite;
+ destlen -= (size_t)nwrite;
+ res += nwrite;
}
- res += nwrite;
+ if (pkt_type != NGTCP2_PKT_HANDSHAKE && hs_pktns &&
+ hs_pktns->crypto.tx.ckm) {
+ nwrite = ngtcp2_conn_write_single_frame_pkt(
+ conn, dest, destlen, NGTCP2_PKT_HANDSHAKE, &conn->dcid.current.cid,
+ &fr, NGTCP2_RTB_FLAG_NONE, ts);
+ if (nwrite < 0) {
+ return nwrite;
+ }
+
+ dest += nwrite;
+ destlen -= (size_t)nwrite;
+ res += nwrite;
+ }
}
- nwrite = ngtcp2_conn_write_single_frame_pkt(
- conn, dest + res, destlen - (size_t)res, pkt_type,
- &conn->dcid.current.cid, &fr, NGTCP2_RTB_FLAG_NONE, ts);
+ nwrite = ngtcp2_conn_write_single_frame_pkt(conn, dest, destlen, pkt_type,
+ &conn->dcid.current.cid, &fr,
+ NGTCP2_RTB_FLAG_NONE, ts);
if (nwrite < 0) {
return nwrite;
@@ -8754,10 +8908,11 @@ int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, int64_t stream_id,
* Out of memory.
*/
static int conn_extend_max_stream_offset(ngtcp2_conn *conn, ngtcp2_strm *strm,
- size_t datalen) {
+ uint64_t datalen) {
ngtcp2_strm *top;
- if (strm->rx.unsent_max_offset > NGTCP2_MAX_VARINT - datalen) {
+ if (datalen > NGTCP2_MAX_VARINT ||
+ strm->rx.unsent_max_offset > NGTCP2_MAX_VARINT - datalen) {
strm->rx.unsent_max_offset = NGTCP2_MAX_VARINT;
} else {
strm->rx.unsent_max_offset += datalen;
@@ -8779,7 +8934,7 @@ static int conn_extend_max_stream_offset(ngtcp2_conn *conn, ngtcp2_strm *strm,
}
int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn, int64_t stream_id,
- size_t datalen) {
+ uint64_t datalen) {
ngtcp2_strm *strm;
strm = ngtcp2_conn_find_stream(conn, stream_id);
@@ -8790,8 +8945,8 @@ int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn, int64_t stream_id,
return conn_extend_max_stream_offset(conn, strm, datalen);
}
-void ngtcp2_conn_extend_max_offset(ngtcp2_conn *conn, size_t datalen) {
- if (NGTCP2_MAX_VARINT < (uint64_t)datalen ||
+void ngtcp2_conn_extend_max_offset(ngtcp2_conn *conn, uint64_t datalen) {
+ if (NGTCP2_MAX_VARINT < datalen ||
conn->rx.unsent_max_offset > NGTCP2_MAX_VARINT - datalen) {
conn->rx.unsent_max_offset = NGTCP2_MAX_VARINT;
return;
@@ -8808,10 +8963,6 @@ void ngtcp2_conn_extend_max_streams_uni(ngtcp2_conn *conn, size_t n) {
handle_max_remote_streams_extension(&conn->remote.uni.unsent_max_streams, n);
}
-size_t ngtcp2_conn_get_bytes_in_flight(ngtcp2_conn *conn) {
- return conn->ccs.bytes_in_flight;
-}
-
const ngtcp2_cid *ngtcp2_conn_get_dcid(ngtcp2_conn *conn) {
return &conn->dcid.current.cid;
}
@@ -8828,7 +8979,7 @@ int ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn) {
conn->flags |= NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED;
- ngtcp2_rtb_remove_all(rtb, &frc);
+ ngtcp2_rtb_remove_all(rtb, &frc, &conn->cstat);
rv = conn_resched_frames(conn, pktns, &frc);
if (rv != 0) {
@@ -8842,167 +8993,147 @@ int ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn) {
void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
ngtcp2_duration ack_delay) {
- ngtcp2_rcvry_stat *rcs = &conn->rcs;
-
- rcs->latest_rtt = rtt;
+ ngtcp2_conn_stat *cstat = &conn->cstat;
- if (rcs->smoothed_rtt == 0) {
- rcs->min_rtt = rtt;
- rcs->smoothed_rtt = rtt;
- rcs->rttvar = rtt / 2;
- return;
- }
+ rtt = ngtcp2_max(rtt, NGTCP2_GRANULARITY);
- rcs->min_rtt = ngtcp2_min(rcs->min_rtt, rtt);
- if (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) {
- ack_delay =
- ngtcp2_min(ack_delay, conn->remote.transport_params.max_ack_delay);
+ if (cstat->min_rtt == UINT64_MAX) {
+ cstat->latest_rtt = rtt;
+ cstat->min_rtt = rtt;
+ cstat->smoothed_rtt = rtt;
+ cstat->rttvar = rtt / 2;
} else {
- ack_delay = ngtcp2_min(ack_delay, NGTCP2_DEFAULT_MAX_ACK_DELAY);
- }
- if (rtt > rcs->min_rtt + ack_delay) {
- rtt -= ack_delay;
- }
+ cstat->min_rtt = ngtcp2_min(cstat->min_rtt, rtt);
+ if (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) {
+ ack_delay =
+ ngtcp2_min(ack_delay, conn->remote.transport_params.max_ack_delay);
+ } else {
+ ack_delay = ngtcp2_min(ack_delay, NGTCP2_DEFAULT_MAX_ACK_DELAY);
+ }
+ if (rtt > cstat->min_rtt + ack_delay) {
+ rtt -= ack_delay;
+ }
- rcs->rttvar =
- (rcs->rttvar * 3 + (rcs->smoothed_rtt < rtt ? rtt - rcs->smoothed_rtt
- : rcs->smoothed_rtt - rtt)) /
- 4;
- rcs->smoothed_rtt = (rcs->smoothed_rtt * 7 + rtt) / 8;
+ cstat->latest_rtt = rtt;
+
+ cstat->rttvar = (cstat->rttvar * 3 + (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_RCV,
"latest_rtt=%" PRIu64 " min_rtt=%" PRIu64
" smoothed_rtt=%" PRIu64 " rttvar=%" PRIu64
" ack_delay=%" PRIu64,
- (uint64_t)(rcs->latest_rtt / NGTCP2_MILLISECONDS),
- (uint64_t)(rcs->min_rtt / NGTCP2_MILLISECONDS),
- rcs->smoothed_rtt / NGTCP2_MILLISECONDS,
- rcs->rttvar / NGTCP2_MILLISECONDS,
+ (uint64_t)(cstat->latest_rtt / NGTCP2_MILLISECONDS),
+ (uint64_t)(cstat->min_rtt / NGTCP2_MILLISECONDS),
+ cstat->smoothed_rtt / NGTCP2_MILLISECONDS,
+ cstat->rttvar / NGTCP2_MILLISECONDS,
(uint64_t)(ack_delay / NGTCP2_MILLISECONDS));
}
-const ngtcp2_rcvry_stat *ngtcp2_conn_get_rcvry_stat(ngtcp2_conn *conn) {
- return &conn->rcs;
-}
-
-const ngtcp2_cc_stat *ngtcp2_conn_get_cc_stat(ngtcp2_conn *conn) {
- return &conn->ccs;
+void ngtcp2_conn_get_conn_stat(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat) {
+ *cstat = conn->cstat;
}
-static ngtcp2_pktns *conn_get_earliest_loss_time_pktns(ngtcp2_conn *conn) {
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_pktns *hs_pktns = conn->hs_pktns;
- ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_pktns *res = in_pktns;
-
- if (hs_pktns && hs_pktns->rtb.loss_time != UINT64_MAX &&
- (res == NULL || hs_pktns->rtb.loss_time < res->rtb.loss_time)) {
- res = hs_pktns;
- }
- if ((conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) &&
- pktns->rtb.loss_time != UINT64_MAX &&
- (res == NULL || pktns->rtb.loss_time < res->rtb.loss_time)) {
- res = pktns;
- }
-
- return res;
-}
-
-static ngtcp2_tstamp conn_get_earliest_last_tx_pkt_ts(ngtcp2_conn *conn) {
+static ngtcp2_pktns *conn_get_earliest_pktns(ngtcp2_conn *conn,
+ ngtcp2_tstamp *pts,
+ const ngtcp2_tstamp *times) {
ngtcp2_pktns *ns[] = {conn->in_pktns, conn->hs_pktns, &conn->pktns};
- ngtcp2_rcvry_stat *rcs = &conn->rcs;
- ngtcp2_tstamp earliest_ts = rcs->last_tx_pkt_ts[NGTCP2_CRYPTO_LEVEL_INITIAL];
- ngtcp2_pktns *pktns = ns[0];
+ ngtcp2_pktns *res = ns[0];
size_t i;
-
- for (i = NGTCP2_CRYPTO_LEVEL_HANDSHAKE; i <= NGTCP2_CRYPTO_LEVEL_APP; ++i) {
- if (rcs->last_tx_pkt_ts[i] != UINT64_MAX &&
- (!pktns || rcs->last_tx_pkt_ts[i] < earliest_ts) &&
- (i != NGTCP2_CRYPTO_LEVEL_APP ||
- (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED))) {
- earliest_ts = rcs->last_tx_pkt_ts[i];
- pktns = ns[i];
+ ngtcp2_tstamp earliest_ts = times[NGTCP2_PKTNS_ID_INITIAL];
+
+ for (i = NGTCP2_PKTNS_ID_HANDSHAKE; i < NGTCP2_PKTNS_ID_MAX; ++i) {
+ if (ns[i] == NULL || ns[i]->rtb.num_ack_eliciting == 0 ||
+ (times[i] == UINT64_MAX ||
+ (earliest_ts != UINT64_MAX && times[i] >= earliest_ts) ||
+ (i == NGTCP2_PKTNS_ID_APP &&
+ !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)))) {
+ continue;
}
+
+ earliest_ts = times[i];
+ res = ns[i];
}
- return earliest_ts;
-}
+ if (res == NULL && !conn->server) {
+ earliest_ts = UINT64_MAX;
-static ngtcp2_pktns *
-conn_get_earliest_non_null_last_tx_pktns(ngtcp2_conn *conn) {
- ngtcp2_pktns *ns[] = {conn->in_pktns, conn->hs_pktns, &conn->pktns};
- ngtcp2_pktns *res = ns[0];
- ngtcp2_rcvry_stat *rcs = &conn->rcs;
- size_t i, earliest_ts = rcs->last_tx_pkt_ts[NGTCP2_CRYPTO_LEVEL_INITIAL];
-
- for (i = NGTCP2_CRYPTO_LEVEL_HANDSHAKE; i <= NGTCP2_CRYPTO_LEVEL_APP; ++i) {
- if (res == NULL ||
- (rcs->last_tx_pkt_ts[i] != UINT64_MAX &&
- (earliest_ts == UINT64_MAX || rcs->last_tx_pkt_ts[i] < earliest_ts) &&
- (i != NGTCP2_CRYPTO_LEVEL_APP ||
- (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)))) {
- earliest_ts = rcs->last_tx_pkt_ts[i];
- res = ns[i];
+ if (conn->hs_pktns && conn->hs_pktns->crypto.tx.ckm) {
+ res = conn->hs_pktns;
+ } else {
+ res = conn->in_pktns;
}
}
+ if (pts) {
+ *pts = earliest_ts;
+ }
return res;
}
void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- ngtcp2_rcvry_stat *rcs = &conn->rcs;
+ ngtcp2_conn_stat *cstat = &conn->cstat;
ngtcp2_duration timeout;
ngtcp2_pktns *in_pktns = conn->in_pktns;
ngtcp2_pktns *hs_pktns = conn->hs_pktns;
ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_pktns *earliest_pktns = conn_get_earliest_loss_time_pktns(conn);
+ ngtcp2_pktns *earliest_pktns;
+ ngtcp2_tstamp earliest_loss_time;
ngtcp2_tstamp last_tx_pkt_ts;
- if (earliest_pktns && earliest_pktns->rtb.loss_time != UINT64_MAX) {
- rcs->loss_detection_timer = earliest_pktns->rtb.loss_time;
+ conn_get_earliest_pktns(conn, &earliest_loss_time, cstat->loss_time);
+
+ if (earliest_loss_time != UINT64_MAX) {
+ cstat->loss_detection_timer = earliest_loss_time;
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
"loss_detection_timer=%" PRIu64 " nonzero crypto loss time",
- rcs->loss_detection_timer);
+ cstat->loss_detection_timer);
return;
}
- if ((!in_pktns || ngtcp2_rtb_num_ack_eliciting(&in_pktns->rtb) == 0) &&
- (!hs_pktns || ngtcp2_rtb_num_ack_eliciting(&hs_pktns->rtb) == 0) &&
- ngtcp2_rtb_num_ack_eliciting(&pktns->rtb) == 0 &&
- (conn->server || (conn->flags & NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED))) {
- if (rcs->loss_detection_timer) {
+ if ((!in_pktns || in_pktns->rtb.num_ack_eliciting == 0) &&
+ (!hs_pktns || hs_pktns->rtb.num_ack_eliciting == 0) &&
+ (pktns->rtb.num_ack_eliciting == 0 ||
+ !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) &&
+ (conn->server ||
+ (conn->flags & (NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED |
+ NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)))) {
+ if (cstat->loss_detection_timer) {
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
"loss detection timer canceled");
- rcs->loss_detection_timer = 0;
+ cstat->loss_detection_timer = 0;
+ cstat->pto_count = 0;
}
return;
}
- if (rcs->smoothed_rtt == 0) {
- timeout = 2 * NGTCP2_DEFAULT_INITIAL_RTT;
- } else {
- timeout = conn_compute_pto(conn);
- }
- timeout *= 1ULL << rcs->pto_count;
+ earliest_pktns =
+ conn_get_earliest_pktns(conn, &last_tx_pkt_ts, cstat->last_tx_pkt_ts);
- last_tx_pkt_ts = conn_get_earliest_last_tx_pkt_ts(conn);
+ assert(earliest_pktns);
if (last_tx_pkt_ts == UINT64_MAX) {
last_tx_pkt_ts = ts;
}
- rcs->loss_detection_timer = last_tx_pkt_ts + timeout;
+ timeout = conn_compute_pto(conn, earliest_pktns) * (1ULL << cstat->pto_count);
+
+ cstat->loss_detection_timer = last_tx_pkt_ts + timeout;
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
"loss_detection_timer=%" PRIu64 " last_tx_pkt_ts=%" PRIu64
" timeout=%" PRIu64,
- rcs->loss_detection_timer, last_tx_pkt_ts,
+ cstat->loss_detection_timer, last_tx_pkt_ts,
(uint64_t)(timeout / NGTCP2_MILLISECONDS));
}
/*
- * conn_handshake_pkt_lost is called when handshake packets which
+ * conn_on_crypto_timeout is called when handshake packets which
* belong to |pktns| are lost.
*
* This function returns 0 if it succeeds, or one of the following
@@ -9015,7 +9146,7 @@ static int conn_on_crypto_timeout(ngtcp2_conn *conn, ngtcp2_pktns *pktns) {
ngtcp2_frame_chain *frc = NULL;
int rv;
- rv = ngtcp2_rtb_on_crypto_timeout(&pktns->rtb, &frc);
+ rv = ngtcp2_rtb_on_crypto_timeout(&pktns->rtb, &frc, &conn->cstat);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));
ngtcp2_frame_chain_list_del(frc, conn->mem);
@@ -9032,11 +9163,13 @@ static int conn_on_crypto_timeout(ngtcp2_conn *conn, ngtcp2_pktns *pktns) {
}
int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- ngtcp2_rcvry_stat *rcs = &conn->rcs;
+ ngtcp2_conn_stat *cstat = &conn->cstat;
int rv;
ngtcp2_pktns *in_pktns = conn->in_pktns;
ngtcp2_pktns *hs_pktns = conn->hs_pktns;
- ngtcp2_pktns *loss_pktns = conn_get_earliest_loss_time_pktns(conn);
+ ngtcp2_tstamp earliest_loss_time;
+ ngtcp2_pktns *loss_pktns =
+ conn_get_earliest_pktns(conn, &earliest_loss_time, cstat->loss_time);
ngtcp2_pktns *earliest_pktns;
conn->log.last_ts = ts;
@@ -9045,21 +9178,22 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
switch (conn->state) {
case NGTCP2_CS_CLOSING:
case NGTCP2_CS_DRAINING:
- rcs->loss_detection_timer = 0;
+ cstat->loss_detection_timer = 0;
+ cstat->pto_count = 0;
return 0;
default:
break;
}
- if (!rcs->loss_detection_timer) {
+ if (!cstat->loss_detection_timer) {
return 0;
}
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
"loss detection timer fired");
- if (loss_pktns && loss_pktns->rtb.loss_time != UINT64_MAX) {
- rv = ngtcp2_conn_detect_lost_pkt(conn, loss_pktns, rcs, ts);
+ if (earliest_loss_time != UINT64_MAX) {
+ rv = ngtcp2_conn_detect_lost_pkt(conn, loss_pktns, cstat, ts);
if (rv != 0) {
return rv;
}
@@ -9069,18 +9203,25 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
if (!conn->server && !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
if (hs_pktns->crypto.tx.ckm) {
+ rv = conn_on_crypto_timeout(conn, hs_pktns);
+ if (rv != 0) {
+ return rv;
+ }
hs_pktns->rtb.probe_pkt_left = 1;
} else {
- conn_on_crypto_timeout(conn, in_pktns);
+ rv = conn_on_crypto_timeout(conn, in_pktns);
+ if (rv != 0) {
+ return rv;
+ }
in_pktns->rtb.probe_pkt_left = 1;
}
} else {
- earliest_pktns = conn_get_earliest_non_null_last_tx_pktns(conn);
+ earliest_pktns = conn_get_earliest_pktns(conn, NULL, cstat->last_tx_pkt_ts);
assert(earliest_pktns);
- switch (earliest_pktns->rtb.crypto_level) {
- case NGTCP2_CRYPTO_LEVEL_INITIAL:
+ switch (earliest_pktns->rtb.pktns_id) {
+ case NGTCP2_PKTNS_ID_INITIAL:
assert(in_pktns);
rv = conn_on_crypto_timeout(conn, in_pktns);
if (rv != 0) {
@@ -9092,7 +9233,7 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
}
/* fall through for server so that it can coalesce packets. */
/* fall through */
- case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
+ case NGTCP2_PKTNS_ID_HANDSHAKE:
assert(hs_pktns);
rv = conn_on_crypto_timeout(conn, hs_pktns);
if (rv != 0) {
@@ -9100,7 +9241,7 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
}
hs_pktns->rtb.probe_pkt_left = 1;
break;
- case NGTCP2_CRYPTO_LEVEL_APP:
+ case NGTCP2_PKTNS_ID_APP:
conn->pktns.rtb.probe_pkt_left = 2;
break;
default:
@@ -9108,10 +9249,10 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
}
}
- ++rcs->pto_count;
+ ++cstat->pto_count;
ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, "pto_count=%zu",
- rcs->pto_count);
+ cstat->pto_count);
ngtcp2_conn_set_loss_detection_timer(conn, ts);
@@ -9124,7 +9265,6 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn,
ngtcp2_pktns *pktns;
ngtcp2_frame_chain *frc;
ngtcp2_crypto *fr;
- ngtcp2_ksl_key key;
int rv;
if (datalen == 0) {
@@ -9160,8 +9300,7 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn,
fr->data[0].len = datalen;
fr->data[0].base = (uint8_t *)data;
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- ngtcp2_ksl_key_ptr(&key, &fr->offset), frc);
+ rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &fr->offset, frc);
if (rv != 0) {
ngtcp2_frame_chain_del(frc, conn->mem);
return rv;
@@ -9173,6 +9312,34 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn,
return 0;
}
+int ngtcp2_conn_submit_new_token(ngtcp2_conn *conn, const uint8_t *token,
+ size_t tokenlen) {
+ int rv;
+ ngtcp2_frame_chain *nfrc;
+ uint8_t *p;
+
+ assert(conn->server);
+ assert(token);
+ assert(tokenlen);
+
+ rv = ngtcp2_frame_chain_extralen_new(&nfrc, tokenlen, conn->mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ nfrc->fr.type = NGTCP2_FRAME_NEW_TOKEN;
+
+ p = (uint8_t *)nfrc + sizeof(*nfrc);
+ memcpy(p, token, tokenlen);
+
+ ngtcp2_vec_init(&nfrc->fr.new_token.token, p, tokenlen);
+
+ nfrc->next = conn->pktns.tx.frq;
+ conn->pktns.tx.frq = nfrc;
+
+ return 0;
+}
+
ngtcp2_strm *ngtcp2_conn_tx_strmq_top(ngtcp2_conn *conn) {
assert(!ngtcp2_pq_empty(&conn->tx.strmq));
return ngtcp2_struct_of(ngtcp2_pq_top(&conn->tx.strmq), ngtcp2_strm, pe);
@@ -9350,6 +9517,21 @@ uint64_t ngtcp2_conn_get_max_data_left(ngtcp2_conn *conn) {
return conn->tx.max_offset - conn->tx.offset;
}
+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;
+}
+
+uint64_t ngtcp2_conn_get_streams_uni_left(ngtcp2_conn *conn) {
+ uint64_t n = ngtcp2_ord_stream_id(conn->local.uni.next_stream_id);
+
+ return n > conn->local.uni.max_streams ? 0
+ : conn->local.uni.max_streams - n + 1;
+}
+
ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) {
ngtcp2_duration trpto;
ngtcp2_duration idle_timeout;
@@ -9358,6 +9540,7 @@ ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) {
completion. */
if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) ||
+ conn->remote.transport_params.max_idle_timeout == 0 ||
(conn->local.settings.transport_params.max_idle_timeout &&
conn->local.settings.transport_params.max_idle_timeout <
conn->remote.transport_params.max_idle_timeout)) {
@@ -9370,13 +9553,19 @@ ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) {
return UINT64_MAX;
}
- trpto = 3 * conn_compute_pto(conn);
+ trpto = 3 * conn_compute_pto(
+ conn, (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)
+ ? &conn->pktns
+ : conn->hs_pktns);
return conn->idle_ts + ngtcp2_max(idle_timeout, trpto);
}
ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn) {
- return conn_compute_pto(conn);
+ return conn_compute_pto(conn,
+ (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)
+ ? &conn->pktns
+ : conn->hs_pktns);
}
void ngtcp2_conn_set_initial_crypto_ctx(ngtcp2_conn *conn,
@@ -9406,6 +9595,15 @@ const ngtcp2_crypto_ctx *ngtcp2_conn_get_crypto_ctx(ngtcp2_conn *conn) {
return &conn->pktns.crypto.ctx;
}
+void *ngtcp2_conn_get_tls_native_handle(ngtcp2_conn *conn) {
+ return conn->crypto.tls_native_handle;
+}
+
+void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn,
+ void *tls_native_handle) {
+ conn->crypto.tls_native_handle = tls_native_handle;
+}
+
void ngtcp2_conn_get_connection_close_error_code(
ngtcp2_conn *conn, ngtcp2_connection_close_error_code *ccec) {
*ccec = conn->rx.ccec;
@@ -9423,6 +9621,8 @@ int ngtcp2_conn_is_local_stream(ngtcp2_conn *conn, int64_t stream_id) {
return conn_local_stream(conn, stream_id);
}
+int ngtcp2_conn_is_server(ngtcp2_conn *conn) { return conn->server; }
+
void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent,
const uint8_t *data) {
memcpy(pcent->data, data, sizeof(pcent->data));
@@ -9430,7 +9630,9 @@ void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent,
void ngtcp2_settings_default(ngtcp2_settings *settings) {
memset(settings, 0, sizeof(*settings));
- settings->transport_params.max_packet_size = NGTCP2_MAX_PKT_SIZE;
+ settings->cc_algo = NGTCP2_CC_ALGO_CUBIC;
+ settings->transport_params.max_udp_payload_size =
+ NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE;
settings->transport_params.ack_delay_exponent =
NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
settings->transport_params.max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
diff --git a/deps/ngtcp2/lib/ngtcp2_conn.h b/deps/ngtcp2/lib/ngtcp2_conn.h
index 3b17a3d230a..39b5b029385 100644
--- a/deps/ngtcp2/lib/ngtcp2_conn.h
+++ b/deps/ngtcp2/lib/ngtcp2_conn.h
@@ -262,16 +262,18 @@ struct ngtcp2_conn {
/* rcid is a connection ID present in Initial or 0-RTT packet from
client as destination connection ID. Server uses this field to
check that duplicated Initial or 0-RTT packet are indeed sent to
- this connection. Client uses this field to validate
- original_connection_id transport parameter. */
+ this connection. It is also sent to client as
+ original_destination_connection_id transport parameter. Client
+ uses this field to validate original_destination_connection_id
+ transport parameter if no Retry packet is involved. */
ngtcp2_cid rcid;
/* oscid is the source connection ID initially used by the local
endpoint. */
ngtcp2_cid oscid;
- /* odcid is the destination connection ID initially negotiated
- during handshake. It is used to receive late handshake packets
- after handshake completion. */
- ngtcp2_cid odcid;
+ /* retry_scid is the source connection ID from Retry packet. Client
+ records it in order to verify retry_source_connection_id
+ transport parameter. Server does not use this field. */
+ ngtcp2_cid retry_scid;
ngtcp2_pktns *in_pktns;
ngtcp2_pktns *hs_pktns;
ngtcp2_pktns pktns;
@@ -338,6 +340,14 @@ struct ngtcp2_conn {
ngtcp2_ringbuf path_challenge;
/* ccec is the received connection close error code. */
ngtcp2_connection_close_error_code ccec;
+ struct {
+ /* start_ts is the time instant when receiving rate measurement
+ is started. */
+ ngtcp2_tstamp start_ts;
+ /* received is the number of bytes received in the current
+ measurement period. */
+ uint64_t received;
+ } rate;
} rx;
struct {
@@ -417,6 +427,8 @@ struct ngtcp2_conn {
ngtcp2_tstamp confirmed_ts;
} key_update;
+ /* tls_native_handle is a native handle to TLS session object. */
+ void *tls_native_handle;
size_t aead_overhead;
/* decrypt_buf is a buffer which is used to write decrypted data. */
ngtcp2_vec decrypt_buf;
@@ -441,23 +453,13 @@ struct ngtcp2_conn {
} pkt;
ngtcp2_map strms;
- ngtcp2_rcvry_stat rcs;
- ngtcp2_cc_stat ccs;
+ ngtcp2_conn_stat cstat;
ngtcp2_pv *pv;
ngtcp2_log log;
ngtcp2_qlog qlog;
ngtcp2_rst rst;
- ngtcp2_default_cc cc;
- /* token is an address validation token received from server. */
- ngtcp2_buf token;
- /* hs_recved is the number of bytes received from client before its
- address is validated. This field is only used by server to
- ensure "3 times received data" rule. */
- size_t hs_recved;
- /* hs_sent is the number of bytes sent from server during handshake.
- This field is only used by server to ensure "3 times received
- data" rule. */
- size_t hs_sent;
+ ngtcp2_cc_algo cc_algo;
+ ngtcp2_cc cc;
const ngtcp2_mem *mem;
/* idle_ts is the time instant when idle timer started. */
ngtcp2_tstamp idle_ts;
@@ -468,101 +470,6 @@ struct ngtcp2_conn {
int server;
};
-/**
- * @function
- *
- * `ngtcp2_conn_read_handshake` performs QUIC cryptographic handshake
- * by reading given data. |pkt| points to the buffer to read and
- * |pktlen| is the length of the buffer. |path| is the network path.
- *
- * The application should call `ngtcp2_conn_write_handshake` (or
- * `ngtcp2_conn_client_write_handshake` for client session) to make
- * handshake go forward after calling this function.
- *
- * Application should call this function until
- * `ngtcp2_conn_get_handshake_completed` returns nonzero. After the
- * completion of handshake, `ngtcp2_conn_read_pkt` and
- * `ngtcp2_conn_write_pkt` should be called instead.
- *
- * This function must not be called from inside the callback
- * functions.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes: (TBD).
- */
-int ngtcp2_conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_write_handshake` performs QUIC cryptographic handshake
- * by writing handshake packets. It may write a packet in the given
- * buffer pointed by |dest| whose capacity is given as |destlen|.
- * Application must ensure that the buffer pointed by |dest| is not
- * empty.
- *
- * Application should keep calling this function repeatedly until it
- * returns zero, or negative error code.
- *
- * Application should call this function until
- * `ngtcp2_conn_get_handshake_completed` returns nonzero. After the
- * completion of handshake, `ngtcp2_conn_read_pkt` and
- * `ngtcp2_conn_write_pkt` should be called instead.
- *
- * During handshake, application can send 0-RTT data (or its response)
- * using `ngtcp2_conn_write_stream`.
- * `ngtcp2_conn_client_write_handshake` is generally efficient because
- * it can coalesce Handshake packet and 0-RTT packet into one UDP
- * packet.
- *
- * This function returns 0 if it cannot write any frame because buffer
- * is too small, or packet is congestion limited. Application should
- * keep reading and wait for congestion window to grow.
- *
- * This function must not be called from inside the callback
- * functions.
- *
- * This function returns the number of bytes written to the buffer
- * pointed by |dest| if it succeeds, or one of the following negative
- * error codes: (TBD).
- */
-ngtcp2_ssize ngtcp2_conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_client_write_handshake` is just like
- * `ngtcp2_conn_write_handshake`, but it is for client only, and can
- * write 0-RTT data. This function can coalesce handshake packet and
- * 0-RTT packet into single UDP packet, thus it is generally more
- * efficient than the combination of `ngtcp2_conn_write_handshake` and
- * `ngtcp2_conn_write_stream`.
- *
- * |stream_id|, |fin|, |datav|, and |datavcnt| are stream identifier
- * to which 0-RTT data is sent, whether it is a last data chunk in
- * this stream, a vector of 0-RTT data, and its number of elements
- * respectively. If there is no 0RTT data to send, pass negative
- * integer to |stream_id|. The amount of 0RTT data sent is assigned
- * to |*pdatalen|. If no data is sent, -1 is assigned. Note that 0
- * length STREAM frame is allowed in QUIC, so 0 might be assigned to
- * |*pdatalen|.
- *
- * This function returns 0 if it cannot write any frame because buffer
- * is too small, or packet is congestion limited. Application should
- * keep reading and wait for congestion window to grow.
- *
- * This function returns the number of bytes written to the buffer
- * pointed by |dest| if it succeeds, or one of the following negative
- * error codes: (TBD).
- */
-ngtcp2_ssize ngtcp2_conn_client_write_handshake(
- ngtcp2_conn *conn, uint8_t *dest, size_t destlen, ngtcp2_ssize *pdatalen,
- uint32_t flags, int64_t stream_id, int fin, const ngtcp2_vec *datav,
- size_t datavcnt, ngtcp2_tstamp ts);
-
/*
* ngtcp2_conn_sched_ack stores packet number |pkt_num| and its
* reception timestamp |ts| in order to send its ACK.
@@ -653,7 +560,7 @@ void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts);
* Out of memory.
*/
int ngtcp2_conn_detect_lost_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
- ngtcp2_rcvry_stat *rcs, ngtcp2_tstamp ts);
+ ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts);
/*
* ngtcp2_conn_tx_strmq_top returns the ngtcp2_strm which sits on the
diff --git a/deps/ngtcp2/lib/ngtcp2_crypto.c b/deps/ngtcp2/lib/ngtcp2_crypto.c
index dd65ff7e303..26eacb87299 100644
--- a/deps/ngtcp2/lib/ngtcp2_crypto.c
+++ b/deps/ngtcp2/lib/ngtcp2_crypto.c
@@ -72,6 +72,7 @@ int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
(*pckm)->iv.base = p;
(*pckm)->iv.len = ivlen;
(*pckm)->pkt_num = -1;
+ (*pckm)->use_count = 0;
(*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE;
return 0;
@@ -118,6 +119,33 @@ static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id,
return ngtcp2_put_varint(p, value);
}
+/*
+ * 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_varint_len(id) + ngtcp2_put_varint_len(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_varint(p, id);
+ p = ngtcp2_put_varint(p, cid->datalen);
+ if (cid->datalen) {
+ p = ngtcp2_cpymem(p, cid->data, cid->datalen);
+ }
+ return p;
+}
+
ngtcp2_ssize
ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
ngtcp2_transport_params_type exttype,
@@ -131,6 +159,10 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
case NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO:
break;
case NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS:
+ len +=
+ cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
+ &params->original_dcid);
+
if (params->stateless_reset_token_present) {
len +=
ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) +
@@ -138,8 +170,7 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
NGTCP2_STATELESS_RESET_TOKENLEN;
}
if (params->preferred_address_present) {
- assert(params->preferred_address.cid.datalen == 0 ||
- params->preferred_address.cid.datalen >= NGTCP2_MIN_CIDLEN);
+ assert(params->preferred_address.cid.datalen >= NGTCP2_MIN_CIDLEN);
assert(params->preferred_address.cid.datalen <= NGTCP2_MAX_CIDLEN);
preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ +
16 /* ipv6Address */ + 2 /* ipv6Port */
@@ -149,17 +180,18 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) +
ngtcp2_put_varint_len(preferred_addrlen) + preferred_addrlen;
}
- if (params->original_connection_id_present) {
- len +=
- ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_ORIGINAL_CONNECTION_ID) +
- ngtcp2_put_varint_len(params->original_connection_id.datalen) +
- params->original_connection_id.datalen;
+ if (params->retry_scid_present) {
+ len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
+ &params->retry_scid);
}
break;
default:
return NGTCP2_ERR_INVALID_ARGUMENT;
}
+ len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
+ &params->initial_scid);
+
if (params->initial_max_stream_data_bidi_local) {
len += varint_paramlen(
NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
@@ -186,9 +218,9 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
params->initial_max_streams_uni);
}
- if (params->max_packet_size != NGTCP2_MAX_PKT_SIZE) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_PACKET_SIZE,
- params->max_packet_size);
+ if (params->max_udp_payload_size != NGTCP2_DEFAULT_MAX_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,
@@ -221,6 +253,10 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
p = dest;
if (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
+ p = write_cid_param(
+ p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
+ &params->original_dcid);
+
if (params->stateless_reset_token_present) {
p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN);
p = ngtcp2_put_varint(p, sizeof(params->stateless_reset_token));
@@ -248,14 +284,15 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
p, params->preferred_address.stateless_reset_token,
sizeof(params->preferred_address.stateless_reset_token));
}
- if (params->original_connection_id_present) {
- p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_CONNECTION_ID);
- p = ngtcp2_put_varint(p, params->original_connection_id.datalen);
- p = ngtcp2_cpymem(p, params->original_connection_id.data,
- params->original_connection_id.datalen);
+ if (params->retry_scid_present) {
+ p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
+ &params->retry_scid);
}
}
+ p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
+ &params->initial_scid);
+
if (params->initial_max_stream_data_bidi_local) {
p = write_varint_param(
p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
@@ -289,9 +326,9 @@ ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
params->initial_max_streams_uni);
}
- if (params->max_packet_size != NGTCP2_MAX_PKT_SIZE) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_PACKET_SIZE,
- params->max_packet_size);
+ if (params->max_udp_payload_size != NGTCP2_DEFAULT_MAX_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) {
@@ -371,6 +408,10 @@ static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p,
p += nread;
+ if (p == end) {
+ return -1;
+ }
+
if ((uint64_t)(end - p) < valuelen) {
return -1;
}
@@ -386,6 +427,37 @@ static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p,
return (ngtcp2_ssize)(p - begin);
}
+/*
+ * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer
+ * pointed by |p| of length |end - p|. The length is encoded in
+ * varint form. If it decodes a value successfully, it stores the
+ * value in |*pdest| and returns the number of bytes read. Otherwise
+ * it returns -1.
+ */
+static ngtcp2_ssize decode_cid_param(ngtcp2_cid *pdest, const uint8_t *p,
+ const uint8_t *end) {
+ const uint8_t *begin = p;
+ uint64_t valuelen;
+ ngtcp2_ssize nread = decode_varint(&valuelen, p, end);
+
+ if (nread < 0) {
+ return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ }
+
+ p += nread;
+
+ 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;
+
+ return (ngtcp2_ssize)(p - begin);
+}
+
int ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
ngtcp2_transport_params_type exttype,
const uint8_t *data, size_t datalen) {
@@ -394,37 +466,37 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
uint64_t param_type;
uint64_t valuelen;
ngtcp2_ssize nread;
- uint8_t scb[8192];
- size_t scb_idx;
- size_t scb_shift;
+ int initial_scid_present = 0;
+ int original_dcid_present = 0;
p = data;
end = data + datalen;
/* Set default values */
+ memset(params, 0, sizeof(*params));
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_packet_size = NGTCP2_MAX_PKT_SIZE;
+ params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE;
params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
params->stateless_reset_token_present = 0;
params->preferred_address_present = 0;
- memset(&params->preferred_address, 0, sizeof(params->preferred_address));
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->original_connection_id_present = 0;
+ params->retry_scid_present = 0;
+ memset(&params->retry_scid, 0, sizeof(params->retry_scid));
+ memset(&params->initial_scid, 0, sizeof(params->initial_scid));
+ memset(&params->original_dcid, 0, sizeof(params->original_dcid));
if (datalen == 0) {
return 0;
}
- memset(scb, 0, sizeof(scb));
-
for (; (size_t)(end - p) >= 2;) {
nread = decode_varint(&param_type, p, end);
if (nread < 0) {
@@ -432,13 +504,6 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
}
p += nread;
- scb_idx = param_type / 8;
- scb_shift = param_type % 8;
-
- if (scb[scb_idx] & (1 << scb_shift)) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- scb[scb_idx] |= (uint8_t)(1 << scb_shift);
switch (param_type) {
case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
nread = decode_varint_param(&params->initial_max_stream_data_bidi_local,
@@ -498,8 +563,8 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
params->max_idle_timeout *= NGTCP2_MILLISECONDS;
p += nread;
break;
- case NGTCP2_TRANSPORT_PARAM_MAX_PACKET_SIZE:
- nread = decode_varint_param(&params->max_packet_size, p, end);
+ case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE:
+ nread = decode_varint_param(&params->max_udp_payload_size, p, end);
if (nread < 0) {
return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
}
@@ -570,8 +635,7 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
len += params->preferred_address.cid.datalen;
if (valuelen != len ||
params->preferred_address.cid.datalen > NGTCP2_MAX_CIDLEN ||
- (params->preferred_address.cid.datalen != 0 &&
- params->preferred_address.cid.datalen < NGTCP2_MIN_CIDLEN)) {
+ params->preferred_address.cid.datalen < NGTCP2_MIN_CIDLEN) {
return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
}
if (params->preferred_address.cid.datalen) {
@@ -594,22 +658,35 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
p += nread;
params->disable_active_migration = 1;
break;
- case NGTCP2_TRANSPORT_PARAM_ORIGINAL_CONNECTION_ID:
+ case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID:
if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
}
- nread = decode_varint(&valuelen, p, end);
+ nread = decode_cid_param(&params->original_dcid, p, end);
if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
+ return (int)nread;
}
+ original_dcid_present = 1;
p += nread;
- if (valuelen < NGTCP2_MIN_CIDLEN || valuelen > NGTCP2_MAX_CIDLEN ||
- (size_t)(end - p) < valuelen) {
+ break;
+ case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID:
+ if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
}
- ngtcp2_cid_init(&params->original_connection_id, p, valuelen);
- params->original_connection_id_present = 1;
- p += valuelen;
+ nread = decode_cid_param(&params->retry_scid, p, end);
+ if (nread < 0) {
+ return (int)nread;
+ }
+ params->retry_scid_present = 1;
+ p += nread;
+ break;
+ case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID:
+ nread = decode_cid_param(&params->initial_scid, p, end);
+ if (nread < 0) {
+ return (int)nread;
+ }
+ initial_scid_present = 1;
+ p += nread;
break;
case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY:
nread = decode_varint_param(&params->max_ack_delay, p, end);
@@ -645,5 +722,11 @@ int ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
}
+ if (!initial_scid_present ||
+ (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS &&
+ !original_dcid_present)) {
+ return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
+ }
+
return 0;
}
diff --git a/deps/ngtcp2/lib/ngtcp2_crypto.h b/deps/ngtcp2/lib/ngtcp2_crypto.h
index 8dc1ef9f39d..1cc144e801a 100644
--- a/deps/ngtcp2/lib/ngtcp2_crypto.h
+++ b/deps/ngtcp2/lib/ngtcp2_crypto.h
@@ -57,6 +57,10 @@ typedef struct {
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 or decryption failure. For
+ tx key, this is the number of encryption. For rx key, this is
+ the number of decryption failure. */
+ uint64_t use_count;
/* flags is the bitwise OR of zero or more of
ngtcp2_crypto_km_flag. */
uint8_t flags;
@@ -88,7 +92,7 @@ void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem);
typedef struct {
ngtcp2_crypto_aead aead;
ngtcp2_crypto_cipher hp;
- const ngtcp2_crypto_km *ckm;
+ ngtcp2_crypto_km *ckm;
const ngtcp2_vec *hp_key;
size_t aead_overhead;
ngtcp2_encrypt encrypt;
diff --git a/deps/ngtcp2/lib/ngtcp2_err.c b/deps/ngtcp2/lib/ngtcp2_err.c
index ae2edb35ee4..6de827b0f97 100644
--- a/deps/ngtcp2/lib/ngtcp2_err.c
+++ b/deps/ngtcp2/lib/ngtcp2_err.c
@@ -98,6 +98,8 @@ const char *ngtcp2_strerror(int liberr) {
return "ERR_WRITE_STREAM_MORE";
case NGTCP2_ERR_RETRY:
return "ERR_RETRY";
+ case NGTCP2_ERR_DROP_CONN:
+ return "ERR_DROP_CONN";
default:
return "(unknown)";
}
diff --git a/deps/ngtcp2/lib/ngtcp2_gaptr.c b/deps/ngtcp2/lib/ngtcp2_gaptr.c
index 4cbd898a292..b93cd828c21 100644
--- a/deps/ngtcp2/lib/ngtcp2_gaptr.c
+++ b/deps/ngtcp2/lib/ngtcp2_gaptr.c
@@ -30,7 +30,6 @@
int ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem) {
int rv;
ngtcp2_range range = {0, UINT64_MAX};
- ngtcp2_ksl_key key;
rv = ngtcp2_ksl_init(&gaptr->gap, ngtcp2_ksl_range_compar,
sizeof(ngtcp2_range), mem);
@@ -38,8 +37,7 @@ int ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem) {
return rv;
}
- rv = ngtcp2_ksl_insert(&gaptr->gap, NULL, ngtcp2_ksl_key_ptr(&key, &range),
- NULL);
+ rv = ngtcp2_ksl_insert(&gaptr->gap, NULL, &range, NULL);
if (rv != 0) {
ngtcp2_ksl_free(&gaptr->gap);
return rv;
@@ -62,37 +60,33 @@ int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, size_t datalen) {
int rv;
ngtcp2_range k, m, l, r, q = {offset, offset + datalen};
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key, old_key;
- it = ngtcp2_ksl_lower_bound_compar(&gaptr->gap, ngtcp2_ksl_key_ptr(&key, &q),
+ it = ngtcp2_ksl_lower_bound_compar(&gaptr->gap, &q,
ngtcp2_ksl_range_exclusive_compar);
for (; !ngtcp2_ksl_it_end(&it);) {
- k = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it).ptr;
+ k = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
m = ngtcp2_range_intersect(&q, &k);
if (!ngtcp2_range_len(&m)) {
break;
}
if (ngtcp2_range_eq(&k, &m)) {
- ngtcp2_ksl_remove(&gaptr->gap, &it, ngtcp2_ksl_key_ptr(&key, &k));
+ ngtcp2_ksl_remove(&gaptr->gap, &it, &k);
continue;
}
ngtcp2_range_cut(&l, &r, &k, &m);
if (ngtcp2_range_len(&l)) {
- ngtcp2_ksl_update_key(&gaptr->gap, ngtcp2_ksl_key_ptr(&old_key, &k),
- ngtcp2_ksl_key_ptr(&key, &l));
+ ngtcp2_ksl_update_key(&gaptr->gap, &k, &l);
if (ngtcp2_range_len(&r)) {
- rv = ngtcp2_ksl_insert(&gaptr->gap, &it, ngtcp2_ksl_key_ptr(&key, &r),
- NULL);
+ rv = ngtcp2_ksl_insert(&gaptr->gap, &it, &r, NULL);
if (rv != 0) {
return rv;
}
}
} else if (ngtcp2_range_len(&r)) {
- ngtcp2_ksl_update_key(&gaptr->gap, ngtcp2_ksl_key_ptr(&old_key, &k),
- ngtcp2_ksl_key_ptr(&key, &r));
+ ngtcp2_ksl_update_key(&gaptr->gap, &k, &r);
}
ngtcp2_ksl_it_next(&it);
}
@@ -101,27 +95,23 @@ int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, size_t datalen) {
uint64_t ngtcp2_gaptr_first_gap_offset(ngtcp2_gaptr *gaptr) {
ngtcp2_ksl_it it = ngtcp2_ksl_begin(&gaptr->gap);
- ngtcp2_range r = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it).ptr;
+ ngtcp2_range r = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
return r.begin;
}
ngtcp2_ksl_it ngtcp2_gaptr_get_first_gap_after(ngtcp2_gaptr *gaptr,
uint64_t offset) {
ngtcp2_range q = {offset, offset + 1};
- ngtcp2_ksl_key key;
- return ngtcp2_ksl_lower_bound_compar(&gaptr->gap,
- ngtcp2_ksl_key_ptr(&key, &q),
+ return ngtcp2_ksl_lower_bound_compar(&gaptr->gap, &q,
ngtcp2_ksl_range_exclusive_compar);
}
int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset,
size_t datalen) {
- ngtcp2_ksl_key key;
ngtcp2_range q = {offset, offset + datalen};
- ngtcp2_ksl_it it =
- ngtcp2_ksl_lower_bound_compar(&gaptr->gap, ngtcp2_ksl_key_ptr(&key, &q),
- ngtcp2_ksl_range_exclusive_compar);
- ngtcp2_range k = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it).ptr;
+ ngtcp2_ksl_it it = ngtcp2_ksl_lower_bound_compar(
+ &gaptr->gap, &q, ngtcp2_ksl_range_exclusive_compar);
+ ngtcp2_range k = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
ngtcp2_range m = ngtcp2_range_intersect(&q, &k);
return ngtcp2_range_len(&m) == 0;
}
diff --git a/deps/ngtcp2/lib/ngtcp2_ksl.c b/deps/ngtcp2/lib/ngtcp2_ksl.c
index 7936a269127..10c49806254 100644
--- a/deps/ngtcp2/lib/ngtcp2_ksl.c
+++ b/deps/ngtcp2/lib/ngtcp2_ksl.c
@@ -48,30 +48,7 @@ static size_t ksl_blklen(size_t nodelen) {
*/
static void ksl_node_set_key(ngtcp2_ksl *ksl, ngtcp2_ksl_node *node,
const void *key) {
- memcpy(&node->key, key, ksl->keylen);
-}
-
-/*
- * ksl_node_key assigns the pointer to key of |node| to key->ptr and
- * returns |key|.
- */
-static ngtcp2_ksl_key *ksl_node_key(ngtcp2_ksl_key *key,
- ngtcp2_ksl_node *node) {
- key->ptr = &node->key;
- return key;
-}
-
-/*
- * ksl_nth_node returns |n|th node under |blk|.
- */
-static ngtcp2_ksl_node *ksl_nth_node(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
- size_t n) {
- return (ngtcp2_ksl_node *)(void *)(blk->nodes + ksl->nodelen * n);
-}
-
-ngtcp2_ksl_node *ngtcp2_ksl_nth_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
- size_t n) {
- return ksl_nth_node(ksl, blk, n);
+ memcpy(node->key, key, ksl->keylen);
}
int ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, size_t keylen,
@@ -107,7 +84,7 @@ static void ksl_free_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
if (!blk->leaf) {
for (i = 0; i < blk->n; ++i) {
- ksl_free_blk(ksl, ksl_nth_node(ksl, blk, i)->blk);
+ ksl_free_blk(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk);
}
}
@@ -174,7 +151,7 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
*/
static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
ngtcp2_ksl_node *node;
- ngtcp2_ksl_blk *lblk = ksl_nth_node(ksl, blk, i)->blk, *rblk;
+ ngtcp2_ksl_blk *lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk, *rblk;
rblk = ksl_split_blk(ksl, lblk);
if (rblk == NULL) {
@@ -185,13 +162,13 @@ static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
blk->nodes + (i + 1) * ksl->nodelen,
ksl->nodelen * (blk->n - (i + 1)));
- node = ksl_nth_node(ksl, blk, i + 1);
+ node = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
node->blk = rblk;
++blk->n;
- ksl_node_set_key(ksl, node, &ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
+ ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
- node = ksl_nth_node(ksl, blk, i);
- ksl_node_set_key(ksl, node, &ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
+ node = ngtcp2_ksl_nth_node(ksl, blk, i);
+ ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
return 0;
}
@@ -226,12 +203,12 @@ static int ksl_split_head(ngtcp2_ksl *ksl) {
nhead->n = 2;
nhead->leaf = 0;
- node = ksl_nth_node(ksl, nhead, 0);
- ksl_node_set_key(ksl, node, &ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
+ node = ngtcp2_ksl_nth_node(ksl, nhead, 0);
+ ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
node->blk = lblk;
- node = ksl_nth_node(ksl, nhead, 1);
- ksl_node_set_key(ksl, node, &ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
+ node = ngtcp2_ksl_nth_node(ksl, nhead, 1);
+ ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
node->blk = rblk;
ksl->head = nhead;
@@ -254,8 +231,8 @@ static void ksl_insert_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i,
memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen,
ksl->nodelen * (blk->n - i));
- node = ksl_nth_node(ksl, blk, i);
- ksl_node_set_key(ksl, node, key->ptr);
+ node = ngtcp2_ksl_nth_node(ksl, blk, i);
+ ksl_node_set_key(ksl, node, key);
node->data = data;
++blk->n;
@@ -265,12 +242,11 @@ static size_t ksl_bsearch(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
const ngtcp2_ksl_key *key, ngtcp2_ksl_compar compar) {
ngtcp2_ssize left = -1, right = (ngtcp2_ssize)blk->n, mid;
ngtcp2_ksl_node *node;
- ngtcp2_ksl_key node_key;
while (right - left > 1) {
mid = (left + right) / 2;
- node = ksl_nth_node(ksl, blk, (size_t)mid);
- if (compar(ksl_node_key(&node_key, node), key)) {
+ node = ngtcp2_ksl_nth_node(ksl, blk, (size_t)mid);
+ if (compar((ngtcp2_ksl_key *)node->key, key)) {
left = mid;
} else {
right = mid;
@@ -284,7 +260,6 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
const ngtcp2_ksl_key *key, void *data) {
ngtcp2_ksl_blk *blk = ksl->head;
ngtcp2_ksl_node *node;
- ngtcp2_ksl_key node_key;
size_t i;
int rv;
@@ -311,15 +286,15 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
if (i == blk->n) {
/* This insertion extends the largest key in this subtree. */
for (; !blk->leaf;) {
- node = ksl_nth_node(ksl, blk, blk->n - 1);
+ node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1);
if (node->blk->n == NGTCP2_KSL_MAX_NBLK) {
rv = ksl_split_node(ksl, blk, blk->n - 1);
if (rv != 0) {
return rv;
}
- node = ksl_nth_node(ksl, blk, blk->n - 1);
+ node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1);
}
- ksl_node_set_key(ksl, node, key->ptr);
+ ksl_node_set_key(ksl, node, key);
blk = node->blk;
}
ksl_insert_node(ksl, blk, blk->n, key, data);
@@ -330,17 +305,17 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
return 0;
}
- node = ksl_nth_node(ksl, blk, i);
+ node = ngtcp2_ksl_nth_node(ksl, blk, i);
if (node->blk->n == NGTCP2_KSL_MAX_NBLK) {
rv = ksl_split_node(ksl, blk, i);
if (rv != 0) {
return rv;
}
- if (ksl->compar(ksl_node_key(&node_key, node), key)) {
- node = ksl_nth_node(ksl, blk, i + 1);
- if (ksl->compar(ksl_node_key(&node_key, node), key)) {
- ksl_node_set_key(ksl, node, key->ptr);
+ 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,8 +351,8 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
assert(i + 1 < blk->n);
- lblk = ksl_nth_node(ksl, blk, i)->blk;
- rblk = ksl_nth_node(ksl, blk, i + 1)->blk;
+ lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
+ rblk = ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk;
assert(lblk->n + rblk->n < NGTCP2_KSL_MAX_NBLK);
@@ -399,8 +374,8 @@ 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, ksl_nth_node(ksl, blk, i),
- &ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
+ ksl_node_set_key(ksl, ngtcp2_ksl_nth_node(ksl, blk, i),
+ ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
}
return lblk;
@@ -415,17 +390,17 @@ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
assert(i > 0);
- lnode = ksl_nth_node(ksl, blk, i - 1);
- rnode = ksl_nth_node(ksl, blk, 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);
- dest = ksl_nth_node(ksl, lnode->blk, lnode->blk->n);
- src = ksl_nth_node(ksl, rnode->blk, 0);
+ dest = ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n);
+ src = ngtcp2_ksl_nth_node(ksl, rnode->blk, 0);
memcpy(dest, src, ksl->nodelen);
- ksl_node_set_key(ksl, lnode, &dest->key);
+ ksl_node_set_key(ksl, lnode, dest->key);
++lnode->blk->n;
--rnode->blk->n;
@@ -442,8 +417,8 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
assert(i < blk->n - 1);
- lnode = ksl_nth_node(ksl, blk, i);
- rnode = ksl_nth_node(ksl, blk, i + 1);
+ 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);
@@ -452,14 +427,14 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
ksl->nodelen * rnode->blk->n);
++rnode->blk->n;
- dest = ksl_nth_node(ksl, rnode->blk, 0);
- src = ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1);
+ dest = ngtcp2_ksl_nth_node(ksl, rnode->blk, 0);
+ src = ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1);
memcpy(dest, src, ksl->nodelen);
--lnode->blk->n;
- ksl_node_set_key(ksl, lnode,
- &ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key);
+ ksl_node_set_key(
+ ksl, lnode, ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key);
}
/*
@@ -478,8 +453,8 @@ void ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
size_t i;
if (!blk->leaf && blk->n == 2 &&
- ksl_nth_node(ksl, blk, 0)->blk->n == NGTCP2_KSL_MIN_NBLK &&
- ksl_nth_node(ksl, blk, 1)->blk->n == NGTCP2_KSL_MIN_NBLK) {
+ 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);
}
@@ -502,15 +477,18 @@ void ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
return;
}
- node = ksl_nth_node(ksl, blk, i);
+ node = ngtcp2_ksl_nth_node(ksl, blk, i);
if (node->blk->n == NGTCP2_KSL_MIN_NBLK) {
if (i > 0 &&
- ksl_nth_node(ksl, blk, i - 1)->blk->n > NGTCP2_KSL_MIN_NBLK) {
+ ngtcp2_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGTCP2_KSL_MIN_NBLK) {
ksl_shift_right(ksl, blk, i - 1);
+ blk = node->blk;
} else if (i + 1 < blk->n &&
- ksl_nth_node(ksl, blk, i + 1)->blk->n > NGTCP2_KSL_MIN_NBLK) {
+ ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk->n >
+ NGTCP2_KSL_MIN_NBLK) {
ksl_shift_left(ksl, blk, i + 1);
+ blk = node->blk;
} else if (i > 0) {
blk = ksl_merge_node(ksl, blk, i - 1);
} else {
@@ -544,7 +522,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound(ngtcp2_ksl *ksl,
if (i == blk->n) {
/* This happens if descendant has smaller key. Fast forward to
find last node in this subtree. */
- for (; !blk->leaf; blk = ksl_nth_node(ksl, blk, blk->n - 1)->blk)
+ for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
;
if (blk->next) {
blk = blk->next;
@@ -555,7 +533,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound(ngtcp2_ksl *ksl,
ngtcp2_ksl_it_init(&it, ksl, blk, i);
return it;
}
- blk = ksl_nth_node(ksl, blk, i)->blk;
+ blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
}
}
@@ -581,7 +559,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl,
if (i == blk->n) {
/* This happens if descendant has smaller key. Fast forward to
find last node in this subtree. */
- for (; !blk->leaf; blk = ksl_nth_node(ksl, blk, blk->n - 1)->blk)
+ for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
;
if (blk->next) {
blk = blk->next;
@@ -592,7 +570,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl,
ngtcp2_ksl_it_init(&it, ksl, blk, i);
return it;
}
- blk = ksl_nth_node(ksl, blk, i)->blk;
+ blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
}
}
@@ -600,25 +578,23 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key,
const ngtcp2_ksl_key *new_key) {
ngtcp2_ksl_blk *blk = ksl->head;
ngtcp2_ksl_node *node;
- ngtcp2_ksl_key node_key;
size_t i;
for (;;) {
i = ksl_bsearch(ksl, blk, old_key, ksl->compar);
assert(i < blk->n);
- node = ksl_nth_node(ksl, blk, i);
+ node = ngtcp2_ksl_nth_node(ksl, blk, i);
if (blk->leaf) {
- assert(key_equal(ksl->compar, ksl_node_key(&node_key, node), old_key));
- ksl_node_set_key(ksl, node, new_key->ptr);
+ assert(key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key));
+ ksl_node_set_key(ksl, node, new_key);
return;
}
- ksl_node_key(&node_key, node);
- if (key_equal(ksl->compar, &node_key, old_key) ||
- ksl->compar(&node_key, new_key)) {
- ksl_node_set_key(ksl, node, new_key->ptr);
+ if (key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key) ||
+ ksl->compar((ngtcp2_ksl_key *)node->key, new_key)) {
+ ksl_node_set_key(ksl, node, new_key);
}
blk = node->blk;
@@ -628,21 +604,20 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key,
static void ksl_print(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) {
size_t i;
ngtcp2_ksl_node *node;
- ngtcp2_ksl_key node_key;
fprintf(stderr, "LV=%zu n=%zu\n", level, blk->n);
if (blk->leaf) {
for (i = 0; i < blk->n; ++i) {
- node = ksl_nth_node(ksl, blk, i);
- fprintf(stderr, " %" PRId64, *ksl_node_key(&node_key, node)->i);
+ node = ngtcp2_ksl_nth_node(ksl, blk, i);
+ fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key);
}
fprintf(stderr, "\n");
return;
}
for (i = 0; i < blk->n; ++i) {
- ksl_print(ksl, ksl_nth_node(ksl, blk, i)->blk, level + 1);
+ ksl_print(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk, level + 1);
}
}
@@ -654,7 +629,7 @@ void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) {
if (!ksl->head->leaf) {
for (i = 0; i < ksl->head->n; ++i) {
- ksl_free_blk(ksl, ksl_nth_node(ksl, ksl->head, i)->blk);
+ ksl_free_blk(ksl, ngtcp2_ksl_nth_node(ksl, ksl->head, i)->blk);
}
}
@@ -691,16 +666,7 @@ void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl,
void *ngtcp2_ksl_it_get(const ngtcp2_ksl_it *it) {
assert(it->i < it->blk->n);
- return ksl_nth_node(it->ksl, it->blk, it->i)->data;
-}
-
-void ngtcp2_ksl_it_next(ngtcp2_ksl_it *it) {
- assert(!ngtcp2_ksl_it_end(it));
-
- if (++it->i == it->blk->n && it->blk->next) {
- it->blk = it->blk->next;
- it->i = 0;
- }
+ return ngtcp2_ksl_nth_node(it->ksl, it->blk, it->i)->data;
}
void ngtcp2_ksl_it_prev(ngtcp2_ksl_it *it) {
@@ -714,36 +680,19 @@ void ngtcp2_ksl_it_prev(ngtcp2_ksl_it *it) {
}
}
-int ngtcp2_ksl_it_end(const ngtcp2_ksl_it *it) {
- return it->blk->n == it->i && it->blk->next == NULL;
-}
-
int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it) {
return it->i == 0 && it->blk->prev == NULL;
}
-ngtcp2_ksl_key ngtcp2_ksl_it_key(const ngtcp2_ksl_it *it) {
- ngtcp2_ksl_key node_key;
-
- assert(it->i < it->blk->n);
-
- return *ksl_node_key(&node_key, ksl_nth_node(it->ksl, it->blk, it->i));
-}
-
-ngtcp2_ksl_key *ngtcp2_ksl_key_ptr(ngtcp2_ksl_key *key, const void *ptr) {
- key->ptr = ptr;
- return key;
-}
-
int ngtcp2_ksl_range_compar(const ngtcp2_ksl_key *lhs,
const ngtcp2_ksl_key *rhs) {
- const ngtcp2_range *a = lhs->ptr, *b = rhs->ptr;
+ const ngtcp2_range *a = lhs, *b = rhs;
return a->begin < b->begin;
}
int ngtcp2_ksl_range_exclusive_compar(const ngtcp2_ksl_key *lhs,
const ngtcp2_ksl_key *rhs) {
- const ngtcp2_range *a = lhs->ptr, *b = rhs->ptr;
+ const ngtcp2_range *a = lhs, *b = rhs;
return a->begin < b->begin &&
!(ngtcp2_max(a->begin, b->begin) < ngtcp2_min(a->end, b->end));
}
diff --git a/deps/ngtcp2/lib/ngtcp2_ksl.h b/deps/ngtcp2/lib/ngtcp2_ksl.h
index c9ce128a220..ae8bb8de5b5 100644
--- a/deps/ngtcp2/lib/ngtcp2_ksl.h
+++ b/deps/ngtcp2/lib/ngtcp2_ksl.h
@@ -37,7 +37,7 @@
* Skip List using single key instead of range.
*/
-#define NGTCP2_KSL_DEGR 8
+#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)
@@ -48,12 +48,7 @@
/*
* ngtcp2_ksl_key represents key in ngtcp2_ksl.
*/
-typedef union {
- /* i is defined to retrieve int64_t key for convenience. */
- const int64_t *i;
- /* ptr points to the key. */
- const void *ptr;
-} ngtcp2_ksl_key;
+typedef void ngtcp2_ksl_key;
struct ngtcp2_ksl_node;
typedef struct ngtcp2_ksl_node ngtcp2_ksl_node;
@@ -246,11 +241,10 @@ size_t ngtcp2_ksl_len(ngtcp2_ksl *ksl);
void ngtcp2_ksl_clear(ngtcp2_ksl *ksl);
/*
- * ngtcp2_ksl_nth_node returns the |n|th node under |blk|. This
- * function is provided for unit testing.
+ * ngtcp2_ksl_nth_node returns the |n|th node under |blk|.
*/
-ngtcp2_ksl_node *ngtcp2_ksl_nth_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
- size_t n);
+#define ngtcp2_ksl_nth_node(KSL, BLK, N) \
+ ((ngtcp2_ksl_node *)(void *)((BLK)->nodes + (KSL)->nodelen * (N)))
/*
* ngtcp2_ksl_print prints its internal state in stderr. It assumes
@@ -277,7 +271,10 @@ void *ngtcp2_ksl_it_get(const ngtcp2_ksl_it *it);
* if this function is called when ngtcp2_ksl_it_end(it) returns
* nonzero.
*/
-void ngtcp2_ksl_it_next(ngtcp2_ksl_it *it);
+#define ngtcp2_ksl_it_next(IT) \
+ (++(IT)->i == (IT)->blk->n && (IT)->blk->next \
+ ? ((IT)->blk = (IT)->blk->next, (IT)->i = 0) \
+ : 0)
/*
* ngtcp2_ksl_it_prev moves backward the iterator by one. It is
@@ -290,7 +287,8 @@ void ngtcp2_ksl_it_prev(ngtcp2_ksl_it *it);
* ngtcp2_ksl_it_end returns nonzero if |it| points to the beyond the
* last node.
*/
-int ngtcp2_ksl_it_end(const ngtcp2_ksl_it *it);
+#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
@@ -304,13 +302,8 @@ int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it);
* It is undefined to call this function when ngtcp2_ksl_it_end(it)
* returns nonzero.
*/
-ngtcp2_ksl_key ngtcp2_ksl_it_key(const ngtcp2_ksl_it *it);
-
-/*
- * ngtcp2_ksl_key_ptr is a convenient function which initializes |key|
- * with |ptr| and returns |key|.
- */
-ngtcp2_ksl_key *ngtcp2_ksl_key_ptr(ngtcp2_ksl_key *key, const void *ptr);
+#define ngtcp2_ksl_it_key(IT) \
+ ((ngtcp2_ksl_key *)ngtcp2_ksl_nth_node((IT)->ksl, (IT)->blk, (IT)->i)->key)
/*
* ngtcp2_ksl_range_compar is an implementation of ngtcp2_ksl_compar.
diff --git a/deps/ngtcp2/lib/ngtcp2_log.c b/deps/ngtcp2/lib/ngtcp2_log.c
index 11f335d974c..8b7ec0def65 100644
--- a/deps/ngtcp2/lib/ngtcp2_log.c
+++ b/deps/ngtcp2/lib/ngtcp2_log.c
@@ -29,7 +29,6 @@
# include <unistd.h>
#endif
#include <assert.h>
-#include <errno.h>
#include <string.h>
#include "ngtcp2_str.h"
@@ -115,8 +114,8 @@ static const char *strerrorcode(uint64_t error_code) {
return "NO_ERROR";
case NGTCP2_INTERNAL_ERROR:
return "INTERNAL_ERROR";
- case NGTCP2_SERVER_BUSY:
- return "SERVER_BUSY";
+ case NGTCP2_CONNECTION_REFUSED:
+ return "CONNECTION_REFUSED";
case NGTCP2_FLOW_CONTROL_ERROR:
return "FLOW_CONTROL_ERROR";
case NGTCP2_STREAM_LIMIT_ERROR:
@@ -135,6 +134,8 @@ static const char *strerrorcode(uint64_t error_code) {
return "PROTOCOL_VIOLATION";
case NGTCP2_INVALID_TOKEN:
return "INVALID_TOKEN";
+ case NGTCP2_APPLICATION_ERROR:
+ return "APPLICATION_ERROR";
case NGTCP2_CRYPTO_BUFFER_EXCEEDED:
return "CRYPTO_BUFFER_EXCEEDED";
case NGTCP2_KEY_UPDATE_ERROR:
@@ -200,13 +201,13 @@ 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%02x) 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->log_printf(log->user_data,
+ (NGTCP2_LOG_PKT " STREAM(0x%02x) id=0x%" PRIx64
+ " fin=%d offset=%" PRIu64 " len=%zu 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,
@@ -245,8 +246,7 @@ static void log_fr_ack(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
static void log_fr_padding(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
const ngtcp2_padding *fr, const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " PADDING(0x%02x) len=%" PRIu64),
+ log->log_printf(log->user_data, (NGTCP2_LOG_PKT " PADDING(0x%02x) len=%zu"),
NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->len);
}
@@ -270,7 +270,7 @@ static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
log->log_printf(log->user_data,
(NGTCP2_LOG_PKT
" CONNECTION_CLOSE(0x%02x) error_code=%s(0x%" PRIx64 ") "
- "frame_type=%" PRIx64 " reason_len=%" PRIu64 " reason=[%s]"),
+ "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)
@@ -323,7 +323,8 @@ static void log_fr_stream_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
log->log_printf(log->user_data,
(NGTCP2_LOG_PKT " STREAM_DATA_BLOCKED(0x%02x) id=0x%" PRIx64
" offset=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->stream_id, fr->offset);
+ NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id,
+ fr->offset);
}
static void log_fr_streams_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
@@ -407,17 +408,16 @@ static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
uint8_t buf[128 + 1 + 1];
uint8_t *p;
- if (fr->tokenlen > 64) {
- p = ngtcp2_encode_hex(buf, fr->token, 64);
+ if (fr->token.len > 64) {
+ p = ngtcp2_encode_hex(buf, fr->token.base, 64);
p[128] = '*';
p[129] = '\0';
} else {
- p = ngtcp2_encode_hex(buf, fr->token, fr->tokenlen);
+ p = ngtcp2_encode_hex(buf, fr->token.base, fr->token.len);
}
log->log_printf(
- log->user_data,
- (NGTCP2_LOG_PKT " NEW_TOKEN(0x%02x) token=0x%s token_len=%zu"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)p, fr->tokenlen);
+ log->user_data, (NGTCP2_LOG_PKT " NEW_TOKEN(0x%02x) token=0x%s len=%zu"),
+ NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)p, fr->token.len);
}
static void log_fr_retire_connection_id(ngtcp2_log *log,
@@ -615,40 +615,57 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, uint8_t exttype,
sizeof(params->preferred_address.stateless_reset_token)));
}
- if (params->original_connection_id_present) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " original_connection_id=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(
- cid, params->original_connection_id.data,
- params->original_connection_id.datalen));
+ 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));
+
+ 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->log_printf(
- log->user_data, (NGTCP2_LOG_TP " initial_max_stream_data_bidi_local=%u"),
+ 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->log_printf(
- log->user_data, (NGTCP2_LOG_TP " initial_max_stream_data_bidi_remote=%u"),
+ 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=%u"),
+ (NGTCP2_LOG_TP " initial_max_stream_data_uni=%" PRIu64),
NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_uni);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " initial_max_data=%u"),
+ log->log_printf(log->user_data, (NGTCP2_LOG_TP " initial_max_data=%" PRIu64),
NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_data);
log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " initial_max_bidi_streams=%u"),
+ (NGTCP2_LOG_TP " initial_max_bidi_streams=%" PRIu64),
NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_streams_bidi);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " initial_max_uni_streams=%u"),
+ log->log_printf(log->user_data,
+ (NGTCP2_LOG_TP " initial_max_uni_streams=%" PRIu64),
NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_streams_uni);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_idle_timeout=%u"),
+ log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_idle_timeout=%" PRIu64),
NGTCP2_LOG_TP_HD_FIELDS,
params->max_idle_timeout / NGTCP2_MILLISECONDS);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_packet_size=%u"),
- NGTCP2_LOG_TP_HD_FIELDS, params->max_packet_size);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " ack_delay_exponent=%u"),
+ log->log_printf(log->user_data,
+ (NGTCP2_LOG_TP " max_udp_payload_size=%" PRIu64),
+ NGTCP2_LOG_TP_HD_FIELDS, params->max_udp_payload_size);
+ log->log_printf(log->user_data,
+ (NGTCP2_LOG_TP " ack_delay_exponent=%" PRIu64),
NGTCP2_LOG_TP_HD_FIELDS, params->ack_delay_exponent);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_ack_delay=%u"),
+ log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_ack_delay=%" PRIu64),
NGTCP2_LOG_TP_HD_FIELDS,
params->max_ack_delay / NGTCP2_MILLISECONDS);
log->log_printf(log->user_data,
diff --git a/deps/ngtcp2/lib/ngtcp2_log.h b/deps/ngtcp2/lib/ngtcp2_log.h
index bb9737e354b..985aa84b271 100644
--- a/deps/ngtcp2/lib/ngtcp2_log.h
+++ b/deps/ngtcp2/lib/ngtcp2_log.h
@@ -33,22 +33,6 @@
#include "ngtcp2_pkt.h"
-typedef enum {
- NGTCP2_LOG_EVENT_NONE,
- /* connection (catch-all) event */
- NGTCP2_LOG_EVENT_CON,
- /* packet event */
- NGTCP2_LOG_EVENT_PKT,
- /* frame event */
- NGTCP2_LOG_EVENT_FRM,
- /* recovery event */
- NGTCP2_LOG_EVENT_RCV,
- /* crypto event */
- NGTCP2_LOG_EVENT_CRY,
- /* path validation event */
- NGTCP2_LOG_EVENT_PTV,
-} ngtcp2_log_event;
-
struct ngtcp2_log {
/* log_printf is a sink to write log. NULL means no logging
output. */
@@ -76,9 +60,6 @@ void ngtcp2_log_rx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
void ngtcp2_log_tx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
const ngtcp2_frame *fr);
-void ngtcp2_log_info(ngtcp2_log *log, ngtcp2_log_event ev, const char *fmt,
- ...);
-
void ngtcp2_log_rx_vn(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
const uint32_t *sv, size_t nsv);
diff --git a/deps/ngtcp2/lib/ngtcp2_net.h b/deps/ngtcp2/lib/ngtcp2_net.h
deleted file mode 100644
index 9c121ea7f21..00000000000
--- a/deps/ngtcp2/lib/ngtcp2_net.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 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_NET_H
-#define NGTCP2_NET_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif /* HAVE_ARPA_INET_H */
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif /* HAVE_NETINET_IN_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#if defined(WIN32)
-/* Windows requires ws2_32 library for ntonl family functions. We
- define inline functions for those function so that we don't have
- dependeny on that lib. */
-
-# ifdef _MSC_VER
-# define STIN static __inline
-# else
-# define STIN static inline
-# endif
-
-STIN uint32_t htonl(uint32_t hostlong) {
- uint32_t res;
- unsigned char *p = (unsigned char *)&res;
- *p++ = hostlong >> 24;
- *p++ = (hostlong >> 16) & 0xffu;
- *p++ = (hostlong >> 8) & 0xffu;
- *p = hostlong & 0xffu;
- return res;
-}
-
-STIN uint16_t htons(uint16_t hostshort) {
- uint16_t res;
- unsigned char *p = (unsigned char *)&res;
- *p++ = hostshort >> 8;
- *p = hostshort & 0xffu;
- return res;
-}
-
-STIN uint32_t ntohl(uint32_t netlong) {
- uint32_t res;
- unsigned char *p = (unsigned char *)&netlong;
- res = *p++ << 24;
- res += *p++ << 16;
- res += *p++ << 8;
- res += *p;
- return res;
-}
-
-STIN uint16_t ntohs(uint16_t netshort) {
- uint16_t res;
- unsigned char *p = (unsigned char *)&netshort;
- res = *p++ << 8;
- res += *p;
- return res;
-}
-
-#endif /* WIN32 */
-
-#endif /* NGTCP2_NET_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_pipeack.c b/deps/ngtcp2/lib/ngtcp2_pipeack.c
deleted file mode 100644
index f44bdf07bbb..00000000000
--- a/deps/ngtcp2/lib/ngtcp2_pipeack.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 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_pipeack.h"
-
-#include <string.h>
-
-#include "ngtcp2_macro.h"
-#include "ngtcp2_rcvry.h"
-
-void ngtcp2_pipeack_init(ngtcp2_pipeack *pipeack, ngtcp2_tstamp ts) {
- ngtcp2_pipeack_sample *sample;
-
- memset(pipeack, 0, sizeof(*pipeack));
-
- /* Initialize value to UINT64_MAX so that it does not restrict CWND
- growth. It serves as "undefined" value. */
- pipeack->value = UINT64_MAX;
- pipeack->ts = ts;
- pipeack->len = 1;
-
- sample = &pipeack->samples[pipeack->pos];
- sample->value = 0;
- sample->ts = ts;
-}
-
-static ngtcp2_duration get_rtt(const ngtcp2_rcvry_stat *rcs) {
- if (rcs->smoothed_rtt == 0) {
- return NGTCP2_DEFAULT_INITIAL_RTT;
- }
- return rcs->smoothed_rtt;
-}
-
-/*
- * compute_sampling_period returns pipeACK sampling period.
- */
-static ngtcp2_duration compute_sampling_period(ngtcp2_duration rtt) {
- return ngtcp2_max(rtt * 3, NGTCP2_SECONDS);
-}
-
-/*
- * compute_measurement_period returns the measurement period using
- * pipeACK sampling period |speriod|.
- */
-static ngtcp2_duration compute_measurement_period(ngtcp2_duration speriod) {
- return speriod / NGTCP2_PIPEACK_NUM_SAMPLES;
-}
-
-static void pipeack_update_sample(ngtcp2_pipeack *pipeack, uint64_t acked_bytes,
- const ngtcp2_rcvry_stat *rcs,
- ngtcp2_tstamp ts) {
- ngtcp2_pipeack_sample *sample;
- ngtcp2_duration rtt = get_rtt(rcs);
- ngtcp2_duration speriod = compute_sampling_period(rtt);
- ngtcp2_duration mperiod = compute_measurement_period(speriod);
-
- if (pipeack->len == 0) {
- pipeack->len = 1;
-
- sample = &pipeack->samples[pipeack->pos];
- sample->ts = ts;
- sample->value = acked_bytes;
-
- return;
- }
-
- sample = &pipeack->samples[pipeack->pos];
- if (sample->ts + mperiod <= ts) {
- ts = sample->ts + (ts - sample->ts) / mperiod * mperiod;
- pipeack->pos = (pipeack->pos - 1) & (NGTCP2_PIPEACK_NUM_SAMPLES - 1);
-
- if (pipeack->len < NGTCP2_PIPEACK_NUM_SAMPLES) {
- ++pipeack->len;
- }
-
- sample = &pipeack->samples[pipeack->pos];
- sample->ts = ts;
- sample->value = acked_bytes;
-
- return;
- }
-
- sample->value = ngtcp2_max(sample->value, acked_bytes);
-}
-
-void ngtcp2_pipeack_update(ngtcp2_pipeack *pipeack, uint64_t acked_bytes,
- const ngtcp2_rcvry_stat *rcs, ngtcp2_tstamp ts) {
- uint64_t value;
- ngtcp2_duration d = ts - pipeack->ts;
- ngtcp2_duration rtt = get_rtt(rcs);
-
- pipeack->acked_bytes += acked_bytes;
-
- if (d < rtt) {
- return;
- }
-
- value = pipeack->acked_bytes * rtt / d;
- pipeack->acked_bytes = 0;
- pipeack->ts = ts;
-
- pipeack_update_sample(pipeack, value, rcs, ts);
-}
-
-void ngtcp2_pipeack_update_value(ngtcp2_pipeack *pipeack,
- const ngtcp2_rcvry_stat *rcs,
- ngtcp2_tstamp ts) {
- ngtcp2_pipeack_sample *sample;
- ngtcp2_duration rtt = get_rtt(rcs);
- ngtcp2_duration speriod = compute_sampling_period(rtt);
- ngtcp2_duration mperiod = compute_measurement_period(speriod);
- size_t i;
- uint64_t res = 0;
-
- for (i = pipeack->len; i > 0; --i) {
- sample = &pipeack->samples[(pipeack->pos + i - 1) &
- (NGTCP2_PIPEACK_NUM_SAMPLES - 1)];
- if (sample->ts + speriod <= ts) {
- --pipeack->len;
- continue;
- }
- if (sample->ts + mperiod > ts) {
- break;
- }
-
- res = ngtcp2_max(res, sample->value);
- }
-
- if (res == 0) {
- pipeack->value = UINT64_MAX;
- } else {
- pipeack->value = res;
- }
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_pipeack.h b/deps/ngtcp2/lib/ngtcp2_pipeack.h
deleted file mode 100644
index d7a34a936bb..00000000000
--- a/deps/ngtcp2/lib/ngtcp2_pipeack.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 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_PIPEACK_H
-#define NGTCP2_PIPEACK_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-typedef struct ngtcp2_pipeack_sample {
- /*
- * value is the maximum cumulative acknowledged bytes per RTT in
- * this sample.
- */
- uint64_t value;
- /* ts is the time when this sample started. */
- ngtcp2_tstamp ts;
-} ngtcp2_pipeack_sample;
-
-#define NGTCP2_PIPEACK_NUM_SAMPLES 4
-
-/*
- * ngtcp2_pipeack implements pipeACK measurement described in RFC
- * 7661.
- */
-typedef struct ngtcp2_pipeack {
- /* value is the pre-computed maximum pipeACK value in the effective
- sample period. */
- uint64_t value;
- /* acked_bytes is the accumulated acked_bytes per RTT. */
- uint64_t acked_bytes;
- /* ts is the timestamp when the accumulation to acked_bytes
- started. */
- ngtcp2_tstamp ts;
- /* pos points to the latest sample in samples. */
- size_t pos;
- /* len is the number of effective from pos. samples is treated as
- ring buffer and its index will wrap when pos + len goes beyond
- NGTCP2_PIPEACK_NUM_SAMPLES - 1. */
- size_t len;
- ngtcp2_pipeack_sample samples[NGTCP2_PIPEACK_NUM_SAMPLES];
-} ngtcp2_pipeack;
-
-/*
- * ngtcp2_pipeack_init initializes the object pointed by |pipeack|.
- */
-void ngtcp2_pipeack_init(ngtcp2_pipeack *pipeack, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_pipeack_update notifies the acknowledged bytes |acked_bytes|
- * to |pipeack|.
- */
-void ngtcp2_pipeack_update(ngtcp2_pipeack *pipeack, uint64_t acked_bytes,
- const ngtcp2_rcvry_stat *rcs, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_pipeack_update_value computes maximum pipeACK value.
- * Samples which have timestamp <= |ts| - pipeACK sampling period are
- * discarded.
- */
-void ngtcp2_pipeack_update_value(ngtcp2_pipeack *pipeack,
- const ngtcp2_rcvry_stat *rcs,
- ngtcp2_tstamp ts);
-
-#endif /* NGTCP2_PIPEACK_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_pkt.c b/deps/ngtcp2/lib/ngtcp2_pkt.c
index 059022bf2ca..a67a376d364 100644
--- a/deps/ngtcp2/lib/ngtcp2_pkt.c
+++ b/deps/ngtcp2/lib/ngtcp2_pkt.c
@@ -141,8 +141,8 @@ void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type,
ngtcp2_cid_zero(&hd->scid);
}
hd->pkt_num = pkt_num;
- hd->token = NULL;
- hd->tokenlen = 0;
+ hd->token.base = NULL;
+ hd->token.len = 0;
hd->pkt_numlen = pkt_numlen;
hd->version = version;
hd->len = len;
@@ -161,6 +161,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
size_t ntokenlen = 0;
const uint8_t *token = NULL;
size_t tokenlen = 0;
+ uint64_t vi;
if (pktlen < 5) {
return NGTCP2_ERR_INVALID_ARGUMENT;
@@ -241,12 +242,12 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
return NGTCP2_ERR_INVALID_ARGUMENT;
}
- tokenlen = ngtcp2_get_varint(&ntokenlen, p);
- len += tokenlen;
-
- if (pktlen < len) {
+ vi = ngtcp2_get_varint(&ntokenlen, p);
+ if (pktlen - len < vi) {
return NGTCP2_ERR_INVALID_ARGUMENT;
}
+ tokenlen = (size_t)vi;
+ len += tokenlen;
p += ntokenlen;
@@ -283,8 +284,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
ngtcp2_cid_init(&dest->scid, p, scil);
p += scil;
- dest->token = (uint8_t *)token;
- dest->tokenlen = tokenlen;
+ dest->token.base = (uint8_t *)token;
+ dest->token.len = tokenlen;
p += ntokenlen + tokenlen;
switch (type) {
@@ -293,7 +294,11 @@ ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
dest->len = 0;
break;
default:
- dest->len = ngtcp2_get_varint(&n, p);
+ vi = ngtcp2_get_varint(&n, p);
+ if (vi > SIZE_MAX) {
+ return NGTCP2_ERR_INVALID_ARGUMENT;
+ }
+ dest->len = (size_t)vi;
p += n;
}
@@ -352,7 +357,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen,
}
if (hd->type == NGTCP2_PKT_INITIAL) {
- len += ngtcp2_put_varint_len(hd->tokenlen) + hd->tokenlen;
+ len += ngtcp2_put_varint_len(hd->token.len) + hd->token.len;
}
if (outlen < len) {
@@ -374,9 +379,9 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen,
}
if (hd->type == NGTCP2_PKT_INITIAL) {
- p = ngtcp2_put_varint(p, hd->tokenlen);
- if (hd->tokenlen) {
- p = ngtcp2_cpymem(p, hd->token, hd->tokenlen);
+ p = ngtcp2_put_varint(p, hd->token.len);
+ if (hd->token.len) {
+ p = ngtcp2_cpymem(p, hd->token.base, hd->token.len);
}
}
@@ -504,6 +509,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest,
size_t datalen;
size_t ndatalen = 0;
size_t n;
+ uint64_t vi;
if (payloadlen < len) {
return NGTCP2_ERR_FRAME_ENCODING;
@@ -551,12 +557,12 @@ ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest,
return NGTCP2_ERR_FRAME_ENCODING;
}
- datalen = ngtcp2_get_varint(&ndatalen, p);
- len += datalen;
-
- if (payloadlen < len) {
+ vi = ngtcp2_get_varint(&ndatalen, p);
+ if (payloadlen - len < vi) {
return NGTCP2_ERR_FRAME_ENCODING;
}
+ datalen = (size_t)vi;
+ len += datalen;
} else {
len = payloadlen;
}
@@ -607,6 +613,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest,
ngtcp2_ack_blk *blk;
size_t n;
uint8_t type;
+ uint64_t vi;
if (payloadlen < len) {
return NGTCP2_ERR_FRAME_ENCODING;
@@ -644,13 +651,14 @@ ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest,
return NGTCP2_ERR_FRAME_ENCODING;
}
- num_blks = ngtcp2_get_varint(&nnum_blks, p);
- len += num_blks * (1 + 1);
-
- if (payloadlen < len) {
+ vi = ngtcp2_get_varint(&nnum_blks, p);
+ if (vi > SIZE_MAX / (1 + 1) || payloadlen - len < vi * (1 + 1)) {
return NGTCP2_ERR_FRAME_ENCODING;
}
+ num_blks = (size_t)vi;
+ len += num_blks * (1 + 1);
+
p += nnum_blks;
/* First ACK Block */
@@ -810,6 +818,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame(
size_t nreasonlen;
size_t n;
uint8_t type;
+ uint64_t vi;
if (payloadlen < len) {
return NGTCP2_ERR_FRAME_ENCODING;
@@ -845,12 +854,12 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame(
return NGTCP2_ERR_FRAME_ENCODING;
}
- reasonlen = ngtcp2_get_varint(&nreasonlen, p);
- len += reasonlen;
-
- if (payloadlen < len) {
+ vi = ngtcp2_get_varint(&nreasonlen, p);
+ if (payloadlen - len < vi) {
return NGTCP2_ERR_FRAME_ENCODING;
}
+ reasonlen = (size_t)vi;
+ len += reasonlen;
p = payload + 1;
@@ -1232,6 +1241,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest,
size_t datalen;
size_t ndatalen;
size_t n;
+ uint64_t vi;
if (payloadlen < len) {
return NGTCP2_ERR_FRAME_ENCODING;
@@ -1255,13 +1265,14 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest,
return NGTCP2_ERR_FRAME_ENCODING;
}
- datalen = ngtcp2_get_varint(&ndatalen, p);
- len += datalen;
-
- if (payloadlen < len) {
+ vi = ngtcp2_get_varint(&ndatalen, p);
+ if (payloadlen - len < vi) {
return NGTCP2_ERR_FRAME_ENCODING;
}
+ datalen = (size_t)vi;
+ len += datalen;
+
p = payload + 1;
dest->type = NGTCP2_FRAME_CRYPTO;
@@ -1290,6 +1301,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest,
const uint8_t *p;
size_t n;
size_t datalen;
+ uint64_t vi;
if (payloadlen < len) {
return NGTCP2_ERR_FRAME_ENCODING;
@@ -1304,18 +1316,18 @@ ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest,
return NGTCP2_ERR_FRAME_ENCODING;
}
- datalen = ngtcp2_get_varint(&n, p);
- len += datalen;
-
- if (payloadlen < len) {
+ vi = ngtcp2_get_varint(&n, p);
+ if (payloadlen - len < vi) {
return NGTCP2_ERR_FRAME_ENCODING;
}
+ datalen = (size_t)vi;
+ len += datalen;
dest->type = NGTCP2_FRAME_NEW_TOKEN;
- dest->tokenlen = datalen;
+ dest->token.len = datalen;
p += n;
- dest->token = p;
- p += dest->tokenlen;
+ dest->token.base = (uint8_t *)p;
+ p += dest->token.len;
assert((size_t)(p - payload) == len);
@@ -1844,9 +1856,11 @@ ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen,
ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen,
const ngtcp2_new_token *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->tokenlen) + fr->tokenlen;
+ size_t len = 1 + ngtcp2_put_varint_len(fr->token.len) + fr->token.len;
uint8_t *p;
+ assert(fr->token.len);
+
if (outlen < len) {
return NGTCP2_ERR_NOBUF;
}
@@ -1855,10 +1869,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen,
*p++ = NGTCP2_FRAME_NEW_TOKEN;
- p = ngtcp2_put_varint(p, fr->tokenlen);
- if (fr->tokenlen) {
- p = ngtcp2_cpymem(p, fr->token, fr->tokenlen);
- }
+ p = ngtcp2_put_varint(p, fr->token.len);
+ p = ngtcp2_cpymem(p, fr->token.base, fr->token.len);
assert((size_t)(p - out) == len);
@@ -1976,9 +1988,9 @@ int ngtcp2_pkt_decode_retry(ngtcp2_pkt_retry *dest, const uint8_t *payload,
return NGTCP2_ERR_INVALID_ARGUMENT;
}
- dest->token = payload;
- dest->tokenlen = (size_t)(payloadlen - NGTCP2_RETRY_TAGLEN);
- ngtcp2_cpymem(dest->tag, payload + dest->tokenlen, NGTCP2_RETRY_TAGLEN);
+ dest->token.base = (uint8_t *)payload;
+ dest->token.len = (size_t)(payloadlen - NGTCP2_RETRY_TAGLEN);
+ ngtcp2_cpymem(dest->tag, payload + dest->token.len, NGTCP2_RETRY_TAGLEN);
return 0;
}
@@ -2055,9 +2067,9 @@ ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen,
}
static const uint8_t retry_key[] =
- "\x4d\x32\xec\xdb\x2a\x21\x33\xc8\x41\xe4\x04\x3d\xf2\x7d\x44\x30";
+ "\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1";
static const uint8_t retry_nonce[] =
- "\x4d\x16\x11\xd0\x55\x13\xa5\x52\xc5\x87\xd5\x75";
+ "\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c";
ngtcp2_ssize
ngtcp2_pkt_write_retry(uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
@@ -2194,7 +2206,9 @@ size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset,
left -= n;
if (left > 8 + 1073741823 && len > 1073741823) {
+#if SIZE_MAX > UINT32_MAX
len = ngtcp2_min(len, 4611686018427387903lu);
+#endif /* SIZE_MAX > UINT32_MAX */
return ngtcp2_min(len, left - 8);
}
@@ -2222,7 +2236,9 @@ size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
left -= n;
if (left > 8 + 1073741823 && len > 1073741823) {
+#if SIZE_MAX > UINT32_MAX
len = ngtcp2_min(len, 4611686018427387903lu);
+#endif /* SIZE_MAX > UINT32_MAX */
return ngtcp2_min(len, left - 8);
}
@@ -2241,7 +2257,7 @@ size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
}
uint8_t ngtcp2_pkt_get_type_long(uint8_t c) {
- return (c & NGTCP2_LONG_TYPE_MASK) >> 4;
+ return (uint8_t)((c & NGTCP2_LONG_TYPE_MASK) >> 4);
}
int ngtcp2_pkt_verify_reserved_bits(uint8_t c) {
diff --git a/deps/ngtcp2/lib/ngtcp2_pkt.h b/deps/ngtcp2/lib/ngtcp2_pkt.h
index 962218057af..caf4152c045 100644
--- a/deps/ngtcp2/lib/ngtcp2_pkt.h
+++ b/deps/ngtcp2/lib/ngtcp2_pkt.h
@@ -89,7 +89,7 @@
/* NGTCP2_MAX_NUM_ACK_BLK is the maximum number of Additional ACK
blocks which this library can create, or decode. */
-#define NGTCP2_MAX_ACK_BLKS 255
+#define NGTCP2_MAX_ACK_BLKS 32
/* NGTCP2_MAX_PKT_NUM is the maximum packet number. */
#define NGTCP2_MAX_PKT_NUM ((int64_t)((1ll << 62) - 1))
@@ -99,6 +99,15 @@
Reset. */
#define NGTCP2_MIN_PKT_EXPANDLEN 22
+/* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */
+#define NGTCP2_RETRY_TAGLEN 16
+
+typedef struct ngtcp2_pkt_retry {
+ ngtcp2_cid odcid;
+ ngtcp2_vec token;
+ uint8_t tag[NGTCP2_RETRY_TAGLEN];
+} ngtcp2_pkt_retry;
+
typedef enum {
NGTCP2_FRAME_PADDING = 0x00,
NGTCP2_FRAME_PING = 0x01,
@@ -155,8 +164,7 @@ typedef struct {
uint64_t ack_delay;
/**
* ack_delay_unscaled is an ack_delay multiplied by
- * 2**ack_delay_component * NGTCP2_DURATION_TICK /
- * NGTCP2_MICROSECONDS.
+ * 2**ack_delay_component * NGTCP2_MICROSECONDS.
*/
ngtcp2_duration ack_delay_unscaled;
uint64_t first_ack_blklen;
@@ -263,8 +271,7 @@ typedef struct {
typedef struct {
uint8_t type;
- size_t tokenlen;
- const uint8_t *token;
+ ngtcp2_vec token;
} ngtcp2_new_token;
typedef struct {
diff --git a/deps/ngtcp2/lib/ngtcp2_ppe.c b/deps/ngtcp2/lib/ngtcp2_ppe.c
index e4aab22ca33..c1856d0fe09 100644
--- a/deps/ngtcp2/lib/ngtcp2_ppe.c
+++ b/deps/ngtcp2/lib/ngtcp2_ppe.c
@@ -55,7 +55,7 @@ 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_varint_len(hd->tokenlen) + hd->tokenlen;
+ ppe->len_offset += ngtcp2_put_varint_len(hd->token.len) + hd->token.len;
}
ppe->pkt_num_offset = ppe->len_offset + 2;
rv = ngtcp2_pkt_encode_hd_long(
diff --git a/deps/ngtcp2/lib/ngtcp2_psl.c b/deps/ngtcp2/lib/ngtcp2_psl.c
deleted file mode 100644
index 54a8e894d50..00000000000
--- a/deps/ngtcp2/lib/ngtcp2_psl.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 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_psl.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "ngtcp2_macro.h"
-#include "ngtcp2_mem.h"
-
-int ngtcp2_psl_init(ngtcp2_psl *psl, const ngtcp2_mem *mem) {
- ngtcp2_psl_blk *head;
-
- psl->mem = mem;
- psl->head = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_psl_blk));
- if (!psl->head) {
- return NGTCP2_ERR_NOMEM;
- }
- psl->front = psl->head;
- psl->n = 0;
-
- head = psl->head;
-
- head->next = NULL;
- head->n = 1;
- head->leaf = 1;
- head->nodes[0].range.begin = UINT64_MAX;
- head->nodes[0].range.end = UINT64_MAX;
- head->nodes[0].data = NULL;
-
- return 0;
-}
-
-/*
- * free_blk frees |blk| recursively.
- */
-static void free_blk(ngtcp2_psl_blk *blk, const ngtcp2_mem *mem) {
- size_t i;
-
- if (!blk->leaf) {
- for (i = 0; i < blk->n; ++i) {
- free_blk(blk->nodes[i].blk, mem);
- }
- }
-
- ngtcp2_mem_free(mem, blk);
-}
-
-void ngtcp2_psl_free(ngtcp2_psl *psl) {
- if (!psl) {
- return;
- }
-
- free_blk(psl->head, psl->mem);
-}
-
-/*
- * psl_split_blk splits |blk| into 2 ngtcp2_psl_blk objects. The new
- * ngtcp2_psl_blk is always the "right" block.
- *
- * It returns the pointer to the ngtcp2_psl_blk created which is the
- * located at the right of |blk|, or NULL which indicates out of
- * memory error.
- */
-static ngtcp2_psl_blk *psl_split_blk(ngtcp2_psl *psl, ngtcp2_psl_blk *blk) {
- ngtcp2_psl_blk *rblk;
-
- rblk = ngtcp2_mem_malloc(psl->mem, sizeof(ngtcp2_psl_blk));
- if (rblk == NULL) {
- return NULL;
- }
-
- rblk->next = blk->next;
- blk->next = rblk;
- rblk->leaf = blk->leaf;
-
- rblk->n = blk->n / 2;
-
- memcpy(rblk->nodes, &blk->nodes[blk->n - rblk->n],
- sizeof(ngtcp2_psl_node) * rblk->n);
-
- blk->n -= rblk->n;
-
- assert(blk->n >= NGTCP2_PSL_MIN_NBLK);
- assert(rblk->n >= NGTCP2_PSL_MIN_NBLK);
-
- return rblk;
-}
-
-/*
- * psl_split_node splits a node included in |blk| at the position |i|
- * into 2 adjacent nodes. The new node is always inserted at the
- * position |i+1|.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int psl_split_node(ngtcp2_psl *psl, ngtcp2_psl_blk *blk, size_t i) {
- ngtcp2_psl_blk *lblk = blk->nodes[i].blk, *rblk;
-
- rblk = psl_split_blk(psl, lblk);
- if (rblk == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- memmove(&blk->nodes[i + 2], &blk->nodes[i + 1],
- sizeof(ngtcp2_psl_node) * (blk->n - (i + 1)));
-
- blk->nodes[i + 1].blk = rblk;
-
- ++blk->n;
-
- blk->nodes[i].range = lblk->nodes[lblk->n - 1].range;
- blk->nodes[i + 1].range = rblk->nodes[rblk->n - 1].range;
-
- return 0;
-}
-
-/*
- * psl_split_head splits a head (root) block. It increases the height
- * of skip list by 1.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int psl_split_head(ngtcp2_psl *psl) {
- ngtcp2_psl_blk *rblk = NULL, *lblk, *nhead = NULL;
-
- rblk = psl_split_blk(psl, psl->head);
- if (rblk == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- lblk = psl->head;
-
- nhead = ngtcp2_mem_malloc(psl->mem, sizeof(ngtcp2_psl_blk));
- if (nhead == NULL) {
- ngtcp2_mem_free(psl->mem, rblk);
- return NGTCP2_ERR_NOMEM;
- }
- nhead->next = NULL;
- nhead->n = 2;
- nhead->leaf = 0;
-
- nhead->nodes[0].range = lblk->nodes[lblk->n - 1].range;
- nhead->nodes[0].blk = lblk;
- nhead->nodes[1].range = rblk->nodes[rblk->n - 1].range;
- nhead->nodes[1].blk = rblk;
-
- psl->head = nhead;
-
- return 0;
-}
-
-/*
- * insert_node inserts a node whose range is |range| 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_PSL_MAX_NBLK.
- */
-static void insert_node(ngtcp2_psl_blk *blk, size_t i,
- const ngtcp2_range *range, void *data) {
- ngtcp2_psl_node *node;
-
- assert(blk->n < NGTCP2_PSL_MAX_NBLK);
-
- memmove(&blk->nodes[i + 1], &blk->nodes[i],
- sizeof(ngtcp2_psl_node) * (blk->n - i));
-
- node = &blk->nodes[i];
- node->range = *range;
- node->data = data;
-
- ++blk->n;
-}
-
-static int range_intersect(const ngtcp2_range *a, const ngtcp2_range *b) {
- return ngtcp2_max(a->begin, b->begin) < ngtcp2_min(a->end, b->end);
-}
-
-int ngtcp2_psl_insert(ngtcp2_psl *psl, ngtcp2_psl_it *it,
- const ngtcp2_range *range, void *data) {
- ngtcp2_psl_blk *blk = psl->head;
- ngtcp2_psl_node *node;
- size_t i;
- int rv;
-
- if (blk->n == NGTCP2_PSL_MAX_NBLK) {
- rv = psl_split_head(psl);
- if (rv != 0) {
- return rv;
- }
- blk = psl->head;
- }
-
- for (;;) {
- for (i = 0, node = &blk->nodes[i]; node->range.begin < range->begin;
- ++i, ++node)
- ;
-
- assert(!range_intersect(&node->range, range));
-
- if (blk->leaf) {
- insert_node(blk, i, range, data);
- ++psl->n;
- if (it) {
- ngtcp2_psl_it_init(it, blk, i);
- }
- return 0;
- }
-
- if (node->blk->n == NGTCP2_PSL_MAX_NBLK) {
- rv = psl_split_node(psl, blk, i);
- if (rv != 0) {
- return rv;
- }
- if (node->range.begin < range->begin) {
- node = &blk->nodes[i + 1];
- }
- }
-
- blk = node->blk;
- }
-}
-
-/*
- * remove_node removes the node included in |blk| at the index of |i|.
- */
-static void remove_node(ngtcp2_psl_blk *blk, size_t i) {
- memmove(&blk->nodes[i], &blk->nodes[i + 1],
- sizeof(ngtcp2_psl_node) * (blk->n - (i + 1)));
-
- --blk->n;
-}
-
-/*
- * psl_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 |psl| by 1.
- *
- * This function returns the pointer to the merged block.
- */
-static ngtcp2_psl_blk *psl_merge_node(ngtcp2_psl *psl, ngtcp2_psl_blk *blk,
- size_t i) {
- ngtcp2_psl_blk *lblk, *rblk;
-
- assert(i + 1 < blk->n);
-
- lblk = blk->nodes[i].blk;
- rblk = blk->nodes[i + 1].blk;
-
- assert(lblk->n + rblk->n < NGTCP2_PSL_MAX_NBLK);
-
- memcpy(&lblk->nodes[lblk->n], &rblk->nodes[0],
- sizeof(ngtcp2_psl_node) * rblk->n);
-
- lblk->n += rblk->n;
- lblk->next = rblk->next;
-
- ngtcp2_mem_free(psl->mem, rblk);
-
- if (psl->head == blk && blk->n == 2) {
- ngtcp2_mem_free(psl->mem, psl->head);
- psl->head = lblk;
- } else {
- remove_node(blk, i + 1);
- blk->nodes[i].range = lblk->nodes[lblk->n - 1].range;
- }
-
- return lblk;
-}
-
-/*
- * psl_relocate_node replaces the key at the index |*pi| in
- * *pblk->nodes with something other without violating contract. It
- * might involve merging 2 nodes or moving a node to left or right.
- *
- * It assigns the index of the block in |*pblk| where the node is
- * moved to |*pi|. If merging 2 nodes occurs and it becomes new head,
- * the new head is assigned to |*pblk| and it still contains the key.
- * The caller should handle this situation.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int psl_relocate_node(ngtcp2_psl *psl, ngtcp2_psl_blk **pblk,
- size_t *pi) {
- ngtcp2_psl_blk *blk = *pblk;
- size_t i = *pi;
- ngtcp2_psl_node *node = &blk->nodes[i];
- ngtcp2_psl_node *rnode = &blk->nodes[i + 1];
- size_t j;
- int rv;
-
- assert(i + 1 < blk->n);
-
- if (node->blk->n == NGTCP2_PSL_MIN_NBLK &&
- node->blk->n + rnode->blk->n < NGTCP2_PSL_MAX_NBLK) {
- j = node->blk->n - 1;
- blk = psl_merge_node(psl, blk, i);
- if (blk != psl->head) {
- return 0;
- }
- *pblk = blk;
- i = j;
- if (blk->leaf) {
- *pi = i;
- return 0;
- }
- node = &blk->nodes[i];
- rnode = &blk->nodes[i + 1];
-
- if (node->blk->n == NGTCP2_PSL_MIN_NBLK &&
- node->blk->n + rnode->blk->n < NGTCP2_PSL_MAX_NBLK) {
- j = node->blk->n - 1;
- blk = psl_merge_node(psl, blk, i);
- assert(blk != psl->head);
- *pi = j;
- return 0;
- }
- }
-
- if (node->blk->n < rnode->blk->n) {
- node->blk->nodes[node->blk->n] = rnode->blk->nodes[0];
- memmove(&rnode->blk->nodes[0], &rnode->blk->nodes[1],
- sizeof(ngtcp2_psl_node) * (rnode->blk->n - 1));
- --rnode->blk->n;
- ++node->blk->n;
- node->range = node->blk->nodes[node->blk->n - 1].range;
- *pi = i;
- return 0;
- }
-
- if (rnode->blk->n == NGTCP2_PSL_MAX_NBLK) {
- rv = psl_split_node(psl, blk, i + 1);
- if (rv != 0) {
- return rv;
- }
- }
-
- memmove(&rnode->blk->nodes[1], &rnode->blk->nodes[0],
- sizeof(ngtcp2_psl_node) * rnode->blk->n);
-
- rnode->blk->nodes[0] = node->blk->nodes[node->blk->n - 1];
- ++rnode->blk->n;
-
- --node->blk->n;
-
- node->range = node->blk->nodes[node->blk->n - 1].range;
-
- *pi = i + 1;
- return 0;
-}
-
-/*
- * shift_left moves the first node in blk->nodes[i]->blk->nodes to
- * blk->nodes[i - 1]->blk->nodes.
- */
-static void shift_left(ngtcp2_psl_blk *blk, size_t i) {
- ngtcp2_psl_node *lnode, *rnode;
-
- assert(i > 0);
-
- lnode = &blk->nodes[i - 1];
- rnode = &blk->nodes[i];
-
- assert(lnode->blk->n < NGTCP2_PSL_MAX_NBLK);
- assert(rnode->blk->n > NGTCP2_PSL_MIN_NBLK);
-
- lnode->blk->nodes[lnode->blk->n] = rnode->blk->nodes[0];
- lnode->range = lnode->blk->nodes[lnode->blk->n].range;
- ++lnode->blk->n;
-
- --rnode->blk->n;
- memmove(&rnode->blk->nodes[0], &rnode->blk->nodes[1],
- sizeof(ngtcp2_psl_node) * rnode->blk->n);
-}
-
-/*
- * shift_right moves the last node in blk->nodes[i]->blk->nodes to
- * blk->nodes[i + 1]->blk->nodes.
- */
-static void shift_right(ngtcp2_psl_blk *blk, size_t i) {
- ngtcp2_psl_node *lnode, *rnode;
-
- assert(i < blk->n - 1);
-
- lnode = &blk->nodes[i];
- rnode = &blk->nodes[i + 1];
-
- assert(lnode->blk->n > NGTCP2_PSL_MIN_NBLK);
- assert(rnode->blk->n < NGTCP2_PSL_MAX_NBLK);
-
- memmove(&rnode->blk->nodes[1], &rnode->blk->nodes[0],
- sizeof(ngtcp2_psl_node) * rnode->blk->n);
- ++rnode->blk->n;
- rnode->blk->nodes[0] = lnode->blk->nodes[lnode->blk->n - 1];
-
- --lnode->blk->n;
- lnode->range = lnode->blk->nodes[lnode->blk->n - 1].range;
-}
-
-int ngtcp2_psl_remove(ngtcp2_psl *psl, ngtcp2_psl_it *it,
- const ngtcp2_range *range) {
- ngtcp2_psl_blk *blk = psl->head, *lblk, *rblk;
- ngtcp2_psl_node *node;
- size_t i, j;
- int rv;
-
- if (!blk->leaf && blk->n == NGTCP2_PSL_MAX_NBLK) {
- rv = psl_split_head(psl);
- if (rv != 0) {
- return rv;
- }
- blk = psl->head;
- }
-
- for (;;) {
- for (i = 0, node = &blk->nodes[i]; node->range.begin < range->begin;
- ++i, ++node)
- ;
-
- if (blk->leaf) {
- assert(i < blk->n);
- remove_node(blk, i);
- --psl->n;
- if (it) {
- if (blk->n == i) {
- ngtcp2_psl_it_init(it, blk->next, 0);
- } else {
- ngtcp2_psl_it_init(it, blk, i);
- }
- }
- return 0;
- }
-
- if (node->blk->n == NGTCP2_PSL_MAX_NBLK) {
- rv = psl_split_node(psl, blk, i);
- if (rv != 0) {
- return rv;
- }
- if (node->range.begin < range->begin) {
- ++i;
- node = &blk->nodes[i];
- }
- }
-
- if (ngtcp2_range_eq(&node->range, range)) {
- rv = psl_relocate_node(psl, &blk, &i);
- if (rv != 0) {
- return rv;
- }
- if (!blk->leaf) {
- node = &blk->nodes[i];
- blk = node->blk;
- }
- } else if (node->blk->n == NGTCP2_PSL_MIN_NBLK) {
- j = i == 0 ? 0 : i - 1;
-
- lblk = blk->nodes[j].blk;
- rblk = blk->nodes[j + 1].blk;
-
- if (lblk->n + rblk->n < NGTCP2_PSL_MAX_NBLK) {
- blk = psl_merge_node(psl, blk, j);
- } else {
- if (i == j) {
- shift_left(blk, j + 1);
- } else {
- shift_right(blk, j);
- }
- blk = node->blk;
- }
- } else {
- blk = node->blk;
- }
- }
-}
-
-ngtcp2_psl_it ngtcp2_psl_lower_bound(ngtcp2_psl *psl,
- const ngtcp2_range *range) {
- ngtcp2_psl_blk *blk = psl->head;
- ngtcp2_psl_node *node;
- size_t i;
-
- for (;;) {
- for (i = 0, node = &blk->nodes[i]; node->range.begin < range->begin &&
- !range_intersect(&node->range, range);
- ++i, node = &blk->nodes[i])
- ;
-
- if (blk->leaf) {
- ngtcp2_psl_it it = {blk, i};
- return it;
- }
-
- blk = node->blk;
- }
-}
-
-void ngtcp2_psl_update_range(ngtcp2_psl *psl, const ngtcp2_range *old_range,
- const ngtcp2_range *new_range) {
- ngtcp2_psl_blk *blk = psl->head;
- ngtcp2_psl_node *node;
- size_t i;
-
- assert(old_range->begin <= new_range->begin);
- assert(new_range->end <= old_range->end);
-
- for (;;) {
- for (i = 0, node = &blk->nodes[i]; node->range.begin < old_range->begin;
- ++i, node = &blk->nodes[i])
- ;
-
- if (blk->leaf) {
- assert(ngtcp2_range_eq(&node->range, old_range));
- node->range = *new_range;
- return;
- }
-
- if (ngtcp2_range_eq(&node->range, old_range)) {
- node->range = *new_range;
- } else {
- assert(!range_intersect(&node->range, old_range));
- }
-
- blk = node->blk;
- }
-}
-
-static void psl_print(ngtcp2_psl *psl, const ngtcp2_psl_blk *blk,
- size_t level) {
- size_t i;
-
- fprintf(stderr, "LV=%zu n=%zu\n", level, blk->n);
-
- if (blk->leaf) {
- for (i = 0; i < blk->n; ++i) {
- fprintf(stderr, " [%" PRIu64 ", %" PRIu64 ")", blk->nodes[i].range.begin,
- blk->nodes[i].range.end);
- }
- fprintf(stderr, "\n");
- return;
- }
-
- for (i = 0; i < blk->n; ++i) {
- psl_print(psl, blk->nodes[i].blk, level + 1);
- }
-}
-
-void ngtcp2_psl_print(ngtcp2_psl *psl) { psl_print(psl, psl->head, 0); }
-
-ngtcp2_psl_it ngtcp2_psl_begin(const ngtcp2_psl *psl) {
- ngtcp2_psl_it it = {psl->front, 0};
- return it;
-}
-
-size_t ngtcp2_psl_len(ngtcp2_psl *psl) { return psl->n; }
-
-void ngtcp2_psl_it_init(ngtcp2_psl_it *it, const ngtcp2_psl_blk *blk,
- size_t i) {
- it->blk = blk;
- it->i = i;
-}
-
-void *ngtcp2_psl_it_get(const ngtcp2_psl_it *it) {
- return it->blk->nodes[it->i].data;
-}
-
-void ngtcp2_psl_it_next(ngtcp2_psl_it *it) {
- assert(!ngtcp2_psl_it_end(it));
-
- if (++it->i == it->blk->n) {
- it->blk = it->blk->next;
- it->i = 0;
- }
-}
-
-int ngtcp2_psl_it_end(const ngtcp2_psl_it *it) {
- ngtcp2_range end = {UINT64_MAX, UINT64_MAX};
- return ngtcp2_range_eq(&end, &it->blk->nodes[it->i].range);
-}
-
-ngtcp2_range ngtcp2_psl_it_range(const ngtcp2_psl_it *it) {
- return it->blk->nodes[it->i].range;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_psl.h b/deps/ngtcp2/lib/ngtcp2_psl.h
deleted file mode 100644
index f0310a87e41..00000000000
--- a/deps/ngtcp2/lib/ngtcp2_psl.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 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_PSL_H
-#define NGTCP2_PSL_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stdlib.h>
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_range.h"
-
-/*
- * Skip List implementation inspired by
- * https://github.com/jabr/olio/blob/master/skiplist.c
- */
-
-#define NGTCP2_PSL_DEGR 8
-/* NGTCP2_PSL_MAX_NBLK is the maximum number of nodes which a single
- block can contain. */
-#define NGTCP2_PSL_MAX_NBLK (2 * NGTCP2_PSL_DEGR - 1)
-/* NGTCP2_PSL_MIN_NBLK is the minimum number of nodes which a single
- block other than root must contains. */
-#define NGTCP2_PSL_MIN_NBLK (NGTCP2_PSL_DEGR - 1)
-
-struct ngtcp2_psl_node;
-typedef struct ngtcp2_psl_node ngtcp2_psl_node;
-
-struct ngtcp2_psl_blk;
-typedef struct ngtcp2_psl_blk ngtcp2_psl_blk;
-
-/*
- * ngtcp2_psl_node is a node which contains either ngtcp2_psl_blk or
- * opaque data. If a node is an internal node, it contains
- * ngtcp2_psl_blk. Otherwise, it has data. The invariant is that the
- * range of internal node dictates the maximum range in its
- * descendants, and the corresponding leaf node must exist.
- */
-struct ngtcp2_psl_node {
- ngtcp2_range range;
- union {
- ngtcp2_psl_blk *blk;
- void *data;
- };
-};
-
-/*
- * ngtcp2_psl_blk contains ngtcp2_psl_node objects.
- */
-struct ngtcp2_psl_blk {
- /* next points to the next block if leaf field is nonzero. */
- ngtcp2_psl_blk *next;
- /* n is the number of nodes this object contains in nodes. */
- size_t n;
- /* leaf is nonzero if this block contains leaf nodes. */
- int leaf;
- ngtcp2_psl_node nodes[NGTCP2_PSL_MAX_NBLK];
-};
-
-struct ngtcp2_psl_it;
-typedef struct ngtcp2_psl_it ngtcp2_psl_it;
-
-/*
- * ngtcp2_psl_it is a forward iterator to iterate nodes.
- */
-struct ngtcp2_psl_it {
- const ngtcp2_psl_blk *blk;
- size_t i;
-};
-
-struct ngtcp2_psl;
-typedef struct ngtcp2_psl ngtcp2_psl;
-
-/*
- * ngtcp2_psl is a deterministic paged skip list.
- */
-struct ngtcp2_psl {
- /* head points to the root block. */
- ngtcp2_psl_blk *head;
- /* front points to the first leaf block. */
- ngtcp2_psl_blk *front;
- size_t n;
- const ngtcp2_mem *mem;
-};
-
-/*
- * ngtcp2_psl_init initializes |psl|.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_psl_init(ngtcp2_psl *psl, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_psl_free frees resources allocated for |psl|. If |psl| is
- * NULL, this function does nothing. It does not free the memory
- * region pointed by |psl| itself.
- */
-void ngtcp2_psl_free(ngtcp2_psl *psl);
-
-/*
- * ngtcp2_psl_insert inserts |range| with its associated |data|. On
- * successful insertion, the iterator points to the inserted node is
- * stored in |*it|.
- *
- * This function assumes that the existing ranges do not intersect
- * with |range|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_psl_insert(ngtcp2_psl *psl, ngtcp2_psl_it *it,
- const ngtcp2_range *range, void *data);
-
-/*
- * ngtcp2_psl_remove removes the |range| from |psl|. It assumes such
- * the range is included in |psl|.
- *
- * 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.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_psl_remove(ngtcp2_psl *psl, ngtcp2_psl_it *it,
- const ngtcp2_range *range);
-
-/*
- * ngtcp2_psl_update_range replaces the range of nodes which has
- * |old_range| with |new_range|. |old_range| must include
- * |new_range|.
- */
-void ngtcp2_psl_update_range(ngtcp2_psl *psl, const ngtcp2_range *old_range,
- const ngtcp2_range *new_range);
-
-/*
- * ngtcp2_psl_lower_bound returns the iterator which points to the
- * first node whose range intersects with |range|. If there is no
- * such node, it returns the iterator which satisfies
- * ngtcp2_psl_it_end(it) != 0.
- */
-ngtcp2_psl_it ngtcp2_psl_lower_bound(ngtcp2_psl *psl,
- const ngtcp2_range *range);
-
-/*
- * ngtcp2_psl_begin returns the iterator which points to the first
- * node. If there is no node in |psl|, it returns the iterator which
- * satisfies ngtcp2_psl_it_end(it) != 0.
- */
-ngtcp2_psl_it ngtcp2_psl_begin(const ngtcp2_psl *psl);
-
-/*
- * ngtcp2_psl_len returns the number of elements stored in |ksl|.
- */
-size_t ngtcp2_psl_len(ngtcp2_psl *psl);
-
-/*
- * ngtcp2_psl_print prints its internal state in stderr. This
- * function should be used for the debugging purpose only.
- */
-void ngtcp2_psl_print(ngtcp2_psl *psl);
-
-/*
- * ngtcp2_psl_it_init initializes |it|.
- */
-void ngtcp2_psl_it_init(ngtcp2_psl_it *it, const ngtcp2_psl_blk *blk, size_t i);
-
-/*
- * ngtcp2_psl_it_get returns the data associated to the node which
- * |it| points to. If this function is called when
- * ngtcp2_psl_it_end(it) returns nonzero, it returns NULL.
- */
-void *ngtcp2_psl_it_get(const ngtcp2_psl_it *it);
-
-/*
- * ngtcp2_psl_it_next advances the iterator by one. It is undefined
- * if this function is called when ngtcp2_psl_it_end(it) returns
- * nonzero.
- */
-void ngtcp2_psl_it_next(ngtcp2_psl_it *it);
-
-/*
- * ngtcp2_psl_it_end returns nonzero if |it| points to the beyond the
- * last node.
- */
-int ngtcp2_psl_it_end(const ngtcp2_psl_it *it);
-
-/*
- * ngtcp2_psl_range returns the range of the node which |it| points
- * to. It is OK to call this function when ngtcp2_psl_it_end(it)
- * returns nonzero. In this case, this function returns {UINT64_MAX,
- * UINT64_MAX}.
- */
-ngtcp2_range ngtcp2_psl_it_range(const ngtcp2_psl_it *it);
-
-#endif /* NGTCP2_PSL_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_qlog.c b/deps/ngtcp2/lib/ngtcp2_qlog.c
index 2f6d2390c9a..f0abc8dba7c 100644
--- a/deps/ngtcp2/lib/ngtcp2_qlog.c
+++ b/deps/ngtcp2/lib/ngtcp2_qlog.c
@@ -447,14 +447,17 @@ static uint8_t *write_new_token_frame(uint8_t *p, const ngtcp2_new_token *fr) {
(void)fr;
/*
- * {"frame_type":"new_token"}
+ * {"frame_type":"new_token","length":0000000000000000000,"token":""}
*/
-#define NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD 26
+#define NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD 66
*p++ = '{';
p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
ngtcp2_vec_lit(&value, "new_token"));
- /* TODO Write token here */
+ *p++ = ',';
+ p = write_pair_number(p, ngtcp2_vec_lit(&name, "length"), fr->token.len);
+ *p++ = ',';
+ p = write_pair_hex(p, ngtcp2_vec_lit(&name, "token"), &fr->token);
*p++ = '}';
return p;
@@ -870,7 +873,8 @@ void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) {
p = write_crypto_frame(p, &fr->crypto);
break;
case NGTCP2_FRAME_NEW_TOKEN:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD + 1 +
+ if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD +
+ fr->new_token.token.len * 2 + 1 +
NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
return;
}
@@ -1010,7 +1014,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 local) {
+ ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server,
+ int local) {
uint8_t buf[1024];
uint8_t *p = buf;
ngtcp2_vec name, value;
@@ -1032,9 +1037,19 @@ void ngtcp2_qlog_parameters_set_transport_params(
local ? ngtcp2_vec_lit(&value, "local")
: ngtcp2_vec_lit(&value, "remote"));
*p++ = ',';
- if (params->original_connection_id_present) {
- p = write_pair_cid(p, ngtcp2_vec_lit(&name, "original_connection_id"),
- &params->original_connection_id);
+ p = write_pair_cid(p, ngtcp2_vec_lit(&name, "initial_source_connection_id"),
+ &params->initial_scid);
+ *p++ = ',';
+ if (!server == !local) {
+ p = write_pair_cid(
+ p, ngtcp2_vec_lit(&name, "original_destination_connection_id"),
+ &params->original_dcid);
+ *p++ = ',';
+ }
+ if (params->retry_scid_present) {
+ assert(!server);
+ p = write_pair_cid(p, ngtcp2_vec_lit(&name, "retry_source_connection_id"),
+ &params->retry_scid);
*p++ = ',';
}
if (params->stateless_reset_token_present) {
@@ -1049,8 +1064,8 @@ void ngtcp2_qlog_parameters_set_transport_params(
p = write_pair_duration(p, ngtcp2_vec_lit(&name, "max_idle_timeout"),
params->max_idle_timeout);
*p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "max_packet_size"),
- params->max_packet_size);
+ p = write_pair_number(p, ngtcp2_vec_lit(&name, "max_udp_payload_size"),
+ params->max_udp_payload_size);
*p++ = ',';
p = write_pair_number(p, ngtcp2_vec_lit(&name, "ack_delay_exponent"),
params->ack_delay_exponent);
@@ -1115,8 +1130,7 @@ void ngtcp2_qlog_parameters_set_transport_params(
}
void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog,
- const ngtcp2_rcvry_stat *rcs,
- ngtcp2_cc_stat *ccs) {
+ const ngtcp2_conn_stat *cstat) {
uint8_t buf[1024];
uint8_t *p = buf;
ngtcp2_vec name, value;
@@ -1134,30 +1148,33 @@ void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog,
*p++ = ',';
*p++ = '{';
- if (rcs->min_rtt != UINT64_MAX) {
- p = write_pair_duration(p, ngtcp2_vec_lit(&name, "min_rtt"), rcs->min_rtt);
+ if (cstat->min_rtt != UINT64_MAX) {
+ p = write_pair_duration(p, ngtcp2_vec_lit(&name, "min_rtt"),
+ cstat->min_rtt);
*p++ = ',';
}
p = write_pair_duration(p, ngtcp2_vec_lit(&name, "smoothed_rtt"),
- rcs->smoothed_rtt);
+ cstat->smoothed_rtt);
*p++ = ',';
p = write_pair_duration(p, ngtcp2_vec_lit(&name, "latest_rtt"),
- rcs->latest_rtt);
+ cstat->latest_rtt);
*p++ = ',';
p = write_pair_duration(p, ngtcp2_vec_lit(&name, "rtt_variance"),
- rcs->rttvar);
+ cstat->rttvar);
*p++ = ',';
/* TODO max_ack_delay? */
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "pto_count"), rcs->pto_count);
+ p = write_pair_number(p, ngtcp2_vec_lit(&name, "pto_count"),
+ cstat->pto_count);
*p++ = ',';
p = write_pair_number(p, ngtcp2_vec_lit(&name, "congestion_window"),
- ccs->cwnd);
+ cstat->cwnd);
*p++ = ',';
p = write_pair_number(p, ngtcp2_vec_lit(&name, "bytes_in_flight"),
- ccs->bytes_in_flight);
- if (ccs->ssthresh != UINT64_MAX) {
+ cstat->bytes_in_flight);
+ if (cstat->ssthresh != UINT64_MAX) {
*p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "ssthresh"), ccs->ssthresh);
+ p = write_pair_number(p, ngtcp2_vec_lit(&name, "ssthresh"),
+ cstat->ssthresh);
}
*p++ = '}';
diff --git a/deps/ngtcp2/lib/ngtcp2_qlog.h b/deps/ngtcp2/lib/ngtcp2_qlog.h
index 160cacd2322..cd967984a74 100644
--- a/deps/ngtcp2/lib/ngtcp2_qlog.h
+++ b/deps/ngtcp2/lib/ngtcp2_qlog.h
@@ -110,19 +110,20 @@ void ngtcp2_qlog_pkt_sent_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
/*
* ngtcp2_qlog_parameters_set_transport_params writes |params| to qlog
- * as parameters_set event. If |local| is nonzero, it is "owner"
- * field becomes "local", otherwise "remote".
+ * as parameters_set event. |server| is nonzero if the local endpoint
+ * is server. If |local| is nonzero, it is "owner" field becomes
+ * "local", otherwise "remote".
*/
void ngtcp2_qlog_parameters_set_transport_params(
- ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int local);
+ ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server,
+ int local);
/*
* ngtcp2_qlog_metrics_updated writes metrics_updated event of
* recovery category.
*/
void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog,
- const ngtcp2_rcvry_stat *rcs,
- ngtcp2_cc_stat *ccs);
+ const ngtcp2_conn_stat *cstat);
/*
* ngtcp2_qlog_pkt_lost writes packet_lost event.
diff --git a/deps/ngtcp2/lib/ngtcp2_rcvry.h b/deps/ngtcp2/lib/ngtcp2_rcvry.h
index 254c3c797a0..0ff0bc4b6ed 100644
--- a/deps/ngtcp2/lib/ngtcp2_rcvry.h
+++ b/deps/ngtcp2/lib/ngtcp2_rcvry.h
@@ -39,6 +39,6 @@
draft-ietf-quic-recovery-17. */
#define NGTCP2_GRANULARITY NGTCP2_MILLISECONDS
-#define NGTCP2_DEFAULT_INITIAL_RTT (500 * NGTCP2_MILLISECONDS)
+#define NGTCP2_DEFAULT_INITIAL_RTT (333 * NGTCP2_MILLISECONDS)
#endif /* NGTCP2_RCVRY_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_rob.c b/deps/ngtcp2/lib/ngtcp2_rob.c
index ab7f44ecb88..499c07ec6be 100644
--- a/deps/ngtcp2/lib/ngtcp2_rob.c
+++ b/deps/ngtcp2/lib/ngtcp2_rob.c
@@ -68,7 +68,6 @@ void ngtcp2_rob_data_del(ngtcp2_rob_data *d, const ngtcp2_mem *mem) {
int ngtcp2_rob_init(ngtcp2_rob *rob, size_t chunk, const ngtcp2_mem *mem) {
int rv;
ngtcp2_rob_gap *g;
- ngtcp2_ksl_key key;
rv = ngtcp2_ksl_init(&rob->gapksl, ngtcp2_ksl_range_compar,
sizeof(ngtcp2_range), mem);
@@ -81,8 +80,7 @@ int ngtcp2_rob_init(ngtcp2_rob *rob, size_t chunk, const ngtcp2_mem *mem) {
goto fail_rob_gap_new;
}
- rv = ngtcp2_ksl_insert(&rob->gapksl, NULL,
- ngtcp2_ksl_key_ptr(&key, &g->range), g);
+ rv = ngtcp2_ksl_insert(&rob->gapksl, NULL, &g->range, g);
if (rv != 0) {
goto fail_gapksl_ksl_insert;
}
@@ -135,10 +133,8 @@ static int rob_write_data(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
ngtcp2_rob_data *d;
ngtcp2_range range = {offset, offset + len};
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
- for (it = ngtcp2_ksl_lower_bound_compar(&rob->dataksl,
- ngtcp2_ksl_key_ptr(&key, &range),
+ for (it = ngtcp2_ksl_lower_bound_compar(&rob->dataksl, &range,
ngtcp2_ksl_range_exclusive_compar);
len; ngtcp2_ksl_it_next(&it)) {
if (ngtcp2_ksl_it_end(&it)) {
@@ -154,15 +150,14 @@ static int rob_write_data(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
return rv;
}
- rv = ngtcp2_ksl_insert(&rob->dataksl, &it,
- ngtcp2_ksl_key_ptr(&key, &d->range), d);
+ rv = ngtcp2_ksl_insert(&rob->dataksl, &it, &d->range, d);
if (rv != 0) {
ngtcp2_rob_data_del(d, rob->mem);
return rv;
}
}
- n = ngtcp2_min(len, d->range.begin + rob->chunk - offset);
+ n = (size_t)ngtcp2_min((uint64_t)len, d->range.begin + rob->chunk - offset);
memcpy(d->begin + (offset - d->range.begin), data, n);
offset += n;
data += n;
@@ -178,9 +173,8 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
ngtcp2_rob_gap *g;
ngtcp2_range m, l, r, q = {offset, offset + datalen};
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key, old_key;
- it = ngtcp2_ksl_lower_bound_compar(&rob->gapksl, ngtcp2_ksl_key_ptr(&key, &q),
+ it = ngtcp2_ksl_lower_bound_compar(&rob->gapksl, &q,
ngtcp2_ksl_range_exclusive_compar);
for (; !ngtcp2_ksl_it_end(&it);) {
@@ -191,10 +185,10 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
break;
}
if (ngtcp2_range_eq(&g->range, &m)) {
- ngtcp2_ksl_remove(&rob->gapksl, &it, ngtcp2_ksl_key_ptr(&key, &g->range));
+ ngtcp2_ksl_remove(&rob->gapksl, &it, &g->range);
ngtcp2_rob_gap_del(g, rob->mem);
rv = rob_write_data(rob, m.begin, data + (m.begin - offset),
- ngtcp2_range_len(&m));
+ (size_t)ngtcp2_range_len(&m));
if (rv != 0) {
return rv;
}
@@ -203,9 +197,7 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
}
ngtcp2_range_cut(&l, &r, &g->range, &m);
if (ngtcp2_range_len(&l)) {
- ngtcp2_ksl_update_key(&rob->gapksl,
- ngtcp2_ksl_key_ptr(&old_key, &g->range),
- ngtcp2_ksl_key_ptr(&key, &l));
+ ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &l);
g->range = l;
if (ngtcp2_range_len(&r)) {
@@ -214,21 +206,18 @@ int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
if (rv != 0) {
return rv;
}
- rv = ngtcp2_ksl_insert(&rob->gapksl, &it,
- ngtcp2_ksl_key_ptr(&key, &ng->range), ng);
+ rv = ngtcp2_ksl_insert(&rob->gapksl, &it, &ng->range, ng);
if (rv != 0) {
ngtcp2_rob_gap_del(ng, rob->mem);
return rv;
}
}
} else if (ngtcp2_range_len(&r)) {
- ngtcp2_ksl_update_key(&rob->gapksl,
- ngtcp2_ksl_key_ptr(&old_key, &g->range),
- ngtcp2_ksl_key_ptr(&key, &r));
+ ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r);
g->range = r;
}
rv = rob_write_data(rob, m.begin, data + (m.begin - offset),
- ngtcp2_range_len(&m));
+ (size_t)ngtcp2_range_len(&m));
if (rv != 0) {
return rv;
}
@@ -241,7 +230,6 @@ int ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) {
ngtcp2_rob_gap *g;
ngtcp2_rob_data *d;
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key, old_key;
it = ngtcp2_ksl_begin(&rob->gapksl);
@@ -252,13 +240,11 @@ int ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) {
}
if (offset < g->range.end) {
ngtcp2_range r = {offset, g->range.end};
- ngtcp2_ksl_update_key(&rob->gapksl,
- ngtcp2_ksl_key_ptr(&old_key, &g->range),
- ngtcp2_ksl_key_ptr(&key, &r));
+ ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r);
g->range.begin = offset;
break;
}
- ngtcp2_ksl_remove(&rob->gapksl, &it, ngtcp2_ksl_key_ptr(&key, &g->range));
+ ngtcp2_ksl_remove(&rob->gapksl, &it, &g->range);
ngtcp2_rob_gap_del(g, rob->mem);
}
@@ -269,7 +255,7 @@ int ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) {
if (offset < d->range.begin + rob->chunk) {
return 0;
}
- ngtcp2_ksl_remove(&rob->dataksl, &it, ngtcp2_ksl_key_ptr(&key, &d->range));
+ ngtcp2_ksl_remove(&rob->dataksl, &it, &d->range);
ngtcp2_rob_data_del(d, rob->mem);
}
@@ -302,12 +288,12 @@ size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest,
*pdest = d->begin + (offset - d->range.begin);
- return ngtcp2_min(g->range.begin, d->range.begin + rob->chunk) - offset;
+ return (size_t)(ngtcp2_min(g->range.begin, d->range.begin + rob->chunk) -
+ offset);
}
void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len) {
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
ngtcp2_rob_data *d;
it = ngtcp2_ksl_begin(&rob->dataksl);
@@ -319,7 +305,7 @@ void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len) {
return;
}
- ngtcp2_ksl_remove(&rob->dataksl, NULL, ngtcp2_ksl_key_ptr(&key, &d->range));
+ ngtcp2_ksl_remove(&rob->dataksl, NULL, &d->range);
ngtcp2_rob_data_del(d, rob->mem);
}
diff --git a/deps/ngtcp2/lib/ngtcp2_rst.c b/deps/ngtcp2/lib/ngtcp2_rst.c
index c9c994e2bae..e546fdf85c6 100644
--- a/deps/ngtcp2/lib/ngtcp2_rst.c
+++ b/deps/ngtcp2/lib/ngtcp2_rst.c
@@ -27,15 +27,7 @@
#include "ngtcp2_cc.h"
#include "ngtcp2_macro.h"
-void ngtcp2_rst_init(ngtcp2_rst *rst) {
- ngtcp2_rs *rs = &rst->rs;
-
- rst->delivered = 0;
- rst->delivered_ts = 0;
- rst->first_sent_ts = 0;
- rst->app_limited = 0;
-
- rs->delivery_rate = 0.;
+void ngtcp2_rs_init(ngtcp2_rs *rs) {
rs->interval = UINT64_MAX;
rs->delivered = 0;
rs->prior_delivered = 0;
@@ -45,9 +37,17 @@ void ngtcp2_rst_init(ngtcp2_rst *rst) {
rs->is_app_limited = 0;
}
+void ngtcp2_rst_init(ngtcp2_rst *rst) {
+ ngtcp2_rs_init(&rst->rs);
+ rst->delivered = 0;
+ rst->delivered_ts = 0;
+ rst->first_sent_ts = 0;
+ rst->app_limited = 0;
+}
+
void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent,
- const ngtcp2_cc_stat *ccs) {
- if (ccs->bytes_in_flight == 0) {
+ const ngtcp2_conn_stat *cstat) {
+ if (cstat->bytes_in_flight == 0) {
rst->first_sent_ts = rst->delivered_ts = ent->ts;
}
ent->rst.first_sent_ts = rst->first_sent_ts;
@@ -56,7 +56,7 @@ void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent,
ent->rst.is_app_limited = rst->app_limited != 0;
}
-int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, const ngtcp2_rcvry_stat *rcs) {
+int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) {
ngtcp2_rs *rs = &rst->rs;
if (rst->app_limited && rst->delivered > rst->app_limited) {
@@ -71,16 +71,16 @@ int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, const ngtcp2_rcvry_stat *rcs) {
rs->delivered = rst->delivered - rs->prior_delivered;
- if (rs->interval < rcs->min_rtt) {
+ if (rs->interval < cstat->min_rtt) {
rs->interval = UINT64_MAX;
return 0;
}
if (rs->interval) {
- rs->delivery_rate = (double)rs->delivered / (double)rs->interval;
+ cstat->delivery_rate_sec = rs->delivered * NGTCP2_SECONDS / rs->interval;
}
- return 1;
+ return 0;
}
void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent,
@@ -100,8 +100,8 @@ void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent,
}
}
-void ngtcp2_rst_update_app_limited(ngtcp2_rst *rst, const ngtcp2_cc_stat *ccs) {
+void ngtcp2_rst_update_app_limited(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) {
(void)rst;
- (void)ccs;
+ (void)cstat;
/* TODO Not implemented */
}
diff --git a/deps/ngtcp2/lib/ngtcp2_rst.h b/deps/ngtcp2/lib/ngtcp2_rst.h
index b7137b79c95..f68a1f9b22d 100644
--- a/deps/ngtcp2/lib/ngtcp2_rst.h
+++ b/deps/ngtcp2/lib/ngtcp2_rst.h
@@ -34,8 +34,12 @@
struct ngtcp2_rtb_entry;
typedef struct ngtcp2_rtb_entry ngtcp2_rtb_entry;
+/**
+ * @struct
+ *
+ * ngtcp2_rs contains connection state for delivery rate estimation.
+ */
typedef struct ngtcp2_rs {
- double delivery_rate;
ngtcp2_duration interval;
uint64_t delivered;
uint64_t prior_delivered;
@@ -45,25 +49,27 @@ typedef struct ngtcp2_rs {
int is_app_limited;
} ngtcp2_rs;
+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
*/
typedef struct ngtcp2_rst {
+ ngtcp2_rs rs;
uint64_t delivered;
ngtcp2_tstamp delivered_ts;
ngtcp2_tstamp first_sent_ts;
uint64_t app_limited;
- ngtcp2_rs rs;
} ngtcp2_rst;
void ngtcp2_rst_init(ngtcp2_rst *rst);
void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent,
- const ngtcp2_cc_stat *ccs);
-int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, const ngtcp2_rcvry_stat *rcs);
+ const ngtcp2_conn_stat *cstat);
+int 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, const ngtcp2_cc_stat *ccs);
+void ngtcp2_rst_update_app_limited(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat);
#endif /* NGTCP2_RST_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_rtb.c b/deps/ngtcp2/lib/ngtcp2_rtb.c
index 83936f2aa69..e7e6762e03d 100644
--- a/deps/ngtcp2/lib/ngtcp2_rtb.c
+++ b/deps/ngtcp2/lib/ngtcp2_rtb.c
@@ -144,12 +144,12 @@ void ngtcp2_rtb_entry_del(ngtcp2_rtb_entry *ent, const ngtcp2_mem *mem) {
}
static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return *lhs->i > *rhs->i;
+ return *(int64_t *)lhs > *(int64_t *)rhs;
}
-void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_crypto_level crypto_level,
- ngtcp2_strm *crypto, ngtcp2_rst *rst,
- ngtcp2_default_cc *cc, ngtcp2_log *log, ngtcp2_qlog *qlog,
+void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id,
+ ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc,
+ ngtcp2_log *log, ngtcp2_qlog *qlog,
const ngtcp2_mem *mem) {
ngtcp2_ksl_init(&rtb->ents, greater, sizeof(int64_t), mem);
rtb->crypto = crypto;
@@ -160,10 +160,10 @@ void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_crypto_level crypto_level,
rtb->mem = mem;
rtb->largest_acked_tx_pkt_num = -1;
rtb->num_ack_eliciting = 0;
- rtb->loss_time = UINT64_MAX;
rtb->probe_pkt_left = 0;
- rtb->crypto_level = crypto_level;
+ rtb->pktns_id = pktns_id;
rtb->cc_pkt_num = 0;
+ rtb->cc_bytes_in_flight = 0;
}
void ngtcp2_rtb_free(ngtcp2_rtb *rtb) {
@@ -182,29 +182,35 @@ void ngtcp2_rtb_free(ngtcp2_rtb *rtb) {
ngtcp2_ksl_free(&rtb->ents);
}
-static void rtb_on_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent) {
- ngtcp2_rst_on_pkt_sent(rtb->rst, ent, rtb->cc->ccs);
+static void rtb_on_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
+ ngtcp2_conn_stat *cstat) {
+ ngtcp2_rst_on_pkt_sent(rtb->rst, ent, cstat);
assert(rtb->cc_pkt_num <= ent->hd.pkt_num);
- rtb->cc->ccs->bytes_in_flight += ent->pktlen;
+ cstat->bytes_in_flight += ent->pktlen;
+ rtb->cc_bytes_in_flight += ent->pktlen;
- ngtcp2_rst_update_app_limited(rtb->rst, rtb->cc->ccs);
+ ngtcp2_rst_update_app_limited(rtb->rst, cstat);
if (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
++rtb->num_ack_eliciting;
}
}
-static void rtb_on_remove(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent) {
+static void rtb_on_remove(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
+ ngtcp2_conn_stat *cstat) {
if (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
assert(rtb->num_ack_eliciting);
--rtb->num_ack_eliciting;
}
if (rtb->cc_pkt_num <= ent->hd.pkt_num) {
- assert(rtb->cc->ccs->bytes_in_flight >= ent->pktlen);
- rtb->cc->ccs->bytes_in_flight -= ent->pktlen;
+ assert(cstat->bytes_in_flight >= ent->pktlen);
+ cstat->bytes_in_flight -= ent->pktlen;
+
+ assert(rtb->cc_bytes_in_flight >= ent->pktlen);
+ rtb->cc_bytes_in_flight -= ent->pktlen;
}
}
@@ -229,24 +235,28 @@ static void rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
frame_chain_insert(pfrc, ent->frc);
ent->frc = NULL;
}
+ } else {
+ ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
+ "pkn=%" PRId64
+ " is a probe packet, no retransmission is necessary",
+ ent->hd.pkt_num);
}
ngtcp2_rtb_entry_del(ent, rtb->mem);
}
-int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent) {
+int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
+ ngtcp2_conn_stat *cstat) {
int rv;
- ngtcp2_ksl_key key;
ent->next = NULL;
- rv = ngtcp2_ksl_insert(&rtb->ents, NULL,
- ngtcp2_ksl_key_ptr(&key, &ent->hd.pkt_num), ent);
+ rv = ngtcp2_ksl_insert(&rtb->ents, NULL, &ent->hd.pkt_num, ent);
if (rv != 0) {
return rv;
}
- rtb_on_add(rtb, ent);
+ rtb_on_add(rtb, ent, cstat);
return 0;
}
@@ -256,22 +266,21 @@ ngtcp2_ksl_it ngtcp2_rtb_head(ngtcp2_rtb *rtb) {
}
static void rtb_remove(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it,
- ngtcp2_rtb_entry *ent) {
- ngtcp2_ksl_key key;
-
- ngtcp2_ksl_remove(&rtb->ents, it, ngtcp2_ksl_key_ptr(&key, &ent->hd.pkt_num));
- rtb_on_remove(rtb, ent);
+ ngtcp2_rtb_entry *ent, ngtcp2_conn_stat *cstat) {
+ ngtcp2_ksl_remove(&rtb->ents, it, &ent->hd.pkt_num);
+ rtb_on_remove(rtb, ent, cstat);
ngtcp2_rtb_entry_del(ent, rtb->mem);
}
-static int rtb_call_acked_stream_offset(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
- ngtcp2_conn *conn) {
+static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
+ ngtcp2_conn *conn) {
ngtcp2_frame_chain *frc;
uint64_t prev_stream_offset, stream_offset;
ngtcp2_strm *strm;
int rv;
- size_t datalen;
+ uint64_t datalen;
ngtcp2_strm *crypto = rtb->crypto;
+ ngtcp2_crypto_level crypto_level;
for (frc = ent->frc; frc; frc = frc->next) {
switch (frc->fr.type) {
@@ -326,9 +335,22 @@ static int rtb_call_acked_stream_offset(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
break;
}
- rv = conn->callbacks.acked_crypto_offset(conn, rtb->crypto_level,
- prev_stream_offset, datalen,
- conn->user_data);
+ switch (rtb->pktns_id) {
+ case NGTCP2_PKTNS_ID_INITIAL:
+ crypto_level = NGTCP2_CRYPTO_LEVEL_INITIAL;
+ break;
+ case NGTCP2_PKTNS_ID_HANDSHAKE:
+ crypto_level = NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
+ break;
+ case NGTCP2_PKTNS_ID_APP:
+ crypto_level = NGTCP2_CRYPTO_LEVEL_APP;
+ break;
+ default:
+ assert(0);
+ }
+
+ rv = conn->callbacks.acked_crypto_offset(
+ conn, crypto_level, prev_stream_offset, datalen, conn->user_data);
if (rv != 0) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -345,34 +367,47 @@ static int rtb_call_acked_stream_offset(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
return rv;
}
break;
+ case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
+ assert(conn->dcid.num_retire_queued);
+ --conn->dcid.num_retire_queued;
+ break;
}
}
return 0;
}
static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
- ngtcp2_tstamp ts) {
+ ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) {
+ ngtcp2_cc *cc = rtb->cc;
ngtcp2_cc_pkt pkt;
ngtcp2_rst_update_rate_sample(rtb->rst, ent, ts);
- ngtcp2_default_cc_on_pkt_acked(
- rtb->cc, ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen, ent->ts));
+ cc->on_pkt_acked(cc, cstat,
+ ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen,
+ rtb->pktns_id, ent->ts),
+ ts);
+
+ if (!(ent->flags & NGTCP2_RTB_FLAG_PROBE) &&
+ (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING)) {
+ cstat->pto_count = 0;
+ }
}
ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
- ngtcp2_conn *conn, ngtcp2_tstamp pkt_ts,
- ngtcp2_tstamp ts) {
+ ngtcp2_conn_stat *cstat, ngtcp2_conn *conn,
+ ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) {
ngtcp2_rtb_entry *ent;
int64_t largest_ack = fr->largest_ack, min_ack;
size_t i;
int rv;
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
ngtcp2_ssize num_acked = 0;
int largest_pkt_acked = 0;
int rtt_updated = 0;
ngtcp2_tstamp largest_pkt_sent_ts = 0;
+ int64_t pkt_num;
+ ngtcp2_cc *cc = rtb->cc;
if (conn && (conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) &&
largest_ack >= conn->pktns.crypto.tx.ckm->pkt_num) {
@@ -386,8 +421,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
ngtcp2_max(rtb->largest_acked_tx_pkt_num, largest_ack);
/* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
- it = ngtcp2_ksl_lower_bound(&rtb->ents,
- ngtcp2_ksl_key_ptr(&key, &largest_ack));
+ it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack);
if (ngtcp2_ksl_it_end(&it)) {
return 0;
}
@@ -395,15 +429,15 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
min_ack = largest_ack - (int64_t)fr->first_ack_blklen;
for (; !ngtcp2_ksl_it_end(&it);) {
- key = ngtcp2_ksl_it_key(&it);
- if (min_ack <= *key.i && *key.i <= largest_ack) {
+ pkt_num = *(int64_t *)ngtcp2_ksl_it_key(&it);
+ if (min_ack <= pkt_num && pkt_num <= largest_ack) {
ent = ngtcp2_ksl_it_get(&it);
if (conn) {
- rv = rtb_call_acked_stream_offset(rtb, ent, conn);
+ rv = rtb_process_acked_pkt(rtb, ent, conn);
if (rv != 0) {
return rv;
}
- if (largest_ack == *key.i) {
+ if (largest_ack == pkt_num) {
largest_pkt_sent_ts = ent->ts;
largest_pkt_acked = 1;
}
@@ -412,12 +446,16 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
rtt_updated = 1;
ngtcp2_conn_update_rtt(conn, pkt_ts - largest_pkt_sent_ts,
fr->ack_delay_unscaled);
+ if (cc->new_rtt_sample) {
+ cc->new_rtt_sample(cc, cstat, ts);
+ }
}
- rtb_on_pkt_acked(rtb, ent, ts);
+
+ rtb_on_pkt_acked(rtb, ent, cstat, ts);
/* At this point, it is invalided because rtb->ents might be
modified. */
}
- rtb_remove(rtb, &it, ent);
+ rtb_remove(rtb, &it, ent, cstat);
++num_acked;
continue;
}
@@ -428,20 +466,19 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
largest_ack = min_ack - (int64_t)fr->blks[i].gap - 2;
min_ack = largest_ack - (int64_t)fr->blks[i].blklen;
- it = ngtcp2_ksl_lower_bound(&rtb->ents,
- ngtcp2_ksl_key_ptr(&key, &largest_ack));
+ it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack);
if (ngtcp2_ksl_it_end(&it)) {
break;
}
for (; !ngtcp2_ksl_it_end(&it);) {
- key = ngtcp2_ksl_it_key(&it);
- if (*key.i < min_ack) {
+ pkt_num = *(int64_t *)ngtcp2_ksl_it_key(&it);
+ if (pkt_num < min_ack) {
break;
}
ent = ngtcp2_ksl_it_get(&it);
if (conn) {
- rv = rtb_call_acked_stream_offset(rtb, ent, conn);
+ rv = rtb_process_acked_pkt(rtb, ent, conn);
if (rv != 0) {
return rv;
}
@@ -450,38 +487,50 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
rtt_updated = 1;
ngtcp2_conn_update_rtt(conn, pkt_ts - largest_pkt_sent_ts,
fr->ack_delay_unscaled);
+ if (cc->new_rtt_sample) {
+ cc->new_rtt_sample(cc, cstat, ts);
+ }
}
- rtb_on_pkt_acked(rtb, ent, ts);
+
+ rtb_on_pkt_acked(rtb, ent, cstat, ts);
}
- rtb_remove(rtb, &it, ent);
+ rtb_remove(rtb, &it, ent, cstat);
++num_acked;
}
++i;
}
- if (conn) {
- ngtcp2_rst_on_ack_recv(rtb->rst, &conn->rcs);
- ngtcp2_default_cc_on_ack_recv(rtb->cc,
- rtt_updated ? conn->rcs.latest_rtt : 0, ts);
- }
+ ngtcp2_rst_on_ack_recv(rtb->rst, cstat);
+ cc->on_ack_recv(cc, cstat, ts);
return num_acked;
}
-static int rtb_pkt_lost(ngtcp2_rtb *rtb, const ngtcp2_rtb_entry *ent,
- uint64_t loss_delay, ngtcp2_tstamp lost_send_time) {
+static int rtb_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat,
+ const ngtcp2_rtb_entry *ent, uint64_t loss_delay,
+ ngtcp2_tstamp lost_send_time) {
+ ngtcp2_tstamp loss_time;
+ uint64_t pkt_thres =
+ rtb->cc_bytes_in_flight / cstat->max_udp_payload_size / 2;
+
+ pkt_thres = ngtcp2_max(pkt_thres, NGTCP2_PKT_THRESHOLD);
+
if (ent->ts <= lost_send_time ||
- rtb->largest_acked_tx_pkt_num >= ent->hd.pkt_num + NGTCP2_PKT_THRESHOLD) {
+ rtb->largest_acked_tx_pkt_num >= ent->hd.pkt_num + (int64_t)pkt_thres) {
return 1;
}
- if (rtb->loss_time == UINT64_MAX) {
- rtb->loss_time = ent->ts + loss_delay;
+ loss_time = cstat->loss_time[rtb->pktns_id];
+
+ if (loss_time == UINT64_MAX) {
+ loss_time = ent->ts + loss_delay;
} else {
- rtb->loss_time = ngtcp2_min(rtb->loss_time, ent->ts + loss_delay);
+ loss_time = ngtcp2_min(loss_time, ent->ts + loss_delay);
}
+ cstat->loss_time[rtb->pktns_id] = loss_time;
+
return 0;
}
@@ -489,15 +538,15 @@ static int rtb_pkt_lost(ngtcp2_rtb *rtb, const ngtcp2_rtb_entry *ent,
* rtb_compute_pkt_loss_delay computes delay until packet is
* considered lost in NGTCP2_MICROSECONDS resolution.
*/
-static ngtcp2_duration compute_pkt_loss_delay(const ngtcp2_rcvry_stat *rcs) {
+static ngtcp2_duration compute_pkt_loss_delay(const ngtcp2_conn_stat *cstat) {
/* 9/8 is kTimeThreshold */
ngtcp2_duration loss_delay =
- ngtcp2_max(rcs->latest_rtt, rcs->smoothed_rtt) * 9 / 8;
+ ngtcp2_max(cstat->latest_rtt, cstat->smoothed_rtt) * 9 / 8;
return ngtcp2_max(loss_delay, NGTCP2_GRANULARITY);
}
void ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
- ngtcp2_rcvry_stat *rcs, ngtcp2_duration pto,
+ ngtcp2_conn_stat *cstat, ngtcp2_duration pto,
ngtcp2_tstamp ts) {
ngtcp2_rtb_entry *ent;
ngtcp2_duration loss_delay;
@@ -505,26 +554,25 @@ void ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
ngtcp2_ksl_it it;
ngtcp2_tstamp latest_ts, oldest_ts;
int64_t last_lost_pkt_num;
- ngtcp2_ksl_key key;
+ ngtcp2_duration loss_window, congestion_period;
+ ngtcp2_cc *cc = rtb->cc;
- rtb->loss_time = UINT64_MAX;
- loss_delay = compute_pkt_loss_delay(rcs);
+ cstat->loss_time[rtb->pktns_id] = UINT64_MAX;
+ loss_delay = compute_pkt_loss_delay(cstat);
lost_send_time = ts - loss_delay;
- it = ngtcp2_ksl_lower_bound(
- &rtb->ents, ngtcp2_ksl_key_ptr(&key, &rtb->largest_acked_tx_pkt_num));
+ it = ngtcp2_ksl_lower_bound(&rtb->ents, &rtb->largest_acked_tx_pkt_num);
for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) {
ent = ngtcp2_ksl_it_get(&it);
- if (rtb_pkt_lost(rtb, ent, loss_delay, lost_send_time)) {
+ if (rtb_pkt_lost(rtb, cstat, ent, loss_delay, lost_send_time)) {
/* All entries from ent are considered to be lost. */
latest_ts = oldest_ts = ent->ts;
last_lost_pkt_num = ent->hd.pkt_num;
for (; !ngtcp2_ksl_it_end(&it);) {
ent = ngtcp2_ksl_it_get(&it);
- ngtcp2_ksl_remove(&rtb->ents, &it,
- ngtcp2_ksl_key_ptr(&key, &ent->hd.pkt_num));
+ ngtcp2_ksl_remove(&rtb->ents, &it, &ent->hd.pkt_num);
if (last_lost_pkt_num == ent->hd.pkt_num + 1) {
last_lost_pkt_num = ent->hd.pkt_num;
@@ -533,15 +581,23 @@ void ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
}
oldest_ts = ent->ts;
- rtb_on_remove(rtb, ent);
+ rtb_on_remove(rtb, ent, cstat);
rtb_on_pkt_lost(rtb, pfrc, ent);
}
- ngtcp2_default_cc_congestion_event(rtb->cc, latest_ts, ts);
+ cc->congestion_event(cc, cstat, latest_ts, ts);
if (last_lost_pkt_num != -1) {
- ngtcp2_default_cc_handle_persistent_congestion(
- rtb->cc, latest_ts - oldest_ts, pto);
+ loss_window = latest_ts - oldest_ts;
+ congestion_period = pto * NGTCP2_PERSISTENT_CONGESTION_THRESHOLD;
+ if (loss_window >= congestion_period) {
+ ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
+ "persistent congestion loss_window=%" PRIu64
+ " congestion_period=%" PRIu64,
+ loss_window, congestion_period);
+
+ cc->on_persistent_congestion(cc, cstat, ts);
+ }
}
return;
@@ -549,25 +605,25 @@ void ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
}
}
-void ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc) {
+void ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
+ ngtcp2_conn_stat *cstat) {
ngtcp2_rtb_entry *ent;
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key;
it = ngtcp2_ksl_begin(&rtb->ents);
for (; !ngtcp2_ksl_it_end(&it);) {
ent = ngtcp2_ksl_it_get(&it);
- rtb_on_remove(rtb, ent);
- ngtcp2_ksl_remove(&rtb->ents, &it,
- ngtcp2_ksl_key_ptr(&key, &ent->hd.pkt_num));
+ rtb_on_remove(rtb, ent, cstat);
+ ngtcp2_ksl_remove(&rtb->ents, &it, &ent->hd.pkt_num);
rtb_on_pkt_lost(rtb, pfrc, ent);
}
}
-int ngtcp2_rtb_on_crypto_timeout(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc) {
+int ngtcp2_rtb_on_crypto_timeout(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
+ ngtcp2_conn_stat *cstat) {
ngtcp2_rtb_entry *ent;
ngtcp2_ksl_it it;
ngtcp2_frame_chain *nfrc;
@@ -577,7 +633,6 @@ int ngtcp2_rtb_on_crypto_timeout(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc) {
ngtcp2_crypto *fr;
int all_acked;
int rv;
- ngtcp2_ksl_key key;
it = ngtcp2_ksl_begin(&rtb->ents);
@@ -601,7 +656,7 @@ int ngtcp2_rtb_on_crypto_timeout(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc) {
been acknowledged */
gapit = ngtcp2_gaptr_get_first_gap_after(&rtb->crypto->tx.acked_offset,
fr->offset);
- gap = *(ngtcp2_range *)ngtcp2_ksl_it_key(&gapit).ptr;
+ gap = *(ngtcp2_range *)ngtcp2_ksl_it_key(&gapit);
range.begin = fr->offset;
range.end = fr->offset + ngtcp2_vec_len(fr->data, fr->datacnt);
@@ -630,9 +685,8 @@ int ngtcp2_rtb_on_crypto_timeout(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc) {
if (all_acked) {
/* If the frames that ent contains have been acknowledged,
remove it from rtb. Otherwise crypto timer keeps firing. */
- rtb_on_remove(rtb, ent);
- ngtcp2_ksl_remove(&rtb->ents, &it,
- ngtcp2_ksl_key_ptr(&key, &ent->hd.pkt_num));
+ rtb_on_remove(rtb, ent, cstat);
+ ngtcp2_ksl_remove(&rtb->ents, &it, &ent->hd.pkt_num);
ngtcp2_rtb_entry_del(ent, rtb->mem);
continue;
}
@@ -649,22 +703,7 @@ int ngtcp2_rtb_empty(ngtcp2_rtb *rtb) {
return ngtcp2_ksl_len(&rtb->ents) == 0;
}
-uint64_t ngtcp2_rtb_get_bytes_in_flight(ngtcp2_rtb *rtb) {
- uint64_t bytes_in_flight = 0;
- ngtcp2_ksl_it it;
- ngtcp2_rtb_entry *ent;
-
- for (it = ngtcp2_ksl_begin(&rtb->ents); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- ent = ngtcp2_ksl_it_get(&it);
- if (rtb->cc_pkt_num <= ent->hd.pkt_num) {
- bytes_in_flight += ent->pktlen;
- }
- }
-
- return bytes_in_flight;
-}
-
-size_t ngtcp2_rtb_num_ack_eliciting(ngtcp2_rtb *rtb) {
- return rtb->num_ack_eliciting;
+void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num) {
+ rtb->cc_pkt_num = cc_pkt_num;
+ rtb->cc_bytes_in_flight = 0;
}
diff --git a/deps/ngtcp2/lib/ngtcp2_rtb.h b/deps/ngtcp2/lib/ngtcp2_rtb.h
index 0e11cea5d4f..6dac9b6357e 100644
--- a/deps/ngtcp2/lib/ngtcp2_rtb.h
+++ b/deps/ngtcp2/lib/ngtcp2_rtb.h
@@ -47,9 +47,6 @@ typedef struct ngtcp2_log ngtcp2_log;
struct ngtcp2_qlog;
typedef struct ngtcp2_qlog ngtcp2_qlog;
-struct ngtcp2_default_cc;
-typedef struct ngtcp2_default_cc ngtcp2_default_cc;
-
struct ngtcp2_strm;
typedef struct ngtcp2_strm ngtcp2_strm;
@@ -211,31 +208,34 @@ typedef struct {
/* crypto is CRYPTO stream. */
ngtcp2_strm *crypto;
ngtcp2_rst *rst;
- ngtcp2_default_cc *cc;
+ 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. */
int64_t largest_acked_tx_pkt_num;
+ /* num_ack_eliciting is the number of ACK eliciting entries. */
size_t num_ack_eliciting;
- ngtcp2_tstamp loss_time;
/* probe_pkt_left is the number of probe packet to send */
size_t probe_pkt_left;
- /* crypto_level is encryption level which |crypto| belongs to. */
- ngtcp2_crypto_level crypto_level;
+ /* 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
- bytes_in_flight. */
+ 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. */
+ uint64_t cc_bytes_in_flight;
} ngtcp2_rtb;
/*
* ngtcp2_rtb_init initializes |rtb|.
*/
-void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_crypto_level crypto_level,
- ngtcp2_strm *crypto, ngtcp2_rst *rst,
- ngtcp2_default_cc *cc, ngtcp2_log *log, ngtcp2_qlog *qlog,
- const ngtcp2_mem *mem);
+void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id,
+ ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc,
+ ngtcp2_log *log, ngtcp2_qlog *qlog, const ngtcp2_mem *mem);
/*
* ngtcp2_rtb_free deallocates resources allocated for |rtb|.
@@ -251,7 +251,8 @@ void ngtcp2_rtb_free(ngtcp2_rtb *rtb);
* NGTCP2_ERR_NOMEM
* Out of memory
*/
-int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent);
+int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
+ ngtcp2_conn_stat *cstat);
/*
* ngtcp2_rtb_head returns the iterator which points to the entry
@@ -276,8 +277,8 @@ ngtcp2_ksl_it ngtcp2_rtb_head(ngtcp2_rtb *rtb);
* Out of memory
*/
ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
- ngtcp2_conn *conn, ngtcp2_tstamp pkt_ts,
- ngtcp2_tstamp ts);
+ ngtcp2_conn_stat *cstat, ngtcp2_conn *conn,
+ ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts);
/*
* ngtcp2_rtb_detect_lost_pkt detects lost packets and prepends the
@@ -286,7 +287,7 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
* handle them. |pto| is PTO.
*/
void ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
- ngtcp2_rcvry_stat *rcs, ngtcp2_duration pto,
+ ngtcp2_conn_stat *cstat, ngtcp2_duration pto,
ngtcp2_tstamp ts);
/*
@@ -294,7 +295,8 @@ void ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
* all frames to |*pfrc|. Even when this function fails, some frames
* might be prepended to |*pfrc| and the caller should handle them.
*/
-void ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc);
+void ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
+ ngtcp2_conn_stat *cstat);
/*
* ngtcp2_rtb_on_crypto_timeout copies all unacknowledged CRYPTO
@@ -307,7 +309,8 @@ void ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc);
* NGTCP2_ERR_NOMEM
* Out of memory
*/
-int ngtcp2_rtb_on_crypto_timeout(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc);
+int ngtcp2_rtb_on_crypto_timeout(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
+ ngtcp2_conn_stat *cstat);
/*
* ngtcp2_rtb_empty returns nonzero if |rtb| have no entry.
@@ -315,15 +318,10 @@ int ngtcp2_rtb_on_crypto_timeout(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc);
int ngtcp2_rtb_empty(ngtcp2_rtb *rtb);
/*
- * ngtcp2_rtb_get_bytes_in_flight returns the sum of bytes in flight
- * for the stored entries.
- */
-uint64_t ngtcp2_rtb_get_bytes_in_flight(ngtcp2_rtb *rtb);
-
-/*
- * ngtcp2_rtb_num_ack_eliciting returns the number of ACK eliciting
- * entries.
+ * ngtcp2_rtb_reset_cc_state resets congestion state in |rtb|.
+ * |cc_pkt_num| is the next outbound packet number which is sent under
+ * new congestion state.
*/
-size_t ngtcp2_rtb_num_ack_eliciting(ngtcp2_rtb *rtb);
+void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num);
#endif /* NGTCP2_RTB_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_strm.c b/deps/ngtcp2/lib/ngtcp2_strm.c
index b6b315489dc..6c02e8a2274 100644
--- a/deps/ngtcp2/lib/ngtcp2_strm.c
+++ b/deps/ngtcp2/lib/ngtcp2_strm.c
@@ -32,7 +32,7 @@
#include "ngtcp2_vec.h"
static int offset_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return *lhs->i < *rhs->i;
+ return *(int64_t *)lhs < *(int64_t *)rhs;
}
int ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
@@ -110,13 +110,10 @@ void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags) {
}
int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc) {
- ngtcp2_ksl_key key;
-
assert(frc->fr.type == NGTCP2_FRAME_STREAM);
assert(frc->next == NULL);
- return ngtcp2_ksl_insert(&strm->tx.streamfrq, NULL,
- ngtcp2_ksl_key_ptr(&key, &frc->fr.stream.offset),
+ return ngtcp2_ksl_insert(&strm->tx.streamfrq, NULL, &frc->fr.stream.offset,
frc);
}
@@ -131,7 +128,6 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
ngtcp2_vec b[NGTCP2_MAX_STREAM_DATACNT];
size_t acnt, bcnt;
ngtcp2_ksl_it it;
- ngtcp2_ksl_key key, old_key;
uint64_t old_offset;
if (ngtcp2_ksl_len(&strm->tx.streamfrq) == 0) {
@@ -153,8 +149,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
}
}
- ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL,
- ngtcp2_ksl_key_ptr(&key, &fr->offset));
+ ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL, &fr->offset);
if (datalen > left) {
ngtcp2_vec_copy(a, fr->data, fr->datacnt);
@@ -182,8 +177,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
nfr->datacnt = bcnt;
ngtcp2_vec_copy(nfr->data, b, bcnt);
- rv = ngtcp2_ksl_insert(&strm->tx.streamfrq, NULL,
- ngtcp2_ksl_key_ptr(&key, &nfr->offset), nfrc);
+ rv = ngtcp2_ksl_insert(&strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
if (rv != 0) {
assert(ngtcp2_err_is_fatal(rv));
ngtcp2_frame_chain_del(nfrc, strm->mem);
@@ -228,8 +222,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
if (nfr->fin && nfr->datacnt == 0) {
fr->fin = 1;
- ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL,
- ngtcp2_ksl_key_ptr(&key, &nfr->offset));
+ ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL, &nfr->offset);
ngtcp2_frame_chain_del(nfrc, strm->mem);
break;
}
@@ -245,8 +238,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
if (nfr->datacnt == 0) {
fr->fin = nfr->fin;
- ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL,
- ngtcp2_ksl_key_ptr(&key, &nfr->offset));
+ ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL, &nfr->offset);
ngtcp2_frame_chain_del(nfrc, strm->mem);
continue;
}
@@ -254,9 +246,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
old_offset = nfr->offset;
nfr->offset += nmerged;
- ngtcp2_ksl_update_key(&strm->tx.streamfrq,
- ngtcp2_ksl_key_ptr(&old_key, &old_offset),
- ngtcp2_ksl_key_ptr(&key, &nfr->offset));
+ ngtcp2_ksl_update_key(&strm->tx.streamfrq, &old_offset, &nfr->offset);
break;
}
diff --git a/deps/ngtcp2/ngtcp2.gyp b/deps/ngtcp2/ngtcp2.gyp
index f86dcc5693e..532ee07b61e 100644
--- a/deps/ngtcp2/ngtcp2.gyp
+++ b/deps/ngtcp2/ngtcp2.gyp
@@ -10,8 +10,9 @@
'type': 'static_library',
'include_dirs': [
'lib/includes',
- 'crypto/includes',
'lib',
+ 'crypto/includes',
+ 'crypto'
],
'defines': [
'BUILDING_NGTCP2',
@@ -44,7 +45,7 @@
'defines': [ 'NGTCP2_STATICLIB' ],
'include_dirs': [
'lib/includes',
- 'crypto/includes'
+ 'crypto/includes',
]
},
'sources': [
@@ -79,19 +80,14 @@
'lib/ngtcp2_map.h',
'lib/ngtcp2_mem.c',
'lib/ngtcp2_mem.h',
- 'lib/ngtcp2_net.h',
'lib/ngtcp2_path.c',
'lib/ngtcp2_path.h',
- 'lib/ngtcp2_pipeack.c',
- 'lib/ngtcp2_pipeack.h',
'lib/ngtcp2_pkt.c',
'lib/ngtcp2_pkt.h',
'lib/ngtcp2_ppe.c',
'lib/ngtcp2_ppe.h',
'lib/ngtcp2_pq.c',
'lib/ngtcp2_pq.h',
- 'lib/ngtcp2_psl.c',
- 'lib/ngtcp2_psl.h',
'lib/ngtcp2_pv.c',
'lib/ngtcp2_pv.h',
'lib/ngtcp2_qlog.c',