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