1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
25392f7a3SLiteSpeed Tech/*
35392f7a3SLiteSpeed Tech * test_trapa.c -- Test transport parameters.
45392f7a3SLiteSpeed Tech */
55392f7a3SLiteSpeed Tech
65392f7a3SLiteSpeed Tech#include <assert.h>
75392f7a3SLiteSpeed Tech
85392f7a3SLiteSpeed Tech#include <stddef.h>
95392f7a3SLiteSpeed Tech#include <stdint.h>
105392f7a3SLiteSpeed Tech#include <stdio.h>
115392f7a3SLiteSpeed Tech#include <stdlib.h>
125392f7a3SLiteSpeed Tech#include <string.h>
13fb3e20e0SDmitri Tikhonov#ifndef WIN32
145392f7a3SLiteSpeed Tech#include <unistd.h>
15fb3e20e0SDmitri Tikhonov#else
16fb3e20e0SDmitri Tikhonov#include "getopt.h"
17fb3e20e0SDmitri Tikhonov#endif
185392f7a3SLiteSpeed Tech
195392f7a3SLiteSpeed Tech#include "lsquic.h"
205392f7a3SLiteSpeed Tech#include "lsquic_types.h"
215392f7a3SLiteSpeed Tech#include "lsquic_sizes.h"
225392f7a3SLiteSpeed Tech#include "lsquic_logger.h"
235392f7a3SLiteSpeed Tech#include "lsquic_trans_params.h"
245392f7a3SLiteSpeed Tech
255392f7a3SLiteSpeed Tech#define ENC_BUF_SZ 0x1000
265392f7a3SLiteSpeed Tech
275392f7a3SLiteSpeed Techstruct trapa_test
285392f7a3SLiteSpeed Tech{
295392f7a3SLiteSpeed Tech    int                         line;
305392f7a3SLiteSpeed Tech    enum {
315392f7a3SLiteSpeed Tech        TEST_ENCODE = 1 << 0,
325392f7a3SLiteSpeed Tech        TEST_DECODE = 1 << 1,
335392f7a3SLiteSpeed Tech    }                           flags;
345392f7a3SLiteSpeed Tech    struct transport_params     params;
355392f7a3SLiteSpeed Tech    size_t                      enc_len, dec_len;
361bdb91d1SDmitri Tikhonov    unsigned                    addl_set;
371bdb91d1SDmitri Tikhonov    int                         is_server;
385392f7a3SLiteSpeed Tech    int                         expect_decode_err;
395392f7a3SLiteSpeed Tech    unsigned char               encoded[ENC_BUF_SZ];
405392f7a3SLiteSpeed Tech};
415392f7a3SLiteSpeed Tech
425392f7a3SLiteSpeed Techstatic const struct trapa_test tests[] =
435392f7a3SLiteSpeed Tech{
445392f7a3SLiteSpeed Tech
455392f7a3SLiteSpeed Tech    {
465392f7a3SLiteSpeed Tech        .line   = __LINE__,
475392f7a3SLiteSpeed Tech        .flags  = TEST_ENCODE | TEST_DECODE,
485392f7a3SLiteSpeed Tech        .params = {
495392f7a3SLiteSpeed Tech            TP_DEFAULT_VALUES,
505392f7a3SLiteSpeed Tech        },
51bc520ef7SDmitri Tikhonov        .enc_len = 0,
525392f7a3SLiteSpeed Tech        .encoded =
535392f7a3SLiteSpeed Tech    /* Trailer to make the end easily visible in gdb: */
545392f7a3SLiteSpeed Tech    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
555392f7a3SLiteSpeed Tech    },
565392f7a3SLiteSpeed Tech
575392f7a3SLiteSpeed Tech    {
585392f7a3SLiteSpeed Tech        .line   = __LINE__,
595392f7a3SLiteSpeed Tech        .flags  = TEST_ENCODE | TEST_DECODE,
605392f7a3SLiteSpeed Tech        .params = {
611bdb91d1SDmitri Tikhonov            .tp_set = (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL)
621bdb91d1SDmitri Tikhonov                    | (1 << TPI_INIT_MAX_DATA)
631bdb91d1SDmitri Tikhonov                    | (1 << TPI_MAX_IDLE_TIMEOUT)
641bdb91d1SDmitri Tikhonov                    | (1 << TPI_MAX_ACK_DELAY)
65fb73393fSDmitri Tikhonov                    | (1 << TPI_MAX_UDP_PAYLOAD_SIZE)
661bdb91d1SDmitri Tikhonov                    | (1 << TPI_ACK_DELAY_EXPONENT)
67fb73393fSDmitri Tikhonov                    | (1 << TPI_INITIAL_SOURCE_CID)
681bdb91d1SDmitri Tikhonov                    | (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT),
695392f7a3SLiteSpeed Tech            .tp_init_max_stream_data_bidi_local = 0x12348877,
705392f7a3SLiteSpeed Tech            .tp_init_max_data = 0xAABB,
71fb73393fSDmitri Tikhonov            .tp_max_udp_payload_size = 1213,
729fc12041SDmitri Tikhonov            .tp_max_idle_timeout = 10 * 1000,
735392f7a3SLiteSpeed Tech            .tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY,
745392f7a3SLiteSpeed Tech            .tp_active_connection_id_limit = 7,
75fb73393fSDmitri Tikhonov            .tp_initial_source_cid = { .len = 8, .u_cid.id = 0x0807060504030201ull, },
765392f7a3SLiteSpeed Tech        },
771bdb91d1SDmitri Tikhonov        .is_server = 0,
78fb73393fSDmitri Tikhonov        .enc_len = 36,
795392f7a3SLiteSpeed Tech        .encoded =
80bc520ef7SDmitri Tikhonov     /* Idle timeout */     "\x01\x02\x67\x10"
8177a28812SDmitri Tikhonov     /* Packet size */      "\x03\x02\x44\xBD"
82bc520ef7SDmitri Tikhonov     /* Max data */         "\x04\x04\x80\x00\xAA\xBB"
83bc520ef7SDmitri Tikhonov     /* Bidi local */       "\x05\x04\x92\x34\x88\x77"
84bc520ef7SDmitri Tikhonov     /* Ack delay exp */    "\x0A\x01\x00"
85bc520ef7SDmitri Tikhonov     /* Active CID limit */ "\x0E\x01\x07"
86fb73393fSDmitri Tikhonov     /* Initial SCID */     "\x0F\x08\x01\x02\x03\x04\x05\x06\x07\x08"
875392f7a3SLiteSpeed Tech    /* Trailer to make the end easily visible in gdb: */
885392f7a3SLiteSpeed Tech    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
895392f7a3SLiteSpeed Tech    },
905392f7a3SLiteSpeed Tech
915392f7a3SLiteSpeed Tech    {
925392f7a3SLiteSpeed Tech        .line   = __LINE__,
935392f7a3SLiteSpeed Tech        .flags  = TEST_DECODE,
945392f7a3SLiteSpeed Tech        .dec_len = 1,
955392f7a3SLiteSpeed Tech        .expect_decode_err = 1,
965392f7a3SLiteSpeed Tech    },
975392f7a3SLiteSpeed Tech
985392f7a3SLiteSpeed Tech    {
995392f7a3SLiteSpeed Tech        .line   = __LINE__,
1005392f7a3SLiteSpeed Tech        .flags  = TEST_DECODE,
1015392f7a3SLiteSpeed Tech        .dec_len = 3,
1025392f7a3SLiteSpeed Tech        .expect_decode_err = 1,
1035392f7a3SLiteSpeed Tech        .encoded = "\x00\x04",
1045392f7a3SLiteSpeed Tech    },
1055392f7a3SLiteSpeed Tech
1065392f7a3SLiteSpeed Tech
1075392f7a3SLiteSpeed Tech    {
1085392f7a3SLiteSpeed Tech        .line   = __LINE__,
1095392f7a3SLiteSpeed Tech        .flags  = TEST_ENCODE | TEST_DECODE,
1105392f7a3SLiteSpeed Tech        .params = {
1115392f7a3SLiteSpeed Tech            TP_DEFAULT_VALUES,
1125392f7a3SLiteSpeed Tech            .tp_init_max_data = 0x123456,
1135392f7a3SLiteSpeed Tech            .tp_init_max_stream_data_bidi_local = 0xABCDEF88,
114fb73393fSDmitri Tikhonov            .tp_max_udp_payload_size = 0x555,
1155392f7a3SLiteSpeed Tech        },
1161bdb91d1SDmitri Tikhonov        .is_server = 1,
1171bdb91d1SDmitri Tikhonov        .addl_set = 1 << TPI_DISABLE_ACTIVE_MIGRATION,
118bc520ef7SDmitri Tikhonov        .enc_len = 22,
1195392f7a3SLiteSpeed Tech        .encoded =
12077a28812SDmitri Tikhonov     /* Packet size */      "\x03\x02\x45\x55"
121bc520ef7SDmitri Tikhonov     /* Max data */         "\x04\x04\x80\x12\x34\x56"
122bc520ef7SDmitri Tikhonov     /* Bidi local */       "\x05\x08\xC0\x00\x00\x00\xAB\xCD\xEF\x88"
123bc520ef7SDmitri Tikhonov     /* Migration */        "\x0C\x00"
1245392f7a3SLiteSpeed Tech    /* Trailer to make the end easily visible in gdb: */
1255392f7a3SLiteSpeed Tech    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
1265392f7a3SLiteSpeed Tech    },
1275392f7a3SLiteSpeed Tech
1285392f7a3SLiteSpeed Tech    /* Test server preferred address. */
1295392f7a3SLiteSpeed Tech    {
1305392f7a3SLiteSpeed Tech        .line   = __LINE__,
1315392f7a3SLiteSpeed Tech        .flags  = TEST_DECODE,
1325392f7a3SLiteSpeed Tech        .params = {
1335392f7a3SLiteSpeed Tech            TP_DEFAULT_VALUES,
1345392f7a3SLiteSpeed Tech            .tp_max_ack_delay = 25,
135fb73393fSDmitri Tikhonov            .tp_max_udp_payload_size = 0x555,
1365392f7a3SLiteSpeed Tech            .tp_preferred_address = {
1375392f7a3SLiteSpeed Tech                .ipv4_addr = "\x01\x02\x03\x04",
1385392f7a3SLiteSpeed Tech                .ipv4_port = 0x1234,
1395392f7a3SLiteSpeed Tech                .ipv6_addr = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
1405392f7a3SLiteSpeed Tech                .ipv6_port = 0x9001,
1415392f7a3SLiteSpeed Tech                .cid = { .len = 11, .idbuf = "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A", },
1425392f7a3SLiteSpeed Tech                .srst = "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F",
1435392f7a3SLiteSpeed Tech            },
1445392f7a3SLiteSpeed Tech        },
1451bdb91d1SDmitri Tikhonov        .is_server = 1,
1461bdb91d1SDmitri Tikhonov        .addl_set = 1 << TPI_PREFERRED_ADDRESS,
147bc520ef7SDmitri Tikhonov        .enc_len = 0x3A,
148bc520ef7SDmitri Tikhonov        .dec_len = 0x3A,
1495392f7a3SLiteSpeed Tech        .encoded =
150bc520ef7SDmitri Tikhonov     /* Preferred Address */"\x0D"
151bc520ef7SDmitri Tikhonov                            "\x34"
1525392f7a3SLiteSpeed Tech                            "\x01\x02\x03\x04"
1535392f7a3SLiteSpeed Tech                            "\x12\x34"
1545392f7a3SLiteSpeed Tech                            "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
1555392f7a3SLiteSpeed Tech                            "\x90\x01"
1565392f7a3SLiteSpeed Tech                            "\x0B"  /* CID len */
1575392f7a3SLiteSpeed Tech                            "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A"
1585392f7a3SLiteSpeed Tech                            "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
15977a28812SDmitri Tikhonov     /* Packet size */      "\x03\x02\x45\x55"
1605392f7a3SLiteSpeed Tech    /* Trailer to make the end easily visible in gdb: */
1615392f7a3SLiteSpeed Tech    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
1625392f7a3SLiteSpeed Tech    },
1635392f7a3SLiteSpeed Tech
1645392f7a3SLiteSpeed Tech};
1655392f7a3SLiteSpeed Tech
1665392f7a3SLiteSpeed Tech
1675392f7a3SLiteSpeed Techstatic int
1685392f7a3SLiteSpeed Techparams_are_equal (const struct transport_params *a,
1695392f7a3SLiteSpeed Tech                  const struct transport_params *b)
1705392f7a3SLiteSpeed Tech{
1715392f7a3SLiteSpeed Tech#define MCMP(f) 0 == memcmp(&a->f, &b->f, sizeof(a->f))
1721bdb91d1SDmitri Tikhonov    return MCMP(tp_numerics)
1731bdb91d1SDmitri Tikhonov        && MCMP(tp_set)
1745392f7a3SLiteSpeed Tech        && MCMP(tp_stateless_reset_token)
1755392f7a3SLiteSpeed Tech        && MCMP(tp_preferred_address.ipv4_addr)
1765392f7a3SLiteSpeed Tech        && MCMP(tp_preferred_address.ipv6_addr)
1775392f7a3SLiteSpeed Tech        && MCMP(tp_preferred_address.srst)
1785392f7a3SLiteSpeed Tech        && MCMP(tp_preferred_address.cid.idbuf)
1795392f7a3SLiteSpeed Tech        && a->tp_preferred_address.ipv4_port == b->tp_preferred_address.ipv4_port
1805392f7a3SLiteSpeed Tech        && a->tp_preferred_address.ipv6_port == b->tp_preferred_address.ipv6_port
1815392f7a3SLiteSpeed Tech        && a->tp_preferred_address.cid.len == b->tp_preferred_address.cid.len
182fb73393fSDmitri Tikhonov        && MCMP(tp_original_dest_cid.idbuf)
183fb73393fSDmitri Tikhonov        && a->tp_original_dest_cid.len == b->tp_original_dest_cid.len
1845392f7a3SLiteSpeed Tech        ;
1855392f7a3SLiteSpeed Tech#undef MCMP
1865392f7a3SLiteSpeed Tech}
1875392f7a3SLiteSpeed Tech
1885392f7a3SLiteSpeed Tech
1895392f7a3SLiteSpeed Techstatic void
1905392f7a3SLiteSpeed Techrun_test (const struct trapa_test *test)
1915392f7a3SLiteSpeed Tech{
1921bdb91d1SDmitri Tikhonov    struct transport_params source_params;
1935392f7a3SLiteSpeed Tech    struct transport_params decoded_params;
1945392f7a3SLiteSpeed Tech    size_t dec_len;
1955392f7a3SLiteSpeed Tech    int s;
1965392f7a3SLiteSpeed Tech    unsigned char buf[ENC_BUF_SZ];
1975392f7a3SLiteSpeed Tech
1981bdb91d1SDmitri Tikhonov    source_params = test->params;
1991bdb91d1SDmitri Tikhonov    source_params.tp_set |= test->addl_set;
2001bdb91d1SDmitri Tikhonov
2015392f7a3SLiteSpeed Tech    if (test->flags & TEST_ENCODE)
2025392f7a3SLiteSpeed Tech    {
2031bdb91d1SDmitri Tikhonov        s = lsquic_tp_encode(&source_params, test->is_server, buf, sizeof(buf));
204bc520ef7SDmitri Tikhonov        assert(s >= 0);
2055392f7a3SLiteSpeed Tech        assert((size_t) s == test->enc_len);
2065392f7a3SLiteSpeed Tech        assert(0 == memcmp(test->encoded, buf, s));
2075392f7a3SLiteSpeed Tech    }
2085392f7a3SLiteSpeed Tech
2095392f7a3SLiteSpeed Tech    if (test->flags & TEST_DECODE)
2105392f7a3SLiteSpeed Tech    {
2115392f7a3SLiteSpeed Tech        if (test->dec_len)
2125392f7a3SLiteSpeed Tech            dec_len = test->dec_len;
2135392f7a3SLiteSpeed Tech        else
214bc520ef7SDmitri Tikhonov            dec_len = test->enc_len;
2155392f7a3SLiteSpeed Tech        s = lsquic_tp_decode(test->encoded, dec_len,
2161bdb91d1SDmitri Tikhonov                     test->is_server, &decoded_params);
2175392f7a3SLiteSpeed Tech        if (!test->expect_decode_err)
2185392f7a3SLiteSpeed Tech        {
219bc520ef7SDmitri Tikhonov            assert(s >= 0);
2205392f7a3SLiteSpeed Tech            assert((size_t) s == test->enc_len);
2211bdb91d1SDmitri Tikhonov            /* The decoder initializes all default values, so set the flag
2221bdb91d1SDmitri Tikhonov             * accordingly:
2231bdb91d1SDmitri Tikhonov             */
2241bdb91d1SDmitri Tikhonov            source_params.tp_set |= ((1 << (MAX_NUM_WITH_DEF_TPI + 1)) - 1);
2251bdb91d1SDmitri Tikhonov            s = params_are_equal(&source_params, &decoded_params);
2265392f7a3SLiteSpeed Tech            assert(s);
2275392f7a3SLiteSpeed Tech        }
2285392f7a3SLiteSpeed Tech        else
2295392f7a3SLiteSpeed Tech            assert(s < 0);
2305392f7a3SLiteSpeed Tech    }
2315392f7a3SLiteSpeed Tech}
2325392f7a3SLiteSpeed Tech
2335392f7a3SLiteSpeed Tech
2345392f7a3SLiteSpeed Techstatic void
2355392f7a3SLiteSpeed Techdecode_file (const char *name)
2365392f7a3SLiteSpeed Tech{
2375392f7a3SLiteSpeed Tech    FILE *file;
2385392f7a3SLiteSpeed Tech    size_t nread;
2395392f7a3SLiteSpeed Tech    int s;
2405392f7a3SLiteSpeed Tech    struct transport_params params;
2415392f7a3SLiteSpeed Tech    unsigned char buf[0x1000];
2425392f7a3SLiteSpeed Tech
2435392f7a3SLiteSpeed Tech    file = fopen(name, "rb");
2445392f7a3SLiteSpeed Tech    if (!file)
2455392f7a3SLiteSpeed Tech    {
2465392f7a3SLiteSpeed Tech        perror("fopen");
2475392f7a3SLiteSpeed Tech        exit(1);
2485392f7a3SLiteSpeed Tech    }
2495392f7a3SLiteSpeed Tech
2505392f7a3SLiteSpeed Tech    nread = fread(buf, 1, sizeof(buf), file);
2515392f7a3SLiteSpeed Tech
2525392f7a3SLiteSpeed Tech    s = lsquic_tp_decode(buf, nread, 0, &params);
2535392f7a3SLiteSpeed Tech
2545392f7a3SLiteSpeed Tech    fclose(file);
2555392f7a3SLiteSpeed Tech
2565392f7a3SLiteSpeed Tech    printf("decoded params from %s: %d (%s)\n", name, s, s > 0 ? "OK" : "FAIL");
2575392f7a3SLiteSpeed Tech}
2585392f7a3SLiteSpeed Tech
2595392f7a3SLiteSpeed Tech
2605392f7a3SLiteSpeed Techint
2615392f7a3SLiteSpeed Techmain (int argc, char **argv)
2625392f7a3SLiteSpeed Tech{
2635392f7a3SLiteSpeed Tech    unsigned i;
2645392f7a3SLiteSpeed Tech    int opt;
2655392f7a3SLiteSpeed Tech
2665392f7a3SLiteSpeed Tech    while (-1 != (opt = getopt(argc, argv, "d:l:")))
2675392f7a3SLiteSpeed Tech    {
2685392f7a3SLiteSpeed Tech        switch (opt)
2695392f7a3SLiteSpeed Tech        {
2705392f7a3SLiteSpeed Tech        case 'd':
2715392f7a3SLiteSpeed Tech            decode_file(optarg);
2725392f7a3SLiteSpeed Tech            return 0;
2735392f7a3SLiteSpeed Tech        case 'l':
2745392f7a3SLiteSpeed Tech            lsquic_log_to_fstream(stderr, 0);
2755392f7a3SLiteSpeed Tech            lsquic_logger_lopt(optarg);
2765392f7a3SLiteSpeed Tech            break;
2775392f7a3SLiteSpeed Tech        default:
2785392f7a3SLiteSpeed Tech            exit(1);
2795392f7a3SLiteSpeed Tech        }
2805392f7a3SLiteSpeed Tech    }
2815392f7a3SLiteSpeed Tech
2825392f7a3SLiteSpeed Tech    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
2835392f7a3SLiteSpeed Tech        run_test(&tests[i]);
2845392f7a3SLiteSpeed Tech
2855392f7a3SLiteSpeed Tech    return 0;
2865392f7a3SLiteSpeed Tech}
287