lsquic_pr_queue.c revision 03e6b668
15392f7a3SLiteSpeed Tech/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
25392f7a3SLiteSpeed Tech/*
35392f7a3SLiteSpeed Tech * lsquic_pr_queue.c -- packet request queue.
45392f7a3SLiteSpeed Tech */
55392f7a3SLiteSpeed Tech
65392f7a3SLiteSpeed Tech#include <assert.h>
75392f7a3SLiteSpeed Tech#include <errno.h>
85392f7a3SLiteSpeed Tech#include <inttypes.h>
95392f7a3SLiteSpeed Tech#include <netinet/in.h>
105392f7a3SLiteSpeed Tech#include <stdlib.h>
115392f7a3SLiteSpeed Tech#include <string.h>
125392f7a3SLiteSpeed Tech#include <sys/queue.h>
135392f7a3SLiteSpeed Tech#include <sys/socket.h>
145392f7a3SLiteSpeed Tech
155392f7a3SLiteSpeed Tech#include <openssl/aead.h>
165392f7a3SLiteSpeed Tech#include <openssl/rand.h>
175392f7a3SLiteSpeed Tech
185392f7a3SLiteSpeed Tech#include "lsquic.h"
195392f7a3SLiteSpeed Tech#include "lsquic_types.h"
205392f7a3SLiteSpeed Tech#include "lsquic_int_types.h"
215392f7a3SLiteSpeed Tech#include "lsquic_packet_common.h"
225392f7a3SLiteSpeed Tech#include "lsquic_packet_gquic.h"
235392f7a3SLiteSpeed Tech#include "lsquic_packet_out.h"
245392f7a3SLiteSpeed Tech#include "lsquic_packet_in.h"
255392f7a3SLiteSpeed Tech#include "lsquic_hash.h"
265392f7a3SLiteSpeed Tech#include "lsquic_conn.h"
275392f7a3SLiteSpeed Tech#include "lsquic_parse.h"
285392f7a3SLiteSpeed Tech#include "lsquic_malo.h"
295392f7a3SLiteSpeed Tech#include "lsquic_pr_queue.h"
305392f7a3SLiteSpeed Tech#include "lsquic_parse_common.h"
315392f7a3SLiteSpeed Tech#include "lsquic_tokgen.h"
325392f7a3SLiteSpeed Tech#include "lsquic_version.h"
335392f7a3SLiteSpeed Tech#include "lsquic_mm.h"
345392f7a3SLiteSpeed Tech#include "lsquic_engine_public.h"
355392f7a3SLiteSpeed Tech#include "lsquic_sizes.h"
365392f7a3SLiteSpeed Tech#include "lsquic_handshake.h"
3792f6e17bSDmitri Tikhonov#include "lsquic_xxhash.h"
385392f7a3SLiteSpeed Tech
395392f7a3SLiteSpeed Tech#define LSQUIC_LOGGER_MODULE LSQLM_PRQ
405392f7a3SLiteSpeed Tech#include "lsquic_logger.h"
415392f7a3SLiteSpeed Tech
425392f7a3SLiteSpeed Tech#define MAX(a, b) ((a) > (b) ? (a) : (b))
4392f6e17bSDmitri Tikhonov#define MIN(a, b) ((a) < (b) ? (a) : (b))
445392f7a3SLiteSpeed Tech
455392f7a3SLiteSpeed Tech
465392f7a3SLiteSpeed Techstatic const struct conn_iface evanescent_conn_iface;
475392f7a3SLiteSpeed Tech
485392f7a3SLiteSpeed Tech
495392f7a3SLiteSpeed Techstruct packet_req
505392f7a3SLiteSpeed Tech{
5192f6e17bSDmitri Tikhonov    struct lsquic_hash_elem     pr_hash_el;
525392f7a3SLiteSpeed Tech    lsquic_cid_t                pr_scid;
535392f7a3SLiteSpeed Tech    lsquic_cid_t                pr_dcid;
545392f7a3SLiteSpeed Tech    enum packet_req_type        pr_type;
5592f6e17bSDmitri Tikhonov    enum pr_flags {
565392f7a3SLiteSpeed Tech        PR_GQUIC    = 1 << 0,
575392f7a3SLiteSpeed Tech    }                           pr_flags;
585392f7a3SLiteSpeed Tech    enum lsquic_version         pr_version;
5992f6e17bSDmitri Tikhonov    unsigned                    pr_rst_sz;
605392f7a3SLiteSpeed Tech    struct network_path         pr_path;
615392f7a3SLiteSpeed Tech};
625392f7a3SLiteSpeed Tech
635392f7a3SLiteSpeed Tech
645392f7a3SLiteSpeed Techstruct evanescent_conn
655392f7a3SLiteSpeed Tech{
665392f7a3SLiteSpeed Tech    struct lsquic_conn          evc_conn;
675392f7a3SLiteSpeed Tech    struct packet_req          *evc_req;
685392f7a3SLiteSpeed Tech    struct pr_queue            *evc_queue;
695392f7a3SLiteSpeed Tech    struct lsquic_packet_out    evc_packet_out;
705392f7a3SLiteSpeed Tech    struct conn_cid_elem        evc_cces[1];
715392f7a3SLiteSpeed Tech    unsigned char               evc_buf[0];
725392f7a3SLiteSpeed Tech};
735392f7a3SLiteSpeed Tech
745392f7a3SLiteSpeed Tech
755392f7a3SLiteSpeed Tech/* [draft-ietf-quic-transport-22], Section 17.2.1 */
765392f7a3SLiteSpeed Tech#define IQUIC_VERNEG_SIZE (1 /* Type */ + 4 /* Version (zero tag) */ \
775392f7a3SLiteSpeed Tech                + 1 /* DCIL */ + MAX_CID_LEN + 1 /* SCIL */ + MAX_CID_LEN + \
785392f7a3SLiteSpeed Tech                4 * N_LSQVER)
795392f7a3SLiteSpeed Tech
805392f7a3SLiteSpeed Tech
815392f7a3SLiteSpeed Techstruct pr_queue
825392f7a3SLiteSpeed Tech{
835392f7a3SLiteSpeed Tech    TAILQ_HEAD(, lsquic_conn)   prq_free_conns,
845392f7a3SLiteSpeed Tech                                prq_returned_conns;
855392f7a3SLiteSpeed Tech    struct malo                *prq_reqs_pool;
865392f7a3SLiteSpeed Tech    const struct lsquic_engine_public
875392f7a3SLiteSpeed Tech                               *prq_enpub;
8892f6e17bSDmitri Tikhonov    struct lsquic_hash         *prq_reqs_hash;
895392f7a3SLiteSpeed Tech    unsigned                    prq_max_reqs;
905392f7a3SLiteSpeed Tech    unsigned                    prq_nreqs;
915392f7a3SLiteSpeed Tech    unsigned                    prq_max_conns;
925392f7a3SLiteSpeed Tech    unsigned                    prq_nconns;
935392f7a3SLiteSpeed Tech    unsigned                    prq_verneg_g_sz;  /* Size of prq_verneg_g_buf */
945392f7a3SLiteSpeed Tech    unsigned                    prq_pubres_g_sz;  /* Size of prq_pubres_g_buf */
955392f7a3SLiteSpeed Tech
965392f7a3SLiteSpeed Tech    /* GQUIC version negotiation and stateless reset packets are generated
975392f7a3SLiteSpeed Tech     * once, when the Packet Request Queue is created.  For each request,
985392f7a3SLiteSpeed Tech     * these buffers are simply copied and the connection ID is replaced.
995392f7a3SLiteSpeed Tech     *
1005392f7a3SLiteSpeed Tech     * Since IETF QUIC uses variable-length connections IDs, we have to
1015392f7a3SLiteSpeed Tech     * generate packets every time.
1025392f7a3SLiteSpeed Tech     */
1035392f7a3SLiteSpeed Tech    unsigned char               prq_pubres_g_buf[GQUIC_RESET_SZ];
1045392f7a3SLiteSpeed Tech    unsigned char               prq_verneg_g_buf[1 + GQUIC_CID_LEN
1055392f7a3SLiteSpeed Tech                                                                + N_LSQVER * 4];
106a0e1aeeeSDmitri Tikhonov    /* We generate random nybbles in batches */
107a0e1aeeeSDmitri Tikhonov#define NYBBLE_COUNT_BITS 4
108a0e1aeeeSDmitri Tikhonov#define NYBBLE_COUNT (1 << NYBBLE_COUNT_BITS)
109a0e1aeeeSDmitri Tikhonov#define NYBBLE_MASK (NYBBLE_COUNT - 1)
110a0e1aeeeSDmitri Tikhonov    unsigned                    prq_rand_nybble_off;
111a0e1aeeeSDmitri Tikhonov    uint8_t                     prq_rand_nybble_buf[NYBBLE_COUNT * 2];
1125392f7a3SLiteSpeed Tech};
1135392f7a3SLiteSpeed Tech
1145392f7a3SLiteSpeed Tech
115a0e1aeeeSDmitri Tikhonovstatic uint8_t
116a0e1aeeeSDmitri Tikhonovget_rand_byte (struct pr_queue *);
117a0e1aeeeSDmitri Tikhonov
118a0e1aeeeSDmitri Tikhonov
11992f6e17bSDmitri Tikhonovstatic int
12092f6e17bSDmitri Tikhonovcomp_reqs (const void *s1, const void *s2, size_t n)
12192f6e17bSDmitri Tikhonov{
12292f6e17bSDmitri Tikhonov    const struct packet_req *a, *b;
12392f6e17bSDmitri Tikhonov
12492f6e17bSDmitri Tikhonov    a = s1;
12592f6e17bSDmitri Tikhonov    b = s2;
12692f6e17bSDmitri Tikhonov    if (a->pr_type == b->pr_type && LSQUIC_CIDS_EQ(&a->pr_dcid, &b->pr_dcid))
12792f6e17bSDmitri Tikhonov        return 0;
12892f6e17bSDmitri Tikhonov    else
12992f6e17bSDmitri Tikhonov        return -1;
13092f6e17bSDmitri Tikhonov}
13192f6e17bSDmitri Tikhonov
13292f6e17bSDmitri Tikhonov
13392f6e17bSDmitri Tikhonovstatic unsigned
13492f6e17bSDmitri Tikhonovhash_req (const void *p, size_t len, unsigned seed)
13592f6e17bSDmitri Tikhonov{
13692f6e17bSDmitri Tikhonov    const struct packet_req *req;
13792f6e17bSDmitri Tikhonov
13892f6e17bSDmitri Tikhonov    req = p;
13992f6e17bSDmitri Tikhonov    return XXH32(req->pr_dcid.idbuf, req->pr_dcid.len, seed);
14092f6e17bSDmitri Tikhonov}
14192f6e17bSDmitri Tikhonov
14292f6e17bSDmitri Tikhonov
1435392f7a3SLiteSpeed Techstruct pr_queue *
1445392f7a3SLiteSpeed Techprq_create (unsigned max_elems, unsigned max_conns,
1455392f7a3SLiteSpeed Tech                        const struct lsquic_engine_public *enpub)
1465392f7a3SLiteSpeed Tech{
1475392f7a3SLiteSpeed Tech    const struct parse_funcs *pf;
1485392f7a3SLiteSpeed Tech    struct pr_queue *prq;
1495392f7a3SLiteSpeed Tech    struct malo *malo;
15092f6e17bSDmitri Tikhonov    struct lsquic_hash *hash;
1515392f7a3SLiteSpeed Tech    unsigned verneg_g_sz;
1525392f7a3SLiteSpeed Tech    ssize_t prst_g_sz;
1535392f7a3SLiteSpeed Tech    int len;
1545392f7a3SLiteSpeed Tech
1555392f7a3SLiteSpeed Tech    malo = lsquic_malo_create(sizeof(struct packet_req));
1565392f7a3SLiteSpeed Tech    if (!malo)
1575392f7a3SLiteSpeed Tech    {
1585392f7a3SLiteSpeed Tech        LSQ_WARN("malo_create failed: %s", strerror(errno));
1595392f7a3SLiteSpeed Tech        goto err0;
1605392f7a3SLiteSpeed Tech    }
1615392f7a3SLiteSpeed Tech
16292f6e17bSDmitri Tikhonov
16392f6e17bSDmitri Tikhonov    hash = lsquic_hash_create_ext(comp_reqs, hash_req);
16492f6e17bSDmitri Tikhonov    if (!hash)
16592f6e17bSDmitri Tikhonov    {
16692f6e17bSDmitri Tikhonov        LSQ_WARN("cannot create hash");
16792f6e17bSDmitri Tikhonov        goto err1;
16892f6e17bSDmitri Tikhonov    }
16992f6e17bSDmitri Tikhonov
1705392f7a3SLiteSpeed Tech    prq = malloc(sizeof(*prq));
1715392f7a3SLiteSpeed Tech    if (!prq)
1725392f7a3SLiteSpeed Tech    {
1735392f7a3SLiteSpeed Tech        LSQ_WARN("malloc failed: %s", strerror(errno));
17492f6e17bSDmitri Tikhonov        goto err2;
1755392f7a3SLiteSpeed Tech    }
1765392f7a3SLiteSpeed Tech
1775392f7a3SLiteSpeed Tech    const lsquic_cid_t cid = { .len = 8, };
1785392f7a3SLiteSpeed Tech    pf = select_pf_by_ver(LSQVER_039);
1795392f7a3SLiteSpeed Tech    len = lsquic_gquic_gen_ver_nego_pkt(prq->prq_verneg_g_buf,
1805392f7a3SLiteSpeed Tech                    sizeof(prq->prq_verneg_g_buf), &cid,
1815392f7a3SLiteSpeed Tech                    enpub->enp_settings.es_versions);
1825392f7a3SLiteSpeed Tech    assert(len > 0);
1835392f7a3SLiteSpeed Tech    if (len <= 0)
1845392f7a3SLiteSpeed Tech    {
1855392f7a3SLiteSpeed Tech        LSQ_ERROR("cannot generate version negotiation packet");
18692f6e17bSDmitri Tikhonov        goto err3;
1875392f7a3SLiteSpeed Tech    }
1885392f7a3SLiteSpeed Tech    verneg_g_sz = (unsigned) len;
1895392f7a3SLiteSpeed Tech
1905392f7a3SLiteSpeed Tech    prst_g_sz = pf->pf_generate_simple_prst(0 /* This is just placeholder */,
1915392f7a3SLiteSpeed Tech                                prq->prq_pubres_g_buf, sizeof(prq->prq_pubres_g_buf));
1925392f7a3SLiteSpeed Tech    if (prst_g_sz < 0)
1935392f7a3SLiteSpeed Tech    {
1945392f7a3SLiteSpeed Tech        LSQ_ERROR("cannot generate public reset packet");
19592f6e17bSDmitri Tikhonov        goto err3;
1965392f7a3SLiteSpeed Tech    }
1975392f7a3SLiteSpeed Tech
1985392f7a3SLiteSpeed Tech    TAILQ_INIT(&prq->prq_free_conns);
1995392f7a3SLiteSpeed Tech    TAILQ_INIT(&prq->prq_returned_conns);
20092f6e17bSDmitri Tikhonov    prq->prq_reqs_hash = hash;
2015392f7a3SLiteSpeed Tech    prq->prq_reqs_pool = malo;
2025392f7a3SLiteSpeed Tech    prq->prq_max_reqs = max_elems;
2035392f7a3SLiteSpeed Tech    prq->prq_nreqs = 0;
2045392f7a3SLiteSpeed Tech    prq->prq_max_conns = max_conns;
2055392f7a3SLiteSpeed Tech    prq->prq_nconns = 0;
2065392f7a3SLiteSpeed Tech    prq->prq_verneg_g_sz = verneg_g_sz;
2075392f7a3SLiteSpeed Tech    prq->prq_pubres_g_sz = (unsigned) prst_g_sz;
2085392f7a3SLiteSpeed Tech    prq->prq_enpub       = enpub;
209a0e1aeeeSDmitri Tikhonov    prq->prq_rand_nybble_off = 0;
2105392f7a3SLiteSpeed Tech
2115392f7a3SLiteSpeed Tech    LSQ_INFO("initialized queue of size %d", max_elems);
2125392f7a3SLiteSpeed Tech
2135392f7a3SLiteSpeed Tech    return prq;
2145392f7a3SLiteSpeed Tech
21592f6e17bSDmitri Tikhonov  err3:
2165392f7a3SLiteSpeed Tech    free(prq);
21792f6e17bSDmitri Tikhonov  err2:
21892f6e17bSDmitri Tikhonov    lsquic_hash_destroy(hash);
2195392f7a3SLiteSpeed Tech  err1:
2205392f7a3SLiteSpeed Tech    lsquic_malo_destroy(malo);
2215392f7a3SLiteSpeed Tech  err0:
2225392f7a3SLiteSpeed Tech    return NULL;
2235392f7a3SLiteSpeed Tech}
2245392f7a3SLiteSpeed Tech
2255392f7a3SLiteSpeed Tech
2265392f7a3SLiteSpeed Techvoid
2275392f7a3SLiteSpeed Techprq_destroy (struct pr_queue *prq)
2285392f7a3SLiteSpeed Tech{
2295392f7a3SLiteSpeed Tech    struct lsquic_conn *conn;
2305392f7a3SLiteSpeed Tech
2315392f7a3SLiteSpeed Tech    LSQ_INFO("destroy");
2325392f7a3SLiteSpeed Tech    while ((conn = TAILQ_FIRST(&prq->prq_free_conns)))
2335392f7a3SLiteSpeed Tech    {
2345392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_free_conns, conn, cn_next_pr);
2355392f7a3SLiteSpeed Tech        free(conn);
2365392f7a3SLiteSpeed Tech    }
23792f6e17bSDmitri Tikhonov    lsquic_hash_destroy(prq->prq_reqs_hash);
2385392f7a3SLiteSpeed Tech    lsquic_malo_destroy(prq->prq_reqs_pool);
2395392f7a3SLiteSpeed Tech    free(prq);
2405392f7a3SLiteSpeed Tech}
2415392f7a3SLiteSpeed Tech
2425392f7a3SLiteSpeed Tech
2435392f7a3SLiteSpeed Techstatic struct packet_req *
2445392f7a3SLiteSpeed Techget_req (struct pr_queue *prq)
2455392f7a3SLiteSpeed Tech{
2465392f7a3SLiteSpeed Tech    struct packet_req *req;
2475392f7a3SLiteSpeed Tech    if (prq->prq_nreqs < prq->prq_max_reqs)
2485392f7a3SLiteSpeed Tech    {
2495392f7a3SLiteSpeed Tech        req = lsquic_malo_get(prq->prq_reqs_pool);
2505392f7a3SLiteSpeed Tech        if (req)
2515392f7a3SLiteSpeed Tech            ++prq->prq_nreqs;
2525392f7a3SLiteSpeed Tech        else
2535392f7a3SLiteSpeed Tech            LSQ_WARN("malo_get failed: %s", strerror(errno));
2545392f7a3SLiteSpeed Tech        return req;
2555392f7a3SLiteSpeed Tech    }
2565392f7a3SLiteSpeed Tech    else
2575392f7a3SLiteSpeed Tech        return NULL;
2585392f7a3SLiteSpeed Tech}
2595392f7a3SLiteSpeed Tech
2605392f7a3SLiteSpeed Tech
2615392f7a3SLiteSpeed Techstatic void
2625392f7a3SLiteSpeed Techput_req (struct pr_queue *prq, struct packet_req *req)
2635392f7a3SLiteSpeed Tech{
2645392f7a3SLiteSpeed Tech    lsquic_malo_put(req);
2655392f7a3SLiteSpeed Tech    --prq->prq_nreqs;
2665392f7a3SLiteSpeed Tech}
2675392f7a3SLiteSpeed Tech
2685392f7a3SLiteSpeed Tech
2695392f7a3SLiteSpeed Techint
27003e6b668SDmitri Tikhonovlsquic_prq_new_req (struct pr_queue *prq, enum packet_req_type type,
27103e6b668SDmitri Tikhonov    unsigned flags, enum lsquic_version version, unsigned short data_sz,
27203e6b668SDmitri Tikhonov    const lsquic_cid_t *dcid, const lsquic_cid_t *scid, void *peer_ctx,
27303e6b668SDmitri Tikhonov    const struct sockaddr *local_addr, const struct sockaddr *peer_addr)
2745392f7a3SLiteSpeed Tech{
2755392f7a3SLiteSpeed Tech    struct packet_req *req;
276a0e1aeeeSDmitri Tikhonov    unsigned max, size, rand;
27792f6e17bSDmitri Tikhonov
27892f6e17bSDmitri Tikhonov    if (type == PACKET_REQ_PUBRES && !(flags & PR_GQUIC))
27992f6e17bSDmitri Tikhonov    {
28003e6b668SDmitri Tikhonov        if (data_sz <= IQUIC_MIN_SRST_SIZE)
28192f6e17bSDmitri Tikhonov        {
28292f6e17bSDmitri Tikhonov            LSQ_DEBUGC("not scheduling public reset: incoming packet for CID "
28303e6b668SDmitri Tikhonov                "%"CID_FMT" too small: %hu bytes", CID_BITS(dcid), data_sz);
28492f6e17bSDmitri Tikhonov            return -1;
28592f6e17bSDmitri Tikhonov        }
28692f6e17bSDmitri Tikhonov        /* Use a random stateless reset size */
28703e6b668SDmitri Tikhonov        max = MIN(IQUIC_MAX_SRST_SIZE, data_sz - 1u);
28892f6e17bSDmitri Tikhonov        if (max > IQUIC_MIN_SRST_SIZE)
289a0e1aeeeSDmitri Tikhonov        {
290a0e1aeeeSDmitri Tikhonov            rand = get_rand_byte(prq);
291a0e1aeeeSDmitri Tikhonov            size = IQUIC_MIN_SRST_SIZE + rand % (max - IQUIC_MIN_SRST_SIZE);
292a0e1aeeeSDmitri Tikhonov        }
29392f6e17bSDmitri Tikhonov        else
29492f6e17bSDmitri Tikhonov            size = IQUIC_MIN_SRST_SIZE;
29592f6e17bSDmitri Tikhonov        LSQ_DEBUGC("selected %u-byte reset size for CID %"CID_FMT
29603e6b668SDmitri Tikhonov            " (range is [%u, %u])", size, CID_BITS(dcid),
29792f6e17bSDmitri Tikhonov            IQUIC_MIN_SRST_SIZE, max);
29892f6e17bSDmitri Tikhonov    }
29992f6e17bSDmitri Tikhonov    else
30092f6e17bSDmitri Tikhonov        size = 0;
3015392f7a3SLiteSpeed Tech
3025392f7a3SLiteSpeed Tech    req = get_req(prq);
3035392f7a3SLiteSpeed Tech    if (!req)
3045392f7a3SLiteSpeed Tech    {
3055392f7a3SLiteSpeed Tech        LSQ_DEBUG("out of reqs: cannot allocated another one");
3065392f7a3SLiteSpeed Tech        return -1;
3075392f7a3SLiteSpeed Tech    }
3085392f7a3SLiteSpeed Tech
3095392f7a3SLiteSpeed Tech    req->pr_type     = type;
31003e6b668SDmitri Tikhonov    req->pr_dcid     = *dcid;
31192f6e17bSDmitri Tikhonov    if (lsquic_hash_find(prq->prq_reqs_hash, req, sizeof(req)))
31292f6e17bSDmitri Tikhonov    {
31392f6e17bSDmitri Tikhonov        LSQ_DEBUG("request for this DCID and type already exists");
31492f6e17bSDmitri Tikhonov        put_req(prq, req);
31592f6e17bSDmitri Tikhonov        return -1;
31692f6e17bSDmitri Tikhonov    }
31792f6e17bSDmitri Tikhonov
31892f6e17bSDmitri Tikhonov    req->pr_hash_el.qhe_flags = 0;
31992f6e17bSDmitri Tikhonov    if (!lsquic_hash_insert(prq->prq_reqs_hash, req, sizeof(req),
32092f6e17bSDmitri Tikhonov                                                    req, &req->pr_hash_el))
32192f6e17bSDmitri Tikhonov    {
32292f6e17bSDmitri Tikhonov        LSQ_DEBUG("could not insert req into hash");
32392f6e17bSDmitri Tikhonov        put_req(prq, req);
32492f6e17bSDmitri Tikhonov        return -1;
32592f6e17bSDmitri Tikhonov    }
32692f6e17bSDmitri Tikhonov
32792f6e17bSDmitri Tikhonov    req->pr_flags    = flags;
32892f6e17bSDmitri Tikhonov    req->pr_rst_sz   = size;
32992f6e17bSDmitri Tikhonov    req->pr_version  = version;
33003e6b668SDmitri Tikhonov    req->pr_scid     = *scid;
3315392f7a3SLiteSpeed Tech    req->pr_path.np_peer_ctx = peer_ctx;
3325392f7a3SLiteSpeed Tech    memcpy(NP_LOCAL_SA(&req->pr_path), local_addr,
3335392f7a3SLiteSpeed Tech                                            sizeof(req->pr_path.np_local_addr));
3345392f7a3SLiteSpeed Tech    memcpy(NP_PEER_SA(&req->pr_path), peer_addr,
3355392f7a3SLiteSpeed Tech                                            sizeof(req->pr_path.np_peer_addr));
33692f6e17bSDmitri Tikhonov
3375392f7a3SLiteSpeed Tech    LSQ_DEBUGC("scheduled %s packet for connection %"CID_FMT,
3385392f7a3SLiteSpeed Tech                            lsquic_preqt2str[type], CID_BITS(&req->pr_dcid));
3395392f7a3SLiteSpeed Tech    return 0;
3405392f7a3SLiteSpeed Tech}
3415392f7a3SLiteSpeed Tech
3425392f7a3SLiteSpeed Tech
34303e6b668SDmitri Tikhonovint
34403e6b668SDmitri Tikhonovprq_new_req (struct pr_queue *prq, enum packet_req_type type,
34503e6b668SDmitri Tikhonov         const struct lsquic_packet_in *packet_in, void *peer_ctx,
34603e6b668SDmitri Tikhonov         const struct sockaddr *local_addr, const struct sockaddr *peer_addr)
34703e6b668SDmitri Tikhonov{
34803e6b668SDmitri Tikhonov    lsquic_ver_tag_t ver_tag;
34903e6b668SDmitri Tikhonov    enum lsquic_version version;
35003e6b668SDmitri Tikhonov    enum pr_flags flags;
35103e6b668SDmitri Tikhonov    lsquic_cid_t scid;
35203e6b668SDmitri Tikhonov
35303e6b668SDmitri Tikhonov    if (packet_in->pi_flags & PI_GQUIC)
35403e6b668SDmitri Tikhonov        flags = PR_GQUIC;
35503e6b668SDmitri Tikhonov    else
35603e6b668SDmitri Tikhonov        flags = 0;
35703e6b668SDmitri Tikhonov
35803e6b668SDmitri Tikhonov    if (packet_in->pi_quic_ver)
35903e6b668SDmitri Tikhonov    {
36003e6b668SDmitri Tikhonov        memcpy(&ver_tag, packet_in->pi_data + packet_in->pi_quic_ver,
36103e6b668SDmitri Tikhonov                                                            sizeof(ver_tag));
36203e6b668SDmitri Tikhonov        version = lsquic_tag2ver(ver_tag);
36303e6b668SDmitri Tikhonov    }
36403e6b668SDmitri Tikhonov    else /* Got to set it to something sensible... */
36503e6b668SDmitri Tikhonov        version = LSQVER_ID24;
36603e6b668SDmitri Tikhonov
36703e6b668SDmitri Tikhonov    lsquic_scid_from_packet_in(packet_in, &scid);
36803e6b668SDmitri Tikhonov    return lsquic_prq_new_req(prq, type, flags, version, packet_in->pi_data_sz,
36903e6b668SDmitri Tikhonov                &packet_in->pi_dcid, &scid, peer_ctx, local_addr, peer_addr);
37003e6b668SDmitri Tikhonov}
37103e6b668SDmitri Tikhonov
37203e6b668SDmitri Tikhonov
3735392f7a3SLiteSpeed Techstatic size_t
3745392f7a3SLiteSpeed Techmax_bufsz (const struct pr_queue *prq)
3755392f7a3SLiteSpeed Tech{
3765392f7a3SLiteSpeed Tech    return  MAX(MAX(MAX(IQUIC_VERNEG_SIZE,
3775392f7a3SLiteSpeed Tech                        IQUIC_MIN_SRST_SIZE),
3785392f7a3SLiteSpeed Tech                        sizeof(prq->prq_verneg_g_buf)),
3795392f7a3SLiteSpeed Tech                        sizeof(prq->prq_pubres_g_buf));
3805392f7a3SLiteSpeed Tech}
3815392f7a3SLiteSpeed Tech
3825392f7a3SLiteSpeed Tech
3835392f7a3SLiteSpeed Techstatic struct evanescent_conn *
3845392f7a3SLiteSpeed Techget_evconn (struct pr_queue *prq)
3855392f7a3SLiteSpeed Tech{
3865392f7a3SLiteSpeed Tech    struct evanescent_conn *evconn;
3875392f7a3SLiteSpeed Tech    struct lsquic_conn *lconn;
3885392f7a3SLiteSpeed Tech    struct lsquic_packet_out *packet_out;
3895392f7a3SLiteSpeed Tech    size_t bufsz;
3905392f7a3SLiteSpeed Tech
3915392f7a3SLiteSpeed Tech    if (prq->prq_nconns >= prq->prq_max_conns)
3925392f7a3SLiteSpeed Tech    {   /* This deserves a warning */
3935392f7a3SLiteSpeed Tech        LSQ_WARN("tried to get connection past limit of %u", prq->prq_max_conns);
3945392f7a3SLiteSpeed Tech        return NULL;
3955392f7a3SLiteSpeed Tech    }
3965392f7a3SLiteSpeed Tech
3975392f7a3SLiteSpeed Tech    lconn = TAILQ_FIRST(&prq->prq_free_conns);
3985392f7a3SLiteSpeed Tech    if (lconn)
3995392f7a3SLiteSpeed Tech    {
4005392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_free_conns, lconn, cn_next_pr);
4015392f7a3SLiteSpeed Tech        return (struct evanescent_conn *) lconn;
4025392f7a3SLiteSpeed Tech    }
4035392f7a3SLiteSpeed Tech
4045392f7a3SLiteSpeed Tech    bufsz = max_bufsz(prq);
4055392f7a3SLiteSpeed Tech    evconn = calloc(1, sizeof(*evconn) + bufsz);
4065392f7a3SLiteSpeed Tech    if (!evconn)
4075392f7a3SLiteSpeed Tech    {
4085392f7a3SLiteSpeed Tech        LSQ_WARN("calloc failed: %s", strerror(errno));
4095392f7a3SLiteSpeed Tech        return NULL;
4105392f7a3SLiteSpeed Tech    }
4115392f7a3SLiteSpeed Tech
4125392f7a3SLiteSpeed Tech    /* These values stay the same between connection usages: */
4135392f7a3SLiteSpeed Tech    evconn->evc_queue = prq;
4145392f7a3SLiteSpeed Tech    lconn = &evconn->evc_conn;
4155392f7a3SLiteSpeed Tech    lconn->cn_cces = evconn->evc_cces;
4165392f7a3SLiteSpeed Tech    lconn->cn_cces_mask = 1;
4175392f7a3SLiteSpeed Tech    lconn->cn_n_cces = sizeof(evconn->evc_cces) / sizeof(evconn->evc_cces[0]);
4185392f7a3SLiteSpeed Tech    lconn->cn_if = &evanescent_conn_iface;
4195392f7a3SLiteSpeed Tech    lconn->cn_flags = LSCONN_EVANESCENT;
4205392f7a3SLiteSpeed Tech    packet_out = &evconn->evc_packet_out;
4215392f7a3SLiteSpeed Tech    packet_out->po_flags = PO_NOENCRYPT;
4225392f7a3SLiteSpeed Tech    packet_out->po_data = evconn->evc_buf;
4235392f7a3SLiteSpeed Tech
4245392f7a3SLiteSpeed Tech    return evconn;
4255392f7a3SLiteSpeed Tech}
4265392f7a3SLiteSpeed Tech
4275392f7a3SLiteSpeed Tech
428a0e1aeeeSDmitri Tikhonovstatic uint8_t
429a0e1aeeeSDmitri Tikhonovget_rand_nybble (struct pr_queue *prq)
430a0e1aeeeSDmitri Tikhonov{
431a0e1aeeeSDmitri Tikhonov    uint8_t byte;
432a0e1aeeeSDmitri Tikhonov
433a0e1aeeeSDmitri Tikhonov    if (prq->prq_rand_nybble_off == 0)
434a0e1aeeeSDmitri Tikhonov        RAND_bytes(prq->prq_rand_nybble_buf, sizeof(prq->prq_rand_nybble_buf));
435a0e1aeeeSDmitri Tikhonov
436a0e1aeeeSDmitri Tikhonov    byte = prq->prq_rand_nybble_buf[prq->prq_rand_nybble_off / 2];
437a0e1aeeeSDmitri Tikhonov    if (prq->prq_rand_nybble_off & 1)
438a0e1aeeeSDmitri Tikhonov        byte >>= 4;
439a0e1aeeeSDmitri Tikhonov    else
440a0e1aeeeSDmitri Tikhonov        byte &= 0xF;
441a0e1aeeeSDmitri Tikhonov    prq->prq_rand_nybble_off = (prq->prq_rand_nybble_off + 1) & NYBBLE_MASK;
442a0e1aeeeSDmitri Tikhonov    return byte;
443a0e1aeeeSDmitri Tikhonov}
444a0e1aeeeSDmitri Tikhonov
445a0e1aeeeSDmitri Tikhonov
446a0e1aeeeSDmitri Tikhonovstatic uint8_t
447a0e1aeeeSDmitri Tikhonovget_rand_byte (struct pr_queue *prq)
448a0e1aeeeSDmitri Tikhonov{
449a0e1aeeeSDmitri Tikhonov    return (get_rand_nybble(prq) << 4) | get_rand_nybble(prq);
450a0e1aeeeSDmitri Tikhonov}
451a0e1aeeeSDmitri Tikhonov
452a0e1aeeeSDmitri Tikhonov
4535392f7a3SLiteSpeed Techstruct lsquic_conn *
4545392f7a3SLiteSpeed Techprq_next_conn (struct pr_queue *prq)
4555392f7a3SLiteSpeed Tech{
4565392f7a3SLiteSpeed Tech    struct evanescent_conn *evconn;
4575392f7a3SLiteSpeed Tech    struct lsquic_conn *lconn;
45892f6e17bSDmitri Tikhonov    struct lsquic_hash_elem *el;
4595392f7a3SLiteSpeed Tech    struct packet_req *req;
4605392f7a3SLiteSpeed Tech    struct lsquic_packet_out *packet_out;
4615392f7a3SLiteSpeed Tech    int (*gen_verneg) (unsigned char *, size_t, const lsquic_cid_t *,
462a0e1aeeeSDmitri Tikhonov                                    const lsquic_cid_t *, unsigned, uint8_t);
4635392f7a3SLiteSpeed Tech    int len;
4645392f7a3SLiteSpeed Tech
4655392f7a3SLiteSpeed Tech    lconn = TAILQ_FIRST(&prq->prq_returned_conns);
4665392f7a3SLiteSpeed Tech    if (lconn)
4675392f7a3SLiteSpeed Tech    {
4685392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_returned_conns, lconn, cn_next_pr);
4695392f7a3SLiteSpeed Tech        return lconn;
4705392f7a3SLiteSpeed Tech    }
4715392f7a3SLiteSpeed Tech
47292f6e17bSDmitri Tikhonov    el = lsquic_hash_first(prq->prq_reqs_hash);
47392f6e17bSDmitri Tikhonov    if (!el)           /* Nothing is queued */
4745392f7a3SLiteSpeed Tech        return NULL;
4755392f7a3SLiteSpeed Tech
4765392f7a3SLiteSpeed Tech    evconn = get_evconn(prq);
4775392f7a3SLiteSpeed Tech    if (!evconn)         /* Reached limit or malloc failed */
4785392f7a3SLiteSpeed Tech        return NULL;
4795392f7a3SLiteSpeed Tech
48092f6e17bSDmitri Tikhonov    req = lsquic_hashelem_getdata(el);
4815392f7a3SLiteSpeed Tech    packet_out = &evconn->evc_packet_out;
4825392f7a3SLiteSpeed Tech    switch ((req->pr_type << 29) | req->pr_flags)
4835392f7a3SLiteSpeed Tech    {
4845392f7a3SLiteSpeed Tech    case (PACKET_REQ_VERNEG << 29) | PR_GQUIC:
4855392f7a3SLiteSpeed Tech        packet_out->po_data_sz = prq->prq_verneg_g_sz;
4865392f7a3SLiteSpeed Tech        packet_out->po_flags |= PO_VERNEG;
4875392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data, prq->prq_verneg_g_buf,
4885392f7a3SLiteSpeed Tech                                                    prq->prq_verneg_g_sz);
4895392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data + 1, req->pr_dcid.idbuf, GQUIC_CID_LEN);
4905392f7a3SLiteSpeed Tech        break;
4915392f7a3SLiteSpeed Tech    case (PACKET_REQ_PUBRES << 29) | PR_GQUIC:
4925392f7a3SLiteSpeed Tech        packet_out->po_flags &= ~PO_VERNEG;
4935392f7a3SLiteSpeed Tech        packet_out->po_data_sz = prq->prq_pubres_g_sz;
4945392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data, prq->prq_pubres_g_buf,
4955392f7a3SLiteSpeed Tech                                                    prq->prq_pubres_g_sz);
4965392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data + 1, req->pr_dcid.idbuf, GQUIC_CID_LEN);
4975392f7a3SLiteSpeed Tech        break;
4985392f7a3SLiteSpeed Tech    case (PACKET_REQ_VERNEG << 29) | 0:
4995392f7a3SLiteSpeed Tech        packet_out->po_flags |= PO_VERNEG;
5005392f7a3SLiteSpeed Tech        if (req->pr_version == LSQVER_046)
5015392f7a3SLiteSpeed Tech            gen_verneg = lsquic_Q046_gen_ver_nego_pkt;
5025392f7a3SLiteSpeed Tech        else
5035392f7a3SLiteSpeed Tech            gen_verneg = lsquic_ietf_v1_gen_ver_nego_pkt;
5045392f7a3SLiteSpeed Tech        len = gen_verneg(packet_out->po_data, max_bufsz(prq),
5055392f7a3SLiteSpeed Tech                    /* Flip SCID/DCID here: */ &req->pr_dcid, &req->pr_scid,
506a0e1aeeeSDmitri Tikhonov                    prq->prq_enpub->enp_settings.es_versions,
5071c9cee3eSDmitri Tikhonov                    get_rand_byte(prq));
5085392f7a3SLiteSpeed Tech        if (len > 0)
5095392f7a3SLiteSpeed Tech            packet_out->po_data_sz = len;
5105392f7a3SLiteSpeed Tech        else
5115392f7a3SLiteSpeed Tech            packet_out->po_data_sz = 0;
5125392f7a3SLiteSpeed Tech        break;
5135392f7a3SLiteSpeed Tech    default:
5145392f7a3SLiteSpeed Tech        packet_out->po_flags &= ~PO_VERNEG;
51592f6e17bSDmitri Tikhonov        packet_out->po_data_sz = req->pr_rst_sz;
51692f6e17bSDmitri Tikhonov        RAND_bytes(packet_out->po_data, req->pr_rst_sz - IQUIC_SRESET_TOKEN_SZ);
5175392f7a3SLiteSpeed Tech        packet_out->po_data[0] &= ~0x80;
5185392f7a3SLiteSpeed Tech        packet_out->po_data[0] |=  0x40;
5195392f7a3SLiteSpeed Tech        lsquic_tg_generate_sreset(prq->prq_enpub->enp_tokgen, &req->pr_dcid,
52092f6e17bSDmitri Tikhonov            packet_out->po_data + req->pr_rst_sz - IQUIC_SRESET_TOKEN_SZ);
5215392f7a3SLiteSpeed Tech        break;
5225392f7a3SLiteSpeed Tech    }
5235392f7a3SLiteSpeed Tech
52492f6e17bSDmitri Tikhonov    lsquic_hash_erase(prq->prq_reqs_hash, el);
5255392f7a3SLiteSpeed Tech    evconn->evc_req = req;
5265392f7a3SLiteSpeed Tech
5275392f7a3SLiteSpeed Tech    lconn= &evconn->evc_conn;
5285392f7a3SLiteSpeed Tech    evconn->evc_cces[0].cce_cid = req->pr_dcid;
5295392f7a3SLiteSpeed Tech    packet_out->po_path = &req->pr_path;
5305392f7a3SLiteSpeed Tech
5315392f7a3SLiteSpeed Tech    ++prq->prq_nconns;
5325392f7a3SLiteSpeed Tech    return lconn;
5335392f7a3SLiteSpeed Tech}
5345392f7a3SLiteSpeed Tech
5355392f7a3SLiteSpeed Tech
5365392f7a3SLiteSpeed Techint
5375392f7a3SLiteSpeed Techprq_have_pending (const struct pr_queue *prq)
5385392f7a3SLiteSpeed Tech{
53992f6e17bSDmitri Tikhonov    return lsquic_hash_count(prq->prq_reqs_hash) > 0;
5405392f7a3SLiteSpeed Tech}
5415392f7a3SLiteSpeed Tech
5425392f7a3SLiteSpeed Tech
5435392f7a3SLiteSpeed Techstatic struct lsquic_packet_out *
5445392f7a3SLiteSpeed Techevanescent_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
5455392f7a3SLiteSpeed Tech{
5465392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5475392f7a3SLiteSpeed Tech    assert(size == 0);
5485392f7a3SLiteSpeed Tech    return &evconn->evc_packet_out;
5495392f7a3SLiteSpeed Tech}
5505392f7a3SLiteSpeed Tech
5515392f7a3SLiteSpeed Tech
5525392f7a3SLiteSpeed Techstatic void
5535392f7a3SLiteSpeed Techevanescent_conn_ci_packet_sent (struct lsquic_conn *lconn,
5545392f7a3SLiteSpeed Tech                            struct lsquic_packet_out *packet_out)
5555392f7a3SLiteSpeed Tech{
5565392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5575392f7a3SLiteSpeed Tech    struct pr_queue *const prq = evconn->evc_queue;
5585392f7a3SLiteSpeed Tech
5595392f7a3SLiteSpeed Tech    assert(packet_out == &evconn->evc_packet_out);
5605392f7a3SLiteSpeed Tech    assert(prq->prq_nconns > 0);
5615392f7a3SLiteSpeed Tech
5625392f7a3SLiteSpeed Tech    LSQ_DEBUGC("sent %s packet for connection %"CID_FMT"; free resources",
5635392f7a3SLiteSpeed Tech        lsquic_preqt2str[ evconn->evc_req->pr_type ],
5645392f7a3SLiteSpeed Tech        CID_BITS(&evconn->evc_req->pr_dcid));
5655392f7a3SLiteSpeed Tech    TAILQ_INSERT_HEAD(&prq->prq_free_conns, lconn, cn_next_pr);
5665392f7a3SLiteSpeed Tech    put_req(prq, evconn->evc_req);
5675392f7a3SLiteSpeed Tech    --prq->prq_nconns;
5685392f7a3SLiteSpeed Tech}
5695392f7a3SLiteSpeed Tech
5705392f7a3SLiteSpeed Tech
5715392f7a3SLiteSpeed Techstatic void
5725392f7a3SLiteSpeed Techevanescent_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
5735392f7a3SLiteSpeed Tech                                struct lsquic_packet_out *packet_out)
5745392f7a3SLiteSpeed Tech{
5755392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5765392f7a3SLiteSpeed Tech    struct pr_queue *const prq = evconn->evc_queue;
5775392f7a3SLiteSpeed Tech
5785392f7a3SLiteSpeed Tech    assert(packet_out == &evconn->evc_packet_out);
5795392f7a3SLiteSpeed Tech    assert(prq->prq_nconns > 0);
5805392f7a3SLiteSpeed Tech
5815392f7a3SLiteSpeed Tech    LSQ_DEBUG("packet not sent; put connection onto used list");
5825392f7a3SLiteSpeed Tech    TAILQ_INSERT_HEAD(&prq->prq_returned_conns, lconn, cn_next_pr);
5835392f7a3SLiteSpeed Tech}
5845392f7a3SLiteSpeed Tech
5855392f7a3SLiteSpeed Tech
5865392f7a3SLiteSpeed Techstatic enum tick_st
5875392f7a3SLiteSpeed Techevanescent_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
5885392f7a3SLiteSpeed Tech{
5895392f7a3SLiteSpeed Tech    assert(0);
5905392f7a3SLiteSpeed Tech    return TICK_CLOSE;
5915392f7a3SLiteSpeed Tech}
5925392f7a3SLiteSpeed Tech
5935392f7a3SLiteSpeed Tech
5945392f7a3SLiteSpeed Techstatic void
5955392f7a3SLiteSpeed Techevanescent_conn_ci_destroy (struct lsquic_conn *lconn)
5965392f7a3SLiteSpeed Tech{
5975392f7a3SLiteSpeed Tech    assert(0);
5985392f7a3SLiteSpeed Tech}
5995392f7a3SLiteSpeed Tech
6005392f7a3SLiteSpeed Tech
6015392f7a3SLiteSpeed Techstatic struct lsquic_engine *
6025392f7a3SLiteSpeed Techevanescent_conn_ci_get_engine (struct lsquic_conn *lconn)
6035392f7a3SLiteSpeed Tech{
6045392f7a3SLiteSpeed Tech    assert(0);
6055392f7a3SLiteSpeed Tech    return NULL;
6065392f7a3SLiteSpeed Tech}
6075392f7a3SLiteSpeed Tech
6085392f7a3SLiteSpeed Tech
6095392f7a3SLiteSpeed Techstatic void
6105392f7a3SLiteSpeed Techevanescent_conn_ci_hsk_done (struct lsquic_conn *lconn,
6115392f7a3SLiteSpeed Tech                                                enum lsquic_hsk_status status)
6125392f7a3SLiteSpeed Tech{
6135392f7a3SLiteSpeed Tech    assert(0);
6145392f7a3SLiteSpeed Tech}
6155392f7a3SLiteSpeed Tech
6165392f7a3SLiteSpeed Tech
6175392f7a3SLiteSpeed Techstatic void
6185392f7a3SLiteSpeed Techevanescent_conn_ci_packet_in (struct lsquic_conn *lconn,
6195392f7a3SLiteSpeed Tech                          struct lsquic_packet_in *packet_in)
6205392f7a3SLiteSpeed Tech{
6215392f7a3SLiteSpeed Tech    assert(0);
6225392f7a3SLiteSpeed Tech}
6235392f7a3SLiteSpeed Tech
6245392f7a3SLiteSpeed Tech
6255392f7a3SLiteSpeed Techstatic void
6265392f7a3SLiteSpeed Techevanescent_conn_ci_client_call_on_new (struct lsquic_conn *lconn)
6275392f7a3SLiteSpeed Tech{
6285392f7a3SLiteSpeed Tech    assert(0);
6295392f7a3SLiteSpeed Tech}
6305392f7a3SLiteSpeed Tech
6315392f7a3SLiteSpeed Tech
6325392f7a3SLiteSpeed Techstatic struct network_path *
6335392f7a3SLiteSpeed Techevanescent_conn_ci_get_path (struct lsquic_conn *lconn,
6345392f7a3SLiteSpeed Tech                                                    const struct sockaddr *sa)
6355392f7a3SLiteSpeed Tech{
6365392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
6375392f7a3SLiteSpeed Tech
6385392f7a3SLiteSpeed Tech    return &evconn->evc_req->pr_path;
6395392f7a3SLiteSpeed Tech}
6405392f7a3SLiteSpeed Tech
6415392f7a3SLiteSpeed Tech
6425392f7a3SLiteSpeed Techstatic unsigned char
6435392f7a3SLiteSpeed Techevanescent_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
6445392f7a3SLiteSpeed Tech            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
6455392f7a3SLiteSpeed Tech{
6465392f7a3SLiteSpeed Tech    assert(0);
6475392f7a3SLiteSpeed Tech    return 0;
6485392f7a3SLiteSpeed Tech}
6495392f7a3SLiteSpeed Tech
6505392f7a3SLiteSpeed Tech
6515392f7a3SLiteSpeed Techstatic const struct conn_iface evanescent_conn_iface = {
6525392f7a3SLiteSpeed Tech    .ci_client_call_on_new   =  evanescent_conn_ci_client_call_on_new,
6535392f7a3SLiteSpeed Tech    .ci_destroy              =  evanescent_conn_ci_destroy,
6545392f7a3SLiteSpeed Tech    .ci_get_engine           =  evanescent_conn_ci_get_engine,
6555392f7a3SLiteSpeed Tech    .ci_get_path             =  evanescent_conn_ci_get_path,
6565392f7a3SLiteSpeed Tech    .ci_hsk_done             =  evanescent_conn_ci_hsk_done,
6575392f7a3SLiteSpeed Tech    .ci_next_packet_to_send  =  evanescent_conn_ci_next_packet_to_send,
6585392f7a3SLiteSpeed Tech    .ci_packet_in            =  evanescent_conn_ci_packet_in,
6595392f7a3SLiteSpeed Tech    .ci_packet_not_sent      =  evanescent_conn_ci_packet_not_sent,
6605392f7a3SLiteSpeed Tech    .ci_packet_sent          =  evanescent_conn_ci_packet_sent,
6615392f7a3SLiteSpeed Tech    .ci_record_addrs         =  evanescent_conn_ci_record_addrs,
6625392f7a3SLiteSpeed Tech    .ci_tick                 =  evanescent_conn_ci_tick,
6635392f7a3SLiteSpeed Tech};
6645392f7a3SLiteSpeed Tech
6655392f7a3SLiteSpeed Tech
6665392f7a3SLiteSpeed Techconst char *const lsquic_preqt2str[] =
6675392f7a3SLiteSpeed Tech{
6685392f7a3SLiteSpeed Tech    [PACKET_REQ_VERNEG] = "version negotiation",
6695392f7a3SLiteSpeed Tech    [PACKET_REQ_PUBRES] = "stateless reset",
6705392f7a3SLiteSpeed Tech};
671