deps: update ngtcp2
Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/34752 Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
bc8a4df1bb
commit
c788be2e6e
117
deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
vendored
117
deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
vendored
@ -210,8 +210,9 @@ NGTCP2_EXTERN int ngtcp2_crypto_derive_packet_protection_key(
|
|||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int ngtcp2_crypto_encrypt(uint8_t *dest,
|
NGTCP2_EXTERN int ngtcp2_crypto_encrypt(uint8_t *dest,
|
||||||
const ngtcp2_crypto_aead *aead,
|
const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *plaintext,
|
const uint8_t *plaintext,
|
||||||
size_t plaintextlen, const uint8_t *key,
|
size_t plaintextlen,
|
||||||
const uint8_t *nonce, size_t noncelen,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
const uint8_t *ad, size_t adlen);
|
const uint8_t *ad, size_t adlen);
|
||||||
|
|
||||||
@ -227,9 +228,10 @@ NGTCP2_EXTERN int ngtcp2_crypto_encrypt(uint8_t *dest,
|
|||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int
|
NGTCP2_EXTERN int
|
||||||
ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *plaintext, size_t plaintextlen,
|
const uint8_t *plaintext, size_t plaintextlen,
|
||||||
const uint8_t *key, const uint8_t *nonce,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen);
|
const uint8_t *ad, size_t adlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -243,11 +245,13 @@ ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
|||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or -1.
|
* This function returns 0 if it succeeds, or -1.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int
|
NGTCP2_EXTERN int ngtcp2_crypto_decrypt(uint8_t *dest,
|
||||||
ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
const ngtcp2_crypto_aead *aead,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *key, const uint8_t *nonce, size_t noncelen,
|
const uint8_t *ciphertext,
|
||||||
const uint8_t *ad, size_t adlen);
|
size_t ciphertextlen,
|
||||||
|
const uint8_t *nonce, size_t noncelen,
|
||||||
|
const uint8_t *ad, size_t adlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -261,9 +265,10 @@ ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
|||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int
|
NGTCP2_EXTERN int
|
||||||
ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
const uint8_t *ciphertext, size_t ciphertextlen,
|
||||||
const uint8_t *key, const uint8_t *nonce,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen);
|
const uint8_t *ad, size_t adlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -277,7 +282,7 @@ ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
|||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int ngtcp2_crypto_hp_mask(uint8_t *dest,
|
NGTCP2_EXTERN int ngtcp2_crypto_hp_mask(uint8_t *dest,
|
||||||
const ngtcp2_crypto_cipher *hp,
|
const ngtcp2_crypto_cipher *hp,
|
||||||
const uint8_t *key,
|
const ngtcp2_crypto_cipher_ctx *hp_ctx,
|
||||||
const uint8_t *sample);
|
const uint8_t *sample);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -290,10 +295,10 @@ NGTCP2_EXTERN int ngtcp2_crypto_hp_mask(uint8_t *dest,
|
|||||||
* This function returns 0 if it succeeds, or
|
* This function returns 0 if it succeeds, or
|
||||||
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
|
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int ngtcp2_crypto_hp_mask_cb(uint8_t *dest,
|
NGTCP2_EXTERN int
|
||||||
const ngtcp2_crypto_cipher *hp,
|
ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
|
||||||
const uint8_t *key,
|
const ngtcp2_crypto_cipher_ctx *hp_ctx,
|
||||||
const uint8_t *sample);
|
const uint8_t *sample);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -381,10 +386,12 @@ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_tx_key(
|
|||||||
* The derived packet protection key for decryption is written to the
|
* The derived packet protection key for decryption is written to the
|
||||||
* buffer pointed by |rx_key|. The derived packet protection IV for
|
* buffer pointed by |rx_key|. The derived packet protection IV for
|
||||||
* decryption is written to the buffer pointed by |rx_iv|.
|
* decryption is written to the buffer pointed by |rx_iv|.
|
||||||
|
* |rx_aead_ctx| must be constructed with |rx_key|.
|
||||||
*
|
*
|
||||||
* The derived packet protection key for encryption is written to the
|
* The derived packet protection key for encryption is written to the
|
||||||
* buffer pointed by |tx_key|. The derived packet protection IV for
|
* buffer pointed by |tx_key|. The derived packet protection IV for
|
||||||
* encryption is written to the buffer pointed by |tx_iv|.
|
* encryption is written to the buffer pointed by |tx_iv|.
|
||||||
|
* |tx_aead_ctx| must be constructed with |rx_key|.
|
||||||
*
|
*
|
||||||
* |current_rx_secret| and |current_tx_secret| are the current traffic
|
* |current_rx_secret| and |current_tx_secret| are the current traffic
|
||||||
* secrets for decryption and encryption. |secretlen| specifies the
|
* secrets for decryption and encryption. |secretlen| specifies the
|
||||||
@ -397,12 +404,12 @@ NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_tx_key(
|
|||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or -1.
|
* This function returns 0 if it succeeds, or -1.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int
|
NGTCP2_EXTERN int ngtcp2_crypto_update_key(
|
||||||
ngtcp2_crypto_update_key(ngtcp2_conn *conn, uint8_t *rx_secret,
|
ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
|
||||||
uint8_t *tx_secret, uint8_t *rx_key, uint8_t *rx_iv,
|
ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv,
|
||||||
uint8_t *tx_key, uint8_t *tx_iv,
|
ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv,
|
||||||
const uint8_t *current_rx_secret,
|
const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
|
||||||
const uint8_t *current_tx_secret, size_t secretlen);
|
size_t secretlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -415,8 +422,9 @@ ngtcp2_crypto_update_key(ngtcp2_conn *conn, uint8_t *rx_secret,
|
|||||||
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
|
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb(
|
NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb(
|
||||||
ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret, uint8_t *rx_key,
|
ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
|
||||||
uint8_t *rx_iv, uint8_t *tx_key, uint8_t *tx_iv,
|
ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
|
||||||
|
ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
|
||||||
const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
|
const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
|
||||||
size_t secretlen, void *user_data);
|
size_t secretlen, void *user_data);
|
||||||
|
|
||||||
@ -543,6 +551,69 @@ ngtcp2_crypto_write_retry(uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
|
|||||||
const ngtcp2_cid *scid, const ngtcp2_cid *odcid,
|
const ngtcp2_cid *scid, const ngtcp2_cid *odcid,
|
||||||
const uint8_t *token, size_t tokenlen);
|
const uint8_t *token, size_t tokenlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_aead_ctx_encrypt_init` initializes |aead_ctx| with
|
||||||
|
* new AEAD cipher context object for encryption which is constructed
|
||||||
|
* to use |key| as encryption key. |aead| specifies AEAD cipher to
|
||||||
|
* use. |noncelen| is the length of nonce.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or -1.
|
||||||
|
*/
|
||||||
|
NGTCP2_EXTERN int
|
||||||
|
ngtcp2_crypto_aead_ctx_encrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
|
const ngtcp2_crypto_aead *aead,
|
||||||
|
const uint8_t *key, size_t noncelen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_aead_ctx_decrypt_init` initializes |aead_ctx| with
|
||||||
|
* new AEAD cipher context object for decryption which is constructed
|
||||||
|
* to use |key| as encryption key. |aead| specifies AEAD cipher to
|
||||||
|
* use. |noncelen| is the length of nonce.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or -1.
|
||||||
|
*/
|
||||||
|
NGTCP2_EXTERN int
|
||||||
|
ngtcp2_crypto_aead_ctx_decrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
|
const ngtcp2_crypto_aead *aead,
|
||||||
|
const uint8_t *key, size_t noncelen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_aead_ctx_free` frees up resources used by
|
||||||
|
* |aead_ctx|. This function does not free the memory pointed by
|
||||||
|
* |aead_ctx| itself.
|
||||||
|
*/
|
||||||
|
NGTCP2_EXTERN void
|
||||||
|
ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx *aead_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_delete_crypto_aead_ctx_cb` deletes the given |aead_ctx|.
|
||||||
|
*
|
||||||
|
* This function can be directly passed to delete_crypto_aead_ctx
|
||||||
|
* field in ngtcp2_callbacks.
|
||||||
|
*/
|
||||||
|
NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_aead_ctx_cb(
|
||||||
|
ngtcp2_conn *conn, ngtcp2_crypto_aead_ctx *aead_ctx, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_delete_crypto_cipher_ctx_cb` deletes the given
|
||||||
|
* |cipher_ctx|.
|
||||||
|
*
|
||||||
|
* This function can be directly passed to delete_crypto_cipher_ctx
|
||||||
|
* field in ngtcp2_callbacks.
|
||||||
|
*/
|
||||||
|
NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_cipher_ctx_cb(
|
||||||
|
ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
179
deps/ngtcp2/crypto/openssl/openssl.c
vendored
179
deps/ngtcp2/crypto/openssl/openssl.c
vendored
@ -173,6 +173,92 @@ size_t ngtcp2_crypto_aead_taglen(const ngtcp2_crypto_aead *aead) {
|
|||||||
return crypto_aead_taglen(aead->native_handle);
|
return crypto_aead_taglen(aead->native_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ngtcp2_crypto_aead_ctx_encrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
|
const ngtcp2_crypto_aead *aead,
|
||||||
|
const uint8_t *key, size_t noncelen) {
|
||||||
|
const EVP_CIPHER *cipher = aead->native_handle;
|
||||||
|
EVP_CIPHER_CTX *actx;
|
||||||
|
|
||||||
|
actx = EVP_CIPHER_CTX_new();
|
||||||
|
if (actx == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EVP_EncryptInit_ex(actx, cipher, NULL, NULL, NULL) ||
|
||||||
|
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_IVLEN, (int)noncelen,
|
||||||
|
NULL) ||
|
||||||
|
(cipher == EVP_aes_128_ccm() &&
|
||||||
|
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG,
|
||||||
|
(int)crypto_aead_taglen(cipher), NULL)) ||
|
||||||
|
!EVP_EncryptInit_ex(actx, NULL, NULL, key, NULL)) {
|
||||||
|
EVP_CIPHER_CTX_free(actx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
aead_ctx->native_handle = actx;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngtcp2_crypto_aead_ctx_decrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
|
const ngtcp2_crypto_aead *aead,
|
||||||
|
const uint8_t *key, size_t noncelen) {
|
||||||
|
const EVP_CIPHER *cipher = aead->native_handle;
|
||||||
|
EVP_CIPHER_CTX *actx;
|
||||||
|
|
||||||
|
actx = EVP_CIPHER_CTX_new();
|
||||||
|
if (actx == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EVP_DecryptInit_ex(actx, cipher, NULL, NULL, NULL) ||
|
||||||
|
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_IVLEN, (int)noncelen,
|
||||||
|
NULL) ||
|
||||||
|
(cipher == EVP_aes_128_ccm() &&
|
||||||
|
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG,
|
||||||
|
(int)crypto_aead_taglen(cipher), NULL)) ||
|
||||||
|
!EVP_DecryptInit_ex(actx, NULL, NULL, key, NULL)) {
|
||||||
|
EVP_CIPHER_CTX_free(actx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
aead_ctx->native_handle = actx;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx *aead_ctx) {
|
||||||
|
if (aead_ctx->native_handle) {
|
||||||
|
EVP_CIPHER_CTX_free(aead_ctx->native_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngtcp2_crypto_cipher_ctx_encrypt_init(ngtcp2_crypto_cipher_ctx *cipher_ctx,
|
||||||
|
const ngtcp2_crypto_cipher *cipher,
|
||||||
|
const uint8_t *key) {
|
||||||
|
EVP_CIPHER_CTX *actx;
|
||||||
|
|
||||||
|
actx = EVP_CIPHER_CTX_new();
|
||||||
|
if (actx == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EVP_EncryptInit_ex(actx, cipher->native_handle, NULL, key, NULL)) {
|
||||||
|
EVP_CIPHER_CTX_free(actx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cipher_ctx->native_handle = actx;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngtcp2_crypto_cipher_ctx_free(ngtcp2_crypto_cipher_ctx *cipher_ctx) {
|
||||||
|
if (cipher_ctx->native_handle) {
|
||||||
|
EVP_CIPHER_CTX_free(cipher_ctx->native_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md,
|
int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md,
|
||||||
const uint8_t *secret, size_t secretlen,
|
const uint8_t *secret, size_t secretlen,
|
||||||
const uint8_t *salt, size_t saltlen) {
|
const uint8_t *salt, size_t saltlen) {
|
||||||
@ -226,26 +312,18 @@ int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
int ngtcp2_crypto_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *plaintext, size_t plaintextlen,
|
const uint8_t *plaintext, size_t plaintextlen,
|
||||||
const uint8_t *key, const uint8_t *nonce,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen) {
|
const uint8_t *ad, size_t adlen) {
|
||||||
const EVP_CIPHER *cipher = aead->native_handle;
|
const EVP_CIPHER *cipher = aead->native_handle;
|
||||||
size_t taglen = crypto_aead_taglen(cipher);
|
size_t taglen = crypto_aead_taglen(cipher);
|
||||||
EVP_CIPHER_CTX *actx;
|
EVP_CIPHER_CTX *actx = aead_ctx->native_handle;
|
||||||
int rv = 0;
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
actx = EVP_CIPHER_CTX_new();
|
(void)noncelen;
|
||||||
if (actx == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EVP_EncryptInit_ex(actx, cipher, NULL, NULL, NULL) ||
|
if (!EVP_EncryptInit_ex(actx, NULL, NULL, NULL, nonce) ||
|
||||||
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_IVLEN, (int)noncelen,
|
|
||||||
NULL) ||
|
|
||||||
(cipher == EVP_aes_128_ccm() &&
|
|
||||||
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG, (int)taglen, NULL)) ||
|
|
||||||
!EVP_EncryptInit_ex(actx, NULL, NULL, key, nonce) ||
|
|
||||||
(cipher == EVP_aes_128_ccm() &&
|
(cipher == EVP_aes_128_ccm() &&
|
||||||
!EVP_EncryptUpdate(actx, NULL, &len, NULL, (int)plaintextlen)) ||
|
!EVP_EncryptUpdate(actx, NULL, &len, NULL, (int)plaintextlen)) ||
|
||||||
!EVP_EncryptUpdate(actx, NULL, &len, ad, (int)adlen) ||
|
!EVP_EncryptUpdate(actx, NULL, &len, ad, (int)adlen) ||
|
||||||
@ -253,25 +331,25 @@ int ngtcp2_crypto_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
|||||||
!EVP_EncryptFinal_ex(actx, dest + len, &len) ||
|
!EVP_EncryptFinal_ex(actx, dest + len, &len) ||
|
||||||
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_GET_TAG, (int)taglen,
|
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_GET_TAG, (int)taglen,
|
||||||
dest + plaintextlen)) {
|
dest + plaintextlen)) {
|
||||||
rv = -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_CIPHER_CTX_free(actx);
|
return 0;
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
int ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
const uint8_t *ciphertext, size_t ciphertextlen,
|
||||||
const uint8_t *key, const uint8_t *nonce,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen) {
|
const uint8_t *ad, size_t adlen) {
|
||||||
const EVP_CIPHER *cipher = aead->native_handle;
|
const EVP_CIPHER *cipher = aead->native_handle;
|
||||||
size_t taglen = crypto_aead_taglen(cipher);
|
size_t taglen = crypto_aead_taglen(cipher);
|
||||||
EVP_CIPHER_CTX *actx;
|
EVP_CIPHER_CTX *actx = aead_ctx->native_handle;
|
||||||
int rv = 0;
|
|
||||||
int len;
|
int len;
|
||||||
const uint8_t *tag;
|
const uint8_t *tag;
|
||||||
|
|
||||||
|
(void)noncelen;
|
||||||
|
|
||||||
if (taglen > ciphertextlen) {
|
if (taglen > ciphertextlen) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -279,56 +357,37 @@ int ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
|||||||
ciphertextlen -= taglen;
|
ciphertextlen -= taglen;
|
||||||
tag = ciphertext + ciphertextlen;
|
tag = ciphertext + ciphertextlen;
|
||||||
|
|
||||||
actx = EVP_CIPHER_CTX_new();
|
if (!EVP_DecryptInit_ex(actx, NULL, NULL, NULL, nonce) ||
|
||||||
if (actx == NULL) {
|
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG, (int)taglen,
|
||||||
return -1;
|
(uint8_t *)tag) ||
|
||||||
}
|
|
||||||
|
|
||||||
if (!EVP_DecryptInit_ex(actx, cipher, NULL, NULL, NULL) ||
|
|
||||||
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_IVLEN, (int)noncelen,
|
|
||||||
NULL) ||
|
|
||||||
(cipher == EVP_aes_128_ccm() &&
|
|
||||||
!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG, (int)taglen,
|
|
||||||
(uint8_t *)tag)) ||
|
|
||||||
!EVP_DecryptInit_ex(actx, NULL, NULL, key, nonce) ||
|
|
||||||
(cipher == EVP_aes_128_ccm() &&
|
(cipher == EVP_aes_128_ccm() &&
|
||||||
!EVP_DecryptUpdate(actx, NULL, &len, NULL, (int)ciphertextlen)) ||
|
!EVP_DecryptUpdate(actx, NULL, &len, NULL, (int)ciphertextlen)) ||
|
||||||
!EVP_DecryptUpdate(actx, NULL, &len, ad, (int)adlen) ||
|
!EVP_DecryptUpdate(actx, NULL, &len, ad, (int)adlen) ||
|
||||||
!EVP_DecryptUpdate(actx, dest, &len, ciphertext, (int)ciphertextlen) ||
|
!EVP_DecryptUpdate(actx, dest, &len, ciphertext, (int)ciphertextlen) ||
|
||||||
(cipher != EVP_aes_128_ccm() &&
|
(cipher != EVP_aes_128_ccm() &&
|
||||||
(!EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG, (int)taglen,
|
!EVP_DecryptFinal_ex(actx, dest + ciphertextlen, &len))) {
|
||||||
(uint8_t *)tag) ||
|
|
||||||
!EVP_DecryptFinal_ex(actx, dest + ciphertextlen, &len)))) {
|
|
||||||
rv = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
EVP_CIPHER_CTX_free(actx);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
|
|
||||||
const uint8_t *hp_key, const uint8_t *sample) {
|
|
||||||
static const uint8_t PLAINTEXT[] = "\x00\x00\x00\x00\x00";
|
|
||||||
const EVP_CIPHER *cipher = hp->native_handle;
|
|
||||||
EVP_CIPHER_CTX *actx;
|
|
||||||
int rv = 0;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
actx = EVP_CIPHER_CTX_new();
|
|
||||||
if (actx == NULL) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EVP_EncryptInit_ex(actx, cipher, NULL, hp_key, sample) ||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
|
||||||
|
const ngtcp2_crypto_cipher_ctx *hp_ctx,
|
||||||
|
const uint8_t *sample) {
|
||||||
|
static const uint8_t PLAINTEXT[] = "\x00\x00\x00\x00\x00";
|
||||||
|
EVP_CIPHER_CTX *actx = hp_ctx->native_handle;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
(void)hp;
|
||||||
|
|
||||||
|
if (!EVP_EncryptInit_ex(actx, NULL, NULL, NULL, sample) ||
|
||||||
!EVP_EncryptUpdate(actx, dest, &len, PLAINTEXT, sizeof(PLAINTEXT) - 1) ||
|
!EVP_EncryptUpdate(actx, dest, &len, PLAINTEXT, sizeof(PLAINTEXT) - 1) ||
|
||||||
!EVP_EncryptFinal_ex(actx, dest + sizeof(PLAINTEXT) - 1, &len)) {
|
!EVP_EncryptFinal_ex(actx, dest + sizeof(PLAINTEXT) - 1, &len)) {
|
||||||
rv = -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_CIPHER_CTX_free(actx);
|
return 0;
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static OSSL_ENCRYPTION_LEVEL
|
static OSSL_ENCRYPTION_LEVEL
|
||||||
|
347
deps/ngtcp2/crypto/shared.c
vendored
347
deps/ngtcp2/crypto/shared.c
vendored
@ -153,9 +153,11 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key,
|
|||||||
const ngtcp2_crypto_ctx *ctx;
|
const ngtcp2_crypto_ctx *ctx;
|
||||||
const ngtcp2_crypto_aead *aead;
|
const ngtcp2_crypto_aead *aead;
|
||||||
const ngtcp2_crypto_md *md;
|
const ngtcp2_crypto_md *md;
|
||||||
|
const ngtcp2_crypto_cipher *hp;
|
||||||
|
ngtcp2_crypto_aead_ctx aead_ctx = {0};
|
||||||
|
ngtcp2_crypto_cipher_ctx hp_ctx = {0};
|
||||||
void *tls = ngtcp2_conn_get_tls_native_handle(conn);
|
void *tls = ngtcp2_conn_get_tls_native_handle(conn);
|
||||||
uint8_t keybuf[64], ivbuf[64], hp_keybuf[64];
|
uint8_t keybuf[64], ivbuf[64], hp_keybuf[64];
|
||||||
size_t keylen;
|
|
||||||
size_t ivlen;
|
size_t ivlen;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
@ -185,7 +187,7 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key,
|
|||||||
|
|
||||||
aead = &ctx->aead;
|
aead = &ctx->aead;
|
||||||
md = &ctx->md;
|
md = &ctx->md;
|
||||||
keylen = ngtcp2_crypto_aead_keylen(aead);
|
hp = &ctx->hp;
|
||||||
ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
||||||
|
|
||||||
if (ngtcp2_crypto_derive_packet_protection_key(key, iv, hp_key, aead, md,
|
if (ngtcp2_crypto_derive_packet_protection_key(key, iv, hp_key, aead, md,
|
||||||
@ -193,36 +195,79 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_aead_ctx_decrypt_init(&aead_ctx, aead, key, ivlen) != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_cipher_ctx_encrypt_init(&hp_ctx, hp, hp_key) != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case NGTCP2_CRYPTO_LEVEL_EARLY:
|
case NGTCP2_CRYPTO_LEVEL_EARLY:
|
||||||
rv = ngtcp2_conn_install_early_key(conn, key, iv, hp_key, keylen, ivlen);
|
rv = ngtcp2_conn_install_early_key(conn, &aead_ctx, iv, ivlen, &hp_ctx);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
|
case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
|
||||||
rv = ngtcp2_conn_install_rx_handshake_key(conn, key, iv, hp_key, keylen,
|
rv = ngtcp2_conn_install_rx_handshake_key(conn, &aead_ctx, iv, ivlen,
|
||||||
ivlen);
|
&hp_ctx);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NGTCP2_CRYPTO_LEVEL_APP:
|
case NGTCP2_CRYPTO_LEVEL_APP:
|
||||||
if (!ngtcp2_conn_is_server(conn)) {
|
if (!ngtcp2_conn_is_server(conn)) {
|
||||||
rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
|
rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = ngtcp2_conn_install_rx_key(conn, secret, key, iv, hp_key, secretlen,
|
rv = ngtcp2_conn_install_rx_key(conn, secret, secretlen, &aead_ctx, iv,
|
||||||
keylen, ivlen);
|
ivlen, &hp_ctx);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ngtcp2_crypto_cipher_ctx_free(&hp_ctx);
|
||||||
|
ngtcp2_crypto_aead_ctx_free(&aead_ctx);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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, ¶ms);
|
||||||
|
|
||||||
|
nwrite = ngtcp2_encode_transport_params(buf, sizeof(buf), exttype, ¶ms);
|
||||||
|
if (nwrite < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_set_local_transport_params(tls, buf, (size_t)nwrite) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,9 +282,11 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key,
|
|||||||
const ngtcp2_crypto_ctx *ctx;
|
const ngtcp2_crypto_ctx *ctx;
|
||||||
const ngtcp2_crypto_aead *aead;
|
const ngtcp2_crypto_aead *aead;
|
||||||
const ngtcp2_crypto_md *md;
|
const ngtcp2_crypto_md *md;
|
||||||
|
const ngtcp2_crypto_cipher *hp;
|
||||||
|
ngtcp2_crypto_aead_ctx aead_ctx = {0};
|
||||||
|
ngtcp2_crypto_cipher_ctx hp_ctx = {0};
|
||||||
void *tls = ngtcp2_conn_get_tls_native_handle(conn);
|
void *tls = ngtcp2_conn_get_tls_native_handle(conn);
|
||||||
uint8_t keybuf[64], ivbuf[64], hp_keybuf[64];
|
uint8_t keybuf[64], ivbuf[64], hp_keybuf[64];
|
||||||
size_t keylen;
|
|
||||||
size_t ivlen;
|
size_t ivlen;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
@ -269,7 +316,7 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key,
|
|||||||
|
|
||||||
aead = &ctx->aead;
|
aead = &ctx->aead;
|
||||||
md = &ctx->md;
|
md = &ctx->md;
|
||||||
keylen = ngtcp2_crypto_aead_keylen(aead);
|
hp = &ctx->hp;
|
||||||
ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
||||||
|
|
||||||
if (ngtcp2_crypto_derive_packet_protection_key(key, iv, hp_key, aead, md,
|
if (ngtcp2_crypto_derive_packet_protection_key(key, iv, hp_key, aead, md,
|
||||||
@ -277,40 +324,59 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_aead_ctx_encrypt_init(&aead_ctx, aead, key, ivlen) != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_cipher_ctx_encrypt_init(&hp_ctx, hp, hp_key) != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case NGTCP2_CRYPTO_LEVEL_EARLY:
|
case NGTCP2_CRYPTO_LEVEL_EARLY:
|
||||||
rv = ngtcp2_conn_install_early_key(conn, key, iv, hp_key, keylen, ivlen);
|
rv = ngtcp2_conn_install_early_key(conn, &aead_ctx, iv, ivlen, &hp_ctx);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
|
case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
|
||||||
|
rv = ngtcp2_conn_install_tx_handshake_key(conn, &aead_ctx, iv, ivlen,
|
||||||
|
&hp_ctx);
|
||||||
|
if (rv != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngtcp2_conn_is_server(conn)) {
|
if (ngtcp2_conn_is_server(conn)) {
|
||||||
rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
|
rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crypto_set_local_transport_params(conn, tls) != 0) {
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = ngtcp2_conn_install_tx_handshake_key(conn, key, iv, hp_key, keylen,
|
|
||||||
ivlen);
|
|
||||||
if (rv != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case NGTCP2_CRYPTO_LEVEL_APP:
|
case NGTCP2_CRYPTO_LEVEL_APP:
|
||||||
rv = ngtcp2_conn_install_tx_key(conn, secret, key, iv, hp_key, secretlen,
|
rv = ngtcp2_conn_install_tx_key(conn, secret, secretlen, &aead_ctx, iv,
|
||||||
keylen, ivlen);
|
ivlen, &hp_ctx);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ngtcp2_crypto_cipher_ctx_free(&hp_ctx);
|
||||||
|
ngtcp2_crypto_aead_ctx_free(&aead_ctx);
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_derive_and_install_initial_key(
|
int ngtcp2_crypto_derive_and_install_initial_key(
|
||||||
@ -329,7 +395,13 @@ int ngtcp2_crypto_derive_and_install_initial_key(
|
|||||||
uint8_t tx_hp_keybuf[NGTCP2_CRYPTO_INITIAL_KEYLEN];
|
uint8_t tx_hp_keybuf[NGTCP2_CRYPTO_INITIAL_KEYLEN];
|
||||||
ngtcp2_crypto_ctx ctx;
|
ngtcp2_crypto_ctx ctx;
|
||||||
ngtcp2_crypto_aead retry_aead;
|
ngtcp2_crypto_aead retry_aead;
|
||||||
|
ngtcp2_crypto_aead_ctx rx_aead_ctx = {0};
|
||||||
|
ngtcp2_crypto_cipher_ctx rx_hp_ctx = {0};
|
||||||
|
ngtcp2_crypto_aead_ctx tx_aead_ctx = {0};
|
||||||
|
ngtcp2_crypto_cipher_ctx tx_hp_ctx = {0};
|
||||||
|
ngtcp2_crypto_aead_ctx retry_aead_ctx = {0};
|
||||||
int rv;
|
int rv;
|
||||||
|
int server = ngtcp2_conn_is_server(conn);
|
||||||
|
|
||||||
ngtcp2_crypto_ctx_initial(&ctx);
|
ngtcp2_crypto_ctx_initial(&ctx);
|
||||||
|
|
||||||
@ -366,8 +438,8 @@ int ngtcp2_crypto_derive_and_install_initial_key(
|
|||||||
|
|
||||||
if (ngtcp2_crypto_derive_initial_secrets(
|
if (ngtcp2_crypto_derive_initial_secrets(
|
||||||
rx_secret, tx_secret, initial_secret, client_dcid,
|
rx_secret, tx_secret, initial_secret, client_dcid,
|
||||||
ngtcp2_conn_is_server(conn) ? NGTCP2_CRYPTO_SIDE_SERVER
|
server ? NGTCP2_CRYPTO_SIDE_SERVER : NGTCP2_CRYPTO_SIDE_CLIENT) !=
|
||||||
: NGTCP2_CRYPTO_SIDE_CLIENT) != 0) {
|
0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,27 +455,69 @@ int ngtcp2_crypto_derive_and_install_initial_key(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = ngtcp2_conn_install_initial_key(
|
if (ngtcp2_crypto_aead_ctx_decrypt_init(&rx_aead_ctx, &ctx.aead, rx_key,
|
||||||
conn, rx_key, rx_iv, rx_hp_key, tx_key, tx_iv, tx_hp_key,
|
NGTCP2_CRYPTO_INITIAL_IVLEN) != 0) {
|
||||||
NGTCP2_CRYPTO_INITIAL_KEYLEN, NGTCP2_CRYPTO_INITIAL_IVLEN);
|
goto fail;
|
||||||
if (rv != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngtcp2_conn_set_retry_aead(conn, ngtcp2_crypto_aead_retry(&retry_aead));
|
if (ngtcp2_crypto_cipher_ctx_encrypt_init(&rx_hp_ctx, &ctx.hp, rx_hp_key) !=
|
||||||
|
0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_aead_ctx_encrypt_init(&tx_aead_ctx, &ctx.aead, tx_key,
|
||||||
|
NGTCP2_CRYPTO_INITIAL_IVLEN) != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_cipher_ctx_encrypt_init(&tx_hp_ctx, &ctx.hp, tx_hp_key) !=
|
||||||
|
0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!server && !ngtcp2_conn_after_retry(conn)) {
|
||||||
|
ngtcp2_crypto_aead_retry(&retry_aead);
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_aead_ctx_encrypt_init(
|
||||||
|
&retry_aead_ctx, &retry_aead, (const uint8_t *)NGTCP2_RETRY_KEY,
|
||||||
|
sizeof(NGTCP2_RETRY_NONCE) - 1) != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = ngtcp2_conn_install_initial_key(conn, &rx_aead_ctx, rx_iv, &rx_hp_ctx,
|
||||||
|
&tx_aead_ctx, tx_iv, &tx_hp_ctx,
|
||||||
|
NGTCP2_CRYPTO_INITIAL_IVLEN);
|
||||||
|
if (rv != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retry_aead_ctx.native_handle) {
|
||||||
|
ngtcp2_conn_set_retry_aead(conn, &retry_aead, &retry_aead_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ngtcp2_crypto_aead_ctx_free(&retry_aead_ctx);
|
||||||
|
ngtcp2_crypto_cipher_ctx_free(&tx_hp_ctx);
|
||||||
|
ngtcp2_crypto_aead_ctx_free(&tx_aead_ctx);
|
||||||
|
ngtcp2_crypto_cipher_ctx_free(&rx_hp_ctx);
|
||||||
|
ngtcp2_crypto_aead_ctx_free(&rx_aead_ctx);
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_update_key(ngtcp2_conn *conn, uint8_t *rx_secret,
|
int ngtcp2_crypto_update_key(
|
||||||
uint8_t *tx_secret, uint8_t *rx_key,
|
ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
|
||||||
uint8_t *rx_iv, uint8_t *tx_key, uint8_t *tx_iv,
|
ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv,
|
||||||
const uint8_t *current_rx_secret,
|
ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv,
|
||||||
const uint8_t *current_tx_secret,
|
const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
|
||||||
size_t secretlen) {
|
size_t secretlen) {
|
||||||
const ngtcp2_crypto_ctx *ctx = ngtcp2_conn_get_crypto_ctx(conn);
|
const ngtcp2_crypto_ctx *ctx = ngtcp2_conn_get_crypto_ctx(conn);
|
||||||
const ngtcp2_crypto_aead *aead = &ctx->aead;
|
const ngtcp2_crypto_aead *aead = &ctx->aead;
|
||||||
const ngtcp2_crypto_md *md = &ctx->md;
|
const ngtcp2_crypto_md *md = &ctx->md;
|
||||||
|
size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
||||||
|
|
||||||
if (ngtcp2_crypto_update_traffic_secret(rx_secret, md, current_rx_secret,
|
if (ngtcp2_crypto_update_traffic_secret(rx_secret, md, current_rx_secret,
|
||||||
secretlen) != 0) {
|
secretlen) != 0) {
|
||||||
@ -425,51 +539,69 @@ int ngtcp2_crypto_update_key(ngtcp2_conn *conn, uint8_t *rx_secret,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_aead_ctx_decrypt_init(rx_aead_ctx, aead, rx_key, ivlen) !=
|
||||||
|
0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_aead_ctx_encrypt_init(tx_aead_ctx, aead, tx_key, ivlen) !=
|
||||||
|
0) {
|
||||||
|
ngtcp2_crypto_aead_ctx_free(rx_aead_ctx);
|
||||||
|
rx_aead_ctx->native_handle = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
int ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *plaintext, size_t plaintextlen,
|
const uint8_t *plaintext, size_t plaintextlen,
|
||||||
const uint8_t *key, const uint8_t *nonce,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen) {
|
const uint8_t *ad, size_t adlen) {
|
||||||
if (ngtcp2_crypto_encrypt(dest, aead, plaintext, plaintextlen, key, nonce,
|
if (ngtcp2_crypto_encrypt(dest, aead, aead_ctx, plaintext, plaintextlen,
|
||||||
noncelen, ad, adlen) != 0) {
|
nonce, noncelen, ad, adlen) != 0) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
int ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
const uint8_t *ciphertext, size_t ciphertextlen,
|
||||||
const uint8_t *key, const uint8_t *nonce,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen) {
|
const uint8_t *ad, size_t adlen) {
|
||||||
if (ngtcp2_crypto_decrypt(dest, aead, ciphertext, ciphertextlen, key, nonce,
|
if (ngtcp2_crypto_decrypt(dest, aead, aead_ctx, ciphertext, ciphertextlen,
|
||||||
noncelen, ad, adlen) != 0) {
|
nonce, noncelen, ad, adlen) != 0) {
|
||||||
return NGTCP2_ERR_TLS_DECRYPT;
|
return NGTCP2_ERR_TLS_DECRYPT;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
|
int ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
|
||||||
const uint8_t *hp_key, const uint8_t *sample) {
|
const ngtcp2_crypto_cipher_ctx *hp_ctx,
|
||||||
if (ngtcp2_crypto_hp_mask(dest, hp, hp_key, sample) != 0) {
|
const uint8_t *sample) {
|
||||||
|
if (ngtcp2_crypto_hp_mask(dest, hp, hp_ctx, sample) != 0) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_update_key_cb(ngtcp2_conn *conn, uint8_t *rx_secret,
|
int ngtcp2_crypto_update_key_cb(
|
||||||
uint8_t *tx_secret, uint8_t *rx_key,
|
ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
|
||||||
uint8_t *rx_iv, uint8_t *tx_key, uint8_t *tx_iv,
|
ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
|
||||||
const uint8_t *current_rx_secret,
|
ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
|
||||||
const uint8_t *current_tx_secret,
|
const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
|
||||||
size_t secretlen, void *user_data) {
|
size_t secretlen, void *user_data) {
|
||||||
|
uint8_t rx_key[64];
|
||||||
|
uint8_t tx_key[64];
|
||||||
(void)conn;
|
(void)conn;
|
||||||
(void)user_data;
|
(void)user_data;
|
||||||
|
|
||||||
if (ngtcp2_crypto_update_key(conn, rx_secret, tx_secret, rx_key, rx_iv,
|
if (ngtcp2_crypto_update_key(conn, rx_secret, tx_secret, rx_aead_ctx, rx_key,
|
||||||
tx_key, tx_iv, current_rx_secret,
|
rx_iv, tx_aead_ctx, tx_key, tx_iv,
|
||||||
current_tx_secret, secretlen) != 0) {
|
current_rx_secret, current_tx_secret,
|
||||||
|
secretlen) != 0) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -509,6 +641,8 @@ ngtcp2_ssize ngtcp2_crypto_write_connection_close(uint8_t *dest, size_t destlen,
|
|||||||
uint8_t tx_hp_key[NGTCP2_CRYPTO_INITIAL_KEYLEN];
|
uint8_t tx_hp_key[NGTCP2_CRYPTO_INITIAL_KEYLEN];
|
||||||
ngtcp2_crypto_ctx ctx;
|
ngtcp2_crypto_ctx ctx;
|
||||||
ngtcp2_ssize spktlen;
|
ngtcp2_ssize spktlen;
|
||||||
|
ngtcp2_crypto_aead_ctx aead_ctx = {0};
|
||||||
|
ngtcp2_crypto_cipher_ctx hp_ctx = {0};
|
||||||
|
|
||||||
ngtcp2_crypto_ctx_initial(&ctx);
|
ngtcp2_crypto_ctx_initial(&ctx);
|
||||||
|
|
||||||
@ -524,13 +658,28 @@ ngtcp2_ssize ngtcp2_crypto_write_connection_close(uint8_t *dest, size_t destlen,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_aead_ctx_encrypt_init(&aead_ctx, &ctx.aead, tx_key,
|
||||||
|
NGTCP2_CRYPTO_INITIAL_IVLEN) != 0) {
|
||||||
|
spktlen = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngtcp2_crypto_cipher_ctx_encrypt_init(&hp_ctx, &ctx.hp, tx_hp_key) != 0) {
|
||||||
|
spktlen = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
spktlen = ngtcp2_pkt_write_connection_close(
|
spktlen = ngtcp2_pkt_write_connection_close(
|
||||||
dest, destlen, dcid, scid, error_code, ngtcp2_crypto_encrypt_cb,
|
dest, destlen, dcid, scid, error_code, ngtcp2_crypto_encrypt_cb,
|
||||||
&ctx.aead, tx_key, tx_iv, ngtcp2_crypto_hp_mask_cb, &ctx.hp, tx_hp_key);
|
&ctx.aead, &aead_ctx, tx_iv, ngtcp2_crypto_hp_mask_cb, &ctx.hp, &hp_ctx);
|
||||||
if (spktlen < 0) {
|
if (spktlen < 0) {
|
||||||
return -1;
|
spktlen = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
ngtcp2_crypto_cipher_ctx_free(&hp_ctx);
|
||||||
|
ngtcp2_crypto_aead_ctx_free(&aead_ctx);
|
||||||
|
|
||||||
return spktlen;
|
return spktlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,72 +690,51 @@ ngtcp2_ssize ngtcp2_crypto_write_retry(uint8_t *dest, size_t destlen,
|
|||||||
const uint8_t *token, size_t tokenlen) {
|
const uint8_t *token, size_t tokenlen) {
|
||||||
ngtcp2_crypto_aead aead;
|
ngtcp2_crypto_aead aead;
|
||||||
ngtcp2_ssize spktlen;
|
ngtcp2_ssize spktlen;
|
||||||
|
ngtcp2_crypto_aead_ctx aead_ctx = {0};
|
||||||
|
|
||||||
ngtcp2_crypto_aead_retry(&aead);
|
ngtcp2_crypto_aead_retry(&aead);
|
||||||
|
|
||||||
spktlen = ngtcp2_pkt_write_retry(dest, destlen, dcid, scid, odcid, token,
|
if (ngtcp2_crypto_aead_ctx_encrypt_init(&aead_ctx, &aead,
|
||||||
tokenlen, ngtcp2_crypto_encrypt_cb, &aead);
|
(const uint8_t *)NGTCP2_RETRY_KEY,
|
||||||
if (spktlen < 0) {
|
NGTCP2_CRYPTO_INITIAL_IVLEN) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spktlen =
|
||||||
|
ngtcp2_pkt_write_retry(dest, destlen, dcid, scid, odcid, token, tokenlen,
|
||||||
|
ngtcp2_crypto_encrypt_cb, &aead, &aead_ctx);
|
||||||
|
if (spktlen < 0) {
|
||||||
|
spktlen = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngtcp2_crypto_aead_ctx_free(&aead_ctx);
|
||||||
|
|
||||||
return spktlen;
|
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, ¶ms);
|
|
||||||
|
|
||||||
nwrite = ngtcp2_encode_transport_params(buf, sizeof(buf), exttype, ¶ms);
|
|
||||||
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
|
* crypto_setup_initial_crypto establishes the initial secrets and
|
||||||
* encryption keys, and prepares local QUIC transport parameters.
|
* encryption keys, and prepares local QUIC transport parameters.
|
||||||
*/
|
*/
|
||||||
static int crypto_setup_initial_crypto(ngtcp2_conn *conn,
|
static int crypto_setup_initial_crypto(ngtcp2_conn *conn,
|
||||||
const ngtcp2_cid *dcid) {
|
const ngtcp2_cid *dcid) {
|
||||||
void *tls = ngtcp2_conn_get_tls_native_handle(conn);
|
return ngtcp2_crypto_derive_and_install_initial_key(
|
||||||
|
conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, dcid);
|
||||||
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) {
|
int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn, void *user_data) {
|
||||||
const ngtcp2_cid *dcid = ngtcp2_conn_get_dcid(conn);
|
const ngtcp2_cid *dcid = ngtcp2_conn_get_dcid(conn);
|
||||||
|
void *tls = ngtcp2_conn_get_tls_native_handle(conn);
|
||||||
(void)user_data;
|
(void)user_data;
|
||||||
|
|
||||||
if (crypto_setup_initial_crypto(conn, dcid) != 0) {
|
if (crypto_setup_initial_crypto(conn, dcid) != 0) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (crypto_set_local_transport_params(conn, tls) != 0) {
|
||||||
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngtcp2_crypto_read_write_crypto_data(conn, NGTCP2_CRYPTO_LEVEL_INITIAL,
|
if (ngtcp2_crypto_read_write_crypto_data(conn, NGTCP2_CRYPTO_LEVEL_INITIAL,
|
||||||
NULL, 0) != 0) {
|
NULL, 0) != 0) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
@ -639,3 +767,20 @@ int ngtcp2_crypto_recv_client_initial_cb(ngtcp2_conn *conn,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ngtcp2_crypto_delete_crypto_aead_ctx_cb(ngtcp2_conn *conn,
|
||||||
|
ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
|
void *user_data) {
|
||||||
|
(void)conn;
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
|
ngtcp2_crypto_aead_ctx_free(aead_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngtcp2_crypto_delete_crypto_cipher_ctx_cb(
|
||||||
|
ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data) {
|
||||||
|
(void)conn;
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
|
ngtcp2_crypto_cipher_ctx_free(cipher_ctx);
|
||||||
|
}
|
||||||
|
23
deps/ngtcp2/crypto/shared.h
vendored
23
deps/ngtcp2/crypto/shared.h
vendored
@ -110,7 +110,6 @@ int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf,
|
|||||||
*/
|
*/
|
||||||
int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls);
|
int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
@ -165,4 +164,26 @@ int ngtcp2_crypto_derive_and_install_initial_key(
|
|||||||
uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp,
|
uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp,
|
||||||
const ngtcp2_cid *client_dcid);
|
const ngtcp2_cid *client_dcid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_cipher_ctx_encrypt_init` initializes |cipher_ctx|
|
||||||
|
* with new cipher context object for encryption which is constructed
|
||||||
|
* to use |key| as encryption key. |cipher| specifies cipher to use.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or -1.
|
||||||
|
*/
|
||||||
|
int ngtcp2_crypto_cipher_ctx_encrypt_init(ngtcp2_crypto_cipher_ctx *cipher_ctx,
|
||||||
|
const ngtcp2_crypto_cipher *cipher,
|
||||||
|
const uint8_t *key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_cipher_ctx_free` frees up resources used by
|
||||||
|
* |cipher_ctx|. This function does not free the memory pointed by
|
||||||
|
* |cipher_ctx| itself.
|
||||||
|
*/
|
||||||
|
void ngtcp2_crypto_cipher_ctx_free(ngtcp2_crypto_cipher_ctx *cipher_ctx);
|
||||||
|
|
||||||
#endif /* NGTCP2_SHARED_H */
|
#endif /* NGTCP2_SHARED_H */
|
||||||
|
431
deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
vendored
431
deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
vendored
@ -49,6 +49,12 @@ extern "C" {
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# include <winsock2.h>
|
||||||
|
#else
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ngtcp2/version.h>
|
#include <ngtcp2/version.h>
|
||||||
|
|
||||||
#ifdef NGTCP2_STATICLIB
|
#ifdef NGTCP2_STATICLIB
|
||||||
@ -190,6 +196,15 @@ typedef struct ngtcp2_mem {
|
|||||||
"\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97\x86\xf1\x9c\x61\x11\xe0\x43\x90" \
|
"\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97\x86\xf1\x9c\x61\x11\xe0\x43\x90" \
|
||||||
"\xa8\x99"
|
"\xa8\x99"
|
||||||
|
|
||||||
|
/* NGTCP2_RETRY_KEY is an encryption key to create integrity tag of
|
||||||
|
Retry packet. */
|
||||||
|
#define NGTCP2_RETRY_KEY \
|
||||||
|
"\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1"
|
||||||
|
|
||||||
|
/* NGTCP2_RETRY_NONCE is nonce used when generating integrity tag of
|
||||||
|
Retry packet. */
|
||||||
|
#define NGTCP2_RETRY_NONCE "\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c"
|
||||||
|
|
||||||
/* NGTCP2_HP_MASKLEN is the length of header protection mask. */
|
/* NGTCP2_HP_MASKLEN is the length of header protection mask. */
|
||||||
#define NGTCP2_HP_MASKLEN 5
|
#define NGTCP2_HP_MASKLEN 5
|
||||||
|
|
||||||
@ -212,6 +227,9 @@ typedef struct ngtcp2_mem {
|
|||||||
nanosecond. */
|
nanosecond. */
|
||||||
#define NGTCP2_NANOSECONDS ((uint64_t)1ULL)
|
#define NGTCP2_NANOSECONDS ((uint64_t)1ULL)
|
||||||
|
|
||||||
|
/* NGTCP2_DEFAULT_INITIAL_RTT is a default initial RTT. */
|
||||||
|
#define NGTCP2_DEFAULT_INITIAL_RTT (333 * NGTCP2_MILLISECONDS)
|
||||||
|
|
||||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||||
typedef enum ngtcp2_lib_error : int {
|
typedef enum ngtcp2_lib_error : int {
|
||||||
#else
|
#else
|
||||||
@ -248,7 +266,7 @@ typedef enum ngtcp2_lib_error {
|
|||||||
NGTCP2_ERR_CONN_ID_BLOCKED = -237,
|
NGTCP2_ERR_CONN_ID_BLOCKED = -237,
|
||||||
NGTCP2_ERR_INTERNAL = -238,
|
NGTCP2_ERR_INTERNAL = -238,
|
||||||
NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED = -239,
|
NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED = -239,
|
||||||
NGTCP2_ERR_WRITE_STREAM_MORE = -240,
|
NGTCP2_ERR_WRITE_MORE = -240,
|
||||||
NGTCP2_ERR_RETRY = -241,
|
NGTCP2_ERR_RETRY = -241,
|
||||||
NGTCP2_ERR_DROP_CONN = -242,
|
NGTCP2_ERR_DROP_CONN = -242,
|
||||||
NGTCP2_ERR_FATAL = -500,
|
NGTCP2_ERR_FATAL = -500,
|
||||||
@ -488,9 +506,8 @@ typedef struct ngtcp2_transport_params {
|
|||||||
ngtcp2_preferred_addr preferred_address;
|
ngtcp2_preferred_addr preferred_address;
|
||||||
/* original_dcid is the Destination Connection ID field from the
|
/* original_dcid is the Destination Connection ID field from the
|
||||||
first Initial packet from client. Server must specify this
|
first Initial packet from client. Server must specify this
|
||||||
field. If application specifies retry_scid_present to nonzero,
|
field. It is expected that application knows the original
|
||||||
then it must also specify this field. It is expected that
|
Destination Connection ID even if it sends Retry packet, for
|
||||||
application knows the original Destination Connection ID, for
|
|
||||||
example, by including it in retry token. Otherwise, application
|
example, by including it in retry token. Otherwise, application
|
||||||
should not specify this field. */
|
should not specify this field. */
|
||||||
ngtcp2_cid original_dcid;
|
ngtcp2_cid original_dcid;
|
||||||
@ -573,6 +590,7 @@ typedef struct ngtcp2_conn_stat {
|
|||||||
ngtcp2_duration min_rtt;
|
ngtcp2_duration min_rtt;
|
||||||
ngtcp2_duration smoothed_rtt;
|
ngtcp2_duration smoothed_rtt;
|
||||||
ngtcp2_duration rttvar;
|
ngtcp2_duration rttvar;
|
||||||
|
ngtcp2_duration initial_rtt;
|
||||||
size_t pto_count;
|
size_t pto_count;
|
||||||
ngtcp2_tstamp loss_detection_timer;
|
ngtcp2_tstamp loss_detection_timer;
|
||||||
/* last_tx_pkt_ts corresponds to
|
/* last_tx_pkt_ts corresponds to
|
||||||
@ -678,8 +696,30 @@ typedef struct ngtcp2_cc {
|
|||||||
ngtcp2_conn_server_new. */
|
ngtcp2_conn_server_new. */
|
||||||
typedef void (*ngtcp2_printf)(void *user_data, const char *format, ...);
|
typedef void (*ngtcp2_printf)(void *user_data, const char *format, ...);
|
||||||
|
|
||||||
typedef void (*ngtcp2_qlog_write)(void *user_data, const void *data,
|
/**
|
||||||
size_t datalen);
|
* @enum
|
||||||
|
*
|
||||||
|
* :type:`ngtcp2_qlog_write_flag` defines the set of flags passed to
|
||||||
|
* :type:`ngtcp2_qlog_write` callback.
|
||||||
|
*/
|
||||||
|
typedef enum ngtcp2_qlog_write_flag {
|
||||||
|
NGTCP2_QLOG_WRITE_FLAG_NONE = 0,
|
||||||
|
/**
|
||||||
|
* NGTCP2_QLOG_WRITE_FLAG_FIN indicates that this is the final call
|
||||||
|
* to :type:`ngtcp2_qlog_write` in the current connection.
|
||||||
|
*/
|
||||||
|
NGTCP2_QLOG_WRITE_FLAG_FIN = 0x01
|
||||||
|
} ngtcp2_qlog_write_flag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @functypedef
|
||||||
|
*
|
||||||
|
* :type:`ngtcp2_qlog_write` is a callback function which is called to
|
||||||
|
* write qlog |data| of length |datalen| bytes. |flags| is bitwise OR
|
||||||
|
* of zero or more of :type:`ngtcp2_qlog_write_flag`.
|
||||||
|
*/
|
||||||
|
typedef void (*ngtcp2_qlog_write)(void *user_data, uint32_t flags,
|
||||||
|
const void *data, size_t datalen);
|
||||||
|
|
||||||
typedef struct ngtcp2_qlog_settings {
|
typedef struct ngtcp2_qlog_settings {
|
||||||
/* odcid is Original Destination Connection ID sent by client. It
|
/* odcid is Original Destination Connection ID sent by client. It
|
||||||
@ -699,6 +739,8 @@ typedef struct ngtcp2_settings {
|
|||||||
ngtcp2_cc *cc;
|
ngtcp2_cc *cc;
|
||||||
/* initial_ts is an initial timestamp given to the library. */
|
/* initial_ts is an initial timestamp given to the library. */
|
||||||
ngtcp2_tstamp initial_ts;
|
ngtcp2_tstamp initial_ts;
|
||||||
|
/* initial_rtt is an initial RTT. */
|
||||||
|
ngtcp2_duration initial_rtt;
|
||||||
/* log_printf is a function that the library uses to write logs.
|
/* log_printf is a function that the library uses to write logs.
|
||||||
NULL means no logging output. */
|
NULL means no logging output. */
|
||||||
ngtcp2_printf log_printf;
|
ngtcp2_printf log_printf;
|
||||||
@ -730,9 +772,9 @@ typedef struct ngtcp2_settings {
|
|||||||
typedef struct ngtcp2_addr {
|
typedef struct ngtcp2_addr {
|
||||||
/* addrlen is the length of addr. */
|
/* addrlen is the length of addr. */
|
||||||
size_t addrlen;
|
size_t addrlen;
|
||||||
/* addr points to the buffer which contains endpoint address. It is
|
/* addr points to the buffer which contains endpoint address. It
|
||||||
opaque to the ngtcp2 library. It must not be NULL. */
|
must not be NULL. */
|
||||||
uint8_t *addr;
|
struct sockaddr *addr;
|
||||||
/* user_data is an arbitrary data and opaque to the library. */
|
/* user_data is an arbitrary data and opaque to the library. */
|
||||||
void *user_data;
|
void *user_data;
|
||||||
} ngtcp2_addr;
|
} ngtcp2_addr;
|
||||||
@ -757,8 +799,8 @@ typedef struct ngtcp2_path {
|
|||||||
* the longest addresses.
|
* the longest addresses.
|
||||||
*/
|
*/
|
||||||
typedef struct ngtcp2_path_storage {
|
typedef struct ngtcp2_path_storage {
|
||||||
uint8_t local_addrbuf[128];
|
struct sockaddr_storage local_addrbuf;
|
||||||
uint8_t remote_addrbuf[128];
|
struct sockaddr_storage remote_addrbuf;
|
||||||
ngtcp2_path path;
|
ngtcp2_path path;
|
||||||
} ngtcp2_path_storage;
|
} ngtcp2_path_storage;
|
||||||
|
|
||||||
@ -799,6 +841,30 @@ typedef struct ngtcp2_crypto_cipher {
|
|||||||
void *native_handle;
|
void *native_handle;
|
||||||
} ngtcp2_crypto_cipher;
|
} ngtcp2_crypto_cipher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_aead_ctx` is a wrapper around native AEAD cipher
|
||||||
|
* context object. It should be initialized with a specific key.
|
||||||
|
* ngtcp2 library reuses this context object to encrypt or decrypt
|
||||||
|
* multiple packets.
|
||||||
|
*/
|
||||||
|
typedef struct ngtcp2_crypto_aead_ctx {
|
||||||
|
void *native_handle;
|
||||||
|
} ngtcp2_crypto_aead_ctx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct
|
||||||
|
*
|
||||||
|
* `ngtcp2_crypto_cipher_ctx` is a wrapper around native cipher
|
||||||
|
* context object. It should be initialized with a specific key.
|
||||||
|
* ngtcp2 library reuses this context object to encrypt or decrypt
|
||||||
|
* multiple packet headers.
|
||||||
|
*/
|
||||||
|
typedef struct ngtcp2_crypto_cipher_ctx {
|
||||||
|
void *native_handle;
|
||||||
|
} ngtcp2_crypto_cipher_ctx;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
@ -1200,9 +1266,10 @@ typedef int (*ngtcp2_recv_retry)(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
|
|||||||
* :type:`ngtcp2_encrypt` is invoked when the ngtcp2 library asks the
|
* :type:`ngtcp2_encrypt` is invoked when the ngtcp2 library asks the
|
||||||
* application to encrypt packet payload. The packet payload to
|
* application to encrypt packet payload. The packet payload to
|
||||||
* encrypt is passed as |plaintext| of length |plaintextlen|. The
|
* encrypt is passed as |plaintext| of length |plaintextlen|. The
|
||||||
* encryption key is passed as |key|. The nonce is passed as |nonce|
|
* AEAD cipher is |aead|. |aead_ctx| is the AEAD cipher context
|
||||||
* of length |noncelen|. The ad, Additional Data to AEAD, is passed
|
* object which is initialized with encryption key. The nonce is
|
||||||
* as |ad| of length |adlen|.
|
* passed as |nonce| of length |noncelen|. The ad, Additional Data to
|
||||||
|
* AEAD, is passed as |ad| of length |adlen|.
|
||||||
*
|
*
|
||||||
* The implementation of this callback must encrypt |plaintext| using
|
* The implementation of this callback must encrypt |plaintext| using
|
||||||
* the negotiated cipher suite and write the ciphertext into the
|
* the negotiated cipher suite and write the ciphertext into the
|
||||||
@ -1216,9 +1283,10 @@ typedef int (*ngtcp2_recv_retry)(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
|
|||||||
* return immediately.
|
* return immediately.
|
||||||
*/
|
*/
|
||||||
typedef int (*ngtcp2_encrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
typedef int (*ngtcp2_encrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *plaintext, size_t plaintextlen,
|
const uint8_t *plaintext, size_t plaintextlen,
|
||||||
const uint8_t *key, const uint8_t *nonce,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen);
|
const uint8_t *ad, size_t adlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @functypedef
|
* @functypedef
|
||||||
@ -1226,7 +1294,8 @@ typedef int (*ngtcp2_encrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
|||||||
* :type:`ngtcp2_decrypt` is invoked when the ngtcp2 library asks the
|
* :type:`ngtcp2_decrypt` is invoked when the ngtcp2 library asks the
|
||||||
* application to decrypt packet payload. The packet payload to
|
* application to decrypt packet payload. The packet payload to
|
||||||
* decrypt is passed as |ciphertext| of length |ciphertextlen|. The
|
* decrypt is passed as |ciphertext| of length |ciphertextlen|. The
|
||||||
* decryption key is passed as |key| of length |keylen|. The nonce is
|
* AEAD cipher is |aead|. |aead_ctx| is the AEAD cipher context
|
||||||
|
* object which is initialized with decryption key. The nonce is
|
||||||
* passed as |nonce| of length |noncelen|. The ad, Additional Data to
|
* passed as |nonce| of length |noncelen|. The ad, Additional Data to
|
||||||
* AEAD, is passed as |ad| of length |adlen|.
|
* AEAD, is passed as |ad| of length |adlen|.
|
||||||
*
|
*
|
||||||
@ -1243,16 +1312,19 @@ typedef int (*ngtcp2_encrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
|||||||
* makes the library call return immediately.
|
* makes the library call return immediately.
|
||||||
*/
|
*/
|
||||||
typedef int (*ngtcp2_decrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
typedef int (*ngtcp2_decrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
const uint8_t *ciphertext, size_t ciphertextlen,
|
||||||
const uint8_t *key, const uint8_t *nonce,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen);
|
const uint8_t *ad, size_t adlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @functypedef
|
* @functypedef
|
||||||
*
|
*
|
||||||
* :type:`ngtcp2_hp_mask` is invoked when the ngtcp2 library asks the
|
* :type:`ngtcp2_hp_mask` is invoked when the ngtcp2 library asks the
|
||||||
* application to produce mask to encrypt or decrypt packet header.
|
* application to produce mask to encrypt or decrypt packet header.
|
||||||
* The key is passed as |hp_key|. The sample is passed as |sample|.
|
* The encryption cipher is |hp|. |hp_ctx| is the cipher context
|
||||||
|
* object which is initialized with header protection key. The sample
|
||||||
|
* is passed as |sample|.
|
||||||
*
|
*
|
||||||
* The implementation of this callback must produce a mask using the
|
* The implementation of this callback must produce a mask using the
|
||||||
* header protection cipher suite specified by QUIC specification and
|
* header protection cipher suite specified by QUIC specification and
|
||||||
@ -1265,7 +1337,8 @@ typedef int (*ngtcp2_decrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
|
|||||||
* return immediately.
|
* return immediately.
|
||||||
*/
|
*/
|
||||||
typedef int (*ngtcp2_hp_mask)(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
|
typedef int (*ngtcp2_hp_mask)(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
|
||||||
const uint8_t *hp_key, const uint8_t *sample);
|
const ngtcp2_crypto_cipher_ctx *hp_ctx,
|
||||||
|
const uint8_t *sample);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum
|
* @enum
|
||||||
@ -1457,8 +1530,7 @@ typedef int (*ngtcp2_extend_max_stream_data)(ngtcp2_conn *conn,
|
|||||||
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
|
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
|
||||||
* immediately.
|
* immediately.
|
||||||
*/
|
*/
|
||||||
typedef int (*ngtcp2_rand)(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
typedef int (*ngtcp2_rand)(uint8_t *dest, size_t destlen, ngtcp2_rand_ctx ctx);
|
||||||
ngtcp2_rand_ctx ctx, void *user_data);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @functypedef
|
* @functypedef
|
||||||
@ -1500,28 +1572,31 @@ typedef int (*ngtcp2_remove_connection_id)(ngtcp2_conn *conn,
|
|||||||
*
|
*
|
||||||
* :type:`ngtcp2_update_key` is a callback function which tells the
|
* :type:`ngtcp2_update_key` is a callback function which tells the
|
||||||
* application that it must generate new packet protection keying
|
* application that it must generate new packet protection keying
|
||||||
* materials. The current set of secrets are given as
|
* materials and AEAD cipher context objects with new keys. The
|
||||||
* |current_rx_secret| and |current_tx_secret| of length |secretlen|.
|
* current set of secrets are given as |current_rx_secret| and
|
||||||
* They are decryption and encryption secrets respectively.
|
* |current_tx_secret| of length |secretlen|. They are decryption and
|
||||||
|
* encryption secrets respectively.
|
||||||
*
|
*
|
||||||
* The application has to generate new secrets and keys for both
|
* The application has to generate new secrets and keys for both
|
||||||
* encryption and decryption, and write decryption secret, key and IV
|
* encryption and decryption, and write decryption secret and IV to
|
||||||
* to the buffer pointed by |rx_secret|, |rx_key| and |rx_iv|
|
* the buffer pointed by |rx_secret| and |rx_iv| respectively. It
|
||||||
* respectively. Similarly, write encryption secret, key and IV to
|
* also has to create new AEAD cipher context object with new
|
||||||
* the buffer pointed by |tx_secret|, |tx_key| and |tx_iv|. All given
|
* decryption key and initialize |rx_aead_ctx| with it. Similarly,
|
||||||
|
* write encryption secret and IV to the buffer pointed by |tx_secret|
|
||||||
|
* and |tx_iv|. Create new AEAD cipher context object with new
|
||||||
|
* encryption key and initialize |tx_aead_ctx| with it. All given
|
||||||
* buffers have the enough capacity to store secret, key and IV.
|
* buffers have the enough capacity to store secret, key and IV.
|
||||||
*
|
*
|
||||||
* The callback function must return 0 if it succeeds. Returning
|
* The callback function must return 0 if it succeeds. Returning
|
||||||
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
|
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
|
||||||
* immediately.
|
* immediately.
|
||||||
*/
|
*/
|
||||||
typedef int (*ngtcp2_update_key)(ngtcp2_conn *conn, uint8_t *rx_secret,
|
typedef int (*ngtcp2_update_key)(
|
||||||
uint8_t *tx_secret, uint8_t *rx_key,
|
ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
|
||||||
uint8_t *rx_iv, uint8_t *tx_key,
|
ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
|
||||||
uint8_t *tx_iv,
|
ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
|
||||||
const uint8_t *current_rx_secret,
|
const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
|
||||||
const uint8_t *current_tx_secret,
|
size_t secretlen, void *user_data);
|
||||||
size_t secretlen, void *user_data);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @functypedef
|
* @functypedef
|
||||||
@ -1608,6 +1683,26 @@ typedef int (*ngtcp2_connection_id_status)(ngtcp2_conn *conn, int type,
|
|||||||
typedef int (*ngtcp2_recv_new_token)(ngtcp2_conn *conn, const ngtcp2_vec *token,
|
typedef int (*ngtcp2_recv_new_token)(ngtcp2_conn *conn, const ngtcp2_vec *token,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @functypedef
|
||||||
|
*
|
||||||
|
* :type:`ngtcp2_delete_crypto_aead_ctx` is a callback function which
|
||||||
|
* must delete the native object pointed by |aead_ctx|->native_handle.
|
||||||
|
*/
|
||||||
|
typedef void (*ngtcp2_delete_crypto_aead_ctx)(ngtcp2_conn *conn,
|
||||||
|
ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @functypedef
|
||||||
|
*
|
||||||
|
* :type:`ngtcp2_delete_crypto_cipher_ctx` is a callback function
|
||||||
|
* which must delete the native object pointed by
|
||||||
|
* |cipher_ctx|->native_handle.
|
||||||
|
*/
|
||||||
|
typedef void (*ngtcp2_delete_crypto_cipher_ctx)(
|
||||||
|
ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data);
|
||||||
|
|
||||||
typedef struct ngtcp2_conn_callbacks {
|
typedef struct ngtcp2_conn_callbacks {
|
||||||
/**
|
/**
|
||||||
* client_initial is a callback function which is invoked when
|
* client_initial is a callback function which is invoked when
|
||||||
@ -1794,6 +1889,16 @@ typedef struct ngtcp2_conn_callbacks {
|
|||||||
* token is received from server. This field is ignored by server.
|
* token is received from server. This field is ignored by server.
|
||||||
*/
|
*/
|
||||||
ngtcp2_recv_new_token recv_new_token;
|
ngtcp2_recv_new_token recv_new_token;
|
||||||
|
/**
|
||||||
|
* delete_crypto_aead_ctx is a callback function which deletes a
|
||||||
|
* given AEAD cipher context object.
|
||||||
|
*/
|
||||||
|
ngtcp2_delete_crypto_aead_ctx delete_crypto_aead_ctx;
|
||||||
|
/**
|
||||||
|
* delete_crypto_cipher_ctx is a callback function which deletes a
|
||||||
|
* given cipher context object.
|
||||||
|
*/
|
||||||
|
ngtcp2_delete_crypto_cipher_ctx delete_crypto_cipher_ctx;
|
||||||
} ngtcp2_conn_callbacks;
|
} ngtcp2_conn_callbacks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1820,9 +1925,9 @@ typedef struct ngtcp2_conn_callbacks {
|
|||||||
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_connection_close(
|
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_connection_close(
|
||||||
uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
|
uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
|
||||||
const ngtcp2_cid *scid, uint64_t error_code, ngtcp2_encrypt encrypt,
|
const ngtcp2_cid *scid, uint64_t error_code, ngtcp2_encrypt encrypt,
|
||||||
const ngtcp2_crypto_aead *aead, const uint8_t *key, const uint8_t *iv,
|
const ngtcp2_crypto_aead *aead, const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp,
|
const uint8_t *iv, ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp,
|
||||||
const uint8_t *hp_key);
|
const ngtcp2_crypto_cipher_ctx *hp_ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -1831,6 +1936,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_connection_close(
|
|||||||
* by |dest| whose length is |destlen|. |odcid| specifies Original
|
* by |dest| whose length is |destlen|. |odcid| specifies Original
|
||||||
* Destination Connection ID. |token| specifies Retry Token, and
|
* Destination Connection ID. |token| specifies Retry Token, and
|
||||||
* |tokenlen| specifies its length. |aead| must be AEAD_AES_128_GCM.
|
* |tokenlen| specifies its length. |aead| must be AEAD_AES_128_GCM.
|
||||||
|
* |aead_ctx| must be initialized with :macro:`NGTCP2_RETRY_KEY` as an
|
||||||
|
* encryption key.
|
||||||
*
|
*
|
||||||
* This function returns the number of bytes written to the buffer, or
|
* This function returns the number of bytes written to the buffer, or
|
||||||
* one of the following negative error codes:
|
* one of the following negative error codes:
|
||||||
@ -1843,7 +1950,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_connection_close(
|
|||||||
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_retry(
|
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_retry(
|
||||||
uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
|
uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
|
||||||
const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token,
|
const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token,
|
||||||
size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead);
|
size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -1983,12 +2091,21 @@ NGTCP2_EXTERN int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn);
|
|||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `ngtcp2_conn_install_initial_key` installs packet protection keying
|
* `ngtcp2_conn_install_initial_key` installs packet protection keying
|
||||||
* materials for Initial packets. |rx_key| of length |keylen|, IV
|
* materials for Initial packets. |rx_aead_ctx| is AEAD cipher
|
||||||
* |rx_iv| of length |rx_ivlen|, and packet header protection key
|
* context object and must be initialized with decryption key, IV
|
||||||
* |rx_hp_key| of length |keylen| to decrypt incoming Initial packets.
|
* |rx_iv| of length |rx_ivlen|, and packet header protection cipher
|
||||||
* Similarly, |tx_key|, |tx_iv| and |tx_hp_key| are for encrypt
|
* context object |rx_hp_ctx| to decrypt incoming Initial packets.
|
||||||
* outgoing packets and are the same length with the rx counterpart .
|
* Similarly, |tx_aead_ctx|, |tx_iv| and |tx_hp_ctx| are for
|
||||||
* If they have already been set, they are overwritten.
|
* encrypting outgoing packets and are the same length with the
|
||||||
|
* decryption counterpart . If they have already been set, they are
|
||||||
|
* overwritten.
|
||||||
|
*
|
||||||
|
* If this function succeeds, |conn| takes ownership of |rx_aead_ctx|,
|
||||||
|
* |rx_hp_ctx|, |tx_aead_ctx|, and |tx_hp_ctx|.
|
||||||
|
* :type:`ngtcp2_delete_crypto_aead_ctx` and
|
||||||
|
* :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
|
||||||
|
* these objects when they are no longer used. If this function
|
||||||
|
* fails, the caller is responsible to delete them.
|
||||||
*
|
*
|
||||||
* After receiving Retry packet, the DCID most likely changes. In
|
* After receiving Retry packet, the DCID most likely changes. In
|
||||||
* that case, client application must generate these keying materials
|
* that case, client application must generate these keying materials
|
||||||
@ -2001,49 +2118,62 @@ NGTCP2_EXTERN int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn);
|
|||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int ngtcp2_conn_install_initial_key(
|
NGTCP2_EXTERN int ngtcp2_conn_install_initial_key(
|
||||||
ngtcp2_conn *conn, const uint8_t *rx_key, const uint8_t *rx_iv,
|
ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *rx_aead_ctx,
|
||||||
const uint8_t *rx_hp_key, const uint8_t *tx_key, const uint8_t *tx_iv,
|
const uint8_t *rx_iv, const ngtcp2_crypto_cipher_ctx *rx_hp_ctx,
|
||||||
const uint8_t *tx_hp_key, size_t keylen, size_t ivlen);
|
const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv,
|
||||||
|
const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `ngtcp2_conn_install_rx_handshake_key` installs packet protection
|
* `ngtcp2_conn_install_rx_handshake_key` installs packet protection
|
||||||
* keying materials for decrypting incoming Handshake packets. |key|
|
* keying materials for decrypting incoming Handshake packets.
|
||||||
* of length |keylen|, IV |iv| of length |ivlen|, and packet header
|
* |aead_ctx| is AEAD cipher context object which must be initialized
|
||||||
* protection key |hp_key| of length |keylen| to decrypt incoming
|
* with decryption key, IV |iv| of length |ivlen|, and packet header
|
||||||
|
* protection cipher context object |hp_ctx| to decrypt incoming
|
||||||
* Handshake packets.
|
* Handshake packets.
|
||||||
*
|
*
|
||||||
|
* If this function succeeds, |conn| takes ownership of |aead_ctx|,
|
||||||
|
* and |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
|
||||||
|
* :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
|
||||||
|
* these objects when they are no longer used. If this function
|
||||||
|
* fails, the caller is responsible to delete them.
|
||||||
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :enum:`NGTCP2_ERR_NOMEM`
|
* :enum:`NGTCP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int
|
NGTCP2_EXTERN int ngtcp2_conn_install_rx_handshake_key(
|
||||||
ngtcp2_conn_install_rx_handshake_key(ngtcp2_conn *conn, const uint8_t *key,
|
ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *iv, const uint8_t *hp_key,
|
const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx);
|
||||||
size_t keylen, size_t ivlen);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `ngtcp2_conn_install_tx_handshake_key` installs packet protection
|
* `ngtcp2_conn_install_tx_handshake_key` installs packet protection
|
||||||
* keying materials for encrypting outgoing Handshake packets. |key|
|
* keying materials for encrypting outgoing Handshake packets.
|
||||||
* of length |keylen|, IV |iv| of length |ivlen|, and packet header
|
* |aead_ctx| is AEAD cipher context object which must be initialized
|
||||||
* protection key |hp_key| of length |keylen| to encrypt outgoing
|
* with encryption key, IV |iv| of length |ivlen|, and packet header
|
||||||
|
* protection cipher context object |hp_ctx| to encrypt outgoing
|
||||||
* Handshake packets.
|
* Handshake packets.
|
||||||
*
|
*
|
||||||
|
* If this function succeeds, |conn| takes ownership of |aead_ctx| and
|
||||||
|
* |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
|
||||||
|
* :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
|
||||||
|
* these objects when they are no longer used. If this function
|
||||||
|
* fails, the caller is responsible to delete them.
|
||||||
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :enum:`NGTCP2_ERR_NOMEM`
|
* :enum:`NGTCP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int
|
NGTCP2_EXTERN int ngtcp2_conn_install_tx_handshake_key(
|
||||||
ngtcp2_conn_install_tx_handshake_key(ngtcp2_conn *conn, const uint8_t *key,
|
ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *iv, const uint8_t *hp_key,
|
const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx);
|
||||||
size_t keylen, size_t ivlen);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -2068,10 +2198,16 @@ NGTCP2_EXTERN size_t ngtcp2_conn_get_aead_overhead(ngtcp2_conn *conn);
|
|||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `ngtcp2_conn_install_early_key` installs packet protection key
|
* `ngtcp2_conn_install_early_key` installs packet protection AEAD
|
||||||
* |key| of length |keylen|, IV |iv| of length |ivlen|, and packet
|
* cipher context object |aead_ctx|, IV |iv| of length |ivlen|, and
|
||||||
* header protection key |hp_key| of length |keylen| to encrypt (for
|
* packet header protection cipher context object |hp_ctx| to encrypt
|
||||||
* client)or decrypt (for server) 0RTT packets.
|
* (for client) or decrypt (for server) 0RTT packets.
|
||||||
|
*
|
||||||
|
* If this function succeeds, |conn| takes ownership of |aead_ctx| and
|
||||||
|
* |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
|
||||||
|
* :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
|
||||||
|
* these objects when they are no longer used. If this function
|
||||||
|
* fails, the caller is responsible to delete them.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
@ -2079,11 +2215,9 @@ NGTCP2_EXTERN size_t ngtcp2_conn_get_aead_overhead(ngtcp2_conn *conn);
|
|||||||
* :enum:`NGTCP2_ERR_NOMEM`
|
* :enum:`NGTCP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int ngtcp2_conn_install_early_key(ngtcp2_conn *conn,
|
NGTCP2_EXTERN int ngtcp2_conn_install_early_key(
|
||||||
const uint8_t *key,
|
ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *iv,
|
const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx);
|
||||||
const uint8_t *hp_key,
|
|
||||||
size_t keylen, size_t ivlen);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -2091,9 +2225,16 @@ NGTCP2_EXTERN int ngtcp2_conn_install_early_key(ngtcp2_conn *conn,
|
|||||||
* `ngtcp2_conn_install_rx_key` installs packet protection keying
|
* `ngtcp2_conn_install_rx_key` installs packet protection keying
|
||||||
* materials for decrypting Short packets. |secret| of length
|
* materials for decrypting Short packets. |secret| of length
|
||||||
* |secretlen| is the decryption secret which is used to derive keying
|
* |secretlen| is the decryption secret which is used to derive keying
|
||||||
* materials passed to this function. |key| of length |keylen|, IV
|
* materials passed to this function. |aead_ctx| is AEAD cipher
|
||||||
* |iv| of length |ivlen|, and packet header protection key |hp_key|
|
* context object which must be initialized with decryption key, IV
|
||||||
* of length |keylen| to decrypt incoming Short packets.
|
* |iv| of length |ivlen|, and packet header protection cipher context
|
||||||
|
* object |hp_ctx| to decrypt incoming Short packets.
|
||||||
|
*
|
||||||
|
* If this function succeeds, |conn| takes ownership of |aead_ctx| and
|
||||||
|
* |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
|
||||||
|
* :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
|
||||||
|
* these objects when they are no longer used. If this function
|
||||||
|
* fails, the caller is responsible to delete them.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
@ -2101,11 +2242,10 @@ NGTCP2_EXTERN int ngtcp2_conn_install_early_key(ngtcp2_conn *conn,
|
|||||||
* :enum:`NGTCP2_ERR_NOMEM`
|
* :enum:`NGTCP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int
|
NGTCP2_EXTERN int ngtcp2_conn_install_rx_key(
|
||||||
ngtcp2_conn_install_rx_key(ngtcp2_conn *conn, const uint8_t *secret,
|
ngtcp2_conn *conn, const uint8_t *secret, size_t secretlen,
|
||||||
const uint8_t *key, const uint8_t *iv,
|
const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen,
|
||||||
const uint8_t *hp_key, size_t secretlen,
|
const ngtcp2_crypto_cipher_ctx *hp_ctx);
|
||||||
size_t keylen, size_t ivlen);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -2113,9 +2253,16 @@ ngtcp2_conn_install_rx_key(ngtcp2_conn *conn, const uint8_t *secret,
|
|||||||
* `ngtcp2_conn_install_tx_key` installs packet protection keying
|
* `ngtcp2_conn_install_tx_key` installs packet protection keying
|
||||||
* materials for encrypting Short packets. |secret| of length
|
* materials for encrypting Short packets. |secret| of length
|
||||||
* |secretlen| is the encryption secret which is used to derive keying
|
* |secretlen| is the encryption secret which is used to derive keying
|
||||||
* materials passed to this function. |key| of length |keylen|, IV
|
* materials passed to this function. |aead_ctx| is AEAD cipher
|
||||||
* |iv| of length |ivlen|, and packet header protection key |hp_key|
|
* context object which must be initialized with encryption key, IV
|
||||||
* of length |keylen| to encrypt outgoing Short packets.
|
* |iv| of length |ivlen|, and packet header protection cipher context
|
||||||
|
* object |hp_ctx| to encrypt outgoing Short packets.
|
||||||
|
*
|
||||||
|
* If this function succeeds, |conn| takes ownership of |aead_ctx| and
|
||||||
|
* |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
|
||||||
|
* :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
|
||||||
|
* these objects when they are no longer used. If this function
|
||||||
|
* fails, the caller is responsible to delete them.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
@ -2123,11 +2270,10 @@ ngtcp2_conn_install_rx_key(ngtcp2_conn *conn, const uint8_t *secret,
|
|||||||
* :enum:`NGTCP2_ERR_NOMEM`
|
* :enum:`NGTCP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int
|
NGTCP2_EXTERN int ngtcp2_conn_install_tx_key(
|
||||||
ngtcp2_conn_install_tx_key(ngtcp2_conn *conn, const uint8_t *secret,
|
ngtcp2_conn *conn, const uint8_t *secret, size_t secretlen,
|
||||||
const uint8_t *key, const uint8_t *iv,
|
const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen,
|
||||||
const uint8_t *hp_key, size_t secretlen,
|
const ngtcp2_crypto_cipher_ctx *hp_ctx);
|
||||||
size_t keylen, size_t ivlen);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -2285,6 +2431,27 @@ ngtcp2_conn_get_remote_transport_params(ngtcp2_conn *conn,
|
|||||||
NGTCP2_EXTERN void ngtcp2_conn_set_early_remote_transport_params(
|
NGTCP2_EXTERN void ngtcp2_conn_set_early_remote_transport_params(
|
||||||
ngtcp2_conn *conn, const ngtcp2_transport_params *params);
|
ngtcp2_conn *conn, const ngtcp2_transport_params *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_conn_set_local_transport_params` sets the local transport
|
||||||
|
* parameters |params|. This function can only be called by server.
|
||||||
|
* Although the local transport parameters are passed to
|
||||||
|
* `ngtcp2_conn_server_new`, server might want to update them after
|
||||||
|
* ALPN is chosen. In that case, server can update the transport
|
||||||
|
* parameter with this function. Server must call this function
|
||||||
|
* before calling `ngtcp2_conn_install_tx_handshake_key`.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* :enum:`NGTCP2_ERR_INVALID_STATE`
|
||||||
|
* `ngtcp2_conn_install_tx_handshake_key` has been called.
|
||||||
|
*/
|
||||||
|
NGTCP2_EXTERN int
|
||||||
|
ngtcp2_conn_set_local_transport_params(ngtcp2_conn *conn,
|
||||||
|
const ngtcp2_transport_params *params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
@ -2483,8 +2650,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
|
|||||||
* packet is nearly full and the library decided to make a complete
|
* packet is nearly full and the library decided to make a complete
|
||||||
* packet. In this case, |*pdatalen| == -1 is asserted.
|
* packet. In this case, |*pdatalen| == -1 is asserted.
|
||||||
*
|
*
|
||||||
* - The function returns :enum:`NGTCP2_ERR_WRITE_STREAM_MORE`. In
|
* - The function returns :enum:`NGTCP2_ERR_WRITE_MORE`. In this
|
||||||
* this case, |*pdatalen| >= 0 is asserted. This indicates that
|
* case, |*pdatalen| >= 0 is asserted. This indicates that
|
||||||
* application can call this function with different stream data to
|
* application can call this function with different stream data to
|
||||||
* pack them into the same packet. Application has to specify the
|
* pack them into the same packet. Application has to specify the
|
||||||
* same |conn|, |path|, |dest|, |destlen|, |pdatalen|, and |ts|
|
* same |conn|, |path|, |dest|, |destlen|, |pdatalen|, and |ts|
|
||||||
@ -2497,14 +2664,14 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
|
|||||||
* - The other error might be returned just like without
|
* - The other error might be returned just like without
|
||||||
* :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE`.
|
* :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE`.
|
||||||
*
|
*
|
||||||
* When application sees :enum:`NGTCP2_ERR_WRITE_STREAM_MORE`, it must
|
* When application sees :enum:`NGTCP2_ERR_WRITE_MORE`, it must not
|
||||||
* not call other ngtcp2 API functions (application can still call
|
* call other ngtcp2 API functions (application can still call
|
||||||
* `ngtcp2_conn_write_connection_close` or
|
* `ngtcp2_conn_write_connection_close` or
|
||||||
* `ngtcp2_conn_write_application_close` to handle error from this
|
* `ngtcp2_conn_write_application_close` to handle error from this
|
||||||
* function). Just keep calling `ngtcp2_conn_writev_stream` or
|
* function). Just keep calling `ngtcp2_conn_writev_stream` or
|
||||||
* `ngtcp2_conn_write_pkt` until it returns a positive number (which
|
* `ngtcp2_conn_write_pkt` until it returns a positive number (which
|
||||||
* indicates a complete packet is ready). If |*pdatalen| >= 0, the
|
* indicates a complete packet is ready). If |*pdatalen| >= 0, the
|
||||||
* function always return :enum:`NGTCP2_ERR_WRITE_STREAM_MORE`.
|
* function always return :enum:`NGTCP2_ERR_WRITE_MORE`.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it cannot write any frame because buffer
|
* This function returns 0 if it cannot write any frame because buffer
|
||||||
* is too small, or packet is congestion limited. Application should
|
* is too small, or packet is congestion limited. Application should
|
||||||
@ -2528,7 +2695,7 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
|
|||||||
* User callback failed
|
* User callback failed
|
||||||
* :enum:`NGTCP2_ERR_STREAM_DATA_BLOCKED`
|
* :enum:`NGTCP2_ERR_STREAM_DATA_BLOCKED`
|
||||||
* Stream is blocked because of flow control.
|
* Stream is blocked because of flow control.
|
||||||
* :enum:`NGTCP2_ERR_WRITE_STREAM_MORE`
|
* :enum:`NGTCP2_ERR_WRITE_MORE`
|
||||||
* (Only when :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE` is specified)
|
* (Only when :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE` is specified)
|
||||||
* Application can call this function to pack more stream data
|
* Application can call this function to pack more stream data
|
||||||
* into the same packet. See above to know how it works.
|
* into the same packet. See above to know how it works.
|
||||||
@ -2549,8 +2716,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream(
|
|||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `ngtcp2_conn_write_connection_close` writes a packet which contains
|
* `ngtcp2_conn_write_connection_close` writes a packet which contains
|
||||||
* a CONNECTION_CLOSE frame in the buffer pointed by |dest| whose
|
* a CONNECTION_CLOSE frame (type 0x1c) in the buffer pointed by
|
||||||
* capacity is |datalen|.
|
* |dest| whose capacity is |datalen|.
|
||||||
*
|
*
|
||||||
* If |path| is not NULL, this function stores the network path with
|
* If |path| is not NULL, this function stores the network path with
|
||||||
* which the packet should be sent. Each addr field must point to the
|
* which the packet should be sent. Each addr field must point to the
|
||||||
@ -2584,8 +2751,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_connection_close(
|
|||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `ngtcp2_conn_write_application_close` writes a packet which
|
* `ngtcp2_conn_write_application_close` writes a packet which
|
||||||
* contains a APPLICATION_CLOSE frame in the buffer pointed by |dest|
|
* contains a CONNECTION_CLOSE frame (type 0x1d) in the buffer pointed
|
||||||
* whose capacity is |datalen|.
|
* by |dest| whose capacity is |datalen|.
|
||||||
*
|
*
|
||||||
* If |path| is not NULL, this function stores the network path with
|
* If |path| is not NULL, this function stores the network path with
|
||||||
* which the packet should be sent. Each addr field must point to the
|
* which the packet should be sent. Each addr field must point to the
|
||||||
@ -2593,6 +2760,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_connection_close(
|
|||||||
* sockaddr_storage)`` is enough. The assignment might not be done if
|
* sockaddr_storage)`` is enough. The assignment might not be done if
|
||||||
* nothing is written to |dest|.
|
* nothing is written to |dest|.
|
||||||
*
|
*
|
||||||
|
* If handshake has not been confirmed yet, CONNECTION_CLOSE (type
|
||||||
|
* 0x1c) with error code :macro:`NGTCP2_APPLICATION_ERROR` is written
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
* This function must not be called from inside the callback
|
* This function must not be called from inside the callback
|
||||||
* functions.
|
* functions.
|
||||||
*
|
*
|
||||||
@ -2605,7 +2776,7 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_connection_close(
|
|||||||
* :enum:`NGTCP2_ERR_NOBUF`
|
* :enum:`NGTCP2_ERR_NOBUF`
|
||||||
* Buffer is too small
|
* Buffer is too small
|
||||||
* :enum:`NGTCP2_ERR_INVALID_STATE`
|
* :enum:`NGTCP2_ERR_INVALID_STATE`
|
||||||
* The current state does not allow sending APPLICATION_CLOSE.
|
* The current state does not allow sending CONNECTION_CLOSE.
|
||||||
* :enum:`NGTCP2_ERR_PKT_NUM_EXHAUSTED`
|
* :enum:`NGTCP2_ERR_PKT_NUM_EXHAUSTED`
|
||||||
* Packet number is exhausted, and cannot send any more packet.
|
* Packet number is exhausted, and cannot send any more packet.
|
||||||
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE`
|
* :enum:`NGTCP2_ERR_CALLBACK_FAILURE`
|
||||||
@ -2974,13 +3145,21 @@ NGTCP2_EXTERN void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn,
|
|||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `ngtcp2_conn_set_retry_aead` sets |aead| for Retry integrity tag
|
* `ngtcp2_conn_set_retry_aead` sets |aead| and |aead_ctx| for Retry
|
||||||
* verification. It must be AEAD_AES_128_GCM. This function must be
|
* integrity tag verification. |aead| must be AEAD_AES_128_GCM.
|
||||||
* called if |conn| is initialized as client. Server does not verify
|
* |aead_ctx| must be initialized with :macro:`NGTCP2_RETRY_KEY` as
|
||||||
* the tag and has no need to call this function.
|
* encryption key. This function must be called if |conn| is
|
||||||
|
* initialized as client. Server does not verify the tag and has no
|
||||||
|
* need to call this function.
|
||||||
|
*
|
||||||
|
* If this function succeeds, |conn| takes ownership of |aead_ctx|.
|
||||||
|
* :type:`ngtcp2_delete_crypto_aead_ctx` will be called to delete this
|
||||||
|
* object when it is no longer used. If this function fails, the
|
||||||
|
* caller is responsible to delete it.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN void ngtcp2_conn_set_retry_aead(ngtcp2_conn *conn,
|
NGTCP2_EXTERN void
|
||||||
const ngtcp2_crypto_aead *aead);
|
ngtcp2_conn_set_retry_aead(ngtcp2_conn *conn, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -3033,6 +3212,30 @@ NGTCP2_EXTERN int ngtcp2_conn_is_local_stream(ngtcp2_conn *conn,
|
|||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN int ngtcp2_conn_is_server(ngtcp2_conn *conn);
|
NGTCP2_EXTERN int ngtcp2_conn_is_server(ngtcp2_conn *conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_conn_after_retry` returns nonzero if |conn| as a client has
|
||||||
|
* received Retry packet from server and successfully validated it.
|
||||||
|
*/
|
||||||
|
NGTCP2_EXTERN int ngtcp2_conn_after_retry(ngtcp2_conn *conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* `ngtcp2_conn_set_stream_user_data` sets |stream_user_data| to the
|
||||||
|
* stream identified by |stream_id|.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* :enum:`NGTCP2_ERR_STREAM_NOT_FOUND`
|
||||||
|
* Stream does not exist
|
||||||
|
*/
|
||||||
|
NGTCP2_EXTERN int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn,
|
||||||
|
int64_t stream_id,
|
||||||
|
void *stream_user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
@ -3061,7 +3264,8 @@ NGTCP2_EXTERN uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr);
|
|||||||
* `ngtcp2_addr_init` initializes |dest| with the given arguments and
|
* `ngtcp2_addr_init` initializes |dest| with the given arguments and
|
||||||
* returns |dest|.
|
* returns |dest|.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const void *addr,
|
NGTCP2_EXTERN ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest,
|
||||||
|
const struct sockaddr *addr,
|
||||||
size_t addrlen, void *user_data);
|
size_t addrlen, void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3070,11 +3274,13 @@ NGTCP2_EXTERN ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const void *addr,
|
|||||||
* `ngtcp2_path_storage_init` initializes |ps| with the given
|
* `ngtcp2_path_storage_init` initializes |ps| with the given
|
||||||
* arguments. This function copies |local_addr| and |remote_addr|.
|
* arguments. This function copies |local_addr| and |remote_addr|.
|
||||||
*/
|
*/
|
||||||
NGTCP2_EXTERN void
|
NGTCP2_EXTERN void ngtcp2_path_storage_init(ngtcp2_path_storage *ps,
|
||||||
ngtcp2_path_storage_init(ngtcp2_path_storage *ps, const void *local_addr,
|
const struct sockaddr *local_addr,
|
||||||
size_t local_addrlen, void *local_user_data,
|
size_t local_addrlen,
|
||||||
const void *remote_addr, size_t remote_addrlen,
|
void *local_user_data,
|
||||||
void *remote_user_data);
|
const struct sockaddr *remote_addr,
|
||||||
|
size_t remote_addrlen,
|
||||||
|
void *remote_user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
@ -3092,6 +3298,7 @@ NGTCP2_EXTERN void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps);
|
|||||||
* default value to the following fields:
|
* default value to the following fields:
|
||||||
*
|
*
|
||||||
* * cc_algo = NGTCP2_CC_ALGO_CUBIC
|
* * cc_algo = NGTCP2_CC_ALGO_CUBIC
|
||||||
|
* * initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT
|
||||||
* * transport_params.max_udp_payload_size = NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE
|
* * transport_params.max_udp_payload_size = NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE
|
||||||
* * transport_params.ack_delay_component = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT
|
* * transport_params.ack_delay_component = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT
|
||||||
* * transport_params.max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY
|
* * transport_params.max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY
|
||||||
|
2
deps/ngtcp2/lib/ngtcp2_acktr.c
vendored
2
deps/ngtcp2/lib/ngtcp2_acktr.c
vendored
@ -297,8 +297,6 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr) {
|
void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr) {
|
||||||
|
43
deps/ngtcp2/lib/ngtcp2_addr.c
vendored
43
deps/ngtcp2/lib/ngtcp2_addr.c
vendored
@ -25,11 +25,24 @@
|
|||||||
#include "ngtcp2_addr.h"
|
#include "ngtcp2_addr.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const void *addr,
|
#ifdef WIN32
|
||||||
|
# include <winsock2.h>
|
||||||
|
# include <ws2tcpip.h>
|
||||||
|
#else
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include <netinet/ip.h>
|
||||||
|
# include <netinet/tcp.h>
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const struct sockaddr *addr,
|
||||||
size_t addrlen, void *user_data) {
|
size_t addrlen, void *user_data) {
|
||||||
dest->addrlen = addrlen;
|
dest->addrlen = addrlen;
|
||||||
dest->addr = (uint8_t *)addr;
|
dest->addr = (struct sockaddr *)addr;
|
||||||
dest->user_data = user_data;
|
dest->user_data = user_data;
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
@ -42,7 +55,7 @@ void ngtcp2_addr_copy(ngtcp2_addr *dest, const ngtcp2_addr *src) {
|
|||||||
dest->user_data = src->user_data;
|
dest->user_data = src->user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_addr_copy_byte(ngtcp2_addr *dest, const void *addr,
|
void ngtcp2_addr_copy_byte(ngtcp2_addr *dest, const struct sockaddr *addr,
|
||||||
size_t addrlen) {
|
size_t addrlen) {
|
||||||
dest->addrlen = addrlen;
|
dest->addrlen = addrlen;
|
||||||
if (addrlen) {
|
if (addrlen) {
|
||||||
@ -50,8 +63,30 @@ void ngtcp2_addr_copy_byte(ngtcp2_addr *dest, const void *addr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sockaddr_eq(const struct sockaddr *a, const struct sockaddr *b) {
|
||||||
|
assert(a->sa_family == b->sa_family);
|
||||||
|
|
||||||
|
switch (a->sa_family) {
|
||||||
|
case AF_INET: {
|
||||||
|
const struct sockaddr_in *ai = (const struct sockaddr_in *)(void *)a,
|
||||||
|
*bi = (const struct sockaddr_in *)(void *)b;
|
||||||
|
return ai->sin_port == bi->sin_port &&
|
||||||
|
memcmp(&ai->sin_addr, &bi->sin_addr, sizeof(ai->sin_addr)) == 0;
|
||||||
|
}
|
||||||
|
case AF_INET6: {
|
||||||
|
const struct sockaddr_in6 *ai = (const struct sockaddr_in6 *)(void *)a,
|
||||||
|
*bi = (const struct sockaddr_in6 *)(void *)b;
|
||||||
|
return ai->sin6_port == bi->sin6_port &&
|
||||||
|
memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr)) == 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ngtcp2_addr_eq(const ngtcp2_addr *a, const ngtcp2_addr *b) {
|
int ngtcp2_addr_eq(const ngtcp2_addr *a, const ngtcp2_addr *b) {
|
||||||
return a->addrlen == b->addrlen && memcmp(a->addr, b->addr, a->addrlen) == 0;
|
return a->addr->sa_family == b->addr->sa_family &&
|
||||||
|
sockaddr_eq(a->addr, b->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_addr_empty(const ngtcp2_addr *addr) { return addr->addrlen == 0; }
|
int ngtcp2_addr_empty(const ngtcp2_addr *addr) { return addr->addrlen == 0; }
|
||||||
|
3
deps/ngtcp2/lib/ngtcp2_addr.h
vendored
3
deps/ngtcp2/lib/ngtcp2_addr.h
vendored
@ -44,7 +44,8 @@ void ngtcp2_addr_copy(ngtcp2_addr *dest, const ngtcp2_addr *src);
|
|||||||
* |addrlen|. This function assumes that dest->addr points to a
|
* |addrlen|. This function assumes that dest->addr points to a
|
||||||
* buffer which have sufficient size to store the copy.
|
* buffer which have sufficient size to store the copy.
|
||||||
*/
|
*/
|
||||||
void ngtcp2_addr_copy_byte(ngtcp2_addr *dest, const void *addr, size_t addrlen);
|
void ngtcp2_addr_copy_byte(ngtcp2_addr *dest, const struct sockaddr *addr,
|
||||||
|
size_t addrlen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_addr_eq returns nonzero if |a| equals |b|.
|
* ngtcp2_addr_eq returns nonzero if |a| equals |b|.
|
||||||
|
61
deps/ngtcp2/lib/ngtcp2_cc.c
vendored
61
deps/ngtcp2/lib/ngtcp2_cc.c
vendored
@ -26,24 +26,15 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# include <intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ngtcp2_log.h"
|
#include "ngtcp2_log.h"
|
||||||
#include "ngtcp2_macro.h"
|
#include "ngtcp2_macro.h"
|
||||||
#include "ngtcp2_mem.h"
|
#include "ngtcp2_mem.h"
|
||||||
#include "ngtcp2_rcvry.h"
|
#include "ngtcp2_rcvry.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <intrin.h>
|
|
||||||
static inline int __builtin_clzll(unsigned long long x) {
|
|
||||||
#if defined(_WIN64) || defined(_LP64)
|
|
||||||
return (int)__lzcnt64(x);
|
|
||||||
#else
|
|
||||||
// TODO(@jasnell): Determine if there's an alternative available for x86
|
|
||||||
assert(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) {
|
uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) {
|
||||||
uint64_t n = 2 * max_udp_payload_size;
|
uint64_t n = 2 * max_udp_payload_size;
|
||||||
n = ngtcp2_max(n, 14720);
|
n = ngtcp2_max(n, 14720);
|
||||||
@ -245,16 +236,35 @@ void ngtcp2_cc_cubic_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) {
|
|||||||
static uint64_t ngtcp2_cbrt(uint64_t n) {
|
static uint64_t ngtcp2_cbrt(uint64_t n) {
|
||||||
int d;
|
int d;
|
||||||
uint64_t a;
|
uint64_t a;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# if defined(_M_X64)
|
||||||
|
d = (int)__lzcnt64(n);
|
||||||
|
# elif defined(_M_ARM64)
|
||||||
|
{
|
||||||
|
unsigned long index;
|
||||||
|
d = sizeof(uint64_t) * CHAR_BIT;
|
||||||
|
if (_BitScanReverse64(&index, n)) {
|
||||||
|
d = d - 1 - index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
if ((n >> 32) != 0) {
|
||||||
|
d = __lzcnt((unsigned int)(n >> 32));
|
||||||
|
} else {
|
||||||
|
d = 32 + __lzcnt((unsigned int)n);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
d = __builtin_clzll(n);
|
d = __builtin_clzll(n);
|
||||||
|
#endif
|
||||||
a = 1ULL << ((64 - d) / 3 + 1);
|
a = 1ULL << ((64 - d) / 3 + 1);
|
||||||
|
|
||||||
for (i = 0; a * a * a > n; ++i) {
|
for (; a * a * a > n;) {
|
||||||
a = (2 * a + n / a / a) / 3;
|
a = (2 * a + n / a / a) / 3;
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
@ -274,6 +284,7 @@ void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
|
|||||||
uint64_t target;
|
uint64_t target;
|
||||||
uint64_t tx, kx, time_delta, delta;
|
uint64_t tx, kx, time_delta, delta;
|
||||||
uint64_t add, tcp_add;
|
uint64_t add, tcp_add;
|
||||||
|
uint64_t m;
|
||||||
|
|
||||||
if (pkt->pktns_id == NGTCP2_PKTNS_ID_APP && cc->window_end != -1 &&
|
if (pkt->pktns_id == NGTCP2_PKTNS_ID_APP && cc->window_end != -1 &&
|
||||||
cc->window_end <= pkt->pkt_num) {
|
cc->window_end <= pkt->pkt_num) {
|
||||||
@ -339,10 +350,12 @@ void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
|
|||||||
"cubic-ca epoch_start=%" PRIu64 " k=%" PRIu64
|
"cubic-ca epoch_start=%" PRIu64 " k=%" PRIu64
|
||||||
" origin_point=%" PRIu64,
|
" origin_point=%" PRIu64,
|
||||||
cc->epoch_start, cc->k, cc->origin_point);
|
cc->epoch_start, cc->k, cc->origin_point);
|
||||||
|
|
||||||
|
cc->pending_add = 0;
|
||||||
|
cc->pending_w_add = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
min_rtt = cstat->min_rtt == UINT64_MAX ? NGTCP2_DEFAULT_INITIAL_RTT
|
min_rtt = cstat->min_rtt == UINT64_MAX ? cstat->initial_rtt : cstat->min_rtt;
|
||||||
: cstat->min_rtt;
|
|
||||||
|
|
||||||
t = ts + min_rtt - cc->epoch_start;
|
t = ts + min_rtt - cc->epoch_start;
|
||||||
|
|
||||||
@ -365,13 +378,19 @@ void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (target > cstat->cwnd) {
|
if (target > cstat->cwnd) {
|
||||||
add = cstat->max_udp_payload_size * (target - cstat->cwnd) / cstat->cwnd;
|
m = cc->pending_add + cstat->max_udp_payload_size * (target - cstat->cwnd);
|
||||||
|
add = m / cstat->cwnd;
|
||||||
|
cc->pending_add = m % cstat->cwnd;
|
||||||
} else {
|
} else {
|
||||||
/* TODO too small, no increment at all */
|
m = cc->pending_add + cstat->max_udp_payload_size;
|
||||||
add = cstat->max_udp_payload_size / (100 * cstat->cwnd);
|
add = m / (100 * cstat->cwnd);
|
||||||
|
cc->pending_add = m % (100 * cstat->cwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
cc->w_tcp += cstat->max_udp_payload_size * pkt->pktlen * 9 / 17 / cstat->cwnd;
|
m = cc->pending_w_add + cstat->max_udp_payload_size * pkt->pktlen;
|
||||||
|
|
||||||
|
cc->w_tcp += m / cstat->cwnd;
|
||||||
|
cc->pending_w_add = m % cstat->cwnd;
|
||||||
|
|
||||||
if (cc->w_tcp > cstat->cwnd) {
|
if (cc->w_tcp > cstat->cwnd) {
|
||||||
tcp_add =
|
tcp_add =
|
||||||
|
2
deps/ngtcp2/lib/ngtcp2_cc.h
vendored
2
deps/ngtcp2/lib/ngtcp2_cc.h
vendored
@ -95,6 +95,8 @@ typedef struct ngtcp2_cubic_cc {
|
|||||||
uint64_t current_round_min_rtt;
|
uint64_t current_round_min_rtt;
|
||||||
uint64_t last_round_min_rtt;
|
uint64_t last_round_min_rtt;
|
||||||
int64_t window_end;
|
int64_t window_end;
|
||||||
|
uint64_t pending_add;
|
||||||
|
uint64_t pending_w_add;
|
||||||
} ngtcp2_cubic_cc;
|
} ngtcp2_cubic_cc;
|
||||||
|
|
||||||
int ngtcp2_cc_cubic_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
|
int ngtcp2_cc_cubic_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
|
||||||
|
1
deps/ngtcp2/lib/ngtcp2_cid.c
vendored
1
deps/ngtcp2/lib/ngtcp2_cid.c
vendored
@ -105,7 +105,6 @@ void ngtcp2_dcid_copy_no_path(ngtcp2_dcid *dest, const ngtcp2_dcid *src) {
|
|||||||
|
|
||||||
int ngtcp2_dcid_verify_uniqueness(ngtcp2_dcid *dcid, uint64_t seq,
|
int ngtcp2_dcid_verify_uniqueness(ngtcp2_dcid *dcid, uint64_t seq,
|
||||||
const ngtcp2_cid *cid, const uint8_t *token) {
|
const ngtcp2_cid *cid, const uint8_t *token) {
|
||||||
|
|
||||||
if (dcid->seq == seq) {
|
if (dcid->seq == seq) {
|
||||||
return ngtcp2_cid_eq(&dcid->cid, cid) &&
|
return ngtcp2_cid_eq(&dcid->cid, cid) &&
|
||||||
memcmp(dcid->token, token,
|
memcmp(dcid->token, token,
|
||||||
|
1554
deps/ngtcp2/lib/ngtcp2_conn.c
vendored
1554
deps/ngtcp2/lib/ngtcp2_conn.c
vendored
File diff suppressed because it is too large
Load Diff
101
deps/ngtcp2/lib/ngtcp2_conn.h
vendored
101
deps/ngtcp2/lib/ngtcp2_conn.h
vendored
@ -106,7 +106,7 @@ typedef enum {
|
|||||||
|
|
||||||
/* NGTCP2_MAX_NON_ACK_TX_PKT is the maximum number of continuous non
|
/* NGTCP2_MAX_NON_ACK_TX_PKT is the maximum number of continuous non
|
||||||
ACK-eliciting packets. */
|
ACK-eliciting packets. */
|
||||||
#define NGTCP2_MAX_NON_ACK_TX_PKT 10
|
#define NGTCP2_MAX_NON_ACK_TX_PKT 3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_max_frame is defined so that it covers the largest ACK
|
* ngtcp2_max_frame is defined so that it covers the largest ACK
|
||||||
@ -186,7 +186,7 @@ typedef struct {
|
|||||||
uint8_t pkt_type;
|
uint8_t pkt_type;
|
||||||
} ngtcp2_crypto_data;
|
} ngtcp2_crypto_data;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct ngtcp2_pktns {
|
||||||
struct {
|
struct {
|
||||||
/* last_pkt_num is the packet number which the local endpoint sent
|
/* last_pkt_num is the packet number which the local endpoint sent
|
||||||
last time.*/
|
last time.*/
|
||||||
@ -203,6 +203,9 @@ typedef struct {
|
|||||||
ngtcp2_gaptr pngap;
|
ngtcp2_gaptr pngap;
|
||||||
/* max_pkt_num is the largest packet number received so far. */
|
/* max_pkt_num is the largest packet number received so far. */
|
||||||
int64_t max_pkt_num;
|
int64_t max_pkt_num;
|
||||||
|
/* max_pkt_ts is the timestamp when max_pkt_num packet is
|
||||||
|
received. */
|
||||||
|
ngtcp2_tstamp max_pkt_ts;
|
||||||
/*
|
/*
|
||||||
* buffed_pkts is buffered packets which cannot be decrypted with
|
* buffed_pkts is buffered packets which cannot be decrypted with
|
||||||
* the current encryption level.
|
* the current encryption level.
|
||||||
@ -236,16 +239,16 @@ typedef struct {
|
|||||||
/* ckm is a cryptographic key, and iv to encrypt outgoing
|
/* ckm is a cryptographic key, and iv to encrypt outgoing
|
||||||
packets. */
|
packets. */
|
||||||
ngtcp2_crypto_km *ckm;
|
ngtcp2_crypto_km *ckm;
|
||||||
/* hp_key is header protection key. */
|
/* hp_ctx is cipher context for packet header protection. */
|
||||||
ngtcp2_vec *hp_key;
|
ngtcp2_crypto_cipher_ctx hp_ctx;
|
||||||
} tx;
|
} tx;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* ckm is a cryptographic key, and iv to decrypt incoming
|
/* ckm is a cryptographic key, and iv to decrypt incoming
|
||||||
packets. */
|
packets. */
|
||||||
ngtcp2_crypto_km *ckm;
|
ngtcp2_crypto_km *ckm;
|
||||||
/* hp_key is header protection key. */
|
/* hp_ctx is cipher context for packet header protection. */
|
||||||
ngtcp2_vec *hp_key;
|
ngtcp2_crypto_cipher_ctx hp_ctx;
|
||||||
} rx;
|
} rx;
|
||||||
|
|
||||||
ngtcp2_strm strm;
|
ngtcp2_strm strm;
|
||||||
@ -286,7 +289,10 @@ struct ngtcp2_conn {
|
|||||||
/* retired is a set of CID retired by local endpoint. Keep them
|
/* retired is a set of CID retired by local endpoint. Keep them
|
||||||
in 3*PTO to catch packets in flight along the old path. */
|
in 3*PTO to catch packets in flight along the old path. */
|
||||||
ngtcp2_ringbuf retired;
|
ngtcp2_ringbuf retired;
|
||||||
/* retire_prior_to is the larget retire_prior_to received so
|
/* seqgap tracks received sequence numbers in order to ignore
|
||||||
|
retransmitted duplicated NEW_CONNECTION_ID frame. */
|
||||||
|
ngtcp2_gaptr seqgap;
|
||||||
|
/* retire_prior_to is the largest retire_prior_to received so
|
||||||
far. */
|
far. */
|
||||||
uint64_t retire_prior_to;
|
uint64_t retire_prior_to;
|
||||||
/* num_retire_queued is the number of RETIRE_CONNECTION_ID frames
|
/* num_retire_queued is the number of RETIRE_CONNECTION_ID frames
|
||||||
@ -352,7 +358,7 @@ struct ngtcp2_conn {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
ngtcp2_crypto_km *ckm;
|
ngtcp2_crypto_km *ckm;
|
||||||
ngtcp2_vec *hp_key;
|
ngtcp2_crypto_cipher_ctx hp_ctx;
|
||||||
} early;
|
} early;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -432,8 +438,12 @@ struct ngtcp2_conn {
|
|||||||
size_t aead_overhead;
|
size_t aead_overhead;
|
||||||
/* decrypt_buf is a buffer which is used to write decrypted data. */
|
/* decrypt_buf is a buffer which is used to write decrypted data. */
|
||||||
ngtcp2_vec decrypt_buf;
|
ngtcp2_vec decrypt_buf;
|
||||||
/* retry_aead is AEAD to verify Retry packet integrity. */
|
/* retry_aead is AEAD to verify Retry packet integrity. It is
|
||||||
|
used by client only. */
|
||||||
ngtcp2_crypto_aead retry_aead;
|
ngtcp2_crypto_aead retry_aead;
|
||||||
|
/* retry_aead_ctx is AEAD cipher context to verify Retry packet
|
||||||
|
integrity. It is used by client only. */
|
||||||
|
ngtcp2_crypto_aead_ctx retry_aead_ctx;
|
||||||
/* tls_error is TLS related error. */
|
/* tls_error is TLS related error. */
|
||||||
int tls_error;
|
int tls_error;
|
||||||
} crypto;
|
} crypto;
|
||||||
@ -470,6 +480,33 @@ struct ngtcp2_conn {
|
|||||||
int server;
|
int server;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum ngtcp2_vmsg_type {
|
||||||
|
NGTCP2_VMSG_TYPE_STREAM,
|
||||||
|
} ngtcp2_vmsg_type;
|
||||||
|
|
||||||
|
typedef struct ngtcp2_vmsg_stream {
|
||||||
|
/* strm is a stream that data is sent to. */
|
||||||
|
ngtcp2_strm *strm;
|
||||||
|
/* flags is bitwise OR of zero or more of
|
||||||
|
ngtcp2_write_stream_flag. */
|
||||||
|
uint32_t flags;
|
||||||
|
/* data is the pointer to ngtcp2_vec array which contains the stream
|
||||||
|
data to send. */
|
||||||
|
const ngtcp2_vec *data;
|
||||||
|
/* datacnt is the number of ngtcp2_vec pointed by data. */
|
||||||
|
size_t datacnt;
|
||||||
|
/* *pdatalen is the pointer to the variable which the number of
|
||||||
|
bytes written is assigned to if pdatalen is not NULL. */
|
||||||
|
ngtcp2_ssize *pdatalen;
|
||||||
|
} ngtcp2_vmsg_stream;
|
||||||
|
|
||||||
|
typedef struct ngtcp2_vmsg {
|
||||||
|
ngtcp2_vmsg_type type;
|
||||||
|
union {
|
||||||
|
ngtcp2_vmsg_stream stream;
|
||||||
|
};
|
||||||
|
} ngtcp2_vmsg;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_conn_sched_ack stores packet number |pkt_num| and its
|
* ngtcp2_conn_sched_ack stores packet number |pkt_num| and its
|
||||||
* reception timestamp |ts| in order to send its ACK.
|
* reception timestamp |ts| in order to send its ACK.
|
||||||
@ -591,6 +628,10 @@ int ngtcp2_conn_tx_strmq_push(ngtcp2_conn *conn, ngtcp2_strm *strm);
|
|||||||
*/
|
*/
|
||||||
ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn);
|
ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn);
|
||||||
|
|
||||||
|
ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
|
||||||
|
uint8_t *dest, size_t destlen,
|
||||||
|
ngtcp2_vmsg *vmsg, ngtcp2_tstamp ts);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_conn_write_single_frame_pkt writes a packet which contains |fr|
|
* ngtcp2_conn_write_single_frame_pkt writes a packet which contains |fr|
|
||||||
* frame only in the buffer pointed by |dest| whose length if
|
* frame only in the buffer pointed by |dest| whose length if
|
||||||
@ -612,4 +653,46 @@ ngtcp2_conn_write_single_frame_pkt(ngtcp2_conn *conn, uint8_t *dest,
|
|||||||
const ngtcp2_cid *dcid, ngtcp2_frame *fr,
|
const ngtcp2_cid *dcid, ngtcp2_frame *fr,
|
||||||
uint8_t rtb_flags, ngtcp2_tstamp ts);
|
uint8_t rtb_flags, ngtcp2_tstamp ts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_conn_commit_local_transport_params commits the local
|
||||||
|
* transport parameters, which is currently set to
|
||||||
|
* conn->local.settings.transport_params. This function will do some
|
||||||
|
* amends on transport parameters for adjusting default values.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* NGTCP2_ERR_NOMEM
|
||||||
|
* Out of memory.
|
||||||
|
* NGTCP2_ERR_INVALID_ARGUMENT
|
||||||
|
* CID in preferred address equals to the original SCID.
|
||||||
|
*/
|
||||||
|
int ngtcp2_conn_commit_local_transport_params(ngtcp2_conn *conn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_conn_lost_pkt_expiry returns the earliest expiry time of
|
||||||
|
* lost packet.
|
||||||
|
*/
|
||||||
|
ngtcp2_tstamp ngtcp2_conn_lost_pkt_expiry(ngtcp2_conn *conn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_conn_remove_lost_pkt removes the expired lost packet.
|
||||||
|
*/
|
||||||
|
void ngtcp2_conn_remove_lost_pkt(ngtcp2_conn *conn, ngtcp2_tstamp ts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_conn_resched_frames reschedules frames linked from |*pfrc|
|
||||||
|
* for retransmission.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* NGTCP2_ERR_NOMEM
|
||||||
|
* Out of memory.
|
||||||
|
*/
|
||||||
|
int ngtcp2_conn_resched_frames(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
|
||||||
|
ngtcp2_frame_chain **pfrc);
|
||||||
|
|
||||||
|
uint64_t ngtcp2_conn_tx_strmq_first_cycle(ngtcp2_conn *conn);
|
||||||
|
|
||||||
#endif /* NGTCP2_CONN_H */
|
#endif /* NGTCP2_CONN_H */
|
||||||
|
16
deps/ngtcp2/lib/ngtcp2_conv.c
vendored
16
deps/ngtcp2/lib/ngtcp2_conv.c
vendored
@ -45,19 +45,19 @@ uint64_t ngtcp2_get_uint48(const uint8_t *p) {
|
|||||||
uint32_t ngtcp2_get_uint32(const uint8_t *p) {
|
uint32_t ngtcp2_get_uint32(const uint8_t *p) {
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
memcpy(&n, p, 4);
|
memcpy(&n, p, 4);
|
||||||
return ntohl(n);
|
return ngtcp2_ntohl(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ngtcp2_get_uint24(const uint8_t *p) {
|
uint32_t ngtcp2_get_uint24(const uint8_t *p) {
|
||||||
uint32_t n = 0;
|
uint32_t n = 0;
|
||||||
memcpy(((uint8_t *)&n) + 1, p, 3);
|
memcpy(((uint8_t *)&n) + 1, p, 3);
|
||||||
return ntohl(n);
|
return ngtcp2_ntohl(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ngtcp2_get_uint16(const uint8_t *p) {
|
uint16_t ngtcp2_get_uint16(const uint8_t *p) {
|
||||||
uint16_t n;
|
uint16_t n;
|
||||||
memcpy(&n, p, 2);
|
memcpy(&n, p, 2);
|
||||||
return ntohs(n);
|
return ngtcp2_ntohs(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p) {
|
uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p) {
|
||||||
@ -76,11 +76,11 @@ uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p) {
|
|||||||
case 2:
|
case 2:
|
||||||
memcpy(&n, p, 2);
|
memcpy(&n, p, 2);
|
||||||
n.b[0] &= 0x3f;
|
n.b[0] &= 0x3f;
|
||||||
return ntohs(n.n16);
|
return ngtcp2_ntohs(n.n16);
|
||||||
case 4:
|
case 4:
|
||||||
memcpy(&n, p, 4);
|
memcpy(&n, p, 4);
|
||||||
n.b[0] &= 0x3f;
|
n.b[0] &= 0x3f;
|
||||||
return ntohl(n.n32);
|
return ngtcp2_ntohl(n.n32);
|
||||||
case 8:
|
case 8:
|
||||||
memcpy(&n, p, 8);
|
memcpy(&n, p, 8);
|
||||||
n.b[0] &= 0x3f;
|
n.b[0] &= 0x3f;
|
||||||
@ -116,17 +116,17 @@ uint8_t *ngtcp2_put_uint48be(uint8_t *p, uint64_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *ngtcp2_put_uint32be(uint8_t *p, uint32_t n) {
|
uint8_t *ngtcp2_put_uint32be(uint8_t *p, uint32_t n) {
|
||||||
n = htonl(n);
|
n = ngtcp2_htonl(n);
|
||||||
return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
|
return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *ngtcp2_put_uint24be(uint8_t *p, uint32_t n) {
|
uint8_t *ngtcp2_put_uint24be(uint8_t *p, uint32_t n) {
|
||||||
n = htonl(n);
|
n = ngtcp2_htonl(n);
|
||||||
return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 1, 3);
|
return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 1, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *ngtcp2_put_uint16be(uint8_t *p, uint16_t n) {
|
uint8_t *ngtcp2_put_uint16be(uint8_t *p, uint16_t n) {
|
||||||
n = htons(n);
|
n = ngtcp2_htons(n);
|
||||||
return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
|
return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
deps/ngtcp2/lib/ngtcp2_conv.h
vendored
41
deps/ngtcp2/lib/ngtcp2_conv.h
vendored
@ -37,6 +37,10 @@
|
|||||||
# include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#endif /* HAVE_NETINET_IN_H */
|
#endif /* HAVE_NETINET_IN_H */
|
||||||
|
|
||||||
|
#ifdef HAVE_BYTESWAP_H
|
||||||
|
# include <byteswap.h>
|
||||||
|
#endif /* HAVE_BYTESWAP_H */
|
||||||
|
|
||||||
#ifdef HAVE_ENDIAN_H
|
#ifdef HAVE_ENDIAN_H
|
||||||
# include <endian.h>
|
# include <endian.h>
|
||||||
#endif /* HAVE_ENDIAN_H */
|
#endif /* HAVE_ENDIAN_H */
|
||||||
@ -47,15 +51,25 @@
|
|||||||
|
|
||||||
#include <ngtcp2/ngtcp2.h>
|
#include <ngtcp2/ngtcp2.h>
|
||||||
|
|
||||||
|
#if defined HAVE_BSWAP_64 || HAVE_DECL_BSWAP_64
|
||||||
|
# define ngtcp2_bswap64 bswap_64
|
||||||
|
#else /* !HAVE_BSWAP_64 */
|
||||||
|
# define ngtcp2_bswap64(N) \
|
||||||
|
((uint64_t)(ntohl((uint32_t)(N))) << 32 | ntohl((uint32_t)((N) >> 32)))
|
||||||
|
#endif /* !HAVE_BSWAP_64 */
|
||||||
|
|
||||||
#if defined HAVE_BE64TOH || HAVE_DECL_BE64TOH
|
#if defined HAVE_BE64TOH || HAVE_DECL_BE64TOH
|
||||||
# define ngtcp2_ntohl64(N) be64toh(N)
|
# define ngtcp2_ntohl64(N) be64toh(N)
|
||||||
# define ngtcp2_htonl64(N) htobe64(N)
|
# define ngtcp2_htonl64(N) htobe64(N)
|
||||||
#else /* !HAVE_BE64TOH */
|
#else /* !HAVE_BE64TOH */
|
||||||
# define ngtcp2_bswap64(N) \
|
# if defined WORDS_BIGENDIAN
|
||||||
((uint64_t)(ntohl((uint32_t)(N))) << 32 | ntohl((uint32_t)((N) >> 32)))
|
# define ngtcp2_ntohl64(N) (N)
|
||||||
# define ngtcp2_ntohl64(N) ngtcp2_bswap64(N)
|
# define ngtcp2_htonl64(N) (N)
|
||||||
# define ngtcp2_htonl64(N) ngtcp2_bswap64(N)
|
# else /* !WORDS_BIGENDIAN */
|
||||||
#endif /* !HAVE_BE64TOH */
|
# define ngtcp2_ntohl64(N) ngtcp2_bswap64(N)
|
||||||
|
# define ngtcp2_htonl64(N) ngtcp2_bswap64(N)
|
||||||
|
# endif /* !WORDS_BIGENDIAN */
|
||||||
|
#endif /* !HAVE_BE64TOH */
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
/* Windows requires ws2_32 library for ntonl family functions. We
|
/* Windows requires ws2_32 library for ntonl family functions. We
|
||||||
@ -68,7 +82,7 @@
|
|||||||
# define STIN static inline
|
# define STIN static inline
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
STIN uint32_t htonl(uint32_t hostlong) {
|
STIN uint32_t ngtcp2_htonl(uint32_t hostlong) {
|
||||||
uint32_t res;
|
uint32_t res;
|
||||||
unsigned char *p = (unsigned char *)&res;
|
unsigned char *p = (unsigned char *)&res;
|
||||||
*p++ = hostlong >> 24;
|
*p++ = hostlong >> 24;
|
||||||
@ -78,7 +92,7 @@ STIN uint32_t htonl(uint32_t hostlong) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
STIN uint16_t htons(uint16_t hostshort) {
|
STIN uint16_t ngtcp2_htons(uint16_t hostshort) {
|
||||||
uint16_t res;
|
uint16_t res;
|
||||||
unsigned char *p = (unsigned char *)&res;
|
unsigned char *p = (unsigned char *)&res;
|
||||||
*p++ = hostshort >> 8;
|
*p++ = hostshort >> 8;
|
||||||
@ -86,7 +100,7 @@ STIN uint16_t htons(uint16_t hostshort) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
STIN uint32_t ntohl(uint32_t netlong) {
|
STIN uint32_t ngtcp2_ntohl(uint32_t netlong) {
|
||||||
uint32_t res;
|
uint32_t res;
|
||||||
unsigned char *p = (unsigned char *)&netlong;
|
unsigned char *p = (unsigned char *)&netlong;
|
||||||
res = *p++ << 24;
|
res = *p++ << 24;
|
||||||
@ -96,7 +110,7 @@ STIN uint32_t ntohl(uint32_t netlong) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
STIN uint16_t ntohs(uint16_t netshort) {
|
STIN uint16_t ngtcp2_ntohs(uint16_t netshort) {
|
||||||
uint16_t res;
|
uint16_t res;
|
||||||
unsigned char *p = (unsigned char *)&netshort;
|
unsigned char *p = (unsigned char *)&netshort;
|
||||||
res = *p++ << 8;
|
res = *p++ << 8;
|
||||||
@ -104,7 +118,14 @@ STIN uint16_t ntohs(uint16_t netshort) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WIN32 */
|
#else /* !WIN32 */
|
||||||
|
|
||||||
|
# define ngtcp2_htonl htonl
|
||||||
|
# define ngtcp2_htons htons
|
||||||
|
# define ngtcp2_ntohl ntohl
|
||||||
|
# define ngtcp2_ntohs ntohs
|
||||||
|
|
||||||
|
#endif /* !WIN32 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_get_uint64 reads 8 bytes from |p| as 64 bits unsigned
|
* ngtcp2_get_uint64 reads 8 bytes from |p| as 64 bits unsigned
|
||||||
|
18
deps/ngtcp2/lib/ngtcp2_crypto.c
vendored
18
deps/ngtcp2/lib/ngtcp2_crypto.c
vendored
@ -32,10 +32,11 @@
|
|||||||
#include "ngtcp2_conn.h"
|
#include "ngtcp2_conn.h"
|
||||||
|
|
||||||
int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
|
int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
|
||||||
size_t secretlen, const uint8_t *key, size_t keylen,
|
size_t secretlen,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *iv, size_t ivlen,
|
const uint8_t *iv, size_t ivlen,
|
||||||
const ngtcp2_mem *mem) {
|
const ngtcp2_mem *mem) {
|
||||||
int rv = ngtcp2_crypto_km_nocopy_new(pckm, secretlen, keylen, ivlen, mem);
|
int rv = ngtcp2_crypto_km_nocopy_new(pckm, secretlen, ivlen, mem);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -43,19 +44,20 @@ int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
|
|||||||
if (secretlen) {
|
if (secretlen) {
|
||||||
memcpy((*pckm)->secret.base, secret, secretlen);
|
memcpy((*pckm)->secret.base, secret, secretlen);
|
||||||
}
|
}
|
||||||
memcpy((*pckm)->key.base, key, keylen);
|
if (aead_ctx) {
|
||||||
|
(*pckm)->aead_ctx = *aead_ctx;
|
||||||
|
}
|
||||||
memcpy((*pckm)->iv.base, iv, ivlen);
|
memcpy((*pckm)->iv.base, iv, ivlen);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
|
int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
|
||||||
size_t keylen, size_t ivlen,
|
size_t ivlen, const ngtcp2_mem *mem) {
|
||||||
const ngtcp2_mem *mem) {
|
|
||||||
size_t len;
|
size_t len;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
|
|
||||||
len = sizeof(ngtcp2_crypto_km) + secretlen + keylen + ivlen;
|
len = sizeof(ngtcp2_crypto_km) + secretlen + ivlen;
|
||||||
|
|
||||||
*pckm = ngtcp2_mem_malloc(mem, len);
|
*pckm = ngtcp2_mem_malloc(mem, len);
|
||||||
if (*pckm == NULL) {
|
if (*pckm == NULL) {
|
||||||
@ -66,11 +68,9 @@ int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
|
|||||||
(*pckm)->secret.base = p;
|
(*pckm)->secret.base = p;
|
||||||
(*pckm)->secret.len = secretlen;
|
(*pckm)->secret.len = secretlen;
|
||||||
p += secretlen;
|
p += secretlen;
|
||||||
(*pckm)->key.base = p;
|
|
||||||
(*pckm)->key.len = keylen;
|
|
||||||
p += keylen;
|
|
||||||
(*pckm)->iv.base = p;
|
(*pckm)->iv.base = p;
|
||||||
(*pckm)->iv.len = ivlen;
|
(*pckm)->iv.len = ivlen;
|
||||||
|
(*pckm)->aead_ctx.native_handle = NULL;
|
||||||
(*pckm)->pkt_num = -1;
|
(*pckm)->pkt_num = -1;
|
||||||
(*pckm)->use_count = 0;
|
(*pckm)->use_count = 0;
|
||||||
(*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE;
|
(*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE;
|
||||||
|
10
deps/ngtcp2/lib/ngtcp2_crypto.h
vendored
10
deps/ngtcp2/lib/ngtcp2_crypto.h
vendored
@ -50,7 +50,7 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngtcp2_vec secret;
|
ngtcp2_vec secret;
|
||||||
ngtcp2_vec key;
|
ngtcp2_crypto_aead_ctx aead_ctx;
|
||||||
ngtcp2_vec iv;
|
ngtcp2_vec iv;
|
||||||
/* pkt_num is a packet number of a packet which uses this keying
|
/* pkt_num is a packet number of a packet which uses this keying
|
||||||
material. For encryption key, it is the lowest packet number of
|
material. For encryption key, it is the lowest packet number of
|
||||||
@ -75,7 +75,8 @@ typedef struct {
|
|||||||
* store secret is update keys. Only 1RTT key can be updated.
|
* store secret is update keys. Only 1RTT key can be updated.
|
||||||
*/
|
*/
|
||||||
int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
|
int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
|
||||||
size_t secretlen, const uint8_t *key, size_t keylen,
|
size_t secretlen,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx,
|
||||||
const uint8_t *iv, size_t ivlen,
|
const uint8_t *iv, size_t ivlen,
|
||||||
const ngtcp2_mem *mem);
|
const ngtcp2_mem *mem);
|
||||||
|
|
||||||
@ -84,8 +85,7 @@ int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
|
|||||||
* it does not copy secret, key and IV.
|
* it does not copy secret, key and IV.
|
||||||
*/
|
*/
|
||||||
int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
|
int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
|
||||||
size_t keylen, size_t ivlen,
|
size_t ivlen, const ngtcp2_mem *mem);
|
||||||
const ngtcp2_mem *mem);
|
|
||||||
|
|
||||||
void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem);
|
void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem);
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ typedef struct {
|
|||||||
ngtcp2_crypto_aead aead;
|
ngtcp2_crypto_aead aead;
|
||||||
ngtcp2_crypto_cipher hp;
|
ngtcp2_crypto_cipher hp;
|
||||||
ngtcp2_crypto_km *ckm;
|
ngtcp2_crypto_km *ckm;
|
||||||
const ngtcp2_vec *hp_key;
|
ngtcp2_crypto_cipher_ctx hp_ctx;
|
||||||
size_t aead_overhead;
|
size_t aead_overhead;
|
||||||
ngtcp2_encrypt encrypt;
|
ngtcp2_encrypt encrypt;
|
||||||
ngtcp2_decrypt decrypt;
|
ngtcp2_decrypt decrypt;
|
||||||
|
4
deps/ngtcp2/lib/ngtcp2_err.c
vendored
4
deps/ngtcp2/lib/ngtcp2_err.c
vendored
@ -94,8 +94,8 @@ const char *ngtcp2_strerror(int liberr) {
|
|||||||
return "ERR_INTERNAL";
|
return "ERR_INTERNAL";
|
||||||
case NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED:
|
case NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED:
|
||||||
return "ERR_CRYPTO_BUFFER_EXCEEDED";
|
return "ERR_CRYPTO_BUFFER_EXCEEDED";
|
||||||
case NGTCP2_ERR_WRITE_STREAM_MORE:
|
case NGTCP2_ERR_WRITE_MORE:
|
||||||
return "ERR_WRITE_STREAM_MORE";
|
return "ERR_WRITE_MORE";
|
||||||
case NGTCP2_ERR_RETRY:
|
case NGTCP2_ERR_RETRY:
|
||||||
return "ERR_RETRY";
|
return "ERR_RETRY";
|
||||||
case NGTCP2_ERR_DROP_CONN:
|
case NGTCP2_ERR_DROP_CONN:
|
||||||
|
12
deps/ngtcp2/lib/ngtcp2_gaptr.c
vendored
12
deps/ngtcp2/lib/ngtcp2_gaptr.c
vendored
@ -26,6 +26,7 @@
|
|||||||
#include "ngtcp2_range.h"
|
#include "ngtcp2_range.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
int ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem) {
|
int ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem) {
|
||||||
int rv;
|
int rv;
|
||||||
@ -115,3 +116,14 @@ int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset,
|
|||||||
ngtcp2_range m = ngtcp2_range_intersect(&q, &k);
|
ngtcp2_range m = ngtcp2_range_intersect(&q, &k);
|
||||||
return ngtcp2_range_len(&m) == 0;
|
return ngtcp2_range_len(&m) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ngtcp2_gaptr_drop_first_gap(ngtcp2_gaptr *gaptr) {
|
||||||
|
ngtcp2_ksl_it it = ngtcp2_ksl_begin(&gaptr->gap);
|
||||||
|
ngtcp2_range r;
|
||||||
|
|
||||||
|
assert(!ngtcp2_ksl_it_end(&it));
|
||||||
|
|
||||||
|
r = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
|
||||||
|
|
||||||
|
ngtcp2_ksl_remove(&gaptr->gap, NULL, &r);
|
||||||
|
}
|
||||||
|
7
deps/ngtcp2/lib/ngtcp2_gaptr.h
vendored
7
deps/ngtcp2/lib/ngtcp2_gaptr.h
vendored
@ -93,4 +93,11 @@ ngtcp2_ksl_it ngtcp2_gaptr_get_first_gap_after(ngtcp2_gaptr *gaptr,
|
|||||||
int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset,
|
int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset,
|
||||||
size_t datalen);
|
size_t datalen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_gaptr_drop_first_gap deletes the first gap entirely as if
|
||||||
|
* the range is pushed. This function assumes that at least one gap
|
||||||
|
* exists.
|
||||||
|
*/
|
||||||
|
void ngtcp2_gaptr_drop_first_gap(ngtcp2_gaptr *gaptr);
|
||||||
|
|
||||||
#endif /* NGTCP2_GAPTR_H */
|
#endif /* NGTCP2_GAPTR_H */
|
||||||
|
27
deps/ngtcp2/lib/ngtcp2_ksl.c
vendored
27
deps/ngtcp2/lib/ngtcp2_ksl.c
vendored
@ -275,6 +275,13 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
|||||||
i = ksl_bsearch(ksl, blk, key, ksl->compar);
|
i = ksl_bsearch(ksl, blk, key, ksl->compar);
|
||||||
|
|
||||||
if (blk->leaf) {
|
if (blk->leaf) {
|
||||||
|
if (i < blk->n &&
|
||||||
|
!ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) {
|
||||||
|
if (it) {
|
||||||
|
*it = ngtcp2_ksl_end(ksl);
|
||||||
|
}
|
||||||
|
return NGTCP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
ksl_insert_node(ksl, blk, i, key, data);
|
ksl_insert_node(ksl, blk, i, key, data);
|
||||||
++ksl->n;
|
++ksl->n;
|
||||||
if (it) {
|
if (it) {
|
||||||
@ -446,8 +453,8 @@ static int key_equal(ngtcp2_ksl_compar compar, const ngtcp2_ksl_key *lhs,
|
|||||||
return !compar(lhs, rhs) && !compar(rhs, lhs);
|
return !compar(lhs, rhs) && !compar(rhs, lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
||||||
const ngtcp2_ksl_key *key) {
|
const ngtcp2_ksl_key *key) {
|
||||||
ngtcp2_ksl_blk *blk = ksl->head;
|
ngtcp2_ksl_blk *blk = ksl->head;
|
||||||
ngtcp2_ksl_node *node;
|
ngtcp2_ksl_node *node;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -461,10 +468,20 @@ void ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
i = ksl_bsearch(ksl, blk, key, ksl->compar);
|
i = ksl_bsearch(ksl, blk, key, ksl->compar);
|
||||||
|
|
||||||
assert(i < blk->n);
|
if (i == blk->n) {
|
||||||
|
if (it) {
|
||||||
|
*it = ngtcp2_ksl_end(ksl);
|
||||||
|
}
|
||||||
|
return NGTCP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
if (blk->leaf) {
|
if (blk->leaf) {
|
||||||
assert(i < blk->n);
|
if (ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) {
|
||||||
|
if (it) {
|
||||||
|
*it = ngtcp2_ksl_end(ksl);
|
||||||
|
}
|
||||||
|
return NGTCP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
ksl_remove_node(ksl, blk, i);
|
ksl_remove_node(ksl, blk, i);
|
||||||
--ksl->n;
|
--ksl->n;
|
||||||
if (it) {
|
if (it) {
|
||||||
@ -474,7 +491,7 @@ void ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
|||||||
ngtcp2_ksl_it_init(it, ksl, blk, i);
|
ngtcp2_ksl_it_init(it, ksl, blk, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = ngtcp2_ksl_nth_node(ksl, blk, i);
|
node = ngtcp2_ksl_nth_node(ksl, blk, i);
|
||||||
|
20
deps/ngtcp2/lib/ngtcp2_ksl.h
vendored
20
deps/ngtcp2/lib/ngtcp2_ksl.h
vendored
@ -167,27 +167,33 @@ void ngtcp2_ksl_free(ngtcp2_ksl *ksl);
|
|||||||
* successful insertion, the iterator points to the inserted node is
|
* successful insertion, the iterator points to the inserted node is
|
||||||
* stored in |*it|.
|
* stored in |*it|.
|
||||||
*
|
*
|
||||||
* This function assumes that |key| does not exist in |ksl|.
|
|
||||||
*
|
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* NGTCP2_ERR_NOMEM
|
* NGTCP2_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
|
* NGTCP2_ERR_INVALID_ARGUMENT
|
||||||
|
* |key| already exists.
|
||||||
*/
|
*/
|
||||||
int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
||||||
const ngtcp2_ksl_key *key, void *data);
|
const ngtcp2_ksl_key *key, void *data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_ksl_remove removes the |key| from |ksl|. It assumes such
|
* ngtcp2_ksl_remove removes the |key| from |ksl|.
|
||||||
* the key is included in |ksl|.
|
|
||||||
*
|
*
|
||||||
* This function assigns the iterator to |*it|, which points to the
|
* 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|
|
* node which is located at the right next of the removed node if |it|
|
||||||
* is not NULL.
|
* is not NULL. If |key| is not found, no deletion takes place and
|
||||||
|
* the return value of ngtcp2_ksl_end(ksl) is assigned to |*it|.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* NGTCP2_ERR_INVALID_ARGUMENT
|
||||||
|
* |key| does not exist.
|
||||||
*/
|
*/
|
||||||
void ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
|
||||||
const ngtcp2_ksl_key *key);
|
const ngtcp2_ksl_key *key);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_ksl_lower_bound returns the iterator which points to the
|
* ngtcp2_ksl_lower_bound returns the iterator which points to the
|
||||||
|
241
deps/ngtcp2/lib/ngtcp2_map.c
vendored
241
deps/ngtcp2/lib/ngtcp2_map.c
vendored
@ -26,6 +26,7 @@
|
|||||||
#include "ngtcp2_map.h"
|
#include "ngtcp2_map.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "ngtcp2_conv.h"
|
#include "ngtcp2_conv.h"
|
||||||
|
|
||||||
@ -34,8 +35,7 @@
|
|||||||
int ngtcp2_map_init(ngtcp2_map *map, const ngtcp2_mem *mem) {
|
int ngtcp2_map_init(ngtcp2_map *map, const ngtcp2_mem *mem) {
|
||||||
map->mem = mem;
|
map->mem = mem;
|
||||||
map->tablelen = INITIAL_TABLE_LENGTH;
|
map->tablelen = INITIAL_TABLE_LENGTH;
|
||||||
map->table =
|
map->table = ngtcp2_mem_calloc(mem, map->tablelen, sizeof(ngtcp2_map_bucket));
|
||||||
ngtcp2_mem_calloc(mem, map->tablelen, sizeof(ngtcp2_map_entry *));
|
|
||||||
if (map->table == NULL) {
|
if (map->table == NULL) {
|
||||||
return NGTCP2_ERR_NOMEM;
|
return NGTCP2_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
@ -45,20 +45,52 @@ int ngtcp2_map_init(ngtcp2_map *map, const ngtcp2_mem *mem) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_map_free(ngtcp2_map *map) { ngtcp2_mem_free(map->mem, map->table); }
|
void ngtcp2_map_free(ngtcp2_map *map) {
|
||||||
|
size_t i;
|
||||||
|
ngtcp2_map_bucket *bkt;
|
||||||
|
|
||||||
|
if (!map) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
|
bkt = &map->table[i];
|
||||||
|
if (bkt->ksl) {
|
||||||
|
ngtcp2_ksl_free(bkt->ksl);
|
||||||
|
ngtcp2_mem_free(map->mem, bkt->ksl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngtcp2_mem_free(map->mem, map->table);
|
||||||
|
}
|
||||||
|
|
||||||
void ngtcp2_map_each_free(ngtcp2_map *map,
|
void ngtcp2_map_each_free(ngtcp2_map *map,
|
||||||
int (*func)(ngtcp2_map_entry *entry, void *ptr),
|
int (*func)(ngtcp2_map_entry *entry, void *ptr),
|
||||||
void *ptr) {
|
void *ptr) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
ngtcp2_map_bucket *bkt;
|
||||||
|
ngtcp2_ksl_it it;
|
||||||
|
|
||||||
for (i = 0; i < map->tablelen; ++i) {
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
ngtcp2_map_entry *entry;
|
bkt = &map->table[i];
|
||||||
for (entry = map->table[i]; entry;) {
|
|
||||||
ngtcp2_map_entry *next = entry->next;
|
if (bkt->ptr) {
|
||||||
func(entry, ptr);
|
func(bkt->ptr, ptr);
|
||||||
entry = next;
|
bkt->ptr = NULL;
|
||||||
|
assert(bkt->ksl == NULL || ngtcp2_ksl_len(bkt->ksl) == 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bkt->ksl) {
|
||||||
|
for (it = ngtcp2_ksl_begin(bkt->ksl); !ngtcp2_ksl_it_end(&it);
|
||||||
|
ngtcp2_ksl_it_next(&it)) {
|
||||||
|
func(ngtcp2_ksl_it_get(&it), ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngtcp2_ksl_free(bkt->ksl);
|
||||||
|
ngtcp2_mem_free(map->mem, bkt->ksl);
|
||||||
|
bkt->ksl = NULL;
|
||||||
}
|
}
|
||||||
map->table[i] = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,15 +99,29 @@ int ngtcp2_map_each(ngtcp2_map *map,
|
|||||||
void *ptr) {
|
void *ptr) {
|
||||||
int rv;
|
int rv;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
ngtcp2_map_bucket *bkt;
|
||||||
|
ngtcp2_ksl_it it;
|
||||||
|
|
||||||
for (i = 0; i < map->tablelen; ++i) {
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
ngtcp2_map_entry *entry, *next;
|
bkt = &map->table[i];
|
||||||
for (entry = map->table[i]; entry;) {
|
|
||||||
next = entry->next;
|
if (bkt->ptr) {
|
||||||
rv = func(entry, ptr);
|
rv = func(bkt->ptr, ptr);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
entry = next;
|
assert(bkt->ksl == NULL || ngtcp2_ksl_len(bkt->ksl) == 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bkt->ksl) {
|
||||||
|
for (it = ngtcp2_ksl_begin(bkt->ksl); !ngtcp2_ksl_it_end(&it);
|
||||||
|
ngtcp2_ksl_it_next(&it)) {
|
||||||
|
rv = func(ngtcp2_ksl_it_get(&it), ptr);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -95,71 +141,124 @@ static uint32_t hash(key_type key, uint32_t mod) {
|
|||||||
p = (uint8_t *)&key;
|
p = (uint8_t *)&key;
|
||||||
end = p + sizeof(key_type);
|
end = p + sizeof(key_type);
|
||||||
|
|
||||||
for (; p != end; ++p) {
|
for (; p != end;) {
|
||||||
h ^= *p;
|
h ^= *p++;
|
||||||
h *= 0x01000193u;
|
h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
return h & (mod - 1);
|
return h & (mod - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int insert(ngtcp2_map_entry **table, uint32_t tablelen,
|
static int less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
|
||||||
ngtcp2_map_entry *entry) {
|
return *(key_type *)lhs < *(key_type *)rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int map_insert(ngtcp2_map *map, ngtcp2_map_bucket *table,
|
||||||
|
uint32_t tablelen, ngtcp2_map_entry *entry) {
|
||||||
uint32_t h = hash(entry->key, tablelen);
|
uint32_t h = hash(entry->key, tablelen);
|
||||||
if (table[h] == NULL) {
|
ngtcp2_map_bucket *bkt = &table[h];
|
||||||
table[h] = entry;
|
const ngtcp2_mem *mem = map->mem;
|
||||||
} else {
|
int rv;
|
||||||
ngtcp2_map_entry *p;
|
|
||||||
/* We won't allow duplicated key, so check it out. */
|
if (bkt->ptr == NULL && (bkt->ksl == NULL || ngtcp2_ksl_len(bkt->ksl) == 0)) {
|
||||||
for (p = table[h]; p; p = p->next) {
|
bkt->ptr = entry;
|
||||||
if (p->key == entry->key) {
|
return 0;
|
||||||
return NGTCP2_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry->next = table[h];
|
|
||||||
table[h] = entry;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
if (!bkt->ksl) {
|
||||||
|
bkt->ksl = ngtcp2_mem_malloc(mem, sizeof(*bkt->ksl));
|
||||||
|
if (bkt->ksl == NULL) {
|
||||||
|
return NGTCP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
ngtcp2_ksl_init(bkt->ksl, less, sizeof(key_type), mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bkt->ptr) {
|
||||||
|
rv = ngtcp2_ksl_insert(bkt->ksl, NULL, &bkt->ptr->key, bkt->ptr);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bkt->ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngtcp2_ksl_insert(bkt->ksl, NULL, &entry->key, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* new_tablelen must be power of 2 */
|
/* new_tablelen must be power of 2 */
|
||||||
static int resize(ngtcp2_map *map, uint32_t new_tablelen) {
|
static int map_resize(ngtcp2_map *map, uint32_t new_tablelen) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
ngtcp2_map_entry **new_table;
|
ngtcp2_map_bucket *new_table;
|
||||||
|
ngtcp2_map_bucket *bkt;
|
||||||
|
ngtcp2_ksl_it it;
|
||||||
|
int rv;
|
||||||
|
|
||||||
new_table =
|
new_table =
|
||||||
ngtcp2_mem_calloc(map->mem, new_tablelen, sizeof(ngtcp2_map_entry *));
|
ngtcp2_mem_calloc(map->mem, new_tablelen, sizeof(ngtcp2_map_bucket));
|
||||||
if (new_table == NULL) {
|
if (new_table == NULL) {
|
||||||
return NGTCP2_ERR_NOMEM;
|
return NGTCP2_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < map->tablelen; ++i) {
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
ngtcp2_map_entry *entry;
|
bkt = &map->table[i];
|
||||||
for (entry = map->table[i]; entry;) {
|
|
||||||
ngtcp2_map_entry *next = entry->next;
|
if (bkt->ptr) {
|
||||||
entry->next = NULL;
|
rv = map_insert(map, new_table, new_tablelen, bkt->ptr);
|
||||||
/* This function must succeed */
|
if (rv != 0) {
|
||||||
insert(new_table, new_tablelen, entry);
|
goto fail;
|
||||||
entry = next;
|
}
|
||||||
|
assert(bkt->ksl == NULL || ngtcp2_ksl_len(bkt->ksl) == 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bkt->ksl) {
|
||||||
|
for (it = ngtcp2_ksl_begin(bkt->ksl); !ngtcp2_ksl_it_end(&it);
|
||||||
|
ngtcp2_ksl_it_next(&it)) {
|
||||||
|
rv = map_insert(map, new_table, new_tablelen, ngtcp2_ksl_it_get(&it));
|
||||||
|
if (rv != 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
|
bkt = &map->table[i];
|
||||||
|
if (bkt->ksl) {
|
||||||
|
ngtcp2_ksl_free(bkt->ksl);
|
||||||
|
ngtcp2_mem_free(map->mem, bkt->ksl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngtcp2_mem_free(map->mem, map->table);
|
ngtcp2_mem_free(map->mem, map->table);
|
||||||
map->tablelen = new_tablelen;
|
map->tablelen = new_tablelen;
|
||||||
map->table = new_table;
|
map->table = new_table;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
for (i = 0; i < new_tablelen; ++i) {
|
||||||
|
bkt = &new_table[i];
|
||||||
|
if (bkt->ksl) {
|
||||||
|
ngtcp2_ksl_free(bkt->ksl);
|
||||||
|
ngtcp2_mem_free(map->mem, bkt->ksl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_entry *new_entry) {
|
int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_entry *new_entry) {
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
/* Load factor is 0.75 */
|
/* Load factor is 0.75 */
|
||||||
if ((map->size + 1) * 4 > map->tablelen * 3) {
|
if ((map->size + 1) * 4 > map->tablelen * 3) {
|
||||||
rv = resize(map, map->tablelen * 2);
|
rv = map_resize(map, map->tablelen * 2);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rv = insert(map->table, map->tablelen, new_entry);
|
rv = map_insert(map, map->table, map->tablelen, new_entry);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -168,40 +267,64 @@ int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_entry *new_entry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngtcp2_map_entry *ngtcp2_map_find(ngtcp2_map *map, key_type key) {
|
ngtcp2_map_entry *ngtcp2_map_find(ngtcp2_map *map, key_type key) {
|
||||||
uint32_t h;
|
ngtcp2_map_bucket *bkt = &map->table[hash(key, map->tablelen)];
|
||||||
ngtcp2_map_entry *entry;
|
ngtcp2_ksl_it it;
|
||||||
h = hash(key, map->tablelen);
|
|
||||||
for (entry = map->table[h]; entry; entry = entry->next) {
|
if (bkt->ptr) {
|
||||||
if (entry->key == key) {
|
if (bkt->ptr->key == key) {
|
||||||
return entry;
|
return bkt->ptr;
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bkt->ksl) {
|
||||||
|
it = ngtcp2_ksl_lower_bound(bkt->ksl, &key);
|
||||||
|
if (ngtcp2_ksl_it_end(&it) || *(key_type *)ngtcp2_ksl_it_key(&it) != key) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ngtcp2_ksl_it_get(&it);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_map_remove(ngtcp2_map *map, key_type key) {
|
int ngtcp2_map_remove(ngtcp2_map *map, key_type key) {
|
||||||
uint32_t h;
|
ngtcp2_map_bucket *bkt = &map->table[hash(key, map->tablelen)];
|
||||||
ngtcp2_map_entry **dst;
|
int rv;
|
||||||
|
|
||||||
h = hash(key, map->tablelen);
|
if (bkt->ptr) {
|
||||||
|
if (bkt->ptr->key == key) {
|
||||||
for (dst = &map->table[h]; *dst; dst = &(*dst)->next) {
|
bkt->ptr = NULL;
|
||||||
if ((*dst)->key != key) {
|
--map->size;
|
||||||
continue;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return NGTCP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
*dst = (*dst)->next;
|
if (bkt->ksl) {
|
||||||
|
rv = ngtcp2_ksl_remove(bkt->ksl, NULL, &key);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
--map->size;
|
--map->size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGTCP2_ERR_INVALID_ARGUMENT;
|
return NGTCP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_map_clear(ngtcp2_map *map) {
|
void ngtcp2_map_clear(ngtcp2_map *map) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
ngtcp2_map_bucket *bkt;
|
||||||
|
|
||||||
for (i = 0; i < map->tablelen; ++i) {
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
map->table[i] = NULL;
|
bkt = &map->table[i];
|
||||||
|
bkt->ptr = NULL;
|
||||||
|
if (bkt->ksl) {
|
||||||
|
ngtcp2_ksl_free(bkt->ksl);
|
||||||
|
ngtcp2_mem_free(map->mem, bkt->ksl);
|
||||||
|
bkt->ksl = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map->size = 0;
|
map->size = 0;
|
||||||
|
8
deps/ngtcp2/lib/ngtcp2_map.h
vendored
8
deps/ngtcp2/lib/ngtcp2_map.h
vendored
@ -33,6 +33,7 @@
|
|||||||
#include <ngtcp2/ngtcp2.h>
|
#include <ngtcp2/ngtcp2.h>
|
||||||
|
|
||||||
#include "ngtcp2_mem.h"
|
#include "ngtcp2_mem.h"
|
||||||
|
#include "ngtcp2_ksl.h"
|
||||||
|
|
||||||
/* Implementation of unordered map */
|
/* Implementation of unordered map */
|
||||||
|
|
||||||
@ -43,8 +44,13 @@ typedef struct ngtcp2_map_entry {
|
|||||||
key_type key;
|
key_type key;
|
||||||
} ngtcp2_map_entry;
|
} ngtcp2_map_entry;
|
||||||
|
|
||||||
|
typedef struct ngtcp2_map_bucket {
|
||||||
|
ngtcp2_map_entry *ptr;
|
||||||
|
ngtcp2_ksl *ksl;
|
||||||
|
} ngtcp2_map_bucket;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngtcp2_map_entry **table;
|
ngtcp2_map_bucket *table;
|
||||||
const ngtcp2_mem *mem;
|
const ngtcp2_mem *mem;
|
||||||
size_t size;
|
size_t size;
|
||||||
uint32_t tablelen;
|
uint32_t tablelen;
|
||||||
|
20
deps/ngtcp2/lib/ngtcp2_path.c
vendored
20
deps/ngtcp2/lib/ngtcp2_path.c
vendored
@ -44,12 +44,16 @@ int ngtcp2_path_eq(const ngtcp2_path *a, const ngtcp2_path *b) {
|
|||||||
ngtcp2_addr_eq(&a->remote, &b->remote);
|
ngtcp2_addr_eq(&a->remote, &b->remote);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_path_storage_init(ngtcp2_path_storage *ps, const void *local_addr,
|
void ngtcp2_path_storage_init(ngtcp2_path_storage *ps,
|
||||||
|
const struct sockaddr *local_addr,
|
||||||
size_t local_addrlen, void *local_user_data,
|
size_t local_addrlen, void *local_user_data,
|
||||||
const void *remote_addr, size_t remote_addrlen,
|
const struct sockaddr *remote_addr,
|
||||||
void *remote_user_data) {
|
size_t remote_addrlen, void *remote_user_data) {
|
||||||
ngtcp2_addr_init(&ps->path.local, ps->local_addrbuf, 0, local_user_data);
|
ngtcp2_addr_init(&ps->path.local, (const struct sockaddr *)&ps->local_addrbuf,
|
||||||
ngtcp2_addr_init(&ps->path.remote, ps->remote_addrbuf, 0, remote_user_data);
|
0, local_user_data);
|
||||||
|
ngtcp2_addr_init(&ps->path.remote,
|
||||||
|
(const struct sockaddr *)&ps->remote_addrbuf, 0,
|
||||||
|
remote_user_data);
|
||||||
|
|
||||||
ngtcp2_addr_copy_byte(&ps->path.local, local_addr, local_addrlen);
|
ngtcp2_addr_copy_byte(&ps->path.local, local_addr, local_addrlen);
|
||||||
ngtcp2_addr_copy_byte(&ps->path.remote, remote_addr, remote_addrlen);
|
ngtcp2_addr_copy_byte(&ps->path.remote, remote_addr, remote_addrlen);
|
||||||
@ -63,6 +67,8 @@ void ngtcp2_path_storage_init2(ngtcp2_path_storage *ps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps) {
|
void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps) {
|
||||||
ngtcp2_addr_init(&ps->path.local, ps->local_addrbuf, 0, NULL);
|
ngtcp2_addr_init(&ps->path.local, (const struct sockaddr *)&ps->local_addrbuf,
|
||||||
ngtcp2_addr_init(&ps->path.remote, ps->remote_addrbuf, 0, NULL);
|
0, NULL);
|
||||||
|
ngtcp2_addr_init(&ps->path.remote,
|
||||||
|
(const struct sockaddr *)&ps->remote_addrbuf, 0, NULL);
|
||||||
}
|
}
|
||||||
|
27
deps/ngtcp2/lib/ngtcp2_pkt.c
vendored
27
deps/ngtcp2/lib/ngtcp2_pkt.c
vendored
@ -474,6 +474,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload,
|
|||||||
return ngtcp2_pkt_decode_stop_sending_frame(&dest->stop_sending, payload,
|
return ngtcp2_pkt_decode_stop_sending_frame(&dest->stop_sending, payload,
|
||||||
payloadlen);
|
payloadlen);
|
||||||
case NGTCP2_FRAME_ACK:
|
case NGTCP2_FRAME_ACK:
|
||||||
|
case NGTCP2_FRAME_ACK_ECN:
|
||||||
return ngtcp2_pkt_decode_ack_frame(&dest->ack, payload, payloadlen);
|
return ngtcp2_pkt_decode_ack_frame(&dest->ack, payload, payloadlen);
|
||||||
case NGTCP2_FRAME_PATH_CHALLENGE:
|
case NGTCP2_FRAME_PATH_CHALLENGE:
|
||||||
return ngtcp2_pkt_decode_path_challenge_frame(&dest->path_challenge,
|
return ngtcp2_pkt_decode_path_challenge_frame(&dest->path_challenge,
|
||||||
@ -2066,16 +2067,12 @@ ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen,
|
|||||||
return p - dest;
|
return p - dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t retry_key[] =
|
|
||||||
"\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1";
|
|
||||||
static const uint8_t retry_nonce[] =
|
|
||||||
"\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c";
|
|
||||||
|
|
||||||
ngtcp2_ssize
|
ngtcp2_ssize
|
||||||
ngtcp2_pkt_write_retry(uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
|
ngtcp2_pkt_write_retry(uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
|
||||||
const ngtcp2_cid *scid, const ngtcp2_cid *odcid,
|
const ngtcp2_cid *scid, const ngtcp2_cid *odcid,
|
||||||
const uint8_t *token, size_t tokenlen,
|
const uint8_t *token, size_t tokenlen,
|
||||||
ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead) {
|
ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx) {
|
||||||
ngtcp2_pkt_hd hd;
|
ngtcp2_pkt_hd hd;
|
||||||
uint8_t pseudo_retry[1500];
|
uint8_t pseudo_retry[1500];
|
||||||
ngtcp2_ssize pseudo_retrylen;
|
ngtcp2_ssize pseudo_retrylen;
|
||||||
@ -2106,8 +2103,10 @@ ngtcp2_pkt_write_retry(uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* OpenSSL does not like NULL plaintext. */
|
/* OpenSSL does not like NULL plaintext. */
|
||||||
rv = encrypt(tag, aead, (const uint8_t *)"", 0, retry_key, retry_nonce,
|
rv = encrypt(tag, aead, aead_ctx, (const uint8_t *)"", 0,
|
||||||
sizeof(retry_nonce) - 1, pseudo_retry, (size_t)pseudo_retrylen);
|
(const uint8_t *)NGTCP2_RETRY_NONCE,
|
||||||
|
sizeof(NGTCP2_RETRY_NONCE) - 1, pseudo_retry,
|
||||||
|
(size_t)pseudo_retrylen);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -2160,7 +2159,8 @@ ngtcp2_ssize ngtcp2_pkt_encode_pseudo_retry(
|
|||||||
int ngtcp2_pkt_verify_retry_tag(const ngtcp2_pkt_retry *retry,
|
int ngtcp2_pkt_verify_retry_tag(const ngtcp2_pkt_retry *retry,
|
||||||
const uint8_t *pkt, size_t pktlen,
|
const uint8_t *pkt, size_t pktlen,
|
||||||
ngtcp2_encrypt encrypt,
|
ngtcp2_encrypt encrypt,
|
||||||
const ngtcp2_crypto_aead *aead) {
|
const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx) {
|
||||||
uint8_t pseudo_retry[1500];
|
uint8_t pseudo_retry[1500];
|
||||||
size_t pseudo_retrylen;
|
size_t pseudo_retrylen;
|
||||||
uint8_t *p = pseudo_retry;
|
uint8_t *p = pseudo_retry;
|
||||||
@ -2181,8 +2181,9 @@ int ngtcp2_pkt_verify_retry_tag(const ngtcp2_pkt_retry *retry,
|
|||||||
pseudo_retrylen = (size_t)(p - pseudo_retry);
|
pseudo_retrylen = (size_t)(p - pseudo_retry);
|
||||||
|
|
||||||
/* OpenSSL does not like NULL plaintext. */
|
/* OpenSSL does not like NULL plaintext. */
|
||||||
rv = encrypt(tag, aead, (const uint8_t *)"", 0, retry_key, retry_nonce,
|
rv = encrypt(tag, aead, aead_ctx, (const uint8_t *)"", 0,
|
||||||
sizeof(retry_nonce) - 1, pseudo_retry, pseudo_retrylen);
|
(const uint8_t *)NGTCP2_RETRY_NONCE,
|
||||||
|
sizeof(NGTCP2_RETRY_NONCE) - 1, pseudo_retry, pseudo_retrylen);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -2229,7 +2230,9 @@ size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset,
|
|||||||
size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
|
size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
|
||||||
size_t n = 1 /* type */ + ngtcp2_put_varint_len(offset);
|
size_t n = 1 /* type */ + ngtcp2_put_varint_len(offset);
|
||||||
|
|
||||||
if (left <= n) {
|
/* CRYPTO frame must contain nonzero length data. Return -1 if
|
||||||
|
there is no space to write crypto data. */
|
||||||
|
if (left <= n + 1) {
|
||||||
return (size_t)-1;
|
return (size_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
deps/ngtcp2/lib/ngtcp2_pkt.h
vendored
3
deps/ngtcp2/lib/ngtcp2_pkt.h
vendored
@ -1120,6 +1120,7 @@ ngtcp2_ssize ngtcp2_pkt_encode_pseudo_retry(
|
|||||||
int ngtcp2_pkt_verify_retry_tag(const ngtcp2_pkt_retry *retry,
|
int ngtcp2_pkt_verify_retry_tag(const ngtcp2_pkt_retry *retry,
|
||||||
const uint8_t *pkt, size_t pktlen,
|
const uint8_t *pkt, size_t pktlen,
|
||||||
ngtcp2_encrypt encrypt,
|
ngtcp2_encrypt encrypt,
|
||||||
const ngtcp2_crypto_aead *aead);
|
const ngtcp2_crypto_aead *aead,
|
||||||
|
const ngtcp2_crypto_aead_ctx *aead_ctx);
|
||||||
|
|
||||||
#endif /* NGTCP2_PKT_H */
|
#endif /* NGTCP2_PKT_H */
|
||||||
|
5
deps/ngtcp2/lib/ngtcp2_ppe.c
vendored
5
deps/ngtcp2/lib/ngtcp2_ppe.c
vendored
@ -123,7 +123,7 @@ ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) {
|
|||||||
ngtcp2_crypto_create_nonce(ppe->nonce, cc->ckm->iv.base, cc->ckm->iv.len,
|
ngtcp2_crypto_create_nonce(ppe->nonce, cc->ckm->iv.base, cc->ckm->iv.len,
|
||||||
ppe->pkt_num);
|
ppe->pkt_num);
|
||||||
|
|
||||||
rv = cc->encrypt(payload, &cc->aead, payload, payloadlen, cc->ckm->key.base,
|
rv = cc->encrypt(payload, &cc->aead, &cc->ckm->aead_ctx, payload, payloadlen,
|
||||||
ppe->nonce, cc->ckm->iv.len, buf->begin, ppe->hdlen);
|
ppe->nonce, cc->ckm->iv.len, buf->begin, ppe->hdlen);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
@ -134,8 +134,7 @@ ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) {
|
|||||||
/* TODO Check that we have enough space to get sample */
|
/* TODO Check that we have enough space to get sample */
|
||||||
assert(ppe->sample_offset + NGTCP2_HP_SAMPLELEN <= ngtcp2_buf_len(buf));
|
assert(ppe->sample_offset + NGTCP2_HP_SAMPLELEN <= ngtcp2_buf_len(buf));
|
||||||
|
|
||||||
rv = cc->hp_mask(mask, &cc->hp, cc->hp_key->base,
|
rv = cc->hp_mask(mask, &cc->hp, &cc->hp_ctx, buf->begin + ppe->sample_offset);
|
||||||
buf->begin + ppe->sample_offset);
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
28
deps/ngtcp2/lib/ngtcp2_qlog.c
vendored
28
deps/ngtcp2/lib/ngtcp2_qlog.c
vendored
@ -230,7 +230,8 @@ void ngtcp2_qlog_start(ngtcp2_qlog *qlog, const ngtcp2_cid *odcid, int server) {
|
|||||||
p = write_event_fields(p);
|
p = write_event_fields(p);
|
||||||
p = write_events_start(p);
|
p = write_events_start(p);
|
||||||
|
|
||||||
qlog->write(qlog->user_data, buf, (size_t)(p - buf));
|
qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf,
|
||||||
|
(size_t)(p - buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_qlog_end(ngtcp2_qlog *qlog) {
|
void ngtcp2_qlog_end(ngtcp2_qlog *qlog) {
|
||||||
@ -245,7 +246,8 @@ void ngtcp2_qlog_end(ngtcp2_qlog *qlog) {
|
|||||||
p = write_trace_end(p);
|
p = write_trace_end(p);
|
||||||
*p++ = '}';
|
*p++ = '}';
|
||||||
|
|
||||||
qlog->write(qlog->user_data, buf, (size_t)(p - buf));
|
qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_FIN, buf,
|
||||||
|
(size_t)(p - buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *write_pkt_hd(uint8_t *p, const ngtcp2_pkt_hd *hd,
|
static uint8_t *write_pkt_hd(uint8_t *p, const ngtcp2_pkt_hd *hd,
|
||||||
@ -814,7 +816,8 @@ static void qlog_pkt_write_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
|
|||||||
|
|
||||||
qlog->buf.last = p;
|
qlog->buf.last = p;
|
||||||
|
|
||||||
qlog->write(qlog->user_data, qlog->buf.pos, ngtcp2_buf_len(&qlog->buf));
|
qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, qlog->buf.pos,
|
||||||
|
ngtcp2_buf_len(&qlog->buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) {
|
void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) {
|
||||||
@ -1015,7 +1018,7 @@ void ngtcp2_qlog_pkt_sent_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
|
|||||||
|
|
||||||
void ngtcp2_qlog_parameters_set_transport_params(
|
void ngtcp2_qlog_parameters_set_transport_params(
|
||||||
ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server,
|
ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server,
|
||||||
int local) {
|
ngtcp2_qlog_side side) {
|
||||||
uint8_t buf[1024];
|
uint8_t buf[1024];
|
||||||
uint8_t *p = buf;
|
uint8_t *p = buf;
|
||||||
ngtcp2_vec name, value;
|
ngtcp2_vec name, value;
|
||||||
@ -1034,20 +1037,20 @@ void ngtcp2_qlog_parameters_set_transport_params(
|
|||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
*p++ = '{';
|
*p++ = '{';
|
||||||
p = write_pair(p, ngtcp2_vec_lit(&name, "owner"),
|
p = write_pair(p, ngtcp2_vec_lit(&name, "owner"),
|
||||||
local ? ngtcp2_vec_lit(&value, "local")
|
side == NGTCP2_QLOG_SIDE_LOCAL
|
||||||
: ngtcp2_vec_lit(&value, "remote"));
|
? ngtcp2_vec_lit(&value, "local")
|
||||||
|
: ngtcp2_vec_lit(&value, "remote"));
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
p = write_pair_cid(p, ngtcp2_vec_lit(&name, "initial_source_connection_id"),
|
p = write_pair_cid(p, ngtcp2_vec_lit(&name, "initial_source_connection_id"),
|
||||||
¶ms->initial_scid);
|
¶ms->initial_scid);
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
if (!server == !local) {
|
if (side == (server ? NGTCP2_QLOG_SIDE_LOCAL : NGTCP2_QLOG_SIDE_REMOTE)) {
|
||||||
p = write_pair_cid(
|
p = write_pair_cid(
|
||||||
p, ngtcp2_vec_lit(&name, "original_destination_connection_id"),
|
p, ngtcp2_vec_lit(&name, "original_destination_connection_id"),
|
||||||
¶ms->original_dcid);
|
¶ms->original_dcid);
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
}
|
}
|
||||||
if (params->retry_scid_present) {
|
if (params->retry_scid_present) {
|
||||||
assert(!server);
|
|
||||||
p = write_pair_cid(p, ngtcp2_vec_lit(&name, "retry_source_connection_id"),
|
p = write_pair_cid(p, ngtcp2_vec_lit(&name, "retry_source_connection_id"),
|
||||||
¶ms->retry_scid);
|
¶ms->retry_scid);
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
@ -1126,7 +1129,8 @@ void ngtcp2_qlog_parameters_set_transport_params(
|
|||||||
*p++ = ']';
|
*p++ = ']';
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
|
|
||||||
qlog->write(qlog->user_data, buf, (size_t)(p - buf));
|
qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf,
|
||||||
|
(size_t)(p - buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog,
|
void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog,
|
||||||
@ -1181,7 +1185,8 @@ void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog,
|
|||||||
*p++ = ']';
|
*p++ = ']';
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
|
|
||||||
qlog->write(qlog->user_data, buf, (size_t)(p - buf));
|
qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf,
|
||||||
|
(size_t)(p - buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_qlog_pkt_lost(ngtcp2_qlog *qlog, ngtcp2_rtb_entry *ent) {
|
void ngtcp2_qlog_pkt_lost(ngtcp2_qlog *qlog, ngtcp2_rtb_entry *ent) {
|
||||||
@ -1215,5 +1220,6 @@ void ngtcp2_qlog_pkt_lost(ngtcp2_qlog *qlog, ngtcp2_rtb_entry *ent) {
|
|||||||
*p++ = ']';
|
*p++ = ']';
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
|
|
||||||
qlog->write(qlog->user_data, buf, (size_t)(p - buf));
|
qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf,
|
||||||
|
(size_t)(p - buf));
|
||||||
}
|
}
|
||||||
|
7
deps/ngtcp2/lib/ngtcp2_qlog.h
vendored
7
deps/ngtcp2/lib/ngtcp2_qlog.h
vendored
@ -40,6 +40,11 @@
|
|||||||
qlog. */
|
qlog. */
|
||||||
#define NGTCP2_QLOG_BUFLEN 4096
|
#define NGTCP2_QLOG_BUFLEN 4096
|
||||||
|
|
||||||
|
typedef enum ngtcp2_qlog_side {
|
||||||
|
NGTCP2_QLOG_SIDE_LOCAL,
|
||||||
|
NGTCP2_QLOG_SIDE_REMOTE,
|
||||||
|
} ngtcp2_qlog_side;
|
||||||
|
|
||||||
typedef struct ngtcp2_qlog {
|
typedef struct ngtcp2_qlog {
|
||||||
/* write is a callback function to write qlog. */
|
/* write is a callback function to write qlog. */
|
||||||
ngtcp2_qlog_write write;
|
ngtcp2_qlog_write write;
|
||||||
@ -116,7 +121,7 @@ void ngtcp2_qlog_pkt_sent_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
|
|||||||
*/
|
*/
|
||||||
void ngtcp2_qlog_parameters_set_transport_params(
|
void ngtcp2_qlog_parameters_set_transport_params(
|
||||||
ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server,
|
ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server,
|
||||||
int local);
|
ngtcp2_qlog_side side);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_qlog_metrics_updated writes metrics_updated event of
|
* ngtcp2_qlog_metrics_updated writes metrics_updated event of
|
||||||
|
2
deps/ngtcp2/lib/ngtcp2_rcvry.h
vendored
2
deps/ngtcp2/lib/ngtcp2_rcvry.h
vendored
@ -39,6 +39,4 @@
|
|||||||
draft-ietf-quic-recovery-17. */
|
draft-ietf-quic-recovery-17. */
|
||||||
#define NGTCP2_GRANULARITY NGTCP2_MILLISECONDS
|
#define NGTCP2_GRANULARITY NGTCP2_MILLISECONDS
|
||||||
|
|
||||||
#define NGTCP2_DEFAULT_INITIAL_RTT (333 * NGTCP2_MILLISECONDS)
|
|
||||||
|
|
||||||
#endif /* NGTCP2_RCVRY_H */
|
#endif /* NGTCP2_RCVRY_H */
|
||||||
|
12
deps/ngtcp2/lib/ngtcp2_ringbuf.c
vendored
12
deps/ngtcp2/lib/ngtcp2_ringbuf.c
vendored
@ -31,6 +31,16 @@
|
|||||||
|
|
||||||
#include "ngtcp2_macro.h"
|
#include "ngtcp2_macro.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(_M_ARM64)
|
||||||
|
unsigned int __popcnt(unsigned int x) {
|
||||||
|
unsigned int c = 0;
|
||||||
|
for (; x; ++c) {
|
||||||
|
x &= x - 1;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size,
|
int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size,
|
||||||
const ngtcp2_mem *mem) {
|
const ngtcp2_mem *mem) {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@ -101,6 +111,4 @@ void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset) {
|
|||||||
return &rb->buf[offset * rb->size];
|
return &rb->buf[offset * rb->size];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ngtcp2_ringbuf_len(ngtcp2_ringbuf *rb) { return rb->len; }
|
|
||||||
|
|
||||||
int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb) { return rb->len == rb->nmemb; }
|
int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb) { return rb->len == rb->nmemb; }
|
||||||
|
2
deps/ngtcp2/lib/ngtcp2_ringbuf.h
vendored
2
deps/ngtcp2/lib/ngtcp2_ringbuf.h
vendored
@ -102,7 +102,7 @@ void ngtcp2_ringbuf_resize(ngtcp2_ringbuf *rb, size_t len);
|
|||||||
void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset);
|
void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset);
|
||||||
|
|
||||||
/* ngtcp2_ringbuf_len returns the number of elements stored. */
|
/* ngtcp2_ringbuf_len returns the number of elements stored. */
|
||||||
size_t ngtcp2_ringbuf_len(ngtcp2_ringbuf *rb);
|
#define ngtcp2_ringbuf_len(RB) ((RB)->len)
|
||||||
|
|
||||||
/* ngtcp2_ringbuf_full returns nonzero if |rb| is full. */
|
/* ngtcp2_ringbuf_full returns nonzero if |rb| is full. */
|
||||||
int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb);
|
int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb);
|
||||||
|
811
deps/ngtcp2/lib/ngtcp2_rtb.c
vendored
811
deps/ngtcp2/lib/ngtcp2_rtb.c
vendored
File diff suppressed because it is too large
Load Diff
131
deps/ngtcp2/lib/ngtcp2_rtb.h
vendored
131
deps/ngtcp2/lib/ngtcp2_rtb.h
vendored
@ -38,6 +38,8 @@
|
|||||||
struct ngtcp2_conn;
|
struct ngtcp2_conn;
|
||||||
typedef struct ngtcp2_conn ngtcp2_conn;
|
typedef struct ngtcp2_conn ngtcp2_conn;
|
||||||
|
|
||||||
|
typedef struct ngtcp2_pktns ngtcp2_pktns;
|
||||||
|
|
||||||
struct ngtcp2_frame_chain;
|
struct ngtcp2_frame_chain;
|
||||||
typedef struct ngtcp2_frame_chain ngtcp2_frame_chain;
|
typedef struct ngtcp2_frame_chain ngtcp2_frame_chain;
|
||||||
|
|
||||||
@ -53,11 +55,47 @@ typedef struct ngtcp2_strm ngtcp2_strm;
|
|||||||
struct ngtcp2_rst;
|
struct ngtcp2_rst;
|
||||||
typedef struct ngtcp2_rst ngtcp2_rst;
|
typedef struct ngtcp2_rst ngtcp2_rst;
|
||||||
|
|
||||||
|
typedef enum ngtcp2_frame_chain_binder_flag {
|
||||||
|
NGTCP2_FRAME_CHAIN_BINDER_FLAG_NONE = 0x00,
|
||||||
|
/* NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK indicates that an information
|
||||||
|
which a frame carries has been acknowledged. */
|
||||||
|
NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK = 0x01,
|
||||||
|
} ngtcp2_frame_chain_binder_flag;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_frame_chain_binder binds 2 or more of ngtcp2_frame_chain to
|
||||||
|
* share the acknowledgement state. In general, all
|
||||||
|
* ngtcp2_frame_chains bound to the same binder must have the same
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
typedef struct ngtcp2_frame_chain_binder {
|
||||||
|
size_t refcount;
|
||||||
|
uint32_t flags;
|
||||||
|
} ngtcp2_frame_chain_binder;
|
||||||
|
|
||||||
|
int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder,
|
||||||
|
const ngtcp2_mem *mem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_bind_frame_chains binds two frame chains |a| and |b| using
|
||||||
|
* new or existing ngtcp2_frame_chain_binder. |a| might have non-NULL
|
||||||
|
* a->binder. |b| must not have non-NULL b->binder.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* NGTCP2_ERR_NOMEM
|
||||||
|
* Out of memory
|
||||||
|
*/
|
||||||
|
int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b,
|
||||||
|
const ngtcp2_mem *mem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_frame_chain chains frames in a single packet.
|
* ngtcp2_frame_chain chains frames in a single packet.
|
||||||
*/
|
*/
|
||||||
struct ngtcp2_frame_chain {
|
struct ngtcp2_frame_chain {
|
||||||
ngtcp2_frame_chain *next;
|
ngtcp2_frame_chain *next;
|
||||||
|
ngtcp2_frame_chain_binder *binder;
|
||||||
ngtcp2_frame fr;
|
ngtcp2_frame fr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -111,6 +149,10 @@ int ngtcp2_frame_chain_crypto_datacnt_new(ngtcp2_frame_chain **pfrc,
|
|||||||
size_t datacnt,
|
size_t datacnt,
|
||||||
const ngtcp2_mem *mem);
|
const ngtcp2_mem *mem);
|
||||||
|
|
||||||
|
int ngtcp2_frame_chain_new_token_new(ngtcp2_frame_chain **pfrc,
|
||||||
|
const ngtcp2_vec *token,
|
||||||
|
const ngtcp2_mem *mem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_frame_chain_del deallocates |frc|. It also deallocates the
|
* ngtcp2_frame_chain_del deallocates |frc|. It also deallocates the
|
||||||
* memory pointed by |frc|.
|
* memory pointed by |frc|.
|
||||||
@ -134,15 +176,23 @@ typedef enum {
|
|||||||
/* NGTCP2_RTB_FLAG_PROBE indicates that the entry includes a probe
|
/* NGTCP2_RTB_FLAG_PROBE indicates that the entry includes a probe
|
||||||
packet. */
|
packet. */
|
||||||
NGTCP2_RTB_FLAG_PROBE = 0x01,
|
NGTCP2_RTB_FLAG_PROBE = 0x01,
|
||||||
/* NGTCP2_RTB_FLAG_CRYPTO_PKT indicates that the entry includes
|
/* NGTCP2_RTB_FLAG_RETRANSMITTABLE indicates that the entry includes
|
||||||
handshake CRYPTO frame. */
|
a frame which must be retransmitted until it is acknowledged. In
|
||||||
NGTCP2_RTB_FLAG_CRYPTO_PKT = 0x02,
|
most cases, this flag is used along with
|
||||||
|
NGTCP2_RTB_FLAG_ACK_ELICITING. We have these 2 flags because
|
||||||
|
NGTCP2_RTB_FLAG_RETRANSMITTABLE triggers PTO, but just
|
||||||
|
NGTCP2_RTB_FLAG_ACK_ELICITING does not. */
|
||||||
|
NGTCP2_RTB_FLAG_RETRANSMITTABLE = 0x02,
|
||||||
/* NGTCP2_RTB_FLAG_ACK_ELICITING indicates that the entry elicits
|
/* NGTCP2_RTB_FLAG_ACK_ELICITING indicates that the entry elicits
|
||||||
acknowledgement. */
|
acknowledgement. */
|
||||||
NGTCP2_RTB_FLAG_ACK_ELICITING = 0x04,
|
NGTCP2_RTB_FLAG_ACK_ELICITING = 0x04,
|
||||||
/* NGTCP2_RTB_FLAG_CRYPTO_TIMEOUT_RETRANSMITTED indicates that the
|
/* NGTCP2_RTB_FLAG_PTO_RECLAIMED indicates that the packet has been
|
||||||
CRYPTO frames have been retransmitted. */
|
reclaimed on PTO. It is not marked lost yet and still consumes
|
||||||
NGTCP2_RTB_FLAG_CRYPTO_TIMEOUT_RETRANSMITTED = 0x08,
|
congestion window. */
|
||||||
|
NGTCP2_RTB_FLAG_PTO_RECLAIMED = 0x08,
|
||||||
|
/* NGTCP2_RTB_FLAG_LOST_RETRANSMITTED indicates that the entry has
|
||||||
|
been marked lost and scheduled to retransmit. */
|
||||||
|
NGTCP2_RTB_FLAG_LOST_RETRANSMITTED = 0x10,
|
||||||
} ngtcp2_rtb_flag;
|
} ngtcp2_rtb_flag;
|
||||||
|
|
||||||
struct ngtcp2_rtb_entry;
|
struct ngtcp2_rtb_entry;
|
||||||
@ -164,6 +214,8 @@ struct ngtcp2_rtb_entry {
|
|||||||
/* ts is the time point when a packet included in this entry is sent
|
/* ts is the time point when a packet included in this entry is sent
|
||||||
to a peer. */
|
to a peer. */
|
||||||
ngtcp2_tstamp ts;
|
ngtcp2_tstamp ts;
|
||||||
|
/* lost_ts is the time when this entry is marked lost. */
|
||||||
|
ngtcp2_tstamp lost_ts;
|
||||||
/* pktlen is the length of QUIC packet */
|
/* pktlen is the length of QUIC packet */
|
||||||
size_t pktlen;
|
size_t pktlen;
|
||||||
struct {
|
struct {
|
||||||
@ -217,6 +269,9 @@ typedef struct {
|
|||||||
int64_t largest_acked_tx_pkt_num;
|
int64_t largest_acked_tx_pkt_num;
|
||||||
/* num_ack_eliciting is the number of ACK eliciting entries. */
|
/* num_ack_eliciting is the number of ACK eliciting entries. */
|
||||||
size_t num_ack_eliciting;
|
size_t num_ack_eliciting;
|
||||||
|
/* num_retransmittable is the number of packets which contain frames
|
||||||
|
that must be retransmitted on loss. */
|
||||||
|
size_t num_retransmittable;
|
||||||
/* probe_pkt_left is the number of probe packet to send */
|
/* probe_pkt_left is the number of probe packet to send */
|
||||||
size_t probe_pkt_left;
|
size_t probe_pkt_left;
|
||||||
/* pktns_id is the identifier of packet number space. */
|
/* pktns_id is the identifier of packet number space. */
|
||||||
@ -228,6 +283,13 @@ typedef struct {
|
|||||||
contributed to ngtcp2_conn_stat.bytes_in_flight. It only
|
contributed to ngtcp2_conn_stat.bytes_in_flight. It only
|
||||||
includes the bytes after congestion state is reset. */
|
includes the bytes after congestion state is reset. */
|
||||||
uint64_t cc_bytes_in_flight;
|
uint64_t cc_bytes_in_flight;
|
||||||
|
/* persistent_congestion_start_ts is the time when persistent
|
||||||
|
congestion evaluation is started. It happens roughly after
|
||||||
|
handshake is confirmed. */
|
||||||
|
ngtcp2_tstamp persistent_congestion_start_ts;
|
||||||
|
/* num_lost_pkts is the number entries in ents which has
|
||||||
|
NGTCP2_RTB_FLAG_LOST_RETRANSMITTED flag set. */
|
||||||
|
size_t num_lost_pkts;
|
||||||
} ngtcp2_rtb;
|
} ngtcp2_rtb;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -286,31 +348,30 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
|
|||||||
* some frames might be prepended to |*pfrc| and the caller should
|
* some frames might be prepended to |*pfrc| and the caller should
|
||||||
* handle them. |pto| is PTO.
|
* handle them. |pto| is PTO.
|
||||||
*/
|
*/
|
||||||
void ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
|
int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
|
||||||
ngtcp2_conn_stat *cstat, ngtcp2_duration pto,
|
ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat,
|
||||||
ngtcp2_tstamp ts);
|
ngtcp2_duration pto, ngtcp2_tstamp ts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_rtb_remove_expired_lost_pkt removes expired lost packet.
|
||||||
|
*/
|
||||||
|
void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_duration pto,
|
||||||
|
ngtcp2_tstamp ts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_rtb_lost_pkt_ts returns the earliest time when the still
|
||||||
|
* retained packet was lost. It returns UINT64_MAX if no such packet
|
||||||
|
* exists.
|
||||||
|
*/
|
||||||
|
ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(ngtcp2_rtb *rtb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_rtb_remove_all removes all packets from |rtb| and prepends
|
* ngtcp2_rtb_remove_all removes all packets from |rtb| and prepends
|
||||||
* all frames to |*pfrc|. Even when this function fails, some frames
|
* all frames to |*pfrc|. Even when this function fails, some frames
|
||||||
* might be prepended to |*pfrc| and the caller should handle them.
|
* might be prepended to |*pfrc| and the caller should handle them.
|
||||||
*/
|
*/
|
||||||
void ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_frame_chain **pfrc,
|
int ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
|
||||||
ngtcp2_conn_stat *cstat);
|
ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat);
|
||||||
|
|
||||||
/*
|
|
||||||
* ngtcp2_rtb_on_crypto_timeout copies all unacknowledged CRYPTO
|
|
||||||
* frames and links them to |*pfrc|. The affected ngtcp2_rtb_entry
|
|
||||||
* will have NGTCP2_RTB_FLAG_CRYPTO_TIMEOUT_RETRANSMITTED set.
|
|
||||||
*
|
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
|
||||||
* negative error codes:
|
|
||||||
*
|
|
||||||
* NGTCP2_ERR_NOMEM
|
|
||||||
* Out of memory
|
|
||||||
*/
|
|
||||||
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.
|
* ngtcp2_rtb_empty returns nonzero if |rtb| have no entry.
|
||||||
@ -324,4 +385,24 @@ int ngtcp2_rtb_empty(ngtcp2_rtb *rtb);
|
|||||||
*/
|
*/
|
||||||
void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num);
|
void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_rtb_remove_expired_lost_pkt ensures that the number of lost
|
||||||
|
* packets at most |n|.
|
||||||
|
*/
|
||||||
|
void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_rtb_reclaim_on_pto reclaims up to |num_pkts| packets which
|
||||||
|
* are in-flight and not marked lost to send them in PTO probe. The
|
||||||
|
* reclaimed frames are chained to |*pfrc|.
|
||||||
|
*
|
||||||
|
* This function returns the number of packets reclaimed if it
|
||||||
|
* succeeds, or one of the following negative error codes:
|
||||||
|
*
|
||||||
|
* NGTCP2_ERR_NOMEM
|
||||||
|
* Out of memory
|
||||||
|
*/
|
||||||
|
ngtcp2_ssize ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
|
||||||
|
ngtcp2_pktns *pktns, size_t num_pkts);
|
||||||
|
|
||||||
#endif /* NGTCP2_RTB_H */
|
#endif /* NGTCP2_RTB_H */
|
||||||
|
469
deps/ngtcp2/lib/ngtcp2_strm.c
vendored
469
deps/ngtcp2/lib/ngtcp2_strm.c
vendored
@ -38,11 +38,14 @@ static int offset_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
|
|||||||
int ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
|
int ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
|
||||||
uint64_t max_rx_offset, uint64_t max_tx_offset,
|
uint64_t max_rx_offset, uint64_t max_tx_offset,
|
||||||
void *stream_user_data, const ngtcp2_mem *mem) {
|
void *stream_user_data, const ngtcp2_mem *mem) {
|
||||||
int rv;
|
|
||||||
|
|
||||||
strm->cycle = 0;
|
strm->cycle = 0;
|
||||||
|
strm->tx.acked_offset = NULL;
|
||||||
|
strm->tx.cont_acked_offset = 0;
|
||||||
|
strm->tx.streamfrq = NULL;
|
||||||
strm->tx.offset = 0;
|
strm->tx.offset = 0;
|
||||||
strm->tx.max_offset = max_tx_offset;
|
strm->tx.max_offset = max_tx_offset;
|
||||||
|
strm->rx.rob = NULL;
|
||||||
|
strm->rx.cont_offset = 0;
|
||||||
strm->rx.last_offset = 0;
|
strm->rx.last_offset = 0;
|
||||||
strm->stream_id = stream_id;
|
strm->stream_id = stream_id;
|
||||||
strm->flags = flags;
|
strm->flags = flags;
|
||||||
@ -54,29 +57,7 @@ int ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
|
|||||||
strm->mem = mem;
|
strm->mem = mem;
|
||||||
strm->app_error_code = 0;
|
strm->app_error_code = 0;
|
||||||
|
|
||||||
rv = ngtcp2_gaptr_init(&strm->tx.acked_offset, mem);
|
|
||||||
if (rv != 0) {
|
|
||||||
goto fail_gaptr_init;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = ngtcp2_rob_init(&strm->rx.rob, 8 * 1024, mem);
|
|
||||||
if (rv != 0) {
|
|
||||||
goto fail_rob_init;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = ngtcp2_ksl_init(&strm->tx.streamfrq, offset_less, sizeof(uint64_t), mem);
|
|
||||||
if (rv != 0) {
|
|
||||||
goto fail_tx_streamfrq_init;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_tx_streamfrq_init:
|
|
||||||
ngtcp2_rob_free(&strm->rx.rob);
|
|
||||||
fail_rob_init:
|
|
||||||
ngtcp2_gaptr_free(&strm->tx.acked_offset);
|
|
||||||
fail_gaptr_init:
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_strm_free(ngtcp2_strm *strm) {
|
void ngtcp2_strm_free(ngtcp2_strm *strm) {
|
||||||
@ -86,37 +67,268 @@ void ngtcp2_strm_free(ngtcp2_strm *strm) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (it = ngtcp2_ksl_begin(&strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
|
if (strm->tx.streamfrq) {
|
||||||
ngtcp2_ksl_it_next(&it)) {
|
for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
|
||||||
ngtcp2_frame_chain_del(ngtcp2_ksl_it_get(&it), strm->mem);
|
ngtcp2_ksl_it_next(&it)) {
|
||||||
|
ngtcp2_frame_chain_del(ngtcp2_ksl_it_get(&it), strm->mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngtcp2_ksl_free(strm->tx.streamfrq);
|
||||||
|
ngtcp2_mem_free(strm->mem, strm->tx.streamfrq);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngtcp2_ksl_free(&strm->tx.streamfrq);
|
ngtcp2_rob_free(strm->rx.rob);
|
||||||
ngtcp2_rob_free(&strm->rx.rob);
|
ngtcp2_mem_free(strm->mem, strm->rx.rob);
|
||||||
ngtcp2_gaptr_free(&strm->tx.acked_offset);
|
ngtcp2_gaptr_free(strm->tx.acked_offset);
|
||||||
|
ngtcp2_mem_free(strm->mem, strm->tx.acked_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int strm_rob_init(ngtcp2_strm *strm) {
|
||||||
|
int rv;
|
||||||
|
ngtcp2_rob *rob = ngtcp2_mem_malloc(strm->mem, sizeof(*rob));
|
||||||
|
|
||||||
|
if (rob == NULL) {
|
||||||
|
return NGTCP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = ngtcp2_rob_init(rob, 8 * 1024, strm->mem);
|
||||||
|
if (rv != 0) {
|
||||||
|
ngtcp2_mem_free(strm->mem, rob);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
strm->rx.rob = rob;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm) {
|
uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm) {
|
||||||
return ngtcp2_rob_first_gap_offset(&strm->rx.rob);
|
if (strm->rx.rob == NULL) {
|
||||||
|
return strm->rx.cont_offset;
|
||||||
|
}
|
||||||
|
return ngtcp2_rob_first_gap_offset(strm->rx.rob);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
|
int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
|
||||||
size_t datalen, uint64_t offset) {
|
size_t datalen, uint64_t offset) {
|
||||||
return ngtcp2_rob_push(&strm->rx.rob, offset, data, datalen);
|
int rv;
|
||||||
|
|
||||||
|
if (strm->rx.rob == NULL) {
|
||||||
|
rv = strm_rob_init(strm);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strm->rx.cont_offset) {
|
||||||
|
rv = ngtcp2_rob_remove_prefix(strm->rx.rob, strm->rx.cont_offset);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngtcp2_rob_push(strm->rx.rob, offset, data, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset) {
|
||||||
|
if (strm->rx.rob == NULL) {
|
||||||
|
strm->rx.cont_offset = offset;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngtcp2_rob_remove_prefix(strm->rx.rob, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags) {
|
void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags) {
|
||||||
strm->flags |= flags & NGTCP2_STRM_FLAG_SHUT_RDWR;
|
strm->flags |= flags & NGTCP2_STRM_FLAG_SHUT_RDWR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int strm_streamfrq_init(ngtcp2_strm *strm) {
|
||||||
|
int rv;
|
||||||
|
ngtcp2_ksl *streamfrq = ngtcp2_mem_malloc(strm->mem, sizeof(*streamfrq));
|
||||||
|
if (streamfrq == NULL) {
|
||||||
|
return NGTCP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = ngtcp2_ksl_init(streamfrq, offset_less, sizeof(uint64_t), strm->mem);
|
||||||
|
if (rv != 0) {
|
||||||
|
ngtcp2_mem_free(strm->mem, streamfrq);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
strm->tx.streamfrq = streamfrq;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc) {
|
int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc) {
|
||||||
|
int rv;
|
||||||
|
|
||||||
assert(frc->fr.type == NGTCP2_FRAME_STREAM);
|
assert(frc->fr.type == NGTCP2_FRAME_STREAM);
|
||||||
assert(frc->next == NULL);
|
assert(frc->next == NULL);
|
||||||
|
|
||||||
return ngtcp2_ksl_insert(&strm->tx.streamfrq, NULL, &frc->fr.stream.offset,
|
if (strm->tx.streamfrq == NULL) {
|
||||||
|
rv = strm_streamfrq_init(strm);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &frc->fr.stream.offset,
|
||||||
frc);
|
frc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm,
|
||||||
|
ngtcp2_frame_chain **pfrc) {
|
||||||
|
ngtcp2_frame_chain *frc, *nfrc;
|
||||||
|
ngtcp2_stream *fr, *nfr;
|
||||||
|
uint64_t offset, end_offset;
|
||||||
|
size_t idx, end_idx;
|
||||||
|
uint64_t base_offset, end_base_offset;
|
||||||
|
ngtcp2_range gap;
|
||||||
|
ngtcp2_vec *v;
|
||||||
|
int rv;
|
||||||
|
ngtcp2_ksl_it it;
|
||||||
|
|
||||||
|
*pfrc = NULL;
|
||||||
|
|
||||||
|
assert(strm->tx.streamfrq);
|
||||||
|
assert(ngtcp2_ksl_len(strm->tx.streamfrq));
|
||||||
|
|
||||||
|
for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);) {
|
||||||
|
frc = ngtcp2_ksl_it_get(&it);
|
||||||
|
fr = &frc->fr.stream;
|
||||||
|
|
||||||
|
ngtcp2_ksl_remove(strm->tx.streamfrq, &it, &fr->offset);
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
offset = fr->offset;
|
||||||
|
base_offset = 0;
|
||||||
|
|
||||||
|
gap = ngtcp2_strm_get_unacked_range_after(strm, offset);
|
||||||
|
if (gap.begin < offset) {
|
||||||
|
gap.begin = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; idx < fr->datacnt && offset < gap.begin; ++idx) {
|
||||||
|
v = &fr->data[idx];
|
||||||
|
if (offset + v->len > gap.begin) {
|
||||||
|
base_offset = gap.begin - offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += v->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == fr->datacnt) {
|
||||||
|
if (fr->fin) {
|
||||||
|
if (strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED) {
|
||||||
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
|
assert(ngtcp2_ksl_len(strm->tx.streamfrq) == 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fr->offset = fr->offset + ngtcp2_vec_len(fr->data, fr->datacnt);
|
||||||
|
fr->datacnt = 0;
|
||||||
|
|
||||||
|
*pfrc = frc;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(gap.begin == offset + base_offset);
|
||||||
|
|
||||||
|
end_idx = idx;
|
||||||
|
end_offset = offset;
|
||||||
|
end_base_offset = 0;
|
||||||
|
|
||||||
|
for (; end_idx < fr->datacnt; ++end_idx) {
|
||||||
|
v = &fr->data[end_idx];
|
||||||
|
if (end_offset + v->len > gap.end) {
|
||||||
|
end_base_offset = gap.end - end_offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
end_offset += v->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fr->offset == offset && base_offset == 0 && fr->datacnt == end_idx) {
|
||||||
|
*pfrc = frc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fr->datacnt == end_idx) {
|
||||||
|
memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx));
|
||||||
|
|
||||||
|
assert(fr->data[0].len > base_offset);
|
||||||
|
|
||||||
|
fr->offset = offset + base_offset;
|
||||||
|
fr->datacnt = end_idx - idx;
|
||||||
|
fr->data[0].base += base_offset;
|
||||||
|
fr->data[0].len -= (size_t)base_offset;
|
||||||
|
|
||||||
|
*pfrc = frc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, fr->datacnt - end_idx,
|
||||||
|
strm->mem);
|
||||||
|
if (rv != 0) {
|
||||||
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfr = &nfrc->fr.stream;
|
||||||
|
memcpy(nfr->data, fr->data + end_idx,
|
||||||
|
sizeof(nfr->data[0]) * (fr->datacnt - end_idx));
|
||||||
|
|
||||||
|
assert(nfr->data[0].len > end_base_offset);
|
||||||
|
|
||||||
|
nfr->type = NGTCP2_FRAME_STREAM;
|
||||||
|
nfr->flags = 0;
|
||||||
|
nfr->fin = fr->fin;
|
||||||
|
nfr->stream_id = fr->stream_id;
|
||||||
|
nfr->offset = end_offset + end_base_offset;
|
||||||
|
nfr->datacnt = fr->datacnt - end_idx;
|
||||||
|
nfr->data[0].base += end_base_offset;
|
||||||
|
nfr->data[0].len -= (size_t)end_base_offset;
|
||||||
|
|
||||||
|
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);
|
||||||
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_base_offset) {
|
||||||
|
++end_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx));
|
||||||
|
|
||||||
|
assert(fr->data[0].len > base_offset);
|
||||||
|
|
||||||
|
fr->fin = 0;
|
||||||
|
fr->offset = offset + base_offset;
|
||||||
|
fr->datacnt = end_idx - idx;
|
||||||
|
if (end_base_offset) {
|
||||||
|
assert(fr->data[fr->datacnt - 1].len > end_base_offset);
|
||||||
|
fr->data[fr->datacnt - 1].len = (size_t)end_base_offset;
|
||||||
|
}
|
||||||
|
fr->data[0].base += base_offset;
|
||||||
|
fr->data[0].len -= (size_t)base_offset;
|
||||||
|
|
||||||
|
*pfrc = frc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
||||||
size_t left) {
|
size_t left) {
|
||||||
ngtcp2_stream *fr, *nfr;
|
ngtcp2_stream *fr, *nfr;
|
||||||
@ -127,30 +339,39 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
|||||||
ngtcp2_vec a[NGTCP2_MAX_STREAM_DATACNT];
|
ngtcp2_vec a[NGTCP2_MAX_STREAM_DATACNT];
|
||||||
ngtcp2_vec b[NGTCP2_MAX_STREAM_DATACNT];
|
ngtcp2_vec b[NGTCP2_MAX_STREAM_DATACNT];
|
||||||
size_t acnt, bcnt;
|
size_t acnt, bcnt;
|
||||||
ngtcp2_ksl_it it;
|
uint64_t unacked_offset;
|
||||||
uint64_t old_offset;
|
|
||||||
|
|
||||||
if (ngtcp2_ksl_len(&strm->tx.streamfrq) == 0) {
|
if (strm->tx.streamfrq == NULL || ngtcp2_ksl_len(strm->tx.streamfrq) == 0) {
|
||||||
*pfrc = NULL;
|
*pfrc = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
it = ngtcp2_ksl_begin(&strm->tx.streamfrq);
|
rv = strm_streamfrq_unacked_pop(strm, &frc);
|
||||||
frc = ngtcp2_ksl_it_get(&it);
|
if (rv != 0) {
|
||||||
fr = &frc->fr.stream;
|
return rv;
|
||||||
|
}
|
||||||
|
if (frc == NULL) {
|
||||||
|
*pfrc = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fr = &frc->fr.stream;
|
||||||
datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
|
datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
|
||||||
|
|
||||||
if (left == 0) {
|
if (left == 0) {
|
||||||
/* datalen could be zero if 0 length STREAM has been sent */
|
/* datalen could be zero if 0 length STREAM has been sent */
|
||||||
if (datalen || ngtcp2_ksl_len(&strm->tx.streamfrq) > 1) {
|
if (datalen || ngtcp2_ksl_len(strm->tx.streamfrq) > 1) {
|
||||||
|
rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &fr->offset, frc);
|
||||||
|
if (rv != 0) {
|
||||||
|
assert(ngtcp2_err_is_fatal(rv));
|
||||||
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
*pfrc = NULL;
|
*pfrc = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL, &fr->offset);
|
|
||||||
|
|
||||||
if (datalen > left) {
|
if (datalen > left) {
|
||||||
ngtcp2_vec_copy(a, fr->data, fr->datacnt);
|
ngtcp2_vec_copy(a, fr->data, fr->datacnt);
|
||||||
acnt = fr->datacnt;
|
acnt = fr->datacnt;
|
||||||
@ -177,7 +398,7 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
|||||||
nfr->datacnt = bcnt;
|
nfr->datacnt = bcnt;
|
||||||
ngtcp2_vec_copy(nfr->data, b, bcnt);
|
ngtcp2_vec_copy(nfr->data, b, bcnt);
|
||||||
|
|
||||||
rv = ngtcp2_ksl_insert(&strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
|
rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
assert(ngtcp2_err_is_fatal(rv));
|
assert(ngtcp2_err_is_fatal(rv));
|
||||||
ngtcp2_frame_chain_del(nfrc, strm->mem);
|
ngtcp2_frame_chain_del(nfrc, strm->mem);
|
||||||
@ -210,19 +431,27 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
|||||||
ngtcp2_vec_copy(a, fr->data, fr->datacnt);
|
ngtcp2_vec_copy(a, fr->data, fr->datacnt);
|
||||||
acnt = fr->datacnt;
|
acnt = fr->datacnt;
|
||||||
|
|
||||||
for (; left && ngtcp2_ksl_len(&strm->tx.streamfrq);) {
|
for (; left && ngtcp2_ksl_len(strm->tx.streamfrq);) {
|
||||||
it = ngtcp2_ksl_begin(&strm->tx.streamfrq);
|
unacked_offset = ngtcp2_strm_streamfrq_unacked_offset(strm);
|
||||||
nfrc = ngtcp2_ksl_it_get(&it);
|
if (unacked_offset != fr->offset + datalen) {
|
||||||
nfr = &nfrc->fr.stream;
|
assert(fr->offset + datalen < unacked_offset);
|
||||||
|
|
||||||
if (nfr->offset != fr->offset + datalen) {
|
|
||||||
assert(fr->offset + datalen < nfr->offset);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = strm_streamfrq_unacked_pop(strm, &nfrc);
|
||||||
|
if (rv != 0) {
|
||||||
|
assert(ngtcp2_err_is_fatal(rv));
|
||||||
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
if (nfrc == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfr = &nfrc->fr.stream;
|
||||||
|
|
||||||
if (nfr->fin && nfr->datacnt == 0) {
|
if (nfr->fin && nfr->datacnt == 0) {
|
||||||
fr->fin = 1;
|
fr->fin = 1;
|
||||||
ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL, &nfr->offset);
|
|
||||||
ngtcp2_frame_chain_del(nfrc, strm->mem);
|
ngtcp2_frame_chain_del(nfrc, strm->mem);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -230,6 +459,13 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
|||||||
nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left,
|
nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left,
|
||||||
NGTCP2_MAX_STREAM_DATACNT);
|
NGTCP2_MAX_STREAM_DATACNT);
|
||||||
if (nmerged == 0) {
|
if (nmerged == 0) {
|
||||||
|
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);
|
||||||
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,15 +474,18 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
|||||||
|
|
||||||
if (nfr->datacnt == 0) {
|
if (nfr->datacnt == 0) {
|
||||||
fr->fin = nfr->fin;
|
fr->fin = nfr->fin;
|
||||||
ngtcp2_ksl_remove(&strm->tx.streamfrq, NULL, &nfr->offset);
|
|
||||||
ngtcp2_frame_chain_del(nfrc, strm->mem);
|
ngtcp2_frame_chain_del(nfrc, strm->mem);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_offset = nfr->offset;
|
|
||||||
nfr->offset += nmerged;
|
nfr->offset += nmerged;
|
||||||
|
|
||||||
ngtcp2_ksl_update_key(&strm->tx.streamfrq, &old_offset, &nfr->offset);
|
rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
|
||||||
|
if (rv != 0) {
|
||||||
|
ngtcp2_frame_chain_del(nfrc, strm->mem);
|
||||||
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -280,29 +519,68 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm) {
|
||||||
|
ngtcp2_frame_chain *frc;
|
||||||
|
ngtcp2_stream *fr;
|
||||||
|
ngtcp2_range gap;
|
||||||
|
ngtcp2_ksl_it it;
|
||||||
|
size_t datalen;
|
||||||
|
|
||||||
|
assert(strm->tx.streamfrq);
|
||||||
|
assert(ngtcp2_ksl_len(strm->tx.streamfrq));
|
||||||
|
|
||||||
|
for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
|
||||||
|
ngtcp2_ksl_it_next(&it)) {
|
||||||
|
frc = ngtcp2_ksl_it_get(&it);
|
||||||
|
fr = &frc->fr.stream;
|
||||||
|
|
||||||
|
gap = ngtcp2_strm_get_unacked_range_after(strm, fr->offset);
|
||||||
|
|
||||||
|
datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
|
||||||
|
|
||||||
|
if (gap.begin <= fr->offset) {
|
||||||
|
return fr->offset;
|
||||||
|
}
|
||||||
|
if (gap.begin < fr->offset + datalen) {
|
||||||
|
return gap.begin;
|
||||||
|
}
|
||||||
|
if (fr->offset + datalen == gap.begin && fr->fin &&
|
||||||
|
!(strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED)) {
|
||||||
|
return fr->offset + datalen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint64_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(ngtcp2_strm *strm) {
|
ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(ngtcp2_strm *strm) {
|
||||||
ngtcp2_ksl_it it;
|
ngtcp2_ksl_it it;
|
||||||
|
|
||||||
assert(ngtcp2_ksl_len(&strm->tx.streamfrq));
|
assert(strm->tx.streamfrq);
|
||||||
|
assert(ngtcp2_ksl_len(strm->tx.streamfrq));
|
||||||
|
|
||||||
it = ngtcp2_ksl_begin(&strm->tx.streamfrq);
|
it = ngtcp2_ksl_begin(strm->tx.streamfrq);
|
||||||
return ngtcp2_ksl_it_get(&it);
|
return ngtcp2_ksl_it_get(&it);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_strm_streamfrq_empty(ngtcp2_strm *strm) {
|
int ngtcp2_strm_streamfrq_empty(ngtcp2_strm *strm) {
|
||||||
return ngtcp2_ksl_len(&strm->tx.streamfrq) == 0;
|
return strm->tx.streamfrq == NULL || ngtcp2_ksl_len(strm->tx.streamfrq) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ngtcp2_strm_streamfrq_clear(ngtcp2_strm *strm) {
|
void ngtcp2_strm_streamfrq_clear(ngtcp2_strm *strm) {
|
||||||
ngtcp2_frame_chain *frc;
|
ngtcp2_frame_chain *frc;
|
||||||
ngtcp2_ksl_it it;
|
ngtcp2_ksl_it it;
|
||||||
|
|
||||||
for (it = ngtcp2_ksl_begin(&strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
|
if (strm->tx.streamfrq == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
|
||||||
ngtcp2_ksl_it_next(&it)) {
|
ngtcp2_ksl_it_next(&it)) {
|
||||||
frc = ngtcp2_ksl_it_get(&it);
|
frc = ngtcp2_ksl_it_get(&it);
|
||||||
ngtcp2_frame_chain_del(frc, strm->mem);
|
ngtcp2_frame_chain_del(frc, strm->mem);
|
||||||
}
|
}
|
||||||
ngtcp2_ksl_clear(&strm->tx.streamfrq);
|
ngtcp2_ksl_clear(strm->tx.streamfrq);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm) {
|
int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm) {
|
||||||
@ -310,6 +588,77 @@ int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm) {
|
int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm) {
|
||||||
return ngtcp2_gaptr_first_gap_offset(&strm->tx.acked_offset) ==
|
if (strm->tx.acked_offset == NULL) {
|
||||||
|
return strm->tx.cont_acked_offset == strm->tx.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngtcp2_gaptr_first_gap_offset(strm->tx.acked_offset) ==
|
||||||
strm->tx.offset;
|
strm->tx.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm,
|
||||||
|
uint64_t offset) {
|
||||||
|
ngtcp2_ksl_it gapit;
|
||||||
|
ngtcp2_range gap;
|
||||||
|
|
||||||
|
if (strm->tx.acked_offset == NULL) {
|
||||||
|
gap.begin = strm->tx.cont_acked_offset;
|
||||||
|
gap.end = UINT64_MAX;
|
||||||
|
return gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
gapit = ngtcp2_gaptr_get_first_gap_after(strm->tx.acked_offset, offset);
|
||||||
|
return *(ngtcp2_range *)ngtcp2_ksl_it_key(&gapit);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm) {
|
||||||
|
if (strm->tx.acked_offset == NULL) {
|
||||||
|
return strm->tx.cont_acked_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngtcp2_gaptr_first_gap_offset(strm->tx.acked_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int strm_acked_offset_init(ngtcp2_strm *strm) {
|
||||||
|
int rv;
|
||||||
|
ngtcp2_gaptr *acked_offset =
|
||||||
|
ngtcp2_mem_malloc(strm->mem, sizeof(*acked_offset));
|
||||||
|
|
||||||
|
if (acked_offset == NULL) {
|
||||||
|
return NGTCP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = ngtcp2_gaptr_init(acked_offset, strm->mem);
|
||||||
|
if (rv != 0) {
|
||||||
|
ngtcp2_mem_free(strm->mem, acked_offset);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
strm->tx.acked_offset = acked_offset;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len) {
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (strm->tx.acked_offset == NULL) {
|
||||||
|
if (strm->tx.cont_acked_offset == offset) {
|
||||||
|
strm->tx.cont_acked_offset += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = strm_acked_offset_init(strm);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv =
|
||||||
|
ngtcp2_gaptr_push(strm->tx.acked_offset, 0, strm->tx.cont_acked_offset);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngtcp2_gaptr_push(strm->tx.acked_offset, offset, len);
|
||||||
|
}
|
||||||
|
53
deps/ngtcp2/lib/ngtcp2_strm.h
vendored
53
deps/ngtcp2/lib/ngtcp2_strm.h
vendored
@ -64,6 +64,9 @@ typedef enum {
|
|||||||
/* NGTCP2_STRM_FLAG_RST_ACKED indicates that the outgoing RST_STREAM
|
/* NGTCP2_STRM_FLAG_RST_ACKED indicates that the outgoing RST_STREAM
|
||||||
is acknowledged by peer. */
|
is acknowledged by peer. */
|
||||||
NGTCP2_STRM_FLAG_RST_ACKED = 0x20,
|
NGTCP2_STRM_FLAG_RST_ACKED = 0x20,
|
||||||
|
/* NGTCP2_STRM_FLAG_FIN_ACKED indicates that a STREAM with FIN bit
|
||||||
|
set is acknowledged by a remote endpoint. */
|
||||||
|
NGTCP2_STRM_FLAG_FIN_ACKED = 0x40,
|
||||||
} ngtcp2_strm_flags;
|
} ngtcp2_strm_flags;
|
||||||
|
|
||||||
struct ngtcp2_strm;
|
struct ngtcp2_strm;
|
||||||
@ -76,12 +79,17 @@ struct ngtcp2_strm {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* acked_offset tracks acknowledged outgoing data. */
|
/* acked_offset tracks acknowledged outgoing data. */
|
||||||
ngtcp2_gaptr acked_offset;
|
ngtcp2_gaptr *acked_offset;
|
||||||
|
/* cont_acked_offset is the offset that all data up to this offset
|
||||||
|
is acknowledged by a remote endpoint. It is used until the
|
||||||
|
remote endpoint acknowledges data in out-of-order. After that,
|
||||||
|
acked_offset is used instead. */
|
||||||
|
uint64_t cont_acked_offset;
|
||||||
/* streamfrq contains STREAM frame for retransmission. The flow
|
/* streamfrq contains STREAM frame for retransmission. The flow
|
||||||
control credits have been paid when they are transmitted first
|
control credits have been paid when they are transmitted first
|
||||||
time. There are no restriction regarding flow control for
|
time. There are no restriction regarding flow control for
|
||||||
retransmission. */
|
retransmission. */
|
||||||
ngtcp2_ksl streamfrq;
|
ngtcp2_ksl *streamfrq;
|
||||||
/* offset is the next offset of outgoing data. In other words, it
|
/* offset is the next offset of outgoing data. In other words, it
|
||||||
is the number of bytes sent in this stream without
|
is the number of bytes sent in this stream without
|
||||||
duplication. */
|
duplication. */
|
||||||
@ -95,7 +103,11 @@ struct ngtcp2_strm {
|
|||||||
/* rob is the reorder buffer for incoming stream data. The data
|
/* rob is the reorder buffer for incoming stream data. The data
|
||||||
received in out of order is buffered and sorted by its offset
|
received in out of order is buffered and sorted by its offset
|
||||||
in this object. */
|
in this object. */
|
||||||
ngtcp2_rob rob;
|
ngtcp2_rob *rob;
|
||||||
|
/* cont_offset is the largest offset of consecutive data. It is
|
||||||
|
used until the endpoint receives out-of-order data. After
|
||||||
|
that, rob is used to track the offset and data. */
|
||||||
|
uint64_t cont_offset;
|
||||||
/* last_offset is the largest offset of stream data received for
|
/* last_offset is the largest offset of stream data received for
|
||||||
this stream. */
|
this stream. */
|
||||||
uint64_t last_offset;
|
uint64_t last_offset;
|
||||||
@ -155,6 +167,15 @@ uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm);
|
|||||||
int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
|
int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
|
||||||
size_t datalen, uint64_t offset);
|
size_t datalen, uint64_t offset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_strm_update_rx_offset tells that data up to offset bytes are
|
||||||
|
* received in order.
|
||||||
|
*
|
||||||
|
* NGTCP2_ERR_NOMEM
|
||||||
|
* Out of memory
|
||||||
|
*/
|
||||||
|
int ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_strm_shutdown shutdowns |strm|. |flags| should be
|
* ngtcp2_strm_shutdown shutdowns |strm|. |flags| should be
|
||||||
* NGTCP2_STRM_FLAG_SHUT_RD, and/or NGTCP2_STRM_FLAG_SHUT_WR.
|
* NGTCP2_STRM_FLAG_SHUT_RD, and/or NGTCP2_STRM_FLAG_SHUT_WR.
|
||||||
@ -189,6 +210,12 @@ int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc);
|
|||||||
int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
|
||||||
size_t left);
|
size_t left);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_strm_streamfrq_unacked_offset returns the smallest offset of
|
||||||
|
* unacknowledged stream data held in strm->tx.streamfrq.
|
||||||
|
*/
|
||||||
|
uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ngtcp2_strm_streamfrq_top returns the first ngtcp2_frame_chain.
|
* ngtcp2_strm_streamfrq_top returns the first ngtcp2_frame_chain.
|
||||||
* The queue must not be empty.
|
* The queue must not be empty.
|
||||||
@ -216,4 +243,24 @@ int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm);
|
|||||||
*/
|
*/
|
||||||
int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm);
|
int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_strm_get_unacked_range_after returns the range that is not
|
||||||
|
* acknowledged yet and intersects or comes after |offset|.
|
||||||
|
*/
|
||||||
|
ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm,
|
||||||
|
uint64_t offset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_strm_get_acked_offset returns offset, that is the data up to
|
||||||
|
* this offset have been acknowledged by a remote endpoint. It
|
||||||
|
* returns 0 if no data is acknowledged.
|
||||||
|
*/
|
||||||
|
uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ngtcp2_strm_ack_data tells |strm| that the data [offset,
|
||||||
|
* offset+len) is acknowledged by a remote endpoint.
|
||||||
|
*/
|
||||||
|
int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len);
|
||||||
|
|
||||||
#endif /* NGTCP2_STRM_H */
|
#endif /* NGTCP2_STRM_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user