diff --git a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h index 003ec6b4c3f23c..c2099d24950ac2 100644 --- a/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h +++ b/deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h @@ -627,7 +627,10 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( * @macro * * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` is the maximum length - * of a token generated by `ngtcp2_crypto_generate_regular_token`. + * of a token generated by `ngtcp2_crypto_generate_regular_token`. + * `ngtcp2_crypto_generate_regular_token2` generates a token of length + * at most :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` bytes + the + * length of the provided opaque data. */ #define NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN \ (/* magic = */ 1 + sizeof(ngtcp2_tstamp) + /* aead tag = */ 16 + \ @@ -787,6 +790,77 @@ NGTCP2_EXTERN int ngtcp2_crypto_verify_regular_token( size_t secretlen, const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts); +/** + * @function + * + * `ngtcp2_crypto_generate_regular_token2` generates a token in the + * buffer pointed by |token| that is sent with NEW_TOKEN frame. The + * buffer pointed by |token| must have at least + * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` + |datalen| bytes long. + * The successfully generated token starts with + * :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR`. |secret| of length + * |secretlen| is a keying material to generate keys to encrypt the + * token. |remote_addr| of length |remote_addrlen| is an address of + * client. |ts| is the timestamp when the token is generated. |data| + * of length |datalen| is an opaque data embedded in the token. + * |datalen| must be less than or equal to 256. + * + * Calling this function with |datalen| = 0 is equivalent to calling + * `ngtcp2_crypto_generate_regular_token`. + * + * To get the opaque data after successful verification, use + * `ngtcp2_crypto_verify_regular_token2`. + * `ngtcp2_crypto_verify_regular_token` can verify the token with + * |datalen| > 0, but it discards the opaque data. + * + * This function returns the length of generated token if it succeeds, + * or -1. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_regular_token2( + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const void *data, size_t datalen, ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_crypto_verify_regular_token2` verifies a regular token + * stored in the buffer pointed by |token| of length |tokenlen|. + * |secret| of length |secretlen| is a keying material to generate + * keys to decrypt the token. |remote_addr| of length + * |remote_addrlen| is an address of client. |timeout| is the period + * during which the token is valid. |ts| is the current timestamp. + * |data| is the pointer to the buffer of length at least + * |max_datalen| bytes. If the token is verified successfully, the + * opaque data embedded in the token is copied to the buffer pointed + * by |data|. + * + * If |tokenlen| is less than + * :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN`, this function returns + * :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN`. + * + * If the length of opaque data is larger than |max_datalen|, the + * verification still succeeds, but nothing is written to the buffer + * pointed by |data|, and this function returns 0. In other words, + * the opaque data is discarded. + * + * This function returns the number of the opaque data written to the + * buffer pointed by |data| if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN` + * A token is badly formatted; or verifying the integrity + * protection failed. + * :macro:`NGTCP2_CRYPTO_ERR_VERIFY_TOKEN` + * A token validity has expired. + * :macro:`NGTCP2_CRYPTO_ERR_INTERNAL` + * Internal error occurred. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_verify_regular_token2( + void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts); + /** * @function * diff --git a/deps/ngtcp2/ngtcp2/crypto/ossl/ossl.c b/deps/ngtcp2/ngtcp2/crypto/ossl/ossl.c index 061d6acd21d976..4b4733a2c36c20 100644 --- a/deps/ngtcp2/ngtcp2/crypto/ossl/ossl.c +++ b/deps/ngtcp2/ngtcp2/crypto/ossl/ossl.c @@ -41,70 +41,40 @@ #include "ngtcp2_macro.h" #include "shared.h" -static int crypto_initialized; +#if defined(OPENSSL_NO_CHACHA) || defined(OPENSSL_NO_POLY1305) +# define NGTCP2_NO_CHACHA_POLY1305 +#endif /* defined(OPENSSL_NO_CHACHA) || \ + defined(OPENSSL_NO_POLY1305) */ + static EVP_CIPHER *crypto_aes_128_gcm; static EVP_CIPHER *crypto_aes_256_gcm; -static EVP_CIPHER *crypto_chacha20_poly1305; static EVP_CIPHER *crypto_aes_128_ccm; static EVP_CIPHER *crypto_aes_128_ctr; static EVP_CIPHER *crypto_aes_256_ctr; +#ifndef NGTCP2_NO_CHACHA_POLY1305 +static EVP_CIPHER *crypto_chacha20_poly1305; static EVP_CIPHER *crypto_chacha20; +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ static EVP_MD *crypto_sha256; static EVP_MD *crypto_sha384; static EVP_KDF *crypto_hkdf; int ngtcp2_crypto_ossl_init(void) { + /* We do not care whether the pre-fetch succeeds or not. If it + fails, it returns NULL, which is still the default value, and our + code should still work with it. */ crypto_aes_128_gcm = EVP_CIPHER_fetch(NULL, "AES-128-GCM", NULL); - if (crypto_aes_128_gcm == NULL) { - return -1; - } - crypto_aes_256_gcm = EVP_CIPHER_fetch(NULL, "AES-256-GCM", NULL); - if (crypto_aes_256_gcm == NULL) { - return -1; - } - - crypto_chacha20_poly1305 = EVP_CIPHER_fetch(NULL, "ChaCha20-Poly1305", NULL); - if (crypto_chacha20_poly1305 == NULL) { - return -1; - } - crypto_aes_128_ccm = EVP_CIPHER_fetch(NULL, "AES-128-CCM", NULL); - if (crypto_aes_128_ccm == NULL) { - return -1; - } - crypto_aes_128_ctr = EVP_CIPHER_fetch(NULL, "AES-128-CTR", NULL); - if (crypto_aes_128_ctr == NULL) { - return -1; - } - crypto_aes_256_ctr = EVP_CIPHER_fetch(NULL, "AES-256-CTR", NULL); - if (crypto_aes_256_ctr == NULL) { - return -1; - } - +#ifndef NGTCP2_NO_CHACHA_POLY1305 + crypto_chacha20_poly1305 = EVP_CIPHER_fetch(NULL, "ChaCha20-Poly1305", NULL); crypto_chacha20 = EVP_CIPHER_fetch(NULL, "ChaCha20", NULL); - if (crypto_chacha20 == NULL) { - return -1; - } - +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ crypto_sha256 = EVP_MD_fetch(NULL, "sha256", NULL); - if (crypto_sha256 == NULL) { - return -1; - } - crypto_sha384 = EVP_MD_fetch(NULL, "sha384", NULL); - if (crypto_sha384 == NULL) { - return -1; - } - crypto_hkdf = EVP_KDF_fetch(NULL, "hkdf", NULL); - if (crypto_hkdf == NULL) { - return -1; - } - - crypto_initialized = 1; return 0; } @@ -125,6 +95,7 @@ static const EVP_CIPHER *crypto_aead_aes_256_gcm(void) { return EVP_aes_256_gcm(); } +#ifndef NGTCP2_NO_CHACHA_POLY1305 static const EVP_CIPHER *crypto_aead_chacha20_poly1305(void) { if (crypto_chacha20_poly1305) { return crypto_chacha20_poly1305; @@ -132,6 +103,7 @@ static const EVP_CIPHER *crypto_aead_chacha20_poly1305(void) { return EVP_chacha20_poly1305(); } +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ static const EVP_CIPHER *crypto_aead_aes_128_ccm(void) { if (crypto_aes_128_ccm) { @@ -157,6 +129,7 @@ static const EVP_CIPHER *crypto_cipher_aes_256_ctr(void) { return EVP_aes_256_ctr(); } +#ifndef NGTCP2_NO_CHACHA_POLY1305 static const EVP_CIPHER *crypto_cipher_chacha20(void) { if (crypto_chacha20) { return crypto_chacha20; @@ -164,6 +137,7 @@ static const EVP_CIPHER *crypto_cipher_chacha20(void) { return EVP_chacha20(); } +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ static const EVP_MD *crypto_md_sha256(void) { if (crypto_sha256) { @@ -189,13 +163,21 @@ static EVP_KDF *crypto_kdf_hkdf(void) { return EVP_KDF_fetch(NULL, "hkdf", NULL); } +static void crypto_kdf_hkdf_free(EVP_KDF *kdf) { + if (kdf && crypto_hkdf != kdf) { + EVP_KDF_free(kdf); + } +} + static size_t crypto_aead_max_overhead(const EVP_CIPHER *aead) { switch (EVP_CIPHER_nid(aead)) { case NID_aes_128_gcm: case NID_aes_256_gcm: return EVP_GCM_TLS_TAG_LEN; +#ifndef NGTCP2_NO_CHACHA_POLY1305 case NID_chacha20_poly1305: return EVP_CHACHAPOLY_TLS_TAG_LEN; +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ case NID_aes_128_ccm: return EVP_CCM_TLS_TAG_LEN; default: @@ -239,8 +221,10 @@ static const EVP_CIPHER *crypto_cipher_id_get_aead(uint32_t cipher_id) { return crypto_aead_aes_128_gcm(); case TLS1_3_CK_AES_256_GCM_SHA384: return crypto_aead_aes_256_gcm(); +#ifndef NGTCP2_NO_CHACHA_POLY1305 case TLS1_3_CK_CHACHA20_POLY1305_SHA256: return crypto_aead_chacha20_poly1305(); +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ case TLS1_3_CK_AES_128_CCM_SHA256: return crypto_aead_aes_128_ccm(); default: @@ -253,8 +237,10 @@ static uint64_t crypto_cipher_id_get_aead_max_encryption(uint32_t cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: case TLS1_3_CK_AES_256_GCM_SHA384: return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM; +#ifndef NGTCP2_NO_CHACHA_POLY1305 case TLS1_3_CK_CHACHA20_POLY1305_SHA256: return NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305; +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ case TLS1_3_CK_AES_128_CCM_SHA256: return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_CCM; default: @@ -268,8 +254,10 @@ crypto_cipher_id_get_aead_max_decryption_failure(uint32_t cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: case TLS1_3_CK_AES_256_GCM_SHA384: return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM; +#ifndef NGTCP2_NO_CHACHA_POLY1305 case TLS1_3_CK_CHACHA20_POLY1305_SHA256: return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305; +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ case TLS1_3_CK_AES_128_CCM_SHA256: return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_CCM; default: @@ -284,8 +272,10 @@ static const EVP_CIPHER *crypto_cipher_id_get_hp(uint32_t cipher_id) { return crypto_cipher_aes_128_ctr(); case TLS1_3_CK_AES_256_GCM_SHA384: return crypto_cipher_aes_256_ctr(); +#ifndef NGTCP2_NO_CHACHA_POLY1305 case TLS1_3_CK_CHACHA20_POLY1305_SHA256: return crypto_cipher_chacha20(); +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ default: return NULL; } @@ -294,7 +284,9 @@ static const EVP_CIPHER *crypto_cipher_id_get_hp(uint32_t cipher_id) { static const EVP_MD *crypto_cipher_id_get_md(uint32_t cipher_id) { switch (cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: +#ifndef NGTCP2_NO_CHACHA_POLY1305 case TLS1_3_CK_CHACHA20_POLY1305_SHA256: +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ case TLS1_3_CK_AES_128_CCM_SHA256: return crypto_md_sha256(); case TLS1_3_CK_AES_256_GCM_SHA384: @@ -308,7 +300,9 @@ static int supported_cipher_id(uint32_t cipher_id) { switch (cipher_id) { case TLS1_3_CK_AES_128_GCM_SHA256: case TLS1_3_CK_AES_256_GCM_SHA384: +#ifndef NGTCP2_NO_CHACHA_POLY1305 case TLS1_3_CK_CHACHA20_POLY1305_SHA256: +#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */ case TLS1_3_CK_AES_128_CCM_SHA256: return 1; default: @@ -697,9 +691,7 @@ int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, }; int rv = 0; - if (!crypto_initialized) { - EVP_KDF_free(kdf); - } + crypto_kdf_hkdf_free(kdf); if (EVP_KDF_derive(kctx, dest, (size_t)EVP_MD_size(prf), params) <= 0) { rv = -1; @@ -730,9 +722,7 @@ int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, }; int rv = 0; - if (!crypto_initialized) { - EVP_KDF_free(kdf); - } + crypto_kdf_hkdf_free(kdf); if (EVP_KDF_derive(kctx, dest, destlen, params) <= 0) { rv = -1; @@ -763,9 +753,7 @@ int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen, }; int rv = 0; - if (!crypto_initialized) { - EVP_KDF_free(kdf); - } + crypto_kdf_hkdf_free(kdf); if (EVP_KDF_derive(kctx, dest, destlen, params) <= 0) { rv = -1; diff --git a/deps/ngtcp2/ngtcp2/crypto/shared.c b/deps/ngtcp2/ngtcp2/crypto/shared.c index 98cd4de7e8097d..062efb45e950cc 100644 --- a/deps/ngtcp2/ngtcp2/crypto/shared.c +++ b/deps/ngtcp2/ngtcp2/crypto/shared.c @@ -461,7 +461,9 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key, if (ngtcp2_conn_is_server(conn) && crypto_set_local_transport_params(conn, tls) != 0) { - goto fail; + /* Just return -1 because aead_ctx and hp_ctx are now owned by + conn. */ + return -1; } break; @@ -1305,13 +1307,22 @@ static size_t crypto_generate_regular_token_aad(uint8_t *dest, return addrlen; } +/* NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN is the maximum length of + opaque data embedded in a regular token. */ +#define NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN 256 + +/* NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN is the maximum length + of plaintext included in a regular token. */ +#define NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN \ + (sizeof(ngtcp2_tstamp) + NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN) + static const uint8_t regular_token_info_prefix[] = "regular_token"; -ngtcp2_ssize ngtcp2_crypto_generate_regular_token( +static ngtcp2_ssize crypto_generate_regular_token( uint8_t *token, const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, - ngtcp2_tstamp ts) { - uint8_t plaintext[sizeof(ngtcp2_tstamp)]; + const void *data, size_t datalen, ngtcp2_tstamp ts) { + uint8_t plaintext[NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN]; uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN]; uint8_t key[16]; uint8_t iv[12]; @@ -1328,9 +1339,18 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token( int rv; (void)remote_addrlen; + if (datalen > NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_DATALEN) { + return -1; + } + memcpy(p, &ts_be, sizeof(ts_be)); p += sizeof(ts_be); + if (datalen) { + memcpy(p, data, datalen); + p += datalen; + } + plaintextlen = (size_t)(p - plaintext); if (ngtcp2_crypto_random(rand_data, sizeof(rand_data)) != 0) { @@ -1378,13 +1398,11 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token( return p - token; } -int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, - const uint8_t *secret, size_t secretlen, - const ngtcp2_sockaddr *remote_addr, - ngtcp2_socklen remote_addrlen, - ngtcp2_duration timeout, - ngtcp2_tstamp ts) { - uint8_t plaintext[sizeof(ngtcp2_tstamp)]; +static ngtcp2_ssize crypto_verify_regular_token( + void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts) { + uint8_t plaintext[NGTCP2_CRYPTO_MAX_REGULAR_TOKEN_PLAINTEXTLEN]; uint8_t key[16]; uint8_t iv[12]; size_t keylen; @@ -1397,13 +1415,14 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, const uint8_t *rand_data; const uint8_t *ciphertext; size_t ciphertextlen; + size_t datalen; int rv; ngtcp2_tstamp gen_ts; (void)remote_addrlen; - if (tokenlen != NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN || + if (tokenlen < NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN || token[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR) { - return -1; + return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN; } rand_data = token + tokenlen - NGTCP2_CRYPTO_TOKEN_RAND_DATALEN; @@ -1413,6 +1432,10 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, ngtcp2_crypto_aead_aes_128_gcm(&aead); ngtcp2_crypto_md_sha256(&md); + if (ciphertextlen > sizeof(plaintext) + aead.max_overhead) { + return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN; + } + keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); @@ -1423,13 +1446,13 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN, regular_token_info_prefix, sizeof(regular_token_info_prefix) - 1) != 0) { - return -1; + return NGTCP2_CRYPTO_ERR_INTERNAL; } aadlen = crypto_generate_regular_token_aad(aad, remote_addr); if (ngtcp2_crypto_aead_ctx_decrypt_init(&aead_ctx, &aead, key, ivlen) != 0) { - return -1; + return NGTCP2_CRYPTO_ERR_INTERNAL; } rv = ngtcp2_crypto_decrypt(plaintext, &aead, &aead_ctx, ciphertext, @@ -1438,19 +1461,74 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, ngtcp2_crypto_aead_ctx_free(&aead_ctx); if (rv != 0) { - return -1; + return NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN; } memcpy(&gen_ts, plaintext, sizeof(gen_ts)); gen_ts = ngtcp2_ntohl64(gen_ts); if (gen_ts + timeout <= ts) { + return NGTCP2_CRYPTO_ERR_VERIFY_TOKEN; + } + + if (max_datalen == 0) { + return 0; + } + + datalen = ciphertextlen - aead.max_overhead - sizeof(gen_ts); + if (datalen > max_datalen) { + return 0; + } + + memcpy(data, plaintext + sizeof(gen_ts), datalen); + + return (ngtcp2_ssize)datalen; +} + +ngtcp2_ssize ngtcp2_crypto_generate_regular_token( + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + ngtcp2_tstamp ts) { + return crypto_generate_regular_token(token, secret, secretlen, remote_addr, + remote_addrlen, NULL, 0, ts); +} + +int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, + ngtcp2_duration timeout, + ngtcp2_tstamp ts) { + ngtcp2_ssize datalen = + crypto_verify_regular_token(NULL, 0, token, tokenlen, secret, secretlen, + remote_addr, remote_addrlen, timeout, ts); + + if (datalen < 0) { return -1; } + assert(0 == datalen); + return 0; } +ngtcp2_ssize ngtcp2_crypto_generate_regular_token2( + uint8_t *token, const uint8_t *secret, size_t secretlen, + const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, + const void *data, size_t datalen, ngtcp2_tstamp ts) { + return crypto_generate_regular_token(token, secret, secretlen, remote_addr, + remote_addrlen, data, datalen, ts); +} + +ngtcp2_ssize ngtcp2_crypto_verify_regular_token2( + void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen, + const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr, + ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts) { + return crypto_verify_regular_token(data, max_datalen, token, tokenlen, secret, + secretlen, remote_addr, remote_addrlen, + timeout, ts); +} + ngtcp2_ssize ngtcp2_crypto_write_connection_close( uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, uint64_t error_code, const uint8_t *reason, diff --git a/deps/ngtcp2/ngtcp2/examples/client.cc b/deps/ngtcp2/ngtcp2/examples/client.cc index 0836551079d025..56b757b2d91ed1 100644 --- a/deps/ngtcp2/ngtcp2/examples/client.cc +++ b/deps/ngtcp2/ngtcp2/examples/client.cc @@ -62,10 +62,10 @@ namespace { constexpr size_t max_preferred_versionslen = 4; } // namespace -Config config{}; +Config config; Stream::Stream(const Request &req, int64_t stream_id) - : req(req), stream_id(stream_id), fd(-1) {} + : req{req}, stream_id{stream_id} {} Stream::~Stream() { if (fd != -1) { @@ -175,26 +175,16 @@ void siginthandler(struct ev_loop *loop, ev_signal *w, int revents) { Client::Client(struct ev_loop *loop, uint32_t client_chosen_version, uint32_t original_version) - : remote_addr_{}, - loop_(loop), - httpconn_(nullptr), - addr_(nullptr), - port_(nullptr), - nstreams_done_(0), - nstreams_closed_(0), - nkey_update_(0), - client_chosen_version_(client_chosen_version), - original_version_(original_version), - early_data_(false), - handshake_confirmed_(false), + : loop_{loop}, + client_chosen_version_{client_chosen_version}, + original_version_{original_version}, no_gso_{ #ifdef UDP_SEGMENT - false + config.no_gso #else // !defined(UDP_SEGMENT) true #endif // !defined(UDP_SEGMENT) - }, - tx_{} { + } { ev_io_init(&wev_, writecb, 0, EV_WRITE); wev_.data = this; ev_timer_init(&timer_, timeoutcb, 0., 0.); @@ -563,8 +553,7 @@ int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path, } // namespace void Client::set_remote_addr(const ngtcp2_addr &remote_addr) { - memcpy(&remote_addr_.su, remote_addr.addr, remote_addr.addrlen); - remote_addr_.len = remote_addr.addrlen; + remote_addr_.set(remote_addr.addr); } namespace { @@ -587,8 +576,10 @@ int select_preferred_address(ngtcp2_conn *conn, ngtcp2_path *dest, return NGTCP2_ERR_CALLBACK_FAILURE; } - ngtcp2_addr_copy_byte(&dest->local, &(*ep)->addr.su.sa, (*ep)->addr.len); - ngtcp2_addr_copy_byte(&dest->remote, &remote_addr.su.sa, remote_addr.len); + ngtcp2_addr_copy_byte(&dest->local, (*ep)->addr.as_sockaddr(), + (*ep)->addr.size()); + ngtcp2_addr_copy_byte(&dest->remote, remote_addr.as_sockaddr(), + remote_addr.size()); dest->user_data = *ep; return 0; @@ -821,16 +812,8 @@ int Client::init(int fd, const Address &local_addr, const Address &remote_addr, params.grease_quic_bit = 1; auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&ep.addr.su.sa), - .addrlen = ep.addr.len, - }, - .remote = - { - .addr = const_cast(&remote_addr.su.sa), - .addrlen = remote_addr.len, - }, + .local = as_ngtcp2_addr(ep.addr), + .remote = as_ngtcp2_addr(remote_addr), .user_data = &ep, }; auto rv = @@ -877,16 +860,11 @@ int Client::feed_data(const Endpoint &ep, const sockaddr *sa, socklen_t salen, const ngtcp2_pkt_info *pi, std::span data) { auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&ep.addr.su.sa), - .addrlen = ep.addr.len, - }, - .remote = - { - .addr = const_cast(sa), - .addrlen = salen, - }, + .local = as_ngtcp2_addr(ep.addr), + .remote{ + .addr = const_cast(sa), + .addrlen = salen, + }, .user_data = const_cast(&ep), }; if (auto rv = ngtcp2_conn_read_pkt(conn_, &path, pi, data.data(), data.size(), @@ -916,7 +894,7 @@ int Client::feed_data(const Endpoint &ep, const sockaddr *sa, socklen_t salen, int Client::on_read(const Endpoint &ep) { std::array buf; - sockaddr_union su; + sockaddr_storage ss; size_t pktcnt = 0; ngtcp2_pkt_info pi; @@ -928,14 +906,21 @@ int Client::on_read(const Endpoint &ep) { uint8_t msg_ctrl[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(int))]; msghdr msg{ - .msg_name = &su, + .msg_name = &ss, .msg_iov = &msg_iov, .msg_iovlen = 1, .msg_control = msg_ctrl, }; - for (;;) { - msg.msg_namelen = sizeof(su); + auto start = util::timestamp(); + + for (; pktcnt < MAX_RECV_PKTS;) { + if (util::recv_pkt_time_threshold_exceeded( + config.cc_algo == NGTCP2_CC_ALGO_BBR, start, pktcnt)) { + break; + } + + msg.msg_namelen = sizeof(ss); msg.msg_controllen = sizeof(msg_ctrl); auto nread = recvmsg(ep.fd, &msg, 0); @@ -954,7 +939,7 @@ int Client::on_read(const Endpoint &ep) { continue; } - pi.ecn = msghdr_get_ecn(&msg, su.storage.ss_family); + pi.ecn = msghdr_get_ecn(&msg, ss.ss_family); auto gso_size = msghdr_get_udp_gro(&msg); if (gso_size == 0) { gso_size = static_cast(nread); @@ -968,9 +953,10 @@ int Client::on_read(const Endpoint &ep) { ++pktcnt; if (!config.quiet) { - std::cerr << "Received packet: local=" - << util::straddr(&ep.addr.su.sa, ep.addr.len) - << " remote=" << util::straddr(&su.sa, msg.msg_namelen) + std::cerr << "Received packet: local=" << util::straddr(ep.addr) + << " remote=" + << util::straddr(reinterpret_cast(&ss), + msg.msg_namelen) << " ecn=0x" << std::hex << static_cast(pi.ecn) << std::dec << " " << datalen << " bytes" << std::endl; } @@ -984,8 +970,8 @@ int Client::on_read(const Endpoint &ep) { if (!config.quiet) { std::cerr << "** Simulated incoming packet loss **" << std::endl; } - } else if (feed_data(ep, &su.sa, msg.msg_namelen, &pi, - {data.data(), datalen}) != 0) { + } else if (feed_data(ep, reinterpret_cast(&ss), + msg.msg_namelen, &pi, {data.data(), datalen}) != 0) { return -1; } @@ -995,10 +981,6 @@ int Client::on_read(const Endpoint &ep) { break; } } - - if (pktcnt >= 10) { - break; - } } if (should_exit()) { @@ -1157,18 +1139,21 @@ int Client::write_streams() { ngtcp2_pkt_info pi; size_t gso_size; auto ts = util::timestamp(); - auto txbuf = std::span{tx_.data}; + auto txbuf = std::span{txbuf_}; + auto buflen = util::clamp_buffer_size(conn_, txbuf.size(), config.gso_burst); ngtcp2_path_storage_zero(&ps); - auto nwrite = - ngtcp2_conn_write_aggregate_pkt(conn_, &ps.path, &pi, txbuf.data(), - txbuf.size(), &gso_size, ::write_pkt, ts); + auto nwrite = ngtcp2_conn_write_aggregate_pkt2( + conn_, &ps.path, &pi, txbuf.data(), buflen, &gso_size, ::write_pkt, + config.gso_burst, ts); if (nwrite < 0) { disconnect(); return -1; } + ngtcp2_conn_update_pkt_tx_time(conn_, ts); + if (nwrite == 0) { return 0; } @@ -1223,8 +1208,7 @@ void Client::update_timer() { #ifdef HAVE_LINUX_RTNETLINK_H namespace { -int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, - int family) { +int bind_addr(Address &local_addr, int fd, const InAddr &ia, int family) { addrinfo hints{ .ai_flags = AI_PASSIVE, .ai_family = family, @@ -1234,15 +1218,16 @@ int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, char *node; std::array nodebuf; - if (iau) { - if (inet_ntop(family, iau, nodebuf.data(), nodebuf.size()) == nullptr) { + if (in_addr_empty(ia)) { + node = nullptr; + } else { + if (inet_ntop(family, in_addr_get_ptr(ia), nodebuf.data(), + nodebuf.size()) == nullptr) { std::cerr << "inet_ntop: " << strerror(errno) << std::endl; return -1; } node = nodebuf.data(); - } else { - node = nullptr; } if (auto rv = getaddrinfo(node, "0", &hints, &res); rv != 0) { @@ -1250,7 +1235,7 @@ int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, return -1; } - auto res_d = defer(freeaddrinfo, res); + auto res_d = defer([res] { freeaddrinfo(res); }); for (rp = res; rp; rp = rp->ai_next) { if (bind(fd, rp->ai_addr, rp->ai_addrlen) != -1) { @@ -1263,13 +1248,14 @@ int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, return -1; } - socklen_t len = sizeof(local_addr.su.storage); - if (getsockname(fd, &local_addr.su.sa, &len) == -1) { + sockaddr_storage ss; + socklen_t len = sizeof(ss); + if (getsockname(fd, reinterpret_cast(&ss), &len) == -1) { std::cerr << "getsockname: " << strerror(errno) << std::endl; return -1; } - local_addr.len = len; - local_addr.ifindex = 0; + + local_addr.set(reinterpret_cast(&ss)); return 0; } @@ -1279,18 +1265,19 @@ int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, #ifndef HAVE_LINUX_RTNETLINK_H namespace { int connect_sock(Address &local_addr, int fd, const Address &remote_addr) { - if (connect(fd, &remote_addr.su.sa, remote_addr.len) != 0) { + if (connect(fd, remote_addr.as_sockaddr(), remote_addr.size()) != 0) { std::cerr << "connect: " << strerror(errno) << std::endl; return -1; } - socklen_t len = sizeof(local_addr.su.storage); - if (getsockname(fd, &local_addr.su.sa, &len) == -1) { + sockaddr_storage ss; + socklen_t len = sizeof(ss); + if (getsockname(fd, reinterpret_cast(&ss), &len) == -1) { std::cerr << "getsockname: " << strerror(errno) << std::endl; return -1; } - local_addr.len = len; - local_addr.ifindex = 0; + + local_addr.set(reinterpret_cast(&ss)); return 0; } @@ -1326,7 +1313,7 @@ int create_sock(Address &remote_addr, const char *addr, const char *port) { return -1; } - auto res_d = defer(freeaddrinfo, res); + auto res_d = defer([res] { freeaddrinfo(res); }); int fd = -1; @@ -1344,9 +1331,7 @@ int create_sock(Address &remote_addr, const char *addr, const char *port) { return -1; } - remote_addr.len = rp->ai_addrlen; - memcpy(&remote_addr.su, rp->ai_addr, rp->ai_addrlen); - remote_addr.ifindex = 0; + remote_addr.set(rp->ai_addr); return fd; } @@ -1354,9 +1339,9 @@ int create_sock(Address &remote_addr, const char *addr, const char *port) { std::optional Client::endpoint_for(const Address &remote_addr) { #ifdef HAVE_LINUX_RTNETLINK_H - in_addr_union iau; + InAddr ia; - if (get_local_addr(iau, remote_addr) != 0) { + if (get_local_addr(ia, remote_addr) != 0) { std::cerr << "Could not get local address for a selected preferred address" << std::endl; return nullptr; @@ -1364,12 +1349,14 @@ std::optional Client::endpoint_for(const Address &remote_addr) { auto current_path = ngtcp2_conn_get_path(conn_); auto current_ep = static_cast(current_path->user_data); - if (addreq(¤t_ep->addr.su.sa, iau)) { + if (addreq(current_ep->addr, ia)) { return current_ep; } #endif // defined(HAVE_LINUX_RTNETLINK_H) - auto fd = udp_sock(remote_addr.su.sa.sa_family); + auto family = remote_addr.family(); + + auto fd = udp_sock(family); if (fd == -1) { return nullptr; } @@ -1377,7 +1364,7 @@ std::optional Client::endpoint_for(const Address &remote_addr) { Address local_addr; #ifdef HAVE_LINUX_RTNETLINK_H - if (bind_addr(local_addr, fd, &iau, remote_addr.su.sa.sa_family) != 0) { + if (bind_addr(local_addr, fd, ia, family) != 0) { close(fd); return nullptr; } @@ -1412,21 +1399,23 @@ int Client::change_local_addr() { std::cerr << "Changing local address" << std::endl; } - auto nfd = udp_sock(remote_addr_.su.sa.sa_family); + auto family = remote_addr_.family(); + + auto nfd = udp_sock(family); if (nfd == -1) { return -1; } #ifdef HAVE_LINUX_RTNETLINK_H - in_addr_union iau; + InAddr ia; - if (get_local_addr(iau, remote_addr_) != 0) { + if (get_local_addr(ia, remote_addr_) != 0) { std::cerr << "Could not get local address" << std::endl; close(nfd); return -1; } - if (bind_addr(local_addr, nfd, &iau, remote_addr_.su.sa.sa_family) != 0) { + if (bind_addr(local_addr, nfd, ia, family) != 0) { close(nfd); return -1; } @@ -1438,8 +1427,8 @@ int Client::change_local_addr() { #endif // !defined(HAVE_LINUX_RTNETLINK_H) if (!config.quiet) { - std::cerr << "Local address is now " - << util::straddr(&local_addr.su.sa, local_addr.len) << std::endl; + std::cerr << "Local address is now " << util::straddr(local_addr) + << std::endl; } endpoints_.emplace_back(); @@ -1450,8 +1439,7 @@ int Client::change_local_addr() { ev_io_init(&ep.rev, readcb, nfd, EV_READ); ep.rev.data = &ep; - ngtcp2_addr addr; - ngtcp2_addr_init(&addr, &local_addr.su.sa, local_addr.len); + auto addr = as_ngtcp2_addr(local_addr); if (config.nat_rebinding) { ngtcp2_conn_set_local_addr(conn_, &addr); @@ -1459,11 +1447,7 @@ int Client::change_local_addr() { } else { auto path = ngtcp2_path{ .local = addr, - .remote = - { - .addr = const_cast(&remote_addr_.su.sa), - .addrlen = remote_addr_.len, - }, + .remote = as_ngtcp2_addr(remote_addr_), .user_data = &ep, }; if (auto rv = ngtcp2_conn_initiate_immediate_migration(conn_, &path, @@ -1672,8 +1656,7 @@ Client::send_packet(const Endpoint &ep, const ngtcp2_addr &remote_addr, assert(static_cast(nwrite) == data.size()); if (!config.quiet) { - std::cerr << "Sent packet: local=" - << util::straddr(&ep.addr.su.sa, ep.addr.len) << " remote=" + std::cerr << "Sent packet: local=" << util::straddr(ep.addr) << " remote=" << util::straddr(remote_addr.addr, remote_addr.addrlen) << " ecn=0x" << std::hex << ecn << std::dec << " " << nwrite << " bytes" << std::endl; @@ -1691,11 +1674,10 @@ void Client::on_send_blocked(const ngtcp2_path &path, unsigned int ecn, auto &p = tx_.blocked; - memcpy(&p.remote_addr.su, path.remote.addr, path.remote.addrlen); + p.remote_addr.set(path.remote.addr); auto &ep = *static_cast(path.user_data); - p.remote_addr.len = path.remote.addrlen; p.endpoint = &ep; p.ecn = ecn; p.data = data; @@ -1723,13 +1705,8 @@ int Client::send_blocked_packet() { auto &p = tx_.blocked; - ngtcp2_addr remote_addr{ - .addr = &p.remote_addr.su.sa, - .addrlen = p.remote_addr.len, - }; - - auto [rest, rv] = - send_packet(*p.endpoint, remote_addr, p.ecn, p.data, p.gso_size); + auto [rest, rv] = send_packet(*p.endpoint, as_ngtcp2_addr(p.remote_addr), + p.ecn, p.data, p.gso_size); if (rv != 0) { assert(NETWORK_ERR_SEND_BLOCKED == rv); @@ -1785,6 +1762,7 @@ int Client::on_stream_close(int64_t stream_id, uint64_t app_error_code) { auto rv = nghttp3_conn_close_stream(httpconn_, stream_id, app_error_code); switch (rv) { case 0: + http_stream_close(stream_id, app_error_code); break; case NGHTTP3_ERR_STREAM_NOT_FOUND: // We have to handle the case when stream opened but no data is @@ -1924,11 +1902,11 @@ int Client::submit_http_request(const Stream *stream) { int Client::recv_stream_data(uint32_t flags, int64_t stream_id, std::span data) { - auto nconsumed = - nghttp3_conn_read_stream(httpconn_, stream_id, data.data(), data.size(), - flags & NGTCP2_STREAM_DATA_FLAG_FIN); + auto nconsumed = nghttp3_conn_read_stream2( + httpconn_, stream_id, data.data(), data.size(), + flags & NGTCP2_STREAM_DATA_FLAG_FIN, ngtcp2_conn_get_timestamp(conn_)); if (nconsumed < 0) { - std::cerr << "nghttp3_conn_read_stream: " + std::cerr << "nghttp3_conn_read_stream2: " << nghttp3_strerror(static_cast(nconsumed)) << std::endl; ngtcp2_ccerr_set_application_error( &last_error_, @@ -1964,15 +1942,13 @@ int Client::select_preferred_address(Address &selected_addr, if (!paddr->ipv4_present) { return -1; } - selected_addr.su.in = paddr->ipv4; - selected_addr.len = sizeof(paddr->ipv4); + selected_addr.skaddr.emplace(paddr->ipv4); break; case AF_INET6: if (!paddr->ipv6_present) { return -1; } - selected_addr.su.in6 = paddr->ipv6; - selected_addr.len = sizeof(paddr->ipv6); + selected_addr.skaddr.emplace(paddr->ipv6); break; default: return -1; @@ -1980,8 +1956,8 @@ int Client::select_preferred_address(Address &selected_addr, if (!config.quiet) { char host[NI_MAXHOST], service[NI_MAXSERV]; - if (auto rv = getnameinfo(&selected_addr.su.sa, selected_addr.len, host, - sizeof(host), service, sizeof(service), + if (auto rv = getnameinfo(selected_addr.as_sockaddr(), selected_addr.size(), + host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); rv != 0) { std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl; @@ -2149,41 +2125,31 @@ int Client::reset_stream(int64_t stream_id, uint64_t app_error_code) { return 0; } -namespace { -int http_stream_close(nghttp3_conn *conn, int64_t stream_id, - uint64_t app_error_code, void *conn_user_data, - void *stream_user_data) { - auto c = static_cast(conn_user_data); - if (c->http_stream_close(stream_id, app_error_code) != 0) { - return NGHTTP3_ERR_CALLBACK_FAILURE; +void Client::http_stream_close(int64_t stream_id, uint64_t app_error_code) { + if (!ngtcp2_is_bidi_stream(stream_id)) { + return; } - return 0; -} -} // namespace -int Client::http_stream_close(int64_t stream_id, uint64_t app_error_code) { - if (ngtcp2_is_bidi_stream(stream_id)) { - assert(ngtcp2_conn_is_local_stream(conn_, stream_id)); + assert(ngtcp2_conn_is_local_stream(conn_, stream_id)); - ++nstreams_closed_; - } else { - assert(!ngtcp2_conn_is_local_stream(conn_, stream_id)); - ngtcp2_conn_extend_max_streams_uni(conn_, 1); + ++nstreams_closed_; + + auto it = streams_.find(stream_id); + if (it == std::ranges::end(streams_)) { + return; } - if (auto it = streams_.find(stream_id); it != std::ranges::end(streams_)) { - if (!config.quiet) { - std::cerr << "HTTP stream " << stream_id << " closed with error code " - << app_error_code << std::endl; - } - streams_.erase(it); + if (!config.quiet) { + std::cerr << "HTTP stream " << stream_id << " closed with error code " + << app_error_code << std::endl; } - return 0; + streams_.erase(it); } namespace { -int http_recv_settings(nghttp3_conn *conn, const nghttp3_settings *settings, +int http_recv_settings(nghttp3_conn *conn, + const nghttp3_proto_settings *settings, void *conn_user_data) { if (!config.quiet) { debug::print_http_settings(settings); @@ -2226,7 +2192,6 @@ int Client::setup_httpconn() { } nghttp3_callbacks callbacks{ - .stream_close = ::http_stream_close, .recv_data = ::http_recv_data, .deferred_consume = ::http_deferred_consume, .begin_headers = ::http_begin_headers, @@ -2237,10 +2202,10 @@ int Client::setup_httpconn() { .end_trailers = ::http_end_trailers, .stop_sending = ::http_stop_sending, .reset_stream = ::http_reset_stream, - .recv_settings = ::http_recv_settings, .recv_origin = ::http_recv_origin, .end_origin = ::http_end_origin, .rand = rand_bytes, + .recv_settings2 = ::http_recv_settings, }; nghttp3_settings settings; nghttp3_settings_default(&settings); @@ -2329,15 +2294,15 @@ int run(Client &c, const char *addr, const char *port, } #ifdef HAVE_LINUX_RTNETLINK_H - in_addr_union iau; + InAddr ia; - if (get_local_addr(iau, remote_addr) != 0) { + if (get_local_addr(ia, remote_addr) != 0) { std::cerr << "Could not get local address" << std::endl; close(fd); return -1; } - if (bind_addr(local_addr, fd, &iau, remote_addr.su.sa.sa_family) != 0) { + if (bind_addr(local_addr, fd, ia, remote_addr.family()) != 0) { close(fd); return -1; } @@ -2436,35 +2401,11 @@ void print_usage() { } } // namespace -namespace { -void config_set_default(Config &config) { - config = Config{ - .tx_loss_prob = 0., - .rx_loss_prob = 0., - .fd = -1, - .ciphers = util::crypto_default_ciphers(), - .groups = util::crypto_default_groups(), - .version = NGTCP2_PROTO_VER_V1, - .timeout = 30 * NGTCP2_SECONDS, - .http_method = "GET"sv, - .max_data = 24_m, - .max_stream_data_bidi_local = 16_m, - .max_stream_data_uni = 16_m, - .max_streams_uni = 100, - .cc_algo = NGTCP2_CC_ALGO_CUBIC, - .initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT, - .handshake_timeout = UINT64_MAX, - .ack_thresh = 2, - .initial_pkt_num = UINT32_MAX, - }; -} -} // namespace - namespace { void print_help() { print_usage(); - config_set_default(config); + Config config; std::cout << R"( Remote server host (DNS name or IP address). In case of @@ -2677,6 +2618,15 @@ void print_help() { the handshake fails with ech_required alert, ECH retry configs, if provided by server, will be written to . + --no-gso Disables GSO. + --show-stat Print the connection statistics when the connection is + closed. + --gso-burst= + The maximum number of packets to aggregate for GSO. If + GSO is disabled, this is the maximum number of packets + to send per an event loop in a single connection. It + defaults to 0, which means it is not limited by the + configuration. -h, --help Display this help and exit. --- @@ -2697,7 +2647,6 @@ void print_help() { } // namespace int main(int argc, char **argv) { - config_set_default(config); char *data_path = nullptr; const char *private_key_file = nullptr; const char *cert_file = nullptr; @@ -2762,6 +2711,9 @@ int main(int argc, char **argv) { {"initial-pkt-num", required_argument, &flag, 42}, {"pmtud-probes", required_argument, &flag, 43}, {"ech-config-list-file", required_argument, &flag, 44}, + {"no-gso", no_argument, &flag, 45}, + {"show-stat", no_argument, &flag, 46}, + {"gso-burst", required_argument, &flag, 47}, {}, }; @@ -3092,9 +3044,9 @@ int main(int argc, char **argv) { if (auto n = util::parse_uint_iec(optarg); !n) { std::cerr << "max-udp-payload-size: invalid argument" << std::endl; exit(EXIT_FAILURE); - } else if (*n > 64_k) { - std::cerr << "max-udp-payload-size: must not exceed 65536" - << std::endl; + } else if (*n > NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE) { + std::cerr << "max-udp-payload-size: must not exceed " + << NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE << std::endl; exit(EXIT_FAILURE); } else if (*n == 0) { std::cerr << "max-udp-payload-size: must not be 0" << std::endl; @@ -3212,10 +3164,12 @@ int main(int argc, char **argv) { if (auto n = util::parse_uint_iec(s); !n) { std::cerr << "pmtud-probes: invalid argument" << std::endl; exit(EXIT_FAILURE); - } else if (*n <= 1200 || *n >= 64_k) { - std::cerr - << "pmtud-probes: must be in range [1201, 65535], inclusive." - << std::endl; + } else if (*n <= NGTCP2_MAX_UDP_PAYLOAD_SIZE || + *n > NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE) { + std::cerr << "pmtud-probes: must be in range [" + << NGTCP2_MAX_UDP_PAYLOAD_SIZE + 1 << ", " + << NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE << "], inclusive." + << std::endl; exit(EXIT_FAILURE); } else { config.pmtud_probes.push_back(static_cast(*n)); @@ -3226,12 +3180,38 @@ int main(int argc, char **argv) { case 44: // --ech-config-list-file config.ech_config_list_file = optarg; + break; + case 45: + // --no-gso + config.no_gso = true; + break; + case 46: + // --show-stat + config.show_stat = true; + break; + case 47: { + // --gso-burst + auto n = util::parse_uint(optarg); + if (!n) { + std::cerr << "gso-burst: invalid argument" << std::endl; + exit(EXIT_FAILURE); + } + + if (*n > 64) { + std::cerr << "gso-burst: must be in range [0, 64], inclusive." + << std::endl; + exit(EXIT_FAILURE); + } + + config.gso_burst = static_cast(*n); + break; } + } break; default: break; - }; + } } if (argc - optind < 2) { @@ -3327,7 +3307,7 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - auto ev_loop_d = defer(ev_loop_destroy, EV_DEFAULT); + auto ev_loop_d = defer([] { ev_loop_destroy(EV_DEFAULT); }); auto keylog_filename = getenv("SSLKEYLOGFILE"); if (keylog_filename) { diff --git a/deps/ngtcp2/ngtcp2/examples/client.h b/deps/ngtcp2/ngtcp2/examples/client.h index 31182f253a0c9a..e2a779493172bd 100644 --- a/deps/ngtcp2/ngtcp2/examples/client.h +++ b/deps/ngtcp2/ngtcp2/examples/client.h @@ -59,7 +59,7 @@ struct Stream { Request req; int64_t stream_id; - int fd; + int fd{-1}; }; class Client; @@ -67,8 +67,8 @@ class Client; struct Endpoint { Address addr; ev_io rev; - Client *client; - int fd; + Client *client{}; + int fd{}; }; class Client : public ClientBase { @@ -133,7 +133,7 @@ class Client : public ClientBase { int extend_max_stream_data(int64_t stream_id, uint64_t max_data); int stop_sending(int64_t stream_id, uint64_t app_error_code); int reset_stream(int64_t stream_id, uint64_t app_error_code); - int http_stream_close(int64_t stream_id, uint64_t app_error_code); + void http_stream_close(int64_t stream_id, uint64_t app_error_code); void on_send_blocked(const ngtcp2_path &path, unsigned int ecn, std::span data, size_t gso_size); @@ -161,24 +161,24 @@ class Client : public ClientBase { struct ev_loop *loop_; std::unordered_map> streams_; std::vector offered_versions_; - nghttp3_conn *httpconn_; + nghttp3_conn *httpconn_{}; // addr_ is the server host address. - const char *addr_; + const char *addr_{}; // port_ is the server port. - const char *port_; + const char *port_{}; // nstreams_done_ is the number of streams opened. - size_t nstreams_done_; + size_t nstreams_done_{}; // nstreams_closed_ is the number of streams get closed. - size_t nstreams_closed_; + size_t nstreams_closed_{}; // nkey_update_ is the number of key update occurred. - size_t nkey_update_; + size_t nkey_update_{}; uint32_t client_chosen_version_; uint32_t original_version_; // early_data_ is true if client attempts to do 0RTT data transfer. - bool early_data_; + bool early_data_{}; // handshake_confirmed_ gets true after handshake has been // confirmed. - bool handshake_confirmed_; + bool handshake_confirmed_{}; bool no_gso_; struct { @@ -191,8 +191,8 @@ class Client : public ClientBase { std::span data; size_t gso_size; } blocked; - std::array data; - } tx_; + } tx_{}; + std::array txbuf_; }; #endif // !defined(CLIENT_H) diff --git a/deps/ngtcp2/ngtcp2/examples/client_base.cc b/deps/ngtcp2/ngtcp2/examples/client_base.cc index 29b1483acafc05..57af4244697998 100644 --- a/deps/ngtcp2/ngtcp2/examples/client_base.cc +++ b/deps/ngtcp2/ngtcp2/examples/client_base.cc @@ -43,16 +43,16 @@ static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) { return c->conn(); } -ClientBase::ClientBase() - : conn_ref_{get_conn, this}, - qlog_(nullptr), - conn_(nullptr), - ticket_received_(false) { +ClientBase::ClientBase() : conn_ref_{get_conn, this} { ngtcp2_ccerr_default(&last_error_); } ClientBase::~ClientBase() { if (conn_) { + if (config.show_stat) { + debug::print_conn_info(conn_); + } + ngtcp2_conn_del(conn_); } diff --git a/deps/ngtcp2/ngtcp2/examples/client_base.h b/deps/ngtcp2/ngtcp2/examples/client_base.h index fb7ec9d948204e..6e8a0f600c1c29 100644 --- a/deps/ngtcp2/ngtcp2/examples/client_base.h +++ b/deps/ngtcp2/ngtcp2/examples/client_base.h @@ -40,6 +40,7 @@ #include "tls_client_session.h" #include "network.h" #include "shared.h" +#include "util.h" using namespace ngtcp2; @@ -50,55 +51,55 @@ struct Request { }; struct Config { - ngtcp2_cid dcid; - ngtcp2_cid scid; - bool scid_present; + ngtcp2_cid dcid{}; + ngtcp2_cid scid{}; + bool scid_present{}; // tx_loss_prob is probability of losing outgoing packet. - double tx_loss_prob; + double tx_loss_prob{}; // rx_loss_prob is probability of losing incoming packet. - double rx_loss_prob; + double rx_loss_prob{}; // fd is a file descriptor to read input for streams. - int fd; + int fd{-1}; // ciphers is the list of enabled ciphers. - const char *ciphers; + const char *ciphers{util::crypto_default_ciphers()}; // groups is the list of supported groups. - const char *groups; + const char *groups{util::crypto_default_groups()}; // nstreams is the number of streams to open. - size_t nstreams; + size_t nstreams{}; // data is the pointer to memory region which maps file denoted by // fd. - uint8_t *data; + uint8_t *data{}; // datalen is the length of file denoted by fd. - size_t datalen; + size_t datalen{}; // version is a QUIC version to use. - uint32_t version; + uint32_t version{NGTCP2_PROTO_VER_V1}; // quiet suppresses the output normally shown except for the error // messages. - bool quiet; + bool quiet{}; // timeout is an idle timeout for QUIC connection. - ngtcp2_duration timeout; + ngtcp2_duration timeout{30 * NGTCP2_SECONDS}; // session_file is a path to a file to write, and read TLS session. - const char *session_file; + const char *session_file{}; // tp_file is a path to a file to write, and read QUIC transport // parameters. - const char *tp_file; + const char *tp_file{}; // show_secret is true if transport secrets should be printed out. - bool show_secret; + bool show_secret{}; // change_local_addr is the duration after which client changes // local address. - ngtcp2_duration change_local_addr; + ngtcp2_duration change_local_addr{}; // key_update is the duration after which client initiates key // update. - ngtcp2_duration key_update; + ngtcp2_duration key_update{}; // delay_stream is the duration after which client sends the first // 1-RTT stream. - ngtcp2_duration delay_stream; + ngtcp2_duration delay_stream{}; // nat_rebinding is true if simulated NAT rebinding is enabled. - bool nat_rebinding; + bool nat_rebinding{}; // no_preferred_addr is true if client do not follow preferred // address offered by server. - bool no_preferred_addr; - std::string_view http_method; + bool no_preferred_addr{}; + std::string_view http_method{"GET"sv}; // download is a path to a directory where a downloaded file is // saved. If it is empty, no file is saved. std::string_view download; @@ -106,55 +107,55 @@ struct Config { std::vector requests; // no_quic_dump is true if hexdump of QUIC STREAM and CRYPTO data // should be disabled. - bool no_quic_dump; + bool no_quic_dump{}; // no_http_dump is true if hexdump of HTTP response body should be // disabled. - bool no_http_dump; + bool no_http_dump{}; // qlog_file is the path to write qlog. std::string_view qlog_file; // qlog_dir is the path to directory where qlog is stored. qlog_dir // and qlog_file are mutually exclusive. std::string_view qlog_dir; // max_data is the initial connection-level flow control window. - uint64_t max_data; + uint64_t max_data{24_m}; // max_stream_data_bidi_local is the initial stream-level flow // control window for a bidirectional stream that the local endpoint // initiates. - uint64_t max_stream_data_bidi_local; + uint64_t max_stream_data_bidi_local{16_m}; // max_stream_data_bidi_remote is the initial stream-level flow // control window for a bidirectional stream that the remote // endpoint initiates. - uint64_t max_stream_data_bidi_remote; + uint64_t max_stream_data_bidi_remote{}; // max_stream_data_uni is the initial stream-level flow control // window for a unidirectional stream. - uint64_t max_stream_data_uni; + uint64_t max_stream_data_uni{16_m}; // max_streams_bidi is the number of the concurrent bidirectional // streams. - uint64_t max_streams_bidi; + uint64_t max_streams_bidi{}; // max_streams_uni is the number of the concurrent unidirectional // streams. - uint64_t max_streams_uni; + uint64_t max_streams_uni{100}; // max_window is the maximum connection-level flow control window // size if auto-tuning is enabled. - uint64_t max_window; + uint64_t max_window{}; // max_stream_window is the maximum stream-level flow control window // size if auto-tuning is enabled. - uint64_t max_stream_window; + uint64_t max_stream_window{}; // exit_on_first_stream_close is the flag that if it is true, client // exits when a first HTTP stream gets closed. It is not // necessarily the same time when the underlying QUIC stream closes // due to the QPACK synchronization. - bool exit_on_first_stream_close; + bool exit_on_first_stream_close{}; // exit_on_all_streams_close is the flag that if it is true, client // exits when all HTTP streams get closed. - bool exit_on_all_streams_close; + bool exit_on_all_streams_close{}; // disable_early_data disables early data. - bool disable_early_data; + bool disable_early_data{}; // static_secret is used to derive keying materials for Stateless // Retry token. std::array static_secret; // cc_algo is the congestion controller algorithm. - ngtcp2_cc_algo cc_algo; + ngtcp2_cc_algo cc_algo{NGTCP2_CC_ALGO_CUBIC}; // token_file is a path to file to read or write token from // NEW_TOKEN frame. std::string_view token_file; @@ -162,13 +163,13 @@ struct Config { // remote host. std::string_view sni; // initial_rtt is an initial RTT. - ngtcp2_duration initial_rtt; + ngtcp2_duration initial_rtt{NGTCP2_DEFAULT_INITIAL_RTT}; // max_udp_payload_size is the maximum UDP payload size that client // transmits. - size_t max_udp_payload_size; + size_t max_udp_payload_size{}; // handshake_timeout is the period of time before giving up QUIC // connection establishment. - ngtcp2_duration handshake_timeout; + ngtcp2_duration handshake_timeout{UINT64_MAX}; // preferred_versions includes QUIC versions in the order of // preference. Client uses this field to select a version from the // version set offered in Version Negotiation packet. @@ -178,24 +179,32 @@ struct Config { // transport_parameter. std::vector available_versions; // no_pmtud disables Path MTU Discovery. - bool no_pmtud; + bool no_pmtud{}; // ack_thresh is the minimum number of the received ACK eliciting // packets that triggers immediate acknowledgement. - size_t ack_thresh; + size_t ack_thresh{2}; // wait_for_ticket, if true, waits for a ticket to be received // before exiting on exit_on_first_stream_close or // exit_on_all_streams_close. - bool wait_for_ticket; + bool wait_for_ticket{}; // initial_pkt_num is the initial packet number for each packet // number space. If it is set to UINT32_MAX, it is chosen randomly. - uint32_t initial_pkt_num; + uint32_t initial_pkt_num{UINT32_MAX}; // pmtud_probes is the array of UDP datagram payload size to probes. std::vector pmtud_probes; // ech_config_list contains ECHConfigList. std::vector ech_config_list; // ech_config_list_file is a path to a file to read and write // ECHConfigList. - const char *ech_config_list_file; + const char *ech_config_list_file{}; + // no_gso disables GSO. + bool no_gso{}; + // show_stat, if true, displays the connection statistics when the + // connection is closed. + bool show_stat{}; + // gso_burst is the number of packets to aggregate in GSO. 0 means + // it is not limited by the configuration. + size_t gso_burst{}; }; class ClientBase { @@ -218,10 +227,10 @@ class ClientBase { protected: ngtcp2_crypto_conn_ref conn_ref_; TLSClientSession tls_session_; - FILE *qlog_; - ngtcp2_conn *conn_; + FILE *qlog_{}; + ngtcp2_conn *conn_{}; ngtcp2_ccerr last_error_; - bool ticket_received_; + bool ticket_received_{}; }; void qlog_write_cb(void *user_data, uint32_t flags, const void *data, diff --git a/deps/ngtcp2/ngtcp2/examples/debug.cc b/deps/ngtcp2/ngtcp2/examples/debug.cc index 8abe80b0f9b1ef..c5216b958558d4 100644 --- a/deps/ngtcp2/ngtcp2/examples/debug.cc +++ b/deps/ngtcp2/ngtcp2/examples/debug.cc @@ -283,7 +283,7 @@ void print_http_response_headers(int64_t stream_id, const nghttp3_nv *nva, } } -void print_http_settings(const nghttp3_settings *settings) { +void print_http_settings(const nghttp3_proto_settings *settings) { fprintf(outfile, "http: remote settings\n" "http: SETTINGS_MAX_FIELD_SECTION_SIZE=%" PRIu64 "\n" @@ -317,6 +317,29 @@ std::string_view secret_title(ngtcp2_encryption_level level) { } } +void print_conn_info(ngtcp2_conn *conn) { + ngtcp2_conn_info cinfo; + + ngtcp2_conn_get_conn_info(conn, &cinfo); + + std::cout << "# Connection Statistics (see ngtcp2_conn_info for details)\n" + "min_rtt=" + << util::format_durationf(cinfo.min_rtt) << '\n' + << "smoothed_rtt=" << util::format_durationf(cinfo.smoothed_rtt) + << '\n' + << "rttvar=" << util::format_durationf(cinfo.rttvar) << '\n' + << "cwnd=" << cinfo.cwnd << '\n' + << "ssthresh=" << cinfo.ssthresh << '\n' + << "pkt_sent=" << cinfo.pkt_sent << '\n' + << "bytes_sent=" << cinfo.bytes_sent << '\n' + << "pkt_recv=" << cinfo.pkt_recv << '\n' + << "bytes_recv=" << cinfo.bytes_recv << '\n' + << "pkt_lost=" << cinfo.pkt_lost << '\n' + << "bytes_lost=" << cinfo.bytes_lost << '\n' + << "ping_recv=" << cinfo.ping_recv << '\n' + << "pkt_discarded=" << cinfo.pkt_discarded << std::endl; +} + } // namespace debug } // namespace ngtcp2 diff --git a/deps/ngtcp2/ngtcp2/examples/debug.h b/deps/ngtcp2/ngtcp2/examples/debug.h index b0f520785267fe..0ccf6ac1049298 100644 --- a/deps/ngtcp2/ngtcp2/examples/debug.h +++ b/deps/ngtcp2/ngtcp2/examples/debug.h @@ -116,7 +116,7 @@ void print_http_request_headers(int64_t stream_id, const nghttp3_nv *nva, void print_http_response_headers(int64_t stream_id, const nghttp3_nv *nva, size_t nvlen); -void print_http_settings(const nghttp3_settings *settings); +void print_http_settings(const nghttp3_proto_settings *settings); void print_http_origin(const uint8_t *origin, size_t originlen); @@ -124,6 +124,8 @@ void print_http_end_origin(); std::string_view secret_title(ngtcp2_encryption_level level); +void print_conn_info(ngtcp2_conn *conn); + } // namespace debug } // namespace ngtcp2 diff --git a/deps/ngtcp2/ngtcp2/examples/examplestest.cc b/deps/ngtcp2/ngtcp2/examples/examplestest.cc index 537e96c24e06ae..9e0fbed9d6b2d3 100644 --- a/deps/ngtcp2/ngtcp2/examples/examplestest.cc +++ b/deps/ngtcp2/ngtcp2/examples/examplestest.cc @@ -32,11 +32,17 @@ // include test cases' include files here #include "util_test.h" #include "siphash_test.h" +#ifdef WITH_EXAMPLE_WOLFSSL +# include "sim_test.h" +#endif // defined(WITH_EXAMPLE_WOLFSSL) int main(int argc, char *argv[]) { const MunitSuite suites[] = { ngtcp2::util_suite, ngtcp2::siphash_suite, +#ifdef WITH_EXAMPLE_WOLFSSL + ngtcp2::sim_suite, +#endif // defined(WITH_EXAMPLE_WOLFSSL) {}, }; const MunitSuite suite = { diff --git a/deps/ngtcp2/ngtcp2/examples/h09client.cc b/deps/ngtcp2/ngtcp2/examples/h09client.cc index 579c2232c0b32e..ef350eb8db0fef 100644 --- a/deps/ngtcp2/ngtcp2/examples/h09client.cc +++ b/deps/ngtcp2/ngtcp2/examples/h09client.cc @@ -62,10 +62,10 @@ namespace { constexpr size_t max_preferred_versionslen = 4; } // namespace -Config config{}; +Config config; Stream::Stream(const Request &req, int64_t stream_id) - : req(req), stream_id(stream_id), fd(-1) { + : req{req}, stream_id{stream_id} { nghttp3_buf_init(&reqbuf); } @@ -177,25 +177,16 @@ void siginthandler(struct ev_loop *loop, ev_signal *w, int revents) { Client::Client(struct ev_loop *loop, uint32_t client_chosen_version, uint32_t original_version) - : remote_addr_{}, - loop_(loop), - addr_(nullptr), - port_(nullptr), - nstreams_done_(0), - nstreams_closed_(0), - nkey_update_(0), - client_chosen_version_(client_chosen_version), - original_version_(original_version), - early_data_(false), - handshake_confirmed_(false), + : loop_{loop}, + client_chosen_version_{client_chosen_version}, + original_version_{original_version}, no_gso_{ #ifdef UDP_SEGMENT - false + config.no_gso #else // !defined(UDP_SEGMENT) true #endif // !defined(UDP_SEGMENT) - }, - tx_{} { + } { ev_io_init(&wev_, writecb, 0, EV_WRITE); wev_.data = this; ev_timer_init(&timer_, timeoutcb, 0., 0.); @@ -515,8 +506,7 @@ int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path, } // namespace void Client::set_remote_addr(const ngtcp2_addr &remote_addr) { - memcpy(&remote_addr_.su, remote_addr.addr, remote_addr.addrlen); - remote_addr_.len = remote_addr.addrlen; + remote_addr_.set(remote_addr.addr); } namespace { @@ -539,8 +529,10 @@ int select_preferred_address(ngtcp2_conn *conn, ngtcp2_path *dest, return NGTCP2_ERR_CALLBACK_FAILURE; } - ngtcp2_addr_copy_byte(&dest->local, &(*ep)->addr.su.sa, (*ep)->addr.len); - ngtcp2_addr_copy_byte(&dest->remote, &remote_addr.su.sa, remote_addr.len); + ngtcp2_addr_copy_byte(&dest->local, (*ep)->addr.as_sockaddr(), + (*ep)->addr.size()); + ngtcp2_addr_copy_byte(&dest->remote, remote_addr.as_sockaddr(), + remote_addr.size()); dest->user_data = *ep; return 0; @@ -750,16 +742,8 @@ int Client::init(int fd, const Address &local_addr, const Address &remote_addr, params.grease_quic_bit = 1; auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&ep.addr.su.sa), - .addrlen = ep.addr.len, - }, - .remote = - { - .addr = const_cast(&remote_addr.su.sa), - .addrlen = remote_addr.len, - }, + .local = as_ngtcp2_addr(ep.addr), + .remote = as_ngtcp2_addr(remote_addr), .user_data = &ep, }; auto rv = @@ -806,16 +790,11 @@ int Client::feed_data(const Endpoint &ep, const sockaddr *sa, socklen_t salen, const ngtcp2_pkt_info *pi, std::span data) { auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&ep.addr.su.sa), - .addrlen = ep.addr.len, - }, - .remote = - { - .addr = const_cast(sa), - .addrlen = salen, - }, + .local = as_ngtcp2_addr(ep.addr), + .remote{ + .addr = const_cast(sa), + .addrlen = salen, + }, .user_data = const_cast(&ep), }; if (auto rv = ngtcp2_conn_read_pkt(conn_, &path, pi, data.data(), data.size(), @@ -845,7 +824,7 @@ int Client::feed_data(const Endpoint &ep, const sockaddr *sa, socklen_t salen, int Client::on_read(const Endpoint &ep) { std::array buf; - sockaddr_union su; + sockaddr_storage ss; size_t pktcnt = 0; ngtcp2_pkt_info pi; @@ -857,14 +836,21 @@ int Client::on_read(const Endpoint &ep) { uint8_t msg_ctrl[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(int))]; msghdr msg{ - .msg_name = &su, + .msg_name = &ss, .msg_iov = &msg_iov, .msg_iovlen = 1, .msg_control = msg_ctrl, }; - for (;;) { - msg.msg_namelen = sizeof(su); + auto start = util::timestamp(); + + for (; pktcnt < MAX_RECV_PKTS;) { + if (util::recv_pkt_time_threshold_exceeded( + config.cc_algo == NGTCP2_CC_ALGO_BBR, start, pktcnt)) { + break; + } + + msg.msg_namelen = sizeof(ss); msg.msg_controllen = sizeof(msg_ctrl); auto nread = recvmsg(ep.fd, &msg, 0); @@ -883,7 +869,7 @@ int Client::on_read(const Endpoint &ep) { continue; } - pi.ecn = msghdr_get_ecn(&msg, su.storage.ss_family); + pi.ecn = msghdr_get_ecn(&msg, ss.ss_family); auto gso_size = msghdr_get_udp_gro(&msg); if (gso_size == 0) { gso_size = static_cast(nread); @@ -897,9 +883,10 @@ int Client::on_read(const Endpoint &ep) { ++pktcnt; if (!config.quiet) { - std::cerr << "Received packet: local=" - << util::straddr(&ep.addr.su.sa, ep.addr.len) - << " remote=" << util::straddr(&su.sa, msg.msg_namelen) + std::cerr << "Received packet: local=" << util::straddr(ep.addr) + << " remote=" + << util::straddr(reinterpret_cast(&ss), + msg.msg_namelen) << " ecn=0x" << std::hex << static_cast(pi.ecn) << std::dec << " " << datalen << " bytes" << std::endl; } @@ -913,8 +900,8 @@ int Client::on_read(const Endpoint &ep) { if (!config.quiet) { std::cerr << "** Simulated incoming packet loss **" << std::endl; } - } else if (feed_data(ep, &su.sa, msg.msg_namelen, &pi, - {data.data(), datalen}) != 0) { + } else if (feed_data(ep, reinterpret_cast(&ss), + msg.msg_namelen, &pi, {data.data(), datalen}) != 0) { return -1; } @@ -924,10 +911,6 @@ int Client::on_read(const Endpoint &ep) { break; } } - - if (pktcnt >= 10) { - break; - } } if (should_exit()) { @@ -1057,18 +1040,21 @@ int Client::write_streams() { ngtcp2_pkt_info pi; size_t gso_size; auto ts = util::timestamp(); - auto txbuf = std::span{tx_.data}; + auto txbuf = std::span{txbuf_}; + auto buflen = util::clamp_buffer_size(conn_, txbuf.size(), config.gso_burst); ngtcp2_path_storage_zero(&ps); - auto nwrite = - ngtcp2_conn_write_aggregate_pkt(conn_, &ps.path, &pi, txbuf.data(), - txbuf.size(), &gso_size, ::write_pkt, ts); + auto nwrite = ngtcp2_conn_write_aggregate_pkt2( + conn_, &ps.path, &pi, txbuf.data(), buflen, &gso_size, ::write_pkt, + config.gso_burst, ts); if (nwrite < 0) { disconnect(); return -1; } + ngtcp2_conn_update_pkt_tx_time(conn_, ts); + if (nwrite == 0) { return 0; } @@ -1123,8 +1109,7 @@ void Client::update_timer() { #ifdef HAVE_LINUX_RTNETLINK_H namespace { -int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, - int family) { +int bind_addr(Address &local_addr, int fd, const InAddr &ia, int family) { addrinfo hints{ .ai_flags = AI_PASSIVE, .ai_family = family, @@ -1134,15 +1119,16 @@ int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, char *node; std::array nodebuf; - if (iau) { - if (inet_ntop(family, iau, nodebuf.data(), nodebuf.size()) == nullptr) { + if (in_addr_empty(ia)) { + node = nullptr; + } else { + if (inet_ntop(family, in_addr_get_ptr(ia), nodebuf.data(), + nodebuf.size()) == nullptr) { std::cerr << "inet_ntop: " << strerror(errno) << std::endl; return -1; } node = nodebuf.data(); - } else { - node = nullptr; } if (auto rv = getaddrinfo(node, "0", &hints, &res); rv != 0) { @@ -1150,7 +1136,7 @@ int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, return -1; } - auto res_d = defer(freeaddrinfo, res); + auto res_d = defer([res] { freeaddrinfo(res); }); for (rp = res; rp; rp = rp->ai_next) { if (bind(fd, rp->ai_addr, rp->ai_addrlen) != -1) { @@ -1163,13 +1149,14 @@ int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, return -1; } - socklen_t len = sizeof(local_addr.su.storage); - if (getsockname(fd, &local_addr.su.sa, &len) == -1) { + sockaddr_storage ss; + socklen_t len = sizeof(ss); + if (getsockname(fd, reinterpret_cast(&ss), &len) == -1) { std::cerr << "getsockname: " << strerror(errno) << std::endl; return -1; } - local_addr.len = len; - local_addr.ifindex = 0; + + local_addr.set(reinterpret_cast(&ss)); return 0; } @@ -1179,18 +1166,19 @@ int bind_addr(Address &local_addr, int fd, const in_addr_union *iau, #ifndef HAVE_LINUX_RTNETLINK_H namespace { int connect_sock(Address &local_addr, int fd, const Address &remote_addr) { - if (connect(fd, &remote_addr.su.sa, remote_addr.len) != 0) { + if (connect(fd, remote_addr.as_sockaddr(), remote_addr.size()) != 0) { std::cerr << "connect: " << strerror(errno) << std::endl; return -1; } - socklen_t len = sizeof(local_addr.su.storage); - if (getsockname(fd, &local_addr.su.sa, &len) == -1) { + sockaddr_storage ss; + socklen_t len = sizeof(ss); + if (getsockname(fd, reinterpret_cast(&ss), &len) == -1) { std::cerr << "getsockname: " << strerror(errno) << std::endl; return -1; } - local_addr.len = len; - local_addr.ifindex = 0; + + local_addr.set(reinterpret_cast(&ss)); return 0; } @@ -1226,7 +1214,7 @@ int create_sock(Address &remote_addr, const char *addr, const char *port) { return -1; } - auto res_d = defer(freeaddrinfo, res); + auto res_d = defer([res] { freeaddrinfo(res); }); int fd = -1; @@ -1244,9 +1232,7 @@ int create_sock(Address &remote_addr, const char *addr, const char *port) { return -1; } - remote_addr.len = rp->ai_addrlen; - memcpy(&remote_addr.su, rp->ai_addr, rp->ai_addrlen); - remote_addr.ifindex = 0; + remote_addr.set(rp->ai_addr); return fd; } @@ -1254,9 +1240,9 @@ int create_sock(Address &remote_addr, const char *addr, const char *port) { std::optional Client::endpoint_for(const Address &remote_addr) { #ifdef HAVE_LINUX_RTNETLINK_H - in_addr_union iau; + InAddr ia; - if (get_local_addr(iau, remote_addr) != 0) { + if (get_local_addr(ia, remote_addr) != 0) { std::cerr << "Could not get local address for a selected preferred address" << std::endl; return nullptr; @@ -1264,12 +1250,14 @@ std::optional Client::endpoint_for(const Address &remote_addr) { auto current_path = ngtcp2_conn_get_path(conn_); auto current_ep = static_cast(current_path->user_data); - if (addreq(¤t_ep->addr.su.sa, iau)) { + if (addreq(current_ep->addr, ia)) { return current_ep; } #endif // defined(HAVE_LINUX_RTNETLINK_H) - auto fd = udp_sock(remote_addr.su.sa.sa_family); + auto family = remote_addr.family(); + + auto fd = udp_sock(family); if (fd == -1) { return nullptr; } @@ -1277,7 +1265,7 @@ std::optional Client::endpoint_for(const Address &remote_addr) { Address local_addr; #ifdef HAVE_LINUX_RTNETLINK_H - if (bind_addr(local_addr, fd, &iau, remote_addr.su.sa.sa_family) != 0) { + if (bind_addr(local_addr, fd, ia, family) != 0) { close(fd); return nullptr; } @@ -1312,21 +1300,23 @@ int Client::change_local_addr() { std::cerr << "Changing local address" << std::endl; } - auto nfd = udp_sock(remote_addr_.su.sa.sa_family); + auto family = remote_addr_.family(); + + auto nfd = udp_sock(family); if (nfd == -1) { return -1; } #ifdef HAVE_LINUX_RTNETLINK_H - in_addr_union iau; + InAddr ia; - if (get_local_addr(iau, remote_addr_) != 0) { + if (get_local_addr(ia, remote_addr_) != 0) { std::cerr << "Could not get local address" << std::endl; close(nfd); return -1; } - if (bind_addr(local_addr, nfd, &iau, remote_addr_.su.sa.sa_family) != 0) { + if (bind_addr(local_addr, nfd, ia, family) != 0) { close(nfd); return -1; } @@ -1338,8 +1328,8 @@ int Client::change_local_addr() { #endif // !defined(HAVE_LINUX_RTNETLINK_H) if (!config.quiet) { - std::cerr << "Local address is now " - << util::straddr(&local_addr.su.sa, local_addr.len) << std::endl; + std::cerr << "Local address is now " << util::straddr(local_addr) + << std::endl; } endpoints_.emplace_back(); @@ -1350,8 +1340,7 @@ int Client::change_local_addr() { ev_io_init(&ep.rev, readcb, nfd, EV_READ); ep.rev.data = &ep; - ngtcp2_addr addr; - ngtcp2_addr_init(&addr, &local_addr.su.sa, local_addr.len); + auto addr = as_ngtcp2_addr(local_addr); if (config.nat_rebinding) { ngtcp2_conn_set_local_addr(conn_, &addr); @@ -1359,11 +1348,7 @@ int Client::change_local_addr() { } else { auto path = ngtcp2_path{ .local = addr, - .remote = - { - .addr = const_cast(&remote_addr_.su.sa), - .addrlen = remote_addr_.len, - }, + .remote = as_ngtcp2_addr(remote_addr_), .user_data = &ep, }; if (auto rv = ngtcp2_conn_initiate_immediate_migration(conn_, &path, @@ -1572,8 +1557,7 @@ Client::send_packet(const Endpoint &ep, const ngtcp2_addr &remote_addr, assert(static_cast(nwrite) == data.size()); if (!config.quiet) { - std::cerr << "Sent packet: local=" - << util::straddr(&ep.addr.su.sa, ep.addr.len) << " remote=" + std::cerr << "Sent packet: local=" << util::straddr(ep.addr) << " remote=" << util::straddr(remote_addr.addr, remote_addr.addrlen) << " ecn=0x" << std::hex << ecn << std::dec << " " << nwrite << " bytes" << std::endl; @@ -1591,11 +1575,10 @@ void Client::on_send_blocked(const ngtcp2_path &path, unsigned int ecn, auto &p = tx_.blocked; - memcpy(&p.remote_addr.su, path.remote.addr, path.remote.addrlen); + p.remote_addr.set(path.remote.addr); auto &ep = *static_cast(path.user_data); - p.remote_addr.len = path.remote.addrlen; p.endpoint = &ep; p.ecn = ecn; p.data = data; @@ -1623,13 +1606,8 @@ int Client::send_blocked_packet() { auto &p = tx_.blocked; - ngtcp2_addr remote_addr{ - .addr = &p.remote_addr.su.sa, - .addrlen = p.remote_addr.len, - }; - - auto [rest, rv] = - send_packet(*p.endpoint, remote_addr, p.ecn, p.data, p.gso_size); + auto [rest, rv] = send_packet(*p.endpoint, as_ngtcp2_addr(p.remote_addr), + p.ecn, p.data, p.gso_size); if (rv != 0) { assert(NETWORK_ERR_SEND_BLOCKED == rv); @@ -1801,15 +1779,13 @@ int Client::select_preferred_address(Address &selected_addr, if (!paddr->ipv4_present) { return -1; } - selected_addr.su.in = paddr->ipv4; - selected_addr.len = sizeof(paddr->ipv4); + selected_addr.skaddr.emplace(paddr->ipv4); break; case AF_INET6: if (!paddr->ipv6_present) { return -1; } - selected_addr.su.in6 = paddr->ipv6; - selected_addr.len = sizeof(paddr->ipv6); + selected_addr.skaddr.emplace(paddr->ipv6); break; default: return -1; @@ -1817,8 +1793,8 @@ int Client::select_preferred_address(Address &selected_addr, if (!config.quiet) { char host[NI_MAXHOST], service[NI_MAXSERV]; - if (auto rv = getnameinfo(&selected_addr.su.sa, selected_addr.len, host, - sizeof(host), service, sizeof(service), + if (auto rv = getnameinfo(selected_addr.as_sockaddr(), selected_addr.size(), + host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); rv != 0) { std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl; @@ -1847,15 +1823,15 @@ int run(Client &c, const char *addr, const char *port, } #ifdef HAVE_LINUX_RTNETLINK_H - in_addr_union iau; + InAddr ia; - if (get_local_addr(iau, remote_addr) != 0) { + if (get_local_addr(ia, remote_addr) != 0) { std::cerr << "Could not get local address" << std::endl; close(fd); return -1; } - if (bind_addr(local_addr, fd, &iau, remote_addr.su.sa.sa_family) != 0) { + if (bind_addr(local_addr, fd, ia, remote_addr.family()) != 0) { close(fd); return -1; } @@ -1949,35 +1925,11 @@ void print_usage() { } } // namespace -namespace { -void config_set_default(Config &config) { - config = Config{ - .tx_loss_prob = 0., - .rx_loss_prob = 0., - .fd = -1, - .ciphers = util::crypto_default_ciphers(), - .groups = util::crypto_default_groups(), - .version = NGTCP2_PROTO_VER_V1, - .timeout = 30 * NGTCP2_SECONDS, - .http_method = "GET"sv, - .max_data = 24_m, - .max_stream_data_bidi_local = 16_m, - .max_stream_data_uni = 16_m, - .max_streams_uni = 100, - .cc_algo = NGTCP2_CC_ALGO_CUBIC, - .initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT, - .handshake_timeout = UINT64_MAX, - .ack_thresh = 2, - .initial_pkt_num = UINT32_MAX, - }; -} -} // namespace - namespace { void print_help() { print_usage(); - config_set_default(config); + Config config; std::cout << R"( Remote server host (DNS name or IP address). In case of @@ -2186,6 +2138,15 @@ void print_help() { the handshake fails with ech_required alert, ECH retry configs, if provided by server, will be written to . + --no-gso Disables GSO. + --show-stat Print the connection statistics when the connection is + closed. + --gso-burst= + The maximum number of packets to aggregate for GSO. If + GSO is disabled, this is the maximum number of packets + to send per an event loop in a single connection. It + defaults to 0, which means it is not limited by the + configuration. -h, --help Display this help and exit. --- @@ -2206,7 +2167,6 @@ void print_help() { } // namespace int main(int argc, char **argv) { - config_set_default(config); char *data_path = nullptr; const char *private_key_file = nullptr; const char *cert_file = nullptr; @@ -2270,6 +2230,9 @@ int main(int argc, char **argv) { {"initial-pkt-num", required_argument, &flag, 42}, {"pmtud-probes", required_argument, &flag, 43}, {"ech-config-list-file", required_argument, &flag, 44}, + {"no-gso", no_argument, &flag, 45}, + {"show-stat", no_argument, &flag, 46}, + {"gso-burst", required_argument, &flag, 47}, {}, }; @@ -2580,9 +2543,9 @@ int main(int argc, char **argv) { if (auto n = util::parse_uint_iec(optarg); !n) { std::cerr << "max-udp-payload-size: invalid argument" << std::endl; exit(EXIT_FAILURE); - } else if (*n > 64_k) { - std::cerr << "max-udp-payload-size: must not exceed 65536" - << std::endl; + } else if (*n > NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE) { + std::cerr << "max-udp-payload-size: must not exceed " + << NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE << std::endl; exit(EXIT_FAILURE); } else if (*n == 0) { std::cerr << "max-udp-payload-size: must not be 0" << std::endl; @@ -2700,10 +2663,12 @@ int main(int argc, char **argv) { if (auto n = util::parse_uint_iec(s); !n) { std::cerr << "pmtud-probes: invalid argument" << std::endl; exit(EXIT_FAILURE); - } else if (*n <= 1200 || *n >= 64_k) { - std::cerr - << "pmtud-probes: must be in range [1201, 65535], inclusive." - << std::endl; + } else if (*n <= NGTCP2_MAX_UDP_PAYLOAD_SIZE || + *n > NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE) { + std::cerr << "pmtud-probes: must be in range [" + << NGTCP2_MAX_UDP_PAYLOAD_SIZE + 1 << ", " + << NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE << "], inclusive." + << std::endl; exit(EXIT_FAILURE); } else { config.pmtud_probes.push_back(static_cast(*n)); @@ -2715,11 +2680,37 @@ int main(int argc, char **argv) { // --ech-config-list-file config.ech_config_list_file = optarg; break; + case 45: + // --no-gso + config.no_gso = true; + break; + case 46: + // --show-stat + config.show_stat = true; + break; + case 47: { + // --gso-burst + auto n = util::parse_uint(optarg); + if (!n) { + std::cerr << "gso-burst: invalid argument" << std::endl; + exit(EXIT_FAILURE); + } + + if (*n > 64) { + std::cerr << "gso-burst: must be in range [0, 64], inclusive." + << std::endl; + exit(EXIT_FAILURE); + } + + config.gso_burst = static_cast(*n); + + break; + } } break; default: break; - }; + } } if (argc - optind < 2) { @@ -2815,7 +2806,7 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - auto ev_loop_d = defer(ev_loop_destroy, EV_DEFAULT); + auto ev_loop_d = defer([] { ev_loop_destroy(EV_DEFAULT); }); auto keylog_filename = getenv("SSLKEYLOGFILE"); if (keylog_filename) { diff --git a/deps/ngtcp2/ngtcp2/examples/h09client.h b/deps/ngtcp2/ngtcp2/examples/h09client.h index 681b5ca426245a..4fa848e4126345 100644 --- a/deps/ngtcp2/ngtcp2/examples/h09client.h +++ b/deps/ngtcp2/ngtcp2/examples/h09client.h @@ -61,7 +61,7 @@ struct Stream { Request req; int64_t stream_id; - int fd; + int fd{-1}; std::string rawreqbuf; nghttp3_buf reqbuf; }; @@ -77,8 +77,8 @@ class Client; struct Endpoint { Address addr; ev_io rev; - Client *client; - int fd; + Client *client{}; + int fd{}; }; class Client : public ClientBase { @@ -167,22 +167,22 @@ class Client : public ClientBase { std::set sendq_; std::vector offered_versions_; // addr_ is the server host address. - const char *addr_; + const char *addr_{}; // port_ is the server port. - const char *port_; + const char *port_{}; // nstreams_done_ is the number of streams opened. - size_t nstreams_done_; + size_t nstreams_done_{}; // nstreams_closed_ is the number of streams get closed. - size_t nstreams_closed_; + size_t nstreams_closed_{}; // nkey_update_ is the number of key update occurred. - size_t nkey_update_; + size_t nkey_update_{}; uint32_t client_chosen_version_; uint32_t original_version_; // early_data_ is true if client attempts to do 0RTT data transfer. - bool early_data_; + bool early_data_{}; // handshake_confirmed_ gets true after handshake has been // confirmed. - bool handshake_confirmed_; + bool handshake_confirmed_{}; bool no_gso_; struct { @@ -195,8 +195,8 @@ class Client : public ClientBase { std::span data; size_t gso_size; } blocked; - std::array data; - } tx_; + } tx_{}; + std::array txbuf_; }; #endif // !defined(H09CLIENT_H) diff --git a/deps/ngtcp2/ngtcp2/examples/h09server.cc b/deps/ngtcp2/ngtcp2/examples/h09server.cc index 061d7bc93e7b7a..6f6102ac7d2011 100644 --- a/deps/ngtcp2/ngtcp2/examples/h09server.cc +++ b/deps/ngtcp2/ngtcp2/examples/h09server.cc @@ -66,22 +66,14 @@ namespace { constexpr size_t max_preferred_versionslen = 4; } // namespace -namespace { -constexpr size_t NGTCP2_STATELESS_RESET_BURST = 100; -} // namespace - -namespace { -constexpr size_t NGTCP2_TX_BUFLEN = 64_k; -} // namespace - namespace { auto randgen = util::make_mt19937(); } // namespace -Config config{}; +Config config; Stream::Stream(int64_t stream_id, Handler *handler) - : stream_id(stream_id), handler(handler), eos(false) { + : stream_id{stream_id}, handler{handler} { nghttp3_buf_init(&respbuf); htp.data = this; http_parser_init(&htp, HTTP_REQUEST); @@ -156,10 +148,10 @@ enum FileEntryFlag { }; struct FileEntry { - uint64_t len; - void *map; - int fd; - uint8_t flags; + uint64_t len{}; + void *map{}; + int fd{}; + uint8_t flags{}; }; namespace { @@ -183,7 +175,7 @@ std::pair Stream::open_file(const std::string &path) { return {{}, -1}; } - FileEntry fe{}; + FileEntry fe; if (st.st_mode & S_IFDIR) { fe.flags |= FILE_ENTRY_TYPE_DIR; fe.fd = -1; @@ -319,10 +311,7 @@ void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { goto fail; } - rv = h->on_write(); - if (rv != 0) { - goto fail; - } + h->signal_write(); return; @@ -339,23 +328,14 @@ void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { } // namespace Handler::Handler(struct ev_loop *loop, Server *server) - : loop_(loop), - server_(server), - qlog_(nullptr), - scid_{}, - nkey_update_(0), + : loop_{loop}, + server_{server}, no_gso_{ #ifdef UDP_SEGMENT - false + config.no_gso #else // !defined(UDP_SEGMENT) true #endif // !defined(UDP_SEGMENT) - }, - close_wait_{ - .next_pkts_recv = 1, - }, - tx_{ - .data = std::unique_ptr(new uint8_t[NGTCP2_TX_BUFLEN]), } { ev_io_init(&wev_, writecb, 0, EV_WRITE); wev_.data = this; @@ -416,19 +396,17 @@ int Handler::handshake_completed() { token.data(), config.static_secret.data(), config.static_secret.size(), path->remote.addr, path->remote.addrlen, t); if (tokenlen < 0) { - if (!config.quiet) { - std::cerr << "Unable to generate token" << std::endl; - } + std::cerr << "Unable to generate token" << std::endl; + return 0; } if (auto rv = ngtcp2_conn_submit_new_token(conn_, token.data(), as_unsigned(tokenlen)); rv != 0) { - if (!config.quiet) { - std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv) - << std::endl; - } + std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv) + << std::endl; + return -1; } @@ -515,9 +493,9 @@ void Handler::on_stream_open(int64_t stream_id) { if (!ngtcp2_is_bidi_stream(stream_id)) { return; } - auto it = streams_.find(stream_id); - (void)it; - assert(it == std::ranges::end(streams_)); + + assert(!streams_.contains(stream_id)); + streams_.emplace(stream_id, std::make_unique(stream_id, this)); } @@ -610,9 +588,7 @@ int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path, token.data(), config.static_secret.data(), config.static_secret.size(), path->remote.addr, path->remote.addrlen, t); if (tokenlen < 0) { - if (!config.quiet) { - std::cerr << "Unable to generate token" << std::endl; - } + std::cerr << "Unable to generate token" << std::endl; return 0; } @@ -620,10 +596,8 @@ int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path, if (auto rv = ngtcp2_conn_submit_new_token(conn, token.data(), as_unsigned(tokenlen)); rv != 0) { - if (!config.quiet) { - std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv) - << std::endl; - } + std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv) + << std::endl; return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -670,7 +644,7 @@ void Handler::write_qlog(const void *data, size_t datalen) { } int Handler::init(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, const ngtcp2_cid *dcid, + const Address &remote_addr, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, const ngtcp2_cid *ocid, std::span token, ngtcp2_token_type token_type, uint32_t version, TLSServerContext &tls_ctx) { @@ -789,16 +763,19 @@ int Handler::init(const Endpoint &ep, const Address &local_addr, return -1; } - if (config.preferred_ipv4_addr.len || config.preferred_ipv6_addr.len) { + if (!config.preferred_ipv4_addr.empty() || + !config.preferred_ipv6_addr.empty()) { params.preferred_addr_present = 1; - if (config.preferred_ipv4_addr.len) { - params.preferred_addr.ipv4 = config.preferred_ipv4_addr.su.in; + if (!config.preferred_ipv4_addr.empty()) { + params.preferred_addr.ipv4 = + std::get(config.preferred_ipv4_addr.skaddr); params.preferred_addr.ipv4_present = 1; } - if (config.preferred_ipv6_addr.len) { - params.preferred_addr.ipv6 = config.preferred_ipv6_addr.su.in6; + if (!config.preferred_ipv6_addr.empty()) { + params.preferred_addr.ipv6 = + std::get(config.preferred_ipv6_addr.skaddr); params.preferred_addr.ipv6_present = 1; } @@ -820,16 +797,8 @@ int Handler::init(const Endpoint &ep, const Address &local_addr, } auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }, - .remote = - { - .addr = const_cast(sa), - .addrlen = salen, - }, + .local = as_ngtcp2_addr(local_addr), + .remote = as_ngtcp2_addr(remote_addr), .user_data = const_cast(&ep), }; if (auto rv = @@ -854,20 +823,11 @@ int Handler::init(const Endpoint &ep, const Address &local_addr, } int Handler::feed_data(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, - const ngtcp2_pkt_info *pi, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data) { auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }, - .remote = - { - .addr = const_cast(sa), - .addrlen = salen, - }, + .local = as_ngtcp2_addr(local_addr), + .remote = as_ngtcp2_addr(remote_addr), .user_data = const_cast(&ep), }; @@ -901,9 +861,9 @@ int Handler::feed_data(const Endpoint &ep, const Address &local_addr, } int Handler::on_read(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, - const ngtcp2_pkt_info *pi, std::span data) { - if (auto rv = feed_data(ep, local_addr, sa, salen, pi, data); rv != 0) { + const Address &remote_addr, const ngtcp2_pkt_info *pi, + std::span data) { + if (auto rv = feed_data(ep, local_addr, remote_addr, pi, data); rv != 0) { return rv; } @@ -1030,17 +990,20 @@ int Handler::write_streams() { ngtcp2_pkt_info pi; size_t gso_size; auto ts = util::timestamp(); - auto txbuf = std::span{tx_.data.get(), NGTCP2_TX_BUFLEN}; + auto txbuf = std::span{txbuf_}; + auto buflen = util::clamp_buffer_size(conn_, txbuf.size(), config.gso_burst); ngtcp2_path_storage_zero(&ps); - auto nwrite = - ngtcp2_conn_write_aggregate_pkt(conn_, &ps.path, &pi, txbuf.data(), - txbuf.size(), &gso_size, ::write_pkt, ts); + auto nwrite = ngtcp2_conn_write_aggregate_pkt2( + conn_, &ps.path, &pi, txbuf.data(), buflen, &gso_size, ::write_pkt, + config.gso_burst, ts); if (nwrite < 0) { return handle_error(); } + ngtcp2_conn_update_pkt_tx_time(conn_, ts); + if (nwrite == 0) { return 0; } @@ -1078,11 +1041,9 @@ void Handler::on_send_blocked(const ngtcp2_path &path, unsigned int ecn, auto &p = tx_.blocked; - memcpy(&p.local_addr.su, path.local.addr, path.local.addrlen); - memcpy(&p.remote_addr.su, path.remote.addr, path.remote.addrlen); + p.local_addr.set(path.local.addr); + p.remote_addr.set(path.remote.addr); - p.local_addr.len = path.local.addrlen; - p.remote_addr.len = path.remote.addrlen; p.endpoint = static_cast(path.user_data); p.ecn = ecn; p.data = data; @@ -1108,17 +1069,9 @@ int Handler::send_blocked_packet() { auto &p = tx_.blocked; - ngtcp2_addr local_addr{ - .addr = &p.local_addr.su.sa, - .addrlen = p.local_addr.len, - }; - ngtcp2_addr remote_addr{ - .addr = &p.remote_addr.su.sa, - .addrlen = p.remote_addr.len, - }; - auto [rest, rv] = server_->send_packet( - *p.endpoint, no_gso_, local_addr, remote_addr, p.ecn, p.data, p.gso_size); + *p.endpoint, no_gso_, as_ngtcp2_addr(p.local_addr), + as_ngtcp2_addr(p.remote_addr), p.ecn, p.data, p.gso_size); if (rv != 0) { assert(NETWORK_ERR_SEND_BLOCKED == rv); @@ -1230,7 +1183,7 @@ int Handler::send_conn_close() { } int Handler::send_conn_close(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data) { assert(conn_closebuf_ && conn_closebuf_->size()); @@ -1244,21 +1197,8 @@ int Handler::send_conn_close(const Endpoint &ep, const Address &local_addr, return 0; } - auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }, - .remote = - { - .addr = const_cast(sa), - .addrlen = salen, - }, - .user_data = const_cast(&ep), - }; - - auto rv = server_->send_packet(ep, path.local, path.remote, + auto rv = server_->send_packet(ep, as_ngtcp2_addr(local_addr), + as_ngtcp2_addr(remote_addr), /* ecn = */ 0, conn_closebuf_->data()); if (rv != 0) { return rv; @@ -1444,9 +1384,7 @@ void siginthandler(struct ev_loop *loop, ev_signal *watcher, int revents) { } // namespace Server::Server(struct ev_loop *loop, TLSServerContext &tls_ctx) - : loop_(loop), - tls_ctx_(tls_ctx), - stateless_reset_bucket_(NGTCP2_STATELESS_RESET_BURST) { + : loop_{loop}, tls_ctx_{tls_ctx} { ev_signal_init(&sigintev_, siginthandler, SIGINT); ev_timer_init( @@ -1513,7 +1451,7 @@ int create_sock(Address &local_addr, const char *addr, const char *port, return -1; } - auto res_d = defer(freeaddrinfo, res); + auto res_d = defer([res] { freeaddrinfo(res); }); int fd = -1; @@ -1565,14 +1503,15 @@ int create_sock(Address &local_addr, const char *addr, const char *port, return -1; } - socklen_t len = sizeof(local_addr.su.storage); - if (getsockname(fd, &local_addr.su.sa, &len) == -1) { + sockaddr_storage ss; + socklen_t len = sizeof(ss); + if (getsockname(fd, reinterpret_cast(&ss), &len) == -1) { std::cerr << "getsockname: " << strerror(errno) << std::endl; close(fd); return -1; } - local_addr.len = len; - local_addr.ifindex = 0; + + local_addr.set(reinterpret_cast(&ss)); return fd; } @@ -1593,6 +1532,7 @@ int add_endpoint(std::vector &endpoints, const char *addr, ep.addr = dest; ep.fd = fd; ev_io_init(&ep.rev, sreadcb, 0, EV_READ); + ev_set_priority(&ep.rev, EV_MAXPRI); return 0; } @@ -1600,14 +1540,16 @@ int add_endpoint(std::vector &endpoints, const char *addr, namespace { int add_endpoint(std::vector &endpoints, const Address &addr) { - auto fd = util::create_nonblock_socket(addr.su.sa.sa_family, SOCK_DGRAM, 0); + auto family = addr.family(); + + auto fd = util::create_nonblock_socket(family, SOCK_DGRAM, 0); if (fd == -1) { std::cerr << "socket: " << strerror(errno) << std::endl; return -1; } int val = 1; - if (addr.su.sa.sa_family == AF_INET6) { + if (family == AF_INET6) { if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, static_cast(sizeof(val))) == -1) { std::cerr << "setsockopt: " << strerror(errno) << std::endl; @@ -1634,12 +1576,12 @@ int add_endpoint(std::vector &endpoints, const Address &addr) { return -1; } - fd_set_recv_ecn(fd, addr.su.sa.sa_family); - fd_set_ip_mtu_discover(fd, addr.su.sa.sa_family); - fd_set_ip_dontfrag(fd, addr.su.sa.sa_family); + fd_set_recv_ecn(fd, family); + fd_set_ip_mtu_discover(fd, family); + fd_set_ip_dontfrag(fd, family); fd_set_udp_gro(fd); - if (bind(fd, &addr.su.sa, addr.len) == -1) { + if (bind(fd, addr.as_sockaddr(), addr.size()) == -1) { std::cerr << "bind: " << strerror(errno) << std::endl; close(fd); return -1; @@ -1650,6 +1592,7 @@ int add_endpoint(std::vector &endpoints, const Address &addr) { ep.addr = addr; ep.fd = fd; ev_io_init(&ep.rev, sreadcb, 0, EV_READ); + ev_set_priority(&ep.rev, EV_MAXPRI); return 0; } @@ -1671,11 +1614,11 @@ int Server::init(const char *addr, const char *port) { return -1; } - if (config.preferred_ipv4_addr.len && + if (!config.preferred_ipv4_addr.empty() && add_endpoint(endpoints_, config.preferred_ipv4_addr) != 0) { return -1; } - if (config.preferred_ipv6_addr.len && + if (!config.preferred_ipv6_addr.empty() && add_endpoint(endpoints_, config.preferred_ipv6_addr) != 0) { return -1; } @@ -1695,7 +1638,7 @@ int Server::init(const char *addr, const char *port) { } int Server::on_read(const Endpoint &ep) { - sockaddr_union su; + sockaddr_storage ss; std::array buf; size_t pktcnt = 0; ngtcp2_pkt_info pi; @@ -1709,14 +1652,21 @@ int Server::on_read(const Endpoint &ep) { CMSG_SPACE(sizeof(int))]; msghdr msg{ - .msg_name = &su, + .msg_name = &ss, .msg_iov = &msg_iov, .msg_iovlen = 1, .msg_control = msg_ctrl, }; - for (; pktcnt < 10;) { - msg.msg_namelen = sizeof(su); + auto start = util::timestamp(); + + for (; pktcnt < MAX_RECV_PKTS;) { + if (util::recv_pkt_time_threshold_exceeded( + config.cc_algo == NGTCP2_CC_ALGO_BBR, start, pktcnt)) { + return 0; + } + + msg.msg_namelen = sizeof(ss); msg.msg_controllen = sizeof(msg_ctrl); auto nread = recvmsg(ep.fd, &msg, 0); @@ -1734,14 +1684,17 @@ int Server::on_read(const Endpoint &ep) { continue; } - if (util::prohibited_port(util::port(&su))) { + Address remote_addr; + remote_addr.set(reinterpret_cast(&ss)); + + if (util::prohibited_port(remote_addr.port())) { ++pktcnt; continue; } - pi.ecn = msghdr_get_ecn(&msg, su.storage.ss_family); - auto local_addr = msghdr_get_local_addr(&msg, su.storage.ss_family); + pi.ecn = msghdr_get_ecn(&msg, ss.ss_family); + auto local_addr = msghdr_get_local_addr(&msg, ss.ss_family); if (!local_addr) { ++pktcnt; std::cerr << "Unable to obtain local address" << std::endl; @@ -1753,7 +1706,7 @@ int Server::on_read(const Endpoint &ep) { gso_size = static_cast(nread); } - set_port(*local_addr, ep.addr); + local_addr->port(ep.addr.port()); auto data = std::span{buf.data(), static_cast(nread)}; @@ -1764,10 +1717,8 @@ int Server::on_read(const Endpoint &ep) { if (!config.quiet) { std::array ifname; - std::cerr << "Received packet: local=" - << util::straddr(&local_addr->su.sa, local_addr->len) - << " remote=" << util::straddr(&su.sa, msg.msg_namelen) - << " if=" + std::cerr << "Received packet: local=" << util::straddr(*local_addr) + << " remote=" << util::straddr(remote_addr) << " if=" << if_indextoname(local_addr->ifindex, ifname.data()) << " ecn=0x" << std::hex << static_cast(pi.ecn) << std::dec << " " << datalen << " bytes" << std::endl; @@ -1783,8 +1734,7 @@ int Server::on_read(const Endpoint &ep) { std::cerr << "** Simulated incoming packet loss **" << std::endl; } } else { - read_pkt(ep, *local_addr, &su.sa, msg.msg_namelen, &pi, - {data.data(), datalen}); + read_pkt(ep, *local_addr, remote_addr, &pi, {data.data(), datalen}); } data = data.subspan(datalen); @@ -1795,8 +1745,7 @@ int Server::on_read(const Endpoint &ep) { } void Server::read_pkt(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, - const ngtcp2_pkt_info *pi, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data) { ngtcp2_version_cid vc; @@ -1807,7 +1756,8 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, break; case NGTCP2_ERR_VERSION_NEGOTIATION: send_version_negotiation(vc.version, {vc.scid, vc.scidlen}, - {vc.dcid, vc.dcidlen}, ep, local_addr, sa, salen); + {vc.dcid, vc.dcidlen}, ep, local_addr, + remote_addr); return; default: std::cerr << "Could not decode version and CID from QUIC packet header: " @@ -1829,7 +1779,7 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, if (!(data[0] & 0x80) && data.size() >= NGTCP2_SV_SCIDLEN + 21) { send_stateless_reset(data.size(), {vc.dcid, vc.dcidlen}, ep, local_addr, - sa, salen); + remote_addr); } return; @@ -1844,25 +1794,25 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, if (config.validate_addr || hd.tokenlen) { std::cerr << "Perform stateless address validation" << std::endl; if (hd.tokenlen == 0) { - send_retry(&hd, ep, local_addr, sa, salen, data.size() * 3); + send_retry(&hd, ep, local_addr, remote_addr, data.size() * 3); return; } if (hd.token[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2 && hd.dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN) { - send_stateless_connection_close(&hd, ep, local_addr, sa, salen); + send_stateless_connection_close(&hd, ep, local_addr, remote_addr); return; } switch (hd.token[0]) { case NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2: - switch (verify_retry_token(&ocid, &hd, sa, salen)) { + switch (verify_retry_token(&ocid, &hd, remote_addr)) { case 0: pocid = &ocid; token_type = NGTCP2_TOKEN_TYPE_RETRY; break; case -1: - send_stateless_connection_close(&hd, ep, local_addr, sa, salen); + send_stateless_connection_close(&hd, ep, local_addr, remote_addr); return; case 1: hd.token = nullptr; @@ -1872,9 +1822,9 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, break; case NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR: - if (verify_token(&hd, sa, salen) != 0) { + if (verify_token(&hd, remote_addr) != 0) { if (config.validate_addr) { - send_retry(&hd, ep, local_addr, sa, salen, data.size() * 3); + send_retry(&hd, ep, local_addr, remote_addr, data.size() * 3); return; } @@ -1889,7 +1839,7 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, std::cerr << "Ignore unrecognized token" << std::endl; } if (config.validate_addr) { - send_retry(&hd, ep, local_addr, sa, salen, data.size() * 3); + send_retry(&hd, ep, local_addr, remote_addr, data.size() * 3); return; } @@ -1900,17 +1850,17 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, } auto h = std::make_unique(loop_, this); - if (h->init(ep, local_addr, sa, salen, &hd.scid, &hd.dcid, pocid, + if (h->init(ep, local_addr, remote_addr, &hd.scid, &hd.dcid, pocid, {hd.token, hd.tokenlen}, token_type, hd.version, tls_ctx_) != 0) { return; } - switch (h->on_read(ep, local_addr, sa, salen, pi, data)) { + switch (h->on_read(ep, local_addr, remote_addr, pi, data)) { case 0: break; case NETWORK_ERR_RETRY: - send_retry(&hd, ep, local_addr, sa, salen, data.size() * 3); + send_retry(&hd, ep, local_addr, remote_addr, data.size() * 3); return; default: return; @@ -1941,7 +1891,7 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, auto h = (*handler_it).second; auto conn = h->conn(); if (ngtcp2_conn_in_closing_period(conn)) { - if (h->send_conn_close(ep, local_addr, sa, salen, pi, data) != 0) { + if (h->send_conn_close(ep, local_addr, remote_addr, pi, data) != 0) { remove(h); } return; @@ -1950,7 +1900,7 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, return; } - if (auto rv = h->on_read(ep, local_addr, sa, salen, pi, data); rv != 0) { + if (auto rv = h->on_read(ep, local_addr, remote_addr, pi, data); rv != 0) { if (rv != NETWORK_ERR_CLOSE_WAIT) { remove(h); } @@ -1961,11 +1911,10 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, } namespace { -uint32_t generate_reserved_version(const sockaddr *sa, socklen_t salen, - uint32_t version) { +uint32_t generate_reserved_version(const Address &addr, uint32_t version) { uint32_t h = 0x811C9DC5u; - const uint8_t *p = (const uint8_t *)sa; - const uint8_t *ep = p + salen; + const uint8_t *p = reinterpret_cast(addr.as_sockaddr()); + const uint8_t *ep = p + addr.size(); for (; p != ep; ++p) { h ^= *p; h *= 0x01000193u; @@ -1988,13 +1937,13 @@ int Server::send_version_negotiation(uint32_t version, std::span scid, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen) { + const Address &remote_addr) { Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE}; std::array sv; auto p = std::ranges::begin(sv); - *p++ = generate_reserved_version(sa, salen, version); + *p++ = generate_reserved_version(remote_addr, version); if (config.preferred_versions.empty()) { *p++ = NGTCP2_PROTO_VER_V1; @@ -2016,17 +1965,8 @@ int Server::send_version_negotiation(uint32_t version, buf.push(as_unsigned(nwrite)); - ngtcp2_addr laddr{ - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }; - ngtcp2_addr raddr{ - .addr = const_cast(sa), - .addrlen = salen, - }; - - if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.data()) != - NETWORK_ERR_OK) { + if (send_packet(ep, as_ngtcp2_addr(local_addr), as_ngtcp2_addr(remote_addr), + /* ecn = */ 0, buf.data()) != NETWORK_ERR_OK) { return -1; } @@ -2034,13 +1974,14 @@ int Server::send_version_negotiation(uint32_t version, } int Server::send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, - const Address &local_addr, const sockaddr *sa, - socklen_t salen, size_t max_pktlen) { + const Address &local_addr, const Address &remote_addr, + size_t max_pktlen) { std::array host; std::array port; - if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(), - port.size(), NI_NUMERICHOST | NI_NUMERICSERV); + if (auto rv = getnameinfo(remote_addr.as_sockaddr(), remote_addr.size(), + host.data(), host.size(), port.data(), port.size(), + NI_NUMERICHOST | NI_NUMERICSERV); rv != 0) { std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl; return -1; @@ -2064,7 +2005,8 @@ int Server::send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, auto tokenlen = ngtcp2_crypto_generate_retry_token2( token.data(), config.static_secret.data(), config.static_secret.size(), - chd->version, sa, salen, &scid, &chd->dcid, t); + chd->version, remote_addr.as_sockaddr(), remote_addr.size(), &scid, + &chd->dcid, t); if (tokenlen < 0) { return -1; } @@ -2087,17 +2029,8 @@ int Server::send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, buf.push(as_unsigned(nwrite)); - ngtcp2_addr laddr{ - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }; - ngtcp2_addr raddr{ - .addr = const_cast(sa), - .addrlen = salen, - }; - - if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.data()) != - NETWORK_ERR_OK) { + if (send_packet(ep, as_ngtcp2_addr(local_addr), as_ngtcp2_addr(remote_addr), + /* ecn = */ 0, buf.data()) != NETWORK_ERR_OK) { return -1; } @@ -2107,8 +2040,7 @@ int Server::send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, int Server::send_stateless_connection_close(const ngtcp2_pkt_hd *chd, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, - socklen_t salen) { + const Address &remote_addr) { Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE}; auto nwrite = ngtcp2_crypto_write_connection_close( @@ -2121,17 +2053,8 @@ int Server::send_stateless_connection_close(const ngtcp2_pkt_hd *chd, buf.push(as_unsigned(nwrite)); - ngtcp2_addr laddr{ - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }; - ngtcp2_addr raddr{ - .addr = const_cast(sa), - .addrlen = salen, - }; - - if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.data()) != - NETWORK_ERR_OK) { + if (send_packet(ep, as_ngtcp2_addr(local_addr), as_ngtcp2_addr(remote_addr), + /* ecn = */ 0, buf.data()) != NETWORK_ERR_OK) { return -1; } @@ -2140,7 +2063,7 @@ int Server::send_stateless_connection_close(const ngtcp2_pkt_hd *chd, int Server::send_stateless_reset(size_t pktlen, std::span dcid, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen) { + const Address &remote_addr) { if (stateless_reset_bucket_ == 0) { return 0; } @@ -2196,17 +2119,8 @@ int Server::send_stateless_reset(size_t pktlen, std::span dcid, buf.push(as_unsigned(nwrite)); - ngtcp2_addr laddr{ - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }; - ngtcp2_addr raddr{ - .addr = const_cast(sa), - .addrlen = salen, - }; - - if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.data()) != - NETWORK_ERR_OK) { + if (send_packet(ep, as_ngtcp2_addr(local_addr), as_ngtcp2_addr(remote_addr), + /* ecn = */ 0, buf.data()) != NETWORK_ERR_OK) { return -1; } @@ -2214,14 +2128,15 @@ int Server::send_stateless_reset(size_t pktlen, std::span dcid, } int Server::verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd, - const sockaddr *sa, socklen_t salen) { + const Address &remote_addr) { int rv; if (!config.quiet) { std::array host; std::array port; - if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(), + if (auto rv = getnameinfo(remote_addr.as_sockaddr(), remote_addr.size(), + host.data(), host.size(), port.data(), port.size(), NI_NUMERICHOST | NI_NUMERICSERV); rv != 0) { std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl; @@ -2237,8 +2152,8 @@ int Server::verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd, rv = ngtcp2_crypto_verify_retry_token2( ocid, hd->token, hd->tokenlen, config.static_secret.data(), - config.static_secret.size(), hd->version, sa, salen, &hd->dcid, - 10 * NGTCP2_SECONDS, t); + config.static_secret.size(), hd->version, remote_addr.as_sockaddr(), + remote_addr.size(), &hd->dcid, 10 * NGTCP2_SECONDS, t); switch (rv) { case 0: break; @@ -2260,13 +2175,13 @@ int Server::verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd, return 0; } -int Server::verify_token(const ngtcp2_pkt_hd *hd, const sockaddr *sa, - socklen_t salen) { +int Server::verify_token(const ngtcp2_pkt_hd *hd, const Address &remote_addr) { std::array host; std::array port; - if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(), - port.size(), NI_NUMERICHOST | NI_NUMERICSERV); + if (auto rv = getnameinfo(remote_addr.as_sockaddr(), remote_addr.size(), + host.data(), host.size(), port.data(), port.size(), + NI_NUMERICHOST | NI_NUMERICSERV); rv != 0) { std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl; return -1; @@ -2280,10 +2195,10 @@ int Server::verify_token(const ngtcp2_pkt_hd *hd, const sockaddr *sa, auto t = util::system_clock_now(); - if (ngtcp2_crypto_verify_regular_token(hd->token, hd->tokenlen, - config.static_secret.data(), - config.static_secret.size(), sa, salen, - 3600 * NGTCP2_SECONDS, t) != 0) { + if (ngtcp2_crypto_verify_regular_token( + hd->token, hd->tokenlen, config.static_secret.data(), + config.static_secret.size(), remote_addr.as_sockaddr(), + remote_addr.size(), 3600 * NGTCP2_SECONDS, t) != 0) { std::cerr << "Could not verify token" << std::endl; return -1; @@ -2559,8 +2474,7 @@ int parse_host_port(Address &dest, int af, const std::string_view &host_port) { return -1; } - dest.len = res->ai_addrlen; - memcpy(&dest.su, res->ai_addr, res->ai_addrlen); + dest.set(res->ai_addr); freeaddrinfo(res); @@ -2581,43 +2495,11 @@ void print_usage() { } } // namespace -namespace { -void config_set_default(Config &config) { - auto path = realpath(".", nullptr); - assert(path); - auto htdocs = std::string(path); - free(path); - - config = Config{ - .tx_loss_prob = 0., - .rx_loss_prob = 0., - .ciphers = util::crypto_default_ciphers(), - .groups = util::crypto_default_groups(), - .htdocs = std::move(htdocs), - .mime_types_file = "/etc/mime.types"sv, - .timeout = 30 * NGTCP2_SECONDS, - .max_data = 1_m, - .max_stream_data_bidi_remote = 256_k, - .max_stream_data_uni = 256_k, - .max_streams_bidi = 100, - .max_streams_uni = 3, - .max_window = 6_m, - .max_stream_window = 6_m, - .max_dyn_length = 20_m, - .cc_algo = NGTCP2_CC_ALGO_CUBIC, - .initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT, - .handshake_timeout = UINT64_MAX, - .ack_thresh = 2, - .initial_pkt_num = UINT32_MAX, - }; -} -} // namespace - namespace { void print_help() { print_usage(); - config_set_default(config); + Config config; std::cout << R"( Address to listen to. '*' binds to any address. @@ -2776,12 +2658,21 @@ void print_help() { Specify UDP datagram payload sizes to probe in Path MTU Discovery. must be strictly larger than 1200. --ech-config-file= - Read private key and ECHConfig from |PATH|. The file - denoted by |PATH| must contain private key and ECHConfig + Read private key and ECHConfig from . The file + denoted by must contain private key and ECHConfig as described in https://datatracker.ietf.org/doc/html/draft-farrell-tls-pemesni. ECH configuration is only applied if an underlying TLS stack supports it. + --no-gso Disables GSO. + --show-stat Print the connection statistics when the connection is + closed. + --gso-burst= + The maximum number of packets to aggregate for GSO. If + GSO is disabled, this is the maximum number of packets + to send per an event loop in a single connection. It + defaults to 0, which means it is not limited by the + configuration. -h, --help Display this help and exit. --- @@ -2804,8 +2695,6 @@ void print_help() { std::ofstream keylog_file; int main(int argc, char **argv) { - config_set_default(config); - if (argc) { prog = basename(argv[0]); } @@ -2854,6 +2743,9 @@ int main(int argc, char **argv) { {"initial-pkt-num", required_argument, &flag, 31}, {"pmtud-probes", required_argument, &flag, 32}, {"ech-config-file", required_argument, &flag, 33}, + {"no-gso", no_argument, &flag, 35}, + {"show-stat", no_argument, &flag, 36}, + {"gso-burst", required_argument, &flag, 37}, {}, }; @@ -3060,9 +2952,9 @@ int main(int argc, char **argv) { if (auto n = util::parse_uint_iec(optarg); !n) { std::cerr << "max-udp-payload-size: invalid argument" << std::endl; exit(EXIT_FAILURE); - } else if (*n > 64_k) { - std::cerr << "max-udp-payload-size: must not exceed 65536" - << std::endl; + } else if (*n > NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE) { + std::cerr << "max-udp-payload-size: must not exceed " + << NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE << std::endl; exit(EXIT_FAILURE); } else { config.max_udp_payload_size = *n; @@ -3192,10 +3084,12 @@ int main(int argc, char **argv) { if (auto n = util::parse_uint_iec(s); !n) { std::cerr << "pmtud-probes: invalid argument" << std::endl; exit(EXIT_FAILURE); - } else if (*n <= 1200 || *n >= 64_k) { - std::cerr - << "pmtud-probes: must be in range [1201, 65535], inclusive." - << std::endl; + } else if (*n <= NGTCP2_MAX_UDP_PAYLOAD_SIZE || + *n > NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE) { + std::cerr << "pmtud-probes: must be in range [" + << NGTCP2_MAX_UDP_PAYLOAD_SIZE + 1 << ", " + << NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE << "], inclusive." + << std::endl; exit(EXIT_FAILURE); } else { config.pmtud_probes.push_back(static_cast(*n)); @@ -3207,11 +3101,37 @@ int main(int argc, char **argv) { // --ech-config-file ech_config_file = optarg; break; + case 35: + // --no-gso + config.no_gso = true; + break; + case 36: + // --show-stat + config.show_stat = true; + break; + case 37: { + // --gso-burst + auto n = util::parse_uint(optarg); + if (!n) { + std::cerr << "gso-burst: invalid argument" << std::endl; + exit(EXIT_FAILURE); + } + + if (*n > 64) { + std::cerr << "gso-burst: must be in range [0, 64], inclusive." + << std::endl; + exit(EXIT_FAILURE); + } + + config.gso_burst = static_cast(*n); + + break; + } } break; default: break; - }; + } } if (argc - optind < 4) { @@ -3265,7 +3185,7 @@ int main(int argc, char **argv) { std::cerr << "Using document root " << config.htdocs << std::endl; - auto ev_loop_d = defer(ev_loop_destroy, EV_DEFAULT); + auto ev_loop_d = defer([] { ev_loop_destroy(EV_DEFAULT); }); auto keylog_filename = getenv("SSLKEYLOGFILE"); if (keylog_filename) { diff --git a/deps/ngtcp2/ngtcp2/examples/h09server.h b/deps/ngtcp2/ngtcp2/examples/h09server.h index 5034141af18b46..50bfae347f10fb 100644 --- a/deps/ngtcp2/ngtcp2/examples/h09server.h +++ b/deps/ngtcp2/ngtcp2/examples/h09server.h @@ -52,14 +52,6 @@ using namespace ngtcp2; -struct HTTPHeader { - HTTPHeader(const std::string_view &name, const std::string_view &value) - : name(name), value(value) {} - - std::string_view name; - std::string_view value; -}; - class Handler; struct FileEntry; @@ -79,7 +71,7 @@ struct Stream { nghttp3_buf respbuf; http_parser htp; // eos gets true when one HTTP request message is seen. - bool eos; + bool eos{}; }; struct StreamIDLess { @@ -94,8 +86,8 @@ class Server; struct Endpoint { Address addr; ev_io rev; - Server *server; - int fd; + Server *server{}; + int fd{}; }; class Handler : public HandlerBase { @@ -103,19 +95,19 @@ class Handler : public HandlerBase { Handler(struct ev_loop *loop, Server *server); ~Handler(); - int init(const Endpoint &ep, const Address &local_addr, const sockaddr *sa, - socklen_t salen, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, - const ngtcp2_cid *ocid, std::span token, - ngtcp2_token_type token_type, uint32_t version, - TLSServerContext &tls_ctx); + int init(const Endpoint &ep, const Address &local_addr, + const Address &remote_addr, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, const ngtcp2_cid *ocid, + std::span token, ngtcp2_token_type token_type, + uint32_t version, TLSServerContext &tls_ctx); - int on_read(const Endpoint &ep, const Address &local_addr, const sockaddr *sa, - socklen_t salen, const ngtcp2_pkt_info *pi, + int on_read(const Endpoint &ep, const Address &local_addr, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data); int on_write(); int write_streams(); int feed_data(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, const ngtcp2_pkt_info *pi, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data); void update_timer(); int handle_expiry(); @@ -135,8 +127,8 @@ class Handler : public HandlerBase { int handle_error(); int send_conn_close(); int send_conn_close(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, - const ngtcp2_pkt_info *pi, std::span data); + const Address &remote_addr, const ngtcp2_pkt_info *pi, + std::span data); int update_key(uint8_t *rx_secret, uint8_t *tx_secret, ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, @@ -166,8 +158,8 @@ class Handler : public HandlerBase { Server *server_; ev_io wev_; ev_timer timer_; - FILE *qlog_; - ngtcp2_cid scid_; + FILE *qlog_{}; + ngtcp2_cid scid_{}; std::unordered_map> streams_; std::set sendq_; // conn_closebuf_ contains a packet which contains CONNECTION_CLOSE. @@ -175,14 +167,14 @@ class Handler : public HandlerBase { // packet in draining period. std::unique_ptr conn_closebuf_; // nkey_update_ is the number of key update occurred. - size_t nkey_update_; + size_t nkey_update_{}; bool no_gso_; struct { size_t bytes_recv; size_t bytes_sent; size_t num_pkts_recv; - size_t next_pkts_recv; - } close_wait_; + size_t next_pkts_recv = 1; + } close_wait_{}; struct { bool send_blocked; @@ -195,8 +187,8 @@ class Handler : public HandlerBase { std::span data; size_t gso_size; } blocked; - std::unique_ptr data; - } tx_; + } tx_{}; + std::array txbuf_; }; class Server { @@ -210,26 +202,25 @@ class Server { int on_read(const Endpoint &ep); void read_pkt(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, const ngtcp2_pkt_info *pi, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data); int send_version_negotiation(uint32_t version, std::span dcid, std::span scid, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen); + const Address &remote_addr); int send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, - const Address &local_addr, const sockaddr *sa, socklen_t salen, + const Address &local_addr, const Address &remote_addr, size_t max_pktlen); int send_stateless_connection_close(const ngtcp2_pkt_hd *chd, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen); + const Address &remote_addr); int send_stateless_reset(size_t pktlen, std::span dcid, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen); + const Address &remote_addr); int verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd, - const sockaddr *sa, socklen_t salen); - int verify_token(const ngtcp2_pkt_hd *hd, const sockaddr *sa, - socklen_t salen); + const Address &remote_addr); + int verify_token(const ngtcp2_pkt_hd *hd, const Address &remote_addr); int send_packet(const Endpoint &ep, const ngtcp2_addr &local_addr, const ngtcp2_addr &remote_addr, unsigned int ecn, std::span data); @@ -251,7 +242,7 @@ class Server { TLSServerContext &tls_ctx_; ev_signal sigintev_; ev_timer stateless_reset_regen_timer_; - size_t stateless_reset_bucket_; + size_t stateless_reset_bucket_{NGTCP2_STATELESS_RESET_BURST}; }; #endif // !defined(H09SERVER_H) diff --git a/deps/ngtcp2/ngtcp2/examples/network.h b/deps/ngtcp2/ngtcp2/examples/network.h index c914ab5763abf8..5698312845f3c7 100644 --- a/deps/ngtcp2/ngtcp2/examples/network.h +++ b/deps/ngtcp2/ngtcp2/examples/network.h @@ -43,6 +43,7 @@ #endif // defined(HAVE_ARPA_INET_H) #include +#include #include @@ -50,29 +51,40 @@ namespace ngtcp2 { enum network_error { NETWORK_ERR_OK = 0, - NETWORK_ERR_FATAL = -10, NETWORK_ERR_SEND_BLOCKED = -11, NETWORK_ERR_CLOSE_WAIT = -12, NETWORK_ERR_RETRY = -13, NETWORK_ERR_DROP_CONN = -14, }; -union in_addr_union { - in_addr in; - in6_addr in6; -}; +using InAddr = std::variant; -union sockaddr_union { - sockaddr_storage storage; - sockaddr sa; - sockaddr_in6 in6; - sockaddr_in in; -}; +using Sockaddr = std::variant; struct Address { - socklen_t len; - union sockaddr_union su; - uint32_t ifindex; + // as_sockaddr returns the pointer to the stored address casted to + // const sockaddr *. + [[nodiscard]] const sockaddr *as_sockaddr() const; + [[nodiscard]] sockaddr *as_sockaddr(); + // family returns the address family. + [[nodiscard]] int family() const; + // port returns the port. + [[nodiscard]] uint16_t port() const; + // port sets |port| to this address. + void port(uint16_t port); + // set stores |sa| to this address. The address family is + // determined by |sa|->sa_family, and |sa| must point to the memory + // that contains valid object which is either sockaddr_in or + // sockaddr_in6. + void set(const sockaddr *sa); + // size returns the size of the stored address. + [[nodiscard]] socklen_t size() const; + // empty returns true if this address does not contain any + // meaningful address. + [[nodiscard]] bool empty() const; + + Sockaddr skaddr; + uint32_t ifindex{}; }; } // namespace ngtcp2 diff --git a/deps/ngtcp2/ngtcp2/examples/server.cc b/deps/ngtcp2/ngtcp2/examples/server.cc index 9ad1e9cb0618e8..f9463eacd9cc7d 100644 --- a/deps/ngtcp2/ngtcp2/examples/server.cc +++ b/deps/ngtcp2/ngtcp2/examples/server.cc @@ -65,28 +65,14 @@ namespace { constexpr size_t max_preferred_versionslen = 4; } // namespace -namespace { -constexpr size_t NGTCP2_STATELESS_RESET_BURST = 100; -} // namespace - -namespace { -constexpr size_t NGTCP2_TX_BUFLEN = 64_k; -} // namespace - namespace { auto randgen = util::make_mt19937(); } // namespace -Config config{}; +Config config; Stream::Stream(int64_t stream_id, Handler *handler) - : stream_id(stream_id), - handler(handler), - data(nullptr), - datalen(0), - dynresp(false), - dyndataleft(0), - dynbuflen(0) {} + : stream_id{stream_id}, handler{handler} {} namespace { constexpr auto NGTCP2_SERVER = "nghttp3/ngtcp2 server"sv; @@ -121,18 +107,17 @@ struct Request { struct { int32_t urgency; int inc; - } pri; + } pri{}; }; namespace { Request request_path(const std::string_view &uri, bool is_connect) { urlparse_url u; Request req{ - .pri = - { - .urgency = -1, - .inc = -1, - }, + .pri{ + .urgency = -1, + .inc = -1, + }, }; if (auto rv = urlparse_parse_url(uri.data(), uri.size(), is_connect, &u); @@ -208,10 +193,10 @@ enum FileEntryFlag { }; struct FileEntry { - uint64_t len; - void *map; - int fd; - uint8_t flags; + uint64_t len{}; + void *map{}; + int fd{}; + uint8_t flags{}; }; namespace { @@ -235,7 +220,7 @@ std::pair Stream::open_file(const std::string &path) { return {{}, -1}; } - FileEntry fe{}; + FileEntry fe; if (st.st_mode & S_IFDIR) { fe.flags |= FILE_ENTRY_TYPE_DIR; fe.fd = -1; @@ -618,10 +603,7 @@ void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { goto fail; } - rv = h->on_write(); - if (rv != 0) { - goto fail; - } + h->signal_write(); return; @@ -638,24 +620,14 @@ void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { } // namespace Handler::Handler(struct ev_loop *loop, Server *server) - : loop_(loop), - server_(server), - qlog_(nullptr), - scid_{}, - httpconn_{nullptr}, - nkey_update_(0), + : loop_{loop}, + server_{server}, no_gso_{ #ifdef UDP_SEGMENT - false + config.no_gso #else // !defined(UDP_SEGMENT) true #endif // !defined(UDP_SEGMENT) - }, - close_wait_{ - .next_pkts_recv = 1, - }, - tx_{ - .data = std::unique_ptr(new uint8_t[NGTCP2_TX_BUFLEN]), } { ev_io_init(&wev_, writecb, 0, EV_WRITE); wev_.data = this; @@ -720,19 +692,17 @@ int Handler::handshake_completed() { token.data(), config.static_secret.data(), config.static_secret.size(), path->remote.addr, path->remote.addrlen, t); if (tokenlen < 0) { - if (!config.quiet) { - std::cerr << "Unable to generate token" << std::endl; - } + std::cerr << "Unable to generate token" << std::endl; + return 0; } if (auto rv = ngtcp2_conn_submit_new_token(conn_, token.data(), as_unsigned(tokenlen)); rv != 0) { - if (!config.quiet) { - std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv) - << std::endl; - } + std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv) + << std::endl; + return -1; } @@ -821,9 +791,9 @@ void Handler::on_stream_open(int64_t stream_id) { if (!ngtcp2_is_bidi_stream(stream_id)) { return; } - auto it = streams_.find(stream_id); - (void)it; - assert(it == std::ranges::end(streams_)); + + assert(!streams_.contains(stream_id)); + streams_.emplace(stream_id, std::make_unique(stream_id, this)); } @@ -978,9 +948,7 @@ int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path, token.data(), config.static_secret.data(), config.static_secret.size(), path->remote.addr, path->remote.addrlen, t); if (tokenlen < 0) { - if (!config.quiet) { - std::cerr << "Unable to generate token" << std::endl; - } + std::cerr << "Unable to generate token" << std::endl; return 0; } @@ -988,10 +956,8 @@ int path_validation(ngtcp2_conn *conn, uint32_t flags, const ngtcp2_path *path, if (auto rv = ngtcp2_conn_submit_new_token(conn, token.data(), as_unsigned(tokenlen)); rv != 0) { - if (!config.quiet) { - std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv) - << std::endl; - } + std::cerr << "ngtcp2_conn_submit_new_token: " << ngtcp2_strerror(rv) + << std::endl; return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -1164,17 +1130,14 @@ void Handler::http_acked_stream_data(Stream *stream, uint64_t datalen) { stream->http_acked_stream_data(datalen); } -namespace { -int http_stream_close(nghttp3_conn *conn, int64_t stream_id, - uint64_t app_error_code, void *conn_user_data, - void *stream_user_data) { - auto h = static_cast(conn_user_data); - h->http_stream_close(stream_id, app_error_code); - return 0; -} -} // namespace - void Handler::http_stream_close(int64_t stream_id, uint64_t app_error_code) { + if (!ngtcp2_is_bidi_stream(stream_id)) { + return; + } + + assert(!ngtcp2_conn_is_local_stream(conn_, stream_id)); + ngtcp2_conn_extend_max_streams_bidi(conn_, 1); + auto it = streams_.find(stream_id); if (it == std::ranges::end(streams_)) { return; @@ -1186,11 +1149,6 @@ void Handler::http_stream_close(int64_t stream_id, uint64_t app_error_code) { } streams_.erase(it); - - if (ngtcp2_is_bidi_stream(stream_id)) { - assert(!ngtcp2_conn_is_local_stream(conn_, stream_id)); - ngtcp2_conn_extend_max_streams_bidi(conn_, 1); - } } namespace { @@ -1240,7 +1198,8 @@ int Handler::http_reset_stream(int64_t stream_id, uint64_t app_error_code) { } namespace { -int http_recv_settings(nghttp3_conn *conn, const nghttp3_settings *settings, +int http_recv_settings(nghttp3_conn *conn, + const nghttp3_proto_settings *settings, void *conn_user_data) { if (!config.quiet) { debug::print_http_settings(settings); @@ -1263,7 +1222,6 @@ int Handler::setup_httpconn() { nghttp3_callbacks callbacks{ .acked_stream_data = ::http_acked_stream_data, - .stream_close = ::http_stream_close, .recv_data = ::http_recv_data, .deferred_consume = ::http_deferred_consume, .begin_headers = ::http_begin_request_headers, @@ -1272,8 +1230,8 @@ int Handler::setup_httpconn() { .stop_sending = ::http_stop_sending, .end_stream = ::http_end_stream, .reset_stream = ::http_reset_stream, - .recv_settings = ::http_recv_settings, .rand = rand_bytes, + .recv_settings2 = ::http_recv_settings, }; nghttp3_settings settings; nghttp3_settings_default(&settings); @@ -1410,7 +1368,7 @@ void Handler::write_qlog(const void *data, size_t datalen) { } int Handler::init(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, const ngtcp2_cid *dcid, + const Address &remote_addr, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, const ngtcp2_cid *ocid, std::span token, ngtcp2_token_type token_type, uint32_t version, TLSServerContext &tls_ctx) { @@ -1533,16 +1491,19 @@ int Handler::init(const Endpoint &ep, const Address &local_addr, return -1; } - if (config.preferred_ipv4_addr.len || config.preferred_ipv6_addr.len) { + if (!config.preferred_ipv4_addr.empty() || + !config.preferred_ipv6_addr.empty()) { params.preferred_addr_present = 1; - if (config.preferred_ipv4_addr.len) { - params.preferred_addr.ipv4 = config.preferred_ipv4_addr.su.in; + if (!config.preferred_ipv4_addr.empty()) { + params.preferred_addr.ipv4 = + std::get(config.preferred_ipv4_addr.skaddr); params.preferred_addr.ipv4_present = 1; } - if (config.preferred_ipv6_addr.len) { - params.preferred_addr.ipv6 = config.preferred_ipv6_addr.su.in6; + if (!config.preferred_ipv6_addr.empty()) { + params.preferred_addr.ipv6 = + std::get(config.preferred_ipv6_addr.skaddr); params.preferred_addr.ipv6_present = 1; } @@ -1564,16 +1525,8 @@ int Handler::init(const Endpoint &ep, const Address &local_addr, } auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }, - .remote = - { - .addr = const_cast(sa), - .addrlen = salen, - }, + .local = as_ngtcp2_addr(local_addr), + .remote = as_ngtcp2_addr(remote_addr), .user_data = const_cast(&ep), }; if (auto rv = @@ -1598,20 +1551,11 @@ int Handler::init(const Endpoint &ep, const Address &local_addr, } int Handler::feed_data(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, - const ngtcp2_pkt_info *pi, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data) { auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }, - .remote = - { - .addr = const_cast(sa), - .addrlen = salen, - }, + .local = as_ngtcp2_addr(local_addr), + .remote = as_ngtcp2_addr(remote_addr), .user_data = const_cast(&ep), }; @@ -1645,9 +1589,9 @@ int Handler::feed_data(const Endpoint &ep, const Address &local_addr, } int Handler::on_read(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, - const ngtcp2_pkt_info *pi, std::span data) { - if (auto rv = feed_data(ep, local_addr, sa, salen, pi, data); rv != 0) { + const Address &remote_addr, const ngtcp2_pkt_info *pi, + std::span data) { + if (auto rv = feed_data(ep, local_addr, remote_addr, pi, data); rv != 0) { return rv; } @@ -1797,17 +1741,20 @@ int Handler::write_streams() { ngtcp2_pkt_info pi; size_t gso_size; auto ts = util::timestamp(); - auto txbuf = std::span{tx_.data.get(), NGTCP2_TX_BUFLEN}; + auto txbuf = std::span{txbuf_}; + auto buflen = util::clamp_buffer_size(conn_, txbuf.size(), config.gso_burst); ngtcp2_path_storage_zero(&ps); - auto nwrite = - ngtcp2_conn_write_aggregate_pkt(conn_, &ps.path, &pi, txbuf.data(), - txbuf.size(), &gso_size, ::write_pkt, ts); + auto nwrite = ngtcp2_conn_write_aggregate_pkt2( + conn_, &ps.path, &pi, txbuf.data(), buflen, &gso_size, ::write_pkt, + config.gso_burst, ts); if (nwrite < 0) { return handle_error(); } + ngtcp2_conn_update_pkt_tx_time(conn_, ts); + if (nwrite == 0) { return 0; } @@ -1845,11 +1792,9 @@ void Handler::on_send_blocked(const ngtcp2_path &path, unsigned int ecn, auto &p = tx_.blocked; - memcpy(&p.local_addr.su, path.local.addr, path.local.addrlen); - memcpy(&p.remote_addr.su, path.remote.addr, path.remote.addrlen); + p.local_addr.set(path.local.addr); + p.remote_addr.set(path.remote.addr); - p.local_addr.len = path.local.addrlen; - p.remote_addr.len = path.remote.addrlen; p.endpoint = static_cast(path.user_data); p.ecn = ecn; p.data = data; @@ -1875,17 +1820,9 @@ int Handler::send_blocked_packet() { auto &p = tx_.blocked; - ngtcp2_addr local_addr{ - .addr = &p.local_addr.su.sa, - .addrlen = p.local_addr.len, - }; - ngtcp2_addr remote_addr{ - .addr = &p.remote_addr.su.sa, - .addrlen = p.remote_addr.len, - }; - auto [rest, rv] = server_->send_packet( - *p.endpoint, no_gso_, local_addr, remote_addr, p.ecn, p.data, p.gso_size); + *p.endpoint, no_gso_, as_ngtcp2_addr(p.local_addr), + as_ngtcp2_addr(p.remote_addr), p.ecn, p.data, p.gso_size); if (rv != 0) { assert(NETWORK_ERR_SEND_BLOCKED == rv); @@ -1997,7 +1934,7 @@ int Handler::send_conn_close() { } int Handler::send_conn_close(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data) { assert(conn_closebuf_ && conn_closebuf_->size()); @@ -2011,21 +1948,8 @@ int Handler::send_conn_close(const Endpoint &ep, const Address &local_addr, return 0; } - auto path = ngtcp2_path{ - .local = - { - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }, - .remote = - { - .addr = const_cast(sa), - .addrlen = salen, - }, - .user_data = const_cast(&ep), - }; - - auto rv = server_->send_packet(ep, path.local, path.remote, + auto rv = server_->send_packet(ep, as_ngtcp2_addr(local_addr), + as_ngtcp2_addr(remote_addr), /* ecn = */ 0, conn_closebuf_->data()); if (rv != 0) { return rv; @@ -2072,11 +1996,11 @@ int Handler::recv_stream_data(uint32_t flags, int64_t stream_id, return 0; } - auto nconsumed = - nghttp3_conn_read_stream(httpconn_, stream_id, data.data(), data.size(), - flags & NGTCP2_STREAM_DATA_FLAG_FIN); + auto nconsumed = nghttp3_conn_read_stream2( + httpconn_, stream_id, data.data(), data.size(), + flags & NGTCP2_STREAM_DATA_FLAG_FIN, ngtcp2_conn_get_timestamp(conn_)); if (nconsumed < 0) { - std::cerr << "nghttp3_conn_read_stream: " + std::cerr << "nghttp3_conn_read_stream2: " << nghttp3_strerror(static_cast(nconsumed)) << std::endl; ngtcp2_ccerr_set_application_error( &last_error_, @@ -2139,6 +2063,7 @@ int Handler::on_stream_close(int64_t stream_id, uint64_t app_error_code) { auto rv = nghttp3_conn_close_stream(httpconn_, stream_id, app_error_code); switch (rv) { case 0: + http_stream_close(stream_id, app_error_code); break; case NGHTTP3_ERR_STREAM_NOT_FOUND: if (ngtcp2_is_bidi_stream(stream_id)) { @@ -2177,9 +2102,7 @@ void siginthandler(struct ev_loop *loop, ev_signal *watcher, int revents) { } // namespace Server::Server(struct ev_loop *loop, TLSServerContext &tls_ctx) - : loop_(loop), - tls_ctx_(tls_ctx), - stateless_reset_bucket_(NGTCP2_STATELESS_RESET_BURST) { + : loop_{loop}, tls_ctx_{tls_ctx} { ev_signal_init(&sigintev_, siginthandler, SIGINT); ev_timer_init( @@ -2246,7 +2169,7 @@ int create_sock(Address &local_addr, const char *addr, const char *port, return -1; } - auto res_d = defer(freeaddrinfo, res); + auto res_d = defer([res] { freeaddrinfo(res); }); int fd = -1; @@ -2298,14 +2221,15 @@ int create_sock(Address &local_addr, const char *addr, const char *port, return -1; } - socklen_t len = sizeof(local_addr.su.storage); - if (getsockname(fd, &local_addr.su.sa, &len) == -1) { + sockaddr_storage ss; + socklen_t len = sizeof(ss); + if (getsockname(fd, reinterpret_cast(&ss), &len) == -1) { std::cerr << "getsockname: " << strerror(errno) << std::endl; close(fd); return -1; } - local_addr.len = len; - local_addr.ifindex = 0; + + local_addr.set(reinterpret_cast(&ss)); return fd; } @@ -2326,6 +2250,7 @@ int add_endpoint(std::vector &endpoints, const char *addr, ep.addr = dest; ep.fd = fd; ev_io_init(&ep.rev, sreadcb, 0, EV_READ); + ev_set_priority(&ep.rev, EV_MAXPRI); return 0; } @@ -2333,14 +2258,16 @@ int add_endpoint(std::vector &endpoints, const char *addr, namespace { int add_endpoint(std::vector &endpoints, const Address &addr) { - auto fd = util::create_nonblock_socket(addr.su.sa.sa_family, SOCK_DGRAM, 0); + auto family = addr.family(); + + auto fd = util::create_nonblock_socket(family, SOCK_DGRAM, 0); if (fd == -1) { std::cerr << "socket: " << strerror(errno) << std::endl; return -1; } int val = 1; - if (addr.su.sa.sa_family == AF_INET6) { + if (family == AF_INET6) { if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, static_cast(sizeof(val))) == -1) { std::cerr << "setsockopt: " << strerror(errno) << std::endl; @@ -2367,12 +2294,12 @@ int add_endpoint(std::vector &endpoints, const Address &addr) { return -1; } - fd_set_recv_ecn(fd, addr.su.sa.sa_family); - fd_set_ip_mtu_discover(fd, addr.su.sa.sa_family); - fd_set_ip_dontfrag(fd, addr.su.sa.sa_family); + fd_set_recv_ecn(fd, family); + fd_set_ip_mtu_discover(fd, family); + fd_set_ip_dontfrag(fd, family); fd_set_udp_gro(fd); - if (bind(fd, &addr.su.sa, addr.len) == -1) { + if (bind(fd, addr.as_sockaddr(), addr.size()) == -1) { std::cerr << "bind: " << strerror(errno) << std::endl; close(fd); return -1; @@ -2383,6 +2310,7 @@ int add_endpoint(std::vector &endpoints, const Address &addr) { ep.addr = addr; ep.fd = fd; ev_io_init(&ep.rev, sreadcb, 0, EV_READ); + ev_set_priority(&ep.rev, EV_MAXPRI); return 0; } @@ -2404,11 +2332,11 @@ int Server::init(const char *addr, const char *port) { return -1; } - if (config.preferred_ipv4_addr.len && + if (!config.preferred_ipv4_addr.empty() && add_endpoint(endpoints_, config.preferred_ipv4_addr) != 0) { return -1; } - if (config.preferred_ipv6_addr.len && + if (!config.preferred_ipv6_addr.empty() && add_endpoint(endpoints_, config.preferred_ipv6_addr) != 0) { return -1; } @@ -2428,7 +2356,7 @@ int Server::init(const char *addr, const char *port) { } int Server::on_read(const Endpoint &ep) { - sockaddr_union su; + sockaddr_storage ss; std::array buf; size_t pktcnt = 0; ngtcp2_pkt_info pi; @@ -2442,14 +2370,21 @@ int Server::on_read(const Endpoint &ep) { CMSG_SPACE(sizeof(int))]; msghdr msg{ - .msg_name = &su, + .msg_name = &ss, .msg_iov = &msg_iov, .msg_iovlen = 1, .msg_control = msg_ctrl, }; - for (; pktcnt < 10;) { - msg.msg_namelen = sizeof(su); + auto start = util::timestamp(); + + for (; pktcnt < MAX_RECV_PKTS;) { + if (util::recv_pkt_time_threshold_exceeded( + config.cc_algo == NGTCP2_CC_ALGO_BBR, start, pktcnt)) { + return 0; + } + + msg.msg_namelen = sizeof(ss); msg.msg_controllen = sizeof(msg_ctrl); auto nread = recvmsg(ep.fd, &msg, 0); @@ -2467,14 +2402,17 @@ int Server::on_read(const Endpoint &ep) { continue; } - if (util::prohibited_port(util::port(&su))) { + Address remote_addr; + remote_addr.set(reinterpret_cast(&ss)); + + if (util::prohibited_port(remote_addr.port())) { ++pktcnt; continue; } - pi.ecn = msghdr_get_ecn(&msg, su.storage.ss_family); - auto local_addr = msghdr_get_local_addr(&msg, su.storage.ss_family); + pi.ecn = msghdr_get_ecn(&msg, ss.ss_family); + auto local_addr = msghdr_get_local_addr(&msg, ss.ss_family); if (!local_addr) { ++pktcnt; std::cerr << "Unable to obtain local address" << std::endl; @@ -2486,7 +2424,7 @@ int Server::on_read(const Endpoint &ep) { gso_size = static_cast(nread); } - set_port(*local_addr, ep.addr); + local_addr->port(ep.addr.port()); auto data = std::span{buf.data(), static_cast(nread)}; @@ -2497,10 +2435,8 @@ int Server::on_read(const Endpoint &ep) { if (!config.quiet) { std::array ifname; - std::cerr << "Received packet: local=" - << util::straddr(&local_addr->su.sa, local_addr->len) - << " remote=" << util::straddr(&su.sa, msg.msg_namelen) - << " if=" + std::cerr << "Received packet: local=" << util::straddr(*local_addr) + << " remote=" << util::straddr(remote_addr) << " if=" << if_indextoname(local_addr->ifindex, ifname.data()) << " ecn=0x" << std::hex << static_cast(pi.ecn) << std::dec << " " << datalen << " bytes" << std::endl; @@ -2516,8 +2452,7 @@ int Server::on_read(const Endpoint &ep) { std::cerr << "** Simulated incoming packet loss **" << std::endl; } } else { - read_pkt(ep, *local_addr, &su.sa, msg.msg_namelen, &pi, - {data.data(), datalen}); + read_pkt(ep, *local_addr, remote_addr, &pi, {data.data(), datalen}); } data = data.subspan(datalen); @@ -2528,8 +2463,7 @@ int Server::on_read(const Endpoint &ep) { } void Server::read_pkt(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, - const ngtcp2_pkt_info *pi, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data) { ngtcp2_version_cid vc; @@ -2540,7 +2474,8 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, break; case NGTCP2_ERR_VERSION_NEGOTIATION: send_version_negotiation(vc.version, {vc.scid, vc.scidlen}, - {vc.dcid, vc.dcidlen}, ep, local_addr, sa, salen); + {vc.dcid, vc.dcidlen}, ep, local_addr, + remote_addr); return; default: std::cerr << "Could not decode version and CID from QUIC packet header: " @@ -2562,7 +2497,7 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, if (!(data[0] & 0x80) && data.size() >= NGTCP2_SV_SCIDLEN + 21) { send_stateless_reset(data.size(), {vc.dcid, vc.dcidlen}, ep, local_addr, - sa, salen); + remote_addr); } return; @@ -2577,25 +2512,25 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, if (config.validate_addr || hd.tokenlen) { std::cerr << "Perform stateless address validation" << std::endl; if (hd.tokenlen == 0) { - send_retry(&hd, ep, local_addr, sa, salen, data.size() * 3); + send_retry(&hd, ep, local_addr, remote_addr, data.size() * 3); return; } if (hd.token[0] != NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2 && hd.dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN) { - send_stateless_connection_close(&hd, ep, local_addr, sa, salen); + send_stateless_connection_close(&hd, ep, local_addr, remote_addr); return; } switch (hd.token[0]) { case NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY2: - switch (verify_retry_token(&ocid, &hd, sa, salen)) { + switch (verify_retry_token(&ocid, &hd, remote_addr)) { case 0: pocid = &ocid; token_type = NGTCP2_TOKEN_TYPE_RETRY; break; case -1: - send_stateless_connection_close(&hd, ep, local_addr, sa, salen); + send_stateless_connection_close(&hd, ep, local_addr, remote_addr); return; case 1: hd.token = nullptr; @@ -2605,9 +2540,9 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, break; case NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR: - if (verify_token(&hd, sa, salen) != 0) { + if (verify_token(&hd, remote_addr) != 0) { if (config.validate_addr) { - send_retry(&hd, ep, local_addr, sa, salen, data.size() * 3); + send_retry(&hd, ep, local_addr, remote_addr, data.size() * 3); return; } @@ -2622,7 +2557,7 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, std::cerr << "Ignore unrecognized token" << std::endl; } if (config.validate_addr) { - send_retry(&hd, ep, local_addr, sa, salen, data.size() * 3); + send_retry(&hd, ep, local_addr, remote_addr, data.size() * 3); return; } @@ -2633,17 +2568,17 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, } auto h = std::make_unique(loop_, this); - if (h->init(ep, local_addr, sa, salen, &hd.scid, &hd.dcid, pocid, + if (h->init(ep, local_addr, remote_addr, &hd.scid, &hd.dcid, pocid, {hd.token, hd.tokenlen}, token_type, hd.version, tls_ctx_) != 0) { return; } - switch (h->on_read(ep, local_addr, sa, salen, pi, data)) { + switch (h->on_read(ep, local_addr, remote_addr, pi, data)) { case 0: break; case NETWORK_ERR_RETRY: - send_retry(&hd, ep, local_addr, sa, salen, data.size() * 3); + send_retry(&hd, ep, local_addr, remote_addr, data.size() * 3); return; default: return; @@ -2674,7 +2609,7 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, auto h = (*handler_it).second; auto conn = h->conn(); if (ngtcp2_conn_in_closing_period(conn)) { - if (h->send_conn_close(ep, local_addr, sa, salen, pi, data) != 0) { + if (h->send_conn_close(ep, local_addr, remote_addr, pi, data) != 0) { remove(h); } return; @@ -2683,7 +2618,7 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, return; } - if (auto rv = h->on_read(ep, local_addr, sa, salen, pi, data); rv != 0) { + if (auto rv = h->on_read(ep, local_addr, remote_addr, pi, data); rv != 0) { if (rv != NETWORK_ERR_CLOSE_WAIT) { remove(h); } @@ -2694,11 +2629,10 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr, } namespace { -uint32_t generate_reserved_version(const sockaddr *sa, socklen_t salen, - uint32_t version) { +uint32_t generate_reserved_version(const Address &addr, uint32_t version) { uint32_t h = 0x811C9DC5u; - const uint8_t *p = (const uint8_t *)sa; - const uint8_t *ep = p + salen; + const uint8_t *p = reinterpret_cast(addr.as_sockaddr()); + const uint8_t *ep = p + addr.size(); for (; p != ep; ++p) { h ^= *p; h *= 0x01000193u; @@ -2721,13 +2655,13 @@ int Server::send_version_negotiation(uint32_t version, std::span scid, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen) { + const Address &remote_addr) { Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE}; std::array sv; auto p = std::ranges::begin(sv); - *p++ = generate_reserved_version(sa, salen, version); + *p++ = generate_reserved_version(remote_addr, version); if (config.preferred_versions.empty()) { *p++ = NGTCP2_PROTO_VER_V1; @@ -2749,17 +2683,8 @@ int Server::send_version_negotiation(uint32_t version, buf.push(as_unsigned(nwrite)); - ngtcp2_addr laddr{ - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }; - ngtcp2_addr raddr{ - .addr = const_cast(sa), - .addrlen = salen, - }; - - if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.data()) != - NETWORK_ERR_OK) { + if (send_packet(ep, as_ngtcp2_addr(local_addr), as_ngtcp2_addr(remote_addr), + /* ecn = */ 0, buf.data()) != NETWORK_ERR_OK) { return -1; } @@ -2767,13 +2692,14 @@ int Server::send_version_negotiation(uint32_t version, } int Server::send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, - const Address &local_addr, const sockaddr *sa, - socklen_t salen, size_t max_pktlen) { + const Address &local_addr, const Address &remote_addr, + size_t max_pktlen) { std::array host; std::array port; - if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(), - port.size(), NI_NUMERICHOST | NI_NUMERICSERV); + if (auto rv = getnameinfo(remote_addr.as_sockaddr(), remote_addr.size(), + host.data(), host.size(), port.data(), port.size(), + NI_NUMERICHOST | NI_NUMERICSERV); rv != 0) { std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl; return -1; @@ -2797,7 +2723,8 @@ int Server::send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, auto tokenlen = ngtcp2_crypto_generate_retry_token2( token.data(), config.static_secret.data(), config.static_secret.size(), - chd->version, sa, salen, &scid, &chd->dcid, t); + chd->version, remote_addr.as_sockaddr(), remote_addr.size(), &scid, + &chd->dcid, t); if (tokenlen < 0) { return -1; } @@ -2820,17 +2747,8 @@ int Server::send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, buf.push(as_unsigned(nwrite)); - ngtcp2_addr laddr{ - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }; - ngtcp2_addr raddr{ - .addr = const_cast(sa), - .addrlen = salen, - }; - - if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.data()) != - NETWORK_ERR_OK) { + if (send_packet(ep, as_ngtcp2_addr(local_addr), as_ngtcp2_addr(remote_addr), + /* ecn = */ 0, buf.data()) != NETWORK_ERR_OK) { return -1; } @@ -2840,8 +2758,7 @@ int Server::send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, int Server::send_stateless_connection_close(const ngtcp2_pkt_hd *chd, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, - socklen_t salen) { + const Address &remote_addr) { Buffer buf{NGTCP2_MAX_UDP_PAYLOAD_SIZE}; auto nwrite = ngtcp2_crypto_write_connection_close( @@ -2854,17 +2771,8 @@ int Server::send_stateless_connection_close(const ngtcp2_pkt_hd *chd, buf.push(as_unsigned(nwrite)); - ngtcp2_addr laddr{ - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }; - ngtcp2_addr raddr{ - .addr = const_cast(sa), - .addrlen = salen, - }; - - if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.data()) != - NETWORK_ERR_OK) { + if (send_packet(ep, as_ngtcp2_addr(local_addr), as_ngtcp2_addr(remote_addr), + /* ecn = */ 0, buf.data()) != NETWORK_ERR_OK) { return -1; } @@ -2873,7 +2781,7 @@ int Server::send_stateless_connection_close(const ngtcp2_pkt_hd *chd, int Server::send_stateless_reset(size_t pktlen, std::span dcid, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen) { + const Address &remote_addr) { if (stateless_reset_bucket_ == 0) { return 0; } @@ -2929,17 +2837,8 @@ int Server::send_stateless_reset(size_t pktlen, std::span dcid, buf.push(as_unsigned(nwrite)); - ngtcp2_addr laddr{ - .addr = const_cast(&local_addr.su.sa), - .addrlen = local_addr.len, - }; - ngtcp2_addr raddr{ - .addr = const_cast(sa), - .addrlen = salen, - }; - - if (send_packet(ep, laddr, raddr, /* ecn = */ 0, buf.data()) != - NETWORK_ERR_OK) { + if (send_packet(ep, as_ngtcp2_addr(local_addr), as_ngtcp2_addr(remote_addr), + /* ecn = */ 0, buf.data()) != NETWORK_ERR_OK) { return -1; } @@ -2947,14 +2846,15 @@ int Server::send_stateless_reset(size_t pktlen, std::span dcid, } int Server::verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd, - const sockaddr *sa, socklen_t salen) { + const Address &remote_addr) { int rv; if (!config.quiet) { std::array host; std::array port; - if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(), + if (auto rv = getnameinfo(remote_addr.as_sockaddr(), remote_addr.size(), + host.data(), host.size(), port.data(), port.size(), NI_NUMERICHOST | NI_NUMERICSERV); rv != 0) { std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl; @@ -2970,8 +2870,8 @@ int Server::verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd, rv = ngtcp2_crypto_verify_retry_token2( ocid, hd->token, hd->tokenlen, config.static_secret.data(), - config.static_secret.size(), hd->version, sa, salen, &hd->dcid, - 10 * NGTCP2_SECONDS, t); + config.static_secret.size(), hd->version, remote_addr.as_sockaddr(), + remote_addr.size(), &hd->dcid, 10 * NGTCP2_SECONDS, t); switch (rv) { case 0: break; @@ -2993,13 +2893,13 @@ int Server::verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd, return 0; } -int Server::verify_token(const ngtcp2_pkt_hd *hd, const sockaddr *sa, - socklen_t salen) { +int Server::verify_token(const ngtcp2_pkt_hd *hd, const Address &remote_addr) { std::array host; std::array port; - if (auto rv = getnameinfo(sa, salen, host.data(), host.size(), port.data(), - port.size(), NI_NUMERICHOST | NI_NUMERICSERV); + if (auto rv = getnameinfo(remote_addr.as_sockaddr(), remote_addr.size(), + host.data(), host.size(), port.data(), port.size(), + NI_NUMERICHOST | NI_NUMERICSERV); rv != 0) { std::cerr << "getnameinfo: " << gai_strerror(rv) << std::endl; return -1; @@ -3013,13 +2913,12 @@ int Server::verify_token(const ngtcp2_pkt_hd *hd, const sockaddr *sa, auto t = util::system_clock_now(); - if (ngtcp2_crypto_verify_regular_token(hd->token, hd->tokenlen, - config.static_secret.data(), - config.static_secret.size(), sa, salen, - 3600 * NGTCP2_SECONDS, t) != 0) { - if (!config.quiet) { - std::cerr << "Could not verify token" << std::endl; - } + if (ngtcp2_crypto_verify_regular_token( + hd->token, hd->tokenlen, config.static_secret.data(), + config.static_secret.size(), remote_addr.as_sockaddr(), + remote_addr.size(), 3600 * NGTCP2_SECONDS, t) != 0) { + std::cerr << "Could not verify token" << std::endl; + return -1; } @@ -3293,8 +3192,7 @@ int parse_host_port(Address &dest, int af, const std::string_view &host_port) { return -1; } - dest.len = res->ai_addrlen; - memcpy(&dest.su, res->ai_addr, res->ai_addrlen); + dest.set(res->ai_addr); freeaddrinfo(res); @@ -3315,43 +3213,11 @@ void print_usage() { } } // namespace -namespace { -void config_set_default(Config &config) { - auto path = realpath(".", nullptr); - assert(path); - auto htdocs = std::string(path); - free(path); - - config = Config{ - .tx_loss_prob = 0., - .rx_loss_prob = 0., - .ciphers = util::crypto_default_ciphers(), - .groups = util::crypto_default_groups(), - .htdocs = std::move(htdocs), - .mime_types_file = "/etc/mime.types"sv, - .timeout = 30 * NGTCP2_SECONDS, - .max_data = 1_m, - .max_stream_data_bidi_remote = 256_k, - .max_stream_data_uni = 256_k, - .max_streams_bidi = 100, - .max_streams_uni = 3, - .max_window = 6_m, - .max_stream_window = 6_m, - .max_dyn_length = 20_m, - .cc_algo = NGTCP2_CC_ALGO_CUBIC, - .initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT, - .handshake_timeout = UINT64_MAX, - .ack_thresh = 2, - .initial_pkt_num = UINT32_MAX, - }; -} -} // namespace - namespace { void print_help() { print_usage(); - config_set_default(config); + Config config; std::cout << R"( Address to listen to. '*' binds to any address. @@ -3510,8 +3376,8 @@ void print_help() { Specify UDP datagram payload sizes to probe in Path MTU Discovery. must be strictly larger than 1200. --ech-config-file= - Read private key and ECHConfig from |PATH|. The file - denoted by |PATH| must contain private key and ECHConfig + Read private key and ECHConfig from . The file + denoted by must contain private key and ECHConfig as described in https://datatracker.ietf.org/doc/html/draft-farrell-tls-pemesni. ECH configuration is only applied if an underlying TLS @@ -3519,6 +3385,15 @@ void print_help() { --origin= Specify the origin to send in ORIGIN frame. Repeat to add multiple origins. + --no-gso Disables GSO. + --show-stat Print the connection statistics when the connection is + closed. + --gso-burst= + The maximum number of packets to aggregate for GSO. If + GSO is disabled, this is the maximum number of packets + to send per an event loop in a single connection. It + defaults to 0, which means it is not limited by the + configuration. -h, --help Display this help and exit. --- @@ -3541,8 +3416,6 @@ void print_help() { std::ofstream keylog_file; int main(int argc, char **argv) { - config_set_default(config); - if (argc) { prog = basename(argv[0]); } @@ -3592,6 +3465,9 @@ int main(int argc, char **argv) { {"pmtud-probes", required_argument, &flag, 32}, {"ech-config-file", required_argument, &flag, 33}, {"origin", required_argument, &flag, 34}, + {"no-gso", no_argument, &flag, 35}, + {"show-stat", no_argument, &flag, 36}, + {"gso-burst", required_argument, &flag, 37}, {}, }; @@ -3798,9 +3674,9 @@ int main(int argc, char **argv) { if (auto n = util::parse_uint_iec(optarg); !n) { std::cerr << "max-udp-payload-size: invalid argument" << std::endl; exit(EXIT_FAILURE); - } else if (*n > 64_k) { - std::cerr << "max-udp-payload-size: must not exceed 65536" - << std::endl; + } else if (*n > NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE) { + std::cerr << "max-udp-payload-size: must not exceed " + << NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE << std::endl; exit(EXIT_FAILURE); } else { config.max_udp_payload_size = *n; @@ -3930,10 +3806,12 @@ int main(int argc, char **argv) { if (auto n = util::parse_uint_iec(s); !n) { std::cerr << "pmtud-probes: invalid argument" << std::endl; exit(EXIT_FAILURE); - } else if (*n <= 1200 || *n >= 64_k) { - std::cerr - << "pmtud-probes: must be in range [1201, 65535], inclusive." - << std::endl; + } else if (*n <= NGTCP2_MAX_UDP_PAYLOAD_SIZE || + *n > NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE) { + std::cerr << "pmtud-probes: must be in range [" + << NGTCP2_MAX_UDP_PAYLOAD_SIZE + 1 << ", " + << NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE << "], inclusive." + << std::endl; exit(EXIT_FAILURE); } else { config.pmtud_probes.push_back(static_cast(*n)); @@ -3962,8 +3840,33 @@ int main(int argc, char **argv) { config.origin_list->push_back(static_cast(origin.size() >> 8)); config.origin_list->push_back(origin.size() & 0xff); - config.origin_list->insert(config.origin_list->end(), origin.begin(), - origin.end()); + std::ranges::copy(origin, std::back_inserter(*config.origin_list)); + + break; + } + case 35: + // --no-gso + config.no_gso = true; + break; + case 36: + // --show-stat + config.show_stat = true; + break; + case 37: { + // --gso-burst + auto n = util::parse_uint(optarg); + if (!n) { + std::cerr << "gso-burst: invalid argument" << std::endl; + exit(EXIT_FAILURE); + } + + if (*n > 64) { + std::cerr << "gso-burst: must be in range [0, 64], inclusive." + << std::endl; + exit(EXIT_FAILURE); + } + + config.gso_burst = static_cast(*n); break; } @@ -3971,7 +3874,7 @@ int main(int argc, char **argv) { break; default: break; - }; + } } if (argc - optind < 4) { @@ -4025,7 +3928,7 @@ int main(int argc, char **argv) { std::cerr << "Using document root " << config.htdocs << std::endl; - auto ev_loop_d = defer(ev_loop_destroy, EV_DEFAULT); + auto ev_loop_d = defer([] { ev_loop_destroy(EV_DEFAULT); }); auto keylog_filename = getenv("SSLKEYLOGFILE"); if (keylog_filename) { diff --git a/deps/ngtcp2/ngtcp2/examples/server.h b/deps/ngtcp2/ngtcp2/examples/server.h index 6f112f13ff61fd..ad12f040fe17bb 100644 --- a/deps/ngtcp2/ngtcp2/examples/server.h +++ b/deps/ngtcp2/ngtcp2/examples/server.h @@ -51,14 +51,6 @@ using namespace ngtcp2; -struct HTTPHeader { - HTTPHeader(const std::string_view &name, const std::string_view &value) - : name(name), value(value) {} - - std::string_view name; - std::string_view value; -}; - class Handler; struct FileEntry; @@ -83,15 +75,15 @@ struct Stream { std::string authority; std::string status_resp_body; // data is a pointer to the memory which maps file denoted by fd. - uint8_t *data; + uint8_t *data{}; // datalen is the length of mapped file by data. - uint64_t datalen; + uint64_t datalen{}; // dynresp is true if dynamic data response is enabled. - bool dynresp; + bool dynresp{}; // dyndataleft is the number of dynamic data left to send. - uint64_t dyndataleft; + uint64_t dyndataleft{}; // dynbuflen is the number of bytes in-flight. - uint64_t dynbuflen; + uint64_t dynbuflen{}; }; class Server; @@ -100,8 +92,8 @@ class Server; struct Endpoint { Address addr; ev_io rev; - Server *server; - int fd; + Server *server{}; + int fd{}; }; class Handler : public HandlerBase { @@ -109,19 +101,19 @@ class Handler : public HandlerBase { Handler(struct ev_loop *loop, Server *server); ~Handler(); - int init(const Endpoint &ep, const Address &local_addr, const sockaddr *sa, - socklen_t salen, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, - const ngtcp2_cid *ocid, std::span token, - ngtcp2_token_type token_type, uint32_t version, - TLSServerContext &tls_ctx); + int init(const Endpoint &ep, const Address &local_addr, + const Address &remote_addr, const ngtcp2_cid *dcid, + const ngtcp2_cid *scid, const ngtcp2_cid *ocid, + std::span token, ngtcp2_token_type token_type, + uint32_t version, TLSServerContext &tls_ctx); - int on_read(const Endpoint &ep, const Address &local_addr, const sockaddr *sa, - socklen_t salen, const ngtcp2_pkt_info *pi, + int on_read(const Endpoint &ep, const Address &local_addr, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data); int on_write(); int write_streams(); int feed_data(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, const ngtcp2_pkt_info *pi, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data); void update_timer(); int handle_expiry(); @@ -140,8 +132,8 @@ class Handler : public HandlerBase { int handle_error(); int send_conn_close(); int send_conn_close(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, - const ngtcp2_pkt_info *pi, std::span data); + const Address &remote_addr, const ngtcp2_pkt_info *pi, + std::span data); int update_key(uint8_t *rx_secret, uint8_t *tx_secret, ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv, @@ -185,23 +177,23 @@ class Handler : public HandlerBase { Server *server_; ev_io wev_; ev_timer timer_; - FILE *qlog_; - ngtcp2_cid scid_; - nghttp3_conn *httpconn_; + FILE *qlog_{}; + ngtcp2_cid scid_{}; + nghttp3_conn *httpconn_{}; std::unordered_map> streams_; // conn_closebuf_ contains a packet which contains CONNECTION_CLOSE. // This packet is repeatedly sent as a response to the incoming // packet in draining period. std::unique_ptr conn_closebuf_; // nkey_update_ is the number of key update occurred. - size_t nkey_update_; + size_t nkey_update_{}; bool no_gso_; struct { size_t bytes_recv; size_t bytes_sent; size_t num_pkts_recv; - size_t next_pkts_recv; - } close_wait_; + size_t next_pkts_recv = 1; + } close_wait_{}; struct { bool send_blocked; @@ -214,8 +206,8 @@ class Handler : public HandlerBase { std::span data; size_t gso_size; } blocked; - std::unique_ptr data; - } tx_; + } tx_{}; + std::array txbuf_; }; class Server { @@ -229,26 +221,25 @@ class Server { int on_read(const Endpoint &ep); void read_pkt(const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen, const ngtcp2_pkt_info *pi, + const Address &remote_addr, const ngtcp2_pkt_info *pi, std::span data); int send_version_negotiation(uint32_t version, std::span dcid, std::span scid, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen); + const Address &remote_addr); int send_retry(const ngtcp2_pkt_hd *chd, const Endpoint &ep, - const Address &local_addr, const sockaddr *sa, socklen_t salen, + const Address &local_addr, const Address &remote_addr, size_t max_pktlen); int send_stateless_connection_close(const ngtcp2_pkt_hd *chd, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen); + const Address &remote_addr); int send_stateless_reset(size_t pktlen, std::span dcid, const Endpoint &ep, const Address &local_addr, - const sockaddr *sa, socklen_t salen); + const Address &remote_addr); int verify_retry_token(ngtcp2_cid *ocid, const ngtcp2_pkt_hd *hd, - const sockaddr *sa, socklen_t salen); - int verify_token(const ngtcp2_pkt_hd *hd, const sockaddr *sa, - socklen_t salen); + const Address &remote_addr); + int verify_token(const ngtcp2_pkt_hd *hd, const Address &remote_addr); int send_packet(const Endpoint &ep, const ngtcp2_addr &local_addr, const ngtcp2_addr &remote_addr, unsigned int ecn, std::span data); @@ -270,7 +261,7 @@ class Server { TLSServerContext &tls_ctx_; ev_signal sigintev_; ev_timer stateless_reset_regen_timer_; - size_t stateless_reset_bucket_; + size_t stateless_reset_bucket_{NGTCP2_STATELESS_RESET_BURST}; }; #endif // !defined(SERVER_H) diff --git a/deps/ngtcp2/ngtcp2/examples/server_base.cc b/deps/ngtcp2/ngtcp2/examples/server_base.cc index d6dbf136b0cbe6..6f0b3be869af50 100644 --- a/deps/ngtcp2/ngtcp2/examples/server_base.cc +++ b/deps/ngtcp2/ngtcp2/examples/server_base.cc @@ -35,20 +35,24 @@ using namespace ngtcp2; extern Config config; Buffer::Buffer(const uint8_t *data, size_t datalen) - : buf{data, data + datalen}, begin(buf.data()), tail(begin + datalen) {} -Buffer::Buffer(size_t datalen) : buf(datalen), begin(buf.data()), tail(begin) {} + : buf{data, data + datalen}, begin{buf.data()}, tail{begin + datalen} {} +Buffer::Buffer(size_t datalen) : buf(datalen), begin{buf.data()}, tail{begin} {} static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) { auto h = static_cast(conn_ref->user_data); return h->conn(); } -HandlerBase::HandlerBase() : conn_ref_{get_conn, this}, conn_(nullptr) { +HandlerBase::HandlerBase() : conn_ref_{get_conn, this} { ngtcp2_ccerr_default(&last_error_); } HandlerBase::~HandlerBase() { if (conn_) { + if (config.show_stat) { + debug::print_conn_info(conn_); + } + ngtcp2_conn_del(conn_); } } diff --git a/deps/ngtcp2/ngtcp2/examples/server_base.h b/deps/ngtcp2/ngtcp2/examples/server_base.h index a2c38272671bfc..5c838bf6971c20 100644 --- a/deps/ngtcp2/ngtcp2/examples/server_base.h +++ b/deps/ngtcp2/ngtcp2/examples/server_base.h @@ -51,93 +51,93 @@ struct Config { Address preferred_ipv4_addr; Address preferred_ipv6_addr; // tx_loss_prob is probability of losing outgoing packet. - double tx_loss_prob; + double tx_loss_prob{}; // rx_loss_prob is probability of losing incoming packet. - double rx_loss_prob; + double rx_loss_prob{}; // ciphers is the list of enabled ciphers. - const char *ciphers; + const char *ciphers{util::crypto_default_ciphers()}; // groups is the list of supported groups. - const char *groups; + const char *groups{util::crypto_default_groups()}; // htdocs is a root directory to serve documents. - std::string htdocs; + std::string htdocs{util::realpath(".")}; // mime_types_file is a path to "MIME media types and the // extensions" file. Ubuntu mime-support package includes it in // /etc/mime/types. - std::string_view mime_types_file; + std::string_view mime_types_file{"/etc/mime.types"sv}; // mime_types maps file extension to MIME media type. std::unordered_map mime_types; // port is the port number which server listens on for incoming // connections. - uint16_t port; + uint16_t port{}; // quiet suppresses the output normally shown except for the error // messages. - bool quiet; + bool quiet{}; // timeout is an idle timeout for QUIC connection. - ngtcp2_duration timeout; + ngtcp2_duration timeout{30 * NGTCP2_SECONDS}; // show_secret is true if transport secrets should be printed out. - bool show_secret; + bool show_secret{}; // validate_addr is true if server requires address validation. - bool validate_addr; + bool validate_addr{}; // early_response is true if server starts sending response when it // receives HTTP header fields without waiting for request body. If // HTTP response data is written before receiving request body, // STOP_SENDING is sent. - bool early_response; + bool early_response{}; // verify_client is true if server verifies client with X.509 // certificate based authentication. - bool verify_client; + bool verify_client{}; // qlog_dir is the path to directory where qlog is stored. std::string_view qlog_dir; // no_quic_dump is true if hexdump of QUIC STREAM and CRYPTO data // should be disabled. - bool no_quic_dump; + bool no_quic_dump{}; // no_http_dump is true if hexdump of HTTP response body should be // disabled. - bool no_http_dump; + bool no_http_dump{}; // max_data is the initial connection-level flow control window. - uint64_t max_data; + uint64_t max_data{1_m}; // max_stream_data_bidi_local is the initial stream-level flow // control window for a bidirectional stream that the local endpoint // initiates. - uint64_t max_stream_data_bidi_local; + uint64_t max_stream_data_bidi_local{}; // max_stream_data_bidi_remote is the initial stream-level flow // control window for a bidirectional stream that the remote // endpoint initiates. - uint64_t max_stream_data_bidi_remote; + uint64_t max_stream_data_bidi_remote{256_k}; // max_stream_data_uni is the initial stream-level flow control // window for a unidirectional stream. - uint64_t max_stream_data_uni; + uint64_t max_stream_data_uni{256_k}; // max_streams_bidi is the number of the concurrent bidirectional // streams. - uint64_t max_streams_bidi; + uint64_t max_streams_bidi{100}; // max_streams_uni is the number of the concurrent unidirectional // streams. - uint64_t max_streams_uni; + uint64_t max_streams_uni{3}; // max_window is the maximum connection-level flow control window // size if auto-tuning is enabled. - uint64_t max_window; + uint64_t max_window{6_m}; // max_stream_window is the maximum stream-level flow control window // size if auto-tuning is enabled. - uint64_t max_stream_window; + uint64_t max_stream_window{6_m}; // max_dyn_length is the maximum length of dynamically generated // response. - uint64_t max_dyn_length; + uint64_t max_dyn_length{20_m}; // static_secret is used to derive keying materials for Retry and // Stateless Retry token. std::array static_secret; // cc_algo is the congestion controller algorithm. - ngtcp2_cc_algo cc_algo; + ngtcp2_cc_algo cc_algo{NGTCP2_CC_ALGO_CUBIC}; // initial_rtt is an initial RTT. - ngtcp2_duration initial_rtt; + ngtcp2_duration initial_rtt{NGTCP2_DEFAULT_INITIAL_RTT}; // max_udp_payload_size is the maximum UDP payload size that server // transmits. - size_t max_udp_payload_size; + size_t max_udp_payload_size{}; // send_trailers controls whether server sends trailer fields or // not. - bool send_trailers; + bool send_trailers{}; // handshake_timeout is the period of time before giving up QUIC // connection establishment. - ngtcp2_duration handshake_timeout; + ngtcp2_duration handshake_timeout{UINT64_MAX}; // preferred_versions includes QUIC versions in the order of // preference. Server negotiates one of those versions if a client // initially selects a less preferred version. @@ -147,21 +147,39 @@ struct Config { // transport_parameter. std::vector available_versions; // no_pmtud disables Path MTU Discovery. - bool no_pmtud; + bool no_pmtud{}; // ack_thresh is the minimum number of the received ACK eliciting // packets that triggers immediate acknowledgement. - size_t ack_thresh; + size_t ack_thresh{2}; // initial_pkt_num is the initial packet number for each packet // number space. If it is set to UINT32_MAX, it is chosen randomly. - uint32_t initial_pkt_num; + uint32_t initial_pkt_num{UINT32_MAX}; // pmtud_probes is the array of UDP datagram payload size to probes. std::vector pmtud_probes; // ech_config contains server-side ECH configuration. - util::ECHServerConfig ech_config; + util::ECHServerConfig ech_config{}; // origin_list contains a payload of ORIGIN frame. std::optional> origin_list; + // no_gso disables GSO. + bool no_gso{}; + // show_stat, if true, displays the connection statistics when the + // connection is closed. + bool show_stat{}; + // gso_burst is the number of packets to aggregate in GSO. 0 means + // it is not limited by the configuration. + size_t gso_burst{}; }; +struct HTTPHeader { + HTTPHeader(const std::string_view &name, const std::string_view &value) + : name{name}, value{value} {} + + std::string_view name; + std::string_view value; +}; + +inline constexpr size_t NGTCP2_STATELESS_RESET_BURST = 100; + struct Buffer { Buffer(const uint8_t *data, size_t datalen); explicit Buffer(size_t datalen); @@ -197,7 +215,7 @@ class HandlerBase { protected: ngtcp2_crypto_conn_ref conn_ref_; TLSServerSession tls_session_; - ngtcp2_conn *conn_; + ngtcp2_conn *conn_{}; ngtcp2_ccerr last_error_; }; diff --git a/deps/ngtcp2/ngtcp2/examples/shared.cc b/deps/ngtcp2/ngtcp2/examples/shared.cc index 8aa09ecdc2e89f..66c44ab51951ed 100644 --- a/deps/ngtcp2/ngtcp2/examples/shared.cc +++ b/deps/ngtcp2/ngtcp2/examples/shared.cc @@ -170,10 +170,9 @@ std::optional
msghdr_get_local_addr(msghdr *msg, int family) { in_pktinfo pktinfo; memcpy(&pktinfo, CMSG_DATA(cmsg), sizeof(pktinfo)); Address res{ - .len = sizeof(res.su.in), .ifindex = static_cast(pktinfo.ipi_ifindex), }; - auto &sa = res.su.in; + auto &sa = res.skaddr.emplace(); sa.sin_family = AF_INET; sa.sin_addr = pktinfo.ipi_addr; return res; @@ -186,10 +185,9 @@ std::optional
msghdr_get_local_addr(msghdr *msg, int family) { in6_pktinfo pktinfo; memcpy(&pktinfo, CMSG_DATA(cmsg), sizeof(pktinfo)); Address res{ - .len = sizeof(res.su.in6), .ifindex = static_cast(pktinfo.ipi6_ifindex), }; - auto &sa = res.su.in6; + auto &sa = res.skaddr.emplace(); sa.sin6_family = AF_INET6; sa.sin6_addr = pktinfo.ipi6_addr; return res; @@ -216,64 +214,52 @@ size_t msghdr_get_udp_gro(msghdr *msg) { return static_cast(gso_size); } -void set_port(Address &dst, const Address &src) { - switch (dst.su.storage.ss_family) { - case AF_INET: - assert(AF_INET == src.su.storage.ss_family); - dst.su.in.sin_port = src.su.in.sin_port; - return; - case AF_INET6: - assert(AF_INET6 == src.su.storage.ss_family); - dst.su.in6.sin6_port = src.su.in6.sin6_port; - return; - default: - assert(0); - } -} - #ifdef HAVE_LINUX_RTNETLINK_H struct nlmsg { nlmsghdr hdr; rtmsg msg; rtattr dst; - in_addr_union dst_addr; + uint8_t dst_addr[sizeof(sockaddr_storage)]; }; namespace { int send_netlink_msg(int fd, const Address &remote_addr, uint32_t seq) { nlmsg nlmsg{ - .hdr = - { - .nlmsg_type = RTM_GETROUTE, - .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, - .nlmsg_seq = seq, - }, - .msg = - { - .rtm_family = static_cast(remote_addr.su.sa.sa_family), - .rtm_protocol = RTPROT_KERNEL, - }, - .dst = - { - .rta_type = RTA_DST, - }, + .hdr{ + .nlmsg_type = RTM_GETROUTE, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, + .nlmsg_seq = seq, + }, + .msg{ + .rtm_family = static_cast(remote_addr.family()), + .rtm_protocol = RTPROT_KERNEL, + }, + .dst{ + .rta_type = RTA_DST, + }, }; - switch (remote_addr.su.sa.sa_family) { - case AF_INET: - nlmsg.dst.rta_len = RTA_LENGTH(sizeof(remote_addr.su.in.sin_addr)); - memcpy(RTA_DATA(&nlmsg.dst), &remote_addr.su.in.sin_addr, - sizeof(remote_addr.su.in.sin_addr)); - break; - case AF_INET6: - nlmsg.dst.rta_len = RTA_LENGTH(sizeof(remote_addr.su.in6.sin6_addr)); - memcpy(RTA_DATA(&nlmsg.dst), &remote_addr.su.in6.sin6_addr, - sizeof(remote_addr.su.in6.sin6_addr)); - break; - default: - assert(0); - } + std::visit( + [&nlmsg](auto &&arg) { + using T = std::decay_t; + + if constexpr (std::is_same_v) { + nlmsg.dst.rta_len = RTA_LENGTH(sizeof(arg.sin_addr)); + memcpy(RTA_DATA(&nlmsg.dst), &arg.sin_addr, sizeof(arg.sin_addr)); + return; + } + + if constexpr (std::is_same_v) { + nlmsg.dst.rta_len = RTA_LENGTH(sizeof(arg.sin6_addr)); + memcpy(RTA_DATA(&nlmsg.dst), &arg.sin6_addr, sizeof(arg.sin6_addr)); + return; + } + + assert(0); + abort(); + }, + remote_addr.skaddr); nlmsg.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(nlmsg.msg) + nlmsg.dst.rta_len); @@ -309,7 +295,7 @@ int send_netlink_msg(int fd, const Address &remote_addr, uint32_t seq) { } // namespace namespace { -int recv_netlink_msg(in_addr_union &iau, int fd, uint32_t seq) { +int recv_netlink_msg(InAddr &ia, int fd, uint32_t seq) { std::array buf; iovec iov = { .iov_base = buf.data(), @@ -334,8 +320,6 @@ int recv_netlink_msg(in_addr_union &iau, int fd, uint32_t seq) { return -1; } - size_t in_addrlen = 0; - for (auto hdr = reinterpret_cast(buf.data()); NLMSG_OK(hdr, nread); hdr = NLMSG_NEXT(hdr, nread)) { if (seq != hdr->nlmsg_seq) { @@ -372,28 +356,42 @@ int recv_netlink_msg(in_addr_union &iau, int fd, uint32_t seq) { } switch (static_cast(NLMSG_DATA(hdr))->rtm_family) { - case AF_INET: - in_addrlen = sizeof(in_addr); + case AF_INET: { + constexpr auto in_addrlen = sizeof(in_addr); + if (RTA_LENGTH(in_addrlen) != rta->rta_len) { + return -1; + } + + in_addr addr; + memcpy(&addr, RTA_DATA(rta), in_addrlen); + + ia.emplace(addr); + break; - case AF_INET6: - in_addrlen = sizeof(in6_addr); + } + case AF_INET6: { + constexpr auto in_addrlen = sizeof(in6_addr); + if (RTA_LENGTH(in_addrlen) != rta->rta_len) { + return -1; + } + + in6_addr addr; + memcpy(&addr, RTA_DATA(rta), in_addrlen); + + ia.emplace(addr); + break; + } default: assert(0); abort(); } - if (RTA_LENGTH(in_addrlen) != rta->rta_len) { - return -1; - } - - memcpy(&iau, RTA_DATA(rta), in_addrlen); - break; } } - if (in_addrlen == 0) { + if (in_addr_empty(ia)) { return -1; } @@ -459,7 +457,7 @@ int recv_netlink_msg(in_addr_union &iau, int fd, uint32_t seq) { } } // namespace -int get_local_addr(in_addr_union &iau, const Address &remote_addr) { +int get_local_addr(InAddr &ia, const Address &remote_addr) { sockaddr_nl sa{ .nl_family = AF_NETLINK, }; @@ -471,7 +469,7 @@ int get_local_addr(in_addr_union &iau, const Address &remote_addr) { return -1; } - auto fd_d = defer(close, fd); + auto fd_d = defer([fd] { close(fd); }); if (bind(fd, reinterpret_cast(&sa), sizeof(sa)) == -1) { std::cerr << "bind: Could not bind netlink socket: " << strerror(errno) @@ -485,23 +483,163 @@ int get_local_addr(in_addr_union &iau, const Address &remote_addr) { return -1; } - return recv_netlink_msg(iau, fd, seq); + return recv_netlink_msg(ia, fd, seq); } #endif // defined(HAVE_LINUX_NETLINK_H) -bool addreq(const sockaddr *sa, const in_addr_union &iau) { +bool addreq(const Address &addr, const InAddr &ia) { + return std::visit( + [&ia](auto &&arg) -> bool { + using T = std::decay_t; + + if constexpr (std::is_same_v) { + auto rhs = std::get_if(&ia); + + return rhs && memcmp(&arg.sin_addr, rhs, sizeof(*rhs)) == 0; + } + + if constexpr (std::is_same_v) { + auto rhs = std::get_if(&ia); + + return rhs && memcmp(&arg.sin6_addr, rhs, sizeof(*rhs)) == 0; + } + + assert(0); + abort(); + }, + addr.skaddr); +} + +const void *in_addr_get_ptr(const InAddr &ia) { + return std::visit( + [](auto &&arg) { + if constexpr (std::is_same_v, + std::monostate>) { + assert(0); + abort(); + } + + return reinterpret_cast(&arg); + }, + ia); +} + +bool in_addr_empty(const InAddr &ia) { + return std::holds_alternative(ia); +} + +const sockaddr *as_sockaddr(const Sockaddr &skaddr) { + return std::visit( + [](auto &&arg) { + if constexpr (std::is_same_v, + std::monostate>) { + assert(0); + abort(); + } + + return reinterpret_cast(&arg); + }, + skaddr); +} + +sockaddr *as_sockaddr(Sockaddr &skaddr) { + return std::visit( + [](auto &&arg) { + if constexpr (std::is_same_v, + std::monostate>) { + assert(0); + abort(); + } + + return reinterpret_cast(&arg); + }, + skaddr); +} + +int sockaddr_family(const Sockaddr &skaddr) { + return as_sockaddr(skaddr)->sa_family; +} + +uint16_t sockaddr_port(const Sockaddr &skaddr) { + return std::visit( + [](auto &&arg) -> uint16_t { + using T = std::decay_t; + + if constexpr (std::is_same_v) { + return ntohs(arg.sin_port); + } + + if constexpr (std::is_same_v) { + return ntohs(arg.sin6_port); + } + + assert(0); + abort(); + }, + skaddr); +} + +void sockaddr_port(Sockaddr &skaddr, uint16_t port) { + std::visit( + [port](auto &&arg) { + using T = std::decay_t; + + if constexpr (std::is_same_v) { + arg.sin_port = htons(port); + return; + } + + if constexpr (std::is_same_v) { + arg.sin6_port = htons(port); + return; + } + + assert(0); + abort(); + }, + skaddr); +} + +void sockaddr_set(Sockaddr &skaddr, const sockaddr *sa) { switch (sa->sa_family) { case AF_INET: - return memcmp(&reinterpret_cast(sa)->sin_addr, &iau.in, - sizeof(iau.in)) == 0; + skaddr.emplace(*reinterpret_cast(sa)); + return; case AF_INET6: - return memcmp(&reinterpret_cast(sa)->sin6_addr, - &iau.in6, sizeof(iau.in6)) == 0; + skaddr.emplace(*reinterpret_cast(sa)); + return; default: assert(0); abort(); } } +socklen_t sockaddr_size(const Sockaddr &skaddr) { + return std::visit( + [](auto &&arg) { return static_cast(sizeof(arg)); }, skaddr); +} + +bool sockaddr_empty(const Sockaddr &skaddr) { + return std::holds_alternative(skaddr); +} + +const sockaddr *Address::as_sockaddr() const { + return ngtcp2::as_sockaddr(skaddr); +} + +sockaddr *Address::as_sockaddr() { return ngtcp2::as_sockaddr(skaddr); } + +int Address::family() const { return sockaddr_family(skaddr); } + +uint16_t Address::port() const { return sockaddr_port(skaddr); } + +void Address::port(uint16_t port) { sockaddr_port(skaddr, port); } + +void Address::set(const sockaddr *sa) { sockaddr_set(skaddr, sa); } + +socklen_t Address::size() const { return sockaddr_size(skaddr); } + +bool Address::empty() const { return sockaddr_empty(skaddr); } + } // namespace ngtcp2 diff --git a/deps/ngtcp2/ngtcp2/examples/shared.h b/deps/ngtcp2/ngtcp2/examples/shared.h index 55d8d189ca03f5..26e678816e8f98 100644 --- a/deps/ngtcp2/ngtcp2/examples/shared.h +++ b/deps/ngtcp2/ngtcp2/examples/shared.h @@ -51,15 +51,17 @@ consteval std::span as_uint8_span(const uint8_t (&s)[N]) { return {s, N - 1}; } -constexpr uint8_t RAW_HQ_ALPN[] = "\xahq-interop"; -constexpr auto HQ_ALPN = as_uint8_span(RAW_HQ_ALPN); -constexpr auto HQ_ALPN_V1 = as_uint8_span(RAW_HQ_ALPN); +inline constexpr uint8_t RAW_HQ_ALPN[] = "\xahq-interop"; +inline constexpr auto HQ_ALPN = as_uint8_span(RAW_HQ_ALPN); +inline constexpr auto HQ_ALPN_V1 = as_uint8_span(RAW_HQ_ALPN); -constexpr uint8_t RAW_H3_ALPN[] = "\x2h3"; -constexpr auto H3_ALPN = as_uint8_span(RAW_H3_ALPN); -constexpr auto H3_ALPN_V1 = as_uint8_span(RAW_H3_ALPN); +inline constexpr uint8_t RAW_H3_ALPN[] = "\x2h3"; +inline constexpr auto H3_ALPN = as_uint8_span(RAW_H3_ALPN); +inline constexpr auto H3_ALPN_V1 = as_uint8_span(RAW_H3_ALPN); -constexpr uint32_t TLS_ALERT_ECH_REQUIRED = 121; +inline constexpr uint32_t TLS_ALERT_ECH_REQUIRED = 121; + +inline constexpr size_t MAX_RECV_PKTS = 64; // msghdr_get_ecn gets ECN bits from |msg|. |family| is the address // family from which packet is received. @@ -85,14 +87,61 @@ std::optional
msghdr_get_local_addr(msghdr *msg, int family); // not found, or UDP_GRO is not supported, this function returns 0. size_t msghdr_get_udp_gro(msghdr *msg); -void set_port(Address &dst, const Address &src); - // get_local_addr stores preferred local address (interface address) -// in |iau| for a given destination address |remote_addr|. -int get_local_addr(in_addr_union &iau, const Address &remote_addr); +// in |ia| for a given destination address |remote_addr|. +int get_local_addr(InAddr &ia, const Address &remote_addr); + +// addreq returns true if |addr| and |ia| contain the same address. +bool addreq(const Address &addr, const InAddr &ia); + +// in_addr_get_ptr returns the pointer to the stored address in |ia|. +// It is undefined if |ia| contains std::monostate. +const void *in_addr_get_ptr(const InAddr &ia); + +// in_addr_empty returns true if |ia| if it does not contain any +// meaningful address. +bool in_addr_empty(const InAddr &ia); + +// as_sockaddr returns the pointer to the stored address casted to +// const sockaddr *. +[[nodiscard]] const sockaddr *as_sockaddr(const Sockaddr &skaddr); +[[nodiscard]] sockaddr *as_sockaddr(Sockaddr &skaddr); + +// sockaddr_family returns the address family. +[[nodiscard]] int sockaddr_family(const Sockaddr &skaddr); + +// sockaddr_port returns the port. +[[nodiscard]] uint16_t sockaddr_port(const Sockaddr &skaddr); -// addreq returns true if |sa| and |iau| contain the same address. -bool addreq(const sockaddr *sa, const in_addr_union &iau); +// sockaddr_port sets |port| to |skaddr|. +void sockaddr_port(Sockaddr &skaddr, uint16_t port); + +// sockaddr_set stores |sa| to |skaddr|. The address family is +// determined by |sa|->sa_family, and |sa| must point to the memory +// that contains valid object which is either sockaddr_in or +// sockaddr_in6. +void sockaddr_set(Sockaddr &skaddr, const sockaddr *sa); + +// sockaddr_size returns the size of the stored address. +[[nodiscard]] socklen_t sockaddr_size(const Sockaddr &skaddr); + +// sockaddr_empty returns true if |skaddr| does not contain any +// meaningful address. +[[nodiscard]] bool sockaddr_empty(const Sockaddr &skaddr); + +[[nodiscard]] inline ngtcp2_addr as_ngtcp2_addr(const Address &addr) { + return { + .addr = const_cast(addr.as_sockaddr()), + .addrlen = addr.size(), + }; +} + +[[nodiscard]] inline ngtcp2_addr as_ngtcp2_addr(Address &addr) { + return { + .addr = addr.as_sockaddr(), + .addrlen = addr.size(), + }; +} } // namespace ngtcp2 diff --git a/deps/ngtcp2/ngtcp2/examples/sim.cc b/deps/ngtcp2/ngtcp2/examples/sim.cc new file mode 100644 index 00000000000000..d4dc423eebe189 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/examples/sim.cc @@ -0,0 +1,977 @@ +/* + * ngtcp2 + * + * Copyright (c) 2025 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "sim.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "ngtcp2/ngtcp2_crypto_wolfssl.h" + +#include "util.h" +#include "shared.h" +#include "debug.h" + +using namespace std::literals; + +namespace ngtcp2 { + +namespace { +constexpr auto ALPN_LIST = "ngtcp2-sim"sv; +constexpr size_t CIDLEN = 10; +constexpr uint8_t SERVER_SECRET[] = "server_secret"; + +int generate_secure_random(std::span data) { + if (wolfSSL_RAND_bytes(data.data(), static_cast(data.size())) != 1) { + return -1; + } + + return 0; +} + +void rand_bytes(uint8_t *dest, size_t destlen, + const ngtcp2_rand_ctx *rand_ctx) { + auto rv = generate_secure_random({dest, destlen}); + (void)rv; + assert(0 == rv); +} + +int get_new_connection_id(ngtcp2_conn *conn, ngtcp2_cid *cid, uint8_t *token, + size_t cidlen, void *user_data) { + if (generate_secure_random({cid->data, cidlen}) != 0) { + return NGTCP2_ERR_CALLBACK_FAILURE; + } + + cid->datalen = cidlen; + if (ngtcp2_crypto_generate_stateless_reset_token( + token, SERVER_SECRET, sizeof(SERVER_SECRET) - 1, cid) != 0) { + return NGTCP2_ERR_CALLBACK_FAILURE; + } + + return 0; +} +} // namespace + +ngtcp2_tstamp to_ngtcp2_tstamp(const Timestamp &ts) { + return static_cast(ts.time_since_epoch().count()); +} + +Timestamp to_timestamp(ngtcp2_tstamp ts) { + return Timestamp{Timestamp::duration{ts}}; +} + +uint64_t LinkConfig::compute_expected_goodput(Timestamp::duration rtt) const { + // Assume 80% usage ratio. + uint64_t g = rate * 8 / 10; + + if (loss < 1e-9) { + return g; + } + + constexpr double margin = 0.95; + + return std::min(g, + static_cast(MAX_UDP_PAYLOAD_SIZE * NGTCP2_SECONDS / + static_cast(rtt.count()) / + sqrt(loss) * 8 * margin)); +} + +namespace { +int recv_stream_data(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id, + uint64_t offset, const uint8_t *data, size_t datalen, + void *user_data, void *stream_user_data) { + ngtcp2_conn_extend_max_stream_offset(conn, stream_id, datalen); + ngtcp2_conn_extend_max_offset(conn, datalen); + + return 0; +} +} // namespace + +ngtcp2_callbacks default_client_callbacks() { + return ngtcp2_callbacks{ + .client_initial = ngtcp2_crypto_client_initial_cb, + .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb, + .encrypt = ngtcp2_crypto_encrypt_cb, + .decrypt = ngtcp2_crypto_decrypt_cb, + .hp_mask = ngtcp2_crypto_hp_mask_cb, + .recv_stream_data = recv_stream_data, + .recv_retry = ngtcp2_crypto_recv_retry_cb, + .rand = rand_bytes, + .get_new_connection_id = get_new_connection_id, + .update_key = ngtcp2_crypto_update_key_cb, + .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb, + .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb, + .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb, + .version_negotiation = ngtcp2_crypto_version_negotiation_cb, + }; +} + +ngtcp2_callbacks default_server_callbacks() { + return ngtcp2_callbacks{ + .recv_client_initial = ngtcp2_crypto_recv_client_initial_cb, + .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb, + .encrypt = ngtcp2_crypto_encrypt_cb, + .decrypt = ngtcp2_crypto_decrypt_cb, + .hp_mask = ngtcp2_crypto_hp_mask_cb, + .recv_stream_data = recv_stream_data, + .rand = rand_bytes, + .get_new_connection_id = get_new_connection_id, + .update_key = ngtcp2_crypto_update_key_cb, + .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb, + .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb, + .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb, + .version_negotiation = ngtcp2_crypto_version_negotiation_cb, + }; +} + +ngtcp2_settings default_client_settings() { + ngtcp2_settings settings; + ngtcp2_settings_default(&settings); + + settings.log_printf = debug::log_printf; + + return settings; +} + +ngtcp2_settings default_server_settings() { + ngtcp2_settings settings; + ngtcp2_settings_default(&settings); + + settings.log_printf = debug::log_printf; + + return settings; +} + +ngtcp2_transport_params default_client_transport_params() { + ngtcp2_transport_params params; + ngtcp2_transport_params_default(¶ms); + + return params; +} + +ngtcp2_transport_params default_server_transport_params() { + ngtcp2_transport_params params; + ngtcp2_transport_params_default(¶ms); + + return params; +} + +Sockaddr getaddrinfo(const char *host, const char *svc) { + auto hints = addrinfo{ + .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV, + .ai_family = AF_UNSPEC, + }; + addrinfo *rp; + + auto rv = getaddrinfo(host, svc, &hints, &rp); + (void)rv; + assert(0 == rv); + + Sockaddr skaddr; + sockaddr_set(skaddr, rp->ai_addr); + + freeaddrinfo(rp); + + return skaddr; +} + +ngtcp2_addr default_client_addr() { + static auto skaddr = getaddrinfo("10.0.1.1", "12345"); + + return ngtcp2_addr{ + .addr = as_sockaddr(skaddr), + .addrlen = sockaddr_size(skaddr), + }; +} + +ngtcp2_addr default_server_addr() { + static auto skaddr = getaddrinfo("10.0.2.1", "443"); + + return ngtcp2_addr{ + .addr = as_sockaddr(skaddr), + .addrlen = sockaddr_size(skaddr), + }; +} + +EndpointConfig default_client_endpoint_config() { + return EndpointConfig{ + .callbacks = default_client_callbacks(), + .settings = default_client_settings(), + .params = default_client_transport_params(), + .local_addr = default_client_addr(), + }; +} + +EndpointConfig default_server_endpoint_config() { + return EndpointConfig{ + .server = true, + .callbacks = default_server_callbacks(), + .settings = default_server_settings(), + .params = default_server_transport_params(), + .local_addr = default_server_addr(), + }; +} + +namespace { +ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) { + auto ep = static_cast(conn_ref->user_data); + return ep->get_conn(); +} +} // namespace + +Endpoint::Endpoint() + : conn_ref_{ngtcp2::get_conn, this}, channel_{config_.link} {} + +Endpoint::Endpoint(const EndpointConfig &config) + : config_{config}, + conn_ref_{ngtcp2::get_conn, this}, + channel_{config_.link} {} + +Endpoint::Endpoint(Endpoint &&other) noexcept + : config_{std::exchange(other.config_, {})}, + ssl_ctx_{std::exchange(other.ssl_ctx_, nullptr)}, + ssl_{std::exchange(other.ssl_, nullptr)}, + conn_{std::exchange(other.conn_, nullptr)}, + conn_ref_{ngtcp2::get_conn, this}, + channel_{std::exchange(other.channel_, {})}, + initialized_{std::exchange(other.initialized_, false)} {} + +Endpoint::~Endpoint() { + ngtcp2_conn_del(conn_); + + if (ssl_) { + wolfSSL_free(ssl_); + } + + if (ssl_ctx_) { + wolfSSL_CTX_free(ssl_ctx_); + } +} + +Endpoint &Endpoint::operator=(Endpoint &&other) noexcept { + ngtcp2_conn_del(conn_); + + if (ssl_) { + wolfSSL_free(ssl_); + } + + if (ssl_ctx_) { + wolfSSL_CTX_free(ssl_ctx_); + } + + config_ = std::exchange(other.config_, {}); + ssl_ctx_ = std::exchange(other.ssl_ctx_, nullptr); + ssl_ = std::exchange(other.ssl_, nullptr); + conn_ = std::exchange(other.conn_, nullptr); + conn_ref_ = {ngtcp2::get_conn, this}; + channel_ = std::exchange(other.channel_, {}); + initialized_ = std::exchange(other.initialized_, false); + + if (ssl_) { + wolfSSL_set_app_data(ssl_, &conn_ref_); + } + + return *this; +} + +namespace { +constexpr auto tls_key = R"(-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgwEvkGGgXAcRaG7Z8 +gA7C6+W2RsW9gcjV9e5ybr0ikaahRANCAASCo35bDi+Q/q/CzHI1e5QaBrbqbFhW +G20QbVAeMK8l0oC8OGD3PSpZK1HXwALwzhMuwhxDos3ANb5naa5y17fQ +-----END PRIVATE KEY----- +)"sv; + +constexpr auto tls_crt = R"(-----BEGIN CERTIFICATE----- +MIICBzCCAa2gAwIBAgIUd2l6Pce3S0QH3dQC0Q/CjHbmggowCgYIKoZIzj0EAwIw +WTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu +dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1 +MTExNDExNTcwMFoXDTI1MTIxNDExNTcwMFowWTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +gqN+Ww4vkP6vwsxyNXuUGga26mxYVhttEG1QHjCvJdKAvDhg9z0qWStR18AC8M4T +LsIcQ6LNwDW+Z2mucte30KNTMFEwHQYDVR0OBBYEFFVgXLoLwzpf6+twP5z8Ujr2 +5mxnMB8GA1UdIwQYMBaAFFVgXLoLwzpf6+twP5z8Ujr25mxnMA8GA1UdEwEB/wQF +MAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIhAO4tnDNRAcooz62vf2m7vTyDqFCjcaIv +SJ9Gq0lvEXEcAiBwWBNUASBqLaje3hmtgwxcF7EIqqiGo5j8f9Ufgu6SRg== +-----END CERTIFICATE----- +)"sv; +} // namespace + +int Endpoint::setup_server(std::span original_dcid, + std::span client_scid, + uint32_t version, const ngtcp2_addr *remote_addr) { + int rv; + + ngtcp2_cid scid{ + .datalen = CIDLEN, + }; + + if (generate_secure_random({scid.data, scid.datalen}) != 0) { + return -1; + } + + ngtcp2_cid dcid; + ngtcp2_cid_init(&dcid, client_scid.data(), client_scid.size()); + + auto params = config_.params; + ngtcp2_cid_init(¶ms.original_dcid, original_dcid.data(), + original_dcid.size()); + params.original_dcid_present = 1; + + if (ngtcp2_crypto_generate_stateless_reset_token( + params.stateless_reset_token, SERVER_SECRET, sizeof(SERVER_SECRET) - 1, + &scid)) { + return -1; + } + + auto path = ngtcp2_path{ + .local = config_.local_addr, + .remote = *remote_addr, + }; + + rv = ngtcp2_conn_server_new(&conn_, &dcid, &scid, &path, version, + &config_.callbacks, &config_.settings, ¶ms, + nullptr, config_.user_data); + if (rv != 0) { + return -1; + } + + ssl_ctx_ = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + if (!ssl_ctx_) { + return -1; + } + + if (ngtcp2_crypto_wolfssl_configure_server_context(ssl_ctx_) != 0) { + return -1; + } + + if (wolfSSL_CTX_use_certificate_buffer( + ssl_ctx_, reinterpret_cast(tls_crt.data()), + static_cast(tls_crt.size()), SSL_FILETYPE_PEM) != SSL_SUCCESS) { + return -1; + } + + if (wolfSSL_CTX_use_PrivateKey_buffer( + ssl_ctx_, reinterpret_cast(tls_key.data()), + static_cast(tls_key.size()), SSL_FILETYPE_PEM) != SSL_SUCCESS) { + return -1; + } + + ssl_ = wolfSSL_new(ssl_ctx_); + if (!ssl_) { + return -1; + } + + if (wolfSSL_UseALPN(ssl_, const_cast(ALPN_LIST.data()), + ALPN_LIST.size(), + WOLFSSL_ALPN_FAILED_ON_MISMATCH) != WOLFSSL_SUCCESS) { + return -1; + } + + wolfSSL_set_app_data(ssl_, &conn_ref_); + wolfSSL_set_accept_state(ssl_); + wolfSSL_set_quic_transport_version(ssl_, 0x39); + + ngtcp2_conn_set_tls_native_handle(conn_, ssl_); + + initialized_ = true; + + return 0; +} + +int Endpoint::setup_client(const ngtcp2_addr *remote_addr) { + int rv; + + ngtcp2_cid dcid{ + .datalen = CIDLEN, + }; + ngtcp2_cid scid{ + .datalen = CIDLEN, + }; + + if (generate_secure_random({dcid.data, dcid.datalen}) != 0 || + generate_secure_random({scid.data, scid.datalen}) != 0) { + assert(0); + return -1; + } + + auto path = ngtcp2_path{ + .local = config_.local_addr, + .remote = *remote_addr, + }; + + rv = ngtcp2_conn_client_new(&conn_, &dcid, &scid, &path, NGTCP2_PROTO_VER_V1, + &config_.callbacks, &config_.settings, + &config_.params, nullptr, config_.user_data); + if (rv != 0) { + return -1; + } + + ssl_ctx_ = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + if (!ssl_ctx_) { + return -1; + } + + if (ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx_) != 0) { + return -1; + } + + ssl_ = wolfSSL_new(ssl_ctx_); + if (!ssl_) { + return -1; + } + + if (wolfSSL_UseALPN(ssl_, const_cast(ALPN_LIST.data()), + ALPN_LIST.size(), + WOLFSSL_ALPN_FAILED_ON_MISMATCH) != WOLFSSL_SUCCESS) { + return -1; + } + + wolfSSL_set_app_data(ssl_, &conn_ref_); + wolfSSL_set_connect_state(ssl_); + wolfSSL_set_quic_transport_version(ssl_, 0x39); + + ngtcp2_conn_set_tls_native_handle(conn_, ssl_); + + initialized_ = true; + + return 0; +} + +int Endpoint::on_read(const NetworkPath &path, std::span pkt, + const Context &ctx) { + auto ts = to_ngtcp2_tstamp(ctx.ts); + auto cpath = to_ngtcp2_path(path); + + auto rv = + ngtcp2_conn_read_pkt(conn_, &cpath, nullptr, pkt.data(), pkt.size(), ts); + if (rv != 0) { + std::cerr << "ngtcp2_conn_read_pkt: " << ngtcp2_strerror(rv) << std::endl; + return -1; + } + + ctx.endpoint->get_channel().schedule_timeout(ctx.ts); + + return 0; +} + +int Endpoint::on_write(const Context &ctx) { + if (config_.on_write(conn_, ctx) != 0) { + return -1; + } + + auto next_expiry_ts = ngtcp2_conn_get_expiry(conn_); + if (next_expiry_ts == UINT64_MAX) { + return 0; + } + + ctx.endpoint->get_channel().schedule_timeout(to_timestamp(next_expiry_ts)); + + return 0; +} + +int Endpoint::on_timeout(const Context &ctx) { + auto rv = ngtcp2_conn_handle_expiry(conn_, to_ngtcp2_tstamp(ctx.ts)); + if (rv != 0) { + std::cerr << "ngtcp2_conn_handle_expiry: " << ngtcp2_strerror(rv) + << std::endl; + return -1; + } + + return on_write(ctx); +} + +NetworkPath to_network_path(const ngtcp2_path *path) { + NetworkPath res; + + res.local.set(path->local.addr); + res.remote.set(path->remote.addr); + + return res; +} + +ngtcp2_path to_ngtcp2_path(const NetworkPath &path) { + return { + .local = as_ngtcp2_addr(path.local), + .remote = as_ngtcp2_addr(path.remote), + }; +} + +NetworkPath NetworkPath::invert() { + auto path = *this; + + std::swap(path.local, path.remote); + + return path; +} + +Channel::Channel(const LinkConfig &config) + : link_config_{config}, gen_{link_config_.seed} {} + +Channel::Channel(Channel &&other) noexcept + : link_config_{std::exchange(other.link_config_, {})}, + gen_{std::exchange(other.gen_, {})}, + tx_queue_{std::exchange(other.tx_queue_, {})}, + tx_queue_size_{std::exchange(other.tx_queue_size_, 0)}, + link_free_ts_{std::exchange(other.link_free_ts_, {})}, + queue_{std::exchange(other.queue_, {})}, + timeout_{std::exchange(other.timeout_, {})}, + ts_{std::exchange(other.ts_, {})} {} + +Channel &Channel::operator=(Channel &&other) noexcept { + link_config_ = std::exchange(other.link_config_, {}); + gen_ = std::exchange(other.gen_, {}); + tx_queue_ = std::exchange(other.tx_queue_, {}); + tx_queue_size_ = std::exchange(other.tx_queue_size_, 0); + link_free_ts_ = std::exchange(other.link_free_ts_, {}); + queue_ = std::exchange(other.queue_, {}); + timeout_ = std::exchange(other.timeout_, {}); + ts_ = std::exchange(other.ts_, {}); + + return *this; +} + +void Channel::send_pkt(const NetworkPath &path, std::span pkt) { + auto rate = link_config_.rate / 8; + + if (rate == 0) { + queue_.emplace(Event{ + .ts = ts_ + link_config_.delay, + .type = EVENT_TYPE_PKT, + .path = path, + .pkt = std::vector(std::ranges::begin(pkt), std::ranges::end(pkt)), + }); + + return; + } + + if (link_config_.limit && tx_queue_size_ + pkt.size() > link_config_.limit) { + return; + } + + auto departure_ts = std::max(ts_, link_free_ts_) + + Timestamp::duration{pkt.size() * NGTCP2_SECONDS / rate}; + + if (!decide_pkt_lost()) { + queue_.emplace(Event{ + .ts = departure_ts + link_config_.delay, + .type = EVENT_TYPE_PKT, + .path = path, + .pkt = std::vector(std::ranges::begin(pkt), std::ranges::end(pkt)), + }); + } + + tx_queue_.emplace_back(TxPacket{ + .departure_ts = departure_ts, + .size = pkt.size(), + }); + + tx_queue_size_ += pkt.size(); + link_free_ts_ = departure_ts; +} + +bool Channel::decide_pkt_lost() { + return std::uniform_real_distribution<>(0, 1.0)(gen_) < link_config_.loss; +} + +void Channel::pop_tx_queue() { + size_t n = 0; + + auto it = std::ranges::find_if(tx_queue_, [&n, this](const auto &pkt) { + if (pkt.departure_ts > ts_) { + return true; + } + + n += pkt.size; + + return false; + }); + + assert(tx_queue_size_ >= n); + + tx_queue_size_ -= n; + tx_queue_.erase(std::ranges::begin(tx_queue_), it); +} + +void Channel::schedule_timeout(Timestamp ts) { + timeout_ = std::min(timeout_, ts); +} + +Timestamp Channel::get_next_timestamp() const { + if (queue_.empty()) { + return timeout_; + } + + auto &top = queue_.top(); + + return std::min(timeout_, top.ts); +} + +Event Channel::get_next_event() { + if (!queue_.empty() && queue_.top().ts <= timeout_) { + auto &top = const_cast(queue_.top()); + + auto ev = Event{ + .ts = top.ts, + .type = top.type, + .path = top.path, + .pkt = std::move(top.pkt), + }; + + queue_.pop(); + + return ev; + } + + return Event{ + .ts = std::exchange(timeout_, Timestamp::max()), + .type = EVENT_TYPE_TIMEOUT, + }; +} + +Simulator::Simulator(Endpoint client, Endpoint server) + : client_{std::move(client)}, server_{std::move(server)} {} + +Simulator::Simulator(Simulator &&other) noexcept + : client_{std::exchange(client_, {})}, + server_{std::exchange(server_, {})}, + max_events_{std::exchange(other.max_events_, 0)} {} + +Simulator &Simulator::operator=(Simulator &&other) noexcept { + client_ = std::exchange(other.client_, {}); + server_ = std::exchange(other.server_, {}); + max_events_ = std::exchange(other.max_events_, 0); + + return *this; +} + +std::optional> Simulator::get_next_event() { + auto &client_chan = client_.get_channel(); + auto &server_chan = server_.get_channel(); + + auto client_next_ts = client_chan.get_next_timestamp(); + auto server_next_ts = server_chan.get_next_timestamp(); + + if (client_next_ts == Timestamp::max() && + server_next_ts == Timestamp::max()) { + return {}; + } + + if (client_next_ts <= server_next_ts) { + auto ev = client_chan.get_next_event(); + return {{std::move(ev), client_}}; + } + + auto ev = server_chan.get_next_event(); + + return {{std::move(ev), server_}}; +} + +int Simulator::run() { + if (client_.get_initialized() || + client_.setup_client(&server_.get_endpoint_config().local_addr) != 0) { + return -1; + } + + auto ts = Timestamp{}; + auto &client_chan = client_.get_channel(); + auto &server_chan = server_.get_channel(); + + client_chan.schedule_timeout(ts); + + size_t k = 0; + + for (; k < max_events_; ++k) { + auto maybe_event = get_next_event(); + if (!maybe_event) { + break; + } + + auto &[event, ep] = *maybe_event; + + assert(ts <= event.ts); + + ts = event.ts; + + client_chan.set_timestamp(ts); + server_chan.set_timestamp(ts); + + client_chan.pop_tx_queue(); + server_chan.pop_tx_queue(); + + switch (event.type) { + case EVENT_TYPE_TIMEOUT: { + auto ctx = Context{ + .sim = this, + .ts = ts, + .endpoint = &ep, + }; + + if (ep.on_timeout(ctx) != 0) { + return -1; + } + + break; + } + case EVENT_TYPE_PKT: + if (deliver_pkt(ep, event.path.invert(), event.pkt, ts) != 0) { + return -1; + } + + break; + } + } + + if (k == max_events_) { + return -1; + } + + return 0; +} + +Endpoint &Simulator::get_opposite_endpoint(const Endpoint &ep) { + return &ep == &client_ ? server_ : client_; +} + +int Simulator::deliver_pkt(Endpoint &remote_ep, const NetworkPath &path, + std::span pkt, Timestamp ts) { + auto &local_ep = get_opposite_endpoint(remote_ep); + + if (!local_ep.get_initialized() && local_ep.get_endpoint_config().server) { + ngtcp2_version_cid vcid; + + auto rv = + ngtcp2_pkt_decode_version_cid(&vcid, pkt.data(), pkt.size(), CIDLEN); + if (rv != 0) { + return 0; + } + + ngtcp2_pkt_hd hd; + + if (ngtcp2_accept(&hd, pkt.data(), pkt.size()) != 0) { + return 0; + } + + if (local_ep.setup_server( + {vcid.dcid, vcid.dcidlen}, {vcid.scid, vcid.scidlen}, vcid.version, + &remote_ep.get_endpoint_config().local_addr) != 0) { + return -1; + } + } + + auto ctx = Context{ + .sim = this, + .ts = ts, + .endpoint = &local_ep, + }; + + return local_ep.on_read(path, pkt, ctx); +} + +void HandshakeApp::configure(EndpointConfig &config) { + auto handshake_confirmed = [](ngtcp2_conn *conn, void *user_data) { + auto app = static_cast(user_data); + + app->handshake_confirmed(); + + return 0; + }; + + if (config.server) { + config.callbacks.handshake_completed = handshake_confirmed; + } else { + config.callbacks.handshake_confirmed = handshake_confirmed; + } + + config.on_write = [](ngtcp2_conn *conn, const Context &ctx) { + std::array buf; + + auto ts = to_ngtcp2_tstamp(ctx.ts); + + ngtcp2_path_storage ps; + ngtcp2_path_storage_zero(&ps); + + auto nwrite = ngtcp2_conn_write_pkt(conn, &ps.path, nullptr, buf.data(), + buf.size(), ts); + if (nwrite < 0) { + std::cerr << "ngtcp2_conn_write_pkt: " + << ngtcp2_strerror(static_cast(nwrite)) << std::endl; + return -1; + } + + if (nwrite == 0) { + return 0; + } + + ngtcp2_conn_update_pkt_tx_time(conn, ts); + + ctx.endpoint->get_channel().send_pkt( + to_network_path(&ps.path), {buf.data(), static_cast(nwrite)}); + + return 0; + }; + + config.user_data = this; +} + +UniStreamApp::UniStreamApp(uint64_t max_bytes) : max_bytes_{max_bytes} {} + +namespace { +std::array nulldata; +} // namespace + +void UniStreamApp::configure(EndpointConfig &config) { + config.callbacks.stream_close = [](ngtcp2_conn *conn, uint32_t flags, + int64_t stream_id, uint64_t app_error_code, + void *user_data, void *stream_user_data) { + auto app = static_cast(user_data); + + app->stream_close(conn, stream_id); + + return 0; + }; + + config.callbacks.extend_max_local_streams_uni = + [](ngtcp2_conn *conn, uint64_t max_streams, void *user_data) { + auto app = static_cast(user_data); + + return app->extend_max_local_streams_uni(conn); + }; + + config.on_write = [this](ngtcp2_conn *conn, const Context &ctx) { + return on_write(conn, ctx); + }; + + config.user_data = this; +} + +uint64_t UniStreamApp::compute_goodput() const { + auto d = get_transmit_duration(); + if (d == Timestamp::duration::zero()) { + return 0; + } + + return static_cast(static_cast(bytes_sent_) * + NGTCP2_SECONDS / static_cast(d.count()) * + 8); +} + +void UniStreamApp::stream_close(ngtcp2_conn *conn, int64_t stream_id) { + if (stream_id_ != stream_id) { + return; + } + + if (is_all_bytes_sent()) { + end_ts_ = to_timestamp(ngtcp2_conn_get_timestamp(conn)); + } +} + +int UniStreamApp::extend_max_local_streams_uni(ngtcp2_conn *conn) { + if (stream_id_ != -1) { + return 0; + } + + int64_t stream_id; + + auto rv = ngtcp2_conn_open_uni_stream(conn, &stream_id, nullptr); + if (rv != 0) { + std::cerr << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv) + << std::endl; + return NGTCP2_ERR_CALLBACK_FAILURE; + } + + stream_id_ = stream_id; + start_ts_ = to_timestamp(ngtcp2_conn_get_timestamp(conn)); + + return 0; +} + +int UniStreamApp::on_write(ngtcp2_conn *conn, const Context &ctx) { + std::array buf; + + int64_t stream_id; + ngtcp2_vec vec; + size_t veccnt; + uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_NONE; + + if (stream_id_ != -1 && max_bytes_ > bytes_sent_) { + stream_id = stream_id_; + vec.base = nulldata.data(); + vec.len = static_cast( + std::min(static_cast(buf.size()), max_bytes_ - bytes_sent_)); + veccnt = 1; + + if (bytes_sent_ + vec.len == max_bytes_) { + flags |= NGTCP2_WRITE_STREAM_FLAG_FIN; + } + } else { + stream_id = -1; + veccnt = 0; + } + + auto ts = to_ngtcp2_tstamp(ctx.ts); + + ngtcp2_path_storage ps; + ngtcp2_path_storage_zero(&ps); + + ngtcp2_ssize ndatalen; + + auto nwrite = + ngtcp2_conn_writev_stream(conn, &ps.path, nullptr, buf.data(), buf.size(), + &ndatalen, flags, stream_id, &vec, veccnt, ts); + if (nwrite < 0) { + if (nwrite == NGTCP2_ERR_STREAM_DATA_BLOCKED) { + return 0; + } + + std::cerr << "ngtcp2_conn_writev_stream: " + << ngtcp2_strerror(static_cast(nwrite)) << std::endl; + + return -1; + } + + if (nwrite == 0) { + return 0; + } + + if (ndatalen > 0) { + bytes_sent_ += static_cast(ndatalen); + } + + ngtcp2_conn_update_pkt_tx_time(conn, ts); + + ctx.endpoint->get_channel().send_pkt( + to_network_path(&ps.path), {buf.data(), static_cast(nwrite)}); + + return 0; +} + +} // namespace ngtcp2 diff --git a/deps/ngtcp2/ngtcp2/examples/sim.h b/deps/ngtcp2/ngtcp2/examples/sim.h new file mode 100644 index 00000000000000..d4f31233581110 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/examples/sim.h @@ -0,0 +1,289 @@ +/* + * ngtcp2 + * + * Copyright (c) 2025 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef SIM_H +#define SIM_H + +#ifdef HAVE_CONFIG_H +# include +#endif // defined(HAVE_CONFIG_H) + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "network.h" + +namespace ngtcp2 { +inline constexpr size_t MAX_UDP_PAYLOAD_SIZE = 1500; + +using Timestamp = + std::chrono::time_point; + +ngtcp2_tstamp to_ngtcp2_tstamp(const Timestamp &ts); + +Timestamp to_timestamp(ngtcp2_tstamp ts); + +class Simulator; +class Endpoint; + +struct Context { + Simulator *sim; + Timestamp ts; + Endpoint *endpoint; +}; + +constexpr unsigned long long operator""_kbps(unsigned long long k) { + return k * 1'000; +} + +constexpr unsigned long long operator""_mbps(unsigned long long m) { + return m * 1'000'000; +} + +constexpr unsigned long long operator""_gbps(unsigned long long g) { + return g * 1'000'000'000; +} + +struct LinkConfig { + // compute_expected_goodput computes the expected goodput with the + // given |rtt| in bits per second. + uint64_t compute_expected_goodput(Timestamp::duration rtt) const; + + // delay is the one-way link delay. + Timestamp::duration delay; + // rate is the bandwidth of this link measured in bits per second + // (e.g., 10_mbps). + uint64_t rate{}; + // limit is the maximum queue length of the outgoing packet measured + // in bytes. + uint64_t limit{}; + // loss is the probability of losing a packet. + double loss{}; + // seed is a seed value for the random number generator. + std::mt19937::result_type seed{}; +}; + +struct EndpointConfig { + bool server{}; + ngtcp2_callbacks callbacks{}; + ngtcp2_settings settings{}; + ngtcp2_transport_params params{}; + ngtcp2_addr local_addr{}; + void *user_data{}; + LinkConfig link; + + std::function on_write; +}; + +ngtcp2_callbacks default_client_callbacks(); + +ngtcp2_callbacks default_server_callbacks(); + +ngtcp2_settings default_client_settings(); + +ngtcp2_settings default_server_settings(); + +ngtcp2_transport_params default_client_transport_params(); + +ngtcp2_transport_params default_server_transport_params(); + +ngtcp2_addr default_client_addr(); + +ngtcp2_addr default_server_addr(); + +EndpointConfig default_client_endpoint_config(); + +EndpointConfig default_server_endpoint_config(); + +struct NetworkPath { + NetworkPath invert(); + + Address local{}; + Address remote{}; +}; + +NetworkPath to_network_path(const ngtcp2_path *path); + +ngtcp2_path to_ngtcp2_path(const NetworkPath &path); + +enum EventType { + EVENT_TYPE_TIMEOUT, + EVENT_TYPE_PKT, +}; + +struct Event { + Timestamp ts; + EventType type; + + NetworkPath path; + std::vector pkt; +}; + +constexpr bool operator>(const Event &lhs, const Event &rhs) { + return lhs.ts > rhs.ts; +} + +struct TxPacket { + Timestamp departure_ts; + size_t size; +}; + +class Channel { +public: + Channel() = default; + Channel(const LinkConfig &config); + Channel(const Channel &) = delete; + Channel(Channel &&) noexcept; + + Channel &operator=(const Channel &) = delete; + Channel &operator=(Channel &&) noexcept; + + void send_pkt(const NetworkPath &path, std::span pkt); + void schedule_timeout(Timestamp ts); + void set_timestamp(Timestamp ts) { ts_ = ts; } + Timestamp get_next_timestamp() const; + Event get_next_event(); + void pop_tx_queue(); + +private: + bool decide_pkt_lost(); + + LinkConfig link_config_; + std::mt19937 gen_; + std::deque tx_queue_; + size_t tx_queue_size_{}; + Timestamp link_free_ts_; + using EventQueue = + std::priority_queue, std::greater>; + EventQueue queue_; + Timestamp timeout_{Timestamp::max()}; + Timestamp ts_{}; +}; + +class Endpoint { +public: + Endpoint(); + explicit Endpoint(const EndpointConfig &config); + Endpoint(Endpoint &&endpoint) noexcept; + Endpoint(const Endpoint &) = delete; + ~Endpoint(); + + Endpoint &operator=(const Endpoint &) = delete; + Endpoint &operator=(Endpoint &&) noexcept; + + int setup_client(const ngtcp2_addr *remote_addr); + int setup_server(std::span original_dcid, + std::span client_scid, uint32_t version, + const ngtcp2_addr *remote_addr); + ngtcp2_conn *get_conn() const { return conn_; } + bool get_initialized() const { return initialized_; } + const EndpointConfig &get_endpoint_config() const { return config_; } + int on_read(const NetworkPath &path, std::span pkt, + const Context &ctx); + int on_write(const Context &ctx); + int on_timeout(const Context &ctx); + Channel &get_channel() { return channel_; } + +private: + EndpointConfig config_; + WOLFSSL_CTX *ssl_ctx_{}; + WOLFSSL *ssl_{}; + ngtcp2_conn *conn_{}; + ngtcp2_crypto_conn_ref conn_ref_{}; + Channel channel_; + bool initialized_{}; +}; + +class Simulator { +public: + Simulator(Endpoint client, Endpoint server); + Simulator(const Simulator &) = delete; + Simulator(Simulator &&) noexcept; + + Simulator &operator=(const Simulator &) = delete; + Simulator &operator=(Simulator &&) noexcept; + + int run(); + void set_max_events(size_t n) { max_events_ = n; } + +private: + Endpoint &get_opposite_endpoint(const Endpoint &ep); + std::optional> get_next_event(); + int deliver_pkt(Endpoint &remote_ep, const NetworkPath &path, + std::span pkt, Timestamp ts); + + Endpoint client_; + Endpoint server_; + size_t max_events_{1'000'000}; +}; + +class HandshakeApp { +public: + void configure(EndpointConfig &config); + + bool get_handshake_confirmed() const { return handshake_confirmed_; } + +private: + void handshake_confirmed() { handshake_confirmed_ = true; } + + bool handshake_confirmed_{}; +}; + +class UniStreamApp { +public: + UniStreamApp(uint64_t max_bytes); + + void configure(EndpointConfig &config); + uint64_t get_bytes_sent() const { return bytes_sent_; } + Timestamp::duration get_transmit_duration() const { + return end_ts_ - start_ts_; + } + bool is_all_bytes_sent() const { return bytes_sent_ == max_bytes_; } + // compute_goodput computes goodput in bits per second. + uint64_t compute_goodput() const; + +private: + void stream_close(ngtcp2_conn *conn, int64_t stream_id); + int extend_max_local_streams_uni(ngtcp2_conn *conn); + int on_write(ngtcp2_conn *conn, const Context &ctx); + + int64_t stream_id_{-1}; + uint64_t max_bytes_{}; + uint64_t bytes_sent_{}; + Timestamp start_ts_{Timestamp::max()}; + Timestamp end_ts_{Timestamp::max()}; +}; + +} // namespace ngtcp2 + +#endif // SIM_H diff --git a/deps/ngtcp2/ngtcp2/examples/sim_test.cc b/deps/ngtcp2/ngtcp2/examples/sim_test.cc new file mode 100644 index 00000000000000..76e1c1e498f7fb --- /dev/null +++ b/deps/ngtcp2/ngtcp2/examples/sim_test.cc @@ -0,0 +1,148 @@ +/* + * ngtcp2 + * + * Copyright (c) 2025 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "sim_test.h" + +#include + +#include "sim.h" +#include "util.h" + +using namespace std::literals; + +namespace ngtcp2 { + +namespace { +const MunitTest tests[]{ + munit_void_test(test_sim_handshake), + munit_void_test(test_sim_unistream), + munit_test_end(), +}; +} // namespace + +const MunitSuite sim_suite{ + .prefix = "/sim", + .tests = tests, +}; + +void test_sim_handshake(void) { + struct Test { + const char *name; + Timestamp::duration delay; + }; + + auto tests = std::to_array({ + { + .name = "short delay", + .delay = 15ms, + }, + { + .name = "long delay", + .delay = 1h, + }, + }); + + for (auto &t : tests) { + munit_logf(MUNIT_LOG_INFO, "testcase: %s", t.name); + + auto link = LinkConfig{ + .delay = t.delay, + }; + + HandshakeApp clapp; + auto cl = default_client_endpoint_config(); + clapp.configure(cl); + cl.link = link; + + HandshakeApp svapp; + auto sv = default_server_endpoint_config(); + svapp.configure(sv); + sv.link = link; + + int rv; + + { + rv = Simulator{Endpoint(cl), Endpoint(sv)}.run(); + } + + assert_int(0, ==, rv); + assert_true(clapp.get_handshake_confirmed()); + assert_true(svapp.get_handshake_confirmed()); + } +} + +void test_sim_unistream(void) { + struct Test { + const char *name; + double loss; + }; + + auto tests = std::to_array({ + { + .name = "no loss", + }, + { + .name = "1% loss", + .loss = 0.01, + }, + }); + + for (auto &t : tests) { + munit_logf(MUNIT_LOG_INFO, "testcase: %s", t.name); + + auto link = LinkConfig{ + .delay = 15ms, + .rate = 10_mbps, + .limit = MAX_UDP_PAYLOAD_SIZE * 25, + .loss = t.loss, + .seed = munit_rand_uint32(), + }; + + HandshakeApp clapp; + auto cl = default_client_endpoint_config(); + clapp.configure(cl); + cl.params.initial_max_streams_uni = 1; + cl.params.initial_max_stream_data_uni = 6_m; + cl.params.initial_max_data = 6_m; + cl.link = link; + + UniStreamApp svapp(10_m); + auto sv = default_server_endpoint_config(); + svapp.configure(sv); + sv.link = link; + + int rv; + + { + rv = Simulator{Endpoint(cl), Endpoint(sv)}.run(); + } + + assert_int(0, ==, rv); + assert_true(svapp.is_all_bytes_sent()); + assert_uint64(link.compute_expected_goodput(link.delay * 2), <=, + svapp.compute_goodput()); + } +} + +} // namespace ngtcp2 diff --git a/deps/ngtcp2/ngtcp2/examples/sim_test.h b/deps/ngtcp2/ngtcp2/examples/sim_test.h new file mode 100644 index 00000000000000..ea94520caaa160 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/examples/sim_test.h @@ -0,0 +1,45 @@ +/* + * ngtcp2 + * + * Copyright (c) 2025 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef SIM_TEST_H +#define SIM_TEST_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif // defined(HAVE_CONFIG_H) + +#define MUNIT_ENABLE_ASSERT_ALIASES + +#include "munitxx.h" + +namespace ngtcp2 { + +extern const MunitSuite sim_suite; + +munit_void_test_decl(test_sim_handshake) +munit_void_test_decl(test_sim_unistream) + +} // namespace ngtcp2 + +#endif // !defined(SIM_TEST_H) diff --git a/deps/ngtcp2/ngtcp2/examples/siphash.h b/deps/ngtcp2/ngtcp2/examples/siphash.h index 5d46db3b349e54..8f82c53c79fc05 100644 --- a/deps/ngtcp2/ngtcp2/examples/siphash.h +++ b/deps/ngtcp2/ngtcp2/examples/siphash.h @@ -40,6 +40,7 @@ #ifndef SIPHASH_H #define SIPHASH_H +#include #include #include #include diff --git a/deps/ngtcp2/ngtcp2/examples/template.h b/deps/ngtcp2/ngtcp2/examples/template.h index 5807cb7e6de419..8c73bbf307483e 100644 --- a/deps/ngtcp2/ngtcp2/examples/template.h +++ b/deps/ngtcp2/ngtcp2/examples/template.h @@ -41,20 +41,21 @@ template return static_cast>(n); } -// inspired by , but our -// template can take functions returning other than void. -template struct Defer { - Defer(F &&f, T &&...t) - : f(std::bind(std::forward(f), std::forward(t)...)) {} - Defer(Defer &&o) noexcept : f(std::move(o.f)) {} +template struct Defer { + explicit Defer(F &&f) noexcept(std::is_nothrow_constructible_v) + : f(std::forward(f)) {} ~Defer() { f(); } - using ResultType = std::invoke_result_t; - std::function f; + Defer(Defer &&o) = delete; + Defer(const Defer &) = delete; + Defer &operator=(const Defer &) = delete; + Defer &operator=(Defer &&) = delete; + + F f; }; -template Defer defer(F &&f, T &&...t) { - return Defer(std::forward(f), std::forward(t)...); +template [[nodiscard]] Defer> defer(F &&f) { + return Defer>(std::forward(f)); } template constexpr size_t array_size(T (&)[N]) { diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_boringssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_context_boringssl.cc index b0c0e7dbcb893e..c7f0bf7e2086b8 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_boringssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_boringssl.cc @@ -38,8 +38,6 @@ extern Config config; -TLSClientContext::TLSClientContext() : ssl_ctx_{nullptr} {} - TLSClientContext::~TLSClientContext() { if (ssl_ctx_) { SSL_CTX_free(ssl_ctx_); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_boringssl.h b/deps/ngtcp2/ngtcp2/examples/tls_client_context_boringssl.h index 05370252ecda14..47e7b02e097241 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_boringssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_boringssl.h @@ -33,7 +33,7 @@ class TLSClientContext { public: - TLSClientContext(); + TLSClientContext() = default; ~TLSClientContext(); int init(const char *private_key_file, const char *cert_file); @@ -43,7 +43,7 @@ class TLSClientContext { void enable_keylog(); private: - SSL_CTX *ssl_ctx_; + SSL_CTX *ssl_ctx_{}; }; #endif // !defined(TLS_CLIENT_CONTEXT_BORINGSSL_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_ossl.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_context_ossl.cc index 036b28a7607fea..561db9473144d1 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_ossl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_ossl.cc @@ -38,7 +38,7 @@ #include "template.h" namespace { -auto _ = []() { +auto _ = [] { if (ngtcp2_crypto_ossl_init() != 0) { assert(0); abort(); @@ -50,8 +50,6 @@ auto _ = []() { extern Config config; -TLSClientContext::TLSClientContext() : ssl_ctx_{nullptr} {} - TLSClientContext::~TLSClientContext() { if (ssl_ctx_) { SSL_CTX_free(ssl_ctx_); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_ossl.h b/deps/ngtcp2/ngtcp2/examples/tls_client_context_ossl.h index db65662c4b033d..5c33bfbeadfdeb 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_ossl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_ossl.h @@ -33,7 +33,7 @@ class TLSClientContext { public: - TLSClientContext(); + TLSClientContext() = default; ~TLSClientContext(); int init(const char *private_key_file, const char *cert_file); @@ -43,7 +43,7 @@ class TLSClientContext { void enable_keylog(); private: - SSL_CTX *ssl_ctx_; + SSL_CTX *ssl_ctx_{}; }; #endif // !defined(TLS_CLIENT_CONTEXT_OSSL_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_picotls.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_context_picotls.cc index adedd59ec94fc4..72ce8dd69f8810 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_picotls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_picotls.cc @@ -92,13 +92,13 @@ ptls_cipher_suite_t *cipher_suites[] = { } // namespace TLSClientContext::TLSClientContext() - : ctx_{ - .random_bytes = ptls_openssl_random_bytes, - .get_time = &ptls_get_time, - .key_exchanges = key_exchanges, - .cipher_suites = cipher_suites, - .require_dhe_on_psk = 1, - }, sign_cert_{} {} + : ctx_{ + .random_bytes = ptls_openssl_random_bytes, + .get_time = &ptls_get_time, + .key_exchanges = key_exchanges, + .cipher_suites = cipher_suites, + .require_dhe_on_psk = 1, + } {} TLSClientContext::~TLSClientContext() { if (sign_cert_.key) { @@ -147,7 +147,7 @@ int TLSClientContext::load_private_key(const char *private_key_file) { return -1; } - auto fp_d = defer(fclose, fp); + auto fp_d = defer([fp] { fclose(fp); }); auto pkey = PEM_read_PrivateKey(fp, nullptr, nullptr, nullptr); if (pkey == nullptr) { @@ -156,7 +156,7 @@ int TLSClientContext::load_private_key(const char *private_key_file) { return -1; } - auto pkey_d = defer(EVP_PKEY_free, pkey); + auto pkey_d = defer([pkey] { EVP_PKEY_free(pkey); }); if (ptls_openssl_init_sign_certificate(&sign_cert_, pkey) != 0) { std::cerr << "ptls_openssl_init_sign_certificate failed" << std::endl; diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_picotls.h b/deps/ngtcp2/ngtcp2/examples/tls_client_context_picotls.h index 992ef2fa353a24..b07a2023817991 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_picotls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_picotls.h @@ -47,7 +47,7 @@ class TLSClientContext { int load_private_key(const char *private_key_file); ptls_context_t ctx_; - ptls_openssl_sign_certificate_t sign_cert_; + ptls_openssl_sign_certificate_t sign_cert_{}; }; #endif // !defined(TLS_CLIENT_CONTEXT_PICOTLS_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_quictls.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_context_quictls.cc index 781bec32976666..6b5a37b4b09783 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_quictls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_quictls.cc @@ -38,7 +38,7 @@ #include "template.h" namespace { -auto _ = []() { +auto _ = [] { if (ngtcp2_crypto_quictls_init() != 0) { assert(0); abort(); @@ -50,8 +50,6 @@ auto _ = []() { extern Config config; -TLSClientContext::TLSClientContext() : ssl_ctx_{nullptr} {} - TLSClientContext::~TLSClientContext() { if (ssl_ctx_) { SSL_CTX_free(ssl_ctx_); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_quictls.h b/deps/ngtcp2/ngtcp2/examples/tls_client_context_quictls.h index 325c8c49ed5153..c76353c89e9670 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_quictls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_quictls.h @@ -33,7 +33,7 @@ class TLSClientContext { public: - TLSClientContext(); + TLSClientContext() = default; ~TLSClientContext(); int init(const char *private_key_file, const char *cert_file); @@ -43,7 +43,7 @@ class TLSClientContext { void enable_keylog(); private: - SSL_CTX *ssl_ctx_; + SSL_CTX *ssl_ctx_{}; }; #endif // !defined(TLS_CLIENT_CONTEXT_QUICTLS_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_wolfssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_context_wolfssl.cc index 2c1402745ce660..4d287c42ce75a5 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_wolfssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_wolfssl.cc @@ -39,8 +39,6 @@ extern Config config; -TLSClientContext::TLSClientContext() : ssl_ctx_{nullptr} {} - TLSClientContext::~TLSClientContext() { if (ssl_ctx_) { wolfSSL_CTX_free(ssl_ctx_); @@ -86,7 +84,7 @@ int new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session) { return 0; } - auto f_d = defer(wolfSSL_BIO_free, f); + auto f_d = defer([f] { wolfSSL_BIO_free(f); }); if (!wolfSSL_PEM_write_bio(f, "WOLFSSL SESSION PARAMETERS", "", sbuffer, sz)) { diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_context_wolfssl.h b/deps/ngtcp2/ngtcp2/examples/tls_client_context_wolfssl.h index fbebf7baff5db3..07d967026d9de2 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_context_wolfssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_context_wolfssl.h @@ -35,7 +35,7 @@ class TLSClientContext { public: - TLSClientContext(); + TLSClientContext() = default; ~TLSClientContext(); int init(const char *private_key_file, const char *cert_file); @@ -45,7 +45,7 @@ class TLSClientContext { void enable_keylog(); private: - WOLFSSL_CTX *ssl_ctx_; + WOLFSSL_CTX *ssl_ctx_{}; }; #endif // !defined(TLS_CLIENT_CONTEXT_WOLFSSL_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_boringssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_session_boringssl.cc index 2b0a269904f4bd..e72405cb6a2794 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_boringssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_boringssl.cc @@ -33,10 +33,6 @@ #include "template.h" #include "util.h" -TLSClientSession::TLSClientSession() {} - -TLSClientSession::~TLSClientSession() {} - extern Config config; int TLSClientSession::init(bool &early_data_enabled, diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_boringssl.h b/deps/ngtcp2/ngtcp2/examples/tls_client_session_boringssl.h index 929488ace00cbd..3ce70e9e363415 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_boringssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_boringssl.h @@ -39,8 +39,7 @@ class ClientBase; class TLSClientSession : public TLSSessionBase { public: - TLSClientSession(); - ~TLSClientSession(); + TLSClientSession() = default; int init(bool &early_data_enabled, const TLSClientContext &tls_ctx, const char *remote_addr, ClientBase *client, uint32_t quic_version, diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_ossl.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_session_ossl.cc index f748d0f4930805..74871bf019f120 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_ossl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_ossl.cc @@ -34,10 +34,6 @@ #include "template.h" #include "util.h" -TLSClientSession::TLSClientSession() {} - -TLSClientSession::~TLSClientSession() {} - extern Config config; int TLSClientSession::init(bool &early_data_enabled, diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_ossl.h b/deps/ngtcp2/ngtcp2/examples/tls_client_session_ossl.h index a1ee051338a657..c11e94cd264507 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_ossl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_ossl.h @@ -39,8 +39,7 @@ class ClientBase; class TLSClientSession : public TLSSessionBase { public: - TLSClientSession(); - ~TLSClientSession(); + TLSClientSession() = default; int init(bool &early_data_enabled, const TLSClientContext &tls_ctx, const char *remote_addr, ClientBase *client, uint32_t quic_version, diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_picotls.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_session_picotls.cc index 35c4a18475a22c..3f68bc48ad5503 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_picotls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_picotls.cc @@ -44,8 +44,6 @@ using namespace std::literals; extern Config config; -TLSClientSession::TLSClientSession() {} - TLSClientSession::~TLSClientSession() { auto &hsprops = cptls_.handshake_properties; @@ -126,7 +124,7 @@ int TLSClientSession::init(bool &early_data_enabled, TLSClientContext &tls_ctx, std::cerr << "Could not read TLS session file " << config.session_file << std::endl; } else { - auto f_d = defer(BIO_free, f); + auto f_d = defer([f] { BIO_free(f); }); char *name, *header; unsigned char *data; diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_picotls.h b/deps/ngtcp2/ngtcp2/examples/tls_client_session_picotls.h index 28059be503a62e..6410caf0ab085d 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_picotls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_picotls.h @@ -39,7 +39,7 @@ class ClientBase; class TLSClientSession : public TLSSessionBase { public: - TLSClientSession(); + TLSClientSession() = default; ~TLSClientSession(); int init(bool &early_data_enabled, TLSClientContext &tls_ctx, diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_quictls.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_session_quictls.cc index ceecc5cee55011..1693530255c732 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_quictls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_quictls.cc @@ -34,10 +34,6 @@ #include "template.h" #include "util.h" -TLSClientSession::TLSClientSession() {} - -TLSClientSession::~TLSClientSession() {} - extern Config config; int TLSClientSession::init(bool &early_data_enabled, diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_quictls.h b/deps/ngtcp2/ngtcp2/examples/tls_client_session_quictls.h index cfe082d268c92b..e462c0a5021f64 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_quictls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_quictls.h @@ -39,8 +39,7 @@ class ClientBase; class TLSClientSession : public TLSSessionBase { public: - TLSClientSession(); - ~TLSClientSession(); + TLSClientSession() = default; int init(bool &early_data_enabled, const TLSClientContext &tls_ctx, const char *remote_addr, ClientBase *client, uint32_t quic_version, diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_wolfssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_client_session_wolfssl.cc index 37398d62a31f77..e487c143f9e05b 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_wolfssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_wolfssl.cc @@ -35,10 +35,6 @@ using namespace std::literals; -TLSClientSession::TLSClientSession() {} - -TLSClientSession::~TLSClientSession() {} - extern Config config; namespace { diff --git a/deps/ngtcp2/ngtcp2/examples/tls_client_session_wolfssl.h b/deps/ngtcp2/ngtcp2/examples/tls_client_session_wolfssl.h index 0d892f07846b88..d3a6e166b796ca 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_client_session_wolfssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_client_session_wolfssl.h @@ -39,8 +39,7 @@ class ClientBase; class TLSClientSession : public TLSSessionBase { public: - TLSClientSession(); - ~TLSClientSession(); + TLSClientSession() = default; int init(bool &early_data_enabled, const TLSClientContext &tls_ctx, const char *remote_addr, ClientBase *client, uint32_t quic_version, diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_boringssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_context_boringssl.cc index cce81391145893..2c168514cca7cd 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_boringssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_boringssl.cc @@ -40,8 +40,6 @@ extern Config config; -TLSServerContext::TLSServerContext() : ssl_ctx_{nullptr} {} - TLSServerContext::~TLSServerContext() { if (ssl_ctx_) { SSL_CTX_free(ssl_ctx_); @@ -228,10 +226,10 @@ int TLSServerContext::init(const char *private_key_file, const char *cert_file, return -1; } - auto pkey_d = defer(EVP_HPKE_KEY_free, pkey); + auto pkey_d = defer([pkey] { EVP_HPKE_KEY_free(pkey); }); auto keys = SSL_ECH_KEYS_new(); - auto keys_d = defer(SSL_ECH_KEYS_free, keys); + auto keys_d = defer([keys] { SSL_ECH_KEYS_free(keys); }); if (SSL_ECH_KEYS_add(keys, 1, echconf.ech_config.data(), echconf.ech_config.size(), pkey) != 1) { diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_boringssl.h b/deps/ngtcp2/ngtcp2/examples/tls_server_context_boringssl.h index 48af9a6c2e34b0..57045c122ef4e3 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_boringssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_boringssl.h @@ -37,7 +37,7 @@ using namespace ngtcp2; class TLSServerContext { public: - TLSServerContext(); + TLSServerContext() = default; ~TLSServerContext(); int init(const char *private_key_file, const char *cert_file, @@ -48,7 +48,7 @@ class TLSServerContext { void enable_keylog(); private: - SSL_CTX *ssl_ctx_; + SSL_CTX *ssl_ctx_{}; }; #endif // !defined(TLS_SERVER_CONTEXT_BORINGSSL_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_ossl.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_context_ossl.cc index 65aef5c26095f3..148224651182dc 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_ossl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_ossl.cc @@ -39,7 +39,7 @@ #include "template.h" namespace { -auto _ = []() { +auto _ = [] { if (ngtcp2_crypto_ossl_init() != 0) { assert(0); abort(); @@ -51,8 +51,6 @@ auto _ = []() { extern Config config; -TLSServerContext::TLSServerContext() : ssl_ctx_{nullptr} {} - TLSServerContext::~TLSServerContext() { if (ssl_ctx_) { SSL_CTX_free(ssl_ctx_); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_ossl.h b/deps/ngtcp2/ngtcp2/examples/tls_server_context_ossl.h index 7f9227c361b5a7..d187b25552f6bd 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_ossl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_ossl.h @@ -37,7 +37,7 @@ using namespace ngtcp2; class TLSServerContext { public: - TLSServerContext(); + TLSServerContext() = default; ~TLSServerContext(); int init(const char *private_key_file, const char *cert_file, @@ -48,7 +48,7 @@ class TLSServerContext { void enable_keylog(); private: - SSL_CTX *ssl_ctx_; + SSL_CTX *ssl_ctx_{}; }; #endif // !defined(TLS_SERVER_CONTEXT_OSSL_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_picotls.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_context_picotls.cc index 22ca69f0e04754..a1f8e4753fe695 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_picotls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_picotls.cc @@ -90,8 +90,6 @@ ptls_on_client_hello_t on_client_hello_hq = {on_client_hello_hq_cb}; } // namespace namespace { -auto ticket_hmac = EVP_sha256(); - std::span get_ticket_key_name() { static std::array key_name; ptls_openssl_random_bytes(key_name.data(), key_name.size()); @@ -123,14 +121,21 @@ int ticket_key_cb(unsigned char *key_name, unsigned char *iv, static const auto static_key_name = get_ticket_key_name(); static const auto static_key = get_ticket_key(); static const auto static_hmac_key = get_ticket_hmac_key(); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + static const auto ticket_hmac = EVP_MD_fetch(nullptr, "sha256", nullptr); + static const auto aes_256_cbc = + EVP_CIPHER_fetch(nullptr, "AES-256-CBC", nullptr); +#else // OPENSSL_VERSION_NUMBER < 0x30000000L + static const auto ticket_hmac = EVP_sha256(); + static const auto aes_256_cbc = EVP_aes_256_cbc(); +#endif // OPENSSL_VERSION_NUMBER < 0x30000000L if (enc) { ptls_openssl_random_bytes(iv, EVP_MAX_IV_LENGTH); std::ranges::copy(static_key_name, key_name); - if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, static_key.data(), - iv)) { + if (!EVP_EncryptInit_ex(ctx, aes_256_cbc, nullptr, static_key.data(), iv)) { return 0; } #if OPENSSL_VERSION_NUMBER >= 0x30000000L @@ -163,8 +168,7 @@ int ticket_key_cb(unsigned char *key_name, unsigned char *iv, return 0; } - if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, static_key.data(), - iv)) { + if (!EVP_DecryptInit_ex(ctx, aes_256_cbc, nullptr, static_key.data(), iv)) { return 0; } #if OPENSSL_VERSION_NUMBER >= 0x30000000L @@ -280,18 +284,16 @@ ptls_cipher_suite_t *cipher_suites[] = { } // namespace TLSServerContext::TLSServerContext() - : ctx_{ - .random_bytes = ptls_openssl_random_bytes, - .get_time = &ptls_get_time, - .key_exchanges = key_exchanges, - .cipher_suites = cipher_suites, - .ticket_lifetime = 86400, - .require_dhe_on_psk = 1, - .server_cipher_preference = 1, - .encrypt_ticket = &encrypt_ticket, - }, - sign_cert_{} -{} + : ctx_{ + .random_bytes = ptls_openssl_random_bytes, + .get_time = &ptls_get_time, + .key_exchanges = key_exchanges, + .cipher_suites = cipher_suites, + .ticket_lifetime = 86400, + .require_dhe_on_psk = 1, + .server_cipher_preference = 1, + .encrypt_ticket = &encrypt_ticket, + } {} TLSServerContext::~TLSServerContext() { if (sign_cert_.key) { @@ -317,7 +319,7 @@ int TLSServerContext::init(const char *private_key_file, const char *cert_file, ctx_.on_client_hello = &on_client_hello_hq; break; - }; + } if (ngtcp2_crypto_picotls_configure_server_context(&ctx_) != 0) { std::cerr << "ngtcp2_crypto_picotls_configure_server_context failed" @@ -349,7 +351,7 @@ int TLSServerContext::load_private_key(const char *private_key_file) { return -1; } - auto fp_d = defer(fclose, fp); + auto fp_d = defer([fp] { fclose(fp); }); auto pkey = PEM_read_PrivateKey(fp, nullptr, nullptr, nullptr); if (pkey == nullptr) { @@ -358,7 +360,7 @@ int TLSServerContext::load_private_key(const char *private_key_file) { return -1; } - auto pkey_d = defer(EVP_PKEY_free, pkey); + auto pkey_d = defer([pkey] { EVP_PKEY_free(pkey); }); if (ptls_openssl_init_sign_certificate(&sign_cert_, pkey) != 0) { std::cerr << "ptls_openssl_init_sign_certificate failed" << std::endl; diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_picotls.h b/deps/ngtcp2/ngtcp2/examples/tls_server_context_picotls.h index 14b77c11aadf66..acfa3d6bd2afc2 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_picotls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_picotls.h @@ -52,7 +52,7 @@ class TLSServerContext { int load_private_key(const char *private_key_file); ptls_context_t ctx_; - ptls_openssl_sign_certificate_t sign_cert_; + ptls_openssl_sign_certificate_t sign_cert_{}; }; #endif // !defined(TLS_SERVER_CONTEXT_PICOTLS_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_quictls.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_context_quictls.cc index f4ed5f6277879b..664956814febd0 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_quictls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_quictls.cc @@ -39,7 +39,7 @@ #include "template.h" namespace { -auto _ = []() { +auto _ = [] { if (ngtcp2_crypto_quictls_init() != 0) { assert(0); abort(); @@ -51,8 +51,6 @@ auto _ = []() { extern Config config; -TLSServerContext::TLSServerContext() : ssl_ctx_{nullptr} {} - TLSServerContext::~TLSServerContext() { if (ssl_ctx_) { SSL_CTX_free(ssl_ctx_); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_quictls.h b/deps/ngtcp2/ngtcp2/examples/tls_server_context_quictls.h index 7b1f88f8c9e20c..1f14349e3e7718 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_quictls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_quictls.h @@ -37,7 +37,7 @@ using namespace ngtcp2; class TLSServerContext { public: - TLSServerContext(); + TLSServerContext() = default; ~TLSServerContext(); int init(const char *private_key_file, const char *cert_file, @@ -48,7 +48,7 @@ class TLSServerContext { void enable_keylog(); private: - SSL_CTX *ssl_ctx_; + SSL_CTX *ssl_ctx_{}; }; #endif // !defined(TLS_SERVER_CONTEXT_QUICTLS_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_wolfssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_context_wolfssl.cc index 454861bc5d1dff..53a22175e293d3 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_wolfssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_wolfssl.cc @@ -37,8 +37,6 @@ extern Config config; -TLSServerContext::TLSServerContext() : ssl_ctx_{nullptr} {} - TLSServerContext::~TLSServerContext() { if (ssl_ctx_) { wolfSSL_CTX_free(ssl_ctx_); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_context_wolfssl.h b/deps/ngtcp2/ngtcp2/examples/tls_server_context_wolfssl.h index bd3b00acad5b92..0a5aa70e4bf8a5 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_context_wolfssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_context_wolfssl.h @@ -38,7 +38,7 @@ using namespace ngtcp2; class TLSServerContext { public: - TLSServerContext(); + TLSServerContext() = default; ~TLSServerContext(); int init(const char *private_key_file, const char *cert_file, @@ -49,7 +49,7 @@ class TLSServerContext { void enable_keylog(); private: - WOLFSSL_CTX *ssl_ctx_; + WOLFSSL_CTX *ssl_ctx_{}; }; #endif // !defined(TLS_SERVER_CONTEXT_WOLFSSL_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_boringssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_session_boringssl.cc index 43234d9d821ba8..99af497130f4e0 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_boringssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_boringssl.cc @@ -34,10 +34,6 @@ extern Config config; -TLSServerSession::TLSServerSession() {} - -TLSServerSession::~TLSServerSession() {} - int TLSServerSession::init(const TLSServerContext &tls_ctx, HandlerBase *handler) { auto ssl_ctx = tls_ctx.get_native_handle(); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_boringssl.h b/deps/ngtcp2/ngtcp2/examples/tls_server_session_boringssl.h index 2dc6442f6f1afd..7ffa4f0214abb8 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_boringssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_boringssl.h @@ -36,8 +36,7 @@ class HandlerBase; class TLSServerSession : public TLSSessionBase { public: - TLSServerSession(); - ~TLSServerSession(); + TLSServerSession() = default; int init(const TLSServerContext &tls_ctx, HandlerBase *handler); // ticket is sent automatically. diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_ossl.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_session_ossl.cc index 39e9408a8aacae..0857c83f0b6940 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_ossl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_ossl.cc @@ -31,10 +31,6 @@ #include "tls_server_context_ossl.h" #include "server_base.h" -TLSServerSession::TLSServerSession() {} - -TLSServerSession::~TLSServerSession() {} - int TLSServerSession::init(const TLSServerContext &tls_ctx, HandlerBase *handler) { auto ssl_ctx = tls_ctx.get_native_handle(); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_ossl.h b/deps/ngtcp2/ngtcp2/examples/tls_server_session_ossl.h index 3d4e0d715e3d21..195672c3cbb747 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_ossl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_ossl.h @@ -36,8 +36,7 @@ class HandlerBase; class TLSServerSession : public TLSSessionBase { public: - TLSServerSession(); - ~TLSServerSession(); + TLSServerSession() = default; int init(const TLSServerContext &tls_ctx, HandlerBase *handler); // ticket is sent automatically. diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_picotls.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_session_picotls.cc index 4fed99d66ad3c3..9039fd14ff34a9 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_picotls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_picotls.cc @@ -37,10 +37,6 @@ using namespace ngtcp2; extern Config config; -TLSServerSession::TLSServerSession() {} - -TLSServerSession::~TLSServerSession() {} - int TLSServerSession::init(TLSServerContext &tls_ctx, HandlerBase *handler) { cptls_.ptls = ptls_server_new(tls_ctx.get_native_handle()); if (!cptls_.ptls) { diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_picotls.h b/deps/ngtcp2/ngtcp2/examples/tls_server_session_picotls.h index 9afcf5bf3de726..811b44559d95c9 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_picotls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_picotls.h @@ -36,8 +36,7 @@ class HandlerBase; class TLSServerSession : public TLSSessionBase { public: - TLSServerSession(); - ~TLSServerSession(); + TLSServerSession() = default; int init(TLSServerContext &tls_ctx, HandlerBase *handler); // ticket is sent automatically. diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_quictls.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_session_quictls.cc index 60fe5399c0fd62..39a57ac9a505e4 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_quictls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_quictls.cc @@ -31,10 +31,6 @@ #include "tls_server_context_quictls.h" #include "server_base.h" -TLSServerSession::TLSServerSession() {} - -TLSServerSession::~TLSServerSession() {} - int TLSServerSession::init(const TLSServerContext &tls_ctx, HandlerBase *handler) { auto ssl_ctx = tls_ctx.get_native_handle(); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_quictls.h b/deps/ngtcp2/ngtcp2/examples/tls_server_session_quictls.h index cd7eed5b2cf11c..94c24f851cda7c 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_quictls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_quictls.h @@ -36,8 +36,7 @@ class HandlerBase; class TLSServerSession : public TLSSessionBase { public: - TLSServerSession(); - ~TLSServerSession(); + TLSServerSession() = default; int init(const TLSServerContext &tls_ctx, HandlerBase *handler); // ticket is sent automatically. diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_wolfssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_server_session_wolfssl.cc index 2e542a4e024d2e..0cc2dd64950b7d 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_wolfssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_wolfssl.cc @@ -29,10 +29,6 @@ #include "tls_server_context_wolfssl.h" #include "server_base.h" -TLSServerSession::TLSServerSession() {} - -TLSServerSession::~TLSServerSession() {} - int TLSServerSession::init(const TLSServerContext &tls_ctx, HandlerBase *handler) { auto ssl_ctx = tls_ctx.get_native_handle(); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_server_session_wolfssl.h b/deps/ngtcp2/ngtcp2/examples/tls_server_session_wolfssl.h index 6087edac536912..47458828939dbc 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_server_session_wolfssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_server_session_wolfssl.h @@ -36,8 +36,7 @@ class HandlerBase; class TLSServerSession : public TLSSessionBase { public: - TLSServerSession(); - ~TLSServerSession(); + TLSServerSession() = default; int init(const TLSServerContext &tls_ctx, HandlerBase *handler); // ticket is sent automatically. diff --git a/deps/ngtcp2/ngtcp2/examples/tls_session_base_ossl.cc b/deps/ngtcp2/ngtcp2/examples/tls_session_base_ossl.cc index d166773f2f6d65..cc9edda47c7df8 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_session_base_ossl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_session_base_ossl.cc @@ -33,14 +33,14 @@ using namespace ngtcp2; using namespace std::literals; TLSSessionBase::TLSSessionBase() { - ngtcp2_crypto_ossl_ctx_new(&ossl_ctx_, NULL); + ngtcp2_crypto_ossl_ctx_new(&ossl_ctx_, nullptr); } TLSSessionBase::~TLSSessionBase() { auto ssl = ngtcp2_crypto_ossl_ctx_get_ssl(ossl_ctx_); if (ssl) { - SSL_set_app_data(ssl, NULL); + SSL_set_app_data(ssl, nullptr); SSL_free(ssl); } diff --git a/deps/ngtcp2/ngtcp2/examples/tls_session_base_quictls.cc b/deps/ngtcp2/ngtcp2/examples/tls_session_base_quictls.cc index 5471cf00b8765d..8ef5027af6fde2 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_session_base_quictls.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_session_base_quictls.cc @@ -32,8 +32,6 @@ using namespace ngtcp2; using namespace std::literals; -TLSSessionBase::TLSSessionBase() : ssl_{nullptr} {} - TLSSessionBase::~TLSSessionBase() { if (ssl_) { SSL_free(ssl_); @@ -68,12 +66,11 @@ std::string_view TLSSessionBase::get_negotiated_group() const { return ""sv; } - auto key_del = defer(EVP_PKEY_free, key); + auto key_del = defer([key] { EVP_PKEY_free(key); }); auto nid = EVP_PKEY_id(key); if (nid == EVP_PKEY_EC) { - auto ec = EVP_PKEY_get1_EC_KEY(key); - auto ec_del = defer(EC_KEY_free, ec); + auto ec = EVP_PKEY_get0_EC_KEY(key); nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); } diff --git a/deps/ngtcp2/ngtcp2/examples/tls_session_base_quictls.h b/deps/ngtcp2/ngtcp2/examples/tls_session_base_quictls.h index aee06565bbdb1c..4c022a2422dc8f 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_session_base_quictls.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_session_base_quictls.h @@ -36,7 +36,7 @@ class TLSSessionBase { public: - TLSSessionBase(); + TLSSessionBase() = default; ~TLSSessionBase(); SSL *get_native_handle() const; @@ -48,7 +48,7 @@ class TLSSessionBase { void enable_keylog() {} protected: - SSL *ssl_; + SSL *ssl_{}; }; #endif // !defined(TLS_SESSION_BASE_QUICTLS_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_session_base_wolfssl.cc b/deps/ngtcp2/ngtcp2/examples/tls_session_base_wolfssl.cc index 4620182640728c..d0465b8559f75a 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_session_base_wolfssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/tls_session_base_wolfssl.cc @@ -30,8 +30,6 @@ using namespace ngtcp2; -TLSSessionBase::TLSSessionBase() : ssl_{nullptr} {} - TLSSessionBase::~TLSSessionBase() { if (ssl_) { wolfSSL_free(ssl_); diff --git a/deps/ngtcp2/ngtcp2/examples/tls_session_base_wolfssl.h b/deps/ngtcp2/ngtcp2/examples/tls_session_base_wolfssl.h index b88e2b4e14741f..ec9933da2be97c 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_session_base_wolfssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_session_base_wolfssl.h @@ -38,7 +38,7 @@ class TLSSessionBase { public: - TLSSessionBase(); + TLSSessionBase() = default; ~TLSSessionBase(); WOLFSSL *get_native_handle() const; @@ -54,7 +54,7 @@ class TLSSessionBase { void enable_keylog() {} protected: - WOLFSSL *ssl_; + WOLFSSL *ssl_{}; }; #endif // !defined(TLS_SESSION_BASE_WOLFSSL_H) diff --git a/deps/ngtcp2/ngtcp2/examples/tls_shared_boringssl.h b/deps/ngtcp2/ngtcp2/examples/tls_shared_boringssl.h index 6e52d750e11eb2..c08712d1794828 100644 --- a/deps/ngtcp2/ngtcp2/examples/tls_shared_boringssl.h +++ b/deps/ngtcp2/ngtcp2/examples/tls_shared_boringssl.h @@ -35,7 +35,7 @@ namespace ngtcp2 { namespace tls { -constexpr uint16_t CERTIFICATE_COMPRESSION_ALGO_BROTLI = 2; +inline constexpr uint16_t CERTIFICATE_COMPRESSION_ALGO_BROTLI = 2; #ifdef HAVE_LIBBROTLI int cert_compress(SSL *ssl, CBB *out, const uint8_t *in, size_t in_len); diff --git a/deps/ngtcp2/ngtcp2/examples/util.cc b/deps/ngtcp2/ngtcp2/examples/util.cc index ccd900a2b9b5f0..c5baac9073e9f3 100644 --- a/deps/ngtcp2/ngtcp2/examples/util.cc +++ b/deps/ngtcp2/ngtcp2/examples/util.cc @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -108,7 +109,7 @@ uint64_t round2even(uint64_t n) { } // namespace std::string format_durationf(uint64_t ns) { - static constexpr const std::string_view units[] = {"us"sv, "ms"sv, "s"sv}; + static constexpr std::string_view units[] = {"us"sv, "ms"sv, "s"sv}; if (ns < 1000) { return format_uint(ns) + "ns"; } @@ -351,15 +352,8 @@ std::string straddr(const sockaddr *sa, socklen_t salen) { return res; } -uint16_t port(const sockaddr_union *su) { - switch (su->sa.sa_family) { - case AF_INET: - return ntohs(su->in.sin_port); - case AF_INET6: - return ntohs(su->in6.sin6_port); - default: - return 0; - } +std::string straddr(const Address &addr) { + return straddr(addr.as_sockaddr(), addr.size()); } bool prohibited_port(uint16_t port) { @@ -796,7 +790,7 @@ std::optional> read_file(const std::string_view &path) { return {}; } - auto fd_d = defer(close, fd); + auto fd_d = defer([fd] { close(fd); }); auto size = lseek(fd, 0, SEEK_END); if (size == static_cast(-1)) { @@ -809,13 +803,28 @@ std::optional> read_file(const std::string_view &path) { return {}; } - auto addr_d = defer(munmap, addr, static_cast(size)); + auto addr_d = + defer([addr, size] { munmap(addr, static_cast(size)); }); auto p = static_cast(addr); return {{p, p + size}}; } +size_t clamp_buffer_size(ngtcp2_conn *conn, size_t buflen, size_t gso_burst) { + return std::min(gso_burst == 0 + ? ngtcp2_conn_get_send_quantum(conn) + : ngtcp2_conn_get_path_max_tx_udp_payload_size(conn) * + gso_burst, + buflen); +} + +bool recv_pkt_time_threshold_exceeded(bool time_sensitive, ngtcp2_tstamp start, + size_t pktcnt) { + return time_sensitive && pktcnt && + util::timestamp() - start >= NGTCP2_MILLISECONDS; +} + std::optional read_ech_server_config(const std::string_view &path) { auto pkey = read_hpke_private_key_pem(path); @@ -835,7 +844,7 @@ read_ech_server_config(const std::string_view &path) { } std::span generate_siphash_key() { - static auto key = []() { + static auto key = [] { std::array key; auto rv = generate_secure_random(as_writable_uint8_span(std::span{key})); @@ -852,6 +861,18 @@ std::span generate_siphash_key() { return key; } +std::string realpath(const char *path) { + auto cpath = ::realpath(path, nullptr); + if (!cpath) { + assert(0); + abort(); + } + + auto cpath_d = defer([cpath] { free(cpath); }); + + return cpath; +} + } // namespace util std::ostream &operator<<(std::ostream &os, const ngtcp2_cid &cid) { diff --git a/deps/ngtcp2/ngtcp2/examples/util.h b/deps/ngtcp2/ngtcp2/examples/util.h index a4f6456cfd9245..cccd13c3b1d23a 100644 --- a/deps/ngtcp2/ngtcp2/examples/util.h +++ b/deps/ngtcp2/ngtcp2/examples/util.h @@ -80,18 +80,23 @@ inline nghttp3_nv make_nv_nn(const std::string_view &name, NGHTTP3_NV_FLAG_NO_COPY_NAME | NGHTTP3_NV_FLAG_NO_COPY_VALUE); } -constinit const auto hexdigits = []() { - constexpr char LOWER_XDIGITS[] = "0123456789abcdef"; +inline constexpr char LOWER_XDIGITS[] = "0123456789abcdef"; - std::array tbl; - - for (size_t i = 0; i < 256; ++i) { - tbl[i * 2] = LOWER_XDIGITS[static_cast(i >> 4)]; - tbl[i * 2 + 1] = LOWER_XDIGITS[static_cast(i & 0xf)]; - } +template +requires(std::indirectly_writable) +constexpr O format_hex_uint8(uint8_t b, O result) { +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wsign-conversion" +#endif // __GNUC__ + *result++ = LOWER_XDIGITS[b >> 4]; + *result++ = LOWER_XDIGITS[b & 0xf]; +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif // __GNUC__ - return tbl; -}(); + return result; +} // format_hex converts a range [|first|, |last|) in hex format, and // stores the result in another range, beginning at |result|. It @@ -102,9 +107,7 @@ requires(std::indirectly_writable && sizeof(std::iter_value_t) == sizeof(uint8_t)) constexpr O format_hex(I first, I last, O result) { for (; first != last; ++first) { - result = std::ranges::copy_n( - hexdigits.data() + static_cast(*first) * 2, 2, result) - .out; + result = format_hex_uint8(static_cast(*first), result); } return result; @@ -172,7 +175,7 @@ template requires(std::indirectly_writable) constexpr O format_hex(T n, O result) { if constexpr (sizeof(n) == 1) { - return std::ranges::copy_n(hexdigits.data() + n * 2, 2, result).out; + return format_hex_uint8(n, result); } if constexpr (std::endian::native == std::endian::little) { @@ -180,15 +183,14 @@ constexpr O format_hex(T n, O result) { auto p = end + sizeof(n); for (; p != end; --p) { - result = - std::ranges::copy_n(hexdigits.data() + *(p - 1) * 2, 2, result).out; + result = format_hex_uint8(*(p - 1), result); } } else { auto p = reinterpret_cast(&n); auto end = p + sizeof(n); for (; p != end; ++p) { - result = std::ranges::copy_n(hexdigits.data() + *p * 2, 2, result).out; + result = format_hex_uint8(*p, result); } } @@ -231,29 +233,22 @@ bool numeric_host(const char *hostname, int family); // or -1. int hexdump(FILE *out, const void *data, size_t datalen); -static constexpr uint8_t lowcase_tbl[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', - 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', - 'z', 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, -}; +inline constexpr auto lowcase_tbl = [] { + std::array tbl; + + for (size_t i = 0; i < 256; ++i) { + if ('A' <= i && i <= 'Z') { + tbl[i] = static_cast(i - 'A' + 'a'); + } else { + tbl[i] = static_cast(i); + } + } + + return tbl; +}(); constexpr char lowcase(char c) noexcept { - return as_signed(lowcase_tbl[static_cast(c)]); + return lowcase_tbl[static_cast(c)]; } struct CaseCmp { @@ -277,8 +272,8 @@ ngtcp2_cid make_cid_key(std::span cid); // straddr stringifies |sa| of length |salen| in a format "[IP]:PORT". std::string straddr(const sockaddr *sa, socklen_t salen); -// port returns port from |su|. -uint16_t port(const sockaddr_union *su); +// straddr stringifies |addr| in a format "[IP]:PORT". +std::string straddr(const Address &addr); // prohibited_port returns true if |port| is prohibited as a client // port. @@ -293,7 +288,7 @@ std::string_view strccalgo(ngtcp2_cc_algo cc_algo); std::optional> read_mime_types(const std::string_view &filename); -constinit const auto count_digit_tbl = []() { +inline constexpr auto count_digit_tbl = [] { std::array::digits10> tbl; uint64_t x = 1; @@ -321,7 +316,7 @@ template constexpr size_t count_digit(T x) { return y + 1; } -constinit const auto utos_digits = []() { +inline constexpr auto utos_digits = [] { std::array a; for (size_t i = 0; i < 100; ++i) { @@ -443,7 +438,7 @@ int generate_secret(std::span secret); std::string normalize_path(const std::string_view &path); template Pred> -constexpr auto pred_tbl_gen256(Pred pred) { +consteval auto pred_tbl_gen256(Pred pred) { std::array tbl; for (size_t i = 0; i < tbl.size(); ++i) { @@ -453,17 +448,19 @@ constexpr auto pred_tbl_gen256(Pred pred) { return tbl; } -constexpr auto digit_pred(size_t i) noexcept { return '0' <= i && i <= '9'; } +consteval auto digit_pred(size_t i) noexcept { return '0' <= i && i <= '9'; } -constinit const auto is_digit_tbl = pred_tbl_gen256(digit_pred); +inline constexpr auto is_digit_tbl = pred_tbl_gen256(digit_pred); constexpr bool is_digit(char c) noexcept { return is_digit_tbl[static_cast(c)]; } -constinit const auto is_hex_digit_tbl = pred_tbl_gen256([](auto i) { +consteval auto hex_digit_pred(size_t i) noexcept { return digit_pred(i) || ('A' <= i && i <= 'F') || ('a' <= i && i <= 'f'); -}); +} + +inline constexpr auto is_hex_digit_tbl = pred_tbl_gen256(hex_digit_pred); constexpr bool is_hex_digit(char c) noexcept { return is_hex_digit_tbl[static_cast(c)]; @@ -478,7 +475,7 @@ constexpr bool is_hex_string(R &&r) { return !(std::ranges::size(r) & 1) && std::ranges::all_of(r, is_hex_digit); } -constinit const auto hex_to_uint_tbl = []() { +inline constexpr auto hex_to_uint_tbl = [] { std::array tbl; std::ranges::fill(tbl, 256); @@ -531,12 +528,17 @@ std::vector split_str(const std::string_view &s, char delim = ','); // parse_version parses |s| to get 4 byte QUIC version. |s| must be a -// hex string and must start with "0x" (.e.g, 0x00000001). +// hex string and must start with "0x" (e.g., 0x00000001). std::optional parse_version(const std::string_view &s); // read_file reads a file denoted by |path| and returns its content. std::optional> read_file(const std::string_view &path); +size_t clamp_buffer_size(ngtcp2_conn *conn, size_t buflen, size_t gso_burst); + +bool recv_pkt_time_threshold_exceeded(bool time_sensitive, ngtcp2_tstamp start, + size_t pktcnt); + enum HPKEPrivateKeyType : uint16_t { HPKE_DHKEM_X25519_HKDF_SHA256 = 0x0020, }; @@ -576,6 +578,9 @@ constexpr std::string_view get_string(const std::string_view &uri, return {uri.data() + p->off, p->len}; } +// realpath returns the canonicalized absolute path to |path|. +std::string realpath(const char *path); + } // namespace util std::ostream &operator<<(std::ostream &os, const ngtcp2_cid &cid); @@ -585,7 +590,8 @@ std::ostream &operator<<(std::ostream &os, const ngtcp2_cid &cid); namespace std { template <> struct hash { hash() { - std::ranges::copy(ngtcp2::util::generate_siphash_key(), key.begin()); + std::ranges::copy(ngtcp2::util::generate_siphash_key(), + std::ranges::begin(key)); } std::size_t operator()(const ngtcp2_cid &cid) const noexcept { diff --git a/deps/ngtcp2/ngtcp2/examples/util_openssl.cc b/deps/ngtcp2/ngtcp2/examples/util_openssl.cc index 711ef16d869b19..85ff90d18d7e86 100644 --- a/deps/ngtcp2/ngtcp2/examples/util_openssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/util_openssl.cc @@ -68,10 +68,17 @@ int generate_secret(std::span secret) { return -1; } - auto ctx_deleter = defer(EVP_MD_CTX_free, ctx); + auto ctx_deleter = defer([ctx] { EVP_MD_CTX_free(ctx); }); + + static const auto sha256 = +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD_fetch(nullptr, "sha256", nullptr); +#else // OPENSSL_VERSION_NUMBER < 0x30000000L + EVP_sha256(); +#endif // OPENSSL_VERSION_NUMBER < 0x30000000L auto mdlen = static_cast(secret.size()); - if (!EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) || + if (!EVP_DigestInit_ex(ctx, sha256, nullptr) || !EVP_DigestUpdate(ctx, rand.data(), rand.size()) || !EVP_DigestFinal_ex(ctx, secret.data(), &mdlen)) { return -1; @@ -80,10 +87,6 @@ int generate_secret(std::span secret) { return 0; } -namespace { -void openssl_free_wrap(void *ptr) { OPENSSL_free(ptr); } -} // namespace - std::optional read_hpke_private_key_pem(const std::string_view &filename) { auto f = BIO_new_file(filename.data(), "r"); @@ -92,7 +95,7 @@ read_hpke_private_key_pem(const std::string_view &filename) { return {}; } - auto f_d = defer(BIO_free, f); + auto f_d = defer([f] { BIO_free(f); }); EVP_PKEY *pkey; @@ -100,7 +103,7 @@ read_hpke_private_key_pem(const std::string_view &filename) { return {}; } - auto pkey_d = defer(EVP_PKEY_free, pkey); + auto pkey_d = defer([pkey] { EVP_PKEY_free(pkey); }); HPKEPrivateKey res; @@ -134,7 +137,7 @@ std::optional> read_pem(const std::string_view &filename, return {}; } - auto f_d = defer(BIO_free, f); + auto f_d = defer([f] { BIO_free(f); }); for (;;) { char *pem_type, *header; @@ -147,9 +150,11 @@ std::optional> read_pem(const std::string_view &filename, return {}; } - auto pem_type_d = defer(openssl_free_wrap, pem_type); - auto pem_header = defer(openssl_free_wrap, header); - auto data_d = defer(openssl_free_wrap, data); + auto pem_d = defer([pem_type, header, data] { + OPENSSL_free(pem_type); + OPENSSL_free(header); + OPENSSL_free(data); + }); if (type != pem_type) { continue; diff --git a/deps/ngtcp2/ngtcp2/examples/util_test.cc b/deps/ngtcp2/ngtcp2/examples/util_test.cc index 85e68d729c57be..f234de7c00480e 100644 --- a/deps/ngtcp2/ngtcp2/examples/util_test.cc +++ b/deps/ngtcp2/ngtcp2/examples/util_test.cc @@ -419,6 +419,50 @@ void test_util_format_hex() { assert_stdstring_equal("deadbeef"s, util::format_hex(a)); assert_stdstring_equal("deadbeef"s, util::format_hex(0xdeadbeef)); assert_stdstring_equal("beef"s, util::format_hex(a.data() + 2, 2)); + + std::array buf; + + assert_stdsv_equal( + "00"sv, (std::string_view{std::ranges::begin(buf), + util::format_hex(static_cast(0u), + std::ranges::begin(buf))})); + assert_stdsv_equal( + "ec"sv, (std::string_view{std::ranges::begin(buf), + util::format_hex(static_cast(0xecu), + std::ranges::begin(buf))})); + assert_stdsv_equal( + "00000000"sv, + (std::string_view{std::ranges::begin(buf), + util::format_hex(0u, std::ranges::begin(buf))})); + assert_stdsv_equal( + "0000ab01"sv, + (std::string_view{std::ranges::begin(buf), + util::format_hex(0xab01u, std::ranges::begin(buf))})); + assert_stdsv_equal( + "deadbeefbaadf00d"sv, + (std::string_view{ + std::ranges::begin(buf), + util::format_hex(0xdeadbeefbaadf00du, std::ranges::begin(buf))})); + assert_stdsv_equal( + "ffffffffffffffff"sv, + (std::string_view{std::ranges::begin(buf), + util::format_hex(std::numeric_limits::max(), + std::ranges::begin(buf))})); + + std::vector char_vec; + util::format_hex(a, std::back_inserter(char_vec)); + + assert_stdsv_equal("deadbeef"sv, + (std::string_view{std::ranges::begin(char_vec), + std::ranges::end(char_vec)})); + + std::vector uint8_vec; + util::format_hex(a, std::back_inserter(uint8_vec)); + + assert_stdsv_equal( + "deadbeef"sv, + (std::string_view{reinterpret_cast(uint8_vec.data()), + uint8_vec.size()})); } void test_util_decode_hex() { diff --git a/deps/ngtcp2/ngtcp2/examples/util_wolfssl.cc b/deps/ngtcp2/ngtcp2/examples/util_wolfssl.cc index a8bceab664e11f..1afbaec4502fb9 100644 --- a/deps/ngtcp2/ngtcp2/examples/util_wolfssl.cc +++ b/deps/ngtcp2/ngtcp2/examples/util_wolfssl.cc @@ -87,7 +87,7 @@ std::optional> read_pem(const std::string_view &filename, return {}; } - auto f_d = defer(wolfSSL_BIO_free, f); + auto f_d = defer([f] { wolfSSL_BIO_free(f); }); char *pem_type, *header; unsigned char *data; @@ -98,9 +98,11 @@ std::optional> read_pem(const std::string_view &filename, return {}; } - auto pem_type_d = defer(wolfSSL_OPENSSL_free, pem_type); - auto header_d = defer(wolfSSL_OPENSSL_free, header); - auto data_d = defer(wolfSSL_OPENSSL_free, data); + auto pem_d = defer([pem_type, header, data] { + wolfSSL_OPENSSL_free(pem_type); + wolfSSL_OPENSSL_free(header); + wolfSSL_OPENSSL_free(data); + }); if (type != pem_type) { std::cerr << name << " file " << filename << " contains unexpected type" @@ -134,8 +136,12 @@ const char *crypto_default_ciphers() { const char *crypto_default_groups() { return "X25519:P-256:P-384:P-521" #ifdef WOLFSSL_HAVE_MLKEM +# if LIBWOLFSSL_VERSION_HEX < 0x05008004 ":X25519_ML_KEM_768" -#endif // WOLFSSL_HAVE_MLKEM +# else // LIBWOLFSSL_VERSION_HEX >= 0x05008004 + ":X25519MLKEM768" +# endif // LIBWOLFSSL_VERSION_HEX >= 0x05008004 +#endif // WOLFSSL_HAVE_MLKEM ; } diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h index d58a6f1240d4a4..a89e9d8184d513 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h @@ -306,15 +306,29 @@ typedef struct ngtcp2_mem { * @macro * * :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE` is the default maximum UDP - * datagram payload size that the local endpoint transmits. + * datagram payload size that the local endpoint transmits without + * Path MTU Discovery (PMTUD) or the custom settings (see + * :member:`ngtcp2_settings.max_tx_udp_payload_size` and + * :member:`ngtcp2_settings.no_tx_udp_payload_size_shaping`). */ #define NGTCP2_MAX_UDP_PAYLOAD_SIZE 1200 /** * @macro * - * :macro:`NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE` is the maximum UDP + * :macro:`NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE` is the maximum UDP datagram + * payload size that this library can output. + */ +#define NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE 65527 + +/** + * @macro + * + * :macro:`NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE` was the maximum UDP * datagram payload size that Path MTU Discovery can discover. + * + * Deprecated since v1.17.0. Path MTU Discovery is not capped to this + * value anymore. */ #define NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE 1452 @@ -1561,7 +1575,8 @@ typedef struct ngtcp2_transport_params { } ngtcp2_transport_params; #define NGTCP2_CONN_INFO_V1 1 -#define NGTCP2_CONN_INFO_VERSION NGTCP2_CONN_INFO_V1 +#define NGTCP2_CONN_INFO_V2 2 +#define NGTCP2_CONN_INFO_VERSION NGTCP2_CONN_INFO_V2 /** * @struct @@ -1600,6 +1615,52 @@ typedef struct ngtcp2_conn_info { * packets which have not been acknowledged. */ uint64_t bytes_in_flight; + /* The following fields have been added since NGTCP2_CONN_INFO_V2. */ + /** + * :member:`pkt_sent` is the number of QUIC packets sent. This + * field has been available since v1.16.0. + */ + uint64_t pkt_sent; + /** + * :member:`bytes_sent` is the number of bytes (the sum of QUIC + * packet length) sent. This field has been available since + * v1.16.0. + */ + uint64_t bytes_sent; + /** + * :member:`pkt_recv` is the number of QUIC packets received, + * excluding discarded ones. This field has been available since + * v1.16.0. + */ + uint64_t pkt_recv; + /** + * :member:`bytes_recv` is the number of bytes (the sum of QUIC + * packet length) received, excluding discarded ones. This field + * has been available since v1.16.0. + */ + uint64_t bytes_recv; + /** + * :member:`pkt_lost` is the number of QUIC packets that are + * considered lost, excluding PMTUD packets. This field has been + * available since v1.16.0. + */ + uint64_t pkt_lost; + /** + * :member:`bytes_lost` is the number of bytes (the sum of QUIC + * packet length) lost, excluding PMTUD packets. This field has + * been available since v1.16.0. + */ + uint64_t bytes_lost; + /** + * :member:`ping_recv` is the number of PING frames received. This + * field has been available since v1.16.0. + */ + uint64_t ping_recv; + /** + * :member:`pkt_discarded` is the number of QUIC packets discarded. + * This field has been available since v1.16.0. + */ + uint64_t pkt_discarded; } ngtcp2_conn_info; /** @@ -1739,7 +1800,9 @@ typedef struct ngtcp2_settings { ngtcp2_printf log_printf; /** * :member:`max_tx_udp_payload_size` is the maximum size of UDP - * datagram payload that the local endpoint transmits. + * datagram payload that the local endpoint transmits. This must be + * larger than or equal to :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`, and + * less then or equal to :macro:`NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE`. */ size_t max_tx_udp_payload_size; /** @@ -1904,12 +1967,13 @@ typedef struct ngtcp2_settings { /** * :member:`pmtud_probes` is the array of UDP datagram payload size * to probe during Path MTU Discovery. The discovery is done in the - * order appeared in this array. The size must be strictly larger - * than 1200, otherwise the behavior is undefined. The maximum - * value in this array should be set to - * :member:`max_tx_udp_payload_size`. If this field is not set, the - * predefined PMTUD probes are made. This field has been available - * since v1.4.0. + * order appeared in this array. The payload size must be strictly + * larger than :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`, and less than + * or equal to :macro:`NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE`. Otherwise + * the behavior is undefined. The maximum value in this array + * should be set to :member:`max_tx_udp_payload_size`. If this + * field is not set, the predefined PMTUD probes are made. This + * field has been available since v1.4.0. */ const uint16_t *pmtud_probes; /** @@ -4108,9 +4172,7 @@ NGTCP2_EXTERN void ngtcp2_conn_set_keep_alive_timeout(ngtcp2_conn *conn, * `ngtcp2_conn_get_expiry` returns the next expiry time. It returns * ``UINT64_MAX`` if there is no next expiry. * - * Call `ngtcp2_conn_handle_expiry` and then - * `ngtcp2_conn_writev_stream` (or `ngtcp2_conn_writev_datagram`) when - * the expiry time has passed. + * Call `ngtcp2_conn_handle_expiry` when the expiry time has passed. */ NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn); @@ -4118,6 +4180,20 @@ NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn); * @function * * `ngtcp2_conn_handle_expiry` handles expired timer. + * + * If it returns :macro:`NGTCP2_ERR_IDLE_CLOSE`, it means that an idle + * timer has fired for this particular connection. In this case, drop + * the connection without calling + * `ngtcp2_conn_write_connection_close`. If it returns any of the + * other negative error codes, close the connection by sending the + * terminal packet produced by `ngtcp2_conn_write_connection_close`. + * Otherwise, schedule `ngtcp2_conn_writev_stream` call. An + * application may call any number of additional + * `ngtcp2_conn_read_pkt` and `ngtcp2_conn_handle_expiry` before + * calling `ngtcp2_conn_writev_stream`. After calling + * `ngtcp2_conn_writev_stream`, new expiry is set. The application + * should call `ngtcp2_conn_get_expiry` to get a new deadline and set + * the timer. */ NGTCP2_EXTERN int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts); @@ -5503,7 +5579,9 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr, * |destlen| could be shorten by some factors (e.g., server side * amplification limit). This function returns * :macro:`NGTCP2_ERR_NOBUF` if the resulting buffer is too small even - * if the given buffer has enough space. + * if the given buffer has enough space. This can happen if sending a + * packet would exceed a transmission limit (e.g., for amplification + * attack protection). * * This function must not be called from inside the callback * functions. @@ -5518,7 +5596,8 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_application_error(ngtcp2_ccerr *ccerr, * :macro:`NGTCP2_ERR_NOMEM` * Out of memory * :macro:`NGTCP2_ERR_NOBUF` - * Buffer is too small + * Buffer is too small or packet would exceed the transmission + * limit (e.g., for amplification attack protection). * :macro:`NGTCP2_ERR_INVALID_STATE` * The current state does not allow sending CONNECTION_CLOSE * frame. @@ -5582,6 +5661,26 @@ NGTCP2_EXTERN int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, int64_t stream_id, void *stream_user_data); +/** + * @function + * + * `ngtcp2_conn_get_stream_user_data` returns stream_user_data + * associated to the stream identified by |stream_id|. If the stream + * is not found, or no stream data is associated to the stream, this + * function returns NULL. + * + * The stream_user_data can be associated to the stream by one of the + * following functions: + * + * - `ngtcp2_conn_open_bidi_stream` + * - `ngtcp2_conn_open_uni_stream` + * - `ngtcp2_conn_set_stream_user_data` + * + * This function has been available since v1.17.0. + */ +NGTCP2_EXTERN void *ngtcp2_conn_get_stream_user_data(ngtcp2_conn *conn, + int64_t stream_id); + /** * @function * @@ -5667,14 +5766,23 @@ typedef ngtcp2_ssize (*ngtcp2_write_pkt)(ngtcp2_conn *conn, ngtcp2_path *path, * first packet is `ngtcp2_conn_get_path_max_tx_udp_payload_size(conn) * ` bytes long. The * application can adjust the length of the buffer to limit the number - * of packets to aggregate. If this function returns positive - * integer, all packets share the same :type:`ngtcp2_path` and - * :type:`ngtcp2_pkt_info` values, and they are assigned to the - * objects pointed by |path| and |pi| respectively. The length of all - * packets other than the last packet is assigned to |*pgsolen|. The - * length of last packet is equal to or less than |*pgsolen|. - * |write_pkt| must write a single packet. After all packets are - * written, this function calls `ngtcp2_conn_update_pkt_tx_time`. + * of packets to aggregate (or use `ngtcp2_conn_write_aggregate_pkt2` + * to control the number of packets to write directly). If this + * function returns positive integer, all packets share the same + * :type:`ngtcp2_path` and :type:`ngtcp2_pkt_info` values, and they + * are assigned to the objects pointed by |path| and |pi| + * respectively. The length of all packets other than the last packet + * is assigned to |*pgsolen|. The length of last packet is equal to + * or less than |*pgsolen|. |write_pkt| must write a single packet. + * After all packets are written, this function calls + * `ngtcp2_conn_update_pkt_tx_time`. + * + * This function is equivalent to call + * `ngtcp2_conn_write_aggregate_pkt2` with |buflen| = min(|buflen|, + * `ngtcp2_conn_get_send_quantum(conn) + * `) and |num_pkts| = 0 followed by + * `ngtcp2_conn_update_pkt_tx_time(conn) + * `. * * This function returns the number of bytes written to the buffer, or * a negative error code returned by |write_pkt|. @@ -5686,6 +5794,39 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( ngtcp2_pkt_info *pi, uint8_t *buf, size_t buflen, size_t *pgsolen, ngtcp2_write_pkt write_pkt, ngtcp2_tstamp ts); +/** + * @function + * + * `ngtcp2_conn_write_aggregate_pkt2` behaves like + * `ngtcp2_conn_write_aggregate_pkt`, but it accepts |num_pkts| to + * specify the maximum number of packets to write. If |num_pkts| is + * 0, this function writes packets as much as possible. The actual + * number of packets to write is determined by the connection state + * (e.g., the congestion controller, data available to send) and the + * length of packet produced. It also does not clamp |buflen|, and + * does not call `ngtcp2_conn_update_pkt_tx_time`. + * + * This function offers more flexibility and optimization chances to + * an application. It can experiment different GSO buffer size + * strategy and number of GSO writes per event loop. + * + * This function has been available since v1.17.0. + */ +NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt2_versioned( + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *buf, size_t buflen, size_t *pgsolen, + ngtcp2_write_pkt write_pkt, size_t num_pkts, ngtcp2_tstamp ts); + +/** + * @function + * + * `ngtcp2_conn_get_timestamp` returns the latest timestamp that is + * known to |conn|. + * + * This function has been available since v1.16.0. + */ +NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_timestamp(const ngtcp2_conn *conn); + /** * @function * @@ -5778,9 +5919,9 @@ NGTCP2_EXTERN void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps); * * :member:`handshake_timeout ` = * ``UINT64_MAX`` * * :member:`glitch_ratelim_burst - * ` = 1000 + * ` = 4000 * * :member:`glitch_ratelim_rate - * ` = 33 + * ` = 132 */ NGTCP2_EXTERN void ngtcp2_settings_default_versioned(int settings_version, ngtcp2_settings *settings); @@ -6083,6 +6224,17 @@ NGTCP2_EXTERN uint32_t ngtcp2_select_version(const uint32_t *preferred_versions, (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (BUF), (BUFLEN), (PGSOLEN), \ (WRITE_PKT), (TS)) +/* + * `ngtcp2_conn_write_aggregate_pkt2` is a wrapper around + * `ngtcp2_conn_write_aggregate_pkt2_versioned` to set the correct + * struct version. + */ +#define ngtcp2_conn_write_aggregate_pkt2(CONN, PATH, PI, BUF, BUFLEN, PGSOLEN, \ + WRITE_PKT, NUM_PKTS, TS) \ + ngtcp2_conn_write_aggregate_pkt2_versioned( \ + (CONN), (PATH), NGTCP2_PKT_INFO_VERSION, (PI), (BUF), (BUFLEN), (PGSOLEN), \ + (WRITE_PKT), (NUM_PKTS), (TS)) + /* * `ngtcp2_settings_default` is a wrapper around * `ngtcp2_settings_default_versioned` to set the correct struct diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h index e70a095ceb1300..62904c53ab5df1 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h @@ -36,7 +36,7 @@ * * Version number of the ngtcp2 library release. */ -#define NGTCP2_VERSION "1.15.1" +#define NGTCP2_VERSION "1.19.0" /** * @macro @@ -46,6 +46,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGTCP2_VERSION_NUM 0x010f01 +#define NGTCP2_VERSION_NUM 0x011300 #endif /* !defined(NGTCP2_VERSION_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c index 59bc621ef46b28..4a9ac5cf0aa7c9 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.c @@ -34,9 +34,11 @@ ngtcp2_objalloc_def(acktr_entry, ngtcp2_acktr_entry, oplent) static void acktr_entry_init(ngtcp2_acktr_entry *ent, int64_t pkt_num, ngtcp2_tstamp tstamp) { - ent->pkt_num = pkt_num; - ent->len = 1; - ent->tstamp = tstamp; + *ent = (ngtcp2_acktr_entry){ + .pkt_num = pkt_num, + .len = 1, + .tstamp = tstamp, + }; } int ngtcp2_acktr_entry_objalloc_new(ngtcp2_acktr_entry **ent, int64_t pkt_num, @@ -219,8 +221,10 @@ ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr, int64_t largest_ack) { ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks.rb); - ent->largest_ack = largest_ack; - ent->pkt_num = pkt_num; + *ent = (ngtcp2_acktr_ack_entry){ + .largest_ack = largest_ack, + .pkt_num = pkt_num, + }; return ent; } @@ -333,16 +337,14 @@ void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr) { acktr->flags |= NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK; } -ngtcp2_frame *ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr, - ngtcp2_frame *fr, uint8_t type, - ngtcp2_tstamp ts, - ngtcp2_duration ack_delay, - uint64_t ack_delay_exponent) { +int ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr, ngtcp2_ack *ack, + uint8_t type, ngtcp2_tstamp ts, + ngtcp2_duration ack_delay, + uint64_t ack_delay_exponent) { int64_t last_pkt_num; ngtcp2_ack_range *range; ngtcp2_ksl_it it; ngtcp2_acktr_entry *rpkt; - ngtcp2_ack *ack = &fr->ack; ngtcp2_tstamp largest_ack_ts; size_t num_acks; @@ -351,13 +353,13 @@ ngtcp2_frame *ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr, } if (!ngtcp2_acktr_require_active_ack(acktr, ack_delay, ts)) { - return NULL; + return -1; } it = ngtcp2_acktr_get(acktr); if (ngtcp2_ksl_it_end(&it)) { ngtcp2_acktr_commit_ack(acktr); - return NULL; + return -1; } num_acks = ngtcp2_ksl_len(&acktr->ents); @@ -420,7 +422,7 @@ ngtcp2_frame *ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr, last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); } - return fr; + return 0; } void ngtcp2_acktr_increase_ecn_counts(ngtcp2_acktr *acktr, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h index cf75a774db3e82..6505a1759484e9 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_acktr.h @@ -235,19 +235,18 @@ void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr); /* * ngtcp2_acktr_create_ack_frame creates ACK frame in the object - * pointed by |fr|, and returns |fr| if there are any received packets - * to acknowledge. If there are no packets to acknowledge, this - * function returns NULL. fr->ack.ranges must be able to contain at + * pointed by |ack|, and returns 0 if it successfully creates ACK + * frame in |ack|. If there are no packets to acknowledge, this + * function returns -1. |ack|->ranges must be able to contain at * least NGTCP2_MAX_ACK_RANGES elements. * * Call ngtcp2_acktr_commit_ack after a created ACK frame is * successfully serialized into a packet. */ -ngtcp2_frame *ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr, - ngtcp2_frame *fr, uint8_t type, - ngtcp2_tstamp ts, - ngtcp2_duration ack_delay, - uint64_t ack_delay_exponent); +int ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr, ngtcp2_ack *ack, + uint8_t type, ngtcp2_tstamp ts, + ngtcp2_duration ack_delay, + uint64_t ack_delay_exponent); /* * ngtcp2_acktr_increase_ecn_counts increases ECN counts from |pi|. diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c index 1fb273d494e8e2..58694e3836e42e 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_addr.c @@ -31,8 +31,11 @@ ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const ngtcp2_sockaddr *addr, ngtcp2_socklen addrlen) { - dest->addrlen = addrlen; - dest->addr = (ngtcp2_sockaddr *)addr; + *dest = (ngtcp2_addr){ + .addr = (ngtcp2_sockaddr *)addr, + .addrlen = addrlen, + }; + return dest; } @@ -58,14 +61,12 @@ int ngtcp2_sockaddr_eq(const ngtcp2_sockaddr *a, const ngtcp2_sockaddr *b) { switch (a->sa_family) { case NGTCP2_AF_INET: { - const ngtcp2_sockaddr_in *ai = (const ngtcp2_sockaddr_in *)(void *)a, - *bi = (const ngtcp2_sockaddr_in *)(void *)b; + const ngtcp2_sockaddr_in *ai = (void *)a, *bi = (void *)b; return ai->sin_port == bi->sin_port && memcmp(&ai->sin_addr, &bi->sin_addr, sizeof(ai->sin_addr)) == 0; } case NGTCP2_AF_INET6: { - const ngtcp2_sockaddr_in6 *ai = (const ngtcp2_sockaddr_in6 *)(void *)a, - *bi = (const ngtcp2_sockaddr_in6 *)(void *)b; + const ngtcp2_sockaddr_in6 *ai = (void *)a, *bi = (void *)b; return ai->sin6_port == bi->sin6_port && memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr)) == 0; } @@ -89,8 +90,7 @@ uint32_t ngtcp2_addr_cmp(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { switch (a->sa_family) { case NGTCP2_AF_INET: { - const ngtcp2_sockaddr_in *ai = (const ngtcp2_sockaddr_in *)(void *)a, - *bi = (const ngtcp2_sockaddr_in *)(void *)b; + const ngtcp2_sockaddr_in *ai = (void *)a, *bi = (void *)b; if (memcmp(&ai->sin_addr, &bi->sin_addr, sizeof(ai->sin_addr))) { flags |= NGTCP2_ADDR_CMP_FLAG_ADDR; } @@ -100,8 +100,7 @@ uint32_t ngtcp2_addr_cmp(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { return flags; } case NGTCP2_AF_INET6: { - const ngtcp2_sockaddr_in6 *ai = (const ngtcp2_sockaddr_in6 *)(void *)a, - *bi = (const ngtcp2_sockaddr_in6 *)(void *)b; + const ngtcp2_sockaddr_in6 *ai = (void *)a, *bi = (void *)b; if (memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr))) { flags |= NGTCP2_ADDR_CMP_FLAG_ADDR; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c index 4a6797689fcc01..cb865c5cefdf4c 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_balloc.c @@ -71,7 +71,7 @@ int ngtcp2_balloc_get(ngtcp2_balloc *balloc, void **pbuf, size_t n) { return NGTCP2_ERR_NOMEM; } - hd = (ngtcp2_memblock_hd *)(void *)p; + hd = (void *)p; hd->next = balloc->head; balloc->head = hd; ngtcp2_buf_init( diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c index 44be1e189b8835..02865e2a2fc5f6 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.c @@ -190,20 +190,20 @@ static int bbr_is_reno_coexistence_probe_time(ngtcp2_cc_bbr *bbr, static uint64_t bbr_target_inflight(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat); -static int bbr_is_inflight_too_high(ngtcp2_cc_bbr *bbr); +static int bbr_is_inflight_too_high(ngtcp2_cc_bbr *bbr, const ngtcp2_rs *rs); static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); + const ngtcp2_rs *rs, ngtcp2_tstamp ts); static void bbr_note_loss(ngtcp2_cc_bbr *bbr); static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); -static uint64_t -bbr_inflight_longterm_from_lost_packet(ngtcp2_cc_bbr *bbr, - const ngtcp2_cc_pkt *pkt); +static uint64_t bbr_inflight_at_loss(ngtcp2_cc_bbr *bbr, + const ngtcp2_cc_pkt *pkt, + const ngtcp2_rs *rs); static void bbr_update_min_rtt(ngtcp2_cc_bbr *bbr, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); @@ -334,9 +334,11 @@ static void bbr_on_init(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, bbr->max_inflight = 0; - bbr->congestion_recovery_start_ts = UINT64_MAX; - bbr->bdp = 0; + + bbr->undo_bw_shortterm = 0; + bbr->undo_inflight_shortterm = 0; + bbr->undo_inflight_longterm = 0; } static void bbr_reset_congestion_signals(ngtcp2_cc_bbr *bbr) { @@ -384,15 +386,16 @@ static void bbr_check_full_bw_reached(ngtcp2_cc_bbr *bbr, bbr->full_bw_reached = 1; - ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, - "bbr reached full bandwidth, full_bw=%" PRIu64, bbr->full_bw); + ngtcp2_log_infof(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, + "bbr reached full bandwidth, full_bw=%" PRIu64, + bbr->full_bw); } static void bbr_check_startup_high_loss(ngtcp2_cc_bbr *bbr) { if (bbr->full_bw_reached || bbr->loss_events_in_round <= 6 || (bbr->in_loss_recovery && bbr->round_count <= bbr->round_count_at_recovery) || - !bbr_is_inflight_too_high(bbr)) { + !bbr_is_inflight_too_high(bbr, &bbr->rst->rs)) { return; } @@ -402,11 +405,12 @@ static void bbr_check_startup_high_loss(ngtcp2_cc_bbr *bbr) { } static void bbr_init_pacing_rate(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - cstat->pacing_interval_m = + cstat->pacing_interval_m = ngtcp2_max_uint64( ((cstat->first_rtt_sample_ts == UINT64_MAX ? NGTCP2_MILLISECONDS : cstat->smoothed_rtt) << 10) * - 100 / NGTCP2_BBR_STARTUP_PACING_GAIN_H / bbr->initial_cwnd; + 100 / NGTCP2_BBR_STARTUP_PACING_GAIN_H / bbr->initial_cwnd, + 1); } static void bbr_set_pacing_rate_with_gain(ngtcp2_cc_bbr *bbr, @@ -567,7 +571,8 @@ static void bbr_update_max_bw(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack) { bbr_update_round(bbr, ack); - if (cstat->delivery_rate_sec >= bbr->max_bw || !bbr->rst->rs.is_app_limited) { + if (cstat->delivery_rate_sec && (cstat->delivery_rate_sec >= bbr->max_bw || + !bbr->rst->rs.is_app_limited)) { ngtcp2_window_filter_update(&bbr->max_bw_filter, cstat->delivery_rate_sec, bbr->cycle_count); @@ -879,7 +884,7 @@ static void bbr_adapt_longterm_model(ngtcp2_cc_bbr *bbr, } } - if (!bbr_is_inflight_too_high(bbr)) { + if (!bbr_is_inflight_too_high(bbr, &bbr->rst->rs)) { if (bbr->inflight_longterm == UINT64_MAX) { return; } @@ -925,17 +930,16 @@ static uint64_t bbr_target_inflight(ngtcp2_cc_bbr *bbr, return ngtcp2_min_uint64(bbr->bdp, cstat->cwnd); } -static int bbr_is_inflight_too_high(ngtcp2_cc_bbr *bbr) { - const ngtcp2_rs *rs = &bbr->rst->rs; +static int bbr_is_inflight_too_high(ngtcp2_cc_bbr *bbr, const ngtcp2_rs *rs) { + (void)bbr; return rs->lost * NGTCP2_BBR_LOSS_THRESH_DENOM > rs->tx_in_flight * NGTCP2_BBR_LOSS_THRESH_NUMER; } static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, + const ngtcp2_rs *rs, ngtcp2_tstamp ts) { - const ngtcp2_rs *rs = &bbr->rst->rs; - bbr->bw_probe_samples = 0; if (!rs->is_app_limited) { @@ -959,7 +963,7 @@ static void bbr_note_loss(ngtcp2_cc_bbr *bbr) { static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts) { - ngtcp2_rs *rs = &bbr->rst->rs; + ngtcp2_rs rs = {0}; bbr_note_loss(bbr); @@ -967,22 +971,21 @@ static void bbr_handle_lost_packet(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, return; } - rs->tx_in_flight = pkt->tx_in_flight; + rs.tx_in_flight = pkt->tx_in_flight; assert(bbr->rst->lost >= pkt->lost); - rs->lost = bbr->rst->lost - pkt->lost; - rs->is_app_limited = pkt->is_app_limited; + rs.lost = bbr->rst->lost - pkt->lost; + rs.is_app_limited = pkt->is_app_limited; - if (bbr_is_inflight_too_high(bbr)) { - rs->tx_in_flight = bbr_inflight_longterm_from_lost_packet(bbr, pkt); + if (bbr_is_inflight_too_high(bbr, &rs)) { + rs.tx_in_flight = bbr_inflight_at_loss(bbr, pkt, &rs); - bbr_handle_inflight_too_high(bbr, cstat, ts); + bbr_handle_inflight_too_high(bbr, cstat, &rs, ts); } } -static uint64_t -bbr_inflight_longterm_from_lost_packet(ngtcp2_cc_bbr *bbr, - const ngtcp2_cc_pkt *pkt) { - ngtcp2_rs *rs = &bbr->rst->rs; +static uint64_t bbr_inflight_at_loss(ngtcp2_cc_bbr *bbr, + const ngtcp2_cc_pkt *pkt, + const ngtcp2_rs *rs) { uint64_t inflight_prev, lost_prev, lost_prefix; (void)bbr; @@ -1025,8 +1028,8 @@ static void bbr_update_min_rtt(ngtcp2_cc_bbr *bbr, const ngtcp2_cc_ack *ack, bbr->min_rtt = bbr->probe_rtt_min_delay; bbr->min_rtt_stamp = bbr->probe_rtt_min_stamp; - ngtcp2_log_info(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, - "bbr update min_rtt=%" PRIu64, bbr->min_rtt); + ngtcp2_log_infof(bbr->cc.log, NGTCP2_LOG_EVENT_CCA, + "bbr update min_rtt=%" PRIu64, bbr->min_rtt); } } @@ -1098,13 +1101,8 @@ static void bbr_check_probe_rtt_done(ngtcp2_cc_bbr *bbr, static void bbr_mark_connection_app_limited(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { - uint64_t app_limited = bbr->rst->delivered + cstat->bytes_in_flight; - - if (app_limited) { - bbr->rst->app_limited = app_limited; - } else { - bbr->rst->app_limited = cstat->max_tx_udp_payload_size; - } + bbr->rst->app_limited = + ngtcp2_max_uint64(bbr->rst->delivered + cstat->bytes_in_flight, 1); } static void bbr_exit_probe_rtt(ngtcp2_cc_bbr *bbr, ngtcp2_tstamp ts) { @@ -1279,28 +1277,15 @@ static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, static void bbr_handle_recovery(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack) { - if (bbr->in_loss_recovery) { - if (ack->largest_pkt_sent_ts != UINT64_MAX && - !in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { - bbr->in_loss_recovery = 0; - bbr->round_count_at_recovery = UINT64_MAX; - bbr_restore_cwnd(bbr, cstat); - } - + if (!bbr->in_loss_recovery) { return; } - if (bbr->congestion_recovery_start_ts != UINT64_MAX) { - bbr->in_loss_recovery = 1; - bbr->round_count_at_recovery = - bbr->round_start ? bbr->round_count : bbr->round_count + 1; - bbr_save_cwnd(bbr, cstat); - cstat->cwnd = - cstat->bytes_in_flight + - ngtcp2_max_uint64(ack->bytes_delivered, cstat->max_tx_udp_payload_size); - - cstat->congestion_recovery_start_ts = bbr->congestion_recovery_start_ts; - bbr->congestion_recovery_start_ts = UINT64_MAX; + if (ack->largest_pkt_sent_ts != UINT64_MAX && + !in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { + bbr->in_loss_recovery = 0; + bbr->round_count_at_recovery = UINT64_MAX; + bbr_restore_cwnd(bbr, cstat); } } @@ -1312,18 +1297,25 @@ static void bbr_cc_on_pkt_lost(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, } static void bbr_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp sent_ts, uint64_t bytes_lost, + ngtcp2_tstamp sent_ts, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); - (void)bytes_lost; + (void)ack; - if (bbr->in_loss_recovery || - bbr->congestion_recovery_start_ts != UINT64_MAX || - in_congestion_recovery(cstat, sent_ts)) { + if (bbr->in_loss_recovery || in_congestion_recovery(cstat, sent_ts)) { return; } - bbr->congestion_recovery_start_ts = ts; + bbr->in_loss_recovery = 1; + bbr->round_count_at_recovery = + bbr->round_start ? bbr->round_count : bbr->round_count + 1; + bbr_save_cwnd(bbr, cstat); + bbr->undo_bw_shortterm = bbr->bw_shortterm; + bbr->undo_inflight_shortterm = bbr->inflight_shortterm; + bbr->undo_inflight_longterm = bbr->inflight_longterm; + + cstat->congestion_recovery_start_ts = ts; } static void bbr_cc_on_spurious_congestion(ngtcp2_cc *cc, @@ -1332,14 +1324,19 @@ static void bbr_cc_on_spurious_congestion(ngtcp2_cc *cc, ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); (void)ts; - bbr->congestion_recovery_start_ts = UINT64_MAX; cstat->congestion_recovery_start_ts = UINT64_MAX; - if (bbr->in_loss_recovery) { - bbr->in_loss_recovery = 0; - bbr->round_count_at_recovery = UINT64_MAX; - bbr_restore_cwnd(bbr, cstat); - } + bbr->in_loss_recovery = 0; + bbr->round_count_at_recovery = UINT64_MAX; + bbr_reset_full_bw(bbr); + bbr->loss_in_round = 0; + bbr_restore_cwnd(bbr, cstat); + bbr->bw_shortterm = + ngtcp2_max_uint64(bbr->bw_shortterm, bbr->undo_bw_shortterm); + bbr->inflight_shortterm = + ngtcp2_max_uint64(bbr->inflight_shortterm, bbr->undo_inflight_shortterm); + bbr->inflight_longterm = + ngtcp2_max_uint64(bbr->inflight_longterm, bbr->undo_inflight_longterm); } static void bbr_cc_on_persistent_congestion(ngtcp2_cc *cc, @@ -1349,7 +1346,6 @@ static void bbr_cc_on_persistent_congestion(ngtcp2_cc *cc, (void)ts; cstat->congestion_recovery_start_ts = UINT64_MAX; - bbr->congestion_recovery_start_ts = UINT64_MAX; bbr->in_loss_recovery = 0; bbr->round_count_at_recovery = UINT64_MAX; @@ -1364,6 +1360,11 @@ static void bbr_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_cc_bbr *bbr = ngtcp2_struct_of(cc, ngtcp2_cc_bbr, cc); bbr_handle_recovery(bbr, cstat, ack); + + if (ack->bytes_delivered == 0) { + return; + } + bbr_update_on_ack(bbr, cstat, ack, ts); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h index 0499924f58264f..5a74921c195007 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_bbr.h @@ -106,6 +106,11 @@ typedef struct ngtcp2_cc_bbr { ngtcp2_bbr_state state; uint64_t cwnd_gain_h; + /* Backup for spurious losses */ + uint64_t undo_bw_shortterm; + uint64_t undo_inflight_shortterm; + uint64_t undo_inflight_longterm; + int loss_round_start; uint64_t loss_round_delivered; uint64_t rounds_since_bw_probe; @@ -130,7 +135,6 @@ typedef struct ngtcp2_cc_bbr { int in_loss_recovery; uint64_t round_count_at_recovery; uint64_t max_inflight; - ngtcp2_tstamp congestion_recovery_start_ts; uint64_t bdp; } ngtcp2_cc_bbr; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.c index bf4273f816a810..083a766281b299 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.c @@ -26,8 +26,12 @@ #include "ngtcp2_mem.h" void ngtcp2_buf_init(ngtcp2_buf *buf, uint8_t *begin, size_t len) { - buf->begin = buf->pos = buf->last = begin; - buf->end = begin + len; + *buf = (ngtcp2_buf){ + .begin = begin, + .end = begin + len, + .pos = begin, + .last = begin, + }; } void ngtcp2_buf_reset(ngtcp2_buf *buf) { buf->pos = buf->last = buf->begin; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c index c16953802afd2a..73dfde6904b93d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c @@ -41,6 +41,40 @@ uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) { return ngtcp2_min_uint64(10 * max_udp_payload_size, n); } +/* 1.25 is the under-utilization avoidance factor described in + https://datatracker.ietf.org/doc/html/rfc9002#section-7.7 */ +#define NGTCP2_CC_PACING_GAIN_H 125 + +static void init_pacing_rate(ngtcp2_conn_stat *cstat) { + assert(cstat->cwnd); + + cstat->pacing_interval_m = ngtcp2_max_uint64( + (NGTCP2_MILLISECONDS << 10) * 100 / NGTCP2_CC_PACING_GAIN_H / cstat->cwnd, + 1); + cstat->send_quantum = 10 * cstat->max_tx_udp_payload_size; +} + +static void set_pacing_rate(ngtcp2_conn_stat *cstat) { + size_t send_quantum = 64 * 1024; + + assert(cstat->cwnd); + + cstat->pacing_interval_m = + ((cstat->first_rtt_sample_ts == UINT64_MAX ? NGTCP2_MILLISECONDS + : cstat->smoothed_rtt) + << 10) * + 100 / NGTCP2_CC_PACING_GAIN_H / cstat->cwnd; + + cstat->pacing_interval_m = ngtcp2_max_uint64(cstat->pacing_interval_m, 1); + + send_quantum = + ngtcp2_min_size(send_quantum, (size_t)((NGTCP2_MILLISECONDS << 10) / + cstat->pacing_interval_m)); + + cstat->send_quantum = + ngtcp2_max_size(send_quantum, 10 * cstat->max_tx_udp_payload_size); +} + ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, size_t pktlen, ngtcp2_pktns_id pktns_id, ngtcp2_tstamp sent_ts, uint64_t lost, @@ -56,9 +90,14 @@ ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, return pkt; } -static void reno_cc_reset(ngtcp2_cc_reno *reno) { reno->pending_add = 0; } +static void reno_cc_reset(ngtcp2_cc_reno *reno, ngtcp2_conn_stat *cstat) { + reno->pending_add = 0; -void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log) { + init_pacing_rate(cstat); +} + +void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log, + ngtcp2_conn_stat *cstat) { *reno = (ngtcp2_cc_reno){ .cc = { @@ -70,7 +109,7 @@ void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log) { }, }; - reno_cc_reset(reno); + reno_cc_reset(reno, cstat); } static int in_congestion_recovery(const ngtcp2_conn_stat *cstat, @@ -92,9 +131,12 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, if (cstat->cwnd < cstat->ssthresh) { cstat->cwnd += pkt->pktlen; - ngtcp2_log_info(reno->cc.log, NGTCP2_LOG_EVENT_CCA, - "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64, - pkt->pkt_num, cstat->cwnd); + + set_pacing_rate(cstat); + + ngtcp2_log_infof(reno->cc.log, NGTCP2_LOG_EVENT_CCA, + "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64, + pkt->pkt_num, cstat->cwnd); return; } @@ -102,14 +144,17 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, reno->pending_add = m % cstat->cwnd; cstat->cwnd += m / cstat->cwnd; + + set_pacing_rate(cstat); } void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - uint64_t bytes_lost, ngtcp2_tstamp ts) { + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts) { ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); uint64_t min_cwnd; - (void)bytes_lost; + (void)ack; if (in_congestion_recovery(cstat, sent_ts)) { return; @@ -123,9 +168,11 @@ void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, reno->pending_add = 0; - ngtcp2_log_info(reno->cc.log, NGTCP2_LOG_EVENT_CCA, - "reduce cwnd because of packet loss cwnd=%" PRIu64, - cstat->cwnd); + set_pacing_rate(cstat); + + ngtcp2_log_infof(reno->cc.log, NGTCP2_LOG_EVENT_CCA, + "reduce cwnd because of packet loss cwnd=%" PRIu64, + cstat->cwnd); } void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc, @@ -136,15 +183,16 @@ void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc, cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->congestion_recovery_start_ts = UINT64_MAX; + + set_pacing_rate(cstat); } void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { ngtcp2_cc_reno *reno = ngtcp2_struct_of(cc, ngtcp2_cc_reno, cc); - (void)cstat; (void)ts; - reno_cc_reset(reno); + reno_cc_reset(reno, cstat); } static void cubic_vars_reset(ngtcp2_cubic_vars *v) { @@ -156,11 +204,11 @@ static void cubic_vars_reset(ngtcp2_cubic_vars *v) { v->app_limited_start_ts = UINT64_MAX; v->app_limited_duration = 0; - v->pending_bytes_delivered = 0; - v->pending_est_bytes_delivered = 0; + v->pending_bytes_acked = 0; + v->pending_est_bytes_acked = 0; } -static void cubic_cc_reset(ngtcp2_cc_cubic *cubic) { +static void cubic_cc_reset(ngtcp2_cc_cubic *cubic, ngtcp2_conn_stat *cstat) { cubic_vars_reset(&cubic->current); cubic_vars_reset(&cubic->undo.v); cubic->undo.cwnd = 0; @@ -174,10 +222,12 @@ static void cubic_cc_reset(ngtcp2_cc_cubic *cubic) { cubic->hs.css_round = 0; cubic->next_round_delivered = 0; + + init_pacing_rate(cstat); } void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cubic, ngtcp2_log *log, - ngtcp2_rst *rst) { + ngtcp2_conn_stat *cstat, ngtcp2_rst *rst) { *cubic = (ngtcp2_cc_cubic){ .cc = { @@ -191,7 +241,7 @@ void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cubic, ngtcp2_log *log, .rst = rst, }; - cubic_cc_reset(cubic); + cubic_cc_reset(cubic, cstat); } uint64_t ngtcp2_cbrt(uint64_t n) { @@ -211,7 +261,6 @@ uint64_t ngtcp2_cbrt(uint64_t n) { y <<= 1; b = 3 * y * (y + 1) + 1; if (n >= b) { - n -= b; y++; } @@ -266,12 +315,14 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); uint64_t w_cubic, w_cubic_next; uint64_t target, m; + uint64_t bytes_acked; ngtcp2_duration rtt_thresh; int round_start; int is_app_limited = cubic->rst->rs.is_app_limited && !cubic->rst->is_cwnd_limited; - if (in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { + if (ack->bytes_delivered == 0 || + in_congestion_recovery(cstat, ack->largest_pkt_sent_ts)) { return; } @@ -291,9 +342,11 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cstat->cwnd += ack->bytes_delivered; } - ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "%" PRIu64 " bytes acked, slow start cwnd=%" PRIu64, - ack->bytes_delivered, cstat->cwnd); + set_pacing_rate(cstat); + + ngtcp2_log_infof(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, + "%" PRIu64 " bytes acked, slow start cwnd=%" PRIu64, + ack->bytes_delivered, cstat->cwnd); } if (round_start) { @@ -379,35 +432,46 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, target = w_cubic_next; } - m = ack->bytes_delivered * cstat->max_tx_udp_payload_size + - cubic->current.pending_est_bytes_delivered; - cubic->current.pending_est_bytes_delivered = m % cstat->cwnd; + bytes_acked = ack->bytes_delivered * cstat->max_tx_udp_payload_size; + m = (bytes_acked + cubic->current.pending_est_bytes_acked) / cstat->cwnd; + + cubic->current.pending_est_bytes_acked += bytes_acked; + cubic->current.pending_est_bytes_acked -= m * cstat->cwnd; + + assert(cubic->current.pending_est_bytes_acked < cstat->cwnd); if (cubic->current.w_est < cubic->current.cwnd_prior) { - cubic->current.w_est += m * 9 / 17 / cstat->cwnd; + cubic->current.w_est += m * 9 / 17; } else { - cubic->current.w_est += m / cstat->cwnd; + cubic->current.w_est += m; } if (cubic->current.w_est > w_cubic) { cstat->cwnd = cubic->current.w_est; } else { - m = (target - cstat->cwnd) * cstat->max_tx_udp_payload_size + - cubic->current.pending_bytes_delivered; - cubic->current.pending_bytes_delivered = m % cstat->cwnd; - cstat->cwnd += m / cstat->cwnd; + bytes_acked = (target - cstat->cwnd) * cstat->max_tx_udp_payload_size; + m = (bytes_acked + cubic->current.pending_bytes_acked) / cstat->cwnd; + + cubic->current.pending_bytes_acked += bytes_acked; + cubic->current.pending_bytes_acked -= m * cstat->cwnd; + + assert(cubic->current.pending_bytes_acked < cstat->cwnd); + + cstat->cwnd += m; } - ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "%" PRIu64 " bytes acked, cubic-ca cwnd=%" PRIu64 - " k_m=%" PRIu64 " target=%" PRIu64 " w_est=%" PRIu64, - ack->bytes_delivered, cstat->cwnd, cubic->current.k_m, target, - cubic->current.w_est); + set_pacing_rate(cstat); + + ngtcp2_log_infof(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, + "%" PRIu64 " bytes acked, cubic-ca cwnd=%" PRIu64 + " k_m=%" PRIu64 " target=%" PRIu64 " w_est=%" PRIu64, + ack->bytes_delivered, cstat->cwnd, cubic->current.k_m, + target, cubic->current.w_est); } void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - uint64_t bytes_lost, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts) { ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); uint64_t flight_size; @@ -428,8 +492,8 @@ void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cubic->current.epoch_start = ts; cubic->current.app_limited_start_ts = UINT64_MAX; cubic->current.app_limited_duration = 0; - cubic->current.pending_bytes_delivered = 0; - cubic->current.pending_est_bytes_delivered = 0; + cubic->current.pending_bytes_acked = 0; + cubic->current.pending_est_bytes_acked = 0; if (cstat->cwnd < cubic->current.w_max) { cubic->current.w_max = cstat->cwnd * 17 / 20; @@ -443,7 +507,7 @@ void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cstat->ssthresh = cstat->cwnd * 7 / 10; if (cubic->rst->rs.delivered * 2 < cstat->cwnd) { - flight_size = cstat->bytes_in_flight + bytes_lost; + flight_size = cstat->bytes_in_flight + ack->bytes_lost; cstat->ssthresh = ngtcp2_min_uint64( cstat->ssthresh, ngtcp2_max_uint64(cubic->rst->rs.delivered, flight_size)); @@ -464,9 +528,11 @@ void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, cubic->current.k_m = ngtcp2_cbrt((cwnd_delta << 30) * 10 / 4 / cstat->max_tx_udp_payload_size); - ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "reduce cwnd because of packet loss cwnd=%" PRIu64, - cstat->cwnd); + set_pacing_rate(cstat); + + ngtcp2_log_infof(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, + "reduce cwnd because of packet loss cwnd=%" PRIu64, + cstat->cwnd); } void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *cc, @@ -482,10 +548,12 @@ void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *cc, cstat->cwnd = cubic->undo.cwnd; cstat->ssthresh = cubic->undo.ssthresh; - ngtcp2_log_info(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, - "spurious congestion is detected and congestion state is " - "restored cwnd=%" PRIu64, - cstat->cwnd); + set_pacing_rate(cstat); + + ngtcp2_log_infof(cubic->cc.log, NGTCP2_LOG_EVENT_CCA, + "spurious congestion is detected and congestion state is " + "restored cwnd=%" PRIu64, + cstat->cwnd); } cubic_vars_reset(&cubic->undo.v); @@ -499,17 +567,18 @@ void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc, ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); (void)ts; - cubic_cc_reset(cubic); + cubic_cc_reset(cubic, cstat); cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; cstat->congestion_recovery_start_ts = UINT64_MAX; + + set_pacing_rate(cstat); } void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { ngtcp2_cc_cubic *cubic = ngtcp2_struct_of(cc, ngtcp2_cc_cubic, cc); - (void)cstat; (void)ts; - cubic_cc_reset(cubic); + cubic_cc_reset(cubic, cstat); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h index e4e19e1aa6b945..a19e90b1d0db47 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.h @@ -88,11 +88,6 @@ typedef struct ngtcp2_cc_pkt { * acknowledged and lost bytes. */ typedef struct ngtcp2_cc_ack { - /** - * :member:`prior_bytes_in_flight` is the in-flight bytes before - * processing this ACK. - */ - uint64_t prior_bytes_in_flight; /** * :member:`bytes_delivered` is the number of bytes acknowledged. */ @@ -143,13 +138,16 @@ typedef void (*ngtcp2_cc_on_pkt_lost)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, * @functypedef * * :type:`ngtcp2_cc_congestion_event` is a callback function which is - * called when congestion event happens (e.g., when packet is lost). - * |bytes_lost| is the number of bytes lost in this congestion event. + * called when congestion event happens (e.g., when packet is lost or + * due to ECN). |ack| contains information after ACK processing. + * This callback may be called from non-ACK processing context. In + * that case, the information only taken from |ack| processing has + * default values, like 0 or UINT64_MAX; */ typedef void (*ngtcp2_cc_congestion_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - uint64_t bytes_lost, + const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); /** @@ -186,20 +184,12 @@ typedef void (*ngtcp2_cc_on_ack_recv)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, * @functypedef * * :type:`ngtcp2_cc_on_pkt_sent` is a callback function which is - * called when an ack-eliciting packet is sent. + * called when an ack-eliciting packet is sent. The lost, + * tx_in_flight, and is_app_limited fields in |pkt| are set to 0. */ typedef void (*ngtcp2_cc_on_pkt_sent)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt); -/** - * @functypedef - * - * :type:`ngtcp2_cc_new_rtt_sample` is a callback function which is - * called when new RTT sample is obtained. - */ -typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_tstamp ts); - /** * @functypedef * @@ -209,28 +199,6 @@ typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, typedef void (*ngtcp2_cc_reset)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); -/** - * @enum - * - * :type:`ngtcp2_cc_event_type` defines congestion control events. - */ -typedef enum ngtcp2_cc_event_type { - /** - * :enum:`NGTCP2_CC_EVENT_TX_START` occurs when ack-eliciting packet - * is sent and no other ack-eliciting packet is present. - */ - NGTCP2_CC_EVENT_TYPE_TX_START -} ngtcp2_cc_event_type; - -/** - * @functypedef - * - * :type:`ngtcp2_cc_event` is a callback function which is called when - * a specific event happens. - */ -typedef void (*ngtcp2_cc_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, - ngtcp2_cc_event_type event, ngtcp2_tstamp ts); - /** * @struct * @@ -254,7 +222,7 @@ typedef struct ngtcp2_cc { ngtcp2_cc_on_pkt_lost on_pkt_lost; /** * :member:`congestion_event` is a callback function which is called - * when congestion event happens (.e.g, packet is lost). + * when congestion event happens (e.g., packet is lost). */ ngtcp2_cc_congestion_event congestion_event; /** @@ -277,21 +245,11 @@ typedef struct ngtcp2_cc { * ack-eliciting packet is sent. */ ngtcp2_cc_on_pkt_sent on_pkt_sent; - /** - * :member:`new_rtt_sample` is a callback function which is called - * when new RTT sample is obtained. - */ - ngtcp2_cc_new_rtt_sample new_rtt_sample; /** * :member:`reset` is a callback function which is called when * congestion control state must be reset. */ ngtcp2_cc_reset reset; - /** - * :member:`event` is a callback function which is called when a - * specific event happens. - */ - ngtcp2_cc_event event; } ngtcp2_cc; /* @@ -310,14 +268,16 @@ typedef struct ngtcp2_cc_reno { uint64_t pending_add; } ngtcp2_cc_reno; -void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log); +void ngtcp2_cc_reno_init(ngtcp2_cc_reno *reno, ngtcp2_log *log, + ngtcp2_conn_stat *cstat); void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts); void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - uint64_t bytes_lost, ngtcp2_tstamp ts); + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts); void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, @@ -340,8 +300,8 @@ typedef struct ngtcp2_cubic_vars { /* app_limited_duration is the cumulative duration where a connection is under app limited when ACK is received. */ ngtcp2_duration app_limited_duration; - uint64_t pending_bytes_delivered; - uint64_t pending_est_bytes_delivered; + uint64_t pending_bytes_acked; + uint64_t pending_est_bytes_acked; } ngtcp2_cubic_vars; /* ngtcp2_cc_cubic is CUBIC congestion controller. */ @@ -371,14 +331,15 @@ typedef struct ngtcp2_cc_cubic { } ngtcp2_cc_cubic; void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cc, ngtcp2_log *log, - ngtcp2_rst *rst); + ngtcp2_conn_stat *cstat, ngtcp2_rst *rst); void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_cc_ack *ack, ngtcp2_tstamp ts); void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, ngtcp2_tstamp sent_ts, - uint64_t bytes_lost, ngtcp2_tstamp ts); + const ngtcp2_cc_ack *ack, + ngtcp2_tstamp ts); void ngtcp2_cc_cubic_cc_on_spurious_congestion(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c index acbee78aaf435f..42a4827664912f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cid.c @@ -58,11 +58,13 @@ int ngtcp2_cid_less(const ngtcp2_cid *lhs, const ngtcp2_cid *rhs) { int ngtcp2_cid_empty(const ngtcp2_cid *cid) { return cid->datalen == 0; } void ngtcp2_scid_init(ngtcp2_scid *scid, uint64_t seq, const ngtcp2_cid *cid) { - scid->pe.index = NGTCP2_PQ_BAD_INDEX; - scid->seq = seq; - scid->cid = *cid; - scid->retired_ts = UINT64_MAX; - scid->flags = NGTCP2_SCID_FLAG_NONE; + *scid = (ngtcp2_scid){ + .pe.index = NGTCP2_PQ_BAD_INDEX, + .seq = seq, + .cid = *cid, + .retired_ts = UINT64_MAX, + .flags = NGTCP2_SCID_FLAG_NONE, + }; } void ngtcp2_scid_copy(ngtcp2_scid *dest, const ngtcp2_scid *src) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c index d97ba6a71b2529..fdf9516c3e9345 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -42,6 +42,7 @@ #include "ngtcp2_callbacks.h" #include "ngtcp2_tstamp.h" #include "ngtcp2_frame_chain.h" +#include "ngtcp2_conn_info.h" /* NGTCP2_FLOW_WINDOW_RTT_FACTOR is the factor of RTT when flow control window auto-tuning is triggered. */ @@ -696,8 +697,10 @@ static int conn_call_recv_tx_key(ngtcp2_conn *conn, return 0; } -// pktns_init initializes |pktns|. It assumes that the object pointed -// by |pktns| is zero-cleared. +/* + * pktns_init initializes |pktns|. It assumes that the object pointed + * by |pktns| is zero-cleared. + */ static void pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num, ngtcp2_log *log, ngtcp2_qlog *qlog, @@ -1084,8 +1087,8 @@ static void conn_update_skip_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns) { pktns->tx.skip_pkt.next_pkt_num = pktns->tx.last_pkt_num + gap; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "next skip pkn=%" PRId64, - pktns->tx.skip_pkt.next_pkt_num); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, "next skip pkn=%" PRId64, + pktns->tx.skip_pkt.next_pkt_num); } static int conn_handle_skip_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns, @@ -1165,8 +1168,8 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, assert(settings->max_window <= NGTCP2_MAX_VARINT); assert(settings->max_stream_window <= NGTCP2_MAX_VARINT); - assert(settings->max_tx_udp_payload_size); - assert(settings->max_tx_udp_payload_size <= NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE); + assert(settings->max_tx_udp_payload_size >= NGTCP2_MAX_UDP_PAYLOAD_SIZE); + assert(settings->max_tx_udp_payload_size <= NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE); assert(settings->initial_pkt_num <= INT32_MAX); assert(settings->initial_rtt); assert(params->active_connection_id_limit >= @@ -1202,6 +1205,7 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, for (i = 0; i < settings->pmtud_probeslen; ++i) { assert(settings->pmtud_probes[i] > NGTCP2_MAX_UDP_PAYLOAD_SIZE); + assert(settings->pmtud_probes[i] <= NGTCP2_MAX_TX_UDP_PAYLOAD_SIZE); } if (mem == NULL) { @@ -1334,11 +1338,12 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, switch (settings->cc_algo) { case NGTCP2_CC_ALGO_RENO: - ngtcp2_cc_reno_init(&(*pconn)->reno, &(*pconn)->log); + ngtcp2_cc_reno_init(&(*pconn)->reno, &(*pconn)->log, &(*pconn)->cstat); break; case NGTCP2_CC_ALGO_CUBIC: - ngtcp2_cc_cubic_init(&(*pconn)->cubic, &(*pconn)->log, &(*pconn)->rst); + ngtcp2_cc_cubic_init(&(*pconn)->cubic, &(*pconn)->log, &(*pconn)->cstat, + &(*pconn)->rst); break; case NGTCP2_CC_ALGO_BBR: @@ -1522,6 +1527,8 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, fail_token: ngtcp2_mem_free(mem, *pconn); + *pconn = NULL; + return rv; } @@ -1549,6 +1556,8 @@ int ngtcp2_conn_client_new_versioned( rv = ngtcp2_conn_commit_local_transport_params(*pconn); if (rv != 0) { ngtcp2_conn_del(*pconn); + *pconn = NULL; + return rv; } @@ -1806,8 +1815,18 @@ static int conn_ppe_write_frame(ngtcp2_conn *conn, ngtcp2_ppe *ppe, static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_rtb_entry *ent) { ngtcp2_rtb *rtb = &pktns->rtb; + ngtcp2_cc_pkt cc_pkt; int rv; + if ((ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) && + conn->cc.on_pkt_sent) { + conn->cc.on_pkt_sent( + &conn->cc, &conn->cstat, + ngtcp2_cc_pkt_init(&cc_pkt, ent->hd.pkt_num, ent->pktlen, pktns->id, + ent->ts, /* lost = */ 0, + /* tx_in_flight = */ 0, /* is_app_limited = */ 0)); + } + /* This function implements OnPacketSent, but it handles only non-ACK-only packet. */ rv = ngtcp2_rtb_add(rtb, ent, &conn->cstat); @@ -1862,9 +1881,9 @@ static int conn_cwnd_is_zero(ngtcp2_conn *conn) { uint64_t cwnd = conn->cstat.cwnd; if (bytes_in_flight >= cwnd) { - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, - "cwnd limited bytes_in_flight=%lu cwnd=%lu", - bytes_in_flight, cwnd); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_LDC, + "cwnd limited bytes_in_flight=%lu cwnd=%lu", + bytes_in_flight, cwnd); } return bytes_in_flight >= cwnd; @@ -2012,6 +2031,12 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, return 1; } + /* We might send Handshake packet even if exceeding CWND. In that + case, we do not write non-probe 1RTT packet. */ + if (conn_cwnd_is_zero(conn) && conn->pktns.rtb.probe_pkt_left == 0) { + return 1; + } + min_payloadlen = NGTCP2_MIN_COALESCED_PAYLOADLEN; } @@ -2192,6 +2217,9 @@ static int conn_cut_crypto_frame(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc, /* ngtcp2_frame_chain for the removed data */ removed_frc->fr.stream.type = NGTCP2_FRAME_CRYPTO; + removed_frc->fr.stream.flags = 0; + removed_frc->fr.stream.fin = 0; + removed_frc->fr.stream.stream_id = 0; removed_frc->fr.stream.offset = (*pfrc)->fr.stream.offset + offset; removed_frc->fr.stream.datacnt = 1; removed_frc->fr.stream.data[0] = (ngtcp2_vec){ @@ -2247,6 +2275,9 @@ static int conn_cut_crypto_frame(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc, } left_frc->fr.stream.type = NGTCP2_FRAME_CRYPTO; + left_frc->fr.stream.flags = 0; + left_frc->fr.stream.fin = 0; + left_frc->fr.stream.stream_id = 0; left_frc->fr.stream.offset = (*pfrc)->fr.stream.offset; left_frc->fr.stream.datacnt = 1; left_frc->fr.stream.data[0] = (ngtcp2_vec){ @@ -2372,6 +2403,15 @@ conn_crumble_initial_crypto(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc, return (ngtcp2_ssize)datacnt; } +static size_t conn_dgram_padding(ngtcp2_conn *conn, ngtcp2_ppe *ppe) { + if (conn->local.settings.no_tx_udp_payload_size_shaping) { + return ngtcp2_ppe_dgram_padding_size( + ppe, conn->local.settings.max_tx_udp_payload_size); + } + + return ngtcp2_ppe_dgram_padding(ppe); +} + static size_t conn_min_pktlen(ngtcp2_conn *conn); /* @@ -2402,8 +2442,8 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, ngtcp2_pkt_hd hd; ngtcp2_frame_chain *frq = NULL, **pfrc = &frq; ngtcp2_frame_chain *nfrc; - ngtcp2_max_frame mfr; - ngtcp2_frame *ackfr = NULL, lfr; + ngtcp2_ack_range ack_ranges[NGTCP2_MAX_ACK_RANGES]; + ngtcp2_frame lfr; ngtcp2_ssize spktlen; ngtcp2_crypto_cc cc; ngtcp2_rtb_entry *rtbent; @@ -2478,16 +2518,16 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, return 0; } - ackfr = ngtcp2_acktr_create_ack_frame(&pktns->acktr, &mfr.fr, type, ts, - /* ack_delay = */ 0, - NGTCP2_DEFAULT_ACK_DELAY_EXPONENT); - if (ackfr) { - rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, ackfr); + lfr.ack.ranges = ack_ranges; + if (ngtcp2_acktr_create_ack_frame(&pktns->acktr, &lfr.ack, type, ts, + /* ack_delay = */ 0, + NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) == 0) { + rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &lfr); if (rv != 0) { assert(NGTCP2_ERR_NOBUF == rv); } else { ngtcp2_acktr_commit_ack(&pktns->acktr); - ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, ackfr->ack.largest_ack); + ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, lfr.ack.largest_ack); pkt_empty = 0; } } @@ -2545,7 +2585,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, .type = NGTCP2_FRAME_CRYPTO, .offset = offsets[i], .datacnt = 1, - .data[0] = data[i], + .data = &data[i], }; } @@ -2622,7 +2662,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, if (!(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) && pktns->rtb.probe_pkt_left) { - lfr.type = NGTCP2_FRAME_PING; + lfr.ping.type = NGTCP2_FRAME_PING; rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &lfr); if (rv != 0) { @@ -2638,7 +2678,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, if (!(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { if (ngtcp2_tstamp_elapsed(pktns->tx.non_ack_pkt_start_ts, conn->cstat.smoothed_rtt, ts)) { - lfr.type = NGTCP2_FRAME_PING; + lfr.ping.type = NGTCP2_FRAME_PING; rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &lfr); if (rv != 0) { @@ -2667,12 +2707,12 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, conn, type, ngtcp2_ppe_left(&ppe), write_datalen, (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) != 0, require_padding)) { - lfr.type = NGTCP2_FRAME_PADDING; - lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); + lfr.padding.type = NGTCP2_FRAME_PADDING; + lfr.padding.len = conn_dgram_padding(conn, &ppe); } else if (pkt_empty) { return 0; } else { - lfr.type = NGTCP2_FRAME_PADDING; + lfr.padding.type = NGTCP2_FRAME_PADDING; lfr.padding.len = ngtcp2_ppe_padding_size(&ppe, conn_min_pktlen(conn)); min_padded = 1; } @@ -2735,6 +2775,9 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, conn->tx.pacing.pktlen += (size_t)spktlen; + ++conn->cstat.pkt_sent; + conn->cstat.bytes_sent += (uint64_t)spktlen; + ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); ++pktns->tx.last_pkt_num; @@ -2758,12 +2801,12 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, uint8_t type, ngtcp2_tstamp ts) { - ngtcp2_frame *ackfr; ngtcp2_pktns *pktns; ngtcp2_duration ack_delay; uint64_t ack_delay_exponent; ngtcp2_ssize spktlen; - ngtcp2_max_frame mfr; + ngtcp2_ack_range ack_ranges[NGTCP2_MAX_ACK_RANGES]; + ngtcp2_frame fr; assert(!(conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING)); @@ -2792,15 +2835,15 @@ static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return 0; } - ackfr = ngtcp2_acktr_create_ack_frame(&pktns->acktr, &mfr.fr, type, ts, - ack_delay, ack_delay_exponent); - if (!ackfr) { + fr.ack.ranges = ack_ranges; + if (ngtcp2_acktr_create_ack_frame(&pktns->acktr, &fr.ack, type, ts, ack_delay, + ack_delay_exponent) != 0) { return 0; } spktlen = ngtcp2_conn_write_single_frame_pkt( conn, pi, dest, destlen, type, NGTCP2_WRITE_PKT_FLAG_NONE, - &conn->dcid.current.cid, ackfr, NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); + &conn->dcid.current.cid, &fr, NGTCP2_RTB_ENTRY_FLAG_NONE, NULL, ts); if (spktlen <= 0) { return spktlen; @@ -3063,21 +3106,16 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, dest += nwrite; destlen -= (size_t)nwrite; - /* If initial packet size is at least - NGTCP2_MAX_UDP_PAYLOAD_SIZE, no extra padding is needed in a - subsequent packet. */ - if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE) { - if (conn->server) { - it = ngtcp2_rtb_head(&conn->in_pktns->rtb); - if (!ngtcp2_ksl_it_end(&it)) { - rtbent = ngtcp2_ksl_it_get(&it); - if (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { - wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; - } + if (conn->server) { + it = ngtcp2_rtb_head(&conn->in_pktns->rtb); + if (!ngtcp2_ksl_it_end(&it)) { + rtbent = ngtcp2_ksl_it_get(&it); + if (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { + wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } - } else { - wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } + } else { + wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } } } @@ -3241,7 +3279,7 @@ static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) { return rv; } - nfrc->fr.type = NGTCP2_FRAME_NEW_CONNECTION_ID; + nfrc->fr.new_connection_id.type = NGTCP2_FRAME_NEW_CONNECTION_ID; nfrc->fr.new_connection_id.seq = seq; nfrc->fr.new_connection_id.retire_prior_to = 0; nfrc->fr.new_connection_id.cid = cid; @@ -3415,8 +3453,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, ngtcp2_crypto_cc *cc = &conn->pkt.cc; ngtcp2_ppe *ppe = &conn->pkt.ppe; ngtcp2_pkt_hd *hd = &conn->pkt.hd; - ngtcp2_max_frame mfr; - ngtcp2_frame *ackfr = NULL, lfr; + ngtcp2_ack_range ack_ranges[NGTCP2_MAX_ACK_RANGES]; + ngtcp2_frame lfr; ngtcp2_ssize nwrite; ngtcp2_frame_chain **pfrc, *nfrc, *frc; ngtcp2_rtb_entry *ent; @@ -3442,11 +3480,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, size_t min_pktlen = conn_min_pktlen(conn); int min_padded = 0; int padded = 0; - ngtcp2_cc_pkt cc_pkt; uint64_t crypto_offset; uint64_t stream_offset; ngtcp2_ssize num_reclaimed; - int fin; uint64_t target_max_data; ngtcp2_conn_stat *cstat = &conn->cstat; uint64_t delta; @@ -3559,8 +3595,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, conn->tx.last_max_data_ts = ts; - nfrc->fr.type = NGTCP2_FRAME_MAX_DATA; - nfrc->fr.max_data.max_data = conn->rx.unsent_max_offset + delta; + nfrc->fr.max_data = (ngtcp2_max_data){ + .type = NGTCP2_FRAME_MAX_DATA, + .max_data = conn->rx.unsent_max_offset + delta, + }; nfrc->next = pktns->tx.frq; pktns->tx.frq = nfrc; @@ -3595,7 +3633,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, /* PATH_RESPONSE is bound to the path that the corresponding PATH_CHALLENGE is received. */ if (ngtcp2_path_eq(&conn->dcid.current.ps.path, &pcent->ps.path)) { - lfr.type = NGTCP2_FRAME_PATH_RESPONSE; + lfr.path_response.type = NGTCP2_FRAME_PATH_RESPONSE; memcpy(lfr.path_response.data, pcent->data, sizeof(lfr.path_response.data)); @@ -3616,7 +3654,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, An endpoint that receives a PATH_CHALLENGE on an active path SHOULD send a non-probing packet in response. */ - lfr.type = NGTCP2_FRAME_PING; + lfr.ping.type = NGTCP2_FRAME_PING; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr); if (rv != 0) { assert(NGTCP2_ERR_NOBUF == rv); @@ -3625,20 +3663,19 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } } - ackfr = ngtcp2_acktr_create_ack_frame( - &pktns->acktr, &mfr.fr, type, ts, conn_compute_ack_delay(conn), - conn->local.transport_params.ack_delay_exponent); - if (ackfr) { - rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, ackfr); + lfr.ack.ranges = ack_ranges; + if (ngtcp2_acktr_create_ack_frame( + &pktns->acktr, &lfr.ack, type, ts, conn_compute_ack_delay(conn), + conn->local.transport_params.ack_delay_exponent) == 0) { + rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr); if (rv != 0) { assert(NGTCP2_ERR_NOBUF == rv); } else { ngtcp2_acktr_commit_ack(&pktns->acktr); - ngtcp2_acktr_add_ack(&pktns->acktr, hd->pkt_num, - ackfr->ack.largest_ack); + ngtcp2_acktr_add_ack(&pktns->acktr, hd->pkt_num, lfr.ack.largest_ack); assert(NGTCP2_PKT_1RTT == type); - conn_handle_unconfirmed_key_update_from_remote( - conn, ackfr->ack.largest_ack, ts); + conn_handle_unconfirmed_key_update_from_remote(conn, + lfr.ack.largest_ack, ts); pkt_empty = 0; } } @@ -3653,7 +3690,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, continue; } - switch ((*pfrc)->fr.type) { + switch ((*pfrc)->fr.hd.type) { case NGTCP2_FRAME_RESET_STREAM: strm = ngtcp2_conn_find_stream(conn, (*pfrc)->fr.reset_stream.stream_id); @@ -3803,11 +3840,12 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_RESET_STREAM; - nfrc->fr.reset_stream.stream_id = strm->stream_id; - nfrc->fr.reset_stream.app_error_code = - strm->tx.reset_stream_app_error_code; - nfrc->fr.reset_stream.final_size = strm->tx.offset; + nfrc->fr.reset_stream = (ngtcp2_reset_stream){ + .type = NGTCP2_FRAME_RESET_STREAM, + .stream_id = strm->stream_id, + .app_error_code = strm->tx.reset_stream_app_error_code, + .final_size = strm->tx.offset, + }; *pfrc = nfrc; strm->flags &= ~NGTCP2_STRM_FLAG_SEND_RESET_STREAM; @@ -3846,10 +3884,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_STOP_SENDING; - nfrc->fr.stop_sending.stream_id = strm->stream_id; - nfrc->fr.stop_sending.app_error_code = - strm->tx.stop_sending_app_error_code; + nfrc->fr.stop_sending = (ngtcp2_stop_sending){ + .type = NGTCP2_FRAME_STOP_SENDING, + .stream_id = strm->stream_id, + .app_error_code = strm->tx.stop_sending_app_error_code, + }; *pfrc = nfrc; strm->flags &= ~NGTCP2_STRM_FLAG_SEND_STOP_SENDING; @@ -3877,9 +3916,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED; - nfrc->fr.stream_data_blocked.stream_id = strm->stream_id; - nfrc->fr.stream_data_blocked.offset = strm->tx.max_offset; + nfrc->fr.stream_data_blocked = (ngtcp2_stream_data_blocked){ + .type = NGTCP2_FRAME_STREAM_DATA_BLOCKED, + .stream_id = strm->stream_id, + .offset = strm->tx.max_offset, + }; *pfrc = nfrc; strm->tx.last_blocked_offset = strm->tx.max_offset; @@ -3931,10 +3972,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, strm->tx.last_max_stream_data_ts = ts; - nfrc->fr.type = NGTCP2_FRAME_MAX_STREAM_DATA; - nfrc->fr.max_stream_data.stream_id = strm->stream_id; - nfrc->fr.max_stream_data.max_stream_data = - strm->rx.unsent_max_offset + delta; + nfrc->fr.max_stream_data = (ngtcp2_max_stream_data){ + .type = NGTCP2_FRAME_MAX_STREAM_DATA, + .stream_id = strm->stream_id, + .max_stream_data = strm->rx.unsent_max_offset + delta, + }; *pfrc = nfrc; strm->rx.max_offset = strm->rx.unsent_max_offset = @@ -4030,8 +4072,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, assert(ngtcp2_err_is_fatal(rv)); return rv; } - nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_BIDI; - nfrc->fr.max_streams.max_streams = conn->remote.bidi.unsent_max_streams; + nfrc->fr.max_streams = (ngtcp2_max_streams){ + .type = NGTCP2_FRAME_MAX_STREAMS_BIDI, + .max_streams = conn->remote.bidi.unsent_max_streams, + }; *pfrc = nfrc; conn->remote.bidi.max_streams = conn->remote.bidi.unsent_max_streams; @@ -4062,8 +4106,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, assert(ngtcp2_err_is_fatal(rv)); return rv; } - nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_UNI; - nfrc->fr.max_streams.max_streams = conn->remote.uni.unsent_max_streams; + nfrc->fr.max_streams = (ngtcp2_max_streams){ + .type = NGTCP2_FRAME_MAX_STREAMS_UNI, + .max_streams = conn->remote.uni.unsent_max_streams, + }; *pfrc = nfrc; conn->remote.uni.max_streams = conn->remote.uni.unsent_max_streams; @@ -4136,14 +4182,14 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, nfrc->fr.stream.type = NGTCP2_FRAME_STREAM; nfrc->fr.stream.flags = 0; + nfrc->fr.stream.fin = 0; nfrc->fr.stream.stream_id = vmsg->stream.strm->stream_id; nfrc->fr.stream.offset = vmsg->stream.strm->tx.offset; nfrc->fr.stream.datacnt = datacnt; ngtcp2_vec_copy(nfrc->fr.stream.data, data, datacnt); - fin = (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_FIN) && - ndatalen == datalen; - nfrc->fr.stream.fin = (uint8_t)fin; + nfrc->fr.stream.fin = (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_FIN) && + ndatalen == datalen; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { @@ -4162,7 +4208,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, conn->tx.offset += ndatalen; vmsg->stream.strm->flags |= NGTCP2_STRM_FLAG_ANY_SENT; - if (fin) { + if (nfrc->fr.stream.fin) { ngtcp2_strm_shutdown(vmsg->stream.strm, NGTCP2_STRM_FLAG_SHUT_WR); } @@ -4185,8 +4231,10 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_DATA_BLOCKED; - nfrc->fr.data_blocked.offset = conn->tx.offset; + nfrc->fr.data_blocked = (ngtcp2_data_blocked){ + .type = NGTCP2_FRAME_DATA_BLOCKED, + .offset = conn->tx.offset, + }; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { @@ -4217,9 +4265,11 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - nfrc->fr.type = NGTCP2_FRAME_STREAM_DATA_BLOCKED; - nfrc->fr.stream_data_blocked.stream_id = strm->stream_id; - nfrc->fr.stream_data_blocked.offset = strm->tx.max_offset; + nfrc->fr.stream_data_blocked = (ngtcp2_stream_data_blocked){ + .type = NGTCP2_FRAME_STREAM_DATA_BLOCKED, + .stream_id = strm->stream_id, + .offset = strm->tx.max_offset, + }; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); if (rv != 0) { @@ -4362,7 +4412,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (ngtcp2_tstamp_elapsed(pktns->tx.non_ack_pkt_start_ts, cstat->smoothed_rtt, ts) || keep_alive_expired || conn->pktns.rtb.probe_pkt_left) { - lfr.type = NGTCP2_FRAME_PING; + lfr.ping.type = NGTCP2_FRAME_PING; rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr); if (rv != 0) { @@ -4377,7 +4427,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING; } pktns->tx.non_ack_pkt_start_ts = UINT64_MAX; - pkt_empty = 0; } } else if (pktns->tx.non_ack_pkt_start_ts == UINT64_MAX) { pktns->tx.non_ack_pkt_start_ts = ts; @@ -4392,7 +4441,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { lfr.padding.len = ngtcp2_ppe_padding_size(ppe, destlen); } else if (require_padding) { - lfr.padding.len = ngtcp2_ppe_dgram_padding(ppe); + lfr.padding.len = conn_dgram_padding(conn, ppe); } else { lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen); min_padded = 1; @@ -4403,7 +4452,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { padded = 1; } - lfr.type = NGTCP2_FRAME_PADDING; + lfr.padding.type = NGTCP2_FRAME_PADDING; ngtcp2_log_tx_fr(&conn->log, hd, &lfr); ngtcp2_qlog_write_frame(&conn->qlog, &lfr); } @@ -4439,12 +4488,6 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, *pfrc = NULL; } - if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) && - pktns->rtb.num_ack_eliciting == 0 && conn->cc.event) { - conn->cc.event(&conn->cc, &conn->cstat, NGTCP2_CC_EVENT_TYPE_TX_START, - ts); - } - rv = conn_on_pkt_sent(conn, pktns, ent); if (rv != 0) { assert(ngtcp2_err_is_fatal(rv)); @@ -4453,18 +4496,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, return rv; } - if (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { - if (conn->cc.on_pkt_sent) { - conn->cc.on_pkt_sent( - &conn->cc, &conn->cstat, - ngtcp2_cc_pkt_init(&cc_pkt, hd->pkt_num, (size_t)nwrite, - NGTCP2_PKTNS_ID_APPLICATION, ts, ent->rst.lost, - ent->rst.tx_in_flight, ent->rst.is_app_limited)); - } - - if (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE) { - conn_restart_timer_on_write(conn, ts); - } + if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) && + (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE)) { + conn_restart_timer_on_write(conn, ts); } } else if (pi && conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) { conn_handle_tx_ecn(conn, pi, NULL, pktns, hd, ts); @@ -4476,8 +4510,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { --pktns->rtb.probe_pkt_left; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "probe pkt size=%td", - nwrite); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, "probe pkt size=%td", + nwrite); } conn_update_keep_alive_last_ts(conn, ts); @@ -4486,6 +4520,9 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, conn->tx.pacing.pktlen += (size_t)nwrite; + ++conn->cstat.pkt_sent; + conn->cstat.bytes_sent += (uint64_t)nwrite; + ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); ++pktns->tx.last_pkt_num; @@ -4584,17 +4621,17 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( return 0; } - lfr.type = NGTCP2_FRAME_PADDING; + lfr.padding.type = NGTCP2_FRAME_PADDING; if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL) { lfr.padding.len = ngtcp2_ppe_dgram_padding_size(&ppe, destlen); } else if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) { - lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); + lfr.padding.len = conn_dgram_padding(conn, &ppe); } else { - switch (fr->type) { + switch (fr->hd.type) { case NGTCP2_FRAME_PATH_CHALLENGE: case NGTCP2_FRAME_PATH_RESPONSE: if (!conn->server || destlen >= NGTCP2_MAX_UDP_PAYLOAD_SIZE) { - lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); + lfr.padding.len = conn_dgram_padding(conn, &ppe); } else { lfr.padding.len = 0; } @@ -4621,7 +4658,7 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( ngtcp2_qlog_pkt_sent_end(&conn->qlog, &hd, (size_t)nwrite); /* Do this when we are sure that there is no error. */ - switch (fr->type) { + switch (fr->hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: ngtcp2_acktr_commit_ack(&pktns->acktr); @@ -4636,6 +4673,13 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( padded = 0; } + break; + case NGTCP2_FRAME_CONNECTION_CLOSE: + case NGTCP2_FRAME_CONNECTION_CLOSE_APP: + /* Clear padded so that we never store the terminal packet in + ngtcp2_rtb. */ + padded = 0; + break; } @@ -4669,8 +4713,8 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { --pktns->rtb.probe_pkt_left; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "probe pkt size=%td", - nwrite); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, "probe pkt size=%td", + nwrite); } } } else if (pi && conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) { @@ -4682,7 +4726,7 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( } if (!padded) { - switch (fr->type) { + switch (fr->hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: break; @@ -4693,6 +4737,9 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( conn->tx.pacing.pktlen += (size_t)nwrite; } + ++conn->cstat.pkt_sent; + conn->cstat.bytes_sent += (uint64_t)nwrite; + ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); ++pktns->tx.last_pkt_num; @@ -4759,8 +4806,10 @@ static int conn_enqueue_retire_connection_id(ngtcp2_conn *conn, uint64_t seq) { return rv; } - nfrc->fr.type = NGTCP2_FRAME_RETIRE_CONNECTION_ID; - nfrc->fr.retire_connection_id.seq = seq; + nfrc->fr.retire_connection_id = (ngtcp2_retire_connection_id){ + .type = NGTCP2_FRAME_RETIRE_CONNECTION_ID, + .seq = seq, + }; nfrc->next = pktns->tx.frq; pktns->tx.frq = nfrc; @@ -4899,10 +4948,10 @@ static ngtcp2_ssize conn_write_pmtud_probe(ngtcp2_conn *conn, return 0; } - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "sending PMTUD probe packet len=%zu", probelen); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "sending PMTUD probe packet len=%zu", probelen); - lfr.type = NGTCP2_FRAME_PING; + lfr.ping.type = NGTCP2_FRAME_PING; nwrite = ngtcp2_conn_write_single_frame_pkt( conn, pi, dest, probelen, NGTCP2_PKT_1RTT, @@ -5105,7 +5154,7 @@ static ngtcp2_ssize conn_write_path_challenge(ngtcp2_conn *conn, return rv; } - lfr.type = NGTCP2_FRAME_PATH_CHALLENGE; + lfr.path_challenge.type = NGTCP2_FRAME_PATH_CHALLENGE; initial_pto = conn_compute_initial_pto(conn, &conn->pktns); timeout = conn_compute_pto(conn, &conn->pktns); @@ -5238,7 +5287,7 @@ static ngtcp2_ssize conn_write_path_response(ngtcp2_conn *conn, } } - lfr.type = NGTCP2_FRAME_PATH_RESPONSE; + lfr.path_response.type = NGTCP2_FRAME_PATH_RESPONSE; memcpy(lfr.path_response.data, pcent->data, sizeof(lfr.path_response.data)); nwrite = ngtcp2_conn_write_single_frame_pkt( @@ -5396,11 +5445,11 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, ngtcp2_pktns *in_pktns = conn->in_pktns; ngtcp2_rtb *rtb = &conn->pktns.rtb; ngtcp2_rtb *in_rtb; - uint8_t cidbuf[sizeof(retry.odcid.data) * 2 + 1]; + char cidbuf[sizeof(retry.odcid.data) * 2 + 1]; uint8_t *token; - if (!in_pktns || conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) { - return 0; + if (!in_pktns || (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY)) { + return NGTCP2_ERR_DISCARD_PKT; } in_rtb = &in_pktns->rtb; @@ -5421,9 +5470,9 @@ static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, return rv; } - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "odcid=0x%s", - (const char *)ngtcp2_encode_hex(cidbuf, retry.odcid.data, - retry.odcid.datalen)); + ngtcp2_log_infof( + &conn->log, NGTCP2_LOG_EVENT_PKT, "odcid=0x%s", + ngtcp2_encode_hex_cstr(cidbuf, retry.odcid.data, retry.odcid.datalen)); if (retry.tokenlen == 0) { return NGTCP2_ERR_PROTO; @@ -6351,8 +6400,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_tstamp ts) { ngtcp2_ssize nread; ngtcp2_pkt_hd hd; - ngtcp2_max_frame mfr; - ngtcp2_frame *fr = &mfr.fr; + ngtcp2_frame_decoder frd; + ngtcp2_frame fr; int rv; int require_ack = 0; size_t hdpktlen; @@ -6383,8 +6432,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, return 0; } - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "buffering 1RTT packet len=%zu", pktlen); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "buffering 1RTT packet len=%zu", pktlen); rv = conn_buffer_pkt(conn, &conn->pktns, path, pi, pkt, pktlen, dgramlen, ts); @@ -6531,8 +6580,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } /* Buffer re-ordered 0-RTT packet. */ - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "buffering 0-RTT packet len=%zu", pktlen); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "buffering 0-RTT packet len=%zu", pktlen); rv = conn_buffer_pkt(conn, conn->in_pktns, path, pi, pkt, pktlen, dgramlen, ts); @@ -6554,10 +6603,10 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (conn->server) { if (dgramlen < NGTCP2_MAX_UDP_PAYLOAD_SIZE) { - ngtcp2_log_info( + ngtcp2_log_infof( &conn->log, NGTCP2_LOG_EVENT_PKT, "Initial packet was ignored because it is included in UDP datagram " - "less than %zu bytes: %zu bytes", + "less than %d bytes: %zu bytes", NGTCP2_MAX_UDP_PAYLOAD_SIZE, dgramlen); return NGTCP2_ERR_DISCARD_PKT; } @@ -6637,8 +6686,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, "Handshake packet at this point is unexpected and discarded"); return (ngtcp2_ssize)pktlen; } - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "buffering Handshake packet len=%zu", pktlen); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "buffering Handshake packet len=%zu", pktlen); rv = conn_buffer_pkt(conn, conn->hs_pktns, path, pi, pkt, pktlen, dgramlen, ts); @@ -6692,8 +6741,8 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->acktr.max_pkt_num, hd.pkt_num, hd.pkt_numlen); if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) { - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, - "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_PKT, + "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); return NGTCP2_ERR_DISCARD_PKT; } @@ -6740,9 +6789,9 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, !conn->negotiated_version) { conn->negotiated_version = hd.version; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "the negotiated version is 0x%08x", - conn->negotiated_version); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "the negotiated version is 0x%08x", + conn->negotiated_version); } payload = conn->crypto.decrypt_buf.base; @@ -6798,7 +6847,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_qlog_pkt_received_start(&conn->qlog); for (; payloadlen;) { - nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen); + nread = ngtcp2_frame_decoder_decode(&frd, &fr, payload, payloadlen); if (nread < 0) { return nread; } @@ -6806,14 +6855,14 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, payload += nread; payloadlen -= (size_t)nread; - switch (fr->type) { + switch (fr.hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: - fr->ack.ack_delay = 0; - fr->ack.ack_delay_unscaled = 0; + fr.ack.ack_delay = 0; + fr.ack.ack_delay_unscaled = 0; rv = - ngtcp2_pkt_validate_ack(&fr->ack, conn->local.settings.initial_pkt_num); + ngtcp2_pkt_validate_ack(&fr.ack, conn->local.settings.initial_pkt_num); if (rv != 0) { return rv; } @@ -6821,9 +6870,9 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; } - ngtcp2_log_rx_fr(&conn->log, &hd, fr); + ngtcp2_log_rx_fr(&conn->log, &hd, &fr); - switch (fr->type) { + switch (fr.hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: if (num_ack_processed >= NGTCP2_MAX_ACK_PER_PKT) { @@ -6832,7 +6881,7 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (!conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) { conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED; } - rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts); + rv = conn_recv_ack(conn, pktns, &fr.ack, pkt_ts, ts); if (rv != 0) { return rv; } @@ -6842,34 +6891,35 @@ conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; case NGTCP2_FRAME_CRYPTO: if (!conn->server && !conn->negotiated_version && - ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt)) { + ngtcp2_vec_len(fr.stream.data, fr.stream.datacnt)) { conn->negotiated_version = hd.version; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "the negotiated version is 0x%08x", - conn->negotiated_version); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "the negotiated version is 0x%08x", + conn->negotiated_version); } - rv = conn_recv_crypto(conn, encryption_level, crypto, &fr->stream, ts); + rv = conn_recv_crypto(conn, encryption_level, crypto, &fr.stream, ts); if (rv != 0) { return rv; } require_ack = 1; break; case NGTCP2_FRAME_CONNECTION_CLOSE: - rv = conn_recv_connection_close(conn, &fr->connection_close); + rv = conn_recv_connection_close(conn, &fr.connection_close); if (rv != 0) { return rv; } break; case NGTCP2_FRAME_PING: + ++conn->cstat.ping_recv; require_ack = 1; break; default: return NGTCP2_ERR_PROTO; } - ngtcp2_qlog_write_frame(&conn->qlog, fr); + ngtcp2_qlog_write_frame(&conn->qlog, &fr); } if (hd.type == NGTCP2_PKT_HANDSHAKE) { @@ -6956,6 +7006,8 @@ static ngtcp2_ssize conn_recv_handshake_cpkt(ngtcp2_conn *conn, return nread; } + ++conn->cstat.pkt_discarded; + /* If server discards first Initial, then drop connection state. This is because SCID in packet might be corrupted and the current connection state might wrongly discard @@ -6973,11 +7025,15 @@ static ngtcp2_ssize conn_recv_handshake_cpkt(ngtcp2_conn *conn, unrecoverable, therefore drop connection. */ return nread; } + + ++conn->cstat.pkt_discarded; + return (ngtcp2_ssize)dgramlen; } } if (nread == NGTCP2_ERR_DISCARD_PKT) { + ++conn->cstat.pkt_discarded; return (ngtcp2_ssize)dgramlen; } @@ -6993,8 +7049,11 @@ static ngtcp2_ssize conn_recv_handshake_cpkt(ngtcp2_conn *conn, pkt += nread; pktlen -= (size_t)nread; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, - "read packet %td left %zu", nread, pktlen); + ++conn->cstat.pkt_recv; + conn->cstat.bytes_recv += (uint64_t)nread; + + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_PKT, + "read packet %td left %zu", nread, pktlen); } return (ngtcp2_ssize)dgramlen; @@ -8713,7 +8772,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, ngtcp2_pv *pv = NULL; int rv; ngtcp2_duration pto; - int require_new_cid; int local_addr_eq; int pref_addr_migration; uint32_t remote_addr_cmp; @@ -8771,9 +8829,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, * continue to use the current connection ID with the new remote * address while still sending from the same local address. */ - require_new_cid = conn->dcid.current.cid.datalen && - ((new_cid_used && remote_addr_cmp) || !local_addr_eq); - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "non-probing packet was received from new remote address"); @@ -8781,8 +8836,6 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "Found DCID which has already been bound to the new path"); - require_new_cid = 0; - if (dcid.cid.datalen) { rv = conn_call_activate_dcid(conn, &dcid); if (rv != 0) { @@ -8790,7 +8843,9 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, } } } else { - if (require_new_cid) { + if (conn->dcid.current.cid.datalen && + ((new_cid_used && remote_addr_cmp) || !local_addr_eq)) { + /* New DCID is required. */ if (ngtcp2_dcidtr_unused_empty(&conn->dcid.dtr)) { return NGTCP2_ERR_CONN_ID_BLOCKED; } @@ -8955,8 +9010,8 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, const uint8_t *payload, size_t payloadlen, ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) { ngtcp2_ssize nread; - ngtcp2_max_frame mfr; - ngtcp2_frame *fr = &mfr.fr; + ngtcp2_frame_decoder frd; + ngtcp2_frame fr; int rv; int require_ack = 0; ngtcp2_pktns *pktns; @@ -8974,7 +9029,7 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, ngtcp2_qlog_pkt_received_start(&conn->qlog); for (; payloadlen;) { - nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen); + nread = ngtcp2_frame_decoder_decode(&frd, &fr, payload, payloadlen); if (nread < 0) { return (int)nread; } @@ -8982,14 +9037,14 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, payload += nread; payloadlen -= (size_t)nread; - switch (fr->type) { + switch (fr.hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: - fr->ack.ack_delay = 0; - fr->ack.ack_delay_unscaled = 0; + fr.ack.ack_delay = 0; + fr.ack.ack_delay_unscaled = 0; rv = - ngtcp2_pkt_validate_ack(&fr->ack, conn->local.settings.initial_pkt_num); + ngtcp2_pkt_validate_ack(&fr.ack, conn->local.settings.initial_pkt_num); if (rv != 0) { return rv; } @@ -8997,9 +9052,9 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, break; } - ngtcp2_log_rx_fr(&conn->log, hd, fr); + ngtcp2_log_rx_fr(&conn->log, hd, &fr); - switch (fr->type) { + switch (fr.hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: if (num_ack_processed >= NGTCP2_MAX_ACK_PER_PKT) { @@ -9008,7 +9063,7 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, if (!conn->server) { conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED; } - rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts); + rv = conn_recv_ack(conn, pktns, &fr.ack, pkt_ts, ts); if (rv != 0) { return rv; } @@ -9017,20 +9072,22 @@ conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, case NGTCP2_FRAME_PADDING: break; case NGTCP2_FRAME_CONNECTION_CLOSE: - rv = conn_recv_connection_close(conn, &fr->connection_close); + rv = conn_recv_connection_close(conn, &fr.connection_close); if (rv != 0) { return rv; } break; - case NGTCP2_FRAME_CRYPTO: case NGTCP2_FRAME_PING: + ++conn->cstat.ping_recv; + /* fall through */ + case NGTCP2_FRAME_CRYPTO: require_ack = 1; break; default: return NGTCP2_ERR_PROTO; } - ngtcp2_qlog_write_frame(&conn->qlog, fr); + ngtcp2_qlog_write_frame(&conn->qlog, &fr); } ngtcp2_qlog_pkt_received_end(&conn->qlog, hd, pktlen); @@ -9098,8 +9155,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, const uint8_t *payload; size_t payloadlen; ngtcp2_ssize nread, nwrite; - ngtcp2_max_frame mfr; - ngtcp2_frame *fr = &mfr.fr; + ngtcp2_frame_decoder frd; + ngtcp2_frame fr; int require_ack = 0; ngtcp2_crypto_aead *aead; ngtcp2_crypto_cipher *hp; @@ -9193,8 +9250,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; default: ngtcp2_log_rx_pkt_hd(&conn->log, &hd); - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, - "packet type 0x%02x was ignored", hd.type); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_PKT, + "packet type 0x%02x was ignored", hd.type); return (ngtcp2_ssize)pktlen; } } else { @@ -9241,8 +9298,8 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->acktr.max_pkt_num, hd.pkt_num, hd.pkt_numlen); if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) { - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, - "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_PKT, + "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num); return NGTCP2_ERR_DISCARD_PKT; } @@ -9253,7 +9310,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, conn->rx.preferred_addr.pkt_num < hd.pkt_num && ngtcp2_sockaddr_eq((const ngtcp2_sockaddr *)&conn->hs_local_addr, path->local.addr)) { - ngtcp2_log_info( + ngtcp2_log_infof( &conn->log, NGTCP2_LOG_EVENT_PKT, "pkt=%" PRId64 " is discarded because it was received on handshake local " @@ -9405,7 +9462,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_qlog_pkt_received_start(&conn->qlog); for (; payloadlen;) { - nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen); + nread = ngtcp2_frame_decoder_decode(&frd, &fr, payload, payloadlen); if (nread < 0) { return nread; } @@ -9413,7 +9470,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, payload += nread; payloadlen -= (size_t)nread; - switch (fr->type) { + switch (fr.hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: if ((hd.flags & NGTCP2_PKT_FLAG_LONG_FORM) && @@ -9422,10 +9479,10 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } assert(conn->remote.transport_params); assign_recved_ack_delay_unscaled( - &fr->ack, conn->remote.transport_params->ack_delay_exponent); + &fr.ack, conn->remote.transport_params->ack_delay_exponent); rv = - ngtcp2_pkt_validate_ack(&fr->ack, conn->local.settings.initial_pkt_num); + ngtcp2_pkt_validate_ack(&fr.ack, conn->local.settings.initial_pkt_num); if (rv != 0) { return rv; } @@ -9433,10 +9490,10 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; } - ngtcp2_log_rx_fr(&conn->log, &hd, fr); + ngtcp2_log_rx_fr(&conn->log, &hd, &fr); if (hd.type == NGTCP2_PKT_0RTT) { - switch (fr->type) { + switch (fr.hd.type) { case NGTCP2_FRAME_PADDING: case NGTCP2_FRAME_PING: case NGTCP2_FRAME_RESET_STREAM: @@ -9462,7 +9519,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, } } - switch (fr->type) { + switch (fr.hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: case NGTCP2_FRAME_PADDING: @@ -9473,7 +9530,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, require_ack = 1; } - switch (fr->type) { + switch (fr.hd.type) { case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: if (num_ack_processed >= NGTCP2_MAX_ACK_PER_PKT) { @@ -9482,7 +9539,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, if (!conn->server) { conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED; } - rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts); + rv = conn_recv_ack(conn, pktns, &fr.ack, pkt_ts, ts); if (rv != 0) { return rv; } @@ -9490,7 +9547,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, ++num_ack_processed; break; case NGTCP2_FRAME_STREAM: - rv = conn_recv_stream(conn, &fr->stream, ts); + rv = conn_recv_stream(conn, &fr.stream, ts); if (rv != 0) { return rv; } @@ -9498,40 +9555,40 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; case NGTCP2_FRAME_CRYPTO: rv = conn_recv_crypto(conn, NGTCP2_ENCRYPTION_LEVEL_1RTT, - &pktns->crypto.strm, &fr->stream, ts); + &pktns->crypto.strm, &fr.stream, ts); if (rv != 0) { return rv; } non_probing_pkt = 1; break; case NGTCP2_FRAME_RESET_STREAM: - rv = conn_recv_reset_stream(conn, &fr->reset_stream, ts); + rv = conn_recv_reset_stream(conn, &fr.reset_stream, ts); if (rv != 0) { return rv; } non_probing_pkt = 1; break; case NGTCP2_FRAME_STOP_SENDING: - rv = conn_recv_stop_sending(conn, &fr->stop_sending, ts); + rv = conn_recv_stop_sending(conn, &fr.stop_sending, ts); if (rv != 0) { return rv; } non_probing_pkt = 1; break; case NGTCP2_FRAME_MAX_STREAM_DATA: - rv = conn_recv_max_stream_data(conn, &fr->max_stream_data, ts); + rv = conn_recv_max_stream_data(conn, &fr.max_stream_data, ts); if (rv != 0) { return rv; } non_probing_pkt = 1; break; case NGTCP2_FRAME_MAX_DATA: - conn_recv_max_data(conn, &fr->max_data); + conn_recv_max_data(conn, &fr.max_data); non_probing_pkt = 1; break; case NGTCP2_FRAME_MAX_STREAMS_BIDI: case NGTCP2_FRAME_MAX_STREAMS_UNI: - rv = conn_recv_max_streams(conn, &fr->max_streams); + rv = conn_recv_max_streams(conn, &fr.max_streams); if (rv != 0) { return rv; } @@ -9539,41 +9596,42 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; case NGTCP2_FRAME_CONNECTION_CLOSE: case NGTCP2_FRAME_CONNECTION_CLOSE_APP: - rv = conn_recv_connection_close(conn, &fr->connection_close); + rv = conn_recv_connection_close(conn, &fr.connection_close); if (rv != 0) { return rv; } break; case NGTCP2_FRAME_PING: + ++conn->cstat.ping_recv; non_probing_pkt = 1; break; case NGTCP2_FRAME_PATH_CHALLENGE: - conn_recv_path_challenge(conn, path, &fr->path_challenge); + conn_recv_path_challenge(conn, path, &fr.path_challenge); path_challenge_recved = 1; break; case NGTCP2_FRAME_PATH_RESPONSE: - rv = conn_recv_path_response(conn, &hd, &fr->path_response, ts); + rv = conn_recv_path_response(conn, &hd, &fr.path_response, ts); if (rv != 0) { return rv; } break; case NGTCP2_FRAME_NEW_CONNECTION_ID: - rv = conn_recv_new_connection_id(conn, &fr->new_connection_id); + rv = conn_recv_new_connection_id(conn, &fr.new_connection_id); if (rv != 0) { return rv; } recv_ncid = 1; break; case NGTCP2_FRAME_RETIRE_CONNECTION_ID: - rv = conn_recv_retire_connection_id(conn, &hd, &fr->retire_connection_id, - ts); + rv = + conn_recv_retire_connection_id(conn, &hd, &fr.retire_connection_id, ts); if (rv != 0) { return rv; } non_probing_pkt = 1; break; case NGTCP2_FRAME_NEW_TOKEN: - rv = conn_recv_new_token(conn, &fr->new_token); + rv = conn_recv_new_token(conn, &fr.new_token); if (rv != 0) { return rv; } @@ -9587,28 +9645,28 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, non_probing_pkt = 1; break; case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI: - rv = conn_recv_streams_blocked_bidi(conn, &fr->streams_blocked); + rv = conn_recv_streams_blocked_bidi(conn, &fr.streams_blocked); if (rv != 0) { return rv; } non_probing_pkt = 1; break; case NGTCP2_FRAME_STREAMS_BLOCKED_UNI: - rv = conn_recv_streams_blocked_uni(conn, &fr->streams_blocked); + rv = conn_recv_streams_blocked_uni(conn, &fr.streams_blocked); if (rv != 0) { return rv; } non_probing_pkt = 1; break; case NGTCP2_FRAME_STREAM_DATA_BLOCKED: - rv = conn_recv_stream_data_blocked(conn, &fr->stream_data_blocked); + rv = conn_recv_stream_data_blocked(conn, &fr.stream_data_blocked); if (rv != 0) { return rv; } non_probing_pkt = 1; break; case NGTCP2_FRAME_DATA_BLOCKED: - rv = conn_recv_data_blocked(conn, &fr->data_blocked); + rv = conn_recv_data_blocked(conn, &fr.data_blocked); if (rv != 0) { return rv; } @@ -9620,7 +9678,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, conn->local.transport_params.max_datagram_frame_size) { return NGTCP2_ERR_PROTO; } - rv = conn_recv_datagram(conn, &fr->datagram); + rv = conn_recv_datagram(conn, &fr.datagram); if (rv != 0) { return rv; } @@ -9628,7 +9686,7 @@ static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, break; } - ngtcp2_qlog_write_frame(&conn->qlog, fr); + ngtcp2_qlog_write_frame(&conn->qlog, &fr); } ngtcp2_qlog_pkt_received_end(&conn->qlog, &hd, pktlen); @@ -9743,6 +9801,7 @@ static int conn_process_buffered_protected_pkt(ngtcp2_conn *conn, *ppc = next; if (nread < 0) { if (nread == NGTCP2_ERR_DISCARD_PKT) { + ++conn->cstat.pkt_discarded; continue; } return (int)nread; @@ -9777,6 +9836,7 @@ static int conn_process_buffered_handshake_pkt(ngtcp2_conn *conn, *ppc = next; if (nread < 0) { if (nread == NGTCP2_ERR_DISCARD_PKT) { + ++conn->cstat.pkt_discarded; continue; } return (int)nread; @@ -9922,6 +9982,7 @@ static int conn_recv_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path, } } if (nread == NGTCP2_ERR_DISCARD_PKT) { + ++conn->cstat.pkt_discarded; return 0; } return (int)nread; @@ -9931,8 +9992,11 @@ static int conn_recv_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path, pkt += nread; pktlen -= (size_t)nread; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, - "read packet %td left %zu", nread, pktlen); + ++conn->cstat.pkt_recv; + conn->cstat.bytes_recv += (uint64_t)nread; + + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_PKT, + "read packet %td left %zu", nread, pktlen); } return 0; @@ -9954,7 +10018,7 @@ static int conn_enqueue_handshake_done(ngtcp2_conn *conn) { return rv; } - nfrc->fr.type = NGTCP2_FRAME_HANDSHAKE_DONE; + nfrc->fr.handshake_done.type = NGTCP2_FRAME_HANDSHAKE_DONE; nfrc->next = pktns->tx.frq; pktns->tx.frq = nfrc; @@ -10104,9 +10168,9 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, if ((size_t)nread < pktlen) { /* We have 1RTT packet and application rx key, but the handshake has not completed yet. */ - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "buffering 1RTT packet len=%zu", - pktlen - (size_t)nread); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "buffering 1RTT packet len=%zu", + pktlen - (size_t)nread); rv = conn_buffer_pkt(conn, &conn->pktns, path, pi, pkt + nread, pktlen - (size_t)nread, pktlen, ts); @@ -10185,8 +10249,8 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, conn_update_timestamp(conn, ts); - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "recv packet len=%zu", - pktlen); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, "recv packet len=%zu", + pktlen); if (pktlen == 0) { return 0; @@ -10198,6 +10262,8 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, !ngtcp2_dcidtr_check_path_retired(&conn->dcid.dtr, path)) { ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "ignore packet from unknown path"); + ++conn->cstat.pkt_discarded; + return 0; } @@ -10552,8 +10618,6 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } res += nwrite; - dest += nwrite; - destlen -= (size_t)nwrite; } if (res == 0) { @@ -10563,8 +10627,6 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } res += nwrite; - dest += nwrite; - origlen -= (size_t)nwrite; } return res; @@ -10800,6 +10862,9 @@ int ngtcp2_conn_install_initial_key( rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL, 0, NULL, tx_iv, ivlen, conn->mem); if (rv != 0) { + ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, conn->mem); + pktns->crypto.rx.ckm = NULL; + return rv; } @@ -10850,6 +10915,9 @@ int ngtcp2_conn_install_vneg_initial_key( rv = ngtcp2_crypto_km_new(&conn->vneg.tx.ckm, NULL, 0, NULL, tx_iv, ivlen, conn->mem); if (rv != 0) { + ngtcp2_crypto_km_del(conn->vneg.rx.ckm, conn->mem); + conn->vneg.rx.ckm = NULL; + return rv; } @@ -10918,21 +10986,27 @@ int ngtcp2_conn_install_tx_handshake_key( if (conn->server) { rv = ngtcp2_conn_commit_local_transport_params(conn); if (rv != 0) { - return rv; + goto fail; } } rv = conn_call_recv_tx_key(conn, NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE); if (rv != 0) { - ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem); - pktns->crypto.tx.ckm = NULL; - - memset(&pktns->crypto.tx.hp_ctx, 0, sizeof(pktns->crypto.tx.hp_ctx)); - - return rv; + goto fail; } return 0; + +fail: + /* If this function fails, aead_ctx and hp_ctx are still owned by + the caller. Delete the install key to remove the any reference + to them. */ + ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem); + pktns->crypto.tx.ckm = NULL; + + memset(&pktns->crypto.tx.hp_ctx, 0, sizeof(pktns->crypto.tx.hp_ctx)); + + return rv; } int ngtcp2_conn_install_0rtt_key(ngtcp2_conn *conn, @@ -11516,9 +11590,9 @@ int ngtcp2_conn_set_remote_transport_params( conn->local.transport_params.version_info.chosen_version = conn->negotiated_version; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "the negotiated version is 0x%08x", - conn->negotiated_version); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "the negotiated version is 0x%08x", + conn->negotiated_version); } else { rv = conn_client_validate_transport_params(conn, params); if (rv != 0) { @@ -11884,11 +11958,8 @@ conn_write_vmsg_wrapper(ngtcp2_conn *conn, ngtcp2_path *path, packet is produced, if it is set, we are sure that we are not app-limited. */ !(conn->flags & NGTCP2_CONN_FLAG_AGGREGATE_PKTS)) { - conn->rst.app_limited = conn->rst.delivered + cstat->bytes_in_flight; - - if (conn->rst.app_limited == 0) { - conn->rst.app_limited = cstat->max_tx_udp_payload_size; - } + conn->rst.app_limited = + ngtcp2_max_uint64(conn->rst.delivered + cstat->bytes_in_flight, 1); } return nwrite; @@ -12071,27 +12142,29 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, conn_client_write_handshake(conn, pi, dest, destlen, wflags, vmsg, ts); /* We might be unable to write a packet because of depletion of congestion window budget, perhaps due to packet loss that - shrinks the window drastically. */ - if (nwrite <= 0) { + shrinks the window drastically. Then continue if we are in + post-handshake. There, we might be able to write packets + exceeding CWND to avoid deadlock. */ + if (nwrite < 0) { return nwrite; } if (conn->state != NGTCP2_CS_POST_HANDSHAKE) { return nwrite; } - assert(nwrite); - assert(dest[0] & NGTCP2_HEADER_FORM_BIT); - assert(conn->negotiated_version); + if (nwrite) { + assert(dest[0] & NGTCP2_HEADER_FORM_BIT); + assert(conn->negotiated_version); - if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE && - ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == + if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == NGTCP2_PKT_INITIAL) { - wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; - } + wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; + } - res = nwrite; - dest += nwrite; - destlen -= (size_t)nwrite; + res = nwrite; + dest += nwrite; + destlen -= (size_t)nwrite; + } /* Break here so that we can coalesces 1RTT packet. */ break; case NGTCP2_CS_SERVER_INITIAL: @@ -12146,7 +12219,7 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, dest += nwrite; destlen -= (size_t)nwrite; - if (res < NGTCP2_MAX_UDP_PAYLOAD_SIZE && conn->in_pktns && nwrite > 0) { + if (conn->in_pktns && nwrite > 0) { it = ngtcp2_rtb_head(&conn->in_pktns->rtb); if (!ngtcp2_ksl_it_end(&it)) { rtbent = ngtcp2_ksl_it_get(&it); @@ -12293,9 +12366,22 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, return nwrite; } if (nwrite > 0) { + /* This makes 1RTT packet padded. If 1RTT packet is not going + to be sent, packet is already padded. */ + if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == + NGTCP2_PKT_INITIAL) { + wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; + } + res = nwrite; dest += nwrite; destlen -= (size_t)nwrite; + + /* We only exceed CWND to avoid deadlock. Do no write 1RTT + packet if CWND is depleted. */ + if (conn_cwnd_is_zero(conn) && conn->pktns.rtb.probe_pkt_left == 0) { + goto fin; + } } else if (destlen == 0) { res = conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts); if (res) { @@ -12306,9 +12392,9 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, } if (conn->pktns.rtb.probe_pkt_left) { - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, - "transmit probe pkt left=%zu", - conn->pktns.rtb.probe_pkt_left); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_CON, + "transmit probe pkt left=%zu", + conn->pktns.rtb.probe_pkt_left); nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg, NGTCP2_PKT_1RTT, wflags, ts); @@ -12362,11 +12448,12 @@ conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, ngtcp2_frame fr; uint8_t flags = NGTCP2_WRITE_PKT_FLAG_NONE; - fr.type = NGTCP2_FRAME_CONNECTION_CLOSE; - fr.connection_close.error_code = error_code; - fr.connection_close.frame_type = 0; - fr.connection_close.reasonlen = reasonlen; - fr.connection_close.reason = (uint8_t *)reason; + fr.connection_close = (ngtcp2_connection_close){ + .type = NGTCP2_FRAME_CONNECTION_CLOSE, + .error_code = error_code, + .reasonlen = reasonlen, + .reason = (uint8_t *)reason, + }; if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) && pkt_type != NGTCP2_PKT_INITIAL) { @@ -12541,11 +12628,12 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( assert(conn->pktns.crypto.tx.ckm); - fr.type = NGTCP2_FRAME_CONNECTION_CLOSE_APP; - fr.connection_close.error_code = app_error_code; - fr.connection_close.frame_type = 0; - fr.connection_close.reasonlen = reasonlen; - fr.connection_close.reason = (uint8_t *)reason; + fr.connection_close = (ngtcp2_connection_close){ + .type = NGTCP2_FRAME_CONNECTION_CLOSE_APP, + .error_code = app_error_code, + .reasonlen = reasonlen, + .reason = (uint8_t *)reason, + }; nwrite = ngtcp2_conn_write_single_frame_pkt( conn, pi, dest, destlen, NGTCP2_PKT_1RTT, NGTCP2_WRITE_PKT_FLAG_NONE, @@ -12569,11 +12657,12 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( static void ccerr_init(ngtcp2_ccerr *ccerr, ngtcp2_ccerr_type type, uint64_t error_code, const uint8_t *reason, size_t reasonlen) { - ccerr->type = type; - ccerr->error_code = error_code; - ccerr->frame_type = 0; - ccerr->reason = (uint8_t *)reason; - ccerr->reasonlen = reasonlen; + *ccerr = (ngtcp2_ccerr){ + .type = type, + .error_code = error_code, + .reason = (uint8_t *)reason, + .reasonlen = reasonlen, + }; } void ngtcp2_ccerr_default(ngtcp2_ccerr *ccerr) { @@ -12608,7 +12697,7 @@ void ngtcp2_ccerr_set_liberr(ngtcp2_ccerr *ccerr, int liberr, reasonlen); return; - }; + } ngtcp2_ccerr_set_transport_error( ccerr, ngtcp2_err_infer_quic_transport_error_code(liberr), reason, @@ -12989,8 +13078,8 @@ int ngtcp2_conn_get_tls_early_data_rejected(ngtcp2_conn *conn) { return (conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED) != 0; } -int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, - ngtcp2_duration ack_delay, ngtcp2_tstamp ts) { +void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, + ngtcp2_duration ack_delay, ngtcp2_tstamp ts) { ngtcp2_conn_stat *cstat = &conn->cstat; assert(rtt > 0); @@ -13011,13 +13100,13 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, rtt < cstat->min_rtt + ack_delay) { /* Ignore RTT sample if adjusting ack_delay causes the sample less than min_rtt before handshake confirmation. */ - ngtcp2_log_info( + ngtcp2_log_infof( &conn->log, NGTCP2_LOG_EVENT_LDC, "ignore rtt sample because ack_delay is too large latest_rtt=%" PRIu64 " min_rtt=%" PRIu64 " ack_delay=%" PRIu64, rtt / NGTCP2_MILLISECONDS, cstat->min_rtt / NGTCP2_MILLISECONDS, ack_delay / NGTCP2_MILLISECONDS); - return NGTCP2_ERR_INVALID_ARGUMENT; + return; } cstat->latest_rtt = rtt; @@ -13034,7 +13123,7 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, cstat->smoothed_rtt = (cstat->smoothed_rtt * 7 + rtt) / 8; } - ngtcp2_log_info( + ngtcp2_log_infof( &conn->log, NGTCP2_LOG_EVENT_LDC, "latest_rtt=%" PRIu64 " min_rtt=%" PRIu64 " smoothed_rtt=%" PRIu64 " rttvar=%" PRIu64 " ack_delay=%" PRIu64, @@ -13042,23 +13131,12 @@ int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, cstat->min_rtt / NGTCP2_MILLISECONDS, cstat->smoothed_rtt / NGTCP2_MILLISECONDS, cstat->rttvar / NGTCP2_MILLISECONDS, ack_delay / NGTCP2_MILLISECONDS); - - return 0; } void ngtcp2_conn_get_conn_info_versioned(ngtcp2_conn *conn, int conn_info_version, ngtcp2_conn_info *cinfo) { - const ngtcp2_conn_stat *cstat = &conn->cstat; - (void)conn_info_version; - - cinfo->latest_rtt = cstat->latest_rtt; - cinfo->min_rtt = cstat->min_rtt; - cinfo->smoothed_rtt = cstat->smoothed_rtt; - cinfo->rttvar = cstat->rttvar; - cinfo->cwnd = cstat->cwnd; - cinfo->ssthresh = cstat->ssthresh; - cinfo->bytes_in_flight = cstat->bytes_in_flight; + ngtcp2_conn_info_init_versioned(conn_info_version, cinfo, &conn->cstat); } static void conn_get_loss_time_and_pktns(ngtcp2_conn *conn, @@ -13140,9 +13218,10 @@ void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (earliest_loss_time != UINT64_MAX) { cstat->loss_detection_timer = earliest_loss_time; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, - "loss_detection_timer=%" PRIu64 " nonzero crypto loss time", - cstat->loss_detection_timer); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_LDC, + "loss_detection_timer=%" PRIu64 + " nonzero crypto loss time", + cstat->loss_detection_timer); return; } @@ -13166,9 +13245,9 @@ void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { timeout = cstat->loss_detection_timer > ts ? cstat->loss_detection_timer - ts : 0; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, - "loss_detection_timer=%" PRIu64 " timeout=%" PRIu64, - cstat->loss_detection_timer, timeout / NGTCP2_MILLISECONDS); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_LDC, + "loss_detection_timer=%" PRIu64 " timeout=%" PRIu64, + cstat->loss_detection_timer, timeout / NGTCP2_MILLISECONDS); } void ngtcp2_conn_cancel_loss_detection_timer(ngtcp2_conn *conn) { @@ -13240,8 +13319,8 @@ int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { ++cstat->pto_count; - ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_LDC, "pto_count=%zu", - cstat->pto_count); + ngtcp2_log_infof(&conn->log, NGTCP2_LOG_EVENT_LDC, "pto_count=%zu", + cstat->pto_count); ngtcp2_conn_set_loss_detection_timer(conn, ts); @@ -13282,7 +13361,6 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn, const uint8_t *data, const size_t datalen) { ngtcp2_pktns *pktns; ngtcp2_frame_chain *frc; - ngtcp2_stream *fr; int rv; if (datalen == 0) { @@ -13310,21 +13388,22 @@ int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn, return rv; } - rv = ngtcp2_frame_chain_objalloc_new(&frc, &conn->frc_objalloc); + rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new( + &frc, 1, &conn->frc_objalloc, conn->mem); if (rv != 0) { return rv; } - fr = &frc->fr.stream; - - fr->type = NGTCP2_FRAME_CRYPTO; - fr->flags = 0; - fr->fin = 0; - fr->stream_id = 0; - fr->offset = pktns->crypto.tx.offset; - fr->datacnt = 1; - fr->data[0].len = datalen; - fr->data[0].base = (uint8_t *)data; + frc->fr.stream.type = NGTCP2_FRAME_CRYPTO; + frc->fr.stream.flags = 0; + frc->fr.stream.fin = 0; + frc->fr.stream.stream_id = 0; + frc->fr.stream.offset = pktns->crypto.tx.offset; + frc->fr.stream.datacnt = 1; + frc->fr.stream.data[0] = (ngtcp2_vec){ + .base = (uint8_t *)data, + .len = datalen, + }; rv = ngtcp2_strm_streamfrq_push(&pktns->crypto.strm, frc); if (rv != 0) { @@ -13825,8 +13904,17 @@ int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, int64_t stream_id, return 0; } +void *ngtcp2_conn_get_stream_user_data(ngtcp2_conn *conn, int64_t stream_id) { + ngtcp2_strm *strm = ngtcp2_conn_find_stream(conn, stream_id); + + if (strm == NULL) { + return NULL; + } + + return strm->stream_user_data; +} + void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) { - uint64_t pacing_interval_m; ngtcp2_duration wait, d; conn_update_timestamp(conn, ts); @@ -13835,20 +13923,9 @@ void ngtcp2_conn_update_pkt_tx_time(ngtcp2_conn *conn, ngtcp2_tstamp ts) { return; } - if (conn->cstat.pacing_interval_m) { - pacing_interval_m = conn->cstat.pacing_interval_m; - } else { - /* 1.25 is the under-utilization avoidance factor described in - https://datatracker.ietf.org/doc/html/rfc9002#section-7.7 */ - pacing_interval_m = ((conn->cstat.first_rtt_sample_ts == UINT64_MAX - ? NGTCP2_MILLISECONDS - : conn->cstat.smoothed_rtt) - << 10) * - 100 / 125 / conn->cstat.cwnd; - pacing_interval_m = ngtcp2_max_uint64(pacing_interval_m, 1); - } - - wait = (ngtcp2_duration)((conn->tx.pacing.pktlen * pacing_interval_m) >> 10); + wait = (ngtcp2_duration)((conn->tx.pacing.pktlen * + conn->cstat.pacing_interval_m) >> + 10); d = ngtcp2_min_uint64(wait / 2, conn->tx.pacing.compensation); wait -= d; @@ -13886,6 +13963,25 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, ngtcp2_pkt_info *pi, uint8_t *buf, size_t buflen, size_t *pgsolen, ngtcp2_write_pkt write_pkt, ngtcp2_tstamp ts) { + ngtcp2_ssize nwrite; + + buflen = ngtcp2_min_size(buflen, ngtcp2_conn_get_send_quantum(conn)); + + nwrite = ngtcp2_conn_write_aggregate_pkt2_versioned( + conn, path, pkt_info_version, pi, buf, buflen, pgsolen, write_pkt, 0, ts); + if (nwrite < 0) { + return nwrite; + } + + ngtcp2_conn_update_pkt_tx_time(conn, ts); + + return nwrite; +} + +ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt2_versioned( + ngtcp2_conn *conn, ngtcp2_path *path, int pkt_info_version, + ngtcp2_pkt_info *pi, uint8_t *buf, size_t buflen, size_t *pgsolen, + ngtcp2_write_pkt write_pkt, size_t num_pkts, ngtcp2_tstamp ts) { size_t max_udp_payloadlen = ngtcp2_conn_get_max_tx_udp_payload_size(conn); size_t path_max_udp_payloadlen = ngtcp2_conn_get_path_max_tx_udp_payload_size(conn); @@ -13900,9 +13996,9 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( assert(buflen >= path_max_udp_payloadlen); - buflen = - ngtcp2_min_size(buflen, ngtcp2_max_size(ngtcp2_conn_get_send_quantum(conn), - path_max_udp_payloadlen)); + if (num_pkts == 0) { + num_pkts = SIZE_MAX; + } for (;;) { ecn_state = conn->tx.ecn.state; @@ -13924,13 +14020,16 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( wbuf += nwrite; buflen -= (size_t)nwrite; + --num_pkts; + if (first_pkt) { assert(!(conn->flags & NGTCP2_CONN_FLAG_AGGREGATE_PKTS)); *pgsolen = (size_t)nwrite; if ((size_t)nwrite != path_max_udp_payloadlen || - buflen < path_max_udp_payloadlen || ecn_state != conn->tx.ecn.state) { + buflen < path_max_udp_payloadlen || ecn_state != conn->tx.ecn.state || + num_pkts == 0) { nwrite = wbuf - buf; break; } @@ -13954,7 +14053,7 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( } if (buflen < path_max_udp_payloadlen || (size_t)nwrite < *pgsolen || - ecn_state != conn->tx.ecn.state) { + ecn_state != conn->tx.ecn.state || num_pkts == 0) { nwrite = wbuf - buf; break; } @@ -13962,11 +14061,13 @@ ngtcp2_ssize ngtcp2_conn_write_aggregate_pkt_versioned( conn->flags &= ~NGTCP2_CONN_FLAG_AGGREGATE_PKTS; - ngtcp2_conn_update_pkt_tx_time(conn, ts); - return nwrite; } +ngtcp2_tstamp ngtcp2_conn_get_timestamp(const ngtcp2_conn *conn) { + return conn->log.last_ts; +} + const ngtcp2_path_history_entry * ngtcp2_conn_find_path_history(ngtcp2_conn *conn, const ngtcp2_path *path, ngtcp2_tstamp ts) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h index 2d607d379fc310..6c11e324173327 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.h @@ -77,10 +77,6 @@ typedef enum { unreceived data. */ #define NGTCP2_MAX_REORDERED_CRYPTO_DATA 65536 -/* NGTCP2_MAX_RETRIES is the number of Retry packet which client can - accept. */ -#define NGTCP2_MAX_RETRIES 3 - /* NGTCP2_MAX_SCID_POOL_SIZE is the maximum number of source connection ID the local endpoint provides to the remote endpoint. The chosen value was described in old draft. Now a remote endpoint @@ -116,19 +112,6 @@ typedef enum { packet as much as possible if the packet is not empty. */ #define NGTCP2_WRITE_PKT_FLAG_PADDING_IF_NOT_EMPTY 0x08u -/* - * ngtcp2_max_frame is defined so that it covers the largest ACK - * frame. - */ -typedef union ngtcp2_max_frame { - ngtcp2_frame fr; - struct { - ngtcp2_ack ack; - /* ack includes 1 ngtcp2_ack_range. */ - ngtcp2_ack_range ranges[NGTCP2_MAX_ACK_RANGES - 1]; - } ackfr; -} ngtcp2_max_frame; - typedef struct ngtcp2_path_challenge_entry { ngtcp2_path_storage ps; uint8_t data[8]; @@ -772,15 +755,9 @@ int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm); * ack_delay included in ACK frame. |ack_delay| is actually tainted * (sent by peer), so don't assume that |ack_delay| is always smaller * than, or equals to |rtt|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_INVALID_ARGUMENT - * RTT sample is ignored. */ -int ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, - ngtcp2_duration ack_delay, ngtcp2_tstamp ts); +void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, + ngtcp2_duration ack_delay, ngtcp2_tstamp ts); void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_info.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_info.c new file mode 100644 index 00000000000000..84bb8820f50d65 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_info.c @@ -0,0 +1,50 @@ +/* + * ngtcp2 + * + * Copyright (c) 2025 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ngtcp2_conn_info.h" +#include "ngtcp2_conn_stat.h" + +void ngtcp2_conn_info_init_versioned(int conn_info_version, + ngtcp2_conn_info *cinfo, + const ngtcp2_conn_stat *cstat) { + cinfo->latest_rtt = cstat->latest_rtt; + cinfo->min_rtt = cstat->min_rtt; + cinfo->smoothed_rtt = cstat->smoothed_rtt; + cinfo->rttvar = cstat->rttvar; + cinfo->cwnd = cstat->cwnd; + cinfo->ssthresh = cstat->ssthresh; + cinfo->bytes_in_flight = cstat->bytes_in_flight; + + switch (conn_info_version) { + case NGTCP2_CONN_INFO_V2: + cinfo->pkt_sent = cstat->pkt_sent; + cinfo->bytes_sent = cstat->bytes_sent; + cinfo->pkt_recv = cstat->pkt_recv; + cinfo->bytes_recv = cstat->bytes_recv; + cinfo->pkt_lost = cstat->pkt_lost; + cinfo->bytes_lost = cstat->bytes_lost; + cinfo->ping_recv = cstat->ping_recv; + cinfo->pkt_discarded = cstat->pkt_discarded; + } +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_info.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_info.h new file mode 100644 index 00000000000000..161309df304314 --- /dev/null +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_info.h @@ -0,0 +1,45 @@ +/* + * ngtcp2 + * + * Copyright (c) 2025 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef NGTCP2_CONN_INFO_H +#define NGTCP2_CONN_INFO_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* defined(HAVE_CONFIG_H) */ + +#include + +typedef struct ngtcp2_conn_stat ngtcp2_conn_stat; + +/* + * ngtcp2_conn_info_init_versioned initializes |cinfo| of version + * |conn_info_version| from |cstat|. This function only fills the + * fields of |cinfo| that are available in the specified version. + */ +void ngtcp2_conn_info_init_versioned(int conn_info_version, + ngtcp2_conn_info *cinfo, + const ngtcp2_conn_stat *cstat); + +#endif /* !defined(NGTCP2_CONN_INFO_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h index be041b9086081d..b5fea473910951 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h @@ -31,6 +31,8 @@ #include +#include "ngtcp2_pktns_id.h" + /** * @struct * @@ -128,6 +130,43 @@ typedef struct ngtcp2_conn_stat { * scheduled and transmitted together. */ size_t send_quantum; + /* + * pkt_sent is the number of QUIC packets sent. + */ + uint64_t pkt_sent; + /* + * bytes_sent is the number of bytes (the sum of QUIC packet length) + * sent. + */ + uint64_t bytes_sent; + /* + * pkt_recv is the number of QUIC packets received, excluding + * discarded ones. + */ + uint64_t pkt_recv; + /* + * bytes_recv is the number of bytes (the sum of QUIC packet length) + * received, excluding discarded ones. + */ + uint64_t bytes_recv; + /* + * pkt_lost is the number of QUIC packets that are considered lost, + * excluding PMTUD packets. + */ + uint64_t pkt_lost; + /* + * bytes_lost is the number of bytes (the sum of QUIC packet length) + * lost, excluding PMTUD packets. + */ + uint64_t bytes_lost; + /* + * ping_recv is the number of PING frames received. + */ + uint64_t ping_recv; + /* + * pkt_discarded is the number of QUIC packets discarded. + */ + uint64_t pkt_discarded; } ngtcp2_conn_stat; #endif /* !defined(NGTCP2_CONN_STAT_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c index 6528011cc0edf4..7b2e02e5b10f5d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conv.c @@ -63,33 +63,33 @@ const uint8_t *ngtcp2_get_uint16(uint16_t *dest, const uint8_t *p) { } static const uint8_t *get_uvarint(uint64_t *dest, const uint8_t *p) { - union { - uint8_t n8; - uint16_t n16; - uint32_t n32; - uint64_t n64; - } n; + uint16_t n16; + uint32_t n32; + uint64_t n64; switch (*p >> 6) { case 0: *dest = *p++; return p; case 1: - memcpy(&n, p, 2); - n.n8 &= 0x3f; - *dest = ngtcp2_ntohs(n.n16); + memcpy(&n16, p, 2); + n16 = ngtcp2_ntohs(n16); + n16 &= 0x3fff; + *dest = n16; return p + 2; case 2: - memcpy(&n, p, 4); - n.n8 &= 0x3f; - *dest = ngtcp2_ntohl(n.n32); + memcpy(&n32, p, 4); + n32 = ngtcp2_ntohl(n32); + n32 &= 0x3fffffff; + *dest = n32; return p + 4; case 3: - memcpy(&n, p, 8); - n.n8 &= 0x3f; - *dest = ngtcp2_ntohl64(n.n64); + memcpy(&n64, p, 8); + n64 = ngtcp2_ntohl64(n64); + n64 &= 0x3fffffffffffffff; + *dest = n64; return p + 8; default: diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c index 1f74e8c58397b1..078568fde3b09e 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c @@ -65,15 +65,21 @@ int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen, } p = (uint8_t *)(*pckm) + sizeof(ngtcp2_crypto_km); - (*pckm)->secret.base = p; - (*pckm)->secret.len = secretlen; - p += secretlen; - (*pckm)->iv.base = p; - (*pckm)->iv.len = ivlen; - (*pckm)->aead_ctx.native_handle = NULL; - (*pckm)->pkt_num = -1; - (*pckm)->use_count = 0; - (*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE; + + **pckm = (ngtcp2_crypto_km){ + .secret = + { + .base = p, + .len = secretlen, + }, + .iv = + { + .base = p + secretlen, + .len = ivlen, + }, + .pkt_num = -1, + .flags = NGTCP2_CRYPTO_KM_FLAG_NONE, + }; return 0; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c index 0f6b06a788d174..dc17d576b8044b 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.c @@ -57,14 +57,26 @@ int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc, size_t datacnt, ngtcp2_objalloc *objalloc, const ngtcp2_mem *mem) { + int rv; + if (datacnt > NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES) { - return ngtcp2_frame_chain_extralen_new(pfrc, - sizeof(ngtcp2_vec) * (datacnt - 1) - - NGTCP2_FRAME_CHAIN_STREAM_AVAIL, - mem); + rv = ngtcp2_frame_chain_extralen_new( + pfrc, + sizeof(ngtcp2_vec) * (datacnt - NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES), + mem); + } else { + rv = ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); } - return ngtcp2_frame_chain_objalloc_new(pfrc, objalloc); + if (rv != 0) { + return rv; + } + + (*pfrc)->fr.stream.data = + (ngtcp2_vec *)(void *)((uint8_t *)*pfrc + + offsetof(ngtcp2_frame_chain, buf)); + + return 0; } int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc, @@ -87,9 +99,9 @@ int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc, } fr = &(*pfrc)->fr; - fr->type = NGTCP2_FRAME_NEW_TOKEN; + fr->new_token.type = NGTCP2_FRAME_NEW_TOKEN; - p = (uint8_t *)fr + sizeof(ngtcp2_new_token); + p = (uint8_t *)*pfrc + offsetof(ngtcp2_frame_chain, buf); memcpy(p, token, tokenlen); fr->new_token.token = p; @@ -122,7 +134,7 @@ void ngtcp2_frame_chain_objalloc_del(ngtcp2_frame_chain *frc, return; } - switch (frc->fr.type) { + switch (frc->fr.hd.type) { case NGTCP2_FRAME_CRYPTO: case NGTCP2_FRAME_STREAM: if (frc->fr.stream.datacnt > NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h index 01f07cfa4d95ed..aa8ce4958386c9 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_frame_chain.h @@ -57,6 +57,19 @@ typedef struct ngtcp2_frame_chain_binder { int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder, const ngtcp2_mem *mem); +/* NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES is the number of datacnt + that changes allocation method. If datacnt is more than this + value, ngtcp2_frame_chain is allocated without ngtcp2_objalloc. + Otherwise, it is allocated using ngtcp2_objalloc. */ +#define NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES 4 + +/* NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES is the length of a token that + changes allocation method. If the length is more than this value, + ngtcp2_frame_chain is allocated without ngtcp2_objalloc. + Otherwise, it is allocated using ngtcp2_objalloc. */ +#define NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES \ + (NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES * sizeof(ngtcp2_vec)) + typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; /* @@ -68,6 +81,7 @@ struct ngtcp2_frame_chain { ngtcp2_frame_chain *next; ngtcp2_frame_chain_binder *binder; ngtcp2_frame fr; + uint8_t buf[sizeof(ngtcp2_vec) * NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES]; }; ngtcp2_opl_entry oplent; @@ -104,26 +118,6 @@ int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc, int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen, const ngtcp2_mem *mem); -/* NGTCP2_FRAME_CHAIN_STREAM_AVAIL is the number of additional bytes - available after ngtcp2_stream when it is embedded in - ngtcp2_frame. */ -#define NGTCP2_FRAME_CHAIN_STREAM_AVAIL \ - (sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream)) - -/* NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES is the number of datacnt - that changes allocation method. If datacnt is more than this - value, ngtcp2_frame_chain is allocated without ngtcp2_objalloc. - Otherwise, it is allocated using ngtcp2_objalloc. */ -#define NGTCP2_FRAME_CHAIN_STREAM_DATACNT_THRES \ - (NGTCP2_FRAME_CHAIN_STREAM_AVAIL / sizeof(ngtcp2_vec) + 1) - -/* NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES is the length of a token that - changes allocation method. If the length is more than this value, - ngtcp2_frame_chain is allocated without ngtcp2_objalloc. - Otherwise, it is allocated using ngtcp2_objalloc. */ -#define NGTCP2_FRAME_CHAIN_NEW_TOKEN_THRES \ - (sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token)) - /* * ngtcp2_frame_chain_stream_datacnt_objalloc_new allocates enough * data to store additional |datacnt| - 1 ngtcp2_vec object after diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c index d04b9634c20528..267bd07225d72b 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_gaptr.c @@ -35,11 +35,11 @@ void ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem) { } static int gaptr_gap_init(ngtcp2_gaptr *gaptr) { - ngtcp2_range range = { - .end = UINT64_MAX, - }; - - return ngtcp2_ksl_insert(&gaptr->gap, NULL, &range, NULL); + return ngtcp2_ksl_insert(&gaptr->gap, NULL, + &(ngtcp2_range){ + .end = UINT64_MAX, + }, + NULL); } void ngtcp2_gaptr_free(ngtcp2_gaptr *gaptr) { @@ -116,10 +116,6 @@ uint64_t ngtcp2_gaptr_first_gap_offset(const ngtcp2_gaptr *gaptr) { ngtcp2_range ngtcp2_gaptr_get_first_gap_after(const ngtcp2_gaptr *gaptr, uint64_t offset) { - ngtcp2_range q = { - .begin = offset, - .end = offset + 1, - }; ngtcp2_ksl_it it; if (ngtcp2_ksl_len(&gaptr->gap) == 0) { @@ -129,7 +125,11 @@ ngtcp2_range ngtcp2_gaptr_get_first_gap_after(const ngtcp2_gaptr *gaptr, return r; } - it = ngtcp2_ksl_lower_bound_search(&gaptr->gap, &q, + it = ngtcp2_ksl_lower_bound_search(&gaptr->gap, + &(ngtcp2_range){ + .begin = offset, + .end = offset + 1, + }, ngtcp2_ksl_range_exclusive_search); assert(!ngtcp2_ksl_it_end(&it)); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c index 22c131a1ac677c..03a95b9319a45d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.c @@ -37,33 +37,30 @@ static ngtcp2_ksl_blk null_blk; ngtcp2_objalloc_def(ksl_blk, ngtcp2_ksl_blk, oplent) -static size_t ksl_nodelen(size_t keylen) { - assert(keylen >= sizeof(uint64_t)); - - return (sizeof(ngtcp2_ksl_node) + keylen - sizeof(uint64_t) + 0x7u) & - ~(uintptr_t)0x7u; -} - -static size_t ksl_blklen(size_t nodelen) { - return sizeof(ngtcp2_ksl_blk) + nodelen * NGTCP2_KSL_MAX_NBLK - - sizeof(uint64_t); +static size_t ksl_blklen(size_t aligned_keylen) { + return sizeof(ngtcp2_ksl_blk) + NGTCP2_KSL_MAX_NBLK * aligned_keylen; } /* - * ksl_node_set_key sets |key| to |node|. + * ksl_set_nth_key sets |key| to |n|th node under |blk|. */ -static void ksl_node_set_key(ngtcp2_ksl *ksl, ngtcp2_ksl_node *node, - const void *key) { - memcpy(node->key, key, ksl->keylen); +static void ksl_set_nth_key(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, + size_t n, const ngtcp2_ksl_key *key) { + memcpy(blk->keys + n * ksl->aligned_keylen, key, ksl->keylen); } void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, ngtcp2_ksl_search search, size_t keylen, const ngtcp2_mem *mem) { - size_t nodelen = ksl_nodelen(keylen); + size_t aligned_keylen; + + assert(keylen >= sizeof(uint64_t)); + + aligned_keylen = (keylen + 0x7u) & ~0x7u; ngtcp2_objalloc_init(&ksl->blkalloc, - (ksl_blklen(nodelen) + 0xfu) & ~(uintptr_t)0xfu, mem); + (ksl_blklen(aligned_keylen) + 0xfu) & ~(uintptr_t)0xfu, + mem); ksl->head = NULL; ksl->front = ksl->back = NULL; @@ -71,12 +68,20 @@ void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, ksl->search = search; ksl->n = 0; ksl->keylen = keylen; - ksl->nodelen = nodelen; + ksl->aligned_keylen = aligned_keylen; } static ngtcp2_ksl_blk *ksl_blk_objalloc_new(ngtcp2_ksl *ksl) { - return ngtcp2_objalloc_ksl_blk_len_get(&ksl->blkalloc, - ksl_blklen(ksl->nodelen)); + ngtcp2_ksl_blk *blk = ngtcp2_objalloc_ksl_blk_len_get( + &ksl->blkalloc, ksl_blklen(ksl->aligned_keylen)); + + if (!blk) { + return NULL; + } + + blk->keys = (uint8_t *)blk + sizeof(*blk); + + return blk; } static void ksl_blk_objalloc_del(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { @@ -109,7 +114,7 @@ static void ksl_free_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { if (!blk->leaf) { for (i = 0; i < blk->n; ++i) { - ksl_free_blk(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk); + ksl_free_blk(ksl, blk->nodes[i].blk); } } @@ -160,8 +165,10 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { rblk->n = blk->n / 2; blk->n -= rblk->n; - memcpy(rblk->nodes, blk->nodes + ksl->nodelen * blk->n, - ksl->nodelen * rblk->n); + memcpy(rblk->nodes, blk->nodes + blk->n, rblk->n * sizeof(ngtcp2_ksl_node)); + + memcpy(rblk->keys, blk->keys + blk->n * ksl->aligned_keylen, + rblk->n * ksl->aligned_keylen); assert(blk->n >= NGTCP2_KSL_MIN_NBLK); assert(rblk->n >= NGTCP2_KSL_MIN_NBLK); @@ -181,25 +188,25 @@ static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) { * Out of memory. */ static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { - ngtcp2_ksl_node *node; - ngtcp2_ksl_blk *lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk, *rblk; + ngtcp2_ksl_blk *lblk = blk->nodes[i].blk, *rblk; rblk = ksl_split_blk(ksl, lblk); if (rblk == NULL) { return NGTCP2_ERR_NOMEM; } - memmove(blk->nodes + (i + 2) * ksl->nodelen, - blk->nodes + (i + 1) * ksl->nodelen, - ksl->nodelen * (blk->n - (i + 1))); + memmove(blk->nodes + (i + 2), blk->nodes + (i + 1), + (blk->n - (i + 1)) * sizeof(ngtcp2_ksl_node)); + + memmove(blk->keys + (i + 2) * ksl->aligned_keylen, + blk->keys + (i + 1) * ksl->aligned_keylen, + (blk->n - (i + 1)) * ksl->aligned_keylen); - node = ngtcp2_ksl_nth_node(ksl, blk, i + 1); - node->blk = rblk; + blk->nodes[i + 1].blk = rblk; ++blk->n; - ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i + 1, ngtcp2_ksl_nth_key(ksl, rblk, rblk->n - 1)); - node = ngtcp2_ksl_nth_node(ksl, blk, i); - ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); return 0; } @@ -216,7 +223,6 @@ static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { */ static int ksl_split_head(ngtcp2_ksl *ksl) { ngtcp2_ksl_blk *rblk = NULL, *lblk, *nhead = NULL; - ngtcp2_ksl_node *node; rblk = ksl_split_blk(ksl, ksl->head); if (rblk == NULL) { @@ -236,13 +242,11 @@ static int ksl_split_head(ngtcp2_ksl *ksl) { nhead->n = 2; nhead->leaf = 0; - node = ngtcp2_ksl_nth_node(ksl, nhead, 0); - ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); - node->blk = lblk; + ksl_set_nth_key(ksl, nhead, 0, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); + nhead->nodes[0].blk = lblk; - node = ngtcp2_ksl_nth_node(ksl, nhead, 1); - ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key); - node->blk = rblk; + ksl_set_nth_key(ksl, nhead, 1, ngtcp2_ksl_nth_key(ksl, rblk, rblk->n - 1)); + nhead->nodes[1].blk = rblk; ksl->head = nhead; @@ -257,16 +261,17 @@ static int ksl_split_head(ngtcp2_ksl *ksl) { */ static void ksl_insert_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i, const ngtcp2_ksl_key *key, void *data) { - ngtcp2_ksl_node *node; - assert(blk->n < NGTCP2_KSL_MAX_NBLK); - memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen, - ksl->nodelen * (blk->n - i)); + memmove(blk->nodes + (i + 1), blk->nodes + i, + (blk->n - i) * sizeof(ngtcp2_ksl_node)); + + memmove(blk->keys + (i + 1) * ksl->aligned_keylen, + blk->keys + i * ksl->aligned_keylen, + (blk->n - i) * ksl->aligned_keylen); - node = ngtcp2_ksl_nth_node(ksl, blk, i); - ksl_node_set_key(ksl, node, key); - node->data = data; + ksl_set_nth_key(ksl, blk, i, key); + blk->nodes[i].data = data; ++blk->n; } @@ -298,8 +303,7 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, i = ksl->search(ksl, blk, key); if (blk->leaf) { - if (i < blk->n && - !ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) { + if (i < blk->n && !ksl->compar(key, ngtcp2_ksl_nth_key(ksl, blk, i))) { if (it) { *it = ngtcp2_ksl_end(ksl); } @@ -320,17 +324,17 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, if (i == blk->n) { /* This insertion extends the largest key in this subtree. */ for (; !blk->leaf;) { - node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1); + node = &blk->nodes[blk->n - 1]; if (node->blk->n == NGTCP2_KSL_MAX_NBLK) { rv = ksl_split_node(ksl, blk, blk->n - 1); if (rv != 0) { return rv; } - node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1); + node = &blk->nodes[blk->n - 1]; } - ksl_node_set_key(ksl, node, key); + ksl_set_nth_key(ksl, blk, blk->n - 1, key); blk = node->blk; } @@ -344,7 +348,7 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, return 0; } - node = ngtcp2_ksl_nth_node(ksl, blk, i); + node = &blk->nodes[i]; if (node->blk->n == NGTCP2_KSL_MAX_NBLK) { rv = ksl_split_node(ksl, blk, i); @@ -352,11 +356,11 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, return rv; } - if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) { - node = ngtcp2_ksl_nth_node(ksl, blk, i + 1); + if (ksl->compar(ngtcp2_ksl_nth_key(ksl, blk, i), key)) { + node = &blk->nodes[i + 1]; - if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) { - ksl_node_set_key(ksl, node, key); + if (ksl->compar(ngtcp2_ksl_nth_key(ksl, blk, i + 1), key)) { + ksl_set_nth_key(ksl, blk, i + 1, key); } } } @@ -370,8 +374,12 @@ int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, * |i|. */ static void ksl_remove_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { - memmove(blk->nodes + i * ksl->nodelen, blk->nodes + (i + 1) * ksl->nodelen, - ksl->nodelen * (blk->n - (i + 1))); + memmove(blk->nodes + i, blk->nodes + (i + 1), + (blk->n - (i + 1)) * sizeof(ngtcp2_ksl_node)); + + memmove(blk->keys + i * ksl->aligned_keylen, + blk->keys + (i + 1) * ksl->aligned_keylen, + (blk->n - (i + 1)) * ksl->aligned_keylen); --blk->n; } @@ -393,15 +401,17 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, assert(i + 1 < blk->n); - lnode = ngtcp2_ksl_nth_node(ksl, blk, i); + lnode = &blk->nodes[i]; lblk = lnode->blk; - rblk = ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk; + rblk = blk->nodes[i + 1].blk; assert(lblk->n + rblk->n < NGTCP2_KSL_MAX_NBLK); - memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes, - ksl->nodelen * rblk->n); + memcpy(lblk->nodes + lblk->n, rblk->nodes, rblk->n * sizeof(ngtcp2_ksl_node)); + + memcpy(lblk->keys + lblk->n * ksl->aligned_keylen, rblk->keys, + rblk->n * ksl->aligned_keylen); lblk->n += rblk->n; lblk->next = rblk->next; @@ -419,8 +429,7 @@ static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, ksl->head = lblk; } else { ksl_remove_node(ksl, blk, i + 1); - ksl_node_set_key(ksl, lnode, - ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); } return lblk; @@ -438,8 +447,8 @@ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { assert(i > 0); - lnode = ngtcp2_ksl_nth_node(ksl, blk, i - 1); - rnode = ngtcp2_ksl_nth_node(ksl, blk, i); + lnode = &blk->nodes[i - 1]; + rnode = &blk->nodes[i]; lblk = lnode->blk; rblk = rnode->blk; @@ -453,15 +462,20 @@ static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { assert(lblk->n <= NGTCP2_KSL_MAX_NBLK - n); assert(rblk->n >= NGTCP2_KSL_MIN_NBLK + n); - memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes, ksl->nodelen * n); + memcpy(lblk->nodes + lblk->n, rblk->nodes, n * sizeof(ngtcp2_ksl_node)); + + memcpy(lblk->keys + lblk->n * ksl->aligned_keylen, rblk->keys, + n * ksl->aligned_keylen); lblk->n += (uint32_t)n; rblk->n -= (uint32_t)n; - ksl_node_set_key(ksl, lnode, - ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i - 1, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); + + memmove(rblk->nodes, rblk->nodes + n, rblk->n * sizeof(ngtcp2_ksl_node)); - memmove(rblk->nodes, rblk->nodes + ksl->nodelen * n, ksl->nodelen * rblk->n); + memmove(rblk->keys, rblk->keys + n * ksl->aligned_keylen, + rblk->n * ksl->aligned_keylen); } /* @@ -476,8 +490,8 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { assert(i < blk->n - 1); - lnode = ngtcp2_ksl_nth_node(ksl, blk, i); - rnode = ngtcp2_ksl_nth_node(ksl, blk, i + 1); + lnode = &blk->nodes[i]; + rnode = &blk->nodes[i + 1]; lblk = lnode->blk; rblk = rnode->blk; @@ -491,15 +505,20 @@ static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) { assert(lblk->n >= NGTCP2_KSL_MIN_NBLK + n); assert(rblk->n <= NGTCP2_KSL_MAX_NBLK - n); - memmove(rblk->nodes + ksl->nodelen * n, rblk->nodes, ksl->nodelen * rblk->n); + memmove(rblk->nodes + n, rblk->nodes, rblk->n * sizeof(ngtcp2_ksl_node)); + + memmove(rblk->keys + n * ksl->aligned_keylen, rblk->keys, + rblk->n * ksl->aligned_keylen); rblk->n += (uint32_t)n; lblk->n -= (uint32_t)n; - memcpy(rblk->nodes, lblk->nodes + ksl->nodelen * lblk->n, ksl->nodelen * n); + memcpy(rblk->nodes, lblk->nodes + lblk->n, n * sizeof(ngtcp2_ksl_node)); + + memcpy(rblk->keys, lblk->keys + lblk->n * ksl->aligned_keylen, + n * ksl->aligned_keylen); - ksl_node_set_key(ksl, lnode, - ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); + ksl_set_nth_key(ksl, blk, i, ngtcp2_ksl_nth_key(ksl, lblk, lblk->n - 1)); } /* @@ -548,8 +567,8 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, } if (!blk->leaf && blk->n == 2 && - ngtcp2_ksl_nth_node(ksl, blk, 0)->blk->n == NGTCP2_KSL_MIN_NBLK && - ngtcp2_ksl_nth_node(ksl, blk, 1)->blk->n == NGTCP2_KSL_MIN_NBLK) { + blk->nodes[0].blk->n == NGTCP2_KSL_MIN_NBLK && + blk->nodes[1].blk->n == NGTCP2_KSL_MIN_NBLK) { blk = ksl_merge_node(ksl, blk, 0); } @@ -565,7 +584,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, } if (blk->leaf) { - if (ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) { + if (ksl->compar(key, ngtcp2_ksl_nth_key(ksl, blk, i))) { if (it) { *it = ngtcp2_ksl_end(ksl); } @@ -587,7 +606,7 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, return 0; } - node = ngtcp2_ksl_nth_node(ksl, blk, i); + node = &blk->nodes[i]; if (node->blk->n > NGTCP2_KSL_MIN_NBLK) { blk = node->blk; @@ -596,16 +615,14 @@ int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it, assert(node->blk->n == NGTCP2_KSL_MIN_NBLK); - if (i + 1 < blk->n && - ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk->n > NGTCP2_KSL_MIN_NBLK) { + if (i + 1 < blk->n && blk->nodes[i + 1].blk->n > NGTCP2_KSL_MIN_NBLK) { ksl_shift_left(ksl, blk, i + 1); blk = node->blk; continue; } - if (i > 0 && - ngtcp2_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGTCP2_KSL_MIN_NBLK) { + if (i > 0 && blk->nodes[i - 1].blk->n > NGTCP2_KSL_MIN_NBLK) { ksl_shift_right(ksl, blk, i - 1); blk = node->blk; @@ -657,7 +674,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_search(const ngtcp2_ksl *ksl, if (i == blk->n) { /* This happens if descendant has smaller key. Fast forward to find last node in this subtree. */ - for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk) + for (; !blk->leaf; blk = blk->nodes[blk->n - 1].blk) ; if (blk->next) { @@ -672,7 +689,7 @@ ngtcp2_ksl_it ngtcp2_ksl_lower_bound_search(const ngtcp2_ksl *ksl, return it; } - blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk; + blk = blk->nodes[i].blk; } } @@ -680,6 +697,7 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, const ngtcp2_ksl_key *new_key) { ngtcp2_ksl_blk *blk = ksl->head; ngtcp2_ksl_node *node; + const ngtcp2_ksl_key *node_key; size_t i; assert(ksl->head); @@ -688,18 +706,19 @@ void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key, i = ksl->search(ksl, blk, old_key); assert(i < blk->n); - node = ngtcp2_ksl_nth_node(ksl, blk, i); + node = &blk->nodes[i]; + node_key = ngtcp2_ksl_nth_key(ksl, blk, i); if (blk->leaf) { - assert(key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key)); - ksl_node_set_key(ksl, node, new_key); + assert(key_equal(ksl->compar, node_key, old_key)); + ksl_set_nth_key(ksl, blk, i, new_key); return; } - if (key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key) || - ksl->compar((ngtcp2_ksl_key *)node->key, new_key)) { - ksl_node_set_key(ksl, node, new_key); + if (key_equal(ksl->compar, node_key, old_key) || + ksl->compar(node_key, new_key)) { + ksl_set_nth_key(ksl, blk, i, new_key); } blk = node->blk; @@ -727,14 +746,12 @@ void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) { static void ksl_print(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) { size_t i; - ngtcp2_ksl_node *node; fprintf(stderr, "LV=%zu n=%u\n", level, blk->n); if (blk->leaf) { for (i = 0; i < blk->n; ++i) { - node = ngtcp2_ksl_nth_node(ksl, blk, i); - fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key); + fprintf(stderr, " %" PRId64, *(int64_t *)ngtcp2_ksl_nth_key(ksl, blk, i)); } fprintf(stderr, "\n"); @@ -743,7 +760,7 @@ static void ksl_print(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, } for (i = 0; i < blk->n; ++i) { - ksl_print(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk, level + 1); + ksl_print(ksl, blk->nodes[i].blk, level + 1); } } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h index d5c3f61d2acc7b..d35c83deab025d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ksl.h @@ -55,22 +55,13 @@ typedef struct ngtcp2_ksl_blk ngtcp2_ksl_blk; /* * ngtcp2_ksl_node is a node which contains either ngtcp2_ksl_blk or * opaque data. If a node is an internal node, it contains - * ngtcp2_ksl_blk. Otherwise, it has data. The key is stored at the - * location starting at key. + * ngtcp2_ksl_blk. Otherwise, it has data. */ struct ngtcp2_ksl_node { union { ngtcp2_ksl_blk *blk; void *data; }; - union { - uint64_t align; - /* key is a buffer to include key associated to this node. - Because the length of key is unknown until ngtcp2_ksl_init is - called, the actual buffer will be allocated after this - field. */ - uint8_t key[1]; - }; }; /* @@ -88,15 +79,12 @@ struct ngtcp2_ksl_blk { uint32_t n; /* leaf is nonzero if this block contains leaf nodes. */ uint32_t leaf; - union { - uint64_t align; - /* nodes is a buffer to contain NGTCP2_KSL_MAX_NBLK - ngtcp2_ksl_node objects. Because ngtcp2_ksl_node object is - allocated along with the additional variable length key - storage, the size of buffer is unknown until ngtcp2_ksl_init is - called. */ - uint8_t nodes[1]; - }; + ngtcp2_ksl_node nodes[NGTCP2_KSL_MAX_NBLK]; + /* keys is a pointer to the buffer to include + NGTCP2_KSL_MAX_NBLK keys. Because the length of key is + unknown until ngtcp2_ksl_init is called, the actual buffer + will be allocated after this field. */ + uint8_t *keys; }; ngtcp2_opl_entry oplent; @@ -131,11 +119,10 @@ typedef size_t (*ngtcp2_ksl_search)(const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, static size_t ksl_##NAME##_search( \ const ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, const ngtcp2_ksl_key *key) { \ size_t i; \ - ngtcp2_ksl_node *node; \ + uint8_t *node_key; \ \ - for (i = 0, node = (ngtcp2_ksl_node *)(void *)blk->nodes; \ - i < blk->n && COMPAR((ngtcp2_ksl_key *)node->key, key); ++i, \ - node = (ngtcp2_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen)) \ + for (i = 0, node_key = blk->keys; i < blk->n && COMPAR(node_key, key); \ + ++i, node_key += ksl->aligned_keylen) \ ; \ \ return i; \ @@ -169,9 +156,7 @@ struct ngtcp2_ksl { size_t n; /* keylen is the size of key */ size_t keylen; - /* nodelen is the actual size of ngtcp2_ksl_node including key - storage. */ - size_t nodelen; + size_t aligned_keylen; }; /* @@ -290,12 +275,11 @@ size_t ngtcp2_ksl_len(const ngtcp2_ksl *ksl); void ngtcp2_ksl_clear(ngtcp2_ksl *ksl); /* - * ngtcp2_ksl_nth_node returns the |n|th node under |blk|. + * ngtcp2_ksl_nth_key returns the |n|th key under |blk|. */ -static inline ngtcp2_ksl_node *ngtcp2_ksl_nth_node(const ngtcp2_ksl *ksl, - const ngtcp2_ksl_blk *blk, - size_t n) { - return (ngtcp2_ksl_node *)(void *)(blk->nodes + ksl->nodelen * n); +static inline const ngtcp2_ksl_key * +ngtcp2_ksl_nth_key(const ngtcp2_ksl *ksl, const ngtcp2_ksl_blk *blk, size_t n) { + return blk->keys + n * ksl->aligned_keylen; } #ifndef WIN32 @@ -319,7 +303,7 @@ void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl, * ngtcp2_ksl_it_end(it) returns nonzero. */ static inline void *ngtcp2_ksl_it_get(const ngtcp2_ksl_it *it) { - return ngtcp2_ksl_nth_node(it->ksl, it->blk, it->i)->data; + return it->blk->nodes[it->i].data; } /* @@ -361,8 +345,8 @@ int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it); * It is undefined to call this function when ngtcp2_ksl_it_end(it) * returns nonzero. */ -static inline ngtcp2_ksl_key *ngtcp2_ksl_it_key(const ngtcp2_ksl_it *it) { - return (ngtcp2_ksl_key *)ngtcp2_ksl_nth_node(it->ksl, it->blk, it->i)->key; +static inline const ngtcp2_ksl_key *ngtcp2_ksl_it_key(const ngtcp2_ksl_it *it) { + return ngtcp2_ksl_nth_key(it->ksl, it->blk, it->i); } /* diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c index e006c22e4e7ff0..2015e401ef2609 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.c @@ -42,7 +42,7 @@ void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid, ngtcp2_printf log_printf, ngtcp2_tstamp ts, void *user_data) { if (scid) { - ngtcp2_encode_hex(log->scid, scid->data, scid->datalen); + ngtcp2_encode_hex_cstr(log->scid, scid->data, scid->datalen); } else { log->scid[0] = '\0'; } @@ -90,23 +90,10 @@ void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid, * Frame type in hex string. */ -#define NGTCP2_LOG_BUFLEN 4096 +#define NGTCP2_LOG_PKT "%s %" PRId64 " %s" +#define NGTCP2_LOG_TP "remote transport_parameters" -/* TODO Split second and remaining fraction with comma */ -#define NGTCP2_LOG_HD "I%08" PRIu64 " 0x%s %s" -#define NGTCP2_LOG_PKT NGTCP2_LOG_HD " %s %" PRId64 " %s" -#define NGTCP2_LOG_TP NGTCP2_LOG_HD " remote transport_parameters" - -#define NGTCP2_LOG_FRM_HD_FIELDS(DIR) \ - timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "frm", \ - (DIR), hd->pkt_num, strpkttype(hd) - -#define NGTCP2_LOG_PKT_HD_FIELDS(DIR) \ - timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "pkt", \ - (DIR), hd->pkt_num, strpkttype(hd) - -#define NGTCP2_LOG_TP_HD_FIELDS \ - timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "cry" +#define NGTCP2_LOG_PKT_HD_FIELDS(DIR) (DIR), hd->pkt_num, strpkttype(hd) static const char *strerrorcode(uint64_t error_code) { switch (error_code) { @@ -140,6 +127,10 @@ static const char *strerrorcode(uint64_t error_code) { return "CRYPTO_BUFFER_EXCEEDED"; case NGTCP2_KEY_UPDATE_ERROR: return "KEY_UPDATE_ERROR"; + case NGTCP2_AEAD_LIMIT_REACHED: + return "AEAD_LIMIT_REACHED"; + case NGTCP2_NO_VIABLE_PATH: + return "NO_VIABLE_PATH"; case NGTCP2_VERSION_NEGOTIATION_ERROR: return "VERSION_NEGOTIATION_ERROR"; default: @@ -188,45 +179,19 @@ static const char *strpkttype(const ngtcp2_pkt_hd *hd) { } static const char *strpkttype_type_flags(uint8_t type, uint8_t flags) { - ngtcp2_pkt_hd hd = {0}; - - hd.type = type; - hd.flags = flags; - - return strpkttype(&hd); -} - -static const char *strevent(ngtcp2_log_event ev) { - switch (ev) { - case NGTCP2_LOG_EVENT_CON: - return "con"; - case NGTCP2_LOG_EVENT_PKT: - return "pkt"; - case NGTCP2_LOG_EVENT_FRM: - return "frm"; - case NGTCP2_LOG_EVENT_LDC: - return "ldc"; - case NGTCP2_LOG_EVENT_CRY: - return "cry"; - case NGTCP2_LOG_EVENT_PTV: - return "ptv"; - case NGTCP2_LOG_EVENT_CCA: - return "cca"; - case NGTCP2_LOG_EVENT_NONE: - default: - return "non"; - } + return strpkttype(&(ngtcp2_pkt_hd){ + .type = type, + .flags = flags, + }); } -static uint64_t timestamp_cast(uint64_t ns) { return ns / NGTCP2_MILLISECONDS; } - static void log_fr_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stream *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 - " fin=%d offset=%" PRIu64 " len=%" PRIu64 " uni=%d"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type | fr->flags, fr->stream_id, fr->fin, + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 + " fin=%d offset=%" PRIu64 " len=%" PRIu64 " uni=%d", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type | fr->flags, fr->stream_id, fr->fin, fr->offset, ngtcp2_vec_len(fr->data, fr->datacnt), (fr->stream_id & 0x2) != 0); } @@ -236,58 +201,58 @@ static void log_fr_ack(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, int64_t largest_ack, min_ack; size_t i; - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") largest_ack=%" PRId64 - " ack_delay=%" PRIu64 "(%" PRIu64 ") ack_range_count=%zu"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->largest_ack, + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") largest_ack=%" PRId64 + " ack_delay=%" PRIu64 "(%" PRIu64 ") ack_range_count=%zu", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->largest_ack, fr->ack_delay_unscaled / NGTCP2_MILLISECONDS, fr->ack_delay, fr->rangecnt); largest_ack = fr->largest_ack; min_ack = fr->largest_ack - (int64_t)fr->first_ack_range; - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") range=[%" PRId64 - "..%" PRId64 "] len=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, largest_ack, min_ack, - fr->first_ack_range); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") range=[%" PRId64 + "..%" PRId64 "] len=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, largest_ack, + min_ack, fr->first_ack_range); for (i = 0; i < fr->rangecnt; ++i) { const ngtcp2_ack_range *range = &fr->ranges[i]; largest_ack = min_ack - (int64_t)range->gap - 2; min_ack = largest_ack - (int64_t)range->len; - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") range=[%" PRId64 - "..%" PRId64 "] gap=%" PRIu64 - " len=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, largest_ack, - min_ack, range->gap, range->len); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") range=[%" PRId64 + "..%" PRId64 "] gap=%" PRIu64 + " len=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, largest_ack, + min_ack, range->gap, range->len); } if (fr->type == NGTCP2_FRAME_ACK_ECN) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") ect0=%" PRIu64 - " ect1=%" PRIu64 " ce=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->ecn.ect0, - fr->ecn.ect1, fr->ecn.ce); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " ACK(0x%02" PRIx64 ") ect0=%" PRIu64 + " ect1=%" PRIu64 " ce=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->ecn.ect0, + fr->ecn.ect1, fr->ecn.ce); } } static void log_fr_padding(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_padding *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " PADDING(0x%02" PRIx64 ") len=%zu"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->len); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " PADDING(0x%02" PRIx64 ") len=%zu", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->len); } static void log_fr_reset_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_reset_stream *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " RESET_STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 - " app_error_code=%s(0x%" PRIx64 ") final_size=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " RESET_STREAM(0x%02" PRIx64 ") id=0x%" PRIx64 + " app_error_code=%s(0x%" PRIx64 ") final_size=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->stream_id, strapperrorcode(fr->app_error_code), fr->app_error_code, fr->final_size); } @@ -297,189 +262,192 @@ static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, char reason[256]; size_t reasonlen = ngtcp2_min_size(sizeof(reason) - 1, fr->reasonlen); - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " CONNECTION_CLOSE(0x%02" PRIx64 - ") error_code=%s(0x%" PRIx64 ") " - "frame_type=%" PRIx64 " reason_len=%zu reason=[%s]"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " CONNECTION_CLOSE(0x%02" PRIx64 ") error_code=%s(0x%" PRIx64 + ") " + "frame_type=%" PRIx64 " reason_len=%zu reason=[%s]", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->type == NGTCP2_FRAME_CONNECTION_CLOSE ? strerrorcode(fr->error_code) : strapperrorcode(fr->error_code), fr->error_code, fr->frame_type, fr->reasonlen, - ngtcp2_encode_printable_ascii(reason, fr->reason, reasonlen)); + ngtcp2_encode_printable_ascii_cstr(reason, fr->reason, reasonlen)); } static void log_fr_max_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_max_data *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " MAX_DATA(0x%02" PRIx64 ") max_data=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_data); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " MAX_DATA(0x%02" PRIx64 + ") max_data=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->max_data); } static void log_fr_max_stream_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_max_stream_data *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " MAX_STREAM_DATA(0x%02" PRIx64 - ") id=0x%" PRIx64 - " max_stream_data=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, - fr->max_stream_data); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " MAX_STREAM_DATA(0x%02" PRIx64 + ") id=0x%" PRIx64 + " max_stream_data=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->stream_id, + fr->max_stream_data); } static void log_fr_max_streams(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_max_streams *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " MAX_STREAMS(0x%02" PRIx64 ") max_streams=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " MAX_STREAMS(0x%02" PRIx64 ") max_streams=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->max_streams); } static void log_fr_ping(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_ping *fr, const char *dir) { - log->log_printf(log->user_data, (NGTCP2_LOG_PKT " PING(0x%02" PRIx64 ")"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " PING(0x%02" PRIx64 ")", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type); } static void log_fr_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_data_blocked *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " DATA_BLOCKED(0x%02" PRIx64 ") offset=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " DATA_BLOCKED(0x%02" PRIx64 + ") offset=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->offset); } static void log_fr_stream_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stream_data_blocked *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " STREAM_DATA_BLOCKED(0x%02" PRIx64 - ") id=0x%" PRIx64 " offset=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, - fr->offset); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " STREAM_DATA_BLOCKED(0x%02" PRIx64 + ") id=0x%" PRIx64 " offset=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->stream_id, + fr->offset); } static void log_fr_streams_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_streams_blocked *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " STREAMS_BLOCKED(0x%02" PRIx64 ") max_streams=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " STREAMS_BLOCKED(0x%02" PRIx64 ") max_streams=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->max_streams); } static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_new_connection_id *fr, const char *dir) { - uint8_t buf[sizeof(fr->stateless_reset_token) * 2 + 1]; - uint8_t cid[sizeof(fr->cid.data) * 2 + 1]; - - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " NEW_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64 - " cid=0x%s retire_prior_to=%" PRIu64 - " stateless_reset_token=0x%s"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq, - (const char *)ngtcp2_encode_hex(cid, fr->cid.data, fr->cid.datalen), + char buf[sizeof(fr->stateless_reset_token) * 2 + 1]; + char cid[sizeof(fr->cid.data) * 2 + 1]; + + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " NEW_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64 + " cid=0x%s retire_prior_to=%" PRIu64 + " stateless_reset_token=0x%s", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->seq, + ngtcp2_encode_hex_cstr(cid, fr->cid.data, fr->cid.datalen), fr->retire_prior_to, - (const char *)ngtcp2_encode_hex(buf, fr->stateless_reset_token, - sizeof(fr->stateless_reset_token))); + ngtcp2_encode_hex_cstr(buf, fr->stateless_reset_token, + sizeof(fr->stateless_reset_token))); } static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stop_sending *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " STOP_SENDING(0x%02" PRIx64 ") id=0x%" PRIx64 - " app_error_code=%s(0x%" PRIx64 ")"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id, - strapperrorcode(fr->app_error_code), fr->app_error_code); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " STOP_SENDING(0x%02" PRIx64 + ") id=0x%" PRIx64 + " app_error_code=%s(0x%" PRIx64 ")", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->stream_id, + strapperrorcode(fr->app_error_code), fr->app_error_code); } static void log_fr_path_challenge(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_path_challenge *fr, const char *dir) { - uint8_t buf[sizeof(fr->data) * 2 + 1]; + char buf[sizeof(fr->data) * 2 + 1]; - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64 ") data=0x%s"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, - (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02" PRIx64 + ") data=0x%s", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, + ngtcp2_encode_hex_cstr(buf, fr->data, sizeof(fr->data))); } static void log_fr_path_response(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_path_response *fr, const char *dir) { - uint8_t buf[sizeof(fr->data) * 2 + 1]; + char buf[sizeof(fr->data) * 2 + 1]; - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64 ") data=0x%s"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, - (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data))); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02" PRIx64 + ") data=0x%s", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, + ngtcp2_encode_hex_cstr(buf, fr->data, sizeof(fr->data))); } static void log_fr_crypto(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_stream *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " CRYPTO(0x%02" PRIx64 ") offset=%" PRIu64 " len=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset, - ngtcp2_vec_len(fr->data, fr->datacnt)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " CRYPTO(0x%02" PRIx64 ") offset=%" PRIu64 + " len=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->offset, + ngtcp2_vec_len(fr->data, fr->datacnt)); } static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_new_token *fr, const char *dir) { /* Show at most first 64 bytes of token. If token is longer than 64 bytes, log first 64 bytes and then append "*" */ - uint8_t buf[128 + 1 + 1]; - uint8_t *p; + char buf[128 + 1 + 1]; + char *p; if (fr->tokenlen > 64) { - p = ngtcp2_encode_hex(buf, fr->token, 64); + p = ngtcp2_encode_hex_cstr(buf, fr->token, 64); p[128] = '*'; p[129] = '\0'; } else { - p = ngtcp2_encode_hex(buf, fr->token, fr->tokenlen); + p = ngtcp2_encode_hex_cstr(buf, fr->token, fr->tokenlen); } - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " NEW_TOKEN(0x%02" PRIx64 ") token=0x%s len=%zu"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)p, fr->tokenlen); + + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " NEW_TOKEN(0x%02" PRIx64 ") token=0x%s len=%zu", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, p, fr->tokenlen); } static void log_fr_retire_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_retire_connection_id *fr, const char *dir) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_PKT " RETIRE_CONNECTION_ID(0x%02" PRIx64 ") seq=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " RETIRE_CONNECTION_ID(0x%02" PRIx64 + ") seq=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, fr->seq); } static void log_fr_handshake_done(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_handshake_done *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " HANDSHAKE_DONE(0x%02" PRIx64 ")"), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " HANDSHAKE_DONE(0x%02" PRIx64 ")", + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type); } static void log_fr_datagram(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_datagram *fr, const char *dir) { - log->log_printf(log->user_data, - (NGTCP2_LOG_PKT " DATAGRAM(0x%02" PRIx64 ") len=%" PRIu64), - NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, - ngtcp2_vec_len(fr->data, fr->datacnt)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_FRM, + NGTCP2_LOG_PKT " DATAGRAM(0x%02" PRIx64 ") len=%" PRIu64, + NGTCP2_LOG_PKT_HD_FIELDS(dir), fr->type, + ngtcp2_vec_len(fr->data, fr->datacnt)); } static void log_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const ngtcp2_frame *fr, const char *dir) { - switch (fr->type) { + switch (fr->hd.type) { case NGTCP2_FRAME_STREAM: log_fr_stream(log, hd, &fr->stream, dir); break; @@ -580,13 +548,13 @@ void ngtcp2_log_rx_vn(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, } for (i = 0; i < nsv; ++i) { - log->log_printf(log->user_data, (NGTCP2_LOG_PKT " v=0x%08x"), - NGTCP2_LOG_PKT_HD_FIELDS("rx"), sv[i]); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_PKT, NGTCP2_LOG_PKT " v=0x%08x", + NGTCP2_LOG_PKT_HD_FIELDS("rx"), sv[i]); } } void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) { - uint8_t buf[sizeof(sr->stateless_reset_token) * 2 + 1]; + char buf[sizeof(sr->stateless_reset_token) * 2 + 1]; ngtcp2_pkt_hd shd; ngtcp2_pkt_hd *hd = &shd; @@ -598,19 +566,19 @@ void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) { .type = NGTCP2_PKT_STATELESS_RESET, }; - log->log_printf( - log->user_data, (NGTCP2_LOG_PKT " token=0x%s randlen=%zu"), + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_PKT, NGTCP2_LOG_PKT " token=0x%s randlen=%zu", NGTCP2_LOG_PKT_HD_FIELDS("rx"), - (const char *)ngtcp2_encode_hex(buf, sr->stateless_reset_token, - sizeof(sr->stateless_reset_token)), + ngtcp2_encode_hex_cstr(buf, sr->stateless_reset_token, + sizeof(sr->stateless_reset_token)), sr->randlen); } void ngtcp2_log_remote_tp(ngtcp2_log *log, const ngtcp2_transport_params *params) { - uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1]; - uint8_t addr[16 * 2 + 7 + 1]; - uint8_t cid[NGTCP2_MAX_CIDLEN * 2 + 1]; + char token[NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1]; + char addr[16 * 2 + 7 + 1]; + char cid[NGTCP2_MAX_CIDLEN * 2 + 1]; size_t i; const ngtcp2_sockaddr_in *sa_in; const ngtcp2_sockaddr_in6 *sa_in6; @@ -622,127 +590,121 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, } if (params->stateless_reset_token_present) { - log->log_printf( - log->user_data, (NGTCP2_LOG_TP " stateless_reset_token=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(token, params->stateless_reset_token, - sizeof(params->stateless_reset_token))); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " stateless_reset_token=0x%s", + ngtcp2_encode_hex_cstr(token, params->stateless_reset_token, + sizeof(params->stateless_reset_token))); } if (params->preferred_addr_present) { if (params->preferred_addr.ipv4_present) { sa_in = ¶ms->preferred_addr.ipv4; - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " preferred_address.ipv4_addr=%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_ipv4( - addr, (const uint8_t *)&sa_in->sin_addr)); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " preferred_address.ipv4_port=%u"), - NGTCP2_LOG_TP_HD_FIELDS, ngtcp2_ntohs(sa_in->sin_port)); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " preferred_address.ipv4_addr=%s", + ngtcp2_encode_ipv4_cstr(addr, (const uint8_t *)&sa_in->sin_addr)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " preferred_address.ipv4_port=%u", + ngtcp2_ntohs(sa_in->sin_port)); } if (params->preferred_addr.ipv6_present) { sa_in6 = ¶ms->preferred_addr.ipv6; - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " preferred_address.ipv6_addr=%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_ipv6( - addr, (const uint8_t *)&sa_in6->sin6_addr)); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " preferred_address.ipv6_port=%u"), - NGTCP2_LOG_TP_HD_FIELDS, ngtcp2_ntohs(sa_in6->sin6_port)); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " preferred_address.ipv6_addr=%s", + ngtcp2_encode_ipv6_cstr(addr, (const uint8_t *)&sa_in6->sin6_addr)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " preferred_address.ipv6_port=%u", + ngtcp2_ntohs(sa_in6->sin6_port)); } - log->log_printf( - log->user_data, (NGTCP2_LOG_TP " preferred_address.cid=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->preferred_addr.cid.data, - params->preferred_addr.cid.datalen)); - log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex( + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_CRY, NGTCP2_LOG_TP " preferred_address.cid=0x%s", + ngtcp2_encode_hex_cstr(cid, params->preferred_addr.cid.data, + params->preferred_addr.cid.datalen)); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s", + ngtcp2_encode_hex_cstr( token, params->preferred_addr.stateless_reset_token, sizeof(params->preferred_addr.stateless_reset_token))); } if (params->original_dcid_present) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " original_destination_connection_id=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->original_dcid.data, - params->original_dcid.datalen)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP + " original_destination_connection_id=0x%s", + ngtcp2_encode_hex_cstr(cid, params->original_dcid.data, + params->original_dcid.datalen)); } if (params->retry_scid_present) { - log->log_printf( - log->user_data, (NGTCP2_LOG_TP " retry_source_connection_id=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->retry_scid.data, - params->retry_scid.datalen)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " retry_source_connection_id=0x%s", + ngtcp2_encode_hex_cstr(cid, params->retry_scid.data, + params->retry_scid.datalen)); } if (params->initial_scid_present) { - log->log_printf( - log->user_data, (NGTCP2_LOG_TP " initial_source_connection_id=0x%s"), - NGTCP2_LOG_TP_HD_FIELDS, - (const char *)ngtcp2_encode_hex(cid, params->initial_scid.data, - params->initial_scid.datalen)); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " initial_source_connection_id=0x%s", + ngtcp2_encode_hex_cstr(cid, params->initial_scid.data, + params->initial_scid.datalen)); } - log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " initial_max_stream_data_bidi_local=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_bidi_local); - log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " initial_max_stream_data_bidi_remote=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_bidi_remote); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " initial_max_stream_data_uni=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_uni); - log->log_printf(log->user_data, (NGTCP2_LOG_TP " initial_max_data=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_data); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " initial_max_streams_bidi=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_streams_bidi); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " initial_max_streams_uni=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_streams_uni); - log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_idle_timeout=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, - params->max_idle_timeout / NGTCP2_MILLISECONDS); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " max_udp_payload_size=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->max_udp_payload_size); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " ack_delay_exponent=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->ack_delay_exponent); - log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_ack_delay=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, - params->max_ack_delay / NGTCP2_MILLISECONDS); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " active_connection_id_limit=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->active_connection_id_limit); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " disable_active_migration=%d"), - NGTCP2_LOG_TP_HD_FIELDS, params->disable_active_migration); - log->log_printf(log->user_data, - (NGTCP2_LOG_TP " max_datagram_frame_size=%" PRIu64), - NGTCP2_LOG_TP_HD_FIELDS, params->max_datagram_frame_size); - log->log_printf(log->user_data, (NGTCP2_LOG_TP " grease_quic_bit=%d"), - NGTCP2_LOG_TP_HD_FIELDS, params->grease_quic_bit); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP + " initial_max_stream_data_bidi_local=%" PRIu64, + params->initial_max_stream_data_bidi_local); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP + " initial_max_stream_data_bidi_remote=%" PRIu64, + params->initial_max_stream_data_bidi_remote); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " initial_max_stream_data_uni=%" PRIu64, + params->initial_max_stream_data_uni); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " initial_max_data=%" PRIu64, + params->initial_max_data); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " initial_max_streams_bidi=%" PRIu64, + params->initial_max_streams_bidi); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " initial_max_streams_uni=%" PRIu64, + params->initial_max_streams_uni); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " max_idle_timeout=%" PRIu64, + params->max_idle_timeout / NGTCP2_MILLISECONDS); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " max_udp_payload_size=%" PRIu64, + params->max_udp_payload_size); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " ack_delay_exponent=%" PRIu64, + params->ack_delay_exponent); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " max_ack_delay=%" PRIu64, + params->max_ack_delay / NGTCP2_MILLISECONDS); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " active_connection_id_limit=%" PRIu64, + params->active_connection_id_limit); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " disable_active_migration=%d", + params->disable_active_migration); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " max_datagram_frame_size=%" PRIu64, + params->max_datagram_frame_size); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " grease_quic_bit=%d", + params->grease_quic_bit); if (params->version_info_present) { - log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " version_information.chosen_version=0x%08x"), - NGTCP2_LOG_TP_HD_FIELDS, params->version_info.chosen_version); + ngtcp2_log_infof_raw(log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP + " version_information.chosen_version=0x%08x", + params->version_info.chosen_version); assert(!(params->version_info.available_versionslen & 0x3)); @@ -751,10 +713,10 @@ void ngtcp2_log_remote_tp(ngtcp2_log *log, i += sizeof(uint32_t)) { p = ngtcp2_get_uint32be(&version, p); - log->log_printf( - log->user_data, - (NGTCP2_LOG_TP " version_information.available_versions[%zu]=0x%08x"), - NGTCP2_LOG_TP_HD_FIELDS, i >> 2, version); + ngtcp2_log_infof_raw( + log, NGTCP2_LOG_EVENT_CRY, + NGTCP2_LOG_TP " version_information.available_versions[%zu]=0x%08x", + i >> 2, version); } } } @@ -765,33 +727,33 @@ void ngtcp2_log_pkt_lost(ngtcp2_log *log, int64_t pkt_num, uint8_t type, return; } - ngtcp2_log_info(log, NGTCP2_LOG_EVENT_LDC, - "pkn=%" PRId64 " lost type=%s sent_ts=%" PRIu64, pkt_num, - strpkttype_type_flags(type, flags), sent_ts); + ngtcp2_log_infof(log, NGTCP2_LOG_EVENT_LDC, + "pkn=%" PRId64 " lost type=%s sent_ts=%" PRIu64, pkt_num, + strpkttype_type_flags(type, flags), sent_ts); } static void log_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd, const char *dir) { - uint8_t dcid[sizeof(hd->dcid.data) * 2 + 1]; - uint8_t scid[sizeof(hd->scid.data) * 2 + 1]; + char dcid[sizeof(hd->dcid.data) * 2 + 1]; + char scid[sizeof(hd->scid.data) * 2 + 1]; if (!log->log_printf || !(log->events & NGTCP2_LOG_EVENT_PKT)) { return; } if (hd->type == NGTCP2_PKT_1RTT) { - ngtcp2_log_info( + ngtcp2_log_infof( log, NGTCP2_LOG_EVENT_PKT, "%s pkn=%" PRId64 " dcid=0x%s type=%s k=%d", dir, hd->pkt_num, - (const char *)ngtcp2_encode_hex(dcid, hd->dcid.data, hd->dcid.datalen), + ngtcp2_encode_hex_cstr(dcid, hd->dcid.data, hd->dcid.datalen), strpkttype(hd), (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) != 0); } else { - ngtcp2_log_info( + ngtcp2_log_infof( log, NGTCP2_LOG_EVENT_PKT, "%s pkn=%" PRId64 " dcid=0x%s scid=0x%s version=0x%08x type=%s len=%zu", dir, hd->pkt_num, - (const char *)ngtcp2_encode_hex(dcid, hd->dcid.data, hd->dcid.datalen), - (const char *)ngtcp2_encode_hex(scid, hd->scid.data, hd->scid.datalen), + ngtcp2_encode_hex_cstr(dcid, hd->dcid.data, hd->dcid.datalen), + ngtcp2_encode_hex_cstr(scid, hd->scid.data, hd->scid.datalen), hd->version, strpkttype(hd), hd->len); } } @@ -804,31 +766,12 @@ void ngtcp2_log_tx_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd) { log_pkt_hd(log, hd, "tx"); } -void ngtcp2_log_info(ngtcp2_log *log, ngtcp2_log_event ev, const char *fmt, - ...) { - va_list ap; - int n; - char buf[NGTCP2_LOG_BUFLEN]; - - if (!log->log_printf || !(log->events & ev)) { - return; - } - - va_start(ap, fmt); - n = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - if (n < 0 || (size_t)n >= sizeof(buf)) { - return; - } - - log->log_printf(log->user_data, (NGTCP2_LOG_HD " %s"), - timestamp_cast(log->last_ts - log->ts), log->scid, - strevent(ev), buf); +void ngtcp2_log_tx_cancel(ngtcp2_log *log, const ngtcp2_pkt_hd *hd) { + ngtcp2_log_infof(log, NGTCP2_LOG_EVENT_PKT, + "cancel tx pkn=%" PRId64 " type=%s", hd->pkt_num, + strpkttype(hd)); } -void ngtcp2_log_tx_cancel(ngtcp2_log *log, const ngtcp2_pkt_hd *hd) { - ngtcp2_log_info(log, NGTCP2_LOG_EVENT_PKT, - "cancel tx pkn=%" PRId64 " type=%s", hd->pkt_num, - strpkttype(hd)); +uint64_t ngtcp2_log_timestamp(const ngtcp2_log *log) { + return (log->last_ts - log->ts) / NGTCP2_MILLISECONDS; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h index 13fb81a72e1d51..fabd5908e0d492 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_log.h @@ -49,7 +49,7 @@ typedef struct ngtcp2_log { log_pritnf. */ void *user_data; /* scid is SCID encoded as NULL-terminated hex string. */ - uint8_t scid[NGTCP2_MAX_CIDLEN * 2 + 1]; + char scid[NGTCP2_MAX_CIDLEN * 2 + 1]; } ngtcp2_log; /** @@ -121,12 +121,71 @@ void ngtcp2_log_tx_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd); void ngtcp2_log_tx_cancel(ngtcp2_log *log, const ngtcp2_pkt_hd *hd); +#define NGTCP2_LOG_HD "I%08" PRIu64 " 0x%s %s" + +uint64_t ngtcp2_log_timestamp(const ngtcp2_log *log); + +static inline const char *ngtcp2_log_event_str(ngtcp2_log_event ev) { + switch (ev) { + case NGTCP2_LOG_EVENT_CON: + return "con"; + case NGTCP2_LOG_EVENT_PKT: + return "pkt"; + case NGTCP2_LOG_EVENT_FRM: + return "frm"; + case NGTCP2_LOG_EVENT_LDC: + return "ldc"; + case NGTCP2_LOG_EVENT_CRY: + return "cry"; + case NGTCP2_LOG_EVENT_PTV: + return "ptv"; + case NGTCP2_LOG_EVENT_CCA: + return "cca"; + case NGTCP2_LOG_EVENT_NONE: + default: + return "non"; + } +} + +#define ngtcp2_log_infof_raw(LOG, EV, FMT, ...) \ + (LOG)->log_printf((LOG)->user_data, NGTCP2_LOG_HD " " FMT, \ + ngtcp2_log_timestamp(LOG), (LOG)->scid, \ + ngtcp2_log_event_str(EV), __VA_ARGS__); + +/** + * @function + * + * `ngtcp2_log_infof` writes info level log with printf like + * formatting. + */ +#define ngtcp2_log_infof(LOG, EV, FMT, ...) \ + do { \ + if (!(LOG)->log_printf || !((LOG)->events & (EV))) { \ + break; \ + } \ + \ + ngtcp2_log_infof_raw((LOG), (EV), FMT, __VA_ARGS__); \ + } while (0) + +#define ngtcp2_log_info_raw(LOG, EV, FMT) \ + (LOG)->log_printf((LOG)->user_data, NGTCP2_LOG_HD " " FMT, \ + ngtcp2_log_timestamp(LOG), (LOG)->scid, \ + ngtcp2_log_event_str(EV)) + /** * @function * - * `ngtcp2_log_info` writes info level log. + * `ngtcp2_log_info` writes info level log. FMT should not contain + * formatting directive. This function exists to workaround the issue + * that __VA_ARGS__ cannot be empty. */ -void ngtcp2_log_info(ngtcp2_log *log, ngtcp2_log_event ev, const char *fmt, - ...); +#define ngtcp2_log_info(LOG, EV, FMT) \ + do { \ + if (!(LOG)->log_printf || !((LOG)->events & (EV))) { \ + break; \ + } \ + \ + ngtcp2_log_info_raw((LOG), (EV), FMT); \ + } while (0) #endif /* !defined(NGTCP2_LOG_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c index 246c779f2908ca..6b332f6b58dbd8 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c @@ -34,11 +34,10 @@ #define NGTCP2_INITIAL_HASHBITS 4 void ngtcp2_map_init(ngtcp2_map *map, uint64_t seed, const ngtcp2_mem *mem) { - map->mem = mem; - map->hashbits = 0; - map->table = NULL; - map->seed = seed; - map->size = 0; + *map = (ngtcp2_map){ + .mem = mem, + .seed = seed, + }; } void ngtcp2_map_free(ngtcp2_map *map) { @@ -46,30 +45,27 @@ void ngtcp2_map_free(ngtcp2_map *map) { return; } - ngtcp2_mem_free(map->mem, map->table); + ngtcp2_mem_free(map->mem, map->keys); } int ngtcp2_map_each(const ngtcp2_map *map, int (*func)(void *data, void *ptr), void *ptr) { int rv; size_t i; - ngtcp2_map_bucket *bkt; size_t tablelen; if (map->size == 0) { return 0; } - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - - if (bkt->data == NULL) { + if (map->psl[i] == 0) { continue; } - rv = func(bkt->data, ptr); + rv = func(map->data[i], ptr); if (rv != 0) { return rv; } @@ -78,176 +74,228 @@ int ngtcp2_map_each(const ngtcp2_map *map, int (*func)(void *data, void *ptr), return 0; } -static size_t map_hash(const ngtcp2_map *map, ngtcp2_map_key_type key) { - /* hasher from - https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs - We do not perform finalization here because we use top bits - anyway. */ - key += map->seed; - key *= 0xf1357aea2e62a9c5ull; - return (size_t)((key * 11400714819323198485llu) >> (64 - map->hashbits)); -} - -static void map_bucket_swap(ngtcp2_map_bucket *a, ngtcp2_map_bucket *b) { - ngtcp2_map_bucket c = *a; +/* Hasher from + https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs + to maximize the output's sensitivity to all input bits. */ +#define NGTCP2_MAP_HASHER 0xf1357aea2e62a9c5ull +/* 64-bit Fibonacci hashing constant, Golden Ratio constant, to get + the high bits with the good distribution. */ +#define NGTCP2_MAP_FIBO 0x9e3779b97f4a7c15ull - *a = *b; - *b = c; +static size_t map_index(const ngtcp2_map *map, ngtcp2_map_key_type key) { + key += map->seed; + key *= NGTCP2_MAP_HASHER; + return (size_t)((key * NGTCP2_MAP_FIBO) >> (64 - map->hashbits)); } #ifndef WIN32 void ngtcp2_map_print_distance(const ngtcp2_map *map) { size_t i; size_t idx; - ngtcp2_map_bucket *bkt; size_t tablelen; if (map->size == 0) { return; } - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - - if (bkt->data == NULL) { + if (map->psl[i] == 0) { fprintf(stderr, "@%zu \n", i); continue; } - idx = map_hash(map, bkt->key); - fprintf(stderr, "@%zu hash=%zu key=%" PRIu64 " base=%zu distance=%u\n", i, - map_hash(map, bkt->key), bkt->key, idx, bkt->psl); + idx = map_index(map, map->keys[i]); + fprintf(stderr, "@%zu key=%" PRIu64 " base=%zu distance=%u\n", i, + map->keys[i], idx, map->psl[i] - 1); } } #endif /* !defined(WIN32) */ -static int map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data) { - size_t idx = map_hash(map, key); - ngtcp2_map_bucket b = { - .key = key, - .data = data, - }; - ngtcp2_map_bucket *bkt; - size_t mask = (1u << map->hashbits) - 1; +static void map_set_entry(ngtcp2_map *map, size_t idx, ngtcp2_map_key_type key, + void *data, size_t psl) { + map->keys[idx] = key; + map->data[idx] = data; + map->psl[idx] = (uint8_t)psl; +} + +#define NGTCP2_SWAP(TYPE, A, B) \ + do { \ + TYPE t = (TYPE) * (A); \ + \ + *(A) = *(B); \ + *(B) = t; \ + } while (0) + +/* + * map_insert inserts |key| and |data| to |map|, and returns the index + * where the pair is stored if it succeeds. Otherwise, it returns one + * of the following negative error codes: + * + * NGTCP2_ERR_INVALID_ARGUMENT + * The another data associated to |key| is already present. + */ +static ngtcp2_ssize map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, + void *data) { + size_t idx = map_index(map, key); + size_t mask = ((size_t)1 << map->hashbits) - 1; + size_t psl = 1; + size_t kpsl; for (;;) { - bkt = &map->table[idx]; + kpsl = map->psl[idx]; - if (bkt->data == NULL) { - *bkt = b; + if (kpsl == 0) { + map_set_entry(map, idx, key, data, psl); ++map->size; - return 0; + + return (ngtcp2_ssize)idx; } - if (b.psl > bkt->psl) { - map_bucket_swap(bkt, &b); - } else if (bkt->key == key) { - /* TODO This check is just a waste after first swap or if this - function is called from map_resize. That said, there is no - difference with or without this conditional in performance - wise. */ + if (psl > kpsl) { + NGTCP2_SWAP(ngtcp2_map_key_type, &key, &map->keys[idx]); + NGTCP2_SWAP(void *, &data, &map->data[idx]); + NGTCP2_SWAP(uint8_t, &psl, &map->psl[idx]); + } else if (map->keys[idx] == key) { + /* This check ensures that no duplicate keys are inserted. But + it is just a waste after first swap or if this function is + called from map_resize. That said, there is no difference + with or without this conditional in performance wise. */ return NGTCP2_ERR_INVALID_ARGUMENT; } - ++b.psl; + ++psl; idx = (idx + 1) & mask; } } +/* NGTCP2_MAP_MAX_HASHBITS is the maximum number of bits used for hash + table. The theoretical limit of the maximum number of keys that + can be stored is 1 << NGTCP2_MAP_MAX_HASHBITS. */ +#define NGTCP2_MAP_MAX_HASHBITS (sizeof(size_t) * 8 - 1) + static int map_resize(ngtcp2_map *map, size_t new_hashbits) { size_t i; - ngtcp2_map_bucket *bkt; size_t tablelen; - int rv; + ngtcp2_ssize idx; ngtcp2_map new_map = { - .table = ngtcp2_mem_calloc(map->mem, 1u << new_hashbits, - sizeof(ngtcp2_map_bucket)), .mem = map->mem, .seed = map->seed, .hashbits = new_hashbits, }; - (void)rv; + void *buf; + (void)idx; - if (new_map.table == NULL) { + if (new_hashbits > NGTCP2_MAP_MAX_HASHBITS) { return NGTCP2_ERR_NOMEM; } + tablelen = (size_t)1 << new_hashbits; + + buf = ngtcp2_mem_calloc(map->mem, tablelen, + sizeof(ngtcp2_map_key_type) + sizeof(void *) + + sizeof(uint8_t)); + if (buf == NULL) { + return NGTCP2_ERR_NOMEM; + } + + new_map.keys = buf; + new_map.data = + (void *)((uint8_t *)new_map.keys + tablelen * sizeof(ngtcp2_map_key_type)); + new_map.psl = (uint8_t *)new_map.data + tablelen * sizeof(void *); + if (map->size) { - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - if (bkt->data == NULL) { + if (map->psl[i] == 0) { continue; } - rv = map_insert(&new_map, bkt->key, bkt->data); + idx = map_insert(&new_map, map->keys[i], map->data[i]); - assert(0 == rv); + /* map_insert must not fail because all keys are unique during + resize. */ + assert(idx >= 0); } } - ngtcp2_mem_free(map->mem, map->table); - map->table = new_map.table; + ngtcp2_mem_free(map->mem, map->keys); + map->keys = new_map.keys; + map->data = new_map.data; + map->psl = new_map.psl; map->hashbits = new_hashbits; return 0; } +/* NGTCP2_MAX_PSL_RESIZE_THRESH is the maximum psl threshold. If + reached, resize the table. */ +#define NGTCP2_MAX_PSL_RESIZE_THRESH 128 + int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data) { int rv; + size_t tablelen; + ngtcp2_ssize idx; assert(data); - /* Load factor is 7/8 */ - /* Under the very initial condition, that is map->size == 0 and - map->hashbits == 0, 8 > 7 still holds nicely. */ - if ((map->size + 1) * 8 > (1u << map->hashbits) * 7) { - if (map->hashbits) { - rv = map_resize(map, map->hashbits + 1); - if (rv != 0) { - return rv; - } - } else { - rv = map_resize(map, NGTCP2_INITIAL_HASHBITS); - if (rv != 0) { - return rv; - } + /* tablelen is incorrect if map->hashbits == 0 which leads to + tablelen = 1, but it is only used to check the load factor, and + it works in this special case. */ + tablelen = (size_t)1 << map->hashbits; + + /* Load factor is 7 / 8. Because tablelen is power of 2, (tablelen + - (tablelen >> 3)) computes tablelen * 7 / 8. */ + if (map->size + 1 >= (tablelen - (tablelen >> 3))) { + rv = map_resize(map, map->hashbits ? map->hashbits + 1 + : NGTCP2_INITIAL_HASHBITS); + if (rv != 0) { + return rv; } + + idx = map_insert(map, key, data); + if (idx < 0) { + return (int)idx; + } + + return 0; } - rv = map_insert(map, key, data); - if (rv != 0) { - return rv; + idx = map_insert(map, key, data); + if (idx < 0) { + return (int)idx; } - return 0; + /* Resize if psl reaches really large value which is almost + improbable, but just in case. */ + if (map->psl[idx] - 1 < NGTCP2_MAX_PSL_RESIZE_THRESH) { + return 0; + } + + return map_resize(map, map->hashbits + 1); } void *ngtcp2_map_find(const ngtcp2_map *map, ngtcp2_map_key_type key) { size_t idx; - ngtcp2_map_bucket *bkt; - size_t psl = 0; + size_t psl = 1; size_t mask; if (map->size == 0) { return NULL; } - idx = map_hash(map, key); - mask = (1u << map->hashbits) - 1; + idx = map_index(map, key); + mask = ((size_t)1 << map->hashbits) - 1; for (;;) { - bkt = &map->table[idx]; - - if (bkt->data == NULL || psl > bkt->psl) { + if (psl > map->psl[idx]) { return NULL; } - if (bkt->key == key) { - return bkt->data; + if (map->keys[idx] == key) { + return map->data[idx]; } ++psl; @@ -257,38 +305,36 @@ void *ngtcp2_map_find(const ngtcp2_map *map, ngtcp2_map_key_type key) { int ngtcp2_map_remove(ngtcp2_map *map, ngtcp2_map_key_type key) { size_t idx; - ngtcp2_map_bucket *b, *bkt; - size_t psl = 0; + size_t dest; + size_t psl = 1, kpsl; size_t mask; if (map->size == 0) { return NGTCP2_ERR_INVALID_ARGUMENT; } - idx = map_hash(map, key); - mask = (1u << map->hashbits) - 1; + idx = map_index(map, key); + mask = ((size_t)1 << map->hashbits) - 1; for (;;) { - bkt = &map->table[idx]; - - if (bkt->data == NULL || psl > bkt->psl) { + if (psl > map->psl[idx]) { return NGTCP2_ERR_INVALID_ARGUMENT; } - if (bkt->key == key) { - b = bkt; + if (map->keys[idx] == key) { + dest = idx; idx = (idx + 1) & mask; for (;;) { - bkt = &map->table[idx]; - if (bkt->data == NULL || bkt->psl == 0) { - b->data = NULL; + kpsl = map->psl[idx]; + if (kpsl <= 1) { + map->psl[dest] = 0; break; } - --bkt->psl; - *b = *bkt; - b = bkt; + map_set_entry(map, dest, map->keys[idx], map->data[idx], kpsl - 1); + + dest = idx; idx = (idx + 1) & mask; } @@ -308,7 +354,7 @@ void ngtcp2_map_clear(ngtcp2_map *map) { return; } - memset(map->table, 0, sizeof(*map->table) * (1u << map->hashbits)); + memset(map->psl, 0, sizeof(*map->psl) * ((size_t)1 << map->hashbits)); map->size = 0; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h index 0c1a76552aa4c4..1afe3167e65b85 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.h @@ -38,14 +38,13 @@ typedef uint64_t ngtcp2_map_key_type; -typedef struct ngtcp2_map_bucket { - uint32_t psl; - ngtcp2_map_key_type key; - void *data; -} ngtcp2_map_bucket; - typedef struct ngtcp2_map { - ngtcp2_map_bucket *table; + ngtcp2_map_key_type *keys; + void **data; + /* psl is the Probe Sequence Length. 0 has special meaning that the + element is not stored at i-th position if psl[i] == 0. Because + of this, the actual psl value is psl[i] - 1 if psl[i] > 0. */ + uint8_t *psl; const ngtcp2_mem *mem; uint64_t seed; size_t size; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.c index 83238730033537..c9636a8db9a90f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.c @@ -28,12 +28,6 @@ #include "ngtcp2_addr.h" -void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local, - const ngtcp2_addr *remote) { - path->local = *local; - path->remote = *remote; -} - void ngtcp2_path_copy(ngtcp2_path *dest, const ngtcp2_path *src) { ngtcp2_addr_copy(&dest->local, &src->local); ngtcp2_addr_copy(&dest->remote, &src->remote); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h index a708378db32fbb..9d4205cee2279f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_path.h @@ -31,14 +31,6 @@ #include -/* - * ngtcp2_path_init initializes |path| with the given addresses. Note - * that the buffer pointed by local->addr and remote->addr are not - * copied. Their pointer values are assigned instead. - */ -void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local, - const ngtcp2_addr *remote); - /* * ngtcp2_path_storage_init2 initializes |ps| using |path| as initial * data. diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pcg.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pcg.c index 9d0eb57e0db940..c8490467e43614 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pcg.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pcg.c @@ -66,7 +66,7 @@ void ngtcp2_pcg32_init(ngtcp2_pcg32 *pcg, uint64_t seed) { } static uint32_t pcg_rotr_32(uint32_t value, unsigned int rot) { - return (value >> rot) | (value << ((-rot) & 31)); + return (value >> rot) | (value << ((32 - rot) & 31)); } static uint32_t pcg_output_xsh_rr_64_32(uint64_t state) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c index d63dc932e1bfb4..9c0e2636bcc051 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.c @@ -482,8 +482,10 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen, return (ngtcp2_ssize)len; } -ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, - size_t payloadlen) { +ngtcp2_ssize ngtcp2_frame_decoder_decode(ngtcp2_frame_decoder *frd, + ngtcp2_frame *dest, + const uint8_t *payload, + size_t payloadlen) { uint8_t type; if (payloadlen == 0) { @@ -532,6 +534,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, payloadlen); case NGTCP2_FRAME_ACK: case NGTCP2_FRAME_ACK_ECN: + dest->ack.ranges = frd->buf.ack_ranges; return ngtcp2_pkt_decode_ack_frame(&dest->ack, payload, payloadlen); case NGTCP2_FRAME_PATH_CHALLENGE: return ngtcp2_pkt_decode_path_challenge_frame(&dest->path_challenge, @@ -540,6 +543,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, return ngtcp2_pkt_decode_path_response_frame(&dest->path_response, payload, payloadlen); case NGTCP2_FRAME_CRYPTO: + dest->stream.data = &frd->buf.stream_data; return ngtcp2_pkt_decode_crypto_frame(&dest->stream, payload, payloadlen); case NGTCP2_FRAME_NEW_TOKEN: return ngtcp2_pkt_decode_new_token_frame(&dest->new_token, payload, @@ -556,6 +560,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, payloadlen); default: if ((type & ~(NGTCP2_FRAME_STREAM - 1)) == NGTCP2_FRAME_STREAM) { + dest->stream.data = &frd->buf.stream_data; return ngtcp2_pkt_decode_stream_frame(&dest->stream, payload, payloadlen); } @@ -918,7 +923,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame( return NGTCP2_ERR_FRAME_ENCODING; } - p = ngtcp2_get_uvarint(&vi, p); + ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1053,6 +1058,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_ping_frame(ngtcp2_ping *dest, (void)payload; (void)payloadlen; + assert(payloadlen > 0); + dest->type = NGTCP2_FRAME_PING; return 1; } @@ -1321,7 +1328,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_stream *dest, return NGTCP2_ERR_FRAME_ENCODING; } - p = ngtcp2_get_uvarint(&vi, p); + ngtcp2_get_uvarint(&vi, p); if (payloadlen - len < vi) { return NGTCP2_ERR_FRAME_ENCODING; } @@ -1428,6 +1435,8 @@ ngtcp2_ssize ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done *dest, (void)payload; (void)payloadlen; + assert(payloadlen > 0); + dest->type = NGTCP2_FRAME_HANDSHAKE_DONE; return 1; } @@ -1442,9 +1451,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest, size_t n; uint64_t vi; - if (payloadlen < len) { - return NGTCP2_ERR_FRAME_ENCODING; - } + assert(payloadlen > 0); type = payload[0]; @@ -1502,7 +1509,7 @@ ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest, ngtcp2_ssize ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen, ngtcp2_frame *fr) { - switch (fr->type) { + switch (fr->hd.type) { case NGTCP2_FRAME_STREAM: return ngtcp2_pkt_encode_stream_frame(out, outlen, &fr->stream); case NGTCP2_FRAME_ACK: diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h index ed358dc48d5cae..78fcd6dcc2b54d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_pkt.h @@ -103,10 +103,6 @@ /* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */ #define NGTCP2_RETRY_TAGLEN 16 -/* NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE is the maximum UDP datagram - payload size that this library can write. */ -#define NGTCP2_HARD_MAX_UDP_PAYLOAD_SIZE ((1 << 24) - 1) - /* NGTCP2_PKT_LENGTHLEN is the number of bytes that is occupied by Length field in Long packet header. */ #define NGTCP2_PKT_LENGTHLEN 4 @@ -184,6 +180,10 @@ typedef struct ngtcp2_pkt_retry { #define NGTCP2_FRAME_DATAGRAM 0x30 #define NGTCP2_FRAME_DATAGRAM_LEN 0x31 +typedef struct ngtcp2_frame_hd { + uint64_t type; +} ngtcp2_frame_hd; + /* ngtcp2_stream represents STREAM and CRYPTO frames. */ typedef struct ngtcp2_stream { uint64_t type; @@ -195,7 +195,7 @@ typedef struct ngtcp2_stream { uint8_t flags; /* CRYPTO frame does not include this field, and must set it to 0. */ - uint8_t fin; + int fin; /* CRYPTO frame does not include this field, and must set it to 0. */ int64_t stream_id; @@ -204,8 +204,9 @@ typedef struct ngtcp2_stream { the length of data is 1 in this definition, the library may allocate extra bytes to hold more elements. */ size_t datacnt; - /* data is the array of ngtcp2_vec which references data. */ - ngtcp2_vec data[1]; + /* data points to ngtcp2_vec array which references data. If + datacnt == 0, this field may be NULL. */ + ngtcp2_vec *data; } ngtcp2_stream; typedef struct ngtcp2_ack_range { @@ -229,7 +230,7 @@ typedef struct ngtcp2_ack { } ecn; uint64_t first_ack_range; size_t rangecnt; - ngtcp2_ack_range ranges[1]; + ngtcp2_ack_range *ranges; } ngtcp2_ack; typedef struct ngtcp2_padding { @@ -349,7 +350,7 @@ typedef struct ngtcp2_datagram { } ngtcp2_datagram; typedef union ngtcp2_frame { - uint64_t type; + ngtcp2_frame_hd hd; ngtcp2_stream stream; ngtcp2_ack ack; ngtcp2_padding padding; @@ -370,11 +371,6 @@ typedef union ngtcp2_frame { ngtcp2_retire_connection_id retire_connection_id; ngtcp2_handshake_done handshake_done; ngtcp2_datagram datagram; - /* Extend ngtcp2_frame so that ngtcp2_stream has at least additional - 3 ngtcp2_vec, totaling 4 slots, which can store HEADERS header, - HEADERS payload, DATA header, and DATA payload in the standard - sized ngtcp2_frame_chain. */ - uint8_t pad[sizeof(ngtcp2_stream) + sizeof(ngtcp2_vec) * 3]; } ngtcp2_frame; typedef struct ngtcp2_pkt_chain ngtcp2_pkt_chain; @@ -454,10 +450,22 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen, ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen, const ngtcp2_pkt_hd *hd); +/* + * ngtcp2_frame_decoder is QUIC frame decoder. For frames that + * require the external buffers (e.g., ngtcp2_stream and ngtcp2_ack), + * it provides those buffers on demand. + */ +typedef struct ngtcp2_frame_decoder { + union { + ngtcp2_vec stream_data; + ngtcp2_ack_range ack_ranges[NGTCP2_MAX_ACK_RANGES]; + } buf; +} ngtcp2_frame_decoder; + /** * @function * - * `ngtcp2_pkt_decode_frame` decodes a QUIC frame from the buffer + * `ngtcp2_frame_decoder_decode` decodes a QUIC frame from the buffer * pointed by |payload| whose length is |payloadlen|. * * This function returns the number of bytes read to decode a single @@ -467,8 +475,10 @@ ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen, * Frame is badly formatted; or frame type is unknown; or * |payloadlen| is 0. */ -ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload, - size_t payloadlen); +ngtcp2_ssize ngtcp2_frame_decoder_decode(ngtcp2_frame_decoder *frd, + ngtcp2_frame *dest, + const uint8_t *payload, + size_t payloadlen); /** * @function diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c index c0f920746a4dff..f0c67acdd51b37 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_qlog.c @@ -55,15 +55,9 @@ static uint8_t *write_string_impl(uint8_t *p, const uint8_t *data, #define write_string(DEST, S) \ write_string_impl((DEST), (const uint8_t *)(S), sizeof(S) - 1) -#define NGTCP2_LOWER_XDIGITS "0123456789abcdef" - static uint8_t *write_hex(uint8_t *p, const uint8_t *data, size_t datalen) { - const uint8_t *b = data, *end = data + datalen; *p++ = '"'; - for (; b != end; ++b) { - *p++ = (uint8_t)NGTCP2_LOWER_XDIGITS[*b >> 4]; - *p++ = (uint8_t)NGTCP2_LOWER_XDIGITS[*b & 0xf]; - } + p = ngtcp2_encode_hex(p, data, datalen); *p++ = '"'; return p; } @@ -72,31 +66,12 @@ static uint8_t *write_cid(uint8_t *p, const ngtcp2_cid *cid) { return write_hex(p, cid->data, cid->datalen); } -static uint8_t *write_number(uint8_t *p, uint64_t n) { - size_t nlen = 0; - uint64_t t; - uint8_t *res; - - if (n == 0) { - *p++ = '0'; - return p; - } - for (t = n; t; t /= 10, ++nlen) - ; - p += nlen; - res = p; - for (; n; n /= 10) { - *--p = (uint8_t)((n % 10) + '0'); - } - return res; -} - static uint8_t *write_tstamp(uint8_t *p, ngtcp2_tstamp ts) { - return write_number(p, ts / NGTCP2_MILLISECONDS); + return ngtcp2_encode_uint(p, ts / NGTCP2_MILLISECONDS); } static uint8_t *write_duration(uint8_t *p, ngtcp2_duration duration) { - return write_number(p, duration / NGTCP2_MILLISECONDS); + return ngtcp2_encode_uint(p, duration / NGTCP2_MILLISECONDS); } static uint8_t *write_bool(uint8_t *p, int b) { @@ -132,7 +107,7 @@ static uint8_t *write_pair_number_impl(uint8_t *p, const uint8_t *name, size_t namelen, uint64_t value) { p = write_string_impl(p, name, namelen); *p++ = ':'; - return write_number(p, value); + return ngtcp2_encode_uint(p, value); } #define write_pair_number(DEST, NAME, VALUE) \ @@ -227,25 +202,24 @@ void ngtcp2_qlog_start(ngtcp2_qlog *qlog, const ngtcp2_cid *odcid, int server) { } void ngtcp2_qlog_end(ngtcp2_qlog *qlog) { - uint8_t buf[1] = {0}; - if (!qlog->write) { return; } - qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_FIN, &buf, 0); + qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_FIN, "", 0); } -static ngtcp2_vec vec_pkt_type_initial = ngtcp2_make_vec_lit("initial"); -static ngtcp2_vec vec_pkt_type_handshake = ngtcp2_make_vec_lit("handshake"); -static ngtcp2_vec vec_pkt_type_0rtt = ngtcp2_make_vec_lit("0RTT"); -static ngtcp2_vec vec_pkt_type_1rtt = ngtcp2_make_vec_lit("1RTT"); -static ngtcp2_vec vec_pkt_type_retry = ngtcp2_make_vec_lit("retry"); -static ngtcp2_vec vec_pkt_type_version_negotiation = +static const ngtcp2_vec vec_pkt_type_initial = ngtcp2_make_vec_lit("initial"); +static const ngtcp2_vec vec_pkt_type_handshake = + ngtcp2_make_vec_lit("handshake"); +static const ngtcp2_vec vec_pkt_type_0rtt = ngtcp2_make_vec_lit("0RTT"); +static const ngtcp2_vec vec_pkt_type_1rtt = ngtcp2_make_vec_lit("1RTT"); +static const ngtcp2_vec vec_pkt_type_retry = ngtcp2_make_vec_lit("retry"); +static const ngtcp2_vec vec_pkt_type_version_negotiation = ngtcp2_make_vec_lit("version_negotiation"); -static ngtcp2_vec vec_pkt_type_stateless_reset = +static const ngtcp2_vec vec_pkt_type_stateless_reset = ngtcp2_make_vec_lit("stateless_reset"); -static ngtcp2_vec vec_pkt_type_unknown = ngtcp2_make_vec_lit("unknown"); +static const ngtcp2_vec vec_pkt_type_unknown = ngtcp2_make_vec_lit("unknown"); static const ngtcp2_vec *qlog_pkt_type(const ngtcp2_pkt_hd *hd) { if (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM) { @@ -340,10 +314,10 @@ static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) { min_ack = fr->largest_ack - (int64_t)fr->first_ack_range; *p++ = '['; - p = write_number(p, (uint64_t)min_ack); + p = ngtcp2_encode_uint(p, (uint64_t)min_ack); if (largest_ack != min_ack) { *p++ = ','; - p = write_number(p, (uint64_t)largest_ack); + p = ngtcp2_encode_uint(p, (uint64_t)largest_ack); } *p++ = ']'; @@ -353,10 +327,10 @@ static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) { min_ack = largest_ack - (int64_t)range->len; *p++ = ','; *p++ = '['; - p = write_number(p, (uint64_t)min_ack); + p = ngtcp2_encode_uint(p, (uint64_t)min_ack); if (largest_ack != min_ack) { *p++ = ','; - p = write_number(p, (uint64_t)largest_ack); + p = ngtcp2_encode_uint(p, (uint64_t)largest_ack); } *p++ = ']'; } @@ -738,7 +712,7 @@ static void qlog_pkt_write_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd, p = write_verbatim(p, "],\"header\":"); p = write_pkt_hd(p, hd); p = write_verbatim(p, ",\"raw\":{\"length\":"); - p = write_number(p, pktlen); + p = ngtcp2_encode_uint(p, pktlen); p = write_verbatim(p, "}}}\n"); qlog->buf.last = p; @@ -754,7 +728,7 @@ void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) { return; } - switch (fr->type) { + switch (fr->hd.type) { case NGTCP2_FRAME_PADDING: if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_PADDING_FRAME_OVERHEAD + 1) { return; @@ -771,7 +745,7 @@ void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) { case NGTCP2_FRAME_ACK_ECN: if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_ACK_FRAME_BASE_OVERHEAD + - (size_t)(fr->type == NGTCP2_FRAME_ACK_ECN + (size_t)(fr->ack.type == NGTCP2_FRAME_ACK_ECN ? NGTCP2_QLOG_ACK_FRAME_ECN_OVERHEAD : 0) + NGTCP2_QLOG_ACK_FRAME_RANGE_OVERHEAD * (1 + fr->ack.rangecnt) + 1) { @@ -1095,7 +1069,6 @@ void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog, void ngtcp2_qlog_pkt_lost(ngtcp2_qlog *qlog, ngtcp2_rtb_entry *ent) { uint8_t buf[256]; uint8_t *p = buf; - ngtcp2_pkt_hd hd = {0}; if (!qlog->write) { return; @@ -1107,11 +1080,11 @@ void ngtcp2_qlog_pkt_lost(ngtcp2_qlog *qlog, ngtcp2_rtb_entry *ent) { p = write_verbatim( p, ",\"name\":\"recovery:packet_lost\",\"data\":{\"header\":"); - hd.type = ent->hd.type; - hd.flags = ent->hd.flags; - hd.pkt_num = ent->hd.pkt_num; - - p = write_pkt_hd(p, &hd); + p = write_pkt_hd(p, &(ngtcp2_pkt_hd){ + .pkt_num = ent->hd.pkt_num, + .type = ent->hd.type, + .flags = ent->hd.flags, + }); p = write_verbatim(p, "}}\n"); qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf, @@ -1154,20 +1127,19 @@ void ngtcp2_qlog_stateless_reset_pkt_received( ngtcp2_qlog *qlog, const ngtcp2_pkt_stateless_reset *sr) { uint8_t buf[256]; uint8_t *p = buf; - ngtcp2_pkt_hd hd = {0}; if (!qlog->write) { return; } - hd.type = NGTCP2_PKT_STATELESS_RESET; - *p++ = '\x1e'; *p++ = '{'; p = qlog_write_time(qlog, p); p = write_verbatim( p, ",\"name\":\"transport:packet_received\",\"data\":{\"header\":"); - p = write_pkt_hd(p, &hd); + p = write_pkt_hd(p, &(ngtcp2_pkt_hd){ + .type = NGTCP2_PKT_STATELESS_RESET, + }); *p++ = ','; p = write_pair_hex(p, "stateless_reset_token", sr->stateless_reset_token, NGTCP2_STATELESS_RESET_TOKENLEN); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c index e89891532936e8..a949a657338e29 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_range.c @@ -26,18 +26,22 @@ #include "ngtcp2_macro.h" void ngtcp2_range_init(ngtcp2_range *r, uint64_t begin, uint64_t end) { - r->begin = begin; - r->end = end; + *r = (ngtcp2_range){ + .begin = begin, + .end = end, + }; } ngtcp2_range ngtcp2_range_intersect(const ngtcp2_range *a, const ngtcp2_range *b) { - ngtcp2_range r = {0}; + ngtcp2_range r; uint64_t begin = ngtcp2_max_uint64(a->begin, b->begin); uint64_t end = ngtcp2_min_uint64(a->end, b->end); if (begin < end) { ngtcp2_range_init(&r, begin, end); + } else { + r = (ngtcp2_range){0}; } return r; @@ -52,10 +56,14 @@ int ngtcp2_range_eq(const ngtcp2_range *a, const ngtcp2_range *b) { void ngtcp2_range_cut(ngtcp2_range *left, ngtcp2_range *right, const ngtcp2_range *a, const ngtcp2_range *b) { /* Assume that b is included in a */ - left->begin = a->begin; - left->end = b->begin; - right->begin = b->end; - right->end = a->end; + *left = (ngtcp2_range){ + .begin = a->begin, + .end = b->begin, + }; + *right = (ngtcp2_range){ + .begin = b->end, + .end = a->end, + }; } int ngtcp2_range_not_after(const ngtcp2_range *a, const ngtcp2_range *b) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ratelim.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ratelim.c index efedc3daa7600f..d13ed9a14aa4bd 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ratelim.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ratelim.c @@ -41,7 +41,7 @@ void ngtcp2_ratelim_init(ngtcp2_ratelim *rlim, uint64_t burst, uint64_t rate, /* ratelim_update updates rlim->tokens with the current |ts|. */ static void ratelim_update(ngtcp2_ratelim *rlim, ngtcp2_tstamp ts) { - uint64_t d, gain; + uint64_t d, gain, gps; assert(ts >= rlim->ts); @@ -52,16 +52,23 @@ static void ratelim_update(ngtcp2_ratelim *rlim, ngtcp2_tstamp ts) { d = ts - rlim->ts; rlim->ts = ts; - gain = rlim->rate * d + rlim->carry; + if (rlim->rate > (UINT64_MAX - rlim->carry) / d) { + gain = UINT64_MAX; + } else { + gain = rlim->rate * d + rlim->carry; + } - rlim->tokens += gain / NGTCP2_SECONDS; + gps = gain / NGTCP2_SECONDS; - if (rlim->tokens < rlim->burst) { + if (gps < rlim->burst && rlim->tokens < rlim->burst - gps) { + rlim->tokens += gps; rlim->carry = gain % NGTCP2_SECONDS; - } else { - rlim->tokens = rlim->burst; - rlim->carry = 0; + + return; } + + rlim->tokens = rlim->burst; + rlim->carry = 0; } int ngtcp2_ratelim_drain(ngtcp2_ratelim *rlim, uint64_t n, ngtcp2_tstamp ts) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ratelim.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ratelim.h index 14485c562d4e32..231f5d1b0182e9 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ratelim.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ratelim.h @@ -28,7 +28,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c index 353afca4d48fb5..40c25f2a3d1cbc 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_ringbuf.c @@ -32,18 +32,8 @@ #include "ngtcp2_macro.h" #ifndef NDEBUG -static int ispow2(size_t n) { -# if defined(_MSC_VER) && !defined(__clang__) && \ - (defined(_M_ARM) || (defined(_M_ARM64) && _MSC_VER < 1941)) - return n && !(n & (n - 1)); -# elif defined(WIN32) - return 1 == __popcnt((unsigned int)n); -# else /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \ - (defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */ - return 1 == __builtin_popcount((unsigned int)n); -# endif /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \ - (defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */ -} +/* Power-of-two test; simple portable bit trick. */ +static int ispow2(size_t n) { return n && !(n & (n - 1)); } #endif /* !defined(NDEBUG) */ int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size, diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c index ef1938ea6326ca..20eae1d8819133 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rob.c @@ -36,8 +36,13 @@ int ngtcp2_rob_gap_new(ngtcp2_rob_gap **pg, uint64_t begin, uint64_t end, return NGTCP2_ERR_NOMEM; } - (*pg)->range.begin = begin; - (*pg)->range.end = end; + **pg = (ngtcp2_rob_gap){ + .range = + { + .begin = begin, + .end = end, + }, + }; return 0; } @@ -53,9 +58,14 @@ int ngtcp2_rob_data_new(ngtcp2_rob_data **pd, uint64_t offset, size_t chunk, return NGTCP2_ERR_NOMEM; } - (*pd)->range.begin = offset; - (*pd)->range.end = offset + chunk; - (*pd)->begin = (uint8_t *)(*pd) + sizeof(ngtcp2_rob_data); + **pd = (ngtcp2_rob_data){ + .range = + { + .begin = offset, + .end = offset + chunk, + }, + .begin = (uint8_t *)(*pd) + sizeof(ngtcp2_rob_data), + }; return 0; } @@ -254,9 +264,11 @@ void ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) { } if (offset < g->range.end) { - ngtcp2_range r = {offset, g->range.end}; - - ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r); + ngtcp2_ksl_update_key(&rob->gapksl, &g->range, + &(ngtcp2_range){ + .begin = offset, + .end = g->range.end, + }); g->range.begin = offset; break; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c index 6f44c8ac8de673..89b395cd954b0d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.c @@ -32,16 +32,11 @@ #include "ngtcp2_conn_stat.h" void ngtcp2_rs_init(ngtcp2_rs *rs) { - rs->interval = UINT64_MAX; - rs->delivered = 0; - rs->prior_delivered = 0; - rs->prior_ts = UINT64_MAX; - rs->tx_in_flight = 0; - rs->lost = 0; - rs->send_elapsed = 0; - rs->ack_elapsed = 0; - rs->last_end_seq = -1; - rs->is_app_limited = 0; + *rs = (ngtcp2_rs){ + .interval = UINT64_MAX, + .prior_ts = UINT64_MAX, + .last_end_seq = -1, + }; } void ngtcp2_rst_init(ngtcp2_rst *rst) { @@ -59,16 +54,27 @@ void ngtcp2_rst_reset(ngtcp2_rst *rst) { rst->lost = 0; } +void ngtcp2_rst_reset_rate_sample(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) { + ngtcp2_rs *rs = &rst->rs; + + rs->interval = UINT64_MAX; + rs->prior_ts = UINT64_MAX; + + cstat->delivery_rate_sec = 0; +} + void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, const ngtcp2_conn_stat *cstat) { - if (cstat->bytes_in_flight == 0) { + /* cstat->bytes_in_flight includes ent->pktlen. If they are the + same, there is no in-flight packets. */ + if (cstat->bytes_in_flight == ent->pktlen) { rst->first_sent_ts = rst->delivered_ts = ent->ts; } ent->rst.first_sent_ts = rst->first_sent_ts; ent->rst.delivered_ts = rst->delivered_ts; ent->rst.delivered = rst->delivered; ent->rst.is_app_limited = rst->app_limited != 0; - ent->rst.tx_in_flight = cstat->bytes_in_flight + ent->pktlen; + ent->rst.tx_in_flight = cstat->bytes_in_flight; ent->rst.lost = rst->lost; ent->rst.end_seq = ++rst->last_seq; } @@ -89,7 +95,6 @@ void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) { rs->delivered = rst->delivered - rs->prior_delivered; if (rs->interval < cstat->min_rtt) { - rs->interval = UINT64_MAX; return; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h index 1bb624de79b53f..b0bc2d06c9ca50 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rst.h @@ -79,6 +79,8 @@ void ngtcp2_rst_init(ngtcp2_rst *rst); void ngtcp2_rst_reset(ngtcp2_rst *rst); +void ngtcp2_rst_reset_rate_sample(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat); + void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent, const ngtcp2_conn_stat *cstat); void ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat); diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c index 7df1c197db79d7..88ec585e69d185 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -128,13 +128,12 @@ void ngtcp2_rtb_free(ngtcp2_rtb *rtb) { static void rtb_on_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, ngtcp2_conn_stat *cstat) { - ngtcp2_rst_on_pkt_sent(rtb->rst, ent, cstat); - assert(rtb->cc_pkt_num <= ent->hd.pkt_num); cstat->bytes_in_flight += ent->pktlen; rtb->cc_bytes_in_flight += ent->pktlen; + ngtcp2_rst_on_pkt_sent(rtb->rst, ent, cstat); ngtcp2_rst_update_app_limited(rtb->rst, cstat); if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { @@ -234,7 +233,7 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, continue; } - switch (frc->fr.type) { + switch (frc->fr.hd.type) { case NGTCP2_FRAME_STREAM: strm = ngtcp2_conn_find_stream(conn, fr->stream.stream_id); if (strm == NULL || (strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM)) { @@ -272,7 +271,12 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, return rv; } - nfrc->fr = *fr; + nfrc->fr.stream.type = fr->stream.type; + nfrc->fr.stream.flags = fr->stream.flags; + nfrc->fr.stream.fin = fr->stream.fin; + nfrc->fr.stream.stream_id = fr->stream.stream_id; + nfrc->fr.stream.offset = fr->stream.offset; + nfrc->fr.stream.datacnt = fr->stream.datacnt; ngtcp2_vec_copy(nfrc->fr.stream.data, fr->stream.data, fr->stream.datacnt); @@ -315,7 +319,12 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, return rv; } - nfrc->fr = *fr; + nfrc->fr.stream.type = fr->stream.type; + nfrc->fr.stream.flags = 0; + nfrc->fr.stream.fin = 0; + nfrc->fr.stream.stream_id = 0; + nfrc->fr.stream.offset = fr->stream.offset; + nfrc->fr.stream.datacnt = fr->stream.datacnt; ngtcp2_vec_copy(nfrc->fr.stream.data, fr->stream.data, fr->stream.datacnt); @@ -416,7 +425,7 @@ static int conn_process_lost_datagram(ngtcp2_conn *conn, int rv; for (frc = ent->frc; frc; frc = frc->next) { - switch (frc->fr.type) { + switch (frc->fr.hd.type) { case NGTCP2_FRAME_DATAGRAM: case NGTCP2_FRAME_DATAGRAM_LEN: assert(conn->callbacks.lost_datagram); @@ -454,23 +463,28 @@ static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, if (ent->flags & (NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE | NGTCP2_RTB_ENTRY_FLAG_SKIP)) { ++rtb->num_lost_ignore_pkts; - } else if (ent->hd.pkt_num >= rtb->cc_pkt_num) { - rtb->rst->lost += ent->pktlen; - - if (rtb->cc->on_pkt_lost) { - cc->on_pkt_lost(cc, cstat, - ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen, - pktns->id, ent->ts, ent->rst.lost, - ent->rst.tx_in_flight, - ent->rst.is_app_limited), - ts); + } else { + ++cstat->pkt_lost; + cstat->bytes_lost += ent->pktlen; + + if (ent->hd.pkt_num >= rtb->cc_pkt_num) { + rtb->rst->lost += ent->pktlen; + + if (rtb->cc->on_pkt_lost) { + cc->on_pkt_lost(cc, cstat, + ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen, + pktns->id, ent->ts, ent->rst.lost, + ent->rst.tx_in_flight, + ent->rst.is_app_limited), + ts); + } } } if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, - "pkn=%" PRId64 " has already been reclaimed on PTO", - ent->hd.pkt_num); + ngtcp2_log_infof(rtb->log, NGTCP2_LOG_EVENT_LDC, + "pkn=%" PRId64 " has already been reclaimed on PTO", + ent->hd.pkt_num); assert(!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED)); assert(UINT64_MAX == ent->lost_ts); } else { @@ -527,9 +541,10 @@ static void rtb_remove(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it, int rv; (void)rv; + rtb_on_remove(rtb, ent, cstat); + rv = ngtcp2_ksl_remove_hint(&rtb->ents, it, it, &ent->hd.pkt_num); assert(0 == rv); - rtb_on_remove(rtb, ent, cstat); assert(ent->next == NULL); @@ -598,7 +613,7 @@ static int process_acked_pkt(ngtcp2_rtb_entry *ent, ngtcp2_conn *conn, frc->binder->flags |= NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK; } - switch (frc->fr.type) { + switch (frc->fr.hd.type) { case NGTCP2_FRAME_STREAM: strm = ngtcp2_conn_find_stream(conn, frc->fr.stream.stream_id); if (strm == NULL) { @@ -733,8 +748,7 @@ static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, const ngtcp2_ack *fr, size_t ecn_acked, - ngtcp2_tstamp largest_pkt_sent_ts, - ngtcp2_tstamp ts) { + const ngtcp2_cc_ack *cc_ack, ngtcp2_tstamp ts) { if (conn->tx.ecn.state == NGTCP2_ECN_STATE_FAILED) { return; } @@ -761,9 +775,9 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, } if (fr->type == NGTCP2_FRAME_ACK_ECN) { - if (cc->congestion_event && largest_pkt_sent_ts != UINT64_MAX && + if (cc->congestion_event && cc_ack->largest_pkt_sent_ts != UINT64_MAX && fr->ecn.ce > pktns->acktr.ecn.ack.ce) { - cc->congestion_event(cc, cstat, largest_pkt_sent_ts, 0, ts); + cc->congestion_event(cc, cstat, cc_ack->largest_pkt_sent_ts, cc_ack, ts); } pktns->acktr.ecn.ack.ect0 = fr->ecn.ect0; @@ -772,7 +786,7 @@ static void conn_verify_ecn(ngtcp2_conn *conn, ngtcp2_pktns *pktns, } } -static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, +static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_cc_ack *cc_ack, ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts); @@ -786,19 +800,18 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, int rv; ngtcp2_ksl_it it; size_t num_acked = 0; - ngtcp2_tstamp largest_pkt_sent_ts = UINT64_MAX; int64_t pkt_num; ngtcp2_cc *cc = rtb->cc; ngtcp2_rtb_entry *acked_ent = NULL; int ack_eliciting_pkt_acked = 0; size_t ecn_acked = 0; int verify_ecn = 0; - ngtcp2_cc_ack cc_ack = {0}; + ngtcp2_cc_ack cc_ack = { + .largest_pkt_sent_ts = UINT64_MAX, + .rtt = UINT64_MAX, + }; size_t num_lost_pkts = rtb->num_lost_pkts - rtb->num_lost_ignore_pkts; - cc_ack.prior_bytes_in_flight = cstat->bytes_in_flight; - cc_ack.rtt = UINT64_MAX; - if (conn && (conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) && (conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_INITIATOR) && largest_ack >= conn->pktns.crypto.tx.ckm->pkt_num) { @@ -814,12 +827,17 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, verify_ecn = 1; } + ngtcp2_rst_reset_rate_sample(rtb->rst, cstat); + /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */ it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack); if (ngtcp2_ksl_it_end(&it)) { if (conn && verify_ecn) { - conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, - largest_pkt_sent_ts, ts); + conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, &cc_ack, ts); + } + + if (cc->on_ack_recv) { + cc->on_ack_recv(cc, cstat, &cc_ack, ts); } return 0; @@ -843,8 +861,8 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, goto fail; } - if (largest_ack == pkt_num) { - largest_pkt_sent_ts = ent->ts; + if (rtb->largest_acked_tx_pkt_num == pkt_num) { + cc_ack.largest_pkt_sent_ts = ent->ts; } if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) { @@ -884,15 +902,11 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, } } - if (largest_pkt_sent_ts != UINT64_MAX && ack_eliciting_pkt_acked) { - cc_ack.rtt = - ngtcp2_max_uint64(pkt_ts - largest_pkt_sent_ts, NGTCP2_NANOSECONDS); + if (cc_ack.largest_pkt_sent_ts != UINT64_MAX && ack_eliciting_pkt_acked) { + cc_ack.rtt = ngtcp2_max_uint64(pkt_ts - cc_ack.largest_pkt_sent_ts, + NGTCP2_NANOSECONDS); - rv = ngtcp2_conn_update_rtt(conn, cc_ack.rtt, fr->ack_delay_unscaled, ts); - if (rv == 0 && cc->new_rtt_sample && - rtb->largest_acked_tx_pkt_num >= rtb->cc_pkt_num) { - cc->new_rtt_sample(cc, cstat, ts); - } + ngtcp2_conn_update_rtt(conn, cc_ack.rtt, fr->ack_delay_unscaled, ts); } if (conn) { @@ -922,11 +936,6 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, rtb->frc_objalloc, rtb->mem); } - - if (verify_ecn) { - conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, - largest_pkt_sent_ts, ts); - } } else { /* For unit tests */ for (ent = acked_ent; ent; ent = acked_ent) { @@ -947,15 +956,18 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr, ngtcp2_rst_on_ack_recv(rtb->rst, cstat); if (conn) { - rv = rtb_detect_lost_pkt(rtb, &cc_ack.bytes_lost, conn, pktns, cstat, ts); + rv = rtb_detect_lost_pkt(rtb, &cc_ack, conn, pktns, cstat, ts); if (rv != 0) { return rv; } } } - cc_ack.largest_pkt_sent_ts = largest_pkt_sent_ts; - if (num_acked && cc->on_ack_recv) { + if (conn && verify_ecn) { + conn_verify_ecn(conn, pktns, rtb->cc, cstat, fr, ecn_acked, &cc_ack, ts); + } + + if (cc->on_ack_recv) { cc->on_ack_recv(cc, cstat, &cc_ack, ts); } @@ -1021,7 +1033,11 @@ static int conn_all_ecn_pkt_lost(ngtcp2_conn *conn) { pktns->tx.ecn.validation_pkt_sent == pktns->tx.ecn.validation_pkt_lost; } -static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, +/* + * This function assigns the number of bytes lost to + * |cc_ack|->bytes_lost if any. + */ +static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_cc_ack *cc_ack, ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { ngtcp2_rtb_entry *ent; @@ -1139,8 +1155,10 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, break; } + cc_ack->bytes_lost = bytes_lost; + if (cc->congestion_event) { - cc->congestion_event(cc, cstat, latest_ts, bytes_lost, ts); + cc->congestion_event(cc, cstat, latest_ts, cc_ack, ts); } loss_window = latest_ts - oldest_ts; @@ -1153,10 +1171,10 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, */ if (pktns->id == NGTCP2_PKTNS_ID_APPLICATION && loss_window && loss_window >= congestion_period) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, - "persistent congestion loss_window=%" PRIu64 - " congestion_period=%" PRIu64, - loss_window, congestion_period); + ngtcp2_log_infof(rtb->log, NGTCP2_LOG_EVENT_LDC, + "persistent congestion loss_window=%" PRIu64 + " congestion_period=%" PRIu64, + loss_window, congestion_period); /* Reset min_rtt, srtt, and rttvar here. Next new RTT sample will be used to recalculate these values. */ @@ -1176,18 +1194,18 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, ngtcp2_rtb_remove_excessive_lost_pkt(rtb, (size_t)pkt_thres); - if (ppkt_lost) { - *ppkt_lost = bytes_lost; - } - return 0; } int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { - return rtb_detect_lost_pkt(rtb, /* ppkt_lost = */ NULL, conn, pktns, cstat, - ts); + return rtb_detect_lost_pkt(rtb, + &(ngtcp2_cc_ack){ + .largest_pkt_sent_ts = UINT64_MAX, + .rtt = UINT64_MAX, + }, + conn, pktns, cstat, ts); } void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n) { @@ -1203,8 +1221,8 @@ void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n) { assert(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED); - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, - "removing stale lost pkn=%" PRId64, ent->hd.pkt_num); + ngtcp2_log_infof(rtb->log, NGTCP2_LOG_EVENT_LDC, + "removing stale lost pkn=%" PRId64, ent->hd.pkt_num); --rtb->num_lost_pkts; @@ -1240,13 +1258,14 @@ void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_ksl_it_prev(&it); ent = ngtcp2_ksl_it_get(&it); - if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED) || - ts - ent->lost_ts < timeout) { + assert(ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED); + + if (ts - ent->lost_ts < timeout) { return; } - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, - "removing stale lost pkn=%" PRId64, ent->hd.pkt_num); + ngtcp2_log_infof(rtb->log, NGTCP2_LOG_EVENT_LDC, + "removing stale lost pkn=%" PRId64, ent->hd.pkt_num); --rtb->num_lost_pkts; @@ -1290,7 +1309,7 @@ static int rtb_reclaim_frame_on_retry(ngtcp2_rtb *rtb, ngtcp2_conn *conn, int rv; for (; *pfrc;) { - switch ((*pfrc)->fr.type) { + switch ((*pfrc)->fr.hd.type) { case NGTCP2_FRAME_STREAM: frc = *pfrc; @@ -1398,15 +1417,22 @@ int ngtcp2_rtb_reclaim_on_retry(ngtcp2_rtb *rtb, ngtcp2_conn *conn, assert(!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE)); if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, - "pkn=%" PRId64 " has already been reclaimed on PTO", - ent->hd.pkt_num); + ngtcp2_log_infof(rtb->log, NGTCP2_LOG_EVENT_LDC, + "pkn=%" PRId64 " has already been reclaimed on PTO", + ent->hd.pkt_num); + + ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, + rtb->frc_objalloc, rtb->mem); + continue; } if (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE) && (!(ent->flags & NGTCP2_RTB_ENTRY_FLAG_DATAGRAM) || !conn->callbacks.lost_datagram)) { + ngtcp2_rtb_entry_objalloc_del(ent, rtb->rtb_entry_objalloc, + rtb->frc_objalloc, rtb->mem); + continue; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h index caa0fb58c58b13..28b91d8d36ff72 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_settings.h @@ -33,10 +33,10 @@ /* NGTCP2_DEFAULT_GLITCH_RATELIM_BURST is the maximum number of tokens in glitch rate limiter. It is also the initial value. */ -#define NGTCP2_DEFAULT_GLITCH_RATELIM_BURST 1000 +#define NGTCP2_DEFAULT_GLITCH_RATELIM_BURST 4000 /* NGTCP2_DEFAULT_GLITCH_RATELIM_RATE is the rate of tokens generated per second for glitch rate limiter. */ -#define NGTCP2_DEFAULT_GLITCH_RATELIM_RATE 33 +#define NGTCP2_DEFAULT_GLITCH_RATELIM_RATE 132 /* * ngtcp2_settings_convert_to_latest converts |src| of version diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.c index a61636d188fae5..1ae0f10d91787a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.c @@ -47,20 +47,25 @@ const void *ngtcp2_get_bytes(void *dest, const void *src, size_t n) { uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len) { size_t i; - uint8_t *p = dest; for (i = 0; i < len; ++i) { - *p++ = (uint8_t)LOWER_XDIGITS[data[i] >> 4]; - *p++ = (uint8_t)LOWER_XDIGITS[data[i] & 0xf]; + *dest++ = (uint8_t)LOWER_XDIGITS[data[i] >> 4]; + *dest++ = (uint8_t)LOWER_XDIGITS[data[i] & 0xf]; } + return dest; +} + +char *ngtcp2_encode_hex_cstr(char *dest, const uint8_t *data, size_t len) { + uint8_t *p = ngtcp2_encode_hex((uint8_t *)dest, data, len); + *p = '\0'; return dest; } -char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data, - size_t len) { +char *ngtcp2_encode_printable_ascii_cstr(char *dest, const uint8_t *data, + size_t len) { size_t i; char *p = dest; uint8_t c; @@ -79,40 +84,15 @@ char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data, return dest; } -/* - * write_uint writes |n| to the buffer pointed by |p| in decimal - * representation. It returns |p| plus the number of bytes written. - * The function assumes that the buffer has enough capacity to contain - * a string. - */ -static uint8_t *write_uint(uint8_t *p, uint64_t n) { - size_t nlen = 0; - uint64_t t; - uint8_t *res; - - if (n == 0) { - *p++ = '0'; - return p; - } - for (t = n; t; t /= 10, ++nlen) - ; - p += nlen; - res = p; - for (; n; n /= 10) { - *--p = (uint8_t)((n % 10) + '0'); - } - return res; -} - -uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr) { +char *ngtcp2_encode_ipv4_cstr(char *dest, const uint8_t *addr) { size_t i; - uint8_t *p = dest; + char *p = dest; - p = write_uint(p, addr[0]); + p = (char *)ngtcp2_encode_uint((uint8_t *)p, addr[0]); for (i = 1; i < 4; ++i) { *p++ = '.'; - p = write_uint(p, addr[i]); + p = (char *)ngtcp2_encode_uint((uint8_t *)p, addr[i]); } *p = '\0'; @@ -125,9 +105,9 @@ uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr) { * length |len| to |dest| in hex string. Any leading zeros are * suppressed. It returns |dest| plus the number of bytes written. */ -static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) { +static char *write_hex_zsup(char *dest, const uint8_t *data, size_t len) { size_t i; - uint8_t *p = dest; + char *p = dest; uint8_t d; for (i = 0; i < len; ++i) { @@ -139,7 +119,7 @@ static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) { d &= 0xf; if (d) { - *p++ = (uint8_t)LOWER_XDIGITS[d]; + *p++ = LOWER_XDIGITS[d]; ++i; break; } @@ -152,19 +132,19 @@ static uint8_t *write_hex_zsup(uint8_t *dest, const uint8_t *data, size_t len) { for (; i < len; ++i) { d = data[i]; - *p++ = (uint8_t)LOWER_XDIGITS[d >> 4]; - *p++ = (uint8_t)LOWER_XDIGITS[d & 0xf]; + *p++ = LOWER_XDIGITS[d >> 4]; + *p++ = LOWER_XDIGITS[d & 0xf]; } return p; } -uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr) { +char *ngtcp2_encode_ipv6_cstr(char *dest, const uint8_t *addr) { uint16_t blks[8]; size_t i; size_t zlen, zoff; size_t max_zlen = 0, max_zoff = 8; - uint8_t *p = dest; + char *p = dest; for (i = 0; i < 16; i += sizeof(uint16_t)) { /* Copy in network byte order. */ @@ -231,3 +211,124 @@ int ngtcp2_cmemeq(const uint8_t *a, const uint8_t *b, size_t n) { return rv == 0; } + +/* countl_zero counts the number of leading zeros in |x|. It is + undefined if |x| is 0. */ +static int countl_zero(uint64_t x) { +#ifdef __GNUC__ + return __builtin_clzll(x); +#else /* !defined(__GNUC__) */ + /* This is the same implementation of Go's LeadingZeros64 in + math/bits package. */ + static const uint8_t len8tab[] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + }; + int n = 0; + + if (x >= 1ull << 32) { + x >>= 32; + n += 32; + } + + if (x >= 1 << 16) { + x >>= 16; + n += 16; + } + + if (x >= 1 << 8) { + x >>= 8; + n += 8; + } + + return 64 - (n + len8tab[x]); +#endif /* !defined(__GNUC__) */ +} + +/* + * count_digit returns the minimum number of digits to represent |x| + * in base 10. + * + * credit: + * https://lemire.me/blog/2025/01/07/counting-the-digits-of-64-bit-integers/ + */ +static size_t count_digit(uint64_t x) { + static const uint64_t count_digit_tbl[] = { + 9ull, + 99ull, + 999ull, + 9999ull, + 99999ull, + 999999ull, + 9999999ull, + 99999999ull, + 999999999ull, + 9999999999ull, + 99999999999ull, + 999999999999ull, + 9999999999999ull, + 99999999999999ull, + 999999999999999ull, + 9999999999999999ull, + 99999999999999999ull, + 999999999999999999ull, + 9999999999999999999ull, + }; + size_t y = (size_t)(19 * (63 - countl_zero(x | 1)) >> 6); + + y += x > count_digit_tbl[y]; + + return y + 1; +} + +uint8_t *ngtcp2_encode_uint(uint8_t *dest, uint64_t n) { + static const uint8_t uint_digits[] = + "00010203040506070809101112131415161718192021222324252627282930313233343536" + "37383940414243444546474849505152535455565758596061626364656667686970717273" + "7475767778798081828384858687888990919293949596979899"; + uint8_t *p; + const uint8_t *tp; + + if (n < 10) { + *dest++ = (uint8_t)('0' + n); + return dest; + } + + if (n < 100) { + tp = &uint_digits[n * 2]; + *dest++ = *tp++; + *dest++ = *tp; + return dest; + } + + dest += count_digit(n); + p = dest; + + for (; n >= 100; n /= 100) { + p -= 2; + tp = &uint_digits[(n % 100) * 2]; + p[0] = *tp++; + p[1] = *tp; + } + + if (n < 10) { + *--p = (uint8_t)('0' + n); + return dest; + } + + p -= 2; + tp = &uint_digits[n * 2]; + p[0] = *tp++; + p[1] = *tp; + + return dest; +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h index f970c153e805a8..051053d75b7c04 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_str.h @@ -46,24 +46,31 @@ uint8_t *ngtcp2_setmem(uint8_t *dest, uint8_t b, size_t n); const void *ngtcp2_get_bytes(void *dest, const void *src, size_t n); /* - * ngtcp2_encode_hex encodes |data| of length |len| in hex string. It - * writes additional NULL bytes at the end of the buffer. The buffer - * pointed by |dest| must have at least |len| * 2 + 1 bytes space. - * This function returns |dest|. + * ngtcp2_encode_hex encodes |data| of length |len| in hex string. + * The buffer pointed by |dest| must have at least |len| * 2 bytes + * space. This function returns |dest| + |len| * 2. */ uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len); /* - * ngtcp2_encode_ipv4 encodes binary form IPv4 address stored in + * ngtcp2_encode_hex_cstr encodes |data| of length |len| in hex + * string. It writes additional NULL bytes at the end of the buffer. + * The buffer pointed by |dest| must have at least |len| * 2 + 1 bytes + * space. This function returns |dest|. + */ +char *ngtcp2_encode_hex_cstr(char *dest, const uint8_t *data, size_t len); + +/* + * ngtcp2_encode_ipv4_cstr encodes binary form IPv4 address stored in * |addr| to human readable text form in the buffer pointed by |dest|. * The capacity of buffer must have enough length to store a text form * plus a terminating NULL byte. The resulting text form ends with * NULL byte. The function returns |dest|. */ -uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr); +char *ngtcp2_encode_ipv4_cstr(char *dest, const uint8_t *addr); /* - * ngtcp2_encode_ipv6 encodes binary form IPv6 address stored in + * ngtcp2_encode_ipv6_cstr encodes binary form IPv6 address stored in * |addr| to human readable text form in the buffer pointed by |dest|. * The capacity of buffer must have enough length to store a text form * plus a terminating NULL byte. The resulting text form ends with @@ -72,7 +79,7 @@ uint8_t *ngtcp2_encode_ipv4(uint8_t *dest, const uint8_t *addr); * https://tools.ietf.org/html/rfc5952#section-4. The function * returns |dest|. */ -uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr); +char *ngtcp2_encode_ipv6_cstr(char *dest, const uint8_t *addr); /* * ngtcp2_encode_printable_ascii encodes |data| of length |len| in @@ -81,8 +88,8 @@ uint8_t *ngtcp2_encode_ipv6(uint8_t *dest, const uint8_t *addr); * writes additional NULL bytes at the end of the buffer. |dest| must * have at least |len| + 1 bytes. This function returns |dest|. */ -char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data, - size_t len); +char *ngtcp2_encode_printable_ascii_cstr(char *dest, const uint8_t *data, + size_t len); /* * ngtcp2_cmemeq returns nonzero if the first |n| bytes of the buffers @@ -91,4 +98,12 @@ char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data, */ int ngtcp2_cmemeq(const uint8_t *a, const uint8_t *b, size_t n); +/* + * ngtcp2_encode_uint encodes |n| as a decimal integer to the buffer + * pointed by |dest|. This function assumes that the buffer contains + * the sufficient capacity to write the number. This function returns + * the pointer to the buffer past the last byte written. + */ +uint8_t *ngtcp2_encode_uint(uint8_t *dest, uint64_t n); + #endif /* !defined(NGTCP2_STR_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c index faa417713224d5..99d02da1b8855f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c @@ -36,30 +36,27 @@ void ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags, uint64_t max_rx_offset, uint64_t max_tx_offset, void *stream_user_data, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { - strm->pe.index = NGTCP2_PQ_BAD_INDEX; - strm->cycle = 0; - strm->frc_objalloc = frc_objalloc; - strm->tx.acked_offset = NULL; - strm->tx.cont_acked_offset = 0; - strm->tx.streamfrq = NULL; - strm->tx.offset = 0; - strm->tx.max_offset = max_tx_offset; - strm->tx.last_blocked_offset = UINT64_MAX; - strm->tx.last_max_stream_data_ts = UINT64_MAX; - strm->tx.loss_count = 0; - strm->tx.last_lost_pkt_num = -1; - strm->tx.stop_sending_app_error_code = 0; - strm->tx.reset_stream_app_error_code = 0; - strm->rx.rob = NULL; - strm->rx.cont_offset = 0; - strm->rx.last_offset = 0; - strm->rx.max_offset = strm->rx.unsent_max_offset = strm->rx.window = - max_rx_offset; - strm->mem = mem; - strm->stream_id = stream_id; - strm->stream_user_data = stream_user_data; - strm->flags = flags; - strm->app_error_code = 0; + *strm = (ngtcp2_strm){ + .pe.index = NGTCP2_PQ_BAD_INDEX, + .frc_objalloc = frc_objalloc, + .tx = + { + .max_offset = max_tx_offset, + .last_blocked_offset = UINT64_MAX, + .last_max_stream_data_ts = UINT64_MAX, + .last_lost_pkt_num = -1, + }, + .rx = + { + .max_offset = max_rx_offset, + .unsent_max_offset = max_rx_offset, + .window = max_rx_offset, + }, + .mem = mem, + .stream_id = stream_id, + .stream_user_data = stream_user_data, + .flags = flags, + }; } void ngtcp2_strm_free(ngtcp2_strm *strm) { @@ -120,7 +117,7 @@ uint64_t ngtcp2_strm_rx_offset(const ngtcp2_strm *strm) { /* strm_rob_heavily_fragmented returns nonzero if the number of gaps in |rob| exceeds the limit. */ static int strm_rob_heavily_fragmented(const ngtcp2_rob *rob) { - return ngtcp2_ksl_len(&rob->gapksl) >= 1000; + return ngtcp2_ksl_len(&rob->gapksl) >= 4000; } ngtcp2_ssize ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data, @@ -193,8 +190,8 @@ static int strm_streamfrq_init(ngtcp2_strm *strm) { int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc) { int rv; - assert(frc->fr.type == NGTCP2_FRAME_STREAM || - frc->fr.type == NGTCP2_FRAME_CRYPTO); + assert(frc->fr.hd.type == NGTCP2_FRAME_STREAM || + frc->fr.hd.type == NGTCP2_FRAME_CRYPTO); assert(frc->next == NULL); if (strm->tx.streamfrq == NULL) { @@ -308,8 +305,7 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, fr->offset = offset + base_offset; fr->datacnt = end_idx - idx; - fr->data[0].base += base_offset; - fr->data[0].len -= (size_t)base_offset; + ngtcp2_vec_drop(&fr->data[0], (size_t)base_offset); *pfrc = frc; @@ -335,8 +331,7 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, 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; + ngtcp2_vec_drop(&nfr->data[0], (size_t)end_base_offset); rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc); if (rv != 0) { @@ -364,8 +359,7 @@ static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm, 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; + ngtcp2_vec_drop(&fr->data[0], (size_t)base_offset); *pfrc = frc; @@ -468,8 +462,11 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, } nfr = &nfrc->fr.stream; - *nfr = *fr; + nfr->type = fr->type; + nfr->flags = fr->flags; nfr->fin = 0; + nfr->stream_id = fr->stream_id; + nfr->offset = fr->offset; nfr->datacnt = acnt; ngtcp2_vec_copy(nfr->data, a, acnt); @@ -595,7 +592,11 @@ int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc, } nfr = &nfrc->fr.stream; - *nfr = *fr; + nfr->type = fr->type; + nfr->flags = fr->flags; + nfr->fin = fr->fin; + nfr->stream_id = fr->stream_id; + nfr->offset = fr->offset; nfr->datacnt = acnt; ngtcp2_vec_copy(nfr->data, a, acnt); @@ -694,12 +695,11 @@ int ngtcp2_strm_is_all_tx_data_fin_acked(const ngtcp2_strm *strm) { ngtcp2_range ngtcp2_strm_get_unacked_range_after(const ngtcp2_strm *strm, uint64_t offset) { - ngtcp2_range gap; - if (strm->tx.acked_offset == NULL) { - gap.begin = strm->tx.cont_acked_offset; - gap.end = UINT64_MAX; - return gap; + return (ngtcp2_range){ + .begin = strm->tx.cont_acked_offset, + .end = UINT64_MAX, + }; } return ngtcp2_gaptr_get_first_gap_after(strm->tx.acked_offset, offset); @@ -754,7 +754,7 @@ int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len) { return rv; } - if (ngtcp2_ksl_len(&strm->tx.acked_offset->gap) >= 1000) { + if (ngtcp2_ksl_len(&strm->tx.acked_offset->gap) >= 4000) { return NGTCP2_ERR_INTERNAL; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c index ada027b9095f4e..f94c6218d53d41 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.c @@ -30,8 +30,11 @@ #include "ngtcp2_str.h" ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len) { - vec->base = (uint8_t *)base; - vec->len = len; + *vec = (ngtcp2_vec){ + .base = (uint8_t *)base, + .len = len, + }; + return vec; } @@ -102,8 +105,7 @@ ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, memcpy(dst, src + i, sizeof(ngtcp2_vec) * nmove); } - dst[0].len -= left; - dst[0].base += left; + ngtcp2_vec_drop(&dst[0], left); src[i].len = left; if (nmove == 0) { @@ -136,8 +138,7 @@ size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, a->len = left; a->base = b->base; - b->len -= left; - b->base += left; + ngtcp2_vec_drop(b, left); return left; } @@ -158,13 +159,14 @@ size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, } else if (*pdstcnt == maxcnt) { break; } else { - dst[*pdstcnt].len = left; - dst[*pdstcnt].base = b->base; + dst[*pdstcnt] = (ngtcp2_vec){ + .base = b->base, + .len = left, + }; ++*pdstcnt; } - b->len -= left; - b->base += left; + ngtcp2_vec_drop(b, left); left = 0; break; @@ -199,8 +201,10 @@ size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t dstcnt, } if (src[i].len > left) { - dst[j].base = src[i].base; - dst[j].len = left; + dst[j] = (ngtcp2_vec){ + .base = src[i].base, + .len = left, + }; return j + 1; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h index af9b4d644539cf..fe6a47a029ad8d 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_vec.h @@ -110,4 +110,14 @@ static inline uint8_t *ngtcp2_vec_end(const ngtcp2_vec *v) { return v->base + v->len; } +/* + * ngtcp2_vec_drop removes the first |n| bytes from |v| by adjusting + * its base and len fields. This function assumes |v|->len > 0 && + * |v|->len >= n. + */ +static inline void ngtcp2_vec_drop(ngtcp2_vec *v, size_t n) { + v->base += n; + v->len -= n; +} + #endif /* !defined(NGTCP2_VEC_H) */ diff --git a/deps/ngtcp2/ngtcp2/third-party/libev/config.h b/deps/ngtcp2/ngtcp2/third-party/libev/config.h deleted file mode 100644 index ca518f45d4c617..00000000000000 --- a/deps/ngtcp2/ngtcp2/third-party/libev/config.h +++ /dev/null @@ -1,137 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define HAVE_CLOCK_GETTIME 1 - -/* Define to 1 to use the syscall interface for clock_gettime */ -/* #undef HAVE_CLOCK_SYSCALL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the `epoll_ctl' function. */ -#define HAVE_EPOLL_CTL 1 - -/* Define to 1 if you have the `eventfd' function. */ -#define HAVE_EVENTFD 1 - -/* Define to 1 if the floor function is available */ -#define HAVE_FLOOR 1 - -/* Define to 1 if you have the `inotify_init' function. */ -#define HAVE_INOTIFY_INIT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if linux/fs.h defined kernel_rwf_t */ -#define HAVE_KERNEL_RWF_T 1 - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef HAVE_KQUEUE */ - -/* Define to 1 if you have the `rt' library (-lrt). */ -/* #undef HAVE_LIBRT */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LINUX_AIO_ABI_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LINUX_FS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `nanosleep' function. */ -#define HAVE_NANOSLEEP 1 - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef HAVE_PORT_CREATE */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define to 1 if you have the `signalfd' function. */ -#define HAVE_SIGNALFD 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_EPOLL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_EVENTFD_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_INOTIFY_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SIGNALFD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIMERFD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#define LT_OBJDIR ".libs/" - -/* Name of package */ -#define PACKAGE "libev" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libev" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libev 4.33" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libev" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "4.33" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "4.33" diff --git a/deps/ngtcp2/ngtcp2/third-party/libev/config.log b/deps/ngtcp2/ngtcp2/third-party/libev/config.log deleted file mode 100644 index f2fc3ea290d199..00000000000000 --- a/deps/ngtcp2/ngtcp2/third-party/libev/config.log +++ /dev/null @@ -1,1301 +0,0 @@ -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by libev configure 4.33, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ ./configure - -## --------- ## -## Platform. ## -## --------- ## - -hostname = james-cloudflare-build -uname -m = x86_64 -uname -r = 6.8.0-64-generic -uname -s = Linux -uname -v = #67~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Jun 24 15:19:46 UTC 2 - -/usr/bin/uname -p = x86_64 -/bin/uname -X = unknown - -/bin/arch = x86_64 -/usr/bin/arch -k = unknown -/usr/convex/getsysinfo = unknown -/usr/bin/hostinfo = unknown -/bin/machine = unknown -/usr/bin/oslevel = unknown -/bin/universe = unknown - -PATH: /home/jsnell/projects/cloudflare/depot_tools -PATH: /home/jsnell/.bun/bin -PATH: /home/jsnell/perl5/bin -PATH: /home/jsnell/.vscode-server/cli/servers/Stable-f220831ea2d946c0dcb0f3eaa480eb435a2c1260/server/bin/remote-cli -PATH: /home/jsnell/projects/cloudflare/depot_tools -PATH: /home/jsnell/.bun/bin -PATH: /home/jsnell/.deno/bin -PATH: /home/jsnell/perl5/bin -PATH: /home/jsnell/google-cloud-sdk/bin -PATH: /home/jsnell/.cargo/bin -PATH: /home/jsnell/.nvm/versions/node/v22.13.0/bin -PATH: /usr/local/sbin -PATH: /usr/local/bin -PATH: /usr/sbin -PATH: /usr/bin -PATH: /sbin -PATH: /bin -PATH: /usr/games -PATH: /usr/local/games -PATH: /snap/bin -PATH: /home/jsnell/go/bin -PATH: /home/jsnell/.vscode-server/data/User/globalStorage/github.copilot-chat/debugCommand -PATH: /home/jsnell/go/bin - - -## ----------- ## -## Core tests. ## -## ----------- ## - -configure:2328: checking for a BSD-compatible install -configure:2396: result: /usr/bin/install -c -configure:2407: checking whether build environment is sane -configure:2462: result: yes -configure:2613: checking for a thread-safe mkdir -p -configure:2652: result: /usr/bin/mkdir -p -configure:2659: checking for gawk -configure:2689: result: no -configure:2659: checking for mawk -configure:2675: found /usr/bin/mawk -configure:2686: result: mawk -configure:2697: checking whether make sets $(MAKE) -configure:2719: result: yes -configure:2748: checking whether make supports nested variables -configure:2765: result: yes -configure:2895: checking whether to enable maintainer-specific portions of Makefiles -configure:2904: result: no -configure:2966: checking for gcc -configure:2993: result: /usr/bin/clang -configure:3222: checking for C compiler version -configure:3231: /usr/bin/clang --version >&5 -Ubuntu clang version 21.0.0 (++20250501031614+2bb2f8ab49d6-1~exp1~20250501151806.2390) -Target: x86_64-pc-linux-gnu -Thread model: posix -InstalledDir: /usr/bin -configure:3242: $? = 0 -configure:3231: /usr/bin/clang -v >&5 -Ubuntu clang version 21.0.0 (++20250501031614+2bb2f8ab49d6-1~exp1~20250501151806.2390) -Target: x86_64-pc-linux-gnu -Thread model: posix -InstalledDir: /usr/bin -Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/11 -Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/12 -Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/12 -Candidate multilib: .;@m64 -Selected multilib: .;@m64 -configure:3242: $? = 0 -configure:3231: /usr/bin/clang -V >&5 -clang: error: argument to '-V' is missing (expected 1 value) -clang: error: no input files -configure:3242: $? = 1 -configure:3231: /usr/bin/clang -qversion >&5 -clang: error: unknown argument '-qversion'; did you mean '--version'? -clang: error: no input files -configure:3242: $? = 1 -configure:3262: checking whether the C compiler works -configure:3284: /usr/bin/clang conftest.c >&5 -configure:3288: $? = 0 -configure:3336: result: yes -configure:3339: checking for C compiler default output file name -configure:3341: result: a.out -configure:3347: checking for suffix of executables -configure:3354: /usr/bin/clang -o conftest conftest.c >&5 -configure:3358: $? = 0 -configure:3380: result: -configure:3402: checking whether we are cross compiling -configure:3410: /usr/bin/clang -o conftest conftest.c >&5 -configure:3414: $? = 0 -configure:3421: ./conftest -configure:3425: $? = 0 -configure:3440: result: no -configure:3445: checking for suffix of object files -configure:3467: /usr/bin/clang -c conftest.c >&5 -configure:3471: $? = 0 -configure:3492: result: o -configure:3496: checking whether we are using the GNU C compiler -configure:3515: /usr/bin/clang -c conftest.c >&5 -configure:3515: $? = 0 -configure:3524: result: yes -configure:3533: checking whether /usr/bin/clang accepts -g -configure:3553: /usr/bin/clang -c -g conftest.c >&5 -configure:3553: $? = 0 -configure:3594: result: yes -configure:3611: checking for /usr/bin/clang option to accept ISO C89 -configure:3674: /usr/bin/clang -c -g -O2 conftest.c >&5 -conftest.c:17:14: warning: a function definition without a prototype is deprecated in all versions of C and is not supported in C23 [-Wdeprecated-non-prototype] - 17 | static char *e (p, i) - | ^ -1 warning generated. -configure:3674: $? = 0 -configure:3687: result: none needed -configure:3712: checking whether /usr/bin/clang understands -c and -o together -configure:3734: /usr/bin/clang -c conftest.c -o conftest2.o -configure:3737: $? = 0 -configure:3734: /usr/bin/clang -c conftest.c -o conftest2.o -configure:3737: $? = 0 -configure:3749: result: yes -configure:3769: checking whether make supports the include directive -configure:3784: make -f confmf.GNU && cat confinc.out -this is the am__doit target -configure:3787: $? = 0 -configure:3806: result: yes (GNU style) -configure:3831: checking dependency style of /usr/bin/clang -configure:3942: result: gcc3 -configure:3994: checking build system type -configure:4008: result: x86_64-pc-linux-gnu -configure:4028: checking host system type -configure:4041: result: x86_64-pc-linux-gnu -configure:4082: checking how to print strings -configure:4109: result: printf -configure:4130: checking for a sed that does not truncate output -configure:4194: result: /usr/bin/sed -configure:4212: checking for grep that handles long lines and -e -configure:4270: result: /usr/bin/grep -configure:4275: checking for egrep -configure:4337: result: /usr/bin/grep -E -configure:4342: checking for fgrep -configure:4404: result: /usr/bin/grep -F -configure:4439: checking for ld used by /usr/bin/clang -configure:4506: result: /usr/bin/ld -configure:4513: checking if the linker (/usr/bin/ld) is GNU ld -configure:4528: result: yes -configure:4540: checking for BSD- or MS-compatible name lister (nm) -configure:4594: result: /usr/bin/nm -B -configure:4724: checking the name lister (/usr/bin/nm -B) interface -configure:4731: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:4734: /usr/bin/nm -B "conftest.o" -configure:4737: output -0000000000000000 B some_variable -configure:4744: result: BSD nm -configure:4747: checking whether ln -s works -configure:4751: result: yes -configure:4759: checking the maximum length of command line arguments -configure:4890: result: 1572864 -configure:4938: checking how to convert x86_64-pc-linux-gnu file names to x86_64-pc-linux-gnu format -configure:4978: result: func_convert_file_noop -configure:4985: checking how to convert x86_64-pc-linux-gnu file names to toolchain format -configure:5005: result: func_convert_file_noop -configure:5012: checking for /usr/bin/ld option to reload object files -configure:5019: result: -r -configure:5093: checking for objdump -configure:5109: found /usr/bin/objdump -configure:5120: result: objdump -configure:5152: checking how to recognize dependent libraries -configure:5352: result: pass_all -configure:5437: checking for dlltool -configure:5467: result: no -configure:5497: checking how to associate runtime and link libraries -configure:5524: result: printf %s\n -configure:5585: checking for ar -configure:5601: found /usr/bin/ar -configure:5612: result: ar -configure:5649: checking for archiver @FILE support -configure:5666: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:5666: $? = 0 -configure:5669: ar cru libconftest.a @conftest.lst >&5 -ar: `u' modifier ignored since `D' is the default (see `U') -configure:5672: $? = 0 -configure:5677: ar cru libconftest.a @conftest.lst >&5 -ar: `u' modifier ignored since `D' is the default (see `U') -ar: conftest.o: No such file or directory -configure:5680: $? = 1 -configure:5692: result: @ -configure:5750: checking for strip -configure:5766: found /usr/bin/strip -configure:5777: result: strip -configure:5849: checking for ranlib -configure:5865: found /usr/bin/ranlib -configure:5876: result: ranlib -configure:5978: checking command to parse /usr/bin/nm -B output from /usr/bin/clang object -configure:6131: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:6134: $? = 0 -configure:6138: /usr/bin/nm -B conftest.o | sed -n -e 's/^.*[ ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p' | sed '/ __gnu_lto/d' > conftest.nm -configure:6204: /usr/bin/clang -o conftest -g -O3 conftest.c conftstm.o >&5 -configure:6207: $? = 0 -configure:6245: result: ok -configure:6292: checking for sysroot -configure:6322: result: no -configure:6329: checking for a working dd -configure:6367: result: /usr/bin/dd -configure:6371: checking how to truncate binary pipes -configure:6386: result: /usr/bin/dd bs=4096 count=1 -configure:6522: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:6525: $? = 0 -configure:6715: checking for mt -configure:6731: found /usr/bin/mt -configure:6742: result: mt -configure:6765: checking if mt is a manifest tool -configure:6771: mt '-?' -configure:6779: result: no -configure:7456: checking how to run the C preprocessor -configure:7487: /usr/bin/clang -E conftest.c -configure:7487: $? = 0 -configure:7501: /usr/bin/clang -E conftest.c -conftest.c:11:10: fatal error: 'ac_nonexistent.h' file not found - 11 | #include - | ^~~~~~~~~~~~~~~~~~ -1 error generated. -configure:7501: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| /* end confdefs.h. */ -| #include -configure:7526: result: /usr/bin/clang -E -configure:7546: /usr/bin/clang -E conftest.c -configure:7546: $? = 0 -configure:7560: /usr/bin/clang -E conftest.c -conftest.c:11:10: fatal error: 'ac_nonexistent.h' file not found - 11 | #include - | ^~~~~~~~~~~~~~~~~~ -1 error generated. -configure:7560: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| /* end confdefs.h. */ -| #include -configure:7589: checking for ANSI C header files -configure:7609: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7609: $? = 0 -configure:7682: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:7682: $? = 0 -configure:7682: ./conftest -configure:7682: $? = 0 -configure:7693: result: yes -configure:7706: checking for sys/types.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7706: checking for sys/stat.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7706: checking for stdlib.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7706: checking for string.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7706: checking for memory.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7706: checking for strings.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7706: checking for inttypes.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7706: checking for stdint.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7706: checking for unistd.h -configure:7706: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7706: $? = 0 -configure:7706: result: yes -configure:7720: checking for dlfcn.h -configure:7720: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:7720: $? = 0 -configure:7720: result: yes -configure:7976: checking for objdir -configure:7991: result: .libs -configure:8251: checking if /usr/bin/clang supports -fno-rtti -fno-exceptions -configure:8269: /usr/bin/clang -c -g -O3 -fno-rtti -fno-exceptions conftest.c >&5 -configure:8273: $? = 0 -configure:8286: result: yes -configure:8644: checking for /usr/bin/clang option to produce PIC -configure:8651: result: -fPIC -DPIC -configure:8659: checking if /usr/bin/clang PIC flag -fPIC -DPIC works -configure:8677: /usr/bin/clang -c -g -O3 -fPIC -DPIC -DPIC conftest.c >&5 -configure:8681: $? = 0 -configure:8694: result: yes -configure:8723: checking if /usr/bin/clang static flag -static works -configure:8751: result: yes -configure:8766: checking if /usr/bin/clang supports -c -o file.o -configure:8787: /usr/bin/clang -c -g -O3 -o out/conftest2.o conftest.c >&5 -configure:8791: $? = 0 -configure:8813: result: yes -configure:8821: checking if /usr/bin/clang supports -c -o file.o -configure:8868: result: yes -configure:8901: checking whether the /usr/bin/clang linker (/usr/bin/ld -m elf_x86_64) supports shared libraries -configure:10164: result: yes -configure:10201: checking whether -lc should be explicitly linked in -configure:10209: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:10212: $? = 0 -configure:10227: /usr/bin/clang -shared -fPIC -DPIC conftest.o -v -Wl,-soname -Wl,conftest -o conftest 2\>\&1 \| /usr/bin/grep -lc \>/dev/null 2\>\&1 -configure:10230: $? = 0 -configure:10244: result: no -configure:10404: checking dynamic linker characteristics -configure:10985: /usr/bin/clang -o conftest -g -O3 -Wl,-rpath -Wl,/foo conftest.c >&5 -configure:10985: $? = 0 -configure:11234: result: GNU/Linux ld.so -configure:11356: checking how to hardcode library paths into programs -configure:11381: result: immediate -configure:11929: checking whether stripping libraries is possible -configure:11934: result: yes -configure:11969: checking if libtool supports shared libraries -configure:11971: result: yes -configure:11974: checking whether to build shared libraries -configure:11999: result: yes -configure:12002: checking whether to build static libraries -configure:12006: result: yes -configure:12048: checking sys/inotify.h usability -configure:12048: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12048: $? = 0 -configure:12048: result: yes -configure:12048: checking sys/inotify.h presence -configure:12048: /usr/bin/clang -E conftest.c -configure:12048: $? = 0 -configure:12048: result: yes -configure:12048: checking for sys/inotify.h -configure:12048: result: yes -configure:12048: checking sys/epoll.h usability -configure:12048: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12048: $? = 0 -configure:12048: result: yes -configure:12048: checking sys/epoll.h presence -configure:12048: /usr/bin/clang -E conftest.c -configure:12048: $? = 0 -configure:12048: result: yes -configure:12048: checking for sys/epoll.h -configure:12048: result: yes -configure:12048: checking sys/event.h usability -configure:12048: /usr/bin/clang -c -g -O3 conftest.c >&5 -conftest.c:58:10: fatal error: 'sys/event.h' file not found - 58 | #include - | ^~~~~~~~~~~~~ -1 error generated. -configure:12048: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define HAVE_DLFCN_H 1 -| #define LT_OBJDIR ".libs/" -| #define HAVE_SYS_INOTIFY_H 1 -| #define HAVE_SYS_EPOLL_H 1 -| /* end confdefs.h. */ -| #include -| #ifdef HAVE_SYS_TYPES_H -| # include -| #endif -| #ifdef HAVE_SYS_STAT_H -| # include -| #endif -| #ifdef STDC_HEADERS -| # include -| # include -| #else -| # ifdef HAVE_STDLIB_H -| # include -| # endif -| #endif -| #ifdef HAVE_STRING_H -| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H -| # include -| # endif -| # include -| #endif -| #ifdef HAVE_STRINGS_H -| # include -| #endif -| #ifdef HAVE_INTTYPES_H -| # include -| #endif -| #ifdef HAVE_STDINT_H -| # include -| #endif -| #ifdef HAVE_UNISTD_H -| # include -| #endif -| #include -configure:12048: result: no -configure:12048: checking sys/event.h presence -configure:12048: /usr/bin/clang -E conftest.c -conftest.c:25:10: fatal error: 'sys/event.h' file not found - 25 | #include - | ^~~~~~~~~~~~~ -1 error generated. -configure:12048: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define HAVE_DLFCN_H 1 -| #define LT_OBJDIR ".libs/" -| #define HAVE_SYS_INOTIFY_H 1 -| #define HAVE_SYS_EPOLL_H 1 -| /* end confdefs.h. */ -| #include -configure:12048: result: no -configure:12048: checking for sys/event.h -configure:12048: result: no -configure:12048: checking port.h usability -configure:12048: /usr/bin/clang -c -g -O3 conftest.c >&5 -conftest.c:58:10: fatal error: 'port.h' file not found - 58 | #include - | ^~~~~~~~ -1 error generated. -configure:12048: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define HAVE_DLFCN_H 1 -| #define LT_OBJDIR ".libs/" -| #define HAVE_SYS_INOTIFY_H 1 -| #define HAVE_SYS_EPOLL_H 1 -| /* end confdefs.h. */ -| #include -| #ifdef HAVE_SYS_TYPES_H -| # include -| #endif -| #ifdef HAVE_SYS_STAT_H -| # include -| #endif -| #ifdef STDC_HEADERS -| # include -| # include -| #else -| # ifdef HAVE_STDLIB_H -| # include -| # endif -| #endif -| #ifdef HAVE_STRING_H -| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H -| # include -| # endif -| # include -| #endif -| #ifdef HAVE_STRINGS_H -| # include -| #endif -| #ifdef HAVE_INTTYPES_H -| # include -| #endif -| #ifdef HAVE_STDINT_H -| # include -| #endif -| #ifdef HAVE_UNISTD_H -| # include -| #endif -| #include -configure:12048: result: no -configure:12048: checking port.h presence -configure:12048: /usr/bin/clang -E conftest.c -conftest.c:25:10: fatal error: 'port.h' file not found - 25 | #include - | ^~~~~~~~ -1 error generated. -configure:12048: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define HAVE_DLFCN_H 1 -| #define LT_OBJDIR ".libs/" -| #define HAVE_SYS_INOTIFY_H 1 -| #define HAVE_SYS_EPOLL_H 1 -| /* end confdefs.h. */ -| #include -configure:12048: result: no -configure:12048: checking for port.h -configure:12048: result: no -configure:12048: checking poll.h usability -configure:12048: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12048: $? = 0 -configure:12048: result: yes -configure:12048: checking poll.h presence -configure:12048: /usr/bin/clang -E conftest.c -configure:12048: $? = 0 -configure:12048: result: yes -configure:12048: checking for poll.h -configure:12048: result: yes -configure:12048: checking sys/timerfd.h usability -configure:12048: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12048: $? = 0 -configure:12048: result: yes -configure:12048: checking sys/timerfd.h presence -configure:12048: /usr/bin/clang -E conftest.c -configure:12048: $? = 0 -configure:12048: result: yes -configure:12048: checking for sys/timerfd.h -configure:12048: result: yes -configure:12061: checking sys/select.h usability -configure:12061: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking sys/select.h presence -configure:12061: /usr/bin/clang -E conftest.c -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking for sys/select.h -configure:12061: result: yes -configure:12061: checking sys/eventfd.h usability -configure:12061: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking sys/eventfd.h presence -configure:12061: /usr/bin/clang -E conftest.c -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking for sys/eventfd.h -configure:12061: result: yes -configure:12061: checking sys/signalfd.h usability -configure:12061: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking sys/signalfd.h presence -configure:12061: /usr/bin/clang -E conftest.c -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking for sys/signalfd.h -configure:12061: result: yes -configure:12061: checking linux/aio_abi.h usability -configure:12061: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking linux/aio_abi.h presence -configure:12061: /usr/bin/clang -E conftest.c -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking for linux/aio_abi.h -configure:12061: result: yes -configure:12061: checking linux/fs.h usability -configure:12061: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking linux/fs.h presence -configure:12061: /usr/bin/clang -E conftest.c -configure:12061: $? = 0 -configure:12061: result: yes -configure:12061: checking for linux/fs.h -configure:12061: result: yes -configure:12075: checking for inotify_init -configure:12075: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:12075: $? = 0 -configure:12075: result: yes -configure:12075: checking for epoll_ctl -configure:12075: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:12075: $? = 0 -configure:12075: result: yes -configure:12075: checking for kqueue -configure:12075: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -/usr/bin/ld: /tmp/conftest-59a648.o: in function `main': -conftest.c:(.text+0x4): undefined reference to `kqueue' -clang: error: linker command failed with exit code 1 (use -v to see invocation) -configure:12075: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define HAVE_DLFCN_H 1 -| #define LT_OBJDIR ".libs/" -| #define HAVE_SYS_INOTIFY_H 1 -| #define HAVE_SYS_EPOLL_H 1 -| #define HAVE_POLL_H 1 -| #define HAVE_SYS_TIMERFD_H 1 -| #define HAVE_SYS_SELECT_H 1 -| #define HAVE_SYS_EVENTFD_H 1 -| #define HAVE_SYS_SIGNALFD_H 1 -| #define HAVE_LINUX_AIO_ABI_H 1 -| #define HAVE_LINUX_FS_H 1 -| #define HAVE_INOTIFY_INIT 1 -| #define HAVE_EPOLL_CTL 1 -| /* end confdefs.h. */ -| /* Define kqueue to an innocuous variant, in case declares kqueue. -| For example, HP-UX 11i declares gettimeofday. */ -| #define kqueue innocuous_kqueue -| -| /* System header to define __stub macros and hopefully few prototypes, -| which can conflict with char kqueue (); below. -| Prefer to if __STDC__ is defined, since -| exists even on freestanding compilers. */ -| -| #ifdef __STDC__ -| # include -| #else -| # include -| #endif -| -| #undef kqueue -| -| /* Override any GCC internal prototype to avoid an error. -| Use char because int might match the return type of a GCC -| builtin and then its argument prototype would still apply. */ -| #ifdef __cplusplus -| extern "C" -| #endif -| char kqueue (); -| /* The GNU C library defines this for functions which it implements -| to always fail with ENOSYS. Some functions are actually named -| something starting with __ and the normal name is an alias. */ -| #if defined __stub_kqueue || defined __stub___kqueue -| choke me -| #endif -| -| int -| main () -| { -| return kqueue (); -| ; -| return 0; -| } -configure:12075: result: no -configure:12075: checking for port_create -configure:12075: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -/usr/bin/ld: /tmp/conftest-05dda3.o: in function `main': -conftest.c:(.text+0x4): undefined reference to `port_create' -clang: error: linker command failed with exit code 1 (use -v to see invocation) -configure:12075: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define HAVE_DLFCN_H 1 -| #define LT_OBJDIR ".libs/" -| #define HAVE_SYS_INOTIFY_H 1 -| #define HAVE_SYS_EPOLL_H 1 -| #define HAVE_POLL_H 1 -| #define HAVE_SYS_TIMERFD_H 1 -| #define HAVE_SYS_SELECT_H 1 -| #define HAVE_SYS_EVENTFD_H 1 -| #define HAVE_SYS_SIGNALFD_H 1 -| #define HAVE_LINUX_AIO_ABI_H 1 -| #define HAVE_LINUX_FS_H 1 -| #define HAVE_INOTIFY_INIT 1 -| #define HAVE_EPOLL_CTL 1 -| /* end confdefs.h. */ -| /* Define port_create to an innocuous variant, in case declares port_create. -| For example, HP-UX 11i declares gettimeofday. */ -| #define port_create innocuous_port_create -| -| /* System header to define __stub macros and hopefully few prototypes, -| which can conflict with char port_create (); below. -| Prefer to if __STDC__ is defined, since -| exists even on freestanding compilers. */ -| -| #ifdef __STDC__ -| # include -| #else -| # include -| #endif -| -| #undef port_create -| -| /* Override any GCC internal prototype to avoid an error. -| Use char because int might match the return type of a GCC -| builtin and then its argument prototype would still apply. */ -| #ifdef __cplusplus -| extern "C" -| #endif -| char port_create (); -| /* The GNU C library defines this for functions which it implements -| to always fail with ENOSYS. Some functions are actually named -| something starting with __ and the normal name is an alias. */ -| #if defined __stub_port_create || defined __stub___port_create -| choke me -| #endif -| -| int -| main () -| { -| return port_create (); -| ; -| return 0; -| } -configure:12075: result: no -configure:12075: checking for poll -configure:12075: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:12075: $? = 0 -configure:12075: result: yes -configure:12075: checking for select -configure:12075: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:12075: $? = 0 -configure:12075: result: yes -configure:12075: checking for eventfd -configure:12075: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:12075: $? = 0 -configure:12075: result: yes -configure:12075: checking for signalfd -configure:12075: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:12075: $? = 0 -configure:12075: result: yes -configure:12087: checking for clock_gettime -configure:12087: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:12087: $? = 0 -configure:12087: result: yes -configure:12191: checking for nanosleep -configure:12191: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -configure:12191: $? = 0 -configure:12191: result: yes -configure:12263: checking for __kernel_rwf_t -configure:12263: /usr/bin/clang -c -g -O3 conftest.c >&5 -configure:12263: $? = 0 -configure:12263: /usr/bin/clang -c -g -O3 conftest.c >&5 -conftest.c:45:29: error: expected expression - 45 | if (sizeof ((__kernel_rwf_t))) - | ^ -1 error generated. -configure:12263: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define HAVE_DLFCN_H 1 -| #define LT_OBJDIR ".libs/" -| #define HAVE_SYS_INOTIFY_H 1 -| #define HAVE_SYS_EPOLL_H 1 -| #define HAVE_POLL_H 1 -| #define HAVE_SYS_TIMERFD_H 1 -| #define HAVE_SYS_SELECT_H 1 -| #define HAVE_SYS_EVENTFD_H 1 -| #define HAVE_SYS_SIGNALFD_H 1 -| #define HAVE_LINUX_AIO_ABI_H 1 -| #define HAVE_LINUX_FS_H 1 -| #define HAVE_INOTIFY_INIT 1 -| #define HAVE_EPOLL_CTL 1 -| #define HAVE_POLL 1 -| #define HAVE_SELECT 1 -| #define HAVE_EVENTFD 1 -| #define HAVE_SIGNALFD 1 -| #define HAVE_CLOCK_GETTIME 1 -| #define HAVE_NANOSLEEP 1 -| /* end confdefs.h. */ -| #include -| -| int -| main () -| { -| if (sizeof ((__kernel_rwf_t))) -| return 0; -| ; -| return 0; -| } -configure:12263: result: yes -configure:12277: checking for library containing floor -configure:12308: /usr/bin/clang -o conftest -g -O3 conftest.c >&5 -conftest.c:48:6: warning: incompatible redeclaration of library function 'floor' [-Wincompatible-library-redeclaration] - 48 | char floor (); - | ^ -conftest.c:48:6: note: 'floor' is a builtin with type 'double (double)' -1 warning generated. -/usr/bin/ld: /tmp/conftest-39fbb2.o: in function `main': -conftest.c:(.text+0x4): undefined reference to `floor' -clang: error: linker command failed with exit code 1 (use -v to see invocation) -configure:12308: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "libev" -| #define PACKAGE_TARNAME "libev" -| #define PACKAGE_VERSION "4.33" -| #define PACKAGE_STRING "libev 4.33" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define PACKAGE "libev" -| #define VERSION "4.33" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define HAVE_DLFCN_H 1 -| #define LT_OBJDIR ".libs/" -| #define HAVE_SYS_INOTIFY_H 1 -| #define HAVE_SYS_EPOLL_H 1 -| #define HAVE_POLL_H 1 -| #define HAVE_SYS_TIMERFD_H 1 -| #define HAVE_SYS_SELECT_H 1 -| #define HAVE_SYS_EVENTFD_H 1 -| #define HAVE_SYS_SIGNALFD_H 1 -| #define HAVE_LINUX_AIO_ABI_H 1 -| #define HAVE_LINUX_FS_H 1 -| #define HAVE_INOTIFY_INIT 1 -| #define HAVE_EPOLL_CTL 1 -| #define HAVE_POLL 1 -| #define HAVE_SELECT 1 -| #define HAVE_EVENTFD 1 -| #define HAVE_SIGNALFD 1 -| #define HAVE_CLOCK_GETTIME 1 -| #define HAVE_NANOSLEEP 1 -| #define HAVE_KERNEL_RWF_T 1 -| /* end confdefs.h. */ -| -| /* Override any GCC internal prototype to avoid an error. -| Use char because int might match the return type of a GCC -| builtin and then its argument prototype would still apply. */ -| #ifdef __cplusplus -| extern "C" -| #endif -| char floor (); -| int -| main () -| { -| return floor (); -| ; -| return 0; -| } -configure:12308: /usr/bin/clang -o conftest -g -O3 conftest.c -lm >&5 -conftest.c:48:6: warning: incompatible redeclaration of library function 'floor' [-Wincompatible-library-redeclaration] - 48 | char floor (); - | ^ -conftest.c:48:6: note: 'floor' is a builtin with type 'double (double)' -1 warning generated. -configure:12308: $? = 0 -configure:12325: result: -lm -configure:12441: checking that generated files are newer than configure -configure:12447: result: done -configure:12474: creating ./config.status - -## ---------------------- ## -## Running config.status. ## -## ---------------------- ## - -This file was extended by libev config.status 4.33, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = - CONFIG_HEADERS = - CONFIG_LINKS = - CONFIG_COMMANDS = - $ ./config.status - -on james-cloudflare-build - -config.status:1106: creating Makefile -config.status:1106: creating config.h -config.status:1335: executing depfiles commands -config.status:1412: cd . && sed -e '/# am--include-marker/d' Makefile | make -f - am--depfiles -config.status:1417: $? = 0 -config.status:1335: executing libtool commands - -## ---------------- ## -## Cache variables. ## -## ---------------- ## - -ac_cv_build=x86_64-pc-linux-gnu -ac_cv_c_compiler_gnu=yes -ac_cv_env_CC_set=set -ac_cv_env_CC_value=/usr/bin/clang -ac_cv_env_CFLAGS_set= -ac_cv_env_CFLAGS_value= -ac_cv_env_CPPFLAGS_set= -ac_cv_env_CPPFLAGS_value= -ac_cv_env_CPP_set= -ac_cv_env_CPP_value= -ac_cv_env_LDFLAGS_set= -ac_cv_env_LDFLAGS_value= -ac_cv_env_LIBS_set= -ac_cv_env_LIBS_value= -ac_cv_env_LT_SYS_LIBRARY_PATH_set= -ac_cv_env_LT_SYS_LIBRARY_PATH_value= -ac_cv_env_build_alias_set= -ac_cv_env_build_alias_value= -ac_cv_env_host_alias_set= -ac_cv_env_host_alias_value= -ac_cv_env_target_alias_set= -ac_cv_env_target_alias_value= -ac_cv_func_clock_gettime=yes -ac_cv_func_epoll_ctl=yes -ac_cv_func_eventfd=yes -ac_cv_func_inotify_init=yes -ac_cv_func_kqueue=no -ac_cv_func_nanosleep=yes -ac_cv_func_poll=yes -ac_cv_func_port_create=no -ac_cv_func_select=yes -ac_cv_func_signalfd=yes -ac_cv_header_dlfcn_h=yes -ac_cv_header_inttypes_h=yes -ac_cv_header_linux_aio_abi_h=yes -ac_cv_header_linux_fs_h=yes -ac_cv_header_memory_h=yes -ac_cv_header_poll_h=yes -ac_cv_header_port_h=no -ac_cv_header_stdc=yes -ac_cv_header_stdint_h=yes -ac_cv_header_stdlib_h=yes -ac_cv_header_string_h=yes -ac_cv_header_strings_h=yes -ac_cv_header_sys_epoll_h=yes -ac_cv_header_sys_event_h=no -ac_cv_header_sys_eventfd_h=yes -ac_cv_header_sys_inotify_h=yes -ac_cv_header_sys_select_h=yes -ac_cv_header_sys_signalfd_h=yes -ac_cv_header_sys_stat_h=yes -ac_cv_header_sys_timerfd_h=yes -ac_cv_header_sys_types_h=yes -ac_cv_header_unistd_h=yes -ac_cv_host=x86_64-pc-linux-gnu -ac_cv_objext=o -ac_cv_path_EGREP='/usr/bin/grep -E' -ac_cv_path_FGREP='/usr/bin/grep -F' -ac_cv_path_GREP=/usr/bin/grep -ac_cv_path_SED=/usr/bin/sed -ac_cv_path_install='/usr/bin/install -c' -ac_cv_path_lt_DD=/usr/bin/dd -ac_cv_path_mkdir=/usr/bin/mkdir -ac_cv_prog_AWK=mawk -ac_cv_prog_CPP='/usr/bin/clang -E' -ac_cv_prog_ac_ct_AR=ar -ac_cv_prog_ac_ct_CC=/usr/bin/clang -ac_cv_prog_ac_ct_MANIFEST_TOOL=mt -ac_cv_prog_ac_ct_OBJDUMP=objdump -ac_cv_prog_ac_ct_RANLIB=ranlib -ac_cv_prog_ac_ct_STRIP=strip -ac_cv_prog_cc_c89= -ac_cv_prog_cc_g=yes -ac_cv_prog_make_make_set=yes -ac_cv_search_floor=-lm -ac_cv_type___kernel_rwf_t=yes -am_cv_CC_dependencies_compiler_type=gcc3 -am_cv_make_support_nested_variables=yes -am_cv_prog_cc_c_o=yes -lt_cv_ar_at_file=@ -lt_cv_archive_cmds_need_lc=no -lt_cv_deplibs_check_method=pass_all -lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_ld_reload_flag=-r -lt_cv_nm_interface='BSD nm' -lt_cv_objdir=.libs -lt_cv_path_LD=/usr/bin/ld -lt_cv_path_NM='/usr/bin/nm -B' -lt_cv_path_mainfest_tool=no -lt_cv_prog_compiler_c_o=yes -lt_cv_prog_compiler_pic='-fPIC -DPIC' -lt_cv_prog_compiler_pic_works=yes -lt_cv_prog_compiler_rtti_exceptions=yes -lt_cv_prog_compiler_static_works=yes -lt_cv_prog_gnu_ld=yes -lt_cv_sharedlib_from_linklib_cmd='printf %s\n' -lt_cv_shlibpath_overrides_runpath=yes -lt_cv_sys_global_symbol_pipe='sed -n -e '\''s/^.*[ ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p'\'' | sed '\''/ __gnu_lto/d'\''' -lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \(.*\) .*$/ {"\1", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW][ABCDGIRSTW]* .* \(.*\)$/ {"\1", (void *) \&\1},/p'\''' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='sed -n -e '\''s/^: \(.*\) .*$/ {"\1", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW][ABCDGIRSTW]* .* \(lib.*\)$/ {"\1", (void *) \&\1},/p'\'' -e '\''s/^[ABCDGIRSTW][ABCDGIRSTW]* .* \(.*\)$/ {"lib\1", (void *) \&\1},/p'\''' -lt_cv_sys_global_symbol_to_cdecl='sed -n -e '\''s/^T .* \(.*\)$/extern int \1();/p'\'' -e '\''s/^[ABCDGIRSTW][ABCDGIRSTW]* .* \(.*\)$/extern char \1;/p'\''' -lt_cv_sys_global_symbol_to_import= -lt_cv_sys_max_cmd_len=1572864 -lt_cv_to_host_file_cmd=func_convert_file_noop -lt_cv_to_tool_file_cmd=func_convert_file_noop -lt_cv_truncate_bin='/usr/bin/dd bs=4096 count=1' - -## ----------------- ## -## Output variables. ## -## ----------------- ## - -ACLOCAL='${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing aclocal-1.16' -AMDEPBACKSLASH='\' -AMDEP_FALSE='#' -AMDEP_TRUE='' -AMTAR='$${TAR-tar}' -AM_BACKSLASH='\' -AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -AM_DEFAULT_VERBOSITY='1' -AM_V='$(V)' -AR='ar' -AUTOCONF='${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing autoconf' -AUTOHEADER='${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing autoheader' -AUTOMAKE='${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing automake-1.16' -AWK='mawk' -CC='/usr/bin/clang' -CCDEPMODE='depmode=gcc3' -CFLAGS='-g -O3' -CPP='/usr/bin/clang -E' -CPPFLAGS='' -CYGPATH_W='echo' -DEFS='-DHAVE_CONFIG_H' -DEPDIR='.deps' -DLLTOOL='false' -DSYMUTIL='' -DUMPBIN='' -ECHO_C='' -ECHO_N='-n' -ECHO_T='' -EGREP='/usr/bin/grep -E' -EXEEXT='' -FGREP='/usr/bin/grep -F' -GREP='/usr/bin/grep' -INSTALL_DATA='${INSTALL} -m 644' -INSTALL_PROGRAM='${INSTALL}' -INSTALL_SCRIPT='${INSTALL}' -INSTALL_STRIP_PROGRAM='$(install_sh) -c -s' -LD='/usr/bin/ld -m elf_x86_64' -LDFLAGS='' -LIBOBJS='' -LIBS='-lm ' -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -LIPO='' -LN_S='ln -s' -LTLIBOBJS='' -LT_SYS_LIBRARY_PATH='' -MAINT='#' -MAINTAINER_MODE_FALSE='' -MAINTAINER_MODE_TRUE='#' -MAKEINFO='${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing makeinfo' -MANIFEST_TOOL=':' -MKDIR_P='/usr/bin/mkdir -p' -NM='/usr/bin/nm -B' -NMEDIT='' -OBJDUMP='objdump' -OBJEXT='o' -OTOOL64='' -OTOOL='' -PACKAGE='libev' -PACKAGE_BUGREPORT='' -PACKAGE_NAME='libev' -PACKAGE_STRING='libev 4.33' -PACKAGE_TARNAME='libev' -PACKAGE_URL='' -PACKAGE_VERSION='4.33' -PATH_SEPARATOR=':' -RANLIB='ranlib' -SED='/usr/bin/sed' -SET_MAKE='' -SHELL='/bin/bash' -STRIP='strip' -VERSION='4.33' -ac_ct_AR='ar' -ac_ct_CC='/usr/bin/clang' -ac_ct_DUMPBIN='' -am__EXEEXT_FALSE='' -am__EXEEXT_TRUE='#' -am__fastdepCC_FALSE='#' -am__fastdepCC_TRUE='' -am__include='include' -am__isrc='' -am__leading_dot='.' -am__nodep='_no' -am__quote='' -am__tar='$${TAR-tar} chof - "$$tardir"' -am__untar='$${TAR-tar} xf -' -bindir='${exec_prefix}/bin' -build='x86_64-pc-linux-gnu' -build_alias='' -build_cpu='x86_64' -build_os='linux-gnu' -build_vendor='pc' -datadir='${datarootdir}' -datarootdir='${prefix}/share' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -dvidir='${docdir}' -exec_prefix='${prefix}' -host='x86_64-pc-linux-gnu' -host_alias='' -host_cpu='x86_64' -host_os='linux-gnu' -host_vendor='pc' -htmldir='${docdir}' -includedir='${prefix}/include' -infodir='${datarootdir}/info' -install_sh='${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/install-sh' -libdir='${exec_prefix}/lib' -libexecdir='${exec_prefix}/libexec' -localedir='${datarootdir}/locale' -localstatedir='${prefix}/var' -mandir='${datarootdir}/man' -mkdir_p='$(MKDIR_P)' -oldincludedir='/usr/include' -pdfdir='${docdir}' -prefix='/usr/local' -program_transform_name='s,x,x,' -psdir='${docdir}' -runstatedir='${localstatedir}/run' -sbindir='${exec_prefix}/sbin' -sharedstatedir='${prefix}/com' -sysconfdir='${prefix}/etc' -target_alias='' - -## ----------- ## -## confdefs.h. ## -## ----------- ## - -/* confdefs.h */ -#define PACKAGE_NAME "libev" -#define PACKAGE_TARNAME "libev" -#define PACKAGE_VERSION "4.33" -#define PACKAGE_STRING "libev 4.33" -#define PACKAGE_BUGREPORT "" -#define PACKAGE_URL "" -#define PACKAGE "libev" -#define VERSION "4.33" -#define STDC_HEADERS 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRING_H 1 -#define HAVE_MEMORY_H 1 -#define HAVE_STRINGS_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_UNISTD_H 1 -#define HAVE_DLFCN_H 1 -#define LT_OBJDIR ".libs/" -#define HAVE_SYS_INOTIFY_H 1 -#define HAVE_SYS_EPOLL_H 1 -#define HAVE_POLL_H 1 -#define HAVE_SYS_TIMERFD_H 1 -#define HAVE_SYS_SELECT_H 1 -#define HAVE_SYS_EVENTFD_H 1 -#define HAVE_SYS_SIGNALFD_H 1 -#define HAVE_LINUX_AIO_ABI_H 1 -#define HAVE_LINUX_FS_H 1 -#define HAVE_INOTIFY_INIT 1 -#define HAVE_EPOLL_CTL 1 -#define HAVE_POLL 1 -#define HAVE_SELECT 1 -#define HAVE_EVENTFD 1 -#define HAVE_SIGNALFD 1 -#define HAVE_CLOCK_GETTIME 1 -#define HAVE_NANOSLEEP 1 -#define HAVE_KERNEL_RWF_T 1 -#define HAVE_FLOOR 1 - -configure: exit 0 diff --git a/deps/ngtcp2/ngtcp2/third-party/libev/config.status b/deps/ngtcp2/ngtcp2/third-party/libev/config.status deleted file mode 100755 index b18ddce4b1011f..00000000000000 --- a/deps/ngtcp2/ngtcp2/third-party/libev/config.status +++ /dev/null @@ -1,1983 +0,0 @@ -#! /bin/bash -# Generated by configure. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=${CONFIG_SHELL-/bin/bash} -export SHELL -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by libev $as_me 4.33, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -# Files that config.status was made for. -config_files=" Makefile" -config_headers=" config.h" -config_commands=" depfiles libtool" - -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE - -Configuration files: -$config_files - -Configuration headers: -$config_headers - -Configuration commands: -$config_commands - -Report bugs to the package provider." - -ac_cs_config="'CC=/usr/bin/clang'" -ac_cs_version="\ -libev config.status 4.33 -configured by ./configure, generated by GNU Autoconf 2.69, - with options \"$ac_cs_config\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='/home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev' -srcdir='.' -INSTALL='/usr/bin/install -c' -MKDIR_P='/usr/bin/mkdir -p' -AWK='mawk' -test -n "$AWK" || AWK=awk -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - as_fn_append CONFIG_HEADERS " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h) - # Conflict between --help and --header - as_fn_error $? "ambiguous option: \`$1' -Try \`$0 --help' for more information.";; - --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -if $ac_cs_recheck; then - set X /bin/bash './configure' 'CC=/usr/bin/clang' $ac_configure_extra_args --no-create --no-recursion - shift - $as_echo "running CONFIG_SHELL=/bin/bash $*" >&6 - CONFIG_SHELL='/bin/bash' - export CONFIG_SHELL - exec "$@" -fi - -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -# -# INIT-COMMANDS -# -AMDEP_TRUE="" MAKE="make" - - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' -double_quote_subst='s/\(["`\\]\)/\\\1/g' -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' -macro_version='2.4.6' -macro_revision='2.4.6' -enable_shared='yes' -enable_static='yes' -pic_mode='default' -enable_fast_install='needless' -shared_archive_member_spec='' -SHELL='/bin/bash' -ECHO='printf %s\n' -PATH_SEPARATOR=':' -host_alias='' -host='x86_64-pc-linux-gnu' -host_os='linux-gnu' -build_alias='' -build='x86_64-pc-linux-gnu' -build_os='linux-gnu' -SED='/usr/bin/sed' -Xsed='/usr/bin/sed -e 1s/^X//' -GREP='/usr/bin/grep' -EGREP='/usr/bin/grep -E' -FGREP='/usr/bin/grep -F' -LD='/usr/bin/ld -m elf_x86_64' -NM='/usr/bin/nm -B' -LN_S='ln -s' -max_cmd_len='1572864' -ac_objext='o' -exeext='' -lt_unset='unset' -lt_SP2NL='tr \040 \012' -lt_NL2SP='tr \015\012 \040\040' -lt_cv_to_host_file_cmd='func_convert_file_noop' -lt_cv_to_tool_file_cmd='func_convert_file_noop' -reload_flag=' -r' -reload_cmds='$LD$reload_flag -o $output$reload_objs' -OBJDUMP='objdump' -deplibs_check_method='pass_all' -file_magic_cmd='$MAGIC_CMD' -file_magic_glob='' -want_nocaseglob='no' -DLLTOOL='false' -sharedlib_from_linklib_cmd='printf %s\n' -AR='ar' -AR_FLAGS='cru' -archiver_list_spec='@' -STRIP='strip' -RANLIB='ranlib' -old_postinstall_cmds='chmod 644 $oldlib~$RANLIB $tool_oldlib' -old_postuninstall_cmds='' -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs~$RANLIB $tool_oldlib' -lock_old_archive_extraction='no' -CC='/usr/bin/clang' -CFLAGS='-g -O3' -compiler='/usr/bin/clang' -GCC='yes' -lt_cv_sys_global_symbol_pipe='sed -n -e '\''s/^.*[ ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p'\'' | sed '\''/ __gnu_lto/d'\''' -lt_cv_sys_global_symbol_to_cdecl='sed -n -e '\''s/^T .* \(.*\)$/extern int \1();/p'\'' -e '\''s/^[ABCDGIRSTW][ABCDGIRSTW]* .* \(.*\)$/extern char \1;/p'\''' -lt_cv_sys_global_symbol_to_import='' -lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \(.*\) .*$/ {"\1", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW][ABCDGIRSTW]* .* \(.*\)$/ {"\1", (void *) \&\1},/p'\''' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='sed -n -e '\''s/^: \(.*\) .*$/ {"\1", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW][ABCDGIRSTW]* .* \(lib.*\)$/ {"\1", (void *) \&\1},/p'\'' -e '\''s/^[ABCDGIRSTW][ABCDGIRSTW]* .* \(.*\)$/ {"lib\1", (void *) \&\1},/p'\''' -lt_cv_nm_interface='BSD nm' -nm_file_list_spec='@' -lt_sysroot='' -lt_cv_truncate_bin='/usr/bin/dd bs=4096 count=1' -objdir='.libs' -MAGIC_CMD='file' -lt_prog_compiler_no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' -lt_prog_compiler_pic=' -fPIC -DPIC' -lt_prog_compiler_wl='-Wl,' -lt_prog_compiler_static='-static' -lt_cv_prog_compiler_c_o='yes' -need_locks='no' -MANIFEST_TOOL=':' -DSYMUTIL='' -NMEDIT='' -LIPO='' -OTOOL='' -OTOOL64='' -libext='a' -shrext_cmds='.so' -extract_expsyms_cmds='' -archive_cmds_need_lc='no' -enable_shared_with_static_runtimes='no' -export_dynamic_flag_spec='$wl--export-dynamic' -whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' -compiler_needs_object='no' -old_archive_from_new_cmds='' -old_archive_from_expsyms_cmds='' -archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' -archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' -module_cmds='' -module_expsym_cmds='' -with_gnu_ld='yes' -allow_undefined_flag='' -no_undefined_flag='' -hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' -hardcode_libdir_separator='' -hardcode_direct='no' -hardcode_direct_absolute='no' -hardcode_minus_L='no' -hardcode_shlibpath_var='unsupported' -hardcode_automatic='no' -inherit_rpath='no' -link_all_deplibs='no' -always_export_symbols='no' -export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' -exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' -include_expsyms='' -prelink_cmds='' -postlink_cmds='' -file_list_spec='' -variables_saved_for_relink='PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH' -need_lib_prefix='no' -need_version='no' -version_type='linux' -runpath_var='LD_RUN_PATH' -shlibpath_var='LD_LIBRARY_PATH' -shlibpath_overrides_runpath='yes' -libname_spec='lib$name' -library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' -soname_spec='$libname$release$shared_ext$major' -install_override_mode='' -postinstall_cmds='' -postuninstall_cmds='' -finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' -finish_eval='' -hardcode_into_libs='yes' -sys_lib_search_path_spec='/usr/lib/clang/21 /usr/lib/gcc/x86_64-linux-gnu/12 /usr/lib64 /lib/x86_64-linux-gnu /lib64 /usr/lib/x86_64-linux-gnu /lib /usr/lib ' -configure_time_dlsearch_path='/lib /usr/lib /usr/lib/x86_64-linux-gnu/libfakeroot /opt/dell/dcc /usr/local/lib/i386-linux-gnu /lib/i386-linux-gnu /usr/lib/i386-linux-gnu /usr/local/lib/i686-linux-gnu /lib/i686-linux-gnu /usr/lib/i686-linux-gnu /usr/local/lib /opt/dell/srvadmin/lib64 /usr/local/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /lib32 /usr/lib32 ' -configure_time_lt_sys_library_path='' -hardcode_action='immediate' -enable_dlopen='unknown' -enable_dlopen_self='unknown' -enable_dlopen_self_static='unknown' -old_striplib='strip --strip-debug' -striplib='strip --strip-unneeded' - -LTCC='/usr/bin/clang' -LTCFLAGS='-g -O3' -compiler='/usr/bin/clang' - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# Quote evaled strings. -for var in SHELL ECHO PATH_SEPARATOR SED GREP EGREP FGREP LD NM LN_S lt_SP2NL lt_NL2SP reload_flag OBJDUMP deplibs_check_method file_magic_cmd file_magic_glob want_nocaseglob DLLTOOL sharedlib_from_linklib_cmd AR AR_FLAGS archiver_list_spec STRIP RANLIB CC CFLAGS compiler lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl lt_cv_sys_global_symbol_to_import lt_cv_sys_global_symbol_to_c_name_address lt_cv_sys_global_symbol_to_c_name_address_lib_prefix lt_cv_nm_interface nm_file_list_spec lt_cv_truncate_bin lt_prog_compiler_no_builtin_flag lt_prog_compiler_pic lt_prog_compiler_wl lt_prog_compiler_static lt_cv_prog_compiler_c_o need_locks MANIFEST_TOOL DSYMUTIL NMEDIT LIPO OTOOL OTOOL64 shrext_cmds export_dynamic_flag_spec whole_archive_flag_spec compiler_needs_object with_gnu_ld allow_undefined_flag no_undefined_flag hardcode_libdir_flag_spec hardcode_libdir_separator exclude_expsyms include_expsyms file_list_spec variables_saved_for_relink libname_spec library_names_spec soname_spec install_override_mode finish_eval old_striplib striplib; do - case `eval \\$ECHO \\""\\$$var"\\"` in - *[\\\`\"\$]*) - eval "lt_$var=\\\"\`\$ECHO \"\$$var\" | \$SED \"\$sed_quote_subst\"\`\\\"" ## exclude from sc_prohibit_nested_quotes - ;; - *) - eval "lt_$var=\\\"\$$var\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in reload_cmds old_postinstall_cmds old_postuninstall_cmds old_archive_cmds extract_expsyms_cmds old_archive_from_new_cmds old_archive_from_expsyms_cmds archive_cmds archive_expsym_cmds module_cmds module_expsym_cmds export_symbols_cmds prelink_cmds postlink_cmds postinstall_cmds postuninstall_cmds finish_cmds sys_lib_search_path_spec configure_time_dlsearch_path configure_time_lt_sys_library_path; do - case `eval \\$ECHO \\""\\$$var"\\"` in - *[\\\`\"\$]*) - eval "lt_$var=\\\"\`\$ECHO \"\$$var\" | \$SED -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ## exclude from sc_prohibit_nested_quotes - ;; - *) - eval "lt_$var=\\\"\$$var\\\"" - ;; - esac -done - -ac_aux_dir='.' - -# See if we are running on zsh, and set the options that allow our -# commands through without removal of \ escapes INIT. -if test -n "${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST -fi - - - PACKAGE='libev' - VERSION='4.33' - RM='rm -f' - ofile='libtool' - - - - - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -cat >>"$ac_tmp/subs1.awk" <<\_ACAWK && -S["am__EXEEXT_FALSE"]="" -S["am__EXEEXT_TRUE"]="#" -S["LTLIBOBJS"]="" -S["LIBOBJS"]="" -S["CPP"]="/usr/bin/clang -E" -S["LT_SYS_LIBRARY_PATH"]="" -S["OTOOL64"]="" -S["OTOOL"]="" -S["LIPO"]="" -S["NMEDIT"]="" -S["DSYMUTIL"]="" -S["MANIFEST_TOOL"]=":" -S["RANLIB"]="ranlib" -S["ac_ct_AR"]="ar" -S["AR"]="ar" -S["DLLTOOL"]="false" -S["OBJDUMP"]="objdump" -S["LN_S"]="ln -s" -S["NM"]="/usr/bin/nm -B" -S["ac_ct_DUMPBIN"]="" -S["DUMPBIN"]="" -S["LD"]="/usr/bin/ld -m elf_x86_64" -S["FGREP"]="/usr/bin/grep -F" -S["EGREP"]="/usr/bin/grep -E" -S["GREP"]="/usr/bin/grep" -S["SED"]="/usr/bin/sed" -S["host_os"]="linux-gnu" -S["host_vendor"]="pc" -S["host_cpu"]="x86_64" -S["host"]="x86_64-pc-linux-gnu" -S["build_os"]="linux-gnu" -S["build_vendor"]="pc" -S["build_cpu"]="x86_64" -S["build"]="x86_64-pc-linux-gnu" -S["LIBTOOL"]="$(SHELL) $(top_builddir)/libtool" -S["am__fastdepCC_FALSE"]="#" -S["am__fastdepCC_TRUE"]="" -S["CCDEPMODE"]="depmode=gcc3" -S["am__nodep"]="_no" -S["AMDEPBACKSLASH"]="\\" -S["AMDEP_FALSE"]="#" -S["AMDEP_TRUE"]="" -S["am__include"]="include" -S["DEPDIR"]=".deps" -S["OBJEXT"]="o" -S["EXEEXT"]="" -S["ac_ct_CC"]="/usr/bin/clang" -S["CPPFLAGS"]="" -S["LDFLAGS"]="" -S["CFLAGS"]="-g -O3" -S["CC"]="/usr/bin/clang" -S["MAINT"]="#" -S["MAINTAINER_MODE_FALSE"]="" -S["MAINTAINER_MODE_TRUE"]="#" -S["AM_BACKSLASH"]="\\" -S["AM_DEFAULT_VERBOSITY"]="1" -S["AM_DEFAULT_V"]="$(AM_DEFAULT_VERBOSITY)" -S["AM_V"]="$(V)" -S["am__untar"]="$${TAR-tar} xf -" -S["am__tar"]="$${TAR-tar} chof - \"$$tardir\"" -S["AMTAR"]="$${TAR-tar}" -S["am__leading_dot"]="." -S["SET_MAKE"]="" -S["AWK"]="mawk" -S["mkdir_p"]="$(MKDIR_P)" -S["MKDIR_P"]="/usr/bin/mkdir -p" -S["INSTALL_STRIP_PROGRAM"]="$(install_sh) -c -s" -S["STRIP"]="strip" -S["install_sh"]="${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/install-sh" -S["MAKEINFO"]="${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing makeinfo" -S["AUTOHEADER"]="${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing autoheader" -S["AUTOMAKE"]="${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing automake-1.16" -S["AUTOCONF"]="${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing autoconf" -S["ACLOCAL"]="${SHELL} /home/jsnell/projects/node/node/deps/ngtcp2/ngtcp2/third-party/libev/missing aclocal-1.16" -S["VERSION"]="4.33" -S["PACKAGE"]="libev" -S["CYGPATH_W"]="echo" -S["am__isrc"]="" -S["INSTALL_DATA"]="${INSTALL} -m 644" -S["INSTALL_SCRIPT"]="${INSTALL}" -S["INSTALL_PROGRAM"]="${INSTALL}" -S["target_alias"]="" -S["host_alias"]="" -S["build_alias"]="" -S["LIBS"]="-lm " -S["ECHO_T"]="" -S["ECHO_N"]="-n" -S["ECHO_C"]="" -S["DEFS"]="-DHAVE_CONFIG_H" -S["mandir"]="${datarootdir}/man" -S["localedir"]="${datarootdir}/locale" -S["libdir"]="${exec_prefix}/lib" -S["psdir"]="${docdir}" -S["pdfdir"]="${docdir}" -S["dvidir"]="${docdir}" -S["htmldir"]="${docdir}" -S["infodir"]="${datarootdir}/info" -S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}" -S["oldincludedir"]="/usr/include" -S["includedir"]="${prefix}/include" -S["runstatedir"]="${localstatedir}/run" -S["localstatedir"]="${prefix}/var" -S["sharedstatedir"]="${prefix}/com" -S["sysconfdir"]="${prefix}/etc" -S["datadir"]="${datarootdir}" -S["datarootdir"]="${prefix}/share" -S["libexecdir"]="${exec_prefix}/libexec" -S["sbindir"]="${exec_prefix}/sbin" -S["bindir"]="${exec_prefix}/bin" -S["program_transform_name"]="s,x,x," -S["prefix"]="/usr/local" -S["exec_prefix"]="${prefix}" -S["PACKAGE_URL"]="" -S["PACKAGE_BUGREPORT"]="" -S["PACKAGE_STRING"]="libev 4.33" -S["PACKAGE_VERSION"]="4.33" -S["PACKAGE_TARNAME"]="libev" -S["PACKAGE_NAME"]="libev" -S["PATH_SEPARATOR"]=":" -S["SHELL"]="/bin/bash" -S["am__quote"]="" -_ACAWK -cat >>"$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -fi # test -n "$CONFIG_FILES" - -# Set up the scripts for CONFIG_HEADERS section. -# No need to generate them if there are no CONFIG_HEADERS. -# This happens for instance with `./config.status Makefile'. -if test -n "$CONFIG_HEADERS"; then -cat >"$ac_tmp/defines.awk" <<\_ACAWK || -BEGIN { -D["PACKAGE_NAME"]=" \"libev\"" -D["PACKAGE_TARNAME"]=" \"libev\"" -D["PACKAGE_VERSION"]=" \"4.33\"" -D["PACKAGE_STRING"]=" \"libev 4.33\"" -D["PACKAGE_BUGREPORT"]=" \"\"" -D["PACKAGE_URL"]=" \"\"" -D["PACKAGE"]=" \"libev\"" -D["VERSION"]=" \"4.33\"" -D["STDC_HEADERS"]=" 1" -D["HAVE_SYS_TYPES_H"]=" 1" -D["HAVE_SYS_STAT_H"]=" 1" -D["HAVE_STDLIB_H"]=" 1" -D["HAVE_STRING_H"]=" 1" -D["HAVE_MEMORY_H"]=" 1" -D["HAVE_STRINGS_H"]=" 1" -D["HAVE_INTTYPES_H"]=" 1" -D["HAVE_STDINT_H"]=" 1" -D["HAVE_UNISTD_H"]=" 1" -D["HAVE_DLFCN_H"]=" 1" -D["LT_OBJDIR"]=" \".libs/\"" -D["HAVE_SYS_INOTIFY_H"]=" 1" -D["HAVE_SYS_EPOLL_H"]=" 1" -D["HAVE_POLL_H"]=" 1" -D["HAVE_SYS_TIMERFD_H"]=" 1" -D["HAVE_SYS_SELECT_H"]=" 1" -D["HAVE_SYS_EVENTFD_H"]=" 1" -D["HAVE_SYS_SIGNALFD_H"]=" 1" -D["HAVE_LINUX_AIO_ABI_H"]=" 1" -D["HAVE_LINUX_FS_H"]=" 1" -D["HAVE_INOTIFY_INIT"]=" 1" -D["HAVE_EPOLL_CTL"]=" 1" -D["HAVE_POLL"]=" 1" -D["HAVE_SELECT"]=" 1" -D["HAVE_EVENTFD"]=" 1" -D["HAVE_SIGNALFD"]=" 1" -D["HAVE_CLOCK_GETTIME"]=" 1" -D["HAVE_NANOSLEEP"]=" 1" -D["HAVE_KERNEL_RWF_T"]=" 1" -D["HAVE_FLOOR"]=" 1" - for (key in D) D_is_set[key] = 1 - FS = "" -} -/^[\t ]*#[\t ]*(define|undef)[\t ]+[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*([\t (]|$)/ { - line = $ 0 - split(line, arg, " ") - if (arg[1] == "#") { - defundef = arg[2] - mac1 = arg[3] - } else { - defundef = substr(arg[1], 2) - mac1 = arg[2] - } - split(mac1, mac2, "(") #) - macro = mac2[1] - prefix = substr(line, 1, index(line, defundef) - 1) - if (D_is_set[macro]) { - # Preserve the white space surrounding the "#". - print prefix "define", macro P[macro] D[macro] - next - } else { - # Replace #undef with comments. This is necessary, for example, - # in the case of _POSIX_SOURCE, which is predefined and required - # on some systems where configure will not decide to define it. - if (defundef == "undef") { - print "/*", prefix defundef, macro, "*/" - next - } - } -} -{ print } -_ACAWK - as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 -fi # test -n "$CONFIG_HEADERS" - - -eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac - ac_MKDIR_P=$MKDIR_P - case $MKDIR_P in - [\\/$]* | ?:[\\/]* ) ;; - */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; - esac -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} - ac_datarootdir_hack=' - s&@datadir@&${datarootdir}&g - s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g - s&@infodir@&${datarootdir}/info&g - s&@localedir@&${datarootdir}/locale&g - s&@mandir@&${datarootdir}/man&g - s&\${datarootdir}&${prefix}/share&g' ;; -esac -ac_sed_extra="/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -} - -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -s&@MKDIR_P@&$ac_MKDIR_P&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - :H) - # - # CONFIG_HEADER - # - if test x"$ac_file" != x-; then - { - $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" - } >"$ac_tmp/config.h" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 -$as_echo "$as_me: $ac_file is unchanged" >&6;} - else - rm -f "$ac_file" - mv "$ac_tmp/config.h" "$ac_file" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - fi - else - $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error $? "could not create -" "$LINENO" 5 - fi -# Compute "$ac_file"'s index in $config_headers. -_am_arg="$ac_file" -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $_am_arg | $_am_arg:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || -$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$_am_arg" : 'X\(//\)[^/]' \| \ - X"$_am_arg" : 'X\(//\)$' \| \ - X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$_am_arg" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'`/stamp-h$_am_stamp_count - ;; - - :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 -$as_echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Older Autoconf quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - # TODO: see whether this extra hack can be removed once we start - # requiring Autoconf 2.70 or later. - case $CONFIG_FILES in #( - *\'*) : - eval set x "$CONFIG_FILES" ;; #( - *) : - set x $CONFIG_FILES ;; #( - *) : - ;; -esac - shift - # Used to flag and report bootstrapping failures. - am_rc=0 - for am_mf - do - # Strip MF so we end up with the name of the file. - am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile which includes - # dependency-tracking related rules and includes. - # Grep'ing the whole file directly is not great: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ - || continue - am_dirpart=`$as_dirname -- "$am_mf" || -$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$am_mf" : 'X\(//\)[^/]' \| \ - X"$am_mf" : 'X\(//\)$' \| \ - X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$am_mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - am_filepart=`$as_basename -- "$am_mf" || -$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ - X"$am_mf" : 'X\(//\)$' \| \ - X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$am_mf" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - { echo "$as_me:$LINENO: cd "$am_dirpart" \ - && sed -e '/# am--include-marker/d' "$am_filepart" \ - | $MAKE -f - am--depfiles" >&5 - (cd "$am_dirpart" \ - && sed -e '/# am--include-marker/d' "$am_filepart" \ - | $MAKE -f - am--depfiles) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } || am_rc=$? - done - if test $am_rc -ne 0; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "Something went wrong bootstrapping makefile fragments - for automatic dependency tracking. Try re-running configure with the - '--disable-dependency-tracking' option to at least be able to build - the package (albeit without support for automatic dependency tracking). -See \`config.log' for more details" "$LINENO" 5; } - fi - { am_dirpart=; unset am_dirpart;} - { am_filepart=; unset am_filepart;} - { am_mf=; unset am_mf;} - { am_rc=; unset am_rc;} - rm -f conftest-deps.mk -} - ;; - "libtool":C) - - # See if we are running on zsh, and set the options that allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST - fi - - cfgfile=${ofile}T - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL -# Generated automatically by $as_me ($PACKAGE) $VERSION -# NOTE: Changes made to this file will be lost: look at ltmain.sh. - -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit, 1996 - -# Copyright (C) 2014 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program or library that is built -# using GNU Libtool, you may include this file under the same -# distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -# The names of the tagged configurations supported by this script. -available_tags='' - -# Configured defaults for sys_lib_dlsearch_path munging. -: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} - -# ### BEGIN LIBTOOL CONFIG - -# Which release of libtool.m4 was used? -macro_version=$macro_version -macro_revision=$macro_revision - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# What type of objects to build. -pic_mode=$pic_mode - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# Shared archive member basename,for filename based shared library versioning on AIX. -shared_archive_member_spec=$shared_archive_member_spec - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# An echo program that protects backslashes. -ECHO=$lt_ECHO - -# The PATH separator for the build system. -PATH_SEPARATOR=$lt_PATH_SEPARATOR - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="\$SED -e 1s/^X//" - -# A grep program that handles long lines. -GREP=$lt_GREP - -# An ERE matcher. -EGREP=$lt_EGREP - -# A literal string matcher. -FGREP=$lt_FGREP - -# A BSD- or MS-compatible name lister. -NM=$lt_NM - -# Whether we need soft or hard links. -LN_S=$lt_LN_S - -# What is the maximum length of a command? -max_cmd_len=$max_cmd_len - -# Object file suffix (normally "o"). -objext=$ac_objext - -# Executable file suffix (normally ""). -exeext=$exeext - -# whether the shell understands "unset". -lt_unset=$lt_unset - -# turn spaces into newlines. -SP2NL=$lt_lt_SP2NL - -# turn newlines into spaces. -NL2SP=$lt_lt_NL2SP - -# convert \$build file names to \$host format. -to_host_file_cmd=$lt_cv_to_host_file_cmd - -# convert \$build files to toolchain format. -to_tool_file_cmd=$lt_cv_to_tool_file_cmd - -# An object symbol dumper. -OBJDUMP=$lt_OBJDUMP - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method = "file_magic". -file_magic_cmd=$lt_file_magic_cmd - -# How to find potential files when deplibs_check_method = "file_magic". -file_magic_glob=$lt_file_magic_glob - -# Find potential files using nocaseglob when deplibs_check_method = "file_magic". -want_nocaseglob=$lt_want_nocaseglob - -# DLL creation program. -DLLTOOL=$lt_DLLTOOL - -# Command to associate shared and link libraries. -sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd - -# The archiver. -AR=$lt_AR - -# Flags to create an archive. -AR_FLAGS=$lt_AR_FLAGS - -# How to feed a file listing to the archiver. -archiver_list_spec=$lt_archiver_list_spec - -# A symbol stripping program. -STRIP=$lt_STRIP - -# Commands used to install an old-style archive. -RANLIB=$lt_RANLIB -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Whether to use a lock for old archive extraction. -lock_old_archive_extraction=$lock_old_archive_extraction - -# A C compiler. -LTCC=$lt_CC - -# LTCC compiler flags. -LTCFLAGS=$lt_CFLAGS - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration. -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm into a list of symbols to manually relocate. -global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import - -# Transform the output of nm in a C name address pair. -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# Transform the output of nm in a C name address pair when lib prefix is needed. -global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix - -# The name lister interface. -nm_interface=$lt_lt_cv_nm_interface - -# Specify filename containing input files for \$NM. -nm_file_list_spec=$lt_nm_file_list_spec - -# The root where to search for dependent libraries,and where our libraries should be installed. -lt_sysroot=$lt_sysroot - -# Command to truncate a binary pipe. -lt_truncate_bin=$lt_lt_cv_truncate_bin - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# Used to examine libraries when file_magic_cmd begins with "file". -MAGIC_CMD=$MAGIC_CMD - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Manifest tool. -MANIFEST_TOOL=$lt_MANIFEST_TOOL - -# Tool to manipulate archived DWARF debug symbol files on Mac OS X. -DSYMUTIL=$lt_DSYMUTIL - -# Tool to change global to local symbols on Mac OS X. -NMEDIT=$lt_NMEDIT - -# Tool to manipulate fat objects and archives on Mac OS X. -LIPO=$lt_LIPO - -# ldd/readelf like tool for Mach-O binaries on Mac OS X. -OTOOL=$lt_OTOOL - -# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. -OTOOL64=$lt_OTOOL64 - -# Old archive suffix (normally "a"). -libext=$libext - -# Shared library suffix (normally ".so"). -shrext_cmds=$lt_shrext_cmds - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at link time. -variables_saved_for_relink=$lt_variables_saved_for_relink - -# Do we need the "lib" prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Library versioning type. -version_type=$version_type - -# Shared library runtime path variable. -runpath_var=$runpath_var - -# Shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Permission mode override for installation of shared libraries. -install_override_mode=$lt_install_override_mode - -# Command to use after installation of a shared archive. -postinstall_cmds=$lt_postinstall_cmds - -# Command to use after uninstallation of a shared archive. -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# As "finish_cmds", except a single script fragment to be evaled but -# not shown. -finish_eval=$lt_finish_eval - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Compile-time system search path for libraries. -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Detected run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path - -# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. -configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - - -# The linker used to build libraries. -LD=$lt_LD - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# Commands used to build an old-style archive. -old_archive_cmds=$lt_old_archive_cmds - -# A language specific compiler. -CC=$lt_compiler - -# Is the compiler the GNU compiler? -with_gcc=$GCC - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc - -# Whether or not to disallow shared libs when runtime libs are static. -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec - -# Whether the compiler copes with passing no objects directly. -compiler_needs_object=$lt_compiler_needs_object - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds - -# Commands used to build a shared archive. -archive_cmds=$lt_archive_cmds -archive_expsym_cmds=$lt_archive_expsym_cmds - -# Commands used to build a loadable module if different from building -# a shared archive. -module_cmds=$lt_module_cmds -module_expsym_cmds=$lt_module_expsym_cmds - -# Whether we are building with GNU ld or not. -with_gnu_ld=$lt_with_gnu_ld - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag - -# Flag that enforces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec - -# Whether we need a single "-rpath" flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator - -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes -# DIR into the resulting binary. -hardcode_direct=$hardcode_direct - -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes -# DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \$shlibpath_var if the -# library is relocated. -hardcode_direct_absolute=$hardcode_direct_absolute - -# Set to "yes" if using the -LDIR flag during linking hardcodes DIR -# into the resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR -# into the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Set to "yes" if building a shared library automatically hardcodes DIR -# into the library and all subsequent libraries and executables linked -# against it. -hardcode_automatic=$hardcode_automatic - -# Set to yes if linker adds runtime paths of dependent libraries -# to runtime path list. -inherit_rpath=$inherit_rpath - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs - -# Set to "yes" if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms - -# Commands necessary for linking programs (against libraries) with templates. -prelink_cmds=$lt_prelink_cmds - -# Commands necessary for finishing linking programs. -postlink_cmds=$lt_postlink_cmds - -# Specify filename containing input files. -file_list_spec=$lt_file_list_spec - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# ### END LIBTOOL CONFIG - -_LT_EOF - - cat <<'_LT_EOF' >> "$cfgfile" - -# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE - -# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x$2 in - x) - ;; - *:) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" - ;; - x:*) - eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" - ;; - *) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" - ;; - esac -} - - -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in $*""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} - - -# ### END FUNCTIONS SHARED WITH CONFIGURE - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test set != "${COLLECT_NAMES+set}"; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - -ltmain=$ac_aux_dir/ltmain.sh - - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" - - ;; - - esac -done # for ac_tag - - -as_fn_exit 0 diff --git a/deps/ngtcp2/ngtcp2/third-party/libev/libtool b/deps/ngtcp2/ngtcp2/third-party/libev/libtool deleted file mode 100755 index 4378dd37aefa43..00000000000000 --- a/deps/ngtcp2/ngtcp2/third-party/libev/libtool +++ /dev/null @@ -1,11746 +0,0 @@ -#! /bin/bash -# Generated automatically by config.status (libev) 4.33 -# NOTE: Changes made to this file will be lost: look at ltmain.sh. - -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit, 1996 - -# Copyright (C) 2014 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program or library that is built -# using GNU Libtool, you may include this file under the same -# distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -# The names of the tagged configurations supported by this script. -available_tags='' - -# Configured defaults for sys_lib_dlsearch_path munging. -: ${LT_SYS_LIBRARY_PATH=""} - -# ### BEGIN LIBTOOL CONFIG - -# Which release of libtool.m4 was used? -macro_version=2.4.6 -macro_revision=2.4.6 - -# Whether or not to build shared libraries. -build_libtool_libs=yes - -# Whether or not to build static libraries. -build_old_libs=yes - -# What type of objects to build. -pic_mode=default - -# Whether or not to optimize for fast installation. -fast_install=needless - -# Shared archive member basename,for filename based shared library versioning on AIX. -shared_archive_member_spec= - -# Shell to use when invoking shell scripts. -SHELL="/bin/bash" - -# An echo program that protects backslashes. -ECHO="printf %s\\n" - -# The PATH separator for the build system. -PATH_SEPARATOR=":" - -# The host system. -host_alias= -host=x86_64-pc-linux-gnu -host_os=linux-gnu - -# The build system. -build_alias= -build=x86_64-pc-linux-gnu -build_os=linux-gnu - -# A sed program that does not truncate output. -SED="/usr/bin/sed" - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e 1s/^X//" - -# A grep program that handles long lines. -GREP="/usr/bin/grep" - -# An ERE matcher. -EGREP="/usr/bin/grep -E" - -# A literal string matcher. -FGREP="/usr/bin/grep -F" - -# A BSD- or MS-compatible name lister. -NM="/usr/bin/nm -B" - -# Whether we need soft or hard links. -LN_S="ln -s" - -# What is the maximum length of a command? -max_cmd_len=1572864 - -# Object file suffix (normally "o"). -objext=o - -# Executable file suffix (normally ""). -exeext= - -# whether the shell understands "unset". -lt_unset=unset - -# turn spaces into newlines. -SP2NL="tr \\040 \\012" - -# turn newlines into spaces. -NL2SP="tr \\015\\012 \\040\\040" - -# convert $build file names to $host format. -to_host_file_cmd=func_convert_file_noop - -# convert $build files to toolchain format. -to_tool_file_cmd=func_convert_file_noop - -# An object symbol dumper. -OBJDUMP="objdump" - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method="pass_all" - -# Command to use when deplibs_check_method = "file_magic". -file_magic_cmd="\$MAGIC_CMD" - -# How to find potential files when deplibs_check_method = "file_magic". -file_magic_glob="" - -# Find potential files using nocaseglob when deplibs_check_method = "file_magic". -want_nocaseglob="no" - -# DLL creation program. -DLLTOOL="false" - -# Command to associate shared and link libraries. -sharedlib_from_linklib_cmd="printf %s\\n" - -# The archiver. -AR="ar" - -# Flags to create an archive. -AR_FLAGS="cru" - -# How to feed a file listing to the archiver. -archiver_list_spec="@" - -# A symbol stripping program. -STRIP="strip" - -# Commands used to install an old-style archive. -RANLIB="ranlib" -old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$tool_oldlib" -old_postuninstall_cmds="" - -# Whether to use a lock for old archive extraction. -lock_old_archive_extraction=no - -# A C compiler. -LTCC="/usr/bin/clang" - -# LTCC compiler flags. -LTCFLAGS="-g -O3" - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ ][ ]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p' | sed '/ __gnu_lto/d'" - -# Transform the output of nm in a proper C declaration. -global_symbol_to_cdecl="sed -n -e 's/^T .* \\(.*\\)\$/extern int \\1();/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/extern char \\1;/p'" - -# Transform the output of nm into a list of symbols to manually relocate. -global_symbol_to_import="" - -# Transform the output of nm in a C name address pair. -global_symbol_to_c_name_address="sed -n -e 's/^: \\(.*\\) .*\$/ {\"\\1\", (void *) 0},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/ {\"\\1\", (void *) \\&\\1},/p'" - -# Transform the output of nm in a C name address pair when lib prefix is needed. -global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \\(.*\\) .*\$/ {\"\\1\", (void *) 0},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(lib.*\\)\$/ {\"\\1\", (void *) \\&\\1},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/ {\"lib\\1\", (void *) \\&\\1},/p'" - -# The name lister interface. -nm_interface="BSD nm" - -# Specify filename containing input files for $NM. -nm_file_list_spec="@" - -# The root where to search for dependent libraries,and where our libraries should be installed. -lt_sysroot= - -# Command to truncate a binary pipe. -lt_truncate_bin="/usr/bin/dd bs=4096 count=1" - -# The name of the directory that contains temporary libtool files. -objdir=.libs - -# Used to examine libraries when file_magic_cmd begins with "file". -MAGIC_CMD=file - -# Must we lock files when doing compilation? -need_locks="no" - -# Manifest tool. -MANIFEST_TOOL=":" - -# Tool to manipulate archived DWARF debug symbol files on Mac OS X. -DSYMUTIL="" - -# Tool to change global to local symbols on Mac OS X. -NMEDIT="" - -# Tool to manipulate fat objects and archives on Mac OS X. -LIPO="" - -# ldd/readelf like tool for Mach-O binaries on Mac OS X. -OTOOL="" - -# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. -OTOOL64="" - -# Old archive suffix (normally "a"). -libext=a - -# Shared library suffix (normally ".so"). -shrext_cmds=".so" - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds="" - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at link time. -variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" - -# Do we need the "lib" prefix for modules? -need_lib_prefix=no - -# Do we need a version for libraries? -need_version=no - -# Library versioning type. -version_type=linux - -# Shared library runtime path variable. -runpath_var=LD_RUN_PATH - -# Shared library path variable. -shlibpath_var=LD_LIBRARY_PATH - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=yes - -# Format of library name prefix. -libname_spec="lib\$name" - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME -library_names_spec="\$libname\$release\$shared_ext\$versuffix \$libname\$release\$shared_ext\$major \$libname\$shared_ext" - -# The coded name of the library, if different from the real name. -soname_spec="\$libname\$release\$shared_ext\$major" - -# Permission mode override for installation of shared libraries. -install_override_mode="" - -# Command to use after installation of a shared archive. -postinstall_cmds="" - -# Command to use after uninstallation of a shared archive. -postuninstall_cmds="" - -# Commands used to finish a libtool library installation in a directory. -finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir" - -# As "finish_cmds", except a single script fragment to be evaled but -# not shown. -finish_eval="" - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=yes - -# Compile-time system search path for libraries. -sys_lib_search_path_spec="/usr/lib/clang/21 /usr/lib/gcc/x86_64-linux-gnu/12 /usr/lib64 /lib/x86_64-linux-gnu /lib64 /usr/lib/x86_64-linux-gnu /lib /usr/lib " - -# Detected run-time system search path for libraries. -sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib/x86_64-linux-gnu/libfakeroot /opt/dell/dcc /usr/local/lib/i386-linux-gnu /lib/i386-linux-gnu /usr/lib/i386-linux-gnu /usr/local/lib/i686-linux-gnu /lib/i686-linux-gnu /usr/lib/i686-linux-gnu /usr/local/lib /opt/dell/srvadmin/lib64 /usr/local/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /lib32 /usr/lib32 " - -# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. -configure_time_lt_sys_library_path="" - -# Whether dlopen is supported. -dlopen_support=unknown - -# Whether dlopen of programs is supported. -dlopen_self=unknown - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=unknown - -# Commands to strip libraries. -old_striplib="strip --strip-debug" -striplib="strip --strip-unneeded" - - -# The linker used to build libraries. -LD="/usr/bin/ld -m elf_x86_64" - -# How to create reloadable object files. -reload_flag=" -r" -reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs" - -# Commands used to build an old-style archive. -old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$tool_oldlib" - -# A language specific compiler. -CC="/usr/bin/clang" - -# Is the compiler the GNU compiler? -with_gcc=yes - -# Compiler flag to turn off builtin functions. -no_builtin_flag=" -fno-builtin -fno-rtti -fno-exceptions" - -# Additional compiler flags for building library objects. -pic_flag=" -fPIC -DPIC" - -# How to pass a linker flag through the compiler. -wl="-Wl," - -# Compiler flag to prevent dynamic linking. -link_static_flag="-static" - -# Does compiler simultaneously support -c and -o options? -compiler_c_o="yes" - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=no - -# Whether or not to disallow shared libs when runtime libs are static. -allow_libtool_libs_with_static_runtimes=no - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec="\$wl--export-dynamic" - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec="\$wl--whole-archive\$convenience \$wl--no-whole-archive" - -# Whether the compiler copes with passing no objects directly. -compiler_needs_object="no" - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds="" - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds="" - -# Commands used to build a shared archive. -archive_cmds="\$CC -shared \$pic_flag \$libobjs \$deplibs \$compiler_flags \$wl-soname \$wl\$soname -o \$lib" -archive_expsym_cmds="echo \\\"{ global:\\\" > \$output_objdir/\$libname.ver~ - cat \$export_symbols | sed -e \\\"s/\\\\(.*\\\\)/\\\\1;/\\\" >> \$output_objdir/\$libname.ver~ - echo \\\"local: *; };\\\" >> \$output_objdir/\$libname.ver~ - \$CC -shared \$pic_flag \$libobjs \$deplibs \$compiler_flags \$wl-soname \$wl\$soname \$wl-version-script \$wl\$output_objdir/\$libname.ver -o \$lib" - -# Commands used to build a loadable module if different from building -# a shared archive. -module_cmds="" -module_expsym_cmds="" - -# Whether we are building with GNU ld or not. -with_gnu_ld="yes" - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag="" - -# Flag that enforces no undefined symbols. -no_undefined_flag="" - -# Flag to hardcode $libdir into a binary during linking. -# This must work even if $libdir does not exist -hardcode_libdir_flag_spec="\$wl-rpath \$wl\$libdir" - -# Whether we need a single "-rpath" flag with a separated argument. -hardcode_libdir_separator="" - -# Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes -# DIR into the resulting binary. -hardcode_direct=no - -# Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes -# DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting $shlibpath_var if the -# library is relocated. -hardcode_direct_absolute=no - -# Set to "yes" if using the -LDIR flag during linking hardcodes DIR -# into the resulting binary. -hardcode_minus_L=no - -# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR -# into the resulting binary. -hardcode_shlibpath_var=unsupported - -# Set to "yes" if building a shared library automatically hardcodes DIR -# into the library and all subsequent libraries and executables linked -# against it. -hardcode_automatic=no - -# Set to yes if linker adds runtime paths of dependent libraries -# to runtime path list. -inherit_rpath=no - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=no - -# Set to "yes" if exported symbols are required. -always_export_symbols=no - -# The commands to list exported symbols. -export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols" - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms="_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*" - -# Symbols that must always be exported. -include_expsyms="" - -# Commands necessary for linking programs (against libraries) with templates. -prelink_cmds="" - -# Commands necessary for finishing linking programs. -postlink_cmds="" - -# Specify filename containing input files. -file_list_spec="" - -# How to hardcode a shared library path into an executable. -hardcode_action=immediate - -# ### END LIBTOOL CONFIG - - -# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE - -# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x$2 in - x) - ;; - *:) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" - ;; - x:*) - eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" - ;; - *) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" - ;; - esac -} - - -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in $*""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} - - -# ### END FUNCTIONS SHARED WITH CONFIGURE - -#! /bin/sh -## DO NOT EDIT - This file generated from ./build-aux/ltmain.in -## by inline-source v2014-01-03.01 - -# libtool (GNU libtool) 2.4.6 -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit , 1996 - -# Copyright (C) 1996-2015 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -PROGRAM=libtool -PACKAGE=libtool -VERSION="2.4.6 Debian-2.4.6-9" -package_revision=2.4.6 - - -## ------ ## -## Usage. ## -## ------ ## - -# Run './libtool --help' for help with using this script from the -# command line. - - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# After configure completes, it has a better idea of some of the -# shell tools we need than the defaults used by the functions shared -# with bootstrap, so set those here where they can still be over- -# ridden by the user, but otherwise take precedence. - -: ${AUTOCONF="autoconf"} -: ${AUTOMAKE="automake"} - - -## -------------------------- ## -## Source external libraries. ## -## -------------------------- ## - -# Much of our low-level functionality needs to be sourced from external -# libraries, which are installed to $pkgauxdir. - -# Set a version string for this script. -scriptversion=2015-01-20.17; # UTC - -# General shell script boiler plate, and helper functions. -# Written by Gary V. Vaughan, 2004 - -# Copyright (C) 2004-2015 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. - -# As a special exception to the GNU General Public License, if you distribute -# this file as part of a program or library that is built using GNU Libtool, -# you may include this file under the same distribution terms that you use -# for the rest of that program. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Evaluate this file near the top of your script to gain access to -# the functions and variables defined here: -# -# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh -# -# If you need to override any of the default environment variable -# settings, do that before evaluating this file. - - -## -------------------- ## -## Shell normalisation. ## -## -------------------- ## - -# Some shells need a little help to be as Bourne compatible as possible. -# Before doing anything else, make sure all that help has been provided! - -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac -fi - -# NLS nuisances: We save the old values in case they are required later. -_G_user_locale= -_G_safe_locale= -for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test set = \"\${$_G_var+set}\"; then - save_$_G_var=\$$_G_var - $_G_var=C - export $_G_var - _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" - _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" - fi" -done - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Make sure IFS has a sensible default -sp=' ' -nl=' -' -IFS="$sp $nl" - -# There are apparently some retarded systems that use ';' as a PATH separator! -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - - -## ------------------------- ## -## Locate command utilities. ## -## ------------------------- ## - - -# func_executable_p FILE -# ---------------------- -# Check that FILE is an executable regular file. -func_executable_p () -{ - test -f "$1" && test -x "$1" -} - - -# func_path_progs PROGS_LIST CHECK_FUNC [PATH] -# -------------------------------------------- -# Search for either a program that responds to --version with output -# containing "GNU", or else returned by CHECK_FUNC otherwise, by -# trying all the directories in PATH with each of the elements of -# PROGS_LIST. -# -# CHECK_FUNC should accept the path to a candidate program, and -# set $func_check_prog_result if it truncates its output less than -# $_G_path_prog_max characters. -func_path_progs () -{ - _G_progs_list=$1 - _G_check_func=$2 - _G_PATH=${3-"$PATH"} - - _G_path_prog_max=0 - _G_path_prog_found=false - _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} - for _G_dir in $_G_PATH; do - IFS=$_G_save_IFS - test -z "$_G_dir" && _G_dir=. - for _G_prog_name in $_G_progs_list; do - for _exeext in '' .EXE; do - _G_path_prog=$_G_dir/$_G_prog_name$_exeext - func_executable_p "$_G_path_prog" || continue - case `"$_G_path_prog" --version 2>&1` in - *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; - *) $_G_check_func $_G_path_prog - func_path_progs_result=$func_check_prog_result - ;; - esac - $_G_path_prog_found && break 3 - done - done - done - IFS=$_G_save_IFS - test -z "$func_path_progs_result" && { - echo "no acceptable sed could be found in \$PATH" >&2 - exit 1 - } -} - - -# We want to be able to use the functions in this file before configure -# has figured out where the best binaries are kept, which means we have -# to search for them ourselves - except when the results are already set -# where we skip the searches. - -# Unless the user overrides by setting SED, search the path for either GNU -# sed, or the sed that truncates its output the least. -test -z "$SED" && { - _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for _G_i in 1 2 3 4 5 6 7; do - _G_sed_script=$_G_sed_script$nl$_G_sed_script - done - echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed - _G_sed_script= - - func_check_prog_sed () - { - _G_path_prog=$1 - - _G_count=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo '' >> conftest.nl - "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin - rm -f conftest.sed - SED=$func_path_progs_result -} - - -# Unless the user overrides by setting GREP, search the path for either GNU -# grep, or the grep that truncates its output the least. -test -z "$GREP" && { - func_check_prog_grep () - { - _G_path_prog=$1 - - _G_count=0 - _G_path_prog_max=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo 'GREP' >> conftest.nl - "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin - GREP=$func_path_progs_result -} - - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# All uppercase variable names are used for environment variables. These -# variables can be overridden by the user before calling a script that -# uses them if a suitable command of that name is not already available -# in the command search PATH. - -: ${CP="cp -f"} -: ${ECHO="printf %s\n"} -: ${EGREP="$GREP -E"} -: ${FGREP="$GREP -F"} -: ${LN_S="ln -s"} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} - - -## -------------------- ## -## Useful sed snippets. ## -## -------------------- ## - -sed_dirname='s|/[^/]*$||' -sed_basename='s|^.*/||' - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Same as above, but do not quote variable references. -sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' - -# Sed substitution that converts a w32 file name or path -# that contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-'\' parameter expansions in output of sed_double_quote_subst that -# were '\'-ed in input to the same. If an odd number of '\' preceded a -# '$' in input to sed_double_quote_subst, that '$' was protected from -# expansion. Since each input '\' is now two '\'s, look for any number -# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. -_G_bs='\\' -_G_bs2='\\\\' -_G_bs4='\\\\\\\\' -_G_dollar='\$' -sed_double_backslash="\ - s/$_G_bs4/&\\ -/g - s/^$_G_bs2$_G_dollar/$_G_bs&/ - s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g - s/\n//g" - - -## ----------------- ## -## Global variables. ## -## ----------------- ## - -# Except for the global variables explicitly listed below, the following -# functions in the '^func_' namespace, and the '^require_' namespace -# variables initialised in the 'Resource management' section, sourcing -# this file will not pollute your global namespace with anything -# else. There's no portable way to scope variables in Bourne shell -# though, so actually running these functions will sometimes place -# results into a variable named after the function, and often use -# temporary variables in the '^_G_' namespace. If you are careful to -# avoid using those namespaces casually in your sourcing script, things -# should continue to work as you expect. And, of course, you can freely -# overwrite any of the functions or variables defined here before -# calling anything to customize them. - -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -# Allow overriding, eg assuming that you follow the convention of -# putting '$debug_cmd' at the start of all your functions, you can get -# bash to show function call trace with: -# -# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name -debug_cmd=${debug_cmd-":"} -exit_cmd=: - -# By convention, finish your script with: -# -# exit $exit_status -# -# so that you can set exit_status to non-zero if you want to indicate -# something went wrong during execution without actually bailing out at -# the point of failure. -exit_status=$EXIT_SUCCESS - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath=$0 - -# The name of this program. -progname=`$ECHO "$progpath" |$SED "$sed_basename"` - -# Make sure we have an absolute progpath for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` - progdir=`cd "$progdir" && pwd` - progpath=$progdir/$progname - ;; - *) - _G_IFS=$IFS - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS=$_G_IFS - test -x "$progdir/$progname" && break - done - IFS=$_G_IFS - test -n "$progdir" || progdir=`pwd` - progpath=$progdir/$progname - ;; -esac - - -## ----------------- ## -## Standard options. ## -## ----------------- ## - -# The following options affect the operation of the functions defined -# below, and should be set appropriately depending on run-time para- -# meters passed on the command line. - -opt_dry_run=false -opt_quiet=false -opt_verbose=false - -# Categories 'all' and 'none' are always available. Append any others -# you will pass as the first argument to func_warning from your own -# code. -warning_categories= - -# By default, display warnings according to 'opt_warning_types'. Set -# 'warning_func' to ':' to elide all warnings, or func_fatal_error to -# treat the next displayed warning as a fatal error. -warning_func=func_warn_and_continue - -# Set to 'all' to display all warnings, 'none' to suppress all -# warnings, or a space delimited list of some subset of -# 'warning_categories' to display only the listed warnings. -opt_warning_types=all - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Call them using their associated -# 'require_*' variable to ensure that they are executed, at most, once. -# -# It's entirely deliberate that calling these functions can set -# variables that don't obey the namespace limitations obeyed by the rest -# of this file, in order that that they be as useful as possible to -# callers. - - -# require_term_colors -# ------------------- -# Allow display of bold text on terminals that support it. -require_term_colors=func_require_term_colors -func_require_term_colors () -{ - $debug_cmd - - test -t 1 && { - # COLORTERM and USE_ANSI_COLORS environment variables take - # precedence, because most terminfo databases neglect to describe - # whether color sequences are supported. - test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} - - if test 1 = "$USE_ANSI_COLORS"; then - # Standard ANSI escape sequences - tc_reset='' - tc_bold=''; tc_standout='' - tc_red=''; tc_green='' - tc_blue=''; tc_cyan='' - else - # Otherwise trust the terminfo database after all. - test -n "`tput sgr0 2>/dev/null`" && { - tc_reset=`tput sgr0` - test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` - tc_standout=$tc_bold - test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` - test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` - test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` - test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` - test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` - } - fi - } - - require_term_colors=: -} - - -## ----------------- ## -## Function library. ## -## ----------------- ## - -# This section contains a variety of useful functions to call in your -# scripts. Take note of the portable wrappers for features provided by -# some modern shells, which will fall back to slower equivalents on -# less featureful shells. - - -# func_append VAR VALUE -# --------------------- -# Append VALUE onto the existing contents of VAR. - - # We should try to minimise forks, especially on Windows where they are - # unreasonably slow, so skip the feature probes when bash or zsh are - # being used: - if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then - : ${_G_HAVE_ARITH_OP="yes"} - : ${_G_HAVE_XSI_OPS="yes"} - # The += operator was introduced in bash 3.1 - case $BASH_VERSION in - [12].* | 3.0 | 3.0*) ;; - *) - : ${_G_HAVE_PLUSEQ_OP="yes"} - ;; - esac - fi - - # _G_HAVE_PLUSEQ_OP - # Can be empty, in which case the shell is probed, "yes" if += is - # useable or anything else if it does not work. - test -z "$_G_HAVE_PLUSEQ_OP" \ - && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ - && _G_HAVE_PLUSEQ_OP=yes - -if test yes = "$_G_HAVE_PLUSEQ_OP" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_append () - { - $debug_cmd - - eval "$1+=\$2" - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_append () - { - $debug_cmd - - eval "$1=\$$1\$2" - } -fi - - -# func_append_quoted VAR VALUE -# ---------------------------- -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -if test yes = "$_G_HAVE_PLUSEQ_OP"; then - eval 'func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1+=\\ \$func_quote_for_eval_result" - }' -else - func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1=\$$1\\ \$func_quote_for_eval_result" - } -fi - - -# func_append_uniq VAR VALUE -# -------------------------- -# Append unique VALUE onto the existing contents of VAR, assuming -# entries are delimited by the first character of VALUE. For example: -# -# func_append_uniq options " --another-option option-argument" -# -# will only append to $options if " --another-option option-argument " -# is not already present somewhere in $options already (note spaces at -# each end implied by leading space in second argument). -func_append_uniq () -{ - $debug_cmd - - eval _G_current_value='`$ECHO $'$1'`' - _G_delim=`expr "$2" : '\(.\)'` - - case $_G_delim$_G_current_value$_G_delim in - *"$2$_G_delim"*) ;; - *) func_append "$@" ;; - esac -} - - -# func_arith TERM... -# ------------------ -# Set func_arith_result to the result of evaluating TERMs. - test -z "$_G_HAVE_ARITH_OP" \ - && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ - && _G_HAVE_ARITH_OP=yes - -if test yes = "$_G_HAVE_ARITH_OP"; then - eval 'func_arith () - { - $debug_cmd - - func_arith_result=$(( $* )) - }' -else - func_arith () - { - $debug_cmd - - func_arith_result=`expr "$@"` - } -fi - - -# func_basename FILE -# ------------------ -# Set func_basename_result to FILE with everything up to and including -# the last / stripped. -if test yes = "$_G_HAVE_XSI_OPS"; then - # If this shell supports suffix pattern removal, then use it to avoid - # forking. Hide the definitions single quotes in case the shell chokes - # on unsupported syntax... - _b='func_basename_result=${1##*/}' - _d='case $1 in - */*) func_dirname_result=${1%/*}$2 ;; - * ) func_dirname_result=$3 ;; - esac' - -else - # ...otherwise fall back to using sed. - _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' - _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` - if test "X$func_dirname_result" = "X$1"; then - func_dirname_result=$3 - else - func_append func_dirname_result "$2" - fi' -fi - -eval 'func_basename () -{ - $debug_cmd - - '"$_b"' -}' - - -# func_dirname FILE APPEND NONDIR_REPLACEMENT -# ------------------------------------------- -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -eval 'func_dirname () -{ - $debug_cmd - - '"$_d"' -}' - - -# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT -# -------------------------------------------------------- -# Perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# For efficiency, we do not delegate to the functions above but instead -# duplicate the functionality here. -eval 'func_dirname_and_basename () -{ - $debug_cmd - - '"$_b"' - '"$_d"' -}' - - -# func_echo ARG... -# ---------------- -# Echo program name prefixed message. -func_echo () -{ - $debug_cmd - - _G_message=$* - - func_echo_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS - $ECHO "$progname: $_G_line" - done - IFS=$func_echo_IFS -} - - -# func_echo_all ARG... -# -------------------- -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - - -# func_echo_infix_1 INFIX ARG... -# ------------------------------ -# Echo program name, followed by INFIX on the first line, with any -# additional lines not showing INFIX. -func_echo_infix_1 () -{ - $debug_cmd - - $require_term_colors - - _G_infix=$1; shift - _G_indent=$_G_infix - _G_prefix="$progname: $_G_infix: " - _G_message=$* - - # Strip color escape sequences before counting printable length - for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" - do - test -n "$_G_tc" && { - _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` - _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` - } - done - _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes - - func_echo_infix_1_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_infix_1_IFS - $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 - _G_prefix=$_G_indent - done - IFS=$func_echo_infix_1_IFS -} - - -# func_error ARG... -# ----------------- -# Echo program name prefixed message to standard error. -func_error () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 -} - - -# func_fatal_error ARG... -# ----------------------- -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - $debug_cmd - - func_error "$*" - exit $EXIT_FAILURE -} - - -# func_grep EXPRESSION FILENAME -# ----------------------------- -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $debug_cmd - - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_len STRING -# --------------- -# Set func_len_result to the length of STRING. STRING may not -# start with a hyphen. - test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_len () - { - $debug_cmd - - func_len_result=${#1} - }' -else - func_len () - { - $debug_cmd - - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` - } -fi - - -# func_mkdir_p DIRECTORY-PATH -# --------------------------- -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - $debug_cmd - - _G_directory_path=$1 - _G_dir_list= - - if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then - - # Protect directory names starting with '-' - case $_G_directory_path in - -*) _G_directory_path=./$_G_directory_path ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$_G_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - _G_dir_list=$_G_directory_path:$_G_dir_list - - # If the last portion added has no slash in it, the list is done - case $_G_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` - done - _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` - - func_mkdir_p_IFS=$IFS; IFS=: - for _G_dir in $_G_dir_list; do - IFS=$func_mkdir_p_IFS - # mkdir can fail with a 'File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$_G_dir" 2>/dev/null || : - done - IFS=$func_mkdir_p_IFS - - # Bail out if we (or some other process) failed to create a directory. - test -d "$_G_directory_path" || \ - func_fatal_error "Failed to create '$1'" - fi -} - - -# func_mktempdir [BASENAME] -# ------------------------- -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, BASENAME is the basename for that directory. -func_mktempdir () -{ - $debug_cmd - - _G_template=${TMPDIR-/tmp}/${1-$progname} - - if test : = "$opt_dry_run"; then - # Return a directory name, but don't create it in dry-run mode - _G_tmpdir=$_G_template-$$ - else - - # If mktemp works, use that first and foremost - _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` - - if test ! -d "$_G_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - _G_tmpdir=$_G_template-${RANDOM-0}$$ - - func_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$_G_tmpdir" - umask $func_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$_G_tmpdir" || \ - func_fatal_error "cannot create temporary directory '$_G_tmpdir'" - fi - - $ECHO "$_G_tmpdir" -} - - -# func_normal_abspath PATH -# ------------------------ -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -func_normal_abspath () -{ - $debug_cmd - - # These SED scripts presuppose an absolute path with a trailing slash. - _G_pathcar='s|^/\([^/]*\).*$|\1|' - _G_pathcdr='s|^/[^/]*||' - _G_removedotparts=':dotsl - s|/\./|/|g - t dotsl - s|/\.$|/|' - _G_collapseslashes='s|/\{1,\}|/|g' - _G_finalslash='s|/*$|/|' - - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` - while :; do - # Processed it all yet? - if test / = "$func_normal_abspath_tpath"; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result"; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - - -# func_notquiet ARG... -# -------------------- -# Echo program name prefixed message only when not in quiet mode. -func_notquiet () -{ - $debug_cmd - - $opt_quiet || func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} - - -# func_relative_path SRCDIR DSTDIR -# -------------------------------- -# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. -func_relative_path () -{ - $debug_cmd - - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=$func_dirname_result - if test -z "$func_relative_path_tlibdir"; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test -n "$func_stripname_result"; then - func_append func_relative_path_result "/$func_stripname_result" - fi - - # Normalisation. If bindir is libdir, return '.' else relative path. - if test -n "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - fi - - test -n "$func_relative_path_result" || func_relative_path_result=. - - : -} - - -# func_quote_for_eval ARG... -# -------------------------- -# Aesthetically quote ARGs to be evaled later. -# This function returns two values: -# i) func_quote_for_eval_result -# double-quoted, suitable for a subsequent eval -# ii) func_quote_for_eval_unquoted_result -# has all characters that are still active within double -# quotes backslashified. -func_quote_for_eval () -{ - $debug_cmd - - func_quote_for_eval_unquoted_result= - func_quote_for_eval_result= - while test 0 -lt $#; do - case $1 in - *[\\\`\"\$]*) - _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; - *) - _G_unquoted_arg=$1 ;; - esac - if test -n "$func_quote_for_eval_unquoted_result"; then - func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" - else - func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" - fi - - case $_G_unquoted_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and variable expansion - # for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_quoted_arg=\"$_G_unquoted_arg\" - ;; - *) - _G_quoted_arg=$_G_unquoted_arg - ;; - esac - - if test -n "$func_quote_for_eval_result"; then - func_append func_quote_for_eval_result " $_G_quoted_arg" - else - func_append func_quote_for_eval_result "$_G_quoted_arg" - fi - shift - done -} - - -# func_quote_for_expand ARG -# ------------------------- -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - $debug_cmd - - case $1 in - *[\\\`\"]*) - _G_arg=`$ECHO "$1" | $SED \ - -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; - *) - _G_arg=$1 ;; - esac - - case $_G_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_arg=\"$_G_arg\" - ;; - esac - - func_quote_for_expand_result=$_G_arg -} - - -# func_stripname PREFIX SUFFIX NAME -# --------------------------------- -# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_stripname () - { - $debug_cmd - - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary variable first. - func_stripname_result=$3 - func_stripname_result=${func_stripname_result#"$1"} - func_stripname_result=${func_stripname_result%"$2"} - }' -else - func_stripname () - { - $debug_cmd - - case $2 in - .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; - *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; - esac - } -fi - - -# func_show_eval CMD [FAIL_EXP] -# ----------------------------- -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - func_quote_for_expand "$_G_cmd" - eval "func_notquiet $func_quote_for_expand_result" - - $opt_dry_run || { - eval "$_G_cmd" - _G_status=$? - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_show_eval_locale CMD [FAIL_EXP] -# ------------------------------------ -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - $opt_quiet || { - func_quote_for_expand "$_G_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - $opt_dry_run || { - eval "$_G_user_locale - $_G_cmd" - _G_status=$? - eval "$_G_safe_locale" - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_tr_sh -# ---------- -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - $debug_cmd - - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_verbose ARG... -# ------------------- -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $debug_cmd - - $opt_verbose && func_echo "$*" - - : -} - - -# func_warn_and_continue ARG... -# ----------------------------- -# Echo program name prefixed warning message to standard error. -func_warn_and_continue () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 -} - - -# func_warning CATEGORY ARG... -# ---------------------------- -# Echo program name prefixed warning message to standard error. Warning -# messages can be filtered according to CATEGORY, where this function -# elides messages where CATEGORY is not listed in the global variable -# 'opt_warning_types'. -func_warning () -{ - $debug_cmd - - # CATEGORY must be in the warning_categories list! - case " $warning_categories " in - *" $1 "*) ;; - *) func_internal_error "invalid warning category '$1'" ;; - esac - - _G_category=$1 - shift - - case " $opt_warning_types " in - *" $_G_category "*) $warning_func ${1+"$@"} ;; - esac -} - - -# func_sort_ver VER1 VER2 -# ----------------------- -# 'sort -V' is not generally available. -# Note this deviates from the version comparison in automake -# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a -# but this should suffice as we won't be specifying old -# version formats or redundant trailing .0 in bootstrap.conf. -# If we did want full compatibility then we should probably -# use m4_version_compare from autoconf. -func_sort_ver () -{ - $debug_cmd - - printf '%s\n%s\n' "$1" "$2" \ - | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n -} - -# func_lt_ver PREV CURR -# --------------------- -# Return true if PREV and CURR are in the correct order according to -# func_sort_ver, otherwise false. Use it like this: -# -# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." -func_lt_ver () -{ - $debug_cmd - - test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: -#! /bin/sh - -# Set a version string for this script. -scriptversion=2015-10-07.11; # UTC - -# A portable, pluggable option parser for Bourne shell. -# Written by Gary V. Vaughan, 2010 - -# Copyright (C) 2010-2015 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# This file is a library for parsing options in your shell scripts along -# with assorted other useful supporting features that you can make use -# of too. -# -# For the simplest scripts you might need only: -# -# #!/bin/sh -# . relative/path/to/funclib.sh -# . relative/path/to/options-parser -# scriptversion=1.0 -# func_options ${1+"$@"} -# eval set dummy "$func_options_result"; shift -# ...rest of your script... -# -# In order for the '--version' option to work, you will need to have a -# suitably formatted comment like the one at the top of this file -# starting with '# Written by ' and ending with '# warranty; '. -# -# For '-h' and '--help' to work, you will also need a one line -# description of your script's purpose in a comment directly above the -# '# Written by ' line, like the one at the top of this file. -# -# The default options also support '--debug', which will turn on shell -# execution tracing (see the comment above debug_cmd below for another -# use), and '--verbose' and the func_verbose function to allow your script -# to display verbose messages only when your user has specified -# '--verbose'. -# -# After sourcing this file, you can plug processing for additional -# options by amending the variables from the 'Configuration' section -# below, and following the instructions in the 'Option parsing' -# section further down. - -## -------------- ## -## Configuration. ## -## -------------- ## - -# You should override these variables in your script after sourcing this -# file so that they reflect the customisations you have added to the -# option parser. - -# The usage line for option parsing errors and the start of '-h' and -# '--help' output messages. You can embed shell variables for delayed -# expansion at the time the message is displayed, but you will need to -# quote other shell meta-characters carefully to prevent them being -# expanded when the contents are evaled. -usage='$progpath [OPTION]...' - -# Short help message in response to '-h' and '--help'. Add to this or -# override it after sourcing this library to reflect the full set of -# options your script accepts. -usage_message="\ - --debug enable verbose shell tracing - -W, --warnings=CATEGORY - report the warnings falling in CATEGORY [all] - -v, --verbose verbosely report processing - --version print version information and exit - -h, --help print short or long help message and exit -" - -# Additional text appended to 'usage_message' in response to '--help'. -long_help_message=" -Warning categories include: - 'all' show all warnings - 'none' turn off all the warnings - 'error' warnings are treated as fatal errors" - -# Help message printed before fatal option parsing errors. -fatal_help="Try '\$progname --help' for more information." - - - -## ------------------------- ## -## Hook function management. ## -## ------------------------- ## - -# This section contains functions for adding, removing, and running hooks -# to the main code. A hook is just a named list of of function, that can -# be run in order later on. - -# func_hookable FUNC_NAME -# ----------------------- -# Declare that FUNC_NAME will run hooks added with -# 'func_add_hook FUNC_NAME ...'. -func_hookable () -{ - $debug_cmd - - func_append hookable_fns " $1" -} - - -# func_add_hook FUNC_NAME HOOK_FUNC -# --------------------------------- -# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must -# first have been declared "hookable" by a call to 'func_hookable'. -func_add_hook () -{ - $debug_cmd - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not accept hook functions." ;; - esac - - eval func_append ${1}_hooks '" $2"' -} - - -# func_remove_hook FUNC_NAME HOOK_FUNC -# ------------------------------------ -# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. -func_remove_hook () -{ - $debug_cmd - - eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' -} - - -# func_run_hooks FUNC_NAME [ARG]... -# --------------------------------- -# Run all hook functions registered to FUNC_NAME. -# It is assumed that the list of hook functions contains nothing more -# than a whitespace-delimited list of legal shell function names, and -# no effort is wasted trying to catch shell meta-characters or preserve -# whitespace. -func_run_hooks () -{ - $debug_cmd - - _G_rc_run_hooks=false - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not support hook funcions.n" ;; - esac - - eval _G_hook_fns=\$$1_hooks; shift - - for _G_hook in $_G_hook_fns; do - if eval $_G_hook '"$@"'; then - # store returned options list back into positional - # parameters for next 'cmd' execution. - eval _G_hook_result=\$${_G_hook}_result - eval set dummy "$_G_hook_result"; shift - _G_rc_run_hooks=: - fi - done - - $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result -} - - - -## --------------- ## -## Option parsing. ## -## --------------- ## - -# In order to add your own option parsing hooks, you must accept the -# full positional parameter list in your hook function, you may remove/edit -# any options that you action, and then pass back the remaining unprocessed -# options in '_result', escaped suitably for -# 'eval'. In this case you also must return $EXIT_SUCCESS to let the -# hook's caller know that it should pay attention to -# '_result'. Returning $EXIT_FAILURE signalizes that -# arguments are left untouched by the hook and therefore caller will ignore the -# result variable. -# -# Like this: -# -# my_options_prep () -# { -# $debug_cmd -# -# # Extend the existing usage message. -# usage_message=$usage_message' -# -s, --silent don'\''t print informational messages -# ' -# # No change in '$@' (ignored completely by this hook). There is -# # no need to do the equivalent (but slower) action: -# # func_quote_for_eval ${1+"$@"} -# # my_options_prep_result=$func_quote_for_eval_result -# false -# } -# func_add_hook func_options_prep my_options_prep -# -# -# my_silent_option () -# { -# $debug_cmd -# -# args_changed=false -# -# # Note that for efficiency, we parse as many options as we can -# # recognise in a loop before passing the remainder back to the -# # caller on the first unrecognised argument we encounter. -# while test $# -gt 0; do -# opt=$1; shift -# case $opt in -# --silent|-s) opt_silent=: -# args_changed=: -# ;; -# # Separate non-argument short options: -# -s*) func_split_short_opt "$_G_opt" -# set dummy "$func_split_short_opt_name" \ -# "-$func_split_short_opt_arg" ${1+"$@"} -# shift -# args_changed=: -# ;; -# *) # Make sure the first unrecognised option "$_G_opt" -# # is added back to "$@", we could need that later -# # if $args_changed is true. -# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; -# esac -# done -# -# if $args_changed; then -# func_quote_for_eval ${1+"$@"} -# my_silent_option_result=$func_quote_for_eval_result -# fi -# -# $args_changed -# } -# func_add_hook func_parse_options my_silent_option -# -# -# my_option_validation () -# { -# $debug_cmd -# -# $opt_silent && $opt_verbose && func_fatal_help "\ -# '--silent' and '--verbose' options are mutually exclusive." -# -# false -# } -# func_add_hook func_validate_options my_option_validation -# -# You'll also need to manually amend $usage_message to reflect the extra -# options you parse. It's preferable to append if you can, so that -# multiple option parsing hooks can be added safely. - - -# func_options_finish [ARG]... -# ---------------------------- -# Finishing the option parse loop (call 'func_options' hooks ATM). -func_options_finish () -{ - $debug_cmd - - _G_func_options_finish_exit=false - if func_run_hooks func_options ${1+"$@"}; then - func_options_finish_result=$func_run_hooks_result - _G_func_options_finish_exit=: - fi - - $_G_func_options_finish_exit -} - - -# func_options [ARG]... -# --------------------- -# All the functions called inside func_options are hookable. See the -# individual implementations for details. -func_hookable func_options -func_options () -{ - $debug_cmd - - _G_rc_options=false - - for my_func in options_prep parse_options validate_options options_finish - do - if eval func_$my_func '${1+"$@"}'; then - eval _G_res_var='$'"func_${my_func}_result" - eval set dummy "$_G_res_var" ; shift - _G_rc_options=: - fi - done - - # Save modified positional parameters for caller. As a top-level - # options-parser function we always need to set the 'func_options_result' - # variable (regardless the $_G_rc_options value). - if $_G_rc_options; then - func_options_result=$_G_res_var - else - func_quote_for_eval ${1+"$@"} - func_options_result=$func_quote_for_eval_result - fi - - $_G_rc_options -} - - -# func_options_prep [ARG]... -# -------------------------- -# All initialisations required before starting the option parse loop. -# Note that when calling hook functions, we pass through the list of -# positional parameters. If a hook function modifies that list, and -# needs to propagate that back to rest of this script, then the complete -# modified list must be put in 'func_run_hooks_result' before -# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). -func_hookable func_options_prep -func_options_prep () -{ - $debug_cmd - - # Option defaults: - opt_verbose=false - opt_warning_types= - - _G_rc_options_prep=false - if func_run_hooks func_options_prep ${1+"$@"}; then - _G_rc_options_prep=: - # save modified positional parameters for caller - func_options_prep_result=$func_run_hooks_result - fi - - $_G_rc_options_prep -} - - -# func_parse_options [ARG]... -# --------------------------- -# The main option parsing loop. -func_hookable func_parse_options -func_parse_options () -{ - $debug_cmd - - func_parse_options_result= - - _G_rc_parse_options=false - # this just eases exit handling - while test $# -gt 0; do - # Defer to hook functions for initial option parsing, so they - # get priority in the event of reusing an option name. - if func_run_hooks func_parse_options ${1+"$@"}; then - eval set dummy "$func_run_hooks_result"; shift - _G_rc_parse_options=: - fi - - # Break out of the loop if we already parsed every option. - test $# -gt 0 || break - - _G_match_parse_options=: - _G_opt=$1 - shift - case $_G_opt in - --debug|-x) debug_cmd='set -x' - func_echo "enabling shell trace mode" - $debug_cmd - ;; - - --no-warnings|--no-warning|--no-warn) - set dummy --warnings none ${1+"$@"} - shift - ;; - - --warnings|--warning|-W) - if test $# = 0 && func_missing_arg $_G_opt; then - _G_rc_parse_options=: - break - fi - case " $warning_categories $1" in - *" $1 "*) - # trailing space prevents matching last $1 above - func_append_uniq opt_warning_types " $1" - ;; - *all) - opt_warning_types=$warning_categories - ;; - *none) - opt_warning_types=none - warning_func=: - ;; - *error) - opt_warning_types=$warning_categories - warning_func=func_fatal_error - ;; - *) - func_fatal_error \ - "unsupported warning category: '$1'" - ;; - esac - shift - ;; - - --verbose|-v) opt_verbose=: ;; - --version) func_version ;; - -\?|-h) func_usage ;; - --help) func_help ;; - - # Separate optargs to long options (plugins may need this): - --*=*) func_split_equals "$_G_opt" - set dummy "$func_split_equals_lhs" \ - "$func_split_equals_rhs" ${1+"$@"} - shift - ;; - - # Separate optargs to short options: - -W*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-v*|-x*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) _G_rc_parse_options=: ; break ;; - -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; - *) set dummy "$_G_opt" ${1+"$@"}; shift - _G_match_parse_options=false - break - ;; - esac - - $_G_match_parse_options && _G_rc_parse_options=: - done - - - if $_G_rc_parse_options; then - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - func_parse_options_result=$func_quote_for_eval_result - fi - - $_G_rc_parse_options -} - - -# func_validate_options [ARG]... -# ------------------------------ -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -func_hookable func_validate_options -func_validate_options () -{ - $debug_cmd - - _G_rc_validate_options=false - - # Display all warnings if -W was not given. - test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" - - if func_run_hooks func_validate_options ${1+"$@"}; then - # save modified positional parameters for caller - func_validate_options_result=$func_run_hooks_result - _G_rc_validate_options=: - fi - - # Bail if the options were screwed! - $exit_cmd $EXIT_FAILURE - - $_G_rc_validate_options -} - - - -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of the -# hookable option parser framework in ascii-betical order. - - -# func_fatal_help ARG... -# ---------------------- -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - $debug_cmd - - eval \$ECHO \""Usage: $usage"\" - eval \$ECHO \""$fatal_help"\" - func_error ${1+"$@"} - exit $EXIT_FAILURE -} - - -# func_help -# --------- -# Echo long help message to standard output and exit. -func_help () -{ - $debug_cmd - - func_usage_message - $ECHO "$long_help_message" - exit 0 -} - - -# func_missing_arg ARGNAME -# ------------------------ -# Echo program name prefixed message to standard error and set global -# exit_cmd. -func_missing_arg () -{ - $debug_cmd - - func_error "Missing argument for '$1'." - exit_cmd=exit -} - - -# func_split_equals STRING -# ------------------------ -# Set func_split_equals_lhs and func_split_equals_rhs shell variables after -# splitting STRING at the '=' sign. -test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=${1%%=*} - func_split_equals_rhs=${1#*=} - test "x$func_split_equals_lhs" = "x$1" \ - && func_split_equals_rhs= - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` - func_split_equals_rhs= - test "x$func_split_equals_lhs" = "x$1" \ - || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` - } -fi #func_split_equals - - -# func_split_short_opt SHORTOPT -# ----------------------------- -# Set func_split_short_opt_name and func_split_short_opt_arg shell -# variables after splitting SHORTOPT after the 2nd character. -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"} - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` - func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` - } -fi #func_split_short_opt - - -# func_usage -# ---------- -# Echo short help message to standard output and exit. -func_usage () -{ - $debug_cmd - - func_usage_message - $ECHO "Run '$progname --help |${PAGER-more}' for full usage" - exit 0 -} - - -# func_usage_message -# ------------------ -# Echo short help message to standard output. -func_usage_message () -{ - $debug_cmd - - eval \$ECHO \""Usage: $usage"\" - echo - $SED -n 's|^# || - /^Written by/{ - x;p;x - } - h - /^Written by/q' < "$progpath" - echo - eval \$ECHO \""$usage_message"\" -} - - -# func_version -# ------------ -# Echo version message to standard output and exit. -func_version () -{ - $debug_cmd - - printf '%s\n' "$progname $scriptversion" - $SED -n ' - /(C)/!b go - :more - /\./!{ - N - s|\n# | | - b more - } - :go - /^# Written by /,/# warranty; / { - s|^# || - s|^# *$|| - s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| - p - } - /^# Written by / { - s|^# || - p - } - /^warranty; /q' < "$progpath" - - exit $? -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: - -# Set a version string. -scriptversion='(GNU libtool) 2.4.6' - - -# func_echo ARG... -# ---------------- -# Libtool also displays the current mode in messages, so override -# funclib.sh func_echo with this custom definition. -func_echo () -{ - $debug_cmd - - _G_message=$* - - func_echo_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS - $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" - done - IFS=$func_echo_IFS -} - - -# func_warning ARG... -# ------------------- -# Libtool warnings are not categorized, so override funclib.sh -# func_warning with this simpler definition. -func_warning () -{ - $debug_cmd - - $warning_func ${1+"$@"} -} - - -## ---------------- ## -## Options parsing. ## -## ---------------- ## - -# Hook in the functions to make sure our own options are parsed during -# the option parsing loop. - -usage='$progpath [OPTION]... [MODE-ARG]...' - -# Short help message in response to '-h'. -usage_message="Options: - --config show all configuration variables - --debug enable verbose shell tracing - -n, --dry-run display commands without modifying any files - --features display basic configuration information and exit - --mode=MODE use operation mode MODE - --no-warnings equivalent to '-Wnone' - --preserve-dup-deps don't remove duplicate dependency libraries - --quiet, --silent don't print informational messages - --tag=TAG use configuration variables from tag TAG - -v, --verbose print more informational messages than default - --version print version information - -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] - -h, --help, --help-all print short, long, or detailed help message -" - -# Additional text appended to 'usage_message' in response to '--help'. -func_help () -{ - $debug_cmd - - func_usage_message - $ECHO "$long_help_message - -MODE must be one of the following: - - clean remove files from the build directory - compile compile a source file into a libtool object - execute automatically set library path, then run a program - finish complete the installation of libtool libraries - install install libraries or executables - link create a library or an executable - uninstall remove libraries from an installed directory - -MODE-ARGS vary depending on the MODE. When passed as first option, -'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. -Try '$progname --help --mode=MODE' for a more detailed description of MODE. - -When reporting a bug, please describe a test case to reproduce it and -include the following information: - - host-triplet: $host - shell: $SHELL - compiler: $LTCC - compiler flags: $LTCFLAGS - linker: $LD (gnu? $with_gnu_ld) - version: $progname $scriptversion Debian-2.4.6-9 - automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` - autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` - -Report bugs to . -GNU libtool home page: . -General help using GNU software: ." - exit 0 -} - - -# func_lo2o OBJECT-NAME -# --------------------- -# Transform OBJECT-NAME from a '.lo' suffix to the platform specific -# object suffix. - -lo2o=s/\\.lo\$/.$objext/ -o2lo=s/\\.$objext\$/.lo/ - -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_lo2o () - { - case $1 in - *.lo) func_lo2o_result=${1%.lo}.$objext ;; - * ) func_lo2o_result=$1 ;; - esac - }' - - # func_xform LIBOBJ-OR-SOURCE - # --------------------------- - # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) - # suffix to a '.lo' libtool-object suffix. - eval 'func_xform () - { - func_xform_result=${1%.*}.lo - }' -else - # ...otherwise fall back to using sed. - func_lo2o () - { - func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` - } - - func_xform () - { - func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` - } -fi - - -# func_fatal_configuration ARG... -# ------------------------------- -# Echo program name prefixed message to standard error, followed by -# a configuration failure hint, and exit. -func_fatal_configuration () -{ - func__fatal_error ${1+"$@"} \ - "See the $PACKAGE documentation for more information." \ - "Fatal configuration error." -} - - -# func_config -# ----------- -# Display the configuration for all the tags in this script. -func_config () -{ - re_begincf='^# ### BEGIN LIBTOOL' - re_endcf='^# ### END LIBTOOL' - - # Default configuration. - $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" - - # Now print the configurations for the tags. - for tagname in $taglist; do - $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" - done - - exit $? -} - - -# func_features -# ------------- -# Display the features supported by this script. -func_features () -{ - echo "host: $host" - if test yes = "$build_libtool_libs"; then - echo "enable shared libraries" - else - echo "disable shared libraries" - fi - if test yes = "$build_old_libs"; then - echo "enable static libraries" - else - echo "disable static libraries" - fi - - exit $? -} - - -# func_enable_tag TAGNAME -# ----------------------- -# Verify that TAGNAME is valid, and either flag an error and exit, or -# enable the TAGNAME tag. We also add TAGNAME to the global $taglist -# variable here. -func_enable_tag () -{ - # Global variable: - tagname=$1 - - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf=/$re_begincf/,/$re_endcf/p - - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac - - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; - *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" - - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac -} - - -# func_check_version_match -# ------------------------ -# Ensure that we are using m4 macros, and libtool script from the same -# release of libtool. -func_check_version_match () -{ - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from an older release. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - fi - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, -$progname: but the definition of this LT_INIT comes from revision $macro_revision. -$progname: You should recreate aclocal.m4 with macros from revision $package_revision -$progname: of $PACKAGE $VERSION and run autoconf again. -_LT_EOF - fi - - exit $EXIT_MISMATCH - fi -} - - -# libtool_options_prep [ARG]... -# ----------------------------- -# Preparation for options parsed by libtool. -libtool_options_prep () -{ - $debug_mode - - # Option defaults: - opt_config=false - opt_dlopen= - opt_dry_run=false - opt_help=false - opt_mode= - opt_preserve_dup_deps=false - opt_quiet=false - - nonopt= - preserve_args= - - _G_rc_lt_options_prep=: - - # Shorthand for --mode=foo, only valid as the first argument - case $1 in - clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; - compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; - execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; - finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; - install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; - link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; - uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; - *) - _G_rc_lt_options_prep=false - ;; - esac - - if $_G_rc_lt_options_prep; then - # Pass back the list of options. - func_quote_for_eval ${1+"$@"} - libtool_options_prep_result=$func_quote_for_eval_result - fi - - $_G_rc_lt_options_prep -} -func_add_hook func_options_prep libtool_options_prep - - -# libtool_parse_options [ARG]... -# --------------------------------- -# Provide handling for libtool specific options. -libtool_parse_options () -{ - $debug_cmd - - _G_rc_lt_parse_options=false - - # Perform our own loop to consume as many options as possible in - # each iteration. - while test $# -gt 0; do - _G_match_lt_parse_options=: - _G_opt=$1 - shift - case $_G_opt in - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - - --config) func_config ;; - - --dlopen|-dlopen) - opt_dlopen="${opt_dlopen+$opt_dlopen -}$1" - shift - ;; - - --preserve-dup-deps) - opt_preserve_dup_deps=: ;; - - --features) func_features ;; - - --finish) set dummy --mode finish ${1+"$@"}; shift ;; - - --help) opt_help=: ;; - - --help-all) opt_help=': help-all' ;; - - --mode) test $# = 0 && func_missing_arg $_G_opt && break - opt_mode=$1 - case $1 in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $_G_opt" - exit_cmd=exit - break - ;; - esac - shift - ;; - - --no-silent|--no-quiet) - opt_quiet=false - func_append preserve_args " $_G_opt" - ;; - - --no-warnings|--no-warning|--no-warn) - opt_warning=false - func_append preserve_args " $_G_opt" - ;; - - --no-verbose) - opt_verbose=false - func_append preserve_args " $_G_opt" - ;; - - --silent|--quiet) - opt_quiet=: - opt_verbose=false - func_append preserve_args " $_G_opt" - ;; - - --tag) test $# = 0 && func_missing_arg $_G_opt && break - opt_tag=$1 - func_append preserve_args " $_G_opt $1" - func_enable_tag "$1" - shift - ;; - - --verbose|-v) opt_quiet=false - opt_verbose=: - func_append preserve_args " $_G_opt" - ;; - - # An option not handled by this hook function: - *) set dummy "$_G_opt" ${1+"$@"} ; shift - _G_match_lt_parse_options=false - break - ;; - esac - $_G_match_lt_parse_options && _G_rc_lt_parse_options=: - done - - if $_G_rc_lt_parse_options; then - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - libtool_parse_options_result=$func_quote_for_eval_result - fi - - $_G_rc_lt_parse_options -} -func_add_hook func_parse_options libtool_parse_options - - - -# libtool_validate_options [ARG]... -# --------------------------------- -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -libtool_validate_options () -{ - # save first non-option argument - if test 0 -lt $#; then - nonopt=$1 - shift - fi - - # preserve --debug - test : = "$debug_cmd" || func_append preserve_args " --debug" - - case $host in - # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 - # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 - *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac - - $opt_help || { - # Sanity checks first: - func_check_version_match - - test yes != "$build_libtool_libs" \ - && test yes != "$build_old_libs" \ - && func_fatal_configuration "not configured to build any kind of library" - - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test execute != "$opt_mode"; then - func_error "unrecognized option '-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help=$help - help="Try '$progname --help --mode=$opt_mode' for more information." - } - - # Pass back the unparsed argument list - func_quote_for_eval ${1+"$@"} - libtool_validate_options_result=$func_quote_for_eval_result -} -func_add_hook func_validate_options libtool_validate_options - - -# Process options as early as possible so that --help and --version -# can return quickly. -func_options ${1+"$@"} -eval set dummy "$func_options_result"; shift - - - -## ----------- ## -## Main. ## -## ----------- ## - -magic='%%%MAGIC variable%%%' -magic_exe='%%%MAGIC EXE variable%%%' - -# Global variables. -extracted_archives= -extracted_serial=0 - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# func_generated_by_libtool -# True iff stdin has been generated by Libtool. This function is only -# a basic sanity check; it will hardly flush out determined imposters. -func_generated_by_libtool_p () -{ - $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 -} - -# func_lalib_p file -# True iff FILE is a libtool '.la' library or '.lo' object file. -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_lalib_p () -{ - test -f "$1" && - $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p -} - -# func_lalib_unsafe_p file -# True iff FILE is a libtool '.la' library or '.lo' object file. -# This function implements the same check as func_lalib_p without -# resorting to external programs. To this end, it redirects stdin and -# closes it afterwards, without saving the original file descriptor. -# As a safety measure, use it only where a negative result would be -# fatal anyway. Works if 'file' does not exist. -func_lalib_unsafe_p () -{ - lalib_p=no - if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then - for lalib_p_l in 1 2 3 4 - do - read lalib_p_line - case $lalib_p_line in - \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; - esac - done - exec 0<&5 5<&- - fi - test yes = "$lalib_p" -} - -# func_ltwrapper_script_p file -# True iff FILE is a libtool wrapper script -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_script_p () -{ - test -f "$1" && - $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p -} - -# func_ltwrapper_executable_p file -# True iff FILE is a libtool wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_executable_p () -{ - func_ltwrapper_exec_suffix= - case $1 in - *.exe) ;; - *) func_ltwrapper_exec_suffix=.exe ;; - esac - $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 -} - -# func_ltwrapper_scriptname file -# Assumes file is an ltwrapper_executable -# uses $file to determine the appropriate filename for a -# temporary ltwrapper_script. -func_ltwrapper_scriptname () -{ - func_dirname_and_basename "$1" "" "." - func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper -} - -# func_ltwrapper_p file -# True iff FILE is a libtool wrapper script or wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_p () -{ - func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" -} - - -# func_execute_cmds commands fail_cmd -# Execute tilde-delimited COMMANDS. -# If FAIL_CMD is given, eval that upon failure. -# FAIL_CMD may read-access the current command in variable CMD! -func_execute_cmds () -{ - $debug_cmd - - save_ifs=$IFS; IFS='~' - for cmd in $1; do - IFS=$sp$nl - eval cmd=\"$cmd\" - IFS=$save_ifs - func_show_eval "$cmd" "${2-:}" - done - IFS=$save_ifs -} - - -# func_source file -# Source FILE, adding directory component if necessary. -# Note that it is not necessary on cygwin/mingw to append a dot to -# FILE even if both FILE and FILE.exe exist: automatic-append-.exe -# behavior happens only for exec(3), not for open(2)! Also, sourcing -# 'FILE.' does not work on cygwin managed mounts. -func_source () -{ - $debug_cmd - - case $1 in - */* | *\\*) . "$1" ;; - *) . "./$1" ;; - esac -} - - -# func_resolve_sysroot PATH -# Replace a leading = in PATH with a sysroot. Store the result into -# func_resolve_sysroot_result -func_resolve_sysroot () -{ - func_resolve_sysroot_result=$1 - case $func_resolve_sysroot_result in - =*) - func_stripname '=' '' "$func_resolve_sysroot_result" - func_resolve_sysroot_result=$lt_sysroot$func_stripname_result - ;; - esac -} - -# func_replace_sysroot PATH -# If PATH begins with the sysroot, replace it with = and -# store the result into func_replace_sysroot_result. -func_replace_sysroot () -{ - case $lt_sysroot:$1 in - ?*:"$lt_sysroot"*) - func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result='='$func_stripname_result - ;; - *) - # Including no sysroot. - func_replace_sysroot_result=$1 - ;; - esac -} - -# func_infer_tag arg -# Infer tagged configuration to use if any are available and -# if one wasn't chosen via the "--tag" command line option. -# Only attempt this if the compiler in the base compile -# command doesn't match the default compiler. -# arg is usually of the form 'gcc ...' -func_infer_tag () -{ - $debug_cmd - - if test -n "$available_tags" && test -z "$tagname"; then - CC_quoted= - for arg in $CC; do - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case $@ in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then - # Evaluate the configuration. - eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" - CC_quoted= - for arg in $CC; do - # Double-quote args containing other shell metacharacters. - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case "$@ " in - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with '--tag'" -# else -# func_verbose "using $tagname tagged configuration" - fi - ;; - esac - fi -} - - - -# func_write_libtool_object output_name pic_name nonpic_name -# Create a libtool object file (analogous to a ".la" file), -# but don't create it if we're doing a dry run. -func_write_libtool_object () -{ - write_libobj=$1 - if test yes = "$build_libtool_libs"; then - write_lobj=\'$2\' - else - write_lobj=none - fi - - if test yes = "$build_old_libs"; then - write_oldobj=\'$3\' - else - write_oldobj=none - fi - - $opt_dry_run || { - cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then - func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$sed_naive_backslashify"` - else - func_convert_core_file_wine_to_w32_result= - fi - fi -} -# end: func_convert_core_file_wine_to_w32 - - -# func_convert_core_path_wine_to_w32 ARG -# Helper function used by path conversion functions when $build is *nix, and -# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly -# configured wine environment available, with the winepath program in $build's -# $PATH. Assumes ARG has no leading or trailing path separator characters. -# -# ARG is path to be converted from $build format to win32. -# Result is available in $func_convert_core_path_wine_to_w32_result. -# Unconvertible file (directory) names in ARG are skipped; if no directory names -# are convertible, then the result may be empty. -func_convert_core_path_wine_to_w32 () -{ - $debug_cmd - - # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result= - if test -n "$1"; then - oldIFS=$IFS - IFS=: - for func_convert_core_path_wine_to_w32_f in $1; do - IFS=$oldIFS - func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result"; then - if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result - else - func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" - fi - fi - done - IFS=$oldIFS - fi -} -# end: func_convert_core_path_wine_to_w32 - - -# func_cygpath ARGS... -# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when -# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) -# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or -# (2), returns the Cygwin file name or path in func_cygpath_result (input -# file name or path is assumed to be in w32 format, as previously converted -# from $build's *nix or MSYS format). In case (3), returns the w32 file name -# or path in func_cygpath_result (input file name or path is assumed to be in -# Cygwin format). Returns an empty string on error. -# -# ARGS are passed to cygpath, with the last one being the file name or path to -# be converted. -# -# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH -# environment variable; do not put it in $PATH. -func_cygpath () -{ - $debug_cmd - - if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then - func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` - if test "$?" -ne 0; then - # on failure, ensure result is empty - func_cygpath_result= - fi - else - func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" - fi -} -#end: func_cygpath - - -# func_convert_core_msys_to_w32 ARG -# Convert file name or path ARG from MSYS format to w32 format. Return -# result in func_convert_core_msys_to_w32_result. -func_convert_core_msys_to_w32 () -{ - $debug_cmd - - # awkward: cmd appends spaces to result - func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` -} -#end: func_convert_core_msys_to_w32 - - -# func_convert_file_check ARG1 ARG2 -# Verify that ARG1 (a file name in $build format) was converted to $host -# format in ARG2. Otherwise, emit an error message, but continue (resetting -# func_to_host_file_result to ARG1). -func_convert_file_check () -{ - $debug_cmd - - if test -z "$2" && test -n "$1"; then - func_error "Could not determine host file name corresponding to" - func_error " '$1'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback: - func_to_host_file_result=$1 - fi -} -# end func_convert_file_check - - -# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH -# Verify that FROM_PATH (a path in $build format) was converted to $host -# format in TO_PATH. Otherwise, emit an error message, but continue, resetting -# func_to_host_file_result to a simplistic fallback value (see below). -func_convert_path_check () -{ - $debug_cmd - - if test -z "$4" && test -n "$3"; then - func_error "Could not determine the host path corresponding to" - func_error " '$3'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback. This is a deliberately simplistic "conversion" and - # should not be "improved". See libtool.info. - if test "x$1" != "x$2"; then - lt_replace_pathsep_chars="s|$1|$2|g" - func_to_host_path_result=`echo "$3" | - $SED -e "$lt_replace_pathsep_chars"` - else - func_to_host_path_result=$3 - fi - fi -} -# end func_convert_path_check - - -# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG -# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT -# and appending REPL if ORIG matches BACKPAT. -func_convert_path_front_back_pathsep () -{ - $debug_cmd - - case $4 in - $1 ) func_to_host_path_result=$3$func_to_host_path_result - ;; - esac - case $4 in - $2 ) func_append func_to_host_path_result "$3" - ;; - esac -} -# end func_convert_path_front_back_pathsep - - -################################################## -# $build to $host FILE NAME CONVERSION FUNCTIONS # -################################################## -# invoked via '$to_host_file_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# Result will be available in $func_to_host_file_result. - - -# func_to_host_file ARG -# Converts the file name ARG from $build format to $host format. Return result -# in func_to_host_file_result. -func_to_host_file () -{ - $debug_cmd - - $to_host_file_cmd "$1" -} -# end func_to_host_file - - -# func_to_tool_file ARG LAZY -# converts the file name ARG from $build format to toolchain format. Return -# result in func_to_tool_file_result. If the conversion in use is listed -# in (the comma separated) LAZY, no conversion takes place. -func_to_tool_file () -{ - $debug_cmd - - case ,$2, in - *,"$to_tool_file_cmd",*) - func_to_tool_file_result=$1 - ;; - *) - $to_tool_file_cmd "$1" - func_to_tool_file_result=$func_to_host_file_result - ;; - esac -} -# end func_to_tool_file - - -# func_convert_file_noop ARG -# Copy ARG to func_to_host_file_result. -func_convert_file_noop () -{ - func_to_host_file_result=$1 -} -# end func_convert_file_noop - - -# func_convert_file_msys_to_w32 ARG -# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_file_result. -func_convert_file_msys_to_w32 () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_to_host_file_result=$func_convert_core_msys_to_w32_result - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_w32 - - -# func_convert_file_cygwin_to_w32 ARG -# Convert file name ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_file_cygwin_to_w32 () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - # because $build is cygwin, we call "the" cygpath in $PATH; no need to use - # LT_CYGPATH in this case. - func_to_host_file_result=`cygpath -m "$1"` - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_cygwin_to_w32 - - -# func_convert_file_nix_to_w32 ARG -# Convert file name ARG from *nix to w32 format. Requires a wine environment -# and a working winepath. Returns result in func_to_host_file_result. -func_convert_file_nix_to_w32 () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result=$func_convert_core_file_wine_to_w32_result - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_w32 - - -# func_convert_file_msys_to_cygwin ARG -# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_file_msys_to_cygwin () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result=$func_cygpath_result - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_cygwin - - -# func_convert_file_nix_to_cygwin ARG -# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed -# in a wine environment, working winepath, and LT_CYGPATH set. Returns result -# in func_to_host_file_result. -func_convert_file_nix_to_cygwin () -{ - $debug_cmd - - func_to_host_file_result=$1 - if test -n "$1"; then - # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. - func_convert_core_file_wine_to_w32 "$1" - func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result=$func_cygpath_result - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_cygwin - - -############################################# -# $build to $host PATH CONVERSION FUNCTIONS # -############################################# -# invoked via '$to_host_path_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# The result will be available in $func_to_host_path_result. -# -# Path separators are also converted from $build format to $host format. If -# ARG begins or ends with a path separator character, it is preserved (but -# converted to $host format) on output. -# -# All path conversion functions are named using the following convention: -# file name conversion function : func_convert_file_X_to_Y () -# path conversion function : func_convert_path_X_to_Y () -# where, for any given $build/$host combination the 'X_to_Y' value is the -# same. If conversion functions are added for new $build/$host combinations, -# the two new functions must follow this pattern, or func_init_to_host_path_cmd -# will break. - - -# func_init_to_host_path_cmd -# Ensures that function "pointer" variable $to_host_path_cmd is set to the -# appropriate value, based on the value of $to_host_file_cmd. -to_host_path_cmd= -func_init_to_host_path_cmd () -{ - $debug_cmd - - if test -z "$to_host_path_cmd"; then - func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd=func_convert_path_$func_stripname_result - fi -} - - -# func_to_host_path ARG -# Converts the path ARG from $build format to $host format. Return result -# in func_to_host_path_result. -func_to_host_path () -{ - $debug_cmd - - func_init_to_host_path_cmd - $to_host_path_cmd "$1" -} -# end func_to_host_path - - -# func_convert_path_noop ARG -# Copy ARG to func_to_host_path_result. -func_convert_path_noop () -{ - func_to_host_path_result=$1 -} -# end func_convert_path_noop - - -# func_convert_path_msys_to_w32 ARG -# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_path_result. -func_convert_path_msys_to_w32 () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # Remove leading and trailing path separator characters from ARG. MSYS - # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; - # and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result=$func_convert_core_msys_to_w32_result - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_msys_to_w32 - - -# func_convert_path_cygwin_to_w32 ARG -# Convert path ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_path_cygwin_to_w32 () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_cygwin_to_w32 - - -# func_convert_path_nix_to_w32 ARG -# Convert path ARG from *nix to w32 format. Requires a wine environment and -# a working winepath. Returns result in func_to_host_file_result. -func_convert_path_nix_to_w32 () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result=$func_convert_core_path_wine_to_w32_result - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_nix_to_w32 - - -# func_convert_path_msys_to_cygwin ARG -# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_path_msys_to_cygwin () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result=$func_cygpath_result - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_msys_to_cygwin - - -# func_convert_path_nix_to_cygwin ARG -# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a -# a wine environment, working winepath, and LT_CYGPATH set. Returns result in -# func_to_host_file_result. -func_convert_path_nix_to_cygwin () -{ - $debug_cmd - - func_to_host_path_result=$1 - if test -n "$1"; then - # Remove leading and trailing path separator characters from - # ARG. msys behavior is inconsistent here, cygpath turns them - # into '.;' and ';.', and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result=$func_cygpath_result - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_nix_to_cygwin - - -# func_dll_def_p FILE -# True iff FILE is a Windows DLL '.def' file. -# Keep in sync with _LT_DLL_DEF_P in libtool.m4 -func_dll_def_p () -{ - $debug_cmd - - func_dll_def_p_tmp=`$SED -n \ - -e 's/^[ ]*//' \ - -e '/^\(;.*\)*$/d' \ - -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ - -e q \ - "$1"` - test DEF = "$func_dll_def_p_tmp" -} - - -# func_mode_compile arg... -func_mode_compile () -{ - $debug_cmd - - # Get the compilation command and the source file. - base_compile= - srcfile=$nonopt # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - pie_flag= - - for arg - do - case $arg_mode in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg=$arg - arg_mode=normal - ;; - - target ) - libobj=$arg - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - test -n "$libobj" && \ - func_fatal_error "you cannot specify '-o' more than once" - arg_mode=target - continue - ;; - - -pie | -fpie | -fPIE) - func_append pie_flag " $arg" - continue - ;; - - -shared | -static | -prefer-pic | -prefer-non-pic) - func_append later " $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - lastarg= - save_ifs=$IFS; IFS=, - for arg in $args; do - IFS=$save_ifs - func_append_quoted lastarg "$arg" - done - IFS=$save_ifs - func_stripname ' ' '' "$lastarg" - lastarg=$func_stripname_result - - # Add the arguments to base_compile. - func_append base_compile " $lastarg" - continue - ;; - - *) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg=$srcfile - srcfile=$arg - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - func_append_quoted base_compile "$lastarg" - done # for arg - - case $arg_mode in - arg) - func_fatal_error "you must specify an argument for -Xcompile" - ;; - target) - func_fatal_error "you must specify a target with '-o'" - ;; - *) - # Get the name of the library object. - test -z "$libobj" && { - func_basename "$srcfile" - libobj=$func_basename_result - } - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - case $libobj in - *.[cCFSifmso] | \ - *.ada | *.adb | *.ads | *.asm | \ - *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ - *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) - func_xform "$libobj" - libobj=$func_xform_result - ;; - esac - - case $libobj in - *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; - *) - func_fatal_error "cannot determine name of library object from '$libobj'" - ;; - esac - - func_infer_tag $base_compile - - for arg in $later; do - case $arg in - -shared) - test yes = "$build_libtool_libs" \ - || func_fatal_configuration "cannot build a shared library" - build_old_libs=no - continue - ;; - - -static) - build_libtool_libs=no - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - func_quote_for_eval "$libobj" - test "X$libobj" != "X$func_quote_for_eval_result" \ - && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name '$libobj' may not contain shell special characters." - func_dirname_and_basename "$obj" "/" "" - objname=$func_basename_result - xdir=$func_dirname_result - lobj=$xdir$objdir/$objname - - test -z "$base_compile" && \ - func_fatal_help "you must specify a compilation command" - - # Delete any leftover library objects. - if test yes = "$build_old_libs"; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2* | cegcc*) - pic_mode=default - ;; - esac - if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test no = "$compiler_c_o"; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext - lockfile=$output_obj.lock - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test yes = "$need_locks"; then - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - elif test warn = "$need_locks"; then - if test -f "$lockfile"; then - $ECHO "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - func_append removelist " $output_obj" - $ECHO "$srcfile" > "$lockfile" - fi - - $opt_dry_run || $RM $removelist - func_append removelist " $lockfile" - trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 - - func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 - srcfile=$func_to_tool_file_result - func_quote_for_eval "$srcfile" - qsrcfile=$func_quote_for_eval_result - - # Only build a PIC object if we are building libtool libraries. - if test yes = "$build_libtool_libs"; then - # Without this assignment, base_compile gets emptied. - fbsd_hideous_sh_bug=$base_compile - - if test no != "$pic_mode"; then - command="$base_compile $qsrcfile $pic_flag" - else - # Don't build PIC code - command="$base_compile $qsrcfile" - fi - - func_mkdir_p "$xdir$objdir" - - if test -z "$output_obj"; then - # Place PIC objects in $objdir - func_append command " -o $lobj" - fi - - func_show_eval_locale "$command" \ - 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - - if test warn = "$need_locks" && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - func_show_eval '$MV "$output_obj" "$lobj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - - # Allow error messages only from the first compilation. - if test yes = "$suppress_opt"; then - suppress_output=' >/dev/null 2>&1' - fi - fi - - # Only build a position-dependent object if we build old libraries. - if test yes = "$build_old_libs"; then - if test yes != "$pic_mode"; then - # Don't build PIC code - command="$base_compile $qsrcfile$pie_flag" - else - command="$base_compile $qsrcfile $pic_flag" - fi - if test yes = "$compiler_c_o"; then - func_append command " -o $obj" - fi - - # Suppress compiler output if we already did a PIC compilation. - func_append command "$suppress_output" - func_show_eval_locale "$command" \ - '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - - if test warn = "$need_locks" && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - func_show_eval '$MV "$output_obj" "$obj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - fi - - $opt_dry_run || { - func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" - - # Unlock the critical section if it was locked - if test no != "$need_locks"; then - removelist=$lockfile - $RM "$lockfile" - fi - } - - exit $EXIT_SUCCESS -} - -$opt_help || { - test compile = "$opt_mode" && func_mode_compile ${1+"$@"} -} - -func_mode_help () -{ - # We need to display help for each of the modes. - case $opt_mode in - "") - # Generic help is extracted from the usage comments - # at the start of this file. - func_help - ;; - - clean) - $ECHO \ -"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - - compile) - $ECHO \ -"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -no-suppress do not suppress compiler output for multiple passes - -prefer-pic try to build PIC objects only - -prefer-non-pic try to build non-PIC objects only - -shared do not build a '.o' file suitable for static linking - -static only build a '.o' file suitable for static linking - -Wc,FLAG pass FLAG directly to the compiler - -COMPILE-COMMAND is a command to be used in creating a 'standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix '.c' with the -library object suffix, '.lo'." - ;; - - execute) - $ECHO \ -"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to '-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - - finish) - $ECHO \ -"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the '--dry-run' option if you just want to see what would be executed." - ;; - - install) - $ECHO \ -"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the 'install' or 'cp' program. - -The following components of INSTALL-COMMAND are treated specially: - - -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - - link) - $ECHO \ -"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -bindir BINDIR specify path to binaries directory (for systems where - libraries must be found in the PATH setting at runtime) - -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE use a list of object files found in FILE to specify objects - -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -shared only do dynamic linking of libtool libraries - -shrext SUFFIX override the standard shared library file extension - -static do not do any dynamic linking of uninstalled libtool libraries - -static-libtool-libs - do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -weak LIBNAME declare that the target provides the LIBNAME interface - -Wc,FLAG - -Xcompiler FLAG pass linker-specific FLAG directly to the compiler - -Wl,FLAG - -Xlinker FLAG pass linker-specific FLAG directly to the linker - -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) - -All other options (arguments beginning with '-') are ignored. - -Every other argument is treated as a filename. Files ending in '.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in '.la', then a libtool library is created, -only library objects ('.lo' files) may be specified, and '-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created -using 'ar' and 'ranlib', or on Windows using 'lib'. - -If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file -is created, otherwise an executable program is created." - ;; - - uninstall) - $ECHO \ -"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - - *) - func_fatal_help "invalid operation mode '$opt_mode'" - ;; - esac - - echo - $ECHO "Try '$progname --help' for more information about other modes." -} - -# Now that we've collected a possible --mode arg, show help if necessary -if $opt_help; then - if test : = "$opt_help"; then - func_mode_help - else - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - func_mode_help - done - } | $SED -n '1p; 2,$s/^Usage:/ or: /p' - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - echo - func_mode_help - done - } | - $SED '1d - /^When reporting/,/^Report/{ - H - d - } - $x - /information about other modes/d - /more detailed .*MODE/d - s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' - fi - exit $? -fi - - -# func_mode_execute arg... -func_mode_execute () -{ - $debug_cmd - - # The first argument is the command name. - cmd=$nonopt - test -z "$cmd" && \ - func_fatal_help "you must specify a COMMAND" - - # Handle -dlopen flags immediately. - for file in $opt_dlopen; do - test -f "$file" \ - || func_fatal_help "'$file' is not a file" - - dir= - case $file in - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "'$lib' is not a valid libtool archive" - - # Read the libtool library. - dlname= - library_names= - func_source "$file" - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && \ - func_warning "'$file' was not linked with '-export-dynamic'" - continue - fi - - func_dirname "$file" "" "." - dir=$func_dirname_result - - if test -f "$dir/$objdir/$dlname"; then - func_append dir "/$objdir" - else - if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" - fi - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - func_dirname "$file" "" "." - dir=$func_dirname_result - ;; - - *) - func_warning "'-dlopen' is ignored for non-libtool libraries and objects" - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir=$absdir - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic=$magic - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -* | *.la | *.lo ) ;; - *) - # Do a test to see if this is really a libtool program. - if func_ltwrapper_script_p "$file"; then - func_source "$file" - # Transform arg to wrapped name. - file=$progdir/$program - elif func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - func_source "$func_ltwrapper_scriptname_result" - # Transform arg to wrapped name. - file=$progdir/$program - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - func_append_quoted args "$file" - done - - if $opt_dry_run; then - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS - else - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES - do - eval "if test \"\${save_$lt_var+set}\" = set; then - $lt_var=\$save_$lt_var; export $lt_var - else - $lt_unset $lt_var - fi" - done - - # Now prepare to actually exec the command. - exec_cmd=\$cmd$args - fi -} - -test execute = "$opt_mode" && func_mode_execute ${1+"$@"} - - -# func_mode_finish arg... -func_mode_finish () -{ - $debug_cmd - - libs= - libdirs= - admincmds= - - for opt in "$nonopt" ${1+"$@"} - do - if test -d "$opt"; then - func_append libdirs " $opt" - - elif test -f "$opt"; then - if func_lalib_unsafe_p "$opt"; then - func_append libs " $opt" - else - func_warning "'$opt' is not a valid libtool archive" - fi - - else - func_fatal_error "invalid argument '$opt'" - fi - done - - if test -n "$libs"; then - if test -n "$lt_sysroot"; then - sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` - sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" - else - sysroot_cmd= - fi - - # Remove sysroot references - if $opt_dry_run; then - for lib in $libs; do - echo "removing references to $lt_sysroot and '=' prefixes from $lib" - done - else - tmpdir=`func_mktempdir` - for lib in $libs; do - $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ - > $tmpdir/tmp-la - mv -f $tmpdir/tmp-la $lib - done - ${RM}r "$tmpdir" - fi - fi - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - func_execute_cmds "$finish_cmds" 'admincmds="$admincmds -'"$cmd"'"' - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $opt_dry_run || eval "$cmds" || func_append admincmds " - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - $opt_quiet && exit $EXIT_SUCCESS - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - echo "----------------------------------------------------------------------" - echo "Libraries have been installed in:" - for libdir in $libdirs; do - $ECHO " $libdir" - done - echo - echo "If you ever happen to want to link against installed libraries" - echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the '-LLIBDIR'" - echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the '$shlibpath_var' environment variable" - echo " during execution" - fi - if test -n "$runpath_var"; then - echo " - add LIBDIR to the '$runpath_var' environment variable" - echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $ECHO " - use the '$flag' linker flag" - fi - if test -n "$admincmds"; then - $ECHO " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" - fi - echo - - echo "See any operating system documentation about shared libraries for" - case $host in - solaris2.[6789]|solaris2.1[0-9]) - echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" - echo "pages." - ;; - *) - echo "more information, such as the ld(1) and ld.so(8) manual pages." - ;; - esac - echo "----------------------------------------------------------------------" - fi - exit $EXIT_SUCCESS -} - -test finish = "$opt_mode" && func_mode_finish ${1+"$@"} - - -# func_mode_install arg... -func_mode_install () -{ - $debug_cmd - - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || - # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac - then - # Aesthetically quote it. - func_quote_for_eval "$nonopt" - install_prog="$func_quote_for_eval_result " - arg=$1 - shift - else - install_prog= - arg=$nonopt - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - func_quote_for_eval "$arg" - func_append install_prog "$func_quote_for_eval_result" - install_shared_prog=$install_prog - case " $install_prog " in - *[\\\ /]cp\ *) install_cp=: ;; - *) install_cp=false ;; - esac - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=false - stripme= - no_mode=: - for arg - do - arg2= - if test -n "$dest"; then - func_append files " $dest" - dest=$arg - continue - fi - - case $arg in - -d) isdir=: ;; - -f) - if $install_cp; then :; else - prev=$arg - fi - ;; - -g | -m | -o) - prev=$arg - ;; - -s) - stripme=" -s" - continue - ;; - -*) - ;; - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - if test X-m = "X$prev" && test -n "$install_override_mode"; then - arg2=$install_override_mode - no_mode=false - fi - prev= - else - dest=$arg - continue - fi - ;; - esac - - # Aesthetically quote the argument. - func_quote_for_eval "$arg" - func_append install_prog " $func_quote_for_eval_result" - if test -n "$arg2"; then - func_quote_for_eval "$arg2" - fi - func_append install_shared_prog " $func_quote_for_eval_result" - done - - test -z "$install_prog" && \ - func_fatal_help "you must specify an install program" - - test -n "$prev" && \ - func_fatal_help "the '$prev' option requires an argument" - - if test -n "$install_override_mode" && $no_mode; then - if $install_cp; then :; else - func_quote_for_eval "$install_override_mode" - func_append install_shared_prog " -m $func_quote_for_eval_result" - fi - fi - - if test -z "$files"; then - if test -z "$dest"; then - func_fatal_help "no file or destination specified" - else - func_fatal_help "you must specify a destination" - fi - fi - - # Strip any trailing slash from the destination. - func_stripname '' '/' "$dest" - dest=$func_stripname_result - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=: - if $isdir; then - destdir=$dest - destname= - else - func_dirname_and_basename "$dest" "" "." - destdir=$func_dirname_result - destname=$func_basename_result - - # Not a directory, so check to see that there is only one file specified. - set dummy $files; shift - test "$#" -gt 1 && \ - func_fatal_help "'$dest' is not a directory" - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - func_fatal_help "'$destdir' must be an absolute directory name" - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic=$magic - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - func_append staticlibs " $file" - ;; - - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "'$file' is not a valid libtool archive" - - library_names= - old_library= - relink_command= - func_source "$file" - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) func_append current_libdirs " $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) func_append future_libdirs " $libdir" ;; - esac - fi - - func_dirname "$file" "/" "" - dir=$func_dirname_result - func_append dir "$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` - else - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` - fi - - func_warning "relinking '$file'" - func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' - fi - - # See the names of the shared library. - set dummy $library_names; shift - if test -n "$1"; then - realname=$1 - shift - - srcname=$realname - test -n "$relink_command" && srcname=${realname}T - - # Install the shared library and build the symlinks. - func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ - 'exit $?' - tstripme=$stripme - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - case $realname in - *.dll.a) - tstripme= - ;; - esac - ;; - os2*) - case $realname in - *_dll.a) - tstripme= - ;; - esac - ;; - esac - if test -n "$tstripme" && test -n "$striplib"; then - func_show_eval "$striplib $destdir/$realname" 'exit $?' - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - # Try 'ln -sf' first, because the 'ln' binary might depend on - # the symlink we replace! Solaris /bin/ln does not understand -f, - # so we also need to try rm && ln -s. - for linkname - do - test "$linkname" != "$realname" \ - && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" - done - fi - - # Do each command in the postinstall commands. - lib=$destdir/$realname - func_execute_cmds "$postinstall_cmds" 'exit $?' - fi - - # Install the pseudo-library for information purposes. - func_basename "$file" - name=$func_basename_result - instname=$dir/${name}i - func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' - - # Maybe install the static library, too. - test -n "$old_library" && func_append staticlibs " $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile=$destdir/$destname - else - func_basename "$file" - destfile=$func_basename_result - destfile=$destdir/$destfile - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - func_lo2o "$destfile" - staticdest=$func_lo2o_result - ;; - *.$objext) - staticdest=$destfile - destfile= - ;; - *) - func_fatal_help "cannot copy a libtool object to '$destfile'" - ;; - esac - - # Install the libtool object if requested. - test -n "$destfile" && \ - func_show_eval "$install_prog $file $destfile" 'exit $?' - - # Install the old object if enabled. - if test yes = "$build_old_libs"; then - # Deduce the name of the old-style object file. - func_lo2o "$file" - staticobj=$func_lo2o_result - func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' - fi - exit $EXIT_SUCCESS - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile=$destdir/$destname - else - func_basename "$file" - destfile=$func_basename_result - destfile=$destdir/$destfile - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext= - case $file in - *.exe) - if test ! -f "$file"; then - func_stripname '' '.exe' "$file" - file=$func_stripname_result - stripped_ext=.exe - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin* | *mingw*) - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - wrapper=$func_ltwrapper_scriptname_result - else - func_stripname '' '.exe' "$file" - wrapper=$func_stripname_result - fi - ;; - *) - wrapper=$file - ;; - esac - if func_ltwrapper_script_p "$wrapper"; then - notinst_deplibs= - relink_command= - - func_source "$wrapper" - - # Check the variables that should have been set. - test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script '$wrapper'" - - finalize=: - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - func_source "$lib" - fi - libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` - if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "'$lib' has not been installed in '$libdir'" - finalize=false - fi - done - - relink_command= - func_source "$wrapper" - - outputname= - if test no = "$fast_install" && test -n "$relink_command"; then - $opt_dry_run || { - if $finalize; then - tmpdir=`func_mktempdir` - func_basename "$file$stripped_ext" - file=$func_basename_result - outputname=$tmpdir/$file - # Replace the output file specification. - relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - - $opt_quiet || { - func_quote_for_expand "$relink_command" - eval "func_echo $func_quote_for_expand_result" - } - if eval "$relink_command"; then : - else - func_error "error: relink '$file' with the above command before installing it" - $opt_dry_run || ${RM}r "$tmpdir" - continue - fi - file=$outputname - else - func_warning "cannot relink '$file'" - fi - } - else - # Install the binary that we compiled earlier. - file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyway - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - func_stripname '' '.exe' "$destfile" - destfile=$func_stripname_result - ;; - esac - ;; - esac - func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' - $opt_dry_run || if test -n "$outputname"; then - ${RM}r "$tmpdir" - fi - ;; - esac - done - - for file in $staticlibs; do - func_basename "$file" - name=$func_basename_result - - # Set up the ranlib parameters. - oldlib=$destdir/$name - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - - func_show_eval "$install_prog \$file \$oldlib" 'exit $?' - - if test -n "$stripme" && test -n "$old_striplib"; then - func_show_eval "$old_striplib $tool_oldlib" 'exit $?' - fi - - # Do each command in the postinstall commands. - func_execute_cmds "$old_postinstall_cmds" 'exit $?' - done - - test -n "$future_libdirs" && \ - func_warning "remember to run '$progname --finish$future_libdirs'" - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' - else - exit $EXIT_SUCCESS - fi -} - -test install = "$opt_mode" && func_mode_install ${1+"$@"} - - -# func_generate_dlsyms outputname originator pic_p -# Extract symbols from dlprefiles and create ${outputname}S.o with -# a dlpreopen symbol table. -func_generate_dlsyms () -{ - $debug_cmd - - my_outputname=$1 - my_originator=$2 - my_pic_p=${3-false} - my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` - my_dlsyms= - - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms=${my_outputname}S.c - else - func_error "not configured to extract global symbols from dlpreopened files" - fi - fi - - if test -n "$my_dlsyms"; then - case $my_dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist=$output_objdir/$my_outputname.nm - - func_show_eval "$RM $nlist ${nlist}S ${nlist}T" - - # Parse the name list into a source file. - func_verbose "creating $output_objdir/$my_dlsyms" - - $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) -#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" -#endif - -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined __osf__ -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - -#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) - -/* External symbol declarations for the compiler. */\ -" - - if test yes = "$dlself"; then - func_verbose "generating symbol list for '$output'" - - $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` - for progfile in $progfiles; do - func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from '$func_to_tool_file_result'" - $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $opt_dry_run || { - eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - if test -n "$export_symbols_regex"; then - $opt_dry_run || { - eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols=$output_objdir/$outputname.exp - $opt_dry_run || { - $RM $export_symbols - eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' - ;; - esac - } - else - $opt_dry_run || { - eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' - eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' - ;; - esac - } - fi - fi - - for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from '$dlprefile'" - func_basename "$dlprefile" - name=$func_basename_result - case $host in - *cygwin* | *mingw* | *cegcc* ) - # if an import library, we need to obtain dlname - if func_win32_import_lib_p "$dlprefile"; then - func_tr_sh "$dlprefile" - eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename= - if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then - # Use subshell, to avoid clobbering current variable values - dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname"; then - func_basename "$dlprefile_dlname" - dlprefile_dlbasename=$func_basename_result - else - # no lafile. user explicitly requested -dlpreopen . - $sharedlib_from_linklib_cmd "$dlprefile" - dlprefile_dlbasename=$sharedlib_from_linklib_result - fi - fi - $opt_dry_run || { - if test -n "$dlprefile_dlbasename"; then - eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' - else - func_warning "Could not compute DLL name from $name" - eval '$ECHO ": $name " >> "$nlist"' - fi - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | - $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" - } - else # not an import lib - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - fi - ;; - *) - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - ;; - esac - done - - $opt_dry_run || { - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $MV "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if $GREP -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - $GREP -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' - else - echo '/* NONE */' >> "$output_objdir/$my_dlsyms" - fi - - func_show_eval '$RM "${nlist}I"' - if test -n "$global_symbol_to_import"; then - eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' - fi - - echo >> "$output_objdir/$my_dlsyms" "\ - -/* The mapping between symbol names and symbols. */ -typedef struct { - const char *name; - void *address; -} lt_dlsymlist; -extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[];\ -" - - if test -s "$nlist"I; then - echo >> "$output_objdir/$my_dlsyms" "\ -static void lt_syminit(void) -{ - LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; - for (; symbol->name; ++symbol) - {" - $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" - echo >> "$output_objdir/$my_dlsyms" "\ - } -}" - fi - echo >> "$output_objdir/$my_dlsyms" "\ -LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[] = -{ {\"$my_originator\", (void *) 0}," - - if test -s "$nlist"I; then - echo >> "$output_objdir/$my_dlsyms" "\ - {\"@INIT@\", (void *) <_syminit}," - fi - - case $need_lib_prefix in - no) - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - *) - eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - esac - echo >> "$output_objdir/$my_dlsyms" "\ - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_${my_prefix}_LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - } # !$opt_dry_run - - pic_flag_for_symtable= - case "$compile_command " in - *" -static "*) ;; - *) - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; - *-*-hpux*) - pic_flag_for_symtable=" $pic_flag" ;; - *) - $my_pic_p && pic_flag_for_symtable=" $pic_flag" - ;; - esac - ;; - esac - symtab_cflags= - for arg in $LTCFLAGS; do - case $arg in - -pie | -fpie | -fPIE) ;; - *) func_append symtab_cflags " $arg" ;; - esac - done - - # Now compile the dynamic symbol file. - func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' - - # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' - - # Transform the symbol file into the correct name. - symfileobj=$output_objdir/${my_outputname}S.$objext - case $host in - *cygwin* | *mingw* | *cegcc* ) - if test -f "$output_objdir/$my_outputname.def"; then - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - else - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - fi - ;; - *) - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - ;; - esac - ;; - *) - func_fatal_error "unknown suffix for '$my_dlsyms'" - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` - fi -} - -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $debug_cmd - - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $debug_cmd - - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - -# func_win32_libid arg -# return the library type of file 'arg' -# -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -# Despite the name, also deal with 64 bit binaries. -func_win32_libid () -{ - $debug_cmd - - win32_libid_type=unknown - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - case $nm_interface in - "MS dumpbin") - if func_cygming_ms_implib_p "$1" || - func_cygming_gnu_implib_p "$1" - then - win32_nmres=import - else - win32_nmres= - fi - ;; - *) - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' - 1,100{ - / I /{ - s|.*|import| - p - q - } - }'` - ;; - esac - case $win32_nmres in - import*) win32_libid_type="x86 archive import";; - *) win32_libid_type="x86 archive static";; - esac - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $ECHO "$win32_libid_type" -} - -# func_cygming_dll_for_implib ARG -# -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib () -{ - $debug_cmd - - sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` -} - -# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs -# -# The is the core of a fallback implementation of a -# platform-specific function to extract the name of the -# DLL associated with the specified import library LIBNAME. -# -# SECTION_NAME is either .idata$6 or .idata$7, depending -# on the platform and compiler that created the implib. -# -# Echos the name of the DLL associated with the -# specified import library. -func_cygming_dll_for_implib_fallback_core () -{ - $debug_cmd - - match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` - $OBJDUMP -s --section "$1" "$2" 2>/dev/null | - $SED '/^Contents of section '"$match_literal"':/{ - # Place marker at beginning of archive member dllname section - s/.*/====MARK====/ - p - d - } - # These lines can sometimes be longer than 43 characters, but - # are always uninteresting - /:[ ]*file format pe[i]\{,1\}-/d - /^In archive [^:]*:/d - # Ensure marker is printed - /^====MARK====/p - # Remove all lines with less than 43 characters - /^.\{43\}/!d - # From remaining lines, remove first 43 characters - s/^.\{43\}//' | - $SED -n ' - # Join marker and all lines until next marker into a single line - /^====MARK====/ b para - H - $ b para - b - :para - x - s/\n//g - # Remove the marker - s/^====MARK====// - # Remove trailing dots and whitespace - s/[\. \t]*$// - # Print - /./p' | - # we now have a list, one entry per line, of the stringified - # contents of the appropriate section of all members of the - # archive that possess that section. Heuristic: eliminate - # all those that have a first or second character that is - # a '.' (that is, objdump's representation of an unprintable - # character.) This should work for all archives with less than - # 0x302f exports -- but will fail for DLLs whose name actually - # begins with a literal '.' or a single character followed by - # a '.'. - # - # Of those that remain, print the first one. - $SED -e '/^\./d;/^.\./d;q' -} - -# func_cygming_dll_for_implib_fallback ARG -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# -# This fallback implementation is for use when $DLLTOOL -# does not support the --identify-strict option. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib_fallback () -{ - $debug_cmd - - if func_cygming_gnu_implib_p "$1"; then - # binutils import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1"; then - # ms-generated import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` - else - # unknown - sharedlib_from_linklib_result= - fi -} - - -# func_extract_an_archive dir oldlib -func_extract_an_archive () -{ - $debug_cmd - - f_ex_an_ar_dir=$1; shift - f_ex_an_ar_oldlib=$1 - if test yes = "$lock_old_archive_extraction"; then - lockfile=$f_ex_an_ar_oldlib.lock - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - fi - func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ - 'stat=$?; rm -f "$lockfile"; exit $stat' - if test yes = "$lock_old_archive_extraction"; then - $opt_dry_run || rm -f "$lockfile" - fi - if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then - : - else - func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" - fi -} - - -# func_extract_archives gentop oldlib ... -func_extract_archives () -{ - $debug_cmd - - my_gentop=$1; shift - my_oldlibs=${1+"$@"} - my_oldobjs= - my_xlib= - my_xabs= - my_xdir= - - for my_xlib in $my_oldlibs; do - # Extract the objects. - case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; - *) my_xabs=`pwd`"/$my_xlib" ;; - esac - func_basename "$my_xlib" - my_xlib=$func_basename_result - my_xlib_u=$my_xlib - while :; do - case " $extracted_archives " in - *" $my_xlib_u "*) - func_arith $extracted_serial + 1 - extracted_serial=$func_arith_result - my_xlib_u=lt$extracted_serial-$my_xlib ;; - *) break ;; - esac - done - extracted_archives="$extracted_archives $my_xlib_u" - my_xdir=$my_gentop/$my_xlib_u - - func_mkdir_p "$my_xdir" - - case $host in - *-darwin*) - func_verbose "Extracting $my_xabs" - # Do not bother doing anything if just a dry run - $opt_dry_run || { - darwin_orig_dir=`pwd` - cd $my_xdir || exit $? - darwin_archive=$my_xabs - darwin_curdir=`pwd` - func_basename "$darwin_archive" - darwin_base_archive=$func_basename_result - darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` - if test -n "$darwin_arches"; then - darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` - darwin_arch= - func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches; do - func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" - $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" - cd "unfat-$$/$darwin_base_archive-$darwin_arch" - func_extract_an_archive "`pwd`" "$darwin_base_archive" - cd "$darwin_curdir" - $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" - done # $darwin_arches - ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` - darwin_file= - darwin_files= - for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` - $LIPO -create -output "$darwin_file" $darwin_files - done # $darwin_filelist - $RM -rf unfat-$$ - cd "$darwin_orig_dir" - else - cd $darwin_orig_dir - func_extract_an_archive "$my_xdir" "$my_xabs" - fi # $darwin_arches - } # !$opt_dry_run - ;; - *) - func_extract_an_archive "$my_xdir" "$my_xabs" - ;; - esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` - done - - func_extract_archives_result=$my_oldobjs -} - - -# func_emit_wrapper [arg=no] -# -# Emit a libtool wrapper script on stdout. -# Don't directly open a file because we may want to -# incorporate the script contents within a cygwin/mingw -# wrapper executable. Must ONLY be called from within -# func_mode_link because it depends on a number of variables -# set therein. -# -# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR -# variable will take. If 'yes', then the emitted script -# will assume that the directory where it is stored is -# the $objdir directory. This is a cygwin/mingw-specific -# behavior. -func_emit_wrapper () -{ - func_emit_wrapper_arg1=${1-no} - - $ECHO "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE) $VERSION -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='$sed_quote_subst' - -# Be Bourne compatible -if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variables: - generated_by_libtool_version='$macro_version' - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$ECHO are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - file=\"\$0\"" - - qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` - $ECHO "\ - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - ECHO=\"$qECHO\" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on -# windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options that match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's $0 value, followed by "$@". -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=\$0 - shift - for lt_opt - do - case \"\$lt_opt\" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` - test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. - lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` - cat \"\$lt_dump_D/\$lt_dump_F\" - exit 0 - ;; - --lt-*) - \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n \"\$lt_option_debug\"; then - echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" - lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2* | *-cegcc*) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $ECHO "\ - \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from \$@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case \" \$* \" in - *\\ --lt-*) - for lt_wr_arg - do - case \$lt_wr_arg in - --lt-*) ;; - *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; - esac - shift - done ;; - esac - func_exec_program_core \${1+\"\$@\"} -} - - # Parse options - func_parse_lt_options \"\$0\" \${1+\"\$@\"} - - # Find the directory that this script lives in. - thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 - if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then - # special case for '.' - if test \"\$thisdir\" = \".\"; then - thisdir=\`pwd\` - fi - # remove .libs from thisdir - case \"\$thisdir\" in - *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; - $objdir ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test yes = "$fast_install"; then - $ECHO "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $MKDIR \"\$progdir\" - else - $RM \"\$progdir/\$file\" - fi" - - $ECHO "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - \$ECHO \"\$relink_command_output\" >&2 - $RM \"\$progdir/\$file\" - exit 1 - fi - fi - - $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $RM \"\$progdir/\$program\"; - $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $RM \"\$progdir/\$file\" - fi" - else - $ECHO "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $ECHO "\ - - if test -f \"\$progdir/\$program\"; then" - - # fixup the dll searchpath if we need to. - # - # Fix the DLL searchpath if we need to. Do this before prepending - # to shlibpath, because on Windows, both are PATH and uninstalled - # libraries must come first. - if test -n "$dllsearchpath"; then - $ECHO "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - # Export our shlibpath_var if we have one. - if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $ECHO "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` - - export $shlibpath_var -" - fi - - $ECHO "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. - func_exec_program \${1+\"\$@\"} - fi - else - # The program doesn't exist. - \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 - \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 - \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" -} - - -# func_emit_cwrapperexe_src -# emit the source code for a wrapper executable on stdout -# Must ONLY be called from within func_mode_link because -# it depends on a number of variable set therein. -func_emit_cwrapperexe_src () -{ - cat < -#include -#ifdef _MSC_VER -# include -# include -# include -#else -# include -# include -# ifdef __CYGWIN__ -# include -# endif -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) - -/* declarations of non-ANSI functions */ -#if defined __MINGW32__ -# ifdef __STRICT_ANSI__ -int _putenv (const char *); -# endif -#elif defined __CYGWIN__ -# ifdef __STRICT_ANSI__ -char *realpath (const char *, char *); -int putenv (char *); -int setenv (const char *, const char *, int); -# endif -/* #elif defined other_platform || defined ... */ -#endif - -/* portability defines, excluding path handling macros */ -#if defined _MSC_VER -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -# define S_IXUSR _S_IEXEC -#elif defined __MINGW32__ -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -#elif defined __CYGWIN__ -# define HAVE_SETENV -# define FOPEN_WB "wb" -/* #elif defined other platforms ... */ -#endif - -#if defined PATH_MAX -# define LT_PATHMAX PATH_MAX -#elif defined MAXPATHLEN -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef S_IXOTH -# define S_IXOTH 0 -#endif -#ifndef S_IXGRP -# define S_IXGRP 0 -#endif - -/* path handling portability macros */ -#ifndef DIR_SEPARATOR -# define DIR_SEPARATOR '/' -# define PATH_SEPARATOR ':' -#endif - -#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ - defined __OS2__ -# define HAVE_DOS_BASED_FILE_SYSTEM -# define FOPEN_WB "wb" -# ifndef DIR_SEPARATOR_2 -# define DIR_SEPARATOR_2 '\\' -# endif -# ifndef PATH_SEPARATOR_2 -# define PATH_SEPARATOR_2 ';' -# endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#ifndef PATH_SEPARATOR_2 -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) -#else /* PATH_SEPARATOR_2 */ -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) -#endif /* PATH_SEPARATOR_2 */ - -#ifndef FOPEN_WB -# define FOPEN_WB "w" -#endif -#ifndef _O_BINARY -# define _O_BINARY 0 -#endif - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free (stale); stale = 0; } \ -} while (0) - -#if defined LT_DEBUGWRAPPER -static int lt_debug = 1; -#else -static int lt_debug = 0; -#endif - -const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ - -void *xmalloc (size_t num); -char *xstrdup (const char *string); -const char *base_name (const char *name); -char *find_executable (const char *wrapper); -char *chase_symlinks (const char *pathspec); -int make_executable (const char *path); -int check_executable (const char *path); -char *strendzap (char *str, const char *pat); -void lt_debugprintf (const char *file, int line, const char *fmt, ...); -void lt_fatal (const char *file, int line, const char *message, ...); -static const char *nonnull (const char *s); -static const char *nonempty (const char *s); -void lt_setenv (const char *name, const char *value); -char *lt_extend_str (const char *orig_value, const char *add, int to_end); -void lt_update_exe_path (const char *name, const char *value); -void lt_update_lib_path (const char *name, const char *value); -char **prepare_spawn (char **argv); -void lt_dump_script (FILE *f); -EOF - - cat <= 0) - && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - return 1; - else - return 0; -} - -int -make_executable (const char *path) -{ - int rval = 0; - struct stat st; - - lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", - nonempty (path)); - if ((!path) || (!*path)) - return 0; - - if (stat (path, &st) >= 0) - { - rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); - } - return rval; -} - -/* Searches for the full path of the wrapper. Returns - newly allocated full path name if found, NULL otherwise - Does not chase symlinks, even on platforms that support them. -*/ -char * -find_executable (const char *wrapper) -{ - int has_slash = 0; - const char *p; - const char *p_next; - /* static buffer for getcwd */ - char tmp[LT_PATHMAX + 1]; - size_t tmp_len; - char *concat_name; - - lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", - nonempty (wrapper)); - - if ((wrapper == NULL) || (*wrapper == '\0')) - return NULL; - - /* Absolute path? */ -#if defined HAVE_DOS_BASED_FILE_SYSTEM - if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - else - { -#endif - if (IS_DIR_SEPARATOR (wrapper[0])) - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } -#if defined HAVE_DOS_BASED_FILE_SYSTEM - } -#endif - - for (p = wrapper; *p; p++) - if (*p == '/') - { - has_slash = 1; - break; - } - if (!has_slash) - { - /* no slashes; search PATH */ - const char *path = getenv ("PATH"); - if (path != NULL) - { - for (p = path; *p; p = p_next) - { - const char *q; - size_t p_len; - for (q = p; *q; q++) - if (IS_PATH_SEPARATOR (*q)) - break; - p_len = (size_t) (q - p); - p_next = (*q == '\0' ? q : q + 1); - if (p_len == 0) - { - /* empty path: current directory */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = - XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - } - else - { - concat_name = - XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, p, p_len); - concat_name[p_len] = '/'; - strcpy (concat_name + p_len + 1, wrapper); - } - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - } - /* not found in PATH; assume curdir */ - } - /* Relative path | not found in path: prepend cwd */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - return NULL; -} - -char * -chase_symlinks (const char *pathspec) -{ -#ifndef S_ISLNK - return xstrdup (pathspec); -#else - char buf[LT_PATHMAX]; - struct stat s; - char *tmp_pathspec = xstrdup (pathspec); - char *p; - int has_symlinks = 0; - while (strlen (tmp_pathspec) && !has_symlinks) - { - lt_debugprintf (__FILE__, __LINE__, - "checking path component for symlinks: %s\n", - tmp_pathspec); - if (lstat (tmp_pathspec, &s) == 0) - { - if (S_ISLNK (s.st_mode) != 0) - { - has_symlinks = 1; - break; - } - - /* search backwards for last DIR_SEPARATOR */ - p = tmp_pathspec + strlen (tmp_pathspec) - 1; - while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - p--; - if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - { - /* no more DIR_SEPARATORS left */ - break; - } - *p = '\0'; - } - else - { - lt_fatal (__FILE__, __LINE__, - "error accessing file \"%s\": %s", - tmp_pathspec, nonnull (strerror (errno))); - } - } - XFREE (tmp_pathspec); - - if (!has_symlinks) - { - return xstrdup (pathspec); - } - - tmp_pathspec = realpath (pathspec, buf); - if (tmp_pathspec == 0) - { - lt_fatal (__FILE__, __LINE__, - "could not follow symlinks for %s", pathspec); - } - return xstrdup (tmp_pathspec); -#endif -} - -char * -strendzap (char *str, const char *pat) -{ - size_t len, patlen; - - assert (str != NULL); - assert (pat != NULL); - - len = strlen (str); - patlen = strlen (pat); - - if (patlen <= len) - { - str += len - patlen; - if (STREQ (str, pat)) - *str = '\0'; - } - return str; -} - -void -lt_debugprintf (const char *file, int line, const char *fmt, ...) -{ - va_list args; - if (lt_debug) - { - (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); - } -} - -static void -lt_error_core (int exit_status, const char *file, - int line, const char *mode, - const char *message, va_list ap) -{ - fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *file, int line, const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); - va_end (ap); -} - -static const char * -nonnull (const char *s) -{ - return s ? s : "(null)"; -} - -static const char * -nonempty (const char *s) -{ - return (s && !*s) ? "(empty)" : nonnull (s); -} - -void -lt_setenv (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_setenv) setting '%s' to '%s'\n", - nonnull (name), nonnull (value)); - { -#ifdef HAVE_SETENV - /* always make a copy, for consistency with !HAVE_SETENV */ - char *str = xstrdup (value); - setenv (name, str, 1); -#else - size_t len = strlen (name) + 1 + strlen (value) + 1; - char *str = XMALLOC (char, len); - sprintf (str, "%s=%s", name, value); - if (putenv (str) != EXIT_SUCCESS) - { - XFREE (str); - } -#endif - } -} - -char * -lt_extend_str (const char *orig_value, const char *add, int to_end) -{ - char *new_value; - if (orig_value && *orig_value) - { - size_t orig_value_len = strlen (orig_value); - size_t add_len = strlen (add); - new_value = XMALLOC (char, add_len + orig_value_len + 1); - if (to_end) - { - strcpy (new_value, orig_value); - strcpy (new_value + orig_value_len, add); - } - else - { - strcpy (new_value, add); - strcpy (new_value + add_len, orig_value); - } - } - else - { - new_value = xstrdup (add); - } - return new_value; -} - -void -lt_update_exe_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - /* some systems can't cope with a ':'-terminated path #' */ - size_t len = strlen (new_value); - while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) - { - new_value[--len] = '\0'; - } - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -void -lt_update_lib_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -EOF - case $host_os in - mingw*) - cat <<"EOF" - -/* Prepares an argument vector before calling spawn(). - Note that spawn() does not by itself call the command interpreter - (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : - ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&v); - v.dwPlatformId == VER_PLATFORM_WIN32_NT; - }) ? "cmd.exe" : "command.com"). - Instead it simply concatenates the arguments, separated by ' ', and calls - CreateProcess(). We must quote the arguments since Win32 CreateProcess() - interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a - special way: - - Space and tab are interpreted as delimiters. They are not treated as - delimiters if they are surrounded by double quotes: "...". - - Unescaped double quotes are removed from the input. Their only effect is - that within double quotes, space and tab are treated like normal - characters. - - Backslashes not followed by double quotes are not special. - - But 2*n+1 backslashes followed by a double quote become - n backslashes followed by a double quote (n >= 0): - \" -> " - \\\" -> \" - \\\\\" -> \\" - */ -#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -char ** -prepare_spawn (char **argv) -{ - size_t argc; - char **new_argv; - size_t i; - - /* Count number of arguments. */ - for (argc = 0; argv[argc] != NULL; argc++) - ; - - /* Allocate new argument vector. */ - new_argv = XMALLOC (char *, argc + 1); - - /* Put quoted arguments into the new argument vector. */ - for (i = 0; i < argc; i++) - { - const char *string = argv[i]; - - if (string[0] == '\0') - new_argv[i] = xstrdup ("\"\""); - else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) - { - int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); - size_t length; - unsigned int backslashes; - const char *s; - char *quoted_string; - char *p; - - length = 0; - backslashes = 0; - if (quote_around) - length++; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - length += backslashes + 1; - length++; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - - quoted_string = XMALLOC (char, length + 1); - - p = quoted_string; - backslashes = 0; - if (quote_around) - *p++ = '"'; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - { - unsigned int j; - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - *p++ = c; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - unsigned int j; - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - - new_argv[i] = quoted_string; - } - else - new_argv[i] = (char *) string; - } - new_argv[argc] = NULL; - - return new_argv; -} -EOF - ;; - esac - - cat <<"EOF" -void lt_dump_script (FILE* f) -{ -EOF - func_emit_wrapper yes | - $SED -n -e ' -s/^\(.\{79\}\)\(..*\)/\1\ -\2/ -h -s/\([\\"]\)/\\\1/g -s/$/\\n/ -s/\([^\n]*\).*/ fputs ("\1", f);/p -g -D' - cat <<"EOF" -} -EOF -} -# end: func_emit_cwrapperexe_src - -# func_win32_import_lib_p ARG -# True if ARG is an import lib, as indicated by $file_magic_cmd -func_win32_import_lib_p () -{ - $debug_cmd - - case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in - *import*) : ;; - *) false ;; - esac -} - -# func_suncc_cstd_abi -# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! -# Several compiler flags select an ABI that is incompatible with the -# Cstd library. Avoid specifying it if any are in CXXFLAGS. -func_suncc_cstd_abi () -{ - $debug_cmd - - case " $compile_command " in - *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) - suncc_use_cstd_abi=no - ;; - *) - suncc_use_cstd_abi=yes - ;; - esac -} - -# func_mode_link arg... -func_mode_link () -{ - $debug_cmd - - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - # It is impossible to link a dll without this setting, and - # we shouldn't force the makefile maintainer to figure out - # what system we are compiling for in order to pass an extra - # flag for every libtool invocation. - # allow_undefined=no - - # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll that has undefined symbols, in which case not - # even a static library is built. For now, we need to specify - # -no-undefined on the libtool link line when we can be certain - # that all symbols are satisfied, otherwise we get a static library. - allow_undefined=yes - ;; - *) - allow_undefined=yes - ;; - esac - libtool_args=$nonopt - base_compile="$nonopt $@" - compile_command=$nonopt - finalize_command=$nonopt - - compile_rpath= - finalize_rpath= - compile_shlibpath= - finalize_shlibpath= - convenience= - old_convenience= - deplibs= - old_deplibs= - compiler_flags= - linker_flags= - dllsearchpath= - lib_search_path=`pwd` - inst_prefix_dir= - new_inherited_linker_flags= - - avoid_version=no - bindir= - dlfiles= - dlprefiles= - dlself=no - export_dynamic=no - export_symbols= - export_symbols_regex= - generated= - libobjs= - ltlibs= - module=no - no_install=no - objs= - os2dllname= - non_pic_objects= - precious_files_regex= - prefer_static_libs=no - preload=false - prev= - prevarg= - release= - rpath= - xrpath= - perm_rpath= - temp_rpath= - thread_safe=no - vinfo= - vinfo_number=no - weak_libs= - single_module=$wl-single_module - func_infer_tag $base_compile - - # We need to know -static, to get the right output filenames. - for arg - do - case $arg in - -shared) - test yes != "$build_libtool_libs" \ - && func_fatal_configuration "cannot build a shared library" - build_old_libs=no - break - ;; - -all-static | -static | -static-libtool-libs) - case $arg in - -all-static) - if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then - func_warning "complete static linking is impossible in this configuration" - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - -static) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=built - ;; - -static-libtool-libs) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - esac - build_libtool_libs=no - build_old_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg=$1 - shift - func_quote_for_eval "$arg" - qarg=$func_quote_for_eval_unquoted_result - func_append libtool_args " $func_quote_for_eval_result" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - func_append compile_command " @OUTPUT@" - func_append finalize_command " @OUTPUT@" - ;; - esac - - case $prev in - bindir) - bindir=$arg - prev= - continue - ;; - dlfiles|dlprefiles) - $preload || { - # Add the symbol object into the linking commands. - func_append compile_command " @SYMFILE@" - func_append finalize_command " @SYMFILE@" - preload=: - } - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test no = "$dlself"; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test dlprefiles = "$prev"; then - dlself=yes - elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test dlfiles = "$prev"; then - func_append dlfiles " $arg" - else - func_append dlprefiles " $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols=$arg - test -f "$arg" \ - || func_fatal_error "symbol file '$arg' does not exist" - prev= - continue - ;; - expsyms_regex) - export_symbols_regex=$arg - prev= - continue - ;; - framework) - case $host in - *-*-darwin*) - case "$deplibs " in - *" $qarg.ltframework "*) ;; - *) func_append deplibs " $qarg.ltframework" # this is fixed later - ;; - esac - ;; - esac - prev= - continue - ;; - inst_prefix) - inst_prefix_dir=$arg - prev= - continue - ;; - mllvm) - # Clang does not use LLVM to link, so we can simply discard any - # '-mllvm $arg' options when doing the link step. - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat "$save_arg"` - do -# func_append moreargs " $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test none = "$pic_object" && - test none = "$non_pic_object"; then - func_fatal_error "cannot find name of object for '$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir=$func_dirname_result - - if test none != "$pic_object"; then - # Prepend the subdirectory the object is found in. - pic_object=$xdir$pic_object - - if test dlfiles = "$prev"; then - if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test dlprefiles = "$prev"; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg=$pic_object - fi - - # Non-PIC object. - if test none != "$non_pic_object"; then - # Prepend the subdirectory the object is found in. - non_pic_object=$xdir$non_pic_object - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test none = "$pic_object"; then - arg=$non_pic_object - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object=$pic_object - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir=$func_dirname_result - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "'$arg' is not a valid libtool object" - fi - fi - done - else - func_fatal_error "link input file '$arg' does not exist" - fi - arg=$save_arg - prev= - continue - ;; - os2dllname) - os2dllname=$arg - prev= - continue - ;; - precious_regex) - precious_files_regex=$arg - prev= - continue - ;; - release) - release=-$arg - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - if test rpath = "$prev"; then - case "$rpath " in - *" $arg "*) ;; - *) func_append rpath " $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) func_append xrpath " $arg" ;; - esac - fi - prev= - continue - ;; - shrext) - shrext_cmds=$arg - prev= - continue - ;; - weak) - func_append weak_libs " $arg" - prev= - continue - ;; - xcclinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xcompiler) - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xlinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $wl$qarg" - prev= - func_append compile_command " $wl$qarg" - func_append finalize_command " $wl$qarg" - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg=$arg - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - # See comment for -static flag below, for more details. - func_append compile_command " $link_static_flag" - func_append finalize_command " $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - func_fatal_error "'-allow-undefined' must not be used because it is the default" - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -bindir) - prev=bindir - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - func_fatal_error "more than one -exported-symbols argument is not allowed" - fi - if test X-export-symbols = "X$arg"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -framework) - prev=framework - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - func_append compile_command " $arg" - func_append finalize_command " $arg" - ;; - esac - continue - ;; - - -L*) - func_stripname "-L" '' "$arg" - if test -z "$func_stripname_result"; then - if test "$#" -gt 0; then - func_fatal_error "require no space between '-L' and '$1'" - else - func_fatal_error "need path for '-L' option" - fi - fi - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of '$dir'" - dir=$absdir - ;; - esac - case "$deplibs " in - *" -L$dir "* | *" $arg "*) - # Will only happen for absolute or sysroot arguments - ;; - *) - # Preserve sysroot, but never include relative directories - case $dir in - [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; - *) func_append deplibs " -L$dir" ;; - esac - func_append lib_search_path " $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$dir:"*) ;; - ::) dllsearchpath=$dir;; - *) func_append dllsearchpath ":$dir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - continue - ;; - - -l*) - if test X-lc = "X$arg" || test X-lm = "X$arg"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-os2*) - # These systems don't actually have a C library (as such) - test X-lc = "X$arg" && continue - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) - # Do not include libc due to us having libc/libc_r. - test X-lc = "X$arg" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - func_append deplibs " System.ltframework" - continue - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - test X-lc = "X$arg" && continue - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - test X-lc = "X$arg" && continue - ;; - esac - elif test X-lc_r = "X$arg"; then - case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - func_append deplibs " $arg" - continue - ;; - - -mllvm) - prev=mllvm - continue - ;; - - -module) - module=yes - continue - ;; - - # Tru64 UNIX uses -model [arg] to determine the layout of C++ - # classes, name mangling, and exception handling. - # Darwin uses the -arch flag to determine output architecture. - -model|-arch|-isysroot|--sysroot) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - prev=xcompiler - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case "$new_inherited_linker_flags " in - *" $arg "*) ;; - * ) func_append new_inherited_linker_flags " $arg" ;; - esac - continue - ;; - - -multi_module) - single_module=$wl-multi_module - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) - # The PATH hackery in wrapper scripts is required on Windows - # and Darwin in order for the loader to find any dlls it needs. - func_warning "'-no-install' is ignored for $host" - func_warning "assuming '-no-fast-install' instead" - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -os2dllname) - prev=os2dllname - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - func_stripname '-R' '' "$arg" - dir=$func_stripname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - =*) - func_stripname '=' '' "$dir" - dir=$lt_sysroot$func_stripname_result - ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - continue - ;; - - -shared) - # The effects of -shared are defined in a previous loop. - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -static | -static-libtool-libs) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -weak) - prev=weak - continue - ;; - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs=$IFS; IFS=, - for flag in $args; do - IFS=$save_ifs - func_quote_for_eval "$flag" - func_append arg " $func_quote_for_eval_result" - func_append compiler_flags " $func_quote_for_eval_result" - done - IFS=$save_ifs - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Wl,*) - func_stripname '-Wl,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs=$IFS; IFS=, - for flag in $args; do - IFS=$save_ifs - func_quote_for_eval "$flag" - func_append arg " $wl$func_quote_for_eval_result" - func_append compiler_flags " $wl$func_quote_for_eval_result" - func_append linker_flags " $func_quote_for_eval_result" - done - IFS=$save_ifs - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # -msg_* for osf cc - -msg_*) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - ;; - - # Flags to be passed through unchanged, with rationale: - # -64, -mips[0-9] enable 64-bit mode for the SGI compiler - # -r[0-9][0-9]* specify processor for the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler - # +DA*, +DD* enable 64-bit mode for the HP compiler - # -q* compiler args for the IBM compiler - # -m*, -t[45]*, -txscale* architecture-specific flags for GCC - # -F/path path to uninstalled frameworks, gcc on darwin - # -p, -pg, --coverage, -fprofile-* profiling flags for GCC - # -fstack-protector* stack protector flags for GCC - # @file GCC response files - # -tp=* Portland pgcc target processor selection - # --sysroot=* for sysroot support - # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization - # -specs=* GCC specs files - # -stdlib=* select c++ std lib with clang - # -fsanitize=* Clang/GCC memory and address sanitizer - # -fuse-ld=* Linker select flags for GCC - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ - -specs=*|-fsanitize=*|-fuse-ld=*) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - func_append compile_command " $arg" - func_append finalize_command " $arg" - func_append compiler_flags " $arg" - continue - ;; - - -Z*) - if test os2 = "`expr $host : '.*\(os2\)'`"; then - # OS/2 uses -Zxxx to specify OS/2-specific options - compiler_flags="$compiler_flags $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case $arg in - -Zlinker | -Zstack) - prev=xcompiler - ;; - esac - continue - else - # Otherwise treat like 'Some other compiler flag' below - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - fi - ;; - - # Some other compiler flag. - -* | +*) - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - ;; - - *.$objext) - # A standard object. - func_append objs " $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test none = "$pic_object" && - test none = "$non_pic_object"; then - func_fatal_error "cannot find name of object for '$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir=$func_dirname_result - - test none = "$pic_object" || { - # Prepend the subdirectory the object is found in. - pic_object=$xdir$pic_object - - if test dlfiles = "$prev"; then - if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test dlprefiles = "$prev"; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg=$pic_object - } - - # Non-PIC object. - if test none != "$non_pic_object"; then - # Prepend the subdirectory the object is found in. - non_pic_object=$xdir$non_pic_object - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test none = "$pic_object"; then - arg=$non_pic_object - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object=$pic_object - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir=$func_dirname_result - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "'$arg' is not a valid libtool object" - fi - fi - ;; - - *.$libext) - # An archive. - func_append deplibs " $arg" - func_append old_deplibs " $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - func_resolve_sysroot "$arg" - if test dlfiles = "$prev"; then - # This library was specified with -dlopen. - func_append dlfiles " $func_resolve_sysroot_result" - prev= - elif test dlprefiles = "$prev"; then - # The library was specified with -dlpreopen. - func_append dlprefiles " $func_resolve_sysroot_result" - prev= - else - func_append deplibs " $func_resolve_sysroot_result" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - done # argument parsing loop - - test -n "$prev" && \ - func_fatal_help "the '$prevarg' option requires an argument" - - if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - func_basename "$output" - outputname=$func_basename_result - libobjs_save=$libobjs - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - # Definition is injected by LT_CONFIG during libtool generation. - func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" - - func_dirname "$output" "/" "" - output_objdir=$func_dirname_result$objdir - func_to_tool_file "$output_objdir/" - tool_output_objdir=$func_to_tool_file_result - # Create the object directory. - func_mkdir_p "$output_objdir" - - # Determine the type of output - case $output in - "") - func_fatal_help "you must specify an output file" - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if $opt_preserve_dup_deps; then - case "$libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append libs " $deplib" - done - - if test lib = "$linkmode"; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if $opt_duplicate_compiler_generated_deps; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; - esac - func_append pre_post_deps " $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - notinst_path= # paths that contain not-installed libtool libraries - - case $linkmode in - lib) - passes="conv dlpreopen link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=false - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - - for pass in $passes; do - # The preopen pass in lib mode reverses $deplibs; put it back here - # so that -L comes before libs that need it for instance... - if test lib,link = "$linkmode,$pass"; then - ## FIXME: Find the place where the list is rebuilt in the wrong - ## order, and fix it there properly - tmp_deplibs= - for deplib in $deplibs; do - tmp_deplibs="$deplib $tmp_deplibs" - done - deplibs=$tmp_deplibs - fi - - if test lib,link = "$linkmode,$pass" || - test prog,scan = "$linkmode,$pass"; then - libs=$deplibs - deplibs= - fi - if test prog = "$linkmode"; then - case $pass in - dlopen) libs=$dlfiles ;; - dlpreopen) libs=$dlprefiles ;; - link) - libs="$deplibs %DEPLIBS%" - test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" - ;; - esac - fi - if test lib,dlpreopen = "$linkmode,$pass"; then - # Collect and forward deplibs of preopened libtool libs - for lib in $dlprefiles; do - # Ignore non-libtool-libs - dependency_libs= - func_resolve_sysroot "$lib" - case $lib in - *.la) func_source "$func_resolve_sysroot_result" ;; - esac - - # Collect preopened libtool deplibs, except any this library - # has declared as weak libs - for deplib in $dependency_libs; do - func_basename "$deplib" - deplib_base=$func_basename_result - case " $weak_libs " in - *" $deplib_base "*) ;; - *) func_append deplibs " $deplib" ;; - esac - done - done - libs=$dlprefiles - fi - if test dlopen = "$pass"; then - # Collect dlpreopened libraries - save_deplibs=$deplibs - deplibs= - fi - - for deplib in $libs; do - lib= - found=false - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append compiler_flags " $deplib" - if test lib = "$linkmode"; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -l*) - if test lib != "$linkmode" && test prog != "$linkmode"; then - func_warning "'-l' is ignored for archives/objects" - continue - fi - func_stripname '-l' '' "$deplib" - name=$func_stripname_result - if test lib = "$linkmode"; then - searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" - else - searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" - fi - for searchdir in $searchdirs; do - for search_ext in .la $std_shrext .so .a; do - # Search the libtool library - lib=$searchdir/lib$name$search_ext - if test -f "$lib"; then - if test .la = "$search_ext"; then - found=: - else - found=false - fi - break 2 - fi - done - done - if $found; then - # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test yes = "$allow_libtool_libs_with_static_runtimes"; then - case " $predeps $postdeps " in - *" $deplib "*) - if func_lalib_p "$lib"; then - library_names= - old_library= - func_source "$lib" - for l in $old_library $library_names; do - ll=$l - done - if test "X$ll" = "X$old_library"; then # only static version available - found=false - func_dirname "$lib" "" "." - ladir=$func_dirname_result - lib=$ladir/$old_library - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - else - # deplib doesn't seem to be a libtool library - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - ;; # -l - *.ltframework) - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - if test lib = "$linkmode"; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test conv = "$pass" && continue - newdependency_libs="$deplib $newdependency_libs" - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - prog) - if test conv = "$pass"; then - deplibs="$deplib $deplibs" - continue - fi - if test scan = "$pass"; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - *) - func_warning "'-L' is ignored for archives/objects" - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test link = "$pass"; then - func_stripname '-R' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) - func_resolve_sysroot "$deplib" - lib=$func_resolve_sysroot_result - ;; - *.$libext) - if test conv = "$pass"; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - # Linking convenience modules into shared libraries is allowed, - # but linking other static libraries is non-portable. - case " $dlpreconveniencelibs " in - *" $deplib "*) ;; - *) - valid_a_lib=false - case $deplibs_check_method in - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=: - fi - ;; - pass_all) - valid_a_lib=: - ;; - esac - if $valid_a_lib; then - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - else - echo - $ECHO "*** Warning: Trying to link with static lib archive $deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because the file extensions .$libext of this argument makes me believe" - echo "*** that it is just a static archive that I should not use here." - fi - ;; - esac - continue - ;; - prog) - if test link != "$pass"; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test conv = "$pass"; then - deplibs="$deplib $deplibs" - elif test prog = "$linkmode"; then - if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - func_append newdlprefiles " $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append newdlfiles " $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=: - continue - ;; - esac # case $deplib - - $found || test -f "$lib" \ - || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$lib" \ - || func_fatal_error "'$lib' is not a valid libtool archive" - - func_dirname "$lib" "" "." - ladir=$func_dirname_result - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - inherited_linker_flags= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - avoidtemprpath= - - - # Read the .la file - func_source "$lib" - - # Convert "-framework foo" to "foo.ltframework" - if test -n "$inherited_linker_flags"; then - tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` - for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do - case " $new_inherited_linker_flags " in - *" $tmp_inherited_linker_flag "*) ;; - *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; - esac - done - fi - dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test lib,link = "$linkmode,$pass" || - test prog,scan = "$linkmode,$pass" || - { test prog != "$linkmode" && test lib != "$linkmode"; }; then - test -n "$dlopen" && func_append dlfiles " $dlopen" - test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" - fi - - if test conv = "$pass"; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for '$lib'" - fi - # It is a libtool convenience library, so add in its objects. - func_append convenience " $ladir/$objdir/$old_library" - func_append old_convenience " $ladir/$objdir/$old_library" - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done - elif test prog != "$linkmode" && test lib != "$linkmode"; then - func_fatal_error "'$lib' is not a convenience library" - fi - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - if test -n "$old_library" && - { test yes = "$prefer_static_libs" || - test built,no = "$prefer_static_libs,$installed"; }; then - linklib=$old_library - else - for l in $old_library $library_names; do - linklib=$l - done - fi - if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for '$lib'" - fi - - # This library was specified with -dlopen. - if test dlopen = "$pass"; then - test -z "$libdir" \ - && func_fatal_error "cannot -dlopen a convenience library: '$lib'" - if test -z "$dlname" || - test yes != "$dlopen_support" || - test no = "$build_libtool_libs" - then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - func_append dlprefiles " $lib $dependency_libs" - else - func_append newdlfiles " $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of '$ladir'" - func_warning "passing it literally to the linker, although it might fail" - abs_ladir=$ladir - fi - ;; - esac - func_basename "$lib" - laname=$func_basename_result - - # Find the relevant object directory and library name. - if test yes = "$installed"; then - if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library '$lib' was moved." - dir=$ladir - absdir=$abs_ladir - libdir=$abs_ladir - else - dir=$lt_sysroot$libdir - absdir=$lt_sysroot$libdir - fi - test yes = "$hardcode_automatic" && avoidtemprpath=yes - else - if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir=$ladir - absdir=$abs_ladir - # Remove this search path later - func_append notinst_path " $abs_ladir" - else - dir=$ladir/$objdir - absdir=$abs_ladir/$objdir - # Remove this search path later - func_append notinst_path " $abs_ladir" - fi - fi # $installed = yes - func_stripname 'lib' '.la' "$laname" - name=$func_stripname_result - - # This library was specified with -dlpreopen. - if test dlpreopen = "$pass"; then - if test -z "$libdir" && test prog = "$linkmode"; then - func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" - fi - case $host in - # special handling for platforms with PE-DLLs. - *cygwin* | *mingw* | *cegcc* ) - # Linker will automatically link against shared library if both - # static and shared are present. Therefore, ensure we extract - # symbols from the import library if a shared library is present - # (otherwise, the dlopen module name will be incorrect). We do - # this by putting the import library name into $newdlprefiles. - # We recover the dlopen module name by 'saving' the la file - # name in a special purpose variable, and (later) extracting the - # dlname from the la file. - if test -n "$dlname"; then - func_tr_sh "$dir/$linklib" - eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" - func_append newdlprefiles " $dir/$linklib" - else - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - fi - ;; - * ) - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - func_append newdlprefiles " $dir/$dlname" - else - func_append newdlprefiles " $dir/$linklib" - fi - ;; - esac - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test lib = "$linkmode"; then - deplibs="$dir/$old_library $deplibs" - elif test prog,link = "$linkmode,$pass"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test prog = "$linkmode" && test link != "$pass"; then - func_append newlib_search_path " $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=false - if test no != "$link_all_deplibs" || test -z "$library_names" || - test no = "$build_libtool_libs"; then - linkalldeplibs=: - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - esac - # Need to link against all dependency_libs? - if $linkalldeplibs; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test prog,link = "$linkmode,$pass"; then - if test -n "$library_names" && - { { test no = "$prefer_static_libs" || - test built,yes = "$prefer_static_libs,$installed"; } || - test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then - # Make sure the rpath contains only unique directories. - case $temp_rpath: in - *"$absdir:"*) ;; - *) func_append temp_rpath "$absdir:" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if $alldeplibs && - { test pass_all = "$deplibs_check_method" || - { test yes = "$build_libtool_libs" && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - use_static_libs=$prefer_static_libs - if test built = "$use_static_libs" && test yes = "$installed"; then - use_static_libs=no - fi - if test -n "$library_names" && - { test no = "$use_static_libs" || test -z "$old_library"; }; then - case $host in - *cygwin* | *mingw* | *cegcc* | *os2*) - # No point in relinking DLLs because paths are not encoded - func_append notinst_deplibs " $lib" - need_relink=no - ;; - *) - if test no = "$installed"; then - func_append notinst_deplibs " $lib" - need_relink=yes - fi - ;; - esac - # This is a shared library - - # Warn about portability, can't link against -module's on some - # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule= - for dlpremoduletest in $dlprefiles; do - if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule=$dlpremoduletest - break - fi - done - if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then - echo - if test prog = "$linkmode"; then - $ECHO "*** Warning: Linking the executable $output against the loadable module" - else - $ECHO "*** Warning: Linking the shared library $output against the loadable module" - fi - $ECHO "*** $linklib is not portable!" - fi - if test lib = "$linkmode" && - test yes = "$hardcode_into_libs"; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - shift - realname=$1 - shift - libname=`eval "\\$ECHO \"$libname_spec\""` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname=$dlname - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw* | *cegcc* | *os2*) - func_arith $current - $age - major=$func_arith_result - versuffix=-$major - ;; - esac - eval soname=\"$soname_spec\" - else - soname=$realname - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot=$soname - func_basename "$soroot" - soname=$func_basename_result - func_stripname 'lib' '.dll' "$soname" - newlib=libimp-$func_stripname_result.a - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - func_verbose "extracting exported symbol list from '$soname'" - func_execute_cmds "$extract_expsyms_cmds" 'exit $?' - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for '$soname'" - func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test prog = "$linkmode" || test relink != "$opt_mode"; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test no = "$hardcode_direct"; then - add=$dir/$linklib - case $host in - *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; - *-*-sysv4*uw2*) add_dir=-L$dir ;; - *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir=-L$dir ;; - *-*-darwin* ) - # if the lib is a (non-dlopened) module then we cannot - # link against it, someone is ignoring the earlier warnings - if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null; then - if test "X$dlopenmodule" != "X$lib"; then - $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library"; then - echo - echo "*** And there doesn't seem to be a static archive available" - echo "*** The link will probably fail, sorry" - else - add=$dir/$old_library - fi - elif test -n "$old_library"; then - add=$dir/$old_library - fi - fi - esac - elif test no = "$hardcode_minus_L"; then - case $host in - *-*-sunos*) add_shlibpath=$dir ;; - esac - add_dir=-L$dir - add=-l$name - elif test no = "$hardcode_shlibpath_var"; then - add_shlibpath=$dir - add=-l$name - else - lib_linked=no - fi - ;; - relink) - if test yes = "$hardcode_direct" && - test no = "$hardcode_direct_absolute"; then - add=$dir/$linklib - elif test yes = "$hardcode_minus_L"; then - add_dir=-L$absdir - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add=-l$name - elif test yes = "$hardcode_shlibpath_var"; then - add_shlibpath=$dir - add=-l$name - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test yes != "$lib_linked"; then - func_fatal_configuration "unsupported hardcode properties" - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) func_append compile_shlibpath "$add_shlibpath:" ;; - esac - fi - if test prog = "$linkmode"; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test yes != "$hardcode_direct" && - test yes != "$hardcode_minus_L" && - test yes = "$hardcode_shlibpath_var"; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - fi - fi - fi - - if test prog = "$linkmode" || test relink = "$opt_mode"; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test yes = "$hardcode_direct" && - test no = "$hardcode_direct_absolute"; then - add=$libdir/$linklib - elif test yes = "$hardcode_minus_L"; then - add_dir=-L$libdir - add=-l$name - elif test yes = "$hardcode_shlibpath_var"; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - add=-l$name - elif test yes = "$hardcode_automatic"; then - if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib"; then - add=$inst_prefix_dir$libdir/$linklib - else - add=$libdir/$linklib - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir=-L$libdir - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add=-l$name - fi - - if test prog = "$linkmode"; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test prog = "$linkmode"; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test unsupported != "$hardcode_direct"; then - test -n "$old_library" && linklib=$old_library - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test yes = "$build_libtool_libs"; then - # Not a shared library - if test pass_all != "$deplibs_check_method"; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - echo - $ECHO "*** Warning: This system cannot link to static lib archive $lib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have." - if test yes = "$module"; then - echo "*** But as you try to build a module library, libtool will still create " - echo "*** a static module, that should work as long as the dlopening application" - echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using 'nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** 'nm' from GNU binutils and a full rebuild may help." - fi - if test no = "$build_old_libs"; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test lib = "$linkmode"; then - if test -n "$dependency_libs" && - { test yes != "$hardcode_into_libs" || - test yes = "$build_old_libs" || - test yes = "$link_static"; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) func_stripname '-R' '' "$libdir" - temp_xrpath=$func_stripname_result - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) func_append xrpath " $temp_xrpath";; - esac;; - *) func_append temp_deplibs " $libdir";; - esac - done - dependency_libs=$temp_deplibs - fi - - func_append newlib_search_path " $absdir" - # Link against this library - test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result";; - *) func_resolve_sysroot "$deplib" ;; - esac - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $func_resolve_sysroot_result "*) - func_append specialdeplibs " $func_resolve_sysroot_result" ;; - esac - fi - func_append tmp_libs " $func_resolve_sysroot_result" - done - - if test no != "$link_all_deplibs"; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - path= - case $deplib in - -L*) path=$deplib ;; - *.la) - func_resolve_sysroot "$deplib" - deplib=$func_resolve_sysroot_result - func_dirname "$deplib" "" "." - dir=$func_dirname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of '$dir'" - absdir=$dir - fi - ;; - esac - if $GREP "^installed=no" $deplib > /dev/null; then - case $host in - *-*-darwin*) - depdepl= - eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names"; then - for tmp in $deplibrary_names; do - depdepl=$tmp - done - if test -f "$absdir/$objdir/$depdepl"; then - depdepl=$absdir/$objdir/$depdepl - darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - if test -z "$darwin_install_name"; then - darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - fi - func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" - func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" - path= - fi - fi - ;; - *) - path=-L$absdir/$objdir - ;; - esac - else - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - test -z "$libdir" && \ - func_fatal_error "'$deplib' is not a valid libtool archive" - test "$absdir" != "$libdir" && \ - func_warning "'$deplib' seems to be moved" - - path=-L$absdir - fi - ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$path $deplibs" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - if test link = "$pass"; then - if test prog = "$linkmode"; then - compile_deplibs="$new_inherited_linker_flags $compile_deplibs" - finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" - else - compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - fi - fi - dependency_libs=$newdependency_libs - if test dlpreopen = "$pass"; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test dlopen != "$pass"; then - test conv = "$pass" || { - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) func_append lib_search_path " $dir" ;; - esac - done - newlib_search_path= - } - - if test prog,link = "$linkmode,$pass"; then - vars="compile_deplibs finalize_deplibs" - else - vars=deplibs - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) func_append tmp_libs " $deplib" ;; - esac - ;; - *) func_append tmp_libs " $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - - # Add Sun CC postdeps if required: - test CXX = "$tagname" && { - case $host_os in - linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C++ 5.9 - func_suncc_cstd_abi - - if test no != "$suncc_use_cstd_abi"; then - func_append postdeps ' -library=Cstd -library=Crun' - fi - ;; - esac - ;; - - solaris*) - func_cc_basename "$CC" - case $func_cc_basename_result in - CC* | sunCC*) - func_suncc_cstd_abi - - if test no != "$suncc_use_cstd_abi"; then - func_append postdeps ' -library=Cstd -library=Crun' - fi - ;; - esac - ;; - esac - } - - # Last step: remove runtime libs from dependency_libs - # (they stay in deplibs) - tmp_libs= - for i in $dependency_libs; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i= - ;; - esac - if test -n "$i"; then - func_append tmp_libs " $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test prog = "$linkmode"; then - dlfiles=$newdlfiles - fi - if test prog = "$linkmode" || test lib = "$linkmode"; then - dlprefiles=$newdlprefiles - fi - - case $linkmode in - oldlib) - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then - func_warning "'-dlopen' is ignored for archives" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "'-l' and '-L' are ignored for archives" ;; - esac - - test -n "$rpath" && \ - func_warning "'-rpath' is ignored for archives" - - test -n "$xrpath" && \ - func_warning "'-R' is ignored for archives" - - test -n "$vinfo" && \ - func_warning "'-version-info/-version-number' is ignored for archives" - - test -n "$release" && \ - func_warning "'-release' is ignored for archives" - - test -n "$export_symbols$export_symbols_regex" && \ - func_warning "'-export-symbols' is ignored for archives" - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs=$output - func_append objs "$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form 'libNAME.la'. - case $outputname in - lib*) - func_stripname 'lib' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - ;; - *) - test no = "$module" \ - && func_fatal_help "libtool library '$output' must begin with 'lib'" - - if test no != "$need_lib_prefix"; then - # Add the "lib" prefix for modules if required - func_stripname '' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - else - func_stripname '' '.la' "$outputname" - libname=$func_stripname_result - fi - ;; - esac - - if test -n "$objs"; then - if test pass_all != "$deplibs_check_method"; then - func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" - else - echo - $ECHO "*** Warning: Linking the shared library $output against the non-libtool" - $ECHO "*** objects $objs is not portable!" - func_append libobjs " $objs" - fi - fi - - test no = "$dlself" \ - || func_warning "'-dlopen self' is ignored for libtool libraries" - - set dummy $rpath - shift - test 1 -lt "$#" \ - && func_warning "ignoring multiple '-rpath's for a libtool library" - - install_libdir=$1 - - oldlibs= - if test -z "$rpath"; then - if test yes = "$build_libtool_libs"; then - # Building a libtool convenience library. - # Some compilers have problems with a '.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - test -n "$vinfo" && \ - func_warning "'-version-info/-version-number' is ignored for convenience libraries" - - test -n "$release" && \ - func_warning "'-release' is ignored for convenience libraries" - else - - # Parse the version information argument. - save_ifs=$IFS; IFS=: - set dummy $vinfo 0 0 0 - shift - IFS=$save_ifs - - test -n "$7" && \ - func_fatal_help "too many parameters to '-version-info'" - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major=$1 - number_minor=$2 - number_revision=$3 - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # that has an extra 1 added just for fun - # - case $version_type in - # correct linux to gnu/linux during the next big refactor - darwin|freebsd-elf|linux|osf|windows|none) - func_arith $number_major + $number_minor - current=$func_arith_result - age=$number_minor - revision=$number_revision - ;; - freebsd-aout|qnx|sunos) - current=$number_major - revision=$number_minor - age=0 - ;; - irix|nonstopux) - func_arith $number_major + $number_minor - current=$func_arith_result - age=$number_minor - revision=$number_minor - lt_irix_increment=no - ;; - *) - func_fatal_configuration "$modename: unknown library version type '$version_type'" - ;; - esac - ;; - no) - current=$1 - revision=$2 - age=$3 - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "CURRENT '$current' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" - ;; - esac - - case $revision in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "REVISION '$revision' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" - ;; - esac - - case $age in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "AGE '$age' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" - ;; - esac - - if test "$age" -gt "$current"; then - func_error "AGE '$age' is greater than the current interface number '$current'" - func_fatal_error "'$vinfo' is not valid version information" - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - func_arith $current - $age - major=.$func_arith_result - versuffix=$major.$age.$revision - # Darwin ld doesn't like 0 for these options... - func_arith $current + 1 - minor_current=$func_arith_result - xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - # On Darwin other compilers - case $CC in - nagfor*) - verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" - ;; - *) - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - esac - ;; - - freebsd-aout) - major=.$current - versuffix=.$current.$revision - ;; - - freebsd-elf) - func_arith $current - $age - major=.$func_arith_result - versuffix=$major.$age.$revision - ;; - - irix | nonstopux) - if test no = "$lt_irix_increment"; then - func_arith $current - $age - else - func_arith $current - $age + 1 - fi - major=$func_arith_result - - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring=$verstring_prefix$major.$revision - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test 0 -ne "$loop"; do - func_arith $revision - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring=$verstring_prefix$major.$iface:$verstring - done - - # Before this point, $major must not contain '.'. - major=.$major - versuffix=$major.$revision - ;; - - linux) # correct to gnu/linux during the next big refactor - func_arith $current - $age - major=.$func_arith_result - versuffix=$major.$age.$revision - ;; - - osf) - func_arith $current - $age - major=.$func_arith_result - versuffix=.$current.$age.$revision - verstring=$current.$age.$revision - - # Add in all the interfaces that we are compatible with. - loop=$age - while test 0 -ne "$loop"; do - func_arith $current - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring=$verstring:$iface.0 - done - - # Make executables depend on our current version. - func_append verstring ":$current.0" - ;; - - qnx) - major=.$current - versuffix=.$current - ;; - - sco) - major=.$current - versuffix=.$current - ;; - - sunos) - major=.$current - versuffix=.$current.$revision - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 file systems. - func_arith $current - $age - major=$func_arith_result - versuffix=-$major - ;; - - *) - func_fatal_configuration "unknown library version type '$version_type'" - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring=0.0 - ;; - esac - if test no = "$need_version"; then - versuffix= - else - versuffix=.0.0 - fi - fi - - # Remove version info from name if versioning should be avoided - if test yes,no = "$avoid_version,$need_version"; then - major= - versuffix= - verstring= - fi - - # Check to see if the archive will have undefined symbols. - if test yes = "$allow_undefined"; then - if test unsupported = "$allow_undefined_flag"; then - if test yes = "$build_old_libs"; then - func_warning "undefined symbols not allowed in $host shared libraries; building static only" - build_libtool_libs=no - else - func_fatal_error "can't build $host shared library unless -no-undefined is specified" - fi - fi - else - # Don't allow undefined symbols. - allow_undefined_flag=$no_undefined_flag - fi - - fi - - func_generate_dlsyms "$libname" "$libname" : - func_append libobjs " $symfileobj" - test " " = "$libobjs" && libobjs= - - if test relink != "$opt_mode"; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$ECHO "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext | *.gcno) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) - if test -n "$precious_files_regex"; then - if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - fi - func_append removelist " $p" - ;; - *) ;; - esac - done - test -n "$removelist" && \ - func_show_eval "${RM}r \$removelist" - fi - - # Now set the variables for building old libraries. - if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then - func_append oldlibs " $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - #for path in $notinst_path; do - # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` - # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` - # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` - #done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - func_replace_sysroot "$libdir" - func_append temp_xrpath " -R$func_replace_sysroot_result" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles=$dlfiles - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) func_append dlfiles " $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles=$dlprefiles - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) func_append dlprefiles " $lib" ;; - esac - done - - if test yes = "$build_libtool_libs"; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - func_append deplibs " System.ltframework" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test yes = "$build_libtool_need_lc"; then - func_append deplibs " -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release= - versuffix= - major= - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $opt_dry_run || $RM conftest.c - cat > conftest.c </dev/null` - $nocaseglob - else - potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` - fi - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null | - $GREP " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib=$potent_lib - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | $SED 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; - *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | - $SED -e 10q | - $EGREP "$file_magic_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib= - break 2 - fi - done - done - fi - if test -n "$a_deplib"; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib"; then - $ECHO "*** with $libname but no candidates were found. (...for file magic test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a file magic. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - for a_deplib in $deplibs; do - case $a_deplib in - -l*) - func_stripname -l '' "$a_deplib" - name=$func_stripname_result - if test yes = "$allow_libtool_libs_with_static_runtimes"; then - case " $predeps $postdeps " in - *" $a_deplib "*) - func_append newdeplibs " $a_deplib" - a_deplib= - ;; - esac - fi - if test -n "$a_deplib"; then - libname=`eval "\\$ECHO \"$libname_spec\""` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib=$potent_lib # see symlink-check above in file_magic test - if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ - $EGREP "$match_pattern_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib= - break 2 - fi - done - done - fi - if test -n "$a_deplib"; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib"; then - $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a regex pattern. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs= - tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test yes = "$allow_libtool_libs_with_static_runtimes"; then - for i in $predeps $postdeps; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` - done - fi - case $tmp_deplibs in - *[!\ \ ]*) - echo - if test none = "$deplibs_check_method"; then - echo "*** Warning: inter-library dependencies are not supported in this platform." - else - echo "*** Warning: inter-library dependencies are not known to be supported." - fi - echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - ;; - esac - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library with the System framework - newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - if test yes = "$droppeddeps"; then - if test yes = "$module"; then - echo - echo "*** Warning: libtool could not satisfy all declared inter-library" - $ECHO "*** dependencies of module $libname. Therefore, libtool will create" - echo "*** a static module, that should work as long as the dlopening" - echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using 'nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** 'nm' from GNU binutils and a full rebuild may help." - fi - if test no = "$build_old_libs"; then - oldlibs=$output_objdir/$libname.$libext - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - echo "*** The inter-library dependencies that have been dropped here will be" - echo "*** automatically added whenever a program is linked with this library" - echo "*** or is declared to -dlopen it." - - if test no = "$allow_undefined"; then - echo - echo "*** Since this library must not contain undefined symbols," - echo "*** because either the platform does not support them or" - echo "*** it was explicitly requested with -no-undefined," - echo "*** libtool will only create a static version of it." - if test no = "$build_old_libs"; then - oldlibs=$output_objdir/$libname.$libext - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - case $host in - *-*-darwin*) - newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - deplibs=$new_libs - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test yes = "$build_libtool_libs"; then - # Remove $wl instances when linking with ld. - # FIXME: should test the right _cmds variable. - case $archive_cmds in - *\$LD\ *) wl= ;; - esac - if test yes = "$hardcode_into_libs"; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath=$finalize_rpath - test relink = "$opt_mode" || rpath=$compile_rpath$rpath - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - func_replace_sysroot "$libdir" - libdir=$func_replace_sysroot_result - if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append dep_rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs - eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath=$finalize_shlibpath - test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext_cmds\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - shift - realname=$1 - shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname=$realname - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib=$output_objdir/$realname - linknames= - for link - do - func_append linknames " $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` - test "X$libobjs" = "X " && libobjs= - - delfiles= - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols=$output_objdir/$libname.uexp - func_append delfiles " $export_symbols" - fi - - orig_export_symbols= - case $host_os in - cygwin* | mingw* | cegcc*) - if test -n "$export_symbols" && test -z "$export_symbols_regex"; then - # exporting using user supplied symfile - func_dll_def_p "$export_symbols" || { - # and it's NOT already a .def file. Must figure out - # which of the given symbols are data symbols and tag - # them as such. So, trigger use of export_symbols_cmds. - # export_symbols gets reassigned inside the "prepare - # the list of exported symbols" if statement, so the - # include_expsyms logic still works. - orig_export_symbols=$export_symbols - export_symbols= - always_export_symbols=yes - } - fi - ;; - esac - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for '$libname.la'" - export_symbols=$output_objdir/$libname.exp - $opt_dry_run || $RM $export_symbols - cmds=$export_symbols_cmds - save_ifs=$IFS; IFS='~' - for cmd1 in $cmds; do - IFS=$save_ifs - # Take the normal branch if the nm_file_list_spec branch - # doesn't work or if tool conversion is not needed. - case $nm_file_list_spec~$to_tool_file_cmd in - *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) - try_normal_branch=yes - eval cmd=\"$cmd1\" - func_len " $cmd" - len=$func_len_result - ;; - *) - try_normal_branch=no - ;; - esac - if test yes = "$try_normal_branch" \ - && { test "$len" -lt "$max_cmd_len" \ - || test "$max_cmd_len" -le -1; } - then - func_show_eval "$cmd" 'exit $?' - skipped_export=false - elif test -n "$nm_file_list_spec"; then - func_basename "$output" - output_la=$func_basename_result - save_libobjs=$libobjs - save_output=$output - output=$output_objdir/$output_la.nm - func_to_tool_file "$output" - libobjs=$nm_file_list_spec$func_to_tool_file_result - func_append delfiles " $output" - func_verbose "creating $NM input file list: $output" - for obj in $save_libobjs; do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > "$output" - eval cmd=\"$cmd1\" - func_show_eval "$cmd" 'exit $?' - output=$save_output - libobjs=$save_libobjs - skipped_export=false - else - # The command line is too long to execute in one step. - func_verbose "using reloadable object file for export list..." - skipped_export=: - # Break out early, otherwise skipped_export may be - # set to false by a later but shorter cmd. - break - fi - done - IFS=$save_ifs - if test -n "$export_symbols_regex" && test : != "$skipped_export"; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols=$export_symbols - test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test : != "$skipped_export" && test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for '$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands, which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - func_append tmp_deplibs " $test_deplib" - ;; - esac - done - deplibs=$tmp_deplibs - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec" && - test yes = "$compiler_needs_object" && - test -z "$libobjs"; then - # extract the archives, so we have objects to list. - # TODO: could optimize this to just extract one archive. - whole_archive_flag_spec= - fi - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - else - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - fi - - if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - func_append linker_flags " $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test relink = "$opt_mode"; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test yes = "$module" && test -n "$module_cmds"; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test : != "$skipped_export" && - func_len " $test_cmds" && - len=$func_len_result && - test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise - # or, if using GNU ld and skipped_export is not :, use a linker - # script. - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - func_basename "$output" - output_la=$func_basename_result - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - last_robj= - k=1 - - if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then - output=$output_objdir/$output_la.lnkscript - func_verbose "creating GNU ld script: $output" - echo 'INPUT (' > $output - for obj in $save_libobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - echo ')' >> $output - func_append delfiles " $output" - func_to_tool_file "$output" - output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then - output=$output_objdir/$output_la.lnk - func_verbose "creating linker input file list: $output" - : > $output - set x $save_libobjs - shift - firstobj= - if test yes = "$compiler_needs_object"; then - firstobj="$1 " - shift - fi - for obj - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - func_append delfiles " $output" - func_to_tool_file "$output" - output=$firstobj\"$file_list_spec$func_to_tool_file_result\" - else - if test -n "$save_libobjs"; then - func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-$k.$objext - eval test_cmds=\"$reload_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - if test -z "$objlist" || - test "$len" -lt "$max_cmd_len"; then - func_append objlist " $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test 1 -eq "$k"; then - # The first file doesn't have a previous command to add. - reload_objs=$objlist - eval concat_cmds=\"$reload_cmds\" - else - # All subsequent reloadable object files will link in - # the last one created. - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" - fi - last_robj=$output_objdir/$output_la-$k.$objext - func_arith $k + 1 - k=$func_arith_result - output=$output_objdir/$output_la-$k.$objext - objlist=" $obj" - func_len " $last_robj" - func_arith $len0 + $func_len_result - len=$func_arith_result - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds$reload_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" - fi - func_append delfiles " $output" - - else - output= - fi - - ${skipped_export-false} && { - func_verbose "generating symbol list for '$libname.la'" - export_symbols=$output_objdir/$libname.exp - $opt_dry_run || $RM $export_symbols - libobjs=$output - # Append the command to create the export file. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" - fi - } - - test -n "$save_libobjs" && - func_verbose "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs=$IFS; IFS='~' - for cmd in $concat_cmds; do - IFS=$save_ifs - $opt_quiet || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS=$save_ifs - - if test -n "$export_symbols_regex" && ${skipped_export-false}; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - - ${skipped_export-false} && { - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols=$export_symbols - test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for '$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands, which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - } - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test yes = "$module" && test -n "$module_cmds"; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - fi - - if test -n "$delfiles"; then - # Append the command to remove temporary files to $cmds. - eval cmds=\"\$cmds~\$RM $delfiles\" - fi - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - - save_ifs=$IFS; IFS='~' - for cmd in $cmds; do - IFS=$sp$nl - eval cmd=\"$cmd\" - IFS=$save_ifs - $opt_quiet || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS=$save_ifs - - # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? - - if test -n "$convenience"; then - if test -z "$whole_archive_flag_spec"; then - func_show_eval '${RM}r "$gentop"' - fi - fi - - exit $EXIT_SUCCESS - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test yes = "$module" || test yes = "$export_dynamic"; then - # On all known operating systems, these are identical. - dlname=$soname - fi - fi - ;; - - obj) - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then - func_warning "'-dlopen' is ignored for objects" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "'-l' and '-L' are ignored for objects" ;; - esac - - test -n "$rpath" && \ - func_warning "'-rpath' is ignored for objects" - - test -n "$xrpath" && \ - func_warning "'-R' is ignored for objects" - - test -n "$vinfo" && \ - func_warning "'-version-info' is ignored for objects" - - test -n "$release" && \ - func_warning "'-release' is ignored for objects" - - case $output in - *.lo) - test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object '$output' from non-libtool objects" - - libobj=$output - func_lo2o "$libobj" - obj=$func_lo2o_result - ;; - *) - libobj= - obj=$output - ;; - esac - - # Delete the old objects. - $opt_dry_run || $RM $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # if reload_cmds runs $LD directly, get rid of -Wl from - # whole_archive_flag_spec and hope we can get by with turning comma - # into space. - case $reload_cmds in - *\$LD[\ \$]*) wl= ;; - esac - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` - reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags - else - gentop=$output_objdir/${obj}x - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - reload_conv_objs="$reload_objs $func_extract_archives_result" - fi - fi - - # If we're not building shared, we need to use non_pic_objs - test yes = "$build_libtool_libs" || libobjs=$non_pic_objects - - # Create the old-style object. - reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs - - output=$obj - func_execute_cmds "$reload_cmds" 'exit $?' - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - fi - - test yes = "$build_libtool_libs" || { - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? - exit $EXIT_SUCCESS - } - - if test -n "$pic_flag" || test default != "$pic_mode"; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output=$libobj - func_execute_cmds "$reload_cmds" 'exit $?' - fi - - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - ;; - - prog) - case $host in - *cygwin*) func_stripname '' '.exe' "$output" - output=$func_stripname_result.exe;; - esac - test -n "$vinfo" && \ - func_warning "'-version-info' is ignored for programs" - - test -n "$release" && \ - func_warning "'-release' is ignored for programs" - - $preload \ - && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ - && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - case $host in - *-*-darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - # But is supposedly fixed on 10.4 or later (yay!). - if test CXX = "$tagname"; then - case ${MACOSX_DEPLOYMENT_TARGET-10.0} in - 10.[0123]) - func_append compile_command " $wl-bind_at_load" - func_append finalize_command " $wl-bind_at_load" - ;; - esac - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $compile_deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $compile_deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - compile_deplibs=$new_libs - - - func_append compile_command " $compile_deplibs" - func_append finalize_command " $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$libdir:"*) ;; - ::) dllsearchpath=$libdir;; - *) func_append dllsearchpath ":$libdir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath=$rpath - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) func_append finalize_perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath=$rpath - - if test -n "$libobjs" && test yes = "$build_old_libs"; then - # Transform all the library objects into standard objects. - compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - fi - - func_generate_dlsyms "$outputname" "@PROGRAM@" false - - # template prelinking step - if test -n "$prelink_cmds"; then - func_execute_cmds "$prelink_cmds" 'exit $?' - fi - - wrappers_required=: - case $host in - *cegcc* | *mingw32ce*) - # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=false - ;; - *cygwin* | *mingw* ) - test yes = "$build_libtool_libs" || wrappers_required=false - ;; - *) - if test no = "$need_relink" || test yes != "$build_libtool_libs"; then - wrappers_required=false - fi - ;; - esac - $wrappers_required || { - # Replace the output file specification. - compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command=$compile_command$compile_rpath - - # We have no uninstalled library dependencies, so finalize right now. - exit_status=0 - func_show_eval "$link_command" 'exit_status=$?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Delete the generated files. - if test -f "$output_objdir/${outputname}S.$objext"; then - func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' - fi - - exit $exit_status - } - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - func_append rpath "$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test yes = "$no_install"; then - # We don't need to create a wrapper script. - link_command=$compile_var$compile_command$compile_rpath - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $opt_dry_run || $RM $output - # Link the executable and exit - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - exit $EXIT_SUCCESS - fi - - case $hardcode_action,$fast_install in - relink,*) - # Fast installation is not supported - link_command=$compile_var$compile_command$compile_rpath - relink_command=$finalize_var$finalize_command$finalize_rpath - - func_warning "this platform does not like uninstalled shared libraries" - func_warning "'$output' will be relinked during installation" - ;; - *,yes) - link_command=$finalize_var$compile_command$finalize_rpath - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - ;; - *,no) - link_command=$compile_var$compile_command$compile_rpath - relink_command=$finalize_var$finalize_command$finalize_rpath - ;; - *,needless) - link_command=$finalize_var$compile_command$finalize_rpath - relink_command= - ;; - esac - - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname - - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output_objdir/$outputname" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Now create the wrapper script. - func_verbose "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - fi - - # Only actually do things if not in dry run mode. - $opt_dry_run || { - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) func_stripname '' '.exe' "$output" - output=$func_stripname_result ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - func_stripname '' '.exe' "$outputname" - outputname=$func_stripname_result ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - func_dirname_and_basename "$output" "" "." - output_name=$func_basename_result - output_path=$func_dirname_result - cwrappersource=$output_path/$objdir/lt-$output_name.c - cwrapper=$output_path/$output_name.exe - $RM $cwrappersource $cwrapper - trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 - - func_emit_cwrapperexe_src > $cwrappersource - - # The wrapper executable is built using the $host compiler, - # because it contains $host paths and files. If cross- - # compiling, it, like the target executable, must be - # executed on the $host or under an emulation environment. - $opt_dry_run || { - $LTCC $LTCFLAGS -o $cwrapper $cwrappersource - $STRIP $cwrapper - } - - # Now, create the wrapper script for func_source use: - func_ltwrapper_scriptname $cwrapper - $RM $func_ltwrapper_scriptname_result - trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 - $opt_dry_run || { - # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host"; then - $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result - else - func_emit_wrapper no > $func_ltwrapper_scriptname_result - fi - } - ;; - * ) - $RM $output - trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 - - func_emit_wrapper no > $output - chmod +x $output - ;; - esac - } - exit $EXIT_SUCCESS - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - case $build_libtool_libs in - convenience) - oldobjs="$libobjs_save $symfileobj" - addlibs=$convenience - build_libtool_libs=no - ;; - module) - oldobjs=$libobjs_save - addlibs=$old_convenience - build_libtool_libs=no - ;; - *) - oldobjs="$old_deplibs $non_pic_objects" - $preload && test -f "$symfileobj" \ - && func_append oldobjs " $symfileobj" - addlibs=$old_convenience - ;; - esac - - if test -n "$addlibs"; then - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - - func_extract_archives $gentop $addlibs - func_append oldobjs " $func_extract_archives_result" - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then - cmds=$old_archive_from_new_cmds - else - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append oldobjs " $func_extract_archives_result" - fi - - # POSIX demands no paths to be encoded in archives. We have - # to avoid creating archives with duplicate basenames if we - # might have to extract them afterwards, e.g., when creating a - # static archive out of a convenience library, or when linking - # the entirety of a libtool archive into another (currently - # not supported by libtool). - if (for obj in $oldobjs - do - func_basename "$obj" - $ECHO "$func_basename_result" - done | sort | sort -uc >/dev/null 2>&1); then - : - else - echo "copying selected object files to avoid basename conflicts..." - gentop=$output_objdir/${outputname}x - func_append generated " $gentop" - func_mkdir_p "$gentop" - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs - do - func_basename "$obj" - objbase=$func_basename_result - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[\ /]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - func_arith $counter + 1 - counter=$func_arith_result - case " $oldobjs " in - *[\ /]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - func_append oldobjs " $gentop/$newobj" - ;; - *) func_append oldobjs " $obj" ;; - esac - done - fi - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - eval cmds=\"$old_archive_cmds\" - - func_len " $cmds" - len=$func_len_result - if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - elif test -n "$archiver_list_spec"; then - func_verbose "using command file archive linking..." - for obj in $oldobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > $output_objdir/$libname.libcmd - func_to_tool_file "$output_objdir/$libname.libcmd" - oldobjs=" $archiver_list_spec$func_to_tool_file_result" - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - func_verbose "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - oldobjs= - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - eval test_cmds=\"$old_archive_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - for obj in $save_oldobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - func_append objlist " $obj" - if test "$len" -lt "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj"; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" - objlist= - len=$len0 - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test -z "$oldobjs"; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - func_execute_cmds "$cmds" 'exit $?' - done - - test -n "$generated" && \ - func_show_eval "${RM}r$generated" - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test yes = "$build_old_libs" && old_library=$libname.$libext - func_verbose "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test yes = "$hardcode_automatic"; then - relink_command= - fi - - # Only create the output if not a dry run. - $opt_dry_run || { - for installed in no yes; do - if test yes = "$installed"; then - if test -z "$install_libdir"; then - break - fi - output=$output_objdir/${outputname}i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - func_basename "$deplib" - name=$func_basename_result - func_resolve_sysroot "$deplib" - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` - test -z "$libdir" && \ - func_fatal_error "'$deplib' is not a valid libtool archive" - func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" - ;; - -L*) - func_stripname -L '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -L$func_replace_sysroot_result" - ;; - -R*) - func_stripname -R '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -R$func_replace_sysroot_result" - ;; - *) func_append newdependency_libs " $deplib" ;; - esac - done - dependency_libs=$newdependency_libs - newdlfiles= - - for lib in $dlfiles; do - case $lib in - *.la) - func_basename "$lib" - name=$func_basename_result - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "'$lib' is not a valid libtool archive" - func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" - ;; - *) func_append newdlfiles " $lib" ;; - esac - done - dlfiles=$newdlfiles - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - *.la) - # Only pass preopened files to the pseudo-archive (for - # eventual linking with the app. that links it) if we - # didn't already link the preopened objects directly into - # the library: - func_basename "$lib" - name=$func_basename_result - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "'$lib' is not a valid libtool archive" - func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" - ;; - esac - done - dlprefiles=$newdlprefiles - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlfiles " $abs" - done - dlfiles=$newdlfiles - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlprefiles " $abs" - done - dlprefiles=$newdlprefiles - fi - $RM $output - # place dlname in correct position for cygwin - # In fact, it would be nice if we could use this code for all target - # systems that can't hard-code library paths into their executables - # and that have no shared library path variable independent of PATH, - # but it turns out we can't easily determine that from inspecting - # libtool variables, so we have to hard-code the OSs to which it - # applies here; at the moment, that means platforms that use the PE - # object format with DLL files. See the long comment at the top of - # tests/bindir.at for full details. - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) - # If a -bindir argument was supplied, place the dll there. - if test -n "$bindir"; then - func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result/$dlname - else - # Otherwise fall back on heuristic. - tdlname=../bin/$dlname - fi - ;; - esac - $ECHO > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE) $VERSION -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Linker flags that cannot go in dependency_libs. -inherited_linker_flags='$new_inherited_linker_flags' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Names of additional weak libraries provided by this library -weak_library_names='$weak_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test no,yes = "$installed,$need_relink"; then - $ECHO >> $output "\ -relink_command=\"$relink_command\"" - fi - done - } - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' - ;; - esac - exit $EXIT_SUCCESS -} - -if test link = "$opt_mode" || test relink = "$opt_mode"; then - func_mode_link ${1+"$@"} -fi - - -# func_mode_uninstall arg... -func_mode_uninstall () -{ - $debug_cmd - - RM=$nonopt - files= - rmforce=false - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic=$magic - - for arg - do - case $arg in - -f) func_append RM " $arg"; rmforce=: ;; - -*) func_append RM " $arg" ;; - *) func_append files " $arg" ;; - esac - done - - test -z "$RM" && \ - func_fatal_help "you must specify an RM program" - - rmdirs= - - for file in $files; do - func_dirname "$file" "" "." - dir=$func_dirname_result - if test . = "$dir"; then - odir=$objdir - else - odir=$dir/$objdir - fi - func_basename "$file" - name=$func_basename_result - test uninstall = "$opt_mode" && odir=$dir - - # Remember odir for removal later, being careful to avoid duplicates - if test clean = "$opt_mode"; then - case " $rmdirs " in - *" $odir "*) ;; - *) func_append rmdirs " $odir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if { test -L "$file"; } >/dev/null 2>&1 || - { test -h "$file"; } >/dev/null 2>&1 || - test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif $rmforce; then - continue - fi - - rmfiles=$file - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if func_lalib_p "$file"; then - func_source $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - func_append rmfiles " $odir/$n" - done - test -n "$old_library" && func_append rmfiles " $odir/$old_library" - - case $opt_mode in - clean) - case " $library_names " in - *" $dlname "*) ;; - *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; - esac - test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" - ;; - uninstall) - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' - fi - # FIXME: should reinstall the best remaining shared library. - ;; - esac - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if func_lalib_p "$file"; then - - # Read the .lo file - func_source $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" && test none != "$pic_object"; then - func_append rmfiles " $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && test none != "$non_pic_object"; then - func_append rmfiles " $dir/$non_pic_object" - fi - fi - ;; - - *) - if test clean = "$opt_mode"; then - noexename=$name - case $file in - *.exe) - func_stripname '' '.exe' "$file" - file=$func_stripname_result - func_stripname '' '.exe' "$name" - noexename=$func_stripname_result - # $file with .exe has already been added to rmfiles, - # add $file without .exe - func_append rmfiles " $file" - ;; - esac - # Do a test to see if this is a libtool program. - if func_ltwrapper_p "$file"; then - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - relink_command= - func_source $func_ltwrapper_scriptname_result - func_append rmfiles " $func_ltwrapper_scriptname_result" - else - relink_command= - func_source $dir/$noexename - fi - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.$objext" - if test yes = "$fast_install" && test -n "$relink_command"; then - func_append rmfiles " $odir/lt-$name" - fi - if test "X$noexename" != "X$name"; then - func_append rmfiles " $odir/lt-$noexename.c" - fi - fi - fi - ;; - esac - func_show_eval "$RM $rmfiles" 'exit_status=1' - done - - # Try to remove the $objdir's in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - func_show_eval "rmdir $dir >/dev/null 2>&1" - fi - done - - exit $exit_status -} - -if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then - func_mode_uninstall ${1+"$@"} -fi - -test -z "$opt_mode" && { - help=$generic_help - func_fatal_help "you must specify a MODE" -} - -test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode '$opt_mode'" - -if test -n "$exec_cmd"; then - eval exec "$exec_cmd" - exit $EXIT_FAILURE -fi - -exit $exit_status - - -# The TAGs below are defined such that we never get into a situation -# where we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -build_libtool_libs=no -build_old_libs=yes -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/deps/ngtcp2/ngtcp2/third-party/libev/stamp-h1 b/deps/ngtcp2/ngtcp2/third-party/libev/stamp-h1 deleted file mode 100644 index 4547fe1b5efa99..00000000000000 --- a/deps/ngtcp2/ngtcp2/third-party/libev/stamp-h1 +++ /dev/null @@ -1 +0,0 @@ -timestamp for config.h diff --git a/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/example.c b/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/example.c index c2ba4a8c1f0ed0..8a2bf1d36bd587 100644 --- a/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/example.c +++ b/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/example.c @@ -333,7 +333,7 @@ static const MunitSuite test_suite = { * about µnit requires it. */ #include -int main(int argc, char *argv[MUNIT_ARRAY_PARAM(argc + 1)]) { +int main(int argc, char *argv[]) { /* Finally, we'll actually run our test suite! That second argument * is the user_data parameter which will be passed either to the * test or (if provided) the fixture setup function. */ diff --git a/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munit.c b/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munit.c index 0cd168151d00f2..c5faec09b11162 100644 --- a/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munit.c +++ b/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munit.c @@ -856,23 +856,18 @@ static psnip_uint64_t munit_clock_get_elapsed(struct PsnipClockTimespec *start, #if defined(_OPENMP) # define ATOMIC_UINT32_T uint32_t -# define ATOMIC_UINT32_INIT(x) (x) #elif defined(HAVE_STDATOMIC) # include # define ATOMIC_UINT32_T _Atomic uint32_t -# define ATOMIC_UINT32_INIT(x) ATOMIC_VAR_INIT(x) #elif defined(HAVE_CLANG_ATOMICS) # define ATOMIC_UINT32_T _Atomic uint32_t -# define ATOMIC_UINT32_INIT(x) (x) #elif defined(_WIN32) # define ATOMIC_UINT32_T volatile LONG -# define ATOMIC_UINT32_INIT(x) (x) #else # define ATOMIC_UINT32_T volatile uint32_t -# define ATOMIC_UINT32_INIT(x) (x) #endif -static ATOMIC_UINT32_T munit_rand_state = ATOMIC_UINT32_INIT(42); +static ATOMIC_UINT32_T munit_rand_state = 42; #if defined(_OPENMP) static inline void munit_atomic_store(ATOMIC_UINT32_T *dest, diff --git a/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munit.h b/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munit.h index a191758daf2979..e78a4801216b37 100644 --- a/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munit.h +++ b/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munit.h @@ -308,8 +308,8 @@ void munit_errorf_ex(const char *filename, int line, const char *format, ...); #include #define munit_assert_string_equal(a, b) \ do { \ - const char *munit_tmp_a_ = a; \ - const char *munit_tmp_b_ = b; \ + const char *munit_tmp_a_ = (a); \ + const char *munit_tmp_b_ = (b); \ if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) != 0)) { \ munit_hexdump_diff(stderr, munit_tmp_a_, strlen(munit_tmp_a_), \ munit_tmp_b_, strlen(munit_tmp_b_)); \ @@ -321,8 +321,8 @@ void munit_errorf_ex(const char *filename, int line, const char *format, ...); #define munit_assert_string_not_equal(a, b) \ do { \ - const char *munit_tmp_a_ = a; \ - const char *munit_tmp_b_ = b; \ + const char *munit_tmp_a_ = (a); \ + const char *munit_tmp_b_ = (b); \ if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) == 0)) { \ munit_errorf("assertion failed: string %s != %s (\"%s\" == \"%s\")", #a, \ #b, munit_tmp_a_, munit_tmp_b_); \ diff --git a/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munitxx.h b/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munitxx.h index dd4478579b35ea..8f9d7830c9c310 100644 --- a/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munitxx.h +++ b/deps/ngtcp2/ngtcp2/third-party/urlparse/munit/munitxx.h @@ -36,8 +36,8 @@ #define munit_assert_stdstring_equal(a, b) \ do { \ - const std::string munit_tmp_a_ = a; \ - const std::string munit_tmp_b_ = b; \ + const std::string munit_tmp_a_ = (a); \ + const std::string munit_tmp_b_ = (b); \ if (MUNIT_UNLIKELY(munit_tmp_a_ != munit_tmp_b_)) { \ munit_hexdump_diff(stderr, munit_tmp_a_.c_str(), munit_tmp_a_.size(), \ munit_tmp_b_.c_str(), munit_tmp_b_.size()); \ @@ -50,8 +50,8 @@ #if __cplusplus >= 201703L # define munit_assert_stdsv_equal(a, b) \ do { \ - const std::string_view munit_tmp_a_ = a; \ - const std::string_view munit_tmp_b_ = b; \ + const std::string_view munit_tmp_a_ = (a); \ + const std::string_view munit_tmp_b_ = (b); \ if (MUNIT_UNLIKELY(munit_tmp_a_ != munit_tmp_b_)) { \ munit_hexdump_diff(stderr, munit_tmp_a_.data(), munit_tmp_a_.size(), \ munit_tmp_b_.data(), munit_tmp_b_.size()); \ diff --git a/deps/ngtcp2/ngtcp2/third-party/urlparse/urlparse.c b/deps/ngtcp2/ngtcp2/third-party/urlparse/urlparse.c index cf5ad9fc67ae47..3e00da5eb0cfbc 100644 --- a/deps/ngtcp2/ngtcp2/third-party/urlparse/urlparse.c +++ b/deps/ngtcp2/ngtcp2/third-party/urlparse/urlparse.c @@ -26,94 +26,24 @@ #include #include -#include - -#define DIGIT_CASES \ - case '0': \ - case '1': \ - case '2': \ - case '3': \ - case '4': \ - case '5': \ - case '6': \ - case '7': \ - case '8': \ - case '9' - -#define LCALPHA_CASES \ - case 'a': \ - case 'b': \ - case 'c': \ - case 'd': \ - case 'e': \ - case 'f': \ - case 'g': \ - case 'h': \ - case 'i': \ - case 'j': \ - case 'k': \ - case 'l': \ - case 'm': \ - case 'n': \ - case 'o': \ - case 'p': \ - case 'q': \ - case 'r': \ - case 's': \ - case 't': \ - case 'u': \ - case 'v': \ - case 'w': \ - case 'x': \ - case 'y': \ - case 'z' - -#define UCALPHA_CASES \ - case 'A': \ - case 'B': \ - case 'C': \ - case 'D': \ - case 'E': \ - case 'F': \ - case 'G': \ - case 'H': \ - case 'I': \ - case 'J': \ - case 'K': \ - case 'L': \ - case 'M': \ - case 'N': \ - case 'O': \ - case 'P': \ - case 'Q': \ - case 'R': \ - case 'S': \ - case 'T': \ - case 'U': \ - case 'V': \ - case 'W': \ - case 'X': \ - case 'Y': \ - case 'Z' - -#define ALPHA_CASES \ - UCALPHA_CASES: \ - LCALPHA_CASES - -#define HEX_CASES \ - DIGIT_CASES: \ - case 'A': \ - case 'B': \ - case 'C': \ - case 'D': \ - case 'E': \ - case 'F': \ - case 'a': \ - case 'b': \ - case 'c': \ - case 'd': \ - case 'e': \ - case 'f' + +#define ALPHAS \ + ['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1, ['F'] = 1, ['G'] = 1, \ + ['H'] = 1, ['I'] = 1, ['J'] = 1, ['K'] = 1, ['L'] = 1, ['M'] = 1, ['N'] = 1, \ + ['O'] = 1, ['P'] = 1, ['Q'] = 1, ['R'] = 1, ['S'] = 1, ['T'] = 1, ['U'] = 1, \ + ['V'] = 1, ['W'] = 1, ['X'] = 1, ['Y'] = 1, ['Z'] = 1, ['a'] = 1, ['b'] = 1, \ + ['c'] = 1, ['d'] = 1, ['e'] = 1, ['f'] = 1, ['g'] = 1, ['h'] = 1, ['i'] = 1, \ + ['j'] = 1, ['k'] = 1, ['l'] = 1, ['m'] = 1, ['n'] = 1, ['o'] = 1, ['p'] = 1, \ + ['q'] = 1, ['r'] = 1, ['s'] = 1, ['t'] = 1, ['u'] = 1, ['v'] = 1, ['w'] = 1, \ + ['x'] = 1, ['y'] = 1, ['z'] = 1 + +#define DIGITS \ + ['0'] = 1, ['1'] = 1, ['2'] = 1, ['3'] = 1, ['4'] = 1, ['5'] = 1, ['6'] = 1, \ + ['7'] = 1, ['8'] = 1, ['9'] = 1 + +#define HEXDIGITS \ + DIGITS, ['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1, ['F'] = 1, \ + ['a'] = 1, ['b'] = 1, ['c'] = 1, ['d'] = 1, ['e'] = 1, ['f'] = 1 typedef struct urlparse_parser { const char *begin; @@ -133,6 +63,13 @@ static void urlparse_url_set_field_data(urlparse_url *dest, int field, dest->field_data[field].len = (uint16_t)(end - start); } +static const uint8_t scheme_chars[256] = { + ALPHAS, + [':'] = 2, + ['/'] = 3, + ['*'] = 3, +}; + static int parse_scheme(urlparse_parser *up, urlparse_url *dest) { const char *start; @@ -140,27 +77,28 @@ static int parse_scheme(urlparse_parser *up, urlparse_url *dest) { return URLPARSE_ERR_PARSE; } - switch (*up->pos) { - ALPHA_CASES: + switch (scheme_chars[(uint8_t)*up->pos]) { + case 0: + case 2: + return URLPARSE_ERR_PARSE; + case 1: break; - case '/': - case '*': + case 3: return 0; - default: - return URLPARSE_ERR_PARSE; } start = up->pos; ++up->pos; for (; !urlparse_parser_eof(up); ++up->pos) { - switch (*up->pos) { - ALPHA_CASES: + switch (scheme_chars[(uint8_t)*up->pos]) { + case 0: + case 3: + return URLPARSE_ERR_PARSE; + case 1: continue; - case ':': + case 2: goto fin; - default: - return URLPARSE_ERR_PARSE; } } @@ -172,6 +110,50 @@ static int parse_scheme(urlparse_parser *up, urlparse_url *dest) { return 0; } +static const uint8_t path_chars[256] = { + /* unreserved */ + DIGITS, + ALPHAS, + ['-'] = 1, + ['.'] = 1, + ['_'] = 1, + ['~'] = 1, + /* pct-encoded */ + ['%'] = 1, + /* sub-delims */ + ['!'] = 1, + ['$'] = 1, + ['&'] = 1, + ['\''] = 1, + ['('] = 1, + [')'] = 1, + ['*'] = 1, + ['+'] = 1, + [','] = 1, + [';'] = 1, + ['='] = 1, + /* extra */ + [':'] = 1, + ['@'] = 1, + ['/'] = 1, + /* http-parser allows the following characters as well. */ + ['"'] = 1, + ['<'] = 1, + ['>'] = 1, + ['['] = 1, + ['\\'] = 1, + [']'] = 1, + ['^'] = 1, + ['`'] = 1, + ['{'] = 1, + ['|'] = 1, + ['}'] = 1, + /* query found */ + ['?'] = 2, + /* fragment found */ + ['#'] = 2, +}; + static int parse_path_abempty(urlparse_parser *up, urlparse_url *dest) { const char *start; @@ -197,50 +179,13 @@ static int parse_path_abempty(urlparse_parser *up, urlparse_url *dest) { start = up->pos++; for (; !urlparse_parser_eof(up); ++up->pos) { - switch (*up->pos) { - /* unreserved */ - ALPHA_CASES: - DIGIT_CASES: - case '-': - case '.': - case '_': - case '~': - /* pct-encoded */ - case '%': - /* sub-delims */ - case '!': - case '$': - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - case '=': - /* extra */ - case ':': - case '@': - case '/': - /* http-parser allows the following characters as well. */ - case '"': - case '<': - case '>': - case '[': - case '\\': - case ']': - case '^': - case '`': - case '{': - case '|': - case '}': + switch (path_chars[(uint8_t)*up->pos]) { + case 0: + return URLPARSE_ERR_PARSE; + case 1: continue; - case '?': - case '#': + case 2: goto fin; - default: - return URLPARSE_ERR_PARSE; } } @@ -250,6 +195,32 @@ static int parse_path_abempty(urlparse_parser *up, urlparse_url *dest) { return 0; } +static const uint8_t userinfo_chars[256] = { + /* unreserved */ + DIGITS, + ALPHAS, + ['-'] = 1, + ['.'] = 1, + ['_'] = 1, + ['~'] = 1, + /* pct-encoded */ + ['%'] = 1, + /* sub-delims */ + ['!'] = 1, + ['$'] = 1, + ['&'] = 1, + ['\''] = 1, + ['('] = 1, + [')'] = 1, + ['*'] = 1, + ['+'] = 1, + [','] = 1, + [';'] = 1, + ['='] = 1, + [':'] = 1, + ['@'] = 2, +}; + static int parse_userinfo(urlparse_parser *up, urlparse_url *dest) { const char *start; @@ -258,34 +229,13 @@ static int parse_userinfo(urlparse_parser *up, urlparse_url *dest) { start = up->pos; for (; !urlparse_parser_eof(up); ++up->pos) { - switch (*up->pos) { - /* unreserved */ - ALPHA_CASES: - DIGIT_CASES: - case '-': - case '.': - case '_': - case '~': - /* pct-encoded */ - case '%': - /* sub-delims */ - case '!': - case '$': - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - case '=': - case ':': + switch (userinfo_chars[(uint8_t)*up->pos]) { + case 0: + return URLPARSE_ERR_PARSE; + case 1: continue; - case '@': + case 2: goto fin; - default: - return URLPARSE_ERR_PARSE; } } @@ -302,6 +252,10 @@ static int parse_userinfo(urlparse_parser *up, urlparse_url *dest) { return 0; } +static const uint8_t host_chars[256] = { + DIGITS, ALPHAS, ['.'] = 1, ['-'] = 1, [':'] = 2, ['/'] = 2, ['?'] = 2, +}; + static int parse_host(urlparse_parser *up, urlparse_url *dest) { const char *start; @@ -310,18 +264,13 @@ static int parse_host(urlparse_parser *up, urlparse_url *dest) { start = up->pos; for (; !urlparse_parser_eof(up); ++up->pos) { - switch (*up->pos) { - ALPHA_CASES: - DIGIT_CASES: - case '.': - case '-': + switch (host_chars[(uint8_t)*up->pos]) { + case 0: + return URLPARSE_ERR_PARSE; + case 1: continue; - case ':': - case '/': - case '?': + case 2: break; - default: - return URLPARSE_ERR_PARSE; } break; @@ -336,6 +285,15 @@ static int parse_host(urlparse_parser *up, urlparse_url *dest) { return 0; } +static const uint8_t ipv6_host_chars[256] = { + HEXDIGITS, [':'] = 1, ['.'] = 1, ['%'] = 2, [']'] = 3, +}; + +static const uint8_t ipv6_zone_chars[256] = { + DIGITS, ALPHAS, ['%'] = 1, ['.'] = 1, + ['-'] = 1, ['_'] = 1, ['~'] = 1, [']'] = 2, +}; + static int parse_ipv6_host(urlparse_parser *up, urlparse_url *dest) { const char *start, *zone_start; @@ -346,12 +304,12 @@ static int parse_ipv6_host(urlparse_parser *up, urlparse_url *dest) { start = up->pos; for (; !urlparse_parser_eof(up); ++up->pos) { - switch (*up->pos) { - HEX_CASES: - case ':': - case '.': + switch (ipv6_host_chars[(uint8_t)*up->pos]) { + case 0: + return URLPARSE_ERR_PARSE; + case 1: continue; - case '%': + case 2: if (start == up->pos) { return URLPARSE_ERR_PARSE; } @@ -364,31 +322,23 @@ static int parse_ipv6_host(urlparse_parser *up, urlparse_url *dest) { } for (; !urlparse_parser_eof(up); ++up->pos) { - switch (*up->pos) { - ALPHA_CASES: - DIGIT_CASES: - case '%': - case '.': - case '-': - case '_': - case '~': + switch (ipv6_zone_chars[(uint8_t)*up->pos]) { + case 0: + return URLPARSE_ERR_PARSE; + case 1: continue; - case ']': + case 2: if (zone_start + 1 == up->pos) { return URLPARSE_ERR_PARSE; } goto fin; - default: - return URLPARSE_ERR_PARSE; } } return URLPARSE_ERR_PARSE; - case ']': + case 3: goto fin; - default: - return URLPARSE_ERR_PARSE; } } @@ -406,6 +356,12 @@ static int parse_ipv6_host(urlparse_parser *up, urlparse_url *dest) { return 0; } +static const uint8_t port_chars[256] = { + DIGITS, + ['/'] = 2, + ['?'] = 2, +}; + static int parse_port(urlparse_parser *up, urlparse_url *dest) { const char *start; uint16_t port, d; @@ -419,8 +375,10 @@ static int parse_port(urlparse_parser *up, urlparse_url *dest) { port = 0; for (; !urlparse_parser_eof(up); ++up->pos) { - switch (*up->pos) { - DIGIT_CASES: + switch (port_chars[(uint8_t)*up->pos]) { + case 0: + return URLPARSE_ERR_PARSE; + case 1: if (port > UINT16_MAX / 10) { return URLPARSE_ERR_PARSE; } @@ -435,16 +393,13 @@ static int parse_port(urlparse_parser *up, urlparse_url *dest) { port += d; break; - case '/': - case '?': + case 2: /* http_parser disallows empty port. */ if (start == up->pos) { return URLPARSE_ERR_PARSE; } goto fin; - default: - return URLPARSE_ERR_PARSE; } } @@ -523,61 +478,66 @@ static int parse_authority(urlparse_parser *up, urlparse_url *dest) { return parse_port(up, dest); } +static const uint8_t extra_chars[256] = { + /* unreserved */ + DIGITS, + ALPHAS, + ['-'] = 1, + ['.'] = 1, + ['_'] = 1, + ['~'] = 1, + /* pct-encoded */ + ['%'] = 1, + /* sub-delims */ + ['!'] = 1, + ['$'] = 1, + ['&'] = 1, + ['\''] = 1, + ['('] = 1, + [')'] = 1, + ['*'] = 1, + ['+'] = 1, + [','] = 1, + [';'] = 1, + ['='] = 1, + /* extra */ + [':'] = 1, + ['@'] = 1, + /* query/fragment specific */ + ['/'] = 1, + ['?'] = 1, + /* http-parser allows the following characters as well. */ + ['"'] = 1, + ['<'] = 1, + ['>'] = 1, + ['['] = 1, + ['\\'] = 1, + [']'] = 1, + ['^'] = 1, + ['`'] = 1, + ['{'] = 1, + ['|'] = 1, + ['}'] = 1, + ['#'] = 2, +}; + static int parse_extra(urlparse_parser *up, urlparse_url *dest, int field) { const char *start; start = up->pos; for (; !urlparse_parser_eof(up); ++up->pos) { - switch (*up->pos) { - /* unreserved */ - ALPHA_CASES: - DIGIT_CASES: - case '-': - case '.': - case '_': - case '~': - /* pct-encoded */ - case '%': - /* sub-delims */ - case '!': - case '$': - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - case '=': - /* extra */ - case ':': - case '@': - /* query/fragment specific */ - case '/': - case '?': - /* http-parser allows the following characters as well. */ - case '"': - case '<': - case '>': - case '[': - case '\\': - case ']': - case '^': - case '`': - case '{': - case '|': - case '}': + switch (extra_chars[(uint8_t)*up->pos]) { + case 0: + return URLPARSE_ERR_PARSE; + case 1: continue; - case '#': + case 2: if (field == URLPARSE_QUERY) { goto fin; } continue; - default: - return URLPARSE_ERR_PARSE; } } diff --git a/deps/ngtcp2/ngtcp2/third-party/urlparse/urlparse_test.c b/deps/ngtcp2/ngtcp2/third-party/urlparse/urlparse_test.c index dde26cb58a3584..7339a253d126fc 100644 --- a/deps/ngtcp2/ngtcp2/third-party/urlparse/urlparse_test.c +++ b/deps/ngtcp2/ngtcp2/third-party/urlparse/urlparse_test.c @@ -504,6 +504,42 @@ void test_urlparse_parse_url(void) { free(b); } + { + /* '*' in scheme */ + init_buffer(b, blen, "https*://example.com"); + + rv = urlparse_parse_url(b, blen, /* is_connect = */ 0, &u); + + assert_int(URLPARSE_ERR_PARSE, ==, rv); + + memset(&hu, 0, sizeof(hu)); + rv = http_parser_parse_url(b, blen, /* is_connect = */ 0, &hu); + + assert_int(0, !=, rv); + + free(b); + } + + { + /* scheme contains a character that has the highest bit set, which + can make the char negative. */ + init_buffer(b, blen, + "https" + "\x80" + "://example.com"); + + rv = urlparse_parse_url(b, blen, /* is_connect = */ 0, &u); + + assert_int(URLPARSE_ERR_PARSE, ==, rv); + + memset(&hu, 0, sizeof(hu)); + rv = http_parser_parse_url(b, blen, /* is_connect = */ 0, &hu); + + assert_int(0, !=, rv); + + free(b); + } + { /* query starts with ?? */ init_buffer(b, blen, "/foo??bar");