mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
26e8f082c9
- [FEATURE] QUIC and HTTP/3 Internet Draft 34 support and v1 support. The latter is turned off by default. - Drop support for ID-28 and ID-32. - [BUGFIX] IETF QUIC mini conn receive history (trechist): allow unlimited inserts by dropping smallest elements. - [BUGFIX] gQUIC: set STTL to correct value, issue #226. - [BUGFIX] Account for poison packet gap when MTU probe was too large.
533 lines
15 KiB
C
533 lines
15 KiB
C
/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc. See LICENSE. */
|
|
/* Tests based on rechist tests */
|
|
|
|
#include <assert.h>
|
|
#include <inttypes.h>
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef WIN32
|
|
#include "vc_compat.h"
|
|
#endif
|
|
|
|
#include "lsquic_int_types.h"
|
|
#include "lsquic_trechist.h"
|
|
|
|
|
|
struct str_range_iter
|
|
{
|
|
char *str;
|
|
struct lsquic_packno_range range;
|
|
};
|
|
|
|
|
|
static const struct lsquic_packno_range *
|
|
next_str_range (void *ctx)
|
|
{
|
|
struct str_range_iter *const str_iter = ctx;
|
|
|
|
if (str_iter->str && str_iter->str[0] == '[')
|
|
{
|
|
str_iter->range.high = strtoul(str_iter->str + 1, &str_iter->str, 10);
|
|
assert('-' == *str_iter->str);
|
|
str_iter->range.low = strtoul(str_iter->str + 1, &str_iter->str, 10);
|
|
assert(']' == *str_iter->str);
|
|
++str_iter->str;
|
|
return &str_iter->range;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static void
|
|
test_clone (trechist_mask_t src_mask, struct trechist_elem *src_elems)
|
|
{
|
|
trechist_mask_t hist_mask;
|
|
struct trechist_elem *hist_elems;
|
|
const struct lsquic_packno_range *ranges[2];
|
|
struct trechist_iter iters[2];
|
|
|
|
hist_elems = malloc(sizeof(hist_elems[0]) * TRECHIST_MAX_RANGES);
|
|
|
|
lsquic_trechist_iter(&iters[0], src_mask, src_elems);
|
|
lsquic_trechist_copy_ranges(&hist_mask, hist_elems, &iters[0],
|
|
lsquic_trechist_first, lsquic_trechist_next);
|
|
|
|
lsquic_trechist_iter(&iters[0], src_mask, src_elems);
|
|
lsquic_trechist_iter(&iters[1], hist_mask, hist_elems);
|
|
|
|
for (ranges[0] = lsquic_trechist_first(&iters[0]),
|
|
ranges[1] = lsquic_trechist_first(&iters[1]);
|
|
|
|
ranges[0] && ranges[1];
|
|
|
|
ranges[0] = lsquic_trechist_next(&iters[0]),
|
|
ranges[1] = lsquic_trechist_next(&iters[1]))
|
|
{
|
|
assert(ranges[0]->low == ranges[1]->low);
|
|
assert(ranges[0]->high == ranges[1]->high);
|
|
}
|
|
|
|
assert(!ranges[0] && !ranges[1]);
|
|
|
|
free(hist_elems);
|
|
}
|
|
|
|
|
|
static void
|
|
test4 (void)
|
|
{
|
|
trechist_mask_t hist_mask;
|
|
struct trechist_elem *hist_elems;
|
|
const struct lsquic_packno_range *range;
|
|
struct trechist_iter iter;
|
|
lsquic_packno_t packno;
|
|
|
|
hist_elems = malloc(sizeof(hist_elems[0]) * TRECHIST_MAX_RANGES);
|
|
hist_mask = 0;
|
|
test_clone(hist_mask, hist_elems);
|
|
|
|
for (packno = 11917; packno <= 11941; ++packno)
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, packno);
|
|
for (packno = 11946; packno <= 11994; ++packno)
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, packno);
|
|
|
|
test_clone(hist_mask, hist_elems);
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(range);
|
|
assert(range->high == 11994);
|
|
assert(range->low == 11946);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(range);
|
|
assert(range->high == 11941);
|
|
assert(range->low == 11917);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(!range);
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 11995);
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 11996);
|
|
test_clone(hist_mask, hist_elems);
|
|
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(range);
|
|
assert(range->high == 11996);
|
|
assert(range->low == 11946);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(range);
|
|
assert(range->high == 11941);
|
|
assert(range->low == 11917);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(!range);
|
|
test_clone(hist_mask, hist_elems);
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 11912);
|
|
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(range);
|
|
assert(range->high == 11996);
|
|
assert(range->low == 11946);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(range);
|
|
assert(range->high == 11941);
|
|
assert(range->low == 11917);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(range);
|
|
assert(range->high == 11912);
|
|
assert(range->low == 11912);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(!range);
|
|
|
|
for (packno = 12169; packno <= 12193; ++packno)
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, packno);
|
|
|
|
test_clone(hist_mask, hist_elems);
|
|
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(range);
|
|
assert(range->high == 12193);
|
|
assert(range->low == 12169);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(range);
|
|
assert(range->high == 11996);
|
|
assert(range->low == 11946);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(range);
|
|
assert(range->high == 11941);
|
|
assert(range->low == 11917);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(range);
|
|
assert(range->high == 11912);
|
|
assert(range->low == 11912);
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(!range);
|
|
|
|
test_clone(hist_mask, hist_elems);
|
|
|
|
free(hist_elems);
|
|
}
|
|
|
|
|
|
static void
|
|
rechist2str (trechist_mask_t hist_mask, const struct trechist_elem *hist_elems,
|
|
char *buf, size_t bufsz)
|
|
{
|
|
const struct lsquic_packno_range *range;
|
|
struct trechist_iter iter;
|
|
size_t off;
|
|
int n;
|
|
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
for (off = 0, range = lsquic_trechist_first(&iter);
|
|
range && off < bufsz;
|
|
off += n, range = lsquic_trechist_next(&iter))
|
|
{
|
|
n = snprintf(buf + off, bufsz - off, "[%"PRIu64"-%"PRIu64"]",
|
|
range->high, range->low);
|
|
if (n < 0 || (size_t) n >= bufsz - off)
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
test5 (void)
|
|
{
|
|
trechist_mask_t hist_mask;
|
|
struct trechist_elem *hist_elems;
|
|
char buf[100];
|
|
|
|
hist_elems = malloc(sizeof(hist_elems[0]) * TRECHIST_MAX_RANGES);
|
|
hist_mask = 0;
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 1);
|
|
/* Packet 2 omitted because it could not be decrypted */
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 3);
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 12);
|
|
|
|
rechist2str(hist_mask, hist_elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf, "[12-12][3-3][1-1]"));
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 4);
|
|
rechist2str(hist_mask, hist_elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf, "[12-12][4-3][1-1]"));
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 10);
|
|
rechist2str(hist_mask, hist_elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf, "[12-12][10-10][4-3][1-1]"));
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 6);
|
|
|
|
rechist2str(hist_mask, hist_elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf, "[12-12][10-10][6-6][4-3][1-1]"));
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 7);
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 8);
|
|
|
|
rechist2str(hist_mask, hist_elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf, "[12-12][10-10][8-6][4-3][1-1]"));
|
|
test_clone(hist_mask, hist_elems);
|
|
assert(!(lsquic_trechist_contains(hist_mask, hist_elems, 0)));
|
|
assert(!(lsquic_trechist_contains(hist_mask, hist_elems, 9)));
|
|
assert(!(lsquic_trechist_contains(hist_mask, hist_elems, 20)));
|
|
assert(lsquic_trechist_contains(hist_mask, hist_elems, 4));
|
|
assert(lsquic_trechist_contains(hist_mask, hist_elems, 1));
|
|
assert(lsquic_trechist_contains(hist_mask, hist_elems, 7));
|
|
assert(lsquic_trechist_contains(hist_mask, hist_elems, 8));
|
|
assert(lsquic_trechist_contains(hist_mask, hist_elems, 6));
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 9);
|
|
|
|
rechist2str(hist_mask, hist_elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf, "[12-12][10-6][4-3][1-1]"));
|
|
test_clone(hist_mask, hist_elems);
|
|
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 5);
|
|
lsquic_trechist_insert(&hist_mask, hist_elems, 11);
|
|
|
|
rechist2str(hist_mask, hist_elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf, "[12-3][1-1]"));
|
|
|
|
free(hist_elems);
|
|
}
|
|
|
|
|
|
static void
|
|
basic_test (void)
|
|
{
|
|
trechist_mask_t hist_mask;
|
|
struct trechist_elem *hist_elems;
|
|
const struct lsquic_packno_range *range;
|
|
struct trechist_iter iter;
|
|
unsigned i;
|
|
int s;
|
|
|
|
hist_elems = malloc(sizeof(hist_elems[0]) * TRECHIST_MAX_RANGES);
|
|
hist_mask = 0;
|
|
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(!range);
|
|
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, 1);
|
|
assert(("inserting packet number one is successful", 0 == s));
|
|
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(("first range returned correctly", range));
|
|
assert(("first range low value checks out", range->low == 1));
|
|
assert(("first range high value checks out", range->high == 1));
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(!range);
|
|
assert(("second range does not exist", !range));
|
|
|
|
for (i = 3; i <= 5; ++i)
|
|
{
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, i);
|
|
assert(("inserting packet", s == 0));
|
|
}
|
|
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(("first range returned correctly", range));
|
|
assert(("first range low value checks out", range->low == 3));
|
|
assert(("first range high value checks out", range->high == 5));
|
|
assert(!(lsquic_trechist_contains(hist_mask, hist_elems, 7)));
|
|
assert(!(lsquic_trechist_contains(hist_mask, hist_elems, 2)));
|
|
assert(lsquic_trechist_contains(hist_mask, hist_elems, 4));
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(("second range returned correctly", range));
|
|
assert(("second range low value checks out", range->low == 1));
|
|
assert(("second range high value checks out", range->high == 1));
|
|
range = lsquic_trechist_next(&iter);
|
|
assert(("third range does not exist", !range));
|
|
|
|
assert(5 == lsquic_trechist_max(hist_mask, hist_elems));
|
|
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, 10);
|
|
assert(("inserting packet", s == 0));
|
|
|
|
assert(10 == lsquic_trechist_max(hist_mask, hist_elems));
|
|
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(("first range returned correctly", range));
|
|
assert(("first range low value checks out", range->low == 10));
|
|
assert(("first range high value checks out", range->high == 10));
|
|
test_clone(hist_mask, hist_elems);
|
|
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, 8);
|
|
assert(("inserting packet", s == 0));
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, 9);
|
|
assert(("inserting packet", s == 0));
|
|
|
|
/* Check merge */
|
|
lsquic_trechist_iter(&iter, hist_mask, hist_elems);
|
|
range = lsquic_trechist_first(&iter);
|
|
assert(("first range returned correctly", range));
|
|
assert(("first range low value checks out", range->low == 8));
|
|
assert(("first range high value checks out", range->high == 10));
|
|
|
|
free(hist_elems);
|
|
}
|
|
|
|
|
|
static void
|
|
test_limits (void)
|
|
{
|
|
trechist_mask_t hist_mask;
|
|
struct trechist_elem *hist_elems;
|
|
unsigned i;
|
|
int s;
|
|
|
|
hist_elems = malloc(sizeof(hist_elems[0]) * TRECHIST_MAX_RANGES);
|
|
hist_mask = 0;
|
|
|
|
for (i = 1; i <= UCHAR_MAX; ++i)
|
|
{
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, i);
|
|
assert(s == 0);
|
|
}
|
|
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, i);
|
|
assert(s == -1); /* Overflow */
|
|
|
|
/* Always successful inserting new entries: */
|
|
for (i = 0; i < TRECHIST_MAX_RANGES * 2; ++i)
|
|
{
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, 1000 + 2 * i);
|
|
assert(s == 0);
|
|
}
|
|
|
|
/* Always successful inserting new entries in descending order, too: */
|
|
for (i = 0; i < TRECHIST_MAX_RANGES * 2; ++i)
|
|
{
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, 10000 - 2 * i);
|
|
assert(s == 0);
|
|
}
|
|
|
|
/* Test merge where count exceeds max: */
|
|
hist_mask = 0;
|
|
lsquic_trechist_copy_ranges(&hist_mask, hist_elems,
|
|
& (struct str_range_iter) { .str = "[400-202][200-1]", },
|
|
next_str_range, next_str_range);
|
|
s = lsquic_trechist_insert(&hist_mask, hist_elems, 201);
|
|
assert(s == -1);
|
|
|
|
free(hist_elems);
|
|
}
|
|
|
|
|
|
static void
|
|
test_overflow (void)
|
|
{
|
|
trechist_mask_t mask;
|
|
struct trechist_elem *elems;
|
|
int s;
|
|
char buf[0x1000];
|
|
|
|
struct str_range_iter str_iter = { .str =
|
|
"[395-390]" /* 1 */
|
|
"[385-380]"
|
|
"[375-370]"
|
|
"[365-360]"
|
|
"[355-350]" /* 5 */
|
|
"[345-340]"
|
|
"[335-330]"
|
|
"[325-320]"
|
|
"[315-310]"
|
|
"[305-300]" /* 10 */
|
|
"[295-290]"
|
|
"[285-280]"
|
|
"[275-270]"
|
|
"[265-260]"
|
|
"[255-250]" /* 15 */
|
|
"[245-240]" /* 16 */
|
|
"[235-230]" /* Overflow vvvvvv */
|
|
"[225-220]"
|
|
"[215-210]"
|
|
"[205-200]"
|
|
"[195-190]"
|
|
"[185-180]" };
|
|
|
|
elems = malloc(sizeof(elems[0]) * TRECHIST_MAX_RANGES);
|
|
lsquic_trechist_copy_ranges(&mask, elems, &str_iter, next_str_range,
|
|
next_str_range);
|
|
|
|
rechist2str(mask, elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf,
|
|
"[395-390]" /* 1 */
|
|
"[385-380]"
|
|
"[375-370]"
|
|
"[365-360]"
|
|
"[355-350]" /* 5 */
|
|
"[345-340]"
|
|
"[335-330]"
|
|
"[325-320]"
|
|
"[315-310]"
|
|
"[305-300]" /* 10 */
|
|
"[295-290]"
|
|
"[285-280]"
|
|
"[275-270]"
|
|
"[265-260]"
|
|
"[255-250]" /* 15 */
|
|
"[245-240]" /* 16 */));
|
|
|
|
s = lsquic_trechist_insert(&mask, elems, 400);
|
|
assert(s == 0);
|
|
rechist2str(mask, elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf,
|
|
"[400-400]"
|
|
"[395-390]"
|
|
"[385-380]"
|
|
"[375-370]"
|
|
"[365-360]"
|
|
"[355-350]"
|
|
"[345-340]"
|
|
"[335-330]"
|
|
"[325-320]"
|
|
"[315-310]"
|
|
"[305-300]"
|
|
"[295-290]"
|
|
"[285-280]"
|
|
"[275-270]"
|
|
"[265-260]"
|
|
"[255-250]"
|
|
));
|
|
|
|
/* One more for a good measure */
|
|
s = lsquic_trechist_insert(&mask, elems, 402);
|
|
assert(s == 0);
|
|
rechist2str(mask, elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf,
|
|
"[402-402]"
|
|
"[400-400]"
|
|
"[395-390]"
|
|
"[385-380]"
|
|
"[375-370]"
|
|
"[365-360]"
|
|
"[355-350]"
|
|
"[345-340]"
|
|
"[335-330]"
|
|
"[325-320]"
|
|
"[315-310]"
|
|
"[305-300]"
|
|
"[295-290]"
|
|
"[285-280]"
|
|
"[275-270]"
|
|
"[265-260]"
|
|
));
|
|
|
|
s = lsquic_trechist_insert(&mask, elems, 401);
|
|
assert(s == 0);
|
|
s = lsquic_trechist_insert(&mask, elems, 500);
|
|
assert(s == 0);
|
|
s = lsquic_trechist_insert(&mask, elems, 200);
|
|
assert(s == 0);
|
|
s = lsquic_trechist_insert(&mask, elems, 267);
|
|
assert(s == 0);
|
|
|
|
/* One more for a good measure */
|
|
s = lsquic_trechist_insert(&mask, elems, 402);
|
|
assert(s == 0);
|
|
rechist2str(mask, elems, buf, sizeof(buf));
|
|
assert(0 == strcmp(buf,
|
|
"[500-500]"
|
|
"[402-400]"
|
|
"[395-390]"
|
|
"[385-380]"
|
|
"[375-370]"
|
|
"[365-360]"
|
|
"[355-350]"
|
|
"[345-340]"
|
|
"[335-330]"
|
|
"[325-320]"
|
|
"[315-310]"
|
|
"[305-300]"
|
|
"[295-290]"
|
|
"[285-280]"
|
|
"[275-270]"
|
|
"[267-267]"
|
|
));
|
|
|
|
free(elems);
|
|
}
|
|
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
basic_test();
|
|
test4();
|
|
test5();
|
|
test_limits();
|
|
test_overflow();
|
|
|
|
return 0;
|
|
}
|