lsquic_full_conn.c revision b62ec17f
1/* Copyright (c) 2017 - 2020 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_sizes.h"
23#include "lsquic.h"
24#include "lsquic_packet_common.h"
25#include "lsquic_alarmset.h"
26#include "lsquic_packet_gquic.h"
27#include "lsquic_parse.h"
28#include "lsquic_packet_in.h"
29#include "lsquic_packet_out.h"
30#include "lsquic_rechist.h"
31#include "lsquic_util.h"
32#include "lsquic_conn_flow.h"
33#include "lsquic_sfcw.h"
34#include "lsquic_varint.h"
35#include "lsquic_hq.h"
36#include "lsquic_hash.h"
37#include "lsquic_stream.h"
38#include "lsquic_senhist.h"
39#include "lsquic_rtt.h"
40#include "lsquic_cubic.h"
41#include "lsquic_pacer.h"
42#include "lsquic_bw_sampler.h"
43#include "lsquic_minmax.h"
44#include "lsquic_bbr.h"
45#include "lsquic_adaptive_cc.h"
46#include "lsquic_set.h"
47#include "lsquic_malo.h"
48#include "lsquic_chsk_stream.h"
49#include "lsquic_shsk_stream.h"
50#include "lshpack.h"
51#include "lsquic_str.h"
52#include "lsquic_qtags.h"
53#include "lsquic_enc_sess.h"
54#include "lsquic_headers_stream.h"
55#include "lsquic_frame_common.h"
56#include "lsquic_frame_reader.h"
57#include "lsquic_frame_writer.h"
58#include "lsquic_http1x_if.h"
59#include "lsquic_mm.h"
60#include "lsquic_engine_public.h"
61#include "lsquic_spi.h"
62#include "lsquic_ev_log.h"
63#include "lsquic_version.h"
64#include "lsquic_headers.h"
65#include "lsquic_handshake.h"
66#include "lsquic_attq.h"
67
68#include "lsquic_conn.h"
69#include "lsquic_send_ctl.h"
70#include "lsquic_conn_public.h"
71#include "lsquic_ver_neg.h"
72#include "lsquic_mini_conn.h"
73#include "lsquic_full_conn.h"
74
75#define LSQUIC_LOGGER_MODULE LSQLM_CONN
76#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(&conn->fc_conn)
77#include "lsquic_logger.h"
78
79enum stream_if { STREAM_IF_STD, STREAM_IF_HSK, STREAM_IF_HDR, N_STREAM_IFS };
80
81#define MAX_RETR_PACKETS_SINCE_LAST_ACK 2
82#define ACK_TIMEOUT                     25000
83
84/* IMPORTANT: Keep values of FC_SERVER and FC_HTTP same as LSENG_SERVER
85 * and LSENG_HTTP.
86 */
87enum full_conn_flags {
88    FC_SERVER         = LSENG_SERVER,   /* Server mode */
89    FC_HTTP           = LSENG_HTTP,     /* HTTP mode */
90    FC_TIMED_OUT      = (1 << 2),
91#define FC_BIT_ERROR 3
92    FC_ERROR          = (1 << FC_BIT_ERROR),
93    FC_ABORTED        = (1 << 4),
94    FC_CLOSING        = (1 << 5),   /* Closing */
95    FC_SEND_PING      = (1 << 6),   /* PING frame scheduled */
96    FC_NSTP           = (1 << 7),   /* NSTP mode */
97    FC_SEND_GOAWAY    = (1 << 8),
98    FC_SEND_WUF       = (1 << 9),
99    FC_SEND_STOP_WAITING
100                      = (1 <<10),
101    FC_ACK_QUEUED     = (1 <<11),
102    FC_ACK_HAD_MISS   = (1 <<12),   /* Last ACK frame had missing packets. */
103    FC_CREATED_OK     = (1 <<13),
104    FC_RECV_CLOSE     = (1 <<14),   /* Received CONNECTION_CLOSE frame */
105    FC_GOING_AWAY     = (1 <<15),   /* Do not accept or create new streams */
106    FC_GOAWAY_SENT    = (1 <<16),   /* Only send GOAWAY once */
107    FC_SUPPORT_PUSH   = (1 <<17),
108    FC_GOT_PRST       = (1 <<18),   /* Received public reset packet */
109    FC_FIRST_TICK     = (1 <<19),
110    FC_TICK_CLOSE     = (1 <<20),   /* We returned TICK_CLOSE */
111    FC_HSK_FAILED     = (1 <<21),
112    FC_HAVE_SAVED_ACK = (1 <<22),
113    FC_ABORT_COMPLAINED
114                      = (1 <<23),
115    FC_GOT_SREJ       = (1 <<24),   /* Don't schedule ACK alarm */
116    FC_NOPROG_TIMEOUT = (1 <<25),
117};
118
119#define FC_IMMEDIATE_CLOSE_FLAGS \
120            (FC_TIMED_OUT|FC_ERROR|FC_ABORTED|FC_HSK_FAILED)
121
122#if LSQUIC_KEEP_STREAM_HISTORY
123#define KEEP_CLOSED_STREAM_HISTORY 0
124#endif
125
126#if KEEP_CLOSED_STREAM_HISTORY
127struct stream_history
128{
129    lsquic_stream_id_t  shist_stream_id;
130    enum stream_flags   shist_stream_flags;
131    unsigned char       shist_hist_buf[1 << SM_HIST_BITS];
132};
133#define SHIST_BITS 5
134#define SHIST_MASK ((1 << SHIST_BITS) - 1)
135#endif
136
137#ifndef KEEP_PACKET_HISTORY
138#ifdef NDEBUG
139#define KEEP_PACKET_HISTORY 0
140#else
141#define KEEP_PACKET_HISTORY 16
142#endif
143#endif
144
145#if KEEP_PACKET_HISTORY
146struct packet_el
147{
148    lsquic_time_t       time;
149    enum quic_ft_bit    frame_types;
150};
151
152struct recent_packets
153{
154    struct packet_el    els[KEEP_PACKET_HISTORY];
155    unsigned            idx;
156};
157#endif
158
159struct stream_id_to_reset
160{
161    STAILQ_ENTRY(stream_id_to_reset)    sitr_next;
162    lsquic_stream_id_t                  sitr_stream_id;
163};
164
165
166struct full_conn
167{
168    struct lsquic_conn           fc_conn;
169    struct conn_cid_elem         fc_cces[2];
170    struct lsquic_rechist        fc_rechist;
171    struct {
172        const struct lsquic_stream_if   *stream_if;
173        void                            *stream_if_ctx;
174    }                            fc_stream_ifs[N_STREAM_IFS];
175    lsquic_conn_ctx_t           *fc_conn_ctx;
176    struct lsquic_send_ctl       fc_send_ctl;
177    struct lsquic_conn_public    fc_pub;
178    lsquic_alarmset_t            fc_alset;
179    lsquic_set64_t               fc_closed_stream_ids[2];
180    const struct lsquic_engine_settings
181                                *fc_settings;
182    struct lsquic_engine_public *fc_enpub;
183    lsquic_packno_t              fc_max_ack_packno;
184    lsquic_packno_t              fc_max_swf_packno;
185    lsquic_time_t                fc_mem_logged_last;
186    struct {
187        unsigned    max_streams_in;
188        unsigned    max_streams_out;
189        unsigned    max_conn_send;
190        unsigned    max_stream_send;
191    }                            fc_cfg;
192    enum full_conn_flags         fc_flags;
193    /* Number ackable packets received since last ACK was sent: */
194    unsigned                     fc_n_slack_akbl;
195    unsigned                     fc_n_delayed_streams;
196    unsigned                     fc_n_cons_unretx;
197    lsquic_stream_id_t           fc_last_stream_id;
198    lsquic_stream_id_t           fc_max_peer_stream_id;
199    lsquic_stream_id_t           fc_goaway_stream_id;
200    struct ver_neg               fc_ver_neg;
201    union {
202        struct client_hsk_ctx    client;
203        struct server_hsk_ctx    server;
204    }                            fc_hsk_ctx;
205#if LSQUIC_CONN_STATS
206    struct conn_stats            fc_stats;
207#endif
208#if KEEP_CLOSED_STREAM_HISTORY
209    /* Rolling log of histories of closed streams.  Older entries are
210     * overwritten.
211     */
212    struct stream_history        fc_stream_histories[1 << SHIST_BITS];
213    unsigned                     fc_stream_hist_idx;
214#endif
215    char                        *fc_errmsg;
216#if KEEP_PACKET_HISTORY
217    struct recent_packets        fc_recent_packets[2];  /* 0: in; 1: out */
218#endif
219    STAILQ_HEAD(, stream_id_to_reset)
220                                 fc_stream_ids_to_reset;
221    lsquic_time_t                fc_saved_ack_received;
222    struct network_path          fc_path;
223    unsigned                     fc_orig_versions;      /* Client only */
224    enum enc_level               fc_crypto_enc_level;
225    struct ack_info              fc_ack;
226};
227
228static const struct ver_neg server_ver_neg;
229
230
231#define MAX_ERRMSG 256
232
233#define SET_ERRMSG(conn, ...) do {                                          \
234    if (!(conn)->fc_errmsg)                                                 \
235        (conn)->fc_errmsg = malloc(MAX_ERRMSG);                             \
236    if ((conn)->fc_errmsg)                                                  \
237        snprintf((conn)->fc_errmsg, MAX_ERRMSG, __VA_ARGS__);               \
238} while (0)
239
240#define ABORT_WITH_FLAG(conn, log_level, flag, ...) do {                    \
241    SET_ERRMSG(conn, __VA_ARGS__);                                          \
242    if (!((conn)->fc_flags & FC_ABORT_COMPLAINED))                          \
243        LSQ_LOG(log_level, "Abort connection: " __VA_ARGS__);               \
244    (conn)->fc_flags |= flag|FC_ABORT_COMPLAINED;                           \
245} while (0)
246
247#define ABORT_ERROR(...) \
248    ABORT_WITH_FLAG(conn, LSQ_LOG_ERROR, FC_ERROR, __VA_ARGS__)
249#define ABORT_WARN(...) \
250    ABORT_WITH_FLAG(conn, LSQ_LOG_WARN, FC_ERROR, __VA_ARGS__)
251
252static void
253idle_alarm_expired (enum alarm_id, void *ctx, lsquic_time_t expiry, lsquic_time_t now);
254
255static void
256ping_alarm_expired (enum alarm_id, void *ctx, lsquic_time_t expiry, lsquic_time_t now);
257
258static void
259handshake_alarm_expired (enum alarm_id, void *ctx, lsquic_time_t expiry, lsquic_time_t now);
260
261static void
262ack_alarm_expired (enum alarm_id, void *ctx, lsquic_time_t expiry, lsquic_time_t now);
263
264static lsquic_stream_t *
265new_stream (struct full_conn *conn, lsquic_stream_id_t stream_id,
266            enum stream_ctor_flags);
267
268static struct lsquic_stream *
269new_stream_ext (struct full_conn *, lsquic_stream_id_t, enum stream_if,
270                                                    enum stream_ctor_flags);
271
272static void
273reset_ack_state (struct full_conn *conn);
274
275static int
276write_is_possible (struct full_conn *);
277
278static const struct headers_stream_callbacks *headers_callbacks_ptr;
279
280#if KEEP_CLOSED_STREAM_HISTORY
281
282static void
283save_stream_history (struct full_conn *conn, const lsquic_stream_t *stream)
284{
285    sm_hist_idx_t idx;
286    struct stream_history *const shist =
287        &conn->fc_stream_histories[ conn->fc_stream_hist_idx++ & SHIST_MASK ];
288
289    shist->shist_stream_id    = stream->id;
290    shist->shist_stream_flags = stream->stream_flags;
291
292    idx = stream->sm_hist_idx & SM_HIST_IDX_MASK;
293    if ('\0' == stream->sm_hist_buf[ idx ])
294        memcpy(shist->shist_hist_buf, stream->sm_hist_buf, idx + 1);
295    else
296    {
297        memcpy(shist->shist_hist_buf,
298            stream->sm_hist_buf + idx, sizeof(stream->sm_hist_buf) - idx);
299        memcpy(shist->shist_hist_buf + sizeof(shist->shist_hist_buf) - idx,
300            stream->sm_hist_buf, idx);
301    }
302}
303
304
305static const struct stream_history *
306find_stream_history (const struct full_conn *conn, lsquic_stream_id_t stream_id)
307{
308    const struct stream_history *shist;
309    const struct stream_history *const shist_end =
310                        conn->fc_stream_histories + (1 << SHIST_BITS);
311    for (shist = conn->fc_stream_histories; shist < shist_end; ++shist)
312        if (shist->shist_stream_id == stream_id)
313            return shist;
314    return NULL;
315}
316
317
318#   define SAVE_STREAM_HISTORY(conn, stream) save_stream_history(conn, stream)
319#else
320#   define SAVE_STREAM_HISTORY(conn, stream)
321#endif
322
323#if KEEP_PACKET_HISTORY
324static void
325recent_packet_hist_new (struct full_conn *conn, unsigned out,
326                                                    lsquic_time_t time)
327{
328    unsigned idx;
329    idx = conn->fc_recent_packets[out].idx++ % KEEP_PACKET_HISTORY;
330    conn->fc_recent_packets[out].els[idx].time = time;
331}
332
333static void
334recent_packet_hist_frames (struct full_conn *conn, unsigned out,
335                                                enum quic_ft_bit frame_types)
336{
337    unsigned idx;
338    idx = (conn->fc_recent_packets[out].idx - 1) % KEEP_PACKET_HISTORY;
339    conn->fc_recent_packets[out].els[idx].frame_types |= frame_types;
340}
341#else
342#define recent_packet_hist_new(conn, out, time)
343#define recent_packet_hist_frames(conn, out, frames)
344#endif
345
346static unsigned
347highest_bit_set (unsigned sz)
348{
349#if __GNUC__
350    unsigned clz = __builtin_clz(sz);
351    return 31 - clz;
352#else
353    unsigned n, y;
354    n = 32;
355    y = sz >> 16;   if (y) { n -= 16; sz = y; }
356    y = sz >>  8;   if (y) { n -=  8; sz = y; }
357    y = sz >>  4;   if (y) { n -=  4; sz = y; }
358    y = sz >>  2;   if (y) { n -=  2; sz = y; }
359    y = sz >>  1;   if (y) return 31 - n + 2;
360    return 31 - n + sz;
361#endif
362}
363
364
365static size_t
366calc_mem_used (const struct full_conn *conn)
367{
368    const lsquic_stream_t *stream;
369    const struct lsquic_hash_elem *el;
370    size_t size;
371
372    size = sizeof(*conn);
373    size -= sizeof(conn->fc_send_ctl);
374    size += lsquic_send_ctl_mem_used(&conn->fc_send_ctl);
375    size += lsquic_hash_mem_used(conn->fc_pub.all_streams);
376    size += lsquic_malo_mem_used(conn->fc_pub.packet_out_malo);
377    if (conn->fc_pub.u.gquic.hs)
378        size += lsquic_headers_stream_mem_used(conn->fc_pub.u.gquic.hs);
379
380    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
381                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
382    {
383        stream = lsquic_hashelem_getdata(el);
384        size += lsquic_stream_mem_used(stream);
385    }
386    size += conn->fc_conn.cn_esf.g->esf_mem_used(conn->fc_conn.cn_enc_session);
387
388    return size;
389}
390
391
392static void
393set_versions (struct full_conn *conn, unsigned versions,
394                                                    enum lsquic_version *ver)
395{
396    conn->fc_ver_neg.vn_supp = versions;
397    conn->fc_ver_neg.vn_ver  = (ver) ? *ver : highest_bit_set(versions);
398    conn->fc_ver_neg.vn_buf  = lsquic_ver2tag(conn->fc_ver_neg.vn_ver);
399    conn->fc_conn.cn_version = conn->fc_ver_neg.vn_ver;
400    conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
401    LSQ_DEBUG("negotiating version %s",
402                            lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
403}
404
405
406static void
407init_ver_neg (struct full_conn *conn, unsigned versions,
408                                                    enum lsquic_version *ver)
409{
410    set_versions(conn, versions, ver);
411    conn->fc_ver_neg.vn_tag   = &conn->fc_ver_neg.vn_buf;
412    conn->fc_ver_neg.vn_state = VN_START;
413}
414
415
416/* If peer supplies odd values, we abort the connection immediately rather
417 * that wait for it to finish "naturally" due to inability to send things.
418 */
419#ifdef NDEBUG
420static
421#endif
422void
423lsquic_full_conn_on_peer_config (struct full_conn *conn, unsigned peer_cfcw,
424                     unsigned peer_sfcw, unsigned max_streams_out)
425{
426    lsquic_stream_t *stream;
427    struct lsquic_hash_elem *el;
428
429    LSQ_INFO("Applying peer config: cfcw: %u; sfcw: %u; # streams: %u",
430        peer_cfcw, peer_sfcw, max_streams_out);
431
432    if (peer_cfcw < conn->fc_pub.conn_cap.cc_sent)
433    {
434        ABORT_ERROR("peer specified CFCW=%u bytes, which is smaller than "
435            "the amount of data already sent on this connection (%"PRIu64
436            " bytes)", peer_cfcw, conn->fc_pub.conn_cap.cc_sent);
437        return;
438    }
439
440    conn->fc_cfg.max_streams_out = max_streams_out;
441    conn->fc_pub.conn_cap.cc_max = peer_cfcw;
442
443    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
444                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
445    {
446        stream = lsquic_hashelem_getdata(el);
447        if (0 != lsquic_stream_set_max_send_off(stream, peer_sfcw))
448        {
449            ABORT_ERROR("cannot set peer-supplied SFCW=%u on stream %"PRIu64,
450                peer_sfcw, stream->id);
451            return;
452        }
453    }
454
455    conn->fc_cfg.max_stream_send = peer_sfcw;
456}
457
458
459static int
460send_smhl (const struct full_conn *conn)
461{
462    uint32_t smhl;
463    return conn->fc_conn.cn_enc_session
464        && 0 == conn->fc_conn.cn_esf.g->esf_get_peer_setting(
465                            conn->fc_conn.cn_enc_session, QTAG_SMHL, &smhl)
466        && 1 == smhl;
467}
468
469
470/* Once handshake has been completed, send settings to peer if appropriate.
471 */
472static void
473maybe_send_settings (struct full_conn *conn)
474{
475    struct lsquic_http2_setting settings[2];
476    unsigned n_settings = 0;
477
478    if (conn->fc_settings->es_max_header_list_size && send_smhl(conn))
479    {
480        settings[n_settings].id    = SETTINGS_MAX_HEADER_LIST_SIZE;
481        settings[n_settings].value = conn->fc_settings->es_max_header_list_size;
482        LSQ_DEBUG("sending settings SETTINGS_MAX_HEADER_LIST_SIZE=%u",
483                                                settings[n_settings].value);
484        ++n_settings;
485    }
486    if (!(conn->fc_flags & FC_SERVER) && !conn->fc_settings->es_support_push)
487    {
488        settings[n_settings].id    = SETTINGS_ENABLE_PUSH;
489        settings[n_settings].value = 0;
490        LSQ_DEBUG("sending settings SETTINGS_ENABLE_PUSH=%u",
491                                                settings[n_settings].value);
492        ++n_settings;
493    }
494
495    if (n_settings)
496    {
497        if (0 != lsquic_headers_stream_send_settings(conn->fc_pub.u.gquic.hs,
498                                                        settings, n_settings))
499            ABORT_ERROR("could not send settings");
500    }
501    else
502        LSQ_DEBUG("not sending any settings");
503}
504
505
506static int
507apply_peer_settings (struct full_conn *conn)
508{
509    uint32_t cfcw, sfcw, mids;
510    unsigned n;
511    const struct {
512        uint32_t    tag;
513        uint32_t   *val;
514        const char *tag_str;
515    } tags[] = {
516        { QTAG_CFCW, &cfcw, "CFCW", },
517        { QTAG_SFCW, &sfcw, "SFCW", },
518        { QTAG_MIDS, &mids, "MIDS", },
519    };
520
521#ifndef NDEBUG
522    if (getenv("LSQUIC_TEST_ENGINE_DTOR"))
523        return 0;
524#endif
525
526    for (n = 0; n < sizeof(tags) / sizeof(tags[0]); ++n)
527        if (0 != conn->fc_conn.cn_esf.g->esf_get_peer_setting(
528                    conn->fc_conn.cn_enc_session, tags[n].tag, tags[n].val))
529        {
530            LSQ_INFO("peer did not supply value for %s", tags[n].tag_str);
531            return -1;
532        }
533
534    LSQ_DEBUG("peer settings: CFCW: %u; SFCW: %u; MIDS: %u",
535        cfcw, sfcw, mids);
536    lsquic_full_conn_on_peer_config(conn, cfcw, sfcw, mids);
537    return 0;
538}
539
540static const struct conn_iface *full_conn_iface_ptr;
541
542
543/* gQUIC up to version Q046 has handshake stream 1 and headers stream 3.
544 * Q050 and later have "crypto streams" -- meaning CRYPTO frames, not
545 * STREAM frames and no stream IDs -- and headers stream 1.
546 */
547static lsquic_stream_id_t
548headers_stream_id_by_ver (enum lsquic_version version)
549{
550    if (version < LSQVER_050)
551        return 3;
552    else
553        return 1;
554}
555
556
557static lsquic_stream_id_t
558headers_stream_id_by_conn (const struct full_conn *conn)
559{
560    return headers_stream_id_by_ver(conn->fc_conn.cn_version);
561}
562
563
564static lsquic_stream_id_t
565hsk_stream_id (const struct full_conn *conn)
566{
567    if (conn->fc_conn.cn_version < LSQVER_050)
568        return 1;
569    else
570        /* Use this otherwise invalid stream ID as ID for the gQUIC crypto
571         * stream.
572         */
573        return (uint64_t) -1;
574}
575
576
577static int
578has_handshake_stream (const struct full_conn *conn)
579{
580    return conn->fc_conn.cn_version < LSQVER_050;
581}
582
583
584static int
585is_handshake_stream_id (const struct full_conn *conn,
586                                                lsquic_stream_id_t stream_id)
587{
588    return conn->fc_conn.cn_version < LSQVER_050 && stream_id == 1;
589}
590
591
592static struct full_conn *
593new_conn_common (lsquic_cid_t cid, struct lsquic_engine_public *enpub,
594                 unsigned flags, enum lsquic_version version)
595{
596    struct full_conn *conn;
597    lsquic_stream_t *headers_stream;
598    int saved_errno;
599
600    assert(0 == (flags & ~(FC_SERVER|FC_HTTP)));
601
602    conn = calloc(1, sizeof(*conn));
603    if (!conn)
604        return NULL;
605    headers_stream = NULL;
606    conn->fc_conn.cn_if = full_conn_iface_ptr;
607    conn->fc_conn.cn_cces = conn->fc_cces;
608    conn->fc_conn.cn_cces_mask = 1;
609    conn->fc_conn.cn_cid = cid;
610    conn->fc_flags = flags;
611    conn->fc_enpub = enpub;
612    conn->fc_pub.enpub = enpub;
613    conn->fc_pub.mm = &enpub->enp_mm;
614    conn->fc_pub.lconn = &conn->fc_conn;
615    conn->fc_pub.send_ctl = &conn->fc_send_ctl;
616#if LSQUIC_CONN_STATS
617    conn->fc_pub.conn_stats = &conn->fc_stats;
618#endif
619    conn->fc_pub.packet_out_malo =
620                        lsquic_malo_create(sizeof(struct lsquic_packet_out));
621    conn->fc_pub.path = &conn->fc_path;
622    conn->fc_stream_ifs[STREAM_IF_STD].stream_if     = enpub->enp_stream_if;
623    conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx = enpub->enp_stream_if_ctx;
624    conn->fc_settings = &enpub->enp_settings;
625    /* Calculate maximum number of incoming streams using the same mechanism
626     * and parameters as found in Chrome:
627     */
628    conn->fc_cfg.max_streams_in =
629        (unsigned) ((float) enpub->enp_settings.es_max_streams_in * 1.1f);
630    if (conn->fc_cfg.max_streams_in <
631                                enpub->enp_settings.es_max_streams_in + 10)
632        conn->fc_cfg.max_streams_in =
633                                enpub->enp_settings.es_max_streams_in + 10;
634    /* `max_streams_out' gets reset when handshake is complete and we
635     * learn of peer settings.  100 seems like a sane default value
636     * because it is what other implementations use.  In server mode,
637     * we do not open any streams until the handshake is complete; in
638     * client mode, we are limited to 98 outgoing requests alongside
639     * handshake and headers streams.
640     */
641    conn->fc_cfg.max_streams_out = 100;
642    TAILQ_INIT(&conn->fc_pub.sending_streams);
643    TAILQ_INIT(&conn->fc_pub.read_streams);
644    TAILQ_INIT(&conn->fc_pub.write_streams);
645    TAILQ_INIT(&conn->fc_pub.service_streams);
646    STAILQ_INIT(&conn->fc_stream_ids_to_reset);
647    lsquic_conn_cap_init(&conn->fc_pub.conn_cap, LSQUIC_MIN_FCW);
648    lsquic_alarmset_init(&conn->fc_alset, &conn->fc_conn);
649    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_IDLE, idle_alarm_expired, conn);
650    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_ACK_APP, ack_alarm_expired, conn);
651    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_PING, ping_alarm_expired, conn);
652    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_HANDSHAKE, handshake_alarm_expired, conn);
653    lsquic_set64_init(&conn->fc_closed_stream_ids[0]);
654    lsquic_set64_init(&conn->fc_closed_stream_ids[1]);
655    lsquic_cfcw_init(&conn->fc_pub.cfcw, &conn->fc_pub, conn->fc_settings->es_cfcw);
656    lsquic_send_ctl_init(&conn->fc_send_ctl, &conn->fc_alset, conn->fc_enpub,
657                     flags & FC_SERVER ? &server_ver_neg : &conn->fc_ver_neg,
658                     &conn->fc_pub, 0);
659
660    conn->fc_pub.all_streams = lsquic_hash_create();
661    if (!conn->fc_pub.all_streams)
662        goto cleanup_on_error;
663    lsquic_rechist_init(&conn->fc_rechist, 0);
664    if (conn->fc_flags & FC_HTTP)
665    {
666        conn->fc_pub.u.gquic.hs = lsquic_headers_stream_new(
667            !!(conn->fc_flags & FC_SERVER), conn->fc_enpub,
668                                                     headers_callbacks_ptr,
669#if LSQUIC_CONN_STATS
670                                                    &conn->fc_stats,
671#endif
672                                                     conn);
673        if (!conn->fc_pub.u.gquic.hs)
674            goto cleanup_on_error;
675        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if     = lsquic_headers_stream_if;
676        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = conn->fc_pub.u.gquic.hs;
677        headers_stream = new_stream_ext(conn, headers_stream_id_by_ver(version),
678                                STREAM_IF_HDR,
679                    SCF_CALL_ON_NEW|SCF_DI_AUTOSWITCH|SCF_CRITICAL|SCF_HEADERS);
680        if (!headers_stream)
681            goto cleanup_on_error;
682    }
683    else
684    {
685        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if     = enpub->enp_stream_if;
686        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = enpub->enp_stream_if_ctx;
687    }
688    if (conn->fc_settings->es_support_push)
689        conn->fc_flags |= FC_SUPPORT_PUSH;
690    conn->fc_conn.cn_n_cces = sizeof(conn->fc_cces) / sizeof(conn->fc_cces[0]);
691    if (conn->fc_settings->es_noprogress_timeout)
692        conn->fc_flags |= FC_NOPROG_TIMEOUT;
693    return conn;
694
695  cleanup_on_error:
696    saved_errno = errno;
697
698    if (conn->fc_pub.all_streams)
699        lsquic_hash_destroy(conn->fc_pub.all_streams);
700    lsquic_rechist_cleanup(&conn->fc_rechist);
701    if (conn->fc_flags & FC_HTTP)
702    {
703        if (conn->fc_pub.u.gquic.hs)
704            lsquic_headers_stream_destroy(conn->fc_pub.u.gquic.hs);
705        if (headers_stream)
706            lsquic_stream_destroy(headers_stream);
707    }
708    memset(conn, 0, sizeof(*conn));
709    free(conn);
710
711    errno = saved_errno;
712    return NULL;
713}
714
715
716struct lsquic_conn *
717lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *enpub,
718                      unsigned versions, unsigned flags,
719                      const char *hostname, unsigned short max_packet_size,
720                      int is_ipv4,
721                      const unsigned char *sess_resume, size_t sess_resume_len)
722{
723    struct full_conn *conn;
724    enum lsquic_version version, sess_resume_version;
725    lsquic_cid_t cid;
726    const struct enc_session_funcs_gquic *esf_g;
727
728    versions &= (~LSQUIC_IETF_VERSIONS & LSQUIC_SUPPORTED_VERSIONS);
729    assert(versions);
730    version = highest_bit_set(versions);
731    if (sess_resume)
732    {
733        sess_resume_version = lsquic_sess_resume_version(sess_resume, sess_resume_len);
734        if (sess_resume_version < N_LSQVER && ((1 << sess_resume_version) & versions))
735            version = sess_resume_version;
736    }
737    esf_g = select_esf_gquic_by_ver(version);
738    lsquic_generate_cid_gquic(&cid);
739    if (!max_packet_size)
740    {
741        if (enpub->enp_settings.es_base_plpmtu)
742            max_packet_size = enpub->enp_settings.es_base_plpmtu;
743        else if (is_ipv4)
744            max_packet_size = GQUIC_MAX_IPv4_PACKET_SZ;
745        else
746            max_packet_size = GQUIC_MAX_IPv6_PACKET_SZ;
747    }
748    conn = new_conn_common(cid, enpub, flags, version);
749    if (!conn)
750        return NULL;
751    init_ver_neg(conn, versions, &version);
752    conn->fc_path.np_pack_size = max_packet_size;
753    conn->fc_conn.cn_esf_c = select_esf_common_by_ver(version);
754    conn->fc_conn.cn_esf.g = esf_g;
755    conn->fc_conn.cn_enc_session =
756        conn->fc_conn.cn_esf.g->esf_create_client(&conn->fc_conn, hostname,
757                                cid, conn->fc_enpub, sess_resume, sess_resume_len);
758    if (!conn->fc_conn.cn_enc_session)
759    {
760        LSQ_WARN("could not create enc session: %s", strerror(errno));
761        conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
762        return NULL;
763    }
764
765    if (conn->fc_flags & FC_HTTP)
766        conn->fc_last_stream_id = headers_stream_id_by_conn(conn);   /* Client goes (3?), 5, 7, 9.... */
767    else if (has_handshake_stream(conn))
768        conn->fc_last_stream_id = 1;
769    else
770        conn->fc_last_stream_id = (uint64_t) -1;    /* +2 will get us to 1  */
771    conn->fc_hsk_ctx.client.lconn   = &conn->fc_conn;
772    conn->fc_hsk_ctx.client.mm      = &enpub->enp_mm;
773    conn->fc_hsk_ctx.client.ver_neg = &conn->fc_ver_neg;
774    conn->fc_stream_ifs[STREAM_IF_HSK]
775                .stream_if     = &lsquic_client_hsk_stream_if;
776    conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
777    conn->fc_orig_versions = versions;
778    if (conn->fc_settings->es_handshake_to)
779        lsquic_alarmset_set(&conn->fc_alset, AL_HANDSHAKE,
780                    lsquic_time_now() + conn->fc_settings->es_handshake_to);
781    if (!new_stream_ext(conn, hsk_stream_id(conn), STREAM_IF_HSK,
782            SCF_CALL_ON_NEW|SCF_DI_AUTOSWITCH|SCF_CRITICAL|SCF_CRYPTO
783            |(conn->fc_conn.cn_version >= LSQVER_050 ? SCF_CRYPTO_FRAMES : 0)))
784    {
785        LSQ_WARN("could not create handshake stream: %s", strerror(errno));
786        conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
787        return NULL;
788    }
789    conn->fc_flags |= FC_CREATED_OK;
790    LSQ_INFO("Created new client connection");
791    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "created full connection");
792    return &conn->fc_conn;
793}
794
795
796static void
797full_conn_ci_client_call_on_new (struct lsquic_conn *lconn)
798{
799    struct full_conn *const conn = (struct full_conn *) lconn;
800    assert(conn->fc_flags & FC_CREATED_OK);
801    conn->fc_conn_ctx = conn->fc_stream_ifs[STREAM_IF_STD].stream_if
802        ->on_new_conn(conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, lconn);
803}
804
805
806/* This function is special in that it peeks into fc_send_ctl.  Other functions
807 * should not do that.
808 */
809struct lsquic_conn *
810lsquic_gquic_full_conn_server_new (struct lsquic_engine_public *enpub,
811                      unsigned flags, lsquic_conn_t *lconn_mini)
812{
813    struct full_conn *conn;
814    struct mini_conn *mc;
815    lsquic_conn_t *lconn_full;
816    lsquic_packet_in_t *packet_in;
817    lsquic_packet_out_t *packet_out;
818    lsquic_stream_t *hsk_stream;
819    lsquic_packno_t next_packno;
820    mconn_packno_set_t received;
821    unsigned n;
822    uint32_t tcid0_val;
823    int have_errors = 0, tcid0;
824    int have_outgoing_ack = 0;
825
826    mc = (struct mini_conn *) lconn_mini;
827    conn = new_conn_common(lconn_mini->cn_cid, enpub, flags,
828                                                    lconn_mini->cn_version);
829    if (!conn)
830        return NULL;
831    lconn_full = &conn->fc_conn;
832    conn->fc_last_stream_id = 0;   /* Server goes 2, 4, 6.... */
833    if (conn->fc_flags & FC_HTTP)
834        conn->fc_max_peer_stream_id = headers_stream_id_by_conn(conn);
835    else if (has_handshake_stream(conn))
836        conn->fc_max_peer_stream_id = 1;
837    else
838        conn->fc_max_peer_stream_id = (uint64_t) -1;
839    conn->fc_stream_ifs[STREAM_IF_HSK]
840                .stream_if     = &lsquic_server_hsk_stream_if;
841    conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.server;
842    conn->fc_ver_neg.vn_ver   = lconn_mini->cn_version;
843    conn->fc_conn.cn_version  = lconn_mini->cn_version;
844    conn->fc_conn.cn_pf       = lconn_mini->cn_pf;
845    conn->fc_conn.cn_esf_c    = lconn_mini->cn_esf_c;
846    conn->fc_conn.cn_esf.g    = lconn_mini->cn_esf.g;
847    conn->fc_conn.cn_flags |= LSCONN_VER_SET | LSCONN_SERVER;
848    conn->fc_pub.rtt_stats = mc->mc_rtt_stats;
849
850    conn->fc_hsk_ctx.server.lconn = lconn_full;
851    conn->fc_hsk_ctx.server.enpub = enpub;
852
853    /* TODO Optimize: we don't need an actual crypto stream and handler
854     * on the server side, as we don't do anything with it.  We can
855     * throw out appropriate frames earlier.
856     */
857
858    /* Adjust offsets in the HANDSHAKE stream: */
859    hsk_stream = new_stream_ext(conn, hsk_stream_id(conn), STREAM_IF_HSK,
860            SCF_CALL_ON_NEW|SCF_DI_AUTOSWITCH|SCF_CRITICAL|SCF_CRYPTO
861            |(conn->fc_conn.cn_version >= LSQVER_050 ? SCF_CRYPTO_FRAMES : 0));
862    if (!hsk_stream)
863    {
864        LSQ_DEBUG("could not create handshake stream: %s", strerror(errno));
865        conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
866        return NULL;
867    }
868    hsk_stream->tosend_off  = mc->mc_write_off;
869    hsk_stream->read_offset = mc->mc_read_off;
870    if (0 != lsquic_stream_update_sfcw(hsk_stream, mc->mc_write_off))
871    {
872        LSQ_WARN("Invalid write offset %u", mc->mc_write_off);
873        ++have_errors;
874    }
875
876    assert(lconn_full->cn_enc_session == NULL);
877    lconn_full->cn_enc_session = lconn_mini->cn_enc_session;
878    lconn_mini->cn_enc_session = NULL;
879    lconn_full->cn_esf_c->esf_set_conn(lconn_full->cn_enc_session,
880                                                            &conn->fc_conn);
881
882    lsquic_send_ctl_verneg_done(&conn->fc_send_ctl);
883    conn->fc_send_ctl.sc_cur_packno = mc->mc_cur_packno;
884    lsquic_send_ctl_begin_optack_detection(&conn->fc_send_ctl);
885
886    /* Remove those that still exist from the set: they will be marked as
887     * received during regular processing in ci_packet_in() later on.
888     */
889    received = mc->mc_received_packnos;
890    TAILQ_FOREACH(packet_in, &mc->mc_packets_in, pi_next)
891        received &= ~MCONN_PACKET_MASK(packet_in->pi_packno);
892
893    for (n = 0; received; ++n)
894    {
895        if (received & (1U << n))
896            /* Setting `now' to zero is OK here, as we should have had at
897             * least one other packet above.
898             */
899            lsquic_rechist_received(&conn->fc_rechist, n + 1, 0);
900        received &= ~(1U << n);
901    }
902
903    /* Mini connection sends out packets 1, 2, 3... and so on.  It deletes
904     * packets that have been successfully sent and acked or those that have
905     * been lost.  We take ownership of all packets in mc_packets_out; those
906     * that are not on the list are recorded in fc_send_ctl.sc_senhist.
907     */
908    next_packno = 0;
909    while ((packet_out = TAILQ_FIRST(&mc->mc_packets_out)))
910    {
911        TAILQ_REMOVE(&mc->mc_packets_out, packet_out, po_next);
912
913        /* Holes in the sequence signify ACKed or lost packets */
914        ++next_packno;
915        for ( ; next_packno < packet_out->po_packno; ++next_packno)
916            lsquic_senhist_add(&conn->fc_send_ctl.sc_senhist, next_packno);
917
918        packet_out->po_path = &conn->fc_path;
919        if (mc->mc_sent_packnos & MCONN_PACKET_MASK(packet_out->po_packno))
920        {
921            LSQ_DEBUG("got sent packet_out %"PRIu64" from mini",
922                                                   packet_out->po_packno);
923            if (0 != lsquic_send_ctl_sent_packet(&conn->fc_send_ctl,
924                                                 packet_out)
925                && !have_errors /* Warn once */)
926            {
927                ++have_errors;
928                LSQ_WARN("could not add packet %"PRIu64" to sent set: %s",
929                    packet_out->po_packno, strerror(errno));
930            }
931        }
932        else
933        {
934            LSQ_DEBUG("got unsent packet_out %"PRIu64" from mini (will send)",
935                                                   packet_out->po_packno);
936            lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
937            have_outgoing_ack |= packet_out->po_frame_types &
938                                                (1 << QUIC_FRAME_ACK);
939        }
940    }
941
942    assert(lconn_mini->cn_flags & LSCONN_HANDSHAKE_DONE);
943    lconn_full->cn_flags |= LSCONN_HANDSHAKE_DONE;
944
945    lconn_full->cn_flags |= lconn_mini->cn_flags &
946        LSCONN_PEER_GOING_AWAY /* We are OK with fc_goaway_stream_id = 0 */;
947    conn->fc_path = mc->mc_path;
948
949    if (0 == apply_peer_settings(conn))
950    {
951        if (conn->fc_flags & FC_HTTP)
952            maybe_send_settings(conn);
953    }
954    else
955        ++have_errors;
956
957    if (0 == have_errors)
958    {
959        tcid0 = conn->fc_settings->es_support_tcid0
960             && 0 == conn->fc_conn.cn_esf.g->esf_get_peer_setting(
961                        conn->fc_conn.cn_enc_session, QTAG_TCID, &tcid0_val)
962             && 0 == tcid0_val;
963        lsquic_send_ctl_set_tcid0(&conn->fc_send_ctl, tcid0);
964        if (tcid0)
965            conn->fc_conn.cn_flags |= LSCONN_TCID0;
966        conn->fc_flags |= FC_CREATED_OK|FC_FIRST_TICK;
967        if (conn->fc_conn.cn_version >= LSQVER_046
968                || conn->fc_conn.cn_esf.g->esf_get_peer_option(
969                                    conn->fc_conn.cn_enc_session, QTAG_NSTP))
970        {
971            conn->fc_flags |= FC_NSTP;
972            lsquic_send_ctl_turn_nstp_on(&conn->fc_send_ctl);
973        }
974        LSQ_DEBUG("Calling on_new_conn callback");
975        conn->fc_conn_ctx = enpub->enp_stream_if->on_new_conn(
976                                    enpub->enp_stream_if_ctx, &conn->fc_conn);
977        /* Now that user code knows about this connection, process incoming
978         * packets, if any.
979         */
980        while ((packet_in = TAILQ_FIRST(&mc->mc_packets_in)))
981        {
982            TAILQ_REMOVE(&mc->mc_packets_in, packet_in, pi_next);
983            packet_in->pi_flags |= PI_FROM_MINI;
984            conn->fc_conn.cn_if->ci_packet_in(&conn->fc_conn, packet_in);
985            lsquic_packet_in_put(conn->fc_pub.mm, packet_in);
986        }
987        /* At this point we may have errors, but we promote it anyway: this is
988         * so that CONNECTION_CLOSE frame can be generated and sent out.
989         */
990        if (have_outgoing_ack)
991            reset_ack_state(conn);
992        lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
993                    lsquic_time_now() + conn->fc_settings->es_idle_conn_to);
994        EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "created full connection");
995        LSQ_INFO("Created new server connection");
996        return &conn->fc_conn;
997    }
998    else
999    {
1000        LSQ_DEBUG("hit errors creating connection, return NULL");
1001        conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
1002        return NULL;
1003    }
1004}
1005
1006
1007static int
1008is_our_stream (const struct full_conn *conn, const lsquic_stream_t *stream)
1009{
1010    int is_server = !!(conn->fc_flags & FC_SERVER);
1011    return (1 & stream->id) ^ is_server;
1012}
1013
1014
1015static unsigned
1016count_streams (const struct full_conn *conn, int peer)
1017{
1018    const lsquic_stream_t *stream;
1019    unsigned count;
1020    int ours;
1021    int is_server;
1022    struct lsquic_hash_elem *el;
1023
1024    peer = !!peer;
1025    is_server = !!(conn->fc_flags & FC_SERVER);
1026    count = 0;
1027
1028    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
1029                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
1030    {
1031        stream = lsquic_hashelem_getdata(el);
1032        ours = (1 & stream->id) ^ is_server;
1033        if (ours ^ peer)
1034            count += !(lsquic_stream_is_closed(stream)
1035                                /* When counting peer-initiated streams, do not
1036                                 * include those that have been reset:
1037                                 */
1038                                || (peer && lsquic_stream_is_reset(stream)));
1039    }
1040
1041    return count;
1042}
1043
1044
1045enum stream_count { SCNT_ALL, SCNT_PEER, SCNT_CLOSED, SCNT_RESET,
1046    SCNT_RES_UNCLO /* reset and not closed */, N_SCNTS };
1047
1048static void
1049collect_stream_counts (const struct full_conn *conn, int peer,
1050                                                    unsigned counts[N_SCNTS])
1051{
1052    const lsquic_stream_t *stream;
1053    int ours;
1054    int is_server;
1055    struct lsquic_hash_elem *el;
1056
1057    peer = !!peer;
1058    is_server = !!(conn->fc_flags & FC_SERVER);
1059    memset(counts, 0, N_SCNTS * sizeof(counts[0]));
1060
1061    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
1062                             el = lsquic_hash_next(conn->fc_pub.all_streams))
1063    {
1064        ++counts[SCNT_ALL];
1065        stream = lsquic_hashelem_getdata(el);
1066        ours = (1 & stream->id) ^ is_server;
1067        if (ours ^ peer)
1068        {
1069            ++counts[SCNT_PEER];
1070            counts[SCNT_CLOSED] += lsquic_stream_is_closed(stream);
1071            counts[SCNT_RESET] += !!lsquic_stream_is_reset(stream);
1072            counts[SCNT_RES_UNCLO] += lsquic_stream_is_reset(stream)
1073                                        && !lsquic_stream_is_closed(stream);
1074        }
1075    }
1076}
1077
1078
1079static void
1080full_conn_ci_destroy (lsquic_conn_t *lconn)
1081{
1082    struct full_conn *conn = (struct full_conn *) lconn;
1083    struct lsquic_hash_elem *el;
1084    struct lsquic_stream *stream;
1085    struct stream_id_to_reset *sitr;
1086
1087    LSQ_DEBUG("destroy connection");
1088    conn->fc_flags |= FC_CLOSING;
1089    lsquic_set64_cleanup(&conn->fc_closed_stream_ids[0]);
1090    lsquic_set64_cleanup(&conn->fc_closed_stream_ids[1]);
1091    while ((el = lsquic_hash_first(conn->fc_pub.all_streams)))
1092    {
1093        stream = lsquic_hashelem_getdata(el);
1094        lsquic_hash_erase(conn->fc_pub.all_streams, el);
1095        lsquic_stream_destroy(stream);
1096    }
1097    lsquic_hash_destroy(conn->fc_pub.all_streams);
1098    if (conn->fc_flags & FC_CREATED_OK)
1099        conn->fc_stream_ifs[STREAM_IF_STD].stream_if
1100                    ->on_conn_closed(&conn->fc_conn);
1101    if (conn->fc_pub.u.gquic.hs)
1102        lsquic_headers_stream_destroy(conn->fc_pub.u.gquic.hs);
1103
1104    lsquic_send_ctl_cleanup(&conn->fc_send_ctl);
1105    lsquic_rechist_cleanup(&conn->fc_rechist);
1106    if (conn->fc_conn.cn_enc_session)
1107        conn->fc_conn.cn_esf.g->esf_destroy(conn->fc_conn.cn_enc_session);
1108    lsquic_malo_destroy(conn->fc_pub.packet_out_malo);
1109#if LSQUIC_CONN_STATS
1110    LSQ_NOTICE("# ticks: %lu", conn->fc_stats.n_ticks);
1111    LSQ_NOTICE("received %lu packets, of which %lu were not decryptable, %lu were "
1112        "dups and %lu were errors; sent %lu packets, avg stream data per outgoing"
1113        " packet is %lu bytes",
1114        conn->fc_stats.in.packets, conn->fc_stats.in.undec_packets,
1115        conn->fc_stats.in.dup_packets, conn->fc_stats.in.err_packets,
1116        conn->fc_stats.out.packets,
1117        conn->fc_stats.out.stream_data_sz / conn->fc_stats.out.packets);
1118    LSQ_NOTICE("ACKs: in: %lu; processed: %lu; merged: %lu",
1119        conn->fc_stats.in.n_acks, conn->fc_stats.in.n_acks_proc,
1120        conn->fc_stats.in.n_acks_merged);
1121#endif
1122    while ((sitr = STAILQ_FIRST(&conn->fc_stream_ids_to_reset)))
1123    {
1124        STAILQ_REMOVE_HEAD(&conn->fc_stream_ids_to_reset, sitr_next);
1125        free(sitr);
1126    }
1127    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "full connection destroyed");
1128    free(conn->fc_errmsg);
1129    free(conn);
1130}
1131
1132
1133static void
1134conn_mark_stream_closed (struct full_conn *conn, lsquic_stream_id_t stream_id)
1135{   /* Because stream IDs are distributed unevenly -- there is a set of odd
1136     * stream IDs and a set of even stream IDs -- it is more efficient to
1137     * maintain two sets of closed stream IDs.
1138     */
1139    int idx = stream_id & 1;
1140    stream_id >>= 1;
1141    if (0 != lsquic_set64_add(&conn->fc_closed_stream_ids[idx], stream_id))
1142        ABORT_ERROR("could not add element to set: %s", strerror(errno));
1143}
1144
1145
1146static int
1147conn_is_stream_closed (struct full_conn *conn, lsquic_stream_id_t stream_id)
1148{
1149    int idx = stream_id & 1;
1150    stream_id >>= 1;
1151    return lsquic_set64_has(&conn->fc_closed_stream_ids[idx], stream_id);
1152}
1153
1154
1155static void
1156set_ack_timer (struct full_conn *conn, lsquic_time_t now)
1157{
1158    lsquic_alarmset_set(&conn->fc_alset, AL_ACK_APP, now + ACK_TIMEOUT);
1159    LSQ_DEBUG("ACK alarm set to %"PRIu64, now + ACK_TIMEOUT);
1160}
1161
1162
1163static void
1164ack_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
1165                                                        lsquic_time_t now)
1166{
1167    struct full_conn *conn = ctx;
1168    LSQ_DEBUG("ACK timer expired (%"PRIu64" < %"PRIu64"): ACK queued",
1169        expiry, now);
1170    conn->fc_flags |= FC_ACK_QUEUED;
1171}
1172
1173
1174static void
1175try_queueing_ack (struct full_conn *conn, int was_missing, lsquic_time_t now)
1176{
1177    if (conn->fc_n_slack_akbl >= MAX_RETR_PACKETS_SINCE_LAST_ACK ||
1178        ((conn->fc_flags & FC_ACK_HAD_MISS) && was_missing)      ||
1179        lsquic_send_ctl_n_stop_waiting(&conn->fc_send_ctl) > 1)
1180    {
1181        lsquic_alarmset_unset(&conn->fc_alset, AL_ACK_APP);
1182        lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
1183        conn->fc_flags |= FC_ACK_QUEUED;
1184        LSQ_DEBUG("ACK queued: ackable: %u; had_miss: %d; "
1185            "was_missing: %d; n_stop_waiting: %u",
1186            conn->fc_n_slack_akbl,
1187            !!(conn->fc_flags & FC_ACK_HAD_MISS), was_missing,
1188            lsquic_send_ctl_n_stop_waiting(&conn->fc_send_ctl));
1189    }
1190    else if (conn->fc_n_slack_akbl > 0)
1191        set_ack_timer(conn, now);
1192}
1193
1194
1195static void
1196reset_ack_state (struct full_conn *conn)
1197{
1198    conn->fc_n_slack_akbl = 0;
1199    lsquic_send_ctl_n_stop_waiting_reset(&conn->fc_send_ctl);
1200    conn->fc_flags &= ~FC_ACK_QUEUED;
1201    lsquic_alarmset_unset(&conn->fc_alset, AL_ACK_APP);
1202    lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
1203    LSQ_DEBUG("ACK state reset");
1204}
1205
1206
1207#if 1
1208#   define verify_ack_frame(a, b, c)
1209#else
1210static void
1211verify_ack_frame (struct full_conn *conn, const unsigned char *buf, int bufsz)
1212{
1213    unsigned i;
1214    int parsed_len;
1215    struct ack_info *ack_info;
1216    const struct lsquic_packno_range *range;
1217    char ack_buf[512];
1218    unsigned buf_off = 0;
1219    int nw;
1220
1221    ack_info = conn->fc_pub.mm->acki;
1222    parsed_len = parse_ack_frame(buf, bufsz, ack_info);
1223    assert(parsed_len == bufsz);
1224
1225    for (range = lsquic_rechist_first(&conn->fc_rechist), i = 0; range;
1226            range = lsquic_rechist_next(&conn->fc_rechist), ++i)
1227    {
1228        assert(i < ack_info->n_ranges);
1229        assert(range->high == ack_info->ranges[i].high);
1230        assert(range->low == ack_info->ranges[i].low);
1231        if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
1232        {
1233            nw = snprintf(ack_buf + buf_off, sizeof(ack_buf) - buf_off,
1234                            "[%"PRIu64"-%"PRIu64"]", range->high, range->low);
1235            assert(nw >= 0);
1236            buf_off += nw;
1237        }
1238    }
1239    assert(i == ack_info->n_ranges);
1240    LSQ_DEBUG("Sent ACK frame %s", ack_buf);
1241}
1242#endif
1243
1244
1245static void
1246full_conn_ci_write_ack (struct lsquic_conn *lconn,
1247                                    struct lsquic_packet_out *packet_out)
1248{
1249    struct full_conn *conn = (struct full_conn *) lconn;
1250    lsquic_time_t now;
1251    int has_missing, w;
1252
1253    now = lsquic_time_now();
1254    w = conn->fc_conn.cn_pf->pf_gen_ack_frame(
1255            packet_out->po_data + packet_out->po_data_sz,
1256            lsquic_packet_out_avail(packet_out),
1257            (gaf_rechist_first_f)        lsquic_rechist_first,
1258            (gaf_rechist_next_f)         lsquic_rechist_next,
1259            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
1260            &conn->fc_rechist, now, &has_missing, &packet_out->po_ack2ed,
1261            NULL);
1262    if (w < 0) {
1263        ABORT_ERROR("generating ACK frame failed: %d", errno);
1264        return;
1265    }
1266#if LSQUIC_CONN_STATS
1267    ++conn->fc_stats.out.acks;
1268#endif
1269    EV_LOG_GENERATED_ACK_FRAME(LSQUIC_LOG_CONN_ID, conn->fc_conn.cn_pf,
1270                        packet_out->po_data + packet_out->po_data_sz, w);
1271    verify_ack_frame(conn, packet_out->po_data + packet_out->po_data_sz, w);
1272    lsquic_send_ctl_scheduled_ack(&conn->fc_send_ctl, PNS_APP,
1273                                                    packet_out->po_ack2ed);
1274    packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK;
1275    if (0 != lsquic_packet_out_add_frame(packet_out, conn->fc_pub.mm, 0,
1276                                QUIC_FRAME_ACK, packet_out->po_data_sz, w))
1277    {
1278        ABORT_ERROR("adding frame to packet failed: %d", errno);
1279        return;
1280    }
1281    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, w);
1282    packet_out->po_regen_sz += w;
1283    if (has_missing)
1284        conn->fc_flags |= FC_ACK_HAD_MISS;
1285    else
1286        conn->fc_flags &= ~FC_ACK_HAD_MISS;
1287    LSQ_DEBUG("Put %d bytes of ACK frame into packet on outgoing queue", w);
1288    if (conn->fc_n_cons_unretx >= 20 &&
1289                !lsquic_send_ctl_have_outgoing_retx_frames(&conn->fc_send_ctl))
1290    {
1291        LSQ_DEBUG("schedule WINDOW_UPDATE frame after %u non-retx "
1292                                    "packets sent", conn->fc_n_cons_unretx);
1293        conn->fc_flags |= FC_SEND_WUF;
1294    }
1295    reset_ack_state(conn);
1296}
1297
1298
1299static lsquic_stream_t *
1300new_stream_ext (struct full_conn *conn, lsquic_stream_id_t stream_id,
1301                enum stream_if if_idx, enum stream_ctor_flags stream_ctor_flags)
1302{
1303    struct lsquic_stream *stream;
1304
1305    stream = lsquic_stream_new(stream_id, &conn->fc_pub,
1306        conn->fc_stream_ifs[if_idx].stream_if,
1307        conn->fc_stream_ifs[if_idx].stream_if_ctx, conn->fc_settings->es_sfcw,
1308        stream_ctor_flags & SCF_CRYPTO
1309                                ? 16 * 1024 : conn->fc_cfg.max_stream_send,
1310        stream_ctor_flags);
1311    if (stream)
1312        lsquic_hash_insert(conn->fc_pub.all_streams, &stream->id,
1313                            sizeof(stream->id), stream, &stream->sm_hash_el);
1314    return stream;
1315}
1316
1317
1318static lsquic_stream_t *
1319new_stream (struct full_conn *conn, lsquic_stream_id_t stream_id,
1320            enum stream_ctor_flags flags)
1321{
1322    flags |= SCF_DI_AUTOSWITCH;
1323    if (conn->fc_pub.u.gquic.hs)
1324        flags |= SCF_HTTP;
1325    if (conn->fc_enpub->enp_settings.es_rw_once)
1326        flags |= SCF_DISP_RW_ONCE;
1327
1328    return new_stream_ext(conn, stream_id, STREAM_IF_STD, flags);
1329}
1330
1331
1332static lsquic_stream_id_t
1333generate_stream_id (struct full_conn *conn)
1334{
1335    conn->fc_last_stream_id += 2;
1336    return conn->fc_last_stream_id;
1337}
1338
1339
1340static unsigned
1341full_conn_ci_n_pending_streams (const struct lsquic_conn *lconn)
1342{
1343    const struct full_conn *conn = (const struct full_conn *) lconn;
1344    return conn->fc_n_delayed_streams;
1345}
1346
1347
1348static unsigned
1349full_conn_ci_cancel_pending_streams (struct lsquic_conn *lconn, unsigned n)
1350{
1351    struct full_conn *conn = (struct full_conn *) lconn;
1352    if (n > conn->fc_n_delayed_streams)
1353        conn->fc_n_delayed_streams = 0;
1354    else
1355        conn->fc_n_delayed_streams -= n;
1356    return conn->fc_n_delayed_streams;
1357}
1358
1359
1360static int
1361either_side_going_away (const struct full_conn *conn)
1362{
1363    return (conn->fc_flags & FC_GOING_AWAY)
1364        || (conn->fc_conn.cn_flags & LSCONN_PEER_GOING_AWAY);
1365}
1366
1367
1368static unsigned
1369full_conn_ci_n_avail_streams (const lsquic_conn_t *lconn)
1370{
1371    struct full_conn *conn = (struct full_conn *) lconn;
1372    unsigned stream_count = count_streams(conn, 0);
1373    if (conn->fc_cfg.max_streams_out < stream_count)
1374        return 0;
1375    return conn->fc_cfg.max_streams_out - stream_count;
1376}
1377
1378
1379static int
1380handshake_done_or_doing_sess_resume (const struct full_conn *conn)
1381{
1382    return (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
1383        || conn->fc_conn.cn_esf_c->esf_is_sess_resume_enabled(
1384                                                conn->fc_conn.cn_enc_session);
1385}
1386
1387
1388static void
1389full_conn_ci_make_stream (struct lsquic_conn *lconn)
1390{
1391    struct full_conn *conn = (struct full_conn *) lconn;
1392    if (handshake_done_or_doing_sess_resume(conn)
1393                                    && full_conn_ci_n_avail_streams(lconn) > 0)
1394    {
1395        if (!new_stream(conn, generate_stream_id(conn), SCF_CALL_ON_NEW))
1396            ABORT_ERROR("could not create new stream: %s", strerror(errno));
1397    }
1398    else if (either_side_going_away(conn))
1399        (void) conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_new_stream(
1400            conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, NULL);
1401    else
1402    {
1403        ++conn->fc_n_delayed_streams;
1404        LSQ_DEBUG("delayed stream creation.  Backlog size: %u",
1405                                                conn->fc_n_delayed_streams);
1406    }
1407}
1408
1409
1410static lsquic_stream_t *
1411find_stream_by_id (struct full_conn *conn, lsquic_stream_id_t stream_id)
1412{
1413    struct lsquic_hash_elem *el;
1414    el = lsquic_hash_find(conn->fc_pub.all_streams, &stream_id, sizeof(stream_id));
1415    if (el)
1416        return lsquic_hashelem_getdata(el);
1417    else
1418        return NULL;
1419}
1420
1421
1422static struct lsquic_stream *
1423full_conn_ci_get_stream_by_id (struct lsquic_conn *lconn,
1424                               lsquic_stream_id_t stream_id)
1425{
1426    struct full_conn *conn = (struct full_conn *) lconn;
1427    struct lsquic_stream *stream;
1428
1429    stream = find_stream_by_id(conn, stream_id);
1430    if (stream && !lsquic_stream_is_closed(stream))
1431        return stream;
1432    else
1433        return NULL;
1434}
1435
1436
1437static struct lsquic_engine *
1438full_conn_ci_get_engine (struct lsquic_conn *lconn)
1439{
1440    struct full_conn *conn = (struct full_conn *) lconn;
1441    return conn->fc_enpub->enp_engine;
1442}
1443
1444
1445static struct network_path *
1446full_conn_ci_get_path (struct lsquic_conn *lconn, const struct sockaddr *sa)
1447{
1448    struct full_conn *conn = (struct full_conn *) lconn;
1449
1450    return &conn->fc_path;
1451}
1452
1453
1454static unsigned char
1455full_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
1456            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
1457{
1458    struct full_conn *conn = (struct full_conn *) lconn;
1459
1460    if (NP_IS_IPv6(&conn->fc_path) != (AF_INET6 == peer_sa->sa_family))
1461        lsquic_send_ctl_return_enc_data(&conn->fc_send_ctl);
1462
1463    size_t len = peer_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in)
1464                                                : sizeof(struct sockaddr_in6);
1465
1466    memcpy(conn->fc_path.np_peer_addr, peer_sa, len);
1467
1468    len = local_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in)
1469                                                : sizeof(struct sockaddr_in6);
1470    memcpy(conn->fc_path.np_local_addr, local_sa, len);
1471    conn->fc_path.np_peer_ctx = peer_ctx;
1472    return 0;
1473}
1474
1475
1476static ptrdiff_t
1477count_zero_bytes (const unsigned char *p, size_t len)
1478{
1479    const unsigned char *const end = p + len;
1480    while (p < end && 0 == *p)
1481        ++p;
1482    return len - (end - p);
1483}
1484
1485
1486static unsigned
1487process_padding_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1488                       const unsigned char *p, size_t len)
1489{
1490    len = (size_t) count_zero_bytes(p, len);
1491    EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len);
1492    return len;
1493}
1494
1495
1496static void
1497log_conn_flow_control (struct full_conn *conn)
1498{
1499    LSQ_DEBUG("connection flow cap: wrote: %"PRIu64
1500        "; max: %"PRIu64, conn->fc_pub.conn_cap.cc_sent,
1501        conn->fc_pub.conn_cap.cc_max);
1502    LSQ_DEBUG("connection flow control window: read: %"PRIu64
1503        "; max: %"PRIu64, conn->fc_pub.cfcw.cf_max_recv_off,
1504        conn->fc_pub.cfcw.cf_recv_off);
1505}
1506
1507
1508static unsigned
1509process_ping_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1510                    const unsigned char *p, size_t len)
1511{   /* This frame causes ACK frame to be queued, but nothing to do here;
1512     * return the length of this frame.
1513     */
1514    EV_LOG_PING_FRAME_IN(LSQUIC_LOG_CONN_ID);
1515    LSQ_DEBUG("received PING");
1516    if (conn->fc_flags & FC_SERVER)
1517        log_conn_flow_control(conn);
1518    return 1;
1519}
1520
1521
1522static int
1523is_peer_initiated (const struct full_conn *conn, lsquic_stream_id_t stream_id)
1524{
1525    unsigned is_server = !!(conn->fc_flags & FC_SERVER);
1526    int peer_initiated = (stream_id & 1) == is_server;
1527    return peer_initiated;
1528}
1529
1530
1531static void
1532maybe_schedule_reset_for_stream (struct full_conn *conn, lsquic_stream_id_t stream_id)
1533{
1534    struct stream_id_to_reset *sitr;
1535
1536    if (conn_is_stream_closed(conn, stream_id))
1537        return;
1538
1539    sitr = malloc(sizeof(*sitr));
1540    if (!sitr)
1541        return;
1542
1543    sitr->sitr_stream_id = stream_id;
1544    STAILQ_INSERT_TAIL(&conn->fc_stream_ids_to_reset, sitr, sitr_next);
1545    conn_mark_stream_closed(conn, stream_id);
1546}
1547
1548
1549static unsigned
1550process_stream_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1551                      const unsigned char *p, size_t len)
1552{
1553    stream_frame_t *stream_frame;
1554    lsquic_stream_t *stream;
1555    enum enc_level enc_level;
1556    int parsed_len;
1557
1558#ifndef LSQUIC_REDO_FAILED_INSERTION
1559#define LSQUIC_REDO_FAILED_INSERTION 0
1560#endif
1561#if LSQUIC_REDO_FAILED_INSERTION
1562    enum lsq_log_level saved_levels[3];
1563#if defined(__GNUC__) && !defined(__clang__)
1564    /* gcc complains about this -- incorrectly -- in optimized mode */
1565    saved_levels[0] = 0;
1566    saved_levels[1] = 0;
1567    saved_levels[2] = 0;
1568#endif
1569    int again = 0;
1570  redo:
1571#endif
1572    stream_frame = lsquic_malo_get(conn->fc_pub.mm->malo.stream_frame);
1573    if (!stream_frame)
1574    {
1575        LSQ_WARN("could not allocate stream frame: %s", strerror(errno));
1576        return 0;
1577    }
1578
1579    parsed_len = conn->fc_conn.cn_pf->pf_parse_stream_frame(p, len,
1580                                                            stream_frame);
1581    if (parsed_len < 0) {
1582        lsquic_malo_put(stream_frame);
1583        return 0;
1584    }
1585    EV_LOG_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_frame);
1586    LSQ_DEBUG("Got stream frame for stream #%"PRIu64, stream_frame->stream_id);
1587#if LSQUIC_CONN_STATS
1588    ++conn->fc_stats.in.stream_frames;
1589    conn->fc_stats.in.stream_data_sz += stream_frame->data_frame.df_size;
1590#endif
1591
1592    enc_level = lsquic_packet_in_enc_level(packet_in);
1593    if (!is_handshake_stream_id(conn, stream_frame->stream_id)
1594        && enc_level == ENC_LEV_CLEAR)
1595    {
1596        lsquic_malo_put(stream_frame);
1597        ABORT_ERROR("received unencrypted data for stream %"PRIu64,
1598                    stream_frame->stream_id);
1599        return 0;
1600    }
1601
1602    if (conn->fc_flags & FC_CLOSING)
1603    {
1604        LSQ_DEBUG("Connection closing: ignore frame");
1605        lsquic_malo_put(stream_frame);
1606        return parsed_len;
1607    }
1608
1609    stream = find_stream_by_id(conn, stream_frame->stream_id);
1610    if (stream)
1611    {
1612        if (lsquic_stream_is_reset(stream))
1613        {
1614            LSQ_DEBUG("stream %"PRIu64" is reset, ignore frame", stream->id);
1615            lsquic_malo_put(stream_frame);
1616            return parsed_len;
1617        }
1618    }
1619    else
1620    {
1621        if (conn_is_stream_closed(conn, stream_frame->stream_id))
1622        {
1623            LSQ_DEBUG("drop frame for closed stream %"PRIu64,
1624                                                stream_frame->stream_id);
1625            lsquic_malo_put(stream_frame);
1626            return parsed_len;
1627        }
1628        if (is_peer_initiated(conn, stream_frame->stream_id))
1629        {
1630            unsigned in_count = count_streams(conn, 1);
1631            LSQ_DEBUG("number of peer-initiated streams: %u", in_count);
1632            if (in_count >= conn->fc_cfg.max_streams_in)
1633            {
1634                if (!(conn->fc_flags & FC_ABORT_COMPLAINED))
1635                {
1636                    unsigned counts[N_SCNTS];
1637                    collect_stream_counts(conn, 1, counts);
1638                    ABORT_WARN("incoming stream would exceed limit: %u.  "
1639                        "all: %u; peer: %u; closed: %u; reset: %u; reset "
1640                        "and not closed: %u", conn->fc_cfg.max_streams_in,
1641                        counts[SCNT_ALL], counts[SCNT_PEER],
1642                        counts[SCNT_CLOSED], counts[SCNT_RESET],
1643                        counts[SCNT_RES_UNCLO]);
1644                }
1645                lsquic_malo_put(stream_frame);
1646                return 0;
1647            }
1648            if ((conn->fc_flags & FC_GOING_AWAY) &&
1649                stream_frame->stream_id > conn->fc_max_peer_stream_id)
1650            {
1651                LSQ_DEBUG("going away: reset new incoming stream %"PRIu64,
1652                                                    stream_frame->stream_id);
1653                maybe_schedule_reset_for_stream(conn, stream_frame->stream_id);
1654                lsquic_malo_put(stream_frame);
1655                return parsed_len;
1656            }
1657        }
1658        else
1659        {
1660            ABORT_ERROR("frame for never-initiated stream");
1661            lsquic_malo_put(stream_frame);
1662            return 0;
1663        }
1664        stream = new_stream(conn, stream_frame->stream_id, SCF_CALL_ON_NEW);
1665        if (!stream)
1666        {
1667            ABORT_ERROR("cannot create new stream: %s", strerror(errno));
1668            lsquic_malo_put(stream_frame);
1669            return 0;
1670        }
1671        if (stream_frame->stream_id > conn->fc_max_peer_stream_id)
1672            conn->fc_max_peer_stream_id = stream_frame->stream_id;
1673    }
1674
1675    stream_frame->packet_in = lsquic_packet_in_get(packet_in);
1676    if (0 != lsquic_stream_frame_in(stream, stream_frame))
1677    {
1678        ABORT_ERROR("cannot insert stream frame");
1679#if LSQUIC_REDO_FAILED_INSERTION
1680        if (again++)
1681        {
1682            lsq_log_levels[LSQLM_STREAM] = saved_levels[0];
1683            lsq_log_levels[LSQLM_DI]     = saved_levels[1];
1684            lsq_log_levels[LSQLM_CONN]   = saved_levels[2];
1685        }
1686        else if (!(LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_STREAM)
1687                && LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_DI)
1688                && LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_CONN)))
1689        {
1690            saved_levels[0] = lsq_log_levels[LSQLM_STREAM];
1691            saved_levels[1] = lsq_log_levels[LSQLM_DI];
1692            saved_levels[2] = lsq_log_levels[LSQLM_CONN];
1693            lsq_log_levels[LSQLM_STREAM] = LSQ_LOG_DEBUG;
1694            lsq_log_levels[LSQLM_DI]     = LSQ_LOG_DEBUG;
1695            lsq_log_levels[LSQLM_CONN]   = LSQ_LOG_DEBUG;
1696            lsquic_stream_dump_state(stream);
1697            LSQ_DEBUG("inserting frame again, this time with debug logging");
1698            goto redo;
1699        }
1700#endif
1701        return 0;
1702    }
1703
1704    if (lsquic_stream_is_crypto(stream)
1705        && (stream->sm_qflags & SMQF_WANT_READ)
1706        && !(conn->fc_flags & FC_SERVER)
1707        && !(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE))
1708    {   /* To enable decryption, process handshake stream as soon as its
1709         * data frames are received.
1710         *
1711         * TODO: this does not work when packets are reordered.  A more
1712         * flexible solution would defer packet decryption if handshake
1713         * has not been completed yet.  Nevertheless, this is good enough
1714         * for now.
1715         */
1716        lsquic_stream_dispatch_read_events(stream);
1717    }
1718
1719    return parsed_len;
1720}
1721
1722
1723static unsigned
1724process_crypto_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1725                      const unsigned char *p, size_t len)
1726{
1727    struct lsquic_stream *stream;
1728    stream_frame_t *stream_frame;
1729    enum enc_level enc_level;
1730    int parsed_len;
1731
1732    stream_frame = lsquic_malo_get(conn->fc_pub.mm->malo.stream_frame);
1733    if (!stream_frame)
1734    {
1735        LSQ_WARN("could not allocate stream frame: %s", strerror(errno));
1736        return 0;
1737    }
1738
1739    parsed_len = conn->fc_conn.cn_pf->pf_parse_crypto_frame(p, len,
1740                                                            stream_frame);
1741    if (parsed_len < 0)
1742    {
1743        lsquic_malo_put(stream_frame);
1744        return 0;
1745    }
1746    enc_level = lsquic_packet_in_enc_level(packet_in);
1747    EV_LOG_CRYPTO_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_frame, enc_level);
1748    LSQ_DEBUG("Got CRYPTO frame on enc level %s", lsquic_enclev2str[enc_level]);
1749
1750    if (enc_level < conn->fc_crypto_enc_level)
1751    {
1752        LSQ_DEBUG("Old enc level: ignore frame");
1753        lsquic_malo_put(stream_frame);
1754        return parsed_len;
1755    }
1756
1757    if (conn->fc_flags & FC_CLOSING)
1758    {
1759        LSQ_DEBUG("Connection closing: ignore frame");
1760        lsquic_malo_put(stream_frame);
1761        return parsed_len;
1762    }
1763
1764    stream = find_stream_by_id(conn, hsk_stream_id(conn));
1765    if (!stream)
1766    {
1767        LSQ_WARN("cannot find handshake stream for CRYPTO frame");
1768        lsquic_malo_put(stream_frame);
1769        return 0;
1770    }
1771
1772    if (enc_level > conn->fc_crypto_enc_level)
1773    {
1774        stream->read_offset = 0;
1775        stream->tosend_off = 0;
1776        conn->fc_crypto_enc_level = enc_level;
1777        LSQ_DEBUG("reset handshake stream offsets, new enc level %u",
1778                                                        (unsigned) enc_level);
1779    }
1780
1781    stream_frame->packet_in = lsquic_packet_in_get(packet_in);
1782    if (0 != lsquic_stream_frame_in(stream, stream_frame))
1783    {
1784        ABORT_ERROR("cannot insert stream frame");
1785        return 0;
1786    }
1787
1788    if ((stream->sm_qflags & SMQF_WANT_READ)
1789        && !(conn->fc_flags & FC_SERVER)
1790        && !(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE))
1791    {
1792        /* XXX what happens for server? */
1793        lsquic_stream_dispatch_read_events(stream);
1794    }
1795
1796    return parsed_len;
1797}
1798
1799
1800static unsigned
1801process_invalid_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1802                                            const unsigned char *p, size_t len)
1803{
1804    ABORT_ERROR("invalid frame");
1805    return 0;
1806}
1807
1808
1809/* Reset locally-initiated streams whose IDs is larger than the stream ID
1810 * specified in received GOAWAY frame.
1811 */
1812static void
1813reset_local_streams_over_goaway (struct full_conn *conn)
1814{
1815    const unsigned is_server = !!(conn->fc_flags & FC_SERVER);
1816    lsquic_stream_t *stream;
1817    struct lsquic_hash_elem *el;
1818
1819    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
1820                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
1821    {
1822        stream = lsquic_hashelem_getdata(el);
1823        if (stream->id > conn->fc_goaway_stream_id &&
1824            ((stream->id & 1) ^ is_server /* Locally initiated? */))
1825        {
1826            lsquic_stream_received_goaway(stream);
1827        }
1828    }
1829}
1830
1831
1832static unsigned
1833process_goaway_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1834                                            const unsigned char *p, size_t len)
1835{
1836    lsquic_stream_id_t stream_id;
1837    uint32_t error_code;
1838    uint16_t reason_length;
1839    const char *reason;
1840    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_goaway_frame(p, len,
1841                            &error_code, &stream_id, &reason_length, &reason);
1842    if (parsed_len < 0)
1843        return 0;
1844    EV_LOG_GOAWAY_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code, stream_id,
1845        reason_length, reason);
1846    LSQ_DEBUG("received GOAWAY frame, last good stream ID: %"PRIu64
1847        ", error code: 0x%X, reason: `%.*s'", stream_id, error_code,
1848        reason_length, reason);
1849    if (0 == (conn->fc_conn.cn_flags & LSCONN_PEER_GOING_AWAY))
1850    {
1851        conn->fc_conn.cn_flags |= LSCONN_PEER_GOING_AWAY;
1852        conn->fc_goaway_stream_id = stream_id;
1853        if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_goaway_received)
1854        {
1855            LSQ_DEBUG("calling on_goaway_received");
1856            conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_goaway_received(
1857                                            &conn->fc_conn);
1858        }
1859        else
1860            LSQ_DEBUG("on_goaway_received not registered");
1861        reset_local_streams_over_goaway(conn);
1862    }
1863    else
1864        LSQ_DEBUG("ignore duplicate GOAWAY frame");
1865    return parsed_len;
1866}
1867
1868
1869static void
1870log_invalid_ack_frame (struct full_conn *conn, const unsigned char *p,
1871                                int parsed_len, const struct ack_info *acki)
1872{
1873    char *buf;
1874
1875    buf = malloc(0x1000);
1876    if (!buf)
1877    {
1878        LSQ_WARN("malloc failed");
1879        return;
1880    }
1881
1882    lsquic_senhist_tostr(&conn->fc_send_ctl.sc_senhist, buf, 0x1000);
1883    LSQ_WARN("send history: %s", buf);
1884    lsquic_hexdump(p, parsed_len, buf, 0x1000);
1885    LSQ_WARN("raw ACK frame:\n%s", buf);
1886    lsquic_acki2str(acki, buf, 0x1000);
1887    LSQ_WARN("parsed ACK frame: %s", buf);
1888    free(buf);
1889}
1890
1891
1892static int
1893process_ack (struct full_conn *conn, struct ack_info *acki,
1894             lsquic_time_t received, lsquic_time_t now)
1895{
1896#if LSQUIC_CONN_STATS
1897    ++conn->fc_stats.in.n_acks_proc;
1898#endif
1899    LSQ_DEBUG("Processing ACK");
1900    if (0 == lsquic_send_ctl_got_ack(&conn->fc_send_ctl, acki, received, now))
1901    {
1902        if (lsquic_send_ctl_largest_ack2ed(&conn->fc_send_ctl, PNS_APP))
1903            lsquic_rechist_stop_wait(&conn->fc_rechist,
1904                lsquic_send_ctl_largest_ack2ed(&conn->fc_send_ctl, PNS_APP)
1905                                                                        + 1);
1906        return 0;
1907    }
1908    else
1909    {
1910        ABORT_ERROR("Received invalid ACK");
1911        return -1;
1912    }
1913}
1914
1915
1916static unsigned
1917process_ack_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1918                                            const unsigned char *p, size_t len)
1919{
1920    struct ack_info *new_acki;
1921    int parsed_len;
1922    lsquic_time_t warn_time;
1923
1924#if LSQUIC_CONN_STATS
1925    ++conn->fc_stats.in.n_acks;
1926#endif
1927
1928    if (conn->fc_flags & FC_HAVE_SAVED_ACK)
1929        new_acki = conn->fc_pub.mm->acki;
1930    else
1931        new_acki = &conn->fc_ack;
1932
1933    parsed_len = conn->fc_conn.cn_pf->pf_parse_ack_frame(p, len, new_acki, 0);
1934    if (parsed_len < 0)
1935        goto err;
1936
1937    if (empty_ack_frame(new_acki))
1938    {
1939        LSQ_DEBUG("Ignore empty ACK frame");
1940        return parsed_len;
1941    }
1942    if (packet_in->pi_packno <= conn->fc_max_ack_packno)
1943    {
1944        LSQ_DEBUG("Ignore old ack (max %"PRIu64")", conn->fc_max_ack_packno);
1945        return parsed_len;
1946    }
1947
1948    new_acki->pns = PNS_APP;
1949    EV_LOG_ACK_FRAME_IN(LSQUIC_LOG_CONN_ID, new_acki);
1950    conn->fc_max_ack_packno = packet_in->pi_packno;
1951
1952    if (new_acki == &conn->fc_ack)
1953    {
1954        LSQ_DEBUG("Saved ACK");
1955        conn->fc_flags |= FC_HAVE_SAVED_ACK;
1956        conn->fc_saved_ack_received = packet_in->pi_received;
1957    }
1958    else
1959    {
1960        if (0 == lsquic_merge_acks(&conn->fc_ack, new_acki))
1961        {
1962#if LSQUIC_CONN_STATS
1963            ++conn->fc_stats.in.n_acks_merged;
1964#endif
1965            LSQ_DEBUG("merged into saved ACK, getting %s",
1966                (lsquic_acki2str(&conn->fc_ack, conn->fc_pub.mm->ack_str,
1967                                MAX_ACKI_STR_SZ), conn->fc_pub.mm->ack_str));
1968        }
1969        else
1970        {
1971            LSQ_DEBUG("could not merge new ACK into saved ACK");
1972            if (0 != process_ack(conn, &conn->fc_ack, packet_in->pi_received,
1973                                                        packet_in->pi_received))
1974                goto err;
1975            conn->fc_ack = *new_acki;
1976        }
1977        conn->fc_saved_ack_received = packet_in->pi_received;
1978    }
1979
1980    return parsed_len;
1981
1982  err:
1983    warn_time = lsquic_time_now();
1984    if (0 == conn->fc_enpub->enp_last_warning[WT_ACKPARSE_FULL]
1985        || conn->fc_enpub->enp_last_warning[WT_ACKPARSE_FULL]
1986                + WARNING_INTERVAL < warn_time)
1987    {
1988        conn->fc_enpub->enp_last_warning[WT_ACKPARSE_FULL] = warn_time;
1989        log_invalid_ack_frame(conn, p, parsed_len, new_acki);
1990    }
1991    return 0;
1992}
1993
1994
1995static unsigned
1996process_stop_waiting_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1997                                            const unsigned char *p, size_t len)
1998{
1999    lsquic_packno_t least, cutoff;
2000    enum packno_bits bits;
2001    int parsed_len;
2002
2003    bits = lsquic_packet_in_packno_bits(packet_in);
2004
2005    if (conn->fc_flags & FC_NSTP)
2006    {
2007        LSQ_DEBUG("NSTP on: ignore STOP_WAITING frame");
2008        parsed_len = conn->fc_conn.cn_pf->pf_skip_stop_waiting_frame(len, bits);
2009        if (parsed_len > 0)
2010            return (unsigned) parsed_len;
2011        else
2012            return 0;
2013    }
2014
2015    parsed_len = conn->fc_conn.cn_pf->pf_parse_stop_waiting_frame(p, len,
2016                                            packet_in->pi_packno, bits, &least);
2017    if (parsed_len < 0)
2018        return 0;
2019
2020    if (packet_in->pi_packno <= conn->fc_max_swf_packno)
2021    {
2022        LSQ_DEBUG("ignore old STOP_WAITING frame");
2023        return parsed_len;
2024    }
2025
2026    LSQ_DEBUG("Got STOP_WAITING frame, least unacked: %"PRIu64, least);
2027    EV_LOG_STOP_WAITING_FRAME_IN(LSQUIC_LOG_CONN_ID, least);
2028
2029    if (least > packet_in->pi_packno)
2030    {
2031        ABORT_ERROR("received invalid STOP_WAITING: %"PRIu64" is larger "
2032            "than the packet number%"PRIu64, least, packet_in->pi_packno);
2033        return 0;
2034    }
2035
2036    cutoff = lsquic_rechist_cutoff(&conn->fc_rechist);
2037    if (cutoff && least < cutoff)
2038    {
2039        ABORT_ERROR("received invalid STOP_WAITING: %"PRIu64" is smaller "
2040            "than the cutoff %"PRIu64, least, cutoff);
2041        return 0;
2042    }
2043
2044    conn->fc_max_swf_packno = packet_in->pi_packno;
2045    lsquic_rechist_stop_wait(&conn->fc_rechist, least);
2046    return parsed_len;
2047}
2048
2049
2050static unsigned
2051process_blocked_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2052                                            const unsigned char *p, size_t len)
2053{
2054    lsquic_stream_id_t stream_id;
2055    struct lsquic_stream *stream;
2056    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_blocked_frame(p, len,
2057                                                                    &stream_id);
2058    if (parsed_len < 0)
2059        return 0;
2060    EV_LOG_BLOCKED_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id);
2061    LSQ_DEBUG("Peer reports stream %"PRIu64" as blocked", stream_id);
2062    if (stream_id)
2063    {
2064        stream = find_stream_by_id(conn, stream_id);
2065        if (stream)
2066            lsquic_stream_peer_blocked_gquic(stream);
2067    }
2068    else
2069        conn->fc_flags |= FC_SEND_WUF;
2070    return parsed_len;
2071}
2072
2073
2074static unsigned
2075process_connection_close_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2076                                const unsigned char *p, size_t len)
2077{
2078    lsquic_stream_t *stream;
2079    struct lsquic_hash_elem *el;
2080    uint64_t error_code;
2081    uint16_t reason_len;
2082    uint8_t reason_off;
2083    int parsed_len;
2084
2085    parsed_len = conn->fc_conn.cn_pf->pf_parse_connect_close_frame(p, len,
2086                                NULL, &error_code, &reason_len, &reason_off);
2087    if (parsed_len < 0)
2088        return 0;
2089    EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code,
2090                            (int) reason_len, (const char *) p + reason_off);
2091    LSQ_INFO("Received CONNECTION_CLOSE frame (code: %"PRIu64"; reason: %.*s)",
2092                error_code, (int) reason_len, (const char *) p + reason_off);
2093    conn->fc_flags |= FC_RECV_CLOSE;
2094    if (!(conn->fc_flags & FC_CLOSING))
2095    {
2096        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
2097                                     el = lsquic_hash_next(conn->fc_pub.all_streams))
2098        {
2099            stream = lsquic_hashelem_getdata(el);
2100            lsquic_stream_shutdown_internal(stream);
2101        }
2102        conn->fc_flags |= FC_CLOSING;
2103    }
2104    return parsed_len;
2105}
2106
2107
2108static unsigned
2109process_rst_stream_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2110                                            const unsigned char *p, size_t len)
2111{
2112    lsquic_stream_id_t stream_id;
2113    uint64_t offset, error_code;
2114    lsquic_stream_t *stream;
2115    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_rst_frame(p, len,
2116                                            &stream_id, &offset, &error_code);
2117    if (parsed_len < 0)
2118        return 0;
2119
2120    EV_LOG_RST_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset,
2121                                                                error_code);
2122    LSQ_DEBUG("Got RST_STREAM; stream: %"PRIu64"; offset: 0x%"PRIX64, stream_id,
2123                                                                    offset);
2124    if (0 == stream_id)
2125    {   /* Follow reference implementation and ignore this apparently
2126         * invalid frame.
2127         */
2128        return parsed_len;
2129    }
2130
2131    stream = find_stream_by_id(conn, stream_id);
2132    if (stream && lsquic_stream_is_critical(stream))
2133    {
2134        ABORT_ERROR("received reset on static stream %"PRIu64, stream_id);
2135        return 0;
2136    }
2137    if (!stream)
2138    {
2139        if (conn_is_stream_closed(conn, stream_id))
2140        {
2141            LSQ_DEBUG("got reset frame for closed stream %"PRIu64, stream_id);
2142            return parsed_len;
2143        }
2144        if (!is_peer_initiated(conn, stream_id))
2145        {
2146            ABORT_ERROR("received reset for never-initiated stream %"PRIu64,
2147                                                                    stream_id);
2148            return 0;
2149        }
2150        stream = new_stream(conn, stream_id, SCF_CALL_ON_NEW);
2151        if (!stream)
2152        {
2153            ABORT_ERROR("cannot create new stream: %s", strerror(errno));
2154            return 0;
2155        }
2156        if (stream_id > conn->fc_max_peer_stream_id)
2157            conn->fc_max_peer_stream_id = stream_id;
2158    }
2159
2160    if (0 != lsquic_stream_rst_in(stream, offset, error_code))
2161    {
2162        ABORT_ERROR("received invalid RST_STREAM");
2163        return 0;
2164    }
2165    return parsed_len;
2166}
2167
2168
2169static unsigned
2170process_window_update_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2171                                             const unsigned char *p, size_t len)
2172{
2173    lsquic_stream_id_t stream_id;
2174    uint64_t offset;
2175    const int parsed_len =
2176                conn->fc_conn.cn_pf->pf_parse_window_update_frame(p, len,
2177                                                        &stream_id, &offset);
2178    if (parsed_len < 0)
2179        return 0;
2180    EV_LOG_WINDOW_UPDATE_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset);
2181    if (stream_id)
2182    {
2183        lsquic_stream_t *stream = find_stream_by_id(conn, stream_id);
2184        if (stream)
2185        {
2186            LSQ_DEBUG("Got window update frame, stream: %"PRIu64
2187                      "; offset: 0x%"PRIX64, stream_id, offset);
2188            lsquic_stream_window_update(stream, offset);
2189        }
2190        else    /* Perhaps a result of lost packets? */
2191            LSQ_DEBUG("Got window update frame for non-existing stream %"PRIu64
2192                                 " (offset: 0x%"PRIX64")", stream_id, offset);
2193    }
2194    else if (offset > conn->fc_pub.conn_cap.cc_max)
2195    {
2196        conn->fc_pub.conn_cap.cc_max = offset;
2197        assert(conn->fc_pub.conn_cap.cc_max >= conn->fc_pub.conn_cap.cc_sent);
2198        LSQ_DEBUG("Connection WUF, new offset 0x%"PRIX64, offset);
2199    }
2200    else
2201        LSQ_DEBUG("Throw ouw duplicate connection WUF");
2202    return parsed_len;
2203}
2204
2205
2206typedef unsigned (*process_frame_f)(
2207    struct full_conn *, lsquic_packet_in_t *, const unsigned char *p, size_t);
2208
2209static process_frame_f const process_frames[N_QUIC_FRAMES] =
2210{
2211    [QUIC_FRAME_ACK]                  =  process_ack_frame,
2212    [QUIC_FRAME_BLOCKED]              =  process_blocked_frame,
2213    [QUIC_FRAME_CONNECTION_CLOSE]     =  process_connection_close_frame,
2214    [QUIC_FRAME_CRYPTO]               =  process_crypto_frame,
2215    [QUIC_FRAME_GOAWAY]               =  process_goaway_frame,
2216    [QUIC_FRAME_INVALID]              =  process_invalid_frame,
2217    [QUIC_FRAME_PADDING]              =  process_padding_frame,
2218    [QUIC_FRAME_PING]                 =  process_ping_frame,
2219    [QUIC_FRAME_RST_STREAM]           =  process_rst_stream_frame,
2220    [QUIC_FRAME_STOP_WAITING]         =  process_stop_waiting_frame,
2221    [QUIC_FRAME_STREAM]               =  process_stream_frame,
2222    [QUIC_FRAME_WINDOW_UPDATE]        =  process_window_update_frame,
2223};
2224
2225static unsigned
2226process_packet_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2227                      const unsigned char *p, size_t len)
2228{
2229    enum quic_frame_type type;
2230
2231    type = conn->fc_conn.cn_pf->pf_parse_frame_type(p, len);
2232    packet_in->pi_frame_types |= 1 << type;
2233    recent_packet_hist_frames(conn, 0, 1 << type);
2234    return process_frames[type](conn, packet_in, p, len);
2235}
2236
2237
2238static void
2239process_ver_neg_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2240{
2241    int s;
2242    struct ver_iter vi;
2243    lsquic_ver_tag_t ver_tag;
2244    enum lsquic_version version;
2245    unsigned versions = 0;
2246
2247    LSQ_DEBUG("Processing version-negotiation packet");
2248
2249    if (conn->fc_ver_neg.vn_state != VN_START)
2250    {
2251        LSQ_DEBUG("ignore a likely duplicate version negotiation packet");
2252        return;
2253    }
2254
2255    for (s = lsquic_packet_in_ver_first(packet_in, &vi, &ver_tag); s;
2256                     s = lsquic_packet_in_ver_next(&vi, &ver_tag))
2257    {
2258        version = lsquic_tag2ver(ver_tag);
2259        if (version < N_LSQVER)
2260        {
2261            versions |= 1 << version;
2262            LSQ_DEBUG("server supports version %s", lsquic_ver2str[version]);
2263            EV_LOG_VER_NEG(LSQUIC_LOG_CONN_ID,
2264                                        "supports", lsquic_ver2str[version]);
2265        }
2266    }
2267
2268    if (versions & (1 << conn->fc_ver_neg.vn_ver))
2269    {
2270        ABORT_ERROR("server replied with version we support: %s",
2271                                    lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
2272        return;
2273    }
2274
2275    versions &= conn->fc_ver_neg.vn_supp;
2276    if (0 == versions)
2277    {
2278        ABORT_ERROR("client does not support any of the server-specified "
2279                    "versions");
2280        return;
2281    }
2282
2283    set_versions(conn, versions, NULL);
2284    conn->fc_ver_neg.vn_state = VN_IN_PROGRESS;
2285    lsquic_send_ctl_expire_all(&conn->fc_send_ctl);
2286}
2287
2288
2289static void
2290reconstruct_packet_number (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2291{
2292    lsquic_packno_t cur_packno, max_packno;
2293    enum packno_bits bits;
2294    unsigned packet_len;
2295
2296    cur_packno = packet_in->pi_packno;
2297    max_packno = lsquic_rechist_largest_packno(&conn->fc_rechist);
2298    bits = lsquic_packet_in_packno_bits(packet_in);
2299    packet_len = conn->fc_conn.cn_pf->pf_packno_bits2len(bits);
2300    packet_in->pi_packno = lsquic_restore_packno(cur_packno, packet_len,
2301                                                                max_packno);
2302    LSQ_DEBUG("reconstructed (bits: %u, packno: %"PRIu64", max: %"PRIu64") "
2303        "to %"PRIu64"", bits, cur_packno, max_packno, packet_in->pi_packno);
2304}
2305
2306
2307static enum dec_packin
2308conn_decrypt_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2309{
2310    return conn->fc_conn.cn_esf_c->esf_decrypt_packet(
2311                    conn->fc_conn.cn_enc_session, conn->fc_enpub,
2312                    &conn->fc_conn, packet_in);
2313}
2314
2315
2316static void
2317parse_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2318{
2319    const unsigned char *p, *pend;
2320    unsigned len;
2321
2322    p = packet_in->pi_data + packet_in->pi_header_sz;
2323    pend = packet_in->pi_data + packet_in->pi_data_sz;
2324
2325    while (p < pend)
2326    {
2327        len = process_packet_frame(conn, packet_in, p, pend - p);
2328        if (len > 0)
2329            p += len;
2330        else
2331        {
2332            ABORT_ERROR("Error parsing frame");
2333            break;
2334        }
2335    }
2336}
2337
2338
2339static int
2340conn_is_stateless_reset (const struct full_conn *conn,
2341                                    const struct lsquic_packet_in *packet_in)
2342{
2343    return packet_in->pi_data_sz > SRST_LENGTH
2344        && 0 == conn->fc_conn.cn_esf_c->esf_verify_reset_token(
2345                    conn->fc_conn.cn_enc_session,
2346                    packet_in->pi_data + packet_in->pi_data_sz - SRST_LENGTH,
2347                    SRST_LENGTH);
2348}
2349
2350
2351static int
2352process_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2353{
2354    enum received_st st;
2355    enum quic_ft_bit frame_types;
2356    int was_missing;
2357
2358    if (conn->fc_conn.cn_version < LSQVER_050)
2359    {
2360        reconstruct_packet_number(conn, packet_in);
2361        EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
2362    }
2363
2364#if LSQUIC_CONN_STATS
2365    ++conn->fc_stats.in.packets;
2366#endif
2367
2368    /* The packet is decrypted before receive history is updated.  This is
2369     * done to make sure that a bad packet won't occupy a slot in receive
2370     * history and subsequent good packet won't be marked as a duplicate.
2371     */
2372    if (0 == (packet_in->pi_flags & PI_DECRYPTED) &&
2373        DECPI_OK != conn_decrypt_packet(conn, packet_in))
2374    {
2375        if (conn_is_stateless_reset(conn, packet_in))
2376        {
2377            LSQ_INFO("received public reset packet: aborting connection");
2378            conn->fc_flags |= FC_GOT_PRST;
2379            return -1;
2380        }
2381        else
2382        {
2383            LSQ_INFO("could not decrypt packet");
2384#if LSQUIC_CONN_STATS
2385            ++conn->fc_stats.in.undec_packets;
2386#endif
2387            return 0;
2388        }
2389    }
2390
2391    if (conn->fc_conn.cn_version >= LSQVER_050)
2392        EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
2393
2394    st = lsquic_rechist_received(&conn->fc_rechist, packet_in->pi_packno,
2395                                                    packet_in->pi_received);
2396    switch (st) {
2397    case REC_ST_OK:
2398        parse_regular_packet(conn, packet_in);
2399        if (0 == (conn->fc_flags & (FC_ACK_QUEUED|FC_GOT_SREJ)))
2400        {
2401            frame_types = packet_in->pi_frame_types;
2402            if ((conn->fc_flags & FC_GOING_AWAY)
2403                && lsquic_hash_count(conn->fc_pub.all_streams) < 3)
2404            {
2405                /* Ignore PING frames if we are going away and there are no
2406                 * active streams.  (HANDSHAKE and HEADERS streams are the
2407                 * two streams that are always in the all_streams hash).
2408                 */
2409                frame_types &= ~(1 << QUIC_FRAME_PING);
2410            }
2411            was_missing = packet_in->pi_packno !=
2412                            lsquic_rechist_largest_packno(&conn->fc_rechist);
2413            conn->fc_n_slack_akbl += !!(frame_types & GQUIC_FRAME_ACKABLE_MASK);
2414            try_queueing_ack(conn, was_missing, packet_in->pi_received);
2415        }
2416        else if (conn->fc_flags & FC_GOT_SREJ)
2417            conn->fc_flags &= ~FC_GOT_SREJ;
2418        return 0;
2419    case REC_ST_DUP:
2420#if LSQUIC_CONN_STATS
2421        ++conn->fc_stats.in.dup_packets;
2422#endif
2423        LSQ_INFO("packet %"PRIu64" is a duplicate", packet_in->pi_packno);
2424        return 0;
2425    default:
2426        assert(0);
2427        /* Fall through */
2428    case REC_ST_ERR:
2429#if LSQUIC_CONN_STATS
2430        ++conn->fc_stats.in.err_packets;
2431#endif
2432        LSQ_INFO("error processing packet %"PRIu64, packet_in->pi_packno);
2433        return -1;
2434    }
2435}
2436
2437
2438/* TODO: Possible optimization: in server mode, we do not perform version
2439 * negotiation.  We can use different functions in client mode (this
2440 * function) and server mode (a different, faster function that ignores
2441 * version flags).
2442 */
2443static int
2444process_incoming_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2445{
2446    int is_prst, is_verneg;
2447
2448    recent_packet_hist_new(conn, 0, packet_in->pi_received);
2449    LSQ_DEBUG("Processing packet %"PRIu64, packet_in->pi_packno);
2450
2451    is_prst = lsquic_packet_in_is_gquic_prst(packet_in);
2452    is_verneg = lsquic_packet_in_is_verneg(packet_in);
2453
2454    /* See flowchart in Section 4.1 of [draft-ietf-quic-transport-00].  We test
2455     * for the common case first.
2456     */
2457    if (0 == is_prst && 0 == is_verneg)
2458    {
2459        if (conn->fc_ver_neg.vn_tag)
2460        {
2461            assert(conn->fc_ver_neg.vn_state != VN_END);
2462            conn->fc_ver_neg.vn_state = VN_END;
2463            conn->fc_ver_neg.vn_tag = NULL;
2464            conn->fc_conn.cn_version = conn->fc_ver_neg.vn_ver;
2465            conn->fc_conn.cn_flags |= LSCONN_VER_SET;
2466            assert(!(conn->fc_flags & FC_NSTP)); /* This bit off at start */
2467            if (conn->fc_conn.cn_version >= LSQVER_046
2468                                    || conn->fc_settings->es_support_nstp)
2469            {
2470                conn->fc_flags |= FC_NSTP;
2471                lsquic_send_ctl_turn_nstp_on(&conn->fc_send_ctl);
2472            }
2473            LSQ_DEBUG("end of version negotiation: agreed upon %s",
2474                                    lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
2475            lsquic_send_ctl_verneg_done(&conn->fc_send_ctl);
2476            EV_LOG_VER_NEG(LSQUIC_LOG_CONN_ID,
2477                            "agreed", lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
2478        }
2479        return process_regular_packet(conn, packet_in);
2480    }
2481    else if (is_prst)
2482    {
2483        LSQ_INFO("received public reset packet: aborting connection");
2484        conn->fc_flags |= FC_GOT_PRST;
2485        return -1;
2486    }
2487    else
2488    {
2489        if (conn->fc_flags & FC_SERVER)
2490            return process_regular_packet(conn, packet_in);
2491        else if (conn->fc_ver_neg.vn_tag)
2492        {
2493            process_ver_neg_packet(conn, packet_in);
2494            return 0;
2495        }
2496        else
2497        {
2498            LSQ_DEBUG("unexpected version negotiation packet: ignore it");
2499            return 0;
2500        }
2501    }
2502}
2503
2504
2505static void
2506idle_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
2507                                                            lsquic_time_t now)
2508{
2509    struct full_conn *conn = ctx;
2510
2511    if ((conn->fc_flags & FC_NOPROG_TIMEOUT)
2512        && conn->fc_pub.last_prog + conn->fc_enpub->enp_noprog_timeout < now)
2513    {
2514        LSQ_DEBUG("connection timed out due to lack of progress");
2515        EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out due to "
2516                                                            "lack of progress");
2517        /* Different flag so that CONNECTION_CLOSE frame is sent */
2518        conn->fc_flags |= FC_ABORTED;
2519    }
2520    else
2521    {
2522        LSQ_DEBUG("connection timed out");
2523        EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out");
2524        conn->fc_flags |= FC_TIMED_OUT;
2525    }
2526}
2527
2528
2529static void
2530handshake_alarm_expired (enum alarm_id al_id, void *ctx,
2531                                    lsquic_time_t expiry, lsquic_time_t now)
2532{
2533    struct full_conn *conn = ctx;
2534    LSQ_DEBUG("connection timed out: handshake timed out");
2535    conn->fc_flags |= FC_TIMED_OUT;
2536}
2537
2538
2539static void
2540ping_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
2541                                                            lsquic_time_t now)
2542{
2543    struct full_conn *conn = ctx;
2544    LSQ_DEBUG("Ping alarm rang: schedule PING frame to be generated");
2545    conn->fc_flags |= FC_SEND_PING;
2546}
2547
2548
2549static lsquic_packet_out_t *
2550get_writeable_packet (struct full_conn *conn, unsigned need_at_least)
2551{
2552    lsquic_packet_out_t *packet_out;
2553    int is_err;
2554
2555    packet_out = lsquic_send_ctl_get_writeable_packet(&conn->fc_send_ctl,
2556                            PNS_APP, need_at_least, &conn->fc_path, 0, &is_err);
2557    if (!packet_out && is_err)
2558        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2559    return packet_out;
2560}
2561
2562
2563static int
2564generate_wuf_stream (struct full_conn *conn, lsquic_stream_t *stream)
2565{
2566    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, GQUIC_WUF_SZ);
2567    if (!packet_out)
2568        return 0;
2569    const uint64_t recv_off = lsquic_stream_fc_recv_off(stream);
2570    int sz = conn->fc_conn.cn_pf->pf_gen_window_update_frame(
2571                packet_out->po_data + packet_out->po_data_sz,
2572                     lsquic_packet_out_avail(packet_out), stream->id, recv_off);
2573    if (sz < 0) {
2574        ABORT_ERROR("gen_window_update_frame failed");
2575        return 0;
2576    }
2577    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2578    packet_out->po_frame_types |= 1 << QUIC_FRAME_WINDOW_UPDATE;
2579    LSQ_DEBUG("wrote WUF: stream %"PRIu64"; offset 0x%"PRIX64, stream->id,
2580                                                                    recv_off);
2581    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID,
2582        "wrote WUF: stream %"PRIu64"; offset 0x%"PRIX64, stream->id, recv_off);
2583    return 1;
2584}
2585
2586
2587static void
2588generate_wuf_conn (struct full_conn *conn)
2589{
2590    assert(conn->fc_flags & FC_SEND_WUF);
2591    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, GQUIC_WUF_SZ);
2592    if (!packet_out)
2593        return;
2594    const uint64_t recv_off = lsquic_cfcw_get_fc_recv_off(&conn->fc_pub.cfcw);
2595    int sz = conn->fc_conn.cn_pf->pf_gen_window_update_frame(
2596                     packet_out->po_data + packet_out->po_data_sz,
2597                     lsquic_packet_out_avail(packet_out), 0, recv_off);
2598    if (sz < 0) {
2599        ABORT_ERROR("gen_window_update_frame failed");
2600        return;
2601    }
2602    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2603    packet_out->po_frame_types |= 1 << QUIC_FRAME_WINDOW_UPDATE;
2604    conn->fc_flags &= ~FC_SEND_WUF;
2605    LSQ_DEBUG("wrote connection WUF: offset 0x%"PRIX64, recv_off);
2606}
2607
2608
2609static void
2610maybe_close_conn (struct full_conn *conn)
2611{
2612#ifndef NDEBUG
2613    struct lsquic_stream *stream;
2614    struct lsquic_hash_elem *el;
2615#endif
2616
2617    if ((conn->fc_flags & (FC_CLOSING|FC_GOAWAY_SENT|FC_SERVER))
2618                                            == (FC_GOAWAY_SENT|FC_SERVER)
2619        && lsquic_hash_count(conn->fc_pub.all_streams) == 2)
2620    {
2621#ifndef NDEBUG
2622        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
2623                             el = lsquic_hash_next(conn->fc_pub.all_streams))
2624        {
2625            stream = lsquic_hashelem_getdata(el);
2626            assert(stream->sm_bflags & (SMBF_CRYPTO|SMBF_HEADERS));
2627        }
2628#endif
2629        conn->fc_flags |= FC_RECV_CLOSE;    /* Fake -- trigger "ok to close" */
2630        conn->fc_flags |= FC_CLOSING;
2631        LSQ_DEBUG("closing connection: GOAWAY sent and no responses remain");
2632    }
2633}
2634
2635
2636static void
2637generate_goaway_frame (struct full_conn *conn)
2638{
2639    int reason_len = 0;
2640    lsquic_packet_out_t *packet_out =
2641        get_writeable_packet(conn, GQUIC_GOAWAY_FRAME_SZ + reason_len);
2642    if (!packet_out)
2643        return;
2644    int sz = conn->fc_conn.cn_pf->pf_gen_goaway_frame(
2645                 packet_out->po_data + packet_out->po_data_sz,
2646                 lsquic_packet_out_avail(packet_out), 0, conn->fc_max_peer_stream_id,
2647                 NULL, reason_len);
2648    if (sz < 0) {
2649        ABORT_ERROR("gen_goaway_frame failed");
2650        return;
2651    }
2652    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2653    packet_out->po_frame_types |= 1 << QUIC_FRAME_GOAWAY;
2654    conn->fc_flags &= ~FC_SEND_GOAWAY;
2655    conn->fc_flags |=  FC_GOAWAY_SENT;
2656    LSQ_DEBUG("wrote GOAWAY frame: stream id: %"PRIu64,
2657                                                conn->fc_max_peer_stream_id);
2658    maybe_close_conn(conn);
2659}
2660
2661
2662static void
2663generate_connection_close_packet (struct full_conn *conn)
2664{
2665    lsquic_packet_out_t *packet_out;
2666
2667    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0, PNS_APP,
2668                                                                &conn->fc_path);
2669    if (!packet_out)
2670    {
2671        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2672        return;
2673    }
2674
2675    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
2676    int sz = conn->fc_conn.cn_pf->pf_gen_connect_close_frame(packet_out->po_data + packet_out->po_data_sz,
2677                     lsquic_packet_out_avail(packet_out), 0, 16 /* PEER_GOING_AWAY */,
2678                     NULL, 0);
2679    if (sz < 0) {
2680        ABORT_ERROR("generate_connection_close_packet failed");
2681        return;
2682    }
2683    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2684    packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
2685    LSQ_DEBUG("generated CONNECTION_CLOSE frame in its own packet");
2686}
2687
2688
2689static int
2690generate_blocked_frame (struct full_conn *conn, lsquic_stream_id_t stream_id)
2691{
2692    lsquic_packet_out_t *packet_out =
2693                            get_writeable_packet(conn, GQUIC_BLOCKED_FRAME_SZ);
2694    if (!packet_out)
2695        return 0;
2696    int sz = conn->fc_conn.cn_pf->pf_gen_blocked_frame(
2697                                 packet_out->po_data + packet_out->po_data_sz,
2698                                 lsquic_packet_out_avail(packet_out), stream_id);
2699    if (sz < 0) {
2700        ABORT_ERROR("gen_blocked_frame failed");
2701        return 0;
2702    }
2703    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2704    packet_out->po_frame_types |= 1 << QUIC_FRAME_BLOCKED;
2705    LSQ_DEBUG("wrote blocked frame: stream %"PRIu64, stream_id);
2706    return 1;
2707}
2708
2709
2710static int
2711generate_stream_blocked_frame (struct full_conn *conn, lsquic_stream_t *stream)
2712{
2713    if (generate_blocked_frame(conn, stream->id))
2714    {
2715        lsquic_stream_blocked_frame_sent(stream);
2716        return 1;
2717    }
2718    else
2719        return 0;
2720}
2721
2722
2723static int
2724generate_rst_stream_frame (struct full_conn *conn, lsquic_stream_t *stream)
2725{
2726    lsquic_packet_out_t *packet_out;
2727    int sz, s;
2728
2729    packet_out = get_writeable_packet(conn, GQUIC_RST_STREAM_SZ);
2730    if (!packet_out)
2731        return 0;
2732    /* TODO Possible optimization: instead of using stream->tosend_off as the
2733     * offset, keep track of the offset that was actually sent: include it
2734     * into frame_rec and update a new per-stream "maximum offset actually
2735     * sent" field.  Then, if a stream is reset, the connection cap can be
2736     * increased.
2737     */
2738    sz = conn->fc_conn.cn_pf->pf_gen_rst_frame(
2739                     packet_out->po_data + packet_out->po_data_sz,
2740                     lsquic_packet_out_avail(packet_out), stream->id,
2741                     stream->tosend_off, stream->error_code);
2742    if (sz < 0) {
2743        ABORT_ERROR("gen_rst_frame failed");
2744        return 0;
2745    }
2746    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2747    packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
2748    s = lsquic_packet_out_add_stream(packet_out, conn->fc_pub.mm, stream,
2749                             QUIC_FRAME_RST_STREAM, packet_out->po_data_sz, sz);
2750    if (s != 0)
2751    {
2752        ABORT_ERROR("adding stream to packet failed: %s", strerror(errno));
2753        return 0;
2754    }
2755    lsquic_stream_rst_frame_sent(stream);
2756    LSQ_DEBUG("wrote RST: stream %"PRIu64"; offset 0x%"PRIX64"; error code "
2757              "%"PRIu64, stream->id, stream->tosend_off, stream->error_code);
2758    return 1;
2759}
2760
2761
2762static void
2763generate_ping_frame (struct full_conn *conn)
2764{
2765    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, 1);
2766    if (!packet_out)
2767    {
2768        LSQ_DEBUG("cannot get writeable packet for PING frame");
2769        return;
2770    }
2771    int sz = conn->fc_conn.cn_pf->pf_gen_ping_frame(
2772                            packet_out->po_data + packet_out->po_data_sz,
2773                            lsquic_packet_out_avail(packet_out));
2774    if (sz < 0) {
2775        ABORT_ERROR("gen_blocked_frame failed");
2776        return;
2777    }
2778    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2779    packet_out->po_frame_types |= 1 << QUIC_FRAME_PING;
2780    LSQ_DEBUG("wrote PING frame");
2781    if (!(conn->fc_flags & FC_SERVER))
2782        log_conn_flow_control(conn);
2783}
2784
2785
2786static void
2787generate_stop_waiting_frame (struct full_conn *conn)
2788{
2789    assert(conn->fc_flags & FC_SEND_STOP_WAITING);
2790
2791    int sz;
2792    unsigned packnum_len;
2793    lsquic_packno_t least_unacked;
2794    lsquic_packet_out_t *packet_out;
2795
2796    /* Get packet that has room for the minimum size STOP_WAITING frame: */
2797    packnum_len = conn->fc_conn.cn_pf->pf_packno_bits2len(GQUIC_PACKNO_LEN_1);
2798    packet_out = get_writeable_packet(conn, 1 + packnum_len);
2799    if (!packet_out)
2800        return;
2801
2802    /* Now calculate number of bytes we really need.  If there is not enough
2803     * room in the current packet, get a new one.
2804     */
2805    packnum_len = conn->fc_conn.cn_pf->pf_packno_bits2len(
2806                                    lsquic_packet_out_packno_bits(packet_out));
2807    if ((unsigned) lsquic_packet_out_avail(packet_out) < 1 + packnum_len)
2808    {
2809        packet_out = get_writeable_packet(conn, 1 + packnum_len);
2810        if (!packet_out)
2811            return;
2812        /* Here, a new packet has been allocated, The number of bytes needed
2813         * to represent packet number in the STOP_WAITING frame may have
2814         * increased.  However, this does not matter, because the newly
2815         * allocated packet must have room for a STOP_WAITING frame of any
2816         * size.
2817         */
2818    }
2819
2820    least_unacked = lsquic_send_ctl_smallest_unacked(&conn->fc_send_ctl);
2821    sz = conn->fc_conn.cn_pf->pf_gen_stop_waiting_frame(
2822                    packet_out->po_data + packet_out->po_data_sz,
2823                    lsquic_packet_out_avail(packet_out), packet_out->po_packno,
2824                    lsquic_packet_out_packno_bits(packet_out), least_unacked);
2825    if (sz < 0) {
2826        ABORT_ERROR("gen_stop_waiting_frame failed");
2827        return;
2828    }
2829    if (0 != lsquic_packet_out_add_frame(packet_out, conn->fc_pub.mm, 0,
2830                        QUIC_FRAME_STOP_WAITING, packet_out->po_data_sz, sz))
2831    {
2832        ABORT_ERROR("adding frame to packet failed: %d", errno);
2833        return;
2834    }
2835    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2836    packet_out->po_regen_sz += sz;
2837    packet_out->po_frame_types |= 1 << QUIC_FRAME_STOP_WAITING;
2838    conn->fc_flags &= ~FC_SEND_STOP_WAITING;
2839    LSQ_DEBUG("wrote STOP_WAITING frame: least unacked: %"PRIu64,
2840                                                            least_unacked);
2841    EV_LOG_GENERATED_STOP_WAITING_FRAME(LSQUIC_LOG_CONN_ID, least_unacked);
2842}
2843
2844
2845static int
2846process_stream_ready_to_send (struct full_conn *conn, lsquic_stream_t *stream)
2847{
2848    int r = 1;
2849    if (stream->sm_qflags & SMQF_SEND_WUF)
2850        r &= generate_wuf_stream(conn, stream);
2851    if (stream->sm_qflags & SMQF_SEND_BLOCKED)
2852        r &= generate_stream_blocked_frame(conn, stream);
2853    if (stream->sm_qflags & SMQF_SEND_RST)
2854        r &= generate_rst_stream_frame(conn, stream);
2855    return r;
2856}
2857
2858
2859static void
2860process_streams_ready_to_send (struct full_conn *conn)
2861{
2862    lsquic_stream_t *stream;
2863    struct stream_prio_iter spi;
2864
2865    assert(!TAILQ_EMPTY(&conn->fc_pub.sending_streams));
2866
2867    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.sending_streams),
2868        TAILQ_LAST(&conn->fc_pub.sending_streams, lsquic_streams_tailq),
2869        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_send_stream),
2870        &conn->fc_conn, "send", NULL, NULL);
2871
2872    for (stream = lsquic_spi_first(&spi); stream;
2873                                            stream = lsquic_spi_next(&spi))
2874        if (!process_stream_ready_to_send(conn, stream))
2875            break;
2876}
2877
2878
2879/* Return true if packetized, false otherwise */
2880static int
2881packetize_standalone_stream_reset (struct full_conn *conn, lsquic_stream_id_t stream_id)
2882{
2883    lsquic_packet_out_t *packet_out;
2884    int sz;
2885
2886    packet_out = get_writeable_packet(conn, GQUIC_RST_STREAM_SZ);
2887    if (!packet_out)
2888        return 0;
2889
2890    sz = conn->fc_conn.cn_pf->pf_gen_rst_frame(
2891                     packet_out->po_data + packet_out->po_data_sz,
2892                     lsquic_packet_out_avail(packet_out), stream_id,
2893                     0, 0x10 /* QUIC_PEER_GOING_AWAY */);
2894    if (sz < 0) {
2895        ABORT_ERROR("gen_rst_frame failed");
2896        return 0;
2897    }
2898    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2899    packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
2900    LSQ_DEBUG("generated standalone RST_STREAM frame for stream %"PRIu64,
2901                                                                    stream_id);
2902    return 1;
2903}
2904
2905
2906static void
2907packetize_standalone_stream_resets (struct full_conn *conn)
2908{
2909    struct stream_id_to_reset *sitr;
2910
2911    while ((sitr = STAILQ_FIRST(&conn->fc_stream_ids_to_reset)))
2912        if (packetize_standalone_stream_reset(conn, sitr->sitr_stream_id))
2913        {
2914            STAILQ_REMOVE_HEAD(&conn->fc_stream_ids_to_reset, sitr_next);
2915            free(sitr);
2916        }
2917        else
2918            break;
2919}
2920
2921
2922static void
2923create_delayed_streams (struct full_conn *conn)
2924{
2925    unsigned stream_count, avail, i;
2926    struct lsquic_stream **new_streams;
2927
2928    stream_count = count_streams(conn, 0);
2929
2930    if (stream_count >= conn->fc_cfg.max_streams_out)
2931        return;
2932
2933    avail = conn->fc_cfg.max_streams_out - stream_count;
2934    if (conn->fc_n_delayed_streams < avail)
2935        avail = conn->fc_n_delayed_streams;
2936    if (avail == 0)
2937	return;
2938
2939    new_streams = malloc(sizeof(new_streams[0]) * avail);
2940    if (!new_streams)
2941    {
2942        ABORT_WARN("%s: malloc failed", __func__);
2943        return;
2944    }
2945
2946    LSQ_DEBUG("creating delayed streams");
2947    for (i = 0; i < avail; ++i)
2948    {
2949        /* Delay calling on_new in order not to let the user screw up
2950         * the counts by making more streams.
2951         */
2952        new_streams[i] = new_stream(conn, generate_stream_id(conn), 0);
2953        if (!new_streams[i])
2954        {
2955            ABORT_ERROR("%s: cannot create new stream: %s", __func__,
2956                                                        strerror(errno));
2957            goto cleanup;
2958        }
2959    }
2960    LSQ_DEBUG("created %u delayed stream%.*s", avail, avail != 1, "s");
2961
2962    assert(count_streams(conn, 0) <= conn->fc_cfg.max_streams_out);
2963    conn->fc_n_delayed_streams -= avail;
2964
2965    for (i = 0; i < avail; ++i)
2966        lsquic_stream_call_on_new(new_streams[i]);
2967  cleanup:
2968    free(new_streams);
2969}
2970
2971
2972static void
2973service_streams (struct full_conn *conn)
2974{
2975    struct lsquic_hash_elem *el;
2976    lsquic_stream_t *stream, *next;
2977    int closed_some = 0;
2978
2979    for (stream = TAILQ_FIRST(&conn->fc_pub.service_streams); stream; stream = next)
2980    {
2981        next = TAILQ_NEXT(stream, next_service_stream);
2982        if (stream->sm_qflags & SMQF_ABORT_CONN)
2983            /* No need to unset this flag or remove this stream: the connection
2984             * is about to be aborted.
2985             */
2986            ABORT_ERROR("aborted due to error in stream %"PRIu64, stream->id);
2987        if (stream->sm_qflags & SMQF_CALL_ONCLOSE)
2988        {
2989            lsquic_stream_call_on_close(stream);
2990            closed_some |= is_our_stream(conn, stream);
2991            conn_mark_stream_closed(conn, stream->id);
2992        }
2993        if (stream->sm_qflags & SMQF_FREE_STREAM)
2994        {
2995            TAILQ_REMOVE(&conn->fc_pub.service_streams, stream, next_service_stream);
2996            el = lsquic_hash_find(conn->fc_pub.all_streams, &stream->id, sizeof(stream->id));
2997            if (el)
2998                lsquic_hash_erase(conn->fc_pub.all_streams, el);
2999            SAVE_STREAM_HISTORY(conn, stream);
3000            lsquic_stream_destroy(stream);
3001        }
3002    }
3003
3004    if (either_side_going_away(conn))
3005    {
3006        while (conn->fc_n_delayed_streams)
3007        {
3008            --conn->fc_n_delayed_streams;
3009            LSQ_DEBUG("goaway mode: delayed stream results in null ctor");
3010            (void) conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_new_stream(
3011                conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, NULL);
3012        }
3013        maybe_close_conn(conn);
3014    }
3015    else
3016        if (closed_some && conn->fc_n_delayed_streams)
3017            create_delayed_streams(conn);
3018}
3019
3020
3021struct filter_stream_ctx
3022{
3023    struct full_conn    *conn;
3024    uint32_t             last_stream_id,
3025                         max_peer_stream_id;
3026};
3027
3028
3029static int
3030filter_out_old_streams (void *ctx, lsquic_stream_t *stream)
3031{
3032    struct filter_stream_ctx *const fctx = ctx;
3033    return ((!((stream->id ^ fctx->last_stream_id)     & 1) &&
3034                                   stream->id > fctx->last_stream_id)
3035           ||
3036            (!((stream->id ^ fctx->max_peer_stream_id) & 1) &&
3037                                   stream->id > fctx->max_peer_stream_id));
3038}
3039
3040
3041static void
3042process_streams_read_events (struct full_conn *conn)
3043{
3044    lsquic_stream_t *stream;
3045    struct filter_stream_ctx fctx;
3046    enum stream_q_flags q_flags;
3047    int needs_service;
3048    struct stream_prio_iter spi;
3049
3050    if (TAILQ_EMPTY(&conn->fc_pub.read_streams))
3051        return;
3052
3053    fctx.last_stream_id     = conn->fc_last_stream_id;
3054    fctx.max_peer_stream_id = conn->fc_max_peer_stream_id;
3055    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.read_streams),
3056        TAILQ_LAST(&conn->fc_pub.read_streams, lsquic_streams_tailq),
3057        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_read_stream),
3058        &conn->fc_conn, "read", NULL, NULL);
3059
3060    needs_service = 0;
3061    for (stream = lsquic_spi_first(&spi); stream;
3062                                            stream = lsquic_spi_next(&spi))
3063    {
3064        q_flags = stream->sm_qflags & SMQF_SERVICE_FLAGS;
3065        lsquic_stream_dispatch_read_events(stream);
3066        needs_service |= q_flags ^ (stream->sm_qflags & SMQF_SERVICE_FLAGS);
3067    }
3068
3069    if (needs_service)
3070        service_streams(conn);
3071
3072    /* If new streams were created as result of the read dispatching above,
3073     * process these new streams.  This logic is only applicable to in the
3074     * server mode, as a client that creates a stream from an on_read() event
3075     * is not likely to want to *read* from it immediately.
3076     */
3077    if ((conn->fc_flags & FC_SERVER) &&
3078        (fctx.last_stream_id     < conn->fc_last_stream_id ||
3079         fctx.max_peer_stream_id < conn->fc_max_peer_stream_id))
3080    {
3081        fctx.conn = conn;
3082        lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.read_streams),
3083            TAILQ_LAST(&conn->fc_pub.read_streams, lsquic_streams_tailq),
3084            (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_read_stream),
3085            &conn->fc_conn, "read-new",
3086            filter_out_old_streams, &fctx);
3087        for (stream = lsquic_spi_first(&spi); stream;
3088                                                stream = lsquic_spi_next(&spi))
3089            lsquic_stream_dispatch_read_events(stream);
3090    }
3091}
3092
3093
3094static void
3095maybe_conn_flush_headers_stream (struct full_conn *conn)
3096{
3097    lsquic_stream_t *stream;
3098
3099    if (conn->fc_flags & FC_HTTP)
3100    {
3101        stream = lsquic_headers_stream_get_stream(conn->fc_pub.u.gquic.hs);
3102        if (lsquic_stream_has_data_to_flush(stream))
3103            (void) lsquic_stream_flush(stream);
3104    }
3105}
3106
3107
3108static void
3109process_streams_write_events (struct full_conn *conn, int high_prio)
3110{
3111    lsquic_stream_t *stream;
3112    struct stream_prio_iter spi;
3113
3114    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.write_streams),
3115        TAILQ_LAST(&conn->fc_pub.write_streams, lsquic_streams_tailq),
3116        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_write_stream),
3117        &conn->fc_conn,
3118        high_prio ? "write-high" : "write-low", NULL, NULL);
3119
3120    if (high_prio)
3121        lsquic_spi_drop_non_high(&spi);
3122    else
3123        lsquic_spi_drop_high(&spi);
3124
3125    for (stream = lsquic_spi_first(&spi); stream && write_is_possible(conn);
3126                                            stream = lsquic_spi_next(&spi))
3127        if (stream->sm_qflags & SMQF_WRITE_Q_FLAGS)
3128            lsquic_stream_dispatch_write_events(stream);
3129
3130    maybe_conn_flush_headers_stream(conn);
3131}
3132
3133
3134static void
3135process_hsk_stream_read_events (struct full_conn *conn)
3136{
3137    lsquic_stream_t *stream;
3138    TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
3139        if (lsquic_stream_is_crypto(stream))
3140        {
3141            lsquic_stream_dispatch_read_events(stream);
3142            break;
3143        }
3144}
3145
3146
3147static void
3148process_hsk_stream_write_events (struct full_conn *conn)
3149{
3150    lsquic_stream_t *stream;
3151    TAILQ_FOREACH(stream, &conn->fc_pub.write_streams, next_write_stream)
3152        if (lsquic_stream_is_crypto(stream))
3153        {
3154            lsquic_stream_dispatch_write_events(stream);
3155            break;
3156        }
3157}
3158
3159
3160static void
3161generate_ack_frame (struct full_conn *conn)
3162{
3163    lsquic_packet_out_t *packet_out;
3164
3165    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0, PNS_APP,
3166                                                                &conn->fc_path);
3167    if (packet_out)
3168    {
3169        lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
3170        full_conn_ci_write_ack(&conn->fc_conn, packet_out);
3171    }
3172    else
3173        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
3174}
3175
3176
3177static int
3178conn_ok_to_close (const struct full_conn *conn)
3179{
3180    assert(conn->fc_flags & FC_CLOSING);
3181    return !(conn->fc_flags & FC_SERVER)
3182        || (conn->fc_flags & FC_RECV_CLOSE)
3183        || (
3184               !lsquic_send_ctl_have_outgoing_stream_frames(&conn->fc_send_ctl)
3185            && lsquic_hash_count(conn->fc_pub.all_streams) == 0
3186            && lsquic_send_ctl_have_unacked_stream_frames(&conn->fc_send_ctl) == 0);
3187}
3188
3189
3190static enum tick_st
3191immediate_close (struct full_conn *conn)
3192{
3193    lsquic_packet_out_t *packet_out;
3194    const char *error_reason;
3195    unsigned error_code;
3196    int sz;
3197
3198    if (conn->fc_flags & (FC_TICK_CLOSE|FC_GOT_PRST))
3199        return TICK_CLOSE;
3200
3201    conn->fc_flags |= FC_TICK_CLOSE;
3202
3203    /* No reason to send anything that's been scheduled if connection is
3204     * being closed immedately.  This also ensures that packet numbers
3205     * sequence is always increasing.
3206     */
3207    lsquic_send_ctl_drop_scheduled(&conn->fc_send_ctl);
3208
3209    if ((conn->fc_flags & FC_TIMED_OUT) && conn->fc_settings->es_silent_close)
3210        return TICK_CLOSE;
3211
3212    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0, PNS_APP,
3213                                                                &conn->fc_path);
3214    if (!packet_out)
3215    {
3216        LSQ_WARN("cannot allocate packet: %s", strerror(errno));
3217        return TICK_CLOSE;
3218    }
3219
3220    assert(conn->fc_flags & (FC_ERROR|FC_ABORTED|FC_TIMED_OUT|FC_HSK_FAILED));
3221    if (conn->fc_flags & FC_ERROR)
3222    {
3223        error_code = 0x01; /* QUIC_INTERNAL_ERROR */
3224        error_reason = "connection error";
3225    }
3226    else if (conn->fc_flags & FC_ABORTED)
3227    {
3228        error_code = 0x10; /* QUIC_PEER_GOING_AWAY */
3229        error_reason = "user aborted connection";
3230    }
3231    else if (conn->fc_flags & FC_TIMED_OUT)
3232    {
3233        error_code = 0x19; /* QUIC_NETWORK_IDLE_TIMEOUT */
3234        error_reason = "connection timed out";
3235    }
3236    else if (conn->fc_flags & FC_HSK_FAILED)
3237    {
3238        error_code = 0x2A; /* QUIC_PROOF_INVALID */
3239        error_reason = "handshake failed";
3240    }
3241    else
3242    {
3243        error_code = 0x10; /* QUIC_PEER_GOING_AWAY */
3244        error_reason = NULL;
3245    }
3246
3247    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
3248    sz = conn->fc_conn.cn_pf->pf_gen_connect_close_frame(
3249                     packet_out->po_data + packet_out->po_data_sz,
3250                     lsquic_packet_out_avail(packet_out), 0, error_code,
3251                     error_reason, error_reason ? strlen(error_reason) : 0);
3252    if (sz < 0) {
3253        LSQ_WARN("%s failed", __func__);
3254        return TICK_CLOSE;
3255    }
3256    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
3257    packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
3258    LSQ_DEBUG("generated CONNECTION_CLOSE frame in its own packet");
3259    return TICK_SEND|TICK_CLOSE;
3260}
3261
3262
3263static int
3264write_is_possible (struct full_conn *conn)
3265{
3266    const lsquic_packet_out_t *packet_out;
3267
3268    packet_out = lsquic_send_ctl_last_scheduled(&conn->fc_send_ctl, PNS_APP,
3269                                                        &conn->fc_path, 0);
3270    return (packet_out && lsquic_packet_out_avail(packet_out) > 10)
3271        || lsquic_send_ctl_can_send(&conn->fc_send_ctl);
3272}
3273
3274
3275static int
3276should_generate_ack (const struct full_conn *conn)
3277{
3278    return (conn->fc_flags & FC_ACK_QUEUED)
3279        || lsquic_send_ctl_lost_ack(&conn->fc_send_ctl);
3280}
3281
3282
3283static int
3284full_conn_ci_can_write_ack (struct lsquic_conn *lconn)
3285{
3286    struct full_conn *conn = (struct full_conn *) lconn;
3287    return should_generate_ack(conn);
3288}
3289
3290
3291struct full_ack_state
3292{
3293    enum full_conn_flags    conn_flags;
3294    enum alarm_id_bit       armed_set;
3295    unsigned                n_slack_akbl;
3296    unsigned                n_stop_waiting;
3297};
3298
3299
3300typedef char ack_state_size[sizeof(struct full_ack_state)
3301                                    <= sizeof(struct ack_state) ? 1 : - 1];
3302
3303static void
3304full_conn_ci_ack_snapshot (struct lsquic_conn *lconn, struct ack_state *opaque)
3305{
3306    struct full_conn *conn = (struct full_conn *) lconn;
3307    struct full_ack_state *const ack_state = (struct full_ack_state *) opaque;
3308
3309    ack_state->conn_flags     = conn->fc_flags;
3310    ack_state->armed_set      = conn->fc_alset.as_armed_set;
3311    ack_state->n_slack_akbl   = conn->fc_n_slack_akbl;
3312    ack_state->n_stop_waiting
3313                        = lsquic_send_ctl_n_stop_waiting(&conn->fc_send_ctl);
3314    LSQ_DEBUG("take ACK snapshot");
3315}
3316
3317
3318static void
3319full_conn_ci_ack_rollback (struct lsquic_conn *lconn, struct ack_state *opaque)
3320{
3321    struct full_ack_state *const ack_state = (struct full_ack_state *) opaque;
3322    struct full_conn *conn = (struct full_conn *) lconn;
3323
3324    conn->fc_flags &= ~(FC_ACK_HAD_MISS|FC_ACK_QUEUED);
3325    conn->fc_flags |= (FC_ACK_HAD_MISS|FC_ACK_QUEUED)
3326                                        & ack_state->conn_flags;
3327
3328    conn->fc_alset.as_armed_set &= ~ALBIT_ACK_APP;
3329    conn->fc_alset.as_armed_set |= ALBIT_ACK_APP & ack_state->armed_set;
3330
3331    conn->fc_n_slack_akbl               = ack_state->n_slack_akbl;
3332    conn->fc_send_ctl.sc_n_stop_waiting = ack_state->n_stop_waiting;
3333
3334    LSQ_DEBUG("roll back ACK state");
3335}
3336
3337
3338/* This should be called before lsquic_alarmset_ring_expired() */
3339static void
3340maybe_set_noprogress_alarm (struct full_conn *conn, lsquic_time_t now)
3341{
3342    lsquic_time_t exp;
3343
3344    if (conn->fc_flags & FC_NOPROG_TIMEOUT)
3345    {
3346        if (conn->fc_pub.last_tick)
3347        {
3348            exp = conn->fc_pub.last_prog + conn->fc_enpub->enp_noprog_timeout;
3349            if (!lsquic_alarmset_is_set(&conn->fc_alset, AL_IDLE)
3350                                    || exp < conn->fc_alset.as_expiry[AL_IDLE])
3351                lsquic_alarmset_set(&conn->fc_alset, AL_IDLE, exp);
3352            conn->fc_pub.last_tick = now;
3353        }
3354        else
3355        {
3356            conn->fc_pub.last_tick = now;
3357            conn->fc_pub.last_prog = now;
3358        }
3359    }
3360}
3361
3362
3363static enum tick_st
3364full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
3365{
3366    struct full_conn *conn = (struct full_conn *) lconn;
3367    int have_delayed_packets;
3368    unsigned n;
3369    int s;
3370    enum tick_st tick = 0;
3371
3372#define CLOSE_IF_NECESSARY() do {                                       \
3373    if (conn->fc_flags & FC_IMMEDIATE_CLOSE_FLAGS)                      \
3374    {                                                                   \
3375        tick |= immediate_close(conn);                         \
3376        goto close_end;                                                 \
3377    }                                                                   \
3378} while (0)
3379
3380#define RETURN_IF_OUT_OF_PACKETS() do {                                 \
3381    if (!lsquic_send_ctl_can_send(&conn->fc_send_ctl))                  \
3382    {                                                                   \
3383        if (0 == lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl))       \
3384        {                                                               \
3385            LSQ_DEBUG("used up packet allowance, quiet now (line %d)",  \
3386                __LINE__);                                              \
3387            tick |= TICK_QUIET;                                         \
3388        }                                                               \
3389        else                                                            \
3390        {                                                               \
3391            LSQ_DEBUG("used up packet allowance, sending now (line %d)",\
3392                __LINE__);                                              \
3393            tick |= TICK_SEND;                                          \
3394        }                                                               \
3395        goto end;                                                       \
3396    }                                                                   \
3397} while (0)
3398
3399#if LSQUIC_CONN_STATS
3400    ++conn->fc_stats.n_ticks;
3401#endif
3402
3403    if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG)
3404        && conn->fc_mem_logged_last + 1000000 <= now)
3405    {
3406        conn->fc_mem_logged_last = now;
3407        LSQ_DEBUG("memory used: %zd bytes", calc_mem_used(conn));
3408    }
3409
3410    if (conn->fc_flags & FC_HAVE_SAVED_ACK)
3411    {
3412        (void) /* If there is an error, we'll fail shortly */
3413            process_ack(conn, &conn->fc_ack, conn->fc_saved_ack_received, now);
3414        conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
3415    }
3416
3417    maybe_set_noprogress_alarm(conn, now);
3418
3419    lsquic_send_ctl_tick_in(&conn->fc_send_ctl, now);
3420    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
3421    CLOSE_IF_NECESSARY();
3422
3423    lsquic_alarmset_ring_expired(&conn->fc_alset, now);
3424    CLOSE_IF_NECESSARY();
3425
3426    /* To make things simple, only stream 1 is active until the handshake
3427     * has been completed.  This will be adjusted in the future: the client
3428     * does not want to wait if it has the server information.
3429     */
3430    if (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
3431        process_streams_read_events(conn);
3432    else
3433        process_hsk_stream_read_events(conn);
3434    CLOSE_IF_NECESSARY();
3435
3436    if (lsquic_send_ctl_pacer_blocked(&conn->fc_send_ctl))
3437        goto skip_write;
3438
3439    if (conn->fc_flags & FC_FIRST_TICK)
3440    {
3441        conn->fc_flags &= ~FC_FIRST_TICK;
3442        have_delayed_packets = 0;
3443    }
3444    else
3445        /* If there are any scheduled packets at this point, it means that
3446         * they were not sent during previous tick; in other words, they
3447         * are delayed.  When there are delayed packets, the only packet
3448         * we sometimes add is a packet with an ACK frame, and we add it
3449         * to the *front* of the queue.
3450         */
3451        have_delayed_packets = lsquic_send_ctl_maybe_squeeze_sched(
3452                                                    &conn->fc_send_ctl);
3453
3454    if (should_generate_ack(conn))
3455    {
3456        if (have_delayed_packets)
3457            lsquic_send_ctl_reset_packnos(&conn->fc_send_ctl);
3458
3459        generate_ack_frame(conn);
3460        CLOSE_IF_NECESSARY();
3461
3462        /* Try to send STOP_WAITING frame at the same time we send an ACK
3463         * This follows reference implementation.
3464         */
3465        if (!(conn->fc_flags & FC_NSTP))
3466            conn->fc_flags |= FC_SEND_STOP_WAITING;
3467
3468        if (have_delayed_packets)
3469        {
3470            if (conn->fc_flags & FC_SEND_STOP_WAITING)
3471            {
3472                /* TODO: ensure that STOP_WAITING frame is in the same packet
3473                 * as the ACK frame in delayed packet mode.
3474                 */
3475                generate_stop_waiting_frame(conn);
3476                CLOSE_IF_NECESSARY();
3477            }
3478            lsquic_send_ctl_ack_to_front(&conn->fc_send_ctl, 1);
3479        }
3480    }
3481
3482    if (have_delayed_packets)
3483    {
3484        /* The reason for not adding STOP_WAITING and other frames below
3485         * to the packet carrying ACK frame generated when there are delayed
3486         * packets is so that if the ACK packet itself is delayed, it can be
3487         * dropped and replaced by new ACK packet.  This way, we are never
3488         * more than 1 packet over CWND.
3489         */
3490        tick |= TICK_SEND;
3491        goto end;
3492    }
3493
3494    /* Try to fit any of the following three frames -- STOP_WAITING,
3495     * WINDOW_UPDATE, and GOAWAY -- before checking if we have run
3496     * out of packets.  If either of them does not fit, it will be
3497     * tried next time around.
3498     */
3499    if (conn->fc_flags & FC_SEND_STOP_WAITING)
3500    {
3501        generate_stop_waiting_frame(conn);
3502        CLOSE_IF_NECESSARY();
3503    }
3504
3505    if (lsquic_cfcw_fc_offsets_changed(&conn->fc_pub.cfcw) ||
3506                                (conn->fc_flags & FC_SEND_WUF))
3507    {
3508        conn->fc_flags |= FC_SEND_WUF;
3509        generate_wuf_conn(conn);
3510        CLOSE_IF_NECESSARY();
3511    }
3512
3513    if (conn->fc_flags & FC_SEND_GOAWAY)
3514    {
3515        generate_goaway_frame(conn);
3516        CLOSE_IF_NECESSARY();
3517    }
3518
3519    n = lsquic_send_ctl_reschedule_packets(&conn->fc_send_ctl);
3520    if (n > 0)
3521        CLOSE_IF_NECESSARY();
3522
3523    if (conn->fc_conn.cn_flags & LSCONN_SEND_BLOCKED)
3524    {
3525        RETURN_IF_OUT_OF_PACKETS();
3526        if (generate_blocked_frame(conn, 0))
3527            conn->fc_conn.cn_flags &= ~LSCONN_SEND_BLOCKED;
3528    }
3529
3530    if (!STAILQ_EMPTY(&conn->fc_stream_ids_to_reset))
3531    {
3532        packetize_standalone_stream_resets(conn);
3533        CLOSE_IF_NECESSARY();
3534    }
3535
3536    if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
3537    {
3538        process_streams_ready_to_send(conn);
3539        CLOSE_IF_NECESSARY();
3540    }
3541
3542    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 0);
3543    if (!handshake_done_or_doing_sess_resume(conn))
3544    {
3545        process_hsk_stream_write_events(conn);
3546        goto end_write;
3547    }
3548
3549    maybe_conn_flush_headers_stream(conn);
3550
3551    s = lsquic_send_ctl_schedule_buffered(&conn->fc_send_ctl, BPT_HIGHEST_PRIO);
3552    conn->fc_flags |= (s < 0) << FC_BIT_ERROR;
3553    if (!write_is_possible(conn))
3554        goto end_write;
3555
3556    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams))
3557    {
3558        process_streams_write_events(conn, 1);
3559        if (!write_is_possible(conn))
3560            goto end_write;
3561    }
3562
3563    s = lsquic_send_ctl_schedule_buffered(&conn->fc_send_ctl, BPT_OTHER_PRIO);
3564    conn->fc_flags |= (s < 0) << FC_BIT_ERROR;
3565    if (!write_is_possible(conn))
3566        goto end_write;
3567
3568    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams))
3569        process_streams_write_events(conn, 0);
3570
3571    lsquic_send_ctl_maybe_app_limited(&conn->fc_send_ctl, &conn->fc_path);
3572
3573  end_write:
3574
3575  skip_write:
3576    if ((conn->fc_flags & FC_CLOSING) && conn_ok_to_close(conn))
3577    {
3578        RETURN_IF_OUT_OF_PACKETS();
3579        LSQ_DEBUG("connection is OK to close");
3580        /* This is normal termination sequence.
3581         *
3582         * Generate CONNECTION_CLOSE frame if we are responding to one, have
3583         * packets scheduled to send, or silent close flag is not set.
3584         */
3585        conn->fc_flags |= FC_TICK_CLOSE;
3586        if ((conn->fc_flags & FC_RECV_CLOSE) ||
3587                0 != lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) ||
3588                                        !conn->fc_settings->es_silent_close)
3589        {
3590            generate_connection_close_packet(conn);
3591            tick |= TICK_SEND|TICK_CLOSE;
3592        }
3593        else
3594            tick |= TICK_CLOSE;
3595        goto end;
3596    }
3597
3598    if (0 == lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl))
3599    {
3600        if (conn->fc_flags & FC_SEND_PING)
3601        {
3602            RETURN_IF_OUT_OF_PACKETS();
3603            conn->fc_flags &= ~FC_SEND_PING;
3604            generate_ping_frame(conn);
3605            CLOSE_IF_NECESSARY();
3606            assert(lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) != 0);
3607        }
3608        else
3609        {
3610            tick |= TICK_QUIET;
3611            goto end;
3612        }
3613    }
3614    else if (conn->fc_settings->es_ping_period)
3615    {
3616        lsquic_alarmset_unset(&conn->fc_alset, AL_PING);
3617        lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
3618        conn->fc_flags &= ~FC_SEND_PING;   /* It may have rung */
3619    }
3620
3621    /* From the spec:
3622     *  " The PING frame should be used to keep a connection alive when
3623     *  " a stream is open.
3624     */
3625    if (conn->fc_settings->es_ping_period
3626                            && lsquic_hash_count(conn->fc_pub.all_streams) > 0)
3627        lsquic_alarmset_set(&conn->fc_alset, AL_PING,
3628                    now + conn->fc_settings->es_ping_period * 1000 * 1000);
3629
3630    tick |= TICK_SEND;
3631
3632  end:
3633    service_streams(conn);
3634    CLOSE_IF_NECESSARY();
3635
3636  close_end:
3637    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
3638    lsquic_send_ctl_tick_out(&conn->fc_send_ctl);
3639    return tick;
3640}
3641
3642
3643static void
3644set_earliest_idle_alarm (struct full_conn *conn, lsquic_time_t idle_conn_to)
3645{
3646    lsquic_time_t exp;
3647
3648    if (conn->fc_pub.last_prog
3649        && (assert(conn->fc_flags & FC_NOPROG_TIMEOUT),
3650            exp = conn->fc_pub.last_prog + conn->fc_enpub->enp_noprog_timeout,
3651            exp < idle_conn_to))
3652        idle_conn_to = exp;
3653    lsquic_alarmset_set(&conn->fc_alset, AL_IDLE, idle_conn_to);
3654}
3655
3656
3657static void
3658full_conn_ci_packet_in (lsquic_conn_t *lconn, lsquic_packet_in_t *packet_in)
3659{
3660    struct full_conn *conn = (struct full_conn *) lconn;
3661
3662#if LSQUIC_CONN_STATS
3663    conn->fc_stats.in.bytes += packet_in->pi_data_sz;
3664#endif
3665    set_earliest_idle_alarm(conn,
3666                packet_in->pi_received + conn->fc_settings->es_idle_conn_to);
3667    if (0 == (conn->fc_flags & FC_ERROR))
3668        if (0 != process_incoming_packet(conn, packet_in))
3669            conn->fc_flags |= FC_ERROR;
3670}
3671
3672
3673static lsquic_packet_out_t *
3674full_conn_ci_next_packet_to_send (struct lsquic_conn *lconn,
3675                                                const struct to_coal *unused)
3676{
3677    struct full_conn *conn = (struct full_conn *) lconn;
3678    return lsquic_send_ctl_next_packet_to_send(&conn->fc_send_ctl, NULL);
3679}
3680
3681
3682static void
3683full_conn_ci_packet_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_out)
3684{
3685    struct full_conn *conn = (struct full_conn *) lconn;
3686    int s;
3687
3688    recent_packet_hist_new(conn, 1, packet_out->po_sent);
3689    recent_packet_hist_frames(conn, 1, packet_out->po_frame_types);
3690
3691    if (packet_out->po_frame_types & GQUIC_FRAME_RETRANSMITTABLE_MASK)
3692        conn->fc_n_cons_unretx = 0;
3693    else
3694        ++conn->fc_n_cons_unretx;
3695    s = lsquic_send_ctl_sent_packet(&conn->fc_send_ctl, packet_out);
3696    if (s != 0)
3697        ABORT_ERROR("sent packet failed: %s", strerror(errno));
3698#if LSQUIC_CONN_STATS
3699    ++conn->fc_stats.out.packets;
3700    conn->fc_stats.out.bytes += lsquic_packet_out_sent_sz(lconn, packet_out);
3701#endif
3702}
3703
3704
3705static void
3706full_conn_ci_packet_not_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_out)
3707{
3708    struct full_conn *conn = (struct full_conn *) lconn;
3709    lsquic_send_ctl_delayed_one(&conn->fc_send_ctl, packet_out);
3710}
3711
3712
3713static void
3714full_conn_ci_hsk_done (lsquic_conn_t *lconn, enum lsquic_hsk_status status)
3715{
3716    struct full_conn *conn = (struct full_conn *) lconn;
3717    lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
3718    switch (status)
3719    {
3720        case LSQ_HSK_RESUMED_FAIL:
3721        case LSQ_HSK_FAIL:
3722            conn->fc_flags |= FC_HSK_FAILED;
3723            break;
3724        case LSQ_HSK_OK:
3725        case LSQ_HSK_RESUMED_OK:
3726            if (0 == apply_peer_settings(conn))
3727            {
3728                if (conn->fc_flags & FC_HTTP)
3729                    maybe_send_settings(conn);
3730                lconn->cn_flags |= LSCONN_HANDSHAKE_DONE;
3731            }
3732            else
3733                conn->fc_flags |= FC_ERROR;
3734            break;
3735    }
3736    if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done)
3737        conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn,
3738                                                                        status);
3739    if (status == LSQ_HSK_OK || status == LSQ_HSK_RESUMED_OK)
3740    {
3741        if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_sess_resume_info)
3742            conn->fc_conn.cn_esf.g->esf_maybe_dispatch_sess_resume(
3743                conn->fc_conn.cn_enc_session,
3744                conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_sess_resume_info);
3745        if (conn->fc_n_delayed_streams)
3746            create_delayed_streams(conn);
3747        if (!(conn->fc_flags & FC_SERVER))
3748            lsquic_send_ctl_begin_optack_detection(&conn->fc_send_ctl);
3749    }
3750}
3751
3752
3753static void
3754full_conn_ci_abort (struct lsquic_conn *lconn)
3755{
3756    struct full_conn *conn = (struct full_conn *) lconn;
3757    LSQ_INFO("User aborted connection");
3758    conn->fc_flags |= FC_ABORTED;
3759}
3760
3761
3762static void
3763full_conn_ci_internal_error (struct lsquic_conn *lconn,
3764                                                    const char *format, ...)
3765{
3766    struct full_conn *const conn = (struct full_conn *) lconn;
3767    LSQ_INFO("Internal error reported");
3768    conn->fc_flags |= FC_ERROR;
3769}
3770
3771
3772/* This function should not be called, as this is specific to IETF QUIC */
3773static void
3774full_conn_ci_abort_error (struct lsquic_conn *lconn, int is_app,
3775                                unsigned error_code, const char *fmt, ...)
3776{
3777    struct full_conn *const conn = (struct full_conn *) lconn;
3778    assert(0);
3779    LSQ_WARN("(GQUIC) abort error is called unexpectedly");
3780    conn->fc_flags |= FC_ERROR;
3781}
3782
3783
3784static void
3785full_conn_ci_close (struct lsquic_conn *lconn)
3786{
3787    struct full_conn *conn = (struct full_conn *) lconn;
3788    lsquic_stream_t *stream;
3789    struct lsquic_hash_elem *el;
3790
3791    if (!(conn->fc_flags & FC_CLOSING))
3792    {
3793        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
3794                                     el = lsquic_hash_next(conn->fc_pub.all_streams))
3795        {
3796            stream = lsquic_hashelem_getdata(el);
3797            lsquic_stream_shutdown_internal(stream);
3798        }
3799        conn->fc_flags |= FC_CLOSING;
3800        if (!(conn->fc_flags & FC_GOAWAY_SENT))
3801            conn->fc_flags |= FC_SEND_GOAWAY;
3802        lsquic_engine_add_conn_to_tickable(conn->fc_enpub, lconn);
3803    }
3804}
3805
3806
3807static void
3808full_conn_ci_going_away (struct lsquic_conn *lconn)
3809{
3810    struct full_conn *conn = (struct full_conn *) lconn;
3811    if (!(conn->fc_flags & (FC_CLOSING|FC_GOING_AWAY)))
3812    {
3813        LSQ_INFO("connection marked as going away");
3814        assert(!(conn->fc_flags & FC_SEND_GOAWAY));
3815        conn->fc_flags |= FC_GOING_AWAY;
3816        if (!(conn->fc_flags & FC_GOAWAY_SENT))
3817        {
3818            conn->fc_flags |= FC_SEND_GOAWAY;
3819            lsquic_engine_add_conn_to_tickable(conn->fc_enpub, lconn);
3820        }
3821    }
3822}
3823
3824
3825/* Find stream when stream ID is read from something other than a STREAM
3826 * frame.  If the stream cannot be found or created, the connection is
3827 * aborted.
3828 */
3829#if __GNUC__
3830__attribute__((nonnull(4)))
3831#endif
3832static lsquic_stream_t *
3833find_stream_on_non_stream_frame (struct full_conn *conn,
3834        lsquic_stream_id_t stream_id, enum stream_ctor_flags stream_ctor_flags,
3835        const char *what)
3836{
3837    lsquic_stream_t *stream;
3838    unsigned in_count;
3839
3840    stream = find_stream_by_id(conn, stream_id);
3841    if (stream)
3842        return stream;
3843
3844    if (conn_is_stream_closed(conn, stream_id))
3845    {
3846        LSQ_DEBUG("drop incoming %s for closed stream %"PRIu64, what, stream_id);
3847        return NULL;
3848    }
3849
3850    /* XXX It seems that if we receive a priority frame for a stream, the
3851     *     stream should exist or have existed at some point.  Thus, if
3852     *     it does not exist, we should return an error here.
3853     */
3854
3855    if (!is_peer_initiated(conn, stream_id))
3856    {
3857        ABORT_ERROR("frame for never-initiated stream (push promise?)");
3858        return NULL;
3859    }
3860
3861    in_count = count_streams(conn, 1);
3862    LSQ_DEBUG("number of peer-initiated streams: %u", in_count);
3863    if (in_count >= conn->fc_cfg.max_streams_in)
3864    {
3865        if (!(conn->fc_flags & FC_ABORT_COMPLAINED))
3866        {
3867            unsigned counts[N_SCNTS];
3868            collect_stream_counts(conn, 1, counts);
3869            ABORT_WARN("incoming %s for stream %"PRIu64" would exceed "
3870                "limit: %u.  all: %u; peer: %u; closed: %u; reset: %u; reset "
3871                "and not closed: %u",
3872                what, stream_id, conn->fc_cfg.max_streams_in, counts[SCNT_ALL],
3873                counts[SCNT_PEER], counts[SCNT_CLOSED], counts[SCNT_RESET],
3874                counts[SCNT_RES_UNCLO]);
3875        }
3876        return NULL;
3877    }
3878    if ((conn->fc_flags & FC_GOING_AWAY) &&
3879        stream_id > conn->fc_max_peer_stream_id)
3880    {
3881        maybe_schedule_reset_for_stream(conn, stream_id);
3882        LSQ_DEBUG("going away: reset new incoming stream %"PRIu64, stream_id);
3883        return NULL;
3884    }
3885
3886    stream = new_stream(conn, stream_id, stream_ctor_flags);
3887    if (!stream)
3888    {
3889        ABORT_ERROR("cannot create new stream: %s", strerror(errno));
3890        return NULL;
3891    }
3892    if (stream_id > conn->fc_max_peer_stream_id)
3893        conn->fc_max_peer_stream_id = stream_id;
3894
3895    return stream;
3896}
3897
3898
3899static void
3900headers_stream_on_conn_error (void *ctx)
3901{
3902    struct full_conn *conn = ctx;
3903    ABORT_ERROR("connection error reported by HEADERS stream");
3904}
3905
3906
3907static void
3908headers_stream_on_stream_error (void *ctx, lsquic_stream_id_t stream_id)
3909{
3910    struct full_conn *conn = ctx;
3911    lsquic_stream_t *stream;
3912
3913    stream = find_stream_on_non_stream_frame(conn, stream_id, SCF_CALL_ON_NEW,
3914                                             "error");
3915    if (stream)
3916    {
3917        LSQ_DEBUG("resetting stream %"PRIu64" due to error", stream_id);
3918        /* We use code 1, which is QUIC_INTERNAL_ERROR (see
3919         * [draft-hamilton-quic-transport-protocol-01], Section 10), for all
3920         * errors.  There does not seem to be a good reason to figure out
3921         * and send more specific error codes.
3922         */
3923        lsquic_stream_reset_ext(stream, 1, 0);
3924    }
3925}
3926
3927
3928static void
3929headers_stream_on_enable_push (void *ctx, int enable_push)
3930{
3931    struct full_conn *conn = ctx;
3932    if (0 == enable_push)
3933    {
3934        LSQ_DEBUG("server push %d -> 0", !!(conn->fc_flags & FC_SUPPORT_PUSH));
3935        conn->fc_flags &= ~FC_SUPPORT_PUSH;
3936    }
3937    else if (conn->fc_settings->es_support_push)
3938    {
3939        LSQ_DEBUG("server push %d -> 1", !!(conn->fc_flags & FC_SUPPORT_PUSH));
3940        conn->fc_flags |= FC_SUPPORT_PUSH;
3941    }
3942    else
3943        LSQ_INFO("not enabling server push that's disabled in engine settings");
3944}
3945
3946
3947static void
3948headers_stream_on_incoming_headers (void *ctx, struct uncompressed_headers *uh)
3949{
3950    struct full_conn *conn = ctx;
3951    lsquic_stream_t *stream;
3952
3953    LSQ_DEBUG("incoming headers for stream %"PRIu64, uh->uh_stream_id);
3954
3955    stream = find_stream_on_non_stream_frame(conn, uh->uh_stream_id, 0,
3956                                             "headers");
3957    if (!stream)
3958        goto free_uh;
3959
3960    if (lsquic_stream_is_reset(stream))
3961    {
3962        LSQ_DEBUG("stream is reset: ignore headers");
3963        goto free_uh;
3964    }
3965
3966    if (0 != lsquic_stream_uh_in(stream, uh))
3967    {
3968        ABORT_ERROR("stream %"PRIu64" refused incoming headers",
3969                                                        uh->uh_stream_id);
3970        goto free_uh;
3971    }
3972
3973    if (!(stream->stream_flags & STREAM_ONNEW_DONE))
3974        lsquic_stream_call_on_new(stream);
3975
3976    return;
3977
3978  free_uh:
3979    if (uh->uh_hset)
3980        conn->fc_enpub->enp_hsi_if->hsi_discard_header_set(uh->uh_hset);
3981    free(uh);
3982}
3983
3984
3985static void
3986headers_stream_on_push_promise (void *ctx, struct uncompressed_headers *uh)
3987{
3988    struct full_conn *conn = ctx;
3989    lsquic_stream_t *stream;
3990
3991    assert(!(conn->fc_flags & FC_SERVER));
3992
3993    LSQ_DEBUG("push promise for stream %"PRIu64" in response to %"PRIu64,
3994                                    uh->uh_oth_stream_id, uh->uh_stream_id);
3995
3996    if (0 == (uh->uh_stream_id & 1)     ||
3997        0 != (uh->uh_oth_stream_id & 1))
3998    {
3999        ABORT_ERROR("invalid push promise stream IDs: %"PRIu64", %"PRIu64,
4000                                    uh->uh_oth_stream_id, uh->uh_stream_id);
4001        goto free_uh;
4002    }
4003
4004    if (!(conn_is_stream_closed(conn, uh->uh_stream_id) ||
4005          find_stream_by_id(conn, uh->uh_stream_id)))
4006    {
4007        ABORT_ERROR("invalid push promise original stream ID %"PRIu64" never "
4008                    "initiated", uh->uh_stream_id);
4009        goto free_uh;
4010    }
4011
4012    if (conn_is_stream_closed(conn, uh->uh_oth_stream_id) ||
4013        find_stream_by_id(conn, uh->uh_oth_stream_id))
4014    {
4015        ABORT_ERROR("invalid promised stream ID %"PRIu64" already used",
4016                                                        uh->uh_oth_stream_id);
4017        goto free_uh;
4018    }
4019
4020    stream = new_stream_ext(conn, uh->uh_oth_stream_id, STREAM_IF_STD,
4021                SCF_DI_AUTOSWITCH|(conn->fc_enpub->enp_settings.es_rw_once ?
4022                                                        SCF_DISP_RW_ONCE : 0));
4023    if (!stream)
4024    {
4025        ABORT_ERROR("cannot create stream: %s", strerror(errno));
4026        goto free_uh;
4027    }
4028    lsquic_stream_push_req(stream, uh);
4029    lsquic_stream_call_on_new(stream);
4030    return;
4031
4032  free_uh:
4033    if (uh->uh_hset)
4034        conn->fc_enpub->enp_hsi_if->hsi_discard_header_set(uh->uh_hset);
4035    free(uh);
4036}
4037
4038
4039static void
4040headers_stream_on_priority (void *ctx, lsquic_stream_id_t stream_id,
4041            int exclusive, lsquic_stream_id_t dep_stream_id, unsigned weight)
4042{
4043    struct full_conn *conn = ctx;
4044    lsquic_stream_t *stream;
4045    LSQ_DEBUG("got priority frame for stream %"PRIu64": (ex: %d; dep stream: "
4046        "%"PRIu64"; weight: %u)", stream_id, exclusive, dep_stream_id, weight);
4047    stream = find_stream_on_non_stream_frame(conn, stream_id, SCF_CALL_ON_NEW,
4048                                             "priority");
4049    if (stream)
4050        lsquic_stream_set_priority_internal(stream, weight);
4051}
4052
4053
4054
4055#define STRLEN(s) (sizeof(s) - 1)
4056
4057static struct uncompressed_headers *
4058synthesize_push_request (struct full_conn *conn, void *hset,
4059         lsquic_stream_id_t pushed_stream_id, const lsquic_stream_t *dep_stream)
4060{
4061    struct uncompressed_headers *uh;
4062
4063    assert(hset);
4064
4065    uh = malloc(sizeof(*uh));
4066    if (!uh)
4067        return NULL;
4068
4069    uh->uh_stream_id     = pushed_stream_id;
4070    uh->uh_oth_stream_id = 0;   /* We don't do dependencies */
4071    uh->uh_weight        = lsquic_stream_priority(dep_stream) / 2 + 1;
4072    uh->uh_exclusive     = 0;
4073    uh->uh_flags         = UH_FIN;
4074    if (lsquic_http1x_if == conn->fc_enpub->enp_hsi_if)
4075        uh->uh_flags    |= UH_H1H;
4076    uh->uh_hset          = hset;
4077
4078    return uh;
4079}
4080
4081
4082static int
4083full_conn_ci_is_push_enabled (struct lsquic_conn *lconn)
4084{
4085    struct full_conn *const conn = (struct full_conn *) lconn;
4086    return conn->fc_flags & FC_SUPPORT_PUSH;
4087}
4088
4089
4090static int
4091full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
4092    struct lsquic_stream *dep_stream, const struct lsquic_http_headers *headers)
4093{
4094    struct full_conn *const conn = (struct full_conn *) lconn;
4095    lsquic_stream_t *pushed_stream;
4096    struct uncompressed_headers *uh;    /* We synthesize the request */
4097    lsquic_stream_id_t stream_id;
4098    int hit_limit;
4099
4100    if ((conn->fc_flags & (FC_SERVER|FC_HTTP)) != (FC_SERVER|FC_HTTP))
4101    {
4102        LSQ_ERROR("must be server in HTTP mode to push streams");
4103        return -1;
4104    }
4105
4106    if (lsquic_stream_is_pushed(dep_stream))
4107    {
4108        LSQ_WARN("cannot push stream dependent on another pushed stream "
4109                 "(%"PRIu64")", dep_stream->id);
4110        return -1;
4111    }
4112
4113    if (!(conn->fc_flags & FC_SUPPORT_PUSH))
4114    {
4115        LSQ_INFO("server push support is disabled");
4116        return 1;
4117    }
4118
4119    if (!hset)
4120    {
4121        LSQ_ERROR("header set must be specified when pushing");
4122        return -1;
4123    }
4124
4125    hit_limit = 0;
4126    if (either_side_going_away(conn) ||
4127        (hit_limit = 1, count_streams(conn, 0) >= conn->fc_cfg.max_streams_out))
4128    {
4129        LSQ_DEBUG("cannot create pushed stream: %s", hit_limit ?
4130            "hit connection limit" : "connection is going away");
4131        return 1;
4132    }
4133
4134    stream_id = generate_stream_id(conn);
4135    uh = synthesize_push_request(conn, hset, stream_id, dep_stream);
4136    if (!uh)
4137    {
4138        ABORT_ERROR("memory allocation failure");
4139        return -1;
4140    }
4141
4142    pushed_stream = new_stream(conn, stream_id, 0);
4143    if (!pushed_stream)
4144    {
4145        LSQ_WARN("cannot create stream: %s", strerror(errno));
4146        free(uh);
4147        return -1;
4148    }
4149
4150    if (0 != lsquic_stream_uh_in(pushed_stream, uh))
4151    {
4152        LSQ_WARN("stream barfed when fed synthetic request");
4153        free(uh);
4154        return -1;
4155    }
4156
4157    if (0 != lsquic_headers_stream_push_promise(conn->fc_pub.u.gquic.hs, dep_stream->id,
4158                                        pushed_stream->id, headers))
4159    {
4160        /* Since the failure to write to HEADERS stream results in aborting
4161         * the connection, we do not bother rolling back.
4162         */
4163        LSQ_ERROR("could not send push promise");
4164        return -1;
4165    }
4166
4167    lsquic_stream_call_on_new(pushed_stream);
4168    return 0;
4169}
4170
4171
4172static void
4173full_conn_ci_tls_alert (struct lsquic_conn *lconn, uint8_t alert)
4174{
4175    assert(0);
4176}
4177
4178
4179static struct lsquic_conn_ctx *
4180full_conn_ci_get_ctx (const struct lsquic_conn *lconn)
4181{
4182    struct full_conn *const conn = (struct full_conn *) lconn;
4183    return conn->fc_conn_ctx;
4184}
4185
4186
4187static void
4188full_conn_ci_set_ctx (struct lsquic_conn *lconn, lsquic_conn_ctx_t *ctx)
4189{
4190    struct full_conn *const conn = (struct full_conn *) lconn;
4191    conn->fc_conn_ctx = ctx;
4192}
4193
4194
4195static enum LSQUIC_CONN_STATUS
4196full_conn_ci_status (struct lsquic_conn *lconn, char *errbuf, size_t bufsz)
4197{
4198    struct full_conn *const conn = (struct full_conn *) lconn;
4199    size_t n;
4200
4201    /* Test the common case first: */
4202    if (!(conn->fc_flags & (FC_ERROR
4203                           |FC_TIMED_OUT
4204                           |FC_ABORTED
4205                           |FC_GOT_PRST
4206                           |FC_HSK_FAILED
4207                           |FC_CLOSING
4208                           |FC_GOING_AWAY)))
4209    {
4210        if (lconn->cn_flags & LSCONN_PEER_GOING_AWAY)
4211            return LSCONN_ST_PEER_GOING_AWAY;
4212        else if (lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
4213            return LSCONN_ST_CONNECTED;
4214        else
4215            return LSCONN_ST_HSK_IN_PROGRESS;
4216    }
4217
4218    if (errbuf && bufsz)
4219    {
4220        if (conn->fc_errmsg)
4221        {
4222            n = bufsz < MAX_ERRMSG ? bufsz : MAX_ERRMSG;
4223            strncpy(errbuf, conn->fc_errmsg, n);
4224            errbuf[n - 1] = '\0';
4225        }
4226        else
4227            errbuf[0] = '\0';
4228    }
4229
4230    if (conn->fc_flags & FC_ERROR)
4231        return LSCONN_ST_ERROR;
4232    if (conn->fc_flags & FC_TIMED_OUT)
4233        return LSCONN_ST_TIMED_OUT;
4234    if (conn->fc_flags & FC_ABORTED)
4235        return LSCONN_ST_USER_ABORTED;
4236    if (conn->fc_flags & FC_GOT_PRST)
4237        return LSCONN_ST_RESET;
4238    if (conn->fc_flags & FC_HSK_FAILED)
4239        return LSCONN_ST_HSK_FAILURE;
4240    if (conn->fc_flags & FC_CLOSING)
4241        return LSCONN_ST_CLOSED;
4242    assert(conn->fc_flags & FC_GOING_AWAY);
4243    return LSCONN_ST_GOING_AWAY;
4244}
4245
4246
4247static int
4248full_conn_ci_is_tickable (lsquic_conn_t *lconn)
4249{
4250    struct full_conn *conn = (struct full_conn *) lconn;
4251    struct lsquic_stream *stream;
4252
4253    if (!TAILQ_EMPTY(&conn->fc_pub.service_streams))
4254    {
4255        LSQ_DEBUG("tickable: there are streams to be serviced");
4256        return 1;
4257    }
4258
4259    if ((conn->fc_enpub->enp_flags & ENPUB_CAN_SEND)
4260        && (should_generate_ack(conn) ||
4261            !lsquic_send_ctl_sched_is_blocked(&conn->fc_send_ctl)))
4262    {
4263        const enum full_conn_flags send_flags = FC_SEND_GOAWAY
4264                |FC_SEND_STOP_WAITING|FC_SEND_PING|FC_SEND_WUF|FC_CLOSING;
4265        if (conn->fc_flags & send_flags)
4266        {
4267            LSQ_DEBUG("tickable: flags: 0x%X", conn->fc_flags & send_flags);
4268            goto check_can_send;
4269        }
4270        if (lsquic_send_ctl_has_sendable(&conn->fc_send_ctl))
4271        {
4272            LSQ_DEBUG("tickable: has sendable packets");
4273            return 1;   /* Don't check can_send: already on scheduled queue */
4274        }
4275        if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
4276                && lsquic_send_ctl_has_buffered(&conn->fc_send_ctl))
4277        {
4278            LSQ_DEBUG("tickable: has buffered packets");
4279            goto check_can_send;
4280        }
4281        if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
4282        {
4283            LSQ_DEBUG("tickable: there are sending streams");
4284            goto check_can_send;
4285        }
4286        if (handshake_done_or_doing_sess_resume(conn))
4287        {
4288            TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
4289                                                        next_write_stream)
4290                if (lsquic_stream_write_avail(stream))
4291                {
4292                    LSQ_DEBUG("tickable: stream %"PRIu64" can be written to",
4293                        stream->id);
4294                    goto check_can_send;
4295                }
4296        }
4297        else
4298        {
4299            TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
4300                                                        next_write_stream)
4301                if (lsquic_stream_is_crypto(stream)
4302                                    && lsquic_stream_write_avail(stream))
4303                {
4304                    LSQ_DEBUG("tickable: stream %"PRIu64" can be written to",
4305                        stream->id);
4306                    goto check_can_send;
4307                }
4308        }
4309        goto check_readable_streams;
4310  check_can_send:
4311        if (lsquic_send_ctl_can_send(&conn->fc_send_ctl))
4312            return 1;
4313    }
4314
4315  check_readable_streams:
4316    TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
4317        if (lsquic_stream_readable(stream))
4318        {
4319            LSQ_DEBUG("tickable: stream %"PRIu64" can be read from",
4320                stream->id);
4321            return 1;
4322        }
4323
4324    LSQ_DEBUG("not tickable");
4325    return 0;
4326}
4327
4328
4329static lsquic_time_t
4330full_conn_ci_next_tick_time (lsquic_conn_t *lconn, unsigned *why)
4331{
4332    struct full_conn *conn = (struct full_conn *) lconn;
4333    lsquic_time_t alarm_time, pacer_time, now;
4334    enum alarm_id al_id;
4335
4336    alarm_time = lsquic_alarmset_mintime(&conn->fc_alset, &al_id);
4337    pacer_time = lsquic_send_ctl_next_pacer_time(&conn->fc_send_ctl);
4338
4339    if (pacer_time && LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
4340    {
4341        now = lsquic_time_now();
4342        if (pacer_time < now)
4343            LSQ_DEBUG("%s: pacer is %"PRIu64" usec in the past", __func__,
4344                                                            now - pacer_time);
4345    }
4346
4347    if (alarm_time && pacer_time)
4348    {
4349        if (alarm_time < pacer_time)
4350        {
4351            *why = N_AEWS + al_id;
4352            return alarm_time;
4353        }
4354        else
4355        {
4356            *why = AEW_PACER;
4357            return pacer_time;
4358        }
4359    }
4360    else if (alarm_time)
4361    {
4362        *why = N_AEWS + al_id;
4363        return alarm_time;
4364    }
4365    else if (pacer_time)
4366    {
4367        *why = AEW_PACER;
4368        return pacer_time;
4369    }
4370    else
4371        return 0;
4372}
4373
4374
4375int
4376lsquic_gquic_full_conn_srej (struct lsquic_conn *lconn)
4377{
4378    struct full_conn *const conn = (struct full_conn *) lconn;
4379    const unsigned cce_idx = lconn->cn_cur_cce_idx;
4380    struct conn_cid_elem *const cce = &lconn->cn_cces[ cce_idx ];
4381    struct lsquic_stream *stream;
4382    enum lsquic_version version;
4383
4384    if (lconn->cn_esf_c->esf_is_sess_resume_enabled(conn->fc_conn.cn_enc_session))
4385    {
4386        /* We need to do this because we do not clean up any data that may
4387         * have been already sent.  This is left an optimization for the
4388         * future.
4389         */
4390        LSQ_DEBUG("received SREJ when 0RTT was on: fail handshake and let "
4391            "caller retry");
4392        full_conn_ci_hsk_done(lconn, LSQ_HSK_RESUMED_FAIL);
4393        return -1;
4394    }
4395
4396    LSQ_DEBUG("reinitialize CID and other state due to SREJ");
4397
4398    /* Generate new CID and update connections hash */
4399    if (cce->cce_hash_el.qhe_flags & QHE_HASHED)
4400    {
4401        lsquic_engine_retire_cid(conn->fc_enpub, lconn, cce_idx,
4402                                        0 /* OK to omit the `now' value */);
4403        lconn->cn_cces_mask |= 1 << cce_idx;
4404        lsquic_generate_cid_gquic(&cce->cce_cid);
4405        if (0 != lsquic_engine_add_cid(conn->fc_enpub, lconn, cce_idx))
4406            return -1;
4407    }
4408    else
4409    {
4410        LSQ_DEBUG("not hashed by CID, no need to reinsert");
4411        lsquic_generate_cid_gquic(&cce->cce_cid);
4412    }
4413    lconn->cn_esf.g->esf_reset_cid(lconn->cn_enc_session, &cce->cce_cid);
4414
4415    /* Reset version negotiation */
4416    version = highest_bit_set(conn->fc_orig_versions);
4417    init_ver_neg(conn, conn->fc_orig_versions, &version);
4418
4419    /* Reset receive history */
4420    lsquic_rechist_cleanup(&conn->fc_rechist);
4421    lsquic_rechist_init(&conn->fc_rechist, 0);
4422
4423    /* Reset send controller state */
4424    lsquic_send_ctl_cleanup(&conn->fc_send_ctl);
4425    lsquic_send_ctl_init(&conn->fc_send_ctl, &conn->fc_alset, conn->fc_enpub,
4426                     &conn->fc_ver_neg, &conn->fc_pub, 0);
4427
4428    /* Reset handshake stream state */
4429    stream = find_stream_by_id(conn, hsk_stream_id(conn));
4430    if (!stream)
4431        return -1;
4432    stream->n_unacked = 0;
4433    stream->tosend_off = 0;
4434    stream->read_offset = 0;
4435    stream->fc.sf_read_off = 0;
4436    stream->fc.sf_max_recv_off = 0;
4437
4438    lsquic_alarmset_unset(&conn->fc_alset, AL_RETX_APP);
4439    lsquic_alarmset_unset(&conn->fc_alset, AL_ACK_APP);
4440    conn->fc_flags &= ~(FC_ACK_QUEUED|FC_ACK_HAD_MISS|FC_NSTP);
4441    conn->fc_flags |= FC_GOT_SREJ;
4442
4443    return 0;
4444}
4445
4446
4447#if LSQUIC_CONN_STATS
4448static const struct conn_stats *
4449full_conn_ci_get_stats (struct lsquic_conn *lconn)
4450{
4451    struct full_conn *conn = (struct full_conn *) lconn;
4452    return &conn->fc_stats;
4453}
4454#endif
4455
4456
4457static const struct headers_stream_callbacks headers_callbacks =
4458{
4459    .hsc_on_headers      = headers_stream_on_incoming_headers,
4460    .hsc_on_push_promise = headers_stream_on_push_promise,
4461    .hsc_on_priority     = headers_stream_on_priority,
4462    .hsc_on_stream_error = headers_stream_on_stream_error,
4463    .hsc_on_conn_error   = headers_stream_on_conn_error,
4464    .hsc_on_enable_push  = headers_stream_on_enable_push,
4465};
4466
4467static const struct headers_stream_callbacks *headers_callbacks_ptr = &headers_callbacks;
4468
4469static const struct conn_iface full_conn_iface = {
4470    .ci_abort                =  full_conn_ci_abort,
4471    .ci_abort_error          =  full_conn_ci_abort_error,
4472    .ci_ack_rollback         =  full_conn_ci_ack_rollback,
4473    .ci_ack_snapshot         =  full_conn_ci_ack_snapshot,
4474    .ci_can_write_ack        =  full_conn_ci_can_write_ack,
4475    .ci_cancel_pending_streams
4476                             =  full_conn_ci_cancel_pending_streams,
4477    .ci_client_call_on_new   =  full_conn_ci_client_call_on_new,
4478    .ci_close                =  full_conn_ci_close,
4479    .ci_destroy              =  full_conn_ci_destroy,
4480    .ci_get_ctx              =  full_conn_ci_get_ctx,
4481    .ci_get_stream_by_id     =  full_conn_ci_get_stream_by_id,
4482    .ci_get_engine           =  full_conn_ci_get_engine,
4483    .ci_get_path             =  full_conn_ci_get_path,
4484#if LSQUIC_CONN_STATS
4485    .ci_get_stats            =  full_conn_ci_get_stats,
4486#endif
4487    .ci_going_away           =  full_conn_ci_going_away,
4488    .ci_hsk_done             =  full_conn_ci_hsk_done,
4489    .ci_internal_error       =  full_conn_ci_internal_error,
4490    .ci_is_push_enabled      =  full_conn_ci_is_push_enabled,
4491    .ci_is_tickable          =  full_conn_ci_is_tickable,
4492    .ci_make_stream          =  full_conn_ci_make_stream,
4493    .ci_n_avail_streams      =  full_conn_ci_n_avail_streams,
4494    .ci_n_pending_streams    =  full_conn_ci_n_pending_streams,
4495    .ci_next_packet_to_send  =  full_conn_ci_next_packet_to_send,
4496    .ci_next_tick_time       =  full_conn_ci_next_tick_time,
4497    .ci_packet_in            =  full_conn_ci_packet_in,
4498    .ci_packet_not_sent      =  full_conn_ci_packet_not_sent,
4499    .ci_packet_sent          =  full_conn_ci_packet_sent,
4500    .ci_record_addrs         =  full_conn_ci_record_addrs,
4501    /* gQUIC connection does not need this functionality because it only
4502     * uses one CID and it's liveness is updated automatically by the
4503     * caller when packets come in.
4504     */
4505    .ci_report_live          =  NULL,
4506    .ci_set_ctx              =  full_conn_ci_set_ctx,
4507    .ci_status               =  full_conn_ci_status,
4508    .ci_tick                 =  full_conn_ci_tick,
4509    .ci_write_ack            =  full_conn_ci_write_ack,
4510    .ci_push_stream          =  full_conn_ci_push_stream,
4511    .ci_tls_alert            =  full_conn_ci_tls_alert,
4512};
4513
4514static const struct conn_iface *full_conn_iface_ptr = &full_conn_iface;
4515