lsquic_mini_conn_ietf.c revision f2a7fa84
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_mini_conn_ietf.c -- Mini connection used by the IETF QUIC
4 */
5
6#include <assert.h>
7#include <errno.h>
8#include <inttypes.h>
9#include <stddef.h>
10#include <stdint.h>
11#include <string.h>
12#include <sys/queue.h>
13#include <stdlib.h>
14
15#include "lsquic.h"
16#include "lsquic_int_types.h"
17#include "lsquic_sizes.h"
18#include "lsquic_hash.h"
19#include "lsquic_conn.h"
20#include "lsquic_mm.h"
21#include "lsquic_malo.h"
22#include "lsquic_engine_public.h"
23#include "lsquic_packet_common.h"
24#include "lsquic_packet_in.h"
25#include "lsquic_packet_out.h"
26#include "lsquic_parse.h"
27#include "lsquic_rtt.h"
28#include "lsquic_util.h"
29#include "lsquic_enc_sess.h"
30#include "lsquic_mini_conn_ietf.h"
31#include "lsquic_ev_log.h"
32#include "lsquic_trans_params.h"
33#include "lsquic_ietf.h"
34#include "lsquic_packet_ietf.h"
35#include "lsquic_attq.h"
36#include "lsquic_alarmset.h"
37
38#define LSQUIC_LOGGER_MODULE LSQLM_MINI_CONN
39#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(&conn->imc_conn)
40#include "lsquic_logger.h"
41
42#define MIN(a, b) ((a) < (b) ? (a) : (b))
43#define MAX(a, b) ((a) > (b) ? (a) : (b))
44
45static const struct conn_iface mini_conn_ietf_iface;
46
47static unsigned highest_bit_set (unsigned long long);
48
49
50static const enum header_type el2hety[] =
51{
52    [ENC_LEV_INIT]  = HETY_HANDSHAKE,
53    [ENC_LEV_CLEAR] = HETY_INITIAL,
54    [ENC_LEV_FORW]  = HETY_NOT_SET,
55    [ENC_LEV_EARLY] = 0,    /* Invalid */
56};
57
58
59static void
60imico_destroy_packet (struct ietf_mini_conn *conn,
61                                        struct lsquic_packet_out *packet_out)
62{
63    lsquic_packet_out_destroy(packet_out, conn->imc_enpub,
64                                                conn->imc_path.np_peer_ctx);
65}
66
67
68int
69lsquic_mini_conn_ietf_ecn_ok (const struct ietf_mini_conn *conn)
70{
71    packno_set_t acked;
72
73    /* First flight has only Initial and Handshake packets */
74    acked = conn->imc_acked_packnos[PNS_INIT]
75          | conn->imc_acked_packnos[PNS_HSK]
76          ;
77    return 0 != (conn->imc_ecn_packnos & acked);
78}
79
80
81#define imico_ecn_ok lsquic_mini_conn_ietf_ecn_ok
82
83
84static enum ecn
85imico_get_ecn (struct ietf_mini_conn *conn)
86{
87    if (!conn->imc_enpub->enp_settings.es_ecn)
88        return ECN_NOT_ECT;
89    else if (!conn->imc_sent_packnos /* We set ECT0 in first flight */
90                                                    || imico_ecn_ok(conn))
91        return ECN_ECT0;
92    else
93        return ECN_NOT_ECT;
94}
95
96
97static struct lsquic_packet_out *
98imico_get_packet_out (struct ietf_mini_conn *conn,
99                                    enum header_type header_type, size_t need)
100{
101    struct lsquic_packet_out *packet_out;
102    enum ecn ecn;
103
104    if (need)
105        TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next)
106            if (!(packet_out->po_flags & PO_SENT)
107                    && packet_out->po_header_type == header_type
108                    && lsquic_packet_out_avail(packet_out) >= need)
109                return packet_out;
110
111    if (conn->imc_next_packno >= MAX_PACKETS)
112    {
113        LSQ_DEBUG("ran out of outgoing packet numbers, won't allocate packet");
114        return NULL;
115    }
116
117    packet_out = lsquic_packet_out_new(&conn->imc_enpub->enp_mm, NULL, 1,
118            &conn->imc_conn, IQUIC_PACKNO_LEN_1, NULL, NULL, &conn->imc_path);
119    if (!packet_out)
120    {
121        LSQ_WARN("could not allocate packet: %s", strerror(errno));
122        return NULL;
123    }
124
125    packet_out->po_header_type = header_type;
126    packet_out->po_packno = conn->imc_next_packno++;
127    packet_out->po_flags |= PO_MINI;
128    lsquic_packet_out_set_pns(packet_out, lsquic_hety2pns[header_type]);
129    ecn = imico_get_ecn(conn);
130    packet_out->po_lflags |= ecn << POECN_SHIFT;
131    TAILQ_INSERT_TAIL(&conn->imc_packets_out, packet_out, po_next);
132    packet_out->po_loss_chain = packet_out;
133    return packet_out;
134}
135
136
137static struct ietf_mini_conn *
138cryst_get_conn (const struct mini_crypto_stream *cryst)
139{
140    return (void *)
141        ((unsigned char *) (cryst - cryst->mcs_enc_level)
142                        - offsetof(struct ietf_mini_conn, imc_streams));
143}
144
145
146struct msg_ctx
147{
148    const unsigned char       *buf;
149    const unsigned char *const end;
150};
151
152
153static size_t
154read_from_msg_ctx (void *ctx, void *buf, size_t len)
155{
156    struct msg_ctx *msg_ctx = ctx;
157    if (len > (uintptr_t) (msg_ctx->end - msg_ctx->buf))
158        len = msg_ctx->end - msg_ctx->buf;
159    memcpy(buf, msg_ctx->buf, len);
160    msg_ctx->buf += len;
161    return len;
162}
163
164
165static ssize_t
166imico_stream_write (void *stream, const void *bufp, size_t bufsz)
167{
168    struct mini_crypto_stream *const cryst = stream;
169    struct ietf_mini_conn *const conn = cryst_get_conn(cryst);
170    struct lsquic_conn *const lconn = &conn->imc_conn;
171    const struct parse_funcs *const pf = lconn->cn_pf;
172    struct msg_ctx msg_ctx = { bufp, (unsigned char *) bufp + bufsz, };
173    struct lsquic_packet_out *packet_out;
174    size_t header_sz, need;
175    const unsigned char *p;
176    int len;
177
178    if (PNS_INIT == lsquic_enclev2pns[ cryst->mcs_enc_level ]
179                                        && (conn->imc_flags & IMC_IGNORE_INIT))
180    {
181        LSQ_WARN("trying to write at the ignored Initial level");
182        return bufsz;
183    }
184
185    while (msg_ctx.buf < msg_ctx.end)
186    {
187        header_sz = lconn->cn_pf->pf_calc_crypto_frame_header_sz(
188                            cryst->mcs_write_off, msg_ctx.end - msg_ctx.buf);
189        need = header_sz + 1;
190        packet_out = imico_get_packet_out(conn,
191                                        el2hety[ cryst->mcs_enc_level ], need);
192        if (!packet_out)
193            return -1;
194
195        p = msg_ctx.buf;
196        len = pf->pf_gen_crypto_frame(packet_out->po_data + packet_out->po_data_sz,
197                    lsquic_packet_out_avail(packet_out), cryst->mcs_write_off,
198                    msg_ctx.end - msg_ctx.buf, read_from_msg_ctx, &msg_ctx);
199        if (len < 0)
200            return len;
201        EV_LOG_GENERATED_CRYPTO_FRAME(LSQUIC_LOG_CONN_ID, pf,
202                                packet_out->po_data + packet_out->po_data_sz, len);
203        packet_out->po_data_sz += len;
204        packet_out->po_frame_types |= 1 << QUIC_FRAME_CRYPTO;
205        packet_out->po_flags |= PO_HELLO;
206        cryst->mcs_write_off += msg_ctx.buf - p;
207    }
208
209    assert(msg_ctx.buf == msg_ctx.end);
210    return bufsz;
211}
212
213
214static int
215imico_stream_flush (void *stream)
216{
217    return 0;
218}
219
220
221static struct stream_frame *
222imico_find_stream_frame (const struct ietf_mini_conn *conn,
223                                enum enc_level enc_level, unsigned read_off)
224{
225    struct stream_frame *frame;
226
227    if (conn->imc_last_in.frame && enc_level == conn->imc_last_in.enc_level
228            && read_off == DF_ROFF(conn->imc_last_in.frame))
229        return conn->imc_last_in.frame;
230
231    TAILQ_FOREACH(frame, &conn->imc_crypto_frames, next_frame)
232        if (enc_level == frame->stream_id && read_off == DF_ROFF(frame))
233            return frame;
234
235    return NULL;
236}
237
238
239static void
240imico_read_chlo_size (struct ietf_mini_conn *conn, const unsigned char *buf,
241                                                                    size_t sz)
242{
243    const unsigned char *const end = buf + sz;
244
245    assert(conn->imc_streams[ENC_LEV_CLEAR].mcs_read_off < 4);
246    switch (conn->imc_streams[ENC_LEV_CLEAR].mcs_read_off)
247    {
248    case 0:
249        if (buf == end)
250            return;
251        if (*buf != 1)
252        {
253            LSQ_DEBUG("Does not begin with ClientHello");
254            conn->imc_flags |= IMC_ERROR;
255            return;
256        }
257        ++buf;
258        /* fall-through */
259    case 1:
260        if (buf == end)
261            return;
262        if (*buf != 0)
263        {
264            LSQ_DEBUG("ClientHello larger than 16K");
265            conn->imc_flags |= IMC_ERROR;
266            return;
267        }
268        ++buf;
269        /* fall-through */
270    case 2:
271        if (buf == end)
272            return;
273        conn->imc_ch_len = *buf << 8;
274        ++buf;
275        /* fall-through */
276    default:
277        if (buf == end)
278            return;
279        conn->imc_ch_len |= *buf;
280    }
281}
282
283
284static int
285imico_chlo_has_been_consumed (const struct ietf_mini_conn *conn)
286{
287    return conn->imc_streams[ENC_LEV_CLEAR].mcs_read_off > 3
288        && conn->imc_streams[ENC_LEV_CLEAR].mcs_read_off >= conn->imc_ch_len;
289}
290
291
292static ssize_t
293imico_stream_readf (void *stream,
294        size_t (*readf)(void *, const unsigned char *, size_t, int), void *ctx)
295{
296    struct mini_crypto_stream *const cryst = stream;
297    struct ietf_mini_conn *const conn = cryst_get_conn(cryst);
298    struct stream_frame *frame;
299    const unsigned char *buf;
300    size_t nread, total_read;
301    unsigned avail;
302
303    total_read = 0;
304    while ((frame = imico_find_stream_frame(conn, cryst->mcs_enc_level,
305                                                        cryst->mcs_read_off)))
306    {
307        avail = DF_SIZE(frame) - frame->data_frame.df_read_off;
308        buf = frame->data_frame.df_data + frame->data_frame.df_read_off;
309        nread = readf(ctx, buf, avail, DF_FIN(frame));
310        if (cryst->mcs_enc_level == ENC_LEV_CLEAR && cryst->mcs_read_off < 4)
311            imico_read_chlo_size(conn, buf, nread);
312        total_read += nread;
313        cryst->mcs_read_off += nread;
314        frame->data_frame.df_read_off += nread;
315        LSQ_DEBUG("read %zu bytes at offset %"PRIu64" on enc level %u", nread,
316            DF_ROFF(frame), cryst->mcs_enc_level);
317        if (DF_END(frame) == DF_ROFF(frame))
318        {
319            if (frame == conn->imc_last_in.frame)
320                conn->imc_last_in.frame = NULL;
321            else
322            {
323                TAILQ_REMOVE(&conn->imc_crypto_frames, frame, next_frame);
324                --conn->imc_n_crypto_frames;
325                conn->imc_crypto_frames_sz -= DF_SIZE(frame);
326                lsquic_packet_in_put(&conn->imc_enpub->enp_mm,
327                                                            frame->packet_in);
328                lsquic_malo_put(frame);
329            }
330        }
331        if (nread < avail)
332            break;
333    }
334
335    if (total_read > 0)
336        return total_read;
337    else
338    {
339        /* CRYPTO streams never end, so zero bytes read always means
340         * EWOULDBLOCK
341         */
342        errno = EWOULDBLOCK;
343        return -1;
344    }
345}
346
347
348static int
349imico_stream_wantX (struct mini_crypto_stream *cryst, int bit, int is_want)
350{
351    int old;
352
353    old = (cryst->mcs_flags & (1 << bit)) > 0;
354    cryst->mcs_flags &= ~(1 << bit);
355    cryst->mcs_flags |= !!is_want << bit;
356    return old;
357}
358
359
360static int
361imico_stream_wantwrite (void *stream, int is_want)
362{
363    return imico_stream_wantX(stream, MCSBIT_WANTWRITE, is_want);
364}
365
366
367static int
368imico_stream_wantread (void *stream, int is_want)
369{
370    return imico_stream_wantX(stream, MCSBIT_WANTREAD, is_want);
371}
372
373
374static enum enc_level
375imico_stream_enc_level (void *stream)
376{
377    struct mini_crypto_stream *const cryst = stream;
378    return cryst->mcs_enc_level;
379}
380
381
382static const struct crypto_stream_if crypto_stream_if =
383{
384    .csi_write      = imico_stream_write,
385    .csi_flush      = imico_stream_flush,
386    .csi_readf      = imico_stream_readf,
387    .csi_wantwrite  = imico_stream_wantwrite,
388    .csi_wantread   = imico_stream_wantread,
389    .csi_enc_level  = imico_stream_enc_level,
390};
391
392
393static int
394is_first_packet_ok (const struct lsquic_packet_in *packet_in,
395                                                    size_t udp_payload_size)
396{
397    if (udp_payload_size < IQUIC_MIN_INIT_PACKET_SZ)
398    {
399        /* [draft-ietf-quic-transport-24] Section 14 */
400        LSQ_LOG1(LSQ_LOG_DEBUG, "incoming UDP payload too small: %zu bytes",
401                                                            udp_payload_size);
402        return 0;
403    }
404    /* TODO: Move decryption of the first packet into this function? */
405    return 1;   /* TODO */
406}
407
408
409struct lsquic_conn *
410lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
411               const struct lsquic_packet_in *packet_in,
412           enum lsquic_version version, int is_ipv4, const lsquic_cid_t *odcid,
413           size_t udp_payload_size)
414{
415    struct ietf_mini_conn *conn;
416    enc_session_t *enc_sess;
417    enum enc_level i;
418    const struct enc_session_funcs_iquic *esfi;
419
420    if (!is_first_packet_ok(packet_in, udp_payload_size))
421        return NULL;
422
423    conn = lsquic_malo_get(enpub->enp_mm.malo.mini_conn_ietf);
424    if (!conn)
425    {
426        LSQ_LOG1(LSQ_LOG_WARN, "cannot allocate mini connection: %s",
427                                                            strerror(errno));
428        return NULL;
429    }
430    memset(conn, 0, sizeof(*conn));
431    conn->imc_conn.cn_if = &mini_conn_ietf_iface;
432    conn->imc_conn.cn_cces = conn->imc_cces;
433    conn->imc_conn.cn_n_cces = sizeof(conn->imc_cces)
434                                                / sizeof(conn->imc_cces[0]);
435    conn->imc_cces[0].cce_cid = packet_in->pi_dcid;
436    conn->imc_cces[0].cce_flags = CCE_USED;
437    conn->imc_conn.cn_cces_mask = 1;
438    lsquic_scid_from_packet_in(packet_in, &conn->imc_path.np_dcid);
439    LSQ_DEBUGC("recv SCID from client %"CID_FMT, CID_BITS(&conn->imc_cces[0].cce_cid));
440    LSQ_DEBUGC("recv DCID from client %"CID_FMT, CID_BITS(&conn->imc_path.np_dcid));
441
442    /* Generate new SCID. Since is not the original SCID, it is given
443     * a sequence number (0) and therefore can be retired by the client.
444     */
445    lsquic_generate_cid(&conn->imc_conn.cn_cces[1].cce_cid,
446                                        enpub->enp_settings.es_scid_len);
447    LSQ_DEBUGC("generated SCID %"CID_FMT" at index %u, switching to it",
448                CID_BITS(&conn->imc_conn.cn_cces[1].cce_cid), 1);
449    conn->imc_conn.cn_cces[1].cce_flags = CCE_SEQNO | CCE_USED;
450    conn->imc_conn.cn_cces_mask |= 1u << 1;
451    conn->imc_conn.cn_cur_cce_idx = 1;
452
453    conn->imc_conn.cn_flags = LSCONN_MINI|LSCONN_IETF|LSCONN_SERVER;
454
455    for (i = 0; i < N_ENC_LEVS; ++i)
456    {
457        conn->imc_streams[i].mcs_enc_level = i;
458        conn->imc_stream_ps[i] = &conn->imc_streams[i];
459    }
460
461    esfi = select_esf_iquic_by_ver(version);
462    enc_sess = esfi->esfi_create_server(enpub, &conn->imc_conn,
463                &packet_in->pi_dcid, conn->imc_stream_ps, &crypto_stream_if,
464                odcid);
465    if (!enc_sess)
466    {
467        lsquic_malo_put(conn);
468        return NULL;
469    }
470
471    conn->imc_enpub = enpub;
472    conn->imc_created = packet_in->pi_received;
473    conn->imc_path.np_pack_size = is_ipv4 ? IQUIC_MAX_IPv4_PACKET_SZ
474                                                    : IQUIC_MAX_IPv6_PACKET_SZ;
475#ifndef NDEBUG
476    if (getenv("LSQUIC_CN_PACK_SIZE"))
477        conn->imc_path.np_pack_size = atoi(getenv("LSQUIC_CN_PACK_SIZE"));
478#endif
479    conn->imc_conn.cn_version = version;
480    conn->imc_conn.cn_pf = select_pf_by_ver(version);
481    conn->imc_conn.cn_esf.i = esfi;
482    conn->imc_conn.cn_enc_session = enc_sess;
483    conn->imc_conn.cn_esf_c = select_esf_common_by_ver(version);
484    TAILQ_INIT(&conn->imc_packets_out);
485    TAILQ_INIT(&conn->imc_app_packets);
486    TAILQ_INIT(&conn->imc_crypto_frames);
487    if (odcid)
488        conn->imc_flags |= IMC_ADDR_VALIDATED;
489
490    LSQ_DEBUG("created mini connection object %p; max packet size=%hu",
491                                                conn, conn->imc_path.np_pack_size);
492    return &conn->imc_conn;
493}
494
495
496static void
497ietf_mini_conn_ci_client_call_on_new (struct lsquic_conn *lconn)
498{
499    assert(0);
500}
501
502
503static void
504ietf_mini_conn_ci_destroy (struct lsquic_conn *lconn)
505{
506    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
507    struct lsquic_packet_out *packet_out;
508    struct lsquic_packet_in *packet_in;
509    struct stream_frame *frame;
510
511    while ((packet_out = TAILQ_FIRST(&conn->imc_packets_out)))
512    {
513        TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next);
514        imico_destroy_packet(conn, packet_out);
515    }
516    while ((packet_in = TAILQ_FIRST(&conn->imc_app_packets)))
517    {
518        TAILQ_REMOVE(&conn->imc_app_packets, packet_in, pi_next);
519        lsquic_packet_in_put(&conn->imc_enpub->enp_mm, packet_in);
520    }
521    while ((frame = TAILQ_FIRST(&conn->imc_crypto_frames)))
522    {
523        TAILQ_REMOVE(&conn->imc_crypto_frames, frame, next_frame);
524        lsquic_packet_in_put(&conn->imc_enpub->enp_mm, frame->packet_in);
525        lsquic_malo_put(frame);
526    }
527    if (lconn->cn_enc_session)
528        lconn->cn_esf.i->esfi_destroy(lconn->cn_enc_session);
529    LSQ_DEBUG("ietf_mini_conn_ci_destroyed");
530    lsquic_malo_put(conn);
531}
532
533
534static struct lsquic_engine *
535ietf_mini_conn_ci_get_engine (struct lsquic_conn *lconn)
536{
537    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
538    return conn->imc_enpub->enp_engine;
539}
540
541
542static void
543ietf_mini_conn_ci_hsk_done (struct lsquic_conn *lconn,
544                                                enum lsquic_hsk_status status)
545{
546    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
547
548    switch (status)
549    {
550    case LSQ_HSK_OK:
551    case LSQ_HSK_0RTT_OK:
552        conn->imc_flags |= IMC_HSK_OK;
553        conn->imc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE;
554        LSQ_DEBUG("handshake OK");
555        break;
556    default:
557        assert(0);
558        /* fall-through */
559    case LSQ_HSK_FAIL:
560        conn->imc_flags |= IMC_HSK_FAILED|IMC_ERROR;
561        LSQ_INFO("handshake failed");
562        break;
563    }
564}
565
566
567static void
568ietf_mini_conn_ci_tls_alert (struct lsquic_conn *lconn, uint8_t alert)
569{
570    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
571    LSQ_DEBUG("got TLS alert %"PRIu8, alert);
572    conn->imc_flags |= IMC_ERROR|IMC_TLS_ALERT;
573    conn->imc_tls_alert = alert;
574}
575
576
577static int
578ietf_mini_conn_ci_is_tickable (struct lsquic_conn *lconn)
579{
580    /* A mini connection is never tickable:  Either there are incoming
581     * packets, in which case, the connection is going to be ticked, or
582     * there is an alarm pending, in which case it will be handled via
583     * the attq.
584     */
585    return 0;
586}
587
588
589static int
590imico_can_send (const struct ietf_mini_conn *conn, size_t size)
591{
592    return (conn->imc_flags & IMC_ADDR_VALIDATED)
593        || conn->imc_bytes_in * 3 >= conn->imc_bytes_out + size
594        ;
595}
596
597
598static struct lsquic_packet_out *
599ietf_mini_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
600{
601    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
602    struct lsquic_packet_out *packet_out;
603    size_t packet_size;
604
605    TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next)
606    {
607        if (packet_out->po_flags & PO_SENT)
608            continue;
609        packet_size = lsquic_packet_out_total_sz(lconn, packet_out);
610        if (size == 0 || packet_size + size <= conn->imc_path.np_pack_size)
611        {
612            if (!imico_can_send(conn, packet_size + IQUIC_TAG_LEN))
613            {
614                LSQ_DEBUG("cannot send packet %"PRIu64" of size %zu: client "
615                    "address has not been validated", packet_out->po_packno,
616                    packet_size + IQUIC_TAG_LEN);
617                return NULL;
618            }
619            packet_out->po_flags |= PO_SENT;
620            conn->imc_bytes_out += packet_size + IQUIC_TAG_LEN;
621            if (size == 0)
622                LSQ_DEBUG("packet_to_send: %"PRIu64, packet_out->po_packno);
623            else
624                LSQ_DEBUG("packet_to_send: %"PRIu64" (coalesced)",
625                                                    packet_out->po_packno);
626            return packet_out;
627        }
628        else
629            return NULL;
630    }
631
632    return NULL;
633}
634
635
636static int
637imico_calc_retx_timeout (const struct ietf_mini_conn *conn)
638{
639    lsquic_time_t to;
640    to = lsquic_rtt_stats_get_srtt(&conn->imc_rtt_stats);
641    if (to)
642    {
643        to += to / 2;
644        if (to < 10000)
645            to = 10000;
646    }
647    else
648        to = 300000;
649    return to << conn->imc_hsk_count;
650}
651
652
653static lsquic_time_t
654ietf_mini_conn_ci_next_tick_time (struct lsquic_conn *lconn, unsigned *why)
655{
656    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
657    const struct lsquic_packet_out *packet_out;
658    lsquic_time_t exp_time, retx_time;
659
660    exp_time = conn->imc_created +
661                        conn->imc_enpub->enp_settings.es_handshake_to;
662
663    TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next)
664        if (packet_out->po_flags & PO_SENT)
665        {
666            retx_time = packet_out->po_sent + imico_calc_retx_timeout(conn);
667            if (retx_time < exp_time)
668            {
669                *why = N_AEWS + AL_RETX_HSK;
670                return retx_time;
671            }
672            else
673            {
674                *why = AEW_MINI_EXPIRE;
675                return exp_time;
676            }
677        }
678
679    *why = AEW_MINI_EXPIRE;
680    return exp_time;
681}
682
683
684#define IMICO_PROC_FRAME_ARGS                                           \
685    struct ietf_mini_conn *conn, struct lsquic_packet_in *packet_in,    \
686    const unsigned char *p, size_t len
687
688
689static void
690imico_dispatch_stream_events (struct ietf_mini_conn *conn)
691{
692    enum enc_level i;
693
694    for (i = 0; i < N_ENC_LEVS; ++i)
695        if ((conn->imc_streams[i].mcs_flags & (MCS_CREATED|MCS_WANTREAD))
696                                                == (MCS_CREATED|MCS_WANTREAD))
697        {
698            LSQ_DEBUG("dispatch read events on level #%u", i);
699            lsquic_mini_cry_sm_if.on_read((void *) &conn->imc_streams[i],
700                                            conn->imc_conn.cn_enc_session);
701        }
702
703    for (i = 0; i < N_ENC_LEVS; ++i)
704        if ((conn->imc_streams[i].mcs_flags & (MCS_CREATED|MCS_WANTWRITE))
705                                                == (MCS_CREATED|MCS_WANTWRITE))
706        {
707            LSQ_DEBUG("dispatch write events on level #%u", i);
708            lsquic_mini_cry_sm_if.on_write((void *) &conn->imc_streams[i],
709                                            conn->imc_conn.cn_enc_session);
710        }
711}
712
713
714static int
715imico_stash_stream_frame (struct ietf_mini_conn *conn,
716        enum enc_level enc_level, struct lsquic_packet_in *packet_in,
717        const struct stream_frame *frame)
718{
719    struct stream_frame *copy;
720
721    if (conn->imc_n_crypto_frames >= IMICO_MAX_STASHED_FRAMES)
722    {
723        LSQ_INFO("cannot stash more CRYPTO frames, at %hhu already, while max "
724            "is %u", conn->imc_n_crypto_frames, IMICO_MAX_STASHED_FRAMES);
725        return -1;
726    }
727
728    if (conn->imc_crypto_frames_sz + DF_SIZE(frame) > IMICO_MAX_BUFFERED_CRYPTO)
729    {
730        LSQ_INFO("cannot stash more than %u bytes of CRYPTO frames",
731            IMICO_MAX_BUFFERED_CRYPTO);
732        return -1;
733    }
734
735    copy = lsquic_malo_get(conn->imc_enpub->enp_mm.malo.stream_frame);
736    if (!copy)
737    {
738        LSQ_INFO("could not allocate stream frame for stashing");
739        return -1;
740    }
741
742    *copy = *frame;
743    copy->packet_in = lsquic_packet_in_get(packet_in);
744    copy->stream_id = enc_level;
745    TAILQ_INSERT_TAIL(&conn->imc_crypto_frames, copy, next_frame);
746    ++conn->imc_n_crypto_frames;
747    conn->imc_crypto_frames_sz += DF_SIZE(frame);
748    return 0;
749}
750
751
752static unsigned
753imico_process_crypto_frame (IMICO_PROC_FRAME_ARGS)
754{
755    int parsed_len;
756    enum enc_level enc_level, i;
757    struct stream_frame stream_frame;
758    const struct transport_params *params;
759
760    parsed_len = conn->imc_conn.cn_pf->pf_parse_crypto_frame(p, len,
761                                                                &stream_frame);
762    if (parsed_len < 0)
763    {
764        conn->imc_flags |= IMC_PARSE_FAILED;
765        return 0;
766    }
767
768    enc_level = lsquic_packet_in_enc_level(packet_in);
769    EV_LOG_CRYPTO_FRAME_IN(LSQUIC_LOG_CONN_ID, &stream_frame, enc_level);
770
771    if (conn->imc_streams[enc_level].mcs_read_off >= DF_OFF(&stream_frame)
772        && conn->imc_streams[enc_level].mcs_read_off < DF_END(&stream_frame))
773        LSQ_DEBUG("Got CRYPTO frame for enc level #%u", enc_level);
774    else if (conn->imc_streams[enc_level].mcs_read_off < DF_OFF(&stream_frame))
775    {
776        LSQ_DEBUG("Can't read CRYPTO frame on enc level #%u at offset %"PRIu64
777            " yet -- stash", enc_level, DF_OFF(&stream_frame));
778        if (0 == imico_stash_stream_frame(conn, enc_level, packet_in,
779                                                                &stream_frame))
780            return parsed_len;
781        else
782            return 0;
783    }
784    else
785    {
786        LSQ_DEBUG("Got duplicate CRYPTO frame for enc level #%u -- ignore",
787                                                                    enc_level);
788        return parsed_len;
789    }
790
791    if (!(conn->imc_flags & IMC_ENC_SESS_INITED))
792    {
793        if (0 != conn->imc_conn.cn_esf.i->esfi_init_server(
794                                            conn->imc_conn.cn_enc_session))
795            return -1;
796        conn->imc_flags |= IMC_ENC_SESS_INITED;
797    }
798
799    if (!(conn->imc_streams[enc_level].mcs_flags & MCS_CREATED))
800    {
801        LSQ_DEBUG("creating stream on level #%u", enc_level);
802        conn->imc_streams[enc_level].mcs_flags |= MCS_CREATED;
803        lsquic_mini_cry_sm_if.on_new_stream(conn->imc_conn.cn_enc_session,
804                                    (void *) &conn->imc_streams[enc_level]);
805    }
806
807    /* Assume that receiving a CRYPTO frame at a higher level means that we
808     * no longer want to read from a lower level.
809     */
810    for (i = 0; i < enc_level; ++i)
811        conn->imc_streams[i].mcs_flags &= ~MCS_WANTREAD;
812
813    conn->imc_last_in.frame = &stream_frame;
814    conn->imc_last_in.enc_level = enc_level;
815    imico_dispatch_stream_events(conn);
816    conn->imc_last_in.frame = NULL;
817
818    if (DF_ROFF(&stream_frame) < DF_END(&stream_frame))
819    {
820        /* This is an odd condition, but let's handle it just in case */
821        LSQ_DEBUG("New CRYPTO frame on enc level #%u not fully read -- stash",
822            enc_level);
823        if (0 != imico_stash_stream_frame(conn, enc_level, packet_in,
824                                                                &stream_frame))
825            return 0;
826    }
827
828
829    if (enc_level == ENC_LEV_CLEAR
830        && imico_chlo_has_been_consumed(conn)
831        && (conn->imc_flags & (IMC_ENC_SESS_INITED|IMC_HAVE_TP))
832                                                    == IMC_ENC_SESS_INITED)
833    {
834        params = conn->imc_conn.cn_esf.i->esfi_get_peer_transport_params(
835                                                conn->imc_conn.cn_enc_session);
836        if (params)
837        {
838            conn->imc_flags |= IMC_HAVE_TP;
839            conn->imc_ack_exp = params->tp_ack_delay_exponent;
840        }
841        else
842        {
843            conn->imc_flags |= IMC_BAD_TRANS_PARAMS;
844            return 0;
845        }
846    }
847
848    return parsed_len;
849}
850
851
852static ptrdiff_t
853imico_count_zero_bytes (const unsigned char *p, size_t len)
854{
855    const unsigned char *const end = p + len;
856    while (p < end && 0 == *p)
857        ++p;
858    return len - (end - p);
859}
860
861
862static unsigned
863imico_process_padding_frame (IMICO_PROC_FRAME_ARGS)
864{
865    len = (size_t) imico_count_zero_bytes(p, len);
866    EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len);
867    return len;
868}
869
870
871static void
872imico_take_rtt_sample (struct ietf_mini_conn *conn,
873                            const struct lsquic_packet_out *packet_out,
874                            lsquic_time_t now, lsquic_time_t lack_delta)
875{
876    assert(packet_out->po_sent);
877    lsquic_time_t measured_rtt = now - packet_out->po_sent;
878    if (lack_delta < measured_rtt)
879    {
880        lsquic_rtt_stats_update(&conn->imc_rtt_stats, measured_rtt, lack_delta);
881        LSQ_DEBUG("srtt: %"PRIu64" usec, var: %"PRIu64,
882                        lsquic_rtt_stats_get_srtt(&conn->imc_rtt_stats),
883                        lsquic_rtt_stats_get_rttvar(&conn->imc_rtt_stats));
884    }
885}
886
887
888static unsigned
889imico_process_ack_frame (IMICO_PROC_FRAME_ARGS)
890{
891    int parsed_len;
892    unsigned n;
893    lsquic_packet_out_t *packet_out, *next;
894    struct ack_info *acki;
895    lsquic_packno_t packno;
896    lsquic_time_t warn_time;
897    packno_set_t acked;
898    enum packnum_space pns;
899    uint8_t ack_exp;
900
901    if (conn->imc_flags & IMC_HAVE_TP)
902        ack_exp = conn->imc_ack_exp;
903    else
904        ack_exp = TP_DEF_ACK_DELAY_EXP; /* Odd: no transport params yet? */
905    acki = conn->imc_enpub->enp_mm.acki;
906    parsed_len = conn->imc_conn.cn_pf->pf_parse_ack_frame(p, len, acki,
907                                                                    ack_exp);
908    if (parsed_len < 0)
909    {
910        conn->imc_flags |= IMC_PARSE_FAILED;
911        return 0;
912    }
913
914    pns = lsquic_hety2pns[ packet_in->pi_header_type ];
915    acked = 0;
916
917    for (n = 0; n < acki->n_ranges; ++n)
918    {
919        if (acki->ranges[n].high <= MAX_PACKETS)
920        {
921            acked |= (1ULL << acki->ranges[n].high)
922                                        | ((1ULL << acki->ranges[n].high) - 1);
923            acked &= ~((1ULL << acki->ranges[n].low) - 1);
924        }
925        else
926        {
927            packno = acki->ranges[n].high;
928            goto err_never_sent;
929        }
930    }
931    if (acked & ~conn->imc_sent_packnos)
932    {
933        packno = highest_bit_set(acked & ~conn->imc_sent_packnos);
934        goto err_never_sent;
935    }
936
937    EV_LOG_ACK_FRAME_IN(LSQUIC_LOG_CONN_ID, acki);
938    for (packet_out = TAILQ_FIRST(&conn->imc_packets_out); packet_out;
939                                                            packet_out = next)
940    {
941        next = TAILQ_NEXT(packet_out, po_next);
942        if ((1ULL << packet_out->po_packno) & acked)
943        {
944            assert(lsquic_packet_out_pns(packet_out) == pns);
945            LSQ_DEBUG("Got ACK for packet %"PRIu64, packet_out->po_packno);
946            if (packet_out->po_packno == largest_acked(acki))
947                imico_take_rtt_sample(conn, packet_out,
948                                    packet_in->pi_received, acki->lack_delta);
949            TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next);
950            imico_destroy_packet(conn, packet_out);
951        }
952    }
953
954    if (conn->imc_sent_packnos & ~conn->imc_acked_packnos[pns] & acked)
955    {
956        LSQ_DEBUG("Newly acked packets, reset handshake count");
957        conn->imc_hsk_count = 0;
958    }
959
960    conn->imc_acked_packnos[pns] |= acked;
961
962    return parsed_len;
963
964  err_never_sent:
965    warn_time = lsquic_time_now();
966    if (0 == conn->imc_enpub->enp_last_warning[WT_ACKPARSE_MINI]
967        || conn->imc_enpub->enp_last_warning[WT_ACKPARSE_MINI]
968                + WARNING_INTERVAL < warn_time)
969    {
970        conn->imc_enpub->enp_last_warning[WT_ACKPARSE_MINI] = warn_time;
971        LSQ_WARN("packet %"PRIu64" (pns: %u) was never sent", packno, pns);
972    }
973    else
974        LSQ_DEBUG("packet %"PRIu64" (pns: %u) was never sent", packno, pns);
975    return 0;
976}
977
978
979static unsigned
980imico_process_ping_frame (IMICO_PROC_FRAME_ARGS)
981{
982    LSQ_DEBUG("got a PING frame, do nothing");
983    return 1;
984}
985
986
987static unsigned
988imico_process_connection_close_frame (IMICO_PROC_FRAME_ARGS)
989{
990    struct lsquic_packet_out *packet_out;
991    uint64_t error_code;
992    uint16_t reason_len;
993    uint8_t reason_off;
994    int parsed_len, app_error;
995
996    while ((packet_out = TAILQ_FIRST(&conn->imc_packets_out)))
997    {
998        TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next);
999        imico_destroy_packet(conn, packet_out);
1000    }
1001    conn->imc_flags |= IMC_CLOSE_RECVD;
1002    parsed_len = conn->imc_conn.cn_pf->pf_parse_connect_close_frame(p, len,
1003                            &app_error, &error_code, &reason_len, &reason_off);
1004    if (parsed_len < 0)
1005    {
1006        conn->imc_flags |= IMC_PARSE_FAILED;
1007        return 0;
1008    }
1009    EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code,
1010                            (int) reason_len, (const char *) p + reason_off);
1011    LSQ_INFO("Received CONNECTION_CLOSE frame (%s-level code: %"PRIu64"; "
1012            "reason: %.*s)", app_error ? "application" : "transport",
1013                error_code, (int) reason_len, (const char *) p + reason_off);
1014    return 0;   /* This shuts down the connection */
1015}
1016
1017
1018static unsigned
1019imico_process_invalid_frame (IMICO_PROC_FRAME_ARGS)
1020{
1021    LSQ_DEBUG("invalid frame %u (%s)", p[0],
1022        frame_type_2_str[ conn->imc_conn.cn_pf->pf_parse_frame_type(p[0]) ]);
1023    return 0;
1024}
1025
1026
1027static unsigned (*const imico_process_frames[N_QUIC_FRAMES])
1028                                                (IMICO_PROC_FRAME_ARGS) =
1029{
1030    [QUIC_FRAME_PADDING]            =  imico_process_padding_frame,
1031    [QUIC_FRAME_CRYPTO]             =  imico_process_crypto_frame,
1032    [QUIC_FRAME_ACK]                =  imico_process_ack_frame,
1033    [QUIC_FRAME_PING]               =  imico_process_ping_frame,
1034    [QUIC_FRAME_CONNECTION_CLOSE]   =  imico_process_connection_close_frame,
1035    /* Some of them are invalid, while others are unexpected.  We treat
1036     * them the same: handshake cannot proceed.
1037     */
1038    [QUIC_FRAME_RST_STREAM]         =  imico_process_invalid_frame,
1039    [QUIC_FRAME_MAX_DATA]           =  imico_process_invalid_frame,
1040    [QUIC_FRAME_MAX_STREAM_DATA]    =  imico_process_invalid_frame,
1041    [QUIC_FRAME_MAX_STREAMS]        =  imico_process_invalid_frame,
1042    [QUIC_FRAME_BLOCKED]            =  imico_process_invalid_frame,
1043    [QUIC_FRAME_STREAM_BLOCKED]     =  imico_process_invalid_frame,
1044    [QUIC_FRAME_STREAMS_BLOCKED]    =  imico_process_invalid_frame,
1045    [QUIC_FRAME_NEW_CONNECTION_ID]  =  imico_process_invalid_frame,
1046    [QUIC_FRAME_STOP_SENDING]       =  imico_process_invalid_frame,
1047    [QUIC_FRAME_PATH_CHALLENGE]     =  imico_process_invalid_frame,
1048    [QUIC_FRAME_PATH_RESPONSE]      =  imico_process_invalid_frame,
1049    /* STREAM frame can only come in the App PNS and we delay those packets: */
1050    [QUIC_FRAME_STREAM]             =  imico_process_invalid_frame,
1051    [QUIC_FRAME_HANDSHAKE_DONE]     =  imico_process_invalid_frame,
1052};
1053
1054
1055static unsigned
1056imico_process_packet_frame (struct ietf_mini_conn *conn,
1057        struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
1058{
1059    enum enc_level enc_level = lsquic_packet_in_enc_level(packet_in);
1060    enum quic_frame_type type = conn->imc_conn.cn_pf->pf_parse_frame_type(p[0]);
1061    if (lsquic_legal_frames_by_level[enc_level] & (1 << type))
1062    {
1063        packet_in->pi_frame_types |= 1 << type;
1064        return imico_process_frames[type](conn, packet_in, p, len);
1065    }
1066    else
1067    {
1068        LSQ_DEBUG("invalid frame %u at encryption level %s", type,
1069                                                lsquic_enclev2str[enc_level]);
1070        return 0;
1071    }
1072}
1073
1074
1075static int
1076imico_parse_regular_packet (struct ietf_mini_conn *conn,
1077                                        struct lsquic_packet_in *packet_in)
1078{
1079    const unsigned char *p, *pend;
1080    unsigned len;
1081
1082    p = packet_in->pi_data + packet_in->pi_header_sz;
1083    pend = packet_in->pi_data + packet_in->pi_data_sz;
1084
1085    while (p < pend)
1086    {
1087        len = imico_process_packet_frame(conn, packet_in, p, pend - p);
1088        if (len > 0)
1089            p += len;
1090        else
1091            return -1;
1092    }
1093
1094    return 0;
1095}
1096
1097
1098static unsigned
1099highest_bit_set (unsigned long long sz)
1100{
1101#if __GNUC__
1102    unsigned clz = __builtin_clzll(sz);
1103    return 63 - clz;
1104#else
1105    unsigned long y;
1106    unsigned n;
1107    n = 64;
1108    y = sz >> 32;     if (y) { n -= 32; sz = y; }
1109    y = sz >> 16;     if (y) { n -= 16; sz = y; }
1110    y = sz >>  8;     if (y) { n -=  8; sz = y; }
1111    y = sz >>  4;     if (y) { n -=  4; sz = y; }
1112    y = sz >>  2;     if (y) { n -=  2; sz = y; }
1113    y = sz >>  1;     if (y) return 63 - n + 2;
1114    return 63 - n + sz;
1115#endif
1116}
1117
1118
1119static void
1120ignore_init (struct ietf_mini_conn *conn)
1121{
1122    struct lsquic_packet_out *packet_out, *next;
1123    unsigned count;
1124
1125    conn->imc_flags |= IMC_IGNORE_INIT;
1126    conn->imc_flags &= ~(IMC_QUEUED_ACK_INIT << PNS_INIT);
1127
1128    count = 0;
1129    for (packet_out = TAILQ_FIRST(&conn->imc_packets_out); packet_out;
1130                                                            packet_out = next)
1131    {
1132        next = TAILQ_NEXT(packet_out, po_next);
1133        if (PNS_INIT == lsquic_packet_out_pns(packet_out))
1134        {
1135            TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next);
1136            imico_destroy_packet(conn, packet_out);
1137            ++count;
1138        }
1139    }
1140
1141    LSQ_DEBUG("henceforth, no Initial packets shall be sent or received; "
1142        "destroyed %u packet%.*s", count, count != 1, "s");
1143}
1144
1145
1146/* Only a single packet is supported */
1147static void
1148ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
1149                        struct lsquic_packet_in *packet_in)
1150{
1151    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1152    enum dec_packin dec_packin;
1153    enum packnum_space pns;
1154
1155    if (conn->imc_flags & IMC_ERROR)
1156    {
1157        LSQ_DEBUG("ignore incoming packet: connection is in error state");
1158        return;
1159    }
1160
1161    pns = lsquic_hety2pns[ packet_in->pi_header_type ];
1162    if (pns == PNS_INIT && (conn->imc_flags & IMC_IGNORE_INIT))
1163    {
1164        LSQ_DEBUG("ignore init packet");    /* Don't bother decrypting */
1165        return;
1166    }
1167
1168    dec_packin = lconn->cn_esf_c->esf_decrypt_packet(lconn->cn_enc_session,
1169                                conn->imc_enpub, &conn->imc_conn, packet_in);
1170    if (dec_packin != DECPI_OK)
1171    {
1172        /* TODO: handle reordering perhaps? */
1173        LSQ_DEBUG("could not decrypt packet");
1174        return;
1175    }
1176
1177    EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
1178    conn->imc_bytes_in += packet_in->pi_data_sz + IQUIC_TAG_LEN;
1179
1180    if (pns == PNS_APP)
1181    {
1182        lsquic_packet_in_upref(packet_in);
1183        TAILQ_INSERT_TAIL(&conn->imc_app_packets, packet_in, pi_next);
1184        LSQ_DEBUG("delay processing of packet %"PRIu64" in pns %u",
1185            packet_in->pi_packno, pns);
1186        return;
1187    }
1188    else if (pns == PNS_HSK)
1189        conn->imc_flags |= IMC_ADDR_VALIDATED;
1190
1191    if (((conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3) < pns)
1192    {
1193        conn->imc_flags &= ~(3 << IMCBIT_PNS_BIT_SHIFT);
1194        conn->imc_flags |= pns << IMCBIT_PNS_BIT_SHIFT;
1195    }
1196
1197    if (pns == PNS_HSK && !(conn->imc_flags & IMC_IGNORE_INIT))
1198        ignore_init(conn);
1199
1200    if (conn->imc_recvd_packnos[pns] & (1ULL << packet_in->pi_packno))
1201    {
1202        LSQ_DEBUG("duplicate packet %"PRIu64, packet_in->pi_packno);
1203        return;
1204    }
1205
1206    /* Update receive history before processing the packet: if there is an
1207     * error, the connection is terminated and recording this packet number
1208     * is helpful when it is printed along with other diagnostics in dtor.
1209     */
1210    if (0 == conn->imc_recvd_packnos[pns] ||
1211            packet_in->pi_packno > highest_bit_set(conn->imc_recvd_packnos[pns]))
1212        conn->imc_largest_recvd[pns] = packet_in->pi_received;
1213    conn->imc_recvd_packnos[pns] |= 1ULL << packet_in->pi_packno;
1214
1215    if (0 != imico_parse_regular_packet(conn, packet_in))
1216    {
1217        LSQ_DEBUG("connection is now in error state");
1218        conn->imc_flags |= IMC_ERROR;
1219        return;
1220    }
1221
1222    conn->imc_flags |= IMC_QUEUED_ACK_INIT << pns;
1223    ++conn->imc_ecn_counts_in[pns][ lsquic_packet_in_ecn(packet_in) ];
1224    conn->imc_incoming_ecn <<= 1;
1225    conn->imc_incoming_ecn |= lsquic_packet_in_ecn(packet_in) != ECN_NOT_ECT;
1226}
1227
1228
1229static void
1230ietf_mini_conn_ci_packet_sent (struct lsquic_conn *lconn,
1231                              struct lsquic_packet_out *packet_out)
1232{
1233    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1234    conn->imc_sent_packnos |= 1ULL << packet_out->po_packno;
1235    conn->imc_ecn_packnos |= !!lsquic_packet_out_ecn(packet_out)
1236                                                    << packet_out->po_packno;
1237#if 0
1238    if (packet_out->po_frame_types & (1 << QUIC_FRAME_ACK))
1239    {
1240        assert(mc->mc_flags & MC_UNSENT_ACK);
1241        mc->mc_flags &= ~MC_UNSENT_ACK;
1242    }
1243#endif
1244    ++conn->imc_ecn_counts_out[ lsquic_packet_out_pns(packet_out) ]
1245                              [ lsquic_packet_out_ecn(packet_out) ];
1246    if (packet_out->po_header_type == HETY_HANDSHAKE)
1247        conn->imc_flags |= IMC_HSK_PACKET_SENT;
1248    LSQ_DEBUG("%s: packet %"PRIu64" sent", __func__, packet_out->po_packno);
1249}
1250
1251
1252static void
1253ietf_mini_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
1254                              struct lsquic_packet_out *packet_out)
1255{
1256    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1257    size_t packet_size;
1258
1259    packet_out->po_flags &= ~PO_SENT;
1260    packet_size = lsquic_packet_out_total_sz(lconn, packet_out);
1261    conn->imc_bytes_out -= packet_size + IQUIC_TAG_LEN;
1262    LSQ_DEBUG("%s: packet %"PRIu64" not sent", __func__, packet_out->po_packno);
1263}
1264
1265
1266static void
1267imico_return_enc_data (struct ietf_mini_conn *conn,
1268                                        struct lsquic_packet_out *packet_out)
1269{
1270    conn->imc_enpub->enp_pmi->pmi_return(conn->imc_enpub->enp_pmi_ctx,
1271        conn->imc_path.np_peer_ctx, packet_out->po_enc_data,
1272        lsquic_packet_out_ipv6(packet_out));
1273    packet_out->po_flags &= ~PO_ENCRYPTED;
1274    packet_out->po_enc_data = NULL;
1275}
1276
1277
1278static int
1279imico_repackage_packet (struct ietf_mini_conn *conn,
1280                                        struct lsquic_packet_out *packet_out)
1281{
1282    const lsquic_packno_t oldno = packet_out->po_packno;
1283    const lsquic_packno_t packno = conn->imc_next_packno++;
1284    if (packno > MAX_PACKETS)
1285        return -1;
1286
1287    LSQ_DEBUG("Packet %"PRIu64" repackaged for resending as packet %"PRIu64,
1288                                                        oldno, packno);
1289    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "packet %"PRIu64" repackaged for "
1290        "resending as packet %"PRIu64, oldno, packno);
1291    packet_out->po_packno = packno;
1292    packet_out->po_flags &= ~PO_SENT;
1293    lsquic_packet_out_set_ecn(packet_out, imico_get_ecn(conn));
1294    if (packet_out->po_flags & PO_ENCRYPTED)
1295        imico_return_enc_data(conn, packet_out);
1296    TAILQ_INSERT_TAIL(&conn->imc_packets_out, packet_out, po_next);
1297    return 0;
1298}
1299
1300
1301static int
1302imico_handle_losses_and_have_unsent (struct ietf_mini_conn *conn,
1303                                                            lsquic_time_t now)
1304{
1305    TAILQ_HEAD(, lsquic_packet_out) lost_packets =
1306                                    TAILQ_HEAD_INITIALIZER(lost_packets);
1307    lsquic_packet_out_t *packet_out, *next;
1308    lsquic_time_t retx_to = 0;
1309    unsigned n_to_send = 0;
1310
1311    for (packet_out = TAILQ_FIRST(&conn->imc_packets_out); packet_out;
1312                                                        packet_out = next)
1313    {
1314        next = TAILQ_NEXT(packet_out, po_next);
1315        if (packet_out->po_flags & PO_SENT)
1316        {
1317            if (0 == retx_to)
1318                retx_to = imico_calc_retx_timeout(conn);
1319            if (packet_out->po_sent + retx_to < now)
1320            {
1321                LSQ_DEBUG("packet %"PRIu64" has been lost (rto: %"PRIu64")",
1322                                                packet_out->po_packno, retx_to);
1323                TAILQ_REMOVE(&conn->imc_packets_out, packet_out, po_next);
1324                TAILQ_INSERT_TAIL(&lost_packets, packet_out, po_next);
1325            }
1326        }
1327        else
1328            ++n_to_send;
1329    }
1330
1331    conn->imc_hsk_count += !TAILQ_EMPTY(&lost_packets);
1332
1333    while ((packet_out = TAILQ_FIRST(&lost_packets)))
1334    {
1335        TAILQ_REMOVE(&lost_packets, packet_out, po_next);
1336        if ((packet_out->po_frame_types & IQUIC_FRAME_RETX_MASK)
1337                            && 0 == imico_repackage_packet(conn, packet_out))
1338            ++n_to_send;
1339        else
1340            imico_destroy_packet(conn, packet_out);
1341    }
1342
1343    return n_to_send > 0;
1344}
1345
1346
1347static int
1348imico_have_packets_to_send (struct ietf_mini_conn *conn, lsquic_time_t now)
1349{
1350    return imico_handle_losses_and_have_unsent(conn, now);
1351}
1352
1353
1354struct ietf_mini_rechist
1355{
1356    const struct ietf_mini_conn *conn;
1357    packno_set_t                 cur_set;
1358    struct lsquic_packno_range   range;   /* We return a pointer to this */
1359    int                          cur_idx;
1360    enum packnum_space           pns;
1361};
1362
1363
1364static void
1365imico_rechist_init (struct ietf_mini_rechist *rechist,
1366                    const struct ietf_mini_conn *conn, enum packnum_space pns)
1367{
1368    rechist->conn    = conn;
1369    rechist->pns     = pns;
1370    rechist->cur_set = 0;
1371    rechist->cur_idx = 0;
1372}
1373
1374
1375static lsquic_time_t
1376imico_rechist_largest_recv (void *rechist_ctx)
1377{
1378    struct ietf_mini_rechist *rechist = rechist_ctx;
1379    return rechist->conn->imc_largest_recvd[ rechist->pns ];
1380}
1381
1382
1383static const struct lsquic_packno_range *
1384imico_rechist_next (void *rechist_ctx)
1385{
1386    struct ietf_mini_rechist *rechist = rechist_ctx;
1387    const struct ietf_mini_conn *conn = rechist->conn;
1388    packno_set_t packnos;
1389    int i;
1390
1391    packnos = rechist->cur_set;
1392    if (0 == packnos)
1393        return NULL;
1394
1395    /* There may be a faster way to do this, but for now, we just want
1396     * correctness.
1397     */
1398    for (i = rechist->cur_idx; i >= 0; --i)
1399        if (packnos & (1ULL << i))
1400        {
1401            rechist->range.low  = i;
1402            rechist->range.high = i;
1403            break;
1404        }
1405    assert(i >= 0); /* We must have hit at least one bit */
1406    --i;
1407    for ( ; i >= 0 && (packnos & (1ULL << i)); --i)
1408        rechist->range.low = i;
1409    if (i >= 0)
1410    {
1411        rechist->cur_set = packnos & ((1ULL << i) - 1);
1412        rechist->cur_idx = i;
1413    }
1414    else
1415        rechist->cur_set = 0;
1416    LSQ_DEBUG("%s: return [%"PRIu64", %"PRIu64"]", __func__,
1417                                rechist->range.low, rechist->range.high);
1418    return &rechist->range;
1419}
1420
1421
1422static const struct lsquic_packno_range *
1423imico_rechist_first (void *rechist_ctx)
1424{
1425    struct ietf_mini_rechist *rechist = rechist_ctx;
1426    rechist->cur_set = rechist->conn->imc_recvd_packnos[ rechist->pns ];
1427    rechist->cur_idx = highest_bit_set(rechist->cur_set);
1428    return imico_rechist_next(rechist_ctx);
1429}
1430
1431
1432static const enum header_type pns2hety[] =
1433{
1434    [PNS_INIT]  = HETY_INITIAL,
1435    [PNS_HSK]   = HETY_HANDSHAKE,
1436    [PNS_APP]   = HETY_NOT_SET,
1437};
1438
1439
1440static int
1441imico_generate_ack (struct ietf_mini_conn *conn, enum packnum_space pns,
1442                                                            lsquic_time_t now)
1443{
1444    struct lsquic_packet_out *packet_out;
1445    enum header_type header_type;
1446    struct ietf_mini_rechist rechist;
1447    int not_used_has_missing, len;
1448    uint64_t ecn_counts_buf[4];
1449    const uint64_t *ecn_counts;
1450
1451    header_type = pns2hety[pns];
1452
1453    if (conn->imc_incoming_ecn)
1454    {
1455        ecn_counts_buf[0]   = conn->imc_ecn_counts_in[pns][0];
1456        ecn_counts_buf[1]   = conn->imc_ecn_counts_in[pns][1];
1457        ecn_counts_buf[2]   = conn->imc_ecn_counts_in[pns][2];
1458        ecn_counts_buf[3]   = conn->imc_ecn_counts_in[pns][3];
1459        ecn_counts = ecn_counts_buf;
1460    }
1461    else
1462        ecn_counts = NULL;
1463
1464    packet_out = imico_get_packet_out(conn, header_type, 0);
1465    if (!packet_out)
1466        return -1;
1467
1468    /* Generate ACK frame */
1469    imico_rechist_init(&rechist, conn, pns);
1470    len = conn->imc_conn.cn_pf->pf_gen_ack_frame(
1471                packet_out->po_data + packet_out->po_data_sz,
1472                lsquic_packet_out_avail(packet_out), imico_rechist_first,
1473                imico_rechist_next, imico_rechist_largest_recv, &rechist,
1474                now, &not_used_has_missing, &packet_out->po_ack2ed, ecn_counts);
1475    if (len < 0)
1476    {
1477        LSQ_WARN("could not generate ACK frame");
1478        return -1;
1479    }
1480    EV_LOG_GENERATED_ACK_FRAME(LSQUIC_LOG_CONN_ID, conn->imc_conn.cn_pf,
1481                        packet_out->po_data + packet_out->po_data_sz, len);
1482    packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK;
1483    packet_out->po_data_sz += len;
1484    packet_out->po_regen_sz += len;
1485    conn->imc_flags &= ~(IMC_QUEUED_ACK_INIT << pns);
1486    LSQ_DEBUG("wrote ACK frame of size %d", len);
1487    return 0;
1488}
1489
1490
1491static int
1492imico_generate_acks (struct ietf_mini_conn *conn, lsquic_time_t now)
1493{
1494    enum packnum_space pns;
1495
1496    for (pns = PNS_INIT; pns < N_PNS; ++pns)
1497        if (conn->imc_flags & (IMC_QUEUED_ACK_INIT << pns)
1498                && !(pns == PNS_INIT && (conn->imc_flags & IMC_IGNORE_INIT)))
1499            if (0 != imico_generate_ack(conn, pns, now))
1500                return -1;
1501
1502    return 0;
1503}
1504
1505
1506static void
1507imico_generate_conn_close (struct ietf_mini_conn *conn)
1508{
1509    struct lsquic_packet_out *packet_out;
1510    enum header_type header_type;
1511    enum packnum_space pns, pns_max;
1512    unsigned error_code;
1513    const char *reason;
1514    size_t need;
1515    int sz, rlen, is_app;
1516    char reason_buf[0x20];
1517
1518    if (conn->imc_flags & IMC_ABORT_ERROR)
1519    {
1520        is_app = !!(conn->imc_flags & IMC_ABORT_ISAPP);
1521        error_code = conn->imc_error_code;
1522        reason = NULL;
1523        rlen = 0;
1524    }
1525    else if (conn->imc_flags & IMC_TLS_ALERT)
1526    {
1527        is_app = 0;
1528        error_code = 0x100 + conn->imc_tls_alert;
1529        if (ALERT_NO_APPLICATION_PROTOCOL == conn->imc_tls_alert)
1530            reason = "no suitable application protocol";
1531        else
1532        {
1533            snprintf(reason_buf, sizeof(reason_buf), "TLS alert %"PRIu8,
1534                                                        conn->imc_tls_alert);
1535            reason = reason_buf;
1536        }
1537        rlen = strlen(reason);
1538    }
1539    else if (conn->imc_flags & IMC_BAD_TRANS_PARAMS)
1540    {
1541        is_app = 0;
1542        error_code = TEC_NO_ERROR;
1543        reason = "bad transport parameters";
1544        rlen = 24;
1545    }
1546    else if (conn->imc_flags & IMC_HSK_FAILED)
1547    {
1548        is_app = 0;
1549        error_code = TEC_NO_ERROR;
1550        reason = "handshake failed";
1551        rlen = 16;
1552    }
1553    else if (conn->imc_flags & IMC_PARSE_FAILED)
1554    {
1555        is_app = 0;
1556        error_code = TEC_FRAME_ENCODING_ERROR;
1557        reason = "cannot decode frame";
1558        rlen = 19;
1559    }
1560    else
1561    {
1562        is_app = 0;
1563        error_code = TEC_INTERNAL_ERROR;
1564        reason = NULL;
1565        rlen = 0;
1566    }
1567
1568
1569/* [draft-ietf-quic-transport-23] Section 12.2:
1570 *
1571 " A client will always know whether the server has Handshake keys (see
1572 " Section 17.2.2.1), but it is possible that a server does not know
1573 " whether the client has Handshake keys.  Under these circumstances, a
1574 " server SHOULD send a CONNECTION_CLOSE frame in both Handshake and
1575 " Initial packets to ensure that at least one of them is processable by
1576 " the client.
1577 */
1578
1579    pns = (conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3;
1580    switch ((!!(conn->imc_flags & IMC_HSK_PACKET_SENT) << 1)
1581                | (pns == PNS_HSK) /* Handshake packet received */)
1582    {
1583    case (0 << 1) | 0:
1584        pns = PNS_INIT;
1585        pns_max = PNS_INIT;
1586        break;
1587    case (1 << 1) | 0:
1588        pns = PNS_INIT;
1589        pns_max = PNS_HSK;
1590        break;
1591    default:
1592        pns = PNS_HSK;
1593        pns_max = PNS_HSK;
1594        break;
1595    }
1596
1597    need = conn->imc_conn.cn_pf->pf_connect_close_frame_size(is_app,
1598                                                        error_code, 0, rlen);
1599    LSQ_DEBUG("will generate %u CONNECTION_CLOSE frame%.*s",
1600        pns_max - pns + 1, pns_max > pns, "s");
1601    do
1602    {
1603        header_type = pns2hety[pns];
1604        packet_out = imico_get_packet_out(conn, header_type, need);
1605        if (!packet_out)
1606            return;
1607        sz = conn->imc_conn.cn_pf->pf_gen_connect_close_frame(
1608                 packet_out->po_data + packet_out->po_data_sz,
1609                 lsquic_packet_out_avail(packet_out), is_app, error_code, reason,
1610                 rlen);
1611        if (sz >= 0)
1612        {
1613            packet_out->po_frame_types |= 1 << QUIC_FRAME_CONNECTION_CLOSE;
1614            packet_out->po_data_sz += sz;
1615            LSQ_DEBUG("generated CONNECTION_CLOSE frame");
1616        }
1617        else
1618            LSQ_WARN("could not generate CONNECTION_CLOSE frame");
1619        ++pns;
1620    }
1621    while (pns <= pns_max);
1622}
1623
1624
1625static int
1626imico_generate_handshake_done (struct ietf_mini_conn *conn)
1627{
1628    struct lsquic_packet_out *packet_out;
1629    unsigned need;
1630    int sz;
1631
1632    need = conn->imc_conn.cn_pf->pf_handshake_done_frame_size();
1633    packet_out = imico_get_packet_out(conn, HETY_NOT_SET, need);
1634    if (!packet_out)
1635        return -1;
1636    sz = conn->imc_conn.cn_pf->pf_gen_handshake_done_frame(
1637                 packet_out->po_data + packet_out->po_data_sz,
1638                 lsquic_packet_out_avail(packet_out));
1639    if (sz < 0)
1640    {
1641        LSQ_WARN("could not generate HANDSHAKE_DONE frame");
1642        return -1;
1643    }
1644
1645    packet_out->po_frame_types |= 1 << QUIC_FRAME_HANDSHAKE_DONE;
1646    packet_out->po_data_sz += sz;
1647    LSQ_DEBUG("generated HANDSHAKE_DONE frame");
1648
1649    return 0;
1650}
1651
1652
1653static enum tick_st
1654ietf_mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
1655{
1656    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1657    enum tick_st tick;
1658
1659    if (conn->imc_created + conn->imc_enpub->enp_settings.es_handshake_to < now)
1660    {
1661        LSQ_DEBUG("connection expired: closing");
1662        return TICK_CLOSE;
1663    }
1664
1665
1666    if (conn->imc_flags &
1667            (IMC_QUEUED_ACK_INIT|IMC_QUEUED_ACK_HSK|IMC_QUEUED_ACK_APP))
1668    {
1669        if (0 != imico_generate_acks(conn, now))
1670        {
1671            conn->imc_flags |= IMC_ERROR;
1672            return TICK_CLOSE;
1673        }
1674    }
1675
1676
1677    tick = 0;
1678
1679    if (conn->imc_flags & IMC_ERROR)
1680    {
1681  close_on_error:
1682        if (!(conn->imc_flags & IMC_CLOSE_RECVD))
1683            imico_generate_conn_close(conn);
1684        tick |= TICK_CLOSE;
1685    }
1686    else if (conn->imc_flags & IMC_HSK_OK)
1687    {
1688        if (conn->imc_conn.cn_version > LSQVER_ID24
1689                                && 0 != imico_generate_handshake_done(conn))
1690            goto close_on_error;
1691        tick |= TICK_PROMOTE;
1692    }
1693
1694    if (imico_have_packets_to_send(conn, now))
1695        tick |= TICK_SEND;
1696    else
1697        tick |= TICK_QUIET;
1698
1699    LSQ_DEBUG("Return TICK %d", tick);
1700    return tick;
1701}
1702
1703
1704static void
1705ietf_mini_conn_ci_internal_error (struct lsquic_conn *lconn,
1706                                                    const char *format, ...)
1707{
1708    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1709    LSQ_INFO("internal error reported");
1710    conn->imc_flags |= IMC_ERROR;
1711}
1712
1713
1714static void
1715ietf_mini_conn_ci_abort_error (struct lsquic_conn *lconn, int is_app,
1716                                unsigned error_code, const char *fmt, ...)
1717{
1718    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1719    va_list ap;
1720    const char *err_str, *percent;
1721    char err_buf[0x100];
1722
1723    percent = strchr(fmt, '%');
1724    if (percent)
1725    {
1726        va_start(ap, fmt);
1727        vsnprintf(err_buf, sizeof(err_buf), fmt, ap);
1728        va_end(ap);
1729        err_str = err_buf;
1730    }
1731    else
1732        err_str = fmt;
1733    LSQ_INFO("abort error: is_app: %d; error code: %u; error str: %s",
1734        is_app, error_code, err_str);
1735    conn->imc_flags |= IMC_ERROR|IMC_ABORT_ERROR;
1736    if (is_app)
1737        conn->imc_flags |= IMC_ABORT_ISAPP;
1738    conn->imc_error_code = error_code;
1739}
1740
1741
1742static struct network_path *
1743ietf_mini_conn_ci_get_path (struct lsquic_conn *lconn,
1744                                                    const struct sockaddr *sa)
1745{
1746    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1747
1748    return &conn->imc_path;
1749}
1750
1751
1752static const lsquic_cid_t *
1753ietf_mini_conn_ci_get_log_cid (const struct lsquic_conn *lconn)
1754{
1755    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1756
1757    if (conn->imc_path.np_dcid.len)
1758        return &conn->imc_path.np_dcid;
1759    else
1760        return CN_SCID(lconn);
1761}
1762
1763
1764static unsigned char
1765ietf_mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
1766            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
1767{
1768    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
1769    const struct sockaddr *orig_peer_sa;
1770    struct lsquic_packet_out *packet_out;
1771    size_t len;
1772    char path_str[4][INET6_ADDRSTRLEN + sizeof(":65535")];
1773
1774    if (NP_IS_IPv6(&conn->imc_path) != (AF_INET6 == peer_sa->sa_family))
1775        TAILQ_FOREACH(packet_out, &conn->imc_packets_out, po_next)
1776            if ((packet_out->po_flags & (PO_SENT|PO_ENCRYPTED)) == PO_ENCRYPTED)
1777                imico_return_enc_data(conn, packet_out);
1778
1779    orig_peer_sa = NP_PEER_SA(&conn->imc_path);
1780    if (orig_peer_sa->sa_family == 0)
1781        LSQ_DEBUG("connection to %s from %s", SA2STR(local_sa, path_str[0]),
1782                                                SA2STR(peer_sa, path_str[1]));
1783    else if (!(lsquic_sockaddr_eq(NP_PEER_SA(&conn->imc_path), peer_sa)
1784              && lsquic_sockaddr_eq(NP_LOCAL_SA(&conn->imc_path), local_sa)))
1785    {
1786        LSQ_DEBUG("path changed from (%s - %s) to (%s - %s)",
1787            SA2STR(NP_LOCAL_SA(&conn->imc_path), path_str[0]),
1788            SA2STR(NP_PEER_SA(&conn->imc_path), path_str[1]),
1789            SA2STR(local_sa, path_str[2]),
1790            SA2STR(peer_sa, path_str[3]));
1791        conn->imc_flags |= IMC_PATH_CHANGED;
1792    }
1793
1794    len = local_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in)
1795                                                : sizeof(struct sockaddr_in6);
1796
1797    memcpy(conn->imc_path.np_peer_addr, peer_sa, len);
1798    memcpy(conn->imc_path.np_local_addr, local_sa, len);
1799    conn->imc_path.np_peer_ctx = peer_ctx;
1800    return 0;
1801}
1802
1803
1804static const struct conn_iface mini_conn_ietf_iface = {
1805    .ci_abort_error          =  ietf_mini_conn_ci_abort_error,
1806    .ci_client_call_on_new   =  ietf_mini_conn_ci_client_call_on_new,
1807    .ci_destroy              =  ietf_mini_conn_ci_destroy,
1808    .ci_get_engine           =  ietf_mini_conn_ci_get_engine,
1809    .ci_get_log_cid          =  ietf_mini_conn_ci_get_log_cid,
1810    .ci_get_path             =  ietf_mini_conn_ci_get_path,
1811    .ci_hsk_done             =  ietf_mini_conn_ci_hsk_done,
1812    .ci_internal_error       =  ietf_mini_conn_ci_internal_error,
1813    .ci_is_tickable          =  ietf_mini_conn_ci_is_tickable,
1814    .ci_next_packet_to_send  =  ietf_mini_conn_ci_next_packet_to_send,
1815    .ci_next_tick_time       =  ietf_mini_conn_ci_next_tick_time,
1816    .ci_packet_in            =  ietf_mini_conn_ci_packet_in,
1817    .ci_packet_not_sent      =  ietf_mini_conn_ci_packet_not_sent,
1818    .ci_packet_sent          =  ietf_mini_conn_ci_packet_sent,
1819    .ci_record_addrs         =  ietf_mini_conn_ci_record_addrs,
1820    .ci_tick                 =  ietf_mini_conn_ci_tick,
1821    .ci_tls_alert            =  ietf_mini_conn_ci_tls_alert,
1822};
1823