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