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