test_elision.c revision 06b2a236
106b2a236SDmitri Tikhonov/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov#include <assert.h>
350aadb33SDmitri Tikhonov#include <errno.h>
450aadb33SDmitri Tikhonov#include <stdio.h>
550aadb33SDmitri Tikhonov#include <stdlib.h>
650aadb33SDmitri Tikhonov#include <string.h>
750aadb33SDmitri Tikhonov#include <sys/queue.h>
850aadb33SDmitri Tikhonov
950aadb33SDmitri Tikhonov#include "lsquic.h"
1050aadb33SDmitri Tikhonov
1150aadb33SDmitri Tikhonov#include "lsquic_int_types.h"
1250aadb33SDmitri Tikhonov#include "lsquic_packet_common.h"
135392f7a3SLiteSpeed Tech#include "lsquic_packet_gquic.h"
1450aadb33SDmitri Tikhonov#include "lsquic_packet_out.h"
1550aadb33SDmitri Tikhonov#include "lsquic_parse.h"
1650aadb33SDmitri Tikhonov#include "lsquic_conn_flow.h"
1750aadb33SDmitri Tikhonov#include "lsquic_sfcw.h"
185392f7a3SLiteSpeed Tech#include "lsquic_varint.h"
195392f7a3SLiteSpeed Tech#include "lsquic_hq.h"
205392f7a3SLiteSpeed Tech#include "lsquic_hash.h"
2150aadb33SDmitri Tikhonov#include "lsquic_stream.h"
2250aadb33SDmitri Tikhonov#include "lsquic_types.h"
2350aadb33SDmitri Tikhonov#include "lsquic_malo.h"
2450aadb33SDmitri Tikhonov#include "lsquic_mm.h"
2550aadb33SDmitri Tikhonov#include "lsquic_engine_public.h"
2650aadb33SDmitri Tikhonov#include "lsquic_logger.h"
2750aadb33SDmitri Tikhonov
2850aadb33SDmitri Tikhonov
29fb96f4ddSDmitri Tikhonovstatic const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043);
3050aadb33SDmitri Tikhonov
3150aadb33SDmitri Tikhonovstatic struct {
324d83f5bdSDmitri Tikhonov    unsigned char   buf[0x1000];
3350aadb33SDmitri Tikhonov    size_t      bufsz;
3450aadb33SDmitri Tikhonov    uint64_t    off;
3550aadb33SDmitri Tikhonov} stream_contents;
3650aadb33SDmitri Tikhonov
3750aadb33SDmitri Tikhonov
3850aadb33SDmitri Tikhonovvoid
3950aadb33SDmitri Tikhonovsetup_stream_contents (uint64_t off, const char *str)
4050aadb33SDmitri Tikhonov{
4150aadb33SDmitri Tikhonov    stream_contents.bufsz = strlen(str);
4250aadb33SDmitri Tikhonov    stream_contents.off   = off;
4350aadb33SDmitri Tikhonov    memcpy(stream_contents.buf, str, stream_contents.bufsz);
4450aadb33SDmitri Tikhonov}
4550aadb33SDmitri Tikhonov
4650aadb33SDmitri Tikhonov
474d83f5bdSDmitri Tikhonovvoid
484d83f5bdSDmitri Tikhonovsetup_stream_contents_n (uint64_t off, const unsigned char *buf, size_t size)
494d83f5bdSDmitri Tikhonov{
504d83f5bdSDmitri Tikhonov    stream_contents.bufsz = size;
514d83f5bdSDmitri Tikhonov    stream_contents.off   = off;
524d83f5bdSDmitri Tikhonov    memcpy(stream_contents.buf, buf, size);
534d83f5bdSDmitri Tikhonov}
544d83f5bdSDmitri Tikhonov
554d83f5bdSDmitri Tikhonov
5650aadb33SDmitri Tikhonovint
5750aadb33SDmitri Tikhonovlsquic_stream_tosend_fin (const lsquic_stream_t *stream)
5850aadb33SDmitri Tikhonov{
5950aadb33SDmitri Tikhonov    return 0;
6050aadb33SDmitri Tikhonov}
6150aadb33SDmitri Tikhonov
6250aadb33SDmitri Tikhonov
6350aadb33SDmitri Tikhonovuint64_t
6450aadb33SDmitri Tikhonovlsquic_stream_tosend_offset (const lsquic_stream_t *stream)
6550aadb33SDmitri Tikhonov{
6650aadb33SDmitri Tikhonov    return stream_contents.off;
6750aadb33SDmitri Tikhonov}
6850aadb33SDmitri Tikhonov
6950aadb33SDmitri Tikhonov
7050aadb33SDmitri Tikhonovsize_t
7150aadb33SDmitri Tikhonovlsquic_stream_tosend_read (lsquic_stream_t *stream, void *buf, size_t len,
7250aadb33SDmitri Tikhonov                           int *reached_fin)
7350aadb33SDmitri Tikhonov{
7450aadb33SDmitri Tikhonov    if (stream_contents.bufsz < len)
7550aadb33SDmitri Tikhonov        len = stream_contents.bufsz;
7650aadb33SDmitri Tikhonov    memcpy(buf, stream_contents.buf, len);
7750aadb33SDmitri Tikhonov    *reached_fin = lsquic_stream_tosend_fin(stream);
7850aadb33SDmitri Tikhonov    return len;
7950aadb33SDmitri Tikhonov}
8050aadb33SDmitri Tikhonov
8150aadb33SDmitri Tikhonov
8250aadb33SDmitri Tikhonovsize_t
8350aadb33SDmitri Tikhonovlsquic_stream_tosend_sz (const lsquic_stream_t *stream)
8450aadb33SDmitri Tikhonov{
8550aadb33SDmitri Tikhonov    return stream_contents.bufsz;
8650aadb33SDmitri Tikhonov}
8750aadb33SDmitri Tikhonov
8850aadb33SDmitri Tikhonov
8950aadb33SDmitri Tikhonovvoid
905392f7a3SLiteSpeed Techlsquic_stream_acked (lsquic_stream_t *stream, enum quic_frame_type frame_type)
9150aadb33SDmitri Tikhonov{
9250aadb33SDmitri Tikhonov    --stream->n_unacked;
9350aadb33SDmitri Tikhonov}
9450aadb33SDmitri Tikhonov
9550aadb33SDmitri Tikhonov
9650aadb33SDmitri Tikhonovstatic void
9750aadb33SDmitri Tikhonovelide_single_stream_frame (void)
9850aadb33SDmitri Tikhonov{
99b8fa6195SDmitri Tikhonov    struct packet_out_frec_iter pofi;
10050aadb33SDmitri Tikhonov    struct lsquic_engine_public enpub;
10150aadb33SDmitri Tikhonov    lsquic_stream_t streams[1];
10250aadb33SDmitri Tikhonov    lsquic_packet_out_t *packet_out;
10350aadb33SDmitri Tikhonov    int len, off = 0;
10450aadb33SDmitri Tikhonov
10550aadb33SDmitri Tikhonov    memset(streams, 0, sizeof(streams));
10650aadb33SDmitri Tikhonov    memset(&enpub, 0, sizeof(enpub));
10750aadb33SDmitri Tikhonov    lsquic_mm_init(&enpub.enp_mm);
1085392f7a3SLiteSpeed Tech    packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
10950aadb33SDmitri Tikhonov
11050aadb33SDmitri Tikhonov    setup_stream_contents(123, "Dude, where is my car?");
11150aadb33SDmitri Tikhonov    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
11250aadb33SDmitri Tikhonov            lsquic_packet_out_avail(packet_out),
11350aadb33SDmitri Tikhonov            streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
114bfc7bfd8SDmitri Tikhonov            lsquic_stream_tosend_fin(&streams[0]),
115bfc7bfd8SDmitri Tikhonov            lsquic_stream_tosend_sz(&streams[0]),
11650aadb33SDmitri Tikhonov            (gsf_read_f) lsquic_stream_tosend_read,
11750aadb33SDmitri Tikhonov            &streams[0]);
11850aadb33SDmitri Tikhonov    packet_out->po_data_sz += len;
11950aadb33SDmitri Tikhonov    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
12050aadb33SDmitri Tikhonov    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
121c51ce338SDmitri Tikhonov                                                QUIC_FRAME_STREAM, off, len);
12250aadb33SDmitri Tikhonov    assert(1 == streams[0].n_unacked);
123b8fa6195SDmitri Tikhonov    assert(lsquic_pofi_first(&pofi, packet_out));
12450aadb33SDmitri Tikhonov
12550aadb33SDmitri Tikhonov    streams[0].stream_flags |= STREAM_RST_SENT;
12650aadb33SDmitri Tikhonov
127292abba1SDmitri Tikhonov    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
12850aadb33SDmitri Tikhonov    assert(0 == streams[0].n_unacked);
12950aadb33SDmitri Tikhonov    assert(0 == packet_out->po_frame_types);
130b8fa6195SDmitri Tikhonov    assert(!lsquic_pofi_first(&pofi, packet_out));
13150aadb33SDmitri Tikhonov
1321e75f938SDmitri Tikhonov    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
13350aadb33SDmitri Tikhonov    lsquic_mm_cleanup(&enpub.enp_mm);
13450aadb33SDmitri Tikhonov}
13550aadb33SDmitri Tikhonov
13650aadb33SDmitri Tikhonov
1374d83f5bdSDmitri Tikhonov/* In this test, we check that if the last STREAM frame is moved due to
1384d83f5bdSDmitri Tikhonov * elision and PO_STREAM_END is set, the packet size is adjusted.  This
1394d83f5bdSDmitri Tikhonov * is needed to prevent data corruption for STREAM frames that have
1404d83f5bdSDmitri Tikhonov * implicit length.
1414d83f5bdSDmitri Tikhonov */
1424d83f5bdSDmitri Tikhonovstatic void
1434d83f5bdSDmitri Tikhonovshrink_packet_post_elision (void)
1444d83f5bdSDmitri Tikhonov{
145b8fa6195SDmitri Tikhonov    struct packet_out_frec_iter pofi;
1464d83f5bdSDmitri Tikhonov    struct lsquic_engine_public enpub;
1474d83f5bdSDmitri Tikhonov    lsquic_stream_t streams[2];
1484d83f5bdSDmitri Tikhonov    lsquic_packet_out_t *packet_out;
149b8fa6195SDmitri Tikhonov    const struct frame_rec *frec;
1504d83f5bdSDmitri Tikhonov    int len, off = 0;
1514d83f5bdSDmitri Tikhonov    unsigned char stream2_data[0x1000];
1524d83f5bdSDmitri Tikhonov
1534d83f5bdSDmitri Tikhonov    memset(stream2_data, '2', sizeof(stream2_data));
1544d83f5bdSDmitri Tikhonov    memset(streams, 0, sizeof(streams));
1554d83f5bdSDmitri Tikhonov    memset(&enpub, 0, sizeof(enpub));
1564d83f5bdSDmitri Tikhonov    lsquic_mm_init(&enpub.enp_mm);
1575392f7a3SLiteSpeed Tech    packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
1584d83f5bdSDmitri Tikhonov
1594d83f5bdSDmitri Tikhonov    setup_stream_contents(123, "Dude, where is my car?");
1604d83f5bdSDmitri Tikhonov    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
1614d83f5bdSDmitri Tikhonov            lsquic_packet_out_avail(packet_out),
1624d83f5bdSDmitri Tikhonov            streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
1634d83f5bdSDmitri Tikhonov            lsquic_stream_tosend_fin(&streams[0]),
1644d83f5bdSDmitri Tikhonov            lsquic_stream_tosend_sz(&streams[0]),
1654d83f5bdSDmitri Tikhonov            (gsf_read_f) lsquic_stream_tosend_read,
1664d83f5bdSDmitri Tikhonov            &streams[0]);
1674d83f5bdSDmitri Tikhonov    packet_out->po_data_sz += len;
1684d83f5bdSDmitri Tikhonov    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
1694d83f5bdSDmitri Tikhonov    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
1704d83f5bdSDmitri Tikhonov                                                QUIC_FRAME_STREAM, off, len);
1714d83f5bdSDmitri Tikhonov
1724d83f5bdSDmitri Tikhonov    /* We want to fill the packet just right so that PO_STREAM_END gets set */
1734d83f5bdSDmitri Tikhonov    const int exp = lsquic_packet_out_avail(packet_out);
1744d83f5bdSDmitri Tikhonov    setup_stream_contents_n(0, stream2_data, exp - 2);
1754d83f5bdSDmitri Tikhonov    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
1764d83f5bdSDmitri Tikhonov            lsquic_packet_out_avail(packet_out),
1774d83f5bdSDmitri Tikhonov            streams[1].id, lsquic_stream_tosend_offset(&streams[1]),
1784d83f5bdSDmitri Tikhonov            lsquic_stream_tosend_fin(&streams[1]),
1794d83f5bdSDmitri Tikhonov            lsquic_stream_tosend_sz(&streams[1]),
1804d83f5bdSDmitri Tikhonov            (gsf_read_f) lsquic_stream_tosend_read,
1814d83f5bdSDmitri Tikhonov            &streams[1]);
1824d83f5bdSDmitri Tikhonov    assert(len == exp);
1834d83f5bdSDmitri Tikhonov    packet_out->po_data_sz += len;
1844d83f5bdSDmitri Tikhonov    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
1854d83f5bdSDmitri Tikhonov    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[1],
1864d83f5bdSDmitri Tikhonov                                                QUIC_FRAME_STREAM, off, len);
1874d83f5bdSDmitri Tikhonov    assert(0 == lsquic_packet_out_avail(packet_out));   /* Same as len == exp check really */
1884d83f5bdSDmitri Tikhonov    packet_out->po_flags |= PO_STREAM_END;
1894d83f5bdSDmitri Tikhonov
1904d83f5bdSDmitri Tikhonov    assert(1 == streams[0].n_unacked);
1914d83f5bdSDmitri Tikhonov    assert(1 == streams[1].n_unacked);
192b8fa6195SDmitri Tikhonov    assert(lsquic_pofi_first(&pofi, packet_out));
1934d83f5bdSDmitri Tikhonov
1944d83f5bdSDmitri Tikhonov    streams[0].stream_flags |= STREAM_RST_SENT;
1954d83f5bdSDmitri Tikhonov
196292abba1SDmitri Tikhonov    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
1974d83f5bdSDmitri Tikhonov    assert(0 == streams[0].n_unacked);
1984d83f5bdSDmitri Tikhonov
1994d83f5bdSDmitri Tikhonov    assert(QUIC_FTBIT_STREAM == packet_out->po_frame_types);
200b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_first(&pofi, packet_out);
201b8fa6195SDmitri Tikhonov    assert(frec->fe_stream == &streams[1]);
2024d83f5bdSDmitri Tikhonov    assert(packet_out->po_data_sz == exp);
2034d83f5bdSDmitri Tikhonov
2044d83f5bdSDmitri Tikhonov    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
2054d83f5bdSDmitri Tikhonov    lsquic_mm_cleanup(&enpub.enp_mm);
2064d83f5bdSDmitri Tikhonov}
2074d83f5bdSDmitri Tikhonov
2084d83f5bdSDmitri Tikhonov
20950aadb33SDmitri Tikhonov/* This test is more involved.  We will construct the following packet:
21050aadb33SDmitri Tikhonov *
21150aadb33SDmitri Tikhonov *      | ACK | STREAM A | STREAM B | STREAM C | RST A | STREAM D | STREAM E
21250aadb33SDmitri Tikhonov *
21350aadb33SDmitri Tikhonov * and elide STREAM A, STREAM C, and STREAM E to get
21450aadb33SDmitri Tikhonov *
21550aadb33SDmitri Tikhonov *      | ACK | STREAM B | RST A | STREAM D |
21650aadb33SDmitri Tikhonov *
21750aadb33SDmitri Tikhonov * If `chop_regen' is set, ACK is dropped (this tests what happens when
21850aadb33SDmitri Tikhonov * packet is resent).
21950aadb33SDmitri Tikhonov *
22050aadb33SDmitri Tikhonov * This should test most of the corner cases.
22150aadb33SDmitri Tikhonov */
22250aadb33SDmitri Tikhonovstatic void
22350aadb33SDmitri Tikhonovelide_three_stream_frames (int chop_regen)
22450aadb33SDmitri Tikhonov{
225b8fa6195SDmitri Tikhonov    struct packet_out_frec_iter pofi;
22650aadb33SDmitri Tikhonov    struct lsquic_engine_public enpub;
22750aadb33SDmitri Tikhonov    lsquic_stream_t streams[5];
22850aadb33SDmitri Tikhonov    lsquic_packet_out_t *packet_out, *ref_out;
229b8fa6195SDmitri Tikhonov    struct frame_rec *frec;
23050aadb33SDmitri Tikhonov    unsigned short b_off, d_off;
23150aadb33SDmitri Tikhonov    int len;
23250aadb33SDmitri Tikhonov
23350aadb33SDmitri Tikhonov    memset(streams, 0, sizeof(streams));
23450aadb33SDmitri Tikhonov    memset(&enpub, 0, sizeof(enpub));
23550aadb33SDmitri Tikhonov    lsquic_mm_init(&enpub.enp_mm);
23650aadb33SDmitri Tikhonov
23750aadb33SDmitri Tikhonov    /* First, we construct the reference packet.  We will only use it to
23850aadb33SDmitri Tikhonov     * compare payload and sizes:
23950aadb33SDmitri Tikhonov     */
24050aadb33SDmitri Tikhonov    {
2415392f7a3SLiteSpeed Tech        ref_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
24250aadb33SDmitri Tikhonov        /* This is fake data for regeneration */
24350aadb33SDmitri Tikhonov        strcpy((char *) ref_out->po_data, "REGEN");
244b8fa6195SDmitri Tikhonov        lsquic_packet_out_add_frame(ref_out, &enpub.enp_mm, 0,
245b8fa6195SDmitri Tikhonov                                QUIC_FRAME_ACK, ref_out->po_data_sz, 5);
24650aadb33SDmitri Tikhonov        ref_out->po_data_sz = ref_out->po_regen_sz = 5;
24750aadb33SDmitri Tikhonov        /* STREAM B */
24850aadb33SDmitri Tikhonov        setup_stream_contents(123, "BBBBBBBBBB");
24950aadb33SDmitri Tikhonov        streams[0].id = 'B';
25050aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(ref_out->po_data + ref_out->po_data_sz,
25150aadb33SDmitri Tikhonov                lsquic_packet_out_avail(ref_out),
25250aadb33SDmitri Tikhonov                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
253bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[0]),
254bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[0]),
25550aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
25650aadb33SDmitri Tikhonov                &streams[0]);
25750aadb33SDmitri Tikhonov        b_off = ref_out->po_data_sz;
25850aadb33SDmitri Tikhonov        ref_out->po_data_sz += len;
25950aadb33SDmitri Tikhonov        len = pf->pf_gen_rst_frame(ref_out->po_data + ref_out->po_data_sz,
26050aadb33SDmitri Tikhonov                lsquic_packet_out_avail(ref_out), 'A', 133, 0);
26150aadb33SDmitri Tikhonov        ref_out->po_data_sz += len;
26250aadb33SDmitri Tikhonov        /* STREAM D */
26350aadb33SDmitri Tikhonov        setup_stream_contents(123, "DDDDDDDDDD");
26450aadb33SDmitri Tikhonov        streams[0].id = 'D';
26550aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(ref_out->po_data + ref_out->po_data_sz,
26650aadb33SDmitri Tikhonov                lsquic_packet_out_avail(ref_out),
26750aadb33SDmitri Tikhonov                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
268bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[0]),
269bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[0]),
27050aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
27150aadb33SDmitri Tikhonov                &streams[0]);
27250aadb33SDmitri Tikhonov        d_off = ref_out->po_data_sz;
27350aadb33SDmitri Tikhonov        ref_out->po_data_sz += len;
27450aadb33SDmitri Tikhonov    }
27550aadb33SDmitri Tikhonov
27650aadb33SDmitri Tikhonov    /* Construct packet from which we will elide streams.  Here, we attach
27750aadb33SDmitri Tikhonov     * stream objects to the packet.
27850aadb33SDmitri Tikhonov     */
27950aadb33SDmitri Tikhonov    {
2805392f7a3SLiteSpeed Tech        packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
28150aadb33SDmitri Tikhonov        /* This is fake data for regeneration */
28250aadb33SDmitri Tikhonov        strcpy((char *) packet_out->po_data, "REGEN");
283b8fa6195SDmitri Tikhonov        lsquic_packet_out_add_frame(packet_out, &enpub.enp_mm, 0,
284b8fa6195SDmitri Tikhonov                                QUIC_FRAME_ACK, packet_out->po_data_sz, 5);
28550aadb33SDmitri Tikhonov        packet_out->po_data_sz = packet_out->po_regen_sz = 5;
28650aadb33SDmitri Tikhonov        /* STREAM A */
28750aadb33SDmitri Tikhonov        setup_stream_contents(123, "AAAAAAAAAA");
28850aadb33SDmitri Tikhonov        streams[0].id = 'A';
28950aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
29050aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
29150aadb33SDmitri Tikhonov                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
292bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[0]),
293bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[0]),
29450aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
29550aadb33SDmitri Tikhonov                &streams[0]);
29650aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
297c51ce338SDmitri Tikhonov                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
29850aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
29950aadb33SDmitri Tikhonov        /* STREAM B */
30050aadb33SDmitri Tikhonov        setup_stream_contents(123, "BBBBBBBBBB");
30150aadb33SDmitri Tikhonov        streams[1].id = 'B';
30250aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
30350aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
30450aadb33SDmitri Tikhonov                streams[1].id, lsquic_stream_tosend_offset(&streams[1]),
305bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[1]),
306bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[1]),
30750aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
30850aadb33SDmitri Tikhonov                &streams[1]);
30950aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[1],
310c51ce338SDmitri Tikhonov                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
31150aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
31250aadb33SDmitri Tikhonov        /* STREAM C */
31350aadb33SDmitri Tikhonov        setup_stream_contents(123, "CCCCCCCCCC");
31450aadb33SDmitri Tikhonov        streams[2].id = 'C';
31550aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
31650aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
31750aadb33SDmitri Tikhonov                streams[2].id, lsquic_stream_tosend_offset(&streams[2]),
318bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[2]),
319bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[2]),
32050aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
32150aadb33SDmitri Tikhonov                &streams[2]);
32250aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[2],
323c51ce338SDmitri Tikhonov                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
32450aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
32550aadb33SDmitri Tikhonov        /* Reset A */
32650aadb33SDmitri Tikhonov        len = pf->pf_gen_rst_frame(packet_out->po_data + packet_out->po_data_sz,
32750aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out), 'A', 133, 0);
32850aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
3294d83f5bdSDmitri Tikhonov                                     QUIC_FRAME_RST_STREAM, packet_out->po_data_sz, len);
33050aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
33150aadb33SDmitri Tikhonov        /* STREAM D */
33250aadb33SDmitri Tikhonov        setup_stream_contents(123, "DDDDDDDDDD");
33350aadb33SDmitri Tikhonov        streams[3].id = 'D';
33450aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
33550aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
33650aadb33SDmitri Tikhonov                streams[3].id, lsquic_stream_tosend_offset(&streams[3]),
337bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[3]),
338bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[3]),
33950aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
34050aadb33SDmitri Tikhonov                &streams[3]);
34150aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[3],
342c51ce338SDmitri Tikhonov                                QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
34350aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
34450aadb33SDmitri Tikhonov        /* STREAM E */
34550aadb33SDmitri Tikhonov        setup_stream_contents(123, "EEEEEEEEEE");
34650aadb33SDmitri Tikhonov        streams[4].id = 'E';
34750aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
34850aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
34950aadb33SDmitri Tikhonov                streams[4].id, lsquic_stream_tosend_offset(&streams[4]),
350bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[4]),
351bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[4]),
35250aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
35350aadb33SDmitri Tikhonov                &streams[4]);
35450aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[4],
355c51ce338SDmitri Tikhonov                                QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
35650aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
35750aadb33SDmitri Tikhonov        packet_out->po_frame_types = (1 << QUIC_FRAME_STREAM) | (1 << QUIC_FRAME_RST_STREAM);
35850aadb33SDmitri Tikhonov    }
35950aadb33SDmitri Tikhonov
36050aadb33SDmitri Tikhonov    /* Reset streams A, C, and E: */
36150aadb33SDmitri Tikhonov    streams[0].stream_flags |= STREAM_RST_SENT;
36250aadb33SDmitri Tikhonov    streams[2].stream_flags |= STREAM_RST_SENT;
36350aadb33SDmitri Tikhonov    streams[4].stream_flags |= STREAM_RST_SENT;
36450aadb33SDmitri Tikhonov
36550aadb33SDmitri Tikhonov    if (chop_regen)
36650aadb33SDmitri Tikhonov        lsquic_packet_out_chop_regen(packet_out);
367292abba1SDmitri Tikhonov    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
36850aadb33SDmitri Tikhonov
36950aadb33SDmitri Tikhonov    assert(ref_out->po_data_sz == packet_out->po_data_sz + (chop_regen ? 5 : 0));
37050aadb33SDmitri Tikhonov    assert(ref_out->po_regen_sz == packet_out->po_regen_sz + (chop_regen ? 5 : 0));
37150aadb33SDmitri Tikhonov    if (chop_regen)
37250aadb33SDmitri Tikhonov        assert(0 == memcmp(ref_out->po_data + 5, packet_out->po_data, packet_out->po_data_sz));
37350aadb33SDmitri Tikhonov    else
37450aadb33SDmitri Tikhonov        assert(0 == memcmp(ref_out->po_data, packet_out->po_data, packet_out->po_data_sz));
37550aadb33SDmitri Tikhonov
37650aadb33SDmitri Tikhonov    assert(1 == streams[0].n_unacked);  /* Still has RST outstanding */
37750aadb33SDmitri Tikhonov    assert(1 == streams[1].n_unacked);
37850aadb33SDmitri Tikhonov    assert(0 == streams[2].n_unacked);
37950aadb33SDmitri Tikhonov    assert(1 == streams[3].n_unacked);
38050aadb33SDmitri Tikhonov    assert(0 == streams[4].n_unacked);
38150aadb33SDmitri Tikhonov
38250aadb33SDmitri Tikhonov    assert(packet_out->po_frame_types == ((1 << QUIC_FRAME_STREAM) | (1 << QUIC_FRAME_RST_STREAM)));
38350aadb33SDmitri Tikhonov
384b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_first(&pofi, packet_out);
385b8fa6195SDmitri Tikhonov    if (!chop_regen)
386b8fa6195SDmitri Tikhonov        frec = lsquic_pofi_next(&pofi);
387b8fa6195SDmitri Tikhonov    assert(frec->fe_stream == &streams[1]);
388b8fa6195SDmitri Tikhonov    assert(frec->fe_frame_type == QUIC_FRAME_STREAM);
389b8fa6195SDmitri Tikhonov    assert(frec->fe_off == b_off - (chop_regen ? 5 : 0));
39050aadb33SDmitri Tikhonov
391b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_next(&pofi);
392b8fa6195SDmitri Tikhonov    assert(frec->fe_stream == &streams[0]);
393b8fa6195SDmitri Tikhonov    assert(frec->fe_frame_type == QUIC_FRAME_RST_STREAM);
3944d83f5bdSDmitri Tikhonov
395b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_next(&pofi);
396b8fa6195SDmitri Tikhonov    assert(frec->fe_stream == &streams[3]);
397b8fa6195SDmitri Tikhonov    assert(frec->fe_frame_type == QUIC_FRAME_STREAM);
398b8fa6195SDmitri Tikhonov    assert(frec->fe_off == d_off - (chop_regen ? 5 : 0));
39950aadb33SDmitri Tikhonov
400b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_next(&pofi);
401b8fa6195SDmitri Tikhonov    assert(!frec);
40250aadb33SDmitri Tikhonov
4031e75f938SDmitri Tikhonov    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
4041e75f938SDmitri Tikhonov    lsquic_packet_out_destroy(ref_out, &enpub, NULL);
40550aadb33SDmitri Tikhonov    lsquic_mm_cleanup(&enpub.enp_mm);
40650aadb33SDmitri Tikhonov}
40750aadb33SDmitri Tikhonov
40850aadb33SDmitri Tikhonov
40950aadb33SDmitri Tikhonovint
41050aadb33SDmitri Tikhonovmain (void)
41150aadb33SDmitri Tikhonov{
41250aadb33SDmitri Tikhonov    /* TODO-ENDIAN: test with every PF */
41350aadb33SDmitri Tikhonov    elide_single_stream_frame();
4144d83f5bdSDmitri Tikhonov    shrink_packet_post_elision();
41550aadb33SDmitri Tikhonov    elide_three_stream_frames(0);
41650aadb33SDmitri Tikhonov    elide_three_stream_frames(1);
41750aadb33SDmitri Tikhonov
41850aadb33SDmitri Tikhonov    return 0;
41950aadb33SDmitri Tikhonov}
420