mirror of
https://github.com/vacp2p/lsquic.git
synced 2026-08-30 22:21:17 +00:00
Remove the HTTP/2 and HTTP/3 push promise implementation while keeping the public APIs in place as disabled stubs. Server push is no longer used, so this drops the associated state, frame generation, parsing callbacks, and stream bookkeeping. Update tests and documentation to cover the disabled behavior and the remaining HTTP/3 framing paths.
1185 lines
39 KiB
C
1185 lines
39 KiB
C
/* Copyright (c) 2017 - 2026 LiteSpeed Technologies Inc. See LICENSE. */
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#ifndef WIN32
|
|
#include <unistd.h>
|
|
#else
|
|
#include <getopt.h>
|
|
#endif
|
|
#include <sys/queue.h>
|
|
|
|
#include "lsquic.h"
|
|
#include "lsquic_frame_common.h"
|
|
#include "lshpack.h"
|
|
#include "lsquic_mm.h"
|
|
#include "lsquic_int_types.h"
|
|
#include "lsquic_conn_flow.h"
|
|
#include "lsquic_sfcw.h"
|
|
#include "lsquic_rtt.h"
|
|
#include "lsquic_hash.h"
|
|
#include "lsquic_conn.h"
|
|
#include "lsquic_varint.h"
|
|
#include "lsquic_hq.h"
|
|
#include "lsquic_stream.h"
|
|
#include "lsquic_conn_public.h"
|
|
#include "lsquic_logger.h"
|
|
#if LSQUIC_CONN_STATS
|
|
#include "lsquic_int_types.h"
|
|
#include "lsquic_conn.h"
|
|
#endif
|
|
|
|
#include "lsquic_frame_reader.h"
|
|
#include "lsquic_headers.h"
|
|
#include "lsquic_http1x_if.h"
|
|
|
|
|
|
struct callback_value /* What callback returns */
|
|
{
|
|
enum {
|
|
CV_HEADERS,
|
|
CV_SETTINGS,
|
|
CV_PRIORITY,
|
|
CV_ERROR,
|
|
} type;
|
|
unsigned stream_off; /* Checked only if not zero */
|
|
union {
|
|
struct headers {
|
|
uint32_t stream_id;
|
|
uint32_t oth_stream_id;
|
|
unsigned short weight;
|
|
signed char exclusive;
|
|
unsigned char flags;
|
|
unsigned size;
|
|
unsigned off;
|
|
char buf[0x100];
|
|
} headers;
|
|
struct {
|
|
uint16_t id;
|
|
uint32_t value;
|
|
} setting;
|
|
struct cv_error {
|
|
enum frame_reader_error code;
|
|
lsquic_stream_id_t stream_id;
|
|
} error;
|
|
struct cv_priority {
|
|
lsquic_stream_id_t stream_id;
|
|
int exclusive;
|
|
lsquic_stream_id_t dep_stream_id;
|
|
unsigned weight;
|
|
} priority;
|
|
} u;
|
|
};
|
|
|
|
|
|
void
|
|
compare_headers (const struct headers *got_h, const struct headers *exp_h)
|
|
{
|
|
assert(got_h->stream_id == exp_h->stream_id);
|
|
assert(got_h->oth_stream_id == exp_h->oth_stream_id);
|
|
assert(got_h->weight == exp_h->weight);
|
|
assert(got_h->exclusive == exp_h->exclusive);
|
|
assert(got_h->size == exp_h->size);
|
|
assert(strlen(got_h->buf) == got_h->size);
|
|
assert(got_h->off == exp_h->off);
|
|
assert(got_h->flags == exp_h->flags);
|
|
assert(0 == memcmp(got_h->buf, exp_h->buf, got_h->size));
|
|
}
|
|
|
|
|
|
void
|
|
compare_priorities (const struct cv_priority *got_prio,
|
|
const struct cv_priority *exp_prio)
|
|
{
|
|
assert(got_prio->stream_id == exp_prio->stream_id);
|
|
assert(got_prio->exclusive == exp_prio->exclusive);
|
|
assert(got_prio->dep_stream_id == exp_prio->dep_stream_id);
|
|
assert(got_prio->weight == exp_prio->weight);
|
|
}
|
|
|
|
|
|
void
|
|
compare_errors (const struct cv_error *got_err,
|
|
const struct cv_error *exp_err)
|
|
{
|
|
assert(got_err->code == exp_err->code);
|
|
assert(got_err->stream_id == exp_err->stream_id);
|
|
}
|
|
|
|
|
|
static void
|
|
compare_cb_vals (const struct callback_value *got,
|
|
const struct callback_value *exp)
|
|
{
|
|
assert(got->type == exp->type);
|
|
if (exp->stream_off)
|
|
assert(exp->stream_off == got->stream_off);
|
|
switch (got->type)
|
|
{
|
|
case CV_HEADERS:
|
|
compare_headers(&got->u.headers, &exp->u.headers);
|
|
break;
|
|
case CV_ERROR:
|
|
compare_errors(&got->u.error, &exp->u.error);
|
|
break;
|
|
case CV_PRIORITY:
|
|
compare_priorities(&got->u.priority, &exp->u.priority);
|
|
break;
|
|
case CV_SETTINGS:
|
|
/* TODO */
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static struct {
|
|
size_t in_sz;
|
|
size_t in_off;
|
|
size_t in_max_req_sz;
|
|
size_t in_max_sz;
|
|
unsigned char in_buf[0x1000];
|
|
} input;
|
|
|
|
|
|
static struct cb_ctx {
|
|
unsigned n_cb_vals;
|
|
struct callback_value cb_vals[10];
|
|
} g_cb_ctx;
|
|
|
|
|
|
static void
|
|
reset_cb_ctx (struct cb_ctx *cb_ctx)
|
|
{
|
|
cb_ctx->n_cb_vals = 0;
|
|
memset(&cb_ctx->cb_vals, 0xA5, sizeof(cb_ctx->cb_vals));
|
|
}
|
|
|
|
|
|
static void
|
|
copy_uh_to_headers (const struct uncompressed_headers *uh, struct headers *h)
|
|
{
|
|
const struct http1x_headers *h1h = uh->uh_hset;
|
|
h->flags = uh->uh_flags;
|
|
h->weight = uh->uh_weight;
|
|
h->stream_id = uh->uh_stream_id;
|
|
h->exclusive = uh->uh_exclusive;
|
|
h->oth_stream_id = uh->uh_oth_stream_id;
|
|
h->size = h1h->h1h_size;
|
|
h->off = h1h->h1h_off;
|
|
memcpy(h->buf, h1h->h1h_buf, h->size);
|
|
h->buf[h->size] = '\0';
|
|
}
|
|
|
|
|
|
static void
|
|
on_incoming_headers (void *ctx, struct uncompressed_headers *uh)
|
|
{
|
|
struct cb_ctx *cb_ctx = ctx;
|
|
assert(cb_ctx == &g_cb_ctx);
|
|
unsigned i = cb_ctx->n_cb_vals++;
|
|
assert(i < sizeof(cb_ctx->cb_vals) / sizeof(cb_ctx->cb_vals[0]));
|
|
cb_ctx->cb_vals[i].type = CV_HEADERS;
|
|
cb_ctx->cb_vals[i].stream_off = input.in_off;
|
|
copy_uh_to_headers(uh, &cb_ctx->cb_vals[i].u.headers);
|
|
assert(uh->uh_flags & UH_H1H);
|
|
lsquic_http1x_if->hsi_discard_header_set(uh->uh_hset);
|
|
free(uh);
|
|
}
|
|
|
|
|
|
static void
|
|
on_error (void *ctx, lsquic_stream_id_t stream_id, enum frame_reader_error error)
|
|
{
|
|
struct cb_ctx *cb_ctx = ctx;
|
|
assert(cb_ctx == &g_cb_ctx);
|
|
unsigned i = cb_ctx->n_cb_vals++;
|
|
assert(i < sizeof(cb_ctx->cb_vals) / sizeof(cb_ctx->cb_vals[0]));
|
|
cb_ctx->cb_vals[i].type = CV_ERROR;
|
|
cb_ctx->cb_vals[i].u.error.stream_id = stream_id;
|
|
cb_ctx->cb_vals[i].u.error.code = error;
|
|
cb_ctx->cb_vals[i].stream_off = input.in_off;
|
|
}
|
|
|
|
|
|
static void
|
|
on_settings (void *ctx, uint16_t id, uint32_t value)
|
|
{
|
|
struct cb_ctx *cb_ctx = ctx;
|
|
assert(cb_ctx == &g_cb_ctx);
|
|
unsigned i = cb_ctx->n_cb_vals++;
|
|
assert(i < sizeof(cb_ctx->cb_vals) / sizeof(cb_ctx->cb_vals[0]));
|
|
cb_ctx->cb_vals[i].type = CV_SETTINGS;
|
|
cb_ctx->cb_vals[i].u.setting.id = id;
|
|
cb_ctx->cb_vals[i].u.setting.value = value;
|
|
cb_ctx->cb_vals[i].stream_off = input.in_off;
|
|
}
|
|
|
|
|
|
static void
|
|
on_priority (void *ctx, lsquic_stream_id_t stream_id, int exclusive,
|
|
lsquic_stream_id_t dep_stream_id, unsigned weight)
|
|
{
|
|
struct cb_ctx *cb_ctx = ctx;
|
|
assert(cb_ctx == &g_cb_ctx);
|
|
unsigned i = cb_ctx->n_cb_vals++;
|
|
assert(i < sizeof(cb_ctx->cb_vals) / sizeof(cb_ctx->cb_vals[0]));
|
|
cb_ctx->cb_vals[i].type = CV_PRIORITY;
|
|
cb_ctx->cb_vals[i].u.priority.stream_id = stream_id;
|
|
cb_ctx->cb_vals[i].u.priority.exclusive = exclusive;
|
|
cb_ctx->cb_vals[i].u.priority.dep_stream_id = dep_stream_id;
|
|
cb_ctx->cb_vals[i].u.priority.weight = weight;
|
|
cb_ctx->cb_vals[i].stream_off = input.in_off;
|
|
}
|
|
|
|
|
|
static const struct frame_reader_callbacks frame_callbacks = {
|
|
.frc_on_headers = on_incoming_headers,
|
|
.frc_on_settings = on_settings,
|
|
.frc_on_priority = on_priority,
|
|
.frc_on_error = on_error,
|
|
};
|
|
|
|
|
|
static ssize_t
|
|
read_from_stream (struct lsquic_stream *stream, void *buf, size_t sz)
|
|
{
|
|
if (sz > input.in_max_req_sz)
|
|
input.in_max_req_sz = sz;
|
|
if (input.in_sz - input.in_off < sz)
|
|
sz = input.in_sz - input.in_off;
|
|
if (sz > input.in_max_sz)
|
|
sz = input.in_max_sz;
|
|
memcpy(buf, input.in_buf + input.in_off, sz);
|
|
input.in_off += sz;
|
|
return sz;
|
|
}
|
|
|
|
|
|
struct frame_reader_test {
|
|
unsigned frt_lineno;
|
|
/* Input */
|
|
enum frame_reader_flags frt_fr_flags;
|
|
unsigned char frt_buf[0x100];
|
|
unsigned short frt_bufsz;
|
|
unsigned frt_max_headers_sz;
|
|
/* Output */
|
|
unsigned short frt_in_off;
|
|
int frt_err; /* True if expecting error */
|
|
unsigned frt_n_cb_vals;
|
|
struct callback_value frt_cb_vals[10];
|
|
};
|
|
|
|
|
|
#define HEADERS(str) .buf = (str), .size = sizeof(str) - 1
|
|
|
|
static const struct frame_reader_test tests[] = {
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x04,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
0x80| /* <----- This bit must be ignored */
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
0x48, 0x82, 0x64, 0x02,
|
|
},
|
|
.frt_bufsz = 13,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0,
|
|
.weight = 0,
|
|
.exclusive = -1,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("HTTP/1.1 302 Found\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x16,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PADDED,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Padding length */0x11,
|
|
/* Block fragment: */
|
|
0x48, 0x82, 0x64, 0x02,
|
|
/* Padding: */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF,
|
|
},
|
|
.frt_bufsz = 9 + 1 + 4 + 17,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0,
|
|
.weight = 0,
|
|
.exclusive = -1,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("HTTP/1.1 302 Found\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x1B,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PADDED|HFHF_PRIORITY|
|
|
HFHF_END_STREAM,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Padding length */0x11,
|
|
/* Exclusive: */ 0x80|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0xFF,
|
|
/* Block fragment: */
|
|
0x48, 0x82, 0x64, 0x02,
|
|
/* Padding: */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF,
|
|
/* Length: */ 0x00, 0x00, 0x05,
|
|
/* Type: */ HTTP_FRAME_PRIORITY,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x00, 0x39,
|
|
/* Dep Stream Id: */0x80, 0x00, 0x00, 0x19,
|
|
/* Weight: */ 0x77,
|
|
},
|
|
.frt_bufsz = 9 + 1 + 5 + 4 + 17
|
|
+ 9 + 5,
|
|
.frt_n_cb_vals = 2,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0x1234,
|
|
.weight = 0xFF + 1,
|
|
.exclusive = 1,
|
|
.off = 0,
|
|
.flags = UH_FIN | UH_H1H,
|
|
HEADERS("HTTP/1.1 302 Found\r\n\r\n"),
|
|
},
|
|
},
|
|
{
|
|
.type = CV_PRIORITY,
|
|
.u.priority = {
|
|
.stream_id = 0x39,
|
|
.exclusive = 1,
|
|
.dep_stream_id = 0x19,
|
|
.weight = 0x77 + 1,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x09,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PRIORITY,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Exclusive: */ 0x00|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0x00,
|
|
/* Block fragment: */
|
|
0x48, 0x82, 0x64, 0x02,
|
|
},
|
|
.frt_bufsz = 9 + 5 + 4,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0x1234,
|
|
.weight = 1,
|
|
.exclusive = 0,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("HTTP/1.1 302 Found\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x0E,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PRIORITY,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Exclusive: */ 0x00|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0x00,
|
|
/* Block fragment: */
|
|
0x48, 0x82, 0x64, 0x02,
|
|
0x60, 0x03, 0x61, 0x3d, 0x62,
|
|
},
|
|
.frt_bufsz = 9 + 5 + 4 + 5,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0x1234,
|
|
.weight = 1,
|
|
.exclusive = 0,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("HTTP/1.1 302 Found\r\n"
|
|
"Cookie: a=b\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x18,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PRIORITY,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Exclusive: */ 0x00|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0x00,
|
|
/* Block fragment: */
|
|
0x48, 0x82, 0x64, 0x02,
|
|
0x60, 0x03, 0x61, 0x3d, 0x62,
|
|
0x60, 0x03, 0x63, 0x3d, 0x64,
|
|
0x60, 0x03, 0x65, 0x3d, 0x66,
|
|
},
|
|
.frt_bufsz = 9 + 5 + 4 + 15,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0x1234,
|
|
.weight = 1,
|
|
.exclusive = 0,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("HTTP/1.1 302 Found\r\n"
|
|
"Cookie: a=b; c=d; e=f\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = FRF_SERVER,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x16,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PRIORITY,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Exclusive: */ 0x00|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0x00,
|
|
/* Block fragment: */
|
|
0x82, 0x84, 0x86, 0x41, 0x8c, 0xf1, 0xe3, 0xc2,
|
|
0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4,
|
|
0xff,
|
|
/* Length: */ 0x00, 0x00, 0xEE,
|
|
/* Type: */ HTTP_FRAME_CONTINUATION,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
'W', 'H', 'A', 'T', 'E', 'V', 'E', 'R',
|
|
},
|
|
.frt_bufsz = 9 + 5 + 17
|
|
+ 9 + 0 + 8,
|
|
.frt_err = 1,
|
|
.frt_in_off = 9 + 5 + 17 + 9,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0x1234,
|
|
.weight = 1,
|
|
.exclusive = 0,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = FRF_SERVER,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x16,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PRIORITY,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Exclusive: */ 0x00|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0x00,
|
|
/* Block fragment: */
|
|
0x82, 0x84, 0x86, 0x41, 0x8c, 0xf1, 0xe3, 0xc2,
|
|
0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4,
|
|
0xff,
|
|
/* Length: */ 0x00, 0x00, 0xEE,
|
|
/* Type: */ HTTP_FRAME_CONTINUATION,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
'W', 'H', 'A', 'T', 'E', 'V', 'E', 'R',
|
|
},
|
|
.frt_bufsz = 9 + 5 + 17
|
|
+ 9 + 0 + 8,
|
|
.frt_err = 1,
|
|
.frt_in_off = 9 + 5 + 17 + 9,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0x1234,
|
|
.weight = 1,
|
|
.exclusive = 0,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = FRF_SERVER,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x16,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_PRIORITY,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Exclusive: */ 0x00|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0x00,
|
|
/* Block fragment: */
|
|
0x82, 0x84, 0x86, 0x41, 0x8c, 0xf1, 0xe3, 0xc2,
|
|
0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4,
|
|
0xff,
|
|
/* Length: */ 0x00, 0x00, 0xEE,
|
|
/* Type: */ HTTP_FRAME_CONTINUATION,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0xFF, 0x30, 0x39, /* Stream ID does not match */
|
|
/* Block fragment: */
|
|
'W', 'H', 'A', 'T', 'E', 'V', 'E', 'R',
|
|
},
|
|
.frt_bufsz = 9 + 5 + 17
|
|
+ 9 + 0 + 8,
|
|
.frt_err = 1,
|
|
.frt_in_off = 9 + 5 + 17 + 9,
|
|
.frt_n_cb_vals = 0,
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = FRF_SERVER,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0xEE,
|
|
/* Type: */ HTTP_FRAME_CONTINUATION,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
'W', 'H', 'A', 'T', 'E', 'V', 'E', 'R',
|
|
},
|
|
.frt_bufsz = 9 + 0 + 8,
|
|
.frt_err = 1,
|
|
.frt_in_off = 9,
|
|
.frt_n_cb_vals = 0,
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = FRF_SERVER,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x10,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ 0x00, /* Note absence of HFHF_END_HEADERS */
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment:
|
|
* perl hpack.pl :method GET :path / host www.example.com
|
|
*/
|
|
0x82, 0x84, 0x66, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5,
|
|
0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff,
|
|
/* Length: */ 0x00, 0x00, 0x08,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
'W', 'H', 'A', 'T', 'E', 'V', 'E', 'R',
|
|
},
|
|
.frt_bufsz = 9 + 0 + 16
|
|
+ 9 + 0 + 8,
|
|
.frt_in_off = 9 + 16 + 9,
|
|
.frt_err = 1,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.u.error = {
|
|
.stream_id = 0x3039,
|
|
.code = FR_ERR_EXPECTED_CONTIN,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = FRF_SERVER,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x10,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment:
|
|
* perl hpack.pl :method GET :path / host www.example.com
|
|
*/
|
|
0x82, 0x84, 0x66, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5,
|
|
0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff,
|
|
/* Length: */ 0x00, 0x00, 0x1A,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PRIORITY,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Exclusive: */ 0x00|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0x00,
|
|
/* Block fragment:
|
|
* perl hpack.pl :method GET :path / :scheme http Host www.example.com
|
|
*/
|
|
0x82, 0x84, 0x86, 0x40, 0x83, 0xc6, 0x74, 0x27,
|
|
0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b,
|
|
0xa0, 0xab, 0x90, 0xf4, 0xff,
|
|
/* Length: */ 0x00, 0x00, 0x11,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
0x82, 0x84, 0x86, 0x41, 0x8c, 0xf1, 0xe3, 0xc2,
|
|
0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4,
|
|
0xff,
|
|
},
|
|
.frt_bufsz = 9 + 0 + 16
|
|
+ 9 + 5 + 21
|
|
+ 9 + 0 + 17,
|
|
.frt_n_cb_vals = 3,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.u.error = {
|
|
.stream_id = 12345,
|
|
.code = FR_ERR_BAD_HEADER,
|
|
},
|
|
},
|
|
{
|
|
.type = CV_ERROR,
|
|
.u.error = {
|
|
.stream_id = 12345,
|
|
.code = FR_ERR_BAD_HEADER,
|
|
},
|
|
},
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0,
|
|
.weight = 0,
|
|
.exclusive = -1,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x15,
|
|
/* Type: */ HTTP_FRAME_PUSH_PROMISE,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Dep stream Id: */0x00, 0x12, 0x34, 0x56,
|
|
/* Block fragment: */
|
|
0x82, 0x84, 0x86, 0x41, 0x8c, 0xf1, 0xe3, 0xc2,
|
|
0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4,
|
|
0xff,
|
|
},
|
|
.frt_bufsz = 9 + 0 + 0x15,
|
|
.frt_in_off = 9,
|
|
.frt_err = 1,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.u.error = {
|
|
.stream_id = 12345,
|
|
.code = FR_ERR_UNEXPECTED_PUSH,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x02,
|
|
/* Type: */ HTTP_FRAME_HEADERS,
|
|
/* Flags: */ 0x00,
|
|
0x80| /* <----- This bit must be ignored */
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
0x48, 0x82,
|
|
/* Length: */ 0x00, 0x00, 0x02,
|
|
/* Type: */ HTTP_FRAME_CONTINUATION,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
0x64, 0x02,
|
|
},
|
|
.frt_bufsz = 9 + 2 + 9 + 2,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_HEADERS,
|
|
.u.headers = {
|
|
.stream_id = 12345,
|
|
.oth_stream_id = 0,
|
|
.weight = 0,
|
|
.exclusive = -1,
|
|
.off = 0,
|
|
.flags = UH_H1H,
|
|
HEADERS("HTTP/1.1 302 Found\r\n\r\n"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x00,
|
|
/* Type: */ HTTP_FRAME_SETTINGS,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
},
|
|
.frt_bufsz = 9,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_err = 1,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.u.error.code = FR_ERR_INVALID_FRAME_SIZE,
|
|
.u.error.stream_id = 12345,
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x07,
|
|
/* Type: */ HTTP_FRAME_SETTINGS,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
},
|
|
.frt_bufsz = 9 + 7,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_err = 1,
|
|
.frt_in_off = 9,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.u.error.code = FR_ERR_INVALID_FRAME_SIZE,
|
|
.u.error.stream_id = 12345,
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x06,
|
|
/* Type: */ HTTP_FRAME_SETTINGS,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
},
|
|
.frt_bufsz = 9 + 6,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_err = 1,
|
|
.frt_in_off = 9,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.u.error.code = FR_ERR_NONZERO_STREAM_ID,
|
|
.u.error.stream_id = 12345,
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x0C,
|
|
/* Type: */ HTTP_FRAME_SETTINGS,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x00, 0x00,
|
|
0x00, SETTINGS_INITIAL_WINDOW_SIZE,
|
|
0x01, 0x02, 0x03, 0x04,
|
|
0x00, SETTINGS_HEADER_TABLE_SIZE,
|
|
0x02, 0x03, 0x04, 0x05,
|
|
},
|
|
.frt_bufsz = 9 + 12,
|
|
.frt_n_cb_vals = 2,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_SETTINGS,
|
|
.u.setting.id = SETTINGS_INITIAL_WINDOW_SIZE,
|
|
.u.setting.value = 0x01020304,
|
|
},
|
|
{
|
|
.type = CV_SETTINGS,
|
|
.u.setting.id = SETTINGS_HEADER_TABLE_SIZE,
|
|
.u.setting.value = 0x02030405,
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x09,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS|HFHF_PRIORITY,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Exclusive: */ 0x00|
|
|
/* Dep Stream Id: */
|
|
0x00, 0x00, 0x12, 0x34,
|
|
/* Weight: */ 0x00,
|
|
/* Block fragment: */
|
|
0x48, 0x82, 0x64, 0x02,
|
|
/* Length: */ 0x00, 0x00, 0x06,
|
|
/* Type: */ HTTP_FRAME_SETTINGS,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x00, 0x00,
|
|
0x00, SETTINGS_INITIAL_WINDOW_SIZE,
|
|
0x01, 0x02, 0x03, 0x04,
|
|
},
|
|
.frt_bufsz = 9 + 5 + 4 + 9 + 6,
|
|
.frt_max_headers_sz = 10,
|
|
.frt_n_cb_vals = 2,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.stream_off = 9 + 5 + 4,
|
|
.u.error.code = FR_ERR_BAD_HEADER,
|
|
.u.error.stream_id = 12345,
|
|
},
|
|
{
|
|
.type = CV_SETTINGS,
|
|
.u.setting.id = SETTINGS_INITIAL_WINDOW_SIZE,
|
|
.u.setting.value = 0x01020304,
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x11,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
/* 0x11 bytes of no consequence: they are not
|
|
* parsed.
|
|
*/
|
|
000, 001, 002, 003, 004, 005, 006, 007,
|
|
010, 011, 012, 013, 014, 015, 016, 017,
|
|
020,
|
|
/* Length: */ 0x00, 0x00, 0x06,
|
|
/* Type: */ HTTP_FRAME_SETTINGS,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x00, 0x00,
|
|
0x00, SETTINGS_INITIAL_WINDOW_SIZE,
|
|
0x01, 0x02, 0x03, 0x04,
|
|
},
|
|
.frt_bufsz = 9 + 0 + 0x11 + 9 + 6,
|
|
.frt_max_headers_sz = 0x10,
|
|
.frt_n_cb_vals = 2,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.stream_off = 9,
|
|
.u.error.code = FR_ERR_BAD_HEADER,
|
|
.u.error.stream_id = 12345,
|
|
},
|
|
{
|
|
.type = CV_SETTINGS,
|
|
.u.setting.id = SETTINGS_INITIAL_WINDOW_SIZE,
|
|
.u.setting.value = 0x01020304,
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x10,
|
|
/* Type: */ 0x01,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
/* 0x10 bytes of no consequence: they are not
|
|
* parsed.
|
|
*/
|
|
000, 001, 002, 003, 004, 005, 006, 007,
|
|
010, 011, 012, 013, 014, 015, 016, 017,
|
|
/* Length: */ 0x00, 0x00, 0x10,
|
|
/* Type: */ HTTP_FRAME_CONTINUATION,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
000, 001, 002, 003, 004, 005, 006, 007,
|
|
010, 011, 012, 013, 014, 015, 016, 017,
|
|
/* Length: */ 0x00, 0x00, 0x10,
|
|
/* Type: */ HTTP_FRAME_CONTINUATION,
|
|
/* Flags: */ HFHF_END_HEADERS,
|
|
/* Stream Id: */ 0x00, 0x00, 0x30, 0x39,
|
|
/* Block fragment: */
|
|
000, 001, 002, 003, 004, 005, 006, 007,
|
|
010, 011, 012, 013, 014, 015, 016, 017,
|
|
/* Length: */ 0x00, 0x00, 0x06,
|
|
/* Type: */ HTTP_FRAME_SETTINGS,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x00, 0x00,
|
|
0x00, SETTINGS_INITIAL_WINDOW_SIZE,
|
|
0x01, 0x02, 0x03, 0x04,
|
|
},
|
|
.frt_bufsz = 9 + 0 + 0x10 + 9 + 0 + 0x10 + 9 + 0 + 0x10 + 9 + 6,
|
|
.frt_max_headers_sz = 0x19,
|
|
.frt_n_cb_vals = 2,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.stream_off = 9 + 0 + 0x10 + 9,
|
|
.u.error.code = FR_ERR_BAD_HEADER,
|
|
.u.error.stream_id = 12345,
|
|
},
|
|
{
|
|
.type = CV_SETTINGS,
|
|
.u.setting.id = SETTINGS_INITIAL_WINDOW_SIZE,
|
|
.u.setting.value = 0x01020304,
|
|
},
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00,
|
|
0x04, /* <-- wrong payload size */
|
|
/* Type: */ HTTP_FRAME_PRIORITY,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x00, 0x39,
|
|
/* Dep Stream Id: */0x80, 0x00, 0x00, 0x19,
|
|
/* Weight: */ 0x77,
|
|
},
|
|
.frt_bufsz = 9 + 5,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_err = 1,
|
|
.frt_in_off = 9,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.stream_off = 9,
|
|
.u.error.code = FR_ERR_INVALID_FRAME_SIZE,
|
|
.u.error.stream_id = 0x39,
|
|
}
|
|
},
|
|
},
|
|
|
|
{ .frt_lineno = __LINE__,
|
|
.frt_fr_flags = 0,
|
|
.frt_buf = {
|
|
/* Length: */ 0x00, 0x00, 0x05,
|
|
/* Type: */ HTTP_FRAME_PRIORITY,
|
|
/* Flags: */ 0x00,
|
|
/* Stream Id: */ 0x00, 0x00, 0x00, 0x00, /* Invalid stream ID */
|
|
/* Dep Stream Id: */0x80, 0x00, 0x00, 0x19,
|
|
/* Weight: */ 0x77,
|
|
},
|
|
.frt_bufsz = 9 + 5,
|
|
.frt_n_cb_vals = 1,
|
|
.frt_err = 1,
|
|
.frt_in_off = 9,
|
|
.frt_cb_vals = {
|
|
{
|
|
.type = CV_ERROR,
|
|
.stream_off = 9,
|
|
.u.error.code = FR_ERR_ZERO_STREAM_ID,
|
|
.u.error.stream_id = 0x00,
|
|
}
|
|
},
|
|
},
|
|
|
|
{
|
|
.frt_bufsz = 0,
|
|
},
|
|
};
|
|
|
|
|
|
static struct lsquic_stream *
|
|
my_get_stream_by_id (struct lsquic_conn *conn, lsquic_stream_id_t stream_id)
|
|
{
|
|
return (void *) my_get_stream_by_id;
|
|
}
|
|
|
|
|
|
static void
|
|
test_one_frt (const struct frame_reader_test *frt)
|
|
{
|
|
struct lsquic_frame_reader *fr;
|
|
unsigned short exp_off;
|
|
struct lshpack_dec hdec;
|
|
struct lsquic_mm mm;
|
|
struct lsquic_conn lconn;
|
|
struct lsquic_conn_public conn_pub;
|
|
struct lsquic_stream stream;
|
|
int s;
|
|
struct conn_iface my_conn_if;
|
|
|
|
#if LSQUIC_CONN_STATS
|
|
struct conn_stats conn_stats;
|
|
memset(&conn_stats, 0, sizeof(conn_stats));
|
|
#endif
|
|
|
|
memset(&stream, 0, sizeof(stream));
|
|
memset(&lconn, 0, sizeof(lconn));
|
|
memset(&conn_pub, 0, sizeof(conn_pub));
|
|
memset(&my_conn_if, 0, sizeof(my_conn_if));
|
|
my_conn_if.ci_get_stream_by_id = my_get_stream_by_id;
|
|
lconn.cn_if = &my_conn_if;
|
|
stream.conn_pub = &conn_pub;
|
|
conn_pub.lconn = &lconn;
|
|
|
|
lsquic_mm_init(&mm);
|
|
|
|
top:
|
|
lshpack_dec_init(&hdec);
|
|
memset(&input, 0, sizeof(input));
|
|
memcpy(input.in_buf, frt->frt_buf, frt->frt_bufsz);
|
|
input.in_sz = frt->frt_bufsz;
|
|
|
|
do
|
|
{
|
|
reset_cb_ctx(&g_cb_ctx);
|
|
input.in_off = 0;
|
|
++input.in_max_sz;
|
|
|
|
fr = lsquic_frame_reader_new(frt->frt_fr_flags, frt->frt_max_headers_sz,
|
|
&mm, &stream, read_from_stream, &hdec, &frame_callbacks, &g_cb_ctx,
|
|
#if LSQUIC_CONN_STATS
|
|
&conn_stats,
|
|
#endif
|
|
lsquic_http1x_if, NULL);
|
|
do
|
|
{
|
|
s = lsquic_frame_reader_read(fr);
|
|
if (s != 0)
|
|
break;
|
|
}
|
|
while (input.in_off < input.in_sz);
|
|
|
|
assert(frt->frt_err || 0 == s);
|
|
|
|
if (my_conn_if.ci_get_stream_by_id)
|
|
{
|
|
assert(g_cb_ctx.n_cb_vals == frt->frt_n_cb_vals);
|
|
|
|
unsigned i;
|
|
for (i = 0; i < g_cb_ctx.n_cb_vals; ++i)
|
|
compare_cb_vals(&g_cb_ctx.cb_vals[i], &frt->frt_cb_vals[i]);
|
|
}
|
|
|
|
exp_off = frt->frt_in_off;
|
|
if (!exp_off)
|
|
exp_off = frt->frt_bufsz;
|
|
assert(input.in_off == exp_off);
|
|
|
|
lsquic_frame_reader_destroy(fr);
|
|
}
|
|
while (input.in_max_sz < input.in_max_req_sz);
|
|
lshpack_dec_cleanup(&hdec);
|
|
|
|
if (!(frt->frt_fr_flags & FRF_SERVER) && my_conn_if.ci_get_stream_by_id)
|
|
{
|
|
/* Do it again, but this time test header block skip logic */
|
|
my_conn_if.ci_get_stream_by_id = NULL;
|
|
goto top;
|
|
}
|
|
|
|
lsquic_mm_cleanup(&mm);
|
|
}
|
|
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
int opt;
|
|
|
|
while (-1 != (opt = getopt(argc, argv, "l:")))
|
|
{
|
|
switch (opt)
|
|
{
|
|
case 'l':
|
|
lsquic_log_to_fstream(stderr, LLTS_NONE);
|
|
lsquic_logger_lopt(optarg);
|
|
break;
|
|
default:
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
const struct frame_reader_test *frt;
|
|
for (frt = tests; frt->frt_bufsz > 0; ++frt)
|
|
test_one_frt(frt);
|
|
return 0;
|
|
}
|