lsquic_full_conn.c revision 7d09751d
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_stream *
1411full_conn_ci_get_stream_by_id (struct lsquic_conn *lconn,
1412                               lsquic_stream_id_t stream_id)
1413{
1414    struct full_conn *conn = (struct full_conn *) lconn;
1415    return find_stream_by_id(conn, stream_id);
1416}
1417
1418
1419static struct lsquic_engine *
1420full_conn_ci_get_engine (struct lsquic_conn *lconn)
1421{
1422    struct full_conn *conn = (struct full_conn *) lconn;
1423    return conn->fc_enpub->enp_engine;
1424}
1425
1426
1427static struct network_path *
1428full_conn_ci_get_path (struct lsquic_conn *lconn, const struct sockaddr *sa)
1429{
1430    struct full_conn *conn = (struct full_conn *) lconn;
1431
1432    return &conn->fc_path;
1433}
1434
1435
1436static unsigned char
1437full_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
1438            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
1439{
1440    struct full_conn *conn = (struct full_conn *) lconn;
1441
1442    if (NP_IS_IPv6(&conn->fc_path) != (AF_INET6 == peer_sa->sa_family))
1443        lsquic_send_ctl_return_enc_data(&conn->fc_send_ctl);
1444
1445    size_t len = peer_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in)
1446                                                : sizeof(struct sockaddr_in6);
1447
1448    memcpy(conn->fc_path.np_peer_addr, peer_sa, len);
1449
1450    len = local_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in)
1451                                                : sizeof(struct sockaddr_in6);
1452    memcpy(conn->fc_path.np_local_addr, local_sa, len);
1453    conn->fc_path.np_peer_ctx = peer_ctx;
1454    return 0;
1455}
1456
1457
1458static ptrdiff_t
1459count_zero_bytes (const unsigned char *p, size_t len)
1460{
1461    const unsigned char *const end = p + len;
1462    while (p < end && 0 == *p)
1463        ++p;
1464    return len - (end - p);
1465}
1466
1467
1468static unsigned
1469process_padding_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1470                       const unsigned char *p, size_t len)
1471{
1472    len = (size_t) count_zero_bytes(p, len);
1473    EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len);
1474    return len;
1475}
1476
1477
1478static unsigned
1479process_ping_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1480                    const unsigned char *p, size_t len)
1481{   /* This frame causes ACK frame to be queued, but nothing to do here;
1482     * return the length of this frame.
1483     */
1484    EV_LOG_PING_FRAME_IN(LSQUIC_LOG_CONN_ID);
1485    LSQ_DEBUG("received PING");
1486    return 1;
1487}
1488
1489
1490static int
1491is_peer_initiated (const struct full_conn *conn, lsquic_stream_id_t stream_id)
1492{
1493    unsigned is_server = !!(conn->fc_flags & FC_SERVER);
1494    int peer_initiated = (stream_id & 1) == is_server;
1495    return peer_initiated;
1496}
1497
1498
1499static void
1500maybe_schedule_reset_for_stream (struct full_conn *conn, lsquic_stream_id_t stream_id)
1501{
1502    struct stream_id_to_reset *sitr;
1503
1504    if (conn_is_stream_closed(conn, stream_id))
1505        return;
1506
1507    sitr = malloc(sizeof(*sitr));
1508    if (!sitr)
1509        return;
1510
1511    sitr->sitr_stream_id = stream_id;
1512    STAILQ_INSERT_TAIL(&conn->fc_stream_ids_to_reset, sitr, sitr_next);
1513    conn_mark_stream_closed(conn, stream_id);
1514}
1515
1516
1517static unsigned
1518process_stream_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1519                      const unsigned char *p, size_t len)
1520{
1521    stream_frame_t *stream_frame;
1522    lsquic_stream_t *stream;
1523    enum enc_level enc_level;
1524    int parsed_len;
1525
1526#ifndef LSQUIC_REDO_FAILED_INSERTION
1527#define LSQUIC_REDO_FAILED_INSERTION 0
1528#endif
1529#if LSQUIC_REDO_FAILED_INSERTION
1530    enum lsq_log_level saved_levels[3];
1531#if defined(__GNUC__) && !defined(__clang__)
1532    /* gcc complains about this -- incorrectly -- in optimized mode */
1533    saved_levels[0] = 0;
1534    saved_levels[1] = 0;
1535    saved_levels[2] = 0;
1536#endif
1537    int again = 0;
1538  redo:
1539#endif
1540    stream_frame = lsquic_malo_get(conn->fc_pub.mm->malo.stream_frame);
1541    if (!stream_frame)
1542    {
1543        LSQ_WARN("could not allocate stream frame: %s", strerror(errno));
1544        return 0;
1545    }
1546
1547    parsed_len = conn->fc_conn.cn_pf->pf_parse_stream_frame(p, len,
1548                                                            stream_frame);
1549    if (parsed_len < 0) {
1550        lsquic_malo_put(stream_frame);
1551        return 0;
1552    }
1553    EV_LOG_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_frame);
1554    LSQ_DEBUG("Got stream frame for stream #%"PRIu64, stream_frame->stream_id);
1555#if LSQUIC_CONN_STATS
1556    ++conn->fc_stats.in.stream_frames;
1557    conn->fc_stats.in.stream_data_sz += stream_frame->data_frame.df_size;
1558#endif
1559
1560    enc_level = lsquic_packet_in_enc_level(packet_in);
1561    if (!is_handshake_stream_id(conn, stream_frame->stream_id)
1562        && enc_level == ENC_LEV_CLEAR)
1563    {
1564        lsquic_malo_put(stream_frame);
1565        ABORT_ERROR("received unencrypted data for stream %"PRIu64,
1566                    stream_frame->stream_id);
1567        return 0;
1568    }
1569
1570    if (conn->fc_flags & FC_CLOSING)
1571    {
1572        LSQ_DEBUG("Connection closing: ignore frame");
1573        lsquic_malo_put(stream_frame);
1574        return parsed_len;
1575    }
1576
1577    stream = find_stream_by_id(conn, stream_frame->stream_id);
1578    if (stream)
1579    {
1580        if (lsquic_stream_is_reset(stream))
1581        {
1582            LSQ_DEBUG("stream %"PRIu64" is reset, ignore frame", stream->id);
1583            lsquic_malo_put(stream_frame);
1584            return parsed_len;
1585        }
1586    }
1587    else
1588    {
1589        if (conn_is_stream_closed(conn, stream_frame->stream_id))
1590        {
1591            LSQ_DEBUG("drop frame for closed stream %"PRIu64,
1592                                                stream_frame->stream_id);
1593            lsquic_malo_put(stream_frame);
1594            return parsed_len;
1595        }
1596        if (is_peer_initiated(conn, stream_frame->stream_id))
1597        {
1598            unsigned in_count = count_streams(conn, 1);
1599            LSQ_DEBUG("number of peer-initiated streams: %u", in_count);
1600            if (in_count >= conn->fc_cfg.max_streams_in)
1601            {
1602                if (!(conn->fc_flags & FC_ABORT_COMPLAINED))
1603                {
1604                    unsigned counts[N_SCNTS];
1605                    collect_stream_counts(conn, 1, counts);
1606                    ABORT_WARN("incoming stream would exceed limit: %u.  "
1607                        "all: %u; peer: %u; closed: %u; reset: %u; reset "
1608                        "and not closed: %u", conn->fc_cfg.max_streams_in,
1609                        counts[SCNT_ALL], counts[SCNT_PEER],
1610                        counts[SCNT_CLOSED], counts[SCNT_RESET],
1611                        counts[SCNT_RES_UNCLO]);
1612                }
1613                lsquic_malo_put(stream_frame);
1614                return 0;
1615            }
1616            if ((conn->fc_flags & FC_GOING_AWAY) &&
1617                stream_frame->stream_id > conn->fc_max_peer_stream_id)
1618            {
1619                LSQ_DEBUG("going away: reset new incoming stream %"PRIu64,
1620                                                    stream_frame->stream_id);
1621                maybe_schedule_reset_for_stream(conn, stream_frame->stream_id);
1622                lsquic_malo_put(stream_frame);
1623                return parsed_len;
1624            }
1625        }
1626        else
1627        {
1628            ABORT_ERROR("frame for never-initiated stream");
1629            lsquic_malo_put(stream_frame);
1630            return 0;
1631        }
1632        stream = new_stream(conn, stream_frame->stream_id, SCF_CALL_ON_NEW);
1633        if (!stream)
1634        {
1635            ABORT_ERROR("cannot create new stream: %s", strerror(errno));
1636            lsquic_malo_put(stream_frame);
1637            return 0;
1638        }
1639        if (stream_frame->stream_id > conn->fc_max_peer_stream_id)
1640            conn->fc_max_peer_stream_id = stream_frame->stream_id;
1641    }
1642
1643    stream_frame->packet_in = lsquic_packet_in_get(packet_in);
1644    if (0 != lsquic_stream_frame_in(stream, stream_frame))
1645    {
1646        ABORT_ERROR("cannot insert stream frame");
1647#if LSQUIC_REDO_FAILED_INSERTION
1648        if (again++)
1649        {
1650            lsq_log_levels[LSQLM_STREAM] = saved_levels[0];
1651            lsq_log_levels[LSQLM_DI]     = saved_levels[1];
1652            lsq_log_levels[LSQLM_CONN]   = saved_levels[2];
1653        }
1654        else if (!(LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_STREAM)
1655                && LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_DI)
1656                && LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_CONN)))
1657        {
1658            saved_levels[0] = lsq_log_levels[LSQLM_STREAM];
1659            saved_levels[1] = lsq_log_levels[LSQLM_DI];
1660            saved_levels[2] = lsq_log_levels[LSQLM_CONN];
1661            lsq_log_levels[LSQLM_STREAM] = LSQ_LOG_DEBUG;
1662            lsq_log_levels[LSQLM_DI]     = LSQ_LOG_DEBUG;
1663            lsq_log_levels[LSQLM_CONN]   = LSQ_LOG_DEBUG;
1664            lsquic_stream_dump_state(stream);
1665            LSQ_DEBUG("inserting frame again, this time with debug logging");
1666            goto redo;
1667        }
1668#endif
1669        return 0;
1670    }
1671
1672    if (lsquic_stream_is_crypto(stream)
1673        && (stream->sm_qflags & SMQF_WANT_READ)
1674        && !(conn->fc_flags & FC_SERVER)
1675        && !(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE))
1676    {   /* To enable decryption, process handshake stream as soon as its
1677         * data frames are received.
1678         *
1679         * TODO: this does not work when packets are reordered.  A more
1680         * flexible solution would defer packet decryption if handshake
1681         * has not been completed yet.  Nevertheless, this is good enough
1682         * for now.
1683         */
1684        lsquic_stream_dispatch_read_events(stream);
1685    }
1686
1687    return parsed_len;
1688}
1689
1690
1691static unsigned
1692process_crypto_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1693                      const unsigned char *p, size_t len)
1694{
1695    struct lsquic_stream *stream;
1696    stream_frame_t *stream_frame;
1697    enum enc_level enc_level;
1698    int parsed_len;
1699
1700    stream_frame = lsquic_malo_get(conn->fc_pub.mm->malo.stream_frame);
1701    if (!stream_frame)
1702    {
1703        LSQ_WARN("could not allocate stream frame: %s", strerror(errno));
1704        return 0;
1705    }
1706
1707    parsed_len = conn->fc_conn.cn_pf->pf_parse_crypto_frame(p, len,
1708                                                            stream_frame);
1709    if (parsed_len < 0)
1710    {
1711        lsquic_malo_put(stream_frame);
1712        return 0;
1713    }
1714    enc_level = lsquic_packet_in_enc_level(packet_in);
1715    EV_LOG_CRYPTO_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_frame, enc_level);
1716    LSQ_DEBUG("Got CRYPTO frame on enc level %s", lsquic_enclev2str[enc_level]);
1717
1718    if (enc_level < conn->fc_crypto_enc_level)
1719    {
1720        LSQ_DEBUG("Old enc level: ignore frame");
1721        lsquic_malo_put(stream_frame);
1722        return parsed_len;
1723    }
1724
1725    if (conn->fc_flags & FC_CLOSING)
1726    {
1727        LSQ_DEBUG("Connection closing: ignore frame");
1728        lsquic_malo_put(stream_frame);
1729        return parsed_len;
1730    }
1731
1732    stream = find_stream_by_id(conn, hsk_stream_id(conn));
1733    if (!stream)
1734    {
1735        LSQ_WARN("cannot find handshake stream for CRYPTO frame");
1736        lsquic_malo_put(stream_frame);
1737        return 0;
1738    }
1739
1740    if (enc_level > conn->fc_crypto_enc_level)
1741    {
1742        stream->read_offset = 0;
1743        stream->tosend_off = 0;
1744        conn->fc_crypto_enc_level = enc_level;
1745        LSQ_DEBUG("reset handshake stream offsets, new enc level %u",
1746                                                        (unsigned) enc_level);
1747    }
1748
1749    stream_frame->packet_in = lsquic_packet_in_get(packet_in);
1750    if (0 != lsquic_stream_frame_in(stream, stream_frame))
1751    {
1752        ABORT_ERROR("cannot insert stream frame");
1753        return 0;
1754    }
1755
1756    if ((stream->sm_qflags & SMQF_WANT_READ)
1757        && !(conn->fc_flags & FC_SERVER)
1758        && !(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE))
1759    {
1760        /* XXX what happens for server? */
1761        lsquic_stream_dispatch_read_events(stream);
1762    }
1763
1764    return parsed_len;
1765}
1766
1767
1768static unsigned
1769process_invalid_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1770                                            const unsigned char *p, size_t len)
1771{
1772    ABORT_ERROR("invalid frame");
1773    return 0;
1774}
1775
1776
1777/* Reset locally-initiated streams whose IDs is larger than the stream ID
1778 * specified in received GOAWAY frame.
1779 */
1780static void
1781reset_local_streams_over_goaway (struct full_conn *conn)
1782{
1783    const unsigned is_server = !!(conn->fc_flags & FC_SERVER);
1784    lsquic_stream_t *stream;
1785    struct lsquic_hash_elem *el;
1786
1787    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
1788                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
1789    {
1790        stream = lsquic_hashelem_getdata(el);
1791        if (stream->id > conn->fc_goaway_stream_id &&
1792            ((stream->id & 1) ^ is_server /* Locally initiated? */))
1793        {
1794            lsquic_stream_received_goaway(stream);
1795        }
1796    }
1797}
1798
1799
1800static unsigned
1801process_goaway_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1802                                            const unsigned char *p, size_t len)
1803{
1804    lsquic_stream_id_t stream_id;
1805    uint32_t error_code;
1806    uint16_t reason_length;
1807    const char *reason;
1808    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_goaway_frame(p, len,
1809                            &error_code, &stream_id, &reason_length, &reason);
1810    if (parsed_len < 0)
1811        return 0;
1812    EV_LOG_GOAWAY_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code, stream_id,
1813        reason_length, reason);
1814    LSQ_DEBUG("received GOAWAY frame, last good stream ID: %"PRIu64
1815        ", error code: 0x%X, reason: `%.*s'", stream_id, error_code,
1816        reason_length, reason);
1817    if (0 == (conn->fc_conn.cn_flags & LSCONN_PEER_GOING_AWAY))
1818    {
1819        conn->fc_conn.cn_flags |= LSCONN_PEER_GOING_AWAY;
1820        conn->fc_goaway_stream_id = stream_id;
1821        if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_goaway_received)
1822        {
1823            LSQ_DEBUG("calling on_goaway_received");
1824            conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_goaway_received(
1825                                            &conn->fc_conn);
1826        }
1827        else
1828            LSQ_DEBUG("on_goaway_received not registered");
1829        reset_local_streams_over_goaway(conn);
1830    }
1831    else
1832        LSQ_DEBUG("ignore duplicate GOAWAY frame");
1833    return parsed_len;
1834}
1835
1836
1837static void
1838log_invalid_ack_frame (struct full_conn *conn, const unsigned char *p,
1839                                int parsed_len, const struct ack_info *acki)
1840{
1841    char *buf;
1842
1843    buf = malloc(0x1000);
1844    if (!buf)
1845    {
1846        LSQ_WARN("malloc failed");
1847        return;
1848    }
1849
1850    lsquic_senhist_tostr(&conn->fc_send_ctl.sc_senhist, buf, 0x1000);
1851    LSQ_WARN("send history: %s", buf);
1852    lsquic_hexdump(p, parsed_len, buf, 0x1000);
1853    LSQ_WARN("raw ACK frame:\n%s", buf);
1854    lsquic_acki2str(acki, buf, 0x1000);
1855    LSQ_WARN("parsed ACK frame: %s", buf);
1856    free(buf);
1857}
1858
1859
1860static int
1861process_ack (struct full_conn *conn, struct ack_info *acki,
1862             lsquic_time_t received, lsquic_time_t now)
1863{
1864#if LSQUIC_CONN_STATS
1865    ++conn->fc_stats.in.n_acks_proc;
1866#endif
1867    LSQ_DEBUG("Processing ACK");
1868    if (0 == lsquic_send_ctl_got_ack(&conn->fc_send_ctl, acki, received, now))
1869    {
1870        if (lsquic_send_ctl_largest_ack2ed(&conn->fc_send_ctl, PNS_APP))
1871            lsquic_rechist_stop_wait(&conn->fc_rechist,
1872                lsquic_send_ctl_largest_ack2ed(&conn->fc_send_ctl, PNS_APP)
1873                                                                        + 1);
1874        return 0;
1875    }
1876    else
1877    {
1878        ABORT_ERROR("Received invalid ACK");
1879        return -1;
1880    }
1881}
1882
1883
1884static unsigned
1885process_ack_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1886                                            const unsigned char *p, size_t len)
1887{
1888    struct ack_info *new_acki;
1889    int parsed_len;
1890    lsquic_time_t warn_time;
1891
1892#if LSQUIC_CONN_STATS
1893    ++conn->fc_stats.in.n_acks;
1894#endif
1895
1896    if (conn->fc_flags & FC_HAVE_SAVED_ACK)
1897        new_acki = conn->fc_pub.mm->acki;
1898    else
1899        new_acki = &conn->fc_ack;
1900
1901    parsed_len = conn->fc_conn.cn_pf->pf_parse_ack_frame(p, len, new_acki, 0);
1902    if (parsed_len < 0)
1903        goto err;
1904
1905    if (empty_ack_frame(new_acki))
1906    {
1907        LSQ_DEBUG("Ignore empty ACK frame");
1908        return parsed_len;
1909    }
1910    if (packet_in->pi_packno <= conn->fc_max_ack_packno)
1911    {
1912        LSQ_DEBUG("Ignore old ack (max %"PRIu64")", conn->fc_max_ack_packno);
1913        return parsed_len;
1914    }
1915
1916    new_acki->pns = PNS_APP;
1917    EV_LOG_ACK_FRAME_IN(LSQUIC_LOG_CONN_ID, new_acki);
1918    conn->fc_max_ack_packno = packet_in->pi_packno;
1919
1920    if (new_acki == &conn->fc_ack)
1921    {
1922        LSQ_DEBUG("Saved ACK");
1923        conn->fc_flags |= FC_HAVE_SAVED_ACK;
1924        conn->fc_saved_ack_received = packet_in->pi_received;
1925    }
1926    else
1927    {
1928        if (0 == lsquic_merge_acks(&conn->fc_ack, new_acki))
1929        {
1930#if LSQUIC_CONN_STATS
1931            ++conn->fc_stats.in.n_acks_merged;
1932#endif
1933            LSQ_DEBUG("merged into saved ACK, getting %s",
1934                (lsquic_acki2str(&conn->fc_ack, conn->fc_pub.mm->ack_str,
1935                                MAX_ACKI_STR_SZ), conn->fc_pub.mm->ack_str));
1936        }
1937        else
1938        {
1939            LSQ_DEBUG("could not merge new ACK into saved ACK");
1940            if (0 != process_ack(conn, &conn->fc_ack, packet_in->pi_received,
1941                                                        packet_in->pi_received))
1942                goto err;
1943            conn->fc_ack = *new_acki;
1944        }
1945        conn->fc_saved_ack_received = packet_in->pi_received;
1946    }
1947
1948    return parsed_len;
1949
1950  err:
1951    warn_time = lsquic_time_now();
1952    if (0 == conn->fc_enpub->enp_last_warning[WT_ACKPARSE_FULL]
1953        || conn->fc_enpub->enp_last_warning[WT_ACKPARSE_FULL]
1954                + WARNING_INTERVAL < warn_time)
1955    {
1956        conn->fc_enpub->enp_last_warning[WT_ACKPARSE_FULL] = warn_time;
1957        log_invalid_ack_frame(conn, p, parsed_len, new_acki);
1958    }
1959    return 0;
1960}
1961
1962
1963static unsigned
1964process_stop_waiting_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1965                                            const unsigned char *p, size_t len)
1966{
1967    lsquic_packno_t least, cutoff;
1968    enum packno_bits bits;
1969    int parsed_len;
1970
1971    bits = lsquic_packet_in_packno_bits(packet_in);
1972
1973    if (conn->fc_flags & FC_NSTP)
1974    {
1975        LSQ_DEBUG("NSTP on: ignore STOP_WAITING frame");
1976        parsed_len = conn->fc_conn.cn_pf->pf_skip_stop_waiting_frame(len, bits);
1977        if (parsed_len > 0)
1978            return (unsigned) parsed_len;
1979        else
1980            return 0;
1981    }
1982
1983    parsed_len = conn->fc_conn.cn_pf->pf_parse_stop_waiting_frame(p, len,
1984                                            packet_in->pi_packno, bits, &least);
1985    if (parsed_len < 0)
1986        return 0;
1987
1988    if (packet_in->pi_packno <= conn->fc_max_swf_packno)
1989    {
1990        LSQ_DEBUG("ignore old STOP_WAITING frame");
1991        return parsed_len;
1992    }
1993
1994    LSQ_DEBUG("Got STOP_WAITING frame, least unacked: %"PRIu64, least);
1995    EV_LOG_STOP_WAITING_FRAME_IN(LSQUIC_LOG_CONN_ID, least);
1996
1997    if (least > packet_in->pi_packno)
1998    {
1999        ABORT_ERROR("received invalid STOP_WAITING: %"PRIu64" is larger "
2000            "than the packet number%"PRIu64, least, packet_in->pi_packno);
2001        return 0;
2002    }
2003
2004    cutoff = lsquic_rechist_cutoff(&conn->fc_rechist);
2005    if (cutoff && least < cutoff)
2006    {
2007        ABORT_ERROR("received invalid STOP_WAITING: %"PRIu64" is smaller "
2008            "than the cutoff %"PRIu64, least, cutoff);
2009        return 0;
2010    }
2011
2012    conn->fc_max_swf_packno = packet_in->pi_packno;
2013    lsquic_rechist_stop_wait(&conn->fc_rechist, least);
2014    return parsed_len;
2015}
2016
2017
2018static unsigned
2019process_blocked_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2020                                            const unsigned char *p, size_t len)
2021{
2022    lsquic_stream_id_t stream_id;
2023    struct lsquic_stream *stream;
2024    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_blocked_frame(p, len,
2025                                                                    &stream_id);
2026    if (parsed_len < 0)
2027        return 0;
2028    EV_LOG_BLOCKED_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id);
2029    LSQ_DEBUG("Peer reports stream %"PRIu64" as blocked", stream_id);
2030    if (stream_id)
2031    {
2032        stream = find_stream_by_id(conn, stream_id);
2033        if (stream)
2034            lsquic_stream_peer_blocked_gquic(stream);
2035    }
2036    else
2037        conn->fc_flags |= FC_SEND_WUF;
2038    return parsed_len;
2039}
2040
2041
2042static unsigned
2043process_connection_close_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2044                                const unsigned char *p, size_t len)
2045{
2046    lsquic_stream_t *stream;
2047    struct lsquic_hash_elem *el;
2048    uint64_t error_code;
2049    uint16_t reason_len;
2050    uint8_t reason_off;
2051    int parsed_len;
2052
2053    parsed_len = conn->fc_conn.cn_pf->pf_parse_connect_close_frame(p, len,
2054                                NULL, &error_code, &reason_len, &reason_off);
2055    if (parsed_len < 0)
2056        return 0;
2057    EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code,
2058                            (int) reason_len, (const char *) p + reason_off);
2059    LSQ_INFO("Received CONNECTION_CLOSE frame (code: %"PRIu64"; reason: %.*s)",
2060                error_code, (int) reason_len, (const char *) p + reason_off);
2061    conn->fc_flags |= FC_RECV_CLOSE;
2062    if (!(conn->fc_flags & FC_CLOSING))
2063    {
2064        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
2065                                     el = lsquic_hash_next(conn->fc_pub.all_streams))
2066        {
2067            stream = lsquic_hashelem_getdata(el);
2068            lsquic_stream_shutdown_internal(stream);
2069        }
2070        conn->fc_flags |= FC_CLOSING;
2071    }
2072    return parsed_len;
2073}
2074
2075
2076static unsigned
2077process_rst_stream_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2078                                            const unsigned char *p, size_t len)
2079{
2080    lsquic_stream_id_t stream_id;
2081    uint64_t offset, error_code;
2082    lsquic_stream_t *stream;
2083    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_rst_frame(p, len,
2084                                            &stream_id, &offset, &error_code);
2085    if (parsed_len < 0)
2086        return 0;
2087
2088    EV_LOG_RST_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset,
2089                                                                error_code);
2090    LSQ_DEBUG("Got RST_STREAM; stream: %"PRIu64"; offset: 0x%"PRIX64, stream_id,
2091                                                                    offset);
2092    if (0 == stream_id)
2093    {   /* Follow reference implementation and ignore this apparently
2094         * invalid frame.
2095         */
2096        return parsed_len;
2097    }
2098
2099    stream = find_stream_by_id(conn, stream_id);
2100    if (stream && lsquic_stream_is_critical(stream))
2101    {
2102        ABORT_ERROR("received reset on static stream %"PRIu64, stream_id);
2103        return 0;
2104    }
2105    if (!stream)
2106    {
2107        if (conn_is_stream_closed(conn, stream_id))
2108        {
2109            LSQ_DEBUG("got reset frame for closed stream %"PRIu64, stream_id);
2110            return parsed_len;
2111        }
2112        if (!is_peer_initiated(conn, stream_id))
2113        {
2114            ABORT_ERROR("received reset for never-initiated stream %"PRIu64,
2115                                                                    stream_id);
2116            return 0;
2117        }
2118        stream = new_stream(conn, stream_id, SCF_CALL_ON_NEW);
2119        if (!stream)
2120        {
2121            ABORT_ERROR("cannot create new stream: %s", strerror(errno));
2122            return 0;
2123        }
2124        if (stream_id > conn->fc_max_peer_stream_id)
2125            conn->fc_max_peer_stream_id = stream_id;
2126    }
2127
2128    if (0 != lsquic_stream_rst_in(stream, offset, error_code))
2129    {
2130        ABORT_ERROR("received invalid RST_STREAM");
2131        return 0;
2132    }
2133    return parsed_len;
2134}
2135
2136
2137static unsigned
2138process_window_update_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2139                                             const unsigned char *p, size_t len)
2140{
2141    lsquic_stream_id_t stream_id;
2142    uint64_t offset;
2143    const int parsed_len =
2144                conn->fc_conn.cn_pf->pf_parse_window_update_frame(p, len,
2145                                                        &stream_id, &offset);
2146    if (parsed_len < 0)
2147        return 0;
2148    EV_LOG_WINDOW_UPDATE_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset);
2149    if (stream_id)
2150    {
2151        lsquic_stream_t *stream = find_stream_by_id(conn, stream_id);
2152        if (stream)
2153        {
2154            LSQ_DEBUG("Got window update frame, stream: %"PRIu64
2155                      "; offset: 0x%"PRIX64, stream_id, offset);
2156            lsquic_stream_window_update(stream, offset);
2157        }
2158        else    /* Perhaps a result of lost packets? */
2159            LSQ_DEBUG("Got window update frame for non-existing stream %"PRIu64
2160                                 " (offset: 0x%"PRIX64")", stream_id, offset);
2161    }
2162    else if (offset > conn->fc_pub.conn_cap.cc_max)
2163    {
2164        conn->fc_pub.conn_cap.cc_max = offset;
2165        assert(conn->fc_pub.conn_cap.cc_max >= conn->fc_pub.conn_cap.cc_sent);
2166        LSQ_DEBUG("Connection WUF, new offset 0x%"PRIX64, offset);
2167    }
2168    else
2169        LSQ_DEBUG("Throw ouw duplicate connection WUF");
2170    return parsed_len;
2171}
2172
2173
2174typedef unsigned (*process_frame_f)(
2175    struct full_conn *, lsquic_packet_in_t *, const unsigned char *p, size_t);
2176
2177static process_frame_f const process_frames[N_QUIC_FRAMES] =
2178{
2179    [QUIC_FRAME_ACK]                  =  process_ack_frame,
2180    [QUIC_FRAME_BLOCKED]              =  process_blocked_frame,
2181    [QUIC_FRAME_CONNECTION_CLOSE]     =  process_connection_close_frame,
2182    [QUIC_FRAME_CRYPTO]               =  process_crypto_frame,
2183    [QUIC_FRAME_GOAWAY]               =  process_goaway_frame,
2184    [QUIC_FRAME_INVALID]              =  process_invalid_frame,
2185    [QUIC_FRAME_PADDING]              =  process_padding_frame,
2186    [QUIC_FRAME_PING]                 =  process_ping_frame,
2187    [QUIC_FRAME_RST_STREAM]           =  process_rst_stream_frame,
2188    [QUIC_FRAME_STOP_WAITING]         =  process_stop_waiting_frame,
2189    [QUIC_FRAME_STREAM]               =  process_stream_frame,
2190    [QUIC_FRAME_WINDOW_UPDATE]        =  process_window_update_frame,
2191};
2192
2193static unsigned
2194process_packet_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
2195                      const unsigned char *p, size_t len)
2196{
2197    enum quic_frame_type type = conn->fc_conn.cn_pf->pf_parse_frame_type(p[0]);
2198    packet_in->pi_frame_types |= 1 << type;
2199    recent_packet_hist_frames(conn, 0, 1 << type);
2200    return process_frames[type](conn, packet_in, p, len);
2201}
2202
2203
2204static void
2205process_ver_neg_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2206{
2207    int s;
2208    struct ver_iter vi;
2209    lsquic_ver_tag_t ver_tag;
2210    enum lsquic_version version;
2211    unsigned versions = 0;
2212
2213    LSQ_DEBUG("Processing version-negotiation packet");
2214
2215    if (conn->fc_ver_neg.vn_state != VN_START)
2216    {
2217        LSQ_DEBUG("ignore a likely duplicate version negotiation packet");
2218        return;
2219    }
2220
2221    for (s = packet_in_ver_first(packet_in, &vi, &ver_tag); s;
2222                     s = packet_in_ver_next(&vi, &ver_tag))
2223    {
2224        version = lsquic_tag2ver(ver_tag);
2225        if (version < N_LSQVER)
2226        {
2227            versions |= 1 << version;
2228            LSQ_DEBUG("server supports version %s", lsquic_ver2str[version]);
2229            EV_LOG_VER_NEG(LSQUIC_LOG_CONN_ID,
2230                                        "supports", lsquic_ver2str[version]);
2231        }
2232    }
2233
2234    if (versions & (1 << conn->fc_ver_neg.vn_ver))
2235    {
2236        ABORT_ERROR("server replied with version we support: %s",
2237                                    lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
2238        return;
2239    }
2240
2241    versions &= conn->fc_ver_neg.vn_supp;
2242    if (0 == versions)
2243    {
2244        ABORT_ERROR("client does not support any of the server-specified "
2245                    "versions");
2246        return;
2247    }
2248
2249    set_versions(conn, versions, NULL);
2250    conn->fc_ver_neg.vn_state = VN_IN_PROGRESS;
2251    lsquic_send_ctl_expire_all(&conn->fc_send_ctl);
2252}
2253
2254
2255static void
2256reconstruct_packet_number (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2257{
2258    lsquic_packno_t cur_packno, max_packno;
2259    enum packno_bits bits;
2260    unsigned packet_len;
2261
2262    cur_packno = packet_in->pi_packno;
2263    max_packno = lsquic_rechist_largest_packno(&conn->fc_rechist);
2264    bits = lsquic_packet_in_packno_bits(packet_in);
2265    packet_len = conn->fc_conn.cn_pf->pf_packno_bits2len(bits);
2266    packet_in->pi_packno = restore_packno(cur_packno, packet_len, max_packno);
2267    LSQ_DEBUG("reconstructed (bits: %u, packno: %"PRIu64", max: %"PRIu64") "
2268        "to %"PRIu64"", bits, cur_packno, max_packno, packet_in->pi_packno);
2269}
2270
2271
2272static enum dec_packin
2273conn_decrypt_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2274{
2275    return conn->fc_conn.cn_esf_c->esf_decrypt_packet(
2276                    conn->fc_conn.cn_enc_session, conn->fc_enpub,
2277                    &conn->fc_conn, packet_in);
2278}
2279
2280
2281static void
2282parse_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2283{
2284    const unsigned char *p, *pend;
2285    unsigned len;
2286
2287    p = packet_in->pi_data + packet_in->pi_header_sz;
2288    pend = packet_in->pi_data + packet_in->pi_data_sz;
2289
2290    while (p < pend)
2291    {
2292        len = process_packet_frame(conn, packet_in, p, pend - p);
2293        if (len > 0)
2294            p += len;
2295        else
2296        {
2297            ABORT_ERROR("Error parsing frame");
2298            break;
2299        }
2300    }
2301}
2302
2303
2304static int
2305conn_is_stateless_reset (const struct full_conn *conn,
2306                                    const struct lsquic_packet_in *packet_in)
2307{
2308    return packet_in->pi_data_sz > SRST_LENGTH
2309        && 0 == conn->fc_conn.cn_esf_c->esf_verify_reset_token(
2310                    conn->fc_conn.cn_enc_session,
2311                    packet_in->pi_data + packet_in->pi_data_sz - SRST_LENGTH,
2312                    SRST_LENGTH);
2313}
2314
2315
2316static int
2317process_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2318{
2319    enum received_st st;
2320    enum quic_ft_bit frame_types;
2321    int was_missing;
2322
2323    if (conn->fc_conn.cn_version < LSQVER_050)
2324    {
2325        reconstruct_packet_number(conn, packet_in);
2326        EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
2327    }
2328
2329#if LSQUIC_CONN_STATS
2330    ++conn->fc_stats.in.packets;
2331#endif
2332
2333    /* The packet is decrypted before receive history is updated.  This is
2334     * done to make sure that a bad packet won't occupy a slot in receive
2335     * history and subsequent good packet won't be marked as a duplicate.
2336     */
2337    if (0 == (packet_in->pi_flags & PI_DECRYPTED) &&
2338        DECPI_OK != conn_decrypt_packet(conn, packet_in))
2339    {
2340        if (conn_is_stateless_reset(conn, packet_in))
2341        {
2342            LSQ_INFO("received public reset packet: aborting connection");
2343            conn->fc_flags |= FC_GOT_PRST;
2344            return -1;
2345        }
2346        else
2347        {
2348            LSQ_INFO("could not decrypt packet");
2349#if LSQUIC_CONN_STATS
2350            ++conn->fc_stats.in.undec_packets;
2351#endif
2352            return 0;
2353        }
2354    }
2355
2356    if (conn->fc_conn.cn_version >= LSQVER_050)
2357        EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
2358
2359    st = lsquic_rechist_received(&conn->fc_rechist, packet_in->pi_packno,
2360                                                    packet_in->pi_received);
2361    switch (st) {
2362    case REC_ST_OK:
2363        parse_regular_packet(conn, packet_in);
2364        if (0 == (conn->fc_flags & (FC_ACK_QUEUED|FC_GOT_SREJ)))
2365        {
2366            frame_types = packet_in->pi_frame_types;
2367            if ((conn->fc_flags & FC_GOING_AWAY)
2368                && lsquic_hash_count(conn->fc_pub.all_streams) < 3)
2369            {
2370                /* Ignore PING frames if we are going away and there are no
2371                 * active streams.  (HANDSHAKE and HEADERS streams are the
2372                 * two streams that are always in the all_streams hash).
2373                 */
2374                frame_types &= ~(1 << QUIC_FRAME_PING);
2375            }
2376            was_missing = packet_in->pi_packno !=
2377                            lsquic_rechist_largest_packno(&conn->fc_rechist);
2378            conn->fc_n_slack_akbl += !!(frame_types & GQUIC_FRAME_ACKABLE_MASK);
2379            try_queueing_ack(conn, was_missing, packet_in->pi_received);
2380        }
2381        else if (conn->fc_flags & FC_GOT_SREJ)
2382            conn->fc_flags &= ~FC_GOT_SREJ;
2383        return 0;
2384    case REC_ST_DUP:
2385#if LSQUIC_CONN_STATS
2386        ++conn->fc_stats.in.dup_packets;
2387#endif
2388        LSQ_INFO("packet %"PRIu64" is a duplicate", packet_in->pi_packno);
2389        return 0;
2390    default:
2391        assert(0);
2392        /* Fall through */
2393    case REC_ST_ERR:
2394#if LSQUIC_CONN_STATS
2395        ++conn->fc_stats.in.err_packets;
2396#endif
2397        LSQ_INFO("error processing packet %"PRIu64, packet_in->pi_packno);
2398        return -1;
2399    }
2400}
2401
2402
2403/* TODO: Possible optimization: in server mode, we do not perform version
2404 * negotiation.  We can use different functions in client mode (this
2405 * function) and server mode (a different, faster function that ignores
2406 * version flags).
2407 */
2408static int
2409process_incoming_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
2410{
2411    int is_prst, is_verneg;
2412
2413    recent_packet_hist_new(conn, 0, packet_in->pi_received);
2414    LSQ_DEBUG("Processing packet %"PRIu64, packet_in->pi_packno);
2415
2416    is_prst = lsquic_packet_in_is_gquic_prst(packet_in);
2417    is_verneg = lsquic_packet_in_is_verneg(packet_in);
2418
2419    /* See flowchart in Section 4.1 of [draft-ietf-quic-transport-00].  We test
2420     * for the common case first.
2421     */
2422    if (0 == is_prst && 0 == is_verneg)
2423    {
2424        if (conn->fc_ver_neg.vn_tag)
2425        {
2426            assert(conn->fc_ver_neg.vn_state != VN_END);
2427            conn->fc_ver_neg.vn_state = VN_END;
2428            conn->fc_ver_neg.vn_tag = NULL;
2429            conn->fc_conn.cn_version = conn->fc_ver_neg.vn_ver;
2430            conn->fc_conn.cn_flags |= LSCONN_VER_SET;
2431            assert(!(conn->fc_flags & FC_NSTP)); /* This bit off at start */
2432            if (conn->fc_conn.cn_version >= LSQVER_046
2433                                    || conn->fc_settings->es_support_nstp)
2434            {
2435                conn->fc_flags |= FC_NSTP;
2436                lsquic_send_ctl_turn_nstp_on(&conn->fc_send_ctl);
2437            }
2438            LSQ_DEBUG("end of version negotiation: agreed upon %s",
2439                                    lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
2440            lsquic_send_ctl_verneg_done(&conn->fc_send_ctl);
2441            EV_LOG_VER_NEG(LSQUIC_LOG_CONN_ID,
2442                            "agreed", lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
2443        }
2444        return process_regular_packet(conn, packet_in);
2445    }
2446    else if (is_prst)
2447    {
2448        LSQ_INFO("received public reset packet: aborting connection");
2449        conn->fc_flags |= FC_GOT_PRST;
2450        return -1;
2451    }
2452    else
2453    {
2454        if (conn->fc_flags & FC_SERVER)
2455            return process_regular_packet(conn, packet_in);
2456        else if (conn->fc_ver_neg.vn_tag)
2457        {
2458            process_ver_neg_packet(conn, packet_in);
2459            return 0;
2460        }
2461        else
2462        {
2463            LSQ_DEBUG("unexpected version negotiation packet: ignore it");
2464            return 0;
2465        }
2466    }
2467}
2468
2469
2470static void
2471idle_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
2472                                                            lsquic_time_t now)
2473{
2474    struct full_conn *conn = ctx;
2475    LSQ_DEBUG("connection timed out");
2476    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out");
2477    conn->fc_flags |= FC_TIMED_OUT;
2478}
2479
2480
2481static void
2482handshake_alarm_expired (enum alarm_id al_id, void *ctx,
2483                                    lsquic_time_t expiry, lsquic_time_t now)
2484{
2485    struct full_conn *conn = ctx;
2486    LSQ_DEBUG("connection timed out: handshake timed out");
2487    conn->fc_flags |= FC_TIMED_OUT;
2488}
2489
2490
2491static void
2492ping_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
2493                                                            lsquic_time_t now)
2494{
2495    struct full_conn *conn = ctx;
2496    LSQ_DEBUG("Ping alarm rang: schedule PING frame to be generated");
2497    conn->fc_flags |= FC_SEND_PING;
2498}
2499
2500
2501static lsquic_packet_out_t *
2502get_writeable_packet (struct full_conn *conn, unsigned need_at_least)
2503{
2504    lsquic_packet_out_t *packet_out;
2505    int is_err;
2506
2507    assert(need_at_least <= GQUIC_MAX_PAYLOAD_SZ);
2508    packet_out = lsquic_send_ctl_get_writeable_packet(&conn->fc_send_ctl,
2509                            PNS_APP, need_at_least, &conn->fc_path, 0, &is_err);
2510    if (!packet_out && is_err)
2511        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2512    return packet_out;
2513}
2514
2515
2516static int
2517generate_wuf_stream (struct full_conn *conn, lsquic_stream_t *stream)
2518{
2519    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, GQUIC_WUF_SZ);
2520    if (!packet_out)
2521        return 0;
2522    const uint64_t recv_off = lsquic_stream_fc_recv_off(stream);
2523    int sz = conn->fc_conn.cn_pf->pf_gen_window_update_frame(
2524                packet_out->po_data + packet_out->po_data_sz,
2525                     lsquic_packet_out_avail(packet_out), stream->id, recv_off);
2526    if (sz < 0) {
2527        ABORT_ERROR("gen_window_update_frame failed");
2528        return 0;
2529    }
2530    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2531    packet_out->po_frame_types |= 1 << QUIC_FRAME_WINDOW_UPDATE;
2532    LSQ_DEBUG("wrote WUF: stream %"PRIu64"; offset 0x%"PRIX64, stream->id,
2533                                                                    recv_off);
2534    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID,
2535        "wrote WUF: stream %"PRIu64"; offset 0x%"PRIX64, stream->id, recv_off);
2536    return 1;
2537}
2538
2539
2540static void
2541generate_wuf_conn (struct full_conn *conn)
2542{
2543    assert(conn->fc_flags & FC_SEND_WUF);
2544    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, GQUIC_WUF_SZ);
2545    if (!packet_out)
2546        return;
2547    const uint64_t recv_off = lsquic_cfcw_get_fc_recv_off(&conn->fc_pub.cfcw);
2548    int sz = conn->fc_conn.cn_pf->pf_gen_window_update_frame(
2549                     packet_out->po_data + packet_out->po_data_sz,
2550                     lsquic_packet_out_avail(packet_out), 0, recv_off);
2551    if (sz < 0) {
2552        ABORT_ERROR("gen_window_update_frame failed");
2553        return;
2554    }
2555    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2556    packet_out->po_frame_types |= 1 << QUIC_FRAME_WINDOW_UPDATE;
2557    conn->fc_flags &= ~FC_SEND_WUF;
2558    LSQ_DEBUG("wrote connection WUF: offset 0x%"PRIX64, recv_off);
2559}
2560
2561
2562static void
2563maybe_close_conn (struct full_conn *conn)
2564{
2565#ifndef NDEBUG
2566    struct lsquic_stream *stream;
2567    struct lsquic_hash_elem *el;
2568#endif
2569
2570    if ((conn->fc_flags & (FC_CLOSING|FC_GOAWAY_SENT|FC_SERVER))
2571                                            == (FC_GOAWAY_SENT|FC_SERVER)
2572        && lsquic_hash_count(conn->fc_pub.all_streams) == 2)
2573    {
2574#ifndef NDEBUG
2575        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
2576                             el = lsquic_hash_next(conn->fc_pub.all_streams))
2577        {
2578            stream = lsquic_hashelem_getdata(el);
2579            assert(stream->sm_bflags & (SMBF_CRYPTO|SMBF_HEADERS));
2580        }
2581#endif
2582        conn->fc_flags |= FC_RECV_CLOSE;    /* Fake -- trigger "ok to close" */
2583        conn->fc_flags |= FC_CLOSING;
2584        LSQ_DEBUG("closing connection: GOAWAY sent and no responses remain");
2585    }
2586}
2587
2588
2589static void
2590generate_goaway_frame (struct full_conn *conn)
2591{
2592    int reason_len = 0;
2593    lsquic_packet_out_t *packet_out =
2594        get_writeable_packet(conn, GQUIC_GOAWAY_FRAME_SZ + reason_len);
2595    if (!packet_out)
2596        return;
2597    int sz = conn->fc_conn.cn_pf->pf_gen_goaway_frame(
2598                 packet_out->po_data + packet_out->po_data_sz,
2599                 lsquic_packet_out_avail(packet_out), 0, conn->fc_max_peer_stream_id,
2600                 NULL, reason_len);
2601    if (sz < 0) {
2602        ABORT_ERROR("gen_goaway_frame failed");
2603        return;
2604    }
2605    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2606    packet_out->po_frame_types |= 1 << QUIC_FRAME_GOAWAY;
2607    conn->fc_flags &= ~FC_SEND_GOAWAY;
2608    conn->fc_flags |=  FC_GOAWAY_SENT;
2609    LSQ_DEBUG("wrote GOAWAY frame: stream id: %"PRIu64,
2610                                                conn->fc_max_peer_stream_id);
2611    maybe_close_conn(conn);
2612}
2613
2614
2615static void
2616generate_connection_close_packet (struct full_conn *conn)
2617{
2618    lsquic_packet_out_t *packet_out;
2619
2620    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0, PNS_APP,
2621                                                                &conn->fc_path);
2622    if (!packet_out)
2623    {
2624        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2625        return;
2626    }
2627
2628    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
2629    int sz = conn->fc_conn.cn_pf->pf_gen_connect_close_frame(packet_out->po_data + packet_out->po_data_sz,
2630                     lsquic_packet_out_avail(packet_out), 0, 16 /* PEER_GOING_AWAY */,
2631                     NULL, 0);
2632    if (sz < 0) {
2633        ABORT_ERROR("generate_connection_close_packet failed");
2634        return;
2635    }
2636    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2637    packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
2638    LSQ_DEBUG("generated CONNECTION_CLOSE frame in its own packet");
2639}
2640
2641
2642static int
2643generate_blocked_frame (struct full_conn *conn, lsquic_stream_id_t stream_id)
2644{
2645    lsquic_packet_out_t *packet_out =
2646                            get_writeable_packet(conn, GQUIC_BLOCKED_FRAME_SZ);
2647    if (!packet_out)
2648        return 0;
2649    int sz = conn->fc_conn.cn_pf->pf_gen_blocked_frame(
2650                                 packet_out->po_data + packet_out->po_data_sz,
2651                                 lsquic_packet_out_avail(packet_out), stream_id);
2652    if (sz < 0) {
2653        ABORT_ERROR("gen_blocked_frame failed");
2654        return 0;
2655    }
2656    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2657    packet_out->po_frame_types |= 1 << QUIC_FRAME_BLOCKED;
2658    LSQ_DEBUG("wrote blocked frame: stream %"PRIu64, stream_id);
2659    return 1;
2660}
2661
2662
2663static int
2664generate_stream_blocked_frame (struct full_conn *conn, lsquic_stream_t *stream)
2665{
2666    if (generate_blocked_frame(conn, stream->id))
2667    {
2668        lsquic_stream_blocked_frame_sent(stream);
2669        return 1;
2670    }
2671    else
2672        return 0;
2673}
2674
2675
2676static int
2677generate_rst_stream_frame (struct full_conn *conn, lsquic_stream_t *stream)
2678{
2679    lsquic_packet_out_t *packet_out;
2680    int sz, s;
2681
2682    packet_out = get_writeable_packet(conn, GQUIC_RST_STREAM_SZ);
2683    if (!packet_out)
2684        return 0;
2685    /* TODO Possible optimization: instead of using stream->tosend_off as the
2686     * offset, keep track of the offset that was actually sent: include it
2687     * into stream_rec and update a new per-stream "maximum offset actually
2688     * sent" field.  Then, if a stream is reset, the connection cap can be
2689     * increased.
2690     */
2691    sz = conn->fc_conn.cn_pf->pf_gen_rst_frame(
2692                     packet_out->po_data + packet_out->po_data_sz,
2693                     lsquic_packet_out_avail(packet_out), stream->id,
2694                     stream->tosend_off, stream->error_code);
2695    if (sz < 0) {
2696        ABORT_ERROR("gen_rst_frame failed");
2697        return 0;
2698    }
2699    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2700    packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
2701    s = lsquic_packet_out_add_stream(packet_out, conn->fc_pub.mm, stream,
2702                             QUIC_FRAME_RST_STREAM, packet_out->po_data_sz, sz);
2703    if (s != 0)
2704    {
2705        ABORT_ERROR("adding stream to packet failed: %s", strerror(errno));
2706        return 0;
2707    }
2708    lsquic_stream_rst_frame_sent(stream);
2709    LSQ_DEBUG("wrote RST: stream %"PRIu64"; offset 0x%"PRIX64"; error code "
2710              "%"PRIu64, stream->id, stream->tosend_off, stream->error_code);
2711    return 1;
2712}
2713
2714
2715static void
2716generate_ping_frame (struct full_conn *conn)
2717{
2718    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, 1);
2719    if (!packet_out)
2720    {
2721        LSQ_DEBUG("cannot get writeable packet for PING frame");
2722        return;
2723    }
2724    int sz = conn->fc_conn.cn_pf->pf_gen_ping_frame(
2725                            packet_out->po_data + packet_out->po_data_sz,
2726                            lsquic_packet_out_avail(packet_out));
2727    if (sz < 0) {
2728        ABORT_ERROR("gen_blocked_frame failed");
2729        return;
2730    }
2731    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2732    packet_out->po_frame_types |= 1 << QUIC_FRAME_PING;
2733    LSQ_DEBUG("wrote PING frame");
2734}
2735
2736
2737static void
2738generate_stop_waiting_frame (struct full_conn *conn)
2739{
2740    assert(conn->fc_flags & FC_SEND_STOP_WAITING);
2741
2742    int sz;
2743    unsigned packnum_len;
2744    lsquic_packno_t least_unacked;
2745    lsquic_packet_out_t *packet_out;
2746
2747    /* Get packet that has room for the minimum size STOP_WAITING frame: */
2748    packnum_len = conn->fc_conn.cn_pf->pf_packno_bits2len(GQUIC_PACKNO_LEN_1);
2749    packet_out = get_writeable_packet(conn, 1 + packnum_len);
2750    if (!packet_out)
2751        return;
2752
2753    /* Now calculate number of bytes we really need.  If there is not enough
2754     * room in the current packet, get a new one.
2755     */
2756    packnum_len = conn->fc_conn.cn_pf->pf_packno_bits2len(
2757                                    lsquic_packet_out_packno_bits(packet_out));
2758    if ((unsigned) lsquic_packet_out_avail(packet_out) < 1 + packnum_len)
2759    {
2760        packet_out = get_writeable_packet(conn, 1 + packnum_len);
2761        if (!packet_out)
2762            return;
2763        /* Here, a new packet has been allocated, The number of bytes needed
2764         * to represent packet number in the STOP_WAITING frame may have
2765         * increased.  However, this does not matter, because the newly
2766         * allocated packet must have room for a STOP_WAITING frame of any
2767         * size.
2768         */
2769    }
2770
2771    least_unacked = lsquic_send_ctl_smallest_unacked(&conn->fc_send_ctl);
2772    sz = conn->fc_conn.cn_pf->pf_gen_stop_waiting_frame(
2773                    packet_out->po_data + packet_out->po_data_sz,
2774                    lsquic_packet_out_avail(packet_out), packet_out->po_packno,
2775                    lsquic_packet_out_packno_bits(packet_out), least_unacked);
2776    if (sz < 0) {
2777        ABORT_ERROR("gen_stop_waiting_frame failed");
2778        return;
2779    }
2780    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2781    packet_out->po_regen_sz += sz;
2782    packet_out->po_frame_types |= 1 << QUIC_FRAME_STOP_WAITING;
2783    conn->fc_flags &= ~FC_SEND_STOP_WAITING;
2784    LSQ_DEBUG("wrote STOP_WAITING frame: least unacked: %"PRIu64,
2785                                                            least_unacked);
2786    EV_LOG_GENERATED_STOP_WAITING_FRAME(LSQUIC_LOG_CONN_ID, least_unacked);
2787}
2788
2789
2790static int
2791process_stream_ready_to_send (struct full_conn *conn, lsquic_stream_t *stream)
2792{
2793    int r = 1;
2794    if (stream->sm_qflags & SMQF_SEND_WUF)
2795        r &= generate_wuf_stream(conn, stream);
2796    if (stream->sm_qflags & SMQF_SEND_BLOCKED)
2797        r &= generate_stream_blocked_frame(conn, stream);
2798    if (stream->sm_qflags & SMQF_SEND_RST)
2799        r &= generate_rst_stream_frame(conn, stream);
2800    return r;
2801}
2802
2803
2804static void
2805process_streams_ready_to_send (struct full_conn *conn)
2806{
2807    lsquic_stream_t *stream;
2808    struct stream_prio_iter spi;
2809
2810    assert(!TAILQ_EMPTY(&conn->fc_pub.sending_streams));
2811
2812    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.sending_streams),
2813        TAILQ_LAST(&conn->fc_pub.sending_streams, lsquic_streams_tailq),
2814        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_send_stream),
2815        SMQF_SENDING_FLAGS, &conn->fc_conn, "send", NULL, NULL);
2816
2817    for (stream = lsquic_spi_first(&spi); stream;
2818                                            stream = lsquic_spi_next(&spi))
2819        if (!process_stream_ready_to_send(conn, stream))
2820            break;
2821}
2822
2823
2824/* Return true if packetized, false otherwise */
2825static int
2826packetize_standalone_stream_reset (struct full_conn *conn, lsquic_stream_id_t stream_id)
2827{
2828    lsquic_packet_out_t *packet_out;
2829    int sz;
2830
2831    packet_out = get_writeable_packet(conn, GQUIC_RST_STREAM_SZ);
2832    if (!packet_out)
2833        return 0;
2834
2835    sz = conn->fc_conn.cn_pf->pf_gen_rst_frame(
2836                     packet_out->po_data + packet_out->po_data_sz,
2837                     lsquic_packet_out_avail(packet_out), stream_id,
2838                     0, 0x10 /* QUIC_PEER_GOING_AWAY */);
2839    if (sz < 0) {
2840        ABORT_ERROR("gen_rst_frame failed");
2841        return 0;
2842    }
2843    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2844    packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
2845    LSQ_DEBUG("generated standalone RST_STREAM frame for stream %"PRIu64,
2846                                                                    stream_id);
2847    return 1;
2848}
2849
2850
2851static void
2852packetize_standalone_stream_resets (struct full_conn *conn)
2853{
2854    struct stream_id_to_reset *sitr;
2855
2856    while ((sitr = STAILQ_FIRST(&conn->fc_stream_ids_to_reset)))
2857        if (packetize_standalone_stream_reset(conn, sitr->sitr_stream_id))
2858        {
2859            STAILQ_REMOVE_HEAD(&conn->fc_stream_ids_to_reset, sitr_next);
2860            free(sitr);
2861        }
2862        else
2863            break;
2864}
2865
2866
2867static void
2868create_delayed_streams (struct full_conn *conn)
2869{
2870    unsigned stream_count, avail, i;
2871    struct lsquic_stream **new_streams;
2872
2873    stream_count = count_streams(conn, 0);
2874
2875    if (stream_count >= conn->fc_cfg.max_streams_out)
2876        return;
2877
2878    avail = conn->fc_cfg.max_streams_out - stream_count;
2879    if (conn->fc_n_delayed_streams < avail)
2880        avail = conn->fc_n_delayed_streams;
2881    if (avail == 0)
2882	return;
2883
2884    new_streams = malloc(sizeof(new_streams[0]) * avail);
2885    if (!new_streams)
2886    {
2887        ABORT_WARN("%s: malloc failed", __func__);
2888        return;
2889    }
2890
2891    LSQ_DEBUG("creating delayed streams");
2892    for (i = 0; i < avail; ++i)
2893    {
2894        /* Delay calling on_new in order not to let the user screw up
2895         * the counts by making more streams.
2896         */
2897        new_streams[i] = new_stream(conn, generate_stream_id(conn), 0);
2898        if (!new_streams[i])
2899        {
2900            ABORT_ERROR("%s: cannot create new stream: %s", __func__,
2901                                                        strerror(errno));
2902            goto cleanup;
2903        }
2904    }
2905    LSQ_DEBUG("created %u delayed stream%.*s", avail, avail != 1, "s");
2906
2907    assert(count_streams(conn, 0) <= conn->fc_cfg.max_streams_out);
2908    conn->fc_n_delayed_streams -= avail;
2909
2910    for (i = 0; i < avail; ++i)
2911        lsquic_stream_call_on_new(new_streams[i]);
2912  cleanup:
2913    free(new_streams);
2914}
2915
2916
2917static void
2918service_streams (struct full_conn *conn)
2919{
2920    struct lsquic_hash_elem *el;
2921    lsquic_stream_t *stream, *next;
2922    int closed_some = 0;
2923
2924    for (stream = TAILQ_FIRST(&conn->fc_pub.service_streams); stream; stream = next)
2925    {
2926        next = TAILQ_NEXT(stream, next_service_stream);
2927        if (stream->sm_qflags & SMQF_ABORT_CONN)
2928            /* No need to unset this flag or remove this stream: the connection
2929             * is about to be aborted.
2930             */
2931            ABORT_ERROR("aborted due to error in stream %"PRIu64, stream->id);
2932        if (stream->sm_qflags & SMQF_CALL_ONCLOSE)
2933        {
2934            lsquic_stream_call_on_close(stream);
2935            closed_some |= is_our_stream(conn, stream);
2936            conn_mark_stream_closed(conn, stream->id);
2937        }
2938        if (stream->sm_qflags & SMQF_FREE_STREAM)
2939        {
2940            TAILQ_REMOVE(&conn->fc_pub.service_streams, stream, next_service_stream);
2941            el = lsquic_hash_find(conn->fc_pub.all_streams, &stream->id, sizeof(stream->id));
2942            if (el)
2943                lsquic_hash_erase(conn->fc_pub.all_streams, el);
2944            SAVE_STREAM_HISTORY(conn, stream);
2945            lsquic_stream_destroy(stream);
2946        }
2947    }
2948
2949    if (either_side_going_away(conn))
2950    {
2951        while (conn->fc_n_delayed_streams)
2952        {
2953            --conn->fc_n_delayed_streams;
2954            LSQ_DEBUG("goaway mode: delayed stream results in null ctor");
2955            (void) conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_new_stream(
2956                conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, NULL);
2957        }
2958        maybe_close_conn(conn);
2959    }
2960    else
2961        if (closed_some && conn->fc_n_delayed_streams)
2962            create_delayed_streams(conn);
2963}
2964
2965
2966struct filter_stream_ctx
2967{
2968    struct full_conn    *conn;
2969    uint32_t             last_stream_id,
2970                         max_peer_stream_id;
2971};
2972
2973
2974static int
2975filter_out_old_streams (void *ctx, lsquic_stream_t *stream)
2976{
2977    struct filter_stream_ctx *const fctx = ctx;
2978    return ((!((stream->id ^ fctx->last_stream_id)     & 1) &&
2979                                   stream->id > fctx->last_stream_id)
2980           ||
2981            (!((stream->id ^ fctx->max_peer_stream_id) & 1) &&
2982                                   stream->id > fctx->max_peer_stream_id));
2983}
2984
2985
2986static void
2987process_streams_read_events (struct full_conn *conn)
2988{
2989    lsquic_stream_t *stream;
2990    struct filter_stream_ctx fctx;
2991    enum stream_q_flags q_flags;
2992    int needs_service;
2993    struct stream_prio_iter spi;
2994
2995    if (TAILQ_EMPTY(&conn->fc_pub.read_streams))
2996        return;
2997
2998    fctx.last_stream_id     = conn->fc_last_stream_id;
2999    fctx.max_peer_stream_id = conn->fc_max_peer_stream_id;
3000    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.read_streams),
3001        TAILQ_LAST(&conn->fc_pub.read_streams, lsquic_streams_tailq),
3002        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_read_stream),
3003        SMQF_WANT_READ, &conn->fc_conn, "read", NULL, NULL);
3004
3005    needs_service = 0;
3006    for (stream = lsquic_spi_first(&spi); stream;
3007                                            stream = lsquic_spi_next(&spi))
3008    {
3009        q_flags = stream->sm_qflags & SMQF_SERVICE_FLAGS;
3010        lsquic_stream_dispatch_read_events(stream);
3011        needs_service |= q_flags ^ (stream->sm_qflags & SMQF_SERVICE_FLAGS);
3012    }
3013
3014    if (needs_service)
3015        service_streams(conn);
3016
3017    /* If new streams were created as result of the read dispatching above,
3018     * process these new streams.  This logic is only applicable to in the
3019     * server mode, as a client that creates a stream from an on_read() event
3020     * is not likely to want to *read* from it immediately.
3021     */
3022    if ((conn->fc_flags & FC_SERVER) &&
3023        (fctx.last_stream_id     < conn->fc_last_stream_id ||
3024         fctx.max_peer_stream_id < conn->fc_max_peer_stream_id))
3025    {
3026        fctx.conn = conn;
3027        lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.read_streams),
3028            TAILQ_LAST(&conn->fc_pub.read_streams, lsquic_streams_tailq),
3029            (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_read_stream),
3030            SMQF_WANT_READ, &conn->fc_conn, "read-new",
3031            filter_out_old_streams, &fctx);
3032        for (stream = lsquic_spi_first(&spi); stream;
3033                                                stream = lsquic_spi_next(&spi))
3034            lsquic_stream_dispatch_read_events(stream);
3035    }
3036}
3037
3038
3039static void
3040maybe_conn_flush_headers_stream (struct full_conn *conn)
3041{
3042    lsquic_stream_t *stream;
3043
3044    if (conn->fc_flags & FC_HTTP)
3045    {
3046        stream = lsquic_headers_stream_get_stream(conn->fc_pub.u.gquic.hs);
3047        if (lsquic_stream_has_data_to_flush(stream))
3048            (void) lsquic_stream_flush(stream);
3049    }
3050}
3051
3052
3053static void
3054process_streams_write_events (struct full_conn *conn, int high_prio)
3055{
3056    lsquic_stream_t *stream;
3057    struct stream_prio_iter spi;
3058
3059    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.write_streams),
3060        TAILQ_LAST(&conn->fc_pub.write_streams, lsquic_streams_tailq),
3061        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_write_stream),
3062        SMQF_WANT_WRITE|SMQF_WANT_FLUSH, &conn->fc_conn,
3063        high_prio ? "write-high" : "write-low", NULL, NULL);
3064
3065    if (high_prio)
3066        lsquic_spi_drop_non_high(&spi);
3067    else
3068        lsquic_spi_drop_high(&spi);
3069
3070    for (stream = lsquic_spi_first(&spi); stream && write_is_possible(conn);
3071                                            stream = lsquic_spi_next(&spi))
3072        if (stream->sm_qflags & SMQF_WRITE_Q_FLAGS)
3073            lsquic_stream_dispatch_write_events(stream);
3074
3075    maybe_conn_flush_headers_stream(conn);
3076}
3077
3078
3079static void
3080process_hsk_stream_read_events (struct full_conn *conn)
3081{
3082    lsquic_stream_t *stream;
3083    TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
3084        if (lsquic_stream_is_crypto(stream))
3085        {
3086            lsquic_stream_dispatch_read_events(stream);
3087            break;
3088        }
3089}
3090
3091
3092static void
3093process_hsk_stream_write_events (struct full_conn *conn)
3094{
3095    lsquic_stream_t *stream;
3096    TAILQ_FOREACH(stream, &conn->fc_pub.write_streams, next_write_stream)
3097        if (lsquic_stream_is_crypto(stream))
3098        {
3099            lsquic_stream_dispatch_write_events(stream);
3100            break;
3101        }
3102}
3103
3104
3105static void
3106generate_ack_frame (struct full_conn *conn)
3107{
3108    lsquic_packet_out_t *packet_out;
3109
3110    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0, PNS_APP,
3111                                                                &conn->fc_path);
3112    if (packet_out)
3113    {
3114        lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
3115        full_conn_ci_write_ack(&conn->fc_conn, packet_out);
3116    }
3117    else
3118        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
3119}
3120
3121
3122static int
3123conn_ok_to_close (const struct full_conn *conn)
3124{
3125    assert(conn->fc_flags & FC_CLOSING);
3126    return !(conn->fc_flags & FC_SERVER)
3127        || (conn->fc_flags & FC_RECV_CLOSE)
3128        || (
3129               !lsquic_send_ctl_have_outgoing_stream_frames(&conn->fc_send_ctl)
3130            && lsquic_hash_count(conn->fc_pub.all_streams) == 0
3131            && lsquic_send_ctl_have_unacked_stream_frames(&conn->fc_send_ctl) == 0);
3132}
3133
3134
3135static enum tick_st
3136immediate_close (struct full_conn *conn)
3137{
3138    lsquic_packet_out_t *packet_out;
3139    const char *error_reason;
3140    unsigned error_code;
3141    int sz;
3142
3143    if (conn->fc_flags & (FC_TICK_CLOSE|FC_GOT_PRST))
3144        return TICK_CLOSE;
3145
3146    conn->fc_flags |= FC_TICK_CLOSE;
3147
3148    /* No reason to send anything that's been scheduled if connection is
3149     * being closed immedately.  This also ensures that packet numbers
3150     * sequence is always increasing.
3151     */
3152    lsquic_send_ctl_drop_scheduled(&conn->fc_send_ctl);
3153
3154    if ((conn->fc_flags & FC_TIMED_OUT) && conn->fc_settings->es_silent_close)
3155        return TICK_CLOSE;
3156
3157    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0, PNS_APP,
3158                                                                &conn->fc_path);
3159    if (!packet_out)
3160    {
3161        LSQ_WARN("cannot allocate packet: %s", strerror(errno));
3162        return TICK_CLOSE;
3163    }
3164
3165    assert(conn->fc_flags & (FC_ERROR|FC_ABORTED|FC_TIMED_OUT|FC_HSK_FAILED));
3166    if (conn->fc_flags & FC_ERROR)
3167    {
3168        error_code = 0x01; /* QUIC_INTERNAL_ERROR */
3169        error_reason = "connection error";
3170    }
3171    else if (conn->fc_flags & FC_ABORTED)
3172    {
3173        error_code = 0x10; /* QUIC_PEER_GOING_AWAY */
3174        error_reason = "user aborted connection";
3175    }
3176    else if (conn->fc_flags & FC_TIMED_OUT)
3177    {
3178        error_code = 0x19; /* QUIC_NETWORK_IDLE_TIMEOUT */
3179        error_reason = "connection timed out";
3180    }
3181    else if (conn->fc_flags & FC_HSK_FAILED)
3182    {
3183        error_code = 0x2A; /* QUIC_PROOF_INVALID */
3184        error_reason = "handshake failed";
3185    }
3186    else
3187    {
3188        error_code = 0x10; /* QUIC_PEER_GOING_AWAY */
3189        error_reason = NULL;
3190    }
3191
3192    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
3193    sz = conn->fc_conn.cn_pf->pf_gen_connect_close_frame(
3194                     packet_out->po_data + packet_out->po_data_sz,
3195                     lsquic_packet_out_avail(packet_out), 0, error_code,
3196                     error_reason, error_reason ? strlen(error_reason) : 0);
3197    if (sz < 0) {
3198        LSQ_WARN("%s failed", __func__);
3199        return TICK_CLOSE;
3200    }
3201    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
3202    packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
3203    LSQ_DEBUG("generated CONNECTION_CLOSE frame in its own packet");
3204    return TICK_SEND|TICK_CLOSE;
3205}
3206
3207
3208static int
3209write_is_possible (struct full_conn *conn)
3210{
3211    const lsquic_packet_out_t *packet_out;
3212
3213    packet_out = lsquic_send_ctl_last_scheduled(&conn->fc_send_ctl, PNS_APP,
3214                                                        &conn->fc_path, 0);
3215    return (packet_out && lsquic_packet_out_avail(packet_out) > 10)
3216        || lsquic_send_ctl_can_send(&conn->fc_send_ctl);
3217}
3218
3219
3220static int
3221should_generate_ack (const struct full_conn *conn)
3222{
3223    return (conn->fc_flags & FC_ACK_QUEUED)
3224        || lsquic_send_ctl_lost_ack(&conn->fc_send_ctl);
3225}
3226
3227
3228static int
3229full_conn_ci_can_write_ack (struct lsquic_conn *lconn)
3230{
3231    struct full_conn *conn = (struct full_conn *) lconn;
3232    return should_generate_ack(conn);
3233}
3234
3235
3236static enum tick_st
3237full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
3238{
3239    struct full_conn *conn = (struct full_conn *) lconn;
3240    int have_delayed_packets;
3241    unsigned n;
3242    int s;
3243    enum tick_st tick = 0;
3244
3245#define CLOSE_IF_NECESSARY() do {                                       \
3246    if (conn->fc_flags & FC_IMMEDIATE_CLOSE_FLAGS)                      \
3247    {                                                                   \
3248        tick |= immediate_close(conn);                         \
3249        goto close_end;                                                 \
3250    }                                                                   \
3251} while (0)
3252
3253#define RETURN_IF_OUT_OF_PACKETS() do {                                 \
3254    if (!lsquic_send_ctl_can_send(&conn->fc_send_ctl))                  \
3255    {                                                                   \
3256        if (0 == lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl))       \
3257        {                                                               \
3258            LSQ_DEBUG("used up packet allowance, quiet now (line %d)",  \
3259                __LINE__);                                              \
3260            tick |= TICK_QUIET;                                         \
3261        }                                                               \
3262        else                                                            \
3263        {                                                               \
3264            LSQ_DEBUG("used up packet allowance, sending now (line %d)",\
3265                __LINE__);                                              \
3266            tick |= TICK_SEND;                                          \
3267        }                                                               \
3268        goto end;                                                       \
3269    }                                                                   \
3270} while (0)
3271
3272#if LSQUIC_CONN_STATS
3273    ++conn->fc_stats.n_ticks;
3274#endif
3275
3276    if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG)
3277        && conn->fc_mem_logged_last + 1000000 <= now)
3278    {
3279        conn->fc_mem_logged_last = now;
3280        LSQ_DEBUG("memory used: %zd bytes", calc_mem_used(conn));
3281    }
3282
3283    if (conn->fc_flags & FC_HAVE_SAVED_ACK)
3284    {
3285        (void) /* If there is an error, we'll fail shortly */
3286            process_ack(conn, &conn->fc_ack, conn->fc_saved_ack_received, now);
3287        conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
3288    }
3289
3290    lsquic_send_ctl_tick_in(&conn->fc_send_ctl, now);
3291    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
3292    CLOSE_IF_NECESSARY();
3293
3294    lsquic_alarmset_ring_expired(&conn->fc_alset, now);
3295    CLOSE_IF_NECESSARY();
3296
3297    /* To make things simple, only stream 1 is active until the handshake
3298     * has been completed.  This will be adjusted in the future: the client
3299     * does not want to wait if it has the server information.
3300     */
3301    if (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
3302        process_streams_read_events(conn);
3303    else
3304        process_hsk_stream_read_events(conn);
3305    CLOSE_IF_NECESSARY();
3306
3307    if (lsquic_send_ctl_pacer_blocked(&conn->fc_send_ctl))
3308        goto skip_write;
3309
3310    if (conn->fc_flags & FC_FIRST_TICK)
3311    {
3312        conn->fc_flags &= ~FC_FIRST_TICK;
3313        have_delayed_packets = 0;
3314    }
3315    else
3316        /* If there are any scheduled packets at this point, it means that
3317         * they were not sent during previous tick; in other words, they
3318         * are delayed.  When there are delayed packets, the only packet
3319         * we sometimes add is a packet with an ACK frame, and we add it
3320         * to the *front* of the queue.
3321         */
3322        have_delayed_packets = lsquic_send_ctl_maybe_squeeze_sched(
3323                                                    &conn->fc_send_ctl);
3324
3325    if (should_generate_ack(conn))
3326    {
3327        if (have_delayed_packets)
3328            lsquic_send_ctl_reset_packnos(&conn->fc_send_ctl);
3329
3330        /* ACK frame generation fails with an error if it does not fit into
3331         * a single packet (it always should fit).
3332         */
3333        generate_ack_frame(conn);
3334        CLOSE_IF_NECESSARY();
3335
3336        /* Try to send STOP_WAITING frame at the same time we send an ACK
3337         * This follows reference implementation.
3338         */
3339        if (!(conn->fc_flags & FC_NSTP))
3340            conn->fc_flags |= FC_SEND_STOP_WAITING;
3341
3342        if (have_delayed_packets)
3343        {
3344            if (conn->fc_flags & FC_SEND_STOP_WAITING)
3345            {
3346                /* TODO: ensure that STOP_WAITING frame is in the same packet
3347                 * as the ACK frame in delayed packet mode.
3348                 */
3349                generate_stop_waiting_frame(conn);
3350                CLOSE_IF_NECESSARY();
3351            }
3352            lsquic_send_ctl_ack_to_front(&conn->fc_send_ctl, 1);
3353        }
3354    }
3355
3356    if (have_delayed_packets)
3357    {
3358        /* The reason for not adding STOP_WAITING and other frames below
3359         * to the packet carrying ACK frame generated when there are delayed
3360         * packets is so that if the ACK packet itself is delayed, it can be
3361         * dropped and replaced by new ACK packet.  This way, we are never
3362         * more than 1 packet over CWND.
3363         */
3364        tick |= TICK_SEND;
3365        goto end;
3366    }
3367
3368    /* Try to fit any of the following three frames -- STOP_WAITING,
3369     * WINDOW_UPDATE, and GOAWAY -- before checking if we have run
3370     * out of packets.  If either of them does not fit, it will be
3371     * tried next time around.
3372     */
3373    if (conn->fc_flags & FC_SEND_STOP_WAITING)
3374    {
3375        generate_stop_waiting_frame(conn);
3376        CLOSE_IF_NECESSARY();
3377    }
3378
3379    if (lsquic_cfcw_fc_offsets_changed(&conn->fc_pub.cfcw) ||
3380                                (conn->fc_flags & FC_SEND_WUF))
3381    {
3382        conn->fc_flags |= FC_SEND_WUF;
3383        generate_wuf_conn(conn);
3384        CLOSE_IF_NECESSARY();
3385    }
3386
3387    if (conn->fc_flags & FC_SEND_GOAWAY)
3388    {
3389        generate_goaway_frame(conn);
3390        CLOSE_IF_NECESSARY();
3391    }
3392
3393    n = lsquic_send_ctl_reschedule_packets(&conn->fc_send_ctl);
3394    if (n > 0)
3395        CLOSE_IF_NECESSARY();
3396
3397    if (conn->fc_conn.cn_flags & LSCONN_SEND_BLOCKED)
3398    {
3399        RETURN_IF_OUT_OF_PACKETS();
3400        if (generate_blocked_frame(conn, 0))
3401            conn->fc_conn.cn_flags &= ~LSCONN_SEND_BLOCKED;
3402    }
3403
3404    if (!STAILQ_EMPTY(&conn->fc_stream_ids_to_reset))
3405    {
3406        packetize_standalone_stream_resets(conn);
3407        CLOSE_IF_NECESSARY();
3408    }
3409
3410    if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
3411    {
3412        process_streams_ready_to_send(conn);
3413        CLOSE_IF_NECESSARY();
3414    }
3415
3416    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 0);
3417    if (!handshake_done_or_doing_zero_rtt(conn))
3418    {
3419        process_hsk_stream_write_events(conn);
3420        goto end_write;
3421    }
3422
3423    maybe_conn_flush_headers_stream(conn);
3424
3425    s = lsquic_send_ctl_schedule_buffered(&conn->fc_send_ctl, BPT_HIGHEST_PRIO);
3426    conn->fc_flags |= (s < 0) << FC_BIT_ERROR;
3427    if (!write_is_possible(conn))
3428        goto end_write;
3429
3430    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams))
3431    {
3432        process_streams_write_events(conn, 1);
3433        if (!write_is_possible(conn))
3434            goto end_write;
3435    }
3436
3437    s = lsquic_send_ctl_schedule_buffered(&conn->fc_send_ctl, BPT_OTHER_PRIO);
3438    conn->fc_flags |= (s < 0) << FC_BIT_ERROR;
3439    if (!write_is_possible(conn))
3440        goto end_write;
3441
3442    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams))
3443        process_streams_write_events(conn, 0);
3444
3445    lsquic_send_ctl_maybe_app_limited(&conn->fc_send_ctl, &conn->fc_path);
3446
3447  end_write:
3448
3449  skip_write:
3450    if ((conn->fc_flags & FC_CLOSING) && conn_ok_to_close(conn))
3451    {
3452        RETURN_IF_OUT_OF_PACKETS();
3453        LSQ_DEBUG("connection is OK to close");
3454        /* This is normal termination sequence.
3455         *
3456         * Generate CONNECTION_CLOSE frame if we are responding to one, have
3457         * packets scheduled to send, or silent close flag is not set.
3458         */
3459        conn->fc_flags |= FC_TICK_CLOSE;
3460        if ((conn->fc_flags & FC_RECV_CLOSE) ||
3461                0 != lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) ||
3462                                        !conn->fc_settings->es_silent_close)
3463        {
3464            generate_connection_close_packet(conn);
3465            tick |= TICK_SEND|TICK_CLOSE;
3466        }
3467        else
3468            tick |= TICK_CLOSE;
3469        goto end;
3470    }
3471
3472    if (0 == lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl))
3473    {
3474        if (conn->fc_flags & FC_SEND_PING)
3475        {
3476            RETURN_IF_OUT_OF_PACKETS();
3477            conn->fc_flags &= ~FC_SEND_PING;
3478            generate_ping_frame(conn);
3479            CLOSE_IF_NECESSARY();
3480            assert(lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) != 0);
3481        }
3482        else
3483        {
3484            tick |= TICK_QUIET;
3485            goto end;
3486        }
3487    }
3488    else if (conn->fc_settings->es_ping_period)
3489    {
3490        lsquic_alarmset_unset(&conn->fc_alset, AL_PING);
3491        lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
3492        conn->fc_flags &= ~FC_SEND_PING;   /* It may have rung */
3493    }
3494
3495    /* From the spec:
3496     *  " The PING frame should be used to keep a connection alive when
3497     *  " a stream is open.
3498     */
3499    if (conn->fc_settings->es_ping_period
3500                            && lsquic_hash_count(conn->fc_pub.all_streams) > 0)
3501        lsquic_alarmset_set(&conn->fc_alset, AL_PING,
3502                    now + conn->fc_settings->es_ping_period * 1000 * 1000);
3503
3504    tick |= TICK_SEND;
3505
3506  end:
3507    service_streams(conn);
3508    CLOSE_IF_NECESSARY();
3509
3510  close_end:
3511    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
3512    lsquic_send_ctl_tick_out(&conn->fc_send_ctl);
3513    return tick;
3514}
3515
3516
3517static void
3518full_conn_ci_packet_in (lsquic_conn_t *lconn, lsquic_packet_in_t *packet_in)
3519{
3520    struct full_conn *conn = (struct full_conn *) lconn;
3521
3522#if LSQUIC_CONN_STATS
3523    conn->fc_stats.in.bytes += packet_in->pi_data_sz;
3524#endif
3525    lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
3526                packet_in->pi_received + conn->fc_settings->es_idle_conn_to);
3527    if (0 == (conn->fc_flags & FC_ERROR))
3528        if (0 != process_incoming_packet(conn, packet_in))
3529            conn->fc_flags |= FC_ERROR;
3530}
3531
3532
3533static lsquic_packet_out_t *
3534full_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
3535{
3536    struct full_conn *conn = (struct full_conn *) lconn;
3537    return lsquic_send_ctl_next_packet_to_send(&conn->fc_send_ctl, 0);
3538}
3539
3540
3541static void
3542full_conn_ci_packet_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_out)
3543{
3544    struct full_conn *conn = (struct full_conn *) lconn;
3545    int s;
3546
3547    recent_packet_hist_new(conn, 1, packet_out->po_sent);
3548    recent_packet_hist_frames(conn, 1, packet_out->po_frame_types);
3549
3550    if (packet_out->po_frame_types & GQUIC_FRAME_RETRANSMITTABLE_MASK)
3551        conn->fc_n_cons_unretx = 0;
3552    else
3553        ++conn->fc_n_cons_unretx;
3554    s = lsquic_send_ctl_sent_packet(&conn->fc_send_ctl, packet_out);
3555    if (s != 0)
3556        ABORT_ERROR("sent packet failed: %s", strerror(errno));
3557#if LSQUIC_CONN_STATS
3558    ++conn->fc_stats.out.packets;
3559    conn->fc_stats.out.bytes += lsquic_packet_out_sent_sz(lconn, packet_out);
3560#endif
3561}
3562
3563
3564static void
3565full_conn_ci_packet_not_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_out)
3566{
3567    struct full_conn *conn = (struct full_conn *) lconn;
3568    lsquic_send_ctl_delayed_one(&conn->fc_send_ctl, packet_out);
3569}
3570
3571
3572static void
3573full_conn_ci_hsk_done (lsquic_conn_t *lconn, enum lsquic_hsk_status status)
3574{
3575    struct full_conn *conn = (struct full_conn *) lconn;
3576    lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
3577    switch (status)
3578    {
3579        case LSQ_HSK_0RTT_FAIL:
3580        case LSQ_HSK_FAIL:
3581            conn->fc_flags |= FC_HSK_FAILED;
3582            break;
3583        case LSQ_HSK_OK:
3584        case LSQ_HSK_0RTT_OK:
3585            if (0 == apply_peer_settings(conn))
3586            {
3587                if (conn->fc_flags & FC_HTTP)
3588                    maybe_send_settings(conn);
3589                lconn->cn_flags |= LSCONN_HANDSHAKE_DONE;
3590            }
3591            else
3592                conn->fc_flags |= FC_ERROR;
3593            break;
3594    }
3595    if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done)
3596        conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn,
3597                                                                        status);
3598    if (status == LSQ_HSK_OK || status == LSQ_HSK_0RTT_OK)
3599    {
3600        if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info)
3601            conn->fc_conn.cn_esf.g->esf_maybe_dispatch_zero_rtt(
3602                conn->fc_conn.cn_enc_session,
3603                conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info);
3604        if (conn->fc_n_delayed_streams)
3605            create_delayed_streams(conn);
3606        if (!(conn->fc_flags & FC_SERVER))
3607            lsquic_send_ctl_begin_optack_detection(&conn->fc_send_ctl);
3608    }
3609}
3610
3611
3612static void
3613full_conn_ci_abort (struct lsquic_conn *lconn)
3614{
3615    struct full_conn *conn = (struct full_conn *) lconn;
3616    LSQ_INFO("User aborted connection");
3617    conn->fc_flags |= FC_ABORTED;
3618}
3619
3620
3621static void
3622full_conn_ci_internal_error (struct lsquic_conn *lconn,
3623                                                    const char *format, ...)
3624{
3625    struct full_conn *const conn = (struct full_conn *) lconn;
3626    LSQ_INFO("Internal error reported");
3627    conn->fc_flags |= FC_ERROR;
3628}
3629
3630
3631/* This function should not be called, as this is specific to IETF QUIC */
3632static void
3633full_conn_ci_abort_error (struct lsquic_conn *lconn, int is_app,
3634                                unsigned error_code, const char *fmt, ...)
3635{
3636    struct full_conn *const conn = (struct full_conn *) lconn;
3637    assert(0);
3638    LSQ_WARN("(GQUIC) abort error is called unexpectedly");
3639    conn->fc_flags |= FC_ERROR;
3640}
3641
3642
3643static void
3644full_conn_ci_close (struct lsquic_conn *lconn)
3645{
3646    struct full_conn *conn = (struct full_conn *) lconn;
3647    lsquic_stream_t *stream;
3648    struct lsquic_hash_elem *el;
3649
3650    if (!(conn->fc_flags & FC_CLOSING))
3651    {
3652        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
3653                                     el = lsquic_hash_next(conn->fc_pub.all_streams))
3654        {
3655            stream = lsquic_hashelem_getdata(el);
3656            lsquic_stream_shutdown_internal(stream);
3657        }
3658        conn->fc_flags |= FC_CLOSING;
3659        if (!(conn->fc_flags & FC_GOAWAY_SENT))
3660            conn->fc_flags |= FC_SEND_GOAWAY;
3661    }
3662}
3663
3664
3665static void
3666full_conn_ci_going_away (struct lsquic_conn *lconn)
3667{
3668    struct full_conn *conn = (struct full_conn *) lconn;
3669    if (!(conn->fc_flags & (FC_CLOSING|FC_GOING_AWAY)))
3670    {
3671        LSQ_INFO("connection marked as going away");
3672        assert(!(conn->fc_flags & FC_SEND_GOAWAY));
3673        conn->fc_flags |= FC_GOING_AWAY;
3674        if (!(conn->fc_flags & FC_GOAWAY_SENT))
3675        {
3676            conn->fc_flags |= FC_SEND_GOAWAY;
3677            lsquic_engine_add_conn_to_tickable(conn->fc_enpub, lconn);
3678        }
3679    }
3680}
3681
3682
3683/* Find stream when stream ID is read from something other than a STREAM
3684 * frame.  If the stream cannot be found or created, the connection is
3685 * aborted.
3686 */
3687#if __GNUC__
3688__attribute__((nonnull(4)))
3689#endif
3690static lsquic_stream_t *
3691find_stream_on_non_stream_frame (struct full_conn *conn,
3692        lsquic_stream_id_t stream_id, enum stream_ctor_flags stream_ctor_flags,
3693        const char *what)
3694{
3695    lsquic_stream_t *stream;
3696    unsigned in_count;
3697
3698    stream = find_stream_by_id(conn, stream_id);
3699    if (stream)
3700        return stream;
3701
3702    if (conn_is_stream_closed(conn, stream_id))
3703    {
3704        LSQ_DEBUG("drop incoming %s for closed stream %"PRIu64, what, stream_id);
3705        return NULL;
3706    }
3707
3708    /* XXX It seems that if we receive a priority frame for a stream, the
3709     *     stream should exist or have existed at some point.  Thus, if
3710     *     it does not exist, we should return an error here.
3711     */
3712
3713    if (!is_peer_initiated(conn, stream_id))
3714    {
3715        ABORT_ERROR("frame for never-initiated stream (push promise?)");
3716        return NULL;
3717    }
3718
3719    in_count = count_streams(conn, 1);
3720    LSQ_DEBUG("number of peer-initiated streams: %u", in_count);
3721    if (in_count >= conn->fc_cfg.max_streams_in)
3722    {
3723        if (!(conn->fc_flags & FC_ABORT_COMPLAINED))
3724        {
3725            unsigned counts[N_SCNTS];
3726            collect_stream_counts(conn, 1, counts);
3727            ABORT_WARN("incoming %s for stream %"PRIu64" would exceed "
3728                "limit: %u.  all: %u; peer: %u; closed: %u; reset: %u; reset "
3729                "and not closed: %u",
3730                what, stream_id, conn->fc_cfg.max_streams_in, counts[SCNT_ALL],
3731                counts[SCNT_PEER], counts[SCNT_CLOSED], counts[SCNT_RESET],
3732                counts[SCNT_RES_UNCLO]);
3733        }
3734        return NULL;
3735    }
3736    if ((conn->fc_flags & FC_GOING_AWAY) &&
3737        stream_id > conn->fc_max_peer_stream_id)
3738    {
3739        maybe_schedule_reset_for_stream(conn, stream_id);
3740        LSQ_DEBUG("going away: reset new incoming stream %"PRIu64, stream_id);
3741        return NULL;
3742    }
3743
3744    stream = new_stream(conn, stream_id, stream_ctor_flags);
3745    if (!stream)
3746    {
3747        ABORT_ERROR("cannot create new stream: %s", strerror(errno));
3748        return NULL;
3749    }
3750    if (stream_id > conn->fc_max_peer_stream_id)
3751        conn->fc_max_peer_stream_id = stream_id;
3752
3753    return stream;
3754}
3755
3756
3757static void
3758headers_stream_on_conn_error (void *ctx)
3759{
3760    struct full_conn *conn = ctx;
3761    ABORT_ERROR("connection error reported by HEADERS stream");
3762}
3763
3764
3765static void
3766headers_stream_on_stream_error (void *ctx, lsquic_stream_id_t stream_id)
3767{
3768    struct full_conn *conn = ctx;
3769    lsquic_stream_t *stream;
3770
3771    stream = find_stream_on_non_stream_frame(conn, stream_id, SCF_CALL_ON_NEW,
3772                                             "error");
3773    if (stream)
3774    {
3775        LSQ_DEBUG("resetting stream %"PRIu64" due to error", stream_id);
3776        /* We use code 1, which is QUIC_INTERNAL_ERROR (see
3777         * [draft-hamilton-quic-transport-protocol-01], Section 10), for all
3778         * errors.  There does not seem to be a good reason to figure out
3779         * and send more specific error codes.
3780         */
3781        lsquic_stream_reset_ext(stream, 1, 0);
3782    }
3783}
3784
3785
3786static void
3787headers_stream_on_enable_push (void *ctx, int enable_push)
3788{
3789    struct full_conn *conn = ctx;
3790    if (0 == enable_push)
3791    {
3792        LSQ_DEBUG("server push %d -> 0", !!(conn->fc_flags & FC_SUPPORT_PUSH));
3793        conn->fc_flags &= ~FC_SUPPORT_PUSH;
3794    }
3795    else if (conn->fc_settings->es_support_push)
3796    {
3797        LSQ_DEBUG("server push %d -> 1", !!(conn->fc_flags & FC_SUPPORT_PUSH));
3798        conn->fc_flags |= FC_SUPPORT_PUSH;
3799    }
3800    else
3801        LSQ_INFO("not enabling server push that's disabled in engine settings");
3802}
3803
3804
3805static void
3806headers_stream_on_incoming_headers (void *ctx, struct uncompressed_headers *uh)
3807{
3808    struct full_conn *conn = ctx;
3809    lsquic_stream_t *stream;
3810
3811    LSQ_DEBUG("incoming headers for stream %"PRIu64, uh->uh_stream_id);
3812
3813    stream = find_stream_on_non_stream_frame(conn, uh->uh_stream_id, 0,
3814                                             "headers");
3815    if (!stream)
3816        goto free_uh;
3817
3818    if (lsquic_stream_is_reset(stream))
3819    {
3820        LSQ_DEBUG("stream is reset: ignore headers");
3821        goto free_uh;
3822    }
3823
3824    if (0 != lsquic_stream_uh_in(stream, uh))
3825    {
3826        ABORT_ERROR("stream %"PRIu64" refused incoming headers",
3827                                                        uh->uh_stream_id);
3828        goto free_uh;
3829    }
3830
3831    if (!(stream->stream_flags & STREAM_ONNEW_DONE))
3832        lsquic_stream_call_on_new(stream);
3833
3834    return;
3835
3836  free_uh:
3837    if (uh->uh_hset)
3838        conn->fc_enpub->enp_hsi_if->hsi_discard_header_set(uh->uh_hset);
3839    free(uh);
3840}
3841
3842
3843static void
3844headers_stream_on_push_promise (void *ctx, struct uncompressed_headers *uh)
3845{
3846    struct full_conn *conn = ctx;
3847    lsquic_stream_t *stream;
3848
3849    assert(!(conn->fc_flags & FC_SERVER));
3850
3851    LSQ_DEBUG("push promise for stream %"PRIu64" in response to %"PRIu64,
3852                                    uh->uh_oth_stream_id, uh->uh_stream_id);
3853
3854    if (0 == (uh->uh_stream_id & 1)     ||
3855        0 != (uh->uh_oth_stream_id & 1))
3856    {
3857        ABORT_ERROR("invalid push promise stream IDs: %"PRIu64", %"PRIu64,
3858                                    uh->uh_oth_stream_id, uh->uh_stream_id);
3859        goto free_uh;
3860    }
3861
3862    if (!(conn_is_stream_closed(conn, uh->uh_stream_id) ||
3863          find_stream_by_id(conn, uh->uh_stream_id)))
3864    {
3865        ABORT_ERROR("invalid push promise original stream ID %"PRIu64" never "
3866                    "initiated", uh->uh_stream_id);
3867        goto free_uh;
3868    }
3869
3870    if (conn_is_stream_closed(conn, uh->uh_oth_stream_id) ||
3871        find_stream_by_id(conn, uh->uh_oth_stream_id))
3872    {
3873        ABORT_ERROR("invalid promised stream ID %"PRIu64" already used",
3874                                                        uh->uh_oth_stream_id);
3875        goto free_uh;
3876    }
3877
3878    stream = new_stream_ext(conn, uh->uh_oth_stream_id, STREAM_IF_STD,
3879                SCF_DI_AUTOSWITCH|(conn->fc_enpub->enp_settings.es_rw_once ?
3880                                                        SCF_DISP_RW_ONCE : 0));
3881    if (!stream)
3882    {
3883        ABORT_ERROR("cannot create stream: %s", strerror(errno));
3884        goto free_uh;
3885    }
3886    lsquic_stream_push_req(stream, uh);
3887    lsquic_stream_call_on_new(stream);
3888    return;
3889
3890  free_uh:
3891    if (uh->uh_hset)
3892        conn->fc_enpub->enp_hsi_if->hsi_discard_header_set(uh->uh_hset);
3893    free(uh);
3894}
3895
3896
3897static void
3898headers_stream_on_priority (void *ctx, lsquic_stream_id_t stream_id,
3899            int exclusive, lsquic_stream_id_t dep_stream_id, unsigned weight)
3900{
3901    struct full_conn *conn = ctx;
3902    lsquic_stream_t *stream;
3903    LSQ_DEBUG("got priority frame for stream %"PRIu64": (ex: %d; dep stream: "
3904        "%"PRIu64"; weight: %u)", stream_id, exclusive, dep_stream_id, weight);
3905    stream = find_stream_on_non_stream_frame(conn, stream_id, SCF_CALL_ON_NEW,
3906                                             "priority");
3907    if (stream)
3908        lsquic_stream_set_priority_internal(stream, weight);
3909}
3910
3911
3912
3913#define STRLEN(s) (sizeof(s) - 1)
3914
3915static struct uncompressed_headers *
3916synthesize_push_request (struct full_conn *conn, void *hset,
3917         const struct iovec* path, const struct iovec* host,
3918         const lsquic_http_headers_t *headers,
3919         lsquic_stream_id_t pushed_stream_id, const lsquic_stream_t *dep_stream)
3920{
3921    struct uncompressed_headers *uh;
3922    struct http1x_ctor_ctx ctor_ctx;
3923    void *hsi_ctx;
3924    unsigned idx, i, n_headers;
3925    const lsquic_http_header_t *header;
3926    enum lsquic_header_status st;
3927    lsquic_http_header_t pseudo_headers[4];
3928    lsquic_http_headers_t all_headers[2];
3929
3930    if (!hset)
3931    {
3932        if (conn->fc_enpub->enp_hsi_if == lsquic_http1x_if)
3933        {
3934            ctor_ctx = (struct http1x_ctor_ctx)
3935            {
3936                .conn      = &conn->fc_conn,
3937                .is_server = 1,
3938                .max_headers_sz = MAX_HTTP1X_HEADERS_SIZE,
3939            };
3940            hsi_ctx = &ctor_ctx;
3941        }
3942        else
3943            hsi_ctx = conn->fc_enpub->enp_hsi_ctx;
3944
3945        hset = conn->fc_enpub->enp_hsi_if->hsi_create_header_set(hsi_ctx, 1);
3946        if (!hset)
3947        {
3948            LSQ_INFO("header set ctor failure");
3949            return NULL;
3950        }
3951
3952        pseudo_headers[0].name. iov_base    = ":method";
3953        pseudo_headers[0].name. iov_len     = 7;
3954        pseudo_headers[0].value.iov_base    = "GET";
3955        pseudo_headers[0].value.iov_len     = 3;
3956        pseudo_headers[1].name .iov_base    = ":path";
3957        pseudo_headers[1].name .iov_len     = 5;
3958        pseudo_headers[1].value             = *path;
3959        pseudo_headers[2].name .iov_base    = ":authority";
3960        pseudo_headers[2].name .iov_len     = 10;
3961        pseudo_headers[2].value             = *host;
3962        pseudo_headers[3].name. iov_base    = ":scheme";
3963        pseudo_headers[3].name. iov_len     = 7;
3964        pseudo_headers[3].value.iov_base    = "https";
3965        pseudo_headers[3].value.iov_len     = 5;
3966
3967        all_headers[0].headers = pseudo_headers;
3968        all_headers[0].count   = sizeof(pseudo_headers)
3969                                                / sizeof(pseudo_headers[0]);
3970        if (headers)
3971        {
3972            all_headers[1]     = *headers;
3973            n_headers = 2;
3974        }
3975        else
3976            n_headers = 1;
3977
3978        for (i = 0; i < n_headers; ++i)
3979            for (header = all_headers[i].headers;
3980                    header < all_headers[i].headers + all_headers[i].count;
3981                        ++header)
3982            {
3983                idx = lshpack_enc_get_stx_tab_id(header->name.iov_base,
3984                                header->name.iov_len, header->value.iov_base,
3985                                header->value.iov_len);
3986                st = conn->fc_enpub->enp_hsi_if->hsi_process_header(hset, idx,
3987                                header->name.iov_base, header->name.iov_len,
3988                                header->value.iov_base, header->value.iov_len);
3989                if (st)
3990                    goto err;
3991            }
3992
3993        st = conn->fc_enpub->enp_hsi_if->hsi_process_header(hset, 0, 0, 0,
3994                                                            0, 0);
3995        if (st)
3996            goto err;
3997    }
3998
3999    uh = malloc(sizeof(*uh));
4000    if (!uh)
4001    {
4002        st = LSQUIC_HDR_ERR_NOMEM;
4003        goto err;
4004    }
4005
4006    uh->uh_stream_id     = pushed_stream_id;
4007    uh->uh_oth_stream_id = 0;   /* We don't do dependencies */
4008    uh->uh_weight        = lsquic_stream_priority(dep_stream) / 2 + 1;
4009    uh->uh_exclusive     = 0;
4010    uh->uh_flags         = UH_FIN;
4011    if (lsquic_http1x_if == conn->fc_enpub->enp_hsi_if)
4012        uh->uh_flags    |= UH_H1H;
4013    uh->uh_hset          = hset;
4014
4015    return uh;
4016
4017  err:
4018    LSQ_INFO("%s: error %u", __func__, st);
4019    return NULL;
4020}
4021
4022
4023static int
4024full_conn_ci_is_push_enabled (struct lsquic_conn *lconn)
4025{
4026    struct full_conn *const conn = (struct full_conn *) lconn;
4027    return conn->fc_flags & FC_SUPPORT_PUSH;
4028}
4029
4030
4031static int
4032full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
4033    struct lsquic_stream *dep_stream, const struct iovec *path,
4034    const struct iovec *host, const struct lsquic_http_headers *headers)
4035{
4036    struct full_conn *const conn = (struct full_conn *) lconn;
4037    lsquic_stream_t *pushed_stream;
4038    struct uncompressed_headers *uh;    /* We synthesize the request */
4039    lsquic_stream_id_t stream_id;
4040    int hit_limit;
4041
4042    if ((conn->fc_flags & (FC_SERVER|FC_HTTP)) != (FC_SERVER|FC_HTTP))
4043    {
4044        LSQ_ERROR("must be server in HTTP mode to push streams");
4045        return -1;
4046    }
4047
4048    if (lsquic_stream_is_pushed(dep_stream))
4049    {
4050        LSQ_WARN("cannot push stream dependent on another pushed stream "
4051                 "(%"PRIu64")", dep_stream->id);
4052        return -1;
4053    }
4054
4055    if (!(conn->fc_flags & FC_SUPPORT_PUSH))
4056    {
4057        LSQ_INFO("server push support is disabled");
4058        return 1;
4059    }
4060
4061    hit_limit = 0;
4062    if (either_side_going_away(conn) ||
4063        (hit_limit = 1, count_streams(conn, 0) >= conn->fc_cfg.max_streams_out))
4064    {
4065        LSQ_DEBUG("cannot create pushed stream: %s", hit_limit ?
4066            "hit connection limit" : "connection is going away");
4067        return 1;
4068    }
4069
4070    stream_id = generate_stream_id(conn);
4071    uh = synthesize_push_request(conn, hset, path, host, headers, stream_id,
4072                                                                dep_stream);
4073    if (!uh)
4074    {
4075        ABORT_ERROR("memory allocation failure");
4076        return -1;
4077    }
4078
4079    pushed_stream = new_stream(conn, stream_id, SCF_CALL_ON_NEW);
4080    if (!pushed_stream)
4081    {
4082        LSQ_WARN("cannot create stream: %s", strerror(errno));
4083        free(uh);
4084        return -1;
4085    }
4086
4087    if (0 != lsquic_stream_uh_in(pushed_stream, uh))
4088    {
4089        LSQ_WARN("stream barfed when fed synthetic request");
4090        free(uh);
4091        return -1;
4092    }
4093
4094    if (0 != lsquic_headers_stream_push_promise(conn->fc_pub.u.gquic.hs, dep_stream->id,
4095                                        pushed_stream->id, path, host, headers))
4096    {
4097        /* Since the failure to write to HEADERS stream results in aborting
4098         * the connection, we do not bother rolling back.
4099         */
4100        LSQ_ERROR("could not send push promise");
4101        return -1;
4102    }
4103
4104    return 0;
4105}
4106
4107
4108static void
4109full_conn_ci_tls_alert (struct lsquic_conn *lconn, uint8_t alert)
4110{
4111    assert(0);
4112}
4113
4114
4115static struct lsquic_conn_ctx *
4116full_conn_ci_get_ctx (const struct lsquic_conn *lconn)
4117{
4118    struct full_conn *const conn = (struct full_conn *) lconn;
4119    return conn->fc_conn_ctx;
4120}
4121
4122
4123static void
4124full_conn_ci_set_ctx (struct lsquic_conn *lconn, lsquic_conn_ctx_t *ctx)
4125{
4126    struct full_conn *const conn = (struct full_conn *) lconn;
4127    conn->fc_conn_ctx = ctx;
4128}
4129
4130
4131static enum LSQUIC_CONN_STATUS
4132full_conn_ci_status (struct lsquic_conn *lconn, char *errbuf, size_t bufsz)
4133{
4134    struct full_conn *const conn = (struct full_conn *) lconn;
4135    size_t n;
4136
4137    /* Test the common case first: */
4138    if (!(conn->fc_flags & (FC_ERROR
4139                           |FC_TIMED_OUT
4140                           |FC_ABORTED
4141                           |FC_GOT_PRST
4142                           |FC_HSK_FAILED
4143                           |FC_CLOSING
4144                           |FC_GOING_AWAY)))
4145    {
4146        if (lconn->cn_flags & LSCONN_PEER_GOING_AWAY)
4147            return LSCONN_ST_PEER_GOING_AWAY;
4148        else if (lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
4149            return LSCONN_ST_CONNECTED;
4150        else
4151            return LSCONN_ST_HSK_IN_PROGRESS;
4152    }
4153
4154    if (errbuf && bufsz)
4155    {
4156        if (conn->fc_errmsg)
4157        {
4158            n = bufsz < MAX_ERRMSG ? bufsz : MAX_ERRMSG;
4159            strncpy(errbuf, conn->fc_errmsg, n);
4160            errbuf[n - 1] = '\0';
4161        }
4162        else
4163            errbuf[0] = '\0';
4164    }
4165
4166    if (conn->fc_flags & FC_ERROR)
4167        return LSCONN_ST_ERROR;
4168    if (conn->fc_flags & FC_TIMED_OUT)
4169        return LSCONN_ST_TIMED_OUT;
4170    if (conn->fc_flags & FC_ABORTED)
4171        return LSCONN_ST_USER_ABORTED;
4172    if (conn->fc_flags & FC_GOT_PRST)
4173        return LSCONN_ST_RESET;
4174    if (conn->fc_flags & FC_HSK_FAILED)
4175        return LSCONN_ST_HSK_FAILURE;
4176    if (conn->fc_flags & FC_CLOSING)
4177        return LSCONN_ST_CLOSED;
4178    assert(conn->fc_flags & FC_GOING_AWAY);
4179    return LSCONN_ST_GOING_AWAY;
4180}
4181
4182
4183static int
4184full_conn_ci_is_tickable (lsquic_conn_t *lconn)
4185{
4186    struct full_conn *conn = (struct full_conn *) lconn;
4187    struct lsquic_stream *stream;
4188
4189    if (!TAILQ_EMPTY(&conn->fc_pub.service_streams))
4190    {
4191        LSQ_DEBUG("tickable: there are streams to be serviced");
4192        return 1;
4193    }
4194
4195    if ((conn->fc_enpub->enp_flags & ENPUB_CAN_SEND)
4196        && (should_generate_ack(conn) ||
4197            !lsquic_send_ctl_sched_is_blocked(&conn->fc_send_ctl)))
4198    {
4199        const enum full_conn_flags send_flags = FC_SEND_GOAWAY
4200                |FC_SEND_STOP_WAITING|FC_SEND_PING|FC_SEND_WUF|FC_CLOSING;
4201        if (conn->fc_flags & send_flags)
4202        {
4203            LSQ_DEBUG("tickable: flags: 0x%X", conn->fc_flags & send_flags);
4204            goto check_can_send;
4205        }
4206        if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
4207                && lsquic_send_ctl_has_buffered(&conn->fc_send_ctl))
4208        {
4209            LSQ_DEBUG("tickable: has buffered packets");
4210            goto check_can_send;
4211        }
4212        if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
4213        {
4214            LSQ_DEBUG("tickable: there are sending streams");
4215            goto check_can_send;
4216        }
4217        if (handshake_done_or_doing_zero_rtt(conn))
4218        {
4219            TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
4220                                                        next_write_stream)
4221                if (lsquic_stream_write_avail(stream))
4222                {
4223                    LSQ_DEBUG("tickable: stream %"PRIu64" can be written to",
4224                        stream->id);
4225                    goto check_can_send;
4226                }
4227        }
4228        else
4229        {
4230            TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
4231                                                        next_write_stream)
4232                if (lsquic_stream_is_crypto(stream)
4233                                    && lsquic_stream_write_avail(stream))
4234                {
4235                    LSQ_DEBUG("tickable: stream %"PRIu64" can be written to",
4236                        stream->id);
4237                    goto check_can_send;
4238                }
4239        }
4240        goto check_readable_streams;
4241  check_can_send:
4242        if (lsquic_send_ctl_can_send(&conn->fc_send_ctl))
4243            return 1;
4244    }
4245
4246  check_readable_streams:
4247    TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
4248        if (lsquic_stream_readable(stream))
4249        {
4250            LSQ_DEBUG("tickable: stream %"PRIu64" can be read from",
4251                stream->id);
4252            return 1;
4253        }
4254
4255    LSQ_DEBUG("not tickable");
4256    return 0;
4257}
4258
4259
4260static lsquic_time_t
4261full_conn_ci_next_tick_time (lsquic_conn_t *lconn, unsigned *why)
4262{
4263    struct full_conn *conn = (struct full_conn *) lconn;
4264    lsquic_time_t alarm_time, pacer_time, now;
4265    enum alarm_id al_id;
4266
4267    alarm_time = lsquic_alarmset_mintime(&conn->fc_alset, &al_id);
4268    pacer_time = lsquic_send_ctl_next_pacer_time(&conn->fc_send_ctl);
4269
4270    if (pacer_time && LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
4271    {
4272        now = lsquic_time_now();
4273        if (pacer_time < now)
4274            LSQ_DEBUG("%s: pacer is %"PRIu64" usec in the past", __func__,
4275                                                            now - pacer_time);
4276    }
4277
4278    if (alarm_time && pacer_time)
4279    {
4280        if (alarm_time < pacer_time)
4281        {
4282            *why = N_AEWS + al_id;
4283            return alarm_time;
4284        }
4285        else
4286        {
4287            *why = AEW_PACER;
4288            return pacer_time;
4289        }
4290    }
4291    else if (alarm_time)
4292    {
4293        *why = N_AEWS + al_id;
4294        return alarm_time;
4295    }
4296    else if (pacer_time)
4297    {
4298        *why = AEW_PACER;
4299        return pacer_time;
4300    }
4301    else
4302        return 0;
4303}
4304
4305
4306int
4307lsquic_gquic_full_conn_srej (struct lsquic_conn *lconn)
4308{
4309    struct full_conn *const conn = (struct full_conn *) lconn;
4310    const unsigned cce_idx = lconn->cn_cur_cce_idx;
4311    struct conn_cid_elem *const cce = &lconn->cn_cces[ cce_idx ];
4312    struct lsquic_stream *stream;
4313    enum lsquic_version version;
4314
4315    if (lconn->cn_esf_c->esf_is_zero_rtt_enabled(conn->fc_conn.cn_enc_session))
4316    {
4317        /* We need to do this because we do not clean up any data that may
4318         * have been already sent.  This is left an optimization for the
4319         * future.
4320         */
4321        LSQ_DEBUG("received SREJ when 0RTT was on: fail handshake and let "
4322            "caller retry");
4323        full_conn_ci_hsk_done(lconn, LSQ_HSK_0RTT_FAIL);
4324        return -1;
4325    }
4326
4327    LSQ_DEBUG("reinitialize CID and other state due to SREJ");
4328
4329    /* Generate new CID and update connections hash */
4330    if (cce->cce_hash_el.qhe_flags & QHE_HASHED)
4331    {
4332        lsquic_engine_retire_cid(conn->fc_enpub, lconn, cce_idx,
4333                                        0 /* OK to omit the `now' value */);
4334        lconn->cn_cces_mask |= 1 << cce_idx;
4335        lsquic_generate_cid_gquic(&cce->cce_cid);
4336        if (0 != lsquic_engine_add_cid(conn->fc_enpub, lconn, cce_idx))
4337            return -1;
4338    }
4339    else
4340    {
4341        LSQ_DEBUG("not hashed by CID, no need to reinsert");
4342        lsquic_generate_cid_gquic(&cce->cce_cid);
4343    }
4344    lconn->cn_esf.g->esf_reset_cid(lconn->cn_enc_session, &cce->cce_cid);
4345
4346    /* Reset version negotiation */
4347    version = highest_bit_set(conn->fc_orig_versions);
4348    init_ver_neg(conn, conn->fc_orig_versions, &version);
4349
4350    /* Reset receive history */
4351    lsquic_rechist_cleanup(&conn->fc_rechist);
4352    lsquic_rechist_init(&conn->fc_rechist, &conn->fc_conn, 0);
4353
4354    /* Reset send controller state */
4355    lsquic_send_ctl_cleanup(&conn->fc_send_ctl);
4356    lsquic_send_ctl_init(&conn->fc_send_ctl, &conn->fc_alset, conn->fc_enpub,
4357                     &conn->fc_ver_neg, &conn->fc_pub, 0);
4358
4359    /* Reset handshake stream state */
4360    stream = find_stream_by_id(conn, hsk_stream_id(conn));
4361    if (!stream)
4362        return -1;
4363    stream->n_unacked = 0;
4364    stream->tosend_off = 0;
4365    stream->read_offset = 0;
4366    stream->fc.sf_read_off = 0;
4367    stream->fc.sf_max_recv_off = 0;
4368
4369    lsquic_alarmset_unset(&conn->fc_alset, AL_RETX_APP);
4370    lsquic_alarmset_unset(&conn->fc_alset, AL_ACK_APP);
4371    conn->fc_flags &= ~(FC_ACK_QUEUED|FC_ACK_HAD_MISS|FC_NSTP);
4372    conn->fc_flags |= FC_GOT_SREJ;
4373
4374    return 0;
4375}
4376
4377
4378#if LSQUIC_CONN_STATS
4379static const struct conn_stats *
4380full_conn_ci_get_stats (struct lsquic_conn *lconn)
4381{
4382    struct full_conn *conn = (struct full_conn *) lconn;
4383    return &conn->fc_stats;
4384}
4385#endif
4386
4387
4388static const struct headers_stream_callbacks headers_callbacks =
4389{
4390    .hsc_on_headers      = headers_stream_on_incoming_headers,
4391    .hsc_on_push_promise = headers_stream_on_push_promise,
4392    .hsc_on_priority     = headers_stream_on_priority,
4393    .hsc_on_stream_error = headers_stream_on_stream_error,
4394    .hsc_on_conn_error   = headers_stream_on_conn_error,
4395    .hsc_on_enable_push  = headers_stream_on_enable_push,
4396};
4397
4398static const struct headers_stream_callbacks *headers_callbacks_ptr = &headers_callbacks;
4399
4400static const struct conn_iface full_conn_iface = {
4401    .ci_abort                =  full_conn_ci_abort,
4402    .ci_abort_error          =  full_conn_ci_abort_error,
4403    .ci_can_write_ack        =  full_conn_ci_can_write_ack,
4404    .ci_cancel_pending_streams
4405                             =  full_conn_ci_cancel_pending_streams,
4406    .ci_client_call_on_new   =  full_conn_ci_client_call_on_new,
4407    .ci_close                =  full_conn_ci_close,
4408    .ci_destroy              =  full_conn_ci_destroy,
4409    .ci_get_ctx              =  full_conn_ci_get_ctx,
4410    .ci_get_engine           =  full_conn_ci_get_engine,
4411    .ci_get_path             =  full_conn_ci_get_path,
4412    .ci_get_stream_by_id     =  full_conn_ci_get_stream_by_id,
4413#if LSQUIC_CONN_STATS
4414    .ci_get_stats            =  full_conn_ci_get_stats,
4415#endif
4416    .ci_going_away           =  full_conn_ci_going_away,
4417    .ci_hsk_done             =  full_conn_ci_hsk_done,
4418    .ci_internal_error       =  full_conn_ci_internal_error,
4419    .ci_is_push_enabled      =  full_conn_ci_is_push_enabled,
4420    .ci_is_tickable          =  full_conn_ci_is_tickable,
4421    .ci_make_stream          =  full_conn_ci_make_stream,
4422    .ci_n_avail_streams      =  full_conn_ci_n_avail_streams,
4423    .ci_n_pending_streams    =  full_conn_ci_n_pending_streams,
4424    .ci_next_packet_to_send  =  full_conn_ci_next_packet_to_send,
4425    .ci_next_tick_time       =  full_conn_ci_next_tick_time,
4426    .ci_packet_in            =  full_conn_ci_packet_in,
4427    .ci_packet_not_sent      =  full_conn_ci_packet_not_sent,
4428    .ci_packet_sent          =  full_conn_ci_packet_sent,
4429    .ci_record_addrs         =  full_conn_ci_record_addrs,
4430    /* gQUIC connection does not need this functionality because it only
4431     * uses one CID and it's liveness is updated automatically by the
4432     * caller when packets come in.
4433     */
4434    .ci_report_live          =  NULL,
4435    .ci_set_ctx              =  full_conn_ci_set_ctx,
4436    .ci_status               =  full_conn_ci_status,
4437    .ci_tick                 =  full_conn_ci_tick,
4438    .ci_write_ack            =  full_conn_ci_write_ack,
4439    .ci_push_stream          =  full_conn_ci_push_stream,
4440    .ci_tls_alert            =  full_conn_ci_tls_alert,
4441};
4442
4443static const struct conn_iface *full_conn_iface_ptr = &full_conn_iface;
4444