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