Release 2.4.7

- Add echo client and server to the distibution.
- Add MD5 client and server to the distibution.
- Fix http_client: check command-line arguments better, prevent crash.
- Fix IETF conn: can_write_ack() should only care about APP PNS.
- Client: delay stream creation until handshake succeds.
- Reset HTTP stream whose write end is closed prematurely.
- Fix tickable(): mirror behavior of tick() wrt buffered packets.
- Log reason why engine is tickable.
This commit is contained in:
Dmitri Tikhonov 2019-10-15 17:02:21 -04:00
parent ad08470cea
commit 0adf085acf
27 changed files with 1668 additions and 92 deletions

View file

@ -32,7 +32,7 @@ lsquic_alarmset_init_alarm (lsquic_alarmset_t *alset, enum alarm_id al_id,
}
static const char *const lsquic_alid2str[] =
const char *const lsquic_alid2str[] =
{
[AL_HANDSHAKE] = "HANDSHAKE",
[AL_RETX_INIT] = "RETX_INIT",
@ -75,20 +75,22 @@ lsquic_alarmset_ring_expired (lsquic_alarmset_t *alset, lsquic_time_t now)
lsquic_time_t
lsquic_alarmset_mintime (const lsquic_alarmset_t *alset)
lsquic_alarmset_mintime (const lsquic_alarmset_t *alset, enum alarm_id *idp)
{
lsquic_time_t expiry;
enum alarm_id al_id;
enum alarm_id al_id, ret_id;
if (alset->as_armed_set)
{
expiry = UINT64_MAX;
for (al_id = 0; al_id < MAX_LSQUIC_ALARMS; ++al_id)
for (al_id = 0, ret_id = 0; al_id < MAX_LSQUIC_ALARMS; ++al_id)
if ((alset->as_armed_set & (1 << al_id))
&& alset->as_expiry[al_id] < expiry)
{
expiry = alset->as_expiry[al_id];
ret_id = al_id;
}
*idp = ret_id;
return expiry;
}
else

View file

@ -94,6 +94,8 @@ void
lsquic_alarmset_ring_expired (lsquic_alarmset_t *, lsquic_time_t now);
lsquic_time_t
lsquic_alarmset_mintime (const lsquic_alarmset_t *);
lsquic_alarmset_mintime (const lsquic_alarmset_t *, enum alarm_id *);
extern const char *const lsquic_alid2str[];
#endif

View file

@ -19,6 +19,8 @@
#include "lsquic_types.h"
#include "lsquic_int_types.h"
#include "lsquic_attq.h"
#include "lsquic_packet_common.h"
#include "lsquic_alarmset.h"
#include "lsquic_malo.h"
#include "lsquic_hash.h"
#include "lsquic_conn.h"
@ -107,7 +109,7 @@ attq_swap (struct attq *q, unsigned a, unsigned b)
int
attq_add (struct attq *q, struct lsquic_conn *conn,
lsquic_time_t advisory_time)
lsquic_time_t advisory_time, enum ae_why why)
{
struct attq_elem *el, **heap;
unsigned n, i;
@ -129,6 +131,7 @@ attq_add (struct attq *q, struct lsquic_conn *conn,
if (!el)
return -1;
el->ae_adv_time = advisory_time;
el->ae_why = why;
/* The only place linkage between conn and attq_elem occurs: */
el->ae_conn = conn;
@ -256,11 +259,29 @@ attq_count_before (struct attq *q, lsquic_time_t cutoff)
}
const lsquic_time_t *
attq_next_time (struct attq *q)
const struct attq_elem *
attq_next (struct attq *q)
{
if (q->aq_nelem > 0)
return &q->aq_heap[0]->ae_adv_time;
return q->aq_heap[0];
else
return NULL;
}
const char *
lsquic_attq_why2str (enum ae_why why)
{
switch (why)
{
case AEW_PACER:
return "PACER";
case AEW_MINI_EXPIRE:
return "MINI-EXPIRE";
default:
why -= N_AEWS;
if ((unsigned) why < (unsigned) MAX_LSQUIC_ALARMS)
return lsquic_alid2str[why];
return "UNKNOWN";
}
}

View file

@ -18,6 +18,15 @@ struct attq_elem
struct lsquic_conn *ae_conn;
lsquic_time_t ae_adv_time;
unsigned ae_heap_idx;
/* The "why" describes why the connection is in the Advisory Tick Time
* Queue. Values past the range describe different alarm types (see
* enum alarm_id).
*/
enum ae_why {
AEW_PACER,
AEW_MINI_EXPIRE,
N_AEWS
} ae_why;
};
@ -29,7 +38,8 @@ attq_destroy (struct attq *);
/* Return 0 on success, -1 on failure (malloc) */
int
attq_add (struct attq *, struct lsquic_conn *, lsquic_time_t advisory_time);
attq_add (struct attq *, struct lsquic_conn *, lsquic_time_t advisory_time,
enum ae_why);
void
attq_remove (struct attq *, struct lsquic_conn *);
@ -40,7 +50,10 @@ attq_pop (struct attq *, lsquic_time_t cutoff);
unsigned
attq_count_before (struct attq *, lsquic_time_t cutoff);
const lsquic_time_t *
attq_next_time (struct attq *);
const struct attq_elem *
attq_next (struct attq *);
const char *
lsquic_attq_why2str (enum ae_why);
#endif

View file

@ -123,7 +123,7 @@ struct conn_iface
(*ci_is_tickable) (struct lsquic_conn *);
lsquic_time_t
(*ci_next_tick_time) (struct lsquic_conn *);
(*ci_next_tick_time) (struct lsquic_conn *, unsigned *why);
int
(*ci_can_write_ack) (struct lsquic_conn *);

View file

@ -2138,6 +2138,14 @@ iquic_esf_alg_keysize (enc_session_t *enc_session_p)
}
static int
iquic_esf_zero_rtt_enabled (enc_session_t *enc_session_p)
{
struct enc_sess_iquic *const enc_sess = enc_session_p;
return enc_sess->esi_zero_rtt_buf != NULL;
}
int
iquic_esfi_reset_dcid (enc_session_t *enc_session_p,
const lsquic_cid_t *old_dcid, const lsquic_cid_t *new_dcid)
@ -2204,6 +2212,7 @@ const struct enc_session_funcs_common lsquic_enc_session_common_ietf_v1 =
.esf_cipher = iquic_esf_cipher,
.esf_keysize = iquic_esf_keysize,
.esf_alg_keysize = iquic_esf_alg_keysize,
.esf_is_zero_rtt_enabled = iquic_esf_zero_rtt_enabled,
};

View file

@ -1179,7 +1179,7 @@ lsquic_engine_add_conn_to_tickable (struct lsquic_engine_public *enpub,
void
lsquic_engine_add_conn_to_attq (struct lsquic_engine_public *enpub,
lsquic_conn_t *conn, lsquic_time_t tick_time)
lsquic_conn_t *conn, lsquic_time_t tick_time, unsigned why)
{
lsquic_engine_t *const engine = (lsquic_engine_t *) enpub;
if (conn->cn_flags & LSCONN_TICKABLE)
@ -1194,11 +1194,11 @@ lsquic_engine_add_conn_to_attq (struct lsquic_engine_public *enpub,
if (lsquic_conn_adv_time(conn) != tick_time)
{
attq_remove(engine->attq, conn);
if (0 != attq_add(engine->attq, conn, tick_time))
if (0 != attq_add(engine->attq, conn, tick_time, why))
engine_decref_conn(engine, conn, LSCONN_ATTQ);
}
}
else if (0 == attq_add(engine->attq, conn, tick_time))
else if (0 == attq_add(engine->attq, conn, tick_time, why))
engine_incref_conn(conn, LSCONN_ATTQ);
}
@ -2355,7 +2355,7 @@ process_connections (lsquic_engine_t *engine, conn_iter_f next_conn,
{
lsquic_conn_t *conn;
enum tick_st tick_st;
unsigned i;
unsigned i, why;
lsquic_time_t next_tick_time;
struct conns_stailq closed_conns;
struct conns_tailq ticked_conns;
@ -2453,10 +2453,10 @@ process_connections (lsquic_engine_t *engine, conn_iter_f next_conn,
}
else if (!(conn->cn_flags & LSCONN_ATTQ))
{
next_tick_time = conn->cn_if->ci_next_tick_time(conn);
next_tick_time = conn->cn_if->ci_next_tick_time(conn, &why);
if (next_tick_time)
{
if (0 == attq_add(engine->attq, conn, next_tick_time))
if (0 == attq_add(engine->attq, conn, next_tick_time, why))
engine_incref_conn(conn, LSCONN_ATTQ);
}
else
@ -2590,38 +2590,80 @@ lsquic_engine_cooldown (lsquic_engine_t *engine)
int
lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
{
const lsquic_time_t *next_attq_time;
const struct attq_elem *next_attq;
lsquic_time_t now, next_time;
const struct lsquic_conn *conn;
const lsquic_cid_t *cid;
const enum lsq_log_level L = LSQ_LOG_DEBUG; /* Easy toggle */
ENGINE_CALLS_INCR(engine);
if (((engine->flags & ENG_PAST_DEADLINE)
if ((engine->flags & ENG_PAST_DEADLINE)
&& lsquic_mh_count(&engine->conns_out))
|| (engine->pr_queue && prq_have_pending(engine->pr_queue))
|| lsquic_mh_count(&engine->conns_tickable))
{
conn = lsquic_mh_peek(&engine->conns_out);
cid = lsquic_conn_log_cid(conn);
LSQ_LOGC(L, "next advisory tick is now: went past deadline last time "
"and have %u outgoing connection%.*s (%"CID_FMT" first)",
lsquic_mh_count(&engine->conns_out),
lsquic_mh_count(&engine->conns_out) != 1, "s", CID_BITS(cid));
*diff = 0;
return 1;
}
next_attq_time = attq_next_time(engine->attq);
if (engine->pr_queue && prq_have_pending(engine->pr_queue))
{
LSQ_LOG(L, "next advisory tick is now: have pending PRQ elements");
*diff = 0;
return 1;
}
if (lsquic_mh_count(&engine->conns_tickable))
{
conn = lsquic_mh_peek(&engine->conns_tickable);
cid = lsquic_conn_log_cid(conn);
LSQ_LOGC(L, "next advisory tick is now: have %u tickable "
"connection%.*s (%"CID_FMT" first)",
lsquic_mh_count(&engine->conns_tickable),
lsquic_mh_count(&engine->conns_tickable) != 1, "s", CID_BITS(cid));
*diff = 0;
return 1;
}
next_attq = attq_next(engine->attq);
if (engine->pub.enp_flags & ENPUB_CAN_SEND)
{
if (next_attq_time)
next_time = *next_attq_time;
if (next_attq)
next_time = next_attq->ae_adv_time;
else
return 0;
}
else
{
if (next_attq_time)
next_time = MIN(*next_attq_time, engine->resume_sending_at);
if (next_attq)
{
next_time = next_attq->ae_adv_time;
if (engine->resume_sending_at < next_time)
{
next_time = engine->resume_sending_at;
next_attq = NULL;
}
}
else
next_time = engine->resume_sending_at;
}
now = lsquic_time_now();
*diff = (int) ((int64_t) next_time - (int64_t) now);
if (next_attq)
{
cid = lsquic_conn_log_cid(next_attq->ae_conn);
LSQ_LOGC(L, "next advisory tick is %d usec away: conn %"CID_FMT
": %s", *diff, CID_BITS(cid),
lsquic_attq_why2str(next_attq->ae_why));
}
else
LSQ_LOG(L, "next advisory tick is %d usec away: resume sending", *diff);
return 1;
}

View file

@ -72,7 +72,7 @@ lsquic_engine_add_conn_to_tickable (struct lsquic_engine_public *,
*/
void
lsquic_engine_add_conn_to_attq (struct lsquic_engine_public *enpub,
lsquic_conn_t *, lsquic_time_t);
lsquic_conn_t *, lsquic_time_t, unsigned why);
void
lsquic_engine_retire_cid (struct lsquic_engine_public *,

View file

@ -63,6 +63,7 @@
#include "lsquic_version.h"
#include "lsquic_headers.h"
#include "lsquic_handshake.h"
#include "lsquic_attq.h"
#include "lsquic_conn.h"
#include "lsquic_conn_public.h"
@ -1326,11 +1327,21 @@ full_conn_ci_n_avail_streams (const lsquic_conn_t *lconn)
}
static int
handshake_done_or_doing_zero_rtt (const struct full_conn *conn)
{
return (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|| conn->fc_conn.cn_esf_c->esf_is_zero_rtt_enabled(
conn->fc_conn.cn_enc_session);
}
static void
full_conn_ci_make_stream (struct lsquic_conn *lconn)
{
struct full_conn *conn = (struct full_conn *) lconn;
if (full_conn_ci_n_avail_streams(lconn) > 0)
if (handshake_done_or_doing_zero_rtt(conn)
&& full_conn_ci_n_avail_streams(lconn) > 0)
{
if (!new_stream(conn, generate_stream_id(conn), SCF_CALL_ON_NEW))
ABORT_ERROR("could not create new stream: %s", strerror(errno));
@ -3440,9 +3451,7 @@ full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
}
lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 0);
if (!(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE) &&
!conn->fc_conn.cn_esf_c->esf_is_zero_rtt_enabled(
conn->fc_conn.cn_enc_session))
if (!handshake_done_or_doing_zero_rtt(conn))
{
process_hsk_stream_write_events(conn);
goto end_write;
@ -3623,12 +3632,14 @@ full_conn_ci_hsk_done (lsquic_conn_t *lconn, enum lsquic_hsk_status status)
if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done)
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn,
status);
if ((status == LSQ_HSK_OK || status == LSQ_HSK_0RTT_OK)
&& conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info)
if (status == LSQ_HSK_OK || status == LSQ_HSK_0RTT_OK)
{
conn->fc_conn.cn_esf.g->esf_maybe_dispatch_zero_rtt(
conn->fc_conn.cn_enc_session, &conn->fc_conn,
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info);
if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info)
conn->fc_conn.cn_esf.g->esf_maybe_dispatch_zero_rtt(
conn->fc_conn.cn_enc_session, &conn->fc_conn,
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info);
if (conn->fc_n_delayed_streams)
create_delayed_streams(conn);
}
}
@ -4227,7 +4238,8 @@ 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_has_buffered(&conn->fc_send_ctl))
if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
&& lsquic_send_ctl_has_buffered(&conn->fc_send_ctl))
{
LSQ_DEBUG("tickable: has buffered packets");
goto check_can_send;
@ -4237,9 +4249,7 @@ full_conn_ci_is_tickable (lsquic_conn_t *lconn)
LSQ_DEBUG("tickable: there are sending streams");
goto check_can_send;
}
if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE) ||
conn->fc_conn.cn_esf_c->esf_is_zero_rtt_enabled(
conn->fc_conn.cn_enc_session))
if (handshake_done_or_doing_zero_rtt(conn))
{
TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
next_write_stream)
@ -4283,12 +4293,13 @@ full_conn_ci_is_tickable (lsquic_conn_t *lconn)
static lsquic_time_t
full_conn_ci_next_tick_time (lsquic_conn_t *lconn)
full_conn_ci_next_tick_time (lsquic_conn_t *lconn, unsigned *why)
{
struct full_conn *conn = (struct full_conn *) lconn;
lsquic_time_t alarm_time, pacer_time, now;
enum alarm_id al_id;
alarm_time = lsquic_alarmset_mintime(&conn->fc_alset);
alarm_time = lsquic_alarmset_mintime(&conn->fc_alset, &al_id);
pacer_time = lsquic_send_ctl_next_pacer_time(&conn->fc_send_ctl);
if (pacer_time && LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
@ -4302,14 +4313,28 @@ full_conn_ci_next_tick_time (lsquic_conn_t *lconn)
if (alarm_time && pacer_time)
{
if (alarm_time < pacer_time)
{
*why = N_AEWS + al_id;
return alarm_time;
}
else
{
*why = AEW_PACER;
return pacer_time;
}
}
else if (alarm_time)
{
*why = N_AEWS + al_id;
return alarm_time;
else
}
else if (pacer_time)
{
*why = AEW_PACER;
return pacer_time;
}
else
return 0;
}

View file

@ -17,6 +17,7 @@
#include "lsquic.h"
#include "lsquic_types.h"
#include "lsquic_int_types.h"
#include "lsquic_attq.h"
#include "lsquic_packet_common.h"
#include "lsquic_packet_ietf.h"
#include "lsquic_packet_in.h"
@ -1301,7 +1302,8 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
static int
should_generate_ack (struct ietf_full_conn *conn)
should_generate_ack (struct ietf_full_conn *conn,
enum ifull_conn_flags ack_queued)
{
unsigned lost_acks;
@ -1312,7 +1314,7 @@ should_generate_ack (struct ietf_full_conn *conn)
if (lost_acks)
conn->ifc_flags |= lost_acks << IFCBIT_ACK_QUED_SHIFT;
return (conn->ifc_flags & IFC_ACK_QUEUED) != 0;
return (conn->ifc_flags & ack_queued) != 0;
}
@ -1320,7 +1322,7 @@ static int
ietf_full_conn_ci_can_write_ack (struct lsquic_conn *lconn)
{
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
return should_generate_ack(conn);
return should_generate_ack(conn, IFC_ACK_QUED_APP);
}
@ -3226,7 +3228,7 @@ ietf_full_conn_ci_is_tickable (struct lsquic_conn *lconn)
}
if ((conn->ifc_enpub->enp_flags & ENPUB_CAN_SEND)
&& (should_generate_ack(conn) ||
&& (should_generate_ack(conn, IFC_ACK_QUEUED) ||
!lsquic_send_ctl_sched_is_blocked(&conn->ifc_send_ctl)))
{
/* XXX What about queued ACKs: why check but not make tickable? */
@ -3235,7 +3237,9 @@ 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_has_buffered(&conn->ifc_send_ctl))
if (conn->ifc_conn.cn_flags & LSCONN_HANDSHAKE_DONE ?
lsquic_send_ctl_has_buffered(&conn->ifc_send_ctl) :
lsquic_send_ctl_has_buffered_high(&conn->ifc_send_ctl))
{
LSQ_DEBUG("tickable: has buffered packets");
goto check_can_send;
@ -3683,12 +3687,13 @@ ietf_full_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
static lsquic_time_t
ietf_full_conn_ci_next_tick_time (struct lsquic_conn *lconn)
ietf_full_conn_ci_next_tick_time (struct lsquic_conn *lconn, unsigned *why)
{
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
lsquic_time_t alarm_time, pacer_time, now;
enum alarm_id al_id;
alarm_time = lsquic_alarmset_mintime(&conn->ifc_alset);
alarm_time = lsquic_alarmset_mintime(&conn->ifc_alset, &al_id);
pacer_time = lsquic_send_ctl_next_pacer_time(&conn->ifc_send_ctl);
if (pacer_time && LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
@ -3702,14 +3707,28 @@ ietf_full_conn_ci_next_tick_time (struct lsquic_conn *lconn)
if (alarm_time && pacer_time)
{
if (alarm_time < pacer_time)
{
*why = N_AEWS + al_id;
return alarm_time;
}
else
{
*why = AEW_PACER;
return pacer_time;
}
}
else if (alarm_time)
{
*why = N_AEWS + al_id;
return alarm_time;
else
}
else if (pacer_time)
{
*why = AEW_PACER;
return pacer_time;
}
else
return 0;
}
@ -5981,7 +6000,7 @@ ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
have_delayed_packets =
lsquic_send_ctl_maybe_squeeze_sched(&conn->ifc_send_ctl);
if (should_generate_ack(conn))
if (should_generate_ack(conn, IFC_ACK_QUEUED))
{
if (have_delayed_packets)
lsquic_send_ctl_reset_packnos(&conn->ifc_send_ctl);
@ -6263,12 +6282,21 @@ ietf_full_conn_ci_n_avail_streams (const struct lsquic_conn *lconn)
}
static int
handshake_done_or_doing_zero_rtt (const struct ietf_full_conn *conn)
{
return (conn->ifc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|| conn->ifc_conn.cn_esf_c->esf_is_zero_rtt_enabled(
conn->ifc_conn.cn_enc_session);
}
static void
ietf_full_conn_ci_make_stream (struct lsquic_conn *lconn)
{
struct ietf_full_conn *const conn = (struct ietf_full_conn *) lconn;
if ((lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
if (handshake_done_or_doing_zero_rtt(conn)
&& ietf_full_conn_ci_n_avail_streams(lconn) > 0)
{
if (0 != create_bidi_stream_out(conn))

View file

@ -29,6 +29,8 @@ lsquic_mh_insert (struct min_heap *, struct lsquic_conn *conn, uint64_t val);
struct lsquic_conn *
lsquic_mh_pop (struct min_heap *);
#define lsquic_mh_peek(heap) ((heap)->mh_elems[0].mhe_conn)
#define lsquic_mh_count(heap) (+(heap)->mh_nelem)
#define lsquic_mh_nalloc(heap) (+(heap)->mh_nalloc)

View file

@ -50,6 +50,8 @@
#include "lsquic_rechist.h"
#include "lsquic_ev_log.h"
#include "lsquic_qtags.h"
#include "lsquic_attq.h"
#include "lsquic_alarmset.h"
#define LSQUIC_LOGGER_MODULE LSQLM_MINI_CONN
#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(&mc->mc_conn)
@ -1892,7 +1894,7 @@ mini_conn_ci_is_tickable (struct lsquic_conn *lconn)
static lsquic_time_t
mini_conn_ci_next_tick_time (struct lsquic_conn *lconn)
mini_conn_ci_next_tick_time (struct lsquic_conn *lconn, unsigned *why)
{
struct mini_conn *mc = (struct mini_conn *) lconn;
lsquic_packet_out_t *packet_out;
@ -1905,11 +1907,18 @@ mini_conn_ci_next_tick_time (struct lsquic_conn *lconn)
{
retx_time = packet_out->po_sent + calc_retx_timeout(mc);
if (retx_time < exp_time)
{
*why = N_AEWS + AL_RETX_HSK;
return retx_time;
}
else
{
*why = AEW_MINI_EXPIRE;
return exp_time;
}
}
*why = AEW_MINI_EXPIRE;
return exp_time;
}

View file

@ -32,6 +32,8 @@
#include "lsquic_trans_params.h"
#include "lsquic_ietf.h"
#include "lsquic_packet_ietf.h"
#include "lsquic_attq.h"
#include "lsquic_alarmset.h"
#define LSQUIC_LOGGER_MODULE LSQLM_MINI_CONN
#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(&conn->imc_conn)
@ -532,7 +534,7 @@ imico_calc_retx_timeout (const struct ietf_mini_conn *conn)
static lsquic_time_t
ietf_mini_conn_ci_next_tick_time (struct lsquic_conn *lconn)
ietf_mini_conn_ci_next_tick_time (struct lsquic_conn *lconn, unsigned *why)
{
struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
const struct lsquic_packet_out *packet_out;
@ -546,11 +548,18 @@ ietf_mini_conn_ci_next_tick_time (struct lsquic_conn *lconn)
{
retx_time = packet_out->po_sent + imico_calc_retx_timeout(conn);
if (retx_time < exp_time)
{
*why = N_AEWS + AL_RETX_HSK;
return retx_time;
}
else
{
*why = AEW_MINI_EXPIRE;
return exp_time;
}
}
*why = AEW_MINI_EXPIRE;
return exp_time;
}

View file

@ -42,6 +42,7 @@
#include "lsquic_enc_sess.h"
#include "lsquic_hash.h"
#include "lsquic_malo.h"
#include "lsquic_attq.h"
#define LSQUIC_LOGGER_MODULE LSQLM_SENDCTL
#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(ctl->sc_conn_pub->lconn)
@ -1294,7 +1295,8 @@ lsquic_send_ctl_can_send (lsquic_send_ctl_t *ctl)
{
ctl->sc_flags &= ~SC_SCHED_TICK;
lsquic_engine_add_conn_to_attq(ctl->sc_enpub,
ctl->sc_conn_pub->lconn, pacer_next_sched(&ctl->sc_pacer));
ctl->sc_conn_pub->lconn, pacer_next_sched(&ctl->sc_pacer),
AEW_PACER);
}
return 0;
}

View file

@ -281,6 +281,9 @@ lsquic_send_ctl_schedule_buffered (lsquic_send_ctl_t *, enum buf_packet_type);
TAILQ_FIRST(&(ctl)->sc_buffered_packets[BPT_HIGHEST_PRIO].bpq_packets) \
|| TAILQ_FIRST(&(ctl)->sc_buffered_packets[BPT_OTHER_PRIO].bpq_packets ))
#define lsquic_send_ctl_has_buffered_high(ctl) ( \
!TAILQ_EMPTY(&(ctl)->sc_buffered_packets[BPT_HIGHEST_PRIO].bpq_packets))
#define lsquic_send_ctl_invalidate_bpt_cache(ctl) do { \
(ctl)->sc_cached_bpt.stream_id = UINT64_MAX; \
} while (0)

View file

@ -1536,7 +1536,13 @@ stream_shutdown_write (lsquic_stream_t *stream)
&& !stream_is_incoming_unidir(stream)
&& !(stream->sm_qflags & SMQF_SEND_RST))
{
if (stream->sm_n_buffered == 0)
if ((stream->sm_bflags & SMBF_USE_HEADERS)
&& !(stream->stream_flags & STREAM_HEADERS_SENT))
{
LSQ_DEBUG("headers not sent, send a reset");
lsquic_stream_reset(stream, 0);
}
else if (stream->sm_n_buffered == 0)
{
if (0 == lsquic_send_ctl_turn_on_fin(stream->conn_pub->send_ctl,
stream))