mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.14.1
- [BUGFIX] Place connections on tickable queue when sending is reenabled. - [BUGFIX] A connection is tickable if it has unsent packets. - [BUGFIX] Heed peer's max_packet_size transport parameter.
This commit is contained in:
parent
7b08963c02
commit
77a28812de
13 changed files with 164 additions and 48 deletions
|
@ -1,3 +1,9 @@
|
|||
2020-04-07
|
||||
- 2.14.1
|
||||
- [BUGFIX] Place connections on tickable queue when sending is reenabled.
|
||||
- [BUGFIX] A connection is tickable if it has unsent packets.
|
||||
- [BUGFIX] Heed peer's max_packet_size transport parameter.
|
||||
|
||||
2020-03-30
|
||||
- 2.14.0
|
||||
- [API] Use lsxpack_header structure to send HTTP headers.
|
||||
|
|
|
@ -26,7 +26,7 @@ author = u'LiteSpeed Technologies'
|
|||
# The short X.Y version
|
||||
version = u'2.14'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'2.14.0'
|
||||
release = u'2.14.1'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 14
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
#define LSQUIC_PATCH_VERSION 1
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
@ -340,6 +340,9 @@ typedef struct ssl_ctx_st * (*lsquic_lookup_cert_f)(
|
|||
/* 1: Cubic; 2: BBR */
|
||||
#define LSQUIC_DF_CC_ALGO 1
|
||||
|
||||
/** By default, incoming packet size is not limited. */
|
||||
#define LSQUIC_DF_MAX_PACKET_SIZE_RX 0
|
||||
|
||||
struct lsquic_engine_settings {
|
||||
/**
|
||||
* This is a bit mask wherein each bit corresponds to a value in
|
||||
|
@ -738,6 +741,17 @@ struct lsquic_engine_settings {
|
|||
* Default value is @ref LSQUIC_DF_TIMESTAMPS
|
||||
*/
|
||||
int es_timestamps;
|
||||
|
||||
/**
|
||||
* Maximum packet size we are willing to receive. This is sent to
|
||||
* peer in transport parameters: the library does not enforce this
|
||||
* limit for incoming packets.
|
||||
*
|
||||
* If set to zero, limit is not set.
|
||||
*
|
||||
* Default value is @ref LSQUIC_DF_MAX_PACKET_SIZE_RX
|
||||
*/
|
||||
unsigned short es_max_packet_size_rx;
|
||||
};
|
||||
|
||||
/* Initialize `settings' to default values */
|
||||
|
|
|
@ -532,7 +532,6 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
|
|||
= TP_DEF_ACK_DELAY_EXP;
|
||||
params.tp_max_idle_timeout = settings->es_idle_timeout * 1000;
|
||||
params.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY;
|
||||
params.tp_max_packet_size = 1370 /* XXX: based on socket */;
|
||||
params.tp_active_connection_id_limit = MAX_IETF_CONN_DCIDS;
|
||||
params.tp_set |= (1 << TPI_INIT_MAX_DATA)
|
||||
| (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL)
|
||||
|
@ -543,9 +542,13 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
|
|||
| (1 << TPI_ACK_DELAY_EXPONENT)
|
||||
| (1 << TPI_MAX_IDLE_TIMEOUT)
|
||||
| (1 << TPI_MAX_ACK_DELAY)
|
||||
| (1 << TPI_MAX_PACKET_SIZE)
|
||||
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT)
|
||||
;
|
||||
if (settings->es_max_packet_size_rx)
|
||||
{
|
||||
params.tp_max_packet_size = settings->es_max_packet_size_rx;
|
||||
params.tp_set |= 1 << TPI_MAX_PACKET_SIZE;
|
||||
}
|
||||
if (!settings->es_allow_migration)
|
||||
params.tp_set |= 1 << TPI_DISABLE_ACTIVE_MIGRATION;
|
||||
if (settings->es_ql_bits)
|
||||
|
|
|
@ -2445,6 +2445,32 @@ reset_deadline (lsquic_engine_t *engine, lsquic_time_t now)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
check_tickable_conns_again (struct lsquic_engine *engine)
|
||||
{
|
||||
struct lsquic_hash_elem *el;
|
||||
struct lsquic_conn *conn;
|
||||
unsigned count;
|
||||
|
||||
count = 0;
|
||||
for (el = lsquic_hash_first(engine->conns_hash); el;
|
||||
el = lsquic_hash_next(engine->conns_hash))
|
||||
{
|
||||
conn = lsquic_hashelem_getdata(el);
|
||||
if (!(conn->cn_flags & LSCONN_TICKABLE)
|
||||
&& conn->cn_if->ci_is_tickable(conn))
|
||||
{
|
||||
lsquic_mh_insert(&engine->conns_tickable, conn,
|
||||
conn->cn_last_ticked);
|
||||
engine_incref_conn(conn, LSCONN_TICKABLE);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
LSQ_DEBUG("%u connection%s tickable again after sending has been "
|
||||
"re-enabled", count, count == 1 ? " is" : "s are");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_engine_send_unsent_packets (lsquic_engine_t *engine)
|
||||
{
|
||||
|
@ -2462,6 +2488,7 @@ lsquic_engine_send_unsent_packets (lsquic_engine_t *engine)
|
|||
LSQ_DEBUG("can send again");
|
||||
EV_LOG_GENERIC_EVENT("can send again");
|
||||
engine->pub.enp_flags |= ENPUB_CAN_SEND;
|
||||
check_tickable_conns_again(engine);
|
||||
}
|
||||
|
||||
send_packets_out(engine, &ticked_conns, &closed_conns);
|
||||
|
|
|
@ -4115,6 +4115,11 @@ 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)
|
||||
{
|
||||
LSQ_DEBUG("tickable: has scheduled packets");
|
||||
return 1; /* Don't check can_send */
|
||||
}
|
||||
if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||
&& lsquic_send_ctl_has_buffered(&conn->fc_send_ctl))
|
||||
{
|
||||
|
|
|
@ -3446,6 +3446,11 @@ 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)
|
||||
{
|
||||
LSQ_DEBUG("tickable: has scheduled packets");
|
||||
return 1; /* Don't check can_send */
|
||||
}
|
||||
if (conn->ifc_conn.cn_flags & LSCONN_SEND_BLOCKED)
|
||||
{
|
||||
LSQ_DEBUG("tickable: send DATA_BLOCKED frame");
|
||||
|
|
|
@ -340,6 +340,8 @@ static
|
|||
enum hsk_failure_reason
|
||||
lsquic_verify_stk (enc_session_t *,
|
||||
const struct sockaddr *ip_addr, uint64_t tm, lsquic_str_t *stk);
|
||||
|
||||
static
|
||||
#endif
|
||||
void lsquic_gen_stk(lsquic_server_config_t *, const struct sockaddr *, uint64_t tm,
|
||||
unsigned char stk_out[STK_LENGTH]);
|
||||
|
|
|
@ -2072,14 +2072,24 @@ mini_conn_ci_hsk_done (struct lsquic_conn *lconn, enum lsquic_hsk_status status)
|
|||
}
|
||||
|
||||
|
||||
/* A mini connection is only tickable if it has unsent packets. This can
|
||||
* occur when packet sending is delayed.
|
||||
*
|
||||
* Otherwise, a mini connection is not tickable: Either there are incoming
|
||||
* packets, in which case, the connection is going to be ticked, or there is
|
||||
* an alarm pending, in which case it will be handled via the attq.
|
||||
*/
|
||||
static int
|
||||
mini_conn_ci_is_tickable (struct lsquic_conn *lconn)
|
||||
{
|
||||
/* A mini connection is never tickable: Either there are incoming
|
||||
* packets, in which case, the connection is going to be ticked, or
|
||||
* there is an alarm pending, in which case it will be handled via
|
||||
* the attq.
|
||||
*/
|
||||
struct mini_conn *const mc = (struct mini_conn *) lconn;
|
||||
const struct lsquic_packet_out *packet_out;
|
||||
|
||||
if (mc->mc_enpub->enp_flags & ENPUB_CAN_SEND)
|
||||
TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
|
||||
if (!(packet_out->po_flags & PO_SENT))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -162,6 +162,50 @@ read_from_msg_ctx (void *ctx, void *buf, size_t len)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
imico_chlo_has_been_consumed (const struct ietf_mini_conn *conn)
|
||||
{
|
||||
return conn->imc_streams[ENC_LEV_CLEAR].mcs_read_off > 3
|
||||
&& conn->imc_streams[ENC_LEV_CLEAR].mcs_read_off >= conn->imc_ch_len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
imico_maybe_process_params (struct ietf_mini_conn *conn)
|
||||
{
|
||||
const struct transport_params *params;
|
||||
|
||||
if (imico_chlo_has_been_consumed(conn)
|
||||
&& (conn->imc_flags & (IMC_ENC_SESS_INITED|IMC_HAVE_TP))
|
||||
== IMC_ENC_SESS_INITED)
|
||||
{
|
||||
params = conn->imc_conn.cn_esf.i->esfi_get_peer_transport_params(
|
||||
conn->imc_conn.cn_enc_session);
|
||||
if (params)
|
||||
{
|
||||
conn->imc_flags |= IMC_HAVE_TP;
|
||||
conn->imc_ack_exp = params->tp_ack_delay_exponent;
|
||||
if (params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
|
||||
{
|
||||
if (params->tp_numerics[TPI_MAX_PACKET_SIZE]
|
||||
< conn->imc_path.np_pack_size)
|
||||
conn->imc_path.np_pack_size =
|
||||
params->tp_numerics[TPI_MAX_PACKET_SIZE];
|
||||
}
|
||||
LSQ_DEBUG("read transport params, packet size is set to %hu bytes",
|
||||
conn->imc_path.np_pack_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->imc_flags |= IMC_BAD_TRANS_PARAMS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
imico_stream_write (void *stream, const void *bufp, size_t bufsz)
|
||||
{
|
||||
|
@ -175,6 +219,9 @@ imico_stream_write (void *stream, const void *bufp, size_t bufsz)
|
|||
const unsigned char *p;
|
||||
int len;
|
||||
|
||||
if (0 != imico_maybe_process_params(conn))
|
||||
return -1;
|
||||
|
||||
if (PNS_INIT == lsquic_enclev2pns[ cryst->mcs_enc_level ]
|
||||
&& (conn->imc_flags & IMC_IGNORE_INIT))
|
||||
{
|
||||
|
@ -281,14 +328,6 @@ imico_read_chlo_size (struct ietf_mini_conn *conn, const unsigned char *buf,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
imico_chlo_has_been_consumed (const struct ietf_mini_conn *conn)
|
||||
{
|
||||
return conn->imc_streams[ENC_LEV_CLEAR].mcs_read_off > 3
|
||||
&& conn->imc_streams[ENC_LEV_CLEAR].mcs_read_off >= conn->imc_ch_len;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
imico_stream_readf (void *stream,
|
||||
size_t (*readf)(void *, const unsigned char *, size_t, int), void *ctx)
|
||||
|
@ -574,14 +613,24 @@ ietf_mini_conn_ci_tls_alert (struct lsquic_conn *lconn, uint8_t alert)
|
|||
}
|
||||
|
||||
|
||||
/* A mini connection is only tickable if it has unsent packets. This can
|
||||
* occur when packet sending is delayed.
|
||||
*
|
||||
* Otherwise, a mini connection is not tickable: Either there are incoming
|
||||
* packets, in which case, the connection is going to be ticked, or there is
|
||||
* an alarm pending, in which case it will be handled via the attq.
|
||||
*/
|
||||
static int
|
||||
ietf_mini_conn_ci_is_tickable (struct lsquic_conn *lconn)
|
||||
{
|
||||
/* A mini connection is never tickable: Either there are incoming
|
||||
* packets, in which case, the connection is going to be ticked, or
|
||||
* there is an alarm pending, in which case it will be handled via
|
||||
* the attq.
|
||||
*/
|
||||
struct ietf_mini_conn *const conn = (struct ietf_mini_conn *) lconn;
|
||||
const struct lsquic_packet_out *packet_out;
|
||||
|
||||
if (conn->imc_enpub->enp_flags & ENPUB_CAN_SEND)
|
||||
TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next)
|
||||
if (!(packet_out->po_flags & PO_SENT))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -755,7 +804,6 @@ imico_process_crypto_frame (IMICO_PROC_FRAME_ARGS)
|
|||
int parsed_len;
|
||||
enum enc_level enc_level, i;
|
||||
struct stream_frame stream_frame;
|
||||
const struct transport_params *params;
|
||||
|
||||
parsed_len = conn->imc_conn.cn_pf->pf_parse_crypto_frame(p, len,
|
||||
&stream_frame);
|
||||
|
@ -826,25 +874,6 @@ imico_process_crypto_frame (IMICO_PROC_FRAME_ARGS)
|
|||
}
|
||||
|
||||
|
||||
if (enc_level == ENC_LEV_CLEAR
|
||||
&& imico_chlo_has_been_consumed(conn)
|
||||
&& (conn->imc_flags & (IMC_ENC_SESS_INITED|IMC_HAVE_TP))
|
||||
== IMC_ENC_SESS_INITED)
|
||||
{
|
||||
params = conn->imc_conn.cn_esf.i->esfi_get_peer_transport_params(
|
||||
conn->imc_conn.cn_enc_session);
|
||||
if (params)
|
||||
{
|
||||
conn->imc_flags |= IMC_HAVE_TP;
|
||||
conn->imc_ack_exp = params->tp_ack_delay_exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->imc_flags |= IMC_BAD_TRANS_PARAMS;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return parsed_len;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,9 @@ static const uint64_t def_vals[MAX_NUM_WITH_DEF_TPI + 1] =
|
|||
|
||||
static const uint64_t max_vals[MAX_NUMERIC_TPI + 1] =
|
||||
{
|
||||
/* We don't enforce the maximum practical UDP payload value of 65527, as
|
||||
* it is not required by the spec and is not necessary.
|
||||
*/
|
||||
[TPI_MAX_PACKET_SIZE] = VINT_MAX_VALUE,
|
||||
[TPI_ACK_DELAY_EXPONENT] = VINT_MAX_VALUE,
|
||||
[TPI_INIT_MAX_STREAMS_UNI] = VINT_MAX_VALUE,
|
||||
|
@ -146,6 +149,8 @@ static const uint64_t max_vals[MAX_NUMERIC_TPI + 1] =
|
|||
|
||||
static const uint64_t min_vals[MAX_NUMERIC_TPI + 1] =
|
||||
{
|
||||
/* On the other hand, we do enforce the lower bound. */
|
||||
[TPI_MAX_PACKET_SIZE] = 1200,
|
||||
[TPI_MIN_ACK_DELAY] = 1,
|
||||
};
|
||||
|
||||
|
|
|
@ -1658,7 +1658,11 @@ send_packets_one_by_one (const struct lsquic_out_spec *specs, unsigned count)
|
|||
prog_sport_cant_send(sport->sp_prog, sport->fd);
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
if (n < orig_count && out_limit)
|
||||
errno = EAGAIN;
|
||||
return n;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(s < 0);
|
||||
|
@ -1911,6 +1915,11 @@ set_engine_option (struct lsquic_engine_settings *settings,
|
|||
settings->es_qpack_dec_max_size = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
if (0 == strncmp(name, "max_packet_size_rx", 18))
|
||||
{
|
||||
settings->es_max_packet_size_rx = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
if (0 == strncmp(name, "max_header_list_size", 20))
|
||||
|
|
|
@ -63,15 +63,16 @@ static const struct trapa_test tests[] =
|
|||
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT),
|
||||
.tp_init_max_stream_data_bidi_local = 0x12348877,
|
||||
.tp_init_max_data = 0xAABB,
|
||||
.tp_max_packet_size = 1213,
|
||||
.tp_max_idle_timeout = 10 * 1000,
|
||||
.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY,
|
||||
.tp_active_connection_id_limit = 7,
|
||||
},
|
||||
.is_server = 0,
|
||||
.enc_len = 25,
|
||||
.enc_len = 26,
|
||||
.encoded =
|
||||
/* Idle timeout */ "\x01\x02\x67\x10"
|
||||
/* Packet size */ "\x03\x01\x00"
|
||||
/* Packet size */ "\x03\x02\x44\xBD"
|
||||
/* Max data */ "\x04\x04\x80\x00\xAA\xBB"
|
||||
/* Bidi local */ "\x05\x04\x92\x34\x88\x77"
|
||||
/* Ack delay exp */ "\x0A\x01\x00"
|
||||
|
@ -103,13 +104,13 @@ static const struct trapa_test tests[] =
|
|||
TP_DEFAULT_VALUES,
|
||||
.tp_init_max_data = 0x123456,
|
||||
.tp_init_max_stream_data_bidi_local = 0xABCDEF88,
|
||||
.tp_max_packet_size = 0x333,
|
||||
.tp_max_packet_size = 0x555,
|
||||
},
|
||||
.is_server = 1,
|
||||
.addl_set = 1 << TPI_DISABLE_ACTIVE_MIGRATION,
|
||||
.enc_len = 22,
|
||||
.encoded =
|
||||
/* Packet size */ "\x03\x02\x43\x33"
|
||||
/* Packet size */ "\x03\x02\x45\x55"
|
||||
/* Max data */ "\x04\x04\x80\x12\x34\x56"
|
||||
/* Bidi local */ "\x05\x08\xC0\x00\x00\x00\xAB\xCD\xEF\x88"
|
||||
/* Migration */ "\x0C\x00"
|
||||
|
@ -124,7 +125,7 @@ static const struct trapa_test tests[] =
|
|||
.params = {
|
||||
TP_DEFAULT_VALUES,
|
||||
.tp_max_ack_delay = 25,
|
||||
.tp_max_packet_size = 0x333,
|
||||
.tp_max_packet_size = 0x555,
|
||||
.tp_preferred_address = {
|
||||
.ipv4_addr = "\x01\x02\x03\x04",
|
||||
.ipv4_port = 0x1234,
|
||||
|
@ -148,7 +149,7 @@ static const struct trapa_test tests[] =
|
|||
"\x0B" /* CID len */
|
||||
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A"
|
||||
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
|
||||
/* Packet size */ "\x03\x02\x43\x33"
|
||||
/* Packet size */ "\x03\x02\x45\x55"
|
||||
/* Trailer to make the end easily visible in gdb: */
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue