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