test_trapa.c revision 9a690580
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * test_trapa.c -- Test transport parameters.
4 */
5
6#include <assert.h>
7
8#include <stddef.h>
9#include <stdint.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14
15#include "lsquic.h"
16#include "lsquic_types.h"
17#include "lsquic_sizes.h"
18#include "lsquic_logger.h"
19#include "lsquic_trans_params.h"
20
21#define ENC_BUF_SZ 0x1000
22
23struct trapa_test
24{
25    int                         line;
26    enum {
27        TEST_ENCODE = 1 << 0,
28        TEST_DECODE = 1 << 1,
29    }                           flags;
30    struct transport_params     params;
31    size_t                      enc_len, dec_len;
32    unsigned                    addl_set;
33    int                         is_server;
34    int                         expect_decode_err;
35    unsigned char               encoded[ENC_BUF_SZ];
36};
37
38static const struct trapa_test tests[] =
39{
40
41    {
42        .line   = __LINE__,
43        .flags  = TEST_ENCODE | TEST_DECODE,
44        .params = {
45            TP_DEFAULT_VALUES,
46        },
47        .enc_len = 0,
48        .encoded =
49    /* Trailer to make the end easily visible in gdb: */
50    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
51    },
52
53    {
54        .line   = __LINE__,
55        .flags  = TEST_ENCODE | TEST_DECODE,
56        .params = {
57            .tp_set = (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL)
58                    | (1 << TPI_INIT_MAX_DATA)
59                    | (1 << TPI_MAX_IDLE_TIMEOUT)
60                    | (1 << TPI_MAX_ACK_DELAY)
61                    | (1 << TPI_MAX_PACKET_SIZE)
62                    | (1 << TPI_ACK_DELAY_EXPONENT)
63                    | (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT),
64            .tp_init_max_stream_data_bidi_local = 0x12348877,
65            .tp_init_max_data = 0xAABB,
66            .tp_max_packet_size = 1213,
67            .tp_max_idle_timeout = 10 * 1000,
68            .tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY,
69            .tp_active_connection_id_limit = 7,
70        },
71        .is_server = 0,
72        .enc_len = 26,
73        .encoded =
74     /* Idle timeout */     "\x01\x02\x67\x10"
75     /* Packet size */      "\x03\x02\x44\xBD"
76     /* Max data */         "\x04\x04\x80\x00\xAA\xBB"
77     /* Bidi local */       "\x05\x04\x92\x34\x88\x77"
78     /* Ack delay exp */    "\x0A\x01\x00"
79     /* Active CID limit */ "\x0E\x01\x07"
80    /* Trailer to make the end easily visible in gdb: */
81    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
82    },
83
84    {
85        .line   = __LINE__,
86        .flags  = TEST_DECODE,
87        .dec_len = 1,
88        .expect_decode_err = 1,
89    },
90
91    {
92        .line   = __LINE__,
93        .flags  = TEST_DECODE,
94        .dec_len = 3,
95        .expect_decode_err = 1,
96        .encoded = "\x00\x04",
97    },
98
99
100    {
101        .line   = __LINE__,
102        .flags  = TEST_ENCODE | TEST_DECODE,
103        .params = {
104            TP_DEFAULT_VALUES,
105            .tp_init_max_data = 0x123456,
106            .tp_init_max_stream_data_bidi_local = 0xABCDEF88,
107            .tp_max_packet_size = 0x555,
108        },
109        .is_server = 1,
110        .addl_set = 1 << TPI_DISABLE_ACTIVE_MIGRATION,
111        .enc_len = 22,
112        .encoded =
113     /* Packet size */      "\x03\x02\x45\x55"
114     /* Max data */         "\x04\x04\x80\x12\x34\x56"
115     /* Bidi local */       "\x05\x08\xC0\x00\x00\x00\xAB\xCD\xEF\x88"
116     /* Migration */        "\x0C\x00"
117    /* Trailer to make the end easily visible in gdb: */
118    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
119    },
120
121    /* Test server preferred address. */
122    {
123        .line   = __LINE__,
124        .flags  = TEST_DECODE,
125        .params = {
126            TP_DEFAULT_VALUES,
127            .tp_max_ack_delay = 25,
128            .tp_max_packet_size = 0x555,
129            .tp_preferred_address = {
130                .ipv4_addr = "\x01\x02\x03\x04",
131                .ipv4_port = 0x1234,
132                .ipv6_addr = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
133                .ipv6_port = 0x9001,
134                .cid = { .len = 11, .idbuf = "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A", },
135                .srst = "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F",
136            },
137        },
138        .is_server = 1,
139        .addl_set = 1 << TPI_PREFERRED_ADDRESS,
140        .enc_len = 0x3A,
141        .dec_len = 0x3A,
142        .encoded =
143     /* Preferred Address */"\x0D"
144                            "\x34"
145                            "\x01\x02\x03\x04"
146                            "\x12\x34"
147                            "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
148                            "\x90\x01"
149                            "\x0B"  /* CID len */
150                            "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A"
151                            "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
152     /* Packet size */      "\x03\x02\x45\x55"
153    /* Trailer to make the end easily visible in gdb: */
154    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
155    },
156
157};
158
159
160static int
161params_are_equal (const struct transport_params *a,
162                  const struct transport_params *b)
163{
164#define MCMP(f) 0 == memcmp(&a->f, &b->f, sizeof(a->f))
165    return MCMP(tp_numerics)
166        && MCMP(tp_set)
167        && MCMP(tp_stateless_reset_token)
168        && MCMP(tp_preferred_address.ipv4_addr)
169        && MCMP(tp_preferred_address.ipv6_addr)
170        && MCMP(tp_preferred_address.srst)
171        && MCMP(tp_preferred_address.cid.idbuf)
172        && a->tp_preferred_address.ipv4_port == b->tp_preferred_address.ipv4_port
173        && a->tp_preferred_address.ipv6_port == b->tp_preferred_address.ipv6_port
174        && a->tp_preferred_address.cid.len == b->tp_preferred_address.cid.len
175        && MCMP(tp_original_cid.idbuf)
176        && a->tp_original_cid.len == b->tp_original_cid.len
177        ;
178#undef MCMP
179}
180
181
182static void
183run_test (const struct trapa_test *test)
184{
185    struct transport_params source_params;
186    struct transport_params decoded_params;
187    size_t dec_len;
188    int s;
189    unsigned char buf[ENC_BUF_SZ];
190
191    source_params = test->params;
192    source_params.tp_set |= test->addl_set;
193
194    if (test->flags & TEST_ENCODE)
195    {
196        s = lsquic_tp_encode(&source_params, test->is_server, buf, sizeof(buf));
197        assert(s >= 0);
198        assert((size_t) s == test->enc_len);
199        assert(0 == memcmp(test->encoded, buf, s));
200    }
201
202    if (test->flags & TEST_DECODE)
203    {
204        if (test->dec_len)
205            dec_len = test->dec_len;
206        else
207            dec_len = test->enc_len;
208        s = lsquic_tp_decode(test->encoded, dec_len,
209                     test->is_server, &decoded_params);
210        if (!test->expect_decode_err)
211        {
212            assert(s >= 0);
213            assert((size_t) s == test->enc_len);
214            /* The decoder initializes all default values, so set the flag
215             * accordingly:
216             */
217            source_params.tp_set |= ((1 << (MAX_NUM_WITH_DEF_TPI + 1)) - 1);
218            s = params_are_equal(&source_params, &decoded_params);
219            assert(s);
220        }
221        else
222            assert(s < 0);
223    }
224}
225
226
227static void
228decode_file (const char *name)
229{
230    FILE *file;
231    size_t nread;
232    int s;
233    struct transport_params params;
234    unsigned char buf[0x1000];
235
236    file = fopen(name, "rb");
237    if (!file)
238    {
239        perror("fopen");
240        exit(1);
241    }
242
243    nread = fread(buf, 1, sizeof(buf), file);
244
245    s = lsquic_tp_decode(buf, nread, 0, &params);
246
247    fclose(file);
248
249    printf("decoded params from %s: %d (%s)\n", name, s, s > 0 ? "OK" : "FAIL");
250}
251
252
253int
254main (int argc, char **argv)
255{
256    unsigned i;
257    int opt;
258
259    while (-1 != (opt = getopt(argc, argv, "d:l:")))
260    {
261        switch (opt)
262        {
263        case 'd':
264            decode_file(optarg);
265            return 0;
266        case 'l':
267            lsquic_log_to_fstream(stderr, 0);
268            lsquic_logger_lopt(optarg);
269            break;
270        default:
271            exit(1);
272        }
273    }
274
275    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
276        run_test(&tests[i]);
277
278    return 0;
279}
280