mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.16.1
- [FEATURE] Use "no-progress timeout" after which connection is closed. - [BUGFIX] Select new SCID when current SCID is retired. - [BUGFIX] Don't warn about dropped Initial packet sequence gaps during mini/full handoff. - [BUGFIX] Send correct conn error when HTTP/3 frame is truncated. - [BUGFIX] Mini conn: consider amplification when deciding to return TICK_SEND. - [BUGFIX] Don't double-count tag length in amplification logic. - [BUGFIX] Don't squeeze out lone path challenges. - [BUGFIX] Log messages dealing with scheduled packet queue squeezing. - [BUGFIX] don't wipe current path if no path challenge responses come back. - [BUGFIX] When path is reset, don't lose path_id which is used for logging. - Downgrade flow control violations to info log level from warnings. - Fix connection cap extra check, avoid checks in nested calls. - Fix some unit tests when extra checks are enabled. - Use ls-hpack 2.2.1. - Turn off unconditional extra checks for IETF clients. - Extra checks: don't verify sent size of hello packets. Client changes DCID length and this check will fail.
This commit is contained in:
parent
6bca16f0d2
commit
8ae5ecb45e
22 changed files with 369 additions and 54 deletions
24
CHANGELOG
24
CHANGELOG
|
@ -1,3 +1,27 @@
|
|||
2020-06-09
|
||||
- 2.16.1
|
||||
- [FEATURE] Use "no-progress timeout" after which connection is closed.
|
||||
- [BUGFIX] Select new SCID when current SCID is retired.
|
||||
- [BUGFIX] Don't warn about dropped Initial packet sequence gaps during
|
||||
mini/full handoff.
|
||||
- [BUGFIX] Send correct conn error when HTTP/3 frame is truncated.
|
||||
- [BUGFIX] Mini conn: consider amplification when deciding to return
|
||||
TICK_SEND.
|
||||
- [BUGFIX] Don't double-count tag length in amplification logic.
|
||||
- [BUGFIX] Don't squeeze out lone path challenges.
|
||||
- [BUGFIX] Log messages dealing with scheduled packet queue squeezing.
|
||||
- [BUGFIX] don't wipe current path if no path challenge responses
|
||||
come back.
|
||||
- [BUGFIX] When path is reset, don't lose path_id which is used for
|
||||
logging.
|
||||
- Downgrade flow control violations to info log level from warnings.
|
||||
- Fix connection cap extra check, avoid checks in nested calls.
|
||||
- Fix some unit tests when extra checks are enabled.
|
||||
- Use ls-hpack 2.2.1.
|
||||
- Turn off unconditional extra checks for IETF clients.
|
||||
- Extra checks: don't verify sent size of hello packets. Client
|
||||
changes DCID length and this check will fail.
|
||||
|
||||
2020-06-03
|
||||
- 2.16.0
|
||||
- [API] Use lsxpack_header v206.
|
||||
|
|
|
@ -1939,6 +1939,11 @@ set_engine_option (struct lsquic_engine_settings *settings,
|
|||
settings->es_qpack_dec_max_size = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
if (0 == strncmp(name, "noprogress_timeout", 18))
|
||||
{
|
||||
settings->es_noprogress_timeout = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
if (0 == strncmp(name, "max_header_list_size", 20))
|
||||
|
|
|
@ -46,13 +46,13 @@ developed by the IETF. Both types are included in a single enum:
|
|||
|
||||
Google QUIC version Q050
|
||||
|
||||
.. member:: LSQVER_ID25
|
||||
|
||||
IETF QUIC version ID (Internet-Draft) 25
|
||||
|
||||
.. member:: LSQVER_ID27
|
||||
|
||||
IETF QUIC version ID 27
|
||||
IETF QUIC version ID (Internet-Draft) 27
|
||||
|
||||
.. member:: LSQVER_ID28
|
||||
|
||||
IETF QUIC version ID 28
|
||||
|
||||
.. member:: N_LSQVER
|
||||
|
||||
|
@ -703,6 +703,19 @@ settings structure:
|
|||
|
||||
Default value is :macro:`LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX`
|
||||
|
||||
.. member:: unsigned es_noprogress_timeout
|
||||
|
||||
No progress timeout.
|
||||
|
||||
If connection does not make progress for this number of seconds, the
|
||||
connection is dropped. Here, progress is defined as user streams
|
||||
being written to or read from.
|
||||
|
||||
If this value is zero, this timeout is disabled.
|
||||
|
||||
Default value is :macro:`LSQUIC_DF_NOPROGRESS_TIMEOUT_SERVER` in server
|
||||
mode and :macro:`LSQUIC_DF_NOPROGRESS_TIMEOUT_CLIENT` in client mode.
|
||||
|
||||
To initialize the settings structure to library defaults, use the following
|
||||
convenience function:
|
||||
|
||||
|
@ -881,6 +894,14 @@ out of date. Please check your :file:`lsquic.h` for actual values.*
|
|||
|
||||
By default, incoming packet size is not limited.
|
||||
|
||||
.. macro:: LSQUIC_DF_NOPROGRESS_TIMEOUT_SERVER
|
||||
|
||||
By default, drop no-progress connections after 60 seconds on the server.
|
||||
|
||||
.. macro:: LSQUIC_DF_NOPROGRESS_TIMEOUT_CLIENT
|
||||
|
||||
By default, do not use no-progress timeout on the client.
|
||||
|
||||
Receiving Packets
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ author = u'LiteSpeed Technologies'
|
|||
# The short X.Y version
|
||||
version = u'2.16'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'2.16.0'
|
||||
release = u'2.16.1'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 16
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
#define LSQUIC_PATCH_VERSION 1
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
@ -343,6 +343,12 @@ typedef struct ssl_ctx_st * (*lsquic_lookup_cert_f)(
|
|||
/** By default, incoming packet size is not limited. */
|
||||
#define LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX 0
|
||||
|
||||
/** By default, drop no-progress connections after 60 seconds on the server */
|
||||
#define LSQUIC_DF_NOPROGRESS_TIMEOUT_SERVER 60
|
||||
|
||||
/** By default, do not use no-progress timeout on the client */
|
||||
#define LSQUIC_DF_NOPROGRESS_TIMEOUT_CLIENT 0
|
||||
|
||||
struct lsquic_engine_settings {
|
||||
/**
|
||||
* This is a bit mask wherein each bit corresponds to a value in
|
||||
|
@ -752,6 +758,20 @@ struct lsquic_engine_settings {
|
|||
* Default value is @ref LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
|
||||
*/
|
||||
unsigned short es_max_udp_payload_size_rx;
|
||||
|
||||
/**
|
||||
* No progress timeout.
|
||||
*
|
||||
* If connection does not make progress for this number of seconds, the
|
||||
* connection is dropped. Here, progress is defined as user streams
|
||||
* being written to or read from.
|
||||
*
|
||||
* If this value is zero, this timeout is disabled.
|
||||
*
|
||||
* Default value is @ref LSQUIC_DF_NOPROGRESS_TIMEOUT_SERVER in server
|
||||
* mode and @ref LSQUIC_DF_NOPROGRESS_TIMEOUT_CLIENT in client mode.
|
||||
*/
|
||||
unsigned es_noprogress_timeout;
|
||||
};
|
||||
|
||||
/* Initialize `settings' to default values */
|
||||
|
|
|
@ -99,7 +99,7 @@ lsquic_cfcw_incr_max_recv_off (struct lsquic_cfcw *fc, uint64_t incr)
|
|||
}
|
||||
else
|
||||
{
|
||||
LSQ_WARN("flow control violation: received at offset %"PRIu64", while "
|
||||
LSQ_INFO("flow control violation: received at offset %"PRIu64", while "
|
||||
"flow control receive offset is %"PRIu64,
|
||||
fc->cf_max_recv_off + incr, fc->cf_recv_off);
|
||||
return 0;
|
||||
|
|
|
@ -56,12 +56,15 @@ struct lsquic_conn_public {
|
|||
const struct network_path *path;
|
||||
#if LSQUIC_EXTRA_CHECKS
|
||||
unsigned long stream_frame_bytes;
|
||||
unsigned wtp_level; /* wtp: Write To Packets */
|
||||
#endif
|
||||
/* "unsigned" is wide enough: these values are only used for amplification
|
||||
* limit before initial path is validated.
|
||||
*/
|
||||
unsigned bytes_in; /* successfully processed */
|
||||
unsigned bytes_out;
|
||||
/* Used for no-progress timeout */
|
||||
lsquic_time_t last_tick, last_prog;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -295,6 +295,8 @@ lsquic_engine_init_settings (struct lsquic_engine_settings *settings,
|
|||
settings->es_init_max_streams_uni
|
||||
= LSQUIC_DF_INIT_MAX_STREAMS_UNI_SERVER;
|
||||
settings->es_ping_period = 0;
|
||||
settings->es_noprogress_timeout
|
||||
= LSQUIC_DF_NOPROGRESS_TIMEOUT_SERVER;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -311,6 +313,8 @@ lsquic_engine_init_settings (struct lsquic_engine_settings *settings,
|
|||
settings->es_init_max_streams_uni
|
||||
= LSQUIC_DF_INIT_MAX_STREAMS_UNI_CLIENT;
|
||||
settings->es_ping_period = LSQUIC_DF_PING_PERIOD;
|
||||
settings->es_noprogress_timeout
|
||||
= LSQUIC_DF_NOPROGRESS_TIMEOUT_CLIENT;
|
||||
}
|
||||
settings->es_max_streams_in = LSQUIC_DF_MAX_STREAMS_IN;
|
||||
settings->es_idle_conn_to = LSQUIC_DF_IDLE_CONN_TO;
|
||||
|
@ -601,6 +605,9 @@ lsquic_engine_new (unsigned flags,
|
|||
if (!engine->pub.enp_tokgen)
|
||||
return NULL;
|
||||
engine->pub.enp_crand = &engine->crand;
|
||||
if (engine->pub.enp_settings.es_noprogress_timeout)
|
||||
engine->pub.enp_noprog_timeout
|
||||
= engine->pub.enp_settings.es_noprogress_timeout * 1000000;
|
||||
if (flags & ENG_SERVER)
|
||||
{
|
||||
engine->pr_queue = lsquic_prq_create(
|
||||
|
|
|
@ -66,6 +66,8 @@ struct lsquic_engine_public {
|
|||
struct crand *enp_crand;
|
||||
struct evp_aead_ctx_st *enp_retry_aead_ctx;
|
||||
unsigned char *enp_alpn; /* May be set if not HTTP */
|
||||
/* es_noprogress_timeout converted to microseconds for speed */
|
||||
lsquic_time_t enp_noprog_timeout;
|
||||
};
|
||||
|
||||
/* Put connection onto the Tickable Queue if it is not already on it. If
|
||||
|
|
|
@ -112,6 +112,7 @@ enum full_conn_flags {
|
|||
FC_ABORT_COMPLAINED
|
||||
= (1 <<23),
|
||||
FC_GOT_SREJ = (1 <<24), /* Don't schedule ACK alarm */
|
||||
FC_NOPROG_TIMEOUT = (1 <<25),
|
||||
};
|
||||
|
||||
#define FC_IMMEDIATE_CLOSE_FLAGS \
|
||||
|
@ -686,6 +687,8 @@ new_conn_common (lsquic_cid_t cid, struct lsquic_engine_public *enpub,
|
|||
if (conn->fc_settings->es_support_push)
|
||||
conn->fc_flags |= FC_SUPPORT_PUSH;
|
||||
conn->fc_conn.cn_n_cces = sizeof(conn->fc_cces) / sizeof(conn->fc_cces[0]);
|
||||
if (conn->fc_settings->es_noprogress_timeout)
|
||||
conn->fc_flags |= FC_NOPROG_TIMEOUT;
|
||||
return conn;
|
||||
|
||||
cleanup_on_error:
|
||||
|
@ -2481,9 +2484,22 @@ idle_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
|
|||
lsquic_time_t now)
|
||||
{
|
||||
struct full_conn *conn = ctx;
|
||||
LSQ_DEBUG("connection timed out");
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out");
|
||||
conn->fc_flags |= FC_TIMED_OUT;
|
||||
|
||||
if ((conn->fc_flags & FC_NOPROG_TIMEOUT)
|
||||
&& conn->fc_pub.last_prog + conn->fc_enpub->enp_noprog_timeout < now)
|
||||
{
|
||||
LSQ_DEBUG("connection timed out due to lack of progress");
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out due to "
|
||||
"lack of progress");
|
||||
/* Different flag so that CONNECTION_CLOSE frame is sent */
|
||||
conn->fc_flags |= FC_ABORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
LSQ_DEBUG("connection timed out");
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out");
|
||||
conn->fc_flags |= FC_TIMED_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3242,6 +3258,31 @@ full_conn_ci_can_write_ack (struct lsquic_conn *lconn)
|
|||
}
|
||||
|
||||
|
||||
/* This should be called before lsquic_alarmset_ring_expired() */
|
||||
static void
|
||||
maybe_set_noprogress_alarm (struct full_conn *conn, lsquic_time_t now)
|
||||
{
|
||||
lsquic_time_t exp;
|
||||
|
||||
if (conn->fc_flags & FC_NOPROG_TIMEOUT)
|
||||
{
|
||||
if (conn->fc_pub.last_tick)
|
||||
{
|
||||
exp = conn->fc_pub.last_prog + conn->fc_enpub->enp_noprog_timeout;
|
||||
if (!lsquic_alarmset_is_set(&conn->fc_alset, AL_IDLE)
|
||||
|| exp < conn->fc_alset.as_expiry[AL_IDLE])
|
||||
lsquic_alarmset_set(&conn->fc_alset, AL_IDLE, exp);
|
||||
conn->fc_pub.last_tick = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->fc_pub.last_tick = now;
|
||||
conn->fc_pub.last_prog = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static enum tick_st
|
||||
full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
|
||||
{
|
||||
|
@ -3296,6 +3337,8 @@ full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
|
|||
conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
|
||||
}
|
||||
|
||||
maybe_set_noprogress_alarm(conn, now);
|
||||
|
||||
lsquic_send_ctl_tick_in(&conn->fc_send_ctl, now);
|
||||
lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
|
||||
CLOSE_IF_NECESSARY();
|
||||
|
@ -3520,6 +3563,20 @@ full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
set_earliest_idle_alarm (struct full_conn *conn, lsquic_time_t idle_conn_to)
|
||||
{
|
||||
lsquic_time_t exp;
|
||||
|
||||
if (conn->fc_pub.last_prog
|
||||
&& (assert(conn->fc_flags & FC_NOPROG_TIMEOUT),
|
||||
exp = conn->fc_pub.last_prog + conn->fc_enpub->enp_noprog_timeout,
|
||||
exp < idle_conn_to))
|
||||
idle_conn_to = exp;
|
||||
lsquic_alarmset_set(&conn->fc_alset, AL_IDLE, idle_conn_to);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
full_conn_ci_packet_in (lsquic_conn_t *lconn, lsquic_packet_in_t *packet_in)
|
||||
{
|
||||
|
@ -3528,7 +3585,7 @@ full_conn_ci_packet_in (lsquic_conn_t *lconn, lsquic_packet_in_t *packet_in)
|
|||
#if LSQUIC_CONN_STATS
|
||||
conn->fc_stats.in.bytes += packet_in->pi_data_sz;
|
||||
#endif
|
||||
lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
|
||||
set_earliest_idle_alarm(conn,
|
||||
packet_in->pi_received + conn->fc_settings->es_idle_conn_to);
|
||||
if (0 == (conn->fc_flags & FC_ERROR))
|
||||
if (0 != process_incoming_packet(conn, packet_in))
|
||||
|
|
|
@ -141,6 +141,7 @@ enum ifull_conn_flags
|
|||
enum more_flags
|
||||
{
|
||||
MF_VALIDATE_PATH = 1 << 0,
|
||||
MF_NOPROG_TIMEOUT = 1 << 1,
|
||||
};
|
||||
|
||||
|
||||
|
@ -476,6 +477,9 @@ static int
|
|||
insert_new_dcid (struct ietf_full_conn *, uint64_t seqno,
|
||||
const lsquic_cid_t *, const unsigned char *token, int update_cur_dcid);
|
||||
|
||||
static struct conn_cid_elem *
|
||||
find_cce_by_cid (struct ietf_full_conn *, const lsquic_cid_t *);
|
||||
|
||||
static unsigned
|
||||
highest_bit_set (unsigned sz)
|
||||
{
|
||||
|
@ -533,9 +537,22 @@ idle_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
|
|||
lsquic_time_t now)
|
||||
{
|
||||
struct ietf_full_conn *const conn = (struct ietf_full_conn *) ctx;
|
||||
LSQ_DEBUG("connection timed out");
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out");
|
||||
conn->ifc_flags |= IFC_TIMED_OUT;
|
||||
|
||||
if ((conn->ifc_mflags & MF_NOPROG_TIMEOUT)
|
||||
&& conn->ifc_pub.last_prog + conn->ifc_enpub->enp_noprog_timeout < now)
|
||||
{
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out due to "
|
||||
"lack of progress");
|
||||
/* Different flag so that CONNECTION_CLOSE frame is sent */
|
||||
ABORT_QUIETLY(0, TEC_APPLICATION_ERROR,
|
||||
"connection timed out due to lack of progress");
|
||||
}
|
||||
else
|
||||
{
|
||||
LSQ_DEBUG("connection timed out");
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out");
|
||||
conn->ifc_flags |= IFC_TIMED_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -564,6 +581,14 @@ cid_throt_alarm_expired (enum alarm_id al_id, void *ctx,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
wipe_path (struct ietf_full_conn *conn, unsigned path_id)
|
||||
{
|
||||
memset(&conn->ifc_paths[path_id], 0, sizeof(conn->ifc_paths[0]));
|
||||
conn->ifc_paths[path_id].cop_path.np_path_id = path_id;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
path_chal_alarm_expired (enum alarm_id al_id, void *ctx,
|
||||
lsquic_time_t expiry, lsquic_time_t now, unsigned path_id)
|
||||
|
@ -577,12 +602,15 @@ path_chal_alarm_expired (enum alarm_id al_id, void *ctx,
|
|||
LSQ_DEBUG("path #%u challenge expired, schedule another one", path_id);
|
||||
conn->ifc_send_flags |= SF_SEND_PATH_CHAL << path_id;
|
||||
}
|
||||
else
|
||||
else if (conn->ifc_cur_path_id != path_id)
|
||||
{
|
||||
LSQ_INFO("migration to path #%u failed after none of %u path "
|
||||
"challenges received responses", path_id, copath->cop_n_chals);
|
||||
memset(copath, 0, sizeof(*copath));
|
||||
wipe_path(conn, path_id);
|
||||
}
|
||||
else
|
||||
LSQ_INFO("no path challenge responses on current path %u, stop "
|
||||
"sending path challenges", path_id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1132,6 +1160,8 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
|
|||
conn->ifc_ping_unretx_thresh = 20;
|
||||
conn->ifc_max_retx_since_last_ack = MAX_RETR_PACKETS_SINCE_LAST_ACK;
|
||||
maybe_enable_spin(conn);
|
||||
if (conn->ifc_settings->es_noprogress_timeout)
|
||||
conn->ifc_mflags |= MF_NOPROG_TIMEOUT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1422,14 +1452,21 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
|
|||
*/
|
||||
have_outgoing_ack = 0;
|
||||
next_packno = ~0ULL;
|
||||
/* mini conn may drop Init packets, making gaps; don't warn about them: */
|
||||
conn->ifc_send_ctl.sc_senhist.sh_flags |= SH_GAP_OK;
|
||||
while ((packet_out = TAILQ_FIRST(&imc->imc_packets_out)))
|
||||
{
|
||||
TAILQ_REMOVE(&imc->imc_packets_out, packet_out, po_next);
|
||||
|
||||
/* Holes in the sequence signify ACKed or lost packets */
|
||||
/* Holes in the sequence signify no-longer-relevant Initial packets or
|
||||
* ACKed or lost packets.
|
||||
*/
|
||||
++next_packno;
|
||||
for ( ; next_packno < packet_out->po_packno; ++next_packno)
|
||||
{
|
||||
lsquic_senhist_add(&conn->ifc_send_ctl.sc_senhist, next_packno);
|
||||
conn->ifc_send_ctl.sc_senhist.sh_warn_thresh = next_packno;
|
||||
}
|
||||
|
||||
packet_out->po_path = CUR_NPATH(conn);
|
||||
if (imc->imc_sent_packnos & (1ULL << packet_out->po_packno))
|
||||
|
@ -1453,6 +1490,11 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
|
|||
(1 << QUIC_FRAME_ACK);
|
||||
}
|
||||
}
|
||||
conn->ifc_send_ctl.sc_senhist.sh_flags &= ~SH_GAP_OK;
|
||||
/* ...Yes, that's a bunch of little annoying steps to suppress the gap
|
||||
* warnings, but it would have been even more annoying (and expensive)
|
||||
* to add packet renumbering logic to the mini conn.
|
||||
*/
|
||||
|
||||
for (pns = 0; pns < N_PNS; ++pns)
|
||||
for (i = 0; i < 4; ++i)
|
||||
|
@ -4307,10 +4349,7 @@ switch_path_to (struct ietf_full_conn *conn, unsigned char path_id)
|
|||
conn->ifc_send_flags &= ~(SF_SEND_PATH_RESP << old_path_id);
|
||||
lsquic_alarmset_unset(&conn->ifc_alset, AL_PATH_CHAL + old_path_id);
|
||||
if (conn->ifc_flags & IFC_SERVER)
|
||||
{
|
||||
memset(&conn->ifc_paths[old_path_id], 0, sizeof(conn->ifc_paths[0]));
|
||||
conn->ifc_paths[old_path_id].cop_path.np_path_id = old_path_id;
|
||||
}
|
||||
wipe_path(conn, old_path_id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5417,6 +5456,24 @@ process_retire_connection_id_frame (struct ietf_full_conn *conn,
|
|||
return 0;
|
||||
}
|
||||
retire_cid(conn, cce, packet_in->pi_received);
|
||||
if (lconn->cn_cur_cce_idx == cce - lconn->cn_cces)
|
||||
{
|
||||
cce = find_cce_by_cid(conn, &packet_in->pi_dcid);
|
||||
if (cce)
|
||||
{
|
||||
LSQ_DEBUGC("current SCID was retired; set current SCID to "
|
||||
"%"CID_FMT" based on DCID in incoming packet",
|
||||
CID_BITS(&packet_in->pi_dcid));
|
||||
cce->cce_flags |= CCE_USED;
|
||||
lconn->cn_cur_cce_idx = cce - lconn->cn_cces;
|
||||
}
|
||||
else
|
||||
LSQ_WARN("current SCID was retired; no new SCID candidate");
|
||||
/* This could theoretically happen when zero-length CIDs were
|
||||
* used. Currently, there should be no way lsquic could get
|
||||
* into this situation.
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
LSQ_DEBUG("cannot retire CID seqno=%"PRIu64": not found", seqno);
|
||||
|
@ -6521,15 +6578,29 @@ process_incoming_packet_fast (struct ietf_full_conn *conn,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
set_earliest_idle_alarm (struct ietf_full_conn *conn, lsquic_time_t idle_conn_to)
|
||||
{
|
||||
lsquic_time_t exp;
|
||||
|
||||
if (conn->ifc_pub.last_prog
|
||||
&& (assert(conn->ifc_mflags & MF_NOPROG_TIMEOUT),
|
||||
exp = conn->ifc_pub.last_prog + conn->ifc_enpub->enp_noprog_timeout,
|
||||
exp < idle_conn_to))
|
||||
idle_conn_to = exp;
|
||||
if (idle_conn_to)
|
||||
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE, idle_conn_to);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ietf_full_conn_ci_packet_in (struct lsquic_conn *lconn,
|
||||
struct lsquic_packet_in *packet_in)
|
||||
{
|
||||
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
|
||||
|
||||
if (conn->ifc_idle_to)
|
||||
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE,
|
||||
packet_in->pi_received + conn->ifc_idle_to);
|
||||
set_earliest_idle_alarm(conn, conn->ifc_idle_to
|
||||
? packet_in->pi_received + conn->ifc_idle_to : 0);
|
||||
if (0 == (conn->ifc_flags & IFC_IMMEDIATE_CLOSE_FLAGS))
|
||||
if (0 != conn->ifc_process_incoming_packet(conn, packet_in))
|
||||
conn->ifc_flags |= IFC_ERROR;
|
||||
|
@ -6646,6 +6717,32 @@ static void (*const send_funcs[N_SEND])(
|
|||
|SF_SEND_ACK_FREQUENCY\
|
||||
|SF_SEND_STOP_SENDING)
|
||||
|
||||
|
||||
/* This should be called before lsquic_alarmset_ring_expired() */
|
||||
static void
|
||||
maybe_set_noprogress_alarm (struct ietf_full_conn *conn, lsquic_time_t now)
|
||||
{
|
||||
lsquic_time_t exp;
|
||||
|
||||
if (conn->ifc_mflags & MF_NOPROG_TIMEOUT)
|
||||
{
|
||||
if (conn->ifc_pub.last_tick)
|
||||
{
|
||||
exp = conn->ifc_pub.last_prog + conn->ifc_enpub->enp_noprog_timeout;
|
||||
if (!lsquic_alarmset_is_set(&conn->ifc_alset, AL_IDLE)
|
||||
|| exp < conn->ifc_alset.as_expiry[AL_IDLE])
|
||||
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE, exp);
|
||||
conn->ifc_pub.last_tick = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->ifc_pub.last_tick = now;
|
||||
conn->ifc_pub.last_prog = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static enum tick_st
|
||||
ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
|
||||
{
|
||||
|
@ -6688,6 +6785,8 @@ ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
|
|||
conn->ifc_flags &= ~IFC_HAVE_SAVED_ACK;
|
||||
}
|
||||
|
||||
maybe_set_noprogress_alarm(conn, now);
|
||||
|
||||
lsquic_send_ctl_tick_in(&conn->ifc_send_ctl, now);
|
||||
lsquic_send_ctl_set_buffer_stream_packets(&conn->ifc_send_ctl, 1);
|
||||
CLOSE_IF_NECESSARY();
|
||||
|
|
|
@ -635,7 +635,7 @@ ietf_mini_conn_ci_is_tickable (struct lsquic_conn *lconn)
|
|||
if (!(packet_out->po_flags & PO_SENT))
|
||||
{
|
||||
packet_size = lsquic_packet_out_total_sz(lconn, packet_out);
|
||||
return imico_can_send(conn, packet_size + IQUIC_TAG_LEN);
|
||||
return imico_can_send(conn, packet_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -665,15 +665,15 @@ ietf_mini_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
|
|||
packet_size = lsquic_packet_out_total_sz(lconn, packet_out);
|
||||
if (size == 0 || packet_size + size <= conn->imc_path.np_pack_size)
|
||||
{
|
||||
if (!imico_can_send(conn, packet_size + IQUIC_TAG_LEN))
|
||||
if (!imico_can_send(conn, packet_size))
|
||||
{
|
||||
LSQ_DEBUG("cannot send packet %"PRIu64" of size %zu: client "
|
||||
"address has not been validated", packet_out->po_packno,
|
||||
packet_size + IQUIC_TAG_LEN);
|
||||
packet_size);
|
||||
return NULL;
|
||||
}
|
||||
packet_out->po_flags |= PO_SENT;
|
||||
conn->imc_bytes_out += packet_size + IQUIC_TAG_LEN;
|
||||
conn->imc_bytes_out += packet_size;
|
||||
if (size == 0)
|
||||
LSQ_DEBUG("packet_to_send: %"PRIu64, packet_out->po_packno);
|
||||
else
|
||||
|
@ -1310,7 +1310,7 @@ ietf_mini_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
|
|||
|
||||
packet_out->po_flags &= ~PO_SENT;
|
||||
packet_size = lsquic_packet_out_total_sz(lconn, packet_out);
|
||||
conn->imc_bytes_out -= packet_size + IQUIC_TAG_LEN;
|
||||
conn->imc_bytes_out -= packet_size;
|
||||
LSQ_DEBUG("%s: packet %"PRIu64" not sent", __func__, packet_out->po_packno);
|
||||
}
|
||||
|
||||
|
@ -1356,9 +1356,11 @@ imico_handle_losses_and_have_unsent (struct ietf_mini_conn *conn,
|
|||
{
|
||||
TAILQ_HEAD(, lsquic_packet_out) lost_packets =
|
||||
TAILQ_HEAD_INITIALIZER(lost_packets);
|
||||
const struct lsquic_conn *const lconn = &conn->imc_conn;
|
||||
lsquic_packet_out_t *packet_out, *next;
|
||||
lsquic_time_t retx_to = 0;
|
||||
unsigned n_to_send = 0;
|
||||
size_t packet_size;
|
||||
|
||||
for (packet_out = TAILQ_FIRST(&conn->imc_packets_out); packet_out;
|
||||
packet_out = next)
|
||||
|
@ -1376,8 +1378,11 @@ imico_handle_losses_and_have_unsent (struct ietf_mini_conn *conn,
|
|||
TAILQ_INSERT_TAIL(&lost_packets, packet_out, po_next);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (packet_size = lsquic_packet_out_total_sz(lconn, packet_out),
|
||||
imico_can_send(conn, packet_size))
|
||||
++n_to_send;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
conn->imc_hsk_count += !TAILQ_EMPTY(&lost_packets);
|
||||
|
@ -1387,7 +1392,11 @@ imico_handle_losses_and_have_unsent (struct ietf_mini_conn *conn,
|
|||
TAILQ_REMOVE(&lost_packets, packet_out, po_next);
|
||||
if ((packet_out->po_frame_types & IQUIC_FRAME_RETX_MASK)
|
||||
&& 0 == imico_repackage_packet(conn, packet_out))
|
||||
++n_to_send;
|
||||
{
|
||||
packet_size = lsquic_packet_out_total_sz(lconn, packet_out);
|
||||
if (imico_can_send(conn, packet_size))
|
||||
++n_to_send;
|
||||
}
|
||||
else
|
||||
imico_destroy_packet(conn, packet_out);
|
||||
}
|
||||
|
|
|
@ -220,7 +220,8 @@ typedef struct lsquic_packet_out
|
|||
#if LSQUIC_EXTRA_CHECKS
|
||||
#define lsquic_packet_out_sent_sz(lconn, p) ( \
|
||||
__builtin_expect(((p)->po_flags & PO_SENT_SZ), 1) ? \
|
||||
(assert((p)->po_sent_sz == lsquic_packet_out_total_sz(lconn, p)), \
|
||||
(assert(((p)->po_flags & PO_HELLO /* Avoid client DCID change */) \
|
||||
|| (p)->po_sent_sz == lsquic_packet_out_total_sz(lconn, p)), \
|
||||
(p)->po_sent_sz) : lsquic_packet_out_total_sz(lconn, p))
|
||||
# else
|
||||
#define lsquic_packet_out_sent_sz(lconn, p) ( \
|
||||
|
|
|
@ -363,10 +363,7 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *ctl, struct lsquic_alarmset *alset,
|
|||
ctl->sc_cached_bpt.stream_id = UINT64_MAX;
|
||||
#if LSQUIC_EXTRA_CHECKS
|
||||
ctl->sc_flags |= SC_SANITY_CHECK;
|
||||
#else
|
||||
if ((ctl->sc_conn_pub->lconn->cn_flags & (LSCONN_IETF|LSCONN_SERVER))
|
||||
== LSCONN_IETF)
|
||||
ctl->sc_flags |= SC_SANITY_CHECK;
|
||||
LSQ_DEBUG("sanity checks enabled");
|
||||
#endif
|
||||
ctl->sc_gap = UINT64_MAX - 1 /* Can't have +1 == 0 */;
|
||||
if ((ctl->sc_conn_pub->lconn->cn_flags & (LSCONN_IETF|LSCONN_SERVER))
|
||||
|
@ -2227,7 +2224,8 @@ lsquic_send_ctl_squeeze_sched (lsquic_send_ctl_t *ctl)
|
|||
packet_out = next)
|
||||
{
|
||||
next = TAILQ_NEXT(packet_out, po_next);
|
||||
if (packet_out->po_regen_sz < packet_out->po_data_sz)
|
||||
if (packet_out->po_regen_sz < packet_out->po_data_sz
|
||||
|| packet_out->po_frame_types == QUIC_FTBIT_PATH_CHALLENGE)
|
||||
{
|
||||
if (packet_out->po_flags & PO_ENCRYPTED)
|
||||
send_ctl_return_enc_data(ctl, packet_out);
|
||||
|
@ -2238,7 +2236,7 @@ lsquic_send_ctl_squeeze_sched (lsquic_send_ctl_t *ctl)
|
|||
/* Log the whole list before we squeeze for the first time */
|
||||
if (!pre_squeeze_logged++)
|
||||
LOG_PACKET_Q(&ctl->sc_scheduled_packets,
|
||||
"unacked packets before squeezing");
|
||||
"scheduled packets before squeezing");
|
||||
#endif
|
||||
send_ctl_sched_remove(ctl, packet_out);
|
||||
LSQ_DEBUG("Dropping packet %"PRIu64" from scheduled queue",
|
||||
|
@ -2255,7 +2253,7 @@ lsquic_send_ctl_squeeze_sched (lsquic_send_ctl_t *ctl)
|
|||
#ifndef NDEBUG
|
||||
if (pre_squeeze_logged)
|
||||
LOG_PACKET_Q(&ctl->sc_scheduled_packets,
|
||||
"unacked packets after squeezing");
|
||||
"scheduled packets after squeezing");
|
||||
else if (ctl->sc_n_scheduled > 0)
|
||||
LOG_PACKET_Q(&ctl->sc_scheduled_packets, "delayed packets");
|
||||
#endif
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
|
||||
typedef struct lsquic_senhist {
|
||||
lsquic_packno_t sh_last_sent;
|
||||
lsquic_packno_t sh_warn_thresh;
|
||||
enum {
|
||||
#if !LSQUIC_SENHIST_FATAL
|
||||
SH_WARNED = 1 << 0, /* Warn once */
|
||||
#endif
|
||||
SH_GAP_OK = 1 << 1, /* Before connection is just about to close */
|
||||
SH_GAP_OK = 1 << 1, /* Before connection is just about to close or
|
||||
* during mini/full packet handoff.
|
||||
*/
|
||||
} sh_flags;
|
||||
} lsquic_senhist_t;
|
||||
|
||||
|
@ -35,7 +38,8 @@ typedef struct lsquic_senhist {
|
|||
|
||||
#if LSQUIC_SENHIST_FATAL
|
||||
#define lsquic_senhist_add(hist, packno) do { \
|
||||
if (!((hist)->sh_flags & SH_GAP_OK)) \
|
||||
if (!((hist)->sh_flags & SH_GAP_OK) \
|
||||
&& (packno) > (hist)->sh_warn_thresh) \
|
||||
assert((hist)->sh_last_sent == packno - 1); \
|
||||
if ((int64_t) (packno) > (int64_t) (hist)->sh_last_sent) \
|
||||
(hist)->sh_last_sent = packno; \
|
||||
|
@ -44,7 +48,8 @@ typedef struct lsquic_senhist {
|
|||
#define lsquic_senhist_add(hist, packno) do { \
|
||||
if ((hist)->sh_last_sent != packno - 1) \
|
||||
{ \
|
||||
if (!((hist)->sh_flags & (SH_WARNED|SH_GAP_OK))) \
|
||||
if (!((hist)->sh_flags & (SH_WARNED|SH_GAP_OK)) \
|
||||
&& (packno) > (hist)->sh_warn_thresh) \
|
||||
{ \
|
||||
LSQ_WARN("send history gap %"PRIu64" - %"PRIu64, \
|
||||
(hist)->sh_last_sent, packno); \
|
||||
|
|
|
@ -137,7 +137,7 @@ lsquic_sfcw_set_max_recv_off (struct lsquic_sfcw *fc, uint64_t max_recv_off)
|
|||
}
|
||||
else
|
||||
{
|
||||
LSQ_WARN("flow control violation: received at offset %"PRIu64", "
|
||||
LSQ_INFO("flow control violation: received at offset %"PRIu64", "
|
||||
"while flow control receive offset is %"PRIu64,
|
||||
max_recv_off, fc->sf_recv_off);
|
||||
return 0;
|
||||
|
|
|
@ -259,6 +259,26 @@ stream_inside_callback (const lsquic_stream_t *stream)
|
|||
}
|
||||
|
||||
|
||||
/* This is an approximation. If data is written or read outside of the
|
||||
* event loop, last_prog will be somewhat out of date, but it's close
|
||||
* enough for our purposes.
|
||||
*/
|
||||
static void
|
||||
maybe_update_last_progress (struct lsquic_stream *stream)
|
||||
{
|
||||
if (stream->conn_pub && !lsquic_stream_is_critical(stream))
|
||||
{
|
||||
if (stream->conn_pub->last_prog != stream->conn_pub->last_tick)
|
||||
LSQ_DEBUG("update last progress to %"PRIu64,
|
||||
stream->conn_pub->last_tick);
|
||||
stream->conn_pub->last_prog = stream->conn_pub->last_tick;
|
||||
#ifndef NDEBUG
|
||||
stream->sm_last_prog = stream->conn_pub->last_tick;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
maybe_conn_to_tickable (lsquic_stream_t *stream)
|
||||
{
|
||||
|
@ -1460,6 +1480,8 @@ ssize_t
|
|||
lsquic_stream_readf (struct lsquic_stream *stream,
|
||||
size_t (*readf)(void *, const unsigned char *, size_t, int), void *ctx)
|
||||
{
|
||||
ssize_t nread;
|
||||
|
||||
SM_HISTORY_APPEND(stream, SHE_USER_READ);
|
||||
|
||||
if (lsquic_stream_is_reset(stream))
|
||||
|
@ -1485,7 +1507,11 @@ lsquic_stream_readf (struct lsquic_stream *stream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
return stream_readf(stream, readf, ctx);
|
||||
nread = stream_readf(stream, readf, ctx);
|
||||
if (nread >= 0)
|
||||
maybe_update_last_progress(stream);
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2745,6 +2771,9 @@ verify_conn_cap (const struct lsquic_conn_public *conn_pub)
|
|||
struct lsquic_hash_elem *el;
|
||||
unsigned n_buffered;
|
||||
|
||||
if (conn_pub->wtp_level > 1)
|
||||
return;
|
||||
|
||||
if (!conn_pub->all_streams)
|
||||
/* TODO: enable this check for unit tests as well */
|
||||
return;
|
||||
|
@ -2760,6 +2789,7 @@ verify_conn_cap (const struct lsquic_conn_public *conn_pub)
|
|||
|
||||
assert(n_buffered + conn_pub->stream_frame_bytes
|
||||
== conn_pub->conn_cap.cc_sent);
|
||||
LSQ_DEBUG("%s: cc_sent: %"PRIu64, __func__, conn_pub->conn_cap.cc_sent);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3056,6 +3086,10 @@ stream_write_to_packets (lsquic_stream_t *stream, struct lsquic_reader *reader,
|
|||
.fgc_nread_from_reader = 0,
|
||||
};
|
||||
|
||||
#if LSQUIC_EXTRA_CHECKS
|
||||
if (stream->conn_pub)
|
||||
++stream->conn_pub->wtp_level;
|
||||
#endif
|
||||
use_framing = (stream->sm_bflags & (SMBF_IETF|SMBF_USE_HEADERS))
|
||||
== (SMBF_IETF|SMBF_USE_HEADERS);
|
||||
if (use_framing)
|
||||
|
@ -3079,7 +3113,10 @@ stream_write_to_packets (lsquic_stream_t *stream, struct lsquic_reader *reader,
|
|||
{
|
||||
case SWTP_OK:
|
||||
if (!seen_ok++)
|
||||
{
|
||||
maybe_conn_to_tickable_if_writeable(stream, 0);
|
||||
maybe_update_last_progress(stream);
|
||||
}
|
||||
if (fg_ctx.fgc_fin(&fg_ctx))
|
||||
{
|
||||
if (use_framing && seen_ok)
|
||||
|
@ -3097,7 +3134,7 @@ stream_write_to_packets (lsquic_stream_t *stream, struct lsquic_reader *reader,
|
|||
default:
|
||||
abort_connection(stream);
|
||||
stream->stream_flags &= ~STREAM_LAST_WRITE_OK;
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3113,7 +3150,7 @@ stream_write_to_packets (lsquic_stream_t *stream, struct lsquic_reader *reader,
|
|||
{
|
||||
nw = save_to_buffer(stream, reader, size);
|
||||
if (nw < 0)
|
||||
return -1;
|
||||
goto err;
|
||||
fg_ctx.fgc_nread_from_reader += nw; /* Make this cleaner? */
|
||||
}
|
||||
}
|
||||
|
@ -3129,7 +3166,18 @@ stream_write_to_packets (lsquic_stream_t *stream, struct lsquic_reader *reader,
|
|||
maybe_mark_as_blocked(stream);
|
||||
|
||||
end:
|
||||
#if LSQUIC_EXTRA_CHECKS
|
||||
if (stream->conn_pub)
|
||||
--stream->conn_pub->wtp_level;
|
||||
#endif
|
||||
return fg_ctx.fgc_nread_from_reader;
|
||||
|
||||
err:
|
||||
#if LSQUIC_EXTRA_CHECKS
|
||||
if (stream->conn_pub)
|
||||
--stream->conn_pub->wtp_level;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4056,6 +4104,7 @@ lsquic_stream_get_hset (struct lsquic_stream *stream)
|
|||
stream->stream_flags |= STREAM_FIN_REACHED;
|
||||
SM_HISTORY_APPEND(stream, SHE_REACH_FIN);
|
||||
}
|
||||
maybe_update_last_progress(stream);
|
||||
LSQ_DEBUG("return header set");
|
||||
return hset;
|
||||
}
|
||||
|
@ -4347,12 +4396,15 @@ hq_read (void *ctx, const unsigned char *buf, size_t sz, int fin)
|
|||
LSQ_INFO("FIN at unexpected place in filter; state: %u",
|
||||
filter->hqfi_state);
|
||||
filter->hqfi_flags |= HQFI_FLAG_ERROR;
|
||||
/* From [draft-ietf-quic-http-16] Section 3.1:
|
||||
* When a stream terminates cleanly, if the last frame on
|
||||
* the stream was truncated, this MUST be treated as a connection error
|
||||
* (see HTTP_MALFORMED_FRAME in Section 8.1).
|
||||
/* From [draft-ietf-quic-http-28] Section 7.1:
|
||||
" When a stream terminates cleanly, if the last frame on the stream was
|
||||
" truncated, this MUST be treated as a connection error (Section 8) of
|
||||
" type H3_FRAME_ERROR. Streams which terminate abruptly may be reset
|
||||
" at any point in a frame.
|
||||
*/
|
||||
abort_connection(stream);
|
||||
lconn = stream->conn_pub->lconn;
|
||||
lconn->cn_if->ci_abort_error(lconn, 1, HEC_FRAME_ERROR,
|
||||
"last HTTP/3 frame on stream %"PRIu64" was truncated", stream->id);
|
||||
}
|
||||
|
||||
return p - buf;
|
||||
|
|
|
@ -317,6 +317,11 @@ struct lsquic_stream
|
|||
|
||||
uint64_t sm_last_frame_off;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Last time stream made progress */
|
||||
lsquic_time_t sm_last_prog;
|
||||
#endif
|
||||
|
||||
/* Content length specified in incoming `content-length' header field.
|
||||
* Used to verify size of DATA frames.
|
||||
*/
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b577d56964e443972adb38ec56706181846cc47f
|
||||
Subproject commit bd5d58987e0e88d7c1b676f83624528926fb423a
|
|
@ -79,6 +79,7 @@ sampler_test_send_packet (struct sampler_test *stest, lsquic_packno_t packno,
|
|||
memset(packet_out, 0, sizeof(*packet_out));
|
||||
packet_out->po_packno = packno;
|
||||
packet_out->po_flags |= PO_SENT_SZ;
|
||||
packet_out->po_flags |= PO_HELLO; /* Bypass sanity check */
|
||||
packet_out->po_sent_sz = kRegularPacketSize;
|
||||
packet_out->po_sent = stest->time;
|
||||
if (retx)
|
||||
|
|
|
@ -143,11 +143,17 @@ get_network_path (struct lsquic_conn *lconn, const struct sockaddr *sa)
|
|||
return &network_path;
|
||||
}
|
||||
|
||||
static void
|
||||
abort_error (struct lsquic_conn *lconn, int is_app,
|
||||
unsigned error_code, const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct conn_iface our_conn_if =
|
||||
{
|
||||
.ci_can_write_ack = unit_test_doesnt_write_ack,
|
||||
.ci_get_path = get_network_path,
|
||||
.ci_abort_error = abort_error,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
int
|
||||
main (void)
|
||||
{
|
||||
struct lsquic_senhist hist = { 0
|
||||
struct lsquic_senhist hist = { 0, 0
|
||||
#if !LSQUIC_SENHIST_FATAL
|
||||
, 0
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue