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:
Dmitri Tikhonov 2021-02-10 08:51:11 -05:00
parent ac0ce07bd0
commit 26e8f082c9
29 changed files with 411 additions and 178 deletions

View file

@ -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";
}
}
}
}

View file

@ -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 )

View file

@ -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",
};

View file

@ -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)

View file

@ -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;
}

View file

@ -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);

View file

@ -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"

View file

@ -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,

View file

@ -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

View file

@ -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;

View file

@ -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,

View file

@ -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))
return -1;
}
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));

View file

@ -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);

View file

@ -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);
}

View file

@ -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)
@ -54,17 +57,22 @@ lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
goto insert_before;
if (packno == el->te_low - 1)
{
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)
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;
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;
}
return 0;
}
if (packno == TE_HIGH(el) + 1)
@ -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;
}
idx = find_free_slot(*mask);
*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;
}

View file

@ -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 *),

View file

@ -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",
};