mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.7.1
- [BUGFIX] client: don't call ignore_init() in middle of batch send. ignore_init() makes an assumption that the send controller has access to all outgoing packets. This change wraps a few IETF full connection methods to delay calling ignore_init() until the engine returns all outgoing packets that were batched. - [BUGFIX] set errno to EAGAIN if sendmmsg() can't send all of them. This needs to be done because the value of errno may be lost on some platforms. - [BUGFIX] Typo that set all bits in sm_qflags lead to crashes. - [BUGFIX] Do not cancel header block processing after failure, as QPACK releases the reference in that case. - [CLEANUP] IETF encrypt: replace assert(0) with a warning. - Several small improvements to the test server.
This commit is contained in:
parent
7ee4152504
commit
936463fe29
8 changed files with 150 additions and 49 deletions
16
CHANGELOG
16
CHANGELOG
|
@ -1,3 +1,19 @@
|
|||
2019-12-05
|
||||
- 2.7.1
|
||||
- [BUGFIX] client: don't call ignore_init() in middle of batch send.
|
||||
ignore_init() makes an assumption that the send controller has access
|
||||
to all outgoing packets. This change wraps a few IETF full connection
|
||||
methods to delay calling ignore_init() until the engine returns all
|
||||
outgoing packets that were batched.
|
||||
- [BUGFIX] set errno to EAGAIN if sendmmsg() can't send all of them.
|
||||
This needs to be done because the value of errno may be lost on
|
||||
some platforms.
|
||||
- [BUGFIX] Typo that set all bits in sm_qflags lead to crashes.
|
||||
- [BUGFIX] Do not cancel header block processing after failure, as
|
||||
QPACK releases the reference in that case.
|
||||
- [CLEANUP] IETF encrypt: replace assert(0) with a warning.
|
||||
- Several small improvements to the test server.
|
||||
|
||||
2019-11-27
|
||||
- 2.7.0
|
||||
- [API, FEATURE] Close connection immediately when ea_packets_out()
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 7
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
#define LSQUIC_PATCH_VERSION 1
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
|
|
@ -1707,7 +1707,8 @@ iquic_esf_encrypt_packet (enc_session_t *enc_session_p,
|
|||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
LSQ_WARN("no keys for encryption level %s",
|
||||
lsquic_enclev2str[enc_level]);
|
||||
return ENCPA_BADCRYPT;
|
||||
}
|
||||
|
||||
|
|
|
@ -369,7 +369,9 @@ struct ietf_full_conn
|
|||
uint64_t ifcli_max_push_id;
|
||||
enum {
|
||||
IFCLI_PUSH_ENABLED = 1 << 0,
|
||||
IFCLI_HSK_SENT_OR_DEL = 1 << 1,
|
||||
} ifcli_flags;
|
||||
unsigned ifcli_packets_out;
|
||||
} cli;
|
||||
struct {
|
||||
uint64_t ifser_max_push_id;
|
||||
|
@ -397,6 +399,7 @@ struct ietf_full_conn
|
|||
static const struct ver_neg server_ver_neg;
|
||||
|
||||
static const struct conn_iface *ietf_full_conn_iface_ptr;
|
||||
static const struct conn_iface *ietf_full_conn_prehsk_iface_ptr;
|
||||
|
||||
static int
|
||||
process_incoming_packet_verneg (struct ietf_full_conn *,
|
||||
|
@ -880,7 +883,10 @@ static int
|
|||
ietf_full_conn_init (struct ietf_full_conn *conn,
|
||||
struct lsquic_engine_public *enpub, unsigned flags, int ecn)
|
||||
{
|
||||
if (flags & IFC_SERVER)
|
||||
conn->ifc_conn.cn_if = ietf_full_conn_iface_ptr;
|
||||
else
|
||||
conn->ifc_conn.cn_if = ietf_full_conn_prehsk_iface_ptr;
|
||||
if (enpub->enp_settings.es_scid_len)
|
||||
assert(CN_SCID(&conn->ifc_conn)->len);
|
||||
conn->ifc_enpub = enpub;
|
||||
|
@ -3699,6 +3705,20 @@ ietf_full_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
|
|||
}
|
||||
|
||||
|
||||
static struct lsquic_packet_out *
|
||||
ietf_full_conn_ci_next_packet_to_send_pre_hsk (struct lsquic_conn *lconn,
|
||||
size_t size)
|
||||
{
|
||||
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
|
||||
struct lsquic_packet_out *packet_out;
|
||||
|
||||
packet_out = ietf_full_conn_ci_next_packet_to_send(lconn, size);
|
||||
if (packet_out)
|
||||
++conn->ifc_u.cli.ifcli_packets_out;
|
||||
return packet_out;
|
||||
}
|
||||
|
||||
|
||||
static lsquic_time_t
|
||||
ietf_full_conn_ci_next_tick_time (struct lsquic_conn *lconn, unsigned *why)
|
||||
{
|
||||
|
@ -5601,11 +5621,14 @@ ignore_init (struct ietf_full_conn *conn)
|
|||
lsquic_send_ctl_empty_pns(&conn->ifc_send_ctl, PNS_INIT);
|
||||
lsquic_rechist_cleanup(&conn->ifc_rechist[PNS_INIT]);
|
||||
if (!(conn->ifc_flags & IFC_SERVER))
|
||||
{
|
||||
if (conn->ifc_u.cli.crypto_streams[ENC_LEV_CLEAR])
|
||||
{
|
||||
lsquic_stream_destroy(conn->ifc_u.cli.crypto_streams[ENC_LEV_CLEAR]);
|
||||
conn->ifc_u.cli.crypto_streams[ENC_LEV_CLEAR] = NULL;
|
||||
}
|
||||
conn->ifc_conn.cn_if = ietf_full_conn_iface_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -5965,6 +5988,34 @@ ietf_full_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
|
|||
}
|
||||
|
||||
|
||||
/* Calling of ignore_init() must be delayed until all batched packets have
|
||||
* been returned by the engine.
|
||||
*/
|
||||
static void
|
||||
pre_hsk_packet_sent_or_delayed (struct ietf_full_conn *conn,
|
||||
const struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
/* Once IFC_IGNORE_INIT is set, the pre-hsk wrapper is removed: */
|
||||
assert(!(conn->ifc_flags & IFC_IGNORE_INIT));
|
||||
--conn->ifc_u.cli.ifcli_packets_out;
|
||||
if (PNS_HSK == lsquic_packet_out_pns(packet_out))
|
||||
conn->ifc_u.cli.ifcli_flags |= IFCLI_HSK_SENT_OR_DEL;
|
||||
if (0 == conn->ifc_u.cli.ifcli_packets_out
|
||||
&& (conn->ifc_u.cli.ifcli_flags & IFCLI_HSK_SENT_OR_DEL))
|
||||
ignore_init(conn);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ietf_full_conn_ci_packet_not_sent_pre_hsk (struct lsquic_conn *lconn,
|
||||
struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
|
||||
ietf_full_conn_ci_packet_not_sent(lconn, packet_out);
|
||||
pre_hsk_packet_sent_or_delayed(conn, packet_out);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ietf_full_conn_ci_packet_sent (struct lsquic_conn *lconn,
|
||||
struct lsquic_packet_out *packet_out)
|
||||
|
@ -5981,11 +6032,16 @@ ietf_full_conn_ci_packet_sent (struct lsquic_conn *lconn,
|
|||
ABORT_ERROR("sent packet failed: %s", strerror(errno));
|
||||
++conn->ifc_ecn_counts_out[ lsquic_packet_out_pns(packet_out) ]
|
||||
[ lsquic_packet_out_ecn(packet_out) ];
|
||||
if (0 == (conn->ifc_flags & (IFC_SERVER|IFC_IGNORE_INIT)))
|
||||
{
|
||||
if (PNS_HSK == lsquic_packet_out_pns(packet_out))
|
||||
ignore_init(conn);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ietf_full_conn_ci_packet_sent_pre_hsk (struct lsquic_conn *lconn,
|
||||
struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
struct ietf_full_conn *const conn = (struct ietf_full_conn *) lconn;
|
||||
ietf_full_conn_ci_packet_sent(lconn, packet_out);
|
||||
pre_hsk_packet_sent_or_delayed(conn, packet_out);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6586,49 +6642,60 @@ ietf_full_conn_ci_drop_crypto_streams (struct lsquic_conn *lconn)
|
|||
}
|
||||
|
||||
|
||||
#define IETF_FULL_CONN_FUNCS \
|
||||
.ci_abort = ietf_full_conn_ci_abort, \
|
||||
.ci_abort_error = ietf_full_conn_ci_abort_error, \
|
||||
.ci_retire_cid = ietf_full_conn_ci_retire_cid, \
|
||||
.ci_can_write_ack = ietf_full_conn_ci_can_write_ack, \
|
||||
.ci_cancel_pending_streams = ietf_full_conn_ci_cancel_pending_streams, \
|
||||
.ci_client_call_on_new = ietf_full_conn_ci_client_call_on_new, \
|
||||
.ci_close = ietf_full_conn_ci_close, \
|
||||
.ci_destroy = ietf_full_conn_ci_destroy, \
|
||||
.ci_drain_time = ietf_full_conn_ci_drain_time, \
|
||||
.ci_drop_crypto_streams = ietf_full_conn_ci_drop_crypto_streams, \
|
||||
.ci_get_ctx = ietf_full_conn_ci_get_ctx, \
|
||||
.ci_get_engine = ietf_full_conn_ci_get_engine, \
|
||||
.ci_get_log_cid = ietf_full_conn_ci_get_log_cid, \
|
||||
.ci_get_path = ietf_full_conn_ci_get_path, \
|
||||
.ci_get_stream_by_id = ieft_full_conn_ci_get_stream_by_id, \
|
||||
.ci_going_away = ietf_full_conn_ci_going_away, \
|
||||
.ci_hsk_done = ietf_full_conn_ci_hsk_done, \
|
||||
.ci_internal_error = ietf_full_conn_ci_internal_error, \
|
||||
.ci_is_push_enabled = ietf_full_conn_ci_is_push_enabled, \
|
||||
.ci_is_tickable = ietf_full_conn_ci_is_tickable, \
|
||||
.ci_make_stream = ietf_full_conn_ci_make_stream, \
|
||||
.ci_n_avail_streams = ietf_full_conn_ci_n_avail_streams, \
|
||||
.ci_n_pending_streams = ietf_full_conn_ci_n_pending_streams, \
|
||||
.ci_next_tick_time = ietf_full_conn_ci_next_tick_time, \
|
||||
.ci_packet_in = ietf_full_conn_ci_packet_in, \
|
||||
.ci_push_stream = ietf_full_conn_ci_push_stream, \
|
||||
.ci_record_addrs = ietf_full_conn_ci_record_addrs, \
|
||||
.ci_report_live = ietf_full_conn_ci_report_live, \
|
||||
.ci_set_ctx = ietf_full_conn_ci_set_ctx, \
|
||||
.ci_status = ietf_full_conn_ci_status, \
|
||||
.ci_stateless_reset = ietf_full_conn_ci_stateless_reset, \
|
||||
.ci_tick = ietf_full_conn_ci_tick, \
|
||||
.ci_tls_alert = ietf_full_conn_ci_tls_alert, \
|
||||
.ci_write_ack = ietf_full_conn_ci_write_ack
|
||||
|
||||
static const struct conn_iface ietf_full_conn_iface = {
|
||||
.ci_abort = ietf_full_conn_ci_abort,
|
||||
.ci_abort_error = ietf_full_conn_ci_abort_error,
|
||||
.ci_retire_cid = ietf_full_conn_ci_retire_cid,
|
||||
.ci_can_write_ack = ietf_full_conn_ci_can_write_ack,
|
||||
.ci_cancel_pending_streams = ietf_full_conn_ci_cancel_pending_streams,
|
||||
.ci_client_call_on_new = ietf_full_conn_ci_client_call_on_new,
|
||||
.ci_close = ietf_full_conn_ci_close,
|
||||
.ci_destroy = ietf_full_conn_ci_destroy,
|
||||
.ci_drain_time = ietf_full_conn_ci_drain_time,
|
||||
.ci_drop_crypto_streams = ietf_full_conn_ci_drop_crypto_streams,
|
||||
.ci_get_ctx = ietf_full_conn_ci_get_ctx,
|
||||
.ci_get_engine = ietf_full_conn_ci_get_engine,
|
||||
.ci_get_log_cid = ietf_full_conn_ci_get_log_cid,
|
||||
.ci_get_path = ietf_full_conn_ci_get_path,
|
||||
.ci_get_stream_by_id = ieft_full_conn_ci_get_stream_by_id,
|
||||
.ci_going_away = ietf_full_conn_ci_going_away,
|
||||
.ci_hsk_done = ietf_full_conn_ci_hsk_done,
|
||||
.ci_internal_error = ietf_full_conn_ci_internal_error,
|
||||
.ci_is_push_enabled = ietf_full_conn_ci_is_push_enabled,
|
||||
.ci_is_tickable = ietf_full_conn_ci_is_tickable,
|
||||
.ci_make_stream = ietf_full_conn_ci_make_stream,
|
||||
.ci_n_avail_streams = ietf_full_conn_ci_n_avail_streams,
|
||||
.ci_n_pending_streams = ietf_full_conn_ci_n_pending_streams,
|
||||
IETF_FULL_CONN_FUNCS,
|
||||
.ci_next_packet_to_send = ietf_full_conn_ci_next_packet_to_send,
|
||||
.ci_next_tick_time = ietf_full_conn_ci_next_tick_time,
|
||||
.ci_packet_in = ietf_full_conn_ci_packet_in,
|
||||
.ci_packet_not_sent = ietf_full_conn_ci_packet_not_sent,
|
||||
.ci_packet_sent = ietf_full_conn_ci_packet_sent,
|
||||
.ci_push_stream = ietf_full_conn_ci_push_stream,
|
||||
.ci_record_addrs = ietf_full_conn_ci_record_addrs,
|
||||
.ci_report_live = ietf_full_conn_ci_report_live,
|
||||
.ci_set_ctx = ietf_full_conn_ci_set_ctx,
|
||||
.ci_status = ietf_full_conn_ci_status,
|
||||
.ci_stateless_reset = ietf_full_conn_ci_stateless_reset,
|
||||
.ci_tick = ietf_full_conn_ci_tick,
|
||||
.ci_tls_alert = ietf_full_conn_ci_tls_alert,
|
||||
.ci_write_ack = ietf_full_conn_ci_write_ack,
|
||||
};
|
||||
|
||||
static const struct conn_iface *ietf_full_conn_iface_ptr =
|
||||
&ietf_full_conn_iface;
|
||||
|
||||
static const struct conn_iface ietf_full_conn_prehsk_iface = {
|
||||
IETF_FULL_CONN_FUNCS,
|
||||
.ci_next_packet_to_send = ietf_full_conn_ci_next_packet_to_send_pre_hsk,
|
||||
.ci_packet_not_sent = ietf_full_conn_ci_packet_not_sent_pre_hsk,
|
||||
.ci_packet_sent = ietf_full_conn_ci_packet_sent_pre_hsk,
|
||||
};
|
||||
static const struct conn_iface *ietf_full_conn_prehsk_iface_ptr =
|
||||
&ietf_full_conn_prehsk_iface;
|
||||
|
||||
|
||||
static void
|
||||
on_cancel_push (void *ctx, uint64_t push_id)
|
||||
|
|
|
@ -3610,7 +3610,7 @@ lsquic_stream_reset_ext (lsquic_stream_t *stream, uint64_t error_code,
|
|||
if (stream->sm_qflags & SMQF_QPACK_DEC)
|
||||
{
|
||||
lsquic_qdh_cancel_stream(stream->conn_pub->u.ietf.qdh, stream);
|
||||
stream->sm_qflags |= ~SMQF_QPACK_DEC;
|
||||
stream->sm_qflags &= ~SMQF_QPACK_DEC;
|
||||
}
|
||||
|
||||
drop_buffered_data(stream);
|
||||
|
@ -4246,6 +4246,7 @@ hq_read (void *ctx, const unsigned char *buf, size_t sz, int fin)
|
|||
goto end;
|
||||
default:
|
||||
assert(LQRHS_ERROR == rhs);
|
||||
stream->sm_qflags &= ~SMQF_QPACK_DEC;
|
||||
filter->hqfi_flags |= HQFI_FLAG_ERROR;
|
||||
LSQ_INFO("error processing header block");
|
||||
abort_connection(stream); /* XXX Overkill? */
|
||||
|
|
|
@ -983,7 +983,7 @@ send_headers2 (struct lsquic_stream *stream, struct lsquic_stream_ctx *st_h,
|
|||
},
|
||||
{
|
||||
.name = { .iov_base = "content-type", .iov_len = 12, },
|
||||
.value = { .iov_base = "application/html", .iov_len = 16, },
|
||||
.value = { .iov_base = "text/html", .iov_len = 9, },
|
||||
},
|
||||
{
|
||||
.name = { .iov_base = "content-length", .iov_len = 14, },
|
||||
|
|
12
test/prog.c
12
test/prog.c
|
@ -613,6 +613,12 @@ static const struct lsquic_keylog_if keylog_if =
|
|||
};
|
||||
|
||||
|
||||
static struct ssl_ctx_st *
|
||||
no_cert (void *cert_lu_ctx, const struct sockaddr *sa_UNUSED, const char *sni)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
prog_prep (struct prog *prog)
|
||||
|
@ -656,6 +662,12 @@ prog_prep (struct prog *prog)
|
|||
prog->prog_api.ea_lookup_cert = lookup_cert;
|
||||
prog->prog_api.ea_cert_lu_ctx = prog->prog_certs;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prog->prog_engine_flags & LSENG_SERVER)
|
||||
LSQ_WARN("Not a single service specified. Use -c option.");
|
||||
prog->prog_api.ea_lookup_cert = no_cert;
|
||||
}
|
||||
|
||||
prog->prog_eb = event_base_new();
|
||||
prog->prog_engine = lsquic_engine_new(prog->prog_engine_flags,
|
||||
|
|
|
@ -1441,6 +1441,10 @@ send_packets_using_sendmmsg (const struct lsquic_out_spec *specs,
|
|||
LSQ_WARN("sendmmsg failed: %s", strerror(saved_errno));
|
||||
errno = saved_errno;
|
||||
}
|
||||
else if (s > 0)
|
||||
errno = EAGAIN;
|
||||
else
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
return s;
|
||||
|
|
Loading…
Reference in a new issue