1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov#include <assert.h>
350aadb33SDmitri Tikhonov#include <stdio.h>
450aadb33SDmitri Tikhonov#include <stdlib.h>
550aadb33SDmitri Tikhonov#include <string.h>
6b62ec17fSDmitri Tikhonov#include <sys/queue.h>
7461e84d8SAmol Deshpande#ifndef WIN32
850aadb33SDmitri Tikhonov#include <sys/time.h>
9fb3e20e0SDmitri Tikhonov#else
10fb3e20e0SDmitri Tikhonov#include "vc_compat.h"
11461e84d8SAmol Deshpande#endif
1250aadb33SDmitri Tikhonov
1350aadb33SDmitri Tikhonov#include "lsquic_types.h"
1450aadb33SDmitri Tikhonov#include "lsquic_parse.h"
1550aadb33SDmitri Tikhonov#include "lsquic_rechist.h"
1650aadb33SDmitri Tikhonov#include "lsquic_util.h"
1750aadb33SDmitri Tikhonov#include "lsquic.h"
185392f7a3SLiteSpeed Tech#include "lsquic_hash.h"
195392f7a3SLiteSpeed Tech#include "lsquic_conn.h"
205392f7a3SLiteSpeed Tech
215392f7a3SLiteSpeed Techstatic struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0);
2250aadb33SDmitri Tikhonov
23f07b3eaeSTyler Young//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043); // will not work on MSVC
24f07b3eaeSTyler Young#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_043))
2550aadb33SDmitri Tikhonov
2650aadb33SDmitri Tikhonov
2750aadb33SDmitri Tikhonovstatic lsquic_packno_t
285392f7a3SLiteSpeed Techn_acked (const struct ack_info *acki)
2950aadb33SDmitri Tikhonov{
3050aadb33SDmitri Tikhonov    lsquic_packno_t n = 0;
3150aadb33SDmitri Tikhonov    unsigned i;
3250aadb33SDmitri Tikhonov    for (i = 0; i < acki->n_ranges; ++i)
3350aadb33SDmitri Tikhonov        n += acki->ranges[i].high - acki->ranges[i].low + 1;
3450aadb33SDmitri Tikhonov    return n;
3550aadb33SDmitri Tikhonov}
3650aadb33SDmitri Tikhonov
3750aadb33SDmitri Tikhonov
3850aadb33SDmitri Tikhonovstatic void
3950aadb33SDmitri Tikhonovtest1 (void)
4050aadb33SDmitri Tikhonov{
4150aadb33SDmitri Tikhonov    /* Test taken from quic_framer_test.cc -- NewAckFrameOneAckBlock */
4250aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
4350aadb33SDmitri Tikhonov        0x45,
4450aadb33SDmitri Tikhonov        0x12, 0x34,             /* Largest acked */
4550aadb33SDmitri Tikhonov        0x00, 0x00,             /* Delta time */
4650aadb33SDmitri Tikhonov        0x12, 0x34,             /* Block length */
4750aadb33SDmitri Tikhonov        0x00,                   /* Number of timestamps */
4850aadb33SDmitri Tikhonov    };
4950aadb33SDmitri Tikhonov
505392f7a3SLiteSpeed Tech    struct ack_info acki;
5150aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
5250aadb33SDmitri Tikhonov
535392f7a3SLiteSpeed Tech    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki, 0);
5450aadb33SDmitri Tikhonov    assert(("Parsed length is correct (8)", len == sizeof(ack_buf)));
5550aadb33SDmitri Tikhonov    assert(("Number of ranges is 1", acki.n_ranges == 1));
5650aadb33SDmitri Tikhonov    assert(("Largest acked is 0x1234", acki.ranges[0].high == 0x1234));
5750aadb33SDmitri Tikhonov    assert(("Lowest acked is 1", acki.ranges[0].low == 1));
5850aadb33SDmitri Tikhonov    unsigned n = n_acked(&acki);
5950aadb33SDmitri Tikhonov    assert(("Number of acked packets is 0x1234", n == 0x1234));
6050aadb33SDmitri Tikhonov
6150aadb33SDmitri Tikhonov    {
6250aadb33SDmitri Tikhonov        size_t sz;
6350aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
6450aadb33SDmitri Tikhonov        {
655392f7a3SLiteSpeed Tech            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki, 0);
6650aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
6750aadb33SDmitri Tikhonov        }
6850aadb33SDmitri Tikhonov    }
6950aadb33SDmitri Tikhonov}
7050aadb33SDmitri Tikhonov
7150aadb33SDmitri Tikhonov
7250aadb33SDmitri Tikhonovstatic void
7350aadb33SDmitri Tikhonovtest2 (void)
7450aadb33SDmitri Tikhonov{
7550aadb33SDmitri Tikhonov    /* Test taken from quic_framer_test.cc -- NewAckFrameOneAckBlock */
7650aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
7750aadb33SDmitri Tikhonov        0x65,
7850aadb33SDmitri Tikhonov        0x12, 0x34,                 /* Largest acked */
7950aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
8050aadb33SDmitri Tikhonov        0x04,                       /* Num ack blocks ranges. */
8150aadb33SDmitri Tikhonov        0x00, 0x01,                 /* First ack block length. */
8250aadb33SDmitri Tikhonov        0x01,                       /* Gap to next block. */
8350aadb33SDmitri Tikhonov        0x0e, 0xaf,                 /* Ack block length. */
8450aadb33SDmitri Tikhonov        0xff,                       /* Gap to next block. */
8550aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Ack block length. */
8650aadb33SDmitri Tikhonov        0x91,                       /* Gap to next block. */
8750aadb33SDmitri Tikhonov        0x01, 0xea,                 /* Ack block length. */
8850aadb33SDmitri Tikhonov        0x05,                       /* Gap to next block. */
8950aadb33SDmitri Tikhonov        0x00, 0x04,                 /* Ack block length. */
9050aadb33SDmitri Tikhonov        0x02,                       /* Number of timestamps. */
9150aadb33SDmitri Tikhonov        0x01,                       /* Delta from largest observed. */
9250aadb33SDmitri Tikhonov        0x10, 0x32, 0x54, 0x76,     /* Delta time. */   /* XXX do we use this at all? */
9350aadb33SDmitri Tikhonov        0x02,                       /* Delta from largest observed. */
9450aadb33SDmitri Tikhonov        0x10, 0x32,                 /* Delta time. */
9550aadb33SDmitri Tikhonov    };
9650aadb33SDmitri Tikhonov
9750aadb33SDmitri Tikhonov    /* We should get the following array of ranges:
9850aadb33SDmitri Tikhonov     *    high      low
9950aadb33SDmitri Tikhonov     *    0x1234    0x1234
10050aadb33SDmitri Tikhonov     *    0x1232    0x384
10150aadb33SDmitri Tikhonov     *    0x1F3     0xA
10250aadb33SDmitri Tikhonov     *    0x4       0x1
10350aadb33SDmitri Tikhonov     */
10450aadb33SDmitri Tikhonov    static const struct { unsigned high, low; } ranges[] = {
10550aadb33SDmitri Tikhonov        {   0x1234, 0x1234 },
10650aadb33SDmitri Tikhonov        {   0x1232, 0x384 },
10750aadb33SDmitri Tikhonov        {   0x1F3,  0xA },
10850aadb33SDmitri Tikhonov        {   0x4,    0x1 },
10950aadb33SDmitri Tikhonov    };
11050aadb33SDmitri Tikhonov
1115392f7a3SLiteSpeed Tech    struct ack_info acki;
11250aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
11350aadb33SDmitri Tikhonov
1145392f7a3SLiteSpeed Tech    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki, 0);
11550aadb33SDmitri Tikhonov    assert(("Parsed length is correct (29)", len == sizeof(ack_buf)));
11650aadb33SDmitri Tikhonov    assert(("Number of ranges is 4", acki.n_ranges == 4));
11750aadb33SDmitri Tikhonov    assert(("Largest acked is 0x1234", acki.ranges[0].high == 0x1234));
11850aadb33SDmitri Tikhonov    unsigned n = n_acked(&acki);
11950aadb33SDmitri Tikhonov    assert(("Number of acked packets is 4254", n == 4254));
12050aadb33SDmitri Tikhonov
12150aadb33SDmitri Tikhonov    for (n = 0; n < 4; ++n)
12250aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
12350aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
12450aadb33SDmitri Tikhonov
12550aadb33SDmitri Tikhonov    {
12650aadb33SDmitri Tikhonov        size_t sz;
12750aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
12850aadb33SDmitri Tikhonov        {
1295392f7a3SLiteSpeed Tech            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki, 0);
13050aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
13150aadb33SDmitri Tikhonov        }
13250aadb33SDmitri Tikhonov    }
13350aadb33SDmitri Tikhonov}
13450aadb33SDmitri Tikhonov
13550aadb33SDmitri Tikhonov
13650aadb33SDmitri Tikhonovstatic void
13750aadb33SDmitri Tikhonovtest3 (void)
13850aadb33SDmitri Tikhonov{
13950aadb33SDmitri Tikhonov    /* Generated by our own code, but failed to parse... */
14050aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
14150aadb33SDmitri Tikhonov        0x60,         /* More than one ack block, 1 byte largest observed, 1 byte block length */
14250aadb33SDmitri Tikhonov        0x06,         /* Largest ACKed */
14350aadb33SDmitri Tikhonov        0x00, 0x00,   /* Delta time */
14450aadb33SDmitri Tikhonov        0x01,         /* Num ACK block ranges */
14550aadb33SDmitri Tikhonov        0x01,         /* First ACK block length */
14650aadb33SDmitri Tikhonov        0x02,         /* Gap to next block */
14750aadb33SDmitri Tikhonov        0x03,         /* Ack block length */
14850aadb33SDmitri Tikhonov        0x00          /* Number of timestamps */
14950aadb33SDmitri Tikhonov    };
15050aadb33SDmitri Tikhonov
15150aadb33SDmitri Tikhonov    /* We should get the following array of ranges:
15250aadb33SDmitri Tikhonov     *    high      low
15350aadb33SDmitri Tikhonov     *    6         6
15450aadb33SDmitri Tikhonov     *    3         1
15550aadb33SDmitri Tikhonov     */
15650aadb33SDmitri Tikhonov    static const struct { unsigned high, low; } ranges[] = {
15750aadb33SDmitri Tikhonov        {   6,      6, },
15850aadb33SDmitri Tikhonov        {   3,      1, },
15950aadb33SDmitri Tikhonov    };
16050aadb33SDmitri Tikhonov
1615392f7a3SLiteSpeed Tech    struct ack_info acki;
16250aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
16350aadb33SDmitri Tikhonov
1645392f7a3SLiteSpeed Tech    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki, 0);
16550aadb33SDmitri Tikhonov    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
16650aadb33SDmitri Tikhonov    assert(("Number of ranges is 2", acki.n_ranges == 2));
16750aadb33SDmitri Tikhonov    assert(("Largest acked is 6", acki.ranges[0].high == 6));
16850aadb33SDmitri Tikhonov    unsigned n = n_acked(&acki);
16950aadb33SDmitri Tikhonov    assert(("Number of acked packets is 4", n == 4));
17050aadb33SDmitri Tikhonov
17150aadb33SDmitri Tikhonov    for (n = 0; n < 2; ++n)
17250aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
17350aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
17450aadb33SDmitri Tikhonov
17550aadb33SDmitri Tikhonov    {
17650aadb33SDmitri Tikhonov        size_t sz;
17750aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
17850aadb33SDmitri Tikhonov        {
1795392f7a3SLiteSpeed Tech            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki, 0);
18050aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
18150aadb33SDmitri Tikhonov        }
18250aadb33SDmitri Tikhonov    }
18350aadb33SDmitri Tikhonov}
18450aadb33SDmitri Tikhonov
18550aadb33SDmitri Tikhonov
18650aadb33SDmitri Tikhonovstatic void
18750aadb33SDmitri Tikhonovtest4 (void)
18850aadb33SDmitri Tikhonov{
18950aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
19050aadb33SDmitri Tikhonov        0x60,       /* More than one ack block, 1 byte largest observed, 1 byte block length */
19150aadb33SDmitri Tikhonov        0x03,       /* Largest ACKed */
19250aadb33SDmitri Tikhonov        0x23, 0x00, /* Delta time */
19350aadb33SDmitri Tikhonov        0x01,       /* Num ACK block ranges */
19450aadb33SDmitri Tikhonov        0x01,       /* First ack block length */
19550aadb33SDmitri Tikhonov        0x01,       /* Gap */
19650aadb33SDmitri Tikhonov        0x01,       /* Ack block length */
19750aadb33SDmitri Tikhonov        0x00,       /* Number of timestamps */
19850aadb33SDmitri Tikhonov    };
19950aadb33SDmitri Tikhonov
20050aadb33SDmitri Tikhonov    /* We should get the following array of ranges:
20150aadb33SDmitri Tikhonov     *    high      low
20250aadb33SDmitri Tikhonov     *    6         6
20350aadb33SDmitri Tikhonov     *    3         1
20450aadb33SDmitri Tikhonov     */
20550aadb33SDmitri Tikhonov    static const struct { unsigned high, low; } ranges[] = {
20650aadb33SDmitri Tikhonov        {   3,      3, },
20750aadb33SDmitri Tikhonov        {   1,      1, },
20850aadb33SDmitri Tikhonov    };
20950aadb33SDmitri Tikhonov
2105392f7a3SLiteSpeed Tech    struct ack_info acki;
21150aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
21250aadb33SDmitri Tikhonov
2135392f7a3SLiteSpeed Tech    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki, 0);
21450aadb33SDmitri Tikhonov    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
21550aadb33SDmitri Tikhonov    assert(("Number of ranges is 2", acki.n_ranges == 2));
21650aadb33SDmitri Tikhonov    assert(("Largest acked is 3", acki.ranges[0].high == 3));
21750aadb33SDmitri Tikhonov    unsigned n = n_acked(&acki);
21850aadb33SDmitri Tikhonov    assert(("Number of acked packets is 2", n == 2));
21950aadb33SDmitri Tikhonov
22050aadb33SDmitri Tikhonov    for (n = 0; n < 2; ++n)
22150aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
22250aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
22350aadb33SDmitri Tikhonov
22450aadb33SDmitri Tikhonov    {
22550aadb33SDmitri Tikhonov        size_t sz;
22650aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
22750aadb33SDmitri Tikhonov        {
2285392f7a3SLiteSpeed Tech            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki, 0);
22950aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
23050aadb33SDmitri Tikhonov        }
23150aadb33SDmitri Tikhonov    }
23250aadb33SDmitri Tikhonov}
23350aadb33SDmitri Tikhonov
23450aadb33SDmitri Tikhonov
23550aadb33SDmitri Tikhonov/* Four-byte packet numbers */
23650aadb33SDmitri Tikhonovstatic void
23750aadb33SDmitri Tikhonovtest5 (void)
23850aadb33SDmitri Tikhonov{
23950aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
24050aadb33SDmitri Tikhonov        0x60
24150aadb33SDmitri Tikhonov            | (2 << 2)  /* Four-byte largest acked */
24250aadb33SDmitri Tikhonov            | (2 << 0)  /* Four-byte ACK block length */
24350aadb33SDmitri Tikhonov        ,
24450aadb33SDmitri Tikhonov        0x23, 0x45, 0x67, 0x89,
24550aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
24650aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
24750aadb33SDmitri Tikhonov        0x00, 0x00, 0x00, 0x01,     /* First ack block length. */
24850aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
24950aadb33SDmitri Tikhonov        0x23, 0x45, 0x67, 0x68,     /* Ack block length. */
25050aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
25150aadb33SDmitri Tikhonov    };
25250aadb33SDmitri Tikhonov
25350aadb33SDmitri Tikhonov    /* We should get the following array of ranges:
25450aadb33SDmitri Tikhonov     *    high      low
25550aadb33SDmitri Tikhonov     *    6         6
25650aadb33SDmitri Tikhonov     *    3         1
25750aadb33SDmitri Tikhonov     */
25850aadb33SDmitri Tikhonov    static const struct { unsigned high, low; } ranges[] = {
25950aadb33SDmitri Tikhonov        {   0x23456789,      0x23456789, },
26050aadb33SDmitri Tikhonov        {   0x23456768,      1, },
26150aadb33SDmitri Tikhonov    };
26250aadb33SDmitri Tikhonov
2635392f7a3SLiteSpeed Tech    struct ack_info acki;
26450aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
26550aadb33SDmitri Tikhonov
2665392f7a3SLiteSpeed Tech    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki, 0);
26750aadb33SDmitri Tikhonov    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
26850aadb33SDmitri Tikhonov    assert(("Number of ranges is 2", acki.n_ranges == 2));
26950aadb33SDmitri Tikhonov    assert(("Largest acked is 0x23456789", acki.ranges[0].high == 0x23456789));
27050aadb33SDmitri Tikhonov    lsquic_packno_t n = n_acked(&acki);
27150aadb33SDmitri Tikhonov    assert(("Number of acked packets is correct", n == 0x23456768 + 1));
27250aadb33SDmitri Tikhonov
27350aadb33SDmitri Tikhonov    for (n = 0; n < 2; ++n)
27450aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
27550aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
27650aadb33SDmitri Tikhonov
27750aadb33SDmitri Tikhonov    {
27850aadb33SDmitri Tikhonov        size_t sz;
27950aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
28050aadb33SDmitri Tikhonov        {
2815392f7a3SLiteSpeed Tech            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki, 0);
28250aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
28350aadb33SDmitri Tikhonov        }
28450aadb33SDmitri Tikhonov    }
28550aadb33SDmitri Tikhonov}
28650aadb33SDmitri Tikhonov
28750aadb33SDmitri Tikhonov
28850aadb33SDmitri Tikhonov/* Six-byte packet numbers */
28950aadb33SDmitri Tikhonovstatic void
29050aadb33SDmitri Tikhonovtest6 (void)
29150aadb33SDmitri Tikhonov{
29250aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
29350aadb33SDmitri Tikhonov        0x60
29450aadb33SDmitri Tikhonov            | (3 << 2)  /* Six-byte largest acked */
29550aadb33SDmitri Tikhonov            | (3 << 0)  /* Six-byte ACK block length */
29650aadb33SDmitri Tikhonov        ,
29750aadb33SDmitri Tikhonov        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x89,
29850aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
29950aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
30050aadb33SDmitri Tikhonov        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* First ack block length. */
30150aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
30250aadb33SDmitri Tikhonov        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x68, /* Ack block length. */
30350aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
30450aadb33SDmitri Tikhonov    };
30550aadb33SDmitri Tikhonov
30650aadb33SDmitri Tikhonov    static const struct { lsquic_packno_t high, low; } ranges[] = {
30750aadb33SDmitri Tikhonov        {   0xABCD23456789,      0xABCD23456789, },
30850aadb33SDmitri Tikhonov        {   0xABCD23456768,      1, },
30950aadb33SDmitri Tikhonov    };
31050aadb33SDmitri Tikhonov
3115392f7a3SLiteSpeed Tech    struct ack_info acki;
31250aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
31350aadb33SDmitri Tikhonov
3145392f7a3SLiteSpeed Tech    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki, 0);
31550aadb33SDmitri Tikhonov    assert(("Parsed length is correct", len == sizeof(ack_buf)));
31650aadb33SDmitri Tikhonov    assert(("Number of ranges is 2", acki.n_ranges == 2));
31750aadb33SDmitri Tikhonov    assert(("Largest acked is 0xABCD23456789", acki.ranges[0].high == 0xABCD23456789));
31850aadb33SDmitri Tikhonov    lsquic_packno_t n = n_acked(&acki);
31950aadb33SDmitri Tikhonov    assert(("Number of acked packets is correct", n == 0xABCD23456768 + 1));
32050aadb33SDmitri Tikhonov
32150aadb33SDmitri Tikhonov    for (n = 0; n < 2; ++n)
32250aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
32350aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
32450aadb33SDmitri Tikhonov
32550aadb33SDmitri Tikhonov    {
32650aadb33SDmitri Tikhonov        size_t sz;
32750aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
32850aadb33SDmitri Tikhonov        {
3295392f7a3SLiteSpeed Tech            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki, 0);
33050aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
33150aadb33SDmitri Tikhonov        }
33250aadb33SDmitri Tikhonov    }
33350aadb33SDmitri Tikhonov}
33450aadb33SDmitri Tikhonov
33550aadb33SDmitri Tikhonov
33650aadb33SDmitri Tikhonovstatic void
33750aadb33SDmitri Tikhonovtest_max_ack (void)
33850aadb33SDmitri Tikhonov{
33950aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
34050aadb33SDmitri Tikhonov    lsquic_time_t now;
34150aadb33SDmitri Tikhonov    unsigned i;
34250aadb33SDmitri Tikhonov    int has_missing, sz[2];
34350aadb33SDmitri Tikhonov    const struct lsquic_packno_range *range;
34450aadb33SDmitri Tikhonov    unsigned char buf[1500];
34550aadb33SDmitri Tikhonov    struct ack_info acki;
34650aadb33SDmitri Tikhonov
347f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
34850aadb33SDmitri Tikhonov    now = lsquic_time_now();
34950aadb33SDmitri Tikhonov
35050aadb33SDmitri Tikhonov    for (i = 1; i <= 300; ++i)
35150aadb33SDmitri Tikhonov    {
35250aadb33SDmitri Tikhonov        lsquic_rechist_received(&rechist, i * 10, now);
35350aadb33SDmitri Tikhonov        now += i * 1000;
35450aadb33SDmitri Tikhonov    }
35550aadb33SDmitri Tikhonov
35650aadb33SDmitri Tikhonov    memset(buf, 0xAA, sizeof(buf));
35750aadb33SDmitri Tikhonov
35816a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
35950aadb33SDmitri Tikhonov    sz[0] = pf->pf_gen_ack_frame(buf, sizeof(buf),
36050aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
36150aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
36250aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
3635392f7a3SLiteSpeed Tech        &rechist, now, &has_missing, &largest, NULL);
36450aadb33SDmitri Tikhonov    assert(sz[0] > 0);
36550aadb33SDmitri Tikhonov    assert(sz[0] <= (int) sizeof(buf));
36650aadb33SDmitri Tikhonov    assert(has_missing);
36750aadb33SDmitri Tikhonov
36850aadb33SDmitri Tikhonov    assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
36950aadb33SDmitri Tikhonov    assert(0xAA == buf[ sz[0] ]);
37050aadb33SDmitri Tikhonov
3715392f7a3SLiteSpeed Tech    sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
37250aadb33SDmitri Tikhonov    assert(sz[1] == sz[0]);
37350aadb33SDmitri Tikhonov    assert(256 == acki.n_ranges);
37450aadb33SDmitri Tikhonov
37550aadb33SDmitri Tikhonov    for (range = lsquic_rechist_first(&rechist), i = 0;
37650aadb33SDmitri Tikhonov                        range && i < acki.n_ranges;
37750aadb33SDmitri Tikhonov                                    range = lsquic_rechist_next(&rechist), ++i)
37850aadb33SDmitri Tikhonov    {
37950aadb33SDmitri Tikhonov        assert(range->high == acki.ranges[i].high);
38050aadb33SDmitri Tikhonov        assert(range->low  == acki.ranges[i].low);
38150aadb33SDmitri Tikhonov    }
38250aadb33SDmitri Tikhonov    assert(i == 256);
38350aadb33SDmitri Tikhonov
38450aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
38550aadb33SDmitri Tikhonov}
38650aadb33SDmitri Tikhonov
38750aadb33SDmitri Tikhonov
38850aadb33SDmitri Tikhonovstatic void
38950aadb33SDmitri Tikhonovtest_ack_truncation (void)
39050aadb33SDmitri Tikhonov{
39150aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
39250aadb33SDmitri Tikhonov    lsquic_time_t now;
39350aadb33SDmitri Tikhonov    unsigned i;
39450aadb33SDmitri Tikhonov    int has_missing, sz[2];
39550aadb33SDmitri Tikhonov    const struct lsquic_packno_range *range;
39650aadb33SDmitri Tikhonov    unsigned char buf[1500];
39750aadb33SDmitri Tikhonov    struct ack_info acki;
39850aadb33SDmitri Tikhonov    size_t bufsz;
39950aadb33SDmitri Tikhonov
400f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
40150aadb33SDmitri Tikhonov    now = lsquic_time_now();
40250aadb33SDmitri Tikhonov
40350aadb33SDmitri Tikhonov    for (i = 1; i <= 300; ++i)
40450aadb33SDmitri Tikhonov    {
40550aadb33SDmitri Tikhonov        lsquic_rechist_received(&rechist, i * 10, now);
40650aadb33SDmitri Tikhonov        now += i * 1000;
40750aadb33SDmitri Tikhonov    }
40850aadb33SDmitri Tikhonov
40950aadb33SDmitri Tikhonov    for (bufsz = 200; bufsz < 210; ++bufsz)
41050aadb33SDmitri Tikhonov    {
41150aadb33SDmitri Tikhonov        memset(buf, 0xAA, sizeof(buf));
41216a9b66aSDmitri Tikhonov        lsquic_packno_t largest = 0;
41350aadb33SDmitri Tikhonov        sz[0] = pf->pf_gen_ack_frame(buf, bufsz,
41450aadb33SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
41550aadb33SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
41650aadb33SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
4175392f7a3SLiteSpeed Tech            &rechist, now, &has_missing, &largest, NULL);
41850aadb33SDmitri Tikhonov        assert(sz[0] > 0);
41950aadb33SDmitri Tikhonov        assert(sz[0] <= (int) bufsz);
42050aadb33SDmitri Tikhonov        assert(has_missing);
42150aadb33SDmitri Tikhonov
42250aadb33SDmitri Tikhonov        assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
42350aadb33SDmitri Tikhonov        assert(0xAA == buf[ sz[0] ]);
42450aadb33SDmitri Tikhonov
4255392f7a3SLiteSpeed Tech        sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
42650aadb33SDmitri Tikhonov        assert(sz[1] == sz[0]);
42750aadb33SDmitri Tikhonov        assert(acki.n_ranges < 256);
42850aadb33SDmitri Tikhonov
42950aadb33SDmitri Tikhonov        for (range = lsquic_rechist_first(&rechist), i = 0;
43050aadb33SDmitri Tikhonov                            range && i < acki.n_ranges;
43150aadb33SDmitri Tikhonov                                        range = lsquic_rechist_next(&rechist), ++i)
43250aadb33SDmitri Tikhonov        {
43350aadb33SDmitri Tikhonov            assert(range->high == acki.ranges[i].high);
43450aadb33SDmitri Tikhonov            assert(range->low  == acki.ranges[i].low);
43550aadb33SDmitri Tikhonov        }
43650aadb33SDmitri Tikhonov    }
43750aadb33SDmitri Tikhonov
43850aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
43950aadb33SDmitri Tikhonov}
44050aadb33SDmitri Tikhonov
44150aadb33SDmitri Tikhonov
4425392f7a3SLiteSpeed Techstatic void
4435392f7a3SLiteSpeed Techtest_empty_ack (void)
4445392f7a3SLiteSpeed Tech{
4455392f7a3SLiteSpeed Tech    int len;
4465392f7a3SLiteSpeed Tech    unsigned char buf[] = { 0x40, 0x00, 0xFF, 0xFF, 0x00, 0x00,
4475392f7a3SLiteSpeed Tech                            /* fluff: */ 0x12, 0x23, 0x34, 0x45, };
4485392f7a3SLiteSpeed Tech    struct ack_info acki;
4495392f7a3SLiteSpeed Tech
4505392f7a3SLiteSpeed Tech    len = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
4515392f7a3SLiteSpeed Tech    assert(6 == len);
4525392f7a3SLiteSpeed Tech    assert(empty_ack_frame(&acki));
4535392f7a3SLiteSpeed Tech}
4545392f7a3SLiteSpeed Tech
4555392f7a3SLiteSpeed Tech
45650aadb33SDmitri Tikhonovint
45750aadb33SDmitri Tikhonovmain (void)
45850aadb33SDmitri Tikhonov{
459c51ce338SDmitri Tikhonov    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
46050aadb33SDmitri Tikhonov    test1();
46150aadb33SDmitri Tikhonov    test2();
46250aadb33SDmitri Tikhonov    test3();
46350aadb33SDmitri Tikhonov    test4();
46450aadb33SDmitri Tikhonov    test5();
46550aadb33SDmitri Tikhonov    test6();
46650aadb33SDmitri Tikhonov    test_max_ack();
46750aadb33SDmitri Tikhonov    test_ack_truncation();
4685392f7a3SLiteSpeed Tech    test_empty_ack();
46950aadb33SDmitri Tikhonov    return 0;
47050aadb33SDmitri Tikhonov}
471