1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov/*
350aadb33SDmitri Tikhonov * Test how ACK frame is encoded.  Receive history module is tested by a
450aadb33SDmitri Tikhonov * separate unit test.
550aadb33SDmitri Tikhonov */
650aadb33SDmitri Tikhonov
750aadb33SDmitri Tikhonov#include <assert.h>
850aadb33SDmitri Tikhonov#include <stdio.h>
950aadb33SDmitri Tikhonov#include <stdlib.h>
1050aadb33SDmitri Tikhonov#include <string.h>
1150aadb33SDmitri Tikhonov
12fb3e20e0SDmitri Tikhonov#ifdef WIN32
13fb3e20e0SDmitri Tikhonov#include "vc_compat.h"
14fb3e20e0SDmitri Tikhonov#endif
15fb3e20e0SDmitri Tikhonov
1650aadb33SDmitri Tikhonov#include "lsquic_types.h"
1750aadb33SDmitri Tikhonov#include "lsquic_int_types.h"
1850aadb33SDmitri Tikhonov#include "lsquic_rechist.h"
1950aadb33SDmitri Tikhonov#include "lsquic_parse.h"
2050aadb33SDmitri Tikhonov#include "lsquic_util.h"
2150aadb33SDmitri Tikhonov#include "lsquic_logger.h"
2250aadb33SDmitri Tikhonov#include "lsquic.h"
2350aadb33SDmitri Tikhonov
24f07b3eaeSTyler Young//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043); // will not work on MSVC
25f07b3eaeSTyler Young#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_043))
2650aadb33SDmitri Tikhonov
2750aadb33SDmitri Tikhonovstatic void
2850aadb33SDmitri Tikhonovtest1 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock */
2950aadb33SDmitri Tikhonov{
3050aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
3150aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
3216a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
3350aadb33SDmitri Tikhonov
34f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
3550aadb33SDmitri Tikhonov
3650aadb33SDmitri Tikhonov    unsigned i;
3750aadb33SDmitri Tikhonov    for (i = 1; i <= 0x1234; ++i)
3850aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
3950aadb33SDmitri Tikhonov
4050aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
4150aadb33SDmitri Tikhonov        0x45,
4250aadb33SDmitri Tikhonov        0x12, 0x34,             /* Largest acked */
4350aadb33SDmitri Tikhonov        0x87, 0xFF,             /* Delta time */
4450aadb33SDmitri Tikhonov        0x12, 0x34,             /* Block length */
4550aadb33SDmitri Tikhonov        0x00,                   /* Number of timestamps */
4650aadb33SDmitri Tikhonov    };
4750aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
4850aadb33SDmitri Tikhonov
4950aadb33SDmitri Tikhonov    int has_missing = -1;
5050aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
5150aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
5250aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
5350aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
545392f7a3SLiteSpeed Tech        &rechist, now + 0x7FF8000, &has_missing, &largest, NULL);
5550aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
5650aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
5750aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
5850aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
5950aadb33SDmitri Tikhonov    assert(("ACK frame has no missing packets", has_missing == 0));
6016a9b66aSDmitri Tikhonov    assert(largest == 0x1234);
6150aadb33SDmitri Tikhonov
6250aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
6350aadb33SDmitri Tikhonov}
6450aadb33SDmitri Tikhonov
6550aadb33SDmitri Tikhonovstatic void
6650aadb33SDmitri Tikhonovtest2 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock, minus
6750aadb33SDmitri Tikhonov              * delta times.
6850aadb33SDmitri Tikhonov              */
6950aadb33SDmitri Tikhonov{
7050aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
7150aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
7250aadb33SDmitri Tikhonov
73f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
7450aadb33SDmitri Tikhonov
7550aadb33SDmitri Tikhonov    /* Encode the following ranges:
7650aadb33SDmitri Tikhonov     *    high      low
7750aadb33SDmitri Tikhonov     *    0x1234    0x1234
7850aadb33SDmitri Tikhonov     *    0x1232    0x384
7950aadb33SDmitri Tikhonov     *    0x1F3     0xA
8050aadb33SDmitri Tikhonov     *    0x4       0x1
8150aadb33SDmitri Tikhonov     */
8250aadb33SDmitri Tikhonov    unsigned i;
8350aadb33SDmitri Tikhonov    for (i = 4; i >= 1; --i)
8450aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
8550aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 0x1234, now);
8650aadb33SDmitri Tikhonov    for (i = 0xA; i <= 0x1F3; ++i)
8750aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
8850aadb33SDmitri Tikhonov    for (i = 0x1232; i >= 0x384; --i)
8950aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
9050aadb33SDmitri Tikhonov
9150aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
9250aadb33SDmitri Tikhonov        0x65,
9350aadb33SDmitri Tikhonov        0x12, 0x34,                 /* Largest acked */
9450aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
9550aadb33SDmitri Tikhonov        0x04,                       /* Num ack blocks ranges. */
9650aadb33SDmitri Tikhonov        0x00, 0x01,                 /* First ack block length. */
9750aadb33SDmitri Tikhonov        0x01,                       /* Gap to next block. */
9850aadb33SDmitri Tikhonov        0x0e, 0xaf,                 /* Ack block length. */
9950aadb33SDmitri Tikhonov        0xff,                       /* Gap to next block. */
10050aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Ack block length. */
10150aadb33SDmitri Tikhonov        0x91,                       /* Gap to next block. */
10250aadb33SDmitri Tikhonov        0x01, 0xea,                 /* Ack block length. */
10350aadb33SDmitri Tikhonov        0x05,                       /* Gap to next block. */
10450aadb33SDmitri Tikhonov        0x00, 0x04,                 /* Ack block length. */
10550aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
10650aadb33SDmitri Tikhonov    };
10750aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
10850aadb33SDmitri Tikhonov
10950aadb33SDmitri Tikhonov    int has_missing = -1;
11016a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
11150aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
11250aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
11350aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
11450aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
1155392f7a3SLiteSpeed Tech        &rechist, now, &has_missing, &largest, NULL);
11650aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
11750aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
11850aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
11950aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
12050aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
12116a9b66aSDmitri Tikhonov    assert(largest == 0x1234);
12250aadb33SDmitri Tikhonov
12350aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
12450aadb33SDmitri Tikhonov}
12550aadb33SDmitri Tikhonov
12650aadb33SDmitri Tikhonovstatic void
12750aadb33SDmitri Tikhonovtest3 (void)
12850aadb33SDmitri Tikhonov{
12950aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
13050aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
13150aadb33SDmitri Tikhonov
132f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
13350aadb33SDmitri Tikhonov
13450aadb33SDmitri Tikhonov    /* Encode the following ranges:
13550aadb33SDmitri Tikhonov     *    high      low
13650aadb33SDmitri Tikhonov     *    3         3
13750aadb33SDmitri Tikhonov     *    1         1
13850aadb33SDmitri Tikhonov     */
13950aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 1, now);
14050aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 3, now);
14150aadb33SDmitri Tikhonov
14250aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
14350aadb33SDmitri Tikhonov        0x60,
14450aadb33SDmitri Tikhonov        0x03,
14550aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
14650aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
14750aadb33SDmitri Tikhonov        0x01,                       /* First ack block length. */
14850aadb33SDmitri Tikhonov        0x01,                       /* Gap to next block. */
14950aadb33SDmitri Tikhonov        0x01,                       /* Ack block length. */
15050aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
15150aadb33SDmitri Tikhonov    };
15250aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
15350aadb33SDmitri Tikhonov
15450aadb33SDmitri Tikhonov    int has_missing = -1;
15516a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
15650aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
15750aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
15850aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
15950aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
1605392f7a3SLiteSpeed Tech        &rechist, now, &has_missing, &largest, NULL);
16150aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
16250aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
16350aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
16450aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
16550aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
16616a9b66aSDmitri Tikhonov    assert(largest == 0x03);
16750aadb33SDmitri Tikhonov
16850aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
16950aadb33SDmitri Tikhonov}
17050aadb33SDmitri Tikhonov
17150aadb33SDmitri Tikhonov
17250aadb33SDmitri Tikhonovstatic void
17350aadb33SDmitri Tikhonovtest4 (void)
17450aadb33SDmitri Tikhonov{
17550aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
17650aadb33SDmitri Tikhonov    int i;
17750aadb33SDmitri Tikhonov
178f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
17950aadb33SDmitri Tikhonov
18050aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
18150aadb33SDmitri Tikhonov    lsquic_rechist_received(&rechist, 1, now);
18250aadb33SDmitri Tikhonov
18350aadb33SDmitri Tikhonov    {
18450aadb33SDmitri Tikhonov        const unsigned char expected_ack_frame[] = {
18550aadb33SDmitri Tikhonov            0x40,
18650aadb33SDmitri Tikhonov            0x01,                   /* Largest acked */
18750aadb33SDmitri Tikhonov            0x00, 0x00,             /* Delta time */
18850aadb33SDmitri Tikhonov            0x01,                   /* Block length */
18950aadb33SDmitri Tikhonov            0x00,                   /* Number of timestamps */
19050aadb33SDmitri Tikhonov        };
19150aadb33SDmitri Tikhonov        unsigned char outbuf[0x100];
19250aadb33SDmitri Tikhonov        int has_missing = -1;
19316a9b66aSDmitri Tikhonov        lsquic_packno_t largest = 0;
19450aadb33SDmitri Tikhonov        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
19550aadb33SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
19650aadb33SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
19750aadb33SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
1985392f7a3SLiteSpeed Tech            &rechist, now, &has_missing, &largest, NULL);
19950aadb33SDmitri Tikhonov        assert(("ACK frame generation successful", w > 0));
20050aadb33SDmitri Tikhonov        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
20150aadb33SDmitri Tikhonov        assert(("ACK frame contents are as expected",
20250aadb33SDmitri Tikhonov            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
20350aadb33SDmitri Tikhonov        assert(("ACK frame has no missing packets", has_missing == 0));
20416a9b66aSDmitri Tikhonov        assert(largest == 1);
20550aadb33SDmitri Tikhonov    }
20650aadb33SDmitri Tikhonov
20750aadb33SDmitri Tikhonov    for (i = 3; i <= 5; ++i)
20850aadb33SDmitri Tikhonov        lsquic_rechist_received(&rechist, i, now);
20950aadb33SDmitri Tikhonov
21050aadb33SDmitri Tikhonov    {
21150aadb33SDmitri Tikhonov        const unsigned char expected_ack_frame[] = {
21250aadb33SDmitri Tikhonov            0x60,
21350aadb33SDmitri Tikhonov            0x05,                   /* Largest acked */
21450aadb33SDmitri Tikhonov            0x00, 0x00,             /* Delta time */
21550aadb33SDmitri Tikhonov            0x01,                   /* Num ack blocks */
21650aadb33SDmitri Tikhonov            0x03,                   /* First block length [3, 5] */
21750aadb33SDmitri Tikhonov            0x01,                   /* Gap to next block */
21850aadb33SDmitri Tikhonov            0x01,                   /* Second block length [1, 1] */
21950aadb33SDmitri Tikhonov            0x00,                   /* Number of timestamps */
22050aadb33SDmitri Tikhonov        };
22150aadb33SDmitri Tikhonov        unsigned char outbuf[0x100];
22250aadb33SDmitri Tikhonov        int has_missing = -1;
22316a9b66aSDmitri Tikhonov        lsquic_packno_t largest = 0;
22450aadb33SDmitri Tikhonov        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
22550aadb33SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
22650aadb33SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
22750aadb33SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
2285392f7a3SLiteSpeed Tech            &rechist, now, &has_missing, &largest, NULL);
22950aadb33SDmitri Tikhonov        assert(("ACK frame generation successful", w > 0));
23050aadb33SDmitri Tikhonov        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
23150aadb33SDmitri Tikhonov        assert(("ACK frame contents are as expected",
23250aadb33SDmitri Tikhonov            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
23350aadb33SDmitri Tikhonov        assert(("ACK frame has missing packets", has_missing > 0));
23416a9b66aSDmitri Tikhonov        assert(largest == 5);
23550aadb33SDmitri Tikhonov    }
23650aadb33SDmitri Tikhonov
23750aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
23850aadb33SDmitri Tikhonov}
23950aadb33SDmitri Tikhonov
24050aadb33SDmitri Tikhonov
24150aadb33SDmitri Tikhonovstatic void
24250aadb33SDmitri Tikhonovtest_4byte_packnos (void)
24350aadb33SDmitri Tikhonov{
24450aadb33SDmitri Tikhonov    lsquic_packno_t packno;
24550aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
24650aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
24750aadb33SDmitri Tikhonov
248f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
24950aadb33SDmitri Tikhonov
25050aadb33SDmitri Tikhonov    packno = 0x23456789;
25150aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, packno - 33, now);
25250aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, packno, now);
25350aadb33SDmitri Tikhonov
25450aadb33SDmitri Tikhonov    /* Adjust: */
255b62ec17fSDmitri Tikhonov    rechist.rh_elems[0].re_low = 1;
256b62ec17fSDmitri Tikhonov    rechist.rh_elems[0].re_count = packno - 33;
25750aadb33SDmitri Tikhonov
25850aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
25950aadb33SDmitri Tikhonov        0x60
26050aadb33SDmitri Tikhonov            | (2 << 2)  /* Four-byte largest acked */
26150aadb33SDmitri Tikhonov            | (2 << 0)  /* Four-byte ACK block length */
26250aadb33SDmitri Tikhonov        ,
26350aadb33SDmitri Tikhonov        0x23, 0x45, 0x67, 0x89,
26450aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
26550aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
26650aadb33SDmitri Tikhonov        0x00, 0x00, 0x00, 0x01,     /* First ack block length. */
26750aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
26850aadb33SDmitri Tikhonov        0x23, 0x45, 0x67, 0x68,     /* Ack block length. */
26950aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
27050aadb33SDmitri Tikhonov    };
27150aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
27250aadb33SDmitri Tikhonov
27350aadb33SDmitri Tikhonov    int has_missing = -1;
27416a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
27550aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
27650aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
27750aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
27850aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
2795392f7a3SLiteSpeed Tech        &rechist, now, &has_missing, &largest, NULL);
28050aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
28150aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
28250aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
28350aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
28450aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
28516a9b66aSDmitri Tikhonov    assert(largest == 0x23456789);
28650aadb33SDmitri Tikhonov
28750aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
28850aadb33SDmitri Tikhonov}
28950aadb33SDmitri Tikhonov
29050aadb33SDmitri Tikhonov
291b62ec17fSDmitri Tikhonov/* lsquic_rechist no longer supports ranges that require integers
292b62ec17fSDmitri Tikhonov * wider than four bytes -- modify the test to use a custom receive
293b62ec17fSDmitri Tikhonov * history.
294b62ec17fSDmitri Tikhonov */
295b62ec17fSDmitri Tikhonovstatic const struct lsquic_packno_range test_6byte_ranges[] = {
296b62ec17fSDmitri Tikhonov    { .high = 0xABCD23456789, .low = 0xABCD23456789, },
297b62ec17fSDmitri Tikhonov    { .high = 0xABCD23456789 - 33, .low = 1, },
298b62ec17fSDmitri Tikhonov};
299b62ec17fSDmitri Tikhonov
300b62ec17fSDmitri Tikhonov
301b62ec17fSDmitri Tikhonovstatic const struct lsquic_packno_range *
302b62ec17fSDmitri Tikhonovtest_6byte_rechist_first (void *rechist)
30350aadb33SDmitri Tikhonov{
304b62ec17fSDmitri Tikhonov    int *next = rechist;
305b62ec17fSDmitri Tikhonov    *next = 1;
306b62ec17fSDmitri Tikhonov    return &test_6byte_ranges[0];
307b62ec17fSDmitri Tikhonov};
30850aadb33SDmitri Tikhonov
30950aadb33SDmitri Tikhonov
310b62ec17fSDmitri Tikhonovstatic const struct lsquic_packno_range *
311b62ec17fSDmitri Tikhonovtest_6byte_rechist_next (void *rechist)
312b62ec17fSDmitri Tikhonov{
313b62ec17fSDmitri Tikhonov    int *next = rechist;
314b62ec17fSDmitri Tikhonov    if (*next == 1)
315b62ec17fSDmitri Tikhonov    {
316b62ec17fSDmitri Tikhonov        ++*next;
317b62ec17fSDmitri Tikhonov        return &test_6byte_ranges[1];
318b62ec17fSDmitri Tikhonov    }
319b62ec17fSDmitri Tikhonov    else
320b62ec17fSDmitri Tikhonov        return NULL;
321b62ec17fSDmitri Tikhonov}
32250aadb33SDmitri Tikhonov
323b62ec17fSDmitri Tikhonov
324b62ec17fSDmitri Tikhonovstatic lsquic_time_t s_test_6byte_now;
325b62ec17fSDmitri Tikhonovstatic lsquic_time_t
326b62ec17fSDmitri Tikhonovtest_6byte_rechist_largest_recv  (void *rechist)
327b62ec17fSDmitri Tikhonov{
328b62ec17fSDmitri Tikhonov    return s_test_6byte_now;
329b62ec17fSDmitri Tikhonov}
330b62ec17fSDmitri Tikhonov
331b62ec17fSDmitri Tikhonov
332b62ec17fSDmitri Tikhonovstatic void
333b62ec17fSDmitri Tikhonovtest_6byte_packnos (void)
334b62ec17fSDmitri Tikhonov{
335b62ec17fSDmitri Tikhonov    int rechist = 0;
336b62ec17fSDmitri Tikhonov    s_test_6byte_now = lsquic_time_now();
33750aadb33SDmitri Tikhonov
33850aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
33950aadb33SDmitri Tikhonov        0x60
34050aadb33SDmitri Tikhonov            | (3 << 2)  /* Six-byte largest acked */
34150aadb33SDmitri Tikhonov            | (3 << 0)  /* Six-byte ACK block length */
34250aadb33SDmitri Tikhonov        ,
34350aadb33SDmitri Tikhonov        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x89,
34450aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
34550aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
34650aadb33SDmitri Tikhonov        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* First ack block length. */
34750aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
34850aadb33SDmitri Tikhonov        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x68, /* Ack block length. */
34950aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
35050aadb33SDmitri Tikhonov    };
35150aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
35250aadb33SDmitri Tikhonov
35350aadb33SDmitri Tikhonov    int has_missing = -1;
35416a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
35550aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
356b62ec17fSDmitri Tikhonov        test_6byte_rechist_first,
357b62ec17fSDmitri Tikhonov        test_6byte_rechist_next,
358b62ec17fSDmitri Tikhonov        test_6byte_rechist_largest_recv,
359b62ec17fSDmitri Tikhonov        &rechist, s_test_6byte_now, &has_missing, &largest, NULL);
36050aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
36150aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
36250aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
36350aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
36450aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
36516a9b66aSDmitri Tikhonov    assert(largest == 0xABCD23456789ULL);
36650aadb33SDmitri Tikhonov}
36750aadb33SDmitri Tikhonov
36850aadb33SDmitri Tikhonov
36950aadb33SDmitri Tikhonovint
37050aadb33SDmitri Tikhonovmain (void)
37150aadb33SDmitri Tikhonov{
372c51ce338SDmitri Tikhonov    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
37350aadb33SDmitri Tikhonov    lsquic_log_to_fstream(stderr, 0);
37450aadb33SDmitri Tikhonov    lsq_log_levels[LSQLM_PARSE]   = LSQ_LOG_DEBUG;
37550aadb33SDmitri Tikhonov
37650aadb33SDmitri Tikhonov    test1();
37750aadb33SDmitri Tikhonov
37850aadb33SDmitri Tikhonov    test2();
37950aadb33SDmitri Tikhonov
38050aadb33SDmitri Tikhonov    test3();
38150aadb33SDmitri Tikhonov
38250aadb33SDmitri Tikhonov    test4();
38350aadb33SDmitri Tikhonov
38450aadb33SDmitri Tikhonov    test_4byte_packnos();
38550aadb33SDmitri Tikhonov
38650aadb33SDmitri Tikhonov    test_6byte_packnos();
38750aadb33SDmitri Tikhonov
38850aadb33SDmitri Tikhonov    return 0;
38950aadb33SDmitri Tikhonov}
390