lsquic_full_conn.c revision 8437e4a4
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_full_conn.c -- A "full" connection object has full functionality
4 */
5
6#include <assert.h>
7#include <errno.h>
8#include <inttypes.h>
9#include <stdarg.h>
10#include <stdlib.h>
11#include <string.h>
12#ifndef WIN32
13#include <netinet/in.h>
14#include <sys/socket.h>
15#include <sys/time.h>
16#endif
17#include <sys/queue.h>
18
19#include <openssl/ssl.h>
20
21#include "lsquic_types.h"
22#include "lsquic.h"
23#include "lsquic_alarmset.h"
24#include "lsquic_packet_common.h"
25#include "lsquic_parse.h"
26#include "lsquic_packet_in.h"
27#include "lsquic_packet_out.h"
28#include "lsquic_rechist.h"
29#include "lsquic_util.h"
30#include "lsquic_conn_flow.h"
31#include "lsquic_sfcw.h"
32#include "lsquic_stream.h"
33#include "lsquic_senhist.h"
34#include "lsquic_rtt.h"
35#include "lsquic_cubic.h"
36#include "lsquic_pacer.h"
37#include "lsquic_send_ctl.h"
38#include "lsquic_set.h"
39#include "lsquic_malo.h"
40#include "lsquic_chsk_stream.h"
41#include "lsquic_str.h"
42#include "lsquic_qtags.h"
43#include "lsquic_handshake.h"
44#include "lsquic_headers_stream.h"
45#include "lsquic_frame_common.h"
46#include "lsquic_frame_reader.h"
47#include "lsquic_frame_writer.h"
48#include "lsquic_http1x_if.h"
49#include "lsquic_mm.h"
50#include "lsquic_engine_public.h"
51#include "lsquic_spi.h"
52#include "lsquic_ev_log.h"
53#include "lsquic_version.h"
54#include "lsquic_hash.h"
55#include "lsquic_headers.h"
56#include "lsquic_handshake.h"
57
58#include "lsquic_conn.h"
59#include "lsquic_conn_public.h"
60#include "lsquic_ver_neg.h"
61#include "lsquic_full_conn.h"
62
63#define LSQUIC_LOGGER_MODULE LSQLM_CONN
64#define LSQUIC_LOG_CONN_ID conn->fc_conn.cn_cid
65#include "lsquic_logger.h"
66
67enum { STREAM_IF_STD, STREAM_IF_HSK, STREAM_IF_HDR, N_STREAM_IFS };
68
69#define MAX_ANY_PACKETS_SINCE_LAST_ACK  20
70#define MAX_RETR_PACKETS_SINCE_LAST_ACK 2
71#define ACK_TIMEOUT                     25000
72#define TIME_BETWEEN_PINGS              15000000
73#define IDLE_TIMEOUT                    30000000
74
75/* IMPORTANT: Keep values of FC_SERVER and FC_HTTP same as LSENG_SERVER
76 * and LSENG_HTTP.
77 */
78enum full_conn_flags {
79    FC_SERVER         = LSENG_SERVER,   /* Server mode */
80    FC_HTTP           = LSENG_HTTP,     /* HTTP mode */
81    FC_TIMED_OUT      = (1 << 2),
82#define FC_BIT_ERROR 3
83    FC_ERROR          = (1 << FC_BIT_ERROR),
84    FC_ABORTED        = (1 << 4),
85    FC_CLOSING        = (1 << 5),   /* Closing */
86    FC_SEND_PING      = (1 << 6),   /* PING frame scheduled */
87    FC_NSTP           = (1 << 7),   /* NSTP mode */
88    FC_SEND_GOAWAY    = (1 << 8),
89    FC_SEND_WUF       = (1 << 9),
90    FC_SEND_STOP_WAITING
91                      = (1 <<10),
92    FC_ACK_QUEUED     = (1 <<11),
93    FC_ACK_HAD_MISS   = (1 <<12),   /* Last ACK frame had missing packets. */
94    FC_CREATED_OK     = (1 <<13),
95    FC_RECV_CLOSE     = (1 <<14),   /* Received CONNECTION_CLOSE frame */
96    FC_GOING_AWAY     = (1 <<15),   /* Do not accept or create new streams */
97    FC_GOAWAY_SENT    = (1 <<16),   /* Only send GOAWAY once */
98    FC_SUPPORT_PUSH   = (1 <<17),
99    FC_GOT_PRST       = (1 <<18),   /* Received public reset packet */
100    FC_FIRST_TICK     = (1 <<19),
101    FC_TICK_CLOSE     = (1 <<20),   /* We returned TICK_CLOSE */
102    FC_HSK_FAILED     = (1 <<21),
103    FC_HAVE_SAVED_ACK = (1 <<22),
104    FC_ABORT_COMPLAINED
105                      = (1 <<23),
106};
107
108#define FC_IMMEDIATE_CLOSE_FLAGS \
109            (FC_TIMED_OUT|FC_ERROR|FC_ABORTED|FC_HSK_FAILED)
110
111#if LSQUIC_KEEP_STREAM_HISTORY
112#define KEEP_CLOSED_STREAM_HISTORY 0
113#endif
114
115#if KEEP_CLOSED_STREAM_HISTORY
116struct stream_history
117{
118    uint32_t            shist_stream_id;
119    enum stream_flags   shist_stream_flags;
120    unsigned char       shist_hist_buf[1 << SM_HIST_BITS];
121};
122#define SHIST_BITS 5
123#define SHIST_MASK ((1 << SHIST_BITS) - 1)
124#endif
125
126#ifndef KEEP_PACKET_HISTORY
127#ifdef NDEBUG
128#define KEEP_PACKET_HISTORY 0
129#else
130#define KEEP_PACKET_HISTORY 16
131#endif
132#endif
133
134#if KEEP_PACKET_HISTORY
135struct packet_el
136{
137    lsquic_time_t       time;
138    enum quic_ft_bit    frame_types;
139};
140
141struct recent_packets
142{
143    struct packet_el    els[KEEP_PACKET_HISTORY];
144    unsigned            idx;
145};
146#endif
147
148struct stream_id_to_reset
149{
150    STAILQ_ENTRY(stream_id_to_reset)    sitr_next;
151    uint32_t                            sitr_stream_id;
152};
153
154
155struct full_conn
156{
157    struct lsquic_conn           fc_conn;
158    struct lsquic_rechist        fc_rechist;
159    struct {
160        const struct lsquic_stream_if   *stream_if;
161        void                            *stream_if_ctx;
162    }                            fc_stream_ifs[N_STREAM_IFS];
163    lsquic_conn_ctx_t           *fc_conn_ctx;
164    struct lsquic_send_ctl       fc_send_ctl;
165    struct lsquic_conn_public    fc_pub;
166    lsquic_alarmset_t            fc_alset;
167    lsquic_set32_t               fc_closed_stream_ids[2];
168    const struct lsquic_engine_settings
169                                *fc_settings;
170    struct lsquic_engine_public *fc_enpub;
171    lsquic_packno_t              fc_max_ack_packno;
172    lsquic_packno_t              fc_max_swf_packno;
173    lsquic_time_t                fc_mem_logged_last;
174    struct {
175        unsigned    max_streams_in;
176        unsigned    max_streams_out;
177        unsigned    max_conn_send;
178        unsigned    max_stream_send;
179    }                            fc_cfg;
180    enum full_conn_flags         fc_flags;
181    /* Number of packets received since last ACK sent: */
182    unsigned                     fc_n_slack_all;
183    /* Number ackable packets received since last ACK was sent: */
184    unsigned                     fc_n_slack_akbl;
185    unsigned                     fc_n_delayed_streams;
186    unsigned                     fc_n_cons_unretx;
187    uint32_t                     fc_last_stream_id;
188    uint32_t                     fc_max_peer_stream_id;
189    uint32_t                     fc_goaway_stream_id;
190    struct ver_neg               fc_ver_neg;
191    union {
192        struct client_hsk_ctx    client;
193    }                            fc_hsk_ctx;
194#if LSQUIC_CONN_STATS
195    struct conn_stats            fc_stats;
196#endif
197#if KEEP_CLOSED_STREAM_HISTORY
198    /* Rolling log of histories of closed streams.  Older entries are
199     * overwritten.
200     */
201    struct stream_history        fc_stream_histories[1 << SHIST_BITS];
202    unsigned                     fc_stream_hist_idx;
203#endif
204    char                        *fc_errmsg;
205#if KEEP_PACKET_HISTORY
206    struct recent_packets        fc_recent_packets[2];  /* 0: in; 1: out */
207#endif
208    STAILQ_HEAD(, stream_id_to_reset)
209                                 fc_stream_ids_to_reset;
210    struct short_ack_info        fc_saved_ack_info;
211    lsquic_time_t                fc_saved_ack_received;
212};
213
214
215#define MAX_ERRMSG 256
216
217#define SET_ERRMSG(conn, ...) do {                                          \
218    if (!(conn)->fc_errmsg)                                                 \
219        (conn)->fc_errmsg = malloc(MAX_ERRMSG);                             \
220    if ((conn)->fc_errmsg)                                                  \
221        snprintf((conn)->fc_errmsg, MAX_ERRMSG, __VA_ARGS__);               \
222} while (0)
223
224#define ABORT_WITH_FLAG(conn, log_level, flag, ...) do {                    \
225    SET_ERRMSG(conn, __VA_ARGS__);                                          \
226    if (!((conn)->fc_flags & FC_ABORT_COMPLAINED))                          \
227        LSQ_LOG(log_level, "Abort connection: " __VA_ARGS__);               \
228    (conn)->fc_flags |= flag|FC_ABORT_COMPLAINED;                           \
229} while (0)
230
231#define ABORT_ERROR(...) \
232    ABORT_WITH_FLAG(conn, LSQ_LOG_ERROR, FC_ERROR, __VA_ARGS__)
233#define ABORT_WARN(...) \
234    ABORT_WITH_FLAG(conn, LSQ_LOG_WARN, FC_ERROR, __VA_ARGS__)
235
236static void
237idle_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
238
239static void
240ping_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
241
242static void
243handshake_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
244
245static void
246ack_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
247
248static lsquic_stream_t *
249new_stream (struct full_conn *conn, uint32_t stream_id, enum stream_ctor_flags);
250
251static void
252reset_ack_state (struct full_conn *conn);
253
254static int
255write_is_possible (struct full_conn *);
256
257static const struct headers_stream_callbacks *headers_callbacks_ptr;
258
259#if KEEP_CLOSED_STREAM_HISTORY
260
261static void
262save_stream_history (struct full_conn *conn, const lsquic_stream_t *stream)
263{
264    sm_hist_idx_t idx;
265    struct stream_history *const shist =
266        &conn->fc_stream_histories[ conn->fc_stream_hist_idx++ & SHIST_MASK ];
267
268    shist->shist_stream_id    = stream->id;
269    shist->shist_stream_flags = stream->stream_flags;
270
271    idx = stream->sm_hist_idx & SM_HIST_IDX_MASK;
272    if ('\0' == stream->sm_hist_buf[ idx ])
273        memcpy(shist->shist_hist_buf, stream->sm_hist_buf, idx + 1);
274    else
275    {
276        memcpy(shist->shist_hist_buf,
277            stream->sm_hist_buf + idx, sizeof(stream->sm_hist_buf) - idx);
278        memcpy(shist->shist_hist_buf + sizeof(shist->shist_hist_buf) - idx,
279            stream->sm_hist_buf, idx);
280    }
281}
282
283
284static const struct stream_history *
285find_stream_history (const struct full_conn *conn, uint32_t stream_id)
286{
287    const struct stream_history *shist;
288    const struct stream_history *const shist_end =
289                        conn->fc_stream_histories + (1 << SHIST_BITS);
290    for (shist = conn->fc_stream_histories; shist < shist_end; ++shist)
291        if (shist->shist_stream_id == stream_id)
292            return shist;
293    return NULL;
294}
295
296
297#   define SAVE_STREAM_HISTORY(conn, stream) save_stream_history(conn, stream)
298#else
299#   define SAVE_STREAM_HISTORY(conn, stream)
300#endif
301
302#if KEEP_PACKET_HISTORY
303static void
304recent_packet_hist_new (struct full_conn *conn, unsigned out,
305                                                    lsquic_time_t time)
306{
307    unsigned idx;
308    idx = conn->fc_recent_packets[out].idx++ % KEEP_PACKET_HISTORY;
309    conn->fc_recent_packets[out].els[idx].time = time;
310}
311
312
313static void
314recent_packet_hist_frames (struct full_conn *conn, unsigned out,
315                                                enum quic_ft_bit frame_types)
316{
317    unsigned idx;
318    idx = (conn->fc_recent_packets[out].idx - 1) % KEEP_PACKET_HISTORY;
319    conn->fc_recent_packets[out].els[idx].frame_types |= frame_types;
320}
321
322
323#else
324#define recent_packet_hist_new(conn, out, time)
325#define recent_packet_hist_frames(conn, out, frames)
326#endif
327
328static unsigned
329highest_bit_set (unsigned sz)
330{
331#if __GNUC__
332    unsigned clz = __builtin_clz(sz);
333    return 31 - clz;
334#else
335    unsigned n, y;
336    n = 32;
337    y = sz >> 16;   if (y) { n -= 16; sz = y; }
338    y = sz >>  8;   if (y) { n -=  8; sz = y; }
339    y = sz >>  4;   if (y) { n -=  4; sz = y; }
340    y = sz >>  2;   if (y) { n -=  2; sz = y; }
341    y = sz >>  1;   if (y) return 31 - n + 2;
342    return 31 - n + sz;
343#endif
344}
345
346
347static size_t
348calc_mem_used (const struct full_conn *conn)
349{
350    const lsquic_stream_t *stream;
351    const struct lsquic_hash_elem *el;
352    size_t size;
353
354    size = sizeof(*conn);
355    size -= sizeof(conn->fc_send_ctl);
356    size += lsquic_send_ctl_mem_used(&conn->fc_send_ctl);
357    size += lsquic_hash_mem_used(conn->fc_pub.all_streams);
358    size += lsquic_malo_mem_used(conn->fc_pub.packet_out_malo);
359    if (conn->fc_pub.hs)
360        size += lsquic_headers_stream_mem_used(conn->fc_pub.hs);
361
362    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
363                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
364    {
365        stream = lsquic_hashelem_getdata(el);
366        size += lsquic_stream_mem_used(stream);
367    }
368    size += conn->fc_conn.cn_esf->esf_mem_used(conn->fc_conn.cn_enc_session);
369
370    return size;
371}
372
373
374static void
375set_versions (struct full_conn *conn, unsigned versions,
376                                                    enum lsquic_version *ver)
377{
378    conn->fc_ver_neg.vn_supp = versions;
379    conn->fc_ver_neg.vn_ver  = (ver) ? *ver : highest_bit_set(versions);
380    conn->fc_ver_neg.vn_buf  = lsquic_ver2tag(conn->fc_ver_neg.vn_ver);
381    conn->fc_conn.cn_version = conn->fc_ver_neg.vn_ver;
382    conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
383    LSQ_DEBUG("negotiating version %s",
384                            lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
385}
386
387
388static void
389init_ver_neg (struct full_conn *conn, unsigned versions,
390                                                    enum lsquic_version *ver)
391{
392    set_versions(conn, versions, ver);
393    conn->fc_ver_neg.vn_tag   = &conn->fc_ver_neg.vn_buf;
394    conn->fc_ver_neg.vn_state = VN_START;
395}
396
397
398/* If peer supplies odd values, we abort the connection immediately rather
399 * that wait for it to finish "naturally" due to inability to send things.
400 */
401static void
402conn_on_peer_config (struct full_conn *conn, unsigned peer_cfcw,
403                     unsigned peer_sfcw, unsigned max_streams_out)
404{
405    lsquic_stream_t *stream;
406    struct lsquic_hash_elem *el;
407
408    LSQ_INFO("Applying peer config: cfcw: %u; sfcw: %u; # streams: %u",
409        peer_cfcw, peer_sfcw, max_streams_out);
410
411    if (peer_cfcw < conn->fc_pub.conn_cap.cc_sent)
412    {
413        ABORT_ERROR("peer specified CFCW=%u bytes, which is smaller than "
414            "the amount of data already sent on this connection (%"PRIu64
415            " bytes)", peer_cfcw, conn->fc_pub.conn_cap.cc_sent);
416        return;
417    }
418
419    conn->fc_cfg.max_streams_out = max_streams_out;
420    conn->fc_pub.conn_cap.cc_max = peer_cfcw;
421
422    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
423                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
424    {
425        stream = lsquic_hashelem_getdata(el);
426        if (0 != lsquic_stream_set_max_send_off(stream, peer_sfcw))
427        {
428            ABORT_ERROR("cannot set peer-supplied SFCW=%u on stream %u",
429                peer_sfcw, stream->id);
430            return;
431        }
432    }
433
434    conn->fc_cfg.max_stream_send = peer_sfcw;
435}
436
437
438static int
439send_smhl (const struct full_conn *conn)
440{
441    uint32_t smhl;
442    return conn->fc_conn.cn_enc_session
443        && 0 == conn->fc_conn.cn_esf->esf_get_peer_setting(
444                            conn->fc_conn.cn_enc_session, QTAG_SMHL, &smhl)
445        && 1 == smhl;
446}
447
448
449/* Once handshake has been completed, send settings to peer if appropriate.
450 */
451static void
452maybe_send_settings (struct full_conn *conn)
453{
454    struct lsquic_http2_setting settings[2];
455    unsigned n_settings = 0;
456
457    if (conn->fc_settings->es_max_header_list_size && send_smhl(conn))
458    {
459        settings[n_settings].id    = SETTINGS_MAX_HEADER_LIST_SIZE;
460        settings[n_settings].value = conn->fc_settings->es_max_header_list_size;
461        LSQ_DEBUG("sending settings SETTINGS_MAX_HEADER_LIST_SIZE=%u",
462                                                settings[n_settings].value);
463        ++n_settings;
464    }
465    if (!(conn->fc_flags & FC_SERVER) && !conn->fc_settings->es_support_push)
466    {
467        settings[n_settings].id    = SETTINGS_ENABLE_PUSH;
468        settings[n_settings].value = 0;
469        LSQ_DEBUG("sending settings SETTINGS_ENABLE_PUSH=%u",
470                                                settings[n_settings].value);
471        ++n_settings;
472    }
473
474    if (n_settings)
475    {
476        if (0 != lsquic_headers_stream_send_settings(conn->fc_pub.hs,
477                                                        settings, n_settings))
478            ABORT_ERROR("could not send settings");
479    }
480    else
481        LSQ_DEBUG("not sending any settings");
482}
483
484
485static int
486apply_peer_settings (struct full_conn *conn)
487{
488    uint32_t cfcw, sfcw, mids;
489    unsigned n;
490    const struct {
491        uint32_t    tag;
492        uint32_t   *val;
493        const char *tag_str;
494    } tags[] = {
495        { QTAG_CFCW, &cfcw, "CFCW", },
496        { QTAG_SFCW, &sfcw, "SFCW", },
497        { QTAG_MIDS, &mids, "MIDS", },
498    };
499
500#ifndef NDEBUG
501    if (getenv("LSQUIC_TEST_ENGINE_DTOR"))
502        return 0;
503#endif
504
505    for (n = 0; n < sizeof(tags) / sizeof(tags[0]); ++n)
506        if (0 != conn->fc_conn.cn_esf->esf_get_peer_setting(
507                    conn->fc_conn.cn_enc_session, tags[n].tag, tags[n].val))
508        {
509            LSQ_INFO("peer did not supply value for %s", tags[n].tag_str);
510            return -1;
511        }
512
513    LSQ_DEBUG("peer settings: CFCW: %u; SFCW: %u; MIDS: %u",
514        cfcw, sfcw, mids);
515    conn_on_peer_config(conn, cfcw, sfcw, mids);
516    return 0;
517}
518
519
520static const struct conn_iface *full_conn_iface_ptr;
521
522static struct full_conn *
523new_conn_common (lsquic_cid_t cid, struct lsquic_engine_public *enpub,
524                 const struct lsquic_stream_if *stream_if,
525                 void *stream_if_ctx, unsigned flags,
526                 unsigned short max_packet_size)
527{
528    struct full_conn *conn;
529    lsquic_stream_t *headers_stream;
530    int saved_errno;
531
532    assert(0 == (flags & ~(FC_SERVER|FC_HTTP)));
533
534    conn = calloc(1, sizeof(*conn));
535    if (!conn)
536        return NULL;
537    headers_stream = NULL;
538    conn->fc_conn.cn_cid = cid;
539    conn->fc_conn.cn_pack_size = max_packet_size;
540    conn->fc_flags = flags;
541    conn->fc_enpub = enpub;
542    conn->fc_pub.enpub = enpub;
543    conn->fc_pub.mm = &enpub->enp_mm;
544    conn->fc_pub.lconn = &conn->fc_conn;
545    conn->fc_pub.send_ctl = &conn->fc_send_ctl;
546#if LSQUIC_CONN_STATS
547    conn->fc_pub.conn_stats = &conn->fc_stats;
548#endif
549    conn->fc_pub.packet_out_malo =
550                        lsquic_malo_create(sizeof(struct lsquic_packet_out));
551    conn->fc_stream_ifs[STREAM_IF_STD].stream_if     = stream_if;
552    conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx = stream_if_ctx;
553    conn->fc_settings = &enpub->enp_settings;
554    /* Calculate maximum number of incoming streams using the same mechanism
555     * and parameters as found in Chrome:
556     */
557    conn->fc_cfg.max_streams_in =
558        (unsigned) ((float) enpub->enp_settings.es_max_streams_in * 1.1f);
559    if (conn->fc_cfg.max_streams_in <
560                                enpub->enp_settings.es_max_streams_in + 10)
561        conn->fc_cfg.max_streams_in =
562                                enpub->enp_settings.es_max_streams_in + 10;
563    /* `max_streams_out' gets reset when handshake is complete and we
564     * learn of peer settings.  100 seems like a sane default value
565     * because it is what other implementations use.  In server mode,
566     * we do not open any streams until the handshake is complete; in
567     * client mode, we are limited to 98 outgoing requests alongside
568     * handshake and headers streams.
569     */
570    conn->fc_cfg.max_streams_out = 100;
571    TAILQ_INIT(&conn->fc_pub.sending_streams);
572    TAILQ_INIT(&conn->fc_pub.read_streams);
573    TAILQ_INIT(&conn->fc_pub.write_streams);
574    TAILQ_INIT(&conn->fc_pub.service_streams);
575    STAILQ_INIT(&conn->fc_stream_ids_to_reset);
576    lsquic_conn_cap_init(&conn->fc_pub.conn_cap, LSQUIC_MIN_FCW);
577    lsquic_alarmset_init(&conn->fc_alset, cid);
578    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_IDLE, idle_alarm_expired, conn);
579    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_ACK, ack_alarm_expired, conn);
580    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_PING, ping_alarm_expired, conn);
581    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_HANDSHAKE, handshake_alarm_expired, conn);
582    lsquic_set32_init(&conn->fc_closed_stream_ids[0]);
583    lsquic_set32_init(&conn->fc_closed_stream_ids[1]);
584    lsquic_cfcw_init(&conn->fc_pub.cfcw, &conn->fc_pub, conn->fc_settings->es_cfcw);
585    lsquic_send_ctl_init(&conn->fc_send_ctl, &conn->fc_alset, conn->fc_enpub,
586                 &conn->fc_ver_neg, &conn->fc_pub, conn->fc_conn.cn_pack_size);
587
588    conn->fc_pub.all_streams = lsquic_hash_create();
589    if (!conn->fc_pub.all_streams)
590        goto cleanup_on_error;
591    lsquic_rechist_init(&conn->fc_rechist, cid);
592    if (conn->fc_flags & FC_HTTP)
593    {
594        conn->fc_pub.hs = lsquic_headers_stream_new(
595            !!(conn->fc_flags & FC_SERVER), conn->fc_enpub,
596                                                     headers_callbacks_ptr,
597#if LSQUIC_CONN_STATS
598                                                    &conn->fc_stats,
599#endif
600                                                     conn);
601        if (!conn->fc_pub.hs)
602            goto cleanup_on_error;
603        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if     = lsquic_headers_stream_if;
604        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = conn->fc_pub.hs;
605        headers_stream = new_stream(conn, LSQUIC_STREAM_HEADERS,
606                                    SCF_CALL_ON_NEW);
607        if (!headers_stream)
608            goto cleanup_on_error;
609    }
610    else
611    {
612        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if     = stream_if;
613        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = stream_if_ctx;
614    }
615    if (conn->fc_settings->es_support_push)
616        conn->fc_flags |= FC_SUPPORT_PUSH;
617    conn->fc_conn.cn_if = full_conn_iface_ptr;
618    return conn;
619
620  cleanup_on_error:
621    saved_errno = errno;
622
623    if (conn->fc_pub.all_streams)
624        lsquic_hash_destroy(conn->fc_pub.all_streams);
625    lsquic_rechist_cleanup(&conn->fc_rechist);
626    if (conn->fc_flags & FC_HTTP)
627    {
628        if (conn->fc_pub.hs)
629            lsquic_headers_stream_destroy(conn->fc_pub.hs);
630        if (headers_stream)
631            lsquic_stream_destroy(headers_stream);
632    }
633    memset(conn, 0, sizeof(*conn));
634    free(conn);
635
636    errno = saved_errno;
637    return NULL;
638}
639
640
641struct lsquic_conn *
642full_conn_client_new (struct lsquic_engine_public *enpub,
643                      const struct lsquic_stream_if *stream_if,
644                      void *stream_if_ctx, unsigned flags,
645                      const char *hostname, unsigned short max_packet_size,
646                      const unsigned char *zero_rtt, size_t zero_rtt_len)
647{
648    struct full_conn *conn;
649    enum lsquic_version version, zero_rtt_version;
650    lsquic_cid_t cid;
651    const struct enc_session_funcs *esf;
652
653    version = highest_bit_set(enpub->enp_settings.es_versions);
654    if (zero_rtt)
655    {
656        zero_rtt_version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_len);
657        if (zero_rtt_version < N_LSQVER &&
658            ((1 << zero_rtt_version) & enpub->enp_settings.es_versions))
659            version = zero_rtt_version;
660    }
661    esf = select_esf_by_ver(version);
662    cid = esf->esf_generate_cid();
663    conn = new_conn_common(cid, enpub, stream_if, stream_if_ctx, flags,
664                                                            max_packet_size);
665    if (!conn)
666        return NULL;
667    conn->fc_conn.cn_esf = esf;
668    conn->fc_conn.cn_enc_session =
669        conn->fc_conn.cn_esf->esf_create_client(hostname, cid, conn->fc_enpub,
670                                                    zero_rtt, zero_rtt_len);
671    if (!conn->fc_conn.cn_enc_session)
672    {
673        LSQ_WARN("could not create enc session: %s", strerror(errno));
674        conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
675        return NULL;
676    }
677
678    if (conn->fc_flags & FC_HTTP)
679        conn->fc_last_stream_id = LSQUIC_STREAM_HEADERS;   /* Client goes 5, 7, 9.... */
680    else
681        conn->fc_last_stream_id = LSQUIC_STREAM_HANDSHAKE;
682    conn->fc_hsk_ctx.client.lconn   = &conn->fc_conn;
683    conn->fc_hsk_ctx.client.mm      = &enpub->enp_mm;
684    conn->fc_hsk_ctx.client.ver_neg = &conn->fc_ver_neg;
685    conn->fc_stream_ifs[STREAM_IF_HSK]
686                .stream_if     = &lsquic_client_hsk_stream_if;
687    conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
688    init_ver_neg(conn, conn->fc_settings->es_versions, &version);
689    if (conn->fc_settings->es_handshake_to)
690        lsquic_alarmset_set(&conn->fc_alset, AL_HANDSHAKE,
691                    lsquic_time_now() + conn->fc_settings->es_handshake_to);
692    if (!new_stream(conn, LSQUIC_STREAM_HANDSHAKE, SCF_CALL_ON_NEW))
693    {
694        LSQ_WARN("could not create handshake stream: %s", strerror(errno));
695        conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
696        return NULL;
697    }
698    conn->fc_flags |= FC_CREATED_OK;
699    LSQ_INFO("Created new client connection");
700    EV_LOG_CONN_EVENT(cid, "created full connection");
701    return &conn->fc_conn;
702}
703
704
705void
706full_conn_client_call_on_new (struct lsquic_conn *lconn)
707{
708    struct full_conn *const conn = (struct full_conn *) lconn;
709    assert(conn->fc_flags & FC_CREATED_OK);
710    conn->fc_conn_ctx = conn->fc_stream_ifs[STREAM_IF_STD].stream_if
711        ->on_new_conn(conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, lconn);
712}
713
714
715static int
716is_our_stream (const struct full_conn *conn, const lsquic_stream_t *stream)
717{
718    int is_server = !!(conn->fc_flags & FC_SERVER);
719    return (1 & stream->id) ^ is_server;
720}
721
722
723static unsigned
724count_streams (const struct full_conn *conn, int peer)
725{
726    const lsquic_stream_t *stream;
727    unsigned count;
728    int ours;
729    int is_server;
730    struct lsquic_hash_elem *el;
731
732    peer = !!peer;
733    is_server = !!(conn->fc_flags & FC_SERVER);
734    count = 0;
735
736    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
737                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
738    {
739        stream = lsquic_hashelem_getdata(el);
740        ours = (1 & stream->id) ^ is_server;
741        if (ours ^ peer)
742            count += !(lsquic_stream_is_closed(stream)
743                                /* When counting peer-initiated streams, do not
744                                 * include those that have been reset:
745                                 */
746                                || (peer && lsquic_stream_is_reset(stream)));
747    }
748
749    return count;
750}
751
752
753enum stream_count { SCNT_ALL, SCNT_PEER, SCNT_CLOSED, SCNT_RESET,
754    SCNT_RES_UNCLO /* reset and not closed */, N_SCNTS };
755
756static void
757collect_stream_counts (const struct full_conn *conn, int peer,
758                                                    unsigned counts[N_SCNTS])
759{
760    const lsquic_stream_t *stream;
761    int ours;
762    int is_server;
763    struct lsquic_hash_elem *el;
764
765    peer = !!peer;
766    is_server = !!(conn->fc_flags & FC_SERVER);
767    memset(counts, 0, N_SCNTS * sizeof(counts[0]));
768
769    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
770                             el = lsquic_hash_next(conn->fc_pub.all_streams))
771    {
772        ++counts[SCNT_ALL];
773        stream = lsquic_hashelem_getdata(el);
774        ours = (1 & stream->id) ^ is_server;
775        if (ours ^ peer)
776        {
777            ++counts[SCNT_PEER];
778            counts[SCNT_CLOSED] += lsquic_stream_is_closed(stream);
779            counts[SCNT_RESET] += lsquic_stream_is_reset(stream);
780            counts[SCNT_RES_UNCLO] += lsquic_stream_is_reset(stream)
781                                        && !lsquic_stream_is_closed(stream);
782        }
783    }
784}
785
786
787static void
788full_conn_ci_destroy (lsquic_conn_t *lconn)
789{
790    struct full_conn *conn = (struct full_conn *) lconn;
791    struct lsquic_hash_elem *el;
792    struct lsquic_stream *stream;
793    struct stream_id_to_reset *sitr;
794
795    LSQ_DEBUG("destroy connection");
796    conn->fc_flags |= FC_CLOSING;
797    lsquic_set32_cleanup(&conn->fc_closed_stream_ids[0]);
798    lsquic_set32_cleanup(&conn->fc_closed_stream_ids[1]);
799    while ((el = lsquic_hash_first(conn->fc_pub.all_streams)))
800    {
801        stream = lsquic_hashelem_getdata(el);
802        lsquic_hash_erase(conn->fc_pub.all_streams, el);
803        lsquic_stream_destroy(stream);
804    }
805    lsquic_hash_destroy(conn->fc_pub.all_streams);
806    if (conn->fc_flags & FC_CREATED_OK)
807        conn->fc_stream_ifs[STREAM_IF_STD].stream_if
808                    ->on_conn_closed(&conn->fc_conn);
809    if (conn->fc_pub.hs)
810        lsquic_headers_stream_destroy(conn->fc_pub.hs);
811
812    lsquic_send_ctl_cleanup(&conn->fc_send_ctl);
813    lsquic_rechist_cleanup(&conn->fc_rechist);
814    if (conn->fc_conn.cn_enc_session)
815        conn->fc_conn.cn_esf->esf_destroy(conn->fc_conn.cn_enc_session);
816    lsquic_malo_destroy(conn->fc_pub.packet_out_malo);
817#if LSQUIC_CONN_STATS
818    LSQ_NOTICE("# ticks: %lu", conn->fc_stats.n_ticks);
819    LSQ_NOTICE("received %lu packets, of which %lu were not decryptable, %lu were "
820        "dups and %lu were errors; sent %lu packets, avg stream data per outgoing"
821        " packet is %lu bytes",
822        conn->fc_stats.in.packets, conn->fc_stats.in.undec_packets,
823        conn->fc_stats.in.dup_packets, conn->fc_stats.in.err_packets,
824        conn->fc_stats.out.packets,
825        conn->fc_stats.out.stream_data_sz / conn->fc_stats.out.packets);
826    LSQ_NOTICE("ACKs: in: %lu; processed: %lu; merged to: new %lu, old %lu",
827        conn->fc_stats.in.n_acks, conn->fc_stats.in.n_acks_proc,
828        conn->fc_stats.in.n_acks_merged[0], conn->fc_stats.in.n_acks_merged[1]);
829#endif
830    while ((sitr = STAILQ_FIRST(&conn->fc_stream_ids_to_reset)))
831    {
832        STAILQ_REMOVE_HEAD(&conn->fc_stream_ids_to_reset, sitr_next);
833        free(sitr);
834    }
835    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "full connection destroyed");
836    free(conn->fc_errmsg);
837    free(conn);
838}
839
840
841static void
842conn_mark_stream_closed (struct full_conn *conn, uint32_t stream_id)
843{   /* Because stream IDs are distributed unevenly -- there is a set of odd
844     * stream IDs and a set of even stream IDs -- it is more efficient to
845     * maintain two sets of closed stream IDs.
846     */
847    int idx = stream_id & 1;
848    stream_id >>= 1;
849    if (0 != lsquic_set32_add(&conn->fc_closed_stream_ids[idx], stream_id))
850        ABORT_ERROR("could not add element to set: %s", strerror(errno));
851}
852
853
854static int
855conn_is_stream_closed (struct full_conn *conn, uint32_t stream_id)
856{
857    int idx = stream_id & 1;
858    stream_id >>= 1;
859    return lsquic_set32_has(&conn->fc_closed_stream_ids[idx], stream_id);
860}
861
862
863static void
864set_ack_timer (struct full_conn *conn, lsquic_time_t now)
865{
866    lsquic_alarmset_set(&conn->fc_alset, AL_ACK, now + ACK_TIMEOUT);
867    LSQ_DEBUG("ACK alarm set to %"PRIu64, now + ACK_TIMEOUT);
868}
869
870
871static void
872ack_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now)
873{
874    struct full_conn *conn = ctx;
875    LSQ_DEBUG("ACK timer expired (%"PRIu64" < %"PRIu64"): ACK queued",
876        expiry, now);
877    conn->fc_flags |= FC_ACK_QUEUED;
878}
879
880
881static void
882try_queueing_ack (struct full_conn *conn, int was_missing, lsquic_time_t now)
883{
884    if (conn->fc_n_slack_akbl >= MAX_RETR_PACKETS_SINCE_LAST_ACK ||
885        (conn->fc_conn.cn_version < LSQVER_039 /* Since Q039 do not ack ACKs */
886            && conn->fc_n_slack_all >= MAX_ANY_PACKETS_SINCE_LAST_ACK) ||
887        ((conn->fc_flags & FC_ACK_HAD_MISS) && was_missing)      ||
888        lsquic_send_ctl_n_stop_waiting(&conn->fc_send_ctl) > 1)
889    {
890        lsquic_alarmset_unset(&conn->fc_alset, AL_ACK);
891        lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
892        conn->fc_flags |= FC_ACK_QUEUED;
893        LSQ_DEBUG("ACK queued: ackable: %u; all: %u; had_miss: %d; "
894            "was_missing: %d; n_stop_waiting: %u",
895            conn->fc_n_slack_akbl, conn->fc_n_slack_all,
896            !!(conn->fc_flags & FC_ACK_HAD_MISS), was_missing,
897            lsquic_send_ctl_n_stop_waiting(&conn->fc_send_ctl));
898    }
899    else if (conn->fc_n_slack_akbl > 0)
900        set_ack_timer(conn, now);
901}
902
903
904static void
905reset_ack_state (struct full_conn *conn)
906{
907    conn->fc_n_slack_all  = 0;
908    conn->fc_n_slack_akbl = 0;
909    lsquic_send_ctl_n_stop_waiting_reset(&conn->fc_send_ctl);
910    conn->fc_flags &= ~FC_ACK_QUEUED;
911    lsquic_alarmset_unset(&conn->fc_alset, AL_ACK);
912    lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
913    LSQ_DEBUG("ACK state reset");
914}
915
916
917#if 1
918#   define verify_ack_frame(a, b, c)
919#else
920static void
921verify_ack_frame (struct full_conn *conn, const unsigned char *buf, int bufsz)
922{
923    unsigned i;
924    int parsed_len;
925    struct ack_info *ack_info;
926    const struct lsquic_packno_range *range;
927    char ack_buf[512];
928    unsigned buf_off = 0;
929    int nw;
930
931    ack_info = conn->fc_pub.mm->acki;
932    parsed_len = parse_ack_frame(buf, bufsz, ack_info);
933    assert(parsed_len == bufsz);
934
935    for (range = lsquic_rechist_first(&conn->fc_rechist), i = 0; range;
936            range = lsquic_rechist_next(&conn->fc_rechist), ++i)
937    {
938        assert(i < ack_info->n_ranges);
939        assert(range->high == ack_info->ranges[i].high);
940        assert(range->low == ack_info->ranges[i].low);
941        if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
942        {
943            nw = snprintf(ack_buf + buf_off, sizeof(ack_buf) - buf_off,
944                            "[%"PRIu64"-%"PRIu64"]", range->high, range->low);
945            assert(nw >= 0);
946            buf_off += nw;
947        }
948    }
949    assert(i == ack_info->n_ranges);
950    LSQ_DEBUG("Sent ACK frame %s", ack_buf);
951}
952
953
954#endif
955
956
957static void
958full_conn_ci_write_ack (struct lsquic_conn *lconn,
959                                    struct lsquic_packet_out *packet_out)
960{
961    struct full_conn *conn = (struct full_conn *) lconn;
962    lsquic_time_t now;
963    int has_missing, w;
964
965    now = lsquic_time_now();
966    w = conn->fc_conn.cn_pf->pf_gen_ack_frame(
967            packet_out->po_data + packet_out->po_data_sz,
968            lsquic_packet_out_avail(packet_out),
969            (gaf_rechist_first_f)        lsquic_rechist_first,
970            (gaf_rechist_next_f)         lsquic_rechist_next,
971            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
972            &conn->fc_rechist, now, &has_missing, &packet_out->po_ack2ed);
973    if (w < 0) {
974        ABORT_ERROR("generating ACK frame failed: %d", errno);
975        return;
976    }
977#if LSQUIC_CONN_STATS
978    ++conn->fc_stats.out.acks;
979#endif
980    EV_LOG_GENERATED_ACK_FRAME(LSQUIC_LOG_CONN_ID, conn->fc_conn.cn_pf,
981                        packet_out->po_data + packet_out->po_data_sz, w);
982    verify_ack_frame(conn, packet_out->po_data + packet_out->po_data_sz, w);
983    lsquic_send_ctl_scheduled_ack(&conn->fc_send_ctl);
984    packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK;
985    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, w);
986    packet_out->po_regen_sz += w;
987    if (has_missing)
988        conn->fc_flags |= FC_ACK_HAD_MISS;
989    else
990        conn->fc_flags &= ~FC_ACK_HAD_MISS;
991    LSQ_DEBUG("Put %d bytes of ACK frame into packet on outgoing queue", w);
992    if (conn->fc_conn.cn_version >= LSQVER_039 &&
993            conn->fc_n_cons_unretx >= 20 &&
994                !lsquic_send_ctl_have_outgoing_retx_frames(&conn->fc_send_ctl))
995    {
996        LSQ_DEBUG("schedule WINDOW_UPDATE frame after %u non-retx "
997                                    "packets sent", conn->fc_n_cons_unretx);
998        conn->fc_flags |= FC_SEND_WUF;
999    }
1000    reset_ack_state(conn);
1001}
1002
1003
1004static lsquic_stream_t *
1005new_stream_ext (struct full_conn *conn, uint32_t stream_id, int if_idx,
1006                enum stream_ctor_flags stream_ctor_flags)
1007{
1008    struct lsquic_stream *stream;
1009
1010    stream = lsquic_stream_new_ext(stream_id, &conn->fc_pub,
1011        conn->fc_stream_ifs[if_idx].stream_if,
1012        conn->fc_stream_ifs[if_idx].stream_if_ctx, conn->fc_settings->es_sfcw,
1013        conn->fc_cfg.max_stream_send, stream_ctor_flags);
1014    if (stream)
1015        lsquic_hash_insert(conn->fc_pub.all_streams, &stream->id, sizeof(stream->id),
1016                                                                        stream);
1017    return stream;
1018}
1019
1020
1021static lsquic_stream_t *
1022new_stream (struct full_conn *conn, uint32_t stream_id,
1023            enum stream_ctor_flags flags)
1024{
1025    int idx;
1026    switch (stream_id)
1027    {
1028    case LSQUIC_STREAM_HANDSHAKE:
1029        idx = STREAM_IF_HSK;
1030        flags |= SCF_DI_AUTOSWITCH|SCF_CRITICAL;
1031        break;
1032    case LSQUIC_STREAM_HEADERS:
1033        idx = STREAM_IF_HDR;
1034        flags |= SCF_DI_AUTOSWITCH|SCF_CRITICAL;
1035        if (!(conn->fc_flags & FC_HTTP) &&
1036                                    conn->fc_enpub->enp_settings.es_rw_once)
1037            flags |= SCF_DISP_RW_ONCE;
1038        break;
1039    default:
1040        idx = STREAM_IF_STD;
1041        flags |= SCF_DI_AUTOSWITCH;
1042        if (conn->fc_enpub->enp_settings.es_rw_once)
1043            flags |= SCF_DISP_RW_ONCE;
1044        break;
1045    }
1046    return new_stream_ext(conn, stream_id, idx, flags);
1047}
1048
1049
1050static uint32_t
1051generate_stream_id (struct full_conn *conn)
1052{
1053    conn->fc_last_stream_id += 2;
1054    return conn->fc_last_stream_id;
1055}
1056
1057
1058unsigned
1059lsquic_conn_n_pending_streams (const lsquic_conn_t *lconn)
1060{
1061    struct full_conn *conn = (struct full_conn *) lconn;
1062    return conn->fc_n_delayed_streams;
1063}
1064
1065
1066unsigned
1067lsquic_conn_cancel_pending_streams (lsquic_conn_t *lconn, unsigned n)
1068{
1069    struct full_conn *conn = (struct full_conn *) lconn;
1070    if (n > conn->fc_n_delayed_streams)
1071        conn->fc_n_delayed_streams = 0;
1072    else
1073        conn->fc_n_delayed_streams -= n;
1074    return conn->fc_n_delayed_streams;
1075}
1076
1077
1078static int
1079either_side_going_away (const struct full_conn *conn)
1080{
1081    return (conn->fc_flags & FC_GOING_AWAY)
1082        || (conn->fc_conn.cn_flags & LSCONN_PEER_GOING_AWAY);
1083}
1084
1085
1086unsigned
1087lsquic_conn_n_avail_streams (const lsquic_conn_t *lconn)
1088{
1089    struct full_conn *conn = (struct full_conn *) lconn;
1090    unsigned stream_count = count_streams(conn, 0);
1091    if (conn->fc_cfg.max_streams_out < stream_count)
1092        return 0;
1093    return conn->fc_cfg.max_streams_out - stream_count;
1094}
1095
1096
1097void
1098lsquic_conn_make_stream (lsquic_conn_t *lconn)
1099{
1100    struct full_conn *conn = (struct full_conn *) lconn;
1101    if (lsquic_conn_n_avail_streams(lconn) > 0)
1102    {
1103        if (!new_stream(conn, generate_stream_id(conn), SCF_CALL_ON_NEW))
1104            ABORT_ERROR("could not create new stream: %s", strerror(errno));
1105    }
1106    else if (either_side_going_away(conn))
1107        (void) conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_new_stream(
1108            conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, NULL);
1109    else
1110    {
1111        ++conn->fc_n_delayed_streams;
1112        LSQ_DEBUG("delayed stream creation.  Backlog size: %u",
1113                                                conn->fc_n_delayed_streams);
1114    }
1115}
1116
1117
1118static lsquic_stream_t *
1119find_stream_by_id (struct full_conn *conn, uint32_t stream_id)
1120{
1121    struct lsquic_hash_elem *el;
1122    el = lsquic_hash_find(conn->fc_pub.all_streams, &stream_id, sizeof(stream_id));
1123    if (el)
1124        return lsquic_hashelem_getdata(el);
1125    else
1126        return NULL;
1127}
1128
1129
1130lsquic_stream_t *
1131lsquic_conn_get_stream_by_id (lsquic_conn_t *lconn, uint32_t stream_id)
1132{
1133    struct full_conn *conn = (struct full_conn *) lconn;
1134    return find_stream_by_id(conn, stream_id);
1135}
1136
1137
1138lsquic_engine_t *
1139lsquic_conn_get_engine (lsquic_conn_t *lconn)
1140{
1141    struct full_conn *conn = (struct full_conn *) lconn;
1142    return conn->fc_enpub->enp_engine;
1143}
1144
1145
1146static ptrdiff_t
1147count_zero_bytes (const unsigned char *p, size_t len)
1148{
1149    const unsigned char *const end = p + len;
1150    while (p < end && 0 == *p)
1151        ++p;
1152    return len - (end - p);
1153}
1154
1155
1156static unsigned
1157process_padding_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1158                       const unsigned char *p, size_t len)
1159{
1160    if (conn->fc_conn.cn_version >= LSQVER_039)
1161        return (unsigned) count_zero_bytes(p, len);
1162    if (lsquic_is_zero(p, len))
1163    {
1164        EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len);
1165        return (unsigned) len;
1166    }
1167    else
1168        return 0;
1169}
1170
1171
1172static unsigned
1173process_ping_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1174                    const unsigned char *p, size_t len)
1175{   /* This frame causes ACK frame to be queued, but nothing to do here;
1176     * return the length of this frame.
1177     */
1178    EV_LOG_PING_FRAME_IN(LSQUIC_LOG_CONN_ID);
1179    LSQ_DEBUG("received PING");
1180    return 1;
1181}
1182
1183
1184static int
1185is_peer_initiated (const struct full_conn *conn, uint32_t stream_id)
1186{
1187    unsigned is_server = !!(conn->fc_flags & FC_SERVER);
1188    int peer_initiated = (stream_id & 1) == is_server;
1189    return peer_initiated;
1190}
1191
1192
1193static void
1194maybe_schedule_reset_for_stream (struct full_conn *conn, uint32_t stream_id)
1195{
1196    struct stream_id_to_reset *sitr;
1197
1198    if (conn_is_stream_closed(conn, stream_id))
1199        return;
1200
1201    sitr = malloc(sizeof(*sitr));
1202    if (!sitr)
1203        return;
1204
1205    sitr->sitr_stream_id = stream_id;
1206    STAILQ_INSERT_TAIL(&conn->fc_stream_ids_to_reset, sitr, sitr_next);
1207    conn_mark_stream_closed(conn, stream_id);
1208}
1209
1210
1211static unsigned
1212process_stream_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1213                      const unsigned char *p, size_t len)
1214{
1215    stream_frame_t *stream_frame;
1216    lsquic_stream_t *stream;
1217    enum enc_level enc_level;
1218    int parsed_len;
1219
1220    stream_frame = lsquic_malo_get(conn->fc_pub.mm->malo.stream_frame);
1221    if (!stream_frame)
1222    {
1223        LSQ_WARN("could not allocate stream frame: %s", strerror(errno));
1224        return 0;
1225    }
1226
1227    parsed_len = conn->fc_conn.cn_pf->pf_parse_stream_frame(p, len,
1228                                                            stream_frame);
1229    if (parsed_len < 0) {
1230        lsquic_malo_put(stream_frame);
1231        return 0;
1232    }
1233    EV_LOG_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_frame);
1234    LSQ_DEBUG("Got stream frame for stream #%u", stream_frame->stream_id);
1235#if LSQUIC_CONN_STATS
1236    ++conn->fc_stats.in.stream_frames;
1237    conn->fc_stats.in.stream_data_sz += stream_frame->data_frame.df_size;
1238#endif
1239
1240    enc_level = lsquic_packet_in_enc_level(packet_in);
1241    if (stream_frame->stream_id != LSQUIC_STREAM_HANDSHAKE
1242        && enc_level != ENC_LEV_FORW
1243        && enc_level != ENC_LEV_INIT)
1244    {
1245        lsquic_malo_put(stream_frame);
1246        ABORT_ERROR("received unencrypted data for stream %u",
1247                    stream_frame->stream_id);
1248        return 0;
1249    }
1250
1251    if (conn->fc_flags & FC_CLOSING)
1252    {
1253        LSQ_DEBUG("Connection closing: ignore frame");
1254        lsquic_malo_put(stream_frame);
1255        return parsed_len;
1256    }
1257
1258    stream = find_stream_by_id(conn, stream_frame->stream_id);
1259    if (stream)
1260    {
1261        if (lsquic_stream_is_reset(stream))
1262        {
1263            LSQ_DEBUG("stream %u is reset, ignore frame", stream->id);
1264            lsquic_malo_put(stream_frame);
1265            return parsed_len;
1266        }
1267    }
1268    else
1269    {
1270        if (conn_is_stream_closed(conn, stream_frame->stream_id))
1271        {
1272            LSQ_DEBUG("drop frame for closed stream %u", stream_frame->stream_id);
1273            lsquic_malo_put(stream_frame);
1274            return parsed_len;
1275        }
1276        if (is_peer_initiated(conn, stream_frame->stream_id))
1277        {
1278            unsigned in_count = count_streams(conn, 1);
1279            LSQ_DEBUG("number of peer-initiated streams: %u", in_count);
1280            if (in_count >= conn->fc_cfg.max_streams_in)
1281            {
1282                if (!(conn->fc_flags & FC_ABORT_COMPLAINED))
1283                {
1284                    unsigned counts[N_SCNTS];
1285                    collect_stream_counts(conn, 1, counts);
1286                    ABORT_WARN("incoming stream would exceed limit: %u.  "
1287                        "all: %u; peer: %u; closed: %u; reset: %u; reset "
1288                        "and not closed: %u", conn->fc_cfg.max_streams_in,
1289                        counts[SCNT_ALL], counts[SCNT_PEER],
1290                        counts[SCNT_CLOSED], counts[SCNT_RESET],
1291                        counts[SCNT_RES_UNCLO]);
1292                }
1293                lsquic_malo_put(stream_frame);
1294                return 0;
1295            }
1296            if ((conn->fc_flags & FC_GOING_AWAY) &&
1297                stream_frame->stream_id > conn->fc_max_peer_stream_id)
1298            {
1299                LSQ_DEBUG("going away: reset new incoming stream %"PRIu32,
1300                                                    stream_frame->stream_id);
1301                maybe_schedule_reset_for_stream(conn, stream_frame->stream_id);
1302                lsquic_malo_put(stream_frame);
1303                return parsed_len;
1304            }
1305        }
1306        else
1307        {
1308            ABORT_ERROR("frame for never-initiated stream");
1309            lsquic_malo_put(stream_frame);
1310            return 0;
1311        }
1312        stream = new_stream(conn, stream_frame->stream_id, SCF_CALL_ON_NEW);
1313        if (!stream)
1314        {
1315            ABORT_ERROR("cannot create new stream: %s", strerror(errno));
1316            lsquic_malo_put(stream_frame);
1317            return 0;
1318        }
1319        if (stream_frame->stream_id > conn->fc_max_peer_stream_id)
1320            conn->fc_max_peer_stream_id = stream_frame->stream_id;
1321    }
1322
1323    stream_frame->packet_in = lsquic_packet_in_get(packet_in);
1324    if (0 != lsquic_stream_frame_in(stream, stream_frame))
1325    {
1326        ABORT_ERROR("cannot insert stream frame");
1327        return 0;
1328    }
1329
1330    if (stream->id == LSQUIC_STREAM_HANDSHAKE
1331        && (stream->stream_flags & STREAM_WANT_READ)
1332        && !(conn->fc_flags & FC_SERVER)
1333        && !(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE))
1334    {   /* To enable decryption, process handshake stream as soon as its
1335         * data frames are received.
1336         *
1337         * TODO: this does not work when packets are reordered.  A more
1338         * flexible solution would defer packet decryption if handshake
1339         * has not been completed yet.  Nevertheless, this is good enough
1340         * for now.
1341         */
1342        lsquic_stream_dispatch_read_events(stream);
1343    }
1344
1345    return parsed_len;
1346}
1347
1348
1349static unsigned
1350process_invalid_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1351                                            const unsigned char *p, size_t len)
1352{
1353    ABORT_ERROR("invalid frame");
1354    return 0;
1355}
1356
1357
1358/* Reset locally-initiated streams whose IDs is larger than the stream ID
1359 * specified in received GOAWAY frame.
1360 */
1361static void
1362reset_local_streams_over_goaway (struct full_conn *conn)
1363{
1364    const unsigned is_server = !!(conn->fc_flags & FC_SERVER);
1365    lsquic_stream_t *stream;
1366    struct lsquic_hash_elem *el;
1367
1368    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
1369                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
1370    {
1371        stream = lsquic_hashelem_getdata(el);
1372        if (stream->id > conn->fc_goaway_stream_id &&
1373            ((stream->id & 1) ^ is_server /* Locally initiated? */))
1374        {
1375            lsquic_stream_received_goaway(stream);
1376        }
1377    }
1378}
1379
1380
1381static unsigned
1382process_goaway_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1383                                            const unsigned char *p, size_t len)
1384{
1385    uint32_t error_code, stream_id;
1386    uint16_t reason_length;
1387    const char *reason;
1388    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_goaway_frame(p, len,
1389                            &error_code, &stream_id, &reason_length, &reason);
1390    if (parsed_len < 0)
1391        return 0;
1392    EV_LOG_GOAWAY_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code, stream_id,
1393        reason_length, reason);
1394    LSQ_DEBUG("received GOAWAY frame, last good stream ID: %u, error code: 0x%X,"
1395        " reason: `%.*s'", stream_id, error_code, reason_length, reason);
1396    if (0 == (conn->fc_conn.cn_flags & LSCONN_PEER_GOING_AWAY))
1397    {
1398        conn->fc_conn.cn_flags |= LSCONN_PEER_GOING_AWAY;
1399        conn->fc_goaway_stream_id = stream_id;
1400        if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_goaway_received)
1401        {
1402            LSQ_DEBUG("calling on_goaway_received");
1403            conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_goaway_received(
1404                                            &conn->fc_conn);
1405        }
1406        else
1407            LSQ_DEBUG("on_goaway_received not registered");
1408        reset_local_streams_over_goaway(conn);
1409    }
1410    else
1411        LSQ_DEBUG("ignore duplicate GOAWAY frame");
1412    return parsed_len;
1413}
1414
1415
1416static void
1417log_invalid_ack_frame (struct full_conn *conn, const unsigned char *p,
1418                                int parsed_len, const struct ack_info *acki)
1419{
1420    char *buf;
1421    size_t sz;
1422
1423    buf = malloc(0x1000);
1424    if (buf)
1425    {
1426        lsquic_senhist_tostr(&conn->fc_send_ctl.sc_senhist, buf, 0x1000);
1427        LSQ_WARN("send history: %s", buf);
1428        hexdump(p, parsed_len, buf, 0x1000);
1429        LSQ_WARN("raw ACK frame:\n%s", buf);
1430        free(buf);
1431    }
1432    else
1433        LSQ_WARN("malloc failed");
1434
1435    buf = acki2str(acki, &sz);
1436    if (buf)
1437    {
1438        LSQ_WARN("parsed ACK frame: %.*s", (int) sz, buf);
1439        free(buf);
1440    }
1441    else
1442        LSQ_WARN("malloc failed");
1443}
1444
1445
1446static int
1447process_ack (struct full_conn *conn, struct ack_info *acki,
1448             lsquic_time_t received)
1449{
1450#if LSQUIC_CONN_STATS
1451    ++conn->fc_stats.in.n_acks_proc;
1452#endif
1453    LSQ_DEBUG("Processing ACK");
1454    if (0 == lsquic_send_ctl_got_ack(&conn->fc_send_ctl, acki, received))
1455    {
1456        if (lsquic_send_ctl_largest_ack2ed(&conn->fc_send_ctl))
1457            lsquic_rechist_stop_wait(&conn->fc_rechist,
1458                lsquic_send_ctl_largest_ack2ed(&conn->fc_send_ctl) + 1);
1459        return 0;
1460    }
1461    else
1462    {
1463        ABORT_ERROR("Received invalid ACK");
1464        return -1;
1465    }
1466}
1467
1468
1469static int
1470process_saved_ack (struct full_conn *conn, int restore_parsed_ack)
1471{
1472    struct ack_info *const acki = conn->fc_pub.mm->acki;
1473    struct lsquic_packno_range range;
1474    unsigned n_ranges, n_timestamps;
1475    lsquic_time_t lack_delta;
1476    int retval;
1477
1478#ifdef WIN32
1479    /* Useless initialization to mollify MSVC: */
1480    memset(&range, 0, sizeof(range));
1481    n_ranges = 0;
1482    n_timestamps = 0;
1483    lack_delta = 0;
1484#endif
1485
1486    if (restore_parsed_ack)
1487    {
1488        n_ranges     = acki->n_ranges;
1489        n_timestamps = acki->n_timestamps;
1490        lack_delta   = acki->lack_delta;
1491        range        = acki->ranges[0];
1492    }
1493
1494    acki->n_ranges     = 1;
1495    acki->n_timestamps = conn->fc_saved_ack_info.sai_n_timestamps;
1496    acki->lack_delta   = conn->fc_saved_ack_info.sai_lack_delta;
1497    acki->ranges[0]    = conn->fc_saved_ack_info.sai_range;
1498
1499    retval = process_ack(conn, acki, conn->fc_saved_ack_received);
1500
1501    if (restore_parsed_ack)
1502    {
1503        acki->n_ranges     = n_ranges;
1504        acki->n_timestamps = n_timestamps;
1505        acki->lack_delta   = lack_delta;
1506        acki->ranges[0]    = range;
1507    }
1508
1509    return retval;
1510}
1511
1512
1513static int
1514new_ack_is_superset (const struct short_ack_info *old, const struct ack_info *new)
1515{
1516    const struct lsquic_packno_range *new_range;
1517
1518    new_range = &new->ranges[ new->n_ranges - 1 ];
1519    return new_range->low  <= old->sai_range.low
1520        && new_range->high >= old->sai_range.high;
1521}
1522
1523
1524static int
1525merge_saved_to_new (const struct short_ack_info *old, struct ack_info *new)
1526{
1527    struct lsquic_packno_range *smallest_range;
1528
1529    assert(new->n_ranges > 1);
1530    smallest_range = &new->ranges[ new->n_ranges - 1 ];
1531    if (old->sai_range.high <= smallest_range->high
1532        && old->sai_range.high >= smallest_range->low
1533        && old->sai_range.low < smallest_range->low)
1534    {
1535        smallest_range->low = old->sai_range.low;
1536        return 1;
1537    }
1538    else
1539        return 0;
1540}
1541
1542
1543static int
1544merge_new_to_saved (struct short_ack_info *old, const struct ack_info *new)
1545{
1546    const struct lsquic_packno_range *new_range;
1547
1548    assert(new->n_ranges == 1);
1549    new_range = &new->ranges[0];
1550    /* Only merge if new is higher, for simplicity.  This is also the
1551     * expected case.
1552     */
1553    if (new_range->high > old->sai_range.high
1554        && new_range->low > old->sai_range.low)
1555    {
1556        old->sai_range.high = new_range->high;
1557        return 1;
1558    }
1559    else
1560        return 0;
1561}
1562
1563
1564static unsigned
1565process_ack_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1566                                            const unsigned char *p, size_t len)
1567{
1568    struct ack_info *const new_acki = conn->fc_pub.mm->acki;
1569    int parsed_len;
1570
1571#if LSQUIC_CONN_STATS
1572    ++conn->fc_stats.in.n_acks;
1573#endif
1574
1575    parsed_len = conn->fc_conn.cn_pf->pf_parse_ack_frame(p, len, new_acki);
1576    if (parsed_len < 0)
1577        goto err;
1578
1579    if (packet_in->pi_packno <= conn->fc_max_ack_packno)
1580    {
1581        LSQ_DEBUG("Ignore old ack (max %"PRIu64")", conn->fc_max_ack_packno);
1582        return parsed_len;
1583    }
1584
1585    EV_LOG_ACK_FRAME_IN(LSQUIC_LOG_CONN_ID, new_acki);
1586    conn->fc_max_ack_packno = packet_in->pi_packno;
1587
1588    if (conn->fc_flags & FC_HAVE_SAVED_ACK)
1589    {
1590        LSQ_DEBUG("old ack [%"PRIu64"-%"PRIu64"]",
1591            conn->fc_saved_ack_info.sai_range.high,
1592            conn->fc_saved_ack_info.sai_range.low);
1593        const int is_superset = new_ack_is_superset(&conn->fc_saved_ack_info,
1594                                                    new_acki);
1595        const int is_1range = new_acki->n_ranges == 1;
1596        switch (
1597             (is_superset << 1)
1598                      | (is_1range << 0))
1599           /* |          |
1600              |          |
1601              V          V                      */ {
1602        case (0 << 1) | (0 << 0):
1603            if (merge_saved_to_new(&conn->fc_saved_ack_info, new_acki))
1604            {
1605#if LSQUIC_CONN_STATS
1606                ++conn->fc_stats.in.n_acks_merged[0]
1607#endif
1608                ;
1609            }
1610            else
1611                process_saved_ack(conn, 1);
1612            conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
1613            if (0 != process_ack(conn, new_acki, packet_in->pi_received))
1614                goto err;
1615            break;
1616        case (0 << 1) | (1 << 0):
1617            if (merge_new_to_saved(&conn->fc_saved_ack_info, new_acki))
1618            {
1619#if LSQUIC_CONN_STATS
1620                ++conn->fc_stats.in.n_acks_merged[1]
1621#endif
1622                ;
1623            }
1624            else
1625            {
1626                process_saved_ack(conn, 1);
1627                conn->fc_saved_ack_info.sai_n_timestamps = new_acki->n_timestamps;
1628                conn->fc_saved_ack_info.sai_range        = new_acki->ranges[0];
1629            }
1630            conn->fc_saved_ack_info.sai_lack_delta   = new_acki->lack_delta;
1631            conn->fc_saved_ack_received              = packet_in->pi_received;
1632            break;
1633        case (1 << 1) | (0 << 0):
1634            conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
1635            if (0 != process_ack(conn, new_acki, packet_in->pi_received))
1636                goto err;
1637            break;
1638        case (1 << 1) | (1 << 0):
1639            conn->fc_saved_ack_info.sai_n_timestamps = new_acki->n_timestamps;
1640            conn->fc_saved_ack_info.sai_lack_delta   = new_acki->lack_delta;
1641            conn->fc_saved_ack_info.sai_range        = new_acki->ranges[0];
1642            conn->fc_saved_ack_received              = packet_in->pi_received;
1643            break;
1644        }
1645    }
1646    else if (new_acki->n_ranges == 1)
1647    {
1648        conn->fc_saved_ack_info.sai_n_timestamps = new_acki->n_timestamps;
1649        conn->fc_saved_ack_info.sai_lack_delta   = new_acki->lack_delta;
1650        conn->fc_saved_ack_info.sai_range        = new_acki->ranges[0];
1651        conn->fc_saved_ack_received              = packet_in->pi_received;
1652        conn->fc_flags |= FC_HAVE_SAVED_ACK;
1653    }
1654    else if (0 != process_ack(conn, new_acki, packet_in->pi_received))
1655        goto err;
1656
1657    return parsed_len;
1658
1659  err:
1660    log_invalid_ack_frame(conn, p, parsed_len, new_acki);
1661    return 0;
1662}
1663
1664
1665static unsigned
1666process_stop_waiting_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1667                                            const unsigned char *p, size_t len)
1668{
1669    lsquic_packno_t least, cutoff;
1670    enum lsquic_packno_bits bits;
1671    int parsed_len;
1672
1673    bits = lsquic_packet_in_packno_bits(packet_in);
1674
1675    if (conn->fc_flags & FC_NSTP)
1676    {
1677        LSQ_DEBUG("NSTP on: ignore STOP_WAITING frame");
1678        parsed_len = conn->fc_conn.cn_pf->pf_skip_stop_waiting_frame(len, bits);
1679        if (parsed_len > 0)
1680            return (unsigned) parsed_len;
1681        else
1682            return 0;
1683    }
1684
1685    parsed_len = conn->fc_conn.cn_pf->pf_parse_stop_waiting_frame(p, len,
1686                                            packet_in->pi_packno, bits, &least);
1687    if (parsed_len < 0)
1688        return 0;
1689
1690    if (packet_in->pi_packno <= conn->fc_max_swf_packno)
1691    {
1692        LSQ_DEBUG("ignore old STOP_WAITING frame");
1693        return parsed_len;
1694    }
1695
1696    LSQ_DEBUG("Got STOP_WAITING frame, least unacked: %"PRIu64, least);
1697    EV_LOG_STOP_WAITING_FRAME_IN(LSQUIC_LOG_CONN_ID, least);
1698
1699    if (least > packet_in->pi_packno)
1700    {
1701        ABORT_ERROR("received invalid STOP_WAITING: %"PRIu64" is larger "
1702            "than the packet number%"PRIu64, least, packet_in->pi_packno);
1703        return 0;
1704    }
1705
1706    cutoff = lsquic_rechist_cutoff(&conn->fc_rechist);
1707    if (cutoff && least < cutoff)
1708    {
1709        ABORT_ERROR("received invalid STOP_WAITING: %"PRIu64" is smaller "
1710            "than the cutoff %"PRIu64, least, cutoff);
1711        return 0;
1712    }
1713
1714    conn->fc_max_swf_packno = packet_in->pi_packno;
1715    lsquic_rechist_stop_wait(&conn->fc_rechist, least);
1716    return parsed_len;
1717}
1718
1719
1720static unsigned
1721process_blocked_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1722                                            const unsigned char *p, size_t len)
1723{
1724    uint32_t stream_id;
1725    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_blocked_frame(p, len,
1726                                                                    &stream_id);
1727    if (parsed_len < 0)
1728        return 0;
1729    EV_LOG_BLOCKED_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id);
1730    LSQ_DEBUG("Peer reports stream %u as blocked", stream_id);
1731    return parsed_len;
1732}
1733
1734
1735static unsigned
1736process_connection_close_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1737                                const unsigned char *p, size_t len)
1738{
1739    lsquic_stream_t *stream;
1740    struct lsquic_hash_elem *el;
1741    uint32_t error_code;
1742    uint16_t reason_len;
1743    uint8_t reason_off;
1744    int parsed_len;
1745
1746    parsed_len = conn->fc_conn.cn_pf->pf_parse_connect_close_frame(p, len,
1747                                        &error_code, &reason_len, &reason_off);
1748    if (parsed_len < 0)
1749        return 0;
1750    EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code,
1751                            (int) reason_len, (const char *) p + reason_off);
1752    LSQ_INFO("Received CONNECTION_CLOSE frame (code: %u; reason: %.*s)",
1753                error_code, (int) reason_len, (const char *) p + reason_off);
1754    conn->fc_flags |= FC_RECV_CLOSE;
1755    if (!(conn->fc_flags & FC_CLOSING))
1756    {
1757        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
1758                                     el = lsquic_hash_next(conn->fc_pub.all_streams))
1759        {
1760            stream = lsquic_hashelem_getdata(el);
1761            lsquic_stream_shutdown_internal(stream);
1762        }
1763        conn->fc_flags |= FC_CLOSING;
1764    }
1765    return parsed_len;
1766}
1767
1768
1769static unsigned
1770process_rst_stream_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1771                                            const unsigned char *p, size_t len)
1772{
1773    uint32_t stream_id, error_code;
1774    uint64_t offset;
1775    lsquic_stream_t *stream;
1776    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_rst_frame(p, len,
1777                                            &stream_id, &offset, &error_code);
1778    if (parsed_len < 0)
1779        return 0;
1780
1781    EV_LOG_RST_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset,
1782                                                                error_code);
1783    LSQ_DEBUG("Got RST_STREAM; stream: %u; offset: 0x%"PRIX64, stream_id,
1784                                                                    offset);
1785    if (0 == stream_id)
1786    {   /* Follow reference implementation and ignore this apparently
1787         * invalid frame.
1788         */
1789        return parsed_len;
1790    }
1791
1792    if (LSQUIC_STREAM_HANDSHAKE == stream_id ||
1793        ((conn->fc_flags & FC_HTTP) && LSQUIC_STREAM_HEADERS == stream_id))
1794    {
1795        ABORT_ERROR("received reset on static stream %u", stream_id);
1796        return 0;
1797    }
1798
1799    stream = find_stream_by_id(conn, stream_id);
1800    if (!stream)
1801    {
1802        if (conn_is_stream_closed(conn, stream_id))
1803        {
1804            LSQ_DEBUG("got reset frame for closed stream %u", stream_id);
1805            return parsed_len;
1806        }
1807        if (!is_peer_initiated(conn, stream_id))
1808        {
1809            ABORT_ERROR("received reset for never-initiated stream %u",
1810                                                                    stream_id);
1811            return 0;
1812        }
1813        stream = new_stream(conn, stream_id, SCF_CALL_ON_NEW);
1814        if (!stream)
1815        {
1816            ABORT_ERROR("cannot create new stream: %s", strerror(errno));
1817            return 0;
1818        }
1819        if (stream_id > conn->fc_max_peer_stream_id)
1820            conn->fc_max_peer_stream_id = stream_id;
1821    }
1822
1823    if (0 != lsquic_stream_rst_in(stream, offset, error_code))
1824    {
1825        ABORT_ERROR("received invalid RST_STREAM");
1826        return 0;
1827    }
1828    return parsed_len;
1829}
1830
1831
1832static unsigned
1833process_window_update_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1834                                             const unsigned char *p, size_t len)
1835{
1836    uint32_t stream_id;
1837    uint64_t offset;
1838    const int parsed_len =
1839                conn->fc_conn.cn_pf->pf_parse_window_update_frame(p, len,
1840                                                        &stream_id, &offset);
1841    if (parsed_len < 0)
1842        return 0;
1843    EV_LOG_WINDOW_UPDATE_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset);
1844    if (stream_id)
1845    {
1846        lsquic_stream_t *stream = find_stream_by_id(conn, stream_id);
1847        if (stream)
1848        {
1849            LSQ_DEBUG("Got window update frame, stream: %u; offset: 0x%"PRIX64,
1850                                                            stream_id, offset);
1851            lsquic_stream_window_update(stream, offset);
1852        }
1853        else    /* Perhaps a result of lost packets? */
1854            LSQ_DEBUG("Got window update frame for non-existing stream %u "
1855                                 "(offset: 0x%"PRIX64")", stream_id, offset);
1856    }
1857    else if (offset > conn->fc_pub.conn_cap.cc_max)
1858    {
1859        conn->fc_pub.conn_cap.cc_max = offset;
1860        assert(conn->fc_pub.conn_cap.cc_max >= conn->fc_pub.conn_cap.cc_sent);
1861        LSQ_DEBUG("Connection WUF, new offset 0x%"PRIX64, offset);
1862    }
1863    else
1864        LSQ_DEBUG("Throw ouw duplicate connection WUF");
1865    return parsed_len;
1866}
1867
1868
1869typedef unsigned (*process_frame_f)(
1870    struct full_conn *, lsquic_packet_in_t *, const unsigned char *p, size_t);
1871
1872static process_frame_f const process_frames[N_QUIC_FRAMES] =
1873{
1874    [QUIC_FRAME_ACK]                  =  process_ack_frame,
1875    [QUIC_FRAME_BLOCKED]              =  process_blocked_frame,
1876    [QUIC_FRAME_CONNECTION_CLOSE]     =  process_connection_close_frame,
1877    [QUIC_FRAME_GOAWAY]               =  process_goaway_frame,
1878    [QUIC_FRAME_INVALID]              =  process_invalid_frame,
1879    [QUIC_FRAME_PADDING]              =  process_padding_frame,
1880    [QUIC_FRAME_PING]                 =  process_ping_frame,
1881    [QUIC_FRAME_RST_STREAM]           =  process_rst_stream_frame,
1882    [QUIC_FRAME_STOP_WAITING]         =  process_stop_waiting_frame,
1883    [QUIC_FRAME_STREAM]               =  process_stream_frame,
1884    [QUIC_FRAME_WINDOW_UPDATE]        =  process_window_update_frame,
1885};
1886
1887static unsigned
1888process_packet_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1889                      const unsigned char *p, size_t len)
1890{
1891    enum quic_frame_type type = conn->fc_conn.cn_pf->pf_parse_frame_type(p[0]);
1892    packet_in->pi_frame_types |= 1 << type;
1893    recent_packet_hist_frames(conn, 0, 1 << type);
1894    return process_frames[type](conn, packet_in, p, len);
1895}
1896
1897
1898static void
1899process_ver_neg_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1900{
1901    int s;
1902    struct ver_iter vi;
1903    lsquic_ver_tag_t ver_tag;
1904    enum lsquic_version version;
1905    unsigned versions = 0;
1906
1907    LSQ_DEBUG("Processing version-negotiation packet");
1908
1909    if (conn->fc_ver_neg.vn_state != VN_START)
1910    {
1911        LSQ_DEBUG("ignore a likely duplicate version negotiation packet");
1912        return;
1913    }
1914
1915    for (s = packet_in_ver_first(packet_in, &vi, &ver_tag); s;
1916                     s = packet_in_ver_next(&vi, &ver_tag))
1917    {
1918        version = lsquic_tag2ver(ver_tag);
1919        if (version < N_LSQVER)
1920        {
1921            versions |= 1 << version;
1922            LSQ_DEBUG("server supports version %s", lsquic_ver2str[version]);
1923        }
1924    }
1925
1926    if (versions & (1 << conn->fc_ver_neg.vn_ver))
1927    {
1928        ABORT_ERROR("server replied with version we support: %s",
1929                                    lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
1930        return;
1931    }
1932
1933    versions &= conn->fc_ver_neg.vn_supp;
1934    if (0 == versions)
1935    {
1936        ABORT_ERROR("client does not support any of the server-specified "
1937                    "versions");
1938        return;
1939    }
1940
1941    set_versions(conn, versions, NULL);
1942    conn->fc_ver_neg.vn_state = VN_IN_PROGRESS;
1943    lsquic_send_ctl_expire_all(&conn->fc_send_ctl);
1944}
1945
1946
1947static void
1948reconstruct_packet_number (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1949{
1950    lsquic_packno_t cur_packno, max_packno;
1951    enum lsquic_packno_bits bits;
1952
1953    cur_packno = packet_in->pi_packno;
1954    max_packno = lsquic_rechist_largest_packno(&conn->fc_rechist);
1955    bits = lsquic_packet_in_packno_bits(packet_in);
1956    packet_in->pi_packno = restore_packno(cur_packno, bits, max_packno);
1957    LSQ_DEBUG("reconstructed (bits: %u, packno: %"PRIu64", max: %"PRIu64") "
1958        "to %"PRIu64"", bits, cur_packno, max_packno, packet_in->pi_packno);
1959}
1960
1961
1962static int
1963conn_decrypt_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1964{
1965    return lsquic_conn_decrypt_packet(&conn->fc_conn, conn->fc_enpub,
1966                                                                packet_in);
1967}
1968
1969
1970static void
1971parse_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1972{
1973    const unsigned char *p, *pend;
1974    unsigned len;
1975
1976    p = packet_in->pi_data + packet_in->pi_header_sz;
1977    pend = packet_in->pi_data + packet_in->pi_data_sz;
1978
1979    while (p < pend)
1980    {
1981        len = process_packet_frame(conn, packet_in, p, pend - p);
1982        if (len > 0)
1983            p += len;
1984        else
1985        {
1986            ABORT_ERROR("Error parsing frame");
1987            break;
1988        }
1989    }
1990}
1991
1992
1993static int
1994conn_is_stateless_reset (const struct full_conn *conn,
1995                                    const struct lsquic_packet_in *packet_in)
1996{
1997    return packet_in->pi_data_sz > SRST_LENGTH
1998        && 0 == conn->fc_conn.cn_esf->esf_verify_reset_token(
1999                    conn->fc_conn.cn_enc_session,
2000                    packet_in->pi_data + packet_in->pi_data_sz - SRST_LENGTH,
2001                    SRST_LENGTH);
2002}
2003
2004
2005static int
2006process_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2007{
2008    enum received_st st;
2009    enum quic_ft_bit frame_types;
2010    int was_missing;
2011
2012    reconstruct_packet_number(conn, packet_in);
2013    EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
2014
2015#if LSQUIC_CONN_STATS
2016    ++conn->fc_stats.in.packets;
2017#endif
2018
2019    /* The packet is decrypted before receive history is updated.  This is
2020     * done to make sure that a bad packet won't occupy a slot in receive
2021     * history and subsequent good packet won't be marked as a duplicate.
2022     */
2023    if (0 == (packet_in->pi_flags & PI_DECRYPTED) &&
2024        0 != conn_decrypt_packet(conn, packet_in))
2025    {
2026        if (conn_is_stateless_reset(conn, packet_in))
2027        {
2028            LSQ_INFO("received public reset packet: aborting connection");
2029            conn->fc_flags |= FC_GOT_PRST;
2030            return -1;
2031        }
2032        else
2033        {
2034            LSQ_INFO("could not decrypt packet");
2035#if LSQUIC_CONN_STATS
2036            ++conn->fc_stats.in.undec_packets;
2037#endif
2038            return 0;
2039        }
2040    }
2041
2042    st = lsquic_rechist_received(&conn->fc_rechist, packet_in->pi_packno,
2043                                                    packet_in->pi_received);
2044    switch (st) {
2045    case REC_ST_OK:
2046        parse_regular_packet(conn, packet_in);
2047        if (0 == (conn->fc_flags & FC_ACK_QUEUED))
2048        {
2049            frame_types = packet_in->pi_frame_types;
2050            was_missing = packet_in->pi_packno !=
2051                            lsquic_rechist_largest_packno(&conn->fc_rechist);
2052            conn->fc_n_slack_all  += 1;
2053            conn->fc_n_slack_akbl += !!(frame_types & QFRAME_ACKABLE_MASK);
2054            try_queueing_ack(conn, was_missing, packet_in->pi_received);
2055        }
2056        return 0;
2057    case REC_ST_DUP:
2058#if LSQUIC_CONN_STATS
2059        ++conn->fc_stats.in.dup_packets;
2060#endif
2061        LSQ_INFO("packet %"PRIu64" is a duplicate", packet_in->pi_packno);
2062        return 0;
2063    default:
2064        assert(0);
2065        /* Fall through */
2066    case REC_ST_ERR:
2067#if LSQUIC_CONN_STATS
2068        ++conn->fc_stats.in.err_packets;
2069#endif
2070        LSQ_INFO("error processing packet %"PRIu64, packet_in->pi_packno);
2071        return -1;
2072    }
2073}
2074
2075
2076static int
2077process_incoming_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2078{
2079    int is_prst, is_verneg;
2080
2081    recent_packet_hist_new(conn, 0, packet_in->pi_received);
2082    LSQ_DEBUG("Processing packet %"PRIu64, packet_in->pi_packno);
2083
2084    is_prst = lsquic_packet_in_is_gquic_prst(packet_in);
2085    is_verneg = lsquic_packet_in_is_verneg(packet_in);
2086
2087    /* See flowchart in Section 4.1 of [draft-ietf-quic-transport-00].  We test
2088     * for the common case first.
2089     */
2090    if (0 == is_prst && 0 == is_verneg)
2091    {
2092        if (conn->fc_ver_neg.vn_tag)
2093        {
2094            assert(conn->fc_ver_neg.vn_state != VN_END);
2095            conn->fc_ver_neg.vn_state = VN_END;
2096            conn->fc_ver_neg.vn_tag = NULL;
2097            conn->fc_conn.cn_version = conn->fc_ver_neg.vn_ver;
2098            conn->fc_conn.cn_flags |= LSCONN_VER_SET;
2099            if (conn->fc_conn.cn_version >= LSQVER_039)
2100            {
2101                assert(!(conn->fc_flags & FC_NSTP)); /* This bit off at start */
2102                if (conn->fc_conn.cn_version >= LSQVER_044
2103                                        || conn->fc_settings->es_support_nstp)
2104                {
2105                    conn->fc_flags |= FC_NSTP;
2106                    lsquic_send_ctl_turn_nstp_on(&conn->fc_send_ctl);
2107                }
2108            }
2109            LSQ_DEBUG("end of version negotiation: agreed upon %s",
2110                                    lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
2111            lsquic_send_ctl_verneg_done(&conn->fc_send_ctl);
2112        }
2113        return process_regular_packet(conn, packet_in);
2114    }
2115    else if (is_prst)
2116    {
2117        LSQ_INFO("received public reset packet: aborting connection");
2118        conn->fc_flags |= FC_GOT_PRST;
2119        return -1;
2120    }
2121    else
2122    {
2123        if (conn->fc_flags & FC_SERVER)
2124            return process_regular_packet(conn, packet_in);
2125        else if (conn->fc_ver_neg.vn_tag)
2126        {
2127            process_ver_neg_packet(conn, packet_in);
2128            return 0;
2129        }
2130        else
2131        {
2132            LSQ_DEBUG("unexpected version negotiation packet: ignore it");
2133            return 0;
2134        }
2135    }
2136}
2137
2138
2139static void
2140idle_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now)
2141{
2142    struct full_conn *conn = ctx;
2143    LSQ_DEBUG("connection timed out");
2144    conn->fc_flags |= FC_TIMED_OUT;
2145}
2146
2147
2148static void
2149handshake_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now)
2150{
2151    struct full_conn *conn = ctx;
2152    LSQ_DEBUG("connection timed out: handshake timed out");
2153    conn->fc_flags |= FC_TIMED_OUT;
2154}
2155
2156
2157static void
2158ping_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now)
2159{
2160    struct full_conn *conn = ctx;
2161    LSQ_DEBUG("Ping alarm rang: schedule PING frame to be generated");
2162    conn->fc_flags |= FC_SEND_PING;
2163}
2164
2165
2166static lsquic_packet_out_t *
2167get_writeable_packet (struct full_conn *conn, unsigned need_at_least)
2168{
2169    lsquic_packet_out_t *packet_out;
2170    int is_err;
2171
2172    assert(need_at_least <= QUIC_MAX_PAYLOAD_SZ);
2173    packet_out = lsquic_send_ctl_get_writeable_packet(&conn->fc_send_ctl,
2174                                                    need_at_least, &is_err);
2175    if (!packet_out && is_err)
2176        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2177    return packet_out;
2178}
2179
2180
2181static int
2182generate_wuf_stream (struct full_conn *conn, lsquic_stream_t *stream)
2183{
2184    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, QUIC_WUF_SZ);
2185    if (!packet_out)
2186        return 0;
2187    const uint64_t recv_off = lsquic_stream_fc_recv_off(stream);
2188    int sz = conn->fc_conn.cn_pf->pf_gen_window_update_frame(
2189                packet_out->po_data + packet_out->po_data_sz,
2190                     lsquic_packet_out_avail(packet_out), stream->id, recv_off);
2191    if (sz < 0) {
2192        ABORT_ERROR("gen_window_update_frame failed");
2193        return 0;
2194    }
2195    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2196    packet_out->po_frame_types |= 1 << QUIC_FRAME_WINDOW_UPDATE;
2197    LSQ_DEBUG("wrote WUF: stream %u; offset 0x%"PRIX64, stream->id, recv_off);
2198    return 1;
2199}
2200
2201
2202static void
2203generate_wuf_conn (struct full_conn *conn)
2204{
2205    assert(conn->fc_flags & FC_SEND_WUF);
2206    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, QUIC_WUF_SZ);
2207    if (!packet_out)
2208        return;
2209    const uint64_t recv_off = lsquic_cfcw_get_fc_recv_off(&conn->fc_pub.cfcw);
2210    int sz = conn->fc_conn.cn_pf->pf_gen_window_update_frame(
2211                     packet_out->po_data + packet_out->po_data_sz,
2212                     lsquic_packet_out_avail(packet_out), 0, recv_off);
2213    if (sz < 0) {
2214        ABORT_ERROR("gen_window_update_frame failed");
2215        return;
2216    }
2217    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2218    packet_out->po_frame_types |= 1 << QUIC_FRAME_WINDOW_UPDATE;
2219    conn->fc_flags &= ~FC_SEND_WUF;
2220    LSQ_DEBUG("wrote connection WUF: offset 0x%"PRIX64, recv_off);
2221}
2222
2223
2224static void
2225generate_goaway_frame (struct full_conn *conn)
2226{
2227    int reason_len = 0;
2228    lsquic_packet_out_t *packet_out =
2229        get_writeable_packet(conn, QUIC_GOAWAY_FRAME_SZ + reason_len);
2230    if (!packet_out)
2231        return;
2232    int sz = conn->fc_conn.cn_pf->pf_gen_goaway_frame(
2233                 packet_out->po_data + packet_out->po_data_sz,
2234                 lsquic_packet_out_avail(packet_out), 0, conn->fc_max_peer_stream_id,
2235                 NULL, reason_len);
2236    if (sz < 0) {
2237        ABORT_ERROR("gen_goaway_frame failed");
2238        return;
2239    }
2240    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2241    packet_out->po_frame_types |= 1 << QUIC_FRAME_GOAWAY;
2242    conn->fc_flags &= ~FC_SEND_GOAWAY;
2243    conn->fc_flags |=  FC_GOAWAY_SENT;
2244    LSQ_DEBUG("wrote GOAWAY frame: stream id: %u", conn->fc_max_peer_stream_id);
2245}
2246
2247
2248static void
2249generate_connection_close_packet (struct full_conn *conn)
2250{
2251    lsquic_packet_out_t *packet_out;
2252
2253    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0);
2254    if (!packet_out)
2255    {
2256        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2257        return;
2258    }
2259
2260    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
2261    int sz = conn->fc_conn.cn_pf->pf_gen_connect_close_frame(packet_out->po_data + packet_out->po_data_sz,
2262                     lsquic_packet_out_avail(packet_out), 16 /* PEER_GOING_AWAY */,
2263                     NULL, 0);
2264    if (sz < 0) {
2265        ABORT_ERROR("generate_connection_close_packet failed");
2266        return;
2267    }
2268    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2269    packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
2270    LSQ_DEBUG("generated CONNECTION_CLOSE frame in its own packet");
2271}
2272
2273
2274static int
2275generate_blocked_frame (struct full_conn *conn, uint32_t stream_id)
2276{
2277    lsquic_packet_out_t *packet_out =
2278                            get_writeable_packet(conn, QUIC_BLOCKED_FRAME_SZ);
2279    if (!packet_out)
2280        return 0;
2281    int sz = conn->fc_conn.cn_pf->pf_gen_blocked_frame(
2282                                 packet_out->po_data + packet_out->po_data_sz,
2283                                 lsquic_packet_out_avail(packet_out), stream_id);
2284    if (sz < 0) {
2285        ABORT_ERROR("gen_blocked_frame failed");
2286        return 0;
2287    }
2288    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2289    packet_out->po_frame_types |= 1 << QUIC_FRAME_BLOCKED;
2290    LSQ_DEBUG("wrote blocked frame: stream %u", stream_id);
2291    return 1;
2292}
2293
2294
2295static int
2296generate_stream_blocked_frame (struct full_conn *conn, lsquic_stream_t *stream)
2297{
2298    if (generate_blocked_frame(conn, stream->id))
2299    {
2300        lsquic_stream_blocked_frame_sent(stream);
2301        return 1;
2302    }
2303    else
2304        return 0;
2305}
2306
2307
2308static int
2309generate_rst_stream_frame (struct full_conn *conn, lsquic_stream_t *stream)
2310{
2311    lsquic_packet_out_t *packet_out;
2312    int sz, s;
2313
2314    packet_out = get_writeable_packet(conn, QUIC_RST_STREAM_SZ);
2315    if (!packet_out)
2316        return 0;
2317    /* TODO Possible optimization: instead of using stream->tosend_off as the
2318     * offset, keep track of the offset that was actually sent: include it
2319     * into stream_rec and update a new per-stream "maximum offset actually
2320     * sent" field.  Then, if a stream is reset, the connection cap can be
2321     * increased.
2322     */
2323    sz = conn->fc_conn.cn_pf->pf_gen_rst_frame(
2324                     packet_out->po_data + packet_out->po_data_sz,
2325                     lsquic_packet_out_avail(packet_out), stream->id,
2326                     stream->tosend_off, stream->error_code);
2327    if (sz < 0) {
2328        ABORT_ERROR("gen_rst_frame failed");
2329        return 0;
2330    }
2331    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2332    packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
2333    s = lsquic_packet_out_add_stream(packet_out, conn->fc_pub.mm, stream,
2334                             QUIC_FRAME_RST_STREAM, packet_out->po_data_sz, sz);
2335    if (s != 0)
2336    {
2337        ABORT_ERROR("adding stream to packet failed: %s", strerror(errno));
2338        return 0;
2339    }
2340    lsquic_stream_rst_frame_sent(stream);
2341    LSQ_DEBUG("wrote RST: stream %u; offset 0x%"PRIX64"; error code 0x%X",
2342                        stream->id, stream->tosend_off, stream->error_code);
2343    return 1;
2344}
2345
2346
2347static void
2348generate_ping_frame (struct full_conn *conn)
2349{
2350    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, 1);
2351    if (!packet_out)
2352    {
2353        LSQ_DEBUG("cannot get writeable packet for PING frame");
2354        return;
2355    }
2356    int sz = conn->fc_conn.cn_pf->pf_gen_ping_frame(
2357                            packet_out->po_data + packet_out->po_data_sz,
2358                            lsquic_packet_out_avail(packet_out));
2359    if (sz < 0) {
2360        ABORT_ERROR("gen_blocked_frame failed");
2361        return;
2362    }
2363    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2364    packet_out->po_frame_types |= 1 << QUIC_FRAME_PING;
2365    LSQ_DEBUG("wrote PING frame");
2366}
2367
2368
2369static void
2370generate_stop_waiting_frame (struct full_conn *conn)
2371{
2372    assert(conn->fc_flags & FC_SEND_STOP_WAITING);
2373
2374    int sz;
2375    unsigned packnum_len;
2376    lsquic_packno_t least_unacked;
2377    lsquic_packet_out_t *packet_out;
2378
2379    /* Get packet that has room for the minimum size STOP_WAITING frame: */
2380    packet_out = get_writeable_packet(conn, 1 + packno_bits2len(PACKNO_LEN_1));
2381    if (!packet_out)
2382        return;
2383
2384    /* Now calculate number of bytes we really need.  If there is not enough
2385     * room in the current packet, get a new one.
2386     */
2387    packnum_len = packno_bits2len(lsquic_packet_out_packno_bits(packet_out));
2388    if ((unsigned) lsquic_packet_out_avail(packet_out) < 1 + packnum_len)
2389    {
2390        packet_out = get_writeable_packet(conn, 1 + packnum_len);
2391        if (!packet_out)
2392            return;
2393        /* Here, a new packet has been allocated, The number of bytes needed
2394         * to represent packet number in the STOP_WAITING frame may have
2395         * increased.  However, this does not matter, because the newly
2396         * allocated packet must have room for a STOP_WAITING frame of any
2397         * size.
2398         */
2399    }
2400
2401    least_unacked = lsquic_send_ctl_smallest_unacked(&conn->fc_send_ctl);
2402    sz = conn->fc_conn.cn_pf->pf_gen_stop_waiting_frame(
2403                    packet_out->po_data + packet_out->po_data_sz,
2404                    lsquic_packet_out_avail(packet_out), packet_out->po_packno,
2405                    lsquic_packet_out_packno_bits(packet_out), least_unacked);
2406    if (sz < 0) {
2407        ABORT_ERROR("gen_stop_waiting_frame failed");
2408        return;
2409    }
2410    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2411    packet_out->po_regen_sz += sz;
2412    packet_out->po_frame_types |= 1 << QUIC_FRAME_STOP_WAITING;
2413    conn->fc_flags &= ~FC_SEND_STOP_WAITING;
2414    LSQ_DEBUG("wrote STOP_WAITING frame: least unacked: %"PRIu64,
2415                                                            least_unacked);
2416    EV_LOG_GENERATED_STOP_WAITING_FRAME(LSQUIC_LOG_CONN_ID, least_unacked);
2417}
2418
2419
2420static int
2421process_stream_ready_to_send (struct full_conn *conn, lsquic_stream_t *stream)
2422{
2423    int r = 1;
2424    if (stream->stream_flags & STREAM_SEND_WUF)
2425        r &= generate_wuf_stream(conn, stream);
2426    if (stream->stream_flags & STREAM_SEND_BLOCKED)
2427        r &= generate_stream_blocked_frame(conn, stream);
2428    if (stream->stream_flags & STREAM_SEND_RST)
2429        r &= generate_rst_stream_frame(conn, stream);
2430    return r;
2431}
2432
2433
2434static void
2435process_streams_ready_to_send (struct full_conn *conn)
2436{
2437    lsquic_stream_t *stream;
2438    struct stream_prio_iter spi;
2439
2440    assert(!TAILQ_EMPTY(&conn->fc_pub.sending_streams));
2441
2442    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.sending_streams),
2443        TAILQ_LAST(&conn->fc_pub.sending_streams, lsquic_streams_tailq),
2444        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_send_stream),
2445        STREAM_SENDING_FLAGS, conn->fc_conn.cn_cid, "send", NULL, NULL);
2446
2447    for (stream = lsquic_spi_first(&spi); stream;
2448                                            stream = lsquic_spi_next(&spi))
2449        if (!process_stream_ready_to_send(conn, stream))
2450            break;
2451}
2452
2453
2454/* Return true if packetized, false otherwise */
2455static int
2456packetize_standalone_stream_reset (struct full_conn *conn, uint32_t stream_id)
2457{
2458    lsquic_packet_out_t *packet_out;
2459    int sz;
2460
2461    packet_out = get_writeable_packet(conn, QUIC_RST_STREAM_SZ);
2462    if (!packet_out)
2463        return 0;
2464
2465    sz = conn->fc_conn.cn_pf->pf_gen_rst_frame(
2466                     packet_out->po_data + packet_out->po_data_sz,
2467                     lsquic_packet_out_avail(packet_out), stream_id,
2468                     0, 0x10 /* QUIC_PEER_GOING_AWAY */);
2469    if (sz < 0) {
2470        ABORT_ERROR("gen_rst_frame failed");
2471        return 0;
2472    }
2473    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2474    packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
2475    LSQ_DEBUG("generated standalone RST_STREAM frame for stream %"PRIu32,
2476                                                                    stream_id);
2477    return 1;
2478}
2479
2480
2481static void
2482packetize_standalone_stream_resets (struct full_conn *conn)
2483{
2484    struct stream_id_to_reset *sitr;
2485
2486    while ((sitr = STAILQ_FIRST(&conn->fc_stream_ids_to_reset)))
2487        if (packetize_standalone_stream_reset(conn, sitr->sitr_stream_id))
2488        {
2489            STAILQ_REMOVE_HEAD(&conn->fc_stream_ids_to_reset, sitr_next);
2490            free(sitr);
2491        }
2492        else
2493            break;
2494}
2495
2496
2497static void
2498create_delayed_streams (struct full_conn *conn)
2499{
2500    unsigned stream_count, avail, i;
2501    struct lsquic_stream **new_streams;
2502
2503    stream_count = count_streams(conn, 0);
2504
2505    if (stream_count >= conn->fc_cfg.max_streams_out)
2506        return;
2507
2508    avail = conn->fc_cfg.max_streams_out - stream_count;
2509    if (conn->fc_n_delayed_streams < avail)
2510        avail = conn->fc_n_delayed_streams;
2511    if (avail == 0)
2512	return;
2513
2514    new_streams = malloc(sizeof(new_streams[0]) * avail);
2515    if (!new_streams)
2516    {
2517        ABORT_WARN("%s: malloc failed", __func__);
2518        return;
2519    }
2520
2521    LSQ_DEBUG("creating delayed streams");
2522    for (i = 0; i < avail; ++i)
2523    {
2524        /* Delay calling on_new in order not to let the user screw up
2525         * the counts by making more streams.
2526         */
2527        new_streams[i] = new_stream(conn, generate_stream_id(conn), 0);
2528        if (!new_streams[i])
2529        {
2530            ABORT_ERROR("%s: cannot create new stream: %s", __func__,
2531                                                        strerror(errno));
2532            goto cleanup;
2533        }
2534    }
2535    LSQ_DEBUG("created %u delayed stream%.*s", avail, avail != 1, "s");
2536
2537    assert(count_streams(conn, 0) <= conn->fc_cfg.max_streams_out);
2538    conn->fc_n_delayed_streams -= avail;
2539
2540    for (i = 0; i < avail; ++i)
2541        lsquic_stream_call_on_new(new_streams[i]);
2542  cleanup:
2543    free(new_streams);
2544}
2545
2546
2547static void
2548service_streams (struct full_conn *conn)
2549{
2550    struct lsquic_hash_elem *el;
2551    lsquic_stream_t *stream, *next;
2552    int closed_some = 0;
2553
2554    for (stream = TAILQ_FIRST(&conn->fc_pub.service_streams); stream; stream = next)
2555    {
2556        next = TAILQ_NEXT(stream, next_service_stream);
2557        if (stream->stream_flags & STREAM_ABORT_CONN)
2558            /* No need to unset this flag or remove this stream: the connection
2559             * is about to be aborted.
2560             */
2561            ABORT_ERROR("aborted due to error in stream %"PRIu32, stream->id);
2562        if (stream->stream_flags & STREAM_CALL_ONCLOSE)
2563        {
2564            lsquic_stream_call_on_close(stream);
2565            closed_some |= is_our_stream(conn, stream);
2566            conn_mark_stream_closed(conn, stream->id);
2567        }
2568        if (stream->stream_flags & STREAM_FREE_STREAM)
2569        {
2570            TAILQ_REMOVE(&conn->fc_pub.service_streams, stream, next_service_stream);
2571            el = lsquic_hash_find(conn->fc_pub.all_streams, &stream->id, sizeof(stream->id));
2572            if (el)
2573                lsquic_hash_erase(conn->fc_pub.all_streams, el);
2574            SAVE_STREAM_HISTORY(conn, stream);
2575            lsquic_stream_destroy(stream);
2576        }
2577    }
2578
2579    if (either_side_going_away(conn))
2580        while (conn->fc_n_delayed_streams)
2581        {
2582            --conn->fc_n_delayed_streams;
2583            LSQ_DEBUG("goaway mode: delayed stream results in null ctor");
2584            (void) conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_new_stream(
2585                conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, NULL);
2586        }
2587    else
2588        if (closed_some && conn->fc_n_delayed_streams)
2589            create_delayed_streams(conn);
2590}
2591
2592
2593static void
2594process_streams_read_events (struct full_conn *conn)
2595{
2596    lsquic_stream_t *stream;
2597    enum stream_flags service_flags;
2598    int needs_service;
2599    struct stream_prio_iter spi;
2600
2601    if (TAILQ_EMPTY(&conn->fc_pub.read_streams))
2602        return;
2603
2604    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.read_streams),
2605        TAILQ_LAST(&conn->fc_pub.read_streams, lsquic_streams_tailq),
2606        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_read_stream),
2607        STREAM_WANT_READ, conn->fc_conn.cn_cid, "read", NULL, NULL);
2608
2609    needs_service = 0;
2610    for (stream = lsquic_spi_first(&spi); stream;
2611                                            stream = lsquic_spi_next(&spi))
2612    {
2613        service_flags = stream->stream_flags & STREAM_SERVICE_FLAGS;
2614        lsquic_stream_dispatch_read_events(stream);
2615        needs_service |= service_flags
2616                                ^ (stream->stream_flags & STREAM_SERVICE_FLAGS);
2617    }
2618
2619    if (needs_service)
2620        service_streams(conn);
2621
2622}
2623
2624
2625static void
2626maybe_conn_flush_headers_stream (struct full_conn *conn)
2627{
2628    lsquic_stream_t *stream;
2629
2630    if (conn->fc_flags & FC_HTTP)
2631    {
2632        stream = lsquic_headers_stream_get_stream(conn->fc_pub.hs);
2633        if (lsquic_stream_has_data_to_flush(stream))
2634            (void) lsquic_stream_flush(stream);
2635    }
2636}
2637
2638
2639static void
2640process_streams_write_events (struct full_conn *conn, int high_prio)
2641{
2642    lsquic_stream_t *stream;
2643    struct stream_prio_iter spi;
2644
2645    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.write_streams),
2646        TAILQ_LAST(&conn->fc_pub.write_streams, lsquic_streams_tailq),
2647        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_write_stream),
2648        STREAM_WANT_WRITE|STREAM_WANT_FLUSH, conn->fc_conn.cn_cid,
2649        high_prio ? "write-high" : "write-low", NULL, NULL);
2650
2651    if (high_prio)
2652        lsquic_spi_drop_non_high(&spi);
2653    else
2654        lsquic_spi_drop_high(&spi);
2655
2656    for (stream = lsquic_spi_first(&spi); stream && write_is_possible(conn);
2657                                            stream = lsquic_spi_next(&spi))
2658        if (stream->stream_flags & STREAM_WRITE_Q_FLAGS)
2659            lsquic_stream_dispatch_write_events(stream);
2660
2661    maybe_conn_flush_headers_stream(conn);
2662}
2663
2664
2665static void
2666process_hsk_stream_read_events (struct full_conn *conn)
2667{
2668    lsquic_stream_t *stream;
2669    TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
2670        if (LSQUIC_STREAM_HANDSHAKE == stream->id)
2671        {
2672            lsquic_stream_dispatch_read_events(stream);
2673            break;
2674        }
2675}
2676
2677
2678static void
2679process_hsk_stream_write_events (struct full_conn *conn)
2680{
2681    lsquic_stream_t *stream;
2682    TAILQ_FOREACH(stream, &conn->fc_pub.write_streams, next_write_stream)
2683        if (LSQUIC_STREAM_HANDSHAKE == stream->id)
2684        {
2685            lsquic_stream_dispatch_write_events(stream);
2686            break;
2687        }
2688}
2689
2690
2691static void
2692generate_ack_frame (struct full_conn *conn)
2693{
2694    lsquic_packet_out_t *packet_out;
2695
2696    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0);
2697    if (packet_out)
2698    {
2699        lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
2700        full_conn_ci_write_ack(&conn->fc_conn, packet_out);
2701    }
2702    else
2703        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2704}
2705
2706
2707static int
2708conn_ok_to_close (const struct full_conn *conn)
2709{
2710    assert(conn->fc_flags & FC_CLOSING);
2711    return !(conn->fc_flags & FC_SERVER)
2712        || (conn->fc_flags & FC_RECV_CLOSE)
2713        || (
2714               !lsquic_send_ctl_have_outgoing_stream_frames(&conn->fc_send_ctl)
2715            && lsquic_hash_count(conn->fc_pub.all_streams) == 0
2716            && lsquic_send_ctl_have_unacked_stream_frames(&conn->fc_send_ctl) == 0);
2717}
2718
2719
2720static enum tick_st
2721immediate_close (struct full_conn *conn)
2722{
2723    lsquic_packet_out_t *packet_out;
2724    const char *error_reason;
2725    unsigned error_code;
2726    int sz;
2727
2728    if (conn->fc_flags & (FC_TICK_CLOSE|FC_GOT_PRST))
2729        return TICK_CLOSE;
2730
2731    conn->fc_flags |= FC_TICK_CLOSE;
2732
2733    /* No reason to send anything that's been scheduled if connection is
2734     * being closed immedately.  This also ensures that packet numbers
2735     * sequence is always increasing.
2736     */
2737    lsquic_send_ctl_drop_scheduled(&conn->fc_send_ctl);
2738
2739    if ((conn->fc_flags & FC_TIMED_OUT) && conn->fc_settings->es_silent_close)
2740        return TICK_CLOSE;
2741
2742    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0);
2743    if (!packet_out)
2744    {
2745        LSQ_WARN("cannot allocate packet: %s", strerror(errno));
2746        return TICK_CLOSE;
2747    }
2748
2749    assert(conn->fc_flags & (FC_ERROR|FC_ABORTED|FC_TIMED_OUT|FC_HSK_FAILED));
2750    if (conn->fc_flags & FC_ERROR)
2751    {
2752        error_code = 0x01; /* QUIC_INTERNAL_ERROR */
2753        error_reason = "connection error";
2754    }
2755    else if (conn->fc_flags & FC_ABORTED)
2756    {
2757        error_code = 0x10; /* QUIC_PEER_GOING_AWAY */
2758        error_reason = "user aborted connection";
2759    }
2760    else if (conn->fc_flags & FC_TIMED_OUT)
2761    {
2762        error_code = 0x19; /* QUIC_NETWORK_IDLE_TIMEOUT */
2763        error_reason = "connection timed out";
2764    }
2765    else if (conn->fc_flags & FC_HSK_FAILED)
2766    {
2767        error_code = 0x2A; /* QUIC_PROOF_INVALID */
2768        error_reason = "handshake failed";
2769    }
2770    else
2771    {
2772        error_code = 0x10; /* QUIC_PEER_GOING_AWAY */
2773        error_reason = NULL;
2774    }
2775
2776    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
2777    sz = conn->fc_conn.cn_pf->pf_gen_connect_close_frame(
2778                     packet_out->po_data + packet_out->po_data_sz,
2779                     lsquic_packet_out_avail(packet_out), error_code,
2780                     error_reason, error_reason ? strlen(error_reason) : 0);
2781    if (sz < 0) {
2782        LSQ_WARN("%s failed", __func__);
2783        return TICK_CLOSE;
2784    }
2785    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2786    packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
2787    LSQ_DEBUG("generated CONNECTION_CLOSE frame in its own packet");
2788    return TICK_SEND|TICK_CLOSE;
2789}
2790
2791
2792static int
2793write_is_possible (struct full_conn *conn)
2794{
2795    const lsquic_packet_out_t *packet_out;
2796
2797    packet_out = lsquic_send_ctl_last_scheduled(&conn->fc_send_ctl);
2798    return (packet_out && lsquic_packet_out_avail(packet_out) > 10)
2799        || lsquic_send_ctl_can_send(&conn->fc_send_ctl);
2800}
2801
2802
2803static int
2804should_generate_ack (const struct full_conn *conn)
2805{
2806    return (conn->fc_flags & FC_ACK_QUEUED)
2807        || lsquic_send_ctl_lost_ack(&conn->fc_send_ctl);
2808}
2809
2810
2811static int
2812full_conn_ci_can_write_ack (struct lsquic_conn *lconn)
2813{
2814    struct full_conn *conn = (struct full_conn *) lconn;
2815    return should_generate_ack(conn);
2816}
2817
2818
2819static enum tick_st
2820full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
2821{
2822    struct full_conn *conn = (struct full_conn *) lconn;
2823    int have_delayed_packets;
2824    unsigned n;
2825    int s;
2826    enum tick_st tick = 0;
2827
2828#define CLOSE_IF_NECESSARY() do {                                       \
2829    if (conn->fc_flags & FC_IMMEDIATE_CLOSE_FLAGS)                      \
2830    {                                                                   \
2831        tick |= immediate_close(conn);                         \
2832        goto close_end;                                                 \
2833    }                                                                   \
2834} while (0)
2835
2836#define RETURN_IF_OUT_OF_PACKETS() do {                                 \
2837    if (!lsquic_send_ctl_can_send(&conn->fc_send_ctl))                  \
2838    {                                                                   \
2839        if (0 == lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl))       \
2840        {                                                               \
2841            LSQ_DEBUG("used up packet allowance, quiet now (line %d)",  \
2842                __LINE__);                                              \
2843            tick |= TICK_QUIET;                                         \
2844        }                                                               \
2845        else                                                            \
2846        {                                                               \
2847            LSQ_DEBUG("used up packet allowance, sending now (line %d)",\
2848                __LINE__);                                              \
2849            tick |= TICK_SEND;                                          \
2850        }                                                               \
2851        goto end;                                                       \
2852    }                                                                   \
2853} while (0)
2854
2855#if LSQUIC_CONN_STATS
2856    ++conn->fc_stats.n_ticks;
2857#endif
2858
2859    if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG)
2860        && conn->fc_mem_logged_last + 1000000 <= now)
2861    {
2862        conn->fc_mem_logged_last = now;
2863        LSQ_DEBUG("memory used: %zd bytes", calc_mem_used(conn));
2864    }
2865
2866    if (conn->fc_flags & FC_HAVE_SAVED_ACK)
2867    {
2868        (void) /* If there is an error, we'll fail shortly */
2869            process_saved_ack(conn, 0);
2870        conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
2871    }
2872
2873    lsquic_send_ctl_tick(&conn->fc_send_ctl, now);
2874    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
2875    CLOSE_IF_NECESSARY();
2876
2877    lsquic_alarmset_ring_expired(&conn->fc_alset, now);
2878    CLOSE_IF_NECESSARY();
2879
2880    /* To make things simple, only stream 1 is active until the handshake
2881     * has been completed.  This will be adjusted in the future: the client
2882     * does not want to wait if it has the server information.
2883     */
2884    if (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
2885        process_streams_read_events(conn);
2886    else
2887        process_hsk_stream_read_events(conn);
2888    CLOSE_IF_NECESSARY();
2889
2890    if (lsquic_send_ctl_pacer_blocked(&conn->fc_send_ctl))
2891        goto skip_write;
2892
2893    if (conn->fc_flags & FC_FIRST_TICK)
2894    {
2895        conn->fc_flags &= ~FC_FIRST_TICK;
2896        have_delayed_packets = 0;
2897    }
2898    else
2899        /* If there are any scheduled packets at this point, it means that
2900         * they were not sent during previous tick; in other words, they
2901         * are delayed.  When there are delayed packets, the only packet
2902         * we sometimes add is a packet with an ACK frame, and we add it
2903         * to the *front* of the queue.
2904         */
2905        have_delayed_packets = lsquic_send_ctl_maybe_squeeze_sched(
2906                                                    &conn->fc_send_ctl);
2907
2908    if (should_generate_ack(conn))
2909    {
2910        if (have_delayed_packets)
2911            lsquic_send_ctl_reset_packnos(&conn->fc_send_ctl);
2912
2913        /* ACK frame generation fails with an error if it does not fit into
2914         * a single packet (it always should fit).
2915         */
2916        generate_ack_frame(conn);
2917        CLOSE_IF_NECESSARY();
2918
2919        /* Try to send STOP_WAITING frame at the same time we send an ACK
2920         * This follows reference implementation.
2921         */
2922        if (!(conn->fc_flags & FC_NSTP))
2923            conn->fc_flags |= FC_SEND_STOP_WAITING;
2924
2925        if (have_delayed_packets)
2926        {
2927            if (conn->fc_flags & FC_SEND_STOP_WAITING)
2928            {
2929                /* TODO: ensure that STOP_WAITING frame is in the same packet
2930                 * as the ACK frame in delayed packet mode.
2931                 */
2932                generate_stop_waiting_frame(conn);
2933                CLOSE_IF_NECESSARY();
2934            }
2935            lsquic_send_ctl_ack_to_front(&conn->fc_send_ctl);
2936        }
2937    }
2938
2939    if (have_delayed_packets)
2940    {
2941        /* The reason for not adding STOP_WAITING and other frames below
2942         * to the packet carrying ACK frame generated when there are delayed
2943         * packets is so that if the ACK packet itself is delayed, it can be
2944         * dropped and replaced by new ACK packet.  This way, we are never
2945         * more than 1 packet over CWND.
2946         */
2947        tick |= TICK_SEND;
2948        goto end;
2949    }
2950
2951    /* Try to fit any of the following three frames -- STOP_WAITING,
2952     * WINDOW_UPDATE, and GOAWAY -- before checking if we have run
2953     * out of packets.  If either of them does not fit, it will be
2954     * tried next time around.
2955     */
2956    if (conn->fc_flags & FC_SEND_STOP_WAITING)
2957    {
2958        generate_stop_waiting_frame(conn);
2959        CLOSE_IF_NECESSARY();
2960    }
2961
2962    if (lsquic_cfcw_fc_offsets_changed(&conn->fc_pub.cfcw) ||
2963                                (conn->fc_flags & FC_SEND_WUF))
2964    {
2965        conn->fc_flags |= FC_SEND_WUF;
2966        generate_wuf_conn(conn);
2967        CLOSE_IF_NECESSARY();
2968    }
2969
2970    if (conn->fc_flags & FC_SEND_GOAWAY)
2971    {
2972        generate_goaway_frame(conn);
2973        CLOSE_IF_NECESSARY();
2974    }
2975
2976    n = lsquic_send_ctl_reschedule_packets(&conn->fc_send_ctl);
2977    if (n > 0)
2978        CLOSE_IF_NECESSARY();
2979
2980    if (conn->fc_conn.cn_flags & LSCONN_SEND_BLOCKED)
2981    {
2982        if (generate_blocked_frame(conn, 0))
2983            conn->fc_conn.cn_flags &= ~LSCONN_SEND_BLOCKED;
2984        else
2985            RETURN_IF_OUT_OF_PACKETS();
2986    }
2987
2988    if (!STAILQ_EMPTY(&conn->fc_stream_ids_to_reset))
2989    {
2990        packetize_standalone_stream_resets(conn);
2991        CLOSE_IF_NECESSARY();
2992    }
2993
2994    if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
2995    {
2996        process_streams_ready_to_send(conn);
2997        CLOSE_IF_NECESSARY();
2998    }
2999
3000    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 0);
3001    if (!(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE) &&
3002        !conn->fc_conn.cn_esf->esf_is_zero_rtt_enabled(
3003                                                conn->fc_conn.cn_enc_session))
3004    {
3005        process_hsk_stream_write_events(conn);
3006        goto end_write;
3007    }
3008
3009    maybe_conn_flush_headers_stream(conn);
3010
3011    s = lsquic_send_ctl_schedule_buffered(&conn->fc_send_ctl, BPT_HIGHEST_PRIO);
3012    conn->fc_flags |= (s < 0) << FC_BIT_ERROR;
3013    if (!write_is_possible(conn))
3014        goto end_write;
3015
3016    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams))
3017    {
3018        process_streams_write_events(conn, 1);
3019        if (!write_is_possible(conn))
3020            goto end_write;
3021    }
3022
3023    s = lsquic_send_ctl_schedule_buffered(&conn->fc_send_ctl, BPT_OTHER_PRIO);
3024    conn->fc_flags |= (s < 0) << FC_BIT_ERROR;
3025    if (!write_is_possible(conn))
3026        goto end_write;
3027
3028    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams))
3029        process_streams_write_events(conn, 0);
3030
3031  end_write:
3032
3033  skip_write:
3034    RETURN_IF_OUT_OF_PACKETS();
3035
3036    if ((conn->fc_flags & FC_CLOSING) && conn_ok_to_close(conn))
3037    {
3038        LSQ_DEBUG("connection is OK to close");
3039        /* This is normal termination sequence.
3040         *
3041         * Generate CONNECTION_CLOSE frame if we are responding to one, have
3042         * packets scheduled to send, or silent close flag is not set.
3043         */
3044        conn->fc_flags |= FC_TICK_CLOSE;
3045        if ((conn->fc_flags & FC_RECV_CLOSE) ||
3046                0 != lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) ||
3047                                        !conn->fc_settings->es_silent_close)
3048        {
3049            generate_connection_close_packet(conn);
3050            tick |= TICK_SEND|TICK_CLOSE;
3051        }
3052        else
3053            tick |= TICK_CLOSE;
3054        goto end;
3055    }
3056
3057    if (0 == lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl))
3058    {
3059        if (conn->fc_flags & FC_SEND_PING)
3060        {
3061            conn->fc_flags &= ~FC_SEND_PING;
3062            generate_ping_frame(conn);
3063            CLOSE_IF_NECESSARY();
3064            assert(lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) != 0);
3065        }
3066        else
3067        {
3068            tick |= TICK_QUIET;
3069            goto end;
3070        }
3071    }
3072    else if (!(conn->fc_flags & FC_SERVER))
3073    {
3074        lsquic_alarmset_unset(&conn->fc_alset, AL_PING);
3075        lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
3076        conn->fc_flags &= ~FC_SEND_PING;   /* It may have rung */
3077    }
3078
3079    now = lsquic_time_now();
3080    lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
3081                                now + conn->fc_settings->es_idle_conn_to);
3082
3083    /* From the spec:
3084     *  " The PING frame should be used to keep a connection alive when
3085     *  " a stream is open.
3086     */
3087    if (0 == (conn->fc_flags & FC_SERVER) &&
3088                                        lsquic_hash_count(conn->fc_pub.all_streams) > 0)
3089        lsquic_alarmset_set(&conn->fc_alset, AL_PING, now + TIME_BETWEEN_PINGS);
3090
3091    tick |= TICK_SEND;
3092
3093  end:
3094    service_streams(conn);
3095    CLOSE_IF_NECESSARY();
3096
3097  close_end:
3098    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
3099    return tick;
3100}
3101
3102
3103static void
3104full_conn_ci_packet_in (lsquic_conn_t *lconn, lsquic_packet_in_t *packet_in)
3105{
3106    struct full_conn *conn = (struct full_conn *) lconn;
3107
3108#if LSQUIC_CONN_STATS
3109    conn->fc_stats.in.bytes += packet_in->pi_data_sz;
3110#endif
3111    lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
3112                packet_in->pi_received + conn->fc_settings->es_idle_conn_to);
3113    if (0 == (conn->fc_flags & FC_ERROR))
3114        if (0 != process_incoming_packet(conn, packet_in))
3115            conn->fc_flags |= FC_ERROR;
3116}
3117
3118
3119static lsquic_packet_out_t *
3120full_conn_ci_next_packet_to_send (lsquic_conn_t *lconn)
3121{
3122    struct full_conn *conn = (struct full_conn *) lconn;
3123    return lsquic_send_ctl_next_packet_to_send(&conn->fc_send_ctl);
3124}
3125
3126
3127static void
3128full_conn_ci_packet_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_out)
3129{
3130    struct full_conn *conn = (struct full_conn *) lconn;
3131    int s;
3132
3133    recent_packet_hist_new(conn, 1, packet_out->po_sent);
3134    recent_packet_hist_frames(conn, 1, packet_out->po_frame_types);
3135
3136    if (packet_out->po_frame_types & QFRAME_RETRANSMITTABLE_MASK)
3137    {
3138        conn->fc_n_cons_unretx = 0;
3139        lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
3140                    packet_out->po_sent + conn->fc_settings->es_idle_conn_to);
3141    }
3142    else
3143        ++conn->fc_n_cons_unretx;
3144    s = lsquic_send_ctl_sent_packet(&conn->fc_send_ctl, packet_out, 1);
3145    if (s != 0)
3146        ABORT_ERROR("sent packet failed: %s", strerror(errno));
3147#if LSQUIC_CONN_STATS
3148    ++conn->fc_stats.out.packets;
3149    conn->fc_stats.out.bytes += lsquic_packet_out_sent_sz(lconn, packet_out);
3150#endif
3151}
3152
3153
3154static void
3155full_conn_ci_packet_not_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_out)
3156{
3157    struct full_conn *conn = (struct full_conn *) lconn;
3158    lsquic_send_ctl_delayed_one(&conn->fc_send_ctl, packet_out);
3159}
3160
3161
3162static void
3163full_conn_ci_hsk_done (lsquic_conn_t *lconn, enum lsquic_hsk_status status)
3164{
3165    struct full_conn *conn = (struct full_conn *) lconn;
3166    lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
3167    switch (status)
3168    {
3169        case LSQ_HSK_FAIL:
3170            conn->fc_flags |= FC_HSK_FAILED;
3171            break;
3172        case LSQ_HSK_OK:
3173        case LSQ_HSK_0RTT_OK:
3174            if (0 == apply_peer_settings(conn))
3175            {
3176                if (conn->fc_flags & FC_HTTP)
3177                    maybe_send_settings(conn);
3178                lconn->cn_flags |= LSCONN_HANDSHAKE_DONE;
3179            }
3180            else
3181                conn->fc_flags |= FC_ERROR;
3182            break;
3183    }
3184    if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done)
3185        conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn,
3186                                                                        status);
3187}
3188
3189
3190void
3191lsquic_conn_abort (lsquic_conn_t *lconn)
3192{
3193    struct full_conn *conn = (struct full_conn *) lconn;
3194    LSQ_INFO("User aborted connection");
3195    conn->fc_flags |= FC_ABORTED;
3196}
3197
3198
3199void
3200lsquic_conn_close (lsquic_conn_t *lconn)
3201{
3202    struct full_conn *conn = (struct full_conn *) lconn;
3203    lsquic_stream_t *stream;
3204    struct lsquic_hash_elem *el;
3205
3206    if (!(conn->fc_flags & FC_CLOSING))
3207    {
3208        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
3209                                     el = lsquic_hash_next(conn->fc_pub.all_streams))
3210        {
3211            stream = lsquic_hashelem_getdata(el);
3212            lsquic_stream_shutdown_internal(stream);
3213        }
3214        conn->fc_flags |= FC_CLOSING;
3215        if (!(conn->fc_flags & FC_GOAWAY_SENT))
3216            conn->fc_flags |= FC_SEND_GOAWAY;
3217    }
3218}
3219
3220
3221void
3222lsquic_conn_going_away (lsquic_conn_t *lconn)
3223{
3224    struct full_conn *conn = (struct full_conn *) lconn;
3225    if (!(conn->fc_flags & (FC_CLOSING|FC_GOING_AWAY)))
3226    {
3227        LSQ_INFO("connection marked as going away");
3228        assert(!(conn->fc_flags & FC_SEND_GOAWAY));
3229        conn->fc_flags |= FC_GOING_AWAY;
3230        if (!(conn->fc_flags & FC_GOAWAY_SENT))
3231            conn->fc_flags |= FC_SEND_GOAWAY;
3232    }
3233}
3234
3235
3236/* Find stream when stream ID is read from something other than a STREAM
3237 * frame.  If the stream cannot be found or created, the connection is
3238 * aborted.
3239 */
3240#if __GNUC__
3241__attribute__((nonnull(4)))
3242#endif
3243static lsquic_stream_t *
3244find_stream_on_non_stream_frame (struct full_conn *conn, uint32_t stream_id,
3245                                 enum stream_ctor_flags stream_ctor_flags,
3246                                 const char *what)
3247{
3248    lsquic_stream_t *stream;
3249    unsigned in_count;
3250
3251    stream = find_stream_by_id(conn, stream_id);
3252    if (stream)
3253        return stream;
3254
3255    if (conn_is_stream_closed(conn, stream_id))
3256    {
3257        LSQ_DEBUG("drop incoming %s for closed stream %u", what, stream_id);
3258        return NULL;
3259    }
3260
3261    /* XXX It seems that if we receive a priority frame for a stream, the
3262     *     stream should exist or have existed at some point.  Thus, if
3263     *     it does not exist, we should return an error here.
3264     */
3265
3266    if (!is_peer_initiated(conn, stream_id))
3267    {
3268        ABORT_ERROR("frame for never-initiated stream (push promise?)");
3269        return NULL;
3270    }
3271
3272    in_count = count_streams(conn, 1);
3273    LSQ_DEBUG("number of peer-initiated streams: %u", in_count);
3274    if (in_count >= conn->fc_cfg.max_streams_in)
3275    {
3276        if (!(conn->fc_flags & FC_ABORT_COMPLAINED))
3277        {
3278            unsigned counts[N_SCNTS];
3279            collect_stream_counts(conn, 1, counts);
3280            ABORT_WARN("incoming %s for stream %u would exceed "
3281                "limit: %u.  all: %u; peer: %u; closed: %u; reset: %u; reset "
3282                "and not closed: %u",
3283                what, stream_id, conn->fc_cfg.max_streams_in, counts[SCNT_ALL],
3284                counts[SCNT_PEER], counts[SCNT_CLOSED], counts[SCNT_RESET],
3285                counts[SCNT_RES_UNCLO]);
3286        }
3287        return NULL;
3288    }
3289    if ((conn->fc_flags & FC_GOING_AWAY) &&
3290        stream_id > conn->fc_max_peer_stream_id)
3291    {
3292        maybe_schedule_reset_for_stream(conn, stream_id);
3293        LSQ_DEBUG("going away: reset new incoming stream %u", stream_id);
3294        return NULL;
3295    }
3296
3297    stream = new_stream(conn, stream_id, stream_ctor_flags);
3298    if (!stream)
3299    {
3300        ABORT_ERROR("cannot create new stream: %s", strerror(errno));
3301        return NULL;
3302    }
3303    if (stream_id > conn->fc_max_peer_stream_id)
3304        conn->fc_max_peer_stream_id = stream_id;
3305
3306    return stream;
3307}
3308
3309
3310static void
3311headers_stream_on_conn_error (void *ctx)
3312{
3313    struct full_conn *conn = ctx;
3314    ABORT_ERROR("connection error reported by HEADERS stream");
3315}
3316
3317
3318static void
3319headers_stream_on_stream_error (void *ctx, uint32_t stream_id)
3320{
3321    struct full_conn *conn = ctx;
3322    lsquic_stream_t *stream;
3323
3324    stream = find_stream_on_non_stream_frame(conn, stream_id, SCF_CALL_ON_NEW,
3325                                             "error");
3326    if (stream)
3327    {
3328        LSQ_DEBUG("resetting stream %u due to error", stream_id);
3329        /* We use code 1, which is QUIC_INTERNAL_ERROR (see
3330         * [draft-hamilton-quic-transport-protocol-01], Section 10), for all
3331         * errors.  There does not seem to be a good reason to figure out
3332         * and send more specific error codes.
3333         */
3334        lsquic_stream_reset_ext(stream, 1, 0);
3335    }
3336}
3337
3338
3339static void
3340headers_stream_on_enable_push (void *ctx, int enable_push)
3341{
3342    struct full_conn *conn = ctx;
3343    if (0 == enable_push)
3344    {
3345        LSQ_DEBUG("server push %d -> 0", !!(conn->fc_flags & FC_SUPPORT_PUSH));
3346        conn->fc_flags &= ~FC_SUPPORT_PUSH;
3347    }
3348    else if (conn->fc_settings->es_support_push)
3349    {
3350        LSQ_DEBUG("server push %d -> 1", !!(conn->fc_flags & FC_SUPPORT_PUSH));
3351        conn->fc_flags |= FC_SUPPORT_PUSH;
3352    }
3353    else
3354        LSQ_INFO("not enabling server push that's disabled in engine settings");
3355}
3356
3357
3358static void
3359headers_stream_on_incoming_headers (void *ctx, struct uncompressed_headers *uh)
3360{
3361    struct full_conn *conn = ctx;
3362    lsquic_stream_t *stream;
3363
3364    LSQ_DEBUG("incoming headers for stream %u", uh->uh_stream_id);
3365
3366    stream = find_stream_on_non_stream_frame(conn, uh->uh_stream_id, 0,
3367                                             "headers");
3368    if (!stream)
3369        goto free_uh;
3370
3371    if (lsquic_stream_is_reset(stream))
3372    {
3373        LSQ_DEBUG("stream is reset: ignore headers");
3374        goto free_uh;
3375    }
3376
3377    if (0 != lsquic_stream_uh_in(stream, uh))
3378    {
3379        ABORT_ERROR("stream %u refused incoming headers", uh->uh_stream_id);
3380        goto free_uh;
3381    }
3382
3383    if (!(stream->stream_flags & STREAM_ONNEW_DONE))
3384        lsquic_stream_call_on_new(stream);
3385
3386    return;
3387
3388  free_uh:
3389    if (uh->uh_hset)
3390        conn->fc_enpub->enp_hsi_if->hsi_discard_header_set(uh->uh_hset);
3391    free(uh);
3392}
3393
3394
3395static void
3396headers_stream_on_push_promise (void *ctx, struct uncompressed_headers *uh)
3397{
3398    struct full_conn *conn = ctx;
3399    lsquic_stream_t *stream;
3400
3401    assert(!(conn->fc_flags & FC_SERVER));
3402
3403    LSQ_DEBUG("push promise for stream %u in response to %u",
3404                                    uh->uh_oth_stream_id, uh->uh_stream_id);
3405
3406    if (0 == (uh->uh_stream_id & 1)     ||
3407        0 != (uh->uh_oth_stream_id & 1))
3408    {
3409        ABORT_ERROR("invalid push promise stream IDs: %u, %u",
3410                                    uh->uh_oth_stream_id, uh->uh_stream_id);
3411        goto free_uh;
3412    }
3413
3414    if (!(conn_is_stream_closed(conn, uh->uh_stream_id) ||
3415          find_stream_by_id(conn, uh->uh_stream_id)))
3416    {
3417        ABORT_ERROR("invalid push promise original stream ID %u never "
3418                    "initiated", uh->uh_stream_id);
3419        goto free_uh;
3420    }
3421
3422    if (conn_is_stream_closed(conn, uh->uh_oth_stream_id) ||
3423        find_stream_by_id(conn, uh->uh_oth_stream_id))
3424    {
3425        ABORT_ERROR("invalid promised stream ID %u already used",
3426                                                        uh->uh_oth_stream_id);
3427        goto free_uh;
3428    }
3429
3430    stream = new_stream_ext(conn, uh->uh_oth_stream_id, STREAM_IF_STD,
3431                SCF_DI_AUTOSWITCH|(conn->fc_enpub->enp_settings.es_rw_once ?
3432                                                        SCF_DISP_RW_ONCE : 0));
3433    if (!stream)
3434    {
3435        ABORT_ERROR("cannot create stream: %s", strerror(errno));
3436        goto free_uh;
3437    }
3438    lsquic_stream_push_req(stream, uh);
3439    lsquic_stream_call_on_new(stream);
3440    return;
3441
3442  free_uh:
3443    if (uh->uh_hset)
3444        conn->fc_enpub->enp_hsi_if->hsi_discard_header_set(uh->uh_hset);
3445    free(uh);
3446}
3447
3448
3449static void
3450headers_stream_on_priority (void *ctx, uint32_t stream_id, int exclusive,
3451                            uint32_t dep_stream_id, unsigned weight)
3452{
3453    struct full_conn *conn = ctx;
3454    lsquic_stream_t *stream;
3455    LSQ_DEBUG("got priority frame for stream %u: (ex: %d; dep stream: %u; "
3456                  "weight: %u)", stream_id, exclusive, dep_stream_id, weight);
3457    stream = find_stream_on_non_stream_frame(conn, stream_id, SCF_CALL_ON_NEW,
3458                                             "priority");
3459    if (stream)
3460        lsquic_stream_set_priority_internal(stream, weight);
3461}
3462
3463
3464int lsquic_conn_is_push_enabled(lsquic_conn_t *c)
3465{
3466    return ((struct full_conn *)c)->fc_flags & FC_SUPPORT_PUSH;
3467}
3468
3469
3470lsquic_conn_ctx_t *
3471lsquic_conn_get_ctx (const lsquic_conn_t *lconn)
3472{
3473    struct full_conn *const conn = (struct full_conn *) lconn;
3474    return conn->fc_conn_ctx;
3475}
3476
3477
3478void lsquic_conn_set_ctx (lsquic_conn_t *lconn, lsquic_conn_ctx_t *ctx)
3479{
3480    struct full_conn *const conn = (struct full_conn *) lconn;
3481    conn->fc_conn_ctx = ctx;
3482}
3483
3484
3485enum LSQUIC_CONN_STATUS
3486lsquic_conn_status (lsquic_conn_t *lconn, char *errbuf, size_t bufsz)
3487{
3488    struct full_conn *const conn = (struct full_conn *) lconn;
3489    size_t n;
3490
3491    /* Test the common case first: */
3492    if (!(conn->fc_flags & (FC_ERROR
3493                           |FC_TIMED_OUT
3494                           |FC_ABORTED
3495                           |FC_GOT_PRST
3496                           |FC_HSK_FAILED
3497                           |FC_CLOSING
3498                           |FC_GOING_AWAY)))
3499    {
3500        if (lconn->cn_flags & LSCONN_PEER_GOING_AWAY)
3501            return LSCONN_ST_PEER_GOING_AWAY;
3502        else if (lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
3503            return LSCONN_ST_CONNECTED;
3504        else
3505            return LSCONN_ST_HSK_IN_PROGRESS;
3506    }
3507
3508    if (errbuf && bufsz)
3509    {
3510        if (conn->fc_errmsg)
3511        {
3512            n = bufsz < MAX_ERRMSG ? bufsz : MAX_ERRMSG;
3513            strncpy(errbuf, conn->fc_errmsg, n);
3514            errbuf[n - 1] = '\0';
3515        }
3516        else
3517            errbuf[0] = '\0';
3518    }
3519
3520    if (conn->fc_flags & FC_ERROR)
3521        return LSCONN_ST_ERROR;
3522    if (conn->fc_flags & FC_TIMED_OUT)
3523        return LSCONN_ST_TIMED_OUT;
3524    if (conn->fc_flags & FC_ABORTED)
3525        return LSCONN_ST_USER_ABORTED;
3526    if (conn->fc_flags & FC_GOT_PRST)
3527        return LSCONN_ST_RESET;
3528    if (conn->fc_flags & FC_HSK_FAILED)
3529        return LSCONN_ST_HSK_FAILURE;
3530    if (conn->fc_flags & FC_CLOSING)
3531        return LSCONN_ST_CLOSED;
3532    assert(conn->fc_flags & FC_GOING_AWAY);
3533    return LSCONN_ST_GOING_AWAY;
3534}
3535
3536
3537static int
3538full_conn_ci_is_tickable (lsquic_conn_t *lconn)
3539{
3540    struct full_conn *conn = (struct full_conn *) lconn;
3541    const struct lsquic_stream *stream;
3542
3543    if (!TAILQ_EMPTY(&conn->fc_pub.service_streams))
3544        return 1;
3545
3546    if ((conn->fc_enpub->enp_flags & ENPUB_CAN_SEND)
3547        && lsquic_send_ctl_can_send(&conn->fc_send_ctl)
3548        && (should_generate_ack(conn) ||
3549            !lsquic_send_ctl_sched_is_blocked(&conn->fc_send_ctl)))
3550    {
3551        if (conn->fc_flags & (FC_SEND_GOAWAY|FC_SEND_STOP_WAITING
3552                             |FC_SEND_PING|FC_SEND_WUF))
3553            return 1;
3554        if (lsquic_send_ctl_has_buffered(&conn->fc_send_ctl))
3555            return 1;
3556        if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
3557            return 1;
3558        if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE) ||
3559            conn->fc_conn.cn_esf->esf_is_zero_rtt_enabled(
3560                                                conn->fc_conn.cn_enc_session))
3561        {
3562            TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
3563                                                        next_write_stream)
3564                if (lsquic_stream_write_avail(stream))
3565                    return 1;
3566        }
3567        else
3568        {
3569            TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
3570                                                        next_write_stream)
3571                if (LSQUIC_STREAM_HANDSHAKE == stream->id
3572                                    && lsquic_stream_write_avail(stream))
3573                    return 1;
3574        }
3575    }
3576
3577    TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
3578        if (lsquic_stream_readable(stream))
3579            return 1;
3580
3581    return 0;
3582}
3583
3584
3585static lsquic_time_t
3586full_conn_ci_next_tick_time (lsquic_conn_t *lconn)
3587{
3588    struct full_conn *conn = (struct full_conn *) lconn;
3589    lsquic_time_t alarm_time, pacer_time;
3590
3591    alarm_time = lsquic_alarmset_mintime(&conn->fc_alset);
3592    pacer_time = lsquic_send_ctl_next_pacer_time(&conn->fc_send_ctl);
3593
3594    if (alarm_time && pacer_time)
3595    {
3596        if (alarm_time < pacer_time)
3597            return alarm_time;
3598        else
3599            return pacer_time;
3600    }
3601    else if (alarm_time)
3602        return alarm_time;
3603    else
3604        return pacer_time;
3605}
3606
3607
3608#if LSQUIC_CONN_STATS
3609static const struct conn_stats *
3610full_conn_ci_get_stats (struct lsquic_conn *lconn)
3611{
3612    struct full_conn *conn = (struct full_conn *) lconn;
3613    return &conn->fc_stats;
3614}
3615
3616
3617#endif
3618
3619
3620static const struct headers_stream_callbacks headers_callbacks =
3621{
3622    .hsc_on_headers      = headers_stream_on_incoming_headers,
3623    .hsc_on_push_promise = headers_stream_on_push_promise,
3624    .hsc_on_priority     = headers_stream_on_priority,
3625    .hsc_on_stream_error = headers_stream_on_stream_error,
3626    .hsc_on_conn_error   = headers_stream_on_conn_error,
3627    .hsc_on_enable_push  = headers_stream_on_enable_push,
3628};
3629
3630static const struct headers_stream_callbacks *headers_callbacks_ptr = &headers_callbacks;
3631
3632static const struct conn_iface full_conn_iface = {
3633    .ci_can_write_ack        =  full_conn_ci_can_write_ack,
3634    .ci_destroy              =  full_conn_ci_destroy,
3635#if LSQUIC_CONN_STATS
3636    .ci_get_stats            =  full_conn_ci_get_stats,
3637#endif
3638    .ci_hsk_done             =  full_conn_ci_hsk_done,
3639    .ci_is_tickable          =  full_conn_ci_is_tickable,
3640    .ci_next_packet_to_send  =  full_conn_ci_next_packet_to_send,
3641    .ci_next_tick_time       =  full_conn_ci_next_tick_time,
3642    .ci_packet_in            =  full_conn_ci_packet_in,
3643    .ci_packet_not_sent      =  full_conn_ci_packet_not_sent,
3644    .ci_packet_sent          =  full_conn_ci_packet_sent,
3645    .ci_tick                 =  full_conn_ci_tick,
3646    .ci_write_ack            =  full_conn_ci_write_ack,
3647};
3648
3649static const struct conn_iface *full_conn_iface_ptr = &full_conn_iface;
3650