mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.17.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 29 support. - [BUGFIX] Check that scheduled packets are also sendable when calculating a connection's "tickable" property. - [BUGFIX] Don't count scheduled packets as in-flight when pacer is checked on tick. - gQUIC: delay calling on_new for pushed stream until headers are available. - Allow nested calls to lsquic_engine_connect().
This commit is contained in:
parent
307ca7fe50
commit
4051ae3a1a
19 changed files with 343 additions and 56 deletions
11
CHANGELOG
11
CHANGELOG
|
@ -1,3 +1,14 @@
|
|||
2020-06-18
|
||||
- 2.17.0
|
||||
- [FEATURE] QUIC and HTTP/3 Internet Draft 29 support.
|
||||
- [BUGFIX] Check that scheduled packets are also sendable when
|
||||
calculating a connection's "tickable" property.
|
||||
- [BUGFIX] Don't count scheduled packets as in-flight when pacer is
|
||||
checked on tick.
|
||||
- gQUIC: delay calling on_new for pushed stream until headers are
|
||||
available.
|
||||
- Allow nested calls to lsquic_engine_connect().
|
||||
|
||||
2020-06-15
|
||||
- 2.16.3
|
||||
- [OPTIMIZATION] Stash up to two reordered packets in IETF mini conn
|
||||
|
|
|
@ -21,7 +21,7 @@ static int
|
|||
select_alpn (SSL *ssl, const unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen, void *arg)
|
||||
{
|
||||
const unsigned char alpn[] = "\x5h3-27\x5h3-28";
|
||||
const unsigned char alpn[] = "\x5h3-27\x5h3-28\x5h3-29";
|
||||
int r;
|
||||
|
||||
r = SSL_select_next_proto((unsigned char **) out, outlen, in, inlen,
|
||||
|
|
|
@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
|
|||
author = u'LiteSpeed Technologies'
|
||||
|
||||
# The short X.Y version
|
||||
version = u'2.16'
|
||||
version = u'2.17'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'2.16.3'
|
||||
release = u'2.17.0'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
|
|
@ -24,8 +24,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 16
|
||||
#define LSQUIC_PATCH_VERSION 3
|
||||
#define LSQUIC_MINOR_VERSION 17
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
@ -86,6 +86,11 @@ enum lsquic_version
|
|||
*/
|
||||
LSQVER_ID28,
|
||||
|
||||
/**
|
||||
* IETF QUIC Draft-29
|
||||
*/
|
||||
LSQVER_ID29,
|
||||
|
||||
/**
|
||||
* Special version to trigger version negotiation.
|
||||
* [draft-ietf-quic-transport-11], Section 3.
|
||||
|
@ -114,10 +119,10 @@ enum lsquic_version
|
|||
#define LSQUIC_GQUIC_HEADER_VERSIONS (1 << LSQVER_043)
|
||||
|
||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
|
||||
| (1 << LSQVER_VERNEG))
|
||||
| (1 << LSQVER_ID29) | (1 << LSQVER_VERNEG))
|
||||
|
||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
|
||||
| (1 << LSQVER_VERNEG))
|
||||
| (1 << LSQVER_ID29) | (1 << LSQVER_VERNEG))
|
||||
|
||||
enum lsquic_hsk_status
|
||||
{
|
||||
|
|
|
@ -334,6 +334,7 @@ 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_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_050 ? &lsquic_enc_session_common_gquic_2 : \
|
||||
&lsquic_enc_session_common_gquic_1 )
|
||||
|
|
|
@ -73,7 +73,8 @@ static const struct alpn_map {
|
|||
} s_h3_alpns[] = {
|
||||
{ LSQVER_ID27, (unsigned char *) "\x05h3-27", },
|
||||
{ LSQVER_ID28, (unsigned char *) "\x05h3-28", },
|
||||
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-28", },
|
||||
{ LSQVER_ID29, (unsigned char *) "\x05h3-29", },
|
||||
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-29", },
|
||||
};
|
||||
|
||||
struct enc_sess_iquic;
|
||||
|
@ -935,7 +936,8 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
|
|||
hp = &enc_sess->esi_hsk_hps[ENC_LEV_CLEAR];
|
||||
|
||||
HKDF_extract(hsk_secret, &hsk_secret_sz, md, cid->idbuf, cid->len,
|
||||
HSK_SALT, HSK_SALT_SZ);
|
||||
enc_sess->esi_conn->cn_version < LSQVER_ID29
|
||||
? HSK_SALT_PRE29 : HSK_SALT, HSK_SALT_SZ);
|
||||
if (enc_sess->esi_flags & ESI_LOG_SECRETS)
|
||||
{
|
||||
LSQ_DEBUG("handshake salt: %s", HEXSTR(HSK_SALT, HSK_SALT_SZ, hexbuf));
|
||||
|
@ -1177,6 +1179,13 @@ iquic_esfi_init_server (enc_session_t *enc_session_p)
|
|||
LSQ_INFO("could not set stream method");
|
||||
return -1;
|
||||
}
|
||||
/* TODO: set to transport parameter string instead of the constant string */
|
||||
if (!SSL_set_quic_early_data_context(enc_sess->esi_ssl,
|
||||
(unsigned char *) "lsquic", 6))
|
||||
{
|
||||
LSQ_INFO("could not set early data context");
|
||||
return -1;
|
||||
}
|
||||
maybe_setup_key_logging(enc_sess);
|
||||
|
||||
transpa_len = gen_trans_params(enc_sess, u.trans_params,
|
||||
|
@ -1756,7 +1765,7 @@ iquic_esfi_destroy (enc_session_t *enc_session_p)
|
|||
struct enc_sess_iquic *const enc_sess = enc_session_p;
|
||||
struct frab_list *fral;
|
||||
LSQ_DEBUG("iquic_esfi_destroy");
|
||||
|
||||
|
||||
for (fral = enc_sess->esi_frals; fral < enc_sess->esi_frals
|
||||
+ sizeof(enc_sess->esi_frals) / sizeof(enc_sess->esi_frals[0]);
|
||||
++fral)
|
||||
|
@ -3004,3 +3013,23 @@ const struct lsquic_stream_if lsquic_mini_cry_sm_if =
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const unsigned char *const lsquic_retry_key_buf[N_IETF_RETRY_VERSIONS] =
|
||||
{
|
||||
/* [draft-ietf-quic-tls-25] Section 5.8 */
|
||||
(unsigned char *)
|
||||
"\x4d\x32\xec\xdb\x2a\x21\x33\xc8\x41\xe4\x04\x3d\xf2\x7d\x44\x30",
|
||||
/* [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",
|
||||
};
|
||||
|
||||
|
||||
const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS] =
|
||||
{
|
||||
/* [draft-ietf-quic-tls-25] Section 5.8 */
|
||||
(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",
|
||||
};
|
||||
|
|
|
@ -135,7 +135,9 @@ force_close_conn (lsquic_engine_t *engine, lsquic_conn_t *conn);
|
|||
#define ENGINE_CALLS_INCR(e)
|
||||
#endif
|
||||
|
||||
/* Nested calls to LSQUIC are not supported */
|
||||
/* Nested calls to some LSQUIC functions are not supported. Functions that
|
||||
* iterate over connections cannot be nested.
|
||||
*/
|
||||
#define ENGINE_IN(e) do { \
|
||||
assert(!((e)->pub.enp_flags & ENPUB_PROC)); \
|
||||
(e)->pub.enp_flags |= ENPUB_PROC; \
|
||||
|
@ -270,7 +272,7 @@ struct lsquic_engine
|
|||
int last_tick_diff;
|
||||
#endif
|
||||
struct crand crand;
|
||||
EVP_AEAD_CTX retry_aead_ctx;
|
||||
EVP_AEAD_CTX retry_aead_ctx[N_IETF_RETRY_VERSIONS];
|
||||
};
|
||||
|
||||
|
||||
|
@ -483,6 +485,7 @@ lsquic_engine_new (unsigned flags,
|
|||
{
|
||||
lsquic_engine_t *engine;
|
||||
size_t alpn_len;
|
||||
unsigned i;
|
||||
char err_buf[100];
|
||||
|
||||
if (!api->ea_packets_out)
|
||||
|
@ -691,14 +694,17 @@ lsquic_engine_new (unsigned flags,
|
|||
#if LSQUIC_CONN_STATS
|
||||
engine->stats_fh = api->ea_stats_fh;
|
||||
#endif
|
||||
if (1 != EVP_AEAD_CTX_init(&engine->retry_aead_ctx, EVP_aead_aes_128_gcm(),
|
||||
IETF_RETRY_KEY_BUF, IETF_RETRY_KEY_SZ, 16, NULL))
|
||||
{
|
||||
LSQ_ERROR("could not initialize retry AEAD ctx");
|
||||
lsquic_engine_destroy(engine);
|
||||
return NULL;
|
||||
}
|
||||
engine->pub.enp_retry_aead_ctx = &engine->retry_aead_ctx;
|
||||
for (i = 0; i < sizeof(engine->retry_aead_ctx)
|
||||
/ sizeof(engine->retry_aead_ctx[0]); ++i)
|
||||
if (1 != EVP_AEAD_CTX_init(&engine->retry_aead_ctx[i],
|
||||
EVP_aead_aes_128_gcm(), lsquic_retry_key_buf[i],
|
||||
IETF_RETRY_KEY_SZ, 16, NULL))
|
||||
{
|
||||
LSQ_ERROR("could not initialize retry AEAD ctx #%u", i);
|
||||
lsquic_engine_destroy(engine);
|
||||
return NULL;
|
||||
}
|
||||
engine->pub.enp_retry_aead_ctx = engine->retry_aead_ctx;
|
||||
|
||||
LSQ_INFO("instantiated engine");
|
||||
return engine;
|
||||
|
@ -1421,6 +1427,7 @@ lsquic_engine_destroy (lsquic_engine_t *engine)
|
|||
{
|
||||
struct lsquic_hash_elem *el;
|
||||
lsquic_conn_t *conn;
|
||||
unsigned i;
|
||||
|
||||
LSQ_DEBUG("destroying engine");
|
||||
#ifndef NDEBUG
|
||||
|
@ -1515,8 +1522,9 @@ lsquic_engine_destroy (lsquic_engine_t *engine)
|
|||
#if LSQUIC_COUNT_ENGINE_CALLS
|
||||
LSQ_NOTICE("number of calls into the engine: %lu", engine->n_engine_calls);
|
||||
#endif
|
||||
if (engine->pub.enp_retry_aead_ctx)
|
||||
EVP_AEAD_CTX_cleanup(engine->pub.enp_retry_aead_ctx);
|
||||
for (i = 0; i < sizeof(engine->retry_aead_ctx)
|
||||
/ sizeof(engine->retry_aead_ctx[0]); ++i)
|
||||
EVP_AEAD_CTX_cleanup(&engine->pub.enp_retry_aead_ctx[i]);
|
||||
free(engine->pub.enp_alpn);
|
||||
free(engine);
|
||||
}
|
||||
|
@ -1579,7 +1587,7 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
|
|||
unsigned flags, versions;
|
||||
int is_ipv4;
|
||||
|
||||
ENGINE_IN(engine);
|
||||
ENGINE_CALLS_INCR(engine);
|
||||
|
||||
if (engine->flags & ENG_SERVER)
|
||||
{
|
||||
|
@ -1650,7 +1658,6 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
|
|||
lsquic_conn_set_ctx(conn, conn_ctx);
|
||||
conn->cn_if->ci_client_call_on_new(conn);
|
||||
end:
|
||||
ENGINE_OUT(engine);
|
||||
return conn;
|
||||
err:
|
||||
conn = NULL;
|
||||
|
|
|
@ -4060,7 +4060,7 @@ full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
|
|||
return -1;
|
||||
}
|
||||
|
||||
pushed_stream = new_stream(conn, stream_id, SCF_CALL_ON_NEW);
|
||||
pushed_stream = new_stream(conn, stream_id, 0);
|
||||
if (!pushed_stream)
|
||||
{
|
||||
LSQ_WARN("cannot create stream: %s", strerror(errno));
|
||||
|
@ -4085,6 +4085,7 @@ full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
|
|||
return -1;
|
||||
}
|
||||
|
||||
lsquic_stream_call_on_new(pushed_stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4187,10 +4188,10 @@ full_conn_ci_is_tickable (lsquic_conn_t *lconn)
|
|||
LSQ_DEBUG("tickable: flags: 0x%X", conn->fc_flags & send_flags);
|
||||
goto check_can_send;
|
||||
}
|
||||
if (lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) > 0)
|
||||
if (lsquic_send_ctl_has_sendable(&conn->fc_send_ctl))
|
||||
{
|
||||
LSQ_DEBUG("tickable: has scheduled packets");
|
||||
return 1; /* Don't check can_send */
|
||||
LSQ_DEBUG("tickable: has sendable packets");
|
||||
return 1; /* Don't check can_send: already on scheduled queue */
|
||||
}
|
||||
if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||
&& lsquic_send_ctl_has_buffered(&conn->fc_send_ctl))
|
||||
|
|
|
@ -410,6 +410,7 @@ struct ietf_full_conn
|
|||
struct ver_neg
|
||||
ifcli_ver_neg;
|
||||
uint64_t ifcli_max_push_id;
|
||||
uint64_t ifcli_min_goaway_stream_id;
|
||||
enum {
|
||||
IFCLI_PUSH_ENABLED = 1 << 0,
|
||||
IFCLI_HSK_SENT_OR_DEL = 1 << 1,
|
||||
|
@ -2889,13 +2890,19 @@ try_to_begin_migration (struct ietf_full_conn *conn,
|
|||
struct sockaddr_in6 v6;
|
||||
} sockaddr;
|
||||
|
||||
if ((params->tp_set & (1 << TPI_DISABLE_ACTIVE_MIGRATION))
|
||||
|| !conn->ifc_settings->es_allow_migration)
|
||||
if (!conn->ifc_settings->es_allow_migration)
|
||||
{
|
||||
if (params->tp_set & (1 << TPI_DISABLE_ACTIVE_MIGRATION))
|
||||
LSQ_DEBUG("TP disables migration: retire PreferredAddress CID");
|
||||
else
|
||||
LSQ_DEBUG("Migration not allowed: retire PreferredAddress CID");
|
||||
LSQ_DEBUG("Migration not allowed: retire PreferredAddress CID");
|
||||
return BM_NOT_MIGRATING;
|
||||
}
|
||||
|
||||
if (conn->ifc_conn.cn_version <= LSQVER_ID28 /* 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. */
|
||||
&& (params->tp_set & (1 << TPI_DISABLE_ACTIVE_MIGRATION)))
|
||||
{
|
||||
LSQ_DEBUG("TP disables migration: retire PreferredAddress CID");
|
||||
return BM_NOT_MIGRATING;
|
||||
}
|
||||
|
||||
|
@ -3547,10 +3554,10 @@ ietf_full_conn_ci_is_tickable (struct lsquic_conn *lconn)
|
|||
LSQ_DEBUG("tickable: send flags: 0x%X", conn->ifc_send_flags);
|
||||
goto check_can_send;
|
||||
}
|
||||
if (lsquic_send_ctl_n_scheduled(&conn->ifc_send_ctl) > 0)
|
||||
if (lsquic_send_ctl_has_sendable(&conn->ifc_send_ctl))
|
||||
{
|
||||
LSQ_DEBUG("tickable: has scheduled packets");
|
||||
return 1; /* Don't check can_send */
|
||||
LSQ_DEBUG("tickable: has sendable packets");
|
||||
return 1; /* Don't check can_send: already on scheduled queue */
|
||||
}
|
||||
if (conn->ifc_conn.cn_flags & LSCONN_SEND_BLOCKED)
|
||||
{
|
||||
|
@ -6046,6 +6053,7 @@ verify_retry_packet (struct ietf_full_conn *conn,
|
|||
{
|
||||
unsigned char *pseudo_packet;
|
||||
size_t out_len, ad_len;
|
||||
unsigned ret_ver;
|
||||
int verified;
|
||||
|
||||
if (1 + CUR_DCID(conn)->len + packet_in->pi_data_sz > 0x1000)
|
||||
|
@ -6070,11 +6078,13 @@ verify_retry_packet (struct ietf_full_conn *conn,
|
|||
memcpy(pseudo_packet + 1 + CUR_DCID(conn)->len, packet_in->pi_data,
|
||||
packet_in->pi_data_sz);
|
||||
|
||||
ret_ver = lsquic_version_2_retryver(conn->ifc_conn.cn_version);
|
||||
out_len = 0;
|
||||
ad_len = 1 + CUR_DCID(conn)->len + packet_in->pi_data_sz - 16;
|
||||
verified = 1 == EVP_AEAD_CTX_open(conn->ifc_enpub->enp_retry_aead_ctx,
|
||||
verified = 1 == EVP_AEAD_CTX_open(
|
||||
&conn->ifc_enpub->enp_retry_aead_ctx[ret_ver],
|
||||
pseudo_packet + ad_len, &out_len, out_len,
|
||||
IETF_RETRY_NONCE_BUF, IETF_RETRY_NONCE_SZ,
|
||||
lsquic_retry_nonce_buf[ret_ver], IETF_RETRY_NONCE_SZ,
|
||||
pseudo_packet + ad_len, 16, pseudo_packet, ad_len)
|
||||
&& out_len == 0;
|
||||
|
||||
|
@ -7472,7 +7482,7 @@ on_setting (void *ctx, uint64_t setting_id, uint64_t value)
|
|||
|
||||
|
||||
static void
|
||||
on_goaway_server (void *ctx, uint64_t stream_id)
|
||||
on_goaway_server_27 (void *ctx, uint64_t stream_id)
|
||||
{
|
||||
struct ietf_full_conn *const conn = ctx;
|
||||
ABORT_QUIETLY(1, HEC_FRAME_UNEXPECTED,
|
||||
|
@ -7481,7 +7491,7 @@ on_goaway_server (void *ctx, uint64_t stream_id)
|
|||
|
||||
|
||||
static void
|
||||
on_goaway (void *ctx, uint64_t stream_id)
|
||||
on_goaway_client_28 (void *ctx, uint64_t stream_id)
|
||||
{
|
||||
struct ietf_full_conn *const conn = ctx;
|
||||
struct lsquic_stream *stream;
|
||||
|
@ -7520,6 +7530,68 @@ on_goaway (void *ctx, uint64_t stream_id)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
on_goaway_client (void *ctx, uint64_t stream_id)
|
||||
{
|
||||
struct ietf_full_conn *const conn = ctx;
|
||||
struct lsquic_stream *stream;
|
||||
struct lsquic_hash_elem *el;
|
||||
enum stream_id_type sit;
|
||||
|
||||
sit = stream_id & SIT_MASK;
|
||||
if (sit != SIT_BIDI_CLIENT)
|
||||
{
|
||||
ABORT_QUIETLY(1, HEC_ID_ERROR,
|
||||
"stream ID %"PRIu64" in GOAWAY frame", stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
LSQ_DEBUG("received GOAWAY frame, last good stream ID: %"PRIu64, stream_id);
|
||||
|
||||
if (conn->ifc_conn.cn_flags & LSCONN_PEER_GOING_AWAY)
|
||||
{
|
||||
if (stream_id == conn->ifc_u.cli.ifcli_min_goaway_stream_id)
|
||||
{
|
||||
LSQ_DEBUG("ignore duplicate GOAWAY frame");
|
||||
return;
|
||||
}
|
||||
if (stream_id > conn->ifc_u.cli.ifcli_min_goaway_stream_id)
|
||||
{
|
||||
ABORT_QUIETLY(1, HEC_ID_ERROR,
|
||||
"stream ID %"PRIu64" is larger than one already seen in a "
|
||||
"previous GOAWAY frame, %"PRIu64, stream_id,
|
||||
conn->ifc_u.cli.ifcli_min_goaway_stream_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->ifc_u.cli.ifcli_min_goaway_stream_id = stream_id;
|
||||
conn->ifc_conn.cn_flags |= LSCONN_PEER_GOING_AWAY;
|
||||
if (conn->ifc_enpub->enp_stream_if->on_goaway_received)
|
||||
conn->ifc_enpub->enp_stream_if->on_goaway_received(&conn->ifc_conn);
|
||||
}
|
||||
|
||||
for (el = lsquic_hash_first(conn->ifc_pub.all_streams); el;
|
||||
el = lsquic_hash_next(conn->ifc_pub.all_streams))
|
||||
{
|
||||
stream = lsquic_hashelem_getdata(el);
|
||||
if (stream->id >= stream_id
|
||||
&& (stream->id & SIT_MASK) == SIT_BIDI_CLIENT)
|
||||
{
|
||||
lsquic_stream_received_goaway(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
on_goaway_server (void *ctx, uint64_t max_push_id)
|
||||
{
|
||||
/* TODO: cancel pushes? */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
on_unexpected_frame (void *ctx, uint64_t frame_type)
|
||||
{
|
||||
|
@ -7529,7 +7601,49 @@ on_unexpected_frame (void *ctx, uint64_t frame_type)
|
|||
}
|
||||
|
||||
|
||||
static const struct hcsi_callbacks hcsi_callbacks_server =
|
||||
static const struct hcsi_callbacks hcsi_callbacks_server_27 =
|
||||
{
|
||||
.on_cancel_push = on_cancel_push,
|
||||
.on_max_push_id = on_max_push_id,
|
||||
.on_settings_frame = on_settings_frame,
|
||||
.on_setting = on_setting,
|
||||
.on_goaway = on_goaway_server_27,
|
||||
.on_unexpected_frame = on_unexpected_frame,
|
||||
};
|
||||
|
||||
static const struct hcsi_callbacks hcsi_callbacks_client_27 =
|
||||
{
|
||||
.on_cancel_push = on_cancel_push,
|
||||
.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,
|
||||
};
|
||||
|
||||
|
||||
static const struct hcsi_callbacks hcsi_callbacks_server_28 =
|
||||
{
|
||||
.on_cancel_push = on_cancel_push,
|
||||
.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,
|
||||
};
|
||||
|
||||
static const struct hcsi_callbacks hcsi_callbacks_client_28 =
|
||||
{
|
||||
.on_cancel_push = on_cancel_push,
|
||||
.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_unexpected_frame = on_unexpected_frame,
|
||||
};
|
||||
|
||||
|
||||
static const struct hcsi_callbacks hcsi_callbacks_server_29 =
|
||||
{
|
||||
.on_cancel_push = on_cancel_push,
|
||||
.on_max_push_id = on_max_push_id,
|
||||
|
@ -7539,13 +7653,13 @@ static const struct hcsi_callbacks hcsi_callbacks_server =
|
|||
.on_unexpected_frame = on_unexpected_frame,
|
||||
};
|
||||
|
||||
static const struct hcsi_callbacks hcsi_callbacks =
|
||||
static const struct hcsi_callbacks hcsi_callbacks_client_29 =
|
||||
{
|
||||
.on_cancel_push = on_cancel_push,
|
||||
.on_max_push_id = on_max_push_id_client,
|
||||
.on_settings_frame = on_settings_frame,
|
||||
.on_setting = on_setting,
|
||||
.on_goaway = on_goaway,
|
||||
.on_goaway = on_goaway_client,
|
||||
.on_unexpected_frame = on_unexpected_frame,
|
||||
};
|
||||
|
||||
|
@ -7554,10 +7668,36 @@ static lsquic_stream_ctx_t *
|
|||
hcsi_on_new (void *stream_if_ctx, struct lsquic_stream *stream)
|
||||
{
|
||||
struct ietf_full_conn *const conn = (void *) stream_if_ctx;
|
||||
const struct hcsi_callbacks *callbacks;
|
||||
|
||||
conn->ifc_stream_hcsi = stream;
|
||||
|
||||
switch ((!!(conn->ifc_flags & IFC_SERVER) << 8) | conn->ifc_conn.cn_version)
|
||||
{
|
||||
case (0 << 8) | LSQVER_ID27:
|
||||
callbacks = &hcsi_callbacks_client_27;
|
||||
break;
|
||||
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:
|
||||
callbacks = &hcsi_callbacks_client_29;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
/* fallthru */
|
||||
case (1 << 8) | LSQVER_ID29:
|
||||
callbacks = &hcsi_callbacks_server_29;
|
||||
break;
|
||||
}
|
||||
lsquic_hcsi_reader_init(&conn->ifc_hcsi.reader, &conn->ifc_conn,
|
||||
conn->ifc_flags & IFC_SERVER ? &hcsi_callbacks_server : &hcsi_callbacks,
|
||||
conn);
|
||||
callbacks, conn);
|
||||
lsquic_stream_wantread(stream, 1);
|
||||
return stream_if_ctx;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
/* [draft-ietf-quic-tls-23] Section 5.2 */
|
||||
#define HSK_SALT_BUF "\xc3\xee\xf7\x12\xc7\x2e\xbb\x5a\x11\xa7" \
|
||||
"\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"
|
||||
#define HSK_SALT ((unsigned char *) HSK_SALT_BUF)
|
||||
#define HSK_SALT_PRE29 ((unsigned char *) HSK_SALT_BUF)
|
||||
/* [draft-ietf-quic-tls-29] Section 5.2 */
|
||||
#define HSK_SALT ((unsigned char *) \
|
||||
"\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97" \
|
||||
"\x86\xf1\x9c\x61\x11\xe0\x43\x90\xa8\x99")
|
||||
#define HSK_SALT_SZ (sizeof(HSK_SALT_BUF) - 1)
|
||||
|
||||
#define CLIENT_LABEL "client in"
|
||||
|
|
|
@ -9,7 +9,7 @@ enum trans_error_code
|
|||
{
|
||||
TEC_NO_ERROR = 0x0,
|
||||
TEC_INTERNAL_ERROR = 0x1,
|
||||
TEC_SERVER_BUSY = 0x2,
|
||||
TEC_CONNECTION_REFUSED = 0x2,
|
||||
TEC_FLOW_CONTROL_ERROR = 0x3,
|
||||
TEC_STREAM_LIMIT_ERROR = 0x4,
|
||||
TEC_STREAM_STATE_ERROR = 0x5,
|
||||
|
@ -27,11 +27,12 @@ enum trans_error_code
|
|||
#define MAX_IETF_CONN_DCIDS 8
|
||||
|
||||
/* [draft-ietf-quic-tls-25] Section 5.8 */
|
||||
#define IETF_RETRY_KEY_BUF ((unsigned char *) \
|
||||
"\x4d\x32\xec\xdb\x2a\x21\x33\xc8\x41\xe4\x04\x3d\xf2\x7d\x44\x30")
|
||||
#define IETF_RETRY_KEY_SZ 16
|
||||
#define IETF_RETRY_NONCE_BUF ((unsigned char *) \
|
||||
"\x4d\x16\x11\xd0\x55\x13\xa5\x52\xc5\x87\xd5\x75")
|
||||
#define IETF_RETRY_NONCE_SZ 12
|
||||
|
||||
#define N_IETF_RETRY_VERSIONS 2
|
||||
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)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1623,7 +1623,7 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
|
|||
else if (conn->imc_flags & IMC_BAD_TRANS_PARAMS)
|
||||
{
|
||||
is_app = 0;
|
||||
error_code = TEC_PROTOCOL_VIOLATION;
|
||||
error_code = TEC_TRANSPORT_PARAMETER_ERROR;
|
||||
reason = "bad transport parameters";
|
||||
rlen = 24;
|
||||
}
|
||||
|
|
|
@ -220,6 +220,34 @@ lsquic_cid_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_ID29] = {
|
||||
[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_ID28] = {
|
||||
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
|
|
|
@ -1369,7 +1369,7 @@ lsquic_send_ctl_pacer_blocked (struct lsquic_send_ctl *ctl)
|
|||
{
|
||||
return (ctl->sc_flags & SC_PACE)
|
||||
&& !lsquic_pacer_can_schedule(&ctl->sc_pacer,
|
||||
ctl->sc_n_scheduled + ctl->sc_n_in_flight_all);
|
||||
ctl->sc_n_in_flight_all);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1674,6 +1674,45 @@ send_ctl_maybe_zero_pad (struct lsquic_send_ctl *ctl,
|
|||
}
|
||||
|
||||
|
||||
/* Predict whether lsquic_send_ctl_next_packet_to_send() will return a
|
||||
* packet by mimicking its logic. Returns true if packet will be returned,
|
||||
* false otherwise.
|
||||
*/
|
||||
int
|
||||
lsquic_send_ctl_next_packet_to_send_predict (struct lsquic_send_ctl *ctl)
|
||||
{
|
||||
const struct lsquic_packet_out *packet_out;
|
||||
unsigned n_rtos;
|
||||
|
||||
n_rtos = ~0u;
|
||||
TAILQ_FOREACH(packet_out, &ctl->sc_scheduled_packets, po_next)
|
||||
{
|
||||
if (!(packet_out->po_frame_types & (1 << QUIC_FRAME_ACK))
|
||||
&& 0 == ctl->sc_next_limit
|
||||
&& 0 != (n_rtos == ~0u ? /* Initialize once */
|
||||
(n_rtos = send_ctl_get_n_consec_rtos(ctl)) : n_rtos))
|
||||
{
|
||||
LSQ_DEBUG("send prediction: no, n_rtos: %u", n_rtos);
|
||||
return 0;
|
||||
}
|
||||
if ((packet_out->po_flags & PO_REPACKNO)
|
||||
&& packet_out->po_regen_sz == packet_out->po_data_sz)
|
||||
{
|
||||
LSQ_DEBUG("send prediction: packet %"PRIu64" would be dropped, "
|
||||
"continue", packet_out->po_packno);
|
||||
continue;
|
||||
}
|
||||
LSQ_DEBUG("send prediction: yes, packet %"PRIu64", flags %u, frames 0x%X",
|
||||
packet_out->po_packno, (unsigned) packet_out->po_flags,
|
||||
(unsigned) packet_out->po_frame_types);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LSQ_DEBUG("send prediction: no, no matching scheduled packets");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
lsquic_packet_out_t *
|
||||
lsquic_send_ctl_next_packet_to_send (struct lsquic_send_ctl *ctl, size_t size)
|
||||
{
|
||||
|
@ -1685,6 +1724,9 @@ lsquic_send_ctl_next_packet_to_send (struct lsquic_send_ctl *ctl, size_t size)
|
|||
if (!packet_out)
|
||||
return NULL;
|
||||
|
||||
/* Note: keep logic in this function and in
|
||||
* lsquic_send_ctl_next_packet_to_send_predict() in synch.
|
||||
*/
|
||||
if (!(packet_out->po_frame_types & (1 << QUIC_FRAME_ACK))
|
||||
&& send_ctl_get_n_consec_rtos(ctl))
|
||||
{
|
||||
|
|
|
@ -168,6 +168,9 @@ lsquic_send_ctl_delayed_one (lsquic_send_ctl_t *, struct lsquic_packet_out *);
|
|||
struct lsquic_packet_out *
|
||||
lsquic_send_ctl_next_packet_to_send (struct lsquic_send_ctl *, size_t);
|
||||
|
||||
int
|
||||
lsquic_send_ctl_next_packet_to_send_predict (struct lsquic_send_ctl *);
|
||||
|
||||
void
|
||||
lsquic_send_ctl_expire_all (lsquic_send_ctl_t *ctl);
|
||||
|
||||
|
@ -387,4 +390,9 @@ lsquic_send_ctl_begin_optack_detection (struct lsquic_send_ctl *);
|
|||
void
|
||||
lsquic_send_ctl_path_validated (struct lsquic_send_ctl *);
|
||||
|
||||
/* Has immediately sendable packets */
|
||||
#define lsquic_send_ctl_has_sendable(ctl_) \
|
||||
(lsquic_send_ctl_n_scheduled(ctl_) > 0 \
|
||||
&& lsquic_send_ctl_next_packet_to_send_predict(ctl_))
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1747,6 +1747,14 @@ void
|
|||
lsquic_stream_received_goaway (lsquic_stream_t *stream)
|
||||
{
|
||||
SM_HISTORY_APPEND(stream, SHE_GOAWAY_IN);
|
||||
|
||||
if (stream->stream_flags & STREAM_GOAWAY_IN)
|
||||
{
|
||||
LSQ_DEBUG("ignore duplicate GOAWAY");
|
||||
return;
|
||||
}
|
||||
stream->stream_flags |= STREAM_GOAWAY_IN;
|
||||
|
||||
if (0 == stream->read_offset &&
|
||||
stream->data_in->di_if->di_empty(stream->data_in))
|
||||
fake_reset_unused_stream(stream); /* Normal condition */
|
||||
|
|
|
@ -208,7 +208,7 @@ enum stream_flags {
|
|||
STREAM_ONNEW_DONE = 1 << 17, /* on_new_stream has been called */
|
||||
STREAM_PUSHING = 1 << 18,
|
||||
STREAM_NOPUSH = 1 << 19, /* Disallow further push promises */
|
||||
STREAM_UNUSED20 = 1 << 20, /* Unused */
|
||||
STREAM_GOAWAY_IN = 1 << 20, /* Incoming GOAWAY has been processed */
|
||||
STREAM_UNUSED21 = 1 << 21, /* Unused */
|
||||
STREAM_RST_ACKED = 1 << 22, /* Packet containing RST has been acked */
|
||||
STREAM_BLOCKED_SENT = 1 << 23, /* Stays set once a STREAM_BLOCKED frame is sent */
|
||||
|
|
|
@ -20,6 +20,7 @@ static const unsigned char version_tags[N_LSQVER][4] =
|
|||
#endif
|
||||
[LSQVER_ID27] = { 0xFF, 0, 0, 27, },
|
||||
[LSQVER_ID28] = { 0xFF, 0, 0, 28, },
|
||||
[LSQVER_ID29] = { 0xFF, 0, 0, 29, },
|
||||
[LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
|
||||
};
|
||||
|
||||
|
@ -58,6 +59,7 @@ const char *const lsquic_ver2str[N_LSQVER] = {
|
|||
#endif
|
||||
[LSQVER_ID27] = "FF00001B",
|
||||
[LSQVER_ID28] = "FF00001C",
|
||||
[LSQVER_ID29] = "FF00001D",
|
||||
[LSQVER_VERNEG] = "FAFAFAFA",
|
||||
};
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ main (void)
|
|||
};
|
||||
|
||||
HKDF_extract(secret, &secret_len, md, dcid.idbuf, dcid.len,
|
||||
HSK_SALT, HSK_SALT_SZ);
|
||||
HSK_SALT_PRE29, HSK_SALT_SZ);
|
||||
|
||||
assert(sizeof(expected_secret) == secret_len);
|
||||
assert(0 == memcmp(secret, expected_secret, sizeof(expected_secret)));
|
||||
|
|
Loading…
Reference in a new issue