1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 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 <stdlib.h>
105392f7a3SLiteSpeed Tech#include <string.h>
115392f7a3SLiteSpeed Tech#include <sys/queue.h>
12fb3e20e0SDmitri Tikhonov
13fb3e20e0SDmitri Tikhonov#ifndef WIN32
14fb3e20e0SDmitri Tikhonov#include <netinet/in.h>
155392f7a3SLiteSpeed Tech#include <sys/socket.h>
16fb3e20e0SDmitri Tikhonov#endif
175392f7a3SLiteSpeed Tech
185392f7a3SLiteSpeed Tech#include <openssl/aead.h>
195392f7a3SLiteSpeed Tech#include <openssl/rand.h>
205392f7a3SLiteSpeed Tech
215392f7a3SLiteSpeed Tech#include "lsquic.h"
225392f7a3SLiteSpeed Tech#include "lsquic_types.h"
235392f7a3SLiteSpeed Tech#include "lsquic_int_types.h"
245392f7a3SLiteSpeed Tech#include "lsquic_packet_common.h"
255392f7a3SLiteSpeed Tech#include "lsquic_packet_gquic.h"
265392f7a3SLiteSpeed Tech#include "lsquic_packet_out.h"
275392f7a3SLiteSpeed Tech#include "lsquic_packet_in.h"
285392f7a3SLiteSpeed Tech#include "lsquic_hash.h"
295392f7a3SLiteSpeed Tech#include "lsquic_conn.h"
305392f7a3SLiteSpeed Tech#include "lsquic_parse.h"
315392f7a3SLiteSpeed Tech#include "lsquic_malo.h"
325392f7a3SLiteSpeed Tech#include "lsquic_pr_queue.h"
335392f7a3SLiteSpeed Tech#include "lsquic_parse_common.h"
345392f7a3SLiteSpeed Tech#include "lsquic_tokgen.h"
355392f7a3SLiteSpeed Tech#include "lsquic_version.h"
365392f7a3SLiteSpeed Tech#include "lsquic_mm.h"
375392f7a3SLiteSpeed Tech#include "lsquic_engine_public.h"
385392f7a3SLiteSpeed Tech#include "lsquic_sizes.h"
395392f7a3SLiteSpeed Tech#include "lsquic_handshake.h"
4092f6e17bSDmitri Tikhonov#include "lsquic_xxhash.h"
4110c41073SDmitri Tikhonov#include "lsquic_crand.h"
425392f7a3SLiteSpeed Tech
435392f7a3SLiteSpeed Tech#define LSQUIC_LOGGER_MODULE LSQLM_PRQ
445392f7a3SLiteSpeed Tech#include "lsquic_logger.h"
455392f7a3SLiteSpeed Tech
465392f7a3SLiteSpeed Tech#define MAX(a, b) ((a) > (b) ? (a) : (b))
4792f6e17bSDmitri Tikhonov#define MIN(a, b) ((a) < (b) ? (a) : (b))
485392f7a3SLiteSpeed Tech
495392f7a3SLiteSpeed Tech
505392f7a3SLiteSpeed Techstatic const struct conn_iface evanescent_conn_iface;
515392f7a3SLiteSpeed Tech
525392f7a3SLiteSpeed Tech
535392f7a3SLiteSpeed Techstruct packet_req
545392f7a3SLiteSpeed Tech{
5592f6e17bSDmitri Tikhonov    struct lsquic_hash_elem     pr_hash_el;
565392f7a3SLiteSpeed Tech    lsquic_cid_t                pr_scid;
575392f7a3SLiteSpeed Tech    lsquic_cid_t                pr_dcid;
585392f7a3SLiteSpeed Tech    enum packet_req_type        pr_type;
5992f6e17bSDmitri Tikhonov    enum pr_flags {
605392f7a3SLiteSpeed Tech        PR_GQUIC    = 1 << 0,
615392f7a3SLiteSpeed Tech    }                           pr_flags;
625392f7a3SLiteSpeed Tech    enum lsquic_version         pr_version;
6392f6e17bSDmitri Tikhonov    unsigned                    pr_rst_sz;
645392f7a3SLiteSpeed Tech    struct network_path         pr_path;
655392f7a3SLiteSpeed Tech};
665392f7a3SLiteSpeed Tech
675392f7a3SLiteSpeed Tech
685392f7a3SLiteSpeed Techstruct evanescent_conn
695392f7a3SLiteSpeed Tech{
705392f7a3SLiteSpeed Tech    struct lsquic_conn          evc_conn;
715392f7a3SLiteSpeed Tech    struct packet_req          *evc_req;
725392f7a3SLiteSpeed Tech    struct pr_queue            *evc_queue;
735392f7a3SLiteSpeed Tech    struct lsquic_packet_out    evc_packet_out;
745392f7a3SLiteSpeed Tech    struct conn_cid_elem        evc_cces[1];
757ee41525SDmitri Tikhonov    enum {
767ee41525SDmitri Tikhonov        EVC_DROP    = 1 << 0,
777ee41525SDmitri Tikhonov    }                           evc_flags;
785392f7a3SLiteSpeed Tech    unsigned char               evc_buf[0];
795392f7a3SLiteSpeed Tech};
805392f7a3SLiteSpeed Tech
815392f7a3SLiteSpeed Tech
825392f7a3SLiteSpeed Tech/* [draft-ietf-quic-transport-22], Section 17.2.1 */
835392f7a3SLiteSpeed Tech#define IQUIC_VERNEG_SIZE (1 /* Type */ + 4 /* Version (zero tag) */ \
845392f7a3SLiteSpeed Tech                + 1 /* DCIL */ + MAX_CID_LEN + 1 /* SCIL */ + MAX_CID_LEN + \
855392f7a3SLiteSpeed Tech                4 * N_LSQVER)
865392f7a3SLiteSpeed Tech
875392f7a3SLiteSpeed Tech
885392f7a3SLiteSpeed Techstruct pr_queue
895392f7a3SLiteSpeed Tech{
905392f7a3SLiteSpeed Tech    TAILQ_HEAD(, lsquic_conn)   prq_free_conns,
915392f7a3SLiteSpeed Tech                                prq_returned_conns;
925392f7a3SLiteSpeed Tech    struct malo                *prq_reqs_pool;
935392f7a3SLiteSpeed Tech    const struct lsquic_engine_public
945392f7a3SLiteSpeed Tech                               *prq_enpub;
9592f6e17bSDmitri Tikhonov    struct lsquic_hash         *prq_reqs_hash;
965392f7a3SLiteSpeed Tech    unsigned                    prq_max_reqs;
975392f7a3SLiteSpeed Tech    unsigned                    prq_nreqs;
985392f7a3SLiteSpeed Tech    unsigned                    prq_max_conns;
995392f7a3SLiteSpeed Tech    unsigned                    prq_nconns;
1005392f7a3SLiteSpeed Tech    unsigned                    prq_verneg_g_sz;  /* Size of prq_verneg_g_buf */
1015392f7a3SLiteSpeed Tech    unsigned                    prq_pubres_g_sz;  /* Size of prq_pubres_g_buf */
1025392f7a3SLiteSpeed Tech
1035392f7a3SLiteSpeed Tech    /* GQUIC version negotiation and stateless reset packets are generated
1045392f7a3SLiteSpeed Tech     * once, when the Packet Request Queue is created.  For each request,
1055392f7a3SLiteSpeed Tech     * these buffers are simply copied and the connection ID is replaced.
1065392f7a3SLiteSpeed Tech     *
1075392f7a3SLiteSpeed Tech     * Since IETF QUIC uses variable-length connections IDs, we have to
1085392f7a3SLiteSpeed Tech     * generate packets every time.
1095392f7a3SLiteSpeed Tech     */
1105392f7a3SLiteSpeed Tech    unsigned char               prq_pubres_g_buf[GQUIC_RESET_SZ];
1115392f7a3SLiteSpeed Tech    unsigned char               prq_verneg_g_buf[1 + GQUIC_CID_LEN
1125392f7a3SLiteSpeed Tech                                                                + N_LSQVER * 4];
1135392f7a3SLiteSpeed Tech};
1145392f7a3SLiteSpeed Tech
1155392f7a3SLiteSpeed Tech
11692f6e17bSDmitri Tikhonovstatic int
11792f6e17bSDmitri Tikhonovcomp_reqs (const void *s1, const void *s2, size_t n)
11892f6e17bSDmitri Tikhonov{
11992f6e17bSDmitri Tikhonov    const struct packet_req *a, *b;
12092f6e17bSDmitri Tikhonov
12192f6e17bSDmitri Tikhonov    a = s1;
12292f6e17bSDmitri Tikhonov    b = s2;
12392f6e17bSDmitri Tikhonov    if (a->pr_type == b->pr_type && LSQUIC_CIDS_EQ(&a->pr_dcid, &b->pr_dcid))
12492f6e17bSDmitri Tikhonov        return 0;
12592f6e17bSDmitri Tikhonov    else
12692f6e17bSDmitri Tikhonov        return -1;
12792f6e17bSDmitri Tikhonov}
12892f6e17bSDmitri Tikhonov
12992f6e17bSDmitri Tikhonov
13092f6e17bSDmitri Tikhonovstatic unsigned
13192f6e17bSDmitri Tikhonovhash_req (const void *p, size_t len, unsigned seed)
13292f6e17bSDmitri Tikhonov{
13392f6e17bSDmitri Tikhonov    const struct packet_req *req;
13492f6e17bSDmitri Tikhonov
13592f6e17bSDmitri Tikhonov    req = p;
13692f6e17bSDmitri Tikhonov    return XXH32(req->pr_dcid.idbuf, req->pr_dcid.len, seed);
13792f6e17bSDmitri Tikhonov}
13892f6e17bSDmitri Tikhonov
13992f6e17bSDmitri Tikhonov
1405392f7a3SLiteSpeed Techstruct pr_queue *
141a5fa05f9SDmitri Tikhonovlsquic_prq_create (unsigned max_elems, unsigned max_conns,
1425392f7a3SLiteSpeed Tech                        const struct lsquic_engine_public *enpub)
1435392f7a3SLiteSpeed Tech{
1445392f7a3SLiteSpeed Tech    const struct parse_funcs *pf;
1455392f7a3SLiteSpeed Tech    struct pr_queue *prq;
1465392f7a3SLiteSpeed Tech    struct malo *malo;
14792f6e17bSDmitri Tikhonov    struct lsquic_hash *hash;
1485392f7a3SLiteSpeed Tech    unsigned verneg_g_sz;
1495392f7a3SLiteSpeed Tech    ssize_t prst_g_sz;
1505392f7a3SLiteSpeed Tech    int len;
1515392f7a3SLiteSpeed Tech
1525392f7a3SLiteSpeed Tech    malo = lsquic_malo_create(sizeof(struct packet_req));
1535392f7a3SLiteSpeed Tech    if (!malo)
1545392f7a3SLiteSpeed Tech    {
1555392f7a3SLiteSpeed Tech        LSQ_WARN("malo_create failed: %s", strerror(errno));
1565392f7a3SLiteSpeed Tech        goto err0;
1575392f7a3SLiteSpeed Tech    }
1585392f7a3SLiteSpeed Tech
15992f6e17bSDmitri Tikhonov
16092f6e17bSDmitri Tikhonov    hash = lsquic_hash_create_ext(comp_reqs, hash_req);
16192f6e17bSDmitri Tikhonov    if (!hash)
16292f6e17bSDmitri Tikhonov    {
16392f6e17bSDmitri Tikhonov        LSQ_WARN("cannot create hash");
16492f6e17bSDmitri Tikhonov        goto err1;
16592f6e17bSDmitri Tikhonov    }
16692f6e17bSDmitri Tikhonov
1675392f7a3SLiteSpeed Tech    prq = malloc(sizeof(*prq));
1685392f7a3SLiteSpeed Tech    if (!prq)
1695392f7a3SLiteSpeed Tech    {
1705392f7a3SLiteSpeed Tech        LSQ_WARN("malloc failed: %s", strerror(errno));
17192f6e17bSDmitri Tikhonov        goto err2;
1725392f7a3SLiteSpeed Tech    }
1735392f7a3SLiteSpeed Tech
1745392f7a3SLiteSpeed Tech    const lsquic_cid_t cid = { .len = 8, };
175fb96f4ddSDmitri Tikhonov    pf = select_pf_by_ver(LSQVER_043);
1765392f7a3SLiteSpeed Tech    len = lsquic_gquic_gen_ver_nego_pkt(prq->prq_verneg_g_buf,
1775392f7a3SLiteSpeed Tech                    sizeof(prq->prq_verneg_g_buf), &cid,
1785392f7a3SLiteSpeed Tech                    enpub->enp_settings.es_versions);
1795392f7a3SLiteSpeed Tech    assert(len > 0);
1805392f7a3SLiteSpeed Tech    if (len <= 0)
1815392f7a3SLiteSpeed Tech    {
1825392f7a3SLiteSpeed Tech        LSQ_ERROR("cannot generate version negotiation packet");
18392f6e17bSDmitri Tikhonov        goto err3;
1845392f7a3SLiteSpeed Tech    }
1855392f7a3SLiteSpeed Tech    verneg_g_sz = (unsigned) len;
1865392f7a3SLiteSpeed Tech
1875392f7a3SLiteSpeed Tech    prst_g_sz = pf->pf_generate_simple_prst(0 /* This is just placeholder */,
1885392f7a3SLiteSpeed Tech                                prq->prq_pubres_g_buf, sizeof(prq->prq_pubres_g_buf));
1895392f7a3SLiteSpeed Tech    if (prst_g_sz < 0)
1905392f7a3SLiteSpeed Tech    {
1915392f7a3SLiteSpeed Tech        LSQ_ERROR("cannot generate public reset packet");
19292f6e17bSDmitri Tikhonov        goto err3;
1935392f7a3SLiteSpeed Tech    }
1945392f7a3SLiteSpeed Tech
1955392f7a3SLiteSpeed Tech    TAILQ_INIT(&prq->prq_free_conns);
1965392f7a3SLiteSpeed Tech    TAILQ_INIT(&prq->prq_returned_conns);
19792f6e17bSDmitri Tikhonov    prq->prq_reqs_hash = hash;
1985392f7a3SLiteSpeed Tech    prq->prq_reqs_pool = malo;
1995392f7a3SLiteSpeed Tech    prq->prq_max_reqs = max_elems;
2005392f7a3SLiteSpeed Tech    prq->prq_nreqs = 0;
2015392f7a3SLiteSpeed Tech    prq->prq_max_conns = max_conns;
2025392f7a3SLiteSpeed Tech    prq->prq_nconns = 0;
2035392f7a3SLiteSpeed Tech    prq->prq_verneg_g_sz = verneg_g_sz;
2045392f7a3SLiteSpeed Tech    prq->prq_pubres_g_sz = (unsigned) prst_g_sz;
2055392f7a3SLiteSpeed Tech    prq->prq_enpub       = enpub;
2065392f7a3SLiteSpeed Tech
2075392f7a3SLiteSpeed Tech    LSQ_INFO("initialized queue of size %d", max_elems);
2085392f7a3SLiteSpeed Tech
2095392f7a3SLiteSpeed Tech    return prq;
2105392f7a3SLiteSpeed Tech
21192f6e17bSDmitri Tikhonov  err3:
2125392f7a3SLiteSpeed Tech    free(prq);
21392f6e17bSDmitri Tikhonov  err2:
21492f6e17bSDmitri Tikhonov    lsquic_hash_destroy(hash);
2155392f7a3SLiteSpeed Tech  err1:
2165392f7a3SLiteSpeed Tech    lsquic_malo_destroy(malo);
2175392f7a3SLiteSpeed Tech  err0:
2185392f7a3SLiteSpeed Tech    return NULL;
2195392f7a3SLiteSpeed Tech}
2205392f7a3SLiteSpeed Tech
2215392f7a3SLiteSpeed Tech
2225392f7a3SLiteSpeed Techvoid
223a5fa05f9SDmitri Tikhonovlsquic_prq_destroy (struct pr_queue *prq)
2245392f7a3SLiteSpeed Tech{
2255392f7a3SLiteSpeed Tech    struct lsquic_conn *conn;
2265392f7a3SLiteSpeed Tech
2275392f7a3SLiteSpeed Tech    LSQ_INFO("destroy");
2285392f7a3SLiteSpeed Tech    while ((conn = TAILQ_FIRST(&prq->prq_free_conns)))
2295392f7a3SLiteSpeed Tech    {
2305392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_free_conns, conn, cn_next_pr);
2315392f7a3SLiteSpeed Tech        free(conn);
2325392f7a3SLiteSpeed Tech    }
23392f6e17bSDmitri Tikhonov    lsquic_hash_destroy(prq->prq_reqs_hash);
2345392f7a3SLiteSpeed Tech    lsquic_malo_destroy(prq->prq_reqs_pool);
2355392f7a3SLiteSpeed Tech    free(prq);
2365392f7a3SLiteSpeed Tech}
2375392f7a3SLiteSpeed Tech
2385392f7a3SLiteSpeed Tech
2395392f7a3SLiteSpeed Techstatic struct packet_req *
2405392f7a3SLiteSpeed Techget_req (struct pr_queue *prq)
2415392f7a3SLiteSpeed Tech{
2425392f7a3SLiteSpeed Tech    struct packet_req *req;
2435392f7a3SLiteSpeed Tech    if (prq->prq_nreqs < prq->prq_max_reqs)
2445392f7a3SLiteSpeed Tech    {
2455392f7a3SLiteSpeed Tech        req = lsquic_malo_get(prq->prq_reqs_pool);
2465392f7a3SLiteSpeed Tech        if (req)
2475392f7a3SLiteSpeed Tech            ++prq->prq_nreqs;
2485392f7a3SLiteSpeed Tech        else
2495392f7a3SLiteSpeed Tech            LSQ_WARN("malo_get failed: %s", strerror(errno));
2505392f7a3SLiteSpeed Tech        return req;
2515392f7a3SLiteSpeed Tech    }
2525392f7a3SLiteSpeed Tech    else
2535392f7a3SLiteSpeed Tech        return NULL;
2545392f7a3SLiteSpeed Tech}
2555392f7a3SLiteSpeed Tech
2565392f7a3SLiteSpeed Tech
2575392f7a3SLiteSpeed Techstatic void
2585392f7a3SLiteSpeed Techput_req (struct pr_queue *prq, struct packet_req *req)
2595392f7a3SLiteSpeed Tech{
2605392f7a3SLiteSpeed Tech    lsquic_malo_put(req);
2615392f7a3SLiteSpeed Tech    --prq->prq_nreqs;
2625392f7a3SLiteSpeed Tech}
2635392f7a3SLiteSpeed Tech
2645392f7a3SLiteSpeed Tech
265a5fa05f9SDmitri Tikhonovstatic int
266a5fa05f9SDmitri Tikhonovlsquic_prq_new_req_ext (struct pr_queue *prq, enum packet_req_type type,
26703e6b668SDmitri Tikhonov    unsigned flags, enum lsquic_version version, unsigned short data_sz,
26803e6b668SDmitri Tikhonov    const lsquic_cid_t *dcid, const lsquic_cid_t *scid, void *peer_ctx,
26903e6b668SDmitri Tikhonov    const struct sockaddr *local_addr, const struct sockaddr *peer_addr)
2705392f7a3SLiteSpeed Tech{
2715392f7a3SLiteSpeed Tech    struct packet_req *req;
272a0e1aeeeSDmitri Tikhonov    unsigned max, size, rand;
27392f6e17bSDmitri Tikhonov
27492f6e17bSDmitri Tikhonov    if (type == PACKET_REQ_PUBRES && !(flags & PR_GQUIC))
27592f6e17bSDmitri Tikhonov    {
27603e6b668SDmitri Tikhonov        if (data_sz <= IQUIC_MIN_SRST_SIZE)
27792f6e17bSDmitri Tikhonov        {
27892f6e17bSDmitri Tikhonov            LSQ_DEBUGC("not scheduling public reset: incoming packet for CID "
27903e6b668SDmitri Tikhonov                "%"CID_FMT" too small: %hu bytes", CID_BITS(dcid), data_sz);
28092f6e17bSDmitri Tikhonov            return -1;
28192f6e17bSDmitri Tikhonov        }
28292f6e17bSDmitri Tikhonov        /* Use a random stateless reset size */
28303e6b668SDmitri Tikhonov        max = MIN(IQUIC_MAX_SRST_SIZE, data_sz - 1u);
28492f6e17bSDmitri Tikhonov        if (max > IQUIC_MIN_SRST_SIZE)
285a0e1aeeeSDmitri Tikhonov        {
28610c41073SDmitri Tikhonov            rand = lsquic_crand_get_byte(prq->prq_enpub->enp_crand);
287a0e1aeeeSDmitri Tikhonov            size = IQUIC_MIN_SRST_SIZE + rand % (max - IQUIC_MIN_SRST_SIZE);
288a0e1aeeeSDmitri Tikhonov        }
28992f6e17bSDmitri Tikhonov        else
29092f6e17bSDmitri Tikhonov            size = IQUIC_MIN_SRST_SIZE;
29192f6e17bSDmitri Tikhonov        LSQ_DEBUGC("selected %u-byte reset size for CID %"CID_FMT
29203e6b668SDmitri Tikhonov            " (range is [%u, %u])", size, CID_BITS(dcid),
29392f6e17bSDmitri Tikhonov            IQUIC_MIN_SRST_SIZE, max);
29492f6e17bSDmitri Tikhonov    }
29592f6e17bSDmitri Tikhonov    else
29692f6e17bSDmitri Tikhonov        size = 0;
2975392f7a3SLiteSpeed Tech
2985392f7a3SLiteSpeed Tech    req = get_req(prq);
2995392f7a3SLiteSpeed Tech    if (!req)
3005392f7a3SLiteSpeed Tech    {
3015392f7a3SLiteSpeed Tech        LSQ_DEBUG("out of reqs: cannot allocated another one");
3025392f7a3SLiteSpeed Tech        return -1;
3035392f7a3SLiteSpeed Tech    }
3045392f7a3SLiteSpeed Tech
3055392f7a3SLiteSpeed Tech    req->pr_type     = type;
30603e6b668SDmitri Tikhonov    req->pr_dcid     = *dcid;
30772bbf1fbSDmitri Tikhonov    if (lsquic_hash_find(prq->prq_reqs_hash, req, sizeof(*req)))
30892f6e17bSDmitri Tikhonov    {
30992f6e17bSDmitri Tikhonov        LSQ_DEBUG("request for this DCID and type already exists");
31092f6e17bSDmitri Tikhonov        put_req(prq, req);
31192f6e17bSDmitri Tikhonov        return -1;
31292f6e17bSDmitri Tikhonov    }
31392f6e17bSDmitri Tikhonov
31492f6e17bSDmitri Tikhonov    req->pr_hash_el.qhe_flags = 0;
31572bbf1fbSDmitri Tikhonov    if (!lsquic_hash_insert(prq->prq_reqs_hash, req, sizeof(*req),
31692f6e17bSDmitri Tikhonov                                                    req, &req->pr_hash_el))
31792f6e17bSDmitri Tikhonov    {
31892f6e17bSDmitri Tikhonov        LSQ_DEBUG("could not insert req into hash");
31992f6e17bSDmitri Tikhonov        put_req(prq, req);
32092f6e17bSDmitri Tikhonov        return -1;
32192f6e17bSDmitri Tikhonov    }
32292f6e17bSDmitri Tikhonov
32392f6e17bSDmitri Tikhonov    req->pr_flags    = flags;
32492f6e17bSDmitri Tikhonov    req->pr_rst_sz   = size;
32592f6e17bSDmitri Tikhonov    req->pr_version  = version;
32603e6b668SDmitri Tikhonov    req->pr_scid     = *scid;
3275392f7a3SLiteSpeed Tech    req->pr_path.np_peer_ctx = peer_ctx;
32872bbf1fbSDmitri Tikhonov    memcpy(req->pr_path.np_local_addr, local_addr,
3295392f7a3SLiteSpeed Tech                                            sizeof(req->pr_path.np_local_addr));
3305392f7a3SLiteSpeed Tech    memcpy(NP_PEER_SA(&req->pr_path), peer_addr,
3315392f7a3SLiteSpeed Tech                                            sizeof(req->pr_path.np_peer_addr));
33292f6e17bSDmitri Tikhonov
3335392f7a3SLiteSpeed Tech    LSQ_DEBUGC("scheduled %s packet for connection %"CID_FMT,
3345392f7a3SLiteSpeed Tech                            lsquic_preqt2str[type], CID_BITS(&req->pr_dcid));
3355392f7a3SLiteSpeed Tech    return 0;
3365392f7a3SLiteSpeed Tech}
3375392f7a3SLiteSpeed Tech
3385392f7a3SLiteSpeed Tech
33903e6b668SDmitri Tikhonovint
340a5fa05f9SDmitri Tikhonovlsquic_prq_new_req (struct pr_queue *prq, enum packet_req_type type,
34103e6b668SDmitri Tikhonov         const struct lsquic_packet_in *packet_in, void *peer_ctx,
34203e6b668SDmitri Tikhonov         const struct sockaddr *local_addr, const struct sockaddr *peer_addr)
34303e6b668SDmitri Tikhonov{
34403e6b668SDmitri Tikhonov    lsquic_ver_tag_t ver_tag;
34503e6b668SDmitri Tikhonov    enum lsquic_version version;
34603e6b668SDmitri Tikhonov    enum pr_flags flags;
34703e6b668SDmitri Tikhonov    lsquic_cid_t scid;
34803e6b668SDmitri Tikhonov
34903e6b668SDmitri Tikhonov    if (packet_in->pi_flags & PI_GQUIC)
35003e6b668SDmitri Tikhonov        flags = PR_GQUIC;
35103e6b668SDmitri Tikhonov    else
35203e6b668SDmitri Tikhonov        flags = 0;
35303e6b668SDmitri Tikhonov
35403e6b668SDmitri Tikhonov    if (packet_in->pi_quic_ver)
35503e6b668SDmitri Tikhonov    {
35603e6b668SDmitri Tikhonov        memcpy(&ver_tag, packet_in->pi_data + packet_in->pi_quic_ver,
35703e6b668SDmitri Tikhonov                                                            sizeof(ver_tag));
35803e6b668SDmitri Tikhonov        version = lsquic_tag2ver(ver_tag);
35903e6b668SDmitri Tikhonov    }
36003e6b668SDmitri Tikhonov    else /* Got to set it to something sensible... */
361fb73393fSDmitri Tikhonov        version = LSQVER_ID27;
36203e6b668SDmitri Tikhonov
36303e6b668SDmitri Tikhonov    lsquic_scid_from_packet_in(packet_in, &scid);
364a5fa05f9SDmitri Tikhonov    return lsquic_prq_new_req_ext(prq, type, flags, version,
365a5fa05f9SDmitri Tikhonov                packet_in->pi_data_sz, &packet_in->pi_dcid, &scid,
366a5fa05f9SDmitri Tikhonov                peer_ctx, local_addr, peer_addr);
36703e6b668SDmitri Tikhonov}
36803e6b668SDmitri Tikhonov
36903e6b668SDmitri Tikhonov
3705392f7a3SLiteSpeed Techstatic size_t
3715392f7a3SLiteSpeed Techmax_bufsz (const struct pr_queue *prq)
3725392f7a3SLiteSpeed Tech{
3735392f7a3SLiteSpeed Tech    return  MAX(MAX(MAX(IQUIC_VERNEG_SIZE,
3745392f7a3SLiteSpeed Tech                        IQUIC_MIN_SRST_SIZE),
3755392f7a3SLiteSpeed Tech                        sizeof(prq->prq_verneg_g_buf)),
3765392f7a3SLiteSpeed Tech                        sizeof(prq->prq_pubres_g_buf));
3775392f7a3SLiteSpeed Tech}
3785392f7a3SLiteSpeed Tech
3795392f7a3SLiteSpeed Tech
3805392f7a3SLiteSpeed Techstatic struct evanescent_conn *
3815392f7a3SLiteSpeed Techget_evconn (struct pr_queue *prq)
3825392f7a3SLiteSpeed Tech{
3835392f7a3SLiteSpeed Tech    struct evanescent_conn *evconn;
3845392f7a3SLiteSpeed Tech    struct lsquic_conn *lconn;
3855392f7a3SLiteSpeed Tech    struct lsquic_packet_out *packet_out;
3865392f7a3SLiteSpeed Tech    size_t bufsz;
3875392f7a3SLiteSpeed Tech
3885392f7a3SLiteSpeed Tech    if (prq->prq_nconns >= prq->prq_max_conns)
3895392f7a3SLiteSpeed Tech    {   /* This deserves a warning */
3905392f7a3SLiteSpeed Tech        LSQ_WARN("tried to get connection past limit of %u", prq->prq_max_conns);
3915392f7a3SLiteSpeed Tech        return NULL;
3925392f7a3SLiteSpeed Tech    }
3935392f7a3SLiteSpeed Tech
3945392f7a3SLiteSpeed Tech    lconn = TAILQ_FIRST(&prq->prq_free_conns);
3955392f7a3SLiteSpeed Tech    if (lconn)
3965392f7a3SLiteSpeed Tech    {
3975392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_free_conns, lconn, cn_next_pr);
3987ee41525SDmitri Tikhonov        evconn = (struct evanescent_conn *) lconn;
3997ee41525SDmitri Tikhonov        evconn->evc_flags = 0;
4007ee41525SDmitri Tikhonov        return evconn;
4015392f7a3SLiteSpeed Tech    }
4025392f7a3SLiteSpeed Tech
4035392f7a3SLiteSpeed Tech    bufsz = max_bufsz(prq);
4045392f7a3SLiteSpeed Tech    evconn = calloc(1, sizeof(*evconn) + bufsz);
4055392f7a3SLiteSpeed Tech    if (!evconn)
4065392f7a3SLiteSpeed Tech    {
4075392f7a3SLiteSpeed Tech        LSQ_WARN("calloc failed: %s", strerror(errno));
4085392f7a3SLiteSpeed Tech        return NULL;
4095392f7a3SLiteSpeed Tech    }
4105392f7a3SLiteSpeed Tech
4115392f7a3SLiteSpeed Tech    /* These values stay the same between connection usages: */
4125392f7a3SLiteSpeed Tech    evconn->evc_queue = prq;
4135392f7a3SLiteSpeed Tech    lconn = &evconn->evc_conn;
4145392f7a3SLiteSpeed Tech    lconn->cn_cces = evconn->evc_cces;
4155392f7a3SLiteSpeed Tech    lconn->cn_cces_mask = 1;
4165392f7a3SLiteSpeed Tech    lconn->cn_n_cces = sizeof(evconn->evc_cces) / sizeof(evconn->evc_cces[0]);
4175392f7a3SLiteSpeed Tech    lconn->cn_if = &evanescent_conn_iface;
4185392f7a3SLiteSpeed Tech    lconn->cn_flags = LSCONN_EVANESCENT;
4195392f7a3SLiteSpeed Tech    packet_out = &evconn->evc_packet_out;
4205392f7a3SLiteSpeed Tech    packet_out->po_flags = PO_NOENCRYPT;
4215392f7a3SLiteSpeed Tech    packet_out->po_data = evconn->evc_buf;
4225392f7a3SLiteSpeed Tech
4235392f7a3SLiteSpeed Tech    return evconn;
4245392f7a3SLiteSpeed Tech}
4255392f7a3SLiteSpeed Tech
4265392f7a3SLiteSpeed Tech
4275392f7a3SLiteSpeed Techstruct lsquic_conn *
428a5fa05f9SDmitri Tikhonovlsquic_prq_next_conn (struct pr_queue *prq)
4295392f7a3SLiteSpeed Tech{
4305392f7a3SLiteSpeed Tech    struct evanescent_conn *evconn;
4315392f7a3SLiteSpeed Tech    struct lsquic_conn *lconn;
43292f6e17bSDmitri Tikhonov    struct lsquic_hash_elem *el;
4335392f7a3SLiteSpeed Tech    struct packet_req *req;
4345392f7a3SLiteSpeed Tech    struct lsquic_packet_out *packet_out;
4355392f7a3SLiteSpeed Tech    int (*gen_verneg) (unsigned char *, size_t, const lsquic_cid_t *,
436a0e1aeeeSDmitri Tikhonov                                    const lsquic_cid_t *, unsigned, uint8_t);
4375392f7a3SLiteSpeed Tech    int len;
4385392f7a3SLiteSpeed Tech
4395392f7a3SLiteSpeed Tech    lconn = TAILQ_FIRST(&prq->prq_returned_conns);
4405392f7a3SLiteSpeed Tech    if (lconn)
4415392f7a3SLiteSpeed Tech    {
4425392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_returned_conns, lconn, cn_next_pr);
4435392f7a3SLiteSpeed Tech        return lconn;
4445392f7a3SLiteSpeed Tech    }
4455392f7a3SLiteSpeed Tech
44692f6e17bSDmitri Tikhonov    el = lsquic_hash_first(prq->prq_reqs_hash);
44792f6e17bSDmitri Tikhonov    if (!el)           /* Nothing is queued */
4485392f7a3SLiteSpeed Tech        return NULL;
4495392f7a3SLiteSpeed Tech
4505392f7a3SLiteSpeed Tech    evconn = get_evconn(prq);
4515392f7a3SLiteSpeed Tech    if (!evconn)         /* Reached limit or malloc failed */
4525392f7a3SLiteSpeed Tech        return NULL;
4535392f7a3SLiteSpeed Tech
45492f6e17bSDmitri Tikhonov    req = lsquic_hashelem_getdata(el);
4555392f7a3SLiteSpeed Tech    packet_out = &evconn->evc_packet_out;
4565392f7a3SLiteSpeed Tech    switch ((req->pr_type << 29) | req->pr_flags)
4575392f7a3SLiteSpeed Tech    {
4585392f7a3SLiteSpeed Tech    case (PACKET_REQ_VERNEG << 29) | PR_GQUIC:
4595392f7a3SLiteSpeed Tech        packet_out->po_data_sz = prq->prq_verneg_g_sz;
4605392f7a3SLiteSpeed Tech        packet_out->po_flags |= PO_VERNEG;
4615392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data, prq->prq_verneg_g_buf,
4625392f7a3SLiteSpeed Tech                                                    prq->prq_verneg_g_sz);
4635392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data + 1, req->pr_dcid.idbuf, GQUIC_CID_LEN);
4645392f7a3SLiteSpeed Tech        break;
4655392f7a3SLiteSpeed Tech    case (PACKET_REQ_PUBRES << 29) | PR_GQUIC:
4665392f7a3SLiteSpeed Tech        packet_out->po_flags &= ~PO_VERNEG;
4675392f7a3SLiteSpeed Tech        packet_out->po_data_sz = prq->prq_pubres_g_sz;
4685392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data, prq->prq_pubres_g_buf,
4695392f7a3SLiteSpeed Tech                                                    prq->prq_pubres_g_sz);
4705392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data + 1, req->pr_dcid.idbuf, GQUIC_CID_LEN);
4715392f7a3SLiteSpeed Tech        break;
4725392f7a3SLiteSpeed Tech    case (PACKET_REQ_VERNEG << 29) | 0:
4735392f7a3SLiteSpeed Tech        packet_out->po_flags |= PO_VERNEG;
4745392f7a3SLiteSpeed Tech        if (req->pr_version == LSQVER_046)
4755392f7a3SLiteSpeed Tech            gen_verneg = lsquic_Q046_gen_ver_nego_pkt;
4765392f7a3SLiteSpeed Tech        else
4775392f7a3SLiteSpeed Tech            gen_verneg = lsquic_ietf_v1_gen_ver_nego_pkt;
4785392f7a3SLiteSpeed Tech        len = gen_verneg(packet_out->po_data, max_bufsz(prq),
4795392f7a3SLiteSpeed Tech                    /* Flip SCID/DCID here: */ &req->pr_dcid, &req->pr_scid,
480a0e1aeeeSDmitri Tikhonov                    prq->prq_enpub->enp_settings.es_versions,
48110c41073SDmitri Tikhonov                    lsquic_crand_get_byte(prq->prq_enpub->enp_crand));
4825392f7a3SLiteSpeed Tech        if (len > 0)
4835392f7a3SLiteSpeed Tech            packet_out->po_data_sz = len;
4845392f7a3SLiteSpeed Tech        else
4855392f7a3SLiteSpeed Tech            packet_out->po_data_sz = 0;
4865392f7a3SLiteSpeed Tech        break;
4875392f7a3SLiteSpeed Tech    default:
4885392f7a3SLiteSpeed Tech        packet_out->po_flags &= ~PO_VERNEG;
48992f6e17bSDmitri Tikhonov        packet_out->po_data_sz = req->pr_rst_sz;
49092f6e17bSDmitri Tikhonov        RAND_bytes(packet_out->po_data, req->pr_rst_sz - IQUIC_SRESET_TOKEN_SZ);
4915392f7a3SLiteSpeed Tech        packet_out->po_data[0] &= ~0x80;
4925392f7a3SLiteSpeed Tech        packet_out->po_data[0] |=  0x40;
4935392f7a3SLiteSpeed Tech        lsquic_tg_generate_sreset(prq->prq_enpub->enp_tokgen, &req->pr_dcid,
49492f6e17bSDmitri Tikhonov            packet_out->po_data + req->pr_rst_sz - IQUIC_SRESET_TOKEN_SZ);
4955392f7a3SLiteSpeed Tech        break;
4965392f7a3SLiteSpeed Tech    }
4975392f7a3SLiteSpeed Tech
49892f6e17bSDmitri Tikhonov    lsquic_hash_erase(prq->prq_reqs_hash, el);
4995392f7a3SLiteSpeed Tech    evconn->evc_req = req;
5005392f7a3SLiteSpeed Tech
5015392f7a3SLiteSpeed Tech    lconn= &evconn->evc_conn;
5025392f7a3SLiteSpeed Tech    evconn->evc_cces[0].cce_cid = req->pr_dcid;
5035392f7a3SLiteSpeed Tech    packet_out->po_path = &req->pr_path;
5045392f7a3SLiteSpeed Tech
5055392f7a3SLiteSpeed Tech    ++prq->prq_nconns;
5065392f7a3SLiteSpeed Tech    return lconn;
5075392f7a3SLiteSpeed Tech}
5085392f7a3SLiteSpeed Tech
5095392f7a3SLiteSpeed Tech
5105392f7a3SLiteSpeed Techint
511a5fa05f9SDmitri Tikhonovlsquic_prq_have_pending (const struct pr_queue *prq)
5125392f7a3SLiteSpeed Tech{
51392f6e17bSDmitri Tikhonov    return lsquic_hash_count(prq->prq_reqs_hash) > 0;
5145392f7a3SLiteSpeed Tech}
5155392f7a3SLiteSpeed Tech
5165392f7a3SLiteSpeed Tech
5175392f7a3SLiteSpeed Techstatic struct lsquic_packet_out *
518b1a7c3f9SDmitri Tikhonovevanescent_conn_ci_next_packet_to_send (struct lsquic_conn *lconn,
519b1a7c3f9SDmitri Tikhonov                                        const struct to_coal *to_coal_UNUSED)
5205392f7a3SLiteSpeed Tech{
5215392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
522b1a7c3f9SDmitri Tikhonov    assert(!to_coal_UNUSED);
5235392f7a3SLiteSpeed Tech    return &evconn->evc_packet_out;
5245392f7a3SLiteSpeed Tech}
5255392f7a3SLiteSpeed Tech
5265392f7a3SLiteSpeed Tech
5275392f7a3SLiteSpeed Techstatic void
5287ee41525SDmitri Tikhonovprq_free_conn (struct pr_queue *prq, struct lsquic_conn *lconn)
5297ee41525SDmitri Tikhonov{
5307ee41525SDmitri Tikhonov    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5317ee41525SDmitri Tikhonov
5327ee41525SDmitri Tikhonov    TAILQ_INSERT_HEAD(&prq->prq_free_conns, lconn, cn_next_pr);
5337ee41525SDmitri Tikhonov    put_req(prq, evconn->evc_req);
5347ee41525SDmitri Tikhonov    --prq->prq_nconns;
5357ee41525SDmitri Tikhonov}
5367ee41525SDmitri Tikhonov
5377ee41525SDmitri Tikhonov
5387ee41525SDmitri Tikhonovstatic void
5395392f7a3SLiteSpeed Techevanescent_conn_ci_packet_sent (struct lsquic_conn *lconn,
5405392f7a3SLiteSpeed Tech                            struct lsquic_packet_out *packet_out)
5415392f7a3SLiteSpeed Tech{
5425392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5435392f7a3SLiteSpeed Tech    struct pr_queue *const prq = evconn->evc_queue;
5445392f7a3SLiteSpeed Tech
5455392f7a3SLiteSpeed Tech    assert(packet_out == &evconn->evc_packet_out);
5465392f7a3SLiteSpeed Tech    assert(prq->prq_nconns > 0);
5475392f7a3SLiteSpeed Tech
5485392f7a3SLiteSpeed Tech    LSQ_DEBUGC("sent %s packet for connection %"CID_FMT"; free resources",
5495392f7a3SLiteSpeed Tech        lsquic_preqt2str[ evconn->evc_req->pr_type ],
5505392f7a3SLiteSpeed Tech        CID_BITS(&evconn->evc_req->pr_dcid));
5517ee41525SDmitri Tikhonov    prq_free_conn(prq, lconn);
5525392f7a3SLiteSpeed Tech}
5535392f7a3SLiteSpeed Tech
5545392f7a3SLiteSpeed Tech
5555392f7a3SLiteSpeed Techstatic void
5565392f7a3SLiteSpeed Techevanescent_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
5575392f7a3SLiteSpeed Tech                                struct lsquic_packet_out *packet_out)
5585392f7a3SLiteSpeed Tech{
5595392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
5605392f7a3SLiteSpeed Tech    struct pr_queue *const prq = evconn->evc_queue;
5615392f7a3SLiteSpeed Tech
5625392f7a3SLiteSpeed Tech    assert(packet_out == &evconn->evc_packet_out);
5635392f7a3SLiteSpeed Tech    assert(prq->prq_nconns > 0);
5645392f7a3SLiteSpeed Tech
5657ee41525SDmitri Tikhonov    if (evconn->evc_flags & EVC_DROP)
5667ee41525SDmitri Tikhonov    {
5677ee41525SDmitri Tikhonov        LSQ_DEBUGC("packet not sent; drop connection %"CID_FMT,
5687ee41525SDmitri Tikhonov                                        CID_BITS(&evconn->evc_req->pr_dcid));
5697ee41525SDmitri Tikhonov        prq_free_conn(prq, lconn);
5707ee41525SDmitri Tikhonov    }
5717ee41525SDmitri Tikhonov    else
5727ee41525SDmitri Tikhonov    {
5737ee41525SDmitri Tikhonov        LSQ_DEBUG("packet not sent; put connection onto used list");
5747ee41525SDmitri Tikhonov        TAILQ_INSERT_HEAD(&prq->prq_returned_conns, lconn, cn_next_pr);
5757ee41525SDmitri Tikhonov    }
5765392f7a3SLiteSpeed Tech}
5775392f7a3SLiteSpeed Tech
5785392f7a3SLiteSpeed Tech
5795392f7a3SLiteSpeed Techstatic enum tick_st
5805392f7a3SLiteSpeed Techevanescent_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
5815392f7a3SLiteSpeed Tech{
5825392f7a3SLiteSpeed Tech    assert(0);
5835392f7a3SLiteSpeed Tech    return TICK_CLOSE;
5845392f7a3SLiteSpeed Tech}
5855392f7a3SLiteSpeed Tech
5865392f7a3SLiteSpeed Tech
5875392f7a3SLiteSpeed Techstatic void
5885392f7a3SLiteSpeed Techevanescent_conn_ci_destroy (struct lsquic_conn *lconn)
5895392f7a3SLiteSpeed Tech{
5905392f7a3SLiteSpeed Tech    assert(0);
5915392f7a3SLiteSpeed Tech}
5925392f7a3SLiteSpeed Tech
5935392f7a3SLiteSpeed Tech
5945392f7a3SLiteSpeed Techstatic struct lsquic_engine *
5955392f7a3SLiteSpeed Techevanescent_conn_ci_get_engine (struct lsquic_conn *lconn)
5965392f7a3SLiteSpeed Tech{
5975392f7a3SLiteSpeed Tech    assert(0);
5985392f7a3SLiteSpeed Tech    return NULL;
5995392f7a3SLiteSpeed Tech}
6005392f7a3SLiteSpeed Tech
6015392f7a3SLiteSpeed Tech
6025392f7a3SLiteSpeed Techstatic void
6035392f7a3SLiteSpeed Techevanescent_conn_ci_hsk_done (struct lsquic_conn *lconn,
6045392f7a3SLiteSpeed Tech                                                enum lsquic_hsk_status status)
6055392f7a3SLiteSpeed Tech{
6065392f7a3SLiteSpeed Tech    assert(0);
6075392f7a3SLiteSpeed Tech}
6085392f7a3SLiteSpeed Tech
6095392f7a3SLiteSpeed Tech
6105392f7a3SLiteSpeed Techstatic void
6115392f7a3SLiteSpeed Techevanescent_conn_ci_packet_in (struct lsquic_conn *lconn,
6125392f7a3SLiteSpeed Tech                          struct lsquic_packet_in *packet_in)
6135392f7a3SLiteSpeed Tech{
6145392f7a3SLiteSpeed Tech    assert(0);
6155392f7a3SLiteSpeed Tech}
6165392f7a3SLiteSpeed Tech
6175392f7a3SLiteSpeed Tech
6185392f7a3SLiteSpeed Techstatic void
6195392f7a3SLiteSpeed Techevanescent_conn_ci_client_call_on_new (struct lsquic_conn *lconn)
6205392f7a3SLiteSpeed Tech{
6215392f7a3SLiteSpeed Tech    assert(0);
6225392f7a3SLiteSpeed Tech}
6235392f7a3SLiteSpeed Tech
6245392f7a3SLiteSpeed Tech
6255392f7a3SLiteSpeed Techstatic struct network_path *
6265392f7a3SLiteSpeed Techevanescent_conn_ci_get_path (struct lsquic_conn *lconn,
6275392f7a3SLiteSpeed Tech                                                    const struct sockaddr *sa)
6285392f7a3SLiteSpeed Tech{
6295392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
6305392f7a3SLiteSpeed Tech
6315392f7a3SLiteSpeed Tech    return &evconn->evc_req->pr_path;
6325392f7a3SLiteSpeed Tech}
6335392f7a3SLiteSpeed Tech
6345392f7a3SLiteSpeed Tech
6355392f7a3SLiteSpeed Techstatic unsigned char
6365392f7a3SLiteSpeed Techevanescent_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
6375392f7a3SLiteSpeed Tech            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
6385392f7a3SLiteSpeed Tech{
6395392f7a3SLiteSpeed Tech    assert(0);
6405392f7a3SLiteSpeed Tech    return 0;
6415392f7a3SLiteSpeed Tech}
6425392f7a3SLiteSpeed Tech
6435392f7a3SLiteSpeed Tech
6445392f7a3SLiteSpeed Techstatic const struct conn_iface evanescent_conn_iface = {
6455392f7a3SLiteSpeed Tech    .ci_client_call_on_new   =  evanescent_conn_ci_client_call_on_new,
6465392f7a3SLiteSpeed Tech    .ci_destroy              =  evanescent_conn_ci_destroy,
6475392f7a3SLiteSpeed Tech    .ci_get_engine           =  evanescent_conn_ci_get_engine,
6485392f7a3SLiteSpeed Tech    .ci_get_path             =  evanescent_conn_ci_get_path,
6495392f7a3SLiteSpeed Tech    .ci_hsk_done             =  evanescent_conn_ci_hsk_done,
6505392f7a3SLiteSpeed Tech    .ci_next_packet_to_send  =  evanescent_conn_ci_next_packet_to_send,
6515392f7a3SLiteSpeed Tech    .ci_packet_in            =  evanescent_conn_ci_packet_in,
6525392f7a3SLiteSpeed Tech    .ci_packet_not_sent      =  evanescent_conn_ci_packet_not_sent,
6535392f7a3SLiteSpeed Tech    .ci_packet_sent          =  evanescent_conn_ci_packet_sent,
6545392f7a3SLiteSpeed Tech    .ci_record_addrs         =  evanescent_conn_ci_record_addrs,
6555392f7a3SLiteSpeed Tech    .ci_tick                 =  evanescent_conn_ci_tick,
6565392f7a3SLiteSpeed Tech};
6575392f7a3SLiteSpeed Tech
6585392f7a3SLiteSpeed Tech
6595392f7a3SLiteSpeed Techconst char *const lsquic_preqt2str[] =
6605392f7a3SLiteSpeed Tech{
6615392f7a3SLiteSpeed Tech    [PACKET_REQ_VERNEG] = "version negotiation",
6625392f7a3SLiteSpeed Tech    [PACKET_REQ_PUBRES] = "stateless reset",
6635392f7a3SLiteSpeed Tech};
6647ee41525SDmitri Tikhonov
6657ee41525SDmitri Tikhonov
6667ee41525SDmitri Tikhonovvoid
6677ee41525SDmitri Tikhonovlsquic_prq_drop (struct lsquic_conn *lconn)
6687ee41525SDmitri Tikhonov{
6697ee41525SDmitri Tikhonov    struct evanescent_conn *const evconn = (void *) lconn;
6707ee41525SDmitri Tikhonov
6717ee41525SDmitri Tikhonov    evconn->evc_flags |= EVC_DROP;
6727ee41525SDmitri Tikhonov    LSQ_DEBUGC("mark for connection %"CID_FMT" for dropping",
6737ee41525SDmitri Tikhonov                                        CID_BITS(&evconn->evc_req->pr_dcid));
6747ee41525SDmitri Tikhonov}
675