1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2767cf611SDmitri Tikhonov#include <assert.h>
3767cf611SDmitri Tikhonov#include <stdio.h>
4767cf611SDmitri Tikhonov#include <stdlib.h>
5767cf611SDmitri Tikhonov#include <string.h>
6b62ec17fSDmitri Tikhonov#include <sys/queue.h>
7767cf611SDmitri Tikhonov#ifndef WIN32
8767cf611SDmitri Tikhonov#include <sys/time.h>
9fb3e20e0SDmitri Tikhonov#else
10fb3e20e0SDmitri Tikhonov#include "vc_compat.h"
11767cf611SDmitri Tikhonov#endif
12767cf611SDmitri Tikhonov
13767cf611SDmitri Tikhonov#include "lsquic_types.h"
14767cf611SDmitri Tikhonov#include "lsquic_parse.h"
15767cf611SDmitri Tikhonov#include "lsquic_rechist.h"
16767cf611SDmitri Tikhonov#include "lsquic_util.h"
17767cf611SDmitri Tikhonov#include "lsquic.h"
18767cf611SDmitri Tikhonov#include "lsquic_hash.h"
19767cf611SDmitri Tikhonov#include "lsquic_conn.h"
20767cf611SDmitri Tikhonov
21767cf611SDmitri Tikhonovstatic struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0);
22767cf611SDmitri Tikhonov
23f07b3eaeSTyler Young//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27); // will not work on MSVC
24f07b3eaeSTyler Young#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_ID27))
25767cf611SDmitri Tikhonov
26767cf611SDmitri Tikhonov
27767cf611SDmitri Tikhonovstatic void
28767cf611SDmitri Tikhonovtest_max_ack (void)
29767cf611SDmitri Tikhonov{
30767cf611SDmitri Tikhonov    lsquic_rechist_t rechist;
31767cf611SDmitri Tikhonov    lsquic_time_t now;
32767cf611SDmitri Tikhonov    unsigned i;
33767cf611SDmitri Tikhonov    int has_missing, sz[2];
34767cf611SDmitri Tikhonov    const struct lsquic_packno_range *range;
35767cf611SDmitri Tikhonov    unsigned char buf[1500];
36767cf611SDmitri Tikhonov    struct ack_info acki;
37767cf611SDmitri Tikhonov
38f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
39767cf611SDmitri Tikhonov    now = lsquic_time_now();
40767cf611SDmitri Tikhonov
41767cf611SDmitri Tikhonov    for (i = 1; i <= 300; ++i)
42767cf611SDmitri Tikhonov    {
43767cf611SDmitri Tikhonov        lsquic_rechist_received(&rechist, i * 10, now);
44767cf611SDmitri Tikhonov        now += i * 1000;
45767cf611SDmitri Tikhonov    }
46767cf611SDmitri Tikhonov
47767cf611SDmitri Tikhonov    memset(buf, 0xAA, sizeof(buf));
48767cf611SDmitri Tikhonov
49767cf611SDmitri Tikhonov    lsquic_packno_t largest = 0;
50767cf611SDmitri Tikhonov    sz[0] = pf->pf_gen_ack_frame(buf, sizeof(buf),
51767cf611SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
52767cf611SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
53767cf611SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
54767cf611SDmitri Tikhonov        &rechist, now, &has_missing, &largest, NULL);
55767cf611SDmitri Tikhonov    assert(sz[0] > 0);
56767cf611SDmitri Tikhonov    assert(sz[0] <= (int) sizeof(buf));
57767cf611SDmitri Tikhonov    assert(has_missing);
58767cf611SDmitri Tikhonov
59767cf611SDmitri Tikhonov    assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
60767cf611SDmitri Tikhonov    assert(0xAA == buf[ sz[0] ]);
61767cf611SDmitri Tikhonov
62767cf611SDmitri Tikhonov    sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
63767cf611SDmitri Tikhonov    assert(sz[1] == sz[0]);
64767cf611SDmitri Tikhonov    assert(256 == acki.n_ranges);
65767cf611SDmitri Tikhonov
66767cf611SDmitri Tikhonov    for (range = lsquic_rechist_first(&rechist), i = 0;
67767cf611SDmitri Tikhonov                        range && i < acki.n_ranges;
68767cf611SDmitri Tikhonov                                    range = lsquic_rechist_next(&rechist), ++i)
69767cf611SDmitri Tikhonov    {
70767cf611SDmitri Tikhonov        assert(range->high == acki.ranges[i].high);
71767cf611SDmitri Tikhonov        assert(range->low  == acki.ranges[i].low);
72767cf611SDmitri Tikhonov    }
73767cf611SDmitri Tikhonov    assert(i == 256);
74767cf611SDmitri Tikhonov
75767cf611SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
76767cf611SDmitri Tikhonov}
77767cf611SDmitri Tikhonov
78767cf611SDmitri Tikhonov
79767cf611SDmitri Tikhonovstatic void
80767cf611SDmitri Tikhonovtest_ack_truncation (void)
81767cf611SDmitri Tikhonov{
82767cf611SDmitri Tikhonov    lsquic_rechist_t rechist;
83767cf611SDmitri Tikhonov    lsquic_time_t now;
84767cf611SDmitri Tikhonov    unsigned i;
85767cf611SDmitri Tikhonov    int has_missing, sz[2];
86767cf611SDmitri Tikhonov    const struct lsquic_packno_range *range;
87767cf611SDmitri Tikhonov    unsigned char buf[1500];
88767cf611SDmitri Tikhonov    struct ack_info acki;
89767cf611SDmitri Tikhonov    size_t bufsz;
90767cf611SDmitri Tikhonov
91f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
92767cf611SDmitri Tikhonov    now = lsquic_time_now();
93767cf611SDmitri Tikhonov
94767cf611SDmitri Tikhonov    for (i = 1; i <= 300; ++i)
95767cf611SDmitri Tikhonov    {
96767cf611SDmitri Tikhonov        lsquic_rechist_received(&rechist, i * 10, now);
97767cf611SDmitri Tikhonov        now += i * 1000;
98767cf611SDmitri Tikhonov    }
99767cf611SDmitri Tikhonov
100767cf611SDmitri Tikhonov    for (bufsz = 200; bufsz < 210; ++bufsz)
101767cf611SDmitri Tikhonov    {
102767cf611SDmitri Tikhonov        memset(buf, 0xAA, sizeof(buf));
103767cf611SDmitri Tikhonov        lsquic_packno_t largest = 0;
104767cf611SDmitri Tikhonov        sz[0] = pf->pf_gen_ack_frame(buf, bufsz,
105767cf611SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
106767cf611SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
107767cf611SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
108767cf611SDmitri Tikhonov            &rechist, now, &has_missing, &largest, NULL);
109767cf611SDmitri Tikhonov        assert(sz[0] > 0);
110767cf611SDmitri Tikhonov        assert(sz[0] <= (int) bufsz);
111767cf611SDmitri Tikhonov        assert(has_missing);
112767cf611SDmitri Tikhonov
113767cf611SDmitri Tikhonov        assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
114767cf611SDmitri Tikhonov        assert(0xAA == buf[ sz[0] ]);
115767cf611SDmitri Tikhonov
116767cf611SDmitri Tikhonov        sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
117767cf611SDmitri Tikhonov        assert(sz[1] == sz[0]);
118767cf611SDmitri Tikhonov        assert(acki.n_ranges < 256);
119767cf611SDmitri Tikhonov
120767cf611SDmitri Tikhonov        for (range = lsquic_rechist_first(&rechist), i = 0;
121767cf611SDmitri Tikhonov                            range && i < acki.n_ranges;
122767cf611SDmitri Tikhonov                                        range = lsquic_rechist_next(&rechist), ++i)
123767cf611SDmitri Tikhonov        {
124767cf611SDmitri Tikhonov            assert(range->high == acki.ranges[i].high);
125767cf611SDmitri Tikhonov            assert(range->low  == acki.ranges[i].low);
126767cf611SDmitri Tikhonov        }
127767cf611SDmitri Tikhonov    }
128767cf611SDmitri Tikhonov
129767cf611SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
130767cf611SDmitri Tikhonov}
131767cf611SDmitri Tikhonov
132767cf611SDmitri Tikhonov
133767cf611SDmitri Tikhonovint
134767cf611SDmitri Tikhonovmain (void)
135767cf611SDmitri Tikhonov{
136767cf611SDmitri Tikhonov    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
137767cf611SDmitri Tikhonov    test_max_ack();
138767cf611SDmitri Tikhonov    test_ack_truncation();
139767cf611SDmitri Tikhonov    return 0;
140767cf611SDmitri Tikhonov}
141