lsquic_qdec_hdl.c revision 5392f7a3
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; 3875392f7a3SLiteSpeed Tech unsigned i; 3885392f7a3SLiteSpeed Tech void *hset; 3895392f7a3SLiteSpeed Tech 3905392f7a3SLiteSpeed Tech hset = hset_if->hsi_create_header_set(qdh->qdh_hsi_ctx, 0); 3915392f7a3SLiteSpeed Tech if (!hset) 3925392f7a3SLiteSpeed Tech { 3935392f7a3SLiteSpeed Tech LSQ_INFO("call to hsi_create_header_set failed"); 3945392f7a3SLiteSpeed Tech return -1; 3955392f7a3SLiteSpeed Tech } 3965392f7a3SLiteSpeed Tech 3975392f7a3SLiteSpeed Tech LSQ_DEBUG("got header set for stream %"PRIu64, stream->id); 3985392f7a3SLiteSpeed Tech 3995392f7a3SLiteSpeed Tech for (i = 0; i < qlist->qhl_count; ++i) 4005392f7a3SLiteSpeed Tech { 4015392f7a3SLiteSpeed Tech header = qlist->qhl_headers[i]; 4025392f7a3SLiteSpeed Tech LSQ_DEBUG("%.*s: %.*s", header->qh_name_len, header->qh_name, 4035392f7a3SLiteSpeed Tech header->qh_value_len, header->qh_value); 4045392f7a3SLiteSpeed Tech st = hset_if->hsi_process_header(hset, 4055392f7a3SLiteSpeed Tech header->qh_flags & QH_ID_SET ? 62 /* XXX: 62 */ + header->qh_static_id : 0, 4065392f7a3SLiteSpeed Tech header->qh_name, header->qh_name_len, 4075392f7a3SLiteSpeed Tech header->qh_value, header->qh_value_len); 4085392f7a3SLiteSpeed Tech if (st != LSQUIC_HDR_OK) 4095392f7a3SLiteSpeed Tech goto err; 4105392f7a3SLiteSpeed Tech } 4115392f7a3SLiteSpeed Tech 4125392f7a3SLiteSpeed Tech lsqpack_dec_destroy_header_list(qlist); 4135392f7a3SLiteSpeed Tech st = hset_if->hsi_process_header(hset, 0, 0, 0, 0, 0); 4145392f7a3SLiteSpeed Tech if (st != LSQUIC_HDR_OK) 4155392f7a3SLiteSpeed Tech goto err; 4165392f7a3SLiteSpeed Tech 4175392f7a3SLiteSpeed Tech uh = calloc(1, sizeof(*uh)); 4185392f7a3SLiteSpeed Tech if (!uh) 4195392f7a3SLiteSpeed Tech goto err; 4205392f7a3SLiteSpeed Tech uh->uh_stream_id = stream->id; 4215392f7a3SLiteSpeed Tech uh->uh_oth_stream_id = 0; 4225392f7a3SLiteSpeed Tech uh->uh_weight = 0; 4235392f7a3SLiteSpeed Tech uh->uh_exclusive = -1; 4245392f7a3SLiteSpeed Tech if (hset_if == lsquic_http1x_if) 4255392f7a3SLiteSpeed Tech uh->uh_flags |= UH_H1H; 4265392f7a3SLiteSpeed Tech uh->uh_hset = hset; 4275392f7a3SLiteSpeed Tech if (0 != lsquic_stream_uh_in(stream, uh)) 4285392f7a3SLiteSpeed Tech goto err; 4295392f7a3SLiteSpeed Tech LSQ_DEBUG("converted qlist to hset and gave it to stream %"PRIu64, 4305392f7a3SLiteSpeed Tech stream->id); 4315392f7a3SLiteSpeed Tech return 0; 4325392f7a3SLiteSpeed Tech 4335392f7a3SLiteSpeed Tech err: 4345392f7a3SLiteSpeed Tech lsqpack_dec_destroy_header_list(qlist); 4355392f7a3SLiteSpeed Tech hset_if->hsi_discard_header_set(hset); 4365392f7a3SLiteSpeed Tech free(uh); 4375392f7a3SLiteSpeed Tech return -1; 4385392f7a3SLiteSpeed Tech} 4395392f7a3SLiteSpeed Tech 4405392f7a3SLiteSpeed Tech 4415392f7a3SLiteSpeed Techstatic enum lsqpack_read_header_status 4425392f7a3SLiteSpeed Techqdh_header_read_results (struct qpack_dec_hdl *qdh, 4435392f7a3SLiteSpeed Tech struct lsquic_stream *stream, enum lsqpack_read_header_status rhs, 4445392f7a3SLiteSpeed Tech struct lsqpack_header_list *qlist, const unsigned char *dec_buf, 4455392f7a3SLiteSpeed Tech size_t dec_buf_sz) 4465392f7a3SLiteSpeed Tech{ 4475392f7a3SLiteSpeed Tech const struct lsqpack_dec_err *qerr; 4485392f7a3SLiteSpeed Tech 4495392f7a3SLiteSpeed Tech if (rhs == LQRHS_DONE) 4505392f7a3SLiteSpeed Tech { 4515392f7a3SLiteSpeed Tech if (qlist) 4525392f7a3SLiteSpeed Tech { 4535392f7a3SLiteSpeed Tech if (0 != qdh_supply_hset_to_stream(qdh, stream, qlist)) 4545392f7a3SLiteSpeed Tech return LQRHS_ERROR; 4555392f7a3SLiteSpeed Tech if (qdh->qdh_dec_sm_out) 4565392f7a3SLiteSpeed Tech { 4575392f7a3SLiteSpeed Tech if (dec_buf_sz 4585392f7a3SLiteSpeed Tech && 0 != qdh_write_decoder(qdh, dec_buf, dec_buf_sz)) 4595392f7a3SLiteSpeed Tech { 4605392f7a3SLiteSpeed Tech return LQRHS_ERROR; 4615392f7a3SLiteSpeed Tech } 4625392f7a3SLiteSpeed Tech if (dec_buf_sz || lsqpack_dec_ici_pending(&qdh->qdh_decoder)) 4635392f7a3SLiteSpeed Tech lsquic_stream_wantwrite(qdh->qdh_dec_sm_out, 1); 4645392f7a3SLiteSpeed Tech } 4655392f7a3SLiteSpeed Tech } 4665392f7a3SLiteSpeed Tech else 4675392f7a3SLiteSpeed Tech { 4685392f7a3SLiteSpeed Tech assert(0); /* XXX TODO What do we do here? */ 4695392f7a3SLiteSpeed Tech return LQRHS_ERROR; 4705392f7a3SLiteSpeed Tech } 4715392f7a3SLiteSpeed Tech } 4725392f7a3SLiteSpeed Tech else if (rhs == LQRHS_ERROR) 4735392f7a3SLiteSpeed Tech { 4745392f7a3SLiteSpeed Tech qerr = lsqpack_dec_get_err_info(&qdh->qdh_decoder); 4755392f7a3SLiteSpeed Tech qdh->qdh_conn->cn_if->ci_abort_error(qdh->qdh_conn, 1, 4765392f7a3SLiteSpeed Tech HEC_QPACK_DECOMPRESSION_FAILED, "QPACK decompression error; " 4775392f7a3SLiteSpeed Tech "stream %"PRIu64", offset %"PRIu64", line %d", qerr->stream_id, 4785392f7a3SLiteSpeed Tech qerr->off, qerr->line); 4795392f7a3SLiteSpeed Tech } 4805392f7a3SLiteSpeed Tech 4815392f7a3SLiteSpeed Tech return rhs; 4825392f7a3SLiteSpeed Tech} 4835392f7a3SLiteSpeed Tech 4845392f7a3SLiteSpeed Tech 4855392f7a3SLiteSpeed Techenum lsqpack_read_header_status 4865392f7a3SLiteSpeed Techlsquic_qdh_header_in_begin (struct qpack_dec_hdl *qdh, 4875392f7a3SLiteSpeed Tech struct lsquic_stream *stream, uint64_t header_size, 4885392f7a3SLiteSpeed Tech const unsigned char **buf, size_t bufsz) 4895392f7a3SLiteSpeed Tech{ 4905392f7a3SLiteSpeed Tech enum lsqpack_read_header_status rhs; 4915392f7a3SLiteSpeed Tech struct lsqpack_header_list *qlist; 4925392f7a3SLiteSpeed Tech size_t dec_buf_sz; 4935392f7a3SLiteSpeed Tech unsigned char dec_buf[LSQPACK_LONGEST_HEADER_ACK]; 4945392f7a3SLiteSpeed Tech 4955392f7a3SLiteSpeed Tech if (qdh->qdh_flags & QDH_INITIALIZED) 4965392f7a3SLiteSpeed Tech { 4975392f7a3SLiteSpeed Tech dec_buf_sz = sizeof(dec_buf); 4985392f7a3SLiteSpeed Tech rhs = lsqpack_dec_header_in(&qdh->qdh_decoder, stream, stream->id, 4995392f7a3SLiteSpeed Tech header_size, buf, bufsz, &qlist, dec_buf, &dec_buf_sz); 5005392f7a3SLiteSpeed Tech return qdh_header_read_results(qdh, stream, rhs, qlist, dec_buf, 5015392f7a3SLiteSpeed Tech dec_buf_sz); 5025392f7a3SLiteSpeed Tech } 5035392f7a3SLiteSpeed Tech else 5045392f7a3SLiteSpeed Tech { 5055392f7a3SLiteSpeed Tech LSQ_WARN("not initialized: cannot process header block"); 5065392f7a3SLiteSpeed Tech return LQRHS_ERROR; 5075392f7a3SLiteSpeed Tech } 5085392f7a3SLiteSpeed Tech 5095392f7a3SLiteSpeed Tech} 5105392f7a3SLiteSpeed Tech 5115392f7a3SLiteSpeed Tech 5125392f7a3SLiteSpeed Techenum lsqpack_read_header_status 5135392f7a3SLiteSpeed Techlsquic_qdh_header_in_continue (struct qpack_dec_hdl *qdh, 5145392f7a3SLiteSpeed Tech struct lsquic_stream *stream, const unsigned char **buf, size_t bufsz) 5155392f7a3SLiteSpeed Tech{ 5165392f7a3SLiteSpeed Tech enum lsqpack_read_header_status rhs; 5175392f7a3SLiteSpeed Tech struct lsqpack_header_list *qlist; 5185392f7a3SLiteSpeed Tech size_t dec_buf_sz; 5195392f7a3SLiteSpeed Tech unsigned char dec_buf[LSQPACK_LONGEST_HEADER_ACK]; 5205392f7a3SLiteSpeed Tech 5215392f7a3SLiteSpeed Tech if (qdh->qdh_flags & QDH_INITIALIZED) 5225392f7a3SLiteSpeed Tech { 5235392f7a3SLiteSpeed Tech dec_buf_sz = sizeof(dec_buf); 5245392f7a3SLiteSpeed Tech rhs = lsqpack_dec_header_read(&qdh->qdh_decoder, stream, 5255392f7a3SLiteSpeed Tech buf, bufsz, &qlist, dec_buf, &dec_buf_sz); 5265392f7a3SLiteSpeed Tech return qdh_header_read_results(qdh, stream, rhs, qlist, dec_buf, 5275392f7a3SLiteSpeed Tech dec_buf_sz); 5285392f7a3SLiteSpeed Tech } 5295392f7a3SLiteSpeed Tech else 5305392f7a3SLiteSpeed Tech { 5315392f7a3SLiteSpeed Tech LSQ_WARN("not initialized: cannot process header block"); 5325392f7a3SLiteSpeed Tech return LQRHS_ERROR; 5335392f7a3SLiteSpeed Tech } 5345392f7a3SLiteSpeed Tech} 5355392f7a3SLiteSpeed Tech 5365392f7a3SLiteSpeed Tech 5375392f7a3SLiteSpeed Techvoid 5385392f7a3SLiteSpeed Techlsquic_qdh_unref_stream (struct qpack_dec_hdl *qdh, 5395392f7a3SLiteSpeed Tech struct lsquic_stream *stream) 5405392f7a3SLiteSpeed Tech{ 5415392f7a3SLiteSpeed Tech if (0 == lsqpack_dec_unref_stream(&qdh->qdh_decoder, stream)) 5425392f7a3SLiteSpeed Tech LSQ_DEBUG("unreffed stream %"PRIu64, stream->id); 5435392f7a3SLiteSpeed Tech else 5445392f7a3SLiteSpeed Tech LSQ_WARN("cannot unref stream %"PRIu64, stream->id); 5455392f7a3SLiteSpeed Tech} 5465392f7a3SLiteSpeed Tech 5475392f7a3SLiteSpeed Tech 5485392f7a3SLiteSpeed Techvoid 5495392f7a3SLiteSpeed Techlsquic_qdh_cancel_stream (struct qpack_dec_hdl *qdh, 5505392f7a3SLiteSpeed Tech struct lsquic_stream *stream) 5515392f7a3SLiteSpeed Tech{ 5525392f7a3SLiteSpeed Tech ssize_t nw; 5535392f7a3SLiteSpeed Tech unsigned char buf[LSQPACK_LONGEST_CANCEL]; 5545392f7a3SLiteSpeed Tech 5555392f7a3SLiteSpeed Tech nw = lsqpack_dec_cancel_stream(&qdh->qdh_decoder, stream, buf, sizeof(buf)); 5565392f7a3SLiteSpeed Tech if (nw > 0) 5575392f7a3SLiteSpeed Tech { 5585392f7a3SLiteSpeed Tech if (0 == qdh_write_decoder(qdh, buf, nw)) 5595392f7a3SLiteSpeed Tech LSQ_DEBUG("cancelled stream %"PRIu64" and wrote %zd-byte Cancel " 5605392f7a3SLiteSpeed Tech "Stream instruction to the decoder stream", stream->id, nw); 5615392f7a3SLiteSpeed Tech } 5625392f7a3SLiteSpeed Tech else if (nw == 0) 5635392f7a3SLiteSpeed Tech LSQ_WARN("cannot cancel stream %"PRIu64" -- not found", stream->id); 5645392f7a3SLiteSpeed Tech else 5655392f7a3SLiteSpeed Tech { 5665392f7a3SLiteSpeed Tech LSQ_WARN("cannot cancel stream %"PRIu64" -- not enough buffer space " 5675392f7a3SLiteSpeed Tech "to encode Cancel Stream instructin", stream->id); 5685392f7a3SLiteSpeed Tech lsquic_qdh_unref_stream(qdh, stream); 5695392f7a3SLiteSpeed Tech } 5705392f7a3SLiteSpeed Tech} 571