lsquic_full_conn.c revision 82f3bcef
1/* Copyright (c) 2017 - 2018 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 "lsquic_types.h"
20#include "lsquic.h"
21#include "lsquic_alarmset.h"
22#include "lsquic_packet_common.h"
23#include "lsquic_parse.h"
24#include "lsquic_packet_in.h"
25#include "lsquic_packet_out.h"
26#include "lsquic_rechist.h"
27#include "lsquic_util.h"
28#include "lsquic_conn_flow.h"
29#include "lsquic_sfcw.h"
30#include "lsquic_stream.h"
31#include "lsquic_senhist.h"
32#include "lsquic_rtt.h"
33#include "lsquic_cubic.h"
34#include "lsquic_pacer.h"
35#include "lsquic_send_ctl.h"
36#include "lsquic_set.h"
37#include "lsquic_malo.h"
38#include "lsquic_chsk_stream.h"
39#include "lsquic_str.h"
40#include "lsquic_qtags.h"
41#include "lsquic_handshake.h"
42#include "lsquic_headers_stream.h"
43#include "lsquic_frame_common.h"
44#include "lsquic_frame_reader.h"
45#include "lsquic_mm.h"
46#include "lsquic_engine_public.h"
47#include "lsquic_spi.h"
48#include "lsquic_ev_log.h"
49#include "lsquic_version.h"
50#include "lsquic_hash.h"
51
52#include "lsquic_conn.h"
53#include "lsquic_conn_public.h"
54#include "lsquic_ver_neg.h"
55#include "lsquic_full_conn.h"
56
57#define LSQUIC_LOGGER_MODULE LSQLM_CONN
58#define LSQUIC_LOG_CONN_ID conn->fc_conn.cn_cid
59#include "lsquic_logger.h"
60
61enum { STREAM_IF_STD, STREAM_IF_HSK, STREAM_IF_HDR, N_STREAM_IFS };
62
63#define MAX_ANY_PACKETS_SINCE_LAST_ACK  20
64#define MAX_RETR_PACKETS_SINCE_LAST_ACK 2
65#define ACK_TIMEOUT                     25000
66#define TIME_BETWEEN_PINGS              15000000
67#define IDLE_TIMEOUT                    30000000
68
69/* IMPORTANT: Keep values of FC_SERVER and FC_HTTP same as LSENG_SERVER
70 * and LSENG_HTTP.
71 */
72enum full_conn_flags {
73    FC_SERVER         = LSENG_SERVER,   /* Server mode */
74    FC_HTTP           = LSENG_HTTP,     /* HTTP mode */
75    FC_TIMED_OUT      = (1 << 2),
76#define FC_BIT_ERROR 3
77    FC_ERROR          = (1 << FC_BIT_ERROR),
78    FC_ABORTED        = (1 << 4),
79    FC_CLOSING        = (1 << 5),   /* Closing */
80    FC_SEND_PING      = (1 << 6),   /* PING frame scheduled */
81    FC_NSTP           = (1 << 7),   /* NSTP mode */
82    FC_SEND_GOAWAY    = (1 << 8),
83    FC_SEND_WUF       = (1 << 9),
84    FC_SEND_STOP_WAITING
85                      = (1 <<10),
86    FC_ACK_QUEUED     = (1 <<11),
87    FC_ACK_HAD_MISS   = (1 <<12),   /* Last ACK frame had missing packets. */
88    FC_CREATED_OK     = (1 <<13),
89    FC_RECV_CLOSE     = (1 <<14),   /* Received CONNECTION_CLOSE frame */
90    FC_GOING_AWAY     = (1 <<15),   /* Do not accept or create new streams */
91    FC_GOAWAY_SENT    = (1 <<16),   /* Only send GOAWAY once */
92    FC_SUPPORT_PUSH   = (1 <<17),
93    FC_GOT_PRST       = (1 <<18),   /* Received public reset packet */
94    FC_FIRST_TICK     = (1 <<19),
95    FC_TICK_CLOSE     = (1 <<20),   /* We returned TICK_CLOSE */
96    FC_HSK_FAILED     = (1 <<21),
97    FC_HAVE_SAVED_ACK = (1 <<22),
98};
99
100#define FC_IMMEDIATE_CLOSE_FLAGS \
101            (FC_TIMED_OUT|FC_ERROR|FC_ABORTED|FC_HSK_FAILED)
102
103#if LSQUIC_KEEP_STREAM_HISTORY
104#define KEEP_CLOSED_STREAM_HISTORY 0
105#endif
106
107#if KEEP_CLOSED_STREAM_HISTORY
108struct stream_history
109{
110    uint32_t            shist_stream_id;
111    enum stream_flags   shist_stream_flags;
112    unsigned char       shist_hist_buf[1 << SM_HIST_BITS];
113};
114#define SHIST_BITS 5
115#define SHIST_MASK ((1 << SHIST_BITS) - 1)
116#endif
117
118#ifndef KEEP_PACKET_HISTORY
119#ifdef NDEBUG
120#define KEEP_PACKET_HISTORY 0
121#else
122#define KEEP_PACKET_HISTORY 16
123#endif
124#endif
125
126#if KEEP_PACKET_HISTORY
127struct packet_el
128{
129    lsquic_time_t       time;
130    enum quic_ft_bit    frame_types;
131};
132
133struct recent_packets
134{
135    struct packet_el    els[KEEP_PACKET_HISTORY];
136    unsigned            idx;
137};
138#endif
139
140struct stream_id_to_reset
141{
142    STAILQ_ENTRY(stream_id_to_reset)    sitr_next;
143    uint32_t                            sitr_stream_id;
144};
145
146
147struct full_conn
148{
149    struct lsquic_conn           fc_conn;
150    struct lsquic_rechist        fc_rechist;
151    struct {
152        const struct lsquic_stream_if   *stream_if;
153        void                            *stream_if_ctx;
154    }                            fc_stream_ifs[N_STREAM_IFS];
155    lsquic_conn_ctx_t           *fc_conn_ctx;
156    struct lsquic_send_ctl       fc_send_ctl;
157    struct lsquic_conn_public    fc_pub;
158    lsquic_alarmset_t            fc_alset;
159    lsquic_set32_t               fc_closed_stream_ids[2];
160    const struct lsquic_engine_settings
161                                *fc_settings;
162    struct lsquic_engine_public *fc_enpub;
163    lsquic_packno_t              fc_max_ack_packno;
164    lsquic_packno_t              fc_max_swf_packno;
165    lsquic_time_t                fc_mem_logged_last;
166    struct {
167        unsigned    max_streams_in;
168        unsigned    max_streams_out;
169        unsigned    max_conn_send;
170        unsigned    max_stream_send;
171    }                            fc_cfg;
172    enum full_conn_flags         fc_flags;
173    /* Number of packets received since last ACK sent: */
174    unsigned                     fc_n_slack_all;
175    /* Number ackable packets received since last ACK was sent: */
176    unsigned                     fc_n_slack_akbl;
177    unsigned                     fc_n_delayed_streams;
178    unsigned                     fc_n_cons_unretx;
179    uint32_t                     fc_last_stream_id;
180    uint32_t                     fc_max_peer_stream_id;
181    uint32_t                     fc_goaway_stream_id;
182    struct ver_neg               fc_ver_neg;
183    union {
184        struct client_hsk_ctx    client;
185    }                            fc_hsk_ctx;
186#if FULL_CONN_STATS
187    struct {
188        unsigned            n_all_packets_in,
189                            n_packets_out,
190                            n_undec_packets,
191                            n_dup_packets,
192                            n_err_packets;
193        unsigned long       stream_data_sz;
194        unsigned long       n_ticks;
195        unsigned            n_acks_in,
196                            n_acks_proc,
197                            n_acks_merged[2];
198    }                            fc_stats;
199#endif
200#if KEEP_CLOSED_STREAM_HISTORY
201    /* Rolling log of histories of closed streams.  Older entries are
202     * overwritten.
203     */
204    struct stream_history        fc_stream_histories[1 << SHIST_BITS];
205    unsigned                     fc_stream_hist_idx;
206#endif
207    char                        *fc_errmsg;
208#if KEEP_PACKET_HISTORY
209    struct recent_packets        fc_recent_packets[2];  /* 0: in; 1: out */
210#endif
211    STAILQ_HEAD(, stream_id_to_reset)
212                                 fc_stream_ids_to_reset;
213    struct short_ack_info        fc_saved_ack_info;
214    lsquic_time_t                fc_saved_ack_received;
215};
216
217
218#define MAX_ERRMSG 256
219
220#define SET_ERRMSG(conn, ...) do {                                          \
221    if (!(conn)->fc_errmsg)                                                 \
222        (conn)->fc_errmsg = malloc(MAX_ERRMSG);                             \
223    if ((conn)->fc_errmsg)                                                  \
224        snprintf((conn)->fc_errmsg, MAX_ERRMSG, __VA_ARGS__);               \
225} while (0)
226
227#define ABORT_WITH_FLAG(conn, flag, ...) do {                               \
228    SET_ERRMSG(conn, __VA_ARGS__);                                          \
229    (conn)->fc_flags |= flag;                                               \
230    LSQ_ERROR("Abort connection: " __VA_ARGS__);                            \
231} while (0)
232
233#define ABORT_ERROR(...) ABORT_WITH_FLAG(conn, FC_ERROR, __VA_ARGS__)
234
235#define ABORT_TIMEOUT(...) ABORT_WITH_FLAG(conn, FC_TIMED_OUT, __VA_ARGS__)
236
237static void
238idle_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
239
240static void
241ping_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
242
243static void
244handshake_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
245
246static void
247ack_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now);
248
249static lsquic_stream_t *
250new_stream (struct full_conn *conn, uint32_t stream_id, enum stream_ctor_flags);
251
252static void
253reset_ack_state (struct full_conn *conn);
254
255static int
256write_is_possible (struct full_conn *);
257
258static const struct headers_stream_callbacks *headers_callbacks_ptr;
259
260#if KEEP_CLOSED_STREAM_HISTORY
261
262static void
263save_stream_history (struct full_conn *conn, const lsquic_stream_t *stream)
264{
265    sm_hist_idx_t idx;
266    struct stream_history *const shist =
267        &conn->fc_stream_histories[ conn->fc_stream_hist_idx++ & SHIST_MASK ];
268
269    shist->shist_stream_id    = stream->id;
270    shist->shist_stream_flags = stream->stream_flags;
271
272    idx = stream->sm_hist_idx & SM_HIST_IDX_MASK;
273    if ('\0' == stream->sm_hist_buf[ idx ])
274        memcpy(shist->shist_hist_buf, stream->sm_hist_buf, idx + 1);
275    else
276    {
277        memcpy(shist->shist_hist_buf,
278            stream->sm_hist_buf + idx, sizeof(stream->sm_hist_buf) - idx);
279        memcpy(shist->shist_hist_buf + sizeof(shist->shist_hist_buf) - idx,
280            stream->sm_hist_buf, idx);
281    }
282}
283
284
285static const struct stream_history *
286find_stream_history (const struct full_conn *conn, uint32_t stream_id)
287{
288    const struct stream_history *shist;
289    const struct stream_history *const shist_end =
290                        conn->fc_stream_histories + (1 << SHIST_BITS);
291    for (shist = conn->fc_stream_histories; shist < shist_end; ++shist)
292        if (shist->shist_stream_id == stream_id)
293            return shist;
294    return NULL;
295}
296
297
298#   define SAVE_STREAM_HISTORY(conn, stream) save_stream_history(conn, stream)
299#else
300#   define SAVE_STREAM_HISTORY(conn, stream)
301#endif
302
303#if KEEP_PACKET_HISTORY
304static void
305recent_packet_hist_new (struct full_conn *conn, unsigned out,
306                                                    lsquic_time_t time)
307{
308    unsigned idx;
309    idx = conn->fc_recent_packets[out].idx++ % KEEP_PACKET_HISTORY;
310    conn->fc_recent_packets[out].els[idx].time = time;
311}
312
313
314static void
315recent_packet_hist_frames (struct full_conn *conn, unsigned out,
316                                                enum quic_ft_bit frame_types)
317{
318    unsigned idx;
319    idx = (conn->fc_recent_packets[out].idx - 1) % KEEP_PACKET_HISTORY;
320    conn->fc_recent_packets[out].els[idx].frame_types |= frame_types;
321}
322
323
324#else
325#define recent_packet_hist_new(conn, out, time)
326#define recent_packet_hist_frames(conn, out, frames)
327#endif
328
329static unsigned
330highest_bit_set (unsigned sz)
331{
332#if __GNUC__
333    unsigned clz = __builtin_clz(sz);
334    return 31 - clz;
335#else
336    unsigned n, y;
337    n = 32;
338    y = sz >> 16;   if (y) { n -= 16; sz = y; }
339    y = sz >>  8;   if (y) { n -=  8; sz = y; }
340    y = sz >>  4;   if (y) { n -=  4; sz = y; }
341    y = sz >>  2;   if (y) { n -=  2; sz = y; }
342    y = sz >>  1;   if (y) return 31 - n + 2;
343    return 31 - n + sz;
344#endif
345}
346
347
348static size_t
349calc_mem_used (const struct full_conn *conn)
350{
351    const lsquic_stream_t *stream;
352    const struct lsquic_hash_elem *el;
353    size_t size;
354
355    size = sizeof(*conn);
356    size -= sizeof(conn->fc_send_ctl);
357    size += lsquic_send_ctl_mem_used(&conn->fc_send_ctl);
358    size += lsquic_hash_mem_used(conn->fc_pub.all_streams);
359    size += lsquic_malo_mem_used(conn->fc_pub.packet_out_malo);
360    if (conn->fc_pub.hs)
361        size += lsquic_headers_stream_mem_used(conn->fc_pub.hs);
362
363    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
364                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
365    {
366        stream = lsquic_hashelem_getdata(el);
367        size += lsquic_stream_mem_used(stream);
368    }
369    size += conn->fc_conn.cn_esf->esf_mem_used(conn->fc_conn.cn_enc_session);
370
371    return size;
372}
373
374
375static void
376set_versions (struct full_conn *conn, unsigned versions)
377{
378    conn->fc_ver_neg.vn_supp = versions;
379    conn->fc_ver_neg.vn_ver  = highest_bit_set(versions);
380    conn->fc_ver_neg.vn_buf  = lsquic_ver2tag(conn->fc_ver_neg.vn_ver);
381    conn->fc_conn.cn_version = conn->fc_ver_neg.vn_ver;
382    LSQ_DEBUG("negotiating version %s",
383                            lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
384}
385
386
387static void
388init_ver_neg (struct full_conn *conn, unsigned versions)
389{
390    set_versions(conn, versions);
391    conn->fc_ver_neg.vn_tag   = &conn->fc_ver_neg.vn_buf;
392    conn->fc_ver_neg.vn_state = VN_START;
393}
394
395
396/* If peer supplies odd values, we abort the connection immediately rather
397 * that wait for it to finish "naturally" due to inability to send things.
398 */
399static void
400conn_on_peer_config (struct full_conn *conn, unsigned peer_cfcw,
401                     unsigned peer_sfcw, unsigned max_streams_out)
402{
403    lsquic_stream_t *stream;
404    struct lsquic_hash_elem *el;
405
406    LSQ_INFO("Applying peer config: cfcw: %u; sfcw: %u; # streams: %u",
407        peer_cfcw, peer_sfcw, max_streams_out);
408
409    if (peer_cfcw < conn->fc_pub.conn_cap.cc_sent)
410    {
411        ABORT_ERROR("peer specified CFCW=%u bytes, which is smaller than "
412            "the amount of data already sent on this connection (%"PRIu64
413            " bytes)", peer_cfcw, conn->fc_pub.conn_cap.cc_sent);
414        return;
415    }
416
417    conn->fc_cfg.max_streams_out = max_streams_out;
418    conn->fc_pub.conn_cap.cc_max = peer_cfcw;
419
420    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
421                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
422    {
423        stream = lsquic_hashelem_getdata(el);
424        if (0 != lsquic_stream_set_max_send_off(stream, peer_sfcw))
425        {
426            ABORT_ERROR("cannot set peer-supplied SFCW=%u on stream %u",
427                peer_sfcw, stream->id);
428            return;
429        }
430    }
431
432    conn->fc_cfg.max_stream_send = peer_sfcw;
433}
434
435
436static int
437send_smhl (const struct full_conn *conn)
438{
439    uint32_t smhl;
440    return conn->fc_conn.cn_enc_session
441        && (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
442        && 0 == conn->fc_conn.cn_esf->esf_get_peer_setting(
443                            conn->fc_conn.cn_enc_session, QTAG_SMHL, &smhl)
444        && 1 == smhl;
445}
446
447
448/* Once handshake has been completed, send settings to peer if appropriate.
449 */
450static void
451maybe_send_settings (struct full_conn *conn)
452{
453    struct lsquic_http2_setting settings[2];
454    unsigned n_settings = 0;
455
456    if (conn->fc_settings->es_max_header_list_size && send_smhl(conn))
457    {
458        settings[n_settings].id    = SETTINGS_MAX_HEADER_LIST_SIZE;
459        settings[n_settings].value = conn->fc_settings->es_max_header_list_size;
460        LSQ_DEBUG("sending settings SETTINGS_MAX_HEADER_LIST_SIZE=%u",
461                                                settings[n_settings].value);
462        ++n_settings;
463    }
464    if (!(conn->fc_flags & FC_SERVER) && !conn->fc_settings->es_support_push)
465    {
466        settings[n_settings].id    = SETTINGS_ENABLE_PUSH;
467        settings[n_settings].value = 0;
468        LSQ_DEBUG("sending settings SETTINGS_ENABLE_PUSH=%u",
469                                                settings[n_settings].value);
470        ++n_settings;
471    }
472
473    if (n_settings)
474    {
475        if (0 != lsquic_headers_stream_send_settings(conn->fc_pub.hs,
476                                                        settings, n_settings))
477            ABORT_ERROR("could not send settings");
478    }
479    else
480        LSQ_DEBUG("not sending any settings");
481}
482
483
484static int
485apply_peer_settings (struct full_conn *conn)
486{
487    uint32_t cfcw, sfcw, mids;
488    unsigned n;
489    const struct {
490        uint32_t    tag;
491        uint32_t   *val;
492        const char *tag_str;
493    } tags[] = {
494        { QTAG_CFCW, &cfcw, "CFCW", },
495        { QTAG_SFCW, &sfcw, "SFCW", },
496        { QTAG_MIDS, &mids, "MIDS", },
497    };
498
499#ifndef NDEBUG
500    if (getenv("LSQUIC_TEST_ENGINE_DTOR"))
501        return 0;
502#endif
503
504        for (n = 0; n < sizeof(tags) / sizeof(tags[0]); ++n)
505            if (0 != conn->fc_conn.cn_esf->esf_get_peer_setting(
506                        conn->fc_conn.cn_enc_session, tags[n].tag, tags[n].val))
507            {
508                LSQ_INFO("peer did not supply value for %s", tags[n].tag_str);
509                return -1;
510            }
511
512    LSQ_DEBUG("peer settings: CFCW: %u; SFCW: %u; MIDS: %u",
513        cfcw, sfcw, mids);
514    conn_on_peer_config(conn, cfcw, sfcw, mids);
515    if (conn->fc_flags & FC_HTTP)
516        maybe_send_settings(conn);
517    return 0;
518}
519
520
521static const struct conn_iface *full_conn_iface_ptr;
522
523static struct full_conn *
524new_conn_common (lsquic_cid_t cid, struct lsquic_engine_public *enpub,
525                 const struct lsquic_stream_if *stream_if,
526                 void *stream_if_ctx, unsigned flags,
527                 unsigned short max_packet_size)
528{
529    struct full_conn *conn;
530    lsquic_stream_t *headers_stream;
531    int saved_errno;
532
533    assert(0 == (flags & ~(FC_SERVER|FC_HTTP)));
534
535    conn = calloc(1, sizeof(*conn));
536    if (!conn)
537        return NULL;
538    headers_stream = NULL;
539    conn->fc_conn.cn_cid = cid;
540    conn->fc_conn.cn_pack_size = max_packet_size;
541    conn->fc_flags = flags;
542    conn->fc_enpub = enpub;
543    conn->fc_pub.enpub = enpub;
544    conn->fc_pub.mm = &enpub->enp_mm;
545    conn->fc_pub.lconn = &conn->fc_conn;
546    conn->fc_pub.send_ctl = &conn->fc_send_ctl;
547    conn->fc_pub.packet_out_malo =
548                        lsquic_malo_create(sizeof(struct lsquic_packet_out));
549    conn->fc_stream_ifs[STREAM_IF_STD].stream_if     = stream_if;
550    conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx = stream_if_ctx;
551    conn->fc_settings = &enpub->enp_settings;
552    /* Calculate maximum number of incoming streams using the same mechanism
553     * and parameters as found in Chrome:
554     */
555    conn->fc_cfg.max_streams_in =
556        (unsigned) ((float) enpub->enp_settings.es_max_streams_in * 1.1f);
557    if (conn->fc_cfg.max_streams_in <
558                                enpub->enp_settings.es_max_streams_in + 10)
559        conn->fc_cfg.max_streams_in =
560                                enpub->enp_settings.es_max_streams_in + 10;
561    /* `max_streams_out' gets reset when handshake is complete and we
562     * learn of peer settings.  100 seems like a sane default value
563     * because it is what other implementations use.  In server mode,
564     * we do not open any streams until the handshake is complete; in
565     * client mode, we are limited to 98 outgoing requests alongside
566     * handshake and headers streams.
567     */
568    conn->fc_cfg.max_streams_out = 100;
569    TAILQ_INIT(&conn->fc_pub.sending_streams);
570    TAILQ_INIT(&conn->fc_pub.read_streams);
571    TAILQ_INIT(&conn->fc_pub.write_streams);
572    TAILQ_INIT(&conn->fc_pub.service_streams);
573    STAILQ_INIT(&conn->fc_stream_ids_to_reset);
574    lsquic_conn_cap_init(&conn->fc_pub.conn_cap, LSQUIC_MIN_FCW);
575    lsquic_alarmset_init(&conn->fc_alset, cid);
576    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_IDLE, idle_alarm_expired, conn);
577    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_ACK, ack_alarm_expired, conn);
578    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_PING, ping_alarm_expired, conn);
579    lsquic_alarmset_init_alarm(&conn->fc_alset, AL_HANDSHAKE, handshake_alarm_expired, conn);
580    lsquic_set32_init(&conn->fc_closed_stream_ids[0]);
581    lsquic_set32_init(&conn->fc_closed_stream_ids[1]);
582    lsquic_cfcw_init(&conn->fc_pub.cfcw, &conn->fc_pub, conn->fc_settings->es_cfcw);
583    lsquic_send_ctl_init(&conn->fc_send_ctl, &conn->fc_alset, conn->fc_enpub,
584                 &conn->fc_ver_neg, &conn->fc_pub, conn->fc_conn.cn_pack_size);
585
586    conn->fc_pub.all_streams = lsquic_hash_create();
587    if (!conn->fc_pub.all_streams)
588        goto cleanup_on_error;
589    lsquic_rechist_init(&conn->fc_rechist, cid);
590    if (conn->fc_flags & FC_HTTP)
591    {
592        conn->fc_pub.hs = lsquic_headers_stream_new(
593            !!(conn->fc_flags & FC_SERVER), conn->fc_pub.mm, conn->fc_settings,
594                                                     headers_callbacks_ptr, conn);
595        if (!conn->fc_pub.hs)
596            goto cleanup_on_error;
597        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if     = lsquic_headers_stream_if;
598        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = conn->fc_pub.hs;
599        headers_stream = new_stream(conn, LSQUIC_STREAM_HEADERS,
600                                    SCF_CALL_ON_NEW);
601        if (!headers_stream)
602            goto cleanup_on_error;
603    }
604    else
605    {
606        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if     = stream_if;
607        conn->fc_stream_ifs[STREAM_IF_HDR].stream_if_ctx = stream_if_ctx;
608    }
609    if (conn->fc_settings->es_support_push)
610        conn->fc_flags |= FC_SUPPORT_PUSH;
611    conn->fc_conn.cn_if = full_conn_iface_ptr;
612    return conn;
613
614  cleanup_on_error:
615    saved_errno = errno;
616
617    if (conn->fc_pub.all_streams)
618        lsquic_hash_destroy(conn->fc_pub.all_streams);
619    lsquic_rechist_cleanup(&conn->fc_rechist);
620    if (conn->fc_flags & FC_HTTP)
621    {
622        if (conn->fc_pub.hs)
623            lsquic_headers_stream_destroy(conn->fc_pub.hs);
624        if (headers_stream)
625            lsquic_stream_destroy(headers_stream);
626    }
627    memset(conn, 0, sizeof(*conn));
628    free(conn);
629
630    errno = saved_errno;
631    return NULL;
632}
633
634
635struct lsquic_conn *
636full_conn_client_new (struct lsquic_engine_public *enpub,
637                      const struct lsquic_stream_if *stream_if,
638                      void *stream_if_ctx, unsigned flags,
639                      const char *hostname, unsigned short max_packet_size)
640{
641    struct full_conn *conn;
642    enum lsquic_version version;
643    lsquic_cid_t cid;
644    const struct enc_session_funcs *esf;
645
646    version = highest_bit_set(enpub->enp_settings.es_versions);
647    esf = select_esf_by_ver(version);
648    cid = esf->esf_generate_cid();
649    conn = new_conn_common(cid, enpub, stream_if, stream_if_ctx, flags,
650                                                            max_packet_size);
651    if (!conn)
652        return NULL;
653    conn->fc_conn.cn_esf = esf;
654    conn->fc_conn.cn_enc_session =
655        conn->fc_conn.cn_esf->esf_create_client(hostname, cid, conn->fc_enpub);
656    if (!conn->fc_conn.cn_enc_session)
657    {
658        LSQ_WARN("could not create enc session: %s", strerror(errno));
659        conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
660        return NULL;
661    }
662
663    if (conn->fc_flags & FC_HTTP)
664        conn->fc_last_stream_id = LSQUIC_STREAM_HEADERS;   /* Client goes 5, 7, 9.... */
665    else
666        conn->fc_last_stream_id = LSQUIC_STREAM_HANDSHAKE;
667    conn->fc_hsk_ctx.client.lconn   = &conn->fc_conn;
668    conn->fc_hsk_ctx.client.mm      = &enpub->enp_mm;
669    conn->fc_hsk_ctx.client.ver_neg = &conn->fc_ver_neg;
670    conn->fc_stream_ifs[STREAM_IF_HSK]
671                .stream_if     = &lsquic_client_hsk_stream_if;
672    conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
673    init_ver_neg(conn, conn->fc_settings->es_versions);
674    conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
675    if (conn->fc_settings->es_handshake_to)
676        lsquic_alarmset_set(&conn->fc_alset, AL_HANDSHAKE,
677                    lsquic_time_now() + conn->fc_settings->es_handshake_to);
678    if (!new_stream(conn, LSQUIC_STREAM_HANDSHAKE, SCF_CALL_ON_NEW))
679    {
680        LSQ_WARN("could not create handshake stream: %s", strerror(errno));
681        conn->fc_conn.cn_if->ci_destroy(&conn->fc_conn);
682        return NULL;
683    }
684    conn->fc_flags |= FC_CREATED_OK;
685    LSQ_INFO("Created new client connection");
686    EV_LOG_CONN_EVENT(cid, "created full connection");
687    return &conn->fc_conn;
688}
689
690
691void
692full_conn_client_call_on_new (struct lsquic_conn *lconn)
693{
694    struct full_conn *const conn = (struct full_conn *) lconn;
695    assert(conn->fc_flags & FC_CREATED_OK);
696    conn->fc_conn_ctx = conn->fc_stream_ifs[STREAM_IF_STD].stream_if
697        ->on_new_conn(conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, lconn);
698}
699
700
701static int
702is_our_stream (const struct full_conn *conn, const lsquic_stream_t *stream)
703{
704    int is_server = !!(conn->fc_flags & FC_SERVER);
705    return (1 & stream->id) ^ is_server;
706}
707
708
709static unsigned
710count_streams (const struct full_conn *conn, int peer)
711{
712    const lsquic_stream_t *stream;
713    unsigned count;
714    int ours;
715    int is_server;
716    struct lsquic_hash_elem *el;
717
718    peer = !!peer;
719    is_server = !!(conn->fc_flags & FC_SERVER);
720    count = 0;
721
722    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
723                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
724    {
725        stream = lsquic_hashelem_getdata(el);
726        ours = (1 & stream->id) ^ is_server;
727        if (ours ^ peer)
728            count += !lsquic_stream_is_closed(stream);
729    }
730
731    return count;
732}
733
734
735static void
736full_conn_ci_destroy (lsquic_conn_t *lconn)
737{
738    struct full_conn *conn = (struct full_conn *) lconn;
739    struct lsquic_hash_elem *el;
740    struct lsquic_stream *stream;
741    struct stream_id_to_reset *sitr;
742
743    LSQ_DEBUG("destroy connection");
744    conn->fc_flags |= FC_CLOSING;
745    lsquic_set32_cleanup(&conn->fc_closed_stream_ids[0]);
746    lsquic_set32_cleanup(&conn->fc_closed_stream_ids[1]);
747    while ((el = lsquic_hash_first(conn->fc_pub.all_streams)))
748    {
749        stream = lsquic_hashelem_getdata(el);
750        lsquic_hash_erase(conn->fc_pub.all_streams, el);
751        lsquic_stream_destroy(stream);
752    }
753    lsquic_hash_destroy(conn->fc_pub.all_streams);
754    if (conn->fc_flags & FC_CREATED_OK)
755        conn->fc_stream_ifs[STREAM_IF_STD].stream_if
756                    ->on_conn_closed(&conn->fc_conn);
757    if (conn->fc_pub.hs)
758        lsquic_headers_stream_destroy(conn->fc_pub.hs);
759
760    lsquic_send_ctl_cleanup(&conn->fc_send_ctl);
761    lsquic_rechist_cleanup(&conn->fc_rechist);
762    if (conn->fc_conn.cn_enc_session)
763        conn->fc_conn.cn_esf->esf_destroy(conn->fc_conn.cn_enc_session);
764    lsquic_malo_destroy(conn->fc_pub.packet_out_malo);
765#if FULL_CONN_STATS
766    LSQ_NOTICE("# ticks: %lu", conn->fc_stats.n_ticks);
767    LSQ_NOTICE("received %u packets, of which %u were not decryptable, %u were "
768        "dups and %u were errors; sent %u packets, avg stream data per outgoing"
769        " packet is %lu bytes",
770        conn->fc_stats.n_all_packets_in, conn->fc_stats.n_undec_packets,
771        conn->fc_stats.n_dup_packets, conn->fc_stats.n_err_packets,
772        conn->fc_stats.n_packets_out,
773        conn->fc_stats.stream_data_sz / conn->fc_stats.n_packets_out);
774    LSQ_NOTICE("ACKs: in: %u; processed: %u; merged to: new %u, old %u",
775        conn->fc_stats.n_acks_in, conn->fc_stats.n_acks_proc,
776        conn->fc_stats.n_acks_merged[0], conn->fc_stats.n_acks_merged[1]);
777#endif
778    while ((sitr = STAILQ_FIRST(&conn->fc_stream_ids_to_reset)))
779    {
780        STAILQ_REMOVE_HEAD(&conn->fc_stream_ids_to_reset, sitr_next);
781        free(sitr);
782    }
783    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "full connection destroyed");
784    free(conn->fc_errmsg);
785    free(conn);
786}
787
788
789static void
790conn_mark_stream_closed (struct full_conn *conn, uint32_t stream_id)
791{   /* Because stream IDs are distributed unevenly -- there is a set of odd
792     * stream IDs and a set of even stream IDs -- it is more efficient to
793     * maintain two sets of closed stream IDs.
794     */
795    int idx = stream_id & 1;
796    stream_id >>= 1;
797    if (0 != lsquic_set32_add(&conn->fc_closed_stream_ids[idx], stream_id))
798        ABORT_ERROR("could not add element to set: %s", strerror(errno));
799}
800
801
802static int
803conn_is_stream_closed (struct full_conn *conn, uint32_t stream_id)
804{
805    int idx = stream_id & 1;
806    stream_id >>= 1;
807    return lsquic_set32_has(&conn->fc_closed_stream_ids[idx], stream_id);
808}
809
810
811static void
812set_ack_timer (struct full_conn *conn, lsquic_time_t now)
813{
814    lsquic_alarmset_set(&conn->fc_alset, AL_ACK, now + ACK_TIMEOUT);
815    LSQ_DEBUG("ACK alarm set to %"PRIu64, now + ACK_TIMEOUT);
816}
817
818
819static void
820ack_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now)
821{
822    struct full_conn *conn = ctx;
823    LSQ_DEBUG("ACK timer expired (%"PRIu64" < %"PRIu64"): ACK queued",
824        expiry, now);
825    conn->fc_flags |= FC_ACK_QUEUED;
826}
827
828
829static void
830try_queueing_ack (struct full_conn *conn, int was_missing, lsquic_time_t now)
831{
832    if (conn->fc_n_slack_akbl >= MAX_RETR_PACKETS_SINCE_LAST_ACK ||
833        (conn->fc_conn.cn_version < LSQVER_039 /* Since Q039 do not ack ACKs */
834            && conn->fc_n_slack_all >= MAX_ANY_PACKETS_SINCE_LAST_ACK) ||
835        ((conn->fc_flags & FC_ACK_HAD_MISS) && was_missing)      ||
836        lsquic_send_ctl_n_stop_waiting(&conn->fc_send_ctl) > 1)
837    {
838        lsquic_alarmset_unset(&conn->fc_alset, AL_ACK);
839        lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
840        conn->fc_flags |= FC_ACK_QUEUED;
841        LSQ_DEBUG("ACK queued: ackable: %u; all: %u; had_miss: %d; "
842            "was_missing: %d; n_stop_waiting: %u",
843            conn->fc_n_slack_akbl, conn->fc_n_slack_all,
844            !!(conn->fc_flags & FC_ACK_HAD_MISS), was_missing,
845            lsquic_send_ctl_n_stop_waiting(&conn->fc_send_ctl));
846    }
847    else if (conn->fc_n_slack_akbl > 0)
848        set_ack_timer(conn, now);
849}
850
851
852static void
853reset_ack_state (struct full_conn *conn)
854{
855    conn->fc_n_slack_all  = 0;
856    conn->fc_n_slack_akbl = 0;
857    lsquic_send_ctl_n_stop_waiting_reset(&conn->fc_send_ctl);
858    conn->fc_flags &= ~FC_ACK_QUEUED;
859    lsquic_alarmset_unset(&conn->fc_alset, AL_ACK);
860    lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
861    LSQ_DEBUG("ACK state reset");
862}
863
864
865static lsquic_stream_t *
866new_stream_ext (struct full_conn *conn, uint32_t stream_id, int if_idx,
867                enum stream_ctor_flags stream_ctor_flags)
868{
869    lsquic_stream_t *stream = lsquic_stream_new_ext(stream_id, &conn->fc_pub,
870        conn->fc_stream_ifs[if_idx].stream_if,
871        conn->fc_stream_ifs[if_idx].stream_if_ctx, conn->fc_settings->es_sfcw,
872        conn->fc_cfg.max_stream_send, stream_ctor_flags);
873    if (stream)
874        lsquic_hash_insert(conn->fc_pub.all_streams, &stream->id, sizeof(stream->id),
875                                                                        stream);
876    return stream;
877}
878
879
880static lsquic_stream_t *
881new_stream (struct full_conn *conn, uint32_t stream_id,
882            enum stream_ctor_flags flags)
883{
884    int idx;
885    switch (stream_id)
886    {
887    case LSQUIC_STREAM_HANDSHAKE:
888        idx = STREAM_IF_HSK;
889        flags |= SCF_DI_AUTOSWITCH;
890        break;
891    case LSQUIC_STREAM_HEADERS:
892        idx = STREAM_IF_HDR;
893        flags |= SCF_DI_AUTOSWITCH;
894        if (!(conn->fc_flags & FC_HTTP) &&
895                                    conn->fc_enpub->enp_settings.es_rw_once)
896            flags |= SCF_DISP_RW_ONCE;
897        break;
898    default:
899        idx = STREAM_IF_STD;
900        flags |= SCF_DI_AUTOSWITCH;
901        if (conn->fc_enpub->enp_settings.es_rw_once)
902            flags |= SCF_DISP_RW_ONCE;
903        break;
904    }
905    return new_stream_ext(conn, stream_id, idx, flags);
906}
907
908
909static uint32_t
910generate_stream_id (struct full_conn *conn)
911{
912    conn->fc_last_stream_id += 2;
913    return conn->fc_last_stream_id;
914}
915
916
917unsigned
918lsquic_conn_n_pending_streams (const lsquic_conn_t *lconn)
919{
920    struct full_conn *conn = (struct full_conn *) lconn;
921    return conn->fc_n_delayed_streams;
922}
923
924
925unsigned
926lsquic_conn_cancel_pending_streams (lsquic_conn_t *lconn, unsigned n)
927{
928    struct full_conn *conn = (struct full_conn *) lconn;
929    if (n > conn->fc_n_delayed_streams)
930        conn->fc_n_delayed_streams = 0;
931    else
932        conn->fc_n_delayed_streams -= n;
933    return conn->fc_n_delayed_streams;
934}
935
936
937static int
938either_side_going_away (const struct full_conn *conn)
939{
940    return (conn->fc_flags & FC_GOING_AWAY)
941        || (conn->fc_conn.cn_flags & LSCONN_PEER_GOING_AWAY);
942}
943
944
945void
946lsquic_conn_make_stream (lsquic_conn_t *lconn)
947{
948    struct full_conn *conn = (struct full_conn *) lconn;
949    unsigned stream_count = count_streams(conn, 0);
950    if (stream_count < conn->fc_cfg.max_streams_out)
951    {
952        if (!new_stream(conn, generate_stream_id(conn), SCF_CALL_ON_NEW))
953            ABORT_ERROR("could not create new stream: %s", strerror(errno));
954    }
955    else if (either_side_going_away(conn))
956        (void) conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_new_stream(
957            conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, NULL);
958    else
959    {
960        ++conn->fc_n_delayed_streams;
961        LSQ_DEBUG("delayed stream creation.  Backlog size: %u",
962                                                conn->fc_n_delayed_streams);
963    }
964}
965
966
967static lsquic_stream_t *
968find_stream_by_id (struct full_conn *conn, uint32_t stream_id)
969{
970    struct lsquic_hash_elem *el;
971    el = lsquic_hash_find(conn->fc_pub.all_streams, &stream_id, sizeof(stream_id));
972    if (el)
973        return lsquic_hashelem_getdata(el);
974    else
975        return NULL;
976}
977
978
979lsquic_stream_t *
980lsquic_conn_get_stream_by_id (lsquic_conn_t *lconn, uint32_t stream_id)
981{
982    struct full_conn *conn = (struct full_conn *) lconn;
983    return find_stream_by_id(conn, stream_id);
984}
985
986
987lsquic_engine_t *
988lsquic_conn_get_engine (lsquic_conn_t *lconn)
989{
990    struct full_conn *conn = (struct full_conn *) lconn;
991    return conn->fc_enpub->enp_engine;
992}
993
994
995static ptrdiff_t
996count_zero_bytes (const unsigned char *p, size_t len)
997{
998    const unsigned char *const end = p + len;
999    while (p < end && 0 == *p)
1000        ++p;
1001    return len - (end - p);
1002}
1003
1004
1005static unsigned
1006process_padding_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1007                       const unsigned char *p, size_t len)
1008{
1009    if (conn->fc_conn.cn_version >= LSQVER_038)
1010        return (unsigned) count_zero_bytes(p, len);
1011    if (lsquic_is_zero(p, len))
1012    {
1013        EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len);
1014        return (unsigned) len;
1015    }
1016    else
1017        return 0;
1018}
1019
1020
1021static unsigned
1022process_ping_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1023                    const unsigned char *p, size_t len)
1024{   /* This frame causes ACK frame to be queued, but nothing to do here;
1025     * return the length of this frame.
1026     */
1027    EV_LOG_PING_FRAME_IN(LSQUIC_LOG_CONN_ID);
1028    LSQ_DEBUG("received PING");
1029    return 1;
1030}
1031
1032
1033static int
1034is_peer_initiated (const struct full_conn *conn, uint32_t stream_id)
1035{
1036    unsigned is_server = !!(conn->fc_flags & FC_SERVER);
1037    int peer_initiated = (stream_id & 1) == is_server;
1038    return peer_initiated;
1039}
1040
1041
1042static void
1043maybe_schedule_reset_for_stream (struct full_conn *conn, uint32_t stream_id)
1044{
1045    struct stream_id_to_reset *sitr;
1046
1047    if (conn_is_stream_closed(conn, stream_id))
1048        return;
1049
1050    sitr = malloc(sizeof(*sitr));
1051    if (!sitr)
1052        return;
1053
1054    sitr->sitr_stream_id = stream_id;
1055    STAILQ_INSERT_TAIL(&conn->fc_stream_ids_to_reset, sitr, sitr_next);
1056    conn_mark_stream_closed(conn, stream_id);
1057}
1058
1059
1060static unsigned
1061process_stream_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1062                      const unsigned char *p, size_t len)
1063{
1064    stream_frame_t *stream_frame;
1065    lsquic_stream_t *stream;
1066    enum enc_level enc_level;
1067    int parsed_len;
1068
1069    stream_frame = lsquic_malo_get(conn->fc_pub.mm->malo.stream_frame);
1070    if (!stream_frame)
1071    {
1072        LSQ_WARN("could not allocate stream frame: %s", strerror(errno));
1073        return 0;
1074    }
1075
1076    parsed_len = conn->fc_conn.cn_pf->pf_parse_stream_frame(p, len,
1077                                                            stream_frame);
1078    if (parsed_len < 0) {
1079        lsquic_malo_put(stream_frame);
1080        return 0;
1081    }
1082    EV_LOG_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_frame);
1083    LSQ_DEBUG("Got stream frame for stream #%u", stream_frame->stream_id);
1084
1085    enc_level = lsquic_packet_in_enc_level(packet_in);
1086    if (stream_frame->stream_id != LSQUIC_STREAM_HANDSHAKE
1087        && enc_level != ENC_LEV_FORW
1088        && enc_level != ENC_LEV_INIT)
1089    {
1090        lsquic_malo_put(stream_frame);
1091        ABORT_ERROR("received unencrypted data for stream %u",
1092                    stream_frame->stream_id);
1093        return 0;
1094    }
1095
1096    if (conn->fc_flags & FC_CLOSING)
1097    {
1098        LSQ_DEBUG("Connection closing: ignore frame");
1099        lsquic_malo_put(stream_frame);
1100        return parsed_len;
1101    }
1102
1103    stream = find_stream_by_id(conn, stream_frame->stream_id);
1104    if (!stream)
1105    {
1106        if (conn_is_stream_closed(conn, stream_frame->stream_id))
1107        {
1108            LSQ_DEBUG("drop frame for closed stream %u", stream_frame->stream_id);
1109            lsquic_malo_put(stream_frame);
1110            return parsed_len;
1111        }
1112        if (is_peer_initiated(conn, stream_frame->stream_id))
1113        {
1114            unsigned in_count = count_streams(conn, 1);
1115            LSQ_DEBUG("number of peer-initiated streams: %u", in_count);
1116            if (in_count >= conn->fc_cfg.max_streams_in)
1117            {
1118                ABORT_ERROR("incoming stream would exceed limit: %u",
1119                                        conn->fc_cfg.max_streams_in);
1120                lsquic_malo_put(stream_frame);
1121                return 0;
1122            }
1123            if ((conn->fc_flags & FC_GOING_AWAY) &&
1124                stream_frame->stream_id > conn->fc_max_peer_stream_id)
1125            {
1126                LSQ_DEBUG("going away: reset new incoming stream %"PRIu32,
1127                                                    stream_frame->stream_id);
1128                maybe_schedule_reset_for_stream(conn, stream_frame->stream_id);
1129                lsquic_malo_put(stream_frame);
1130                return parsed_len;
1131            }
1132        }
1133        else
1134        {
1135            ABORT_ERROR("frame for never-initiated stream");
1136            lsquic_malo_put(stream_frame);
1137            return 0;
1138        }
1139        stream = new_stream(conn, stream_frame->stream_id, SCF_CALL_ON_NEW);
1140        if (!stream)
1141        {
1142            ABORT_ERROR("cannot create new stream: %s", strerror(errno));
1143            lsquic_malo_put(stream_frame);
1144            return 0;
1145        }
1146        if (stream_frame->stream_id > conn->fc_max_peer_stream_id)
1147            conn->fc_max_peer_stream_id = stream_frame->stream_id;
1148    }
1149
1150    stream_frame->packet_in = lsquic_packet_in_get(packet_in);
1151    if (0 != lsquic_stream_frame_in(stream, stream_frame))
1152    {
1153        ABORT_ERROR("cannot insert stream frame");
1154        return 0;
1155    }
1156
1157    if (stream->id == LSQUIC_STREAM_HANDSHAKE
1158        && !(conn->fc_flags & FC_SERVER)
1159        && !(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE))
1160    {   /* To enable decryption, process handshake stream as soon as its
1161         * data frames are received.
1162         *
1163         * TODO: this does not work when packets are reordered.  A more
1164         * flexible solution would defer packet decryption if handshake
1165         * has not been completed yet.  Nevertheless, this is good enough
1166         * for now.
1167         */
1168        lsquic_stream_dispatch_read_events(stream);
1169    }
1170
1171    return parsed_len;
1172}
1173
1174
1175static unsigned
1176process_invalid_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1177                                            const unsigned char *p, size_t len)
1178{
1179    ABORT_ERROR("invalid frame");
1180    return 0;
1181}
1182
1183
1184/* Reset locally-initiated streams whose IDs is larger than the stream ID
1185 * specified in received GOAWAY frame.
1186 */
1187static void
1188reset_local_streams_over_goaway (struct full_conn *conn)
1189{
1190    const unsigned is_server = !!(conn->fc_flags & FC_SERVER);
1191    lsquic_stream_t *stream;
1192    struct lsquic_hash_elem *el;
1193
1194    for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
1195                                 el = lsquic_hash_next(conn->fc_pub.all_streams))
1196    {
1197        stream = lsquic_hashelem_getdata(el);
1198        if (stream->id > conn->fc_goaway_stream_id &&
1199            ((stream->id & 1) ^ is_server /* Locally initiated? */))
1200        {
1201            lsquic_stream_received_goaway(stream);
1202        }
1203    }
1204}
1205
1206
1207static unsigned
1208process_goaway_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1209                                            const unsigned char *p, size_t len)
1210{
1211    uint32_t error_code, stream_id;
1212    uint16_t reason_length;
1213    const char *reason;
1214    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_goaway_frame(p, len,
1215                            &error_code, &stream_id, &reason_length, &reason);
1216    if (parsed_len < 0)
1217        return 0;
1218    EV_LOG_GOAWAY_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code, stream_id,
1219        reason_length, reason);
1220    LSQ_DEBUG("received GOAWAY frame, last good stream ID: %u, error code: 0x%X,"
1221        " reason: `%.*s'", stream_id, error_code, reason_length, reason);
1222    if (0 == (conn->fc_conn.cn_flags & LSCONN_PEER_GOING_AWAY))
1223    {
1224        conn->fc_conn.cn_flags |= LSCONN_PEER_GOING_AWAY;
1225        conn->fc_goaway_stream_id = stream_id;
1226        if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_goaway_received)
1227        {
1228            LSQ_DEBUG("calling on_goaway_received");
1229            conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_goaway_received(
1230                                            &conn->fc_conn);
1231        }
1232        else
1233            LSQ_DEBUG("on_goaway_received not registered");
1234        reset_local_streams_over_goaway(conn);
1235    }
1236    else
1237        LSQ_DEBUG("ignore duplicate GOAWAY frame");
1238    return parsed_len;
1239}
1240
1241
1242static void
1243log_invalid_ack_frame (struct full_conn *conn, const unsigned char *p,
1244                                int parsed_len, const struct ack_info *acki)
1245{
1246    char *buf;
1247    size_t sz;
1248
1249    buf = malloc(0x1000);
1250    if (buf)
1251    {
1252        lsquic_senhist_tostr(&conn->fc_send_ctl.sc_senhist, buf, 0x1000);
1253        LSQ_WARN("send history: %s", buf);
1254        hexdump(p, parsed_len, buf, 0x1000);
1255        LSQ_WARN("raw ACK frame:\n%s", buf);
1256        free(buf);
1257    }
1258    else
1259        LSQ_WARN("malloc failed");
1260
1261    buf = acki2str(acki, &sz);
1262    if (buf)
1263    {
1264        LSQ_WARN("parsed ACK frame: %.*s", (int) sz, buf);
1265        free(buf);
1266    }
1267    else
1268        LSQ_WARN("malloc failed");
1269}
1270
1271
1272static int
1273process_ack (struct full_conn *conn, struct ack_info *acki,
1274             lsquic_time_t received)
1275{
1276#if FULL_CONN_STATS
1277    ++conn->fc_stats.n_acks_proc;
1278#endif
1279    LSQ_DEBUG("Processing ACK");
1280    if (0 == lsquic_send_ctl_got_ack(&conn->fc_send_ctl, acki, received))
1281    {
1282        if (lsquic_send_ctl_largest_ack2ed(&conn->fc_send_ctl))
1283            lsquic_rechist_stop_wait(&conn->fc_rechist,
1284                lsquic_send_ctl_largest_ack2ed(&conn->fc_send_ctl) + 1);
1285        return 0;
1286    }
1287    else
1288    {
1289        ABORT_ERROR("Received invalid ACK");
1290        return -1;
1291    }
1292}
1293
1294
1295static int
1296process_saved_ack (struct full_conn *conn, int restore_parsed_ack)
1297{
1298    struct ack_info *const acki = conn->fc_pub.mm->acki;
1299    struct lsquic_packno_range range;
1300    unsigned n_ranges, n_timestamps;
1301    lsquic_time_t lack_delta;
1302    int retval;
1303
1304#ifdef WIN32
1305    /* Useless initialization to mollify MSVC: */
1306    memset(&range, 0, sizeof(range));
1307    n_ranges = 0;
1308    n_timestamps = 0;
1309    lack_delta = 0;
1310#endif
1311
1312    if (restore_parsed_ack)
1313    {
1314        n_ranges     = acki->n_ranges;
1315        n_timestamps = acki->n_timestamps;
1316        lack_delta   = acki->lack_delta;
1317        range        = acki->ranges[0];
1318    }
1319
1320    acki->n_ranges     = 1;
1321    acki->n_timestamps = conn->fc_saved_ack_info.sai_n_timestamps;
1322    acki->lack_delta   = conn->fc_saved_ack_info.sai_lack_delta;
1323    acki->ranges[0]    = conn->fc_saved_ack_info.sai_range;
1324
1325    retval = process_ack(conn, acki, conn->fc_saved_ack_received);
1326
1327    if (restore_parsed_ack)
1328    {
1329        acki->n_ranges     = n_ranges;
1330        acki->n_timestamps = n_timestamps;
1331        acki->lack_delta   = lack_delta;
1332        acki->ranges[0]    = range;
1333    }
1334
1335    return retval;
1336}
1337
1338
1339static int
1340new_ack_is_superset (const struct short_ack_info *old, const struct ack_info *new)
1341{
1342    const struct lsquic_packno_range *new_range;
1343
1344    new_range = &new->ranges[ new->n_ranges - 1 ];
1345    return new_range->low  <= old->sai_range.low
1346        && new_range->high >= old->sai_range.high;
1347}
1348
1349
1350static int
1351merge_saved_to_new (const struct short_ack_info *old, struct ack_info *new)
1352{
1353    struct lsquic_packno_range *smallest_range;
1354
1355    assert(new->n_ranges > 1);
1356    smallest_range = &new->ranges[ new->n_ranges - 1 ];
1357    if (old->sai_range.high <= smallest_range->high
1358        && old->sai_range.high >= smallest_range->low
1359        && old->sai_range.low < smallest_range->low)
1360    {
1361        smallest_range->low = old->sai_range.low;
1362        return 1;
1363    }
1364    else
1365        return 0;
1366}
1367
1368
1369static int
1370merge_new_to_saved (struct short_ack_info *old, const struct ack_info *new)
1371{
1372    const struct lsquic_packno_range *new_range;
1373
1374    assert(new->n_ranges == 1);
1375    new_range = &new->ranges[0];
1376    /* Only merge if new is higher, for simplicity.  This is also the
1377     * expected case.
1378     */
1379    if (new_range->high > old->sai_range.high
1380        && new_range->low > old->sai_range.low)
1381    {
1382        old->sai_range.high = new_range->high;
1383        return 1;
1384    }
1385    else
1386        return 0;
1387}
1388
1389
1390static unsigned
1391process_ack_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1392                                            const unsigned char *p, size_t len)
1393{
1394    struct ack_info *const new_acki = conn->fc_pub.mm->acki;
1395    int parsed_len;
1396
1397#if FULL_CONN_STATS
1398    ++conn->fc_stats.n_acks_in;
1399#endif
1400
1401    parsed_len = conn->fc_conn.cn_pf->pf_parse_ack_frame(p, len, new_acki);
1402    if (parsed_len < 0)
1403        goto err;
1404
1405    if (packet_in->pi_packno <= conn->fc_max_ack_packno)
1406    {
1407        LSQ_DEBUG("Ignore old ack (max %"PRIu64")", conn->fc_max_ack_packno);
1408        return parsed_len;
1409    }
1410
1411    EV_LOG_ACK_FRAME_IN(LSQUIC_LOG_CONN_ID, new_acki);
1412    conn->fc_max_ack_packno = packet_in->pi_packno;
1413
1414    if (conn->fc_flags & FC_HAVE_SAVED_ACK)
1415    {
1416        LSQ_DEBUG("old ack [%"PRIu64"-%"PRIu64"]",
1417            conn->fc_saved_ack_info.sai_range.high,
1418            conn->fc_saved_ack_info.sai_range.low);
1419        const int is_superset = new_ack_is_superset(&conn->fc_saved_ack_info,
1420                                                    new_acki);
1421        const int is_1range = new_acki->n_ranges == 1;
1422        switch (
1423             (is_superset << 1)
1424                      | (is_1range << 0))
1425           /* |          |
1426              |          |
1427              V          V                      */ {
1428        case (0 << 1) | (0 << 0):
1429            if (merge_saved_to_new(&conn->fc_saved_ack_info, new_acki))
1430            {
1431#if FULL_CONN_STATS
1432                ++conn->fc_stats.n_acks_merged[0]
1433#endif
1434                ;
1435            }
1436            else
1437                process_saved_ack(conn, 1);
1438            conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
1439            if (0 != process_ack(conn, new_acki, packet_in->pi_received))
1440                goto err;
1441            break;
1442        case (0 << 1) | (1 << 0):
1443            if (merge_new_to_saved(&conn->fc_saved_ack_info, new_acki))
1444            {
1445#if FULL_CONN_STATS
1446                ++conn->fc_stats.n_acks_merged[1]
1447#endif
1448                ;
1449            }
1450            else
1451            {
1452                process_saved_ack(conn, 1);
1453                conn->fc_saved_ack_info.sai_n_timestamps = new_acki->n_timestamps;
1454                conn->fc_saved_ack_info.sai_range        = new_acki->ranges[0];
1455            }
1456            conn->fc_saved_ack_info.sai_lack_delta   = new_acki->lack_delta;
1457            conn->fc_saved_ack_received              = packet_in->pi_received;
1458            break;
1459        case (1 << 1) | (0 << 0):
1460            conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
1461            if (0 != process_ack(conn, new_acki, packet_in->pi_received))
1462                goto err;
1463            break;
1464        case (1 << 1) | (1 << 0):
1465            conn->fc_saved_ack_info.sai_n_timestamps = new_acki->n_timestamps;
1466            conn->fc_saved_ack_info.sai_lack_delta   = new_acki->lack_delta;
1467            conn->fc_saved_ack_info.sai_range        = new_acki->ranges[0];
1468            conn->fc_saved_ack_received              = packet_in->pi_received;
1469            break;
1470        }
1471    }
1472    else if (new_acki->n_ranges == 1)
1473    {
1474        conn->fc_saved_ack_info.sai_n_timestamps = new_acki->n_timestamps;
1475        conn->fc_saved_ack_info.sai_lack_delta   = new_acki->lack_delta;
1476        conn->fc_saved_ack_info.sai_range        = new_acki->ranges[0];
1477        conn->fc_saved_ack_received              = packet_in->pi_received;
1478        conn->fc_flags |= FC_HAVE_SAVED_ACK;
1479    }
1480    else if (0 != process_ack(conn, new_acki, packet_in->pi_received))
1481        goto err;
1482
1483    return parsed_len;
1484
1485  err:
1486    log_invalid_ack_frame(conn, p, parsed_len, new_acki);
1487    return 0;
1488}
1489
1490
1491static unsigned
1492process_stop_waiting_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1493                                            const unsigned char *p, size_t len)
1494{
1495    lsquic_packno_t least, cutoff;
1496    enum lsquic_packno_bits bits;
1497    int parsed_len;
1498
1499    bits = lsquic_packet_in_packno_bits(packet_in);
1500
1501    if (conn->fc_flags & FC_NSTP)
1502    {
1503        LSQ_DEBUG("NSTP on: ignore STOP_WAITING frame");
1504        parsed_len = conn->fc_conn.cn_pf->pf_skip_stop_waiting_frame(len, bits);
1505        if (parsed_len > 0)
1506            return (unsigned) parsed_len;
1507        else
1508            return 0;
1509    }
1510
1511    parsed_len = conn->fc_conn.cn_pf->pf_parse_stop_waiting_frame(p, len,
1512                                            packet_in->pi_packno, bits, &least);
1513    if (parsed_len < 0)
1514        return 0;
1515
1516    if (packet_in->pi_packno <= conn->fc_max_swf_packno)
1517    {
1518        LSQ_DEBUG("ignore old STOP_WAITING frame");
1519        return parsed_len;
1520    }
1521
1522    LSQ_DEBUG("Got STOP_WAITING frame, least unacked: %"PRIu64, least);
1523    EV_LOG_STOP_WAITING_FRAME_IN(LSQUIC_LOG_CONN_ID, least);
1524
1525    if (least > packet_in->pi_packno)
1526    {
1527        ABORT_ERROR("received invalid STOP_WAITING: %"PRIu64" is larger "
1528            "than the packet number%"PRIu64, least, packet_in->pi_packno);
1529        return 0;
1530    }
1531
1532    cutoff = lsquic_rechist_cutoff(&conn->fc_rechist);
1533    if (cutoff && least < cutoff)
1534    {
1535        ABORT_ERROR("received invalid STOP_WAITING: %"PRIu64" is smaller "
1536            "than the cutoff %"PRIu64, least, cutoff);
1537        return 0;
1538    }
1539
1540    conn->fc_max_swf_packno = packet_in->pi_packno;
1541    lsquic_rechist_stop_wait(&conn->fc_rechist, least);
1542    return parsed_len;
1543}
1544
1545
1546static unsigned
1547process_blocked_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1548                                            const unsigned char *p, size_t len)
1549{
1550    uint32_t stream_id;
1551    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_blocked_frame(p, len,
1552                                                                    &stream_id);
1553    if (parsed_len < 0)
1554        return 0;
1555    EV_LOG_BLOCKED_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id);
1556    LSQ_DEBUG("Peer reports stream %u as blocked", stream_id);
1557    return parsed_len;
1558}
1559
1560
1561static unsigned
1562process_connection_close_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1563                                const unsigned char *p, size_t len)
1564{
1565    lsquic_stream_t *stream;
1566    struct lsquic_hash_elem *el;
1567    uint32_t error_code;
1568    uint16_t reason_len;
1569    uint8_t reason_off;
1570    int parsed_len;
1571
1572    parsed_len = conn->fc_conn.cn_pf->pf_parse_connect_close_frame(p, len,
1573                                        &error_code, &reason_len, &reason_off);
1574    if (parsed_len < 0)
1575        return 0;
1576    EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code,
1577                            (int) reason_len, (const char *) p + reason_off);
1578    LSQ_INFO("Received CONNECTION_CLOSE frame (code: %u; reason: %.*s)",
1579                error_code, (int) reason_len, (const char *) p + reason_off);
1580    conn->fc_flags |= FC_RECV_CLOSE;
1581    if (!(conn->fc_flags & FC_CLOSING))
1582    {
1583        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
1584                                     el = lsquic_hash_next(conn->fc_pub.all_streams))
1585        {
1586            stream = lsquic_hashelem_getdata(el);
1587            lsquic_stream_shutdown_internal(stream);
1588        }
1589        conn->fc_flags |= FC_CLOSING;
1590    }
1591    return parsed_len;
1592}
1593
1594
1595static unsigned
1596process_rst_stream_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1597                                            const unsigned char *p, size_t len)
1598{
1599    uint32_t stream_id, error_code;
1600    uint64_t offset;
1601    lsquic_stream_t *stream;
1602    const int parsed_len = conn->fc_conn.cn_pf->pf_parse_rst_frame(p, len,
1603                                            &stream_id, &offset, &error_code);
1604    if (parsed_len < 0)
1605        return 0;
1606
1607    EV_LOG_RST_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset,
1608                                                                error_code);
1609    LSQ_DEBUG("Got RST_STREAM; stream: %u; offset: 0x%"PRIX64, stream_id,
1610                                                                    offset);
1611    if (0 == stream_id)
1612    {   /* Follow reference implementation and ignore this apparently
1613         * invalid frame.
1614         */
1615        return parsed_len;
1616    }
1617
1618    if (LSQUIC_STREAM_HANDSHAKE == stream_id ||
1619        ((conn->fc_flags & FC_HTTP) && LSQUIC_STREAM_HEADERS == stream_id))
1620    {
1621        ABORT_ERROR("received reset on static stream %u", stream_id);
1622        return 0;
1623    }
1624
1625    stream = find_stream_by_id(conn, stream_id);
1626    if (!stream)
1627    {
1628        if (conn_is_stream_closed(conn, stream_id))
1629        {
1630            LSQ_DEBUG("got reset frame for closed stream %u", stream_id);
1631            return parsed_len;
1632        }
1633        if (!is_peer_initiated(conn, stream_id))
1634        {
1635            ABORT_ERROR("received reset for never-initiated stream %u",
1636                                                                    stream_id);
1637            return 0;
1638        }
1639        stream = new_stream(conn, stream_id, SCF_CALL_ON_NEW);
1640        if (!stream)
1641        {
1642            ABORT_ERROR("cannot create new stream: %s", strerror(errno));
1643            return 0;
1644        }
1645        if (stream_id > conn->fc_max_peer_stream_id)
1646            conn->fc_max_peer_stream_id = stream_id;
1647    }
1648
1649    if (0 != lsquic_stream_rst_in(stream, offset, error_code))
1650    {
1651        ABORT_ERROR("received invalid RST_STREAM");
1652        return 0;
1653    }
1654    return parsed_len;
1655}
1656
1657
1658static unsigned
1659process_window_update_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1660                                             const unsigned char *p, size_t len)
1661{
1662    uint32_t stream_id;
1663    uint64_t offset;
1664    const int parsed_len =
1665                conn->fc_conn.cn_pf->pf_parse_window_update_frame(p, len,
1666                                                        &stream_id, &offset);
1667    if (parsed_len < 0)
1668        return 0;
1669    EV_LOG_WINDOW_UPDATE_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset);
1670    if (stream_id)
1671    {
1672        lsquic_stream_t *stream = find_stream_by_id(conn, stream_id);
1673        if (stream)
1674        {
1675            LSQ_DEBUG("Got window update frame, stream: %u; offset: 0x%"PRIX64,
1676                                                            stream_id, offset);
1677            lsquic_stream_window_update(stream, offset);
1678        }
1679        else    /* Perhaps a result of lost packets? */
1680            LSQ_DEBUG("Got window update frame for non-existing stream %u "
1681                                 "(offset: 0x%"PRIX64")", stream_id, offset);
1682    }
1683    else if (offset > conn->fc_pub.conn_cap.cc_max)
1684    {
1685        conn->fc_pub.conn_cap.cc_max = offset;
1686        assert(conn->fc_pub.conn_cap.cc_max >= conn->fc_pub.conn_cap.cc_sent);
1687        LSQ_DEBUG("Connection WUF, new offset 0x%"PRIX64, offset);
1688    }
1689    else
1690        LSQ_DEBUG("Throw ouw duplicate connection WUF");
1691    return parsed_len;
1692}
1693
1694
1695typedef unsigned (*process_frame_f)(
1696    struct full_conn *, lsquic_packet_in_t *, const unsigned char *p, size_t);
1697
1698static process_frame_f const process_frames[N_QUIC_FRAMES] =
1699{
1700    [QUIC_FRAME_ACK]                  =  process_ack_frame,
1701    [QUIC_FRAME_BLOCKED]              =  process_blocked_frame,
1702    [QUIC_FRAME_CONNECTION_CLOSE]     =  process_connection_close_frame,
1703    [QUIC_FRAME_GOAWAY]               =  process_goaway_frame,
1704    [QUIC_FRAME_INVALID]              =  process_invalid_frame,
1705    [QUIC_FRAME_PADDING]              =  process_padding_frame,
1706    [QUIC_FRAME_PING]                 =  process_ping_frame,
1707    [QUIC_FRAME_RST_STREAM]           =  process_rst_stream_frame,
1708    [QUIC_FRAME_STOP_WAITING]         =  process_stop_waiting_frame,
1709    [QUIC_FRAME_STREAM]               =  process_stream_frame,
1710    [QUIC_FRAME_WINDOW_UPDATE]        =  process_window_update_frame,
1711};
1712
1713static unsigned
1714process_packet_frame (struct full_conn *conn, lsquic_packet_in_t *packet_in,
1715                      const unsigned char *p, size_t len)
1716{
1717    enum QUIC_FRAME_TYPE type = conn->fc_conn.cn_pf->pf_parse_frame_type(p[0]);
1718    packet_in->pi_frame_types |= 1 << type;
1719    recent_packet_hist_frames(conn, 0, 1 << type);
1720    return process_frames[type](conn, packet_in, p, len);
1721}
1722
1723
1724static void
1725process_ver_neg_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1726{
1727    int s;
1728    struct ver_iter vi;
1729    lsquic_ver_tag_t ver_tag;
1730    enum lsquic_version version;
1731    unsigned versions = 0;
1732
1733    LSQ_DEBUG("Processing version-negotiation packet");
1734
1735    if (conn->fc_ver_neg.vn_state != VN_START)
1736    {
1737        LSQ_DEBUG("ignore a likely duplicate version negotiation packet");
1738        return;
1739    }
1740
1741    for (s = packet_in_ver_first(packet_in, &vi, &ver_tag); s;
1742                     s = packet_in_ver_next(&vi, &ver_tag))
1743    {
1744        version = lsquic_tag2ver(ver_tag);
1745        if (version < N_LSQVER)
1746        {
1747            versions |= 1 << version;
1748            LSQ_DEBUG("server supports version %s", lsquic_ver2str[version]);
1749        }
1750    }
1751
1752    if (versions & (1 << conn->fc_ver_neg.vn_ver))
1753    {
1754        ABORT_ERROR("server replied with version we support: %s",
1755                                    lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
1756        return;
1757    }
1758
1759    versions &= conn->fc_ver_neg.vn_supp;
1760    if (0 == versions)
1761    {
1762        ABORT_ERROR("client does not support any of the server-specified "
1763                    "versions");
1764        return;
1765    }
1766
1767    set_versions(conn, versions);
1768    conn->fc_ver_neg.vn_state = VN_IN_PROGRESS;
1769    lsquic_send_ctl_expire_all(&conn->fc_send_ctl);
1770}
1771
1772
1773static void
1774reconstruct_packet_number (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1775{
1776    lsquic_packno_t cur_packno, max_packno;
1777    enum lsquic_packno_bits bits;
1778
1779    cur_packno = packet_in->pi_packno;
1780    max_packno = lsquic_rechist_largest_packno(&conn->fc_rechist);
1781    bits = lsquic_packet_in_packno_bits(packet_in);
1782    packet_in->pi_packno = restore_packno(cur_packno, bits, max_packno);
1783    LSQ_DEBUG("reconstructed (bits: %u, packno: %"PRIu64", max: %"PRIu64") "
1784        "to %"PRIu64"", bits, cur_packno, max_packno, packet_in->pi_packno);
1785}
1786
1787
1788static int
1789conn_decrypt_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1790{
1791        return lsquic_conn_decrypt_packet(&conn->fc_conn, conn->fc_enpub,
1792                                                                packet_in);
1793}
1794
1795
1796static void
1797parse_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1798{
1799    const unsigned char *p, *pend;
1800    unsigned len;
1801
1802    p = packet_in->pi_data + packet_in->pi_header_sz;
1803    pend = packet_in->pi_data + packet_in->pi_data_sz;
1804
1805    while (p < pend)
1806    {
1807        len = process_packet_frame(conn, packet_in, p, pend - p);
1808        if (len > 0)
1809            p += len;
1810        else
1811        {
1812            ABORT_ERROR("Error parsing frame");
1813            break;
1814        }
1815    }
1816}
1817
1818
1819static int
1820process_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1821{
1822    enum received_st st;
1823    enum quic_ft_bit frame_types;
1824    int was_missing;
1825
1826    reconstruct_packet_number(conn, packet_in);
1827    EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
1828
1829#if FULL_CONN_STATS
1830    ++conn->fc_stats.n_all_packets_in;
1831#endif
1832
1833    /* The packet is decrypted before receive history is updated.  This is
1834     * done to make sure that a bad packet won't occupy a slot in receive
1835     * history and subsequent good packet won't be marked as a duplicate.
1836     */
1837    if (0 == (packet_in->pi_flags & PI_DECRYPTED) &&
1838        0 != conn_decrypt_packet(conn, packet_in))
1839    {
1840        LSQ_INFO("could not decrypt packet");
1841#if FULL_CONN_STATS
1842        ++conn->fc_stats.n_undec_packets;
1843#endif
1844        return 0;
1845    }
1846
1847    st = lsquic_rechist_received(&conn->fc_rechist, packet_in->pi_packno,
1848                                                    packet_in->pi_received);
1849    switch (st) {
1850    case REC_ST_OK:
1851        parse_regular_packet(conn, packet_in);
1852        if (0 == (conn->fc_flags & FC_ACK_QUEUED))
1853        {
1854            frame_types = packet_in->pi_frame_types;
1855            was_missing = packet_in->pi_packno !=
1856                            lsquic_rechist_largest_packno(&conn->fc_rechist);
1857            conn->fc_n_slack_all  += 1;
1858            conn->fc_n_slack_akbl += !!(frame_types & QFRAME_ACKABLE_MASK);
1859            try_queueing_ack(conn, was_missing, packet_in->pi_received);
1860        }
1861        return 0;
1862    case REC_ST_DUP:
1863#if FULL_CONN_STATS
1864    ++conn->fc_stats.n_dup_packets;
1865#endif
1866        LSQ_INFO("packet %"PRIu64" is a duplicate", packet_in->pi_packno);
1867        return 0;
1868    default:
1869        assert(0);
1870        /* Fall through */
1871    case REC_ST_ERR:
1872#if FULL_CONN_STATS
1873    ++conn->fc_stats.n_err_packets;
1874#endif
1875        LSQ_INFO("error processing packet %"PRIu64, packet_in->pi_packno);
1876        return -1;
1877    }
1878}
1879
1880
1881static int
1882process_incoming_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
1883{
1884    recent_packet_hist_new(conn, 0, packet_in->pi_received);
1885    LSQ_DEBUG("Processing packet %"PRIu64, packet_in->pi_packno);
1886    /* See flowchart in Section 4.1 of [draft-ietf-quic-transport-00].  We test
1887     * for the common case first.
1888     */
1889    const unsigned flags = lsquic_packet_in_public_flags(packet_in);
1890    if (0 == (flags & (PACKET_PUBLIC_FLAGS_RST|PACKET_PUBLIC_FLAGS_VERSION)))
1891    {
1892        if (conn->fc_ver_neg.vn_tag)
1893        {
1894            assert(conn->fc_ver_neg.vn_state != VN_END);
1895            conn->fc_ver_neg.vn_state = VN_END;
1896            conn->fc_ver_neg.vn_tag = NULL;
1897            conn->fc_conn.cn_version = conn->fc_ver_neg.vn_ver;
1898            conn->fc_conn.cn_flags |= LSCONN_VER_SET;
1899            if (conn->fc_conn.cn_version >= LSQVER_037)
1900            {
1901                assert(!(conn->fc_flags & FC_NSTP)); /* This bit off at start */
1902                if (conn->fc_settings->es_support_nstp)
1903                {
1904                    conn->fc_flags |= FC_NSTP;
1905                    lsquic_send_ctl_turn_nstp_on(&conn->fc_send_ctl);
1906                }
1907            }
1908            LSQ_DEBUG("end of version negotiation: agreed upon %s",
1909                                    lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
1910        }
1911        return process_regular_packet(conn, packet_in);
1912    }
1913    else if (flags & PACKET_PUBLIC_FLAGS_RST)
1914    {
1915        LSQ_INFO("received public reset packet: aborting connection");
1916        conn->fc_flags |= FC_GOT_PRST;
1917        return -1;
1918    }
1919    else
1920    {
1921        if (conn->fc_flags & FC_SERVER)
1922            return process_regular_packet(conn, packet_in);
1923        else if (conn->fc_ver_neg.vn_tag)
1924        {
1925            process_ver_neg_packet(conn, packet_in);
1926            return 0;
1927        }
1928        else
1929        {
1930            LSQ_DEBUG("unexpected version negotiation packet: ignore it");
1931            return 0;
1932        }
1933    }
1934}
1935
1936
1937static void
1938idle_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now)
1939{
1940    struct full_conn *conn = ctx;
1941    LSQ_DEBUG("connection timed out");
1942    conn->fc_flags |= FC_TIMED_OUT;
1943}
1944
1945
1946static void
1947handshake_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now)
1948{
1949    struct full_conn *conn = ctx;
1950    LSQ_DEBUG("connection timed out: handshake timed out");
1951    conn->fc_flags |= FC_TIMED_OUT;
1952}
1953
1954
1955static void
1956ping_alarm_expired (void *ctx, lsquic_time_t expiry, lsquic_time_t now)
1957{
1958    struct full_conn *conn = ctx;
1959    LSQ_DEBUG("Ping alarm rang: schedule PING frame to be generated");
1960    conn->fc_flags |= FC_SEND_PING;
1961}
1962
1963
1964static lsquic_packet_out_t *
1965get_writeable_packet (struct full_conn *conn, unsigned need_at_least)
1966{
1967    lsquic_packet_out_t *packet_out;
1968    int is_err;
1969
1970    assert(need_at_least <= QUIC_MAX_PAYLOAD_SZ);
1971    packet_out = lsquic_send_ctl_get_writeable_packet(&conn->fc_send_ctl,
1972                                                    need_at_least, &is_err);
1973    if (!packet_out && is_err)
1974        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
1975    return packet_out;
1976}
1977
1978
1979static int
1980generate_wuf_stream (struct full_conn *conn, lsquic_stream_t *stream)
1981{
1982    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, QUIC_WUF_SZ);
1983    if (!packet_out)
1984        return 0;
1985    const uint64_t recv_off = lsquic_stream_fc_recv_off(stream);
1986    int sz = conn->fc_conn.cn_pf->pf_gen_window_update_frame(
1987                packet_out->po_data + packet_out->po_data_sz,
1988                     lsquic_packet_out_avail(packet_out), stream->id, recv_off);
1989    if (sz < 0) {
1990        ABORT_ERROR("gen_window_update_frame failed");
1991        return 0;
1992    }
1993    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
1994    packet_out->po_frame_types |= 1 << QUIC_FRAME_WINDOW_UPDATE;
1995    LSQ_DEBUG("wrote WUF: stream %u; offset 0x%"PRIX64, stream->id, recv_off);
1996    return 1;
1997}
1998
1999
2000static void
2001generate_wuf_conn (struct full_conn *conn)
2002{
2003    assert(conn->fc_flags & FC_SEND_WUF);
2004    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, QUIC_WUF_SZ);
2005    if (!packet_out)
2006        return;
2007    const uint64_t recv_off = lsquic_cfcw_get_fc_recv_off(&conn->fc_pub.cfcw);
2008    int sz = conn->fc_conn.cn_pf->pf_gen_window_update_frame(
2009                     packet_out->po_data + packet_out->po_data_sz,
2010                     lsquic_packet_out_avail(packet_out), 0, recv_off);
2011    if (sz < 0) {
2012        ABORT_ERROR("gen_window_update_frame failed");
2013        return;
2014    }
2015    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2016    packet_out->po_frame_types |= 1 << QUIC_FRAME_WINDOW_UPDATE;
2017    conn->fc_flags &= ~FC_SEND_WUF;
2018    LSQ_DEBUG("wrote connection WUF: offset 0x%"PRIX64, recv_off);
2019}
2020
2021
2022static void
2023generate_goaway_frame (struct full_conn *conn)
2024{
2025    int reason_len = 0;
2026    lsquic_packet_out_t *packet_out =
2027        get_writeable_packet(conn, QUIC_GOAWAY_FRAME_SZ + reason_len);
2028    if (!packet_out)
2029        return;
2030    int sz = conn->fc_conn.cn_pf->pf_gen_goaway_frame(
2031                 packet_out->po_data + packet_out->po_data_sz,
2032                 lsquic_packet_out_avail(packet_out), 0, conn->fc_max_peer_stream_id,
2033                 NULL, reason_len);
2034    if (sz < 0) {
2035        ABORT_ERROR("gen_goaway_frame failed");
2036        return;
2037    }
2038    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2039    packet_out->po_frame_types |= 1 << QUIC_FRAME_GOAWAY;
2040    conn->fc_flags &= ~FC_SEND_GOAWAY;
2041    conn->fc_flags |=  FC_GOAWAY_SENT;
2042    LSQ_DEBUG("wrote GOAWAY frame: stream id: %u", conn->fc_max_peer_stream_id);
2043}
2044
2045
2046static void
2047generate_connection_close_packet (struct full_conn *conn)
2048{
2049    lsquic_packet_out_t *packet_out;
2050
2051    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0);
2052    if (!packet_out)
2053    {
2054        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2055        return;
2056    }
2057
2058    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
2059    int sz = conn->fc_conn.cn_pf->pf_gen_connect_close_frame(packet_out->po_data + packet_out->po_data_sz,
2060                     lsquic_packet_out_avail(packet_out), 16 /* PEER_GOING_AWAY */,
2061                     NULL, 0);
2062    if (sz < 0) {
2063        ABORT_ERROR("generate_connection_close_packet failed");
2064        return;
2065    }
2066    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2067    packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
2068    LSQ_DEBUG("generated CONNECTION_CLOSE frame in its own packet");
2069}
2070
2071
2072static int
2073generate_blocked_frame (struct full_conn *conn, uint32_t stream_id)
2074{
2075    lsquic_packet_out_t *packet_out =
2076                            get_writeable_packet(conn, QUIC_BLOCKED_FRAME_SZ);
2077    if (!packet_out)
2078        return 0;
2079    int sz = conn->fc_conn.cn_pf->pf_gen_blocked_frame(
2080                                 packet_out->po_data + packet_out->po_data_sz,
2081                                 lsquic_packet_out_avail(packet_out), stream_id);
2082    if (sz < 0) {
2083        ABORT_ERROR("gen_blocked_frame failed");
2084        return 0;
2085    }
2086    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2087    packet_out->po_frame_types |= 1 << QUIC_FRAME_BLOCKED;
2088    LSQ_DEBUG("wrote blocked frame: stream %u", stream_id);
2089    return 1;
2090}
2091
2092
2093static int
2094generate_stream_blocked_frame (struct full_conn *conn, lsquic_stream_t *stream)
2095{
2096    if (generate_blocked_frame(conn, stream->id))
2097    {
2098        lsquic_stream_blocked_frame_sent(stream);
2099        return 1;
2100    }
2101    else
2102        return 0;
2103}
2104
2105
2106static int
2107generate_rst_stream_frame (struct full_conn *conn, lsquic_stream_t *stream)
2108{
2109    lsquic_packet_out_t *packet_out;
2110    int sz, s;
2111
2112    packet_out = get_writeable_packet(conn, QUIC_RST_STREAM_SZ);
2113    if (!packet_out)
2114        return 0;
2115    /* TODO Possible optimization: instead of using stream->tosend_off as the
2116     * offset, keep track of the offset that was actually sent: include it
2117     * into stream_rec and update a new per-stream "maximum offset actually
2118     * sent" field.  Then, if a stream is reset, the connection cap can be
2119     * increased.
2120     */
2121    sz = conn->fc_conn.cn_pf->pf_gen_rst_frame(
2122                     packet_out->po_data + packet_out->po_data_sz,
2123                     lsquic_packet_out_avail(packet_out), stream->id,
2124                     stream->tosend_off, stream->error_code);
2125    if (sz < 0) {
2126        ABORT_ERROR("gen_rst_frame failed");
2127        return 0;
2128    }
2129    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2130    packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
2131    s = lsquic_packet_out_add_stream(packet_out, conn->fc_pub.mm, stream,
2132                                     QUIC_FRAME_RST_STREAM, 0, 0);
2133    if (s != 0)
2134    {
2135        ABORT_ERROR("adding stream to packet failed: %s", strerror(errno));
2136        return 0;
2137    }
2138    lsquic_stream_rst_frame_sent(stream);
2139    LSQ_DEBUG("wrote RST: stream %u; offset 0x%"PRIX64"; error code 0x%X",
2140                        stream->id, stream->tosend_off, stream->error_code);
2141    return 1;
2142}
2143
2144
2145static void
2146generate_ping_frame (struct full_conn *conn)
2147{
2148    lsquic_packet_out_t *packet_out = get_writeable_packet(conn, 1);
2149    if (!packet_out)
2150    {
2151        LSQ_DEBUG("cannot get writeable packet for PING frame");
2152        return;
2153    }
2154    int sz = conn->fc_conn.cn_pf->pf_gen_ping_frame(
2155                            packet_out->po_data + packet_out->po_data_sz,
2156                            lsquic_packet_out_avail(packet_out));
2157    if (sz < 0) {
2158        ABORT_ERROR("gen_blocked_frame failed");
2159        return;
2160    }
2161    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2162    packet_out->po_frame_types |= 1 << QUIC_FRAME_PING;
2163    LSQ_DEBUG("wrote PING frame");
2164}
2165
2166
2167static void
2168generate_stop_waiting_frame (struct full_conn *conn)
2169{
2170    assert(conn->fc_flags & FC_SEND_STOP_WAITING);
2171
2172    int sz;
2173    unsigned packnum_len;
2174    lsquic_packno_t least_unacked;
2175    lsquic_packet_out_t *packet_out;
2176
2177    /* Get packet that has room for the minimum size STOP_WAITING frame: */
2178    packet_out = get_writeable_packet(conn, 1 + packno_bits2len(PACKNO_LEN_1));
2179    if (!packet_out)
2180        return;
2181
2182    /* Now calculate number of bytes we really need.  If there is not enough
2183     * room in the current packet, get a new one.
2184     */
2185    packnum_len = packno_bits2len(lsquic_packet_out_packno_bits(packet_out));
2186    if ((unsigned) lsquic_packet_out_avail(packet_out) < 1 + packnum_len)
2187    {
2188        packet_out = get_writeable_packet(conn, 1 + packnum_len);
2189        if (!packet_out)
2190            return;
2191        /* Here, a new packet has been allocated, The number of bytes needed
2192         * to represent packet number in the STOP_WAITING frame may have
2193         * increased.  However, this does not matter, because the newly
2194         * allocated packet must have room for a STOP_WAITING frame of any
2195         * size.
2196         */
2197    }
2198
2199    least_unacked = lsquic_send_ctl_smallest_unacked(&conn->fc_send_ctl);
2200    sz = conn->fc_conn.cn_pf->pf_gen_stop_waiting_frame(
2201                    packet_out->po_data + packet_out->po_data_sz,
2202                    lsquic_packet_out_avail(packet_out), packet_out->po_packno,
2203                    lsquic_packet_out_packno_bits(packet_out), least_unacked);
2204    if (sz < 0) {
2205        ABORT_ERROR("gen_stop_waiting_frame failed");
2206        return;
2207    }
2208    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2209    packet_out->po_regen_sz += sz;
2210    packet_out->po_frame_types |= 1 << QUIC_FRAME_STOP_WAITING;
2211    conn->fc_flags &= ~FC_SEND_STOP_WAITING;
2212    LSQ_DEBUG("wrote STOP_WAITING frame: least unacked: %"PRIu64,
2213                                                            least_unacked);
2214    EV_LOG_GENERATED_STOP_WAITING_FRAME(LSQUIC_LOG_CONN_ID, least_unacked);
2215}
2216
2217
2218static int
2219process_stream_ready_to_send (struct full_conn *conn, lsquic_stream_t *stream)
2220{
2221    int r = 1;
2222    if (stream->stream_flags & STREAM_SEND_WUF)
2223        r &= generate_wuf_stream(conn, stream);
2224    if (stream->stream_flags & STREAM_SEND_BLOCKED)
2225        r &= generate_stream_blocked_frame(conn, stream);
2226    if (stream->stream_flags & STREAM_SEND_RST)
2227        r &= generate_rst_stream_frame(conn, stream);
2228    return r;
2229}
2230
2231
2232static void
2233process_streams_ready_to_send (struct full_conn *conn)
2234{
2235    lsquic_stream_t *stream;
2236    struct stream_prio_iter spi;
2237
2238    assert(!TAILQ_EMPTY(&conn->fc_pub.sending_streams));
2239
2240    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.sending_streams),
2241        TAILQ_LAST(&conn->fc_pub.sending_streams, lsquic_streams_tailq),
2242        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_send_stream),
2243        STREAM_SENDING_FLAGS, conn->fc_conn.cn_cid, "send");
2244
2245    for (stream = lsquic_spi_first(&spi); stream;
2246                                            stream = lsquic_spi_next(&spi))
2247        if (!process_stream_ready_to_send(conn, stream))
2248            break;
2249}
2250
2251
2252/* Return true if packetized, false otherwise */
2253static int
2254packetize_standalone_stream_reset (struct full_conn *conn, uint32_t stream_id)
2255{
2256    lsquic_packet_out_t *packet_out;
2257    int sz;
2258
2259    packet_out = get_writeable_packet(conn, QUIC_RST_STREAM_SZ);
2260    if (!packet_out)
2261        return 0;
2262
2263    sz = conn->fc_conn.cn_pf->pf_gen_rst_frame(
2264                     packet_out->po_data + packet_out->po_data_sz,
2265                     lsquic_packet_out_avail(packet_out), stream_id,
2266                     0, 0x10 /* QUIC_PEER_GOING_AWAY */);
2267    if (sz < 0) {
2268        ABORT_ERROR("gen_rst_frame failed");
2269        return 0;
2270    }
2271    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2272    packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
2273    LSQ_DEBUG("generated standaloen RST_STREAM frame for stream %"PRIu32,
2274                                                                    stream_id);
2275    return 1;
2276}
2277
2278
2279static void
2280packetize_standalone_stream_resets (struct full_conn *conn)
2281{
2282    struct stream_id_to_reset *sitr;
2283
2284    while ((sitr = STAILQ_FIRST(&conn->fc_stream_ids_to_reset)))
2285        if (packetize_standalone_stream_reset(conn, sitr->sitr_stream_id))
2286        {
2287            STAILQ_REMOVE_HEAD(&conn->fc_stream_ids_to_reset, sitr_next);
2288            free(sitr);
2289        }
2290        else
2291            break;
2292}
2293
2294
2295static void
2296service_streams (struct full_conn *conn)
2297{
2298    struct lsquic_hash_elem *el;
2299    lsquic_stream_t *stream, *next;
2300    int n_our_destroyed = 0;
2301
2302    for (stream = TAILQ_FIRST(&conn->fc_pub.service_streams); stream; stream = next)
2303    {
2304        next = TAILQ_NEXT(stream, next_service_stream);
2305        if (stream->stream_flags & STREAM_ABORT_CONN)
2306            /* No need to unset this flag or remove this stream: the connection
2307             * is about to be aborted.
2308             */
2309            ABORT_ERROR("aborted due to error in stream %"PRIu32, stream->id);
2310        if (stream->stream_flags & STREAM_CALL_ONCLOSE)
2311            lsquic_stream_call_on_close(stream);
2312        if (stream->stream_flags & STREAM_FREE_STREAM)
2313        {
2314            n_our_destroyed += is_our_stream(conn, stream);
2315            TAILQ_REMOVE(&conn->fc_pub.service_streams, stream, next_service_stream);
2316            el = lsquic_hash_find(conn->fc_pub.all_streams, &stream->id, sizeof(stream->id));
2317            if (el)
2318                lsquic_hash_erase(conn->fc_pub.all_streams, el);
2319            conn_mark_stream_closed(conn, stream->id);
2320            SAVE_STREAM_HISTORY(conn, stream);
2321            lsquic_stream_destroy(stream);
2322        }
2323    }
2324
2325    if (either_side_going_away(conn))
2326        while (conn->fc_n_delayed_streams)
2327        {
2328            --conn->fc_n_delayed_streams;
2329            LSQ_DEBUG("goaway mode: delayed stream results in null ctor");
2330            (void) conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_new_stream(
2331                conn->fc_stream_ifs[STREAM_IF_STD].stream_if_ctx, NULL);
2332        }
2333    else
2334        while (n_our_destroyed && conn->fc_n_delayed_streams)
2335        {
2336            --n_our_destroyed;
2337            --conn->fc_n_delayed_streams;
2338            LSQ_DEBUG("creating delayed stream");
2339            if (!new_stream(conn, generate_stream_id(conn), SCF_CALL_ON_NEW))
2340            {
2341                ABORT_ERROR("%s: cannot create new stream: %s", __func__,
2342                                                            strerror(errno));
2343                break;
2344            }
2345            assert(count_streams(conn, 0) <= conn->fc_cfg.max_streams_out);
2346        }
2347}
2348
2349
2350static void
2351process_streams_read_events (struct full_conn *conn)
2352{
2353    lsquic_stream_t *stream;
2354    struct stream_prio_iter spi;
2355
2356    if (TAILQ_EMPTY(&conn->fc_pub.read_streams))
2357        return;
2358
2359    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.read_streams),
2360        TAILQ_LAST(&conn->fc_pub.read_streams, lsquic_streams_tailq),
2361        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_read_stream),
2362        STREAM_WANT_READ, conn->fc_conn.cn_cid, "read");
2363
2364    for (stream = lsquic_spi_first(&spi); stream;
2365                                            stream = lsquic_spi_next(&spi))
2366        lsquic_stream_dispatch_read_events(stream);
2367}
2368
2369
2370static void
2371maybe_conn_flush_headers_stream (struct full_conn *conn)
2372{
2373    lsquic_stream_t *stream;
2374
2375    if (conn->fc_flags & FC_HTTP)
2376    {
2377        stream = lsquic_headers_stream_get_stream(conn->fc_pub.hs);
2378        if (lsquic_stream_has_data_to_flush(stream))
2379            (void) lsquic_stream_flush(stream);
2380    }
2381}
2382
2383
2384static void
2385process_streams_write_events (struct full_conn *conn, int high_prio)
2386{
2387    lsquic_stream_t *stream;
2388    struct stream_prio_iter spi;
2389
2390    lsquic_spi_init(&spi, TAILQ_FIRST(&conn->fc_pub.write_streams),
2391        TAILQ_LAST(&conn->fc_pub.write_streams, lsquic_streams_tailq),
2392        (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_write_stream),
2393        STREAM_WANT_WRITE|STREAM_WANT_FLUSH, conn->fc_conn.cn_cid,
2394        high_prio ? "write-high" : "write-low");
2395
2396    if (high_prio)
2397        lsquic_spi_drop_non_high(&spi);
2398    else
2399        lsquic_spi_drop_high(&spi);
2400
2401    for (stream = lsquic_spi_first(&spi); stream && write_is_possible(conn);
2402                                            stream = lsquic_spi_next(&spi))
2403        lsquic_stream_dispatch_write_events(stream);
2404
2405    maybe_conn_flush_headers_stream(conn);
2406}
2407
2408
2409static void
2410process_hsk_stream_read_events (struct full_conn *conn)
2411{
2412    lsquic_stream_t *stream;
2413    TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
2414        if (LSQUIC_STREAM_HANDSHAKE == stream->id)
2415        {
2416            lsquic_stream_dispatch_read_events(stream);
2417            break;
2418        }
2419}
2420
2421
2422static void
2423process_hsk_stream_write_events (struct full_conn *conn)
2424{
2425    lsquic_stream_t *stream;
2426    TAILQ_FOREACH(stream, &conn->fc_pub.write_streams, next_write_stream)
2427        if (LSQUIC_STREAM_HANDSHAKE == stream->id)
2428        {
2429            lsquic_stream_dispatch_write_events(stream);
2430            break;
2431        }
2432}
2433
2434
2435#if 1
2436#   define verify_ack_frame(a, b, c)
2437#else
2438static void
2439verify_ack_frame (struct full_conn *conn, const unsigned char *buf, int bufsz)
2440{
2441    unsigned i;
2442    int parsed_len;
2443    struct ack_info *ack_info;
2444    const struct lsquic_packno_range *range;
2445    char ack_buf[512];
2446    unsigned buf_off = 0;
2447    int nw;
2448
2449    ack_info = conn->fc_pub.mm->acki;
2450    parsed_len = parse_ack_frame(buf, bufsz, ack_info);
2451    assert(parsed_len == bufsz);
2452
2453    for (range = lsquic_rechist_first(&conn->fc_rechist), i = 0; range;
2454            range = lsquic_rechist_next(&conn->fc_rechist), ++i)
2455    {
2456        assert(i < ack_info->n_ranges);
2457        assert(range->high == ack_info->ranges[i].high);
2458        assert(range->low == ack_info->ranges[i].low);
2459        if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
2460        {
2461            nw = snprintf(ack_buf + buf_off, sizeof(ack_buf) - buf_off,
2462                            "[%"PRIu64"-%"PRIu64"]", range->high, range->low);
2463            assert(nw >= 0);
2464            buf_off += nw;
2465        }
2466    }
2467    assert(i == ack_info->n_ranges);
2468    LSQ_DEBUG("Sent ACK frame %s", ack_buf);
2469}
2470
2471
2472#endif
2473
2474
2475static void
2476generate_ack_frame (struct full_conn *conn)
2477{
2478    lsquic_packet_out_t *packet_out;
2479    lsquic_time_t now;
2480    int has_missing, w;
2481
2482    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0);
2483    if (!packet_out)
2484    {
2485        ABORT_ERROR("cannot allocate packet: %s", strerror(errno));
2486        return;
2487    }
2488
2489    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
2490    now = lsquic_time_now();
2491    w = conn->fc_conn.cn_pf->pf_gen_ack_frame(
2492            packet_out->po_data + packet_out->po_data_sz,
2493            lsquic_packet_out_avail(packet_out),
2494            (gaf_rechist_first_f)        lsquic_rechist_first,
2495            (gaf_rechist_next_f)         lsquic_rechist_next,
2496            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
2497            &conn->fc_rechist, now, &has_missing, &packet_out->po_ack2ed);
2498    if (w < 0) {
2499        ABORT_ERROR("generating ACK frame failed: %d", errno);
2500        return;
2501    }
2502    EV_LOG_GENERATED_ACK_FRAME(LSQUIC_LOG_CONN_ID, conn->fc_conn.cn_pf,
2503                        packet_out->po_data + packet_out->po_data_sz, w);
2504    verify_ack_frame(conn, packet_out->po_data + packet_out->po_data_sz, w);
2505    lsquic_send_ctl_scheduled_ack(&conn->fc_send_ctl);
2506    packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK;
2507    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, w);
2508    packet_out->po_regen_sz += w;
2509    if (has_missing)
2510        conn->fc_flags |= FC_ACK_HAD_MISS;
2511    else
2512        conn->fc_flags &= ~FC_ACK_HAD_MISS;
2513    LSQ_DEBUG("Put %d bytes of ACK frame into packet on outgoing queue", w);
2514    if (conn->fc_conn.cn_version >= LSQVER_039 &&
2515            conn->fc_n_cons_unretx >= 20 &&
2516                !lsquic_send_ctl_have_outgoing_retx_frames(&conn->fc_send_ctl))
2517    {
2518        LSQ_DEBUG("schedule WINDOW_UPDATE frame after %u non-retx "
2519                                    "packets sent", conn->fc_n_cons_unretx);
2520        conn->fc_flags |= FC_SEND_WUF;
2521    }
2522}
2523
2524
2525static int
2526conn_ok_to_close (const struct full_conn *conn)
2527{
2528    assert(conn->fc_flags & FC_CLOSING);
2529    return !(conn->fc_flags & FC_SERVER)
2530        || (conn->fc_flags & FC_RECV_CLOSE)
2531        || (
2532               !lsquic_send_ctl_have_outgoing_stream_frames(&conn->fc_send_ctl)
2533            && lsquic_hash_count(conn->fc_pub.all_streams) == 0
2534            && lsquic_send_ctl_have_unacked_stream_frames(&conn->fc_send_ctl) == 0);
2535}
2536
2537
2538static enum tick_st
2539immediate_close (struct full_conn *conn)
2540{
2541    lsquic_packet_out_t *packet_out;
2542    const char *error_reason;
2543    unsigned error_code;
2544    int sz;
2545
2546    if (conn->fc_flags & (FC_TICK_CLOSE|FC_GOT_PRST))
2547        return TICK_CLOSE;
2548
2549    conn->fc_flags |= FC_TICK_CLOSE;
2550
2551    /* No reason to send anything that's been scheduled if connection is
2552     * being closed immedately.  This also ensures that packet numbers
2553     * sequence is always increasing.
2554     */
2555    lsquic_send_ctl_drop_scheduled(&conn->fc_send_ctl);
2556
2557    if ((conn->fc_flags & FC_TIMED_OUT) && conn->fc_settings->es_silent_close)
2558        return TICK_CLOSE;
2559
2560    packet_out = lsquic_send_ctl_new_packet_out(&conn->fc_send_ctl, 0);
2561    if (!packet_out)
2562    {
2563        LSQ_WARN("cannot allocate packet: %s", strerror(errno));
2564        return TICK_CLOSE;
2565    }
2566
2567    assert(conn->fc_flags & (FC_ERROR|FC_ABORTED|FC_TIMED_OUT));
2568    if (conn->fc_flags & FC_ERROR)
2569    {
2570        error_code = 0x01; /* QUIC_INTERNAL_ERROR */
2571        error_reason = "connection error";
2572    }
2573    else if (conn->fc_flags & FC_ABORTED)
2574    {
2575        error_code = 0x10; /* QUIC_PEER_GOING_AWAY */
2576        error_reason = "user aborted connection";
2577    }
2578    else if (conn->fc_flags & FC_TIMED_OUT)
2579    {
2580        error_code = 0x19; /* QUIC_NETWORK_IDLE_TIMEOUT */
2581        error_reason = "connection timed out";
2582    }
2583    else
2584    {
2585        error_code = 0x10; /* QUIC_PEER_GOING_AWAY */
2586        error_reason = NULL;
2587    }
2588
2589    lsquic_send_ctl_scheduled_one(&conn->fc_send_ctl, packet_out);
2590    sz = conn->fc_conn.cn_pf->pf_gen_connect_close_frame(
2591                     packet_out->po_data + packet_out->po_data_sz,
2592                     lsquic_packet_out_avail(packet_out), error_code,
2593                     error_reason, error_reason ? strlen(error_reason) : 0);
2594    if (sz < 0) {
2595        LSQ_WARN("%s failed", __func__);
2596        return TICK_CLOSE;
2597    }
2598    lsquic_send_ctl_incr_pack_sz(&conn->fc_send_ctl, packet_out, sz);
2599    packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
2600    LSQ_DEBUG("generated CONNECTION_CLOSE frame in its own packet");
2601    return TICK_SEND|TICK_CLOSE;
2602}
2603
2604
2605static int
2606write_is_possible (struct full_conn *conn)
2607{
2608    const lsquic_packet_out_t *packet_out;
2609
2610    packet_out = lsquic_send_ctl_last_scheduled(&conn->fc_send_ctl);
2611    return (packet_out && lsquic_packet_out_avail(packet_out) > 10)
2612        || lsquic_send_ctl_can_send(&conn->fc_send_ctl);
2613}
2614
2615
2616static enum tick_st
2617full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
2618{
2619    struct full_conn *conn = (struct full_conn *) lconn;
2620    int have_delayed_packets;
2621    unsigned n;
2622    int s;
2623    enum tick_st tick = 0;
2624
2625#define CLOSE_IF_NECESSARY() do {                                       \
2626    if (conn->fc_flags & FC_IMMEDIATE_CLOSE_FLAGS)                      \
2627    {                                                                   \
2628        tick |= immediate_close(conn);                         \
2629        goto end;                                                       \
2630    }                                                                   \
2631} while (0)
2632
2633#define RETURN_IF_OUT_OF_PACKETS() do {                                 \
2634    if (!lsquic_send_ctl_can_send(&conn->fc_send_ctl))                  \
2635    {                                                                   \
2636        if (0 == lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl))       \
2637        {                                                               \
2638            LSQ_DEBUG("used up packet allowance, quiet now (line %d)",  \
2639                __LINE__);                                              \
2640            tick |= TICK_QUIET;                                         \
2641        }                                                               \
2642        else                                                            \
2643        {                                                               \
2644            LSQ_DEBUG("used up packet allowance, sending now (line %d)",\
2645                __LINE__);                                              \
2646            tick |= TICK_SEND;                                          \
2647        }                                                               \
2648        goto end;                                                       \
2649    }                                                                   \
2650} while (0)
2651
2652#if FULL_CONN_STATS
2653    ++conn->fc_stats.n_ticks;
2654#endif
2655
2656    if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG)
2657        && conn->fc_mem_logged_last + 1000000 <= now)
2658    {
2659        conn->fc_mem_logged_last = now;
2660        LSQ_DEBUG("memory used: %zd bytes", calc_mem_used(conn));
2661    }
2662
2663    if (conn->fc_flags & FC_HAVE_SAVED_ACK)
2664    {
2665        (void) /* If there is an error, we'll fail shortly */
2666            process_saved_ack(conn, 0);
2667        conn->fc_flags &= ~FC_HAVE_SAVED_ACK;
2668    }
2669
2670    lsquic_send_ctl_tick(&conn->fc_send_ctl, now);
2671    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
2672    CLOSE_IF_NECESSARY();
2673
2674    if (!(conn->fc_flags & FC_SERVER))
2675    {
2676        lsquic_alarmset_unset(&conn->fc_alset, AL_PING);
2677        lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
2678    }
2679
2680    lsquic_alarmset_ring_expired(&conn->fc_alset, now);
2681    CLOSE_IF_NECESSARY();
2682
2683    /* To make things simple, only stream 1 is active until the handshake
2684     * has been completed.  This will be adjusted in the future: the client
2685     * does not want to wait if it has the server information.
2686     */
2687    if (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
2688        process_streams_read_events(conn);
2689    else
2690        process_hsk_stream_read_events(conn);
2691    CLOSE_IF_NECESSARY();
2692
2693    if (lsquic_send_ctl_pacer_blocked(&conn->fc_send_ctl))
2694        goto skip_write;
2695
2696    if (conn->fc_flags & FC_FIRST_TICK)
2697    {
2698        conn->fc_flags &= ~FC_FIRST_TICK;
2699        have_delayed_packets = 0;
2700    }
2701    else
2702        /* If there are any scheduled packets at this point, it means that
2703         * they were not sent during previous tick; in other words, they
2704         * are delayed.  When there are delayed packets, the only packet
2705         * we sometimes add is a packet with an ACK frame, and we add it
2706         * to the *front* of the queue.
2707         */
2708        have_delayed_packets = lsquic_send_ctl_maybe_squeeze_sched(
2709                                                    &conn->fc_send_ctl);
2710
2711    if ((conn->fc_flags & FC_ACK_QUEUED) ||
2712                            lsquic_send_ctl_lost_ack(&conn->fc_send_ctl))
2713    {
2714        if (have_delayed_packets)
2715            lsquic_send_ctl_reset_packnos(&conn->fc_send_ctl);
2716
2717        /* ACK frame generation fails with an error if it does not fit into
2718         * a single packet (it always should fit).
2719         */
2720        generate_ack_frame(conn);
2721        CLOSE_IF_NECESSARY();
2722        reset_ack_state(conn);
2723
2724        /* Try to send STOP_WAITING frame at the same time we send an ACK
2725         * This follows reference implementation.
2726         */
2727        if (!(conn->fc_flags & FC_NSTP))
2728            conn->fc_flags |= FC_SEND_STOP_WAITING;
2729
2730        if (have_delayed_packets)
2731        {
2732            if (conn->fc_flags & FC_SEND_STOP_WAITING)
2733            {
2734                /* TODO: ensure that STOP_WAITING frame is in the same packet
2735                 * as the ACK frame in delayed packet mode.
2736                 */
2737                generate_stop_waiting_frame(conn);
2738                CLOSE_IF_NECESSARY();
2739            }
2740            lsquic_send_ctl_ack_to_front(&conn->fc_send_ctl);
2741        }
2742    }
2743
2744    if (have_delayed_packets)
2745    {
2746        /* The reason for not adding STOP_WAITING and other frames below
2747         * to the packet carrying ACK frame generated when there are delayed
2748         * packets is so that if the ACK packet itself is delayed, it can be
2749         * dropped and replaced by new ACK packet.  This way, we are never
2750         * more than 1 packet over CWND.
2751         */
2752        tick |= TICK_SEND;
2753        goto end;
2754    }
2755
2756    /* Try to fit any of the following three frames -- STOP_WAITING,
2757     * WINDOW_UPDATE, and GOAWAY -- before checking if we have run
2758     * out of packets.  If either of them does not fit, it will be
2759     * tried next time around.
2760     */
2761    if (conn->fc_flags & FC_SEND_STOP_WAITING)
2762    {
2763        generate_stop_waiting_frame(conn);
2764        CLOSE_IF_NECESSARY();
2765    }
2766
2767    if (lsquic_cfcw_fc_offsets_changed(&conn->fc_pub.cfcw) ||
2768                                (conn->fc_flags & FC_SEND_WUF))
2769    {
2770        conn->fc_flags |= FC_SEND_WUF;
2771        generate_wuf_conn(conn);
2772        CLOSE_IF_NECESSARY();
2773    }
2774
2775    if (conn->fc_flags & FC_SEND_GOAWAY)
2776    {
2777        generate_goaway_frame(conn);
2778        CLOSE_IF_NECESSARY();
2779    }
2780
2781    n = lsquic_send_ctl_reschedule_packets(&conn->fc_send_ctl);
2782    if (n > 0)
2783        CLOSE_IF_NECESSARY();
2784
2785    RETURN_IF_OUT_OF_PACKETS();
2786
2787    if (conn->fc_conn.cn_flags & LSCONN_SEND_BLOCKED)
2788    {
2789        if (generate_blocked_frame(conn, 0))
2790            conn->fc_conn.cn_flags &= ~LSCONN_SEND_BLOCKED;
2791        else
2792            RETURN_IF_OUT_OF_PACKETS();
2793    }
2794
2795    if (!STAILQ_EMPTY(&conn->fc_stream_ids_to_reset))
2796    {
2797        packetize_standalone_stream_resets(conn);
2798        CLOSE_IF_NECESSARY();
2799    }
2800
2801    if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
2802    {
2803        process_streams_ready_to_send(conn);
2804        CLOSE_IF_NECESSARY();
2805    }
2806
2807    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 0);
2808    if (!(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE))
2809    {
2810        process_hsk_stream_write_events(conn);
2811        goto end_write;
2812    }
2813
2814    maybe_conn_flush_headers_stream(conn);
2815
2816    s = lsquic_send_ctl_schedule_buffered(&conn->fc_send_ctl, BPT_HIGHEST_PRIO);
2817    conn->fc_flags |= (s < 0) << FC_BIT_ERROR;
2818    if (!write_is_possible(conn))
2819        goto end_write;
2820
2821    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams))
2822    {
2823        process_streams_write_events(conn, 1);
2824        if (!write_is_possible(conn))
2825            goto end_write;
2826    }
2827
2828    s = lsquic_send_ctl_schedule_buffered(&conn->fc_send_ctl, BPT_OTHER_PRIO);
2829    conn->fc_flags |= (s < 0) << FC_BIT_ERROR;
2830    if (!write_is_possible(conn))
2831        goto end_write;
2832
2833    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams))
2834        process_streams_write_events(conn, 0);
2835
2836  end_write:
2837
2838  skip_write:
2839    service_streams(conn);
2840    CLOSE_IF_NECESSARY();
2841
2842    RETURN_IF_OUT_OF_PACKETS();
2843
2844    if ((conn->fc_flags & FC_CLOSING) && conn_ok_to_close(conn))
2845    {
2846        LSQ_DEBUG("connection is OK to close");
2847        /* This is normal termination sequence.
2848         *
2849         * Generate CONNECTION_CLOSE frame if we are responding to one, have
2850         * packets scheduled to send, or silent close flag is not set.
2851         */
2852        conn->fc_flags |= FC_TICK_CLOSE;
2853        if ((conn->fc_flags & FC_RECV_CLOSE) ||
2854                0 != lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) ||
2855                                        !conn->fc_settings->es_silent_close)
2856        {
2857            generate_connection_close_packet(conn);
2858            tick |= TICK_SEND|TICK_CLOSE;
2859        }
2860        else
2861            tick |= TICK_CLOSE;
2862        goto end;
2863    }
2864
2865    if (0 == lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl))
2866    {
2867        if (conn->fc_flags & FC_SEND_PING)
2868        {
2869            conn->fc_flags &= ~FC_SEND_PING;
2870            generate_ping_frame(conn);
2871            CLOSE_IF_NECESSARY();
2872            assert(lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) != 0);
2873        }
2874        else
2875        {
2876            tick |= TICK_QUIET;
2877            goto end;
2878        }
2879    }
2880    else if (!(conn->fc_flags & FC_SERVER))
2881    {
2882        lsquic_alarmset_unset(&conn->fc_alset, AL_PING);
2883        lsquic_send_ctl_sanity_check(&conn->fc_send_ctl);
2884        conn->fc_flags &= ~FC_SEND_PING;   /* It may have rung */
2885    }
2886
2887    now = lsquic_time_now();
2888    lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
2889                                now + conn->fc_settings->es_idle_conn_to);
2890
2891    /* From the spec:
2892     *  " The PING frame should be used to keep a connection alive when
2893     *  " a stream is open.
2894     */
2895    if (0 == (conn->fc_flags & FC_SERVER) &&
2896                                        lsquic_hash_count(conn->fc_pub.all_streams) > 0)
2897        lsquic_alarmset_set(&conn->fc_alset, AL_PING, now + TIME_BETWEEN_PINGS);
2898
2899    tick |= TICK_SEND;
2900
2901  end:
2902    lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 1);
2903    return tick;
2904}
2905
2906
2907static void
2908full_conn_ci_packet_in (lsquic_conn_t *lconn, lsquic_packet_in_t *packet_in)
2909{
2910    struct full_conn *conn = (struct full_conn *) lconn;
2911
2912    lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
2913                packet_in->pi_received + conn->fc_settings->es_idle_conn_to);
2914    if (0 == (conn->fc_flags & FC_ERROR))
2915        if (0 != process_incoming_packet(conn, packet_in))
2916            conn->fc_flags |= FC_ERROR;
2917}
2918
2919
2920static lsquic_packet_out_t *
2921full_conn_ci_next_packet_to_send (lsquic_conn_t *lconn)
2922{
2923    struct full_conn *conn = (struct full_conn *) lconn;
2924    return lsquic_send_ctl_next_packet_to_send(&conn->fc_send_ctl);
2925}
2926
2927
2928static void
2929full_conn_ci_packet_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_out)
2930{
2931    struct full_conn *conn = (struct full_conn *) lconn;
2932    int s;
2933
2934    recent_packet_hist_new(conn, 1, packet_out->po_sent);
2935    recent_packet_hist_frames(conn, 1, packet_out->po_frame_types);
2936
2937    if (packet_out->po_frame_types & QFRAME_RETRANSMITTABLE_MASK)
2938    {
2939        conn->fc_n_cons_unretx = 0;
2940        lsquic_alarmset_set(&conn->fc_alset, AL_IDLE,
2941                    packet_out->po_sent + conn->fc_settings->es_idle_conn_to);
2942    }
2943    else
2944        ++conn->fc_n_cons_unretx;
2945    s = lsquic_send_ctl_sent_packet(&conn->fc_send_ctl, packet_out, 1);
2946    if (s != 0)
2947        ABORT_ERROR("sent packet failed: %s", strerror(errno));
2948#if FULL_CONN_STATS
2949    ++conn->fc_stats.n_packets_out;
2950#endif
2951}
2952
2953
2954static void
2955full_conn_ci_packet_not_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_out)
2956{
2957    struct full_conn *conn = (struct full_conn *) lconn;
2958    lsquic_send_ctl_delayed_one(&conn->fc_send_ctl, packet_out);
2959}
2960
2961
2962static void
2963full_conn_ci_handshake_ok (lsquic_conn_t *lconn)
2964{
2965    struct full_conn *conn = (struct full_conn *) lconn;
2966    LSQ_DEBUG("handshake reportedly done");
2967    lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
2968    if (0 == apply_peer_settings(conn))
2969        lconn->cn_flags |= LSCONN_HANDSHAKE_DONE;
2970    else
2971        conn->fc_flags |= FC_ERROR;
2972}
2973
2974
2975static void
2976full_conn_ci_handshake_failed (lsquic_conn_t *lconn)
2977{
2978    struct full_conn *conn = (struct full_conn *) lconn;
2979    LSQ_DEBUG("handshake failed");
2980    lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
2981    conn->fc_flags |= FC_HSK_FAILED;
2982}
2983
2984
2985void
2986lsquic_conn_abort (lsquic_conn_t *lconn)
2987{
2988    struct full_conn *conn = (struct full_conn *) lconn;
2989    LSQ_INFO("User aborted connection");
2990    conn->fc_flags |= FC_ABORTED;
2991}
2992
2993
2994void
2995lsquic_conn_close (lsquic_conn_t *lconn)
2996{
2997    struct full_conn *conn = (struct full_conn *) lconn;
2998    lsquic_stream_t *stream;
2999    struct lsquic_hash_elem *el;
3000
3001    if (!(conn->fc_flags & FC_CLOSING))
3002    {
3003        for (el = lsquic_hash_first(conn->fc_pub.all_streams); el;
3004                                     el = lsquic_hash_next(conn->fc_pub.all_streams))
3005        {
3006            stream = lsquic_hashelem_getdata(el);
3007            lsquic_stream_shutdown_internal(stream);
3008        }
3009        conn->fc_flags |= FC_CLOSING;
3010        if (!(conn->fc_flags & FC_GOAWAY_SENT))
3011            conn->fc_flags |= FC_SEND_GOAWAY;
3012    }
3013}
3014
3015
3016void
3017lsquic_conn_going_away (lsquic_conn_t *lconn)
3018{
3019    struct full_conn *conn = (struct full_conn *) lconn;
3020    if (!(conn->fc_flags & (FC_CLOSING|FC_GOING_AWAY)))
3021    {
3022        LSQ_INFO("connection marked as going away");
3023        assert(!(conn->fc_flags & FC_SEND_GOAWAY));
3024        conn->fc_flags |= FC_GOING_AWAY;
3025        if (!(conn->fc_flags & FC_GOAWAY_SENT))
3026            conn->fc_flags |= FC_SEND_GOAWAY;
3027    }
3028}
3029
3030
3031/* Find stream when stream ID is read from something other than a STREAM
3032 * frame.  If the stream cannot be found or created, the connection is
3033 * aborted.
3034 */
3035#if __GNUC__
3036__attribute__((nonnull(4)))
3037#endif
3038static lsquic_stream_t *
3039find_stream_on_non_stream_frame (struct full_conn *conn, uint32_t stream_id,
3040                                 enum stream_ctor_flags stream_ctor_flags,
3041                                 const char *what)
3042{
3043    lsquic_stream_t *stream;
3044    unsigned in_count;
3045
3046    stream = find_stream_by_id(conn, stream_id);
3047    if (stream)
3048        return stream;
3049
3050    if (conn_is_stream_closed(conn, stream_id))
3051    {
3052        LSQ_DEBUG("drop incoming %s for closed stream %u", what, stream_id);
3053        return NULL;
3054    }
3055
3056    /* XXX It seems that if we receive a priority frame for a stream, the
3057     *     stream should exist or have existed at some point.  Thus, if
3058     *     it does not exist, we should return an error here.
3059     */
3060
3061    if (!is_peer_initiated(conn, stream_id))
3062    {
3063        ABORT_ERROR("frame for never-initiated stream (push promise?)");
3064        return NULL;
3065    }
3066
3067    in_count = count_streams(conn, 1);
3068    LSQ_DEBUG("number of peer-initiated streams: %u", in_count);
3069    if (in_count >= conn->fc_cfg.max_streams_in)
3070    {
3071        ABORT_ERROR("incoming %s for stream %u would exceed "
3072            "limit: %u", what, stream_id, conn->fc_cfg.max_streams_in);
3073        return NULL;
3074    }
3075    if ((conn->fc_flags & FC_GOING_AWAY) &&
3076        stream_id > conn->fc_max_peer_stream_id)
3077    {
3078        maybe_schedule_reset_for_stream(conn, stream_id);
3079        LSQ_DEBUG("going away: reset new incoming stream %u", stream_id);
3080        return NULL;
3081    }
3082
3083    stream = new_stream(conn, stream_id, stream_ctor_flags);
3084    if (!stream)
3085    {
3086        ABORT_ERROR("cannot create new stream: %s", strerror(errno));
3087        return NULL;
3088    }
3089    if (stream_id > conn->fc_max_peer_stream_id)
3090        conn->fc_max_peer_stream_id = stream_id;
3091
3092    return stream;
3093}
3094
3095
3096static void
3097headers_stream_on_conn_error (void *ctx)
3098{
3099    struct full_conn *conn = ctx;
3100    ABORT_ERROR("connection error reported by HEADERS stream");
3101}
3102
3103
3104static void
3105headers_stream_on_stream_error (void *ctx, uint32_t stream_id)
3106{
3107    struct full_conn *conn = ctx;
3108    lsquic_stream_t *stream;
3109
3110    stream = find_stream_on_non_stream_frame(conn, stream_id, SCF_CALL_ON_NEW,
3111                                             "error");
3112    if (stream)
3113    {
3114        LSQ_DEBUG("resetting stream %u due to error", stream_id);
3115        /* We use code 1, which is QUIC_INTERNAL_ERROR (see
3116         * [draft-hamilton-quic-transport-protocol-01], Section 10), for all
3117         * errors.  There does not seem to be a good reason to figure out
3118         * and send more specific error codes.
3119         */
3120        lsquic_stream_reset_ext(stream, 1, 0);
3121    }
3122}
3123
3124
3125static void
3126headers_stream_on_enable_push (void *ctx, int enable_push)
3127{
3128    struct full_conn *conn = ctx;
3129    if (0 == enable_push)
3130    {
3131        LSQ_DEBUG("server push %d -> 0", !!(conn->fc_flags & FC_SUPPORT_PUSH));
3132        conn->fc_flags &= ~FC_SUPPORT_PUSH;
3133    }
3134    else if (conn->fc_settings->es_support_push)
3135    {
3136        LSQ_DEBUG("server push %d -> 1", !!(conn->fc_flags & FC_SUPPORT_PUSH));
3137        conn->fc_flags |= FC_SUPPORT_PUSH;
3138    }
3139    else
3140        LSQ_INFO("not enabling server push that's disabled in engine settings");
3141}
3142
3143
3144static void
3145headers_stream_on_incoming_headers (void *ctx, struct uncompressed_headers *uh)
3146{
3147    struct full_conn *conn = ctx;
3148    lsquic_stream_t *stream;
3149
3150    LSQ_DEBUG("incoming headers for stream %u", uh->uh_stream_id);
3151
3152    stream = find_stream_on_non_stream_frame(conn, uh->uh_stream_id, 0,
3153                                             "headers");
3154    if (!stream)
3155    {
3156        free(uh);
3157        return;
3158    }
3159
3160    if (0 != lsquic_stream_uh_in(stream, uh))
3161    {
3162        ABORT_ERROR("stream %u refused incoming headers", uh->uh_stream_id);
3163        free(uh);
3164    }
3165
3166    if (!(stream->stream_flags & STREAM_ONNEW_DONE))
3167        lsquic_stream_call_on_new(stream);
3168}
3169
3170
3171static void
3172headers_stream_on_push_promise (void *ctx, struct uncompressed_headers *uh)
3173{
3174    struct full_conn *conn = ctx;
3175    lsquic_stream_t *stream;
3176
3177    assert(!(conn->fc_flags & FC_SERVER));
3178
3179    LSQ_DEBUG("push promise for stream %u in response to %u",
3180                                    uh->uh_oth_stream_id, uh->uh_stream_id);
3181
3182    if (0 == (uh->uh_stream_id & 1)     ||
3183        0 != (uh->uh_oth_stream_id & 1))
3184    {
3185        ABORT_ERROR("invalid push promise stream IDs: %u, %u",
3186                                    uh->uh_oth_stream_id, uh->uh_stream_id);
3187        free(uh);
3188        return;
3189    }
3190
3191    if (!(conn_is_stream_closed(conn, uh->uh_stream_id) ||
3192          find_stream_by_id(conn, uh->uh_stream_id)))
3193    {
3194        ABORT_ERROR("invalid push promise original stream ID %u never "
3195                    "initiated", uh->uh_stream_id);
3196        free(uh);
3197        return;
3198    }
3199
3200    if (conn_is_stream_closed(conn, uh->uh_oth_stream_id) ||
3201        find_stream_by_id(conn, uh->uh_oth_stream_id))
3202    {
3203        ABORT_ERROR("invalid promised stream ID %u already used",
3204                                                        uh->uh_oth_stream_id);
3205        free(uh);
3206        return;
3207    }
3208
3209    stream = new_stream_ext(conn, uh->uh_oth_stream_id, STREAM_IF_STD,
3210                SCF_DI_AUTOSWITCH|(conn->fc_enpub->enp_settings.es_rw_once ?
3211                                                        SCF_DISP_RW_ONCE : 0));
3212    if (!stream)
3213    {
3214        ABORT_ERROR("cannot create stream: %s", strerror(errno));
3215        free(uh);
3216        return;
3217    }
3218    lsquic_stream_push_req(stream, uh);
3219    lsquic_stream_call_on_new(stream);
3220    return;
3221}
3222
3223
3224static void
3225headers_stream_on_priority (void *ctx, uint32_t stream_id, int exclusive,
3226                            uint32_t dep_stream_id, unsigned weight)
3227{
3228    struct full_conn *conn = ctx;
3229    lsquic_stream_t *stream;
3230    LSQ_DEBUG("got priority frame for stream %u: (ex: %d; dep stream: %u; "
3231                  "weight: %u)", stream_id, exclusive, dep_stream_id, weight);
3232    stream = find_stream_on_non_stream_frame(conn, stream_id, SCF_CALL_ON_NEW,
3233                                             "priority");
3234    if (stream)
3235        lsquic_stream_set_priority_internal(stream, weight);
3236}
3237
3238
3239int lsquic_conn_is_push_enabled(lsquic_conn_t *c)
3240{
3241    return ((struct full_conn *)c)->fc_flags & FC_SUPPORT_PUSH;
3242}
3243
3244
3245lsquic_conn_ctx_t *
3246lsquic_conn_get_ctx (const lsquic_conn_t *lconn)
3247{
3248    struct full_conn *const conn = (struct full_conn *) lconn;
3249    return conn->fc_conn_ctx;
3250}
3251
3252
3253void lsquic_conn_set_ctx (lsquic_conn_t *lconn, lsquic_conn_ctx_t *ctx)
3254{
3255    struct full_conn *const conn = (struct full_conn *) lconn;
3256    conn->fc_conn_ctx = ctx;
3257}
3258
3259
3260enum LSQUIC_CONN_STATUS
3261lsquic_conn_status (lsquic_conn_t *lconn, char *errbuf, size_t bufsz)
3262{
3263    struct full_conn *const conn = (struct full_conn *) lconn;
3264    size_t n;
3265
3266    /* Test the common case first: */
3267    if (!(conn->fc_flags & (FC_ERROR
3268                           |FC_TIMED_OUT
3269                           |FC_ABORTED
3270                           |FC_GOT_PRST
3271                           |FC_HSK_FAILED
3272                           |FC_CLOSING
3273                           |FC_GOING_AWAY)))
3274    {
3275        if (lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
3276            return LSCONN_ST_CONNECTED;
3277        else
3278            return LSCONN_ST_HSK_IN_PROGRESS;
3279    }
3280
3281    if (errbuf && bufsz)
3282    {
3283        if (conn->fc_errmsg)
3284        {
3285            n = bufsz < MAX_ERRMSG ? bufsz : MAX_ERRMSG;
3286            strncpy(errbuf, conn->fc_errmsg, n);
3287            errbuf[n - 1] = '\0';
3288        }
3289        else
3290            errbuf[0] = '\0';
3291    }
3292
3293    if (conn->fc_flags & FC_ERROR)
3294        return LSCONN_ST_ERROR;
3295    if (conn->fc_flags & FC_TIMED_OUT)
3296        return LSCONN_ST_TIMED_OUT;
3297    if (conn->fc_flags & FC_ABORTED)
3298        return LSCONN_ST_USER_ABORTED;
3299    if (conn->fc_flags & FC_GOT_PRST)
3300        return LSCONN_ST_RESET;
3301    if (conn->fc_flags & FC_HSK_FAILED)
3302        return LSCONN_ST_HSK_FAILURE;
3303    if (conn->fc_flags & FC_CLOSING)
3304        return LSCONN_ST_CLOSED;
3305    assert(conn->fc_flags & FC_GOING_AWAY);
3306    return LSCONN_ST_GOING_AWAY;
3307}
3308
3309
3310static int
3311full_conn_ci_is_tickable (lsquic_conn_t *lconn)
3312{
3313    struct full_conn *conn = (struct full_conn *) lconn;
3314    const struct lsquic_stream *stream;
3315    int can_send;
3316
3317    /* This caches the value so that we only need to call the function once */
3318#define CAN_SEND() \
3319    (can_send >= 0 ? can_send : \
3320        (can_send = lsquic_send_ctl_can_send(&conn->fc_send_ctl)))
3321
3322    if (lsquic_send_ctl_has_buffered(&conn->fc_send_ctl))
3323        return 1;
3324
3325    if (!TAILQ_EMPTY(&conn->fc_pub.service_streams))
3326        return 1;
3327
3328    can_send = -1;
3329    if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams) && CAN_SEND())
3330        return 1;
3331
3332    TAILQ_FOREACH(stream, &conn->fc_pub.read_streams, next_read_stream)
3333        if (lsquic_stream_readable(stream))
3334            return 1;
3335
3336    if (!TAILQ_EMPTY(&conn->fc_pub.write_streams) && CAN_SEND())
3337    {
3338        TAILQ_FOREACH(stream, &conn->fc_pub.write_streams, next_write_stream)
3339            if (lsquic_stream_write_avail(stream))
3340                return 1;
3341    }
3342
3343#undef CAN_SEND
3344
3345    return 0;
3346}
3347
3348
3349static lsquic_time_t
3350full_conn_ci_next_tick_time (lsquic_conn_t *lconn)
3351{
3352    struct full_conn *conn = (struct full_conn *) lconn;
3353    lsquic_time_t alarm_time, pacer_time;
3354
3355    alarm_time = lsquic_alarmset_mintime(&conn->fc_alset);
3356    pacer_time = lsquic_send_ctl_next_pacer_time(&conn->fc_send_ctl);
3357
3358    if (alarm_time && pacer_time)
3359    {
3360        if (alarm_time < pacer_time)
3361            return alarm_time;
3362        else
3363            return pacer_time;
3364    }
3365    else if (alarm_time)
3366        return alarm_time;
3367    else
3368        return pacer_time;
3369}
3370
3371
3372static const struct headers_stream_callbacks headers_callbacks =
3373{
3374    .hsc_on_headers      = headers_stream_on_incoming_headers,
3375    .hsc_on_push_promise = headers_stream_on_push_promise,
3376    .hsc_on_priority     = headers_stream_on_priority,
3377    .hsc_on_stream_error = headers_stream_on_stream_error,
3378    .hsc_on_conn_error   = headers_stream_on_conn_error,
3379    .hsc_on_enable_push  = headers_stream_on_enable_push,
3380};
3381
3382static const struct headers_stream_callbacks *headers_callbacks_ptr = &headers_callbacks;
3383
3384static const struct conn_iface full_conn_iface = {
3385    .ci_destroy              =  full_conn_ci_destroy,
3386    .ci_handshake_failed     =  full_conn_ci_handshake_failed,
3387    .ci_handshake_ok         =  full_conn_ci_handshake_ok,
3388    .ci_is_tickable          =  full_conn_ci_is_tickable,
3389    .ci_next_packet_to_send  =  full_conn_ci_next_packet_to_send,
3390    .ci_next_tick_time       =  full_conn_ci_next_tick_time,
3391    .ci_packet_in            =  full_conn_ci_packet_in,
3392    .ci_packet_not_sent      =  full_conn_ci_packet_not_sent,
3393    .ci_packet_sent          =  full_conn_ci_packet_sent,
3394    .ci_tick                 =  full_conn_ci_tick,
3395};
3396
3397static const struct conn_iface *full_conn_iface_ptr = &full_conn_iface;
3398