test_ackgen_gquic_be.c revision f38b395a
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * Test how ACK frame is encoded.  Receive history module is tested by a
4 * separate unit test.
5 */
6
7#include <assert.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#ifdef WIN32
13#include "vc_compat.h"
14#endif
15
16#include "lsquic_types.h"
17#include "lsquic_int_types.h"
18#include "lsquic_rechist.h"
19#include "lsquic_parse.h"
20#include "lsquic_util.h"
21#include "lsquic_logger.h"
22#include "lsquic.h"
23
24static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043);
25
26static void
27test1 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock */
28{
29    lsquic_rechist_t rechist;
30    lsquic_time_t now = lsquic_time_now();
31    lsquic_packno_t largest = 0;
32
33    lsquic_rechist_init(&rechist, 0, 0);
34
35    unsigned i;
36    for (i = 1; i <= 0x1234; ++i)
37        (void) lsquic_rechist_received(&rechist, i, now);
38
39    const unsigned char expected_ack_frame[] = {
40        0x45,
41        0x12, 0x34,             /* Largest acked */
42        0x87, 0xFF,             /* Delta time */
43        0x12, 0x34,             /* Block length */
44        0x00,                   /* Number of timestamps */
45    };
46    unsigned char outbuf[0x100];
47
48    int has_missing = -1;
49    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
50        (gaf_rechist_first_f)        lsquic_rechist_first,
51        (gaf_rechist_next_f)         lsquic_rechist_next,
52        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
53        &rechist, now + 0x7FF8000, &has_missing, &largest, NULL);
54    assert(("ACK frame generation successful", w > 0));
55    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
56    assert(("ACK frame contents are as expected",
57        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
58    assert(("ACK frame has no missing packets", has_missing == 0));
59    assert(largest == 0x1234);
60
61    lsquic_rechist_cleanup(&rechist);
62}
63
64static void
65test2 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock, minus
66              * delta times.
67              */
68{
69    lsquic_rechist_t rechist;
70    lsquic_time_t now = lsquic_time_now();
71
72    lsquic_rechist_init(&rechist, 0, 0);
73
74    /* Encode the following ranges:
75     *    high      low
76     *    0x1234    0x1234
77     *    0x1232    0x384
78     *    0x1F3     0xA
79     *    0x4       0x1
80     */
81    unsigned i;
82    for (i = 4; i >= 1; --i)
83        (void) lsquic_rechist_received(&rechist, i, now);
84    (void) lsquic_rechist_received(&rechist, 0x1234, now);
85    for (i = 0xA; i <= 0x1F3; ++i)
86        (void) lsquic_rechist_received(&rechist, i, now);
87    for (i = 0x1232; i >= 0x384; --i)
88        (void) lsquic_rechist_received(&rechist, i, now);
89
90    const unsigned char expected_ack_frame[] = {
91        0x65,
92        0x12, 0x34,                 /* Largest acked */
93        0x00, 0x00,                 /* Zero delta time. */
94        0x04,                       /* Num ack blocks ranges. */
95        0x00, 0x01,                 /* First ack block length. */
96        0x01,                       /* Gap to next block. */
97        0x0e, 0xaf,                 /* Ack block length. */
98        0xff,                       /* Gap to next block. */
99        0x00, 0x00,                 /* Ack block length. */
100        0x91,                       /* Gap to next block. */
101        0x01, 0xea,                 /* Ack block length. */
102        0x05,                       /* Gap to next block. */
103        0x00, 0x04,                 /* Ack block length. */
104        0x00,                       /* Number of timestamps. */
105    };
106    unsigned char outbuf[0x100];
107
108    int has_missing = -1;
109    lsquic_packno_t largest = 0;
110    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
111        (gaf_rechist_first_f)        lsquic_rechist_first,
112        (gaf_rechist_next_f)         lsquic_rechist_next,
113        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
114        &rechist, now, &has_missing, &largest, NULL);
115    assert(("ACK frame generation successful", w > 0));
116    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
117    assert(("ACK frame contents are as expected",
118        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
119    assert(("ACK frame has missing packets", has_missing > 0));
120    assert(largest == 0x1234);
121
122    lsquic_rechist_cleanup(&rechist);
123}
124
125static void
126test3 (void)
127{
128    lsquic_rechist_t rechist;
129    lsquic_time_t now = lsquic_time_now();
130
131    lsquic_rechist_init(&rechist, 0, 0);
132
133    /* Encode the following ranges:
134     *    high      low
135     *    3         3
136     *    1         1
137     */
138    (void) lsquic_rechist_received(&rechist, 1, now);
139    (void) lsquic_rechist_received(&rechist, 3, now);
140
141    const unsigned char expected_ack_frame[] = {
142        0x60,
143        0x03,
144        0x00, 0x00,                 /* Zero delta time. */
145        0x01,                       /* Num ack blocks ranges. */
146        0x01,                       /* First ack block length. */
147        0x01,                       /* Gap to next block. */
148        0x01,                       /* Ack block length. */
149        0x00,                       /* Number of timestamps. */
150    };
151    unsigned char outbuf[0x100];
152
153    int has_missing = -1;
154    lsquic_packno_t largest = 0;
155    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
156        (gaf_rechist_first_f)        lsquic_rechist_first,
157        (gaf_rechist_next_f)         lsquic_rechist_next,
158        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
159        &rechist, now, &has_missing, &largest, NULL);
160    assert(("ACK frame generation successful", w > 0));
161    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
162    assert(("ACK frame contents are as expected",
163        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
164    assert(("ACK frame has missing packets", has_missing > 0));
165    assert(largest == 0x03);
166
167    lsquic_rechist_cleanup(&rechist);
168}
169
170
171static void
172test4 (void)
173{
174    lsquic_rechist_t rechist;
175    int i;
176
177    lsquic_rechist_init(&rechist, 0, 0);
178
179    lsquic_time_t now = lsquic_time_now();
180    lsquic_rechist_received(&rechist, 1, now);
181
182    {
183        const unsigned char expected_ack_frame[] = {
184            0x40,
185            0x01,                   /* Largest acked */
186            0x00, 0x00,             /* Delta time */
187            0x01,                   /* Block length */
188            0x00,                   /* Number of timestamps */
189        };
190        unsigned char outbuf[0x100];
191        int has_missing = -1;
192        lsquic_packno_t largest = 0;
193        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
194            (gaf_rechist_first_f)        lsquic_rechist_first,
195            (gaf_rechist_next_f)         lsquic_rechist_next,
196            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
197            &rechist, now, &has_missing, &largest, NULL);
198        assert(("ACK frame generation successful", w > 0));
199        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
200        assert(("ACK frame contents are as expected",
201            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
202        assert(("ACK frame has no missing packets", has_missing == 0));
203        assert(largest == 1);
204    }
205
206    for (i = 3; i <= 5; ++i)
207        lsquic_rechist_received(&rechist, i, now);
208
209    {
210        const unsigned char expected_ack_frame[] = {
211            0x60,
212            0x05,                   /* Largest acked */
213            0x00, 0x00,             /* Delta time */
214            0x01,                   /* Num ack blocks */
215            0x03,                   /* First block length [3, 5] */
216            0x01,                   /* Gap to next block */
217            0x01,                   /* Second block length [1, 1] */
218            0x00,                   /* Number of timestamps */
219        };
220        unsigned char outbuf[0x100];
221        int has_missing = -1;
222        lsquic_packno_t largest = 0;
223        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
224            (gaf_rechist_first_f)        lsquic_rechist_first,
225            (gaf_rechist_next_f)         lsquic_rechist_next,
226            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
227            &rechist, now, &has_missing, &largest, NULL);
228        assert(("ACK frame generation successful", w > 0));
229        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
230        assert(("ACK frame contents are as expected",
231            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
232        assert(("ACK frame has missing packets", has_missing > 0));
233        assert(largest == 5);
234    }
235
236    lsquic_rechist_cleanup(&rechist);
237}
238
239
240static void
241test_4byte_packnos (void)
242{
243    lsquic_packno_t packno;
244    lsquic_rechist_t rechist;
245    lsquic_time_t now = lsquic_time_now();
246
247    lsquic_rechist_init(&rechist, 0, 0);
248
249    packno = 0x23456789;
250    (void) lsquic_rechist_received(&rechist, packno - 33, now);
251    (void) lsquic_rechist_received(&rechist, packno, now);
252
253    /* Adjust: */
254    rechist.rh_elems[0].re_low = 1;
255    rechist.rh_elems[0].re_count = packno - 33;
256
257    const unsigned char expected_ack_frame[] = {
258        0x60
259            | (2 << 2)  /* Four-byte largest acked */
260            | (2 << 0)  /* Four-byte ACK block length */
261        ,
262        0x23, 0x45, 0x67, 0x89,
263        0x00, 0x00,                 /* Zero delta time. */
264        0x01,                       /* Num ack blocks ranges. */
265        0x00, 0x00, 0x00, 0x01,     /* First ack block length. */
266        33 - 1,                     /* Gap to next block. */
267        0x23, 0x45, 0x67, 0x68,     /* Ack block length. */
268        0x00,                       /* Number of timestamps. */
269    };
270    unsigned char outbuf[0x100];
271
272    int has_missing = -1;
273    lsquic_packno_t largest = 0;
274    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
275        (gaf_rechist_first_f)        lsquic_rechist_first,
276        (gaf_rechist_next_f)         lsquic_rechist_next,
277        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
278        &rechist, now, &has_missing, &largest, NULL);
279    assert(("ACK frame generation successful", w > 0));
280    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
281    assert(("ACK frame contents are as expected",
282        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
283    assert(("ACK frame has missing packets", has_missing > 0));
284    assert(largest == 0x23456789);
285
286    lsquic_rechist_cleanup(&rechist);
287}
288
289
290/* lsquic_rechist no longer supports ranges that require integers
291 * wider than four bytes -- modify the test to use a custom receive
292 * history.
293 */
294static const struct lsquic_packno_range test_6byte_ranges[] = {
295    { .high = 0xABCD23456789, .low = 0xABCD23456789, },
296    { .high = 0xABCD23456789 - 33, .low = 1, },
297};
298
299
300static const struct lsquic_packno_range *
301test_6byte_rechist_first (void *rechist)
302{
303    int *next = rechist;
304    *next = 1;
305    return &test_6byte_ranges[0];
306};
307
308
309static const struct lsquic_packno_range *
310test_6byte_rechist_next (void *rechist)
311{
312    int *next = rechist;
313    if (*next == 1)
314    {
315        ++*next;
316        return &test_6byte_ranges[1];
317    }
318    else
319        return NULL;
320}
321
322
323static lsquic_time_t s_test_6byte_now;
324static lsquic_time_t
325test_6byte_rechist_largest_recv  (void *rechist)
326{
327    return s_test_6byte_now;
328}
329
330
331static void
332test_6byte_packnos (void)
333{
334    int rechist = 0;
335    s_test_6byte_now = lsquic_time_now();
336
337    const unsigned char expected_ack_frame[] = {
338        0x60
339            | (3 << 2)  /* Six-byte largest acked */
340            | (3 << 0)  /* Six-byte ACK block length */
341        ,
342        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x89,
343        0x00, 0x00,                 /* Zero delta time. */
344        0x01,                       /* Num ack blocks ranges. */
345        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* First ack block length. */
346        33 - 1,                     /* Gap to next block. */
347        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x68, /* Ack block length. */
348        0x00,                       /* Number of timestamps. */
349    };
350    unsigned char outbuf[0x100];
351
352    int has_missing = -1;
353    lsquic_packno_t largest = 0;
354    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
355        test_6byte_rechist_first,
356        test_6byte_rechist_next,
357        test_6byte_rechist_largest_recv,
358        &rechist, s_test_6byte_now, &has_missing, &largest, NULL);
359    assert(("ACK frame generation successful", w > 0));
360    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
361    assert(("ACK frame contents are as expected",
362        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
363    assert(("ACK frame has missing packets", has_missing > 0));
364    assert(largest == 0xABCD23456789ULL);
365}
366
367
368int
369main (void)
370{
371    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
372    lsquic_log_to_fstream(stderr, 0);
373    lsq_log_levels[LSQLM_PARSE]   = LSQ_LOG_DEBUG;
374
375    test1();
376
377    test2();
378
379    test3();
380
381    test4();
382
383    test_4byte_packnos();
384
385    test_6byte_packnos();
386
387    return 0;
388}
389