mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.22.0
- [FEATURE] Extensible HTTP Priorities (HTTP/3 only). - [FEATURE] Add conn context to packet-out memory interface (PR #175). - [BUGFIX] gQUIC proof generation: allocate buffer big enough for signature (issue #173). - [BUGFIX] Make library thread-safe: drop use of global variables (issue #133, issue #167). - [BUGFIX] Deactivate only *recent* HQ frame, not any HQ frame. - [BUGFIX] gQUIC server: associate compressed cert with SSL_CTX, instead of keeping them in a separate hash, potentially leading to mismatches. - [BUGFIX] Stream data discard infinite loop: break on FIN. - cmake: add install target via -DCMAKE_INSTALL_PREFIX (PR #171). - Support randomized packet number to begin a connection. - Mini and full IETF connection size optimization. - http_client: specify HTTP priorities based on stream conditions.
This commit is contained in:
parent
cb1e8c1022
commit
fbc6cc0413
55 changed files with 6557 additions and 391 deletions
|
@ -161,6 +161,24 @@ strndup(const char *s, size_t n)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* When more than `nread' bytes are read from stream `stream_id', apply
|
||||
* priority in `ehp'.
|
||||
*/
|
||||
struct priority_spec
|
||||
{
|
||||
enum {
|
||||
PRIORITY_SPEC_ACTIVE = 1 << 0,
|
||||
} flags;
|
||||
lsquic_stream_id_t stream_id;
|
||||
size_t nread;
|
||||
struct lsquic_ext_http_prio ehp;
|
||||
};
|
||||
static struct priority_spec *s_priority_specs;
|
||||
static unsigned s_n_prio_specs;
|
||||
|
||||
static void
|
||||
maybe_perform_priority_actions (struct lsquic_stream *, lsquic_stream_ctx_t *);
|
||||
|
||||
struct lsquic_conn_ctx;
|
||||
|
||||
struct path_elem {
|
||||
|
@ -531,7 +549,20 @@ http_client_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
|
|||
LSQ_INFO("created new stream, path: %s", st_h->path);
|
||||
lsquic_stream_wantwrite(stream, 1);
|
||||
if (randomly_reprioritize_streams)
|
||||
lsquic_stream_set_priority(stream, 1 + (random() & 0xFF));
|
||||
{
|
||||
if ((1 << lsquic_conn_quic_version(lsquic_stream_conn(stream)))
|
||||
& LSQUIC_IETF_VERSIONS)
|
||||
lsquic_stream_set_http_prio(stream,
|
||||
&(struct lsquic_ext_http_prio){
|
||||
.urgency = random() & 7,
|
||||
.incremental = random() & 1,
|
||||
}
|
||||
);
|
||||
else
|
||||
lsquic_stream_set_priority(stream, 1 + (random() & 0xFF));
|
||||
}
|
||||
if (s_priority_specs)
|
||||
maybe_perform_priority_actions(stream, st_h);
|
||||
if (s_abandon_early)
|
||||
{
|
||||
st_h->sh_stop = random() % (s_abandon_early + 1);
|
||||
|
@ -547,25 +578,37 @@ send_headers (lsquic_stream_ctx_t *st_h)
|
|||
{
|
||||
const char *hostname = st_h->client_ctx->hostname;
|
||||
struct header_buf hbuf;
|
||||
unsigned h_idx = 0;
|
||||
if (!hostname)
|
||||
hostname = st_h->client_ctx->prog->prog_hostname;
|
||||
hbuf.off = 0;
|
||||
struct lsxpack_header headers_arr[7];
|
||||
struct lsxpack_header headers_arr[9];
|
||||
#define V(v) (v), strlen(v)
|
||||
header_set_ptr(&headers_arr[0], &hbuf, V(":method"), V(st_h->client_ctx->method));
|
||||
header_set_ptr(&headers_arr[1], &hbuf, V(":scheme"), V("https"));
|
||||
header_set_ptr(&headers_arr[2], &hbuf, V(":path"), V(st_h->path));
|
||||
header_set_ptr(&headers_arr[3], &hbuf, V(":authority"), V(hostname));
|
||||
header_set_ptr(&headers_arr[4], &hbuf, V("user-agent"), V(st_h->client_ctx->prog->prog_settings.es_ua));
|
||||
/* The following headers only gets sent if there is request payload: */
|
||||
header_set_ptr(&headers_arr[5], &hbuf, V("content-type"), V("application/octet-stream"));
|
||||
header_set_ptr(&headers_arr[6], &hbuf, V("content-length"), V( st_h->client_ctx->payload_size));
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V(":method"), V(st_h->client_ctx->method));
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V(":scheme"), V("https"));
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V(":path"), V(st_h->path));
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V(":authority"), V(hostname));
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V("user-agent"), V(st_h->client_ctx->prog->prog_settings.es_ua));
|
||||
if (randomly_reprioritize_streams)
|
||||
{
|
||||
char pfv[10];
|
||||
sprintf(pfv, "u=%ld", random() & 7);
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V("priority"), V(pfv));
|
||||
if (random() & 1)
|
||||
sprintf(pfv, "i");
|
||||
else
|
||||
sprintf(pfv, "i=?0");
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V("priority"), V(pfv));
|
||||
}
|
||||
if (st_h->client_ctx->payload)
|
||||
{
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V("content-type"), V("application/octet-stream"));
|
||||
header_set_ptr(&headers_arr[h_idx++], &hbuf, V("content-length"), V( st_h->client_ctx->payload_size));
|
||||
}
|
||||
lsquic_http_headers_t headers = {
|
||||
.count = sizeof(headers_arr) / sizeof(headers_arr[0]),
|
||||
.count = h_idx,
|
||||
.headers = headers_arr,
|
||||
};
|
||||
if (!st_h->client_ctx->payload)
|
||||
headers.count -= 2;
|
||||
if (0 != lsquic_stream_send_headers(st_h->stream, &headers,
|
||||
st_h->client_ctx->payload == NULL))
|
||||
{
|
||||
|
@ -659,6 +702,40 @@ discard (void *ctx, const unsigned char *buf, size_t sz, int fin)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
maybe_perform_priority_actions (struct lsquic_stream *stream,
|
||||
lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
const lsquic_stream_id_t stream_id = lsquic_stream_id(stream);
|
||||
struct priority_spec *spec;
|
||||
unsigned n_active;
|
||||
int s;
|
||||
|
||||
n_active = 0;
|
||||
for (spec = s_priority_specs; spec < s_priority_specs + s_n_prio_specs;
|
||||
++spec)
|
||||
{
|
||||
if ((spec->flags & PRIORITY_SPEC_ACTIVE)
|
||||
&& spec->stream_id == stream_id
|
||||
&& st_h->sh_nread >= spec->nread)
|
||||
{
|
||||
s = lsquic_stream_set_http_prio(stream, &spec->ehp);
|
||||
if (s != 0)
|
||||
{
|
||||
LSQ_ERROR("could not apply priorities to stream %"PRIu64,
|
||||
stream_id);
|
||||
exit(1);
|
||||
}
|
||||
spec->flags &= ~PRIORITY_SPEC_ACTIVE;
|
||||
}
|
||||
n_active += !!(spec->flags & PRIORITY_SPEC_ACTIVE);
|
||||
}
|
||||
|
||||
if (n_active == 0)
|
||||
s_priority_specs = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
|
@ -728,16 +805,36 @@ http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
|||
fwrite(buf, 1, nread, stdout);
|
||||
if (randomly_reprioritize_streams && (st_h->count++ & 0x3F) == 0)
|
||||
{
|
||||
old_prio = lsquic_stream_priority(stream);
|
||||
new_prio = 1 + (random() & 0xFF);
|
||||
if ((1 << lsquic_conn_quic_version(lsquic_stream_conn(stream)))
|
||||
& LSQUIC_IETF_VERSIONS)
|
||||
{
|
||||
struct lsquic_ext_http_prio ehp;
|
||||
if (0 == lsquic_stream_get_http_prio(stream, &ehp))
|
||||
{
|
||||
ehp.urgency = 7 & (ehp.urgency + 1);
|
||||
ehp.incremental = !ehp.incremental;
|
||||
#ifndef NDEBUG
|
||||
const int s =
|
||||
const int s =
|
||||
#endif
|
||||
lsquic_stream_set_priority(stream, new_prio);
|
||||
assert(s == 0);
|
||||
LSQ_DEBUG("changed stream %"PRIu64" priority from %u to %u",
|
||||
lsquic_stream_set_http_prio(stream, &ehp);
|
||||
assert(s == 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
old_prio = lsquic_stream_priority(stream);
|
||||
new_prio = 1 + (random() & 0xFF);
|
||||
#ifndef NDEBUG
|
||||
const int s =
|
||||
#endif
|
||||
lsquic_stream_set_priority(stream, new_prio);
|
||||
assert(s == 0);
|
||||
LSQ_DEBUG("changed stream %"PRIu64" priority from %u to %u",
|
||||
lsquic_stream_id(stream), old_prio, new_prio);
|
||||
}
|
||||
}
|
||||
if (s_priority_specs)
|
||||
maybe_perform_priority_actions(stream, st_h);
|
||||
if ((st_h->sh_flags & ABANDON) && st_h->sh_nread >= st_h->sh_stop)
|
||||
{
|
||||
LSQ_DEBUG("closing stream early having read %zd bytes",
|
||||
|
@ -864,6 +961,9 @@ usage (const char *prog)
|
|||
" -e TOKEN Hexadecimal string representing resume token.\n"
|
||||
" -3 MAX Close stream after reading at most MAX bytes. The actual\n"
|
||||
" number of bytes read is randominzed.\n"
|
||||
" -9 SPEC Priority specification. May be specified several times.\n"
|
||||
" SPEC takes the form stream_id:nread:UI, where U is\n"
|
||||
" urgency and I is incremental. Matched \\d+:\\d+:[0-7][01]\n"
|
||||
, prog);
|
||||
}
|
||||
|
||||
|
@ -1432,6 +1532,7 @@ main (int argc, char **argv)
|
|||
struct sport_head sports;
|
||||
struct prog prog;
|
||||
const char *token = NULL;
|
||||
struct priority_spec *priority_specs = NULL;
|
||||
|
||||
TAILQ_INIT(&sports);
|
||||
memset(&client_ctx, 0, sizeof(client_ctx));
|
||||
|
@ -1450,6 +1551,7 @@ main (int argc, char **argv)
|
|||
while (-1 != (opt = getopt(argc, argv, PROG_OPTS
|
||||
"46Br:R:IKu:EP:M:n:w:H:p:0:q:e:hatT:b:d:"
|
||||
"3:" /* 3 is 133+ for "e" ("e" for "early") */
|
||||
"9:" /* 9 sort of looks like P... */
|
||||
#ifndef WIN32
|
||||
"C:"
|
||||
#endif
|
||||
|
@ -1486,6 +1588,7 @@ main (int argc, char **argv)
|
|||
case 'E': /* E: randomly reprioritize str<E>ams. Now, that's
|
||||
* pretty random. :)
|
||||
*/
|
||||
srand((uintptr_t) argv);
|
||||
randomly_reprioritize_streams = 1;
|
||||
break;
|
||||
case 'n':
|
||||
|
@ -1569,6 +1672,45 @@ main (int argc, char **argv)
|
|||
case '3':
|
||||
s_abandon_early = strtol(optarg, NULL, 10);
|
||||
break;
|
||||
case '9':
|
||||
{
|
||||
/* Parse priority spec and tack it onto the end of the array */
|
||||
lsquic_stream_id_t stream_id;
|
||||
size_t nread;
|
||||
struct lsquic_ext_http_prio ehp;
|
||||
struct priority_spec *new_specs;
|
||||
stream_id = strtoull(optarg, &optarg, 10);
|
||||
if (*optarg != ':')
|
||||
exit(1);
|
||||
++optarg;
|
||||
nread = strtoull(optarg, &optarg, 10);
|
||||
if (*optarg != ':')
|
||||
exit(1);
|
||||
++optarg;
|
||||
if (!(*optarg >= '0' && *optarg <= '7'))
|
||||
exit(1);
|
||||
ehp.urgency = *optarg++ - '0';
|
||||
if (!(*optarg >= '0' && *optarg <= '1'))
|
||||
exit(1);
|
||||
ehp.incremental = *optarg++ - '0';
|
||||
++s_n_prio_specs;
|
||||
new_specs = realloc(priority_specs,
|
||||
sizeof(priority_specs[0]) * s_n_prio_specs);
|
||||
if (!new_specs)
|
||||
{
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
priority_specs = new_specs;
|
||||
priority_specs[s_n_prio_specs - 1] = (struct priority_spec) {
|
||||
.flags = PRIORITY_SPEC_ACTIVE,
|
||||
.stream_id = stream_id,
|
||||
.nread = nread,
|
||||
.ehp = ehp,
|
||||
};
|
||||
s_priority_specs = priority_specs;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (0 != prog_set_opt(&prog, opt, optarg))
|
||||
exit(1);
|
||||
|
@ -1660,5 +1802,6 @@ main (int argc, char **argv)
|
|||
if (client_ctx.qif_fh)
|
||||
(void) fclose(client_ctx.qif_fh);
|
||||
|
||||
free(priority_specs);
|
||||
exit(0 == s ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@
|
|||
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "test_common.h"
|
||||
#include "lsquic.h"
|
||||
#include "test_common.h"
|
||||
#include "prog.h"
|
||||
#include "lsxpack_header.h"
|
||||
|
||||
|
@ -1916,6 +1916,11 @@ set_engine_option (struct lsquic_engine_settings *settings,
|
|||
settings->es_scid_iss_rate = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
if (0 == strncmp(name, "ext_http_prio", 13))
|
||||
{
|
||||
settings->es_ext_http_prio = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
if (0 == strncmp(name, "max_streams_in", 14))
|
||||
|
@ -2043,8 +2048,8 @@ pba_init (struct packout_buf_allocator *pba, unsigned max)
|
|||
|
||||
|
||||
void *
|
||||
pba_allocate (void *packout_buf_allocator, void *peer_ctx, void *conn_ctx, unsigned short size,
|
||||
char is_ipv6)
|
||||
pba_allocate (void *packout_buf_allocator, void *peer_ctx,
|
||||
lsquic_conn_ctx_t *conn_ctx, unsigned short size, char is_ipv6)
|
||||
{
|
||||
struct packout_buf_allocator *const pba = packout_buf_allocator;
|
||||
struct packout_buf *pb;
|
||||
|
|
|
@ -115,7 +115,7 @@ void
|
|||
pba_init (struct packout_buf_allocator *, unsigned max);
|
||||
|
||||
void *
|
||||
pba_allocate (void *packout_buf_allocator, void*, void *conn_ctx, unsigned short, char);
|
||||
pba_allocate (void *packout_buf_allocator, void*, lsquic_conn_ctx_t *, unsigned short, char);
|
||||
|
||||
void
|
||||
pba_release (void *packout_buf_allocator, void *, void *obj, char);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue