test_ackgen_gquic_be.c revision 06b2a236
106b2a236SDmitri Tikhonov/* Copyright (c) 2017 - 2021 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
24fb96f4ddSDmitri Tikhonovstatic const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043);
2550aadb33SDmitri Tikhonov
2650aadb33SDmitri Tikhonovstatic void
2750aadb33SDmitri Tikhonovtest1 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock */
2850aadb33SDmitri Tikhonov{
2950aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
3050aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
3116a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
3250aadb33SDmitri Tikhonov
33f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
3450aadb33SDmitri Tikhonov
3550aadb33SDmitri Tikhonov    unsigned i;
3650aadb33SDmitri Tikhonov    for (i = 1; i <= 0x1234; ++i)
3750aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
3850aadb33SDmitri Tikhonov
3950aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
4050aadb33SDmitri Tikhonov        0x45,
4150aadb33SDmitri Tikhonov        0x12, 0x34,             /* Largest acked */
4250aadb33SDmitri Tikhonov        0x87, 0xFF,             /* Delta time */
4350aadb33SDmitri Tikhonov        0x12, 0x34,             /* Block length */
4450aadb33SDmitri Tikhonov        0x00,                   /* Number of timestamps */
4550aadb33SDmitri Tikhonov    };
4650aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
4750aadb33SDmitri Tikhonov
4850aadb33SDmitri Tikhonov    int has_missing = -1;
4950aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
5050aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
5150aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
5250aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
535392f7a3SLiteSpeed Tech        &rechist, now + 0x7FF8000, &has_missing, &largest, NULL);
5450aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
5550aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
5650aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
5750aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
5850aadb33SDmitri Tikhonov    assert(("ACK frame has no missing packets", has_missing == 0));
5916a9b66aSDmitri Tikhonov    assert(largest == 0x1234);
6050aadb33SDmitri Tikhonov
6150aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
6250aadb33SDmitri Tikhonov}
6350aadb33SDmitri Tikhonov
6450aadb33SDmitri Tikhonovstatic void
6550aadb33SDmitri Tikhonovtest2 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock, minus
6650aadb33SDmitri Tikhonov              * delta times.
6750aadb33SDmitri Tikhonov              */
6850aadb33SDmitri Tikhonov{
6950aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
7050aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
7150aadb33SDmitri Tikhonov
72f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
7350aadb33SDmitri Tikhonov
7450aadb33SDmitri Tikhonov    /* Encode the following ranges:
7550aadb33SDmitri Tikhonov     *    high      low
7650aadb33SDmitri Tikhonov     *    0x1234    0x1234
7750aadb33SDmitri Tikhonov     *    0x1232    0x384
7850aadb33SDmitri Tikhonov     *    0x1F3     0xA
7950aadb33SDmitri Tikhonov     *    0x4       0x1
8050aadb33SDmitri Tikhonov     */
8150aadb33SDmitri Tikhonov    unsigned i;
8250aadb33SDmitri Tikhonov    for (i = 4; i >= 1; --i)
8350aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
8450aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 0x1234, now);
8550aadb33SDmitri Tikhonov    for (i = 0xA; i <= 0x1F3; ++i)
8650aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
8750aadb33SDmitri Tikhonov    for (i = 0x1232; i >= 0x384; --i)
8850aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
8950aadb33SDmitri Tikhonov
9050aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
9150aadb33SDmitri Tikhonov        0x65,
9250aadb33SDmitri Tikhonov        0x12, 0x34,                 /* Largest acked */
9350aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
9450aadb33SDmitri Tikhonov        0x04,                       /* Num ack blocks ranges. */
9550aadb33SDmitri Tikhonov        0x00, 0x01,                 /* First ack block length. */
9650aadb33SDmitri Tikhonov        0x01,                       /* Gap to next block. */
9750aadb33SDmitri Tikhonov        0x0e, 0xaf,                 /* Ack block length. */
9850aadb33SDmitri Tikhonov        0xff,                       /* Gap to next block. */
9950aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Ack block length. */
10050aadb33SDmitri Tikhonov        0x91,                       /* Gap to next block. */
10150aadb33SDmitri Tikhonov        0x01, 0xea,                 /* Ack block length. */
10250aadb33SDmitri Tikhonov        0x05,                       /* Gap to next block. */
10350aadb33SDmitri Tikhonov        0x00, 0x04,                 /* Ack block length. */
10450aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
10550aadb33SDmitri Tikhonov    };
10650aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
10750aadb33SDmitri Tikhonov
10850aadb33SDmitri Tikhonov    int has_missing = -1;
10916a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
11050aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
11150aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
11250aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
11350aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
1145392f7a3SLiteSpeed Tech        &rechist, now, &has_missing, &largest, NULL);
11550aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
11650aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
11750aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
11850aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
11950aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
12016a9b66aSDmitri Tikhonov    assert(largest == 0x1234);
12150aadb33SDmitri Tikhonov
12250aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
12350aadb33SDmitri Tikhonov}
12450aadb33SDmitri Tikhonov
12550aadb33SDmitri Tikhonovstatic void
12650aadb33SDmitri Tikhonovtest3 (void)
12750aadb33SDmitri Tikhonov{
12850aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
12950aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
13050aadb33SDmitri Tikhonov
131f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
13250aadb33SDmitri Tikhonov
13350aadb33SDmitri Tikhonov    /* Encode the following ranges:
13450aadb33SDmitri Tikhonov     *    high      low
13550aadb33SDmitri Tikhonov     *    3         3
13650aadb33SDmitri Tikhonov     *    1         1
13750aadb33SDmitri Tikhonov     */
13850aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 1, now);
13950aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 3, now);
14050aadb33SDmitri Tikhonov
14150aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
14250aadb33SDmitri Tikhonov        0x60,
14350aadb33SDmitri Tikhonov        0x03,
14450aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
14550aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
14650aadb33SDmitri Tikhonov        0x01,                       /* First ack block length. */
14750aadb33SDmitri Tikhonov        0x01,                       /* Gap to next block. */
14850aadb33SDmitri Tikhonov        0x01,                       /* Ack block length. */
14950aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
15050aadb33SDmitri Tikhonov    };
15150aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
15250aadb33SDmitri Tikhonov
15350aadb33SDmitri Tikhonov    int has_missing = -1;
15416a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
15550aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
15650aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
15750aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
15850aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
1595392f7a3SLiteSpeed Tech        &rechist, now, &has_missing, &largest, NULL);
16050aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
16150aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
16250aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
16350aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
16450aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
16516a9b66aSDmitri Tikhonov    assert(largest == 0x03);
16650aadb33SDmitri Tikhonov
16750aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
16850aadb33SDmitri Tikhonov}
16950aadb33SDmitri Tikhonov
17050aadb33SDmitri Tikhonov
17150aadb33SDmitri Tikhonovstatic void
17250aadb33SDmitri Tikhonovtest4 (void)
17350aadb33SDmitri Tikhonov{
17450aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
17550aadb33SDmitri Tikhonov    int i;
17650aadb33SDmitri Tikhonov
177f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
17850aadb33SDmitri Tikhonov
17950aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
18050aadb33SDmitri Tikhonov    lsquic_rechist_received(&rechist, 1, now);
18150aadb33SDmitri Tikhonov
18250aadb33SDmitri Tikhonov    {
18350aadb33SDmitri Tikhonov        const unsigned char expected_ack_frame[] = {
18450aadb33SDmitri Tikhonov            0x40,
18550aadb33SDmitri Tikhonov            0x01,                   /* Largest acked */
18650aadb33SDmitri Tikhonov            0x00, 0x00,             /* Delta time */
18750aadb33SDmitri Tikhonov            0x01,                   /* Block length */
18850aadb33SDmitri Tikhonov            0x00,                   /* Number of timestamps */
18950aadb33SDmitri Tikhonov        };
19050aadb33SDmitri Tikhonov        unsigned char outbuf[0x100];
19150aadb33SDmitri Tikhonov        int has_missing = -1;
19216a9b66aSDmitri Tikhonov        lsquic_packno_t largest = 0;
19350aadb33SDmitri Tikhonov        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
19450aadb33SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
19550aadb33SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
19650aadb33SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
1975392f7a3SLiteSpeed Tech            &rechist, now, &has_missing, &largest, NULL);
19850aadb33SDmitri Tikhonov        assert(("ACK frame generation successful", w > 0));
19950aadb33SDmitri Tikhonov        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
20050aadb33SDmitri Tikhonov        assert(("ACK frame contents are as expected",
20150aadb33SDmitri Tikhonov            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
20250aadb33SDmitri Tikhonov        assert(("ACK frame has no missing packets", has_missing == 0));
20316a9b66aSDmitri Tikhonov        assert(largest == 1);
20450aadb33SDmitri Tikhonov    }
20550aadb33SDmitri Tikhonov
20650aadb33SDmitri Tikhonov    for (i = 3; i <= 5; ++i)
20750aadb33SDmitri Tikhonov        lsquic_rechist_received(&rechist, i, now);
20850aadb33SDmitri Tikhonov
20950aadb33SDmitri Tikhonov    {
21050aadb33SDmitri Tikhonov        const unsigned char expected_ack_frame[] = {
21150aadb33SDmitri Tikhonov            0x60,
21250aadb33SDmitri Tikhonov            0x05,                   /* Largest acked */
21350aadb33SDmitri Tikhonov            0x00, 0x00,             /* Delta time */
21450aadb33SDmitri Tikhonov            0x01,                   /* Num ack blocks */
21550aadb33SDmitri Tikhonov            0x03,                   /* First block length [3, 5] */
21650aadb33SDmitri Tikhonov            0x01,                   /* Gap to next block */
21750aadb33SDmitri Tikhonov            0x01,                   /* Second block length [1, 1] */
21850aadb33SDmitri Tikhonov            0x00,                   /* Number of timestamps */
21950aadb33SDmitri Tikhonov        };
22050aadb33SDmitri Tikhonov        unsigned char outbuf[0x100];
22150aadb33SDmitri Tikhonov        int has_missing = -1;
22216a9b66aSDmitri Tikhonov        lsquic_packno_t largest = 0;
22350aadb33SDmitri Tikhonov        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
22450aadb33SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
22550aadb33SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
22650aadb33SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
2275392f7a3SLiteSpeed Tech            &rechist, now, &has_missing, &largest, NULL);
22850aadb33SDmitri Tikhonov        assert(("ACK frame generation successful", w > 0));
22950aadb33SDmitri Tikhonov        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
23050aadb33SDmitri Tikhonov        assert(("ACK frame contents are as expected",
23150aadb33SDmitri Tikhonov            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
23250aadb33SDmitri Tikhonov        assert(("ACK frame has missing packets", has_missing > 0));
23316a9b66aSDmitri Tikhonov        assert(largest == 5);
23450aadb33SDmitri Tikhonov    }
23550aadb33SDmitri Tikhonov
23650aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
23750aadb33SDmitri Tikhonov}
23850aadb33SDmitri Tikhonov
23950aadb33SDmitri Tikhonov
24050aadb33SDmitri Tikhonovstatic void
24150aadb33SDmitri Tikhonovtest_4byte_packnos (void)
24250aadb33SDmitri Tikhonov{
24350aadb33SDmitri Tikhonov    lsquic_packno_t packno;
24450aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
24550aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
24650aadb33SDmitri Tikhonov
247f38b395aSDmitri Tikhonov    lsquic_rechist_init(&rechist, 0, 0);
24850aadb33SDmitri Tikhonov
24950aadb33SDmitri Tikhonov    packno = 0x23456789;
25050aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, packno - 33, now);
25150aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, packno, now);
25250aadb33SDmitri Tikhonov
25350aadb33SDmitri Tikhonov    /* Adjust: */
254b62ec17fSDmitri Tikhonov    rechist.rh_elems[0].re_low = 1;
255b62ec17fSDmitri Tikhonov    rechist.rh_elems[0].re_count = packno - 33;
25650aadb33SDmitri Tikhonov
25750aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
25850aadb33SDmitri Tikhonov        0x60
25950aadb33SDmitri Tikhonov            | (2 << 2)  /* Four-byte largest acked */
26050aadb33SDmitri Tikhonov            | (2 << 0)  /* Four-byte ACK block length */
26150aadb33SDmitri Tikhonov        ,
26250aadb33SDmitri Tikhonov        0x23, 0x45, 0x67, 0x89,
26350aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
26450aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
26550aadb33SDmitri Tikhonov        0x00, 0x00, 0x00, 0x01,     /* First ack block length. */
26650aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
26750aadb33SDmitri Tikhonov        0x23, 0x45, 0x67, 0x68,     /* Ack block length. */
26850aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
26950aadb33SDmitri Tikhonov    };
27050aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
27150aadb33SDmitri Tikhonov
27250aadb33SDmitri Tikhonov    int has_missing = -1;
27316a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
27450aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
27550aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
27650aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
27750aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
2785392f7a3SLiteSpeed Tech        &rechist, now, &has_missing, &largest, NULL);
27950aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
28050aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
28150aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
28250aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
28350aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
28416a9b66aSDmitri Tikhonov    assert(largest == 0x23456789);
28550aadb33SDmitri Tikhonov
28650aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
28750aadb33SDmitri Tikhonov}
28850aadb33SDmitri Tikhonov
28950aadb33SDmitri Tikhonov
290b62ec17fSDmitri Tikhonov/* lsquic_rechist no longer supports ranges that require integers
291b62ec17fSDmitri Tikhonov * wider than four bytes -- modify the test to use a custom receive
292b62ec17fSDmitri Tikhonov * history.
293b62ec17fSDmitri Tikhonov */
294b62ec17fSDmitri Tikhonovstatic const struct lsquic_packno_range test_6byte_ranges[] = {
295b62ec17fSDmitri Tikhonov    { .high = 0xABCD23456789, .low = 0xABCD23456789, },
296b62ec17fSDmitri Tikhonov    { .high = 0xABCD23456789 - 33, .low = 1, },
297b62ec17fSDmitri Tikhonov};
298b62ec17fSDmitri Tikhonov
299b62ec17fSDmitri Tikhonov
300b62ec17fSDmitri Tikhonovstatic const struct lsquic_packno_range *
301b62ec17fSDmitri Tikhonovtest_6byte_rechist_first (void *rechist)
30250aadb33SDmitri Tikhonov{
303b62ec17fSDmitri Tikhonov    int *next = rechist;
304b62ec17fSDmitri Tikhonov    *next = 1;
305b62ec17fSDmitri Tikhonov    return &test_6byte_ranges[0];
306b62ec17fSDmitri Tikhonov};
30750aadb33SDmitri Tikhonov
30850aadb33SDmitri Tikhonov
309b62ec17fSDmitri Tikhonovstatic const struct lsquic_packno_range *
310b62ec17fSDmitri Tikhonovtest_6byte_rechist_next (void *rechist)
311b62ec17fSDmitri Tikhonov{
312b62ec17fSDmitri Tikhonov    int *next = rechist;
313b62ec17fSDmitri Tikhonov    if (*next == 1)
314b62ec17fSDmitri Tikhonov    {
315b62ec17fSDmitri Tikhonov        ++*next;
316b62ec17fSDmitri Tikhonov        return &test_6byte_ranges[1];
317b62ec17fSDmitri Tikhonov    }
318b62ec17fSDmitri Tikhonov    else
319b62ec17fSDmitri Tikhonov        return NULL;
320b62ec17fSDmitri Tikhonov}
32150aadb33SDmitri Tikhonov
322b62ec17fSDmitri Tikhonov
323b62ec17fSDmitri Tikhonovstatic lsquic_time_t s_test_6byte_now;
324b62ec17fSDmitri Tikhonovstatic lsquic_time_t
325b62ec17fSDmitri Tikhonovtest_6byte_rechist_largest_recv  (void *rechist)
326b62ec17fSDmitri Tikhonov{
327b62ec17fSDmitri Tikhonov    return s_test_6byte_now;
328b62ec17fSDmitri Tikhonov}
329b62ec17fSDmitri Tikhonov
330b62ec17fSDmitri Tikhonov
331b62ec17fSDmitri Tikhonovstatic void
332b62ec17fSDmitri Tikhonovtest_6byte_packnos (void)
333b62ec17fSDmitri Tikhonov{
334b62ec17fSDmitri Tikhonov    int rechist = 0;
335b62ec17fSDmitri Tikhonov    s_test_6byte_now = lsquic_time_now();
33650aadb33SDmitri Tikhonov
33750aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
33850aadb33SDmitri Tikhonov        0x60
33950aadb33SDmitri Tikhonov            | (3 << 2)  /* Six-byte largest acked */
34050aadb33SDmitri Tikhonov            | (3 << 0)  /* Six-byte ACK block length */
34150aadb33SDmitri Tikhonov        ,
34250aadb33SDmitri Tikhonov        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x89,
34350aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
34450aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
34550aadb33SDmitri Tikhonov        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* First ack block length. */
34650aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
34750aadb33SDmitri Tikhonov        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x68, /* Ack block length. */
34850aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
34950aadb33SDmitri Tikhonov    };
35050aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
35150aadb33SDmitri Tikhonov
35250aadb33SDmitri Tikhonov    int has_missing = -1;
35316a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
35450aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
355b62ec17fSDmitri Tikhonov        test_6byte_rechist_first,
356b62ec17fSDmitri Tikhonov        test_6byte_rechist_next,
357b62ec17fSDmitri Tikhonov        test_6byte_rechist_largest_recv,
358b62ec17fSDmitri Tikhonov        &rechist, s_test_6byte_now, &has_missing, &largest, NULL);
35950aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
36050aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
36150aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
36250aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
36350aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
36416a9b66aSDmitri Tikhonov    assert(largest == 0xABCD23456789ULL);
36550aadb33SDmitri Tikhonov}
36650aadb33SDmitri Tikhonov
36750aadb33SDmitri Tikhonov
36850aadb33SDmitri Tikhonovint
36950aadb33SDmitri Tikhonovmain (void)
37050aadb33SDmitri Tikhonov{
371c51ce338SDmitri Tikhonov    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
37250aadb33SDmitri Tikhonov    lsquic_log_to_fstream(stderr, 0);
37350aadb33SDmitri Tikhonov    lsq_log_levels[LSQLM_PARSE]   = LSQ_LOG_DEBUG;
37450aadb33SDmitri Tikhonov
37550aadb33SDmitri Tikhonov    test1();
37650aadb33SDmitri Tikhonov
37750aadb33SDmitri Tikhonov    test2();
37850aadb33SDmitri Tikhonov
37950aadb33SDmitri Tikhonov    test3();
38050aadb33SDmitri Tikhonov
38150aadb33SDmitri Tikhonov    test4();
38250aadb33SDmitri Tikhonov
38350aadb33SDmitri Tikhonov    test_4byte_packnos();
38450aadb33SDmitri Tikhonov
38550aadb33SDmitri Tikhonov    test_6byte_packnos();
38650aadb33SDmitri Tikhonov
38750aadb33SDmitri Tikhonov    return 0;
38850aadb33SDmitri Tikhonov}
389