mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.29.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 34 support and v1 support. The latter is turned off by default. - Drop support for ID-28 and ID-32. - [BUGFIX] IETF QUIC mini conn receive history (trechist): allow unlimited inserts by dropping smallest elements. - [BUGFIX] gQUIC: set STTL to correct value, issue #226. - [BUGFIX] Account for poison packet gap when MTU probe was too large.
This commit is contained in:
parent
ac0ce07bd0
commit
26e8f082c9
29 changed files with 411 additions and 178 deletions
|
@ -8,7 +8,7 @@ task:
|
|||
- cd boringssl
|
||||
# This is so that both GQUIC and IETF branches build. Just picking
|
||||
# a known good revision:
|
||||
- git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1
|
||||
- git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9
|
||||
- cmake .
|
||||
- make
|
||||
- cd -
|
||||
|
|
|
@ -32,7 +32,7 @@ before_script:
|
|||
- cd boringssl
|
||||
# This is so that both GQUIC and IETF branches build. Just picking
|
||||
# a known good revision:
|
||||
- git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1
|
||||
- git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9
|
||||
- cmake .
|
||||
- make
|
||||
- cd -
|
||||
|
|
10
CHANGELOG
10
CHANGELOG
|
@ -1,3 +1,13 @@
|
|||
2021-02-10
|
||||
- 2.29.0
|
||||
- [FEATURE] QUIC and HTTP/3 Internet Draft 34 support and v1 support.
|
||||
The latter is turned off by default.
|
||||
- Drop support for ID-28 and ID-32.
|
||||
- [BUGFIX] IETF QUIC mini conn receive history (trechist): allow
|
||||
unlimited inserts by dropping smallest elements.
|
||||
- [BUGFIX] gQUIC: set STTL to correct value, issue #226.
|
||||
- [BUGFIX] Account for poison packet gap when MTU probe was too large.
|
||||
|
||||
2021-02-03
|
||||
- 2.28.0
|
||||
- [API] lsquic_ssl_sess_to_resume_info() is the new way to get
|
||||
|
|
|
@ -17,7 +17,7 @@ COPY ./ /src/lsquic/
|
|||
|
||||
RUN git clone https://boringssl.googlesource.com/boringssl && \
|
||||
cd boringssl && \
|
||||
git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1 && \
|
||||
git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9 && \
|
||||
cmake . && \
|
||||
make
|
||||
|
||||
|
|
|
@ -13,8 +13,9 @@ and HTTP/3 functionality for servers and clients. Most of the code in this
|
|||
distribution is used in our own products: LiteSpeed Web Server, LiteSpeed ADC,
|
||||
and OpenLiteSpeed.
|
||||
|
||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, ID-28, ID-29,
|
||||
and ID-32. Support for newer versions is added soon after they are released.
|
||||
Currently supported QUIC versions are v1 (disabled by default until the
|
||||
QUIC RFC is released); Internet-Draft versions 34, 29, and 27;
|
||||
and the older "Google" QUIC versions Q043, Q046, an Q050.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
@ -48,7 +49,7 @@ You may need to install pre-requisites like zlib and libevent.
|
|||
2. Use specific BoringSSL version
|
||||
|
||||
```
|
||||
git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1
|
||||
git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9
|
||||
```
|
||||
|
||||
3. Compile the library
|
||||
|
|
|
@ -30,7 +30,7 @@ build_script:
|
|||
|
||||
cd boringssl
|
||||
|
||||
git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1
|
||||
git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9
|
||||
|
||||
cmake -DCMAKE_GENERATOR_PLATFORM=x64 --config Debug -DBUILD_SHARED_LIBS=OFF -DOPENSSL_NO_ASM=1 .
|
||||
|
||||
|
|
|
@ -50,17 +50,18 @@ developed by the IETF. Both types are included in a single enum:
|
|||
|
||||
IETF QUIC version ID (Internet-Draft) 27; this version is deprecated.
|
||||
|
||||
.. member:: LSQVER_ID28
|
||||
|
||||
IETF QUIC version ID 28; this version is deprecated.
|
||||
|
||||
.. member:: LSQVER_ID29
|
||||
|
||||
IETF QUIC version ID 29
|
||||
|
||||
.. member:: LSQVER_ID32
|
||||
.. member:: LSQVER_ID34
|
||||
|
||||
IETF QUIC version ID 32
|
||||
IETF QUIC version ID 34
|
||||
|
||||
.. member:: LSQVER_I001
|
||||
|
||||
IETF QUIC version 1. (This version is disabled by default until
|
||||
the QUIC RFC is released).
|
||||
|
||||
.. member:: N_LSQVER
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@ copyright = u'2021, LiteSpeed Technologies'
|
|||
author = u'LiteSpeed Technologies'
|
||||
|
||||
# The short X.Y version
|
||||
version = u'2.28'
|
||||
version = u'2.29'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'2.28.0'
|
||||
release = u'2.29.0'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
|
|
@ -16,9 +16,9 @@ Most of the code in this distribution has been used in our own products
|
|||
-- `LiteSpeed Web Server`_, `LiteSpeed Web ADC`_, and OpenLiteSpeed_ --
|
||||
since 2017.
|
||||
|
||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, ID-28,
|
||||
ID-29, and ID-32.
|
||||
Support for newer versions will be added soon after they are released.
|
||||
Currently supported QUIC versions are v1 (disabled by default until the
|
||||
QUIC RFC is released); Internet-Draft versions 34, 29, and 27;
|
||||
and the older "Google" QUIC versions Q043, Q046, an Q050.
|
||||
|
||||
LSQUIC is licensed under the `MIT License`_; see LICENSE in the source
|
||||
distribution for details.
|
||||
|
|
|
@ -24,7 +24,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 28
|
||||
#define LSQUIC_MINOR_VERSION 29
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
|
||||
/**
|
||||
|
@ -81,20 +81,21 @@ enum lsquic_version
|
|||
*/
|
||||
LSQVER_ID27,
|
||||
|
||||
/**
|
||||
* IETF QUIC Draft-28; this version is deprecated.
|
||||
*/
|
||||
LSQVER_ID28,
|
||||
|
||||
/**
|
||||
* IETF QUIC Draft-29
|
||||
*/
|
||||
LSQVER_ID29,
|
||||
|
||||
/**
|
||||
* IETF QUIC Draft-32
|
||||
* IETF QUIC Draft-34
|
||||
*/
|
||||
LSQVER_ID32,
|
||||
LSQVER_ID34,
|
||||
|
||||
/**
|
||||
* IETF QUIC v1. Functionally the same as Draft-34, but marked
|
||||
* experimental for now.
|
||||
*/
|
||||
LSQVER_I001,
|
||||
|
||||
/**
|
||||
* Special version to trigger version negotiation.
|
||||
|
@ -106,8 +107,8 @@ enum lsquic_version
|
|||
};
|
||||
|
||||
/**
|
||||
* We currently support versions 43, 46, 50, Draft-27, Draft-28, Draft-29,
|
||||
* and Draft-32.
|
||||
* We currently support versions 43, 46, 50, Draft-27, Draft-29, Draft-34,
|
||||
* and IETF QUIC v1.
|
||||
* @see lsquic_version
|
||||
*/
|
||||
#define LSQUIC_SUPPORTED_VERSIONS ((1 << N_LSQVER) - 1)
|
||||
|
@ -118,19 +119,21 @@ enum lsquic_version
|
|||
#define LSQUIC_FORCED_TCID0_VERSIONS ((1 << LSQVER_046)|(1 << LSQVER_050))
|
||||
|
||||
#define LSQUIC_EXPERIMENTAL_VERSIONS ( \
|
||||
(1 << LSQVER_I001) | \
|
||||
(1 << LSQVER_VERNEG) | LSQUIC_EXPERIMENTAL_Q098)
|
||||
|
||||
#define LSQUIC_DEPRECATED_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28))
|
||||
#define LSQUIC_DEPRECATED_VERSIONS ((1 << LSQVER_ID27))
|
||||
|
||||
#define LSQUIC_GQUIC_HEADER_VERSIONS (1 << LSQVER_043)
|
||||
|
||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
|
||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) \
|
||||
| (1 << LSQVER_ID29) \
|
||||
| (1 << LSQVER_ID32) | (1 << LSQVER_VERNEG))
|
||||
| (1 << LSQVER_ID34) \
|
||||
| (1 << LSQVER_I001) | (1 << LSQVER_VERNEG))
|
||||
|
||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
|
||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) \
|
||||
| (1 << LSQVER_ID29) \
|
||||
| (1 << LSQVER_ID32) | (1 << LSQVER_VERNEG))
|
||||
| (1 << LSQVER_ID34) | (1 << LSQVER_VERNEG))
|
||||
|
||||
enum lsquic_hsk_status
|
||||
{
|
||||
|
|
|
@ -26,6 +26,12 @@ while (<HEADER>) {
|
|||
push @all_versions, $1;
|
||||
push @all_alpns, "h3-$2";
|
||||
}
|
||||
if (/^\s*(LSQVER_I(\d{3}))\b/) {
|
||||
push @all_versions, $1;
|
||||
if (not grep 'h3' eq $_, @all_alpns) {
|
||||
push @all_alpns, "h3";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -339,9 +339,9 @@ extern const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1;
|
|||
|
||||
#define select_esf_common_by_ver(ver) ( \
|
||||
ver == LSQVER_ID27 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_ID28 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_ID29 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_ID32 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_ID34 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_I001 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_050 ? &lsquic_enc_session_common_gquic_2 : \
|
||||
&lsquic_enc_session_common_gquic_1 )
|
||||
|
|
|
@ -72,10 +72,10 @@ static const struct alpn_map {
|
|||
const unsigned char *alpn;
|
||||
} s_h3_alpns[] = {
|
||||
{ LSQVER_ID27, (unsigned char *) "\x05h3-27", },
|
||||
{ LSQVER_ID28, (unsigned char *) "\x05h3-28", },
|
||||
{ LSQVER_ID29, (unsigned char *) "\x05h3-29", },
|
||||
{ LSQVER_ID32, (unsigned char *) "\x05h3-32", },
|
||||
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-32", },
|
||||
{ LSQVER_ID34, (unsigned char *) "\x05h3-34", },
|
||||
{ LSQVER_I001, (unsigned char *) "\x02h3", },
|
||||
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-34", },
|
||||
};
|
||||
|
||||
struct enc_sess_iquic;
|
||||
|
@ -926,6 +926,10 @@ iquic_esfi_create_client (const char *hostname,
|
|||
ERR_error_string(ERR_get_error(), errbuf));
|
||||
goto err;
|
||||
}
|
||||
#if BORINGSSL_API_VERSION >= 13
|
||||
SSL_set_quic_use_legacy_codepoint(enc_sess->esi_ssl,
|
||||
enc_sess->esi_ver_neg->vn_ver < LSQVER_ID34);
|
||||
#endif
|
||||
|
||||
transpa_len = gen_trans_params(enc_sess, trans_params,
|
||||
sizeof(trans_params));
|
||||
|
@ -1109,6 +1113,7 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
|
|||
struct header_prot *hp;
|
||||
size_t hsk_secret_sz, key_len;
|
||||
unsigned cliser, i;
|
||||
const unsigned char *salt;
|
||||
unsigned char hsk_secret[EVP_MAX_MD_SIZE];
|
||||
unsigned char secret[2][SHA256_DIGEST_LENGTH]; /* client, server */
|
||||
unsigned char key[2][EVP_MAX_KEY_LENGTH];
|
||||
|
@ -1131,12 +1136,17 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
|
|||
pair->ykp_thresh = IQUIC_INVALID_PACKNO;
|
||||
hp = &enc_sess->esi_hsk_hps[ENC_LEV_CLEAR];
|
||||
|
||||
if (enc_sess->esi_conn->cn_version < LSQVER_ID29)
|
||||
salt = HSK_SALT_PRE29;
|
||||
else if (enc_sess->esi_conn->cn_version < LSQVER_ID34)
|
||||
salt = HSK_SALT_PRE33;
|
||||
else
|
||||
salt = HSK_SALT;
|
||||
HKDF_extract(hsk_secret, &hsk_secret_sz, md, cid->idbuf, cid->len,
|
||||
enc_sess->esi_conn->cn_version < LSQVER_ID29
|
||||
? HSK_SALT_PRE29 : HSK_SALT, HSK_SALT_SZ);
|
||||
salt, HSK_SALT_SZ);
|
||||
if (enc_sess->esi_flags & ESI_LOG_SECRETS)
|
||||
{
|
||||
LSQ_DEBUG("handshake salt: %s", HEXSTR(HSK_SALT, HSK_SALT_SZ, hexbuf));
|
||||
LSQ_DEBUG("handshake salt: %s", HEXSTR(salt, HSK_SALT_SZ, hexbuf));
|
||||
LSQ_DEBUG("handshake secret: %s", HEXSTR(hsk_secret, hsk_secret_sz,
|
||||
hexbuf));
|
||||
}
|
||||
|
@ -1382,6 +1392,10 @@ iquic_esfi_init_server (enc_session_t *enc_session_p)
|
|||
ERR_error_string(ERR_get_error(), u.errbuf));
|
||||
return -1;
|
||||
}
|
||||
#if BORINGSSL_API_VERSION >= 13
|
||||
SSL_set_quic_use_legacy_codepoint(enc_sess->esi_ssl,
|
||||
enc_sess->esi_conn->cn_version < LSQVER_ID34);
|
||||
#endif
|
||||
if (!(SSL_set_quic_method(enc_sess->esi_ssl, &cry_quic_method)))
|
||||
{
|
||||
LSQ_INFO("could not set stream method");
|
||||
|
@ -3327,6 +3341,9 @@ const unsigned char *const lsquic_retry_key_buf[N_IETF_RETRY_VERSIONS] =
|
|||
/* [draft-ietf-quic-tls-29] Section 5.8 */
|
||||
(unsigned char *)
|
||||
"\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1",
|
||||
/* [draft-ietf-quic-tls-33] Section 5.8 */
|
||||
(unsigned char *)
|
||||
"\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e",
|
||||
};
|
||||
|
||||
|
||||
|
@ -3336,6 +3353,8 @@ const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS] =
|
|||
(unsigned char *) "\x4d\x16\x11\xd0\x55\x13\xa5\x52\xc5\x87\xd5\x75",
|
||||
/* [draft-ietf-quic-tls-29] Section 5.8 */
|
||||
(unsigned char *) "\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c",
|
||||
/* [draft-ietf-quic-tls-33] Section 5.8 */
|
||||
(unsigned char *) "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb",
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -674,7 +674,7 @@ lsquic_engine_new (unsigned flags,
|
|||
{
|
||||
int sz = lsquic_enc_sess_ietf_gen_quic_ctx(
|
||||
&engine->pub.enp_settings,
|
||||
i == 0 ? LSQVER_ID27 : LSQVER_ID28,
|
||||
i == 0 ? LSQVER_ID27 : LSQVER_ID29,
|
||||
engine->pub.enp_quic_ctx_buf[i],
|
||||
sizeof(engine->pub.enp_quic_ctx_buf));
|
||||
if (sz < 0)
|
||||
|
|
|
@ -3314,7 +3314,7 @@ try_to_begin_migration (struct ietf_full_conn *conn,
|
|||
return BM_NOT_MIGRATING;
|
||||
}
|
||||
|
||||
if (conn->ifc_conn.cn_version <= LSQVER_ID28 /* Starting with ID-29,
|
||||
if (conn->ifc_conn.cn_version <= LSQVER_ID27 /* Starting with ID-29,
|
||||
disable_active_migration TP applies only to the time period during
|
||||
the handshake. Our client does not migrate during the handshake:
|
||||
this code runs only after handshake has succeeded. */
|
||||
|
@ -7566,16 +7566,16 @@ process_incoming_packet_verneg (struct ietf_full_conn *conn,
|
|||
*/
|
||||
if (!verneg_ok(conn))
|
||||
{
|
||||
ABORT_ERROR("version negotiation not permitted in this version "
|
||||
"of QUIC");
|
||||
ABORT_WITH_FLAG(conn, LSQ_LOG_NOTICE, IFC_ERROR,
|
||||
"version negotiation not permitted in this version of QUIC");
|
||||
return -1;
|
||||
}
|
||||
|
||||
versions &= conn->ifc_u.cli.ifcli_ver_neg.vn_supp;
|
||||
if (0 == versions)
|
||||
{
|
||||
ABORT_ERROR("client does not support any of the server-specified "
|
||||
"versions");
|
||||
ABORT_WITH_FLAG(conn, LSQ_LOG_NOTICE, IFC_ERROR,
|
||||
"client does not support any of the server-specified versions");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -7663,13 +7663,12 @@ ietf_full_conn_ci_packet_too_large (struct lsquic_conn *lconn,
|
|||
assert(packet_out->po_lflags & POL_HEADER_PROT);
|
||||
#endif
|
||||
|
||||
lsquic_senhist_add(&conn->ifc_send_ctl.sc_senhist, packet_out->po_packno);
|
||||
lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl);
|
||||
if (packet_out->po_flags & PO_MTU_PROBE)
|
||||
{
|
||||
LSQ_DEBUG("%zu-byte MTU probe in packet %"PRIu64" is too large",
|
||||
lsquic_packet_out_sent_sz(&conn->ifc_conn, packet_out),
|
||||
packet_out->po_packno);
|
||||
lsquic_send_ctl_mtu_not_sent(&conn->ifc_send_ctl, packet_out);
|
||||
mtu_probe_too_large(conn, packet_out);
|
||||
}
|
||||
else
|
||||
|
@ -9041,7 +9040,7 @@ on_goaway_server_27 (void *ctx, uint64_t stream_id)
|
|||
|
||||
|
||||
static void
|
||||
on_goaway_client_28 (void *ctx, uint64_t stream_id)
|
||||
on_goaway_client_27 (void *ctx, uint64_t stream_id)
|
||||
{
|
||||
struct ietf_full_conn *const conn = ctx;
|
||||
struct lsquic_stream *stream;
|
||||
|
@ -9348,30 +9347,7 @@ static const struct hcsi_callbacks hcsi_callbacks_client_27 =
|
|||
.on_max_push_id = on_max_push_id_client,
|
||||
.on_settings_frame = on_settings_frame,
|
||||
.on_setting = on_setting,
|
||||
.on_goaway = on_goaway_client_28 /* sic */,
|
||||
.on_unexpected_frame = on_unexpected_frame,
|
||||
.on_priority_update = on_priority_update_client,
|
||||
};
|
||||
|
||||
|
||||
static const struct hcsi_callbacks hcsi_callbacks_server_28 =
|
||||
{
|
||||
.on_cancel_push = on_cancel_push_server,
|
||||
.on_max_push_id = on_max_push_id,
|
||||
.on_settings_frame = on_settings_frame,
|
||||
.on_setting = on_setting,
|
||||
.on_goaway = on_goaway_server /* sic */,
|
||||
.on_unexpected_frame = on_unexpected_frame,
|
||||
.on_priority_update = on_priority_update_server,
|
||||
};
|
||||
|
||||
static const struct hcsi_callbacks hcsi_callbacks_client_28 =
|
||||
{
|
||||
.on_cancel_push = on_cancel_push_client,
|
||||
.on_max_push_id = on_max_push_id_client,
|
||||
.on_settings_frame = on_settings_frame,
|
||||
.on_setting = on_setting,
|
||||
.on_goaway = on_goaway_client_28,
|
||||
.on_goaway = on_goaway_client_27,
|
||||
.on_unexpected_frame = on_unexpected_frame,
|
||||
.on_priority_update = on_priority_update_client,
|
||||
};
|
||||
|
@ -9416,21 +9392,17 @@ hcsi_on_new (void *stream_if_ctx, struct lsquic_stream *stream)
|
|||
case (1 << 8) | LSQVER_ID27:
|
||||
callbacks = &hcsi_callbacks_server_27;
|
||||
break;
|
||||
case (0 << 8) | LSQVER_ID28:
|
||||
callbacks = &hcsi_callbacks_client_28;
|
||||
break;
|
||||
case (1 << 8) | LSQVER_ID28:
|
||||
callbacks = &hcsi_callbacks_server_28;
|
||||
break;
|
||||
case (0 << 8) | LSQVER_ID29:
|
||||
case (0 << 8) | LSQVER_ID32:
|
||||
case (0 << 8) | LSQVER_ID34:
|
||||
case (0 << 8) | LSQVER_I001:
|
||||
callbacks = &hcsi_callbacks_client_29;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
/* fallthru */
|
||||
case (1 << 8) | LSQVER_ID29:
|
||||
case (1 << 8) | LSQVER_ID32:
|
||||
case (1 << 8) | LSQVER_ID34:
|
||||
case (1 << 8) | LSQVER_I001:
|
||||
callbacks = &hcsi_callbacks_server_29;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1963,13 +1963,12 @@ gen_rej1_data (struct lsquic_enc_session *enc_session, uint8_t *data,
|
|||
int len;
|
||||
EVP_PKEY * rsa_priv_key;
|
||||
SSL_CTX *ctx = enc_session->ssl_ctx;
|
||||
const struct lsquic_engine_settings *const settings =
|
||||
&enc_session->enpub->enp_settings;
|
||||
hs_ctx_t *const hs_ctx = &enc_session->hs_ctx;
|
||||
int scfg_len = enc_session->server_config->lsc_scfg->info.scfg_len;
|
||||
uint8_t *scfg_data = enc_session->server_config->lsc_scfg->scfg;
|
||||
size_t msg_len;
|
||||
struct message_writer mw;
|
||||
uint64_t sttl;
|
||||
|
||||
rsa_priv_key = SSL_CTX_get0_privatekey(ctx);
|
||||
if (!rsa_priv_key)
|
||||
|
@ -2029,7 +2028,7 @@ gen_rej1_data (struct lsquic_enc_session *enc_session, uint8_t *data,
|
|||
MSG_LEN_ADD(msg_len, scfg_len);
|
||||
MSG_LEN_ADD(msg_len, STK_LENGTH);
|
||||
MSG_LEN_ADD(msg_len, SNO_LENGTH);
|
||||
MSG_LEN_ADD(msg_len, sizeof(settings->es_sttl));
|
||||
MSG_LEN_ADD(msg_len, sizeof(sttl));
|
||||
MSG_LEN_ADD(msg_len, lsquic_str_len(&hs_ctx->prof));
|
||||
if (hs_ctx->ccert)
|
||||
MSG_LEN_ADD(msg_len, hs_ctx->ccert->len);
|
||||
|
@ -2055,6 +2054,8 @@ gen_rej1_data (struct lsquic_enc_session *enc_session, uint8_t *data,
|
|||
lsquic_str_setlen(&enc_session->ssno, SNO_LENGTH);
|
||||
}
|
||||
RAND_bytes((uint8_t *) lsquic_str_buf(&enc_session->ssno), SNO_LENGTH);
|
||||
sttl = enc_session->enpub->enp_server_config->lsc_scfg->info.expy
|
||||
- (uint64_t) time(NULL);
|
||||
|
||||
MW_BEGIN(&mw, QTAG_REJ, 7, data);
|
||||
MW_WRITE_LS_STR(&mw, QTAG_STK, &enc_session->sstk);
|
||||
|
@ -2062,8 +2063,7 @@ gen_rej1_data (struct lsquic_enc_session *enc_session, uint8_t *data,
|
|||
MW_WRITE_LS_STR(&mw, QTAG_PROF, &hs_ctx->prof);
|
||||
MW_WRITE_BUFFER(&mw, QTAG_SCFG, scfg_data, scfg_len);
|
||||
MW_WRITE_BUFFER(&mw, QTAG_RREJ, &hs_ctx->rrej, sizeof(hs_ctx->rrej));
|
||||
MW_WRITE_BUFFER(&mw, QTAG_STTL, &settings->es_sttl,
|
||||
sizeof(settings->es_sttl));
|
||||
MW_WRITE_BUFFER(&mw, QTAG_STTL, &sttl, sizeof(sttl));
|
||||
if (hs_ctx->ccert)
|
||||
MW_WRITE_BUFFER(&mw, QTAG_CRT, hs_ctx->ccert->buf, hs_ctx->ccert->len);
|
||||
MW_END(&mw);
|
||||
|
|
|
@ -7,9 +7,13 @@
|
|||
"\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"
|
||||
#define HSK_SALT_PRE29 ((unsigned char *) HSK_SALT_BUF)
|
||||
/* [draft-ietf-quic-tls-29] Section 5.2 */
|
||||
#define HSK_SALT ((unsigned char *) \
|
||||
#define HSK_SALT_PRE33 ((unsigned char *) \
|
||||
"\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97" \
|
||||
"\x86\xf1\x9c\x61\x11\xe0\x43\x90\xa8\x99")
|
||||
/* [draft-ietf-quic-tls-33] Section 5.2 */
|
||||
#define HSK_SALT ((unsigned char *) \
|
||||
"\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" \
|
||||
"\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a")
|
||||
#define HSK_SALT_SZ (sizeof(HSK_SALT_BUF) - 1)
|
||||
|
||||
#define CLIENT_LABEL "client in"
|
||||
|
|
|
@ -78,6 +78,7 @@ enum http_error_code
|
|||
HEC_REQUEST_REJECTED = 0x10B,
|
||||
HEC_REQUEST_CANCELLED = 0x10C,
|
||||
HEC_REQUEST_INCOMPLETE = 0x10D,
|
||||
HEC_MESSAGE_ERROR = 0x10E,
|
||||
HEC_CONNECT_ERROR = 0x10F,
|
||||
HEC_VERSION_FALLBACK = 0x110,
|
||||
HEC_QPACK_DECOMPRESSION_FAILED = 0x200,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
/* Things specific to the IETF version of QUIC that do not fit anywhere else */
|
||||
|
||||
/* [draft-ietf-quic-transport-31] Section 20 */
|
||||
/* [draft-ietf-quic-transport-33] Section 20 */
|
||||
enum trans_error_code
|
||||
{
|
||||
TEC_NO_ERROR = 0x0,
|
||||
|
@ -23,6 +23,7 @@ enum trans_error_code
|
|||
TEC_CRYPTO_BUFFER_EXCEEDED = 0xD,
|
||||
TEC_KEY_UPDATE_ERROR = 0xE,
|
||||
TEC_AEAD_LIMIT_REACHED = 0xF,
|
||||
TEC_NO_VIABLE_PATH = 0x10,
|
||||
};
|
||||
|
||||
/* Must be at least two */
|
||||
|
@ -32,9 +33,12 @@ enum trans_error_code
|
|||
#define IETF_RETRY_KEY_SZ 16
|
||||
#define IETF_RETRY_NONCE_SZ 12
|
||||
|
||||
#define N_IETF_RETRY_VERSIONS 2
|
||||
#define N_IETF_RETRY_VERSIONS 3
|
||||
extern const unsigned char *const lsquic_retry_key_buf[N_IETF_RETRY_VERSIONS];
|
||||
extern const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS];
|
||||
#define lsquic_version_2_retryver(ver_) ((ver_) > LSQVER_ID28)
|
||||
#define lsquic_version_2_retryver(ver_) ( \
|
||||
(ver_) <= LSQVER_ID27 ? 0 : \
|
||||
(ver_) <= LSQVER_ID34 ? 1 : \
|
||||
2)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1378,15 +1378,10 @@ imico_switch_to_trechist (struct ietf_mini_conn *conn)
|
|||
if (conn->imc_recvd_packnos.bitmasks[pns])
|
||||
{
|
||||
lsquic_imico_rechist_init(&iter, conn, pns);
|
||||
if (0 != lsquic_trechist_copy_ranges(&masks[pns],
|
||||
lsquic_trechist_copy_ranges(&masks[pns],
|
||||
elems + TRECHIST_MAX_RANGES * pns, &iter,
|
||||
lsquic_imico_rechist_first,
|
||||
lsquic_imico_rechist_next))
|
||||
{
|
||||
LSQ_WARN("cannot copy ranges from bitmask to trechist");
|
||||
free(elems);
|
||||
return -1;
|
||||
}
|
||||
lsquic_imico_rechist_next);
|
||||
}
|
||||
else
|
||||
masks[pns] = 0;
|
||||
|
|
|
@ -336,7 +336,7 @@ lsquic_dcid_from_packet (const unsigned char *buf, size_t bufsz,
|
|||
/* See [draft-ietf-quic-transport-28], Section 12.4 (Table 3) */
|
||||
const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
|
||||
{
|
||||
[LSQVER_ID32] = {
|
||||
[LSQVER_I001] = {
|
||||
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
|
@ -346,7 +346,37 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
|
|||
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
|
||||
| QUIC_FTBIT_STREAMS_BLOCKED
|
||||
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
|
||||
| QUIC_FTBIT_PATH_CHALLENGE
|
||||
| QUIC_FTBIT_DATAGRAM
|
||||
| QUIC_FTBIT_RETIRE_CONNECTION_ID,
|
||||
[ENC_LEV_INIT] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
[ENC_LEV_FORW] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
|
||||
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
|
||||
| QUIC_FTBIT_BLOCKED
|
||||
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
|
||||
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
|
||||
| QUIC_FTBIT_STREAMS_BLOCKED
|
||||
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
|
||||
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
|
||||
| QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY
|
||||
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
|
||||
| QUIC_FTBIT_TIMESTAMP
|
||||
| QUIC_FTBIT_DATAGRAM
|
||||
,
|
||||
},
|
||||
[LSQVER_ID34] = {
|
||||
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
|
||||
| QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE
|
||||
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
|
||||
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
|
||||
| QUIC_FTBIT_STREAMS_BLOCKED
|
||||
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
|
||||
| QUIC_FTBIT_PATH_CHALLENGE
|
||||
| QUIC_FTBIT_DATAGRAM
|
||||
| QUIC_FTBIT_RETIRE_CONNECTION_ID,
|
||||
[ENC_LEV_INIT] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
|
@ -396,34 +426,6 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
|
|||
| QUIC_FTBIT_DATAGRAM
|
||||
,
|
||||
},
|
||||
[LSQVER_ID28] = {
|
||||
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
|
||||
| QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE
|
||||
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
|
||||
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
|
||||
| QUIC_FTBIT_STREAMS_BLOCKED
|
||||
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
|
||||
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
|
||||
| QUIC_FTBIT_RETIRE_CONNECTION_ID,
|
||||
[ENC_LEV_INIT] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
[ENC_LEV_FORW] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
|
||||
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
|
||||
| QUIC_FTBIT_BLOCKED
|
||||
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
|
||||
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
|
||||
| QUIC_FTBIT_STREAMS_BLOCKED
|
||||
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
|
||||
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
|
||||
| QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY
|
||||
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
|
||||
| QUIC_FTBIT_TIMESTAMP
|
||||
,
|
||||
},
|
||||
[LSQVER_ID27] = {
|
||||
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
|
|
|
@ -641,6 +641,10 @@ send_ctl_add_poison (struct lsquic_send_ctl *ctl)
|
|||
{
|
||||
struct lsquic_packet_out *poison;
|
||||
|
||||
/* XXX Allocating the poison packet out of the regular pool can fail.
|
||||
* This leads to a lot of error checking that could be skipped if we
|
||||
* did not have to allocate this packet at all.
|
||||
*/
|
||||
poison = lsquic_malo_get(ctl->sc_conn_pub->packet_out_malo);
|
||||
if (!poison)
|
||||
return -1;
|
||||
|
@ -689,6 +693,33 @@ send_ctl_reschedule_poison (struct lsquic_send_ctl *ctl)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
send_ctl_update_poison_hist (struct lsquic_send_ctl *ctl,
|
||||
lsquic_packno_t packno)
|
||||
{
|
||||
if (packno == ctl->sc_gap + 1)
|
||||
{
|
||||
assert(!(ctl->sc_flags & SC_POISON));
|
||||
lsquic_senhist_add(&ctl->sc_senhist, ctl->sc_gap);
|
||||
if (0 != send_ctl_add_poison(ctl))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_send_ctl_mtu_not_sent (struct lsquic_send_ctl *ctl,
|
||||
struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
(void) /* See comment in send_ctl_add_poison(): the plan is to make
|
||||
this code path always succeed. */
|
||||
send_ctl_update_poison_hist(ctl, packet_out->po_packno);
|
||||
lsquic_senhist_add(&ctl->sc_senhist, packet_out->po_packno);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lsquic_send_ctl_sent_packet (lsquic_send_ctl_t *ctl,
|
||||
struct lsquic_packet_out *packet_out)
|
||||
|
@ -699,13 +730,8 @@ lsquic_send_ctl_sent_packet (lsquic_send_ctl_t *ctl,
|
|||
assert(!(packet_out->po_flags & PO_ENCRYPTED));
|
||||
ctl->sc_last_sent_time = packet_out->po_sent;
|
||||
pns = lsquic_packet_out_pns(packet_out);
|
||||
if (packet_out->po_packno == ctl->sc_gap + 1)
|
||||
{
|
||||
assert(!(ctl->sc_flags & SC_POISON));
|
||||
lsquic_senhist_add(&ctl->sc_senhist, ctl->sc_gap);
|
||||
if (0 != send_ctl_add_poison(ctl))
|
||||
if (0 != send_ctl_update_poison_hist(ctl, packet_out->po_packno))
|
||||
return -1;
|
||||
}
|
||||
LSQ_DEBUG("packet %"PRIu64" has been sent (frame types: %s)",
|
||||
packet_out->po_packno, lsquic_frame_types_to_str(frames,
|
||||
sizeof(frames), packet_out->po_frame_types));
|
||||
|
|
|
@ -155,6 +155,10 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *, struct lsquic_alarmset *,
|
|||
int
|
||||
lsquic_send_ctl_sent_packet (lsquic_send_ctl_t *, struct lsquic_packet_out *);
|
||||
|
||||
void
|
||||
lsquic_send_ctl_mtu_not_sent (struct lsquic_send_ctl *ctl,
|
||||
struct lsquic_packet_out *);
|
||||
|
||||
int
|
||||
lsquic_send_ctl_got_ack (lsquic_send_ctl_t *, const struct ack_info *,
|
||||
lsquic_time_t, lsquic_time_t);
|
||||
|
|
|
@ -1473,7 +1473,7 @@ verify_cl_on_fin (struct lsquic_stream *stream)
|
|||
if (stream->sm_data_in != 0 && stream->sm_cont_len != stream->sm_data_in)
|
||||
{
|
||||
lconn = stream->conn_pub->lconn;
|
||||
lconn->cn_if->ci_abort_error(lconn, 1, HEC_GENERAL_PROTOCOL_ERROR,
|
||||
lconn->cn_if->ci_abort_error(lconn, 1, HEC_MESSAGE_ERROR,
|
||||
"number of bytes in DATA frames of stream %"PRIu64" is %llu, "
|
||||
"while content-length specified of %llu", stream->id,
|
||||
stream->sm_data_in, stream->sm_cont_len);
|
||||
|
@ -4811,7 +4811,7 @@ verify_cl_on_new_data_frame (struct lsquic_stream *stream,
|
|||
if (stream->sm_data_in > stream->sm_cont_len)
|
||||
{
|
||||
lconn = stream->conn_pub->lconn;
|
||||
lconn->cn_if->ci_abort_error(lconn, 1, HEC_GENERAL_PROTOCOL_ERROR,
|
||||
lconn->cn_if->ci_abort_error(lconn, 1, HEC_MESSAGE_ERROR,
|
||||
"number of bytes in DATA frames of stream %"PRIu64" exceeds "
|
||||
"content-length limit of %llu", stream->id, stream->sm_cont_len);
|
||||
}
|
||||
|
|
|
@ -29,12 +29,15 @@ find_free_slot (uint32_t slots)
|
|||
}
|
||||
|
||||
|
||||
/* Returns 0 on success, 1 if dup, -1 if out of elements */
|
||||
/* When capacity is reached, smallest element is removed. When the number
|
||||
* of elements in a single range cannot be represented by te_count, an
|
||||
* error is returned. This is the only error this function returns.
|
||||
*/
|
||||
int
|
||||
lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
|
||||
uint32_t packno)
|
||||
{
|
||||
struct trechist_elem *el, *prev;
|
||||
struct trechist_elem *el, *prev, *cur, *next;
|
||||
unsigned idx;
|
||||
|
||||
if (*mask == 0)
|
||||
|
@ -53,17 +56,22 @@ lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
|
|||
if (packno > TE_HIGH(el) + 1)
|
||||
goto insert_before;
|
||||
if (packno == el->te_low - 1)
|
||||
{
|
||||
if (el->te_next && el->te_low == TE_HIGH(&elems[el->te_next]) + 2)
|
||||
{
|
||||
if (el->te_count + elems[el->te_next].te_count - 1 > UCHAR_MAX)
|
||||
return -1;
|
||||
*mask &= ~(1u << el->te_next);
|
||||
el->te_count += elems[el->te_next].te_count + 1;
|
||||
el->te_low = elems[el->te_next].te_low;
|
||||
el->te_next = elems[el->te_next].te_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (el->te_count == UCHAR_MAX)
|
||||
return -1;
|
||||
--el->te_low;
|
||||
++el->te_count;
|
||||
if (el->te_next && el->te_low == TE_HIGH(&elems[el->te_next]) + 1)
|
||||
{
|
||||
*mask &= ~(1u << el->te_next);
|
||||
el->te_count += elems[el->te_next].te_count;
|
||||
el->te_low = elems[el->te_next].te_low;
|
||||
el->te_next = elems[el->te_next].te_next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -75,15 +83,18 @@ lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
|
|||
return 0;
|
||||
}
|
||||
if (packno >= el->te_low && packno <= TE_HIGH(el))
|
||||
return 1; /* Dup */
|
||||
return 0; /* Dup */
|
||||
if (!el->te_next)
|
||||
break; /* insert tail */
|
||||
prev = el;
|
||||
el = &elems[el->te_next];
|
||||
}
|
||||
|
||||
if (*mask == ((1u << TRECHIST_MAX_RANGES) - 1))
|
||||
return -1;
|
||||
if (*mask == TRECHIST_MAX_RANGES_MASK)
|
||||
/* No need to insert element smaller than the smallest element
|
||||
* already in our list. The new element "overflows".
|
||||
*/
|
||||
return 0;
|
||||
|
||||
idx = find_free_slot(*mask);
|
||||
elems[idx].te_low = packno;
|
||||
|
@ -95,10 +106,17 @@ lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
|
|||
|
||||
insert_before:
|
||||
|
||||
if (*mask == ((1u << TRECHIST_MAX_RANGES) - 1))
|
||||
return -1;
|
||||
|
||||
if (*mask != TRECHIST_MAX_RANGES_MASK)
|
||||
idx = find_free_slot(*mask);
|
||||
else
|
||||
{ /* Drop last element and reuse its slot */
|
||||
for (next = &elems[el->te_next], cur = el; next->te_next;
|
||||
cur = next, next = &elems[cur->te_next])
|
||||
;
|
||||
idx = cur->te_next;
|
||||
cur->te_next = 0;
|
||||
}
|
||||
|
||||
*mask |= 1u << idx;;
|
||||
if (el == elems)
|
||||
{
|
||||
|
@ -159,7 +177,8 @@ lsquic_trechist_next (void *iter_p)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
/* First TRECHIST_MAX_RANGES ranges are copied */
|
||||
void
|
||||
lsquic_trechist_copy_ranges (trechist_mask_t *mask,
|
||||
struct trechist_elem *elems, void *src_rechist,
|
||||
const struct lsquic_packno_range * (*first) (void *),
|
||||
|
@ -182,19 +201,13 @@ lsquic_trechist_copy_ranges (trechist_mask_t *mask,
|
|||
el->te_next = i + 1;
|
||||
}
|
||||
|
||||
if (!range && el)
|
||||
{
|
||||
if (el)
|
||||
el->te_next = 0;
|
||||
|
||||
if (i < 32)
|
||||
*mask = (1u << i) - 1;
|
||||
return 0;
|
||||
}
|
||||
else if (!el)
|
||||
{
|
||||
*mask = 0;
|
||||
return 0; /* Must have been an empty */
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
*mask = UINT32_MAX;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ struct lsquic_packno_range;
|
|||
* UCHAR_MAX, which is how many different values can fit into te_next.
|
||||
*/
|
||||
#define TRECHIST_MAX_RANGES 16
|
||||
#define TRECHIST_MAX_RANGES_MASK ((1u << TRECHIST_MAX_RANGES) - 1)
|
||||
|
||||
struct trechist_elem
|
||||
{
|
||||
|
@ -58,7 +59,7 @@ lsquic_trechist_first (void *iter);
|
|||
const struct lsquic_packno_range *
|
||||
lsquic_trechist_next (void *iter);
|
||||
|
||||
int
|
||||
void
|
||||
lsquic_trechist_copy_ranges (trechist_mask_t *mask /* This gets overwritten */,
|
||||
struct trechist_elem *elems, void *src_rechist,
|
||||
const struct lsquic_packno_range * (*first) (void *),
|
||||
|
|
|
@ -19,9 +19,9 @@ static const unsigned char version_tags[N_LSQVER][4] =
|
|||
[LSQVER_098] = { 'Q', '0', '9', '8', },
|
||||
#endif
|
||||
[LSQVER_ID27] = { 0xFF, 0, 0, 27, },
|
||||
[LSQVER_ID28] = { 0xFF, 0, 0, 28, },
|
||||
[LSQVER_ID29] = { 0xFF, 0, 0, 29, },
|
||||
[LSQVER_ID32] = { 0xFF, 0, 0, 32, },
|
||||
[LSQVER_ID34] = { 0xFF, 0, 0, 34, },
|
||||
[LSQVER_I001] = { 0, 0, 0, 1, },
|
||||
[LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
|
||||
};
|
||||
|
||||
|
@ -59,9 +59,9 @@ const char *const lsquic_ver2str[N_LSQVER] = {
|
|||
[LSQVER_098] = "Q098",
|
||||
#endif
|
||||
[LSQVER_ID27] = "FF00001B",
|
||||
[LSQVER_ID28] = "FF00001C",
|
||||
[LSQVER_ID29] = "FF00001D",
|
||||
[LSQVER_ID32] = "FF000020",
|
||||
[LSQVER_ID34] = "FF000022",
|
||||
[LSQVER_I001] = "00000001",
|
||||
[LSQVER_VERNEG] = "FAFAFAFA",
|
||||
};
|
||||
|
||||
|
|
|
@ -1141,9 +1141,9 @@ fuzz_guided_pwritev_testing (const char *input)
|
|||
case 1: version = LSQVER_046; break;
|
||||
case 2: version = LSQVER_050; break;
|
||||
case 3: version = LSQVER_ID27; break;
|
||||
case 4: version = LSQVER_ID28; break;
|
||||
case 4: version = LSQVER_ID29; break;
|
||||
default:
|
||||
case 5: version = LSQVER_ID29; break;
|
||||
case 5: version = LSQVER_ID34; break;
|
||||
}
|
||||
|
||||
sched_immed = !!(buf[8] & 0x08);
|
||||
|
|
|
@ -16,6 +16,32 @@
|
|||
#include "lsquic_trechist.h"
|
||||
|
||||
|
||||
struct str_range_iter
|
||||
{
|
||||
char *str;
|
||||
struct lsquic_packno_range range;
|
||||
};
|
||||
|
||||
|
||||
static const struct lsquic_packno_range *
|
||||
next_str_range (void *ctx)
|
||||
{
|
||||
struct str_range_iter *const str_iter = ctx;
|
||||
|
||||
if (str_iter->str && str_iter->str[0] == '[')
|
||||
{
|
||||
str_iter->range.high = strtoul(str_iter->str + 1, &str_iter->str, 10);
|
||||
assert('-' == *str_iter->str);
|
||||
str_iter->range.low = strtoul(str_iter->str + 1, &str_iter->str, 10);
|
||||
assert(']' == *str_iter->str);
|
||||
++str_iter->str;
|
||||
return &str_iter->range;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_clone (trechist_mask_t src_mask, struct trechist_elem *src_elems)
|
||||
{
|
||||
|
@ -23,14 +49,12 @@ test_clone (trechist_mask_t src_mask, struct trechist_elem *src_elems)
|
|||
struct trechist_elem *hist_elems;
|
||||
const struct lsquic_packno_range *ranges[2];
|
||||
struct trechist_iter iters[2];
|
||||
int s;
|
||||
|
||||
hist_elems = malloc(sizeof(hist_elems[0]) * TRECHIST_MAX_RANGES);
|
||||
|
||||
lsquic_trechist_iter(&iters[0], src_mask, src_elems);
|
||||
s = lsquic_trechist_copy_ranges(&hist_mask, hist_elems, &iters[0],
|
||||
lsquic_trechist_copy_ranges(&hist_mask, hist_elems, &iters[0],
|
||||
lsquic_trechist_first, lsquic_trechist_next);
|
||||
assert(s == 0);
|
||||
|
||||
lsquic_trechist_iter(&iters[0], src_mask, src_elems);
|
||||
lsquic_trechist_iter(&iters[1], hist_mask, hist_elems);
|
||||
|
@ -254,10 +278,6 @@ basic_test (void)
|
|||
s = lsquic_trechist_insert(&hist_mask, hist_elems, 1);
|
||||
assert(("inserting packet number one is successful", 0 == s));
|
||||
|
||||
s = lsquic_trechist_insert(&hist_mask, hist_elems, 1);
|
||||
assert(("inserting packet number one again results in duplicate error",
|
||||
s == 1));
|
||||
|
||||
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
||||
range = lsquic_trechist_first(&iter);
|
||||
assert(("first range returned correctly", range));
|
||||
|
@ -338,18 +358,168 @@ test_limits (void)
|
|||
s = lsquic_trechist_insert(&hist_mask, hist_elems, i);
|
||||
assert(s == -1); /* Overflow */
|
||||
|
||||
for (i = 0; i < TRECHIST_MAX_RANGES - 1; ++i)
|
||||
/* Always successful inserting new entries: */
|
||||
for (i = 0; i < TRECHIST_MAX_RANGES * 2; ++i)
|
||||
{
|
||||
s = lsquic_trechist_insert(&hist_mask, hist_elems, 1000 + 2 * i);
|
||||
assert(s == 0);
|
||||
}
|
||||
|
||||
s = lsquic_trechist_insert(&hist_mask, hist_elems, 1000 + 2 * i);
|
||||
assert(s == -1); /* Out of ranges */
|
||||
/* Always successful inserting new entries in descending order, too: */
|
||||
for (i = 0; i < TRECHIST_MAX_RANGES * 2; ++i)
|
||||
{
|
||||
s = lsquic_trechist_insert(&hist_mask, hist_elems, 10000 - 2 * i);
|
||||
assert(s == 0);
|
||||
}
|
||||
|
||||
/* Test merge where count exceeds max: */
|
||||
hist_mask = 0;
|
||||
lsquic_trechist_copy_ranges(&hist_mask, hist_elems,
|
||||
& (struct str_range_iter) { .str = "[400-202][200-1]", },
|
||||
next_str_range, next_str_range);
|
||||
s = lsquic_trechist_insert(&hist_mask, hist_elems, 201);
|
||||
assert(s == -1);
|
||||
|
||||
free(hist_elems);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_overflow (void)
|
||||
{
|
||||
trechist_mask_t mask;
|
||||
struct trechist_elem *elems;
|
||||
int s;
|
||||
char buf[0x1000];
|
||||
|
||||
struct str_range_iter str_iter = { .str =
|
||||
"[395-390]" /* 1 */
|
||||
"[385-380]"
|
||||
"[375-370]"
|
||||
"[365-360]"
|
||||
"[355-350]" /* 5 */
|
||||
"[345-340]"
|
||||
"[335-330]"
|
||||
"[325-320]"
|
||||
"[315-310]"
|
||||
"[305-300]" /* 10 */
|
||||
"[295-290]"
|
||||
"[285-280]"
|
||||
"[275-270]"
|
||||
"[265-260]"
|
||||
"[255-250]" /* 15 */
|
||||
"[245-240]" /* 16 */
|
||||
"[235-230]" /* Overflow vvvvvv */
|
||||
"[225-220]"
|
||||
"[215-210]"
|
||||
"[205-200]"
|
||||
"[195-190]"
|
||||
"[185-180]" };
|
||||
|
||||
elems = malloc(sizeof(elems[0]) * TRECHIST_MAX_RANGES);
|
||||
lsquic_trechist_copy_ranges(&mask, elems, &str_iter, next_str_range,
|
||||
next_str_range);
|
||||
|
||||
rechist2str(mask, elems, buf, sizeof(buf));
|
||||
assert(0 == strcmp(buf,
|
||||
"[395-390]" /* 1 */
|
||||
"[385-380]"
|
||||
"[375-370]"
|
||||
"[365-360]"
|
||||
"[355-350]" /* 5 */
|
||||
"[345-340]"
|
||||
"[335-330]"
|
||||
"[325-320]"
|
||||
"[315-310]"
|
||||
"[305-300]" /* 10 */
|
||||
"[295-290]"
|
||||
"[285-280]"
|
||||
"[275-270]"
|
||||
"[265-260]"
|
||||
"[255-250]" /* 15 */
|
||||
"[245-240]" /* 16 */));
|
||||
|
||||
s = lsquic_trechist_insert(&mask, elems, 400);
|
||||
assert(s == 0);
|
||||
rechist2str(mask, elems, buf, sizeof(buf));
|
||||
assert(0 == strcmp(buf,
|
||||
"[400-400]"
|
||||
"[395-390]"
|
||||
"[385-380]"
|
||||
"[375-370]"
|
||||
"[365-360]"
|
||||
"[355-350]"
|
||||
"[345-340]"
|
||||
"[335-330]"
|
||||
"[325-320]"
|
||||
"[315-310]"
|
||||
"[305-300]"
|
||||
"[295-290]"
|
||||
"[285-280]"
|
||||
"[275-270]"
|
||||
"[265-260]"
|
||||
"[255-250]"
|
||||
));
|
||||
|
||||
/* One more for a good measure */
|
||||
s = lsquic_trechist_insert(&mask, elems, 402);
|
||||
assert(s == 0);
|
||||
rechist2str(mask, elems, buf, sizeof(buf));
|
||||
assert(0 == strcmp(buf,
|
||||
"[402-402]"
|
||||
"[400-400]"
|
||||
"[395-390]"
|
||||
"[385-380]"
|
||||
"[375-370]"
|
||||
"[365-360]"
|
||||
"[355-350]"
|
||||
"[345-340]"
|
||||
"[335-330]"
|
||||
"[325-320]"
|
||||
"[315-310]"
|
||||
"[305-300]"
|
||||
"[295-290]"
|
||||
"[285-280]"
|
||||
"[275-270]"
|
||||
"[265-260]"
|
||||
));
|
||||
|
||||
s = lsquic_trechist_insert(&mask, elems, 401);
|
||||
assert(s == 0);
|
||||
s = lsquic_trechist_insert(&mask, elems, 500);
|
||||
assert(s == 0);
|
||||
s = lsquic_trechist_insert(&mask, elems, 200);
|
||||
assert(s == 0);
|
||||
s = lsquic_trechist_insert(&mask, elems, 267);
|
||||
assert(s == 0);
|
||||
|
||||
/* One more for a good measure */
|
||||
s = lsquic_trechist_insert(&mask, elems, 402);
|
||||
assert(s == 0);
|
||||
rechist2str(mask, elems, buf, sizeof(buf));
|
||||
assert(0 == strcmp(buf,
|
||||
"[500-500]"
|
||||
"[402-400]"
|
||||
"[395-390]"
|
||||
"[385-380]"
|
||||
"[375-370]"
|
||||
"[365-360]"
|
||||
"[355-350]"
|
||||
"[345-340]"
|
||||
"[335-330]"
|
||||
"[325-320]"
|
||||
"[315-310]"
|
||||
"[305-300]"
|
||||
"[295-290]"
|
||||
"[285-280]"
|
||||
"[275-270]"
|
||||
"[267-267]"
|
||||
));
|
||||
|
||||
free(elems);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
@ -357,6 +527,7 @@ main (void)
|
|||
test4();
|
||||
test5();
|
||||
test_limits();
|
||||
test_overflow();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue