test_ackparse_gquic_le.c revision 9a690580
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#ifndef WIN32
7#include <sys/time.h>
8#endif
9
10#include "lsquic_types.h"
11#include "lsquic_parse.h"
12#include "lsquic_rechist.h"
13#include "lsquic_util.h"
14#include "lsquic.h"
15
16static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_035);
17
18static lsquic_packno_t
19n_acked (const ack_info_t *acki)
20{
21    lsquic_packno_t n = 0;
22    unsigned i;
23    for (i = 0; i < acki->n_ranges; ++i)
24        n += acki->ranges[i].high - acki->ranges[i].low + 1;
25    return n;
26}
27
28
29static void
30test1 (void)
31{
32    /* Test taken from quic_framer_test.cc -- NewAckFrameOneAckBlock */
33    unsigned char ack_buf[] = {
34        0x45,
35        0x34, 0x12,             /* Largest acked */
36        0x00, 0x00,             /* Delta time */
37        0x34, 0x12,             /* Block length */
38        0x00,                   /* Number of timestamps */
39    };
40
41    ack_info_t acki;
42    memset(&acki, 0xF1, sizeof(acki));
43
44    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
45    assert(("Parsed length is correct (8)", len == sizeof(ack_buf)));
46    assert(("Number of ranges is 1", acki.n_ranges == 1));
47    assert(("Largest acked is 0x1234", acki.ranges[0].high == 0x1234));
48    assert(("Lowest acked is 1", acki.ranges[0].low == 1));
49    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
50    unsigned n = n_acked(&acki);
51    assert(("Number of acked packets is 0x1234", n == 0x1234));
52
53    {
54        size_t sz;
55        for (sz = 1; sz < sizeof(ack_buf); ++sz)
56        {
57            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
58            assert(("Parsing truncated frame failed", len < 0));
59        }
60    }
61}
62
63
64static void
65test2 (void)
66{
67    /* Test taken from quic_framer_test.cc -- NewAckFrameOneAckBlock */
68    unsigned char ack_buf[] = {
69        0x65,
70        0x34, 0x12,                 /* Largest acked */
71        0x00, 0x00,                 /* Zero delta time. */
72        0x04,                       /* Num ack blocks ranges. */
73        0x01, 0x00,                 /* First ack block length. */
74        0x01,                       /* Gap to next block. */
75        0xaf, 0x0e,                 /* Ack block length. */
76        0xff,                       /* Gap to next block. */
77        0x00, 0x00,                 /* Ack block length. */
78        0x91,                       /* Gap to next block. */
79        0xea, 0x01,                 /* Ack block length. */
80        0x05,                       /* Gap to next block. */
81        0x04, 0x00,                 /* Ack block length. */
82        0x02,                       /* Number of timestamps. */
83        0x01,                       /* Delta from largest observed. */
84        0x10, 0x32, 0x54, 0x76,     /* Delta time. */
85        0x02,                       /* Delta from largest observed. */
86        0x10, 0x32,                 /* Delta time. */
87    };
88
89    /* We should get the following array of ranges:
90     *    high      low
91     *    0x1234    0x1234
92     *    0x1232    0x384
93     *    0x1F3     0xA
94     *    0x4       0x1
95     */
96    static const struct { unsigned high, low; } ranges[] = {
97        {   0x1234, 0x1234 },
98        {   0x1232, 0x384 },
99        {   0x1F3,  0xA },
100        {   0x4,    0x1 },
101    };
102
103    ack_info_t acki;
104    memset(&acki, 0xF1, sizeof(acki));
105
106    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
107    assert(("Parsed length is correct (29)", len == sizeof(ack_buf)));
108    assert(("Number of ranges is 4", acki.n_ranges == 4));
109    assert(("Largest acked is 0x1234", acki.ranges[0].high == 0x1234));
110    assert(("Number of timestamps is 2", acki.n_timestamps == 2));
111    unsigned n = n_acked(&acki);
112    assert(("Number of acked packets is 4254", n == 4254));
113
114    for (n = 0; n < 4; ++n)
115        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
116                                &&  ranges[n].low  == acki.ranges[n].low));
117
118    {
119        size_t sz;
120        for (sz = 1; sz < sizeof(ack_buf); ++sz)
121        {
122            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
123            assert(("Parsing truncated frame failed", len < 0));
124        }
125    }
126}
127
128
129static void
130test3 (void)
131{
132    /* Generated by our own code, but failed to parse... */
133    unsigned char ack_buf[] = {
134        0x60,         /* More than one ack block, 1 byte largest observed, 1 byte block length */
135        0x06,         /* Largest ACKed */
136        0x00, 0x00,   /* Delta time */
137        0x01,         /* Num ACK block ranges */
138        0x01,         /* First ACK block length */
139        0x02,         /* Gap to next block */
140        0x03,         /* Ack block length */
141        0x00          /* Number of timestamps */
142    };
143
144    /* We should get the following array of ranges:
145     *    high      low
146     *    6         6
147     *    3         1
148     */
149    static const struct { unsigned high, low; } ranges[] = {
150        {   6,      6, },
151        {   3,      1, },
152    };
153
154    ack_info_t acki;
155    memset(&acki, 0xF1, sizeof(acki));
156
157    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
158    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
159    assert(("Number of ranges is 2", acki.n_ranges == 2));
160    assert(("Largest acked is 6", acki.ranges[0].high == 6));
161    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
162    unsigned n = n_acked(&acki);
163    assert(("Number of acked packets is 4", n == 4));
164
165    for (n = 0; n < 2; ++n)
166        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
167                                &&  ranges[n].low  == acki.ranges[n].low));
168
169    {
170        size_t sz;
171        for (sz = 1; sz < sizeof(ack_buf); ++sz)
172        {
173            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
174            assert(("Parsing truncated frame failed", len < 0));
175        }
176    }
177}
178
179
180static void
181test4 (void)
182{
183    unsigned char ack_buf[] = {
184        0x60,       /* More than one ack block, 1 byte largest observed, 1 byte block length */
185        0x03,       /* Largest ACKed */
186        0x23, 0x00, /* Delta time */
187        0x01,       /* Num ACK block ranges */
188        0x01,       /* First ack block length */
189        0x01,       /* Gap */
190        0x01,       /* Ack block length */
191        0x00,       /* Number of timestamps */
192    };
193
194    /* We should get the following array of ranges:
195     *    high      low
196     *    6         6
197     *    3         1
198     */
199    static const struct { unsigned high, low; } ranges[] = {
200        {   3,      3, },
201        {   1,      1, },
202    };
203
204    ack_info_t acki;
205    memset(&acki, 0xF1, sizeof(acki));
206
207    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
208    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
209    assert(("Number of ranges is 2", acki.n_ranges == 2));
210    assert(("Largest acked is 3", acki.ranges[0].high == 3));
211    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
212    unsigned n = n_acked(&acki);
213    assert(("Number of acked packets is 2", n == 2));
214
215    for (n = 0; n < 2; ++n)
216        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
217                                &&  ranges[n].low  == acki.ranges[n].low));
218
219    {
220        size_t sz;
221        for (sz = 1; sz < sizeof(ack_buf); ++sz)
222        {
223            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
224            assert(("Parsing truncated frame failed", len < 0));
225        }
226    }
227}
228
229
230/* Four-byte packet numbers */
231static void
232test5 (void)
233{
234    unsigned char ack_buf[] = {
235        0x60
236            | (2 << 2)  /* Four-byte largest acked */
237            | (2 << 0)  /* Four-byte ACK block length */
238        ,
239        0x89, 0x67, 0x45, 0x23,
240        0x00, 0x00,                 /* Zero delta time. */
241        0x01,                       /* Num ack blocks ranges. */
242        0x01, 0x00, 0x00, 0x00,     /* First ack block length. */
243        33 - 1,                     /* Gap to next block. */
244        0x68, 0x67, 0x45, 0x23,     /* Ack block length. */
245        0x00,                       /* Number of timestamps. */
246    };
247
248    /* We should get the following array of ranges:
249     *    high      low
250     *    6         6
251     *    3         1
252     */
253    static const struct { unsigned high, low; } ranges[] = {
254        {   0x23456789,      0x23456789, },
255        {   0x23456768,      1, },
256    };
257
258    ack_info_t acki;
259    memset(&acki, 0xF1, sizeof(acki));
260
261    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
262    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
263    assert(("Number of ranges is 2", acki.n_ranges == 2));
264    assert(("Largest acked is 0x23456789", acki.ranges[0].high == 0x23456789));
265    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
266    lsquic_packno_t n = n_acked(&acki);
267    assert(("Number of acked packets is correct", n == 0x23456768 + 1));
268
269    for (n = 0; n < 2; ++n)
270        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
271                                &&  ranges[n].low  == acki.ranges[n].low));
272
273    {
274        size_t sz;
275        for (sz = 1; sz < sizeof(ack_buf); ++sz)
276        {
277            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
278            assert(("Parsing truncated frame failed", len < 0));
279        }
280    }
281}
282
283
284/* Six-byte packet numbers */
285static void
286test6 (void)
287{
288    unsigned char ack_buf[] = {
289        0x60
290            | (3 << 2)  /* Six-byte largest acked */
291            | (3 << 0)  /* Six-byte ACK block length */
292        ,
293        0x89, 0x67, 0x45, 0x23, 0xCD, 0xAB,
294        0x00, 0x00,                 /* Zero delta time. */
295        0x01,                       /* Num ack blocks ranges. */
296        0x01, 0x00, 0x00, 0x00, 0x00, 0x00,    /* First ack block length. */
297        33 - 1,                     /* Gap to next block. */
298        0x68, 0x67, 0x45, 0x23, 0xCD, 0xAB,   /* Ack block length. */
299        0x00,                       /* Number of timestamps. */
300    };
301
302    static const struct { lsquic_packno_t high, low; } ranges[] = {
303        {   0xABCD23456789,      0xABCD23456789, },
304        {   0xABCD23456768,      1, },
305    };
306
307    ack_info_t acki;
308    memset(&acki, 0xF1, sizeof(acki));
309
310    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
311    assert(("Parsed length is correct", len == sizeof(ack_buf)));
312    assert(("Number of ranges is 2", acki.n_ranges == 2));
313    assert(("Largest acked is 0xABCD23456789", acki.ranges[0].high == 0xABCD23456789));
314    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
315    lsquic_packno_t n = n_acked(&acki);
316    assert(("Number of acked packets is correct", n == 0xABCD23456768 + 1));
317
318    for (n = 0; n < 2; ++n)
319        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
320                                &&  ranges[n].low  == acki.ranges[n].low));
321
322    {
323        size_t sz;
324        for (sz = 1; sz < sizeof(ack_buf); ++sz)
325        {
326            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
327            assert(("Parsing truncated frame failed", len < 0));
328        }
329    }
330}
331
332
333static void
334test_max_ack (void)
335{
336    lsquic_rechist_t rechist;
337    lsquic_time_t now;
338    unsigned i;
339    int has_missing, sz[2];
340    const struct lsquic_packno_range *range;
341    unsigned char buf[1500];
342    struct ack_info acki;
343
344    lsquic_rechist_init(&rechist, 12345);
345    now = lsquic_time_now();
346
347    for (i = 1; i <= 300; ++i)
348    {
349        lsquic_rechist_received(&rechist, i * 10, now);
350        now += i * 1000;
351    }
352
353    memset(buf, 0xAA, sizeof(buf));
354
355    lsquic_packno_t largest = 0;
356    sz[0] = pf->pf_gen_ack_frame(buf, sizeof(buf),
357        (gaf_rechist_first_f)        lsquic_rechist_first,
358        (gaf_rechist_next_f)         lsquic_rechist_next,
359        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
360        &rechist, now, &has_missing, &largest);
361    assert(sz[0] > 0);
362    assert(sz[0] <= (int) sizeof(buf));
363    assert(has_missing);
364
365    assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
366    assert(0xAA == buf[ sz[0] ]);
367
368    sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki);
369    assert(sz[1] == sz[0]);
370    assert(256 == acki.n_ranges);
371
372    for (range = lsquic_rechist_first(&rechist), i = 0;
373                        range && i < acki.n_ranges;
374                                    range = lsquic_rechist_next(&rechist), ++i)
375    {
376        assert(range->high == acki.ranges[i].high);
377        assert(range->low  == acki.ranges[i].low);
378    }
379    assert(i == 256);
380
381    lsquic_rechist_cleanup(&rechist);
382}
383
384
385static void
386test_ack_truncation (void)
387{
388    lsquic_rechist_t rechist;
389    lsquic_time_t now;
390    unsigned i;
391    int has_missing, sz[2];
392    const struct lsquic_packno_range *range;
393    unsigned char buf[1500];
394    struct ack_info acki;
395    size_t bufsz;
396
397    lsquic_rechist_init(&rechist, 12345);
398    now = lsquic_time_now();
399
400    for (i = 1; i <= 300; ++i)
401    {
402        lsquic_rechist_received(&rechist, i * 10, now);
403        now += i * 1000;
404    }
405
406    for (bufsz = 200; bufsz < 210; ++bufsz)
407    {
408        memset(buf, 0xAA, sizeof(buf));
409        lsquic_packno_t largest = 0;
410        sz[0] = pf->pf_gen_ack_frame(buf, bufsz,
411            (gaf_rechist_first_f)        lsquic_rechist_first,
412            (gaf_rechist_next_f)         lsquic_rechist_next,
413            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
414            &rechist, now, &has_missing, &largest);
415        assert(sz[0] > 0);
416        assert(sz[0] <= (int) bufsz);
417        assert(has_missing);
418
419        assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
420        assert(0xAA == buf[ sz[0] ]);
421
422        sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki);
423        assert(sz[1] == sz[0]);
424        assert(acki.n_ranges < 256);
425
426        for (range = lsquic_rechist_first(&rechist), i = 0;
427                            range && i < acki.n_ranges;
428                                        range = lsquic_rechist_next(&rechist), ++i)
429        {
430            assert(range->high == acki.ranges[i].high);
431            assert(range->low  == acki.ranges[i].low);
432        }
433    }
434
435    lsquic_rechist_cleanup(&rechist);
436}
437
438
439int
440main (void)
441{
442    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
443    test1();
444    test2();
445    test3();
446    test4();
447    test5();
448    test6();
449    test_max_ack();
450    test_ack_truncation();
451    return 0;
452}
453