mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
77a28812de
- [BUGFIX] Place connections on tickable queue when sending is reenabled. - [BUGFIX] A connection is tickable if it has unsent packets. - [BUGFIX] Heed peer's max_packet_size transport parameter.
279 lines
8 KiB
C
279 lines
8 KiB
C
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
|
/*
|
|
* test_trapa.c -- Test transport parameters.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "lsquic.h"
|
|
#include "lsquic_types.h"
|
|
#include "lsquic_sizes.h"
|
|
#include "lsquic_logger.h"
|
|
#include "lsquic_trans_params.h"
|
|
|
|
#define ENC_BUF_SZ 0x1000
|
|
|
|
struct trapa_test
|
|
{
|
|
int line;
|
|
enum {
|
|
TEST_ENCODE = 1 << 0,
|
|
TEST_DECODE = 1 << 1,
|
|
} flags;
|
|
struct transport_params params;
|
|
size_t enc_len, dec_len;
|
|
unsigned addl_set;
|
|
int is_server;
|
|
int expect_decode_err;
|
|
unsigned char encoded[ENC_BUF_SZ];
|
|
};
|
|
|
|
static const struct trapa_test tests[] =
|
|
{
|
|
|
|
{
|
|
.line = __LINE__,
|
|
.flags = TEST_ENCODE | TEST_DECODE,
|
|
.params = {
|
|
TP_DEFAULT_VALUES,
|
|
},
|
|
.enc_len = 0,
|
|
.encoded =
|
|
/* Trailer to make the end easily visible in gdb: */
|
|
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
},
|
|
|
|
{
|
|
.line = __LINE__,
|
|
.flags = TEST_ENCODE | TEST_DECODE,
|
|
.params = {
|
|
.tp_set = (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL)
|
|
| (1 << TPI_INIT_MAX_DATA)
|
|
| (1 << TPI_MAX_IDLE_TIMEOUT)
|
|
| (1 << TPI_MAX_ACK_DELAY)
|
|
| (1 << TPI_MAX_PACKET_SIZE)
|
|
| (1 << TPI_ACK_DELAY_EXPONENT)
|
|
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT),
|
|
.tp_init_max_stream_data_bidi_local = 0x12348877,
|
|
.tp_init_max_data = 0xAABB,
|
|
.tp_max_packet_size = 1213,
|
|
.tp_max_idle_timeout = 10 * 1000,
|
|
.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY,
|
|
.tp_active_connection_id_limit = 7,
|
|
},
|
|
.is_server = 0,
|
|
.enc_len = 26,
|
|
.encoded =
|
|
/* Idle timeout */ "\x01\x02\x67\x10"
|
|
/* Packet size */ "\x03\x02\x44\xBD"
|
|
/* Max data */ "\x04\x04\x80\x00\xAA\xBB"
|
|
/* Bidi local */ "\x05\x04\x92\x34\x88\x77"
|
|
/* Ack delay exp */ "\x0A\x01\x00"
|
|
/* Active CID limit */ "\x0E\x01\x07"
|
|
/* Trailer to make the end easily visible in gdb: */
|
|
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
},
|
|
|
|
{
|
|
.line = __LINE__,
|
|
.flags = TEST_DECODE,
|
|
.dec_len = 1,
|
|
.expect_decode_err = 1,
|
|
},
|
|
|
|
{
|
|
.line = __LINE__,
|
|
.flags = TEST_DECODE,
|
|
.dec_len = 3,
|
|
.expect_decode_err = 1,
|
|
.encoded = "\x00\x04",
|
|
},
|
|
|
|
|
|
{
|
|
.line = __LINE__,
|
|
.flags = TEST_ENCODE | TEST_DECODE,
|
|
.params = {
|
|
TP_DEFAULT_VALUES,
|
|
.tp_init_max_data = 0x123456,
|
|
.tp_init_max_stream_data_bidi_local = 0xABCDEF88,
|
|
.tp_max_packet_size = 0x555,
|
|
},
|
|
.is_server = 1,
|
|
.addl_set = 1 << TPI_DISABLE_ACTIVE_MIGRATION,
|
|
.enc_len = 22,
|
|
.encoded =
|
|
/* Packet size */ "\x03\x02\x45\x55"
|
|
/* Max data */ "\x04\x04\x80\x12\x34\x56"
|
|
/* Bidi local */ "\x05\x08\xC0\x00\x00\x00\xAB\xCD\xEF\x88"
|
|
/* Migration */ "\x0C\x00"
|
|
/* Trailer to make the end easily visible in gdb: */
|
|
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
},
|
|
|
|
/* Test server preferred address. */
|
|
{
|
|
.line = __LINE__,
|
|
.flags = TEST_DECODE,
|
|
.params = {
|
|
TP_DEFAULT_VALUES,
|
|
.tp_max_ack_delay = 25,
|
|
.tp_max_packet_size = 0x555,
|
|
.tp_preferred_address = {
|
|
.ipv4_addr = "\x01\x02\x03\x04",
|
|
.ipv4_port = 0x1234,
|
|
.ipv6_addr = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
|
|
.ipv6_port = 0x9001,
|
|
.cid = { .len = 11, .idbuf = "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A", },
|
|
.srst = "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F",
|
|
},
|
|
},
|
|
.is_server = 1,
|
|
.addl_set = 1 << TPI_PREFERRED_ADDRESS,
|
|
.enc_len = 0x3A,
|
|
.dec_len = 0x3A,
|
|
.encoded =
|
|
/* Preferred Address */"\x0D"
|
|
"\x34"
|
|
"\x01\x02\x03\x04"
|
|
"\x12\x34"
|
|
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
|
|
"\x90\x01"
|
|
"\x0B" /* CID len */
|
|
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A"
|
|
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
|
|
/* Packet size */ "\x03\x02\x45\x55"
|
|
/* Trailer to make the end easily visible in gdb: */
|
|
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
},
|
|
|
|
};
|
|
|
|
|
|
static int
|
|
params_are_equal (const struct transport_params *a,
|
|
const struct transport_params *b)
|
|
{
|
|
#define MCMP(f) 0 == memcmp(&a->f, &b->f, sizeof(a->f))
|
|
return MCMP(tp_numerics)
|
|
&& MCMP(tp_set)
|
|
&& MCMP(tp_stateless_reset_token)
|
|
&& MCMP(tp_preferred_address.ipv4_addr)
|
|
&& MCMP(tp_preferred_address.ipv6_addr)
|
|
&& MCMP(tp_preferred_address.srst)
|
|
&& MCMP(tp_preferred_address.cid.idbuf)
|
|
&& a->tp_preferred_address.ipv4_port == b->tp_preferred_address.ipv4_port
|
|
&& a->tp_preferred_address.ipv6_port == b->tp_preferred_address.ipv6_port
|
|
&& a->tp_preferred_address.cid.len == b->tp_preferred_address.cid.len
|
|
&& MCMP(tp_original_cid.idbuf)
|
|
&& a->tp_original_cid.len == b->tp_original_cid.len
|
|
;
|
|
#undef MCMP
|
|
}
|
|
|
|
|
|
static void
|
|
run_test (const struct trapa_test *test)
|
|
{
|
|
struct transport_params source_params;
|
|
struct transport_params decoded_params;
|
|
size_t dec_len;
|
|
int s;
|
|
unsigned char buf[ENC_BUF_SZ];
|
|
|
|
source_params = test->params;
|
|
source_params.tp_set |= test->addl_set;
|
|
|
|
if (test->flags & TEST_ENCODE)
|
|
{
|
|
s = lsquic_tp_encode(&source_params, test->is_server, buf, sizeof(buf));
|
|
assert(s >= 0);
|
|
assert((size_t) s == test->enc_len);
|
|
assert(0 == memcmp(test->encoded, buf, s));
|
|
}
|
|
|
|
if (test->flags & TEST_DECODE)
|
|
{
|
|
if (test->dec_len)
|
|
dec_len = test->dec_len;
|
|
else
|
|
dec_len = test->enc_len;
|
|
s = lsquic_tp_decode(test->encoded, dec_len,
|
|
test->is_server, &decoded_params);
|
|
if (!test->expect_decode_err)
|
|
{
|
|
assert(s >= 0);
|
|
assert((size_t) s == test->enc_len);
|
|
/* The decoder initializes all default values, so set the flag
|
|
* accordingly:
|
|
*/
|
|
source_params.tp_set |= ((1 << (MAX_NUM_WITH_DEF_TPI + 1)) - 1);
|
|
s = params_are_equal(&source_params, &decoded_params);
|
|
assert(s);
|
|
}
|
|
else
|
|
assert(s < 0);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
decode_file (const char *name)
|
|
{
|
|
FILE *file;
|
|
size_t nread;
|
|
int s;
|
|
struct transport_params params;
|
|
unsigned char buf[0x1000];
|
|
|
|
file = fopen(name, "rb");
|
|
if (!file)
|
|
{
|
|
perror("fopen");
|
|
exit(1);
|
|
}
|
|
|
|
nread = fread(buf, 1, sizeof(buf), file);
|
|
|
|
s = lsquic_tp_decode(buf, nread, 0, ¶ms);
|
|
|
|
fclose(file);
|
|
|
|
printf("decoded params from %s: %d (%s)\n", name, s, s > 0 ? "OK" : "FAIL");
|
|
}
|
|
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
unsigned i;
|
|
int opt;
|
|
|
|
while (-1 != (opt = getopt(argc, argv, "d:l:")))
|
|
{
|
|
switch (opt)
|
|
{
|
|
case 'd':
|
|
decode_file(optarg);
|
|
return 0;
|
|
case 'l':
|
|
lsquic_log_to_fstream(stderr, 0);
|
|
lsquic_logger_lopt(optarg);
|
|
break;
|
|
default:
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
|
|
run_test(&tests[i]);
|
|
|
|
return 0;
|
|
}
|