lsquic_qdec_hdl.c revision a137764b
15392f7a3SLiteSpeed Tech/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
25392f7a3SLiteSpeed Tech/*
35392f7a3SLiteSpeed Tech * lsquic_qdec_hdl.c -- QPACK decoder streams handler
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>
125392f7a3SLiteSpeed Tech
135392f7a3SLiteSpeed Tech#include "lsquic.h"
145392f7a3SLiteSpeed Tech#include "lsquic_types.h"
155392f7a3SLiteSpeed Tech#include "lsquic_int_types.h"
165392f7a3SLiteSpeed Tech#include "lsquic_sfcw.h"
175392f7a3SLiteSpeed Tech#include "lsquic_varint.h"
185392f7a3SLiteSpeed Tech#include "lsquic_hq.h"
195392f7a3SLiteSpeed Tech#include "lsquic_hash.h"
205392f7a3SLiteSpeed Tech#include "lsquic_stream.h"
215392f7a3SLiteSpeed Tech#include "lsquic_frab_list.h"
225392f7a3SLiteSpeed Tech#include "lsqpack.h"
235392f7a3SLiteSpeed Tech#include "lsquic_http1x_if.h"
245392f7a3SLiteSpeed Tech#include "lsquic_qdec_hdl.h"
255392f7a3SLiteSpeed Tech#include "lsquic_mm.h"
265392f7a3SLiteSpeed Tech#include "lsquic_engine_public.h"
275392f7a3SLiteSpeed Tech#include "lsquic_headers.h"
285392f7a3SLiteSpeed Tech#include "lsquic_http1x_if.h"
295392f7a3SLiteSpeed Tech#include "lsquic_conn.h"
305392f7a3SLiteSpeed Tech
315392f7a3SLiteSpeed Tech#define LSQUIC_LOGGER_MODULE LSQLM_QDEC_HDL
325392f7a3SLiteSpeed Tech#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(qdh->qdh_conn)
335392f7a3SLiteSpeed Tech#include "lsquic_logger.h"
345392f7a3SLiteSpeed Tech
355392f7a3SLiteSpeed Techstatic void
365392f7a3SLiteSpeed Techqdh_hblock_unblocked (void *);
375392f7a3SLiteSpeed Tech
385392f7a3SLiteSpeed Tech
395392f7a3SLiteSpeed Techstatic int
405392f7a3SLiteSpeed Techqdh_write_decoder (struct qpack_dec_hdl *qdh, const unsigned char *buf,
415392f7a3SLiteSpeed Tech                                                                size_t sz)
425392f7a3SLiteSpeed Tech{
435392f7a3SLiteSpeed Tech    ssize_t nw;
445392f7a3SLiteSpeed Tech
455392f7a3SLiteSpeed Tech    if (!(qdh->qdh_dec_sm_out && lsquic_frab_list_empty(&qdh->qdh_fral)))
465392f7a3SLiteSpeed Tech    {
475392f7a3SLiteSpeed Tech  write_to_frab:
485392f7a3SLiteSpeed Tech        if (0 == lsquic_frab_list_write(&qdh->qdh_fral,
495392f7a3SLiteSpeed Tech                                                (unsigned char *) buf, sz))
505392f7a3SLiteSpeed Tech        {
515392f7a3SLiteSpeed Tech            LSQ_DEBUG("wrote %zu bytes to frab list", sz);
525392f7a3SLiteSpeed Tech            lsquic_stream_wantwrite(qdh->qdh_dec_sm_out, 1);
535392f7a3SLiteSpeed Tech            return 0;
545392f7a3SLiteSpeed Tech        }
555392f7a3SLiteSpeed Tech        else
565392f7a3SLiteSpeed Tech        {
575392f7a3SLiteSpeed Tech            LSQ_INFO("error writing to frab list");
585392f7a3SLiteSpeed Tech            return -1;
595392f7a3SLiteSpeed Tech        }
605392f7a3SLiteSpeed Tech    }
615392f7a3SLiteSpeed Tech
625392f7a3SLiteSpeed Tech    nw = lsquic_stream_write(qdh->qdh_dec_sm_out, buf, sz);
635392f7a3SLiteSpeed Tech    if (nw < 0)
645392f7a3SLiteSpeed Tech    {
655392f7a3SLiteSpeed Tech        LSQ_INFO("error writing to outgoing QPACK decoder stream: %s",
665392f7a3SLiteSpeed Tech                                                        strerror(errno));
675392f7a3SLiteSpeed Tech        return -1;
685392f7a3SLiteSpeed Tech    }
695392f7a3SLiteSpeed Tech    LSQ_DEBUG("wrote %zd bytes to outgoing QPACK decoder stream", nw);
705392f7a3SLiteSpeed Tech
715392f7a3SLiteSpeed Tech    if ((size_t) nw == sz)
725392f7a3SLiteSpeed Tech        return 0;
735392f7a3SLiteSpeed Tech
745392f7a3SLiteSpeed Tech    buf = buf + nw;
755392f7a3SLiteSpeed Tech    sz -= (size_t) nw;
765392f7a3SLiteSpeed Tech    goto write_to_frab;
775392f7a3SLiteSpeed Tech}
785392f7a3SLiteSpeed Tech
795392f7a3SLiteSpeed Tech
805392f7a3SLiteSpeed Techstatic int
815392f7a3SLiteSpeed Techqdh_write_type (struct qpack_dec_hdl *qdh)
825392f7a3SLiteSpeed Tech{
835392f7a3SLiteSpeed Tech    int s;
845392f7a3SLiteSpeed Tech
855392f7a3SLiteSpeed Tech#ifndef NDEBUG
865392f7a3SLiteSpeed Tech    const char *env = getenv("LSQUIC_RND_VARINT_LEN");
875392f7a3SLiteSpeed Tech    if (env && atoi(env))
885392f7a3SLiteSpeed Tech    {
895392f7a3SLiteSpeed Tech        s = rand() & 3;
905392f7a3SLiteSpeed Tech        LSQ_DEBUG("writing %d-byte stream type", 1 << s);
915392f7a3SLiteSpeed Tech    }
925392f7a3SLiteSpeed Tech    else
935392f7a3SLiteSpeed Tech#endif
945392f7a3SLiteSpeed Tech        s = 0;
955392f7a3SLiteSpeed Tech
965392f7a3SLiteSpeed Tech    switch (s)
975392f7a3SLiteSpeed Tech    {
985392f7a3SLiteSpeed Tech    case 0:
995392f7a3SLiteSpeed Tech        return qdh_write_decoder(qdh,
1005392f7a3SLiteSpeed Tech                                (unsigned char []) { HQUST_QPACK_DEC }, 1);
1015392f7a3SLiteSpeed Tech    case 1:
1025392f7a3SLiteSpeed Tech        return qdh_write_decoder(qdh,
1035392f7a3SLiteSpeed Tech                            (unsigned char []) { 0x40, HQUST_QPACK_DEC }, 2);
1045392f7a3SLiteSpeed Tech    case 2:
1055392f7a3SLiteSpeed Tech        return qdh_write_decoder(qdh,
1065392f7a3SLiteSpeed Tech                (unsigned char []) { 0x80, 0x00, 0x00, HQUST_QPACK_DEC }, 4);
1075392f7a3SLiteSpeed Tech    default:
1085392f7a3SLiteSpeed Tech        return qdh_write_decoder(qdh,
1095392f7a3SLiteSpeed Tech                (unsigned char []) { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1105392f7a3SLiteSpeed Tech                                                        HQUST_QPACK_DEC }, 8);
1115392f7a3SLiteSpeed Tech    }
1125392f7a3SLiteSpeed Tech}
1135392f7a3SLiteSpeed Tech
1145392f7a3SLiteSpeed Tech
1155392f7a3SLiteSpeed Techstatic void
1165392f7a3SLiteSpeed Techqdh_begin_out (struct qpack_dec_hdl *qdh)
1175392f7a3SLiteSpeed Tech{
1185392f7a3SLiteSpeed Tech    if (0 != qdh_write_type(qdh))
1195392f7a3SLiteSpeed Tech    {
1205392f7a3SLiteSpeed Tech        LSQ_WARN("%s: could not write to decoder", __func__);
1215392f7a3SLiteSpeed Tech        qdh->qdh_conn->cn_if->ci_internal_error(qdh->qdh_conn,
1225392f7a3SLiteSpeed Tech                                        "cannot write to decoder stream");
1235392f7a3SLiteSpeed Tech    }
1245392f7a3SLiteSpeed Tech}
1255392f7a3SLiteSpeed Tech
1265392f7a3SLiteSpeed Tech
1275392f7a3SLiteSpeed Techint
1285392f7a3SLiteSpeed Techlsquic_qdh_init (struct qpack_dec_hdl *qdh, struct lsquic_conn *conn,
1295392f7a3SLiteSpeed Tech                    int is_server, const struct lsquic_engine_public *enpub,
1305392f7a3SLiteSpeed Tech                    unsigned dyn_table_size, unsigned max_risked_streams)
1315392f7a3SLiteSpeed Tech{
1325392f7a3SLiteSpeed Tech    qdh->qdh_conn = conn;
1335392f7a3SLiteSpeed Tech    lsquic_frab_list_init(&qdh->qdh_fral, 0x400, NULL, NULL, NULL);
1345392f7a3SLiteSpeed Tech    lsqpack_dec_init(&qdh->qdh_decoder, (void *) conn, dyn_table_size,
1355392f7a3SLiteSpeed Tech                        max_risked_streams, qdh_hblock_unblocked);
1365392f7a3SLiteSpeed Tech    qdh->qdh_flags |= QDH_INITIALIZED;
1375392f7a3SLiteSpeed Tech    qdh->qdh_enpub = enpub;
1385392f7a3SLiteSpeed Tech    if (qdh->qdh_enpub->enp_hsi_if == lsquic_http1x_if)
1395392f7a3SLiteSpeed Tech    {
1405392f7a3SLiteSpeed Tech        qdh->qdh_h1x_ctor_ctx = (struct http1x_ctor_ctx) {
1415392f7a3SLiteSpeed Tech            .conn           = conn,
1425392f7a3SLiteSpeed Tech            .max_headers_sz = 0x10000,  /* XXX */
1435392f7a3SLiteSpeed Tech            .is_server      = is_server,
1445392f7a3SLiteSpeed Tech        };
1455392f7a3SLiteSpeed Tech        qdh->qdh_hsi_ctx = &qdh->qdh_h1x_ctor_ctx;
1465392f7a3SLiteSpeed Tech    }
1475392f7a3SLiteSpeed Tech    else
1485392f7a3SLiteSpeed Tech        qdh->qdh_hsi_ctx = qdh->qdh_enpub->enp_hsi_ctx;
1495392f7a3SLiteSpeed Tech    if (qdh->qdh_dec_sm_out)
1505392f7a3SLiteSpeed Tech        qdh_begin_out(qdh);
1515392f7a3SLiteSpeed Tech    if (qdh->qdh_enc_sm_in)
1525392f7a3SLiteSpeed Tech        lsquic_stream_wantread(qdh->qdh_enc_sm_in, 1);
1535392f7a3SLiteSpeed Tech    LSQ_DEBUG("initialized");
1545392f7a3SLiteSpeed Tech    return 0;
1555392f7a3SLiteSpeed Tech}
1565392f7a3SLiteSpeed Tech
1575392f7a3SLiteSpeed Tech
1585392f7a3SLiteSpeed Techvoid
1595392f7a3SLiteSpeed Techlsquic_qdh_cleanup (struct qpack_dec_hdl *qdh)
1605392f7a3SLiteSpeed Tech{
1615392f7a3SLiteSpeed Tech    if (qdh->qdh_flags & QDH_INITIALIZED)
1625392f7a3SLiteSpeed Tech    {
1635392f7a3SLiteSpeed Tech        LSQ_DEBUG("cleanup");
1645392f7a3SLiteSpeed Tech        lsqpack_dec_cleanup(&qdh->qdh_decoder);
1655392f7a3SLiteSpeed Tech        lsquic_frab_list_cleanup(&qdh->qdh_fral);
1665392f7a3SLiteSpeed Tech        qdh->qdh_flags &= ~QDH_INITIALIZED;
1675392f7a3SLiteSpeed Tech    }
1685392f7a3SLiteSpeed Tech}
1695392f7a3SLiteSpeed Tech
1705392f7a3SLiteSpeed Techstatic lsquic_stream_ctx_t *
1715392f7a3SLiteSpeed Techqdh_out_on_new (void *stream_if_ctx, struct lsquic_stream *stream)
1725392f7a3SLiteSpeed Tech{
1735392f7a3SLiteSpeed Tech    struct qpack_dec_hdl *const qdh = stream_if_ctx;
1745392f7a3SLiteSpeed Tech    qdh->qdh_dec_sm_out = stream;
1755392f7a3SLiteSpeed Tech    if (qdh->qdh_flags & QDH_INITIALIZED)
1765392f7a3SLiteSpeed Tech        qdh_begin_out(qdh);
1775392f7a3SLiteSpeed Tech    LSQ_DEBUG("initialized outgoing decoder stream");
1785392f7a3SLiteSpeed Tech    return (void *) qdh;
1795392f7a3SLiteSpeed Tech}
1805392f7a3SLiteSpeed Tech
1815392f7a3SLiteSpeed Tech
1825392f7a3SLiteSpeed Techstatic void
1835392f7a3SLiteSpeed Techqdh_out_on_write (struct lsquic_stream *stream, lsquic_stream_ctx_t *ctx)
1845392f7a3SLiteSpeed Tech{
1855392f7a3SLiteSpeed Tech    struct qpack_dec_hdl *const qdh = (void *) ctx;
1865392f7a3SLiteSpeed Tech    struct lsquic_reader reader;
1875392f7a3SLiteSpeed Tech    ssize_t nw;
1885392f7a3SLiteSpeed Tech    unsigned char buf[LSQPACK_LONGEST_ICI];
1895392f7a3SLiteSpeed Tech
1905392f7a3SLiteSpeed Tech    if (lsqpack_dec_ici_pending(&qdh->qdh_decoder))
1915392f7a3SLiteSpeed Tech    {
1925392f7a3SLiteSpeed Tech        nw = lsqpack_dec_write_ici(&qdh->qdh_decoder, buf, sizeof(buf));
1935392f7a3SLiteSpeed Tech        if (nw > 0)
1945392f7a3SLiteSpeed Tech        {
1955392f7a3SLiteSpeed Tech            if (0 == qdh_write_decoder(qdh, buf, nw))
1965392f7a3SLiteSpeed Tech                LSQ_DEBUG("wrote %zd-byte TSS instruction", nw);
1975392f7a3SLiteSpeed Tech            else
1985392f7a3SLiteSpeed Tech                goto err;
1995392f7a3SLiteSpeed Tech        }
2005392f7a3SLiteSpeed Tech        else if (nw < 0)
2015392f7a3SLiteSpeed Tech        {
2025392f7a3SLiteSpeed Tech            LSQ_WARN("could not generate TSS instruction");
2035392f7a3SLiteSpeed Tech            goto err;
2045392f7a3SLiteSpeed Tech        }
2055392f7a3SLiteSpeed Tech    }
2065392f7a3SLiteSpeed Tech
2075392f7a3SLiteSpeed Tech    if (lsquic_frab_list_empty(&qdh->qdh_fral))
2085392f7a3SLiteSpeed Tech    {
2095392f7a3SLiteSpeed Tech        LSQ_DEBUG("%s: nothing to write", __func__);
2105392f7a3SLiteSpeed Tech        lsquic_stream_wantwrite(stream, 0);
2115392f7a3SLiteSpeed Tech        return;
2125392f7a3SLiteSpeed Tech    }
2135392f7a3SLiteSpeed Tech
2145392f7a3SLiteSpeed Tech    reader = (struct lsquic_reader) {
2155392f7a3SLiteSpeed Tech        .lsqr_read  = lsquic_frab_list_read,
2165392f7a3SLiteSpeed Tech        .lsqr_size  = lsquic_frab_list_size,
2175392f7a3SLiteSpeed Tech        .lsqr_ctx   = &qdh->qdh_fral,
2185392f7a3SLiteSpeed Tech    };
2195392f7a3SLiteSpeed Tech
2205392f7a3SLiteSpeed Tech    nw = lsquic_stream_writef(stream, &reader);
2215392f7a3SLiteSpeed Tech    if (nw >= 0)
2225392f7a3SLiteSpeed Tech    {
2235392f7a3SLiteSpeed Tech        LSQ_DEBUG("wrote %zd bytes to stream", nw);
2245392f7a3SLiteSpeed Tech        (void) lsquic_stream_flush(stream);
2255392f7a3SLiteSpeed Tech        if (lsquic_frab_list_empty(&qdh->qdh_fral))
2265392f7a3SLiteSpeed Tech            lsquic_stream_wantwrite(stream, 0);
2275392f7a3SLiteSpeed Tech    }
2285392f7a3SLiteSpeed Tech    else
2295392f7a3SLiteSpeed Tech    {
2305392f7a3SLiteSpeed Tech        LSQ_WARN("cannot write to stream: %s", strerror(errno));
2315392f7a3SLiteSpeed Tech  err:
2325392f7a3SLiteSpeed Tech        lsquic_stream_wantwrite(stream, 0);
2335392f7a3SLiteSpeed Tech        qdh->qdh_conn->cn_if->ci_internal_error(qdh->qdh_conn,
2345392f7a3SLiteSpeed Tech                                        "cannot write to stream");
2355392f7a3SLiteSpeed Tech    }
2365392f7a3SLiteSpeed Tech}
2375392f7a3SLiteSpeed Tech
2385392f7a3SLiteSpeed Tech
2395392f7a3SLiteSpeed Techstatic void
2405392f7a3SLiteSpeed Techqdh_out_on_close (struct lsquic_stream *stream, lsquic_stream_ctx_t *ctx)
2415392f7a3SLiteSpeed Tech{
2425392f7a3SLiteSpeed Tech    struct qpack_dec_hdl *const qdh = (void *) ctx;
2435392f7a3SLiteSpeed Tech    qdh->qdh_dec_sm_out = NULL;
2445392f7a3SLiteSpeed Tech    LSQ_DEBUG("closed outgoing decoder stream");
2455392f7a3SLiteSpeed Tech}
2465392f7a3SLiteSpeed Tech
2475392f7a3SLiteSpeed Tech
2485392f7a3SLiteSpeed Techstatic void
2495392f7a3SLiteSpeed Techqdh_out_on_read (struct lsquic_stream *stream, lsquic_stream_ctx_t *ctx)
2505392f7a3SLiteSpeed Tech{
2515392f7a3SLiteSpeed Tech    assert(0);
2525392f7a3SLiteSpeed Tech}
2535392f7a3SLiteSpeed Tech
2545392f7a3SLiteSpeed Tech
2555392f7a3SLiteSpeed Techstatic const struct lsquic_stream_if qdh_dec_sm_out_if =
2565392f7a3SLiteSpeed Tech{
2575392f7a3SLiteSpeed Tech    .on_new_stream  = qdh_out_on_new,
2585392f7a3SLiteSpeed Tech    .on_read        = qdh_out_on_read,
2595392f7a3SLiteSpeed Tech    .on_write       = qdh_out_on_write,
2605392f7a3SLiteSpeed Tech    .on_close       = qdh_out_on_close,
2615392f7a3SLiteSpeed Tech};
2625392f7a3SLiteSpeed Techconst struct lsquic_stream_if *const lsquic_qdh_dec_sm_out_if =
2635392f7a3SLiteSpeed Tech                                                    &qdh_dec_sm_out_if;
2645392f7a3SLiteSpeed Tech
2655392f7a3SLiteSpeed Tech
2665392f7a3SLiteSpeed Techstatic lsquic_stream_ctx_t *
2675392f7a3SLiteSpeed Techqdh_in_on_new (void *stream_if_ctx, struct lsquic_stream *stream)
2685392f7a3SLiteSpeed Tech{
2695392f7a3SLiteSpeed Tech    struct qpack_dec_hdl *const qdh = stream_if_ctx;
2705392f7a3SLiteSpeed Tech    qdh->qdh_enc_sm_in = stream;
2715392f7a3SLiteSpeed Tech    if (qdh->qdh_flags & QDH_INITIALIZED)
2725392f7a3SLiteSpeed Tech        lsquic_stream_wantread(qdh->qdh_enc_sm_in, 1);
2735392f7a3SLiteSpeed Tech    LSQ_DEBUG("initialized incoming encoder stream");
2745392f7a3SLiteSpeed Tech    return (void *) qdh;
2755392f7a3SLiteSpeed Tech}
2765392f7a3SLiteSpeed Tech
2775392f7a3SLiteSpeed Tech
2785392f7a3SLiteSpeed Techstatic size_t
2795392f7a3SLiteSpeed Techqdh_read_encoder_stream (void *ctx, const unsigned char *buf, size_t sz,
2805392f7a3SLiteSpeed Tech                                                                    int fin)
2815392f7a3SLiteSpeed Tech{
2825392f7a3SLiteSpeed Tech    struct qpack_dec_hdl *const qdh = (void *) ctx;
2835392f7a3SLiteSpeed Tech    const struct lsqpack_dec_err *qerr;
2845392f7a3SLiteSpeed Tech    int s;
2855392f7a3SLiteSpeed Tech
2865392f7a3SLiteSpeed Tech    if (fin)
2875392f7a3SLiteSpeed Tech    {
2885392f7a3SLiteSpeed Tech        LSQ_INFO("encoder stream is closed");
2895392f7a3SLiteSpeed Tech        qdh->qdh_conn->cn_if->ci_abort_error(qdh->qdh_conn, 1,
2905392f7a3SLiteSpeed Tech            HEC_CLOSED_CRITICAL_STREAM, "Peer closed QPACK encoder stream");
2915392f7a3SLiteSpeed Tech        goto end;
2925392f7a3SLiteSpeed Tech    }
2935392f7a3SLiteSpeed Tech
2945392f7a3SLiteSpeed Tech    s = lsqpack_dec_enc_in(&qdh->qdh_decoder, buf, sz);
2955392f7a3SLiteSpeed Tech    if (s != 0)
2965392f7a3SLiteSpeed Tech    {
2975392f7a3SLiteSpeed Tech        LSQ_INFO("error reading decoder stream");
2985392f7a3SLiteSpeed Tech        qerr = lsqpack_dec_get_err_info(&qdh->qdh_decoder);
2995392f7a3SLiteSpeed Tech        qdh->qdh_conn->cn_if->ci_abort_error(qdh->qdh_conn, 1,
3005392f7a3SLiteSpeed Tech            HEC_QPACK_DECODER_STREAM_ERROR, "Error interpreting QPACK encoder "
3015392f7a3SLiteSpeed Tech            "stream; offset %"PRIu64", line %d", qerr->off, qerr->line);
3025392f7a3SLiteSpeed Tech        goto end;
3035392f7a3SLiteSpeed Tech    }
3045392f7a3SLiteSpeed Tech    if (qdh->qdh_dec_sm_out
3055392f7a3SLiteSpeed Tech                    && lsqpack_dec_ici_pending(&qdh->qdh_decoder))
3065392f7a3SLiteSpeed Tech        lsquic_stream_wantwrite(qdh->qdh_dec_sm_out, 1);
3075392f7a3SLiteSpeed Tech
3085392f7a3SLiteSpeed Tech    LSQ_DEBUG("successfully fed %zu bytes to QPACK decoder", sz);
3095392f7a3SLiteSpeed Tech
3105392f7a3SLiteSpeed Tech  end:
3115392f7a3SLiteSpeed Tech    return sz;
3125392f7a3SLiteSpeed Tech}
3135392f7a3SLiteSpeed Tech
3145392f7a3SLiteSpeed Tech
3155392f7a3SLiteSpeed Techstatic void
3165392f7a3SLiteSpeed Techqdh_in_on_read (struct lsquic_stream *stream, lsquic_stream_ctx_t *ctx)
3175392f7a3SLiteSpeed Tech{
3185392f7a3SLiteSpeed Tech    struct qpack_dec_hdl *const qdh = (void *) ctx;
3195392f7a3SLiteSpeed Tech    ssize_t nread;
3205392f7a3SLiteSpeed Tech
3215392f7a3SLiteSpeed Tech    nread = lsquic_stream_readf(stream, qdh_read_encoder_stream, qdh);
3225392f7a3SLiteSpeed Tech    if (nread <= 0)
3235392f7a3SLiteSpeed Tech    {
3245392f7a3SLiteSpeed Tech        if (nread < 0)
3255392f7a3SLiteSpeed Tech        {
3265392f7a3SLiteSpeed Tech            LSQ_WARN("cannot read from encoder stream: %s", strerror(errno));
3275392f7a3SLiteSpeed Tech            qdh->qdh_conn->cn_if->ci_internal_error(qdh->qdh_conn,
3285392f7a3SLiteSpeed Tech                                        "cannot read from encoder stream");
3295392f7a3SLiteSpeed Tech        }
3305392f7a3SLiteSpeed Tech        else
3315392f7a3SLiteSpeed Tech        {
3325392f7a3SLiteSpeed Tech            LSQ_INFO("encoder stream closed by peer: abort connection");
3335392f7a3SLiteSpeed Tech            qdh->qdh_conn->cn_if->ci_abort_error(qdh->qdh_conn, 1,
3345392f7a3SLiteSpeed Tech                HEC_CLOSED_CRITICAL_STREAM, "encoder stream closed");
3355392f7a3SLiteSpeed Tech        }
3365392f7a3SLiteSpeed Tech        lsquic_stream_wantread(stream, 0);
3375392f7a3SLiteSpeed Tech    }
3385392f7a3SLiteSpeed Tech}
3395392f7a3SLiteSpeed Tech
3405392f7a3SLiteSpeed Tech
3415392f7a3SLiteSpeed Techstatic void
3425392f7a3SLiteSpeed Techqdh_in_on_close (struct lsquic_stream *stream, lsquic_stream_ctx_t *ctx)
3435392f7a3SLiteSpeed Tech{
3445392f7a3SLiteSpeed Tech    struct qpack_dec_hdl *const qdh = (void *) ctx;
3455392f7a3SLiteSpeed Tech    LSQ_DEBUG("closed incoming encoder stream");
3465392f7a3SLiteSpeed Tech    qdh->qdh_enc_sm_in = NULL;
3475392f7a3SLiteSpeed Tech}
3485392f7a3SLiteSpeed Tech
3495392f7a3SLiteSpeed Tech
3505392f7a3SLiteSpeed Techstatic void
3515392f7a3SLiteSpeed Techqdh_in_on_write (struct lsquic_stream *stream, lsquic_stream_ctx_t *ctx)
3525392f7a3SLiteSpeed Tech{
3535392f7a3SLiteSpeed Tech    assert(0);
3545392f7a3SLiteSpeed Tech}
3555392f7a3SLiteSpeed Tech
3565392f7a3SLiteSpeed Tech
3575392f7a3SLiteSpeed Techstatic const struct lsquic_stream_if qdh_enc_sm_in_if =
3585392f7a3SLiteSpeed Tech{
3595392f7a3SLiteSpeed Tech    .on_new_stream  = qdh_in_on_new,
3605392f7a3SLiteSpeed Tech    .on_read        = qdh_in_on_read,
3615392f7a3SLiteSpeed Tech    .on_write       = qdh_in_on_write,
3625392f7a3SLiteSpeed Tech    .on_close       = qdh_in_on_close,
3635392f7a3SLiteSpeed Tech};
3645392f7a3SLiteSpeed Techconst struct lsquic_stream_if *const lsquic_qdh_enc_sm_in_if =
3655392f7a3SLiteSpeed Tech                                                    &qdh_enc_sm_in_if;
3665392f7a3SLiteSpeed Tech
3675392f7a3SLiteSpeed Tech
3685392f7a3SLiteSpeed Techstatic void
3695392f7a3SLiteSpeed Techqdh_hblock_unblocked (void *stream_p)
3705392f7a3SLiteSpeed Tech{
3715392f7a3SLiteSpeed Tech    struct lsquic_stream *const stream = stream_p;
3725392f7a3SLiteSpeed Tech    struct qpack_dec_hdl *const qdh = lsquic_stream_get_qdh(stream);
3735392f7a3SLiteSpeed Tech
3745392f7a3SLiteSpeed Tech    LSQ_DEBUG("header block for stream %"PRIu64" unblocked", stream->id);
3755392f7a3SLiteSpeed Tech    lsquic_stream_qdec_unblocked(stream);
3765392f7a3SLiteSpeed Tech}
3775392f7a3SLiteSpeed Tech
3785392f7a3SLiteSpeed Tech
3795392f7a3SLiteSpeed Techstatic int
3805392f7a3SLiteSpeed Techqdh_supply_hset_to_stream (struct qpack_dec_hdl *qdh,
3815392f7a3SLiteSpeed Tech            struct lsquic_stream *stream, struct lsqpack_header_list *qlist)
3825392f7a3SLiteSpeed Tech{
3835392f7a3SLiteSpeed Tech    const struct lsquic_hset_if *const hset_if = qdh->qdh_enpub->enp_hsi_if;
3845392f7a3SLiteSpeed Tech    struct uncompressed_headers *uh = NULL;
3855392f7a3SLiteSpeed Tech    const struct lsqpack_header *header;
3865392f7a3SLiteSpeed Tech    enum lsquic_header_status st;
38702b6086dSDmitri Tikhonov    int push_promise;
3885392f7a3SLiteSpeed Tech    unsigned i;
3895392f7a3SLiteSpeed Tech    void *hset;
3905392f7a3SLiteSpeed Tech
39102b6086dSDmitri Tikhonov    push_promise = lsquic_stream_header_is_pp(stream);
39202b6086dSDmitri Tikhonov    hset = hset_if->hsi_create_header_set(qdh->qdh_hsi_ctx, push_promise);
3935392f7a3SLiteSpeed Tech    if (!hset)
3945392f7a3SLiteSpeed Tech    {
3955392f7a3SLiteSpeed Tech        LSQ_INFO("call to hsi_create_header_set failed");
3965392f7a3SLiteSpeed Tech        return -1;
3975392f7a3SLiteSpeed Tech    }
3985392f7a3SLiteSpeed Tech
3995392f7a3SLiteSpeed Tech    LSQ_DEBUG("got header set for stream %"PRIu64, stream->id);
4005392f7a3SLiteSpeed Tech
4015392f7a3SLiteSpeed Tech    for (i = 0; i < qlist->qhl_count; ++i)
4025392f7a3SLiteSpeed Tech    {
4035392f7a3SLiteSpeed Tech        header = qlist->qhl_headers[i];
4045392f7a3SLiteSpeed Tech        LSQ_DEBUG("%.*s: %.*s", header->qh_name_len, header->qh_name,
4055392f7a3SLiteSpeed Tech                                        header->qh_value_len, header->qh_value);
4065392f7a3SLiteSpeed Tech        st = hset_if->hsi_process_header(hset,
4075392f7a3SLiteSpeed Tech                    header->qh_flags & QH_ID_SET ? 62 /* XXX: 62 */ + header->qh_static_id : 0,
4085392f7a3SLiteSpeed Tech                    header->qh_name, header->qh_name_len,
4095392f7a3SLiteSpeed Tech                    header->qh_value, header->qh_value_len);
4105392f7a3SLiteSpeed Tech        if (st != LSQUIC_HDR_OK)
411a137764bSDmitri Tikhonov        {
412a137764bSDmitri Tikhonov            LSQ_INFO("header process returned non-OK code %u", (unsigned) st);
4135392f7a3SLiteSpeed Tech            goto err;
414a137764bSDmitri Tikhonov        }
4155392f7a3SLiteSpeed Tech    }
4165392f7a3SLiteSpeed Tech
4175392f7a3SLiteSpeed Tech    lsqpack_dec_destroy_header_list(qlist);
418a0e1aeeeSDmitri Tikhonov    qlist = NULL;
4195392f7a3SLiteSpeed Tech    st = hset_if->hsi_process_header(hset, 0, 0, 0, 0, 0);
4205392f7a3SLiteSpeed Tech    if (st != LSQUIC_HDR_OK)
4215392f7a3SLiteSpeed Tech        goto err;
4225392f7a3SLiteSpeed Tech
4235392f7a3SLiteSpeed Tech    uh = calloc(1, sizeof(*uh));
4245392f7a3SLiteSpeed Tech    if (!uh)
4255392f7a3SLiteSpeed Tech        goto err;
4265392f7a3SLiteSpeed Tech    uh->uh_stream_id = stream->id;
4275392f7a3SLiteSpeed Tech    uh->uh_oth_stream_id = 0;
4285392f7a3SLiteSpeed Tech    uh->uh_weight = 0;
4295392f7a3SLiteSpeed Tech    uh->uh_exclusive = -1;
4305392f7a3SLiteSpeed Tech    if (hset_if == lsquic_http1x_if)
4315392f7a3SLiteSpeed Tech        uh->uh_flags    |= UH_H1H;
4325392f7a3SLiteSpeed Tech    uh->uh_hset = hset;
4335392f7a3SLiteSpeed Tech    if (0 != lsquic_stream_uh_in(stream, uh))
4345392f7a3SLiteSpeed Tech        goto err;
4355392f7a3SLiteSpeed Tech    LSQ_DEBUG("converted qlist to hset and gave it to stream %"PRIu64,
4365392f7a3SLiteSpeed Tech                                                                stream->id);
4375392f7a3SLiteSpeed Tech    return 0;
4385392f7a3SLiteSpeed Tech
4395392f7a3SLiteSpeed Tech  err:
440a0e1aeeeSDmitri Tikhonov    if (qlist)
441a0e1aeeeSDmitri Tikhonov        lsqpack_dec_destroy_header_list(qlist);
4425392f7a3SLiteSpeed Tech    hset_if->hsi_discard_header_set(hset);
4435392f7a3SLiteSpeed Tech    free(uh);
4445392f7a3SLiteSpeed Tech    return -1;
4455392f7a3SLiteSpeed Tech}
4465392f7a3SLiteSpeed Tech
4475392f7a3SLiteSpeed Tech
44802b6086dSDmitri Tikhonovstatic int
44902b6086dSDmitri Tikhonovqdh_process_qlist (struct qpack_dec_hdl *qdh,
45002b6086dSDmitri Tikhonov            struct lsquic_stream *stream, struct lsqpack_header_list *qlist)
45102b6086dSDmitri Tikhonov{
45202b6086dSDmitri Tikhonov    if (!lsquic_stream_header_is_trailer(stream))
45302b6086dSDmitri Tikhonov        return qdh_supply_hset_to_stream(qdh, stream, qlist);
45402b6086dSDmitri Tikhonov    else
45502b6086dSDmitri Tikhonov    {
45602b6086dSDmitri Tikhonov        LSQ_DEBUG("discard trailer header set");
45702b6086dSDmitri Tikhonov        lsqpack_dec_destroy_header_list(qlist);
45802b6086dSDmitri Tikhonov        return 0;
45902b6086dSDmitri Tikhonov    }
46002b6086dSDmitri Tikhonov}
46102b6086dSDmitri Tikhonov
46202b6086dSDmitri Tikhonov
4635392f7a3SLiteSpeed Techstatic enum lsqpack_read_header_status
4645392f7a3SLiteSpeed Techqdh_header_read_results (struct qpack_dec_hdl *qdh,
4655392f7a3SLiteSpeed Tech        struct lsquic_stream *stream, enum lsqpack_read_header_status rhs,
4665392f7a3SLiteSpeed Tech        struct lsqpack_header_list *qlist, const unsigned char *dec_buf,
4675392f7a3SLiteSpeed Tech        size_t dec_buf_sz)
4685392f7a3SLiteSpeed Tech{
4695392f7a3SLiteSpeed Tech    const struct lsqpack_dec_err *qerr;
4705392f7a3SLiteSpeed Tech
4715392f7a3SLiteSpeed Tech    if (rhs == LQRHS_DONE)
4725392f7a3SLiteSpeed Tech    {
4735392f7a3SLiteSpeed Tech        if (qlist)
4745392f7a3SLiteSpeed Tech        {
47502b6086dSDmitri Tikhonov            if (0 != qdh_process_qlist(qdh, stream, qlist))
4765392f7a3SLiteSpeed Tech                return LQRHS_ERROR;
4775392f7a3SLiteSpeed Tech            if (qdh->qdh_dec_sm_out)
4785392f7a3SLiteSpeed Tech            {
4795392f7a3SLiteSpeed Tech                if (dec_buf_sz
4805392f7a3SLiteSpeed Tech                    && 0 != qdh_write_decoder(qdh, dec_buf, dec_buf_sz))
4815392f7a3SLiteSpeed Tech                {
4825392f7a3SLiteSpeed Tech                    return LQRHS_ERROR;
4835392f7a3SLiteSpeed Tech                }
4845392f7a3SLiteSpeed Tech                if (dec_buf_sz || lsqpack_dec_ici_pending(&qdh->qdh_decoder))
4855392f7a3SLiteSpeed Tech                    lsquic_stream_wantwrite(qdh->qdh_dec_sm_out, 1);
4865392f7a3SLiteSpeed Tech            }
4875392f7a3SLiteSpeed Tech        }
4885392f7a3SLiteSpeed Tech        else
4895392f7a3SLiteSpeed Tech        {
4905392f7a3SLiteSpeed Tech            assert(0);  /* XXX TODO What do we do here? */
4915392f7a3SLiteSpeed Tech            return LQRHS_ERROR;
4925392f7a3SLiteSpeed Tech        }
4935392f7a3SLiteSpeed Tech    }
4945392f7a3SLiteSpeed Tech    else if (rhs == LQRHS_ERROR)
4955392f7a3SLiteSpeed Tech    {
4965392f7a3SLiteSpeed Tech        qerr = lsqpack_dec_get_err_info(&qdh->qdh_decoder);
4975392f7a3SLiteSpeed Tech        qdh->qdh_conn->cn_if->ci_abort_error(qdh->qdh_conn, 1,
4985392f7a3SLiteSpeed Tech            HEC_QPACK_DECOMPRESSION_FAILED, "QPACK decompression error; "
4995392f7a3SLiteSpeed Tech            "stream %"PRIu64", offset %"PRIu64", line %d", qerr->stream_id,
5005392f7a3SLiteSpeed Tech            qerr->off, qerr->line);
5015392f7a3SLiteSpeed Tech    }
5025392f7a3SLiteSpeed Tech
5035392f7a3SLiteSpeed Tech    return rhs;
5045392f7a3SLiteSpeed Tech}
5055392f7a3SLiteSpeed Tech
5065392f7a3SLiteSpeed Tech
5075392f7a3SLiteSpeed Techenum lsqpack_read_header_status
5085392f7a3SLiteSpeed Techlsquic_qdh_header_in_begin (struct qpack_dec_hdl *qdh,
5095392f7a3SLiteSpeed Tech                        struct lsquic_stream *stream, uint64_t header_size,
5105392f7a3SLiteSpeed Tech                        const unsigned char **buf, size_t bufsz)
5115392f7a3SLiteSpeed Tech{
5125392f7a3SLiteSpeed Tech    enum lsqpack_read_header_status rhs;
5135392f7a3SLiteSpeed Tech    struct lsqpack_header_list *qlist;
5145392f7a3SLiteSpeed Tech    size_t dec_buf_sz;
5155392f7a3SLiteSpeed Tech    unsigned char dec_buf[LSQPACK_LONGEST_HEADER_ACK];
5165392f7a3SLiteSpeed Tech
5175392f7a3SLiteSpeed Tech    if (qdh->qdh_flags & QDH_INITIALIZED)
5185392f7a3SLiteSpeed Tech    {
5195392f7a3SLiteSpeed Tech        dec_buf_sz = sizeof(dec_buf);
5205392f7a3SLiteSpeed Tech        rhs = lsqpack_dec_header_in(&qdh->qdh_decoder, stream, stream->id,
5215392f7a3SLiteSpeed Tech                        header_size, buf, bufsz, &qlist, dec_buf, &dec_buf_sz);
5225392f7a3SLiteSpeed Tech        return qdh_header_read_results(qdh, stream, rhs, qlist, dec_buf,
5235392f7a3SLiteSpeed Tech                                                                dec_buf_sz);
5245392f7a3SLiteSpeed Tech    }
5255392f7a3SLiteSpeed Tech    else
5265392f7a3SLiteSpeed Tech    {
5275392f7a3SLiteSpeed Tech        LSQ_WARN("not initialized: cannot process header block");
5285392f7a3SLiteSpeed Tech        return LQRHS_ERROR;
5295392f7a3SLiteSpeed Tech    }
5305392f7a3SLiteSpeed Tech
5315392f7a3SLiteSpeed Tech}
5325392f7a3SLiteSpeed Tech
5335392f7a3SLiteSpeed Tech
5345392f7a3SLiteSpeed Techenum lsqpack_read_header_status
5355392f7a3SLiteSpeed Techlsquic_qdh_header_in_continue (struct qpack_dec_hdl *qdh,
5365392f7a3SLiteSpeed Tech        struct lsquic_stream *stream, const unsigned char **buf, size_t bufsz)
5375392f7a3SLiteSpeed Tech{
5385392f7a3SLiteSpeed Tech    enum lsqpack_read_header_status rhs;
5395392f7a3SLiteSpeed Tech    struct lsqpack_header_list *qlist;
5405392f7a3SLiteSpeed Tech    size_t dec_buf_sz;
5415392f7a3SLiteSpeed Tech    unsigned char dec_buf[LSQPACK_LONGEST_HEADER_ACK];
5425392f7a3SLiteSpeed Tech
5435392f7a3SLiteSpeed Tech    if (qdh->qdh_flags & QDH_INITIALIZED)
5445392f7a3SLiteSpeed Tech    {
5455392f7a3SLiteSpeed Tech        dec_buf_sz = sizeof(dec_buf);
5465392f7a3SLiteSpeed Tech        rhs = lsqpack_dec_header_read(&qdh->qdh_decoder, stream,
5475392f7a3SLiteSpeed Tech                                    buf, bufsz, &qlist, dec_buf, &dec_buf_sz);
5485392f7a3SLiteSpeed Tech        return qdh_header_read_results(qdh, stream, rhs, qlist, dec_buf,
5495392f7a3SLiteSpeed Tech                                                                dec_buf_sz);
5505392f7a3SLiteSpeed Tech    }
5515392f7a3SLiteSpeed Tech    else
5525392f7a3SLiteSpeed Tech    {
5535392f7a3SLiteSpeed Tech        LSQ_WARN("not initialized: cannot process header block");
5545392f7a3SLiteSpeed Tech        return LQRHS_ERROR;
5555392f7a3SLiteSpeed Tech    }
5565392f7a3SLiteSpeed Tech}
5575392f7a3SLiteSpeed Tech
5585392f7a3SLiteSpeed Tech
5595392f7a3SLiteSpeed Techvoid
5605392f7a3SLiteSpeed Techlsquic_qdh_unref_stream (struct qpack_dec_hdl *qdh,
5615392f7a3SLiteSpeed Tech                                                struct lsquic_stream *stream)
5625392f7a3SLiteSpeed Tech{
5635392f7a3SLiteSpeed Tech    if (0 == lsqpack_dec_unref_stream(&qdh->qdh_decoder, stream))
5645392f7a3SLiteSpeed Tech        LSQ_DEBUG("unreffed stream %"PRIu64, stream->id);
5655392f7a3SLiteSpeed Tech    else
5665392f7a3SLiteSpeed Tech        LSQ_WARN("cannot unref stream %"PRIu64, stream->id);
5675392f7a3SLiteSpeed Tech}
5685392f7a3SLiteSpeed Tech
5695392f7a3SLiteSpeed Tech
5705392f7a3SLiteSpeed Techvoid
5715392f7a3SLiteSpeed Techlsquic_qdh_cancel_stream (struct qpack_dec_hdl *qdh,
5725392f7a3SLiteSpeed Tech                                                struct lsquic_stream *stream)
5735392f7a3SLiteSpeed Tech{
5745392f7a3SLiteSpeed Tech    ssize_t nw;
5755392f7a3SLiteSpeed Tech    unsigned char buf[LSQPACK_LONGEST_CANCEL];
5765392f7a3SLiteSpeed Tech
5775392f7a3SLiteSpeed Tech    nw = lsqpack_dec_cancel_stream(&qdh->qdh_decoder, stream, buf, sizeof(buf));
5785392f7a3SLiteSpeed Tech    if (nw > 0)
5795392f7a3SLiteSpeed Tech    {
5805392f7a3SLiteSpeed Tech        if (0 == qdh_write_decoder(qdh, buf, nw))
5815392f7a3SLiteSpeed Tech            LSQ_DEBUG("cancelled stream %"PRIu64" and wrote %zd-byte Cancel "
5825392f7a3SLiteSpeed Tech                "Stream instruction to the decoder stream", stream->id, nw);
5835392f7a3SLiteSpeed Tech    }
5845392f7a3SLiteSpeed Tech    else if (nw == 0)
5855392f7a3SLiteSpeed Tech        LSQ_WARN("cannot cancel stream %"PRIu64" -- not found", stream->id);
5865392f7a3SLiteSpeed Tech    else
5875392f7a3SLiteSpeed Tech    {
5885392f7a3SLiteSpeed Tech        LSQ_WARN("cannot cancel stream %"PRIu64" -- not enough buffer space "
5895392f7a3SLiteSpeed Tech            "to encode Cancel Stream instructin", stream->id);
5905392f7a3SLiteSpeed Tech        lsquic_qdh_unref_stream(qdh, stream);
5915392f7a3SLiteSpeed Tech    }
5925392f7a3SLiteSpeed Tech}
593