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