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