lsquic_pr_queue.c revision 7d09751d
17d09751dSDmitri Tikhonov/* Copyright (c) 2017 - 2020 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];
717ee41525SDmitri Tikhonov    enum {
727ee41525SDmitri Tikhonov        EVC_DROP    = 1 << 0,
737ee41525SDmitri Tikhonov    }                           evc_flags;
745392f7a3SLiteSpeed Tech    unsigned char               evc_buf[0];
755392f7a3SLiteSpeed Tech};
765392f7a3SLiteSpeed Tech
775392f7a3SLiteSpeed Tech
785392f7a3SLiteSpeed Tech/* [draft-ietf-quic-transport-22], Section 17.2.1 */
795392f7a3SLiteSpeed Tech#define IQUIC_VERNEG_SIZE (1 /* Type */ + 4 /* Version (zero tag) */ \
805392f7a3SLiteSpeed Tech                + 1 /* DCIL */ + MAX_CID_LEN + 1 /* SCIL */ + MAX_CID_LEN + \
815392f7a3SLiteSpeed Tech                4 * N_LSQVER)
825392f7a3SLiteSpeed Tech
835392f7a3SLiteSpeed Tech
845392f7a3SLiteSpeed Techstruct pr_queue
855392f7a3SLiteSpeed Tech{
865392f7a3SLiteSpeed Tech    TAILQ_HEAD(, lsquic_conn)   prq_free_conns,
875392f7a3SLiteSpeed Tech                                prq_returned_conns;
885392f7a3SLiteSpeed Tech    struct malo                *prq_reqs_pool;
895392f7a3SLiteSpeed Tech    const struct lsquic_engine_public
905392f7a3SLiteSpeed Tech                               *prq_enpub;
9192f6e17bSDmitri Tikhonov    struct lsquic_hash         *prq_reqs_hash;
925392f7a3SLiteSpeed Tech    unsigned                    prq_max_reqs;
935392f7a3SLiteSpeed Tech    unsigned                    prq_nreqs;
945392f7a3SLiteSpeed Tech    unsigned                    prq_max_conns;
955392f7a3SLiteSpeed Tech    unsigned                    prq_nconns;
965392f7a3SLiteSpeed Tech    unsigned                    prq_verneg_g_sz;  /* Size of prq_verneg_g_buf */
975392f7a3SLiteSpeed Tech    unsigned                    prq_pubres_g_sz;  /* Size of prq_pubres_g_buf */
985392f7a3SLiteSpeed Tech
995392f7a3SLiteSpeed Tech    /* GQUIC version negotiation and stateless reset packets are generated
1005392f7a3SLiteSpeed Tech     * once, when the Packet Request Queue is created.  For each request,
1015392f7a3SLiteSpeed Tech     * these buffers are simply copied and the connection ID is replaced.
1025392f7a3SLiteSpeed Tech     *
1035392f7a3SLiteSpeed Tech     * Since IETF QUIC uses variable-length connections IDs, we have to
1045392f7a3SLiteSpeed Tech     * generate packets every time.
1055392f7a3SLiteSpeed Tech     */
1065392f7a3SLiteSpeed Tech    unsigned char               prq_pubres_g_buf[GQUIC_RESET_SZ];
1075392f7a3SLiteSpeed Tech    unsigned char               prq_verneg_g_buf[1 + GQUIC_CID_LEN
1085392f7a3SLiteSpeed Tech                                                                + N_LSQVER * 4];
109a0e1aeeeSDmitri Tikhonov    /* We generate random nybbles in batches */
110a0e1aeeeSDmitri Tikhonov#define NYBBLE_COUNT_BITS 4
111a0e1aeeeSDmitri Tikhonov#define NYBBLE_COUNT (1 << NYBBLE_COUNT_BITS)
112a0e1aeeeSDmitri Tikhonov#define NYBBLE_MASK (NYBBLE_COUNT - 1)
113a0e1aeeeSDmitri Tikhonov    unsigned                    prq_rand_nybble_off;
114a0e1aeeeSDmitri Tikhonov    uint8_t                     prq_rand_nybble_buf[NYBBLE_COUNT * 2];
1155392f7a3SLiteSpeed Tech};
1165392f7a3SLiteSpeed Tech
1175392f7a3SLiteSpeed Tech
118a0e1aeeeSDmitri Tikhonovstatic uint8_t
119a0e1aeeeSDmitri Tikhonovget_rand_byte (struct pr_queue *);
120a0e1aeeeSDmitri Tikhonov
121a0e1aeeeSDmitri Tikhonov
12292f6e17bSDmitri Tikhonovstatic int
12392f6e17bSDmitri Tikhonovcomp_reqs (const void *s1, const void *s2, size_t n)
12492f6e17bSDmitri Tikhonov{
12592f6e17bSDmitri Tikhonov    const struct packet_req *a, *b;
12692f6e17bSDmitri Tikhonov
12792f6e17bSDmitri Tikhonov    a = s1;
12892f6e17bSDmitri Tikhonov    b = s2;
12992f6e17bSDmitri Tikhonov    if (a->pr_type == b->pr_type && LSQUIC_CIDS_EQ(&a->pr_dcid, &b->pr_dcid))
13092f6e17bSDmitri Tikhonov        return 0;
13192f6e17bSDmitri Tikhonov    else
13292f6e17bSDmitri Tikhonov        return -1;
13392f6e17bSDmitri Tikhonov}
13492f6e17bSDmitri Tikhonov
13592f6e17bSDmitri Tikhonov
13692f6e17bSDmitri Tikhonovstatic unsigned
13792f6e17bSDmitri Tikhonovhash_req (const void *p, size_t len, unsigned seed)
13892f6e17bSDmitri Tikhonov{
13992f6e17bSDmitri Tikhonov    const struct packet_req *req;
14092f6e17bSDmitri Tikhonov
14192f6e17bSDmitri Tikhonov    req = p;
14292f6e17bSDmitri Tikhonov    return XXH32(req->pr_dcid.idbuf, req->pr_dcid.len, seed);
14392f6e17bSDmitri Tikhonov}
14492f6e17bSDmitri Tikhonov
14592f6e17bSDmitri Tikhonov
1465392f7a3SLiteSpeed Techstruct pr_queue *
1475392f7a3SLiteSpeed Techprq_create (unsigned max_elems, unsigned max_conns,
1485392f7a3SLiteSpeed Tech                        const struct lsquic_engine_public *enpub)
1495392f7a3SLiteSpeed Tech{
1505392f7a3SLiteSpeed Tech    const struct parse_funcs *pf;
1515392f7a3SLiteSpeed Tech    struct pr_queue *prq;
1525392f7a3SLiteSpeed Tech    struct malo *malo;
15392f6e17bSDmitri Tikhonov    struct lsquic_hash *hash;
1545392f7a3SLiteSpeed Tech    unsigned verneg_g_sz;
1555392f7a3SLiteSpeed Tech    ssize_t prst_g_sz;
1565392f7a3SLiteSpeed Tech    int len;
1575392f7a3SLiteSpeed Tech
1585392f7a3SLiteSpeed Tech    malo = lsquic_malo_create(sizeof(struct packet_req));
1595392f7a3SLiteSpeed Tech    if (!malo)
1605392f7a3SLiteSpeed Tech    {
1615392f7a3SLiteSpeed Tech        LSQ_WARN("malo_create failed: %s", strerror(errno));
1625392f7a3SLiteSpeed Tech        goto err0;
1635392f7a3SLiteSpeed Tech    }
1645392f7a3SLiteSpeed Tech
16592f6e17bSDmitri Tikhonov
16692f6e17bSDmitri Tikhonov    hash = lsquic_hash_create_ext(comp_reqs, hash_req);
16792f6e17bSDmitri Tikhonov    if (!hash)
16892f6e17bSDmitri Tikhonov    {
16992f6e17bSDmitri Tikhonov        LSQ_WARN("cannot create hash");
17092f6e17bSDmitri Tikhonov        goto err1;
17192f6e17bSDmitri Tikhonov    }
17292f6e17bSDmitri Tikhonov
1735392f7a3SLiteSpeed Tech    prq = malloc(sizeof(*prq));
1745392f7a3SLiteSpeed Tech    if (!prq)
1755392f7a3SLiteSpeed Tech    {
1765392f7a3SLiteSpeed Tech        LSQ_WARN("malloc failed: %s", strerror(errno));
17792f6e17bSDmitri Tikhonov        goto err2;
1785392f7a3SLiteSpeed Tech    }
1795392f7a3SLiteSpeed Tech
1805392f7a3SLiteSpeed Tech    const lsquic_cid_t cid = { .len = 8, };
1815392f7a3SLiteSpeed Tech    pf = select_pf_by_ver(LSQVER_039);
1825392f7a3SLiteSpeed Tech    len = lsquic_gquic_gen_ver_nego_pkt(prq->prq_verneg_g_buf,
1835392f7a3SLiteSpeed Tech                    sizeof(prq->prq_verneg_g_buf), &cid,
1845392f7a3SLiteSpeed Tech                    enpub->enp_settings.es_versions);
1855392f7a3SLiteSpeed Tech    assert(len > 0);
1865392f7a3SLiteSpeed Tech    if (len <= 0)
1875392f7a3SLiteSpeed Tech    {
1885392f7a3SLiteSpeed Tech        LSQ_ERROR("cannot generate version negotiation packet");
18992f6e17bSDmitri Tikhonov        goto err3;
1905392f7a3SLiteSpeed Tech    }
1915392f7a3SLiteSpeed Tech    verneg_g_sz = (unsigned) len;
1925392f7a3SLiteSpeed Tech
1935392f7a3SLiteSpeed Tech    prst_g_sz = pf->pf_generate_simple_prst(0 /* This is just placeholder */,
1945392f7a3SLiteSpeed Tech                                prq->prq_pubres_g_buf, sizeof(prq->prq_pubres_g_buf));
1955392f7a3SLiteSpeed Tech    if (prst_g_sz < 0)
1965392f7a3SLiteSpeed Tech    {
1975392f7a3SLiteSpeed Tech        LSQ_ERROR("cannot generate public reset packet");
19892f6e17bSDmitri Tikhonov        goto err3;
1995392f7a3SLiteSpeed Tech    }
2005392f7a3SLiteSpeed Tech
2015392f7a3SLiteSpeed Tech    TAILQ_INIT(&prq->prq_free_conns);
2025392f7a3SLiteSpeed Tech    TAILQ_INIT(&prq->prq_returned_conns);
20392f6e17bSDmitri Tikhonov    prq->prq_reqs_hash = hash;
2045392f7a3SLiteSpeed Tech    prq->prq_reqs_pool = malo;
2055392f7a3SLiteSpeed Tech    prq->prq_max_reqs = max_elems;
2065392f7a3SLiteSpeed Tech    prq->prq_nreqs = 0;
2075392f7a3SLiteSpeed Tech    prq->prq_max_conns = max_conns;
2085392f7a3SLiteSpeed Tech    prq->prq_nconns = 0;
2095392f7a3SLiteSpeed Tech    prq->prq_verneg_g_sz = verneg_g_sz;
2105392f7a3SLiteSpeed Tech    prq->prq_pubres_g_sz = (unsigned) prst_g_sz;
2115392f7a3SLiteSpeed Tech    prq->prq_enpub       = enpub;
212a0e1aeeeSDmitri Tikhonov    prq->prq_rand_nybble_off = 0;
2135392f7a3SLiteSpeed Tech
2145392f7a3SLiteSpeed Tech    LSQ_INFO("initialized queue of size %d", max_elems);
2155392f7a3SLiteSpeed Tech
2165392f7a3SLiteSpeed Tech    return prq;
2175392f7a3SLiteSpeed Tech
21892f6e17bSDmitri Tikhonov  err3:
2195392f7a3SLiteSpeed Tech    free(prq);
22092f6e17bSDmitri Tikhonov  err2:
22192f6e17bSDmitri Tikhonov    lsquic_hash_destroy(hash);
2225392f7a3SLiteSpeed Tech  err1:
2235392f7a3SLiteSpeed Tech    lsquic_malo_destroy(malo);
2245392f7a3SLiteSpeed Tech  err0:
2255392f7a3SLiteSpeed Tech    return NULL;
2265392f7a3SLiteSpeed Tech}
2275392f7a3SLiteSpeed Tech
2285392f7a3SLiteSpeed Tech
2295392f7a3SLiteSpeed Techvoid
2305392f7a3SLiteSpeed Techprq_destroy (struct pr_queue *prq)
2315392f7a3SLiteSpeed Tech{
2325392f7a3SLiteSpeed Tech    struct lsquic_conn *conn;
2335392f7a3SLiteSpeed Tech
2345392f7a3SLiteSpeed Tech    LSQ_INFO("destroy");
2355392f7a3SLiteSpeed Tech    while ((conn = TAILQ_FIRST(&prq->prq_free_conns)))
2365392f7a3SLiteSpeed Tech    {
2375392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_free_conns, conn, cn_next_pr);
2385392f7a3SLiteSpeed Tech        free(conn);
2395392f7a3SLiteSpeed Tech    }
24092f6e17bSDmitri Tikhonov    lsquic_hash_destroy(prq->prq_reqs_hash);
2415392f7a3SLiteSpeed Tech    lsquic_malo_destroy(prq->prq_reqs_pool);
2425392f7a3SLiteSpeed Tech    free(prq);
2435392f7a3SLiteSpeed Tech}
2445392f7a3SLiteSpeed Tech
2455392f7a3SLiteSpeed Tech
2465392f7a3SLiteSpeed Techstatic struct packet_req *
2475392f7a3SLiteSpeed Techget_req (struct pr_queue *prq)
2485392f7a3SLiteSpeed Tech{
2495392f7a3SLiteSpeed Tech    struct packet_req *req;
2505392f7a3SLiteSpeed Tech    if (prq->prq_nreqs < prq->prq_max_reqs)
2515392f7a3SLiteSpeed Tech    {
2525392f7a3SLiteSpeed Tech        req = lsquic_malo_get(prq->prq_reqs_pool);
2535392f7a3SLiteSpeed Tech        if (req)
2545392f7a3SLiteSpeed Tech            ++prq->prq_nreqs;
2555392f7a3SLiteSpeed Tech        else
2565392f7a3SLiteSpeed Tech            LSQ_WARN("malo_get failed: %s", strerror(errno));
2575392f7a3SLiteSpeed Tech        return req;
2585392f7a3SLiteSpeed Tech    }
2595392f7a3SLiteSpeed Tech    else
2605392f7a3SLiteSpeed Tech        return NULL;
2615392f7a3SLiteSpeed Tech}
2625392f7a3SLiteSpeed Tech
2635392f7a3SLiteSpeed Tech
2645392f7a3SLiteSpeed Techstatic void
2655392f7a3SLiteSpeed Techput_req (struct pr_queue *prq, struct packet_req *req)
2665392f7a3SLiteSpeed Tech{
2675392f7a3SLiteSpeed Tech    lsquic_malo_put(req);
2685392f7a3SLiteSpeed Tech    --prq->prq_nreqs;
2695392f7a3SLiteSpeed Tech}
2705392f7a3SLiteSpeed Tech
2715392f7a3SLiteSpeed Tech
2725392f7a3SLiteSpeed Techint
27303e6b668SDmitri Tikhonovlsquic_prq_new_req (struct pr_queue *prq, enum packet_req_type type,
27403e6b668SDmitri Tikhonov    unsigned flags, enum lsquic_version version, unsigned short data_sz,
27503e6b668SDmitri Tikhonov    const lsquic_cid_t *dcid, const lsquic_cid_t *scid, void *peer_ctx,
27603e6b668SDmitri Tikhonov    const struct sockaddr *local_addr, const struct sockaddr *peer_addr)
2775392f7a3SLiteSpeed Tech{
2785392f7a3SLiteSpeed Tech    struct packet_req *req;
279a0e1aeeeSDmitri Tikhonov    unsigned max, size, rand;
28092f6e17bSDmitri Tikhonov
28192f6e17bSDmitri Tikhonov    if (type == PACKET_REQ_PUBRES && !(flags & PR_GQUIC))
28292f6e17bSDmitri Tikhonov    {
28303e6b668SDmitri Tikhonov        if (data_sz <= IQUIC_MIN_SRST_SIZE)
28492f6e17bSDmitri Tikhonov        {
28592f6e17bSDmitri Tikhonov            LSQ_DEBUGC("not scheduling public reset: incoming packet for CID "
28603e6b668SDmitri Tikhonov                "%"CID_FMT" too small: %hu bytes", CID_BITS(dcid), data_sz);
28792f6e17bSDmitri Tikhonov            return -1;
28892f6e17bSDmitri Tikhonov        }
28992f6e17bSDmitri Tikhonov        /* Use a random stateless reset size */
29003e6b668SDmitri Tikhonov        max = MIN(IQUIC_MAX_SRST_SIZE, data_sz - 1u);
29192f6e17bSDmitri Tikhonov        if (max > IQUIC_MIN_SRST_SIZE)
292a0e1aeeeSDmitri Tikhonov        {
293a0e1aeeeSDmitri Tikhonov            rand = get_rand_byte(prq);
294a0e1aeeeSDmitri Tikhonov            size = IQUIC_MIN_SRST_SIZE + rand % (max - IQUIC_MIN_SRST_SIZE);
295a0e1aeeeSDmitri Tikhonov        }
29692f6e17bSDmitri Tikhonov        else
29792f6e17bSDmitri Tikhonov            size = IQUIC_MIN_SRST_SIZE;
29892f6e17bSDmitri Tikhonov        LSQ_DEBUGC("selected %u-byte reset size for CID %"CID_FMT
29903e6b668SDmitri Tikhonov            " (range is [%u, %u])", size, CID_BITS(dcid),
30092f6e17bSDmitri Tikhonov            IQUIC_MIN_SRST_SIZE, max);
30192f6e17bSDmitri Tikhonov    }
30292f6e17bSDmitri Tikhonov    else
30392f6e17bSDmitri Tikhonov        size = 0;
3045392f7a3SLiteSpeed Tech
3055392f7a3SLiteSpeed Tech    req = get_req(prq);
3065392f7a3SLiteSpeed Tech    if (!req)
3075392f7a3SLiteSpeed Tech    {
3085392f7a3SLiteSpeed Tech        LSQ_DEBUG("out of reqs: cannot allocated another one");
3095392f7a3SLiteSpeed Tech        return -1;
3105392f7a3SLiteSpeed Tech    }
3115392f7a3SLiteSpeed Tech
3125392f7a3SLiteSpeed Tech    req->pr_type     = type;
31303e6b668SDmitri Tikhonov    req->pr_dcid     = *dcid;
31472bbf1fbSDmitri Tikhonov    if (lsquic_hash_find(prq->prq_reqs_hash, req, sizeof(*req)))
31592f6e17bSDmitri Tikhonov    {
31692f6e17bSDmitri Tikhonov        LSQ_DEBUG("request for this DCID and type already exists");
31792f6e17bSDmitri Tikhonov        put_req(prq, req);
31892f6e17bSDmitri Tikhonov        return -1;
31992f6e17bSDmitri Tikhonov    }
32092f6e17bSDmitri Tikhonov
32192f6e17bSDmitri Tikhonov    req->pr_hash_el.qhe_flags = 0;
32272bbf1fbSDmitri Tikhonov    if (!lsquic_hash_insert(prq->prq_reqs_hash, req, sizeof(*req),
32392f6e17bSDmitri Tikhonov                                                    req, &req->pr_hash_el))
32492f6e17bSDmitri Tikhonov    {
32592f6e17bSDmitri Tikhonov        LSQ_DEBUG("could not insert req into hash");
32692f6e17bSDmitri Tikhonov        put_req(prq, req);
32792f6e17bSDmitri Tikhonov        return -1;
32892f6e17bSDmitri Tikhonov    }
32992f6e17bSDmitri Tikhonov
33092f6e17bSDmitri Tikhonov    req->pr_flags    = flags;
33192f6e17bSDmitri Tikhonov    req->pr_rst_sz   = size;
33292f6e17bSDmitri Tikhonov    req->pr_version  = version;
33303e6b668SDmitri Tikhonov    req->pr_scid     = *scid;
3345392f7a3SLiteSpeed Tech    req->pr_path.np_peer_ctx = peer_ctx;
33572bbf1fbSDmitri Tikhonov    memcpy(req->pr_path.np_local_addr, local_addr,
3365392f7a3SLiteSpeed Tech                                            sizeof(req->pr_path.np_local_addr));
3375392f7a3SLiteSpeed Tech    memcpy(NP_PEER_SA(&req->pr_path), peer_addr,
3385392f7a3SLiteSpeed Tech                                            sizeof(req->pr_path.np_peer_addr));
33992f6e17bSDmitri Tikhonov
3405392f7a3SLiteSpeed Tech    LSQ_DEBUGC("scheduled %s packet for connection %"CID_FMT,
3415392f7a3SLiteSpeed Tech                            lsquic_preqt2str[type], CID_BITS(&req->pr_dcid));
3425392f7a3SLiteSpeed Tech    return 0;
3435392f7a3SLiteSpeed Tech}
3445392f7a3SLiteSpeed Tech
3455392f7a3SLiteSpeed Tech
34603e6b668SDmitri Tikhonovint
34703e6b668SDmitri Tikhonovprq_new_req (struct pr_queue *prq, enum packet_req_type type,
34803e6b668SDmitri Tikhonov         const struct lsquic_packet_in *packet_in, void *peer_ctx,
34903e6b668SDmitri Tikhonov         const struct sockaddr *local_addr, const struct sockaddr *peer_addr)
35003e6b668SDmitri Tikhonov{
35103e6b668SDmitri Tikhonov    lsquic_ver_tag_t ver_tag;
35203e6b668SDmitri Tikhonov    enum lsquic_version version;
35303e6b668SDmitri Tikhonov    enum pr_flags flags;
35403e6b668SDmitri Tikhonov    lsquic_cid_t scid;
35503e6b668SDmitri Tikhonov
35603e6b668SDmitri Tikhonov    if (packet_in->pi_flags & PI_GQUIC)
35703e6b668SDmitri Tikhonov        flags = PR_GQUIC;
35803e6b668SDmitri Tikhonov    else
35903e6b668SDmitri Tikhonov        flags = 0;
36003e6b668SDmitri Tikhonov
36103e6b668SDmitri Tikhonov    if (packet_in->pi_quic_ver)
36203e6b668SDmitri Tikhonov    {
36303e6b668SDmitri Tikhonov        memcpy(&ver_tag, packet_in->pi_data + packet_in->pi_quic_ver,
36403e6b668SDmitri Tikhonov                                                            sizeof(ver_tag));
36503e6b668SDmitri Tikhonov        version = lsquic_tag2ver(ver_tag);
36603e6b668SDmitri Tikhonov    }
36703e6b668SDmitri Tikhonov    else /* Got to set it to something sensible... */
36803e6b668SDmitri Tikhonov        version = LSQVER_ID24;
36903e6b668SDmitri Tikhonov
37003e6b668SDmitri Tikhonov    lsquic_scid_from_packet_in(packet_in, &scid);
37103e6b668SDmitri Tikhonov    return lsquic_prq_new_req(prq, type, flags, version, packet_in->pi_data_sz,
37203e6b668SDmitri Tikhonov                &packet_in->pi_dcid, &scid, peer_ctx, local_addr, peer_addr);
37303e6b668SDmitri Tikhonov}
37403e6b668SDmitri Tikhonov
37503e6b668SDmitri Tikhonov
3765392f7a3SLiteSpeed Techstatic size_t
3775392f7a3SLiteSpeed Techmax_bufsz (const struct pr_queue *prq)
3785392f7a3SLiteSpeed Tech{
3795392f7a3SLiteSpeed Tech    return  MAX(MAX(MAX(IQUIC_VERNEG_SIZE,
3805392f7a3SLiteSpeed Tech                        IQUIC_MIN_SRST_SIZE),
3815392f7a3SLiteSpeed Tech                        sizeof(prq->prq_verneg_g_buf)),
3825392f7a3SLiteSpeed Tech                        sizeof(prq->prq_pubres_g_buf));
3835392f7a3SLiteSpeed Tech}
3845392f7a3SLiteSpeed Tech
3855392f7a3SLiteSpeed Tech
3865392f7a3SLiteSpeed Techstatic struct evanescent_conn *
3875392f7a3SLiteSpeed Techget_evconn (struct pr_queue *prq)
3885392f7a3SLiteSpeed Tech{
3895392f7a3SLiteSpeed Tech    struct evanescent_conn *evconn;
3905392f7a3SLiteSpeed Tech    struct lsquic_conn *lconn;
3915392f7a3SLiteSpeed Tech    struct lsquic_packet_out *packet_out;
3925392f7a3SLiteSpeed Tech    size_t bufsz;
3935392f7a3SLiteSpeed Tech
3945392f7a3SLiteSpeed Tech    if (prq->prq_nconns >= prq->prq_max_conns)
3955392f7a3SLiteSpeed Tech    {   /* This deserves a warning */
3965392f7a3SLiteSpeed Tech        LSQ_WARN("tried to get connection past limit of %u", prq->prq_max_conns);
3975392f7a3SLiteSpeed Tech        return NULL;
3985392f7a3SLiteSpeed Tech    }
3995392f7a3SLiteSpeed Tech
4005392f7a3SLiteSpeed Tech    lconn = TAILQ_FIRST(&prq->prq_free_conns);
4015392f7a3SLiteSpeed Tech    if (lconn)
4025392f7a3SLiteSpeed Tech    {
4035392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_free_conns, lconn, cn_next_pr);
4047ee41525SDmitri Tikhonov        evconn = (struct evanescent_conn *) lconn;
4057ee41525SDmitri Tikhonov        evconn->evc_flags = 0;
4067ee41525SDmitri Tikhonov        return evconn;
4075392f7a3SLiteSpeed Tech    }
4085392f7a3SLiteSpeed Tech
4095392f7a3SLiteSpeed Tech    bufsz = max_bufsz(prq);
4105392f7a3SLiteSpeed Tech    evconn = calloc(1, sizeof(*evconn) + bufsz);
4115392f7a3SLiteSpeed Tech    if (!evconn)
4125392f7a3SLiteSpeed Tech    {
4135392f7a3SLiteSpeed Tech        LSQ_WARN("calloc failed: %s", strerror(errno));
4145392f7a3SLiteSpeed Tech        return NULL;
4155392f7a3SLiteSpeed Tech    }
4165392f7a3SLiteSpeed Tech
4175392f7a3SLiteSpeed Tech    /* These values stay the same between connection usages: */
4185392f7a3SLiteSpeed Tech    evconn->evc_queue = prq;
4195392f7a3SLiteSpeed Tech    lconn = &evconn->evc_conn;
4205392f7a3SLiteSpeed Tech    lconn->cn_cces = evconn->evc_cces;
4215392f7a3SLiteSpeed Tech    lconn->cn_cces_mask = 1;
4225392f7a3SLiteSpeed Tech    lconn->cn_n_cces = sizeof(evconn->evc_cces) / sizeof(evconn->evc_cces[0]);
4235392f7a3SLiteSpeed Tech    lconn->cn_if = &evanescent_conn_iface;
4245392f7a3SLiteSpeed Tech    lconn->cn_flags = LSCONN_EVANESCENT;
4255392f7a3SLiteSpeed Tech    packet_out = &evconn->evc_packet_out;
4265392f7a3SLiteSpeed Tech    packet_out->po_flags = PO_NOENCRYPT;
4275392f7a3SLiteSpeed Tech    packet_out->po_data = evconn->evc_buf;
4285392f7a3SLiteSpeed Tech
4295392f7a3SLiteSpeed Tech    return evconn;
4305392f7a3SLiteSpeed Tech}
4315392f7a3SLiteSpeed Tech
4325392f7a3SLiteSpeed Tech
433a0e1aeeeSDmitri Tikhonovstatic uint8_t
434a0e1aeeeSDmitri Tikhonovget_rand_nybble (struct pr_queue *prq)
435a0e1aeeeSDmitri Tikhonov{
436a0e1aeeeSDmitri Tikhonov    uint8_t byte;
437a0e1aeeeSDmitri Tikhonov
438a0e1aeeeSDmitri Tikhonov    if (prq->prq_rand_nybble_off == 0)
439a0e1aeeeSDmitri Tikhonov        RAND_bytes(prq->prq_rand_nybble_buf, sizeof(prq->prq_rand_nybble_buf));
440a0e1aeeeSDmitri Tikhonov
441a0e1aeeeSDmitri Tikhonov    byte = prq->prq_rand_nybble_buf[prq->prq_rand_nybble_off / 2];
442a0e1aeeeSDmitri Tikhonov    if (prq->prq_rand_nybble_off & 1)
443a0e1aeeeSDmitri Tikhonov        byte >>= 4;
444a0e1aeeeSDmitri Tikhonov    else
445a0e1aeeeSDmitri Tikhonov        byte &= 0xF;
446a0e1aeeeSDmitri Tikhonov    prq->prq_rand_nybble_off = (prq->prq_rand_nybble_off + 1) & NYBBLE_MASK;
447a0e1aeeeSDmitri Tikhonov    return byte;
448a0e1aeeeSDmitri Tikhonov}
449a0e1aeeeSDmitri Tikhonov
450a0e1aeeeSDmitri Tikhonov
451a0e1aeeeSDmitri Tikhonovstatic uint8_t
452a0e1aeeeSDmitri Tikhonovget_rand_byte (struct pr_queue *prq)
453a0e1aeeeSDmitri Tikhonov{
454a0e1aeeeSDmitri Tikhonov    return (get_rand_nybble(prq) << 4) | get_rand_nybble(prq);
455a0e1aeeeSDmitri Tikhonov}
456a0e1aeeeSDmitri Tikhonov
457a0e1aeeeSDmitri Tikhonov
4585392f7a3SLiteSpeed Techstruct lsquic_conn *
4595392f7a3SLiteSpeed Techprq_next_conn (struct pr_queue *prq)
4605392f7a3SLiteSpeed Tech{
4615392f7a3SLiteSpeed Tech    struct evanescent_conn *evconn;
4625392f7a3SLiteSpeed Tech    struct lsquic_conn *lconn;
46392f6e17bSDmitri Tikhonov    struct lsquic_hash_elem *el;
4645392f7a3SLiteSpeed Tech    struct packet_req *req;
4655392f7a3SLiteSpeed Tech    struct lsquic_packet_out *packet_out;
4665392f7a3SLiteSpeed Tech    int (*gen_verneg) (unsigned char *, size_t, const lsquic_cid_t *,
467a0e1aeeeSDmitri Tikhonov                                    const lsquic_cid_t *, unsigned, uint8_t);
4685392f7a3SLiteSpeed Tech    int len;
4695392f7a3SLiteSpeed Tech
4705392f7a3SLiteSpeed Tech    lconn = TAILQ_FIRST(&prq->prq_returned_conns);
4715392f7a3SLiteSpeed Tech    if (lconn)
4725392f7a3SLiteSpeed Tech    {
4735392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_returned_conns, lconn, cn_next_pr);
4745392f7a3SLiteSpeed Tech        return lconn;
4755392f7a3SLiteSpeed Tech    }
4765392f7a3SLiteSpeed Tech
47792f6e17bSDmitri Tikhonov    el = lsquic_hash_first(prq->prq_reqs_hash);
47892f6e17bSDmitri Tikhonov    if (!el)           /* Nothing is queued */
4795392f7a3SLiteSpeed Tech        return NULL;
4805392f7a3SLiteSpeed Tech
4815392f7a3SLiteSpeed Tech    evconn = get_evconn(prq);
4825392f7a3SLiteSpeed Tech    if (!evconn)         /* Reached limit or malloc failed */
4835392f7a3SLiteSpeed Tech        return NULL;
4845392f7a3SLiteSpeed Tech
48592f6e17bSDmitri Tikhonov    req = lsquic_hashelem_getdata(el);
4865392f7a3SLiteSpeed Tech    packet_out = &evconn->evc_packet_out;
4875392f7a3SLiteSpeed Tech    switch ((req->pr_type << 29) | req->pr_flags)
4885392f7a3SLiteSpeed Tech    {
4895392f7a3SLiteSpeed Tech    case (PACKET_REQ_VERNEG << 29) | PR_GQUIC:
4905392f7a3SLiteSpeed Tech        packet_out->po_data_sz = prq->prq_verneg_g_sz;
4915392f7a3SLiteSpeed Tech        packet_out->po_flags |= PO_VERNEG;
4925392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data, prq->prq_verneg_g_buf,
4935392f7a3SLiteSpeed Tech                                                    prq->prq_verneg_g_sz);
4945392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data + 1, req->pr_dcid.idbuf, GQUIC_CID_LEN);
4955392f7a3SLiteSpeed Tech        break;
4965392f7a3SLiteSpeed Tech    case (PACKET_REQ_PUBRES << 29) | PR_GQUIC:
4975392f7a3SLiteSpeed Tech        packet_out->po_flags &= ~PO_VERNEG;
4985392f7a3SLiteSpeed Tech        packet_out->po_data_sz = prq->prq_pubres_g_sz;
4995392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data, prq->prq_pubres_g_buf,
5005392f7a3SLiteSpeed Tech                                                    prq->prq_pubres_g_sz);
5015392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data + 1, req->pr_dcid.idbuf, GQUIC_CID_LEN);
5025392f7a3SLiteSpeed Tech        break;
5035392f7a3SLiteSpeed Tech    case (PACKET_REQ_VERNEG << 29) | 0:
5045392f7a3SLiteSpeed Tech        packet_out->po_flags |= PO_VERNEG;
5055392f7a3SLiteSpeed Tech        if (req->pr_version == LSQVER_046)
5065392f7a3SLiteSpeed Tech            gen_verneg = lsquic_Q046_gen_ver_nego_pkt;
5075392f7a3SLiteSpeed Tech        else
5085392f7a3SLiteSpeed Tech            gen_verneg = lsquic_ietf_v1_gen_ver_nego_pkt;
5095392f7a3SLiteSpeed Tech        len = gen_verneg(packet_out->po_data, max_bufsz(prq),
5105392f7a3SLiteSpeed Tech                    /* Flip SCID/DCID here: */ &req->pr_dcid, &req->pr_scid,
511a0e1aeeeSDmitri Tikhonov                    prq->prq_enpub->enp_settings.es_versions,
5121c9cee3eSDmitri Tikhonov                    get_rand_byte(prq));
5135392f7a3SLiteSpeed Tech        if (len > 0)
5145392f7a3SLiteSpeed Tech            packet_out->po_data_sz = len;
5155392f7a3SLiteSpeed Tech        else
5165392f7a3SLiteSpeed Tech            packet_out->po_data_sz = 0;
5175392f7a3SLiteSpeed Tech        break;
5185392f7a3SLiteSpeed Tech    default:
5195392f7a3SLiteSpeed Tech        packet_out->po_flags &= ~PO_VERNEG;
52092f6e17bSDmitri Tikhonov        packet_out->po_data_sz = req->pr_rst_sz;
52192f6e17bSDmitri Tikhonov        RAND_bytes(packet_out->po_data, req->pr_rst_sz - IQUIC_SRESET_TOKEN_SZ);
5225392f7a3SLiteSpeed Tech        packet_out->po_data[0] &= ~0x80;
5235392f7a3SLiteSpeed Tech        packet_out->po_data[0] |=  0x40;
5245392f7a3SLiteSpeed Tech        lsquic_tg_generate_sreset(prq->prq_enpub->enp_tokgen, &req->pr_dcid,
52592f6e17bSDmitri Tikhonov            packet_out->po_data + req->pr_rst_sz - IQUIC_SRESET_TOKEN_SZ);
5265392f7a3SLiteSpeed Tech        break;
5275392f7a3SLiteSpeed Tech    }
5285392f7a3SLiteSpeed Tech
52992f6e17bSDmitri Tikhonov    lsquic_hash_erase(prq->prq_reqs_hash, el);
5305392f7a3SLiteSpeed Tech    evconn->evc_req = req;
5315392f7a3SLiteSpeed Tech
5325392f7a3SLiteSpeed Tech    lconn= &evconn->evc_conn;
5335392f7a3SLiteSpeed Tech    evconn->evc_cces[0].cce_cid = req->pr_dcid;
5345392f7a3SLiteSpeed Tech    packet_out->po_path = &req->pr_path;
5355392f7a3SLiteSpeed Tech
5365392f7a3SLiteSpeed Tech    ++prq->prq_nconns;
5375392f7a3SLiteSpeed Tech    return lconn;
5385392f7a3SLiteSpeed Tech}
5395392f7a3SLiteSpeed Tech
5405392f7a3SLiteSpeed Tech
5415392f7a3SLiteSpeed Techint
5425392f7a3SLiteSpeed Techprq_have_pending (const struct pr_queue *prq)
5435392f7a3SLiteSpeed Tech{
54492f6e17bSDmitri Tikhonov    return lsquic_hash_count(prq->prq_reqs_hash) > 0;
5455392f7a3SLiteSpeed Tech}
5465392f7a3SLiteSpeed Tech
5475392f7a3SLiteSpeed Tech
5485392f7a3SLiteSpeed Techstatic struct lsquic_packet_out *
5495392f7a3SLiteSpeed Techevanescent_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
5505392f7a3SLiteSpeed Tech{
5515392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5525392f7a3SLiteSpeed Tech    assert(size == 0);
5535392f7a3SLiteSpeed Tech    return &evconn->evc_packet_out;
5545392f7a3SLiteSpeed Tech}
5555392f7a3SLiteSpeed Tech
5565392f7a3SLiteSpeed Tech
5575392f7a3SLiteSpeed Techstatic void
5587ee41525SDmitri Tikhonovprq_free_conn (struct pr_queue *prq, struct lsquic_conn *lconn)
5597ee41525SDmitri Tikhonov{
5607ee41525SDmitri Tikhonov    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5617ee41525SDmitri Tikhonov
5627ee41525SDmitri Tikhonov    TAILQ_INSERT_HEAD(&prq->prq_free_conns, lconn, cn_next_pr);
5637ee41525SDmitri Tikhonov    put_req(prq, evconn->evc_req);
5647ee41525SDmitri Tikhonov    --prq->prq_nconns;
5657ee41525SDmitri Tikhonov}
5667ee41525SDmitri Tikhonov
5677ee41525SDmitri Tikhonov
5687ee41525SDmitri Tikhonovstatic void
5695392f7a3SLiteSpeed Techevanescent_conn_ci_packet_sent (struct lsquic_conn *lconn,
5705392f7a3SLiteSpeed Tech                            struct lsquic_packet_out *packet_out)
5715392f7a3SLiteSpeed Tech{
5725392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5735392f7a3SLiteSpeed Tech    struct pr_queue *const prq = evconn->evc_queue;
5745392f7a3SLiteSpeed Tech
5755392f7a3SLiteSpeed Tech    assert(packet_out == &evconn->evc_packet_out);
5765392f7a3SLiteSpeed Tech    assert(prq->prq_nconns > 0);
5775392f7a3SLiteSpeed Tech
5785392f7a3SLiteSpeed Tech    LSQ_DEBUGC("sent %s packet for connection %"CID_FMT"; free resources",
5795392f7a3SLiteSpeed Tech        lsquic_preqt2str[ evconn->evc_req->pr_type ],
5805392f7a3SLiteSpeed Tech        CID_BITS(&evconn->evc_req->pr_dcid));
5817ee41525SDmitri Tikhonov    prq_free_conn(prq, lconn);
5825392f7a3SLiteSpeed Tech}
5835392f7a3SLiteSpeed Tech
5845392f7a3SLiteSpeed Tech
5855392f7a3SLiteSpeed Techstatic void
5865392f7a3SLiteSpeed Techevanescent_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
5875392f7a3SLiteSpeed Tech                                struct lsquic_packet_out *packet_out)
5885392f7a3SLiteSpeed Tech{
5895392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5905392f7a3SLiteSpeed Tech    struct pr_queue *const prq = evconn->evc_queue;
5915392f7a3SLiteSpeed Tech
5925392f7a3SLiteSpeed Tech    assert(packet_out == &evconn->evc_packet_out);
5935392f7a3SLiteSpeed Tech    assert(prq->prq_nconns > 0);
5945392f7a3SLiteSpeed Tech
5957ee41525SDmitri Tikhonov    if (evconn->evc_flags & EVC_DROP)
5967ee41525SDmitri Tikhonov    {
5977ee41525SDmitri Tikhonov        LSQ_DEBUGC("packet not sent; drop connection %"CID_FMT,
5987ee41525SDmitri Tikhonov                                        CID_BITS(&evconn->evc_req->pr_dcid));
5997ee41525SDmitri Tikhonov        prq_free_conn(prq, lconn);
6007ee41525SDmitri Tikhonov    }
6017ee41525SDmitri Tikhonov    else
6027ee41525SDmitri Tikhonov    {
6037ee41525SDmitri Tikhonov        LSQ_DEBUG("packet not sent; put connection onto used list");
6047ee41525SDmitri Tikhonov        TAILQ_INSERT_HEAD(&prq->prq_returned_conns, lconn, cn_next_pr);
6057ee41525SDmitri Tikhonov    }
6065392f7a3SLiteSpeed Tech}
6075392f7a3SLiteSpeed Tech
6085392f7a3SLiteSpeed Tech
6095392f7a3SLiteSpeed Techstatic enum tick_st
6105392f7a3SLiteSpeed Techevanescent_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
6115392f7a3SLiteSpeed Tech{
6125392f7a3SLiteSpeed Tech    assert(0);
6135392f7a3SLiteSpeed Tech    return TICK_CLOSE;
6145392f7a3SLiteSpeed Tech}
6155392f7a3SLiteSpeed Tech
6165392f7a3SLiteSpeed Tech
6175392f7a3SLiteSpeed Techstatic void
6185392f7a3SLiteSpeed Techevanescent_conn_ci_destroy (struct lsquic_conn *lconn)
6195392f7a3SLiteSpeed Tech{
6205392f7a3SLiteSpeed Tech    assert(0);
6215392f7a3SLiteSpeed Tech}
6225392f7a3SLiteSpeed Tech
6235392f7a3SLiteSpeed Tech
6245392f7a3SLiteSpeed Techstatic struct lsquic_engine *
6255392f7a3SLiteSpeed Techevanescent_conn_ci_get_engine (struct lsquic_conn *lconn)
6265392f7a3SLiteSpeed Tech{
6275392f7a3SLiteSpeed Tech    assert(0);
6285392f7a3SLiteSpeed Tech    return NULL;
6295392f7a3SLiteSpeed Tech}
6305392f7a3SLiteSpeed Tech
6315392f7a3SLiteSpeed Tech
6325392f7a3SLiteSpeed Techstatic void
6335392f7a3SLiteSpeed Techevanescent_conn_ci_hsk_done (struct lsquic_conn *lconn,
6345392f7a3SLiteSpeed Tech                                                enum lsquic_hsk_status status)
6355392f7a3SLiteSpeed Tech{
6365392f7a3SLiteSpeed Tech    assert(0);
6375392f7a3SLiteSpeed Tech}
6385392f7a3SLiteSpeed Tech
6395392f7a3SLiteSpeed Tech
6405392f7a3SLiteSpeed Techstatic void
6415392f7a3SLiteSpeed Techevanescent_conn_ci_packet_in (struct lsquic_conn *lconn,
6425392f7a3SLiteSpeed Tech                          struct lsquic_packet_in *packet_in)
6435392f7a3SLiteSpeed Tech{
6445392f7a3SLiteSpeed Tech    assert(0);
6455392f7a3SLiteSpeed Tech}
6465392f7a3SLiteSpeed Tech
6475392f7a3SLiteSpeed Tech
6485392f7a3SLiteSpeed Techstatic void
6495392f7a3SLiteSpeed Techevanescent_conn_ci_client_call_on_new (struct lsquic_conn *lconn)
6505392f7a3SLiteSpeed Tech{
6515392f7a3SLiteSpeed Tech    assert(0);
6525392f7a3SLiteSpeed Tech}
6535392f7a3SLiteSpeed Tech
6545392f7a3SLiteSpeed Tech
6555392f7a3SLiteSpeed Techstatic struct network_path *
6565392f7a3SLiteSpeed Techevanescent_conn_ci_get_path (struct lsquic_conn *lconn,
6575392f7a3SLiteSpeed Tech                                                    const struct sockaddr *sa)
6585392f7a3SLiteSpeed Tech{
6595392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
6605392f7a3SLiteSpeed Tech
6615392f7a3SLiteSpeed Tech    return &evconn->evc_req->pr_path;
6625392f7a3SLiteSpeed Tech}
6635392f7a3SLiteSpeed Tech
6645392f7a3SLiteSpeed Tech
6655392f7a3SLiteSpeed Techstatic unsigned char
6665392f7a3SLiteSpeed Techevanescent_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
6675392f7a3SLiteSpeed Tech            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
6685392f7a3SLiteSpeed Tech{
6695392f7a3SLiteSpeed Tech    assert(0);
6705392f7a3SLiteSpeed Tech    return 0;
6715392f7a3SLiteSpeed Tech}
6725392f7a3SLiteSpeed Tech
6735392f7a3SLiteSpeed Tech
6745392f7a3SLiteSpeed Techstatic const struct conn_iface evanescent_conn_iface = {
6755392f7a3SLiteSpeed Tech    .ci_client_call_on_new   =  evanescent_conn_ci_client_call_on_new,
6765392f7a3SLiteSpeed Tech    .ci_destroy              =  evanescent_conn_ci_destroy,
6775392f7a3SLiteSpeed Tech    .ci_get_engine           =  evanescent_conn_ci_get_engine,
6785392f7a3SLiteSpeed Tech    .ci_get_path             =  evanescent_conn_ci_get_path,
6795392f7a3SLiteSpeed Tech    .ci_hsk_done             =  evanescent_conn_ci_hsk_done,
6805392f7a3SLiteSpeed Tech    .ci_next_packet_to_send  =  evanescent_conn_ci_next_packet_to_send,
6815392f7a3SLiteSpeed Tech    .ci_packet_in            =  evanescent_conn_ci_packet_in,
6825392f7a3SLiteSpeed Tech    .ci_packet_not_sent      =  evanescent_conn_ci_packet_not_sent,
6835392f7a3SLiteSpeed Tech    .ci_packet_sent          =  evanescent_conn_ci_packet_sent,
6845392f7a3SLiteSpeed Tech    .ci_record_addrs         =  evanescent_conn_ci_record_addrs,
6855392f7a3SLiteSpeed Tech    .ci_tick                 =  evanescent_conn_ci_tick,
6865392f7a3SLiteSpeed Tech};
6875392f7a3SLiteSpeed Tech
6885392f7a3SLiteSpeed Tech
6895392f7a3SLiteSpeed Techconst char *const lsquic_preqt2str[] =
6905392f7a3SLiteSpeed Tech{
6915392f7a3SLiteSpeed Tech    [PACKET_REQ_VERNEG] = "version negotiation",
6925392f7a3SLiteSpeed Tech    [PACKET_REQ_PUBRES] = "stateless reset",
6935392f7a3SLiteSpeed Tech};
6947ee41525SDmitri Tikhonov
6957ee41525SDmitri Tikhonov
6967ee41525SDmitri Tikhonovvoid
6977ee41525SDmitri Tikhonovlsquic_prq_drop (struct lsquic_conn *lconn)
6987ee41525SDmitri Tikhonov{
6997ee41525SDmitri Tikhonov    struct evanescent_conn *const evconn = (void *) lconn;
7007ee41525SDmitri Tikhonov
7017ee41525SDmitri Tikhonov    evconn->evc_flags |= EVC_DROP;
7027ee41525SDmitri Tikhonov    LSQ_DEBUGC("mark for connection %"CID_FMT" for dropping",
7037ee41525SDmitri Tikhonov                                        CID_BITS(&evconn->evc_req->pr_dcid));
7047ee41525SDmitri Tikhonov}
705