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