1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <sys/queue.h>
7#ifndef WIN32
8#include <sys/time.h>
9#else
10#include "vc_compat.h"
11#endif
12
13#include "lsquic_types.h"
14#include "lsquic_parse.h"
15#include "lsquic_rechist.h"
16#include "lsquic_util.h"
17#include "lsquic.h"
18#include "lsquic_hash.h"
19#include "lsquic_conn.h"
20
21static struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0);
22
23//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27); // will not work on MSVC
24#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_ID27))
25
26
27static void
28test_max_ack (void)
29{
30    lsquic_rechist_t rechist;
31    lsquic_time_t now;
32    unsigned i;
33    int has_missing, sz[2];
34    const struct lsquic_packno_range *range;
35    unsigned char buf[1500];
36    struct ack_info acki;
37
38    lsquic_rechist_init(&rechist, 0, 0);
39    now = lsquic_time_now();
40
41    for (i = 1; i <= 300; ++i)
42    {
43        lsquic_rechist_received(&rechist, i * 10, now);
44        now += i * 1000;
45    }
46
47    memset(buf, 0xAA, sizeof(buf));
48
49    lsquic_packno_t largest = 0;
50    sz[0] = pf->pf_gen_ack_frame(buf, sizeof(buf),
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, &has_missing, &largest, NULL);
55    assert(sz[0] > 0);
56    assert(sz[0] <= (int) sizeof(buf));
57    assert(has_missing);
58
59    assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
60    assert(0xAA == buf[ sz[0] ]);
61
62    sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
63    assert(sz[1] == sz[0]);
64    assert(256 == acki.n_ranges);
65
66    for (range = lsquic_rechist_first(&rechist), i = 0;
67                        range && i < acki.n_ranges;
68                                    range = lsquic_rechist_next(&rechist), ++i)
69    {
70        assert(range->high == acki.ranges[i].high);
71        assert(range->low  == acki.ranges[i].low);
72    }
73    assert(i == 256);
74
75    lsquic_rechist_cleanup(&rechist);
76}
77
78
79static void
80test_ack_truncation (void)
81{
82    lsquic_rechist_t rechist;
83    lsquic_time_t now;
84    unsigned i;
85    int has_missing, sz[2];
86    const struct lsquic_packno_range *range;
87    unsigned char buf[1500];
88    struct ack_info acki;
89    size_t bufsz;
90
91    lsquic_rechist_init(&rechist, 0, 0);
92    now = lsquic_time_now();
93
94    for (i = 1; i <= 300; ++i)
95    {
96        lsquic_rechist_received(&rechist, i * 10, now);
97        now += i * 1000;
98    }
99
100    for (bufsz = 200; bufsz < 210; ++bufsz)
101    {
102        memset(buf, 0xAA, sizeof(buf));
103        lsquic_packno_t largest = 0;
104        sz[0] = pf->pf_gen_ack_frame(buf, bufsz,
105            (gaf_rechist_first_f)        lsquic_rechist_first,
106            (gaf_rechist_next_f)         lsquic_rechist_next,
107            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
108            &rechist, now, &has_missing, &largest, NULL);
109        assert(sz[0] > 0);
110        assert(sz[0] <= (int) bufsz);
111        assert(has_missing);
112
113        assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
114        assert(0xAA == buf[ sz[0] ]);
115
116        sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
117        assert(sz[1] == sz[0]);
118        assert(acki.n_ranges < 256);
119
120        for (range = lsquic_rechist_first(&rechist), i = 0;
121                            range && i < acki.n_ranges;
122                                        range = lsquic_rechist_next(&rechist), ++i)
123        {
124            assert(range->high == acki.ranges[i].high);
125            assert(range->low  == acki.ranges[i].low);
126        }
127    }
128
129    lsquic_rechist_cleanup(&rechist);
130}
131
132
133int
134main (void)
135{
136    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
137    test_max_ack();
138    test_ack_truncation();
139    return 0;
140}
141