1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 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>
6461e84d8SAmol Deshpande#ifndef WIN32
750aadb33SDmitri Tikhonov#include <sys/time.h>
8461e84d8SAmol Deshpande#endif
950aadb33SDmitri Tikhonov
1050aadb33SDmitri Tikhonov#include "lsquic_types.h"
1150aadb33SDmitri Tikhonov#include "lsquic_parse.h"
1250aadb33SDmitri Tikhonov#include "lsquic_rechist.h"
1350aadb33SDmitri Tikhonov#include "lsquic_util.h"
1450aadb33SDmitri Tikhonov#include "lsquic.h"
1550aadb33SDmitri Tikhonov
16052a1c28SDmitri Tikhonovstatic const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_035);
1750aadb33SDmitri Tikhonov
1850aadb33SDmitri Tikhonovstatic lsquic_packno_t
1950aadb33SDmitri Tikhonovn_acked (const ack_info_t *acki)
2050aadb33SDmitri Tikhonov{
2150aadb33SDmitri Tikhonov    lsquic_packno_t n = 0;
2250aadb33SDmitri Tikhonov    unsigned i;
2350aadb33SDmitri Tikhonov    for (i = 0; i < acki->n_ranges; ++i)
2450aadb33SDmitri Tikhonov        n += acki->ranges[i].high - acki->ranges[i].low + 1;
2550aadb33SDmitri Tikhonov    return n;
2650aadb33SDmitri Tikhonov}
2750aadb33SDmitri Tikhonov
2850aadb33SDmitri Tikhonov
2950aadb33SDmitri Tikhonovstatic void
3050aadb33SDmitri Tikhonovtest1 (void)
3150aadb33SDmitri Tikhonov{
3250aadb33SDmitri Tikhonov    /* Test taken from quic_framer_test.cc -- NewAckFrameOneAckBlock */
3350aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
3450aadb33SDmitri Tikhonov        0x45,
3550aadb33SDmitri Tikhonov        0x34, 0x12,             /* Largest acked */
3650aadb33SDmitri Tikhonov        0x00, 0x00,             /* Delta time */
3750aadb33SDmitri Tikhonov        0x34, 0x12,             /* Block length */
3850aadb33SDmitri Tikhonov        0x00,                   /* Number of timestamps */
3950aadb33SDmitri Tikhonov    };
4050aadb33SDmitri Tikhonov
4150aadb33SDmitri Tikhonov    ack_info_t acki;
4250aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
4350aadb33SDmitri Tikhonov
4450aadb33SDmitri Tikhonov    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
4550aadb33SDmitri Tikhonov    assert(("Parsed length is correct (8)", len == sizeof(ack_buf)));
4650aadb33SDmitri Tikhonov    assert(("Number of ranges is 1", acki.n_ranges == 1));
4750aadb33SDmitri Tikhonov    assert(("Largest acked is 0x1234", acki.ranges[0].high == 0x1234));
4850aadb33SDmitri Tikhonov    assert(("Lowest acked is 1", acki.ranges[0].low == 1));
4950aadb33SDmitri Tikhonov    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
5050aadb33SDmitri Tikhonov    unsigned n = n_acked(&acki);
5150aadb33SDmitri Tikhonov    assert(("Number of acked packets is 0x1234", n == 0x1234));
5250aadb33SDmitri Tikhonov
5350aadb33SDmitri Tikhonov    {
5450aadb33SDmitri Tikhonov        size_t sz;
5550aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
5650aadb33SDmitri Tikhonov        {
5750aadb33SDmitri Tikhonov            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
5850aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
5950aadb33SDmitri Tikhonov        }
6050aadb33SDmitri Tikhonov    }
6150aadb33SDmitri Tikhonov}
6250aadb33SDmitri Tikhonov
6350aadb33SDmitri Tikhonov
6450aadb33SDmitri Tikhonovstatic void
6550aadb33SDmitri Tikhonovtest2 (void)
6650aadb33SDmitri Tikhonov{
6750aadb33SDmitri Tikhonov    /* Test taken from quic_framer_test.cc -- NewAckFrameOneAckBlock */
6850aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
6950aadb33SDmitri Tikhonov        0x65,
7050aadb33SDmitri Tikhonov        0x34, 0x12,                 /* Largest acked */
7150aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
7250aadb33SDmitri Tikhonov        0x04,                       /* Num ack blocks ranges. */
7350aadb33SDmitri Tikhonov        0x01, 0x00,                 /* First ack block length. */
7450aadb33SDmitri Tikhonov        0x01,                       /* Gap to next block. */
7550aadb33SDmitri Tikhonov        0xaf, 0x0e,                 /* Ack block length. */
7650aadb33SDmitri Tikhonov        0xff,                       /* Gap to next block. */
7750aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Ack block length. */
7850aadb33SDmitri Tikhonov        0x91,                       /* Gap to next block. */
7950aadb33SDmitri Tikhonov        0xea, 0x01,                 /* Ack block length. */
8050aadb33SDmitri Tikhonov        0x05,                       /* Gap to next block. */
8150aadb33SDmitri Tikhonov        0x04, 0x00,                 /* Ack block length. */
8250aadb33SDmitri Tikhonov        0x02,                       /* Number of timestamps. */
8350aadb33SDmitri Tikhonov        0x01,                       /* Delta from largest observed. */
8450aadb33SDmitri Tikhonov        0x10, 0x32, 0x54, 0x76,     /* Delta time. */
8550aadb33SDmitri Tikhonov        0x02,                       /* Delta from largest observed. */
8650aadb33SDmitri Tikhonov        0x10, 0x32,                 /* Delta time. */
8750aadb33SDmitri Tikhonov    };
8850aadb33SDmitri Tikhonov
8950aadb33SDmitri Tikhonov    /* We should get the following array of ranges:
9050aadb33SDmitri Tikhonov     *    high      low
9150aadb33SDmitri Tikhonov     *    0x1234    0x1234
9250aadb33SDmitri Tikhonov     *    0x1232    0x384
9350aadb33SDmitri Tikhonov     *    0x1F3     0xA
9450aadb33SDmitri Tikhonov     *    0x4       0x1
9550aadb33SDmitri Tikhonov     */
9650aadb33SDmitri Tikhonov    static const struct { unsigned high, low; } ranges[] = {
9750aadb33SDmitri Tikhonov        {   0x1234, 0x1234 },
9850aadb33SDmitri Tikhonov        {   0x1232, 0x384 },
9950aadb33SDmitri Tikhonov        {   0x1F3,  0xA },
10050aadb33SDmitri Tikhonov        {   0x4,    0x1 },
10150aadb33SDmitri Tikhonov    };
10250aadb33SDmitri Tikhonov
10350aadb33SDmitri Tikhonov    ack_info_t acki;
10450aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
10550aadb33SDmitri Tikhonov
10650aadb33SDmitri Tikhonov    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
10750aadb33SDmitri Tikhonov    assert(("Parsed length is correct (29)", len == sizeof(ack_buf)));
10850aadb33SDmitri Tikhonov    assert(("Number of ranges is 4", acki.n_ranges == 4));
10950aadb33SDmitri Tikhonov    assert(("Largest acked is 0x1234", acki.ranges[0].high == 0x1234));
11050aadb33SDmitri Tikhonov    assert(("Number of timestamps is 2", acki.n_timestamps == 2));
11150aadb33SDmitri Tikhonov    unsigned n = n_acked(&acki);
11250aadb33SDmitri Tikhonov    assert(("Number of acked packets is 4254", n == 4254));
11350aadb33SDmitri Tikhonov
11450aadb33SDmitri Tikhonov    for (n = 0; n < 4; ++n)
11550aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
11650aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
11750aadb33SDmitri Tikhonov
11850aadb33SDmitri Tikhonov    {
11950aadb33SDmitri Tikhonov        size_t sz;
12050aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
12150aadb33SDmitri Tikhonov        {
12250aadb33SDmitri Tikhonov            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
12350aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
12450aadb33SDmitri Tikhonov        }
12550aadb33SDmitri Tikhonov    }
12650aadb33SDmitri Tikhonov}
12750aadb33SDmitri Tikhonov
12850aadb33SDmitri Tikhonov
12950aadb33SDmitri Tikhonovstatic void
13050aadb33SDmitri Tikhonovtest3 (void)
13150aadb33SDmitri Tikhonov{
13250aadb33SDmitri Tikhonov    /* Generated by our own code, but failed to parse... */
13350aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
13450aadb33SDmitri Tikhonov        0x60,         /* More than one ack block, 1 byte largest observed, 1 byte block length */
13550aadb33SDmitri Tikhonov        0x06,         /* Largest ACKed */
13650aadb33SDmitri Tikhonov        0x00, 0x00,   /* Delta time */
13750aadb33SDmitri Tikhonov        0x01,         /* Num ACK block ranges */
13850aadb33SDmitri Tikhonov        0x01,         /* First ACK block length */
13950aadb33SDmitri Tikhonov        0x02,         /* Gap to next block */
14050aadb33SDmitri Tikhonov        0x03,         /* Ack block length */
14150aadb33SDmitri Tikhonov        0x00          /* Number of timestamps */
14250aadb33SDmitri Tikhonov    };
14350aadb33SDmitri Tikhonov
14450aadb33SDmitri Tikhonov    /* We should get the following array of ranges:
14550aadb33SDmitri Tikhonov     *    high      low
14650aadb33SDmitri Tikhonov     *    6         6
14750aadb33SDmitri Tikhonov     *    3         1
14850aadb33SDmitri Tikhonov     */
14950aadb33SDmitri Tikhonov    static const struct { unsigned high, low; } ranges[] = {
15050aadb33SDmitri Tikhonov        {   6,      6, },
15150aadb33SDmitri Tikhonov        {   3,      1, },
15250aadb33SDmitri Tikhonov    };
15350aadb33SDmitri Tikhonov
15450aadb33SDmitri Tikhonov    ack_info_t acki;
15550aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
15650aadb33SDmitri Tikhonov
15750aadb33SDmitri Tikhonov    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
15850aadb33SDmitri Tikhonov    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
15950aadb33SDmitri Tikhonov    assert(("Number of ranges is 2", acki.n_ranges == 2));
16050aadb33SDmitri Tikhonov    assert(("Largest acked is 6", acki.ranges[0].high == 6));
16150aadb33SDmitri Tikhonov    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
16250aadb33SDmitri Tikhonov    unsigned n = n_acked(&acki);
16350aadb33SDmitri Tikhonov    assert(("Number of acked packets is 4", n == 4));
16450aadb33SDmitri Tikhonov
16550aadb33SDmitri Tikhonov    for (n = 0; n < 2; ++n)
16650aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
16750aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
16850aadb33SDmitri Tikhonov
16950aadb33SDmitri Tikhonov    {
17050aadb33SDmitri Tikhonov        size_t sz;
17150aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
17250aadb33SDmitri Tikhonov        {
17350aadb33SDmitri Tikhonov            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
17450aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
17550aadb33SDmitri Tikhonov        }
17650aadb33SDmitri Tikhonov    }
17750aadb33SDmitri Tikhonov}
17850aadb33SDmitri Tikhonov
17950aadb33SDmitri Tikhonov
18050aadb33SDmitri Tikhonovstatic void
18150aadb33SDmitri Tikhonovtest4 (void)
18250aadb33SDmitri Tikhonov{
18350aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
18450aadb33SDmitri Tikhonov        0x60,       /* More than one ack block, 1 byte largest observed, 1 byte block length */
18550aadb33SDmitri Tikhonov        0x03,       /* Largest ACKed */
18650aadb33SDmitri Tikhonov        0x23, 0x00, /* Delta time */
18750aadb33SDmitri Tikhonov        0x01,       /* Num ACK block ranges */
18850aadb33SDmitri Tikhonov        0x01,       /* First ack block length */
18950aadb33SDmitri Tikhonov        0x01,       /* Gap */
19050aadb33SDmitri Tikhonov        0x01,       /* Ack block length */
19150aadb33SDmitri Tikhonov        0x00,       /* Number of timestamps */
19250aadb33SDmitri Tikhonov    };
19350aadb33SDmitri Tikhonov
19450aadb33SDmitri Tikhonov    /* We should get the following array of ranges:
19550aadb33SDmitri Tikhonov     *    high      low
19650aadb33SDmitri Tikhonov     *    6         6
19750aadb33SDmitri Tikhonov     *    3         1
19850aadb33SDmitri Tikhonov     */
19950aadb33SDmitri Tikhonov    static const struct { unsigned high, low; } ranges[] = {
20050aadb33SDmitri Tikhonov        {   3,      3, },
20150aadb33SDmitri Tikhonov        {   1,      1, },
20250aadb33SDmitri Tikhonov    };
20350aadb33SDmitri Tikhonov
20450aadb33SDmitri Tikhonov    ack_info_t acki;
20550aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
20650aadb33SDmitri Tikhonov
20750aadb33SDmitri Tikhonov    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
20850aadb33SDmitri Tikhonov    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
20950aadb33SDmitri Tikhonov    assert(("Number of ranges is 2", acki.n_ranges == 2));
21050aadb33SDmitri Tikhonov    assert(("Largest acked is 3", acki.ranges[0].high == 3));
21150aadb33SDmitri Tikhonov    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
21250aadb33SDmitri Tikhonov    unsigned n = n_acked(&acki);
21350aadb33SDmitri Tikhonov    assert(("Number of acked packets is 2", n == 2));
21450aadb33SDmitri Tikhonov
21550aadb33SDmitri Tikhonov    for (n = 0; n < 2; ++n)
21650aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
21750aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
21850aadb33SDmitri Tikhonov
21950aadb33SDmitri Tikhonov    {
22050aadb33SDmitri Tikhonov        size_t sz;
22150aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
22250aadb33SDmitri Tikhonov        {
22350aadb33SDmitri Tikhonov            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
22450aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
22550aadb33SDmitri Tikhonov        }
22650aadb33SDmitri Tikhonov    }
22750aadb33SDmitri Tikhonov}
22850aadb33SDmitri Tikhonov
22950aadb33SDmitri Tikhonov
23050aadb33SDmitri Tikhonov/* Four-byte packet numbers */
23150aadb33SDmitri Tikhonovstatic void
23250aadb33SDmitri Tikhonovtest5 (void)
23350aadb33SDmitri Tikhonov{
23450aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
23550aadb33SDmitri Tikhonov        0x60
23650aadb33SDmitri Tikhonov            | (2 << 2)  /* Four-byte largest acked */
23750aadb33SDmitri Tikhonov            | (2 << 0)  /* Four-byte ACK block length */
23850aadb33SDmitri Tikhonov        ,
23950aadb33SDmitri Tikhonov        0x89, 0x67, 0x45, 0x23,
24050aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
24150aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
24250aadb33SDmitri Tikhonov        0x01, 0x00, 0x00, 0x00,     /* First ack block length. */
24350aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
24450aadb33SDmitri Tikhonov        0x68, 0x67, 0x45, 0x23,     /* Ack block length. */
24550aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
24650aadb33SDmitri Tikhonov    };
24750aadb33SDmitri Tikhonov
24850aadb33SDmitri Tikhonov    /* We should get the following array of ranges:
24950aadb33SDmitri Tikhonov     *    high      low
25050aadb33SDmitri Tikhonov     *    6         6
25150aadb33SDmitri Tikhonov     *    3         1
25250aadb33SDmitri Tikhonov     */
25350aadb33SDmitri Tikhonov    static const struct { unsigned high, low; } ranges[] = {
25450aadb33SDmitri Tikhonov        {   0x23456789,      0x23456789, },
25550aadb33SDmitri Tikhonov        {   0x23456768,      1, },
25650aadb33SDmitri Tikhonov    };
25750aadb33SDmitri Tikhonov
25850aadb33SDmitri Tikhonov    ack_info_t acki;
25950aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
26050aadb33SDmitri Tikhonov
26150aadb33SDmitri Tikhonov    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
26250aadb33SDmitri Tikhonov    assert(("Parsed length is correct (9)", len == sizeof(ack_buf)));
26350aadb33SDmitri Tikhonov    assert(("Number of ranges is 2", acki.n_ranges == 2));
26450aadb33SDmitri Tikhonov    assert(("Largest acked is 0x23456789", acki.ranges[0].high == 0x23456789));
26550aadb33SDmitri Tikhonov    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
26650aadb33SDmitri Tikhonov    lsquic_packno_t n = n_acked(&acki);
26750aadb33SDmitri Tikhonov    assert(("Number of acked packets is correct", n == 0x23456768 + 1));
26850aadb33SDmitri Tikhonov
26950aadb33SDmitri Tikhonov    for (n = 0; n < 2; ++n)
27050aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
27150aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
27250aadb33SDmitri Tikhonov
27350aadb33SDmitri Tikhonov    {
27450aadb33SDmitri Tikhonov        size_t sz;
27550aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
27650aadb33SDmitri Tikhonov        {
27750aadb33SDmitri Tikhonov            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
27850aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
27950aadb33SDmitri Tikhonov        }
28050aadb33SDmitri Tikhonov    }
28150aadb33SDmitri Tikhonov}
28250aadb33SDmitri Tikhonov
28350aadb33SDmitri Tikhonov
28450aadb33SDmitri Tikhonov/* Six-byte packet numbers */
28550aadb33SDmitri Tikhonovstatic void
28650aadb33SDmitri Tikhonovtest6 (void)
28750aadb33SDmitri Tikhonov{
28850aadb33SDmitri Tikhonov    unsigned char ack_buf[] = {
28950aadb33SDmitri Tikhonov        0x60
29050aadb33SDmitri Tikhonov            | (3 << 2)  /* Six-byte largest acked */
29150aadb33SDmitri Tikhonov            | (3 << 0)  /* Six-byte ACK block length */
29250aadb33SDmitri Tikhonov        ,
29350aadb33SDmitri Tikhonov        0x89, 0x67, 0x45, 0x23, 0xCD, 0xAB,
29450aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
29550aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
29650aadb33SDmitri Tikhonov        0x01, 0x00, 0x00, 0x00, 0x00, 0x00,    /* First ack block length. */
29750aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
29850aadb33SDmitri Tikhonov        0x68, 0x67, 0x45, 0x23, 0xCD, 0xAB,   /* Ack block length. */
29950aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
30050aadb33SDmitri Tikhonov    };
30150aadb33SDmitri Tikhonov
30250aadb33SDmitri Tikhonov    static const struct { lsquic_packno_t high, low; } ranges[] = {
30350aadb33SDmitri Tikhonov        {   0xABCD23456789,      0xABCD23456789, },
30450aadb33SDmitri Tikhonov        {   0xABCD23456768,      1, },
30550aadb33SDmitri Tikhonov    };
30650aadb33SDmitri Tikhonov
30750aadb33SDmitri Tikhonov    ack_info_t acki;
30850aadb33SDmitri Tikhonov    memset(&acki, 0xF1, sizeof(acki));
30950aadb33SDmitri Tikhonov
31050aadb33SDmitri Tikhonov    int len = pf->pf_parse_ack_frame(ack_buf, sizeof(ack_buf), &acki);
31150aadb33SDmitri Tikhonov    assert(("Parsed length is correct", len == sizeof(ack_buf)));
31250aadb33SDmitri Tikhonov    assert(("Number of ranges is 2", acki.n_ranges == 2));
31350aadb33SDmitri Tikhonov    assert(("Largest acked is 0xABCD23456789", acki.ranges[0].high == 0xABCD23456789));
31450aadb33SDmitri Tikhonov    assert(("Number of timestamps is 0", acki.n_timestamps == 0));
31550aadb33SDmitri Tikhonov    lsquic_packno_t n = n_acked(&acki);
31650aadb33SDmitri Tikhonov    assert(("Number of acked packets is correct", n == 0xABCD23456768 + 1));
31750aadb33SDmitri Tikhonov
31850aadb33SDmitri Tikhonov    for (n = 0; n < 2; ++n)
31950aadb33SDmitri Tikhonov        assert(("Range checks out", ranges[n].high == acki.ranges[n].high
32050aadb33SDmitri Tikhonov                                &&  ranges[n].low  == acki.ranges[n].low));
32150aadb33SDmitri Tikhonov
32250aadb33SDmitri Tikhonov    {
32350aadb33SDmitri Tikhonov        size_t sz;
32450aadb33SDmitri Tikhonov        for (sz = 1; sz < sizeof(ack_buf); ++sz)
32550aadb33SDmitri Tikhonov        {
32650aadb33SDmitri Tikhonov            len = pf->pf_parse_ack_frame(ack_buf, sz, &acki);
32750aadb33SDmitri Tikhonov            assert(("Parsing truncated frame failed", len < 0));
32850aadb33SDmitri Tikhonov        }
32950aadb33SDmitri Tikhonov    }
33050aadb33SDmitri Tikhonov}
33150aadb33SDmitri Tikhonov
33250aadb33SDmitri Tikhonov
33350aadb33SDmitri Tikhonovstatic void
33450aadb33SDmitri Tikhonovtest_max_ack (void)
33550aadb33SDmitri Tikhonov{
33650aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
33750aadb33SDmitri Tikhonov    lsquic_time_t now;
33850aadb33SDmitri Tikhonov    unsigned i;
33950aadb33SDmitri Tikhonov    int has_missing, sz[2];
34050aadb33SDmitri Tikhonov    const struct lsquic_packno_range *range;
34150aadb33SDmitri Tikhonov    unsigned char buf[1500];
34250aadb33SDmitri Tikhonov    struct ack_info acki;
34350aadb33SDmitri Tikhonov
34450aadb33SDmitri Tikhonov    lsquic_rechist_init(&rechist, 12345);
34550aadb33SDmitri Tikhonov    now = lsquic_time_now();
34650aadb33SDmitri Tikhonov
34750aadb33SDmitri Tikhonov    for (i = 1; i <= 300; ++i)
34850aadb33SDmitri Tikhonov    {
34950aadb33SDmitri Tikhonov        lsquic_rechist_received(&rechist, i * 10, now);
35050aadb33SDmitri Tikhonov        now += i * 1000;
35150aadb33SDmitri Tikhonov    }
35250aadb33SDmitri Tikhonov
35350aadb33SDmitri Tikhonov    memset(buf, 0xAA, sizeof(buf));
35450aadb33SDmitri Tikhonov
35516a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
35650aadb33SDmitri Tikhonov    sz[0] = pf->pf_gen_ack_frame(buf, sizeof(buf),
35750aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
35850aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
35950aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
36016a9b66aSDmitri Tikhonov        &rechist, now, &has_missing, &largest);
36150aadb33SDmitri Tikhonov    assert(sz[0] > 0);
36250aadb33SDmitri Tikhonov    assert(sz[0] <= (int) sizeof(buf));
36350aadb33SDmitri Tikhonov    assert(has_missing);
36450aadb33SDmitri Tikhonov
36550aadb33SDmitri Tikhonov    assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
36650aadb33SDmitri Tikhonov    assert(0xAA == buf[ sz[0] ]);
36750aadb33SDmitri Tikhonov
36850aadb33SDmitri Tikhonov    sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki);
36950aadb33SDmitri Tikhonov    assert(sz[1] == sz[0]);
37050aadb33SDmitri Tikhonov    assert(256 == acki.n_ranges);
37150aadb33SDmitri Tikhonov
37250aadb33SDmitri Tikhonov    for (range = lsquic_rechist_first(&rechist), i = 0;
37350aadb33SDmitri Tikhonov                        range && i < acki.n_ranges;
37450aadb33SDmitri Tikhonov                                    range = lsquic_rechist_next(&rechist), ++i)
37550aadb33SDmitri Tikhonov    {
37650aadb33SDmitri Tikhonov        assert(range->high == acki.ranges[i].high);
37750aadb33SDmitri Tikhonov        assert(range->low  == acki.ranges[i].low);
37850aadb33SDmitri Tikhonov    }
37950aadb33SDmitri Tikhonov    assert(i == 256);
38050aadb33SDmitri Tikhonov
38150aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
38250aadb33SDmitri Tikhonov}
38350aadb33SDmitri Tikhonov
38450aadb33SDmitri Tikhonov
38550aadb33SDmitri Tikhonovstatic void
38650aadb33SDmitri Tikhonovtest_ack_truncation (void)
38750aadb33SDmitri Tikhonov{
38850aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
38950aadb33SDmitri Tikhonov    lsquic_time_t now;
39050aadb33SDmitri Tikhonov    unsigned i;
39150aadb33SDmitri Tikhonov    int has_missing, sz[2];
39250aadb33SDmitri Tikhonov    const struct lsquic_packno_range *range;
39350aadb33SDmitri Tikhonov    unsigned char buf[1500];
39450aadb33SDmitri Tikhonov    struct ack_info acki;
39550aadb33SDmitri Tikhonov    size_t bufsz;
39650aadb33SDmitri Tikhonov
39750aadb33SDmitri Tikhonov    lsquic_rechist_init(&rechist, 12345);
39850aadb33SDmitri Tikhonov    now = lsquic_time_now();
39950aadb33SDmitri Tikhonov
40050aadb33SDmitri Tikhonov    for (i = 1; i <= 300; ++i)
40150aadb33SDmitri Tikhonov    {
40250aadb33SDmitri Tikhonov        lsquic_rechist_received(&rechist, i * 10, now);
40350aadb33SDmitri Tikhonov        now += i * 1000;
40450aadb33SDmitri Tikhonov    }
40550aadb33SDmitri Tikhonov
40650aadb33SDmitri Tikhonov    for (bufsz = 200; bufsz < 210; ++bufsz)
40750aadb33SDmitri Tikhonov    {
40850aadb33SDmitri Tikhonov        memset(buf, 0xAA, sizeof(buf));
40916a9b66aSDmitri Tikhonov        lsquic_packno_t largest = 0;
41050aadb33SDmitri Tikhonov        sz[0] = pf->pf_gen_ack_frame(buf, bufsz,
41150aadb33SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
41250aadb33SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
41350aadb33SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
41416a9b66aSDmitri Tikhonov            &rechist, now, &has_missing, &largest);
41550aadb33SDmitri Tikhonov        assert(sz[0] > 0);
41650aadb33SDmitri Tikhonov        assert(sz[0] <= (int) bufsz);
41750aadb33SDmitri Tikhonov        assert(has_missing);
41850aadb33SDmitri Tikhonov
41950aadb33SDmitri Tikhonov        assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
42050aadb33SDmitri Tikhonov        assert(0xAA == buf[ sz[0] ]);
42150aadb33SDmitri Tikhonov
42250aadb33SDmitri Tikhonov        sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki);
42350aadb33SDmitri Tikhonov        assert(sz[1] == sz[0]);
42450aadb33SDmitri Tikhonov        assert(acki.n_ranges < 256);
42550aadb33SDmitri Tikhonov
42650aadb33SDmitri Tikhonov        for (range = lsquic_rechist_first(&rechist), i = 0;
42750aadb33SDmitri Tikhonov                            range && i < acki.n_ranges;
42850aadb33SDmitri Tikhonov                                        range = lsquic_rechist_next(&rechist), ++i)
42950aadb33SDmitri Tikhonov        {
43050aadb33SDmitri Tikhonov            assert(range->high == acki.ranges[i].high);
43150aadb33SDmitri Tikhonov            assert(range->low  == acki.ranges[i].low);
43250aadb33SDmitri Tikhonov        }
43350aadb33SDmitri Tikhonov    }
43450aadb33SDmitri Tikhonov
43550aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
43650aadb33SDmitri Tikhonov}
43750aadb33SDmitri Tikhonov
43850aadb33SDmitri Tikhonov
43950aadb33SDmitri Tikhonovint
44050aadb33SDmitri Tikhonovmain (void)
44150aadb33SDmitri Tikhonov{
442c51ce338SDmitri Tikhonov    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
44350aadb33SDmitri Tikhonov    test1();
44450aadb33SDmitri Tikhonov    test2();
44550aadb33SDmitri Tikhonov    test3();
44650aadb33SDmitri Tikhonov    test4();
44750aadb33SDmitri Tikhonov    test5();
44850aadb33SDmitri Tikhonov    test6();
44950aadb33SDmitri Tikhonov    test_max_ack();
45050aadb33SDmitri Tikhonov    test_ack_truncation();
45150aadb33SDmitri Tikhonov    return 0;
45250aadb33SDmitri Tikhonov}
453