lsquic_pr_queue.c revision 5392f7a3
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"
375392f7a3SLiteSpeed Tech
385392f7a3SLiteSpeed Tech#define LSQUIC_LOGGER_MODULE LSQLM_PRQ
395392f7a3SLiteSpeed Tech#include "lsquic_logger.h"
405392f7a3SLiteSpeed Tech
415392f7a3SLiteSpeed Tech#define MAX(a, b) ((a) > (b) ? (a) : (b))
425392f7a3SLiteSpeed Tech
435392f7a3SLiteSpeed Tech
445392f7a3SLiteSpeed Techstatic const struct conn_iface evanescent_conn_iface;
455392f7a3SLiteSpeed Tech
465392f7a3SLiteSpeed Tech
475392f7a3SLiteSpeed Techstruct packet_req
485392f7a3SLiteSpeed Tech{
495392f7a3SLiteSpeed Tech    STAILQ_ENTRY(packet_req)    pr_next;
505392f7a3SLiteSpeed Tech    lsquic_cid_t                pr_scid;
515392f7a3SLiteSpeed Tech    lsquic_cid_t                pr_dcid;
525392f7a3SLiteSpeed Tech    enum packet_req_type        pr_type;
535392f7a3SLiteSpeed Tech    enum {
545392f7a3SLiteSpeed Tech        PR_GQUIC    = 1 << 0,
555392f7a3SLiteSpeed Tech    }                           pr_flags;
565392f7a3SLiteSpeed Tech    enum lsquic_version         pr_version;
575392f7a3SLiteSpeed Tech    struct network_path         pr_path;
585392f7a3SLiteSpeed Tech};
595392f7a3SLiteSpeed Tech
605392f7a3SLiteSpeed Tech
615392f7a3SLiteSpeed Techstruct evanescent_conn
625392f7a3SLiteSpeed Tech{
635392f7a3SLiteSpeed Tech    struct lsquic_conn          evc_conn;
645392f7a3SLiteSpeed Tech    struct packet_req          *evc_req;
655392f7a3SLiteSpeed Tech    struct pr_queue            *evc_queue;
665392f7a3SLiteSpeed Tech    struct lsquic_packet_out    evc_packet_out;
675392f7a3SLiteSpeed Tech    struct conn_cid_elem        evc_cces[1];
685392f7a3SLiteSpeed Tech    unsigned char               evc_buf[0];
695392f7a3SLiteSpeed Tech};
705392f7a3SLiteSpeed Tech
715392f7a3SLiteSpeed Tech
725392f7a3SLiteSpeed Tech/* [draft-ietf-quic-transport-22], Section 17.2.1 */
735392f7a3SLiteSpeed Tech#define IQUIC_VERNEG_SIZE (1 /* Type */ + 4 /* Version (zero tag) */ \
745392f7a3SLiteSpeed Tech                + 1 /* DCIL */ + MAX_CID_LEN + 1 /* SCIL */ + MAX_CID_LEN + \
755392f7a3SLiteSpeed Tech                4 * N_LSQVER)
765392f7a3SLiteSpeed Tech
775392f7a3SLiteSpeed Tech
785392f7a3SLiteSpeed Techstruct pr_queue
795392f7a3SLiteSpeed Tech{
805392f7a3SLiteSpeed Tech    TAILQ_HEAD(, lsquic_conn)   prq_free_conns,
815392f7a3SLiteSpeed Tech                                prq_returned_conns;
825392f7a3SLiteSpeed Tech    STAILQ_HEAD(, packet_req)   prq_reqs_queue;
835392f7a3SLiteSpeed Tech    struct malo                *prq_reqs_pool;
845392f7a3SLiteSpeed Tech    const struct lsquic_engine_public
855392f7a3SLiteSpeed Tech                               *prq_enpub;
865392f7a3SLiteSpeed Tech    unsigned                    prq_max_reqs;
875392f7a3SLiteSpeed Tech    unsigned                    prq_nreqs;
885392f7a3SLiteSpeed Tech    unsigned                    prq_max_conns;
895392f7a3SLiteSpeed Tech    unsigned                    prq_nconns;
905392f7a3SLiteSpeed Tech    unsigned                    prq_verneg_g_sz;  /* Size of prq_verneg_g_buf */
915392f7a3SLiteSpeed Tech    unsigned                    prq_pubres_g_sz;  /* Size of prq_pubres_g_buf */
925392f7a3SLiteSpeed Tech
935392f7a3SLiteSpeed Tech    /* GQUIC version negotiation and stateless reset packets are generated
945392f7a3SLiteSpeed Tech     * once, when the Packet Request Queue is created.  For each request,
955392f7a3SLiteSpeed Tech     * these buffers are simply copied and the connection ID is replaced.
965392f7a3SLiteSpeed Tech     *
975392f7a3SLiteSpeed Tech     * Since IETF QUIC uses variable-length connections IDs, we have to
985392f7a3SLiteSpeed Tech     * generate packets every time.
995392f7a3SLiteSpeed Tech     */
1005392f7a3SLiteSpeed Tech    unsigned char               prq_pubres_g_buf[GQUIC_RESET_SZ];
1015392f7a3SLiteSpeed Tech    unsigned char               prq_verneg_g_buf[1 + GQUIC_CID_LEN
1025392f7a3SLiteSpeed Tech                                                                + N_LSQVER * 4];
1035392f7a3SLiteSpeed Tech};
1045392f7a3SLiteSpeed Tech
1055392f7a3SLiteSpeed Tech
1065392f7a3SLiteSpeed Techstruct pr_queue *
1075392f7a3SLiteSpeed Techprq_create (unsigned max_elems, unsigned max_conns,
1085392f7a3SLiteSpeed Tech                        const struct lsquic_engine_public *enpub)
1095392f7a3SLiteSpeed Tech{
1105392f7a3SLiteSpeed Tech    const struct parse_funcs *pf;
1115392f7a3SLiteSpeed Tech    struct pr_queue *prq;
1125392f7a3SLiteSpeed Tech    struct malo *malo;
1135392f7a3SLiteSpeed Tech    unsigned verneg_g_sz;
1145392f7a3SLiteSpeed Tech    ssize_t prst_g_sz;
1155392f7a3SLiteSpeed Tech    int len;
1165392f7a3SLiteSpeed Tech
1175392f7a3SLiteSpeed Tech    malo = lsquic_malo_create(sizeof(struct packet_req));
1185392f7a3SLiteSpeed Tech    if (!malo)
1195392f7a3SLiteSpeed Tech    {
1205392f7a3SLiteSpeed Tech        LSQ_WARN("malo_create failed: %s", strerror(errno));
1215392f7a3SLiteSpeed Tech        goto err0;
1225392f7a3SLiteSpeed Tech    }
1235392f7a3SLiteSpeed Tech
1245392f7a3SLiteSpeed Tech    prq = malloc(sizeof(*prq));
1255392f7a3SLiteSpeed Tech    if (!prq)
1265392f7a3SLiteSpeed Tech    {
1275392f7a3SLiteSpeed Tech        LSQ_WARN("malloc failed: %s", strerror(errno));
1285392f7a3SLiteSpeed Tech        goto err1;
1295392f7a3SLiteSpeed Tech    }
1305392f7a3SLiteSpeed Tech
1315392f7a3SLiteSpeed Tech    const lsquic_cid_t cid = { .len = 8, };
1325392f7a3SLiteSpeed Tech    pf = select_pf_by_ver(LSQVER_039);
1335392f7a3SLiteSpeed Tech    len = lsquic_gquic_gen_ver_nego_pkt(prq->prq_verneg_g_buf,
1345392f7a3SLiteSpeed Tech                    sizeof(prq->prq_verneg_g_buf), &cid,
1355392f7a3SLiteSpeed Tech                    enpub->enp_settings.es_versions);
1365392f7a3SLiteSpeed Tech    assert(len > 0);
1375392f7a3SLiteSpeed Tech    if (len <= 0)
1385392f7a3SLiteSpeed Tech    {
1395392f7a3SLiteSpeed Tech        LSQ_ERROR("cannot generate version negotiation packet");
1405392f7a3SLiteSpeed Tech        goto err2;
1415392f7a3SLiteSpeed Tech    }
1425392f7a3SLiteSpeed Tech    verneg_g_sz = (unsigned) len;
1435392f7a3SLiteSpeed Tech
1445392f7a3SLiteSpeed Tech    prst_g_sz = pf->pf_generate_simple_prst(0 /* This is just placeholder */,
1455392f7a3SLiteSpeed Tech                                prq->prq_pubres_g_buf, sizeof(prq->prq_pubres_g_buf));
1465392f7a3SLiteSpeed Tech    if (prst_g_sz < 0)
1475392f7a3SLiteSpeed Tech    {
1485392f7a3SLiteSpeed Tech        LSQ_ERROR("cannot generate public reset packet");
1495392f7a3SLiteSpeed Tech        goto err2;
1505392f7a3SLiteSpeed Tech    }
1515392f7a3SLiteSpeed Tech
1525392f7a3SLiteSpeed Tech    TAILQ_INIT(&prq->prq_free_conns);
1535392f7a3SLiteSpeed Tech    TAILQ_INIT(&prq->prq_returned_conns);
1545392f7a3SLiteSpeed Tech    STAILQ_INIT(&prq->prq_reqs_queue);
1555392f7a3SLiteSpeed Tech    prq->prq_reqs_pool = malo;
1565392f7a3SLiteSpeed Tech    prq->prq_max_reqs = max_elems;
1575392f7a3SLiteSpeed Tech    prq->prq_nreqs = 0;
1585392f7a3SLiteSpeed Tech    prq->prq_max_conns = max_conns;
1595392f7a3SLiteSpeed Tech    prq->prq_nconns = 0;
1605392f7a3SLiteSpeed Tech    prq->prq_verneg_g_sz = verneg_g_sz;
1615392f7a3SLiteSpeed Tech    prq->prq_pubres_g_sz = (unsigned) prst_g_sz;
1625392f7a3SLiteSpeed Tech    prq->prq_enpub       = enpub;
1635392f7a3SLiteSpeed Tech
1645392f7a3SLiteSpeed Tech    LSQ_INFO("initialized queue of size %d", max_elems);
1655392f7a3SLiteSpeed Tech
1665392f7a3SLiteSpeed Tech    return prq;
1675392f7a3SLiteSpeed Tech
1685392f7a3SLiteSpeed Tech  err2:
1695392f7a3SLiteSpeed Tech    free(prq);
1705392f7a3SLiteSpeed Tech  err1:
1715392f7a3SLiteSpeed Tech    lsquic_malo_destroy(malo);
1725392f7a3SLiteSpeed Tech  err0:
1735392f7a3SLiteSpeed Tech    return NULL;
1745392f7a3SLiteSpeed Tech}
1755392f7a3SLiteSpeed Tech
1765392f7a3SLiteSpeed Tech
1775392f7a3SLiteSpeed Techvoid
1785392f7a3SLiteSpeed Techprq_destroy (struct pr_queue *prq)
1795392f7a3SLiteSpeed Tech{
1805392f7a3SLiteSpeed Tech    struct lsquic_conn *conn;
1815392f7a3SLiteSpeed Tech
1825392f7a3SLiteSpeed Tech    LSQ_INFO("destroy");
1835392f7a3SLiteSpeed Tech    while ((conn = TAILQ_FIRST(&prq->prq_free_conns)))
1845392f7a3SLiteSpeed Tech    {
1855392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_free_conns, conn, cn_next_pr);
1865392f7a3SLiteSpeed Tech        free(conn);
1875392f7a3SLiteSpeed Tech    }
1885392f7a3SLiteSpeed Tech    lsquic_malo_destroy(prq->prq_reqs_pool);
1895392f7a3SLiteSpeed Tech    free(prq);
1905392f7a3SLiteSpeed Tech}
1915392f7a3SLiteSpeed Tech
1925392f7a3SLiteSpeed Tech
1935392f7a3SLiteSpeed Techstatic struct packet_req *
1945392f7a3SLiteSpeed Techget_req (struct pr_queue *prq)
1955392f7a3SLiteSpeed Tech{
1965392f7a3SLiteSpeed Tech    struct packet_req *req;
1975392f7a3SLiteSpeed Tech    if (prq->prq_nreqs < prq->prq_max_reqs)
1985392f7a3SLiteSpeed Tech    {
1995392f7a3SLiteSpeed Tech        req = lsquic_malo_get(prq->prq_reqs_pool);
2005392f7a3SLiteSpeed Tech        if (req)
2015392f7a3SLiteSpeed Tech            ++prq->prq_nreqs;
2025392f7a3SLiteSpeed Tech        else
2035392f7a3SLiteSpeed Tech            LSQ_WARN("malo_get failed: %s", strerror(errno));
2045392f7a3SLiteSpeed Tech        return req;
2055392f7a3SLiteSpeed Tech    }
2065392f7a3SLiteSpeed Tech    else
2075392f7a3SLiteSpeed Tech        return NULL;
2085392f7a3SLiteSpeed Tech}
2095392f7a3SLiteSpeed Tech
2105392f7a3SLiteSpeed Tech
2115392f7a3SLiteSpeed Techstatic void
2125392f7a3SLiteSpeed Techput_req (struct pr_queue *prq, struct packet_req *req)
2135392f7a3SLiteSpeed Tech{
2145392f7a3SLiteSpeed Tech    lsquic_malo_put(req);
2155392f7a3SLiteSpeed Tech    --prq->prq_nreqs;
2165392f7a3SLiteSpeed Tech}
2175392f7a3SLiteSpeed Tech
2185392f7a3SLiteSpeed Tech
2195392f7a3SLiteSpeed Techint
2205392f7a3SLiteSpeed Techprq_new_req (struct pr_queue *prq, enum packet_req_type type,
2215392f7a3SLiteSpeed Tech         const struct lsquic_packet_in *packet_in, void *peer_ctx,
2225392f7a3SLiteSpeed Tech         const struct sockaddr *local_addr, const struct sockaddr *peer_addr)
2235392f7a3SLiteSpeed Tech{
2245392f7a3SLiteSpeed Tech    struct packet_req *req;
2255392f7a3SLiteSpeed Tech    lsquic_ver_tag_t ver_tag;
2265392f7a3SLiteSpeed Tech
2275392f7a3SLiteSpeed Tech    req = get_req(prq);
2285392f7a3SLiteSpeed Tech    if (!req)
2295392f7a3SLiteSpeed Tech    {
2305392f7a3SLiteSpeed Tech        LSQ_DEBUG("out of reqs: cannot allocated another one");
2315392f7a3SLiteSpeed Tech        return -1;
2325392f7a3SLiteSpeed Tech    }
2335392f7a3SLiteSpeed Tech
2345392f7a3SLiteSpeed Tech    STAILQ_INSERT_TAIL(&prq->prq_reqs_queue, req, pr_next);
2355392f7a3SLiteSpeed Tech
2365392f7a3SLiteSpeed Tech    req->pr_type     = type;
2375392f7a3SLiteSpeed Tech    req->pr_flags    = packet_in->pi_flags & PI_GQUIC ? PR_GQUIC : 0;
2385392f7a3SLiteSpeed Tech    lsquic_scid_from_packet_in(packet_in, &req->pr_scid);
2395392f7a3SLiteSpeed Tech    req->pr_dcid     = packet_in->pi_dcid;
2405392f7a3SLiteSpeed Tech    req->pr_path.np_peer_ctx = peer_ctx;
2415392f7a3SLiteSpeed Tech    memcpy(NP_LOCAL_SA(&req->pr_path), local_addr,
2425392f7a3SLiteSpeed Tech                                            sizeof(req->pr_path.np_local_addr));
2435392f7a3SLiteSpeed Tech    memcpy(NP_PEER_SA(&req->pr_path), peer_addr,
2445392f7a3SLiteSpeed Tech                                            sizeof(req->pr_path.np_peer_addr));
2455392f7a3SLiteSpeed Tech    if (packet_in->pi_quic_ver)
2465392f7a3SLiteSpeed Tech    {
2475392f7a3SLiteSpeed Tech        memcpy(&ver_tag, packet_in->pi_data + packet_in->pi_quic_ver,
2485392f7a3SLiteSpeed Tech                                                            sizeof(ver_tag));
2495392f7a3SLiteSpeed Tech        req->pr_version = lsquic_tag2ver(ver_tag);
2505392f7a3SLiteSpeed Tech    }
2515392f7a3SLiteSpeed Tech    else /* Got to set it to something sensible... */
2525392f7a3SLiteSpeed Tech        req->pr_version = LSQVER_ID22;
2535392f7a3SLiteSpeed Tech    LSQ_DEBUGC("scheduled %s packet for connection %"CID_FMT,
2545392f7a3SLiteSpeed Tech                            lsquic_preqt2str[type], CID_BITS(&req->pr_dcid));
2555392f7a3SLiteSpeed Tech    return 0;
2565392f7a3SLiteSpeed Tech}
2575392f7a3SLiteSpeed Tech
2585392f7a3SLiteSpeed Tech
2595392f7a3SLiteSpeed Techstatic size_t
2605392f7a3SLiteSpeed Techmax_bufsz (const struct pr_queue *prq)
2615392f7a3SLiteSpeed Tech{
2625392f7a3SLiteSpeed Tech    return  MAX(MAX(MAX(IQUIC_VERNEG_SIZE,
2635392f7a3SLiteSpeed Tech                        IQUIC_MIN_SRST_SIZE),
2645392f7a3SLiteSpeed Tech                        sizeof(prq->prq_verneg_g_buf)),
2655392f7a3SLiteSpeed Tech                        sizeof(prq->prq_pubres_g_buf));
2665392f7a3SLiteSpeed Tech}
2675392f7a3SLiteSpeed Tech
2685392f7a3SLiteSpeed Tech
2695392f7a3SLiteSpeed Techstatic struct evanescent_conn *
2705392f7a3SLiteSpeed Techget_evconn (struct pr_queue *prq)
2715392f7a3SLiteSpeed Tech{
2725392f7a3SLiteSpeed Tech    struct evanescent_conn *evconn;
2735392f7a3SLiteSpeed Tech    struct lsquic_conn *lconn;
2745392f7a3SLiteSpeed Tech    struct lsquic_packet_out *packet_out;
2755392f7a3SLiteSpeed Tech    size_t bufsz;
2765392f7a3SLiteSpeed Tech
2775392f7a3SLiteSpeed Tech    if (prq->prq_nconns >= prq->prq_max_conns)
2785392f7a3SLiteSpeed Tech    {   /* This deserves a warning */
2795392f7a3SLiteSpeed Tech        LSQ_WARN("tried to get connection past limit of %u", prq->prq_max_conns);
2805392f7a3SLiteSpeed Tech        return NULL;
2815392f7a3SLiteSpeed Tech    }
2825392f7a3SLiteSpeed Tech
2835392f7a3SLiteSpeed Tech    lconn = TAILQ_FIRST(&prq->prq_free_conns);
2845392f7a3SLiteSpeed Tech    if (lconn)
2855392f7a3SLiteSpeed Tech    {
2865392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_free_conns, lconn, cn_next_pr);
2875392f7a3SLiteSpeed Tech        return (struct evanescent_conn *) lconn;
2885392f7a3SLiteSpeed Tech    }
2895392f7a3SLiteSpeed Tech
2905392f7a3SLiteSpeed Tech    bufsz = max_bufsz(prq);
2915392f7a3SLiteSpeed Tech    evconn = calloc(1, sizeof(*evconn) + bufsz);
2925392f7a3SLiteSpeed Tech    if (!evconn)
2935392f7a3SLiteSpeed Tech    {
2945392f7a3SLiteSpeed Tech        LSQ_WARN("calloc failed: %s", strerror(errno));
2955392f7a3SLiteSpeed Tech        return NULL;
2965392f7a3SLiteSpeed Tech    }
2975392f7a3SLiteSpeed Tech
2985392f7a3SLiteSpeed Tech    /* These values stay the same between connection usages: */
2995392f7a3SLiteSpeed Tech    evconn->evc_queue = prq;
3005392f7a3SLiteSpeed Tech    lconn = &evconn->evc_conn;
3015392f7a3SLiteSpeed Tech    lconn->cn_cces = evconn->evc_cces;
3025392f7a3SLiteSpeed Tech    lconn->cn_cces_mask = 1;
3035392f7a3SLiteSpeed Tech    lconn->cn_n_cces = sizeof(evconn->evc_cces) / sizeof(evconn->evc_cces[0]);
3045392f7a3SLiteSpeed Tech    lconn->cn_if = &evanescent_conn_iface;
3055392f7a3SLiteSpeed Tech    lconn->cn_flags = LSCONN_EVANESCENT;
3065392f7a3SLiteSpeed Tech    packet_out = &evconn->evc_packet_out;
3075392f7a3SLiteSpeed Tech    packet_out->po_flags = PO_NOENCRYPT;
3085392f7a3SLiteSpeed Tech    packet_out->po_data = evconn->evc_buf;
3095392f7a3SLiteSpeed Tech
3105392f7a3SLiteSpeed Tech    return evconn;
3115392f7a3SLiteSpeed Tech}
3125392f7a3SLiteSpeed Tech
3135392f7a3SLiteSpeed Tech
3145392f7a3SLiteSpeed Techstruct lsquic_conn *
3155392f7a3SLiteSpeed Techprq_next_conn (struct pr_queue *prq)
3165392f7a3SLiteSpeed Tech{
3175392f7a3SLiteSpeed Tech    struct evanescent_conn *evconn;
3185392f7a3SLiteSpeed Tech    struct lsquic_conn *lconn;
3195392f7a3SLiteSpeed Tech    struct packet_req *req;
3205392f7a3SLiteSpeed Tech    struct lsquic_packet_out *packet_out;
3215392f7a3SLiteSpeed Tech    int (*gen_verneg) (unsigned char *, size_t, const lsquic_cid_t *,
3225392f7a3SLiteSpeed Tech                                            const lsquic_cid_t *, unsigned);
3235392f7a3SLiteSpeed Tech    int len;
3245392f7a3SLiteSpeed Tech
3255392f7a3SLiteSpeed Tech    lconn = TAILQ_FIRST(&prq->prq_returned_conns);
3265392f7a3SLiteSpeed Tech    if (lconn)
3275392f7a3SLiteSpeed Tech    {
3285392f7a3SLiteSpeed Tech        TAILQ_REMOVE(&prq->prq_returned_conns, lconn, cn_next_pr);
3295392f7a3SLiteSpeed Tech        return lconn;
3305392f7a3SLiteSpeed Tech    }
3315392f7a3SLiteSpeed Tech
3325392f7a3SLiteSpeed Tech    req = STAILQ_FIRST(&prq->prq_reqs_queue);
3335392f7a3SLiteSpeed Tech    if (!req)           /* Nothing is queued */
3345392f7a3SLiteSpeed Tech        return NULL;
3355392f7a3SLiteSpeed Tech
3365392f7a3SLiteSpeed Tech    evconn = get_evconn(prq);
3375392f7a3SLiteSpeed Tech    if (!evconn)         /* Reached limit or malloc failed */
3385392f7a3SLiteSpeed Tech        return NULL;
3395392f7a3SLiteSpeed Tech
3405392f7a3SLiteSpeed Tech    packet_out = &evconn->evc_packet_out;
3415392f7a3SLiteSpeed Tech    switch ((req->pr_type << 29) | req->pr_flags)
3425392f7a3SLiteSpeed Tech    {
3435392f7a3SLiteSpeed Tech    case (PACKET_REQ_VERNEG << 29) | PR_GQUIC:
3445392f7a3SLiteSpeed Tech        packet_out->po_data_sz = prq->prq_verneg_g_sz;
3455392f7a3SLiteSpeed Tech        packet_out->po_flags |= PO_VERNEG;
3465392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data, prq->prq_verneg_g_buf,
3475392f7a3SLiteSpeed Tech                                                    prq->prq_verneg_g_sz);
3485392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data + 1, req->pr_dcid.idbuf, GQUIC_CID_LEN);
3495392f7a3SLiteSpeed Tech        break;
3505392f7a3SLiteSpeed Tech    case (PACKET_REQ_PUBRES << 29) | PR_GQUIC:
3515392f7a3SLiteSpeed Tech        packet_out->po_flags &= ~PO_VERNEG;
3525392f7a3SLiteSpeed Tech        packet_out->po_data_sz = prq->prq_pubres_g_sz;
3535392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data, prq->prq_pubres_g_buf,
3545392f7a3SLiteSpeed Tech                                                    prq->prq_pubres_g_sz);
3555392f7a3SLiteSpeed Tech        memcpy(packet_out->po_data + 1, req->pr_dcid.idbuf, GQUIC_CID_LEN);
3565392f7a3SLiteSpeed Tech        break;
3575392f7a3SLiteSpeed Tech    case (PACKET_REQ_VERNEG << 29) | 0:
3585392f7a3SLiteSpeed Tech        packet_out->po_flags |= PO_VERNEG;
3595392f7a3SLiteSpeed Tech        if (req->pr_version == LSQVER_046)
3605392f7a3SLiteSpeed Tech            gen_verneg = lsquic_Q046_gen_ver_nego_pkt;
3615392f7a3SLiteSpeed Tech        else
3625392f7a3SLiteSpeed Tech            gen_verneg = lsquic_ietf_v1_gen_ver_nego_pkt;
3635392f7a3SLiteSpeed Tech        len = gen_verneg(packet_out->po_data, max_bufsz(prq),
3645392f7a3SLiteSpeed Tech                    /* Flip SCID/DCID here: */ &req->pr_dcid, &req->pr_scid,
3655392f7a3SLiteSpeed Tech                    prq->prq_enpub->enp_settings.es_versions);
3665392f7a3SLiteSpeed Tech        if (len > 0)
3675392f7a3SLiteSpeed Tech            packet_out->po_data_sz = len;
3685392f7a3SLiteSpeed Tech        else
3695392f7a3SLiteSpeed Tech            packet_out->po_data_sz = 0;
3705392f7a3SLiteSpeed Tech        break;
3715392f7a3SLiteSpeed Tech    default:
3725392f7a3SLiteSpeed Tech        packet_out->po_flags &= ~PO_VERNEG;
3735392f7a3SLiteSpeed Tech        packet_out->po_data_sz = IQUIC_MIN_SRST_SIZE;
3745392f7a3SLiteSpeed Tech        RAND_bytes(packet_out->po_data, IQUIC_MIN_SRST_RANDOM_BYTES);
3755392f7a3SLiteSpeed Tech        packet_out->po_data[0] &= ~0x80;
3765392f7a3SLiteSpeed Tech        packet_out->po_data[0] |=  0x40;
3775392f7a3SLiteSpeed Tech        lsquic_tg_generate_sreset(prq->prq_enpub->enp_tokgen, &req->pr_dcid,
3785392f7a3SLiteSpeed Tech            packet_out->po_data + IQUIC_MIN_SRST_RANDOM_BYTES);
3795392f7a3SLiteSpeed Tech        break;
3805392f7a3SLiteSpeed Tech    }
3815392f7a3SLiteSpeed Tech
3825392f7a3SLiteSpeed Tech    STAILQ_REMOVE_HEAD(&prq->prq_reqs_queue, pr_next);
3835392f7a3SLiteSpeed Tech    evconn->evc_req = req;
3845392f7a3SLiteSpeed Tech
3855392f7a3SLiteSpeed Tech    lconn= &evconn->evc_conn;
3865392f7a3SLiteSpeed Tech    evconn->evc_cces[0].cce_cid = req->pr_dcid;
3875392f7a3SLiteSpeed Tech    packet_out->po_path = &req->pr_path;
3885392f7a3SLiteSpeed Tech
3895392f7a3SLiteSpeed Tech    ++prq->prq_nconns;
3905392f7a3SLiteSpeed Tech    return lconn;
3915392f7a3SLiteSpeed Tech}
3925392f7a3SLiteSpeed Tech
3935392f7a3SLiteSpeed Tech
3945392f7a3SLiteSpeed Techint
3955392f7a3SLiteSpeed Techprq_have_pending (const struct pr_queue *prq)
3965392f7a3SLiteSpeed Tech{
3975392f7a3SLiteSpeed Tech    return !STAILQ_EMPTY(&prq->prq_reqs_queue);
3985392f7a3SLiteSpeed Tech}
3995392f7a3SLiteSpeed Tech
4005392f7a3SLiteSpeed Tech
4015392f7a3SLiteSpeed Techstatic struct lsquic_packet_out *
4025392f7a3SLiteSpeed Techevanescent_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
4035392f7a3SLiteSpeed Tech{
4045392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
4055392f7a3SLiteSpeed Tech    assert(size == 0);
4065392f7a3SLiteSpeed Tech    return &evconn->evc_packet_out;
4075392f7a3SLiteSpeed Tech}
4085392f7a3SLiteSpeed Tech
4095392f7a3SLiteSpeed Tech
4105392f7a3SLiteSpeed Techstatic void
4115392f7a3SLiteSpeed Techevanescent_conn_ci_packet_sent (struct lsquic_conn *lconn,
4125392f7a3SLiteSpeed Tech                            struct lsquic_packet_out *packet_out)
4135392f7a3SLiteSpeed Tech{
4145392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
4155392f7a3SLiteSpeed Tech    struct pr_queue *const prq = evconn->evc_queue;
4165392f7a3SLiteSpeed Tech
4175392f7a3SLiteSpeed Tech    assert(packet_out == &evconn->evc_packet_out);
4185392f7a3SLiteSpeed Tech    assert(prq->prq_nconns > 0);
4195392f7a3SLiteSpeed Tech
4205392f7a3SLiteSpeed Tech    LSQ_DEBUGC("sent %s packet for connection %"CID_FMT"; free resources",
4215392f7a3SLiteSpeed Tech        lsquic_preqt2str[ evconn->evc_req->pr_type ],
4225392f7a3SLiteSpeed Tech        CID_BITS(&evconn->evc_req->pr_dcid));
4235392f7a3SLiteSpeed Tech    TAILQ_INSERT_HEAD(&prq->prq_free_conns, lconn, cn_next_pr);
4245392f7a3SLiteSpeed Tech    put_req(prq, evconn->evc_req);
4255392f7a3SLiteSpeed Tech    --prq->prq_nconns;
4265392f7a3SLiteSpeed Tech}
4275392f7a3SLiteSpeed Tech
4285392f7a3SLiteSpeed Tech
4295392f7a3SLiteSpeed Techstatic void
4305392f7a3SLiteSpeed Techevanescent_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
4315392f7a3SLiteSpeed Tech                                struct lsquic_packet_out *packet_out)
4325392f7a3SLiteSpeed Tech{
4335392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
4345392f7a3SLiteSpeed Tech    struct pr_queue *const prq = evconn->evc_queue;
4355392f7a3SLiteSpeed Tech
4365392f7a3SLiteSpeed Tech    assert(packet_out == &evconn->evc_packet_out);
4375392f7a3SLiteSpeed Tech    assert(prq->prq_nconns > 0);
4385392f7a3SLiteSpeed Tech
4395392f7a3SLiteSpeed Tech    LSQ_DEBUG("packet not sent; put connection onto used list");
4405392f7a3SLiteSpeed Tech    TAILQ_INSERT_HEAD(&prq->prq_returned_conns, lconn, cn_next_pr);
4415392f7a3SLiteSpeed Tech}
4425392f7a3SLiteSpeed Tech
4435392f7a3SLiteSpeed Tech
4445392f7a3SLiteSpeed Techstatic enum tick_st
4455392f7a3SLiteSpeed Techevanescent_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
4465392f7a3SLiteSpeed Tech{
4475392f7a3SLiteSpeed Tech    assert(0);
4485392f7a3SLiteSpeed Tech    return TICK_CLOSE;
4495392f7a3SLiteSpeed Tech}
4505392f7a3SLiteSpeed Tech
4515392f7a3SLiteSpeed Tech
4525392f7a3SLiteSpeed Techstatic void
4535392f7a3SLiteSpeed Techevanescent_conn_ci_destroy (struct lsquic_conn *lconn)
4545392f7a3SLiteSpeed Tech{
4555392f7a3SLiteSpeed Tech    assert(0);
4565392f7a3SLiteSpeed Tech}
4575392f7a3SLiteSpeed Tech
4585392f7a3SLiteSpeed Tech
4595392f7a3SLiteSpeed Techstatic struct lsquic_engine *
4605392f7a3SLiteSpeed Techevanescent_conn_ci_get_engine (struct lsquic_conn *lconn)
4615392f7a3SLiteSpeed Tech{
4625392f7a3SLiteSpeed Tech    assert(0);
4635392f7a3SLiteSpeed Tech    return NULL;
4645392f7a3SLiteSpeed Tech}
4655392f7a3SLiteSpeed Tech
4665392f7a3SLiteSpeed Tech
4675392f7a3SLiteSpeed Techstatic void
4685392f7a3SLiteSpeed Techevanescent_conn_ci_hsk_done (struct lsquic_conn *lconn,
4695392f7a3SLiteSpeed Tech                                                enum lsquic_hsk_status status)
4705392f7a3SLiteSpeed Tech{
4715392f7a3SLiteSpeed Tech    assert(0);
4725392f7a3SLiteSpeed Tech}
4735392f7a3SLiteSpeed Tech
4745392f7a3SLiteSpeed Tech
4755392f7a3SLiteSpeed Techstatic void
4765392f7a3SLiteSpeed Techevanescent_conn_ci_packet_in (struct lsquic_conn *lconn,
4775392f7a3SLiteSpeed Tech                          struct lsquic_packet_in *packet_in)
4785392f7a3SLiteSpeed Tech{
4795392f7a3SLiteSpeed Tech    assert(0);
4805392f7a3SLiteSpeed Tech}
4815392f7a3SLiteSpeed Tech
4825392f7a3SLiteSpeed Tech
4835392f7a3SLiteSpeed Techstatic void
4845392f7a3SLiteSpeed Techevanescent_conn_ci_client_call_on_new (struct lsquic_conn *lconn)
4855392f7a3SLiteSpeed Tech{
4865392f7a3SLiteSpeed Tech    assert(0);
4875392f7a3SLiteSpeed Tech}
4885392f7a3SLiteSpeed Tech
4895392f7a3SLiteSpeed Tech
4905392f7a3SLiteSpeed Techstatic struct network_path *
4915392f7a3SLiteSpeed Techevanescent_conn_ci_get_path (struct lsquic_conn *lconn,
4925392f7a3SLiteSpeed Tech                                                    const struct sockaddr *sa)
4935392f7a3SLiteSpeed Tech{
4945392f7a3SLiteSpeed Tech    struct evanescent_conn *const evconn = (struct evanescent_conn *) lconn;
4955392f7a3SLiteSpeed Tech
4965392f7a3SLiteSpeed Tech    return &evconn->evc_req->pr_path;
4975392f7a3SLiteSpeed Tech}
4985392f7a3SLiteSpeed Tech
4995392f7a3SLiteSpeed Tech
5005392f7a3SLiteSpeed Techstatic unsigned char
5015392f7a3SLiteSpeed Techevanescent_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
5025392f7a3SLiteSpeed Tech            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
5035392f7a3SLiteSpeed Tech{
5045392f7a3SLiteSpeed Tech    assert(0);
5055392f7a3SLiteSpeed Tech    return 0;
5065392f7a3SLiteSpeed Tech}
5075392f7a3SLiteSpeed Tech
5085392f7a3SLiteSpeed Tech
5095392f7a3SLiteSpeed Techstatic const struct conn_iface evanescent_conn_iface = {
5105392f7a3SLiteSpeed Tech    .ci_client_call_on_new   =  evanescent_conn_ci_client_call_on_new,
5115392f7a3SLiteSpeed Tech    .ci_destroy              =  evanescent_conn_ci_destroy,
5125392f7a3SLiteSpeed Tech    .ci_get_engine           =  evanescent_conn_ci_get_engine,
5135392f7a3SLiteSpeed Tech    .ci_get_path             =  evanescent_conn_ci_get_path,
5145392f7a3SLiteSpeed Tech    .ci_hsk_done             =  evanescent_conn_ci_hsk_done,
5155392f7a3SLiteSpeed Tech    .ci_next_packet_to_send  =  evanescent_conn_ci_next_packet_to_send,
5165392f7a3SLiteSpeed Tech    .ci_packet_in            =  evanescent_conn_ci_packet_in,
5175392f7a3SLiteSpeed Tech    .ci_packet_not_sent      =  evanescent_conn_ci_packet_not_sent,
5185392f7a3SLiteSpeed Tech    .ci_packet_sent          =  evanescent_conn_ci_packet_sent,
5195392f7a3SLiteSpeed Tech    .ci_record_addrs         =  evanescent_conn_ci_record_addrs,
5205392f7a3SLiteSpeed Tech    .ci_tick                 =  evanescent_conn_ci_tick,
5215392f7a3SLiteSpeed Tech};
5225392f7a3SLiteSpeed Tech
5235392f7a3SLiteSpeed Tech
5245392f7a3SLiteSpeed Techconst char *const lsquic_preqt2str[] =
5255392f7a3SLiteSpeed Tech{
5265392f7a3SLiteSpeed Tech    [PACKET_REQ_VERNEG] = "version negotiation",
5275392f7a3SLiteSpeed Tech    [PACKET_REQ_PUBRES] = "stateless reset",
5285392f7a3SLiteSpeed Tech};
529