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