1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 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
29f07b3eaeSTyler Young//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043); // will not work on MSVC
30f07b3eaeSTyler Young#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_043))
3150aadb33SDmitri Tikhonov
3250aadb33SDmitri Tikhonovstatic struct {
334d83f5bdSDmitri Tikhonov    unsigned char   buf[0x1000];
3450aadb33SDmitri Tikhonov    size_t      bufsz;
3550aadb33SDmitri Tikhonov    uint64_t    off;
3650aadb33SDmitri Tikhonov} stream_contents;
3750aadb33SDmitri Tikhonov
3850aadb33SDmitri Tikhonov
3950aadb33SDmitri Tikhonovvoid
4050aadb33SDmitri Tikhonovsetup_stream_contents (uint64_t off, const char *str)
4150aadb33SDmitri Tikhonov{
4250aadb33SDmitri Tikhonov    stream_contents.bufsz = strlen(str);
4350aadb33SDmitri Tikhonov    stream_contents.off   = off;
4450aadb33SDmitri Tikhonov    memcpy(stream_contents.buf, str, stream_contents.bufsz);
4550aadb33SDmitri Tikhonov}
4650aadb33SDmitri Tikhonov
4750aadb33SDmitri Tikhonov
484d83f5bdSDmitri Tikhonovvoid
494d83f5bdSDmitri Tikhonovsetup_stream_contents_n (uint64_t off, const unsigned char *buf, size_t size)
504d83f5bdSDmitri Tikhonov{
514d83f5bdSDmitri Tikhonov    stream_contents.bufsz = size;
524d83f5bdSDmitri Tikhonov    stream_contents.off   = off;
534d83f5bdSDmitri Tikhonov    memcpy(stream_contents.buf, buf, size);
544d83f5bdSDmitri Tikhonov}
554d83f5bdSDmitri Tikhonov
564d83f5bdSDmitri Tikhonov
5750aadb33SDmitri Tikhonovint
5850aadb33SDmitri Tikhonovlsquic_stream_tosend_fin (const lsquic_stream_t *stream)
5950aadb33SDmitri Tikhonov{
6050aadb33SDmitri Tikhonov    return 0;
6150aadb33SDmitri Tikhonov}
6250aadb33SDmitri Tikhonov
6350aadb33SDmitri Tikhonov
6450aadb33SDmitri Tikhonovuint64_t
6550aadb33SDmitri Tikhonovlsquic_stream_tosend_offset (const lsquic_stream_t *stream)
6650aadb33SDmitri Tikhonov{
6750aadb33SDmitri Tikhonov    return stream_contents.off;
6850aadb33SDmitri Tikhonov}
6950aadb33SDmitri Tikhonov
7050aadb33SDmitri Tikhonov
7150aadb33SDmitri Tikhonovsize_t
7250aadb33SDmitri Tikhonovlsquic_stream_tosend_read (lsquic_stream_t *stream, void *buf, size_t len,
7350aadb33SDmitri Tikhonov                           int *reached_fin)
7450aadb33SDmitri Tikhonov{
7550aadb33SDmitri Tikhonov    if (stream_contents.bufsz < len)
7650aadb33SDmitri Tikhonov        len = stream_contents.bufsz;
7750aadb33SDmitri Tikhonov    memcpy(buf, stream_contents.buf, len);
7850aadb33SDmitri Tikhonov    *reached_fin = lsquic_stream_tosend_fin(stream);
7950aadb33SDmitri Tikhonov    return len;
8050aadb33SDmitri Tikhonov}
8150aadb33SDmitri Tikhonov
8250aadb33SDmitri Tikhonov
8350aadb33SDmitri Tikhonovsize_t
8450aadb33SDmitri Tikhonovlsquic_stream_tosend_sz (const lsquic_stream_t *stream)
8550aadb33SDmitri Tikhonov{
8650aadb33SDmitri Tikhonov    return stream_contents.bufsz;
8750aadb33SDmitri Tikhonov}
8850aadb33SDmitri Tikhonov
8950aadb33SDmitri Tikhonov
9050aadb33SDmitri Tikhonovvoid
915392f7a3SLiteSpeed Techlsquic_stream_acked (lsquic_stream_t *stream, enum quic_frame_type frame_type)
9250aadb33SDmitri Tikhonov{
9350aadb33SDmitri Tikhonov    --stream->n_unacked;
9450aadb33SDmitri Tikhonov}
9550aadb33SDmitri Tikhonov
9650aadb33SDmitri Tikhonov
9750aadb33SDmitri Tikhonovstatic void
9850aadb33SDmitri Tikhonovelide_single_stream_frame (void)
9950aadb33SDmitri Tikhonov{
100b8fa6195SDmitri Tikhonov    struct packet_out_frec_iter pofi;
10150aadb33SDmitri Tikhonov    struct lsquic_engine_public enpub;
10250aadb33SDmitri Tikhonov    lsquic_stream_t streams[1];
10350aadb33SDmitri Tikhonov    lsquic_packet_out_t *packet_out;
10450aadb33SDmitri Tikhonov    int len, off = 0;
10550aadb33SDmitri Tikhonov
10650aadb33SDmitri Tikhonov    memset(streams, 0, sizeof(streams));
10750aadb33SDmitri Tikhonov    memset(&enpub, 0, sizeof(enpub));
10850aadb33SDmitri Tikhonov    lsquic_mm_init(&enpub.enp_mm);
1095392f7a3SLiteSpeed Tech    packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
11050aadb33SDmitri Tikhonov
11150aadb33SDmitri Tikhonov    setup_stream_contents(123, "Dude, where is my car?");
11250aadb33SDmitri Tikhonov    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
11350aadb33SDmitri Tikhonov            lsquic_packet_out_avail(packet_out),
11450aadb33SDmitri Tikhonov            streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
115bfc7bfd8SDmitri Tikhonov            lsquic_stream_tosend_fin(&streams[0]),
116bfc7bfd8SDmitri Tikhonov            lsquic_stream_tosend_sz(&streams[0]),
11750aadb33SDmitri Tikhonov            (gsf_read_f) lsquic_stream_tosend_read,
11850aadb33SDmitri Tikhonov            &streams[0]);
11950aadb33SDmitri Tikhonov    packet_out->po_data_sz += len;
12050aadb33SDmitri Tikhonov    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
12150aadb33SDmitri Tikhonov    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
122c51ce338SDmitri Tikhonov                                                QUIC_FRAME_STREAM, off, len);
12350aadb33SDmitri Tikhonov    assert(1 == streams[0].n_unacked);
124b8fa6195SDmitri Tikhonov    assert(lsquic_pofi_first(&pofi, packet_out));
12550aadb33SDmitri Tikhonov
12650aadb33SDmitri Tikhonov    streams[0].stream_flags |= STREAM_RST_SENT;
12750aadb33SDmitri Tikhonov
128292abba1SDmitri Tikhonov    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
12950aadb33SDmitri Tikhonov    assert(0 == streams[0].n_unacked);
13050aadb33SDmitri Tikhonov    assert(0 == packet_out->po_frame_types);
131b8fa6195SDmitri Tikhonov    assert(!lsquic_pofi_first(&pofi, packet_out));
13250aadb33SDmitri Tikhonov
1331e75f938SDmitri Tikhonov    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
13450aadb33SDmitri Tikhonov    lsquic_mm_cleanup(&enpub.enp_mm);
13550aadb33SDmitri Tikhonov}
13650aadb33SDmitri Tikhonov
13750aadb33SDmitri Tikhonov
1384d83f5bdSDmitri Tikhonov/* In this test, we check that if the last STREAM frame is moved due to
1394d83f5bdSDmitri Tikhonov * elision and PO_STREAM_END is set, the packet size is adjusted.  This
1404d83f5bdSDmitri Tikhonov * is needed to prevent data corruption for STREAM frames that have
1414d83f5bdSDmitri Tikhonov * implicit length.
1424d83f5bdSDmitri Tikhonov */
1434d83f5bdSDmitri Tikhonovstatic void
1444d83f5bdSDmitri Tikhonovshrink_packet_post_elision (void)
1454d83f5bdSDmitri Tikhonov{
146b8fa6195SDmitri Tikhonov    struct packet_out_frec_iter pofi;
1474d83f5bdSDmitri Tikhonov    struct lsquic_engine_public enpub;
1484d83f5bdSDmitri Tikhonov    lsquic_stream_t streams[2];
1494d83f5bdSDmitri Tikhonov    lsquic_packet_out_t *packet_out;
150b8fa6195SDmitri Tikhonov    const struct frame_rec *frec;
1514d83f5bdSDmitri Tikhonov    int len, off = 0;
1524d83f5bdSDmitri Tikhonov    unsigned char stream2_data[0x1000];
1534d83f5bdSDmitri Tikhonov
1544d83f5bdSDmitri Tikhonov    memset(stream2_data, '2', sizeof(stream2_data));
1554d83f5bdSDmitri Tikhonov    memset(streams, 0, sizeof(streams));
1564d83f5bdSDmitri Tikhonov    memset(&enpub, 0, sizeof(enpub));
1574d83f5bdSDmitri Tikhonov    lsquic_mm_init(&enpub.enp_mm);
1585392f7a3SLiteSpeed Tech    packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
1594d83f5bdSDmitri Tikhonov
1604d83f5bdSDmitri Tikhonov    setup_stream_contents(123, "Dude, where is my car?");
1614d83f5bdSDmitri Tikhonov    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
1624d83f5bdSDmitri Tikhonov            lsquic_packet_out_avail(packet_out),
1634d83f5bdSDmitri Tikhonov            streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
1644d83f5bdSDmitri Tikhonov            lsquic_stream_tosend_fin(&streams[0]),
1654d83f5bdSDmitri Tikhonov            lsquic_stream_tosend_sz(&streams[0]),
1664d83f5bdSDmitri Tikhonov            (gsf_read_f) lsquic_stream_tosend_read,
1674d83f5bdSDmitri Tikhonov            &streams[0]);
1684d83f5bdSDmitri Tikhonov    packet_out->po_data_sz += len;
1694d83f5bdSDmitri Tikhonov    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
1704d83f5bdSDmitri Tikhonov    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
1714d83f5bdSDmitri Tikhonov                                                QUIC_FRAME_STREAM, off, len);
1724d83f5bdSDmitri Tikhonov
1734d83f5bdSDmitri Tikhonov    /* We want to fill the packet just right so that PO_STREAM_END gets set */
1744d83f5bdSDmitri Tikhonov    const int exp = lsquic_packet_out_avail(packet_out);
1754d83f5bdSDmitri Tikhonov    setup_stream_contents_n(0, stream2_data, exp - 2);
1764d83f5bdSDmitri Tikhonov    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
1774d83f5bdSDmitri Tikhonov            lsquic_packet_out_avail(packet_out),
1784d83f5bdSDmitri Tikhonov            streams[1].id, lsquic_stream_tosend_offset(&streams[1]),
1794d83f5bdSDmitri Tikhonov            lsquic_stream_tosend_fin(&streams[1]),
1804d83f5bdSDmitri Tikhonov            lsquic_stream_tosend_sz(&streams[1]),
1814d83f5bdSDmitri Tikhonov            (gsf_read_f) lsquic_stream_tosend_read,
1824d83f5bdSDmitri Tikhonov            &streams[1]);
1834d83f5bdSDmitri Tikhonov    assert(len == exp);
1844d83f5bdSDmitri Tikhonov    packet_out->po_data_sz += len;
1854d83f5bdSDmitri Tikhonov    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
1864d83f5bdSDmitri Tikhonov    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[1],
1874d83f5bdSDmitri Tikhonov                                                QUIC_FRAME_STREAM, off, len);
1884d83f5bdSDmitri Tikhonov    assert(0 == lsquic_packet_out_avail(packet_out));   /* Same as len == exp check really */
1894d83f5bdSDmitri Tikhonov    packet_out->po_flags |= PO_STREAM_END;
1904d83f5bdSDmitri Tikhonov
1914d83f5bdSDmitri Tikhonov    assert(1 == streams[0].n_unacked);
1924d83f5bdSDmitri Tikhonov    assert(1 == streams[1].n_unacked);
193b8fa6195SDmitri Tikhonov    assert(lsquic_pofi_first(&pofi, packet_out));
1944d83f5bdSDmitri Tikhonov
1954d83f5bdSDmitri Tikhonov    streams[0].stream_flags |= STREAM_RST_SENT;
1964d83f5bdSDmitri Tikhonov
197292abba1SDmitri Tikhonov    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
1984d83f5bdSDmitri Tikhonov    assert(0 == streams[0].n_unacked);
1994d83f5bdSDmitri Tikhonov
2004d83f5bdSDmitri Tikhonov    assert(QUIC_FTBIT_STREAM == packet_out->po_frame_types);
201b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_first(&pofi, packet_out);
202b8fa6195SDmitri Tikhonov    assert(frec->fe_stream == &streams[1]);
2034d83f5bdSDmitri Tikhonov    assert(packet_out->po_data_sz == exp);
2044d83f5bdSDmitri Tikhonov
2054d83f5bdSDmitri Tikhonov    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
2064d83f5bdSDmitri Tikhonov    lsquic_mm_cleanup(&enpub.enp_mm);
2074d83f5bdSDmitri Tikhonov}
2084d83f5bdSDmitri Tikhonov
2094d83f5bdSDmitri Tikhonov
21050aadb33SDmitri Tikhonov/* This test is more involved.  We will construct the following packet:
21150aadb33SDmitri Tikhonov *
21250aadb33SDmitri Tikhonov *      | ACK | STREAM A | STREAM B | STREAM C | RST A | STREAM D | STREAM E
21350aadb33SDmitri Tikhonov *
21450aadb33SDmitri Tikhonov * and elide STREAM A, STREAM C, and STREAM E to get
21550aadb33SDmitri Tikhonov *
21650aadb33SDmitri Tikhonov *      | ACK | STREAM B | RST A | STREAM D |
21750aadb33SDmitri Tikhonov *
21850aadb33SDmitri Tikhonov * If `chop_regen' is set, ACK is dropped (this tests what happens when
21950aadb33SDmitri Tikhonov * packet is resent).
22050aadb33SDmitri Tikhonov *
22150aadb33SDmitri Tikhonov * This should test most of the corner cases.
22250aadb33SDmitri Tikhonov */
22350aadb33SDmitri Tikhonovstatic void
22450aadb33SDmitri Tikhonovelide_three_stream_frames (int chop_regen)
22550aadb33SDmitri Tikhonov{
226b8fa6195SDmitri Tikhonov    struct packet_out_frec_iter pofi;
22750aadb33SDmitri Tikhonov    struct lsquic_engine_public enpub;
22850aadb33SDmitri Tikhonov    lsquic_stream_t streams[5];
22950aadb33SDmitri Tikhonov    lsquic_packet_out_t *packet_out, *ref_out;
230b8fa6195SDmitri Tikhonov    struct frame_rec *frec;
23150aadb33SDmitri Tikhonov    unsigned short b_off, d_off;
23250aadb33SDmitri Tikhonov    int len;
23350aadb33SDmitri Tikhonov
23450aadb33SDmitri Tikhonov    memset(streams, 0, sizeof(streams));
23550aadb33SDmitri Tikhonov    memset(&enpub, 0, sizeof(enpub));
23650aadb33SDmitri Tikhonov    lsquic_mm_init(&enpub.enp_mm);
23750aadb33SDmitri Tikhonov
23850aadb33SDmitri Tikhonov    /* First, we construct the reference packet.  We will only use it to
23950aadb33SDmitri Tikhonov     * compare payload and sizes:
24050aadb33SDmitri Tikhonov     */
24150aadb33SDmitri Tikhonov    {
2425392f7a3SLiteSpeed Tech        ref_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
24350aadb33SDmitri Tikhonov        /* This is fake data for regeneration */
24450aadb33SDmitri Tikhonov        strcpy((char *) ref_out->po_data, "REGEN");
245b8fa6195SDmitri Tikhonov        lsquic_packet_out_add_frame(ref_out, &enpub.enp_mm, 0,
246b8fa6195SDmitri Tikhonov                                QUIC_FRAME_ACK, ref_out->po_data_sz, 5);
24750aadb33SDmitri Tikhonov        ref_out->po_data_sz = ref_out->po_regen_sz = 5;
24850aadb33SDmitri Tikhonov        /* STREAM B */
24950aadb33SDmitri Tikhonov        setup_stream_contents(123, "BBBBBBBBBB");
25050aadb33SDmitri Tikhonov        streams[0].id = 'B';
25150aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(ref_out->po_data + ref_out->po_data_sz,
25250aadb33SDmitri Tikhonov                lsquic_packet_out_avail(ref_out),
25350aadb33SDmitri Tikhonov                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
254bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[0]),
255bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[0]),
25650aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
25750aadb33SDmitri Tikhonov                &streams[0]);
25850aadb33SDmitri Tikhonov        b_off = ref_out->po_data_sz;
25950aadb33SDmitri Tikhonov        ref_out->po_data_sz += len;
26050aadb33SDmitri Tikhonov        len = pf->pf_gen_rst_frame(ref_out->po_data + ref_out->po_data_sz,
26150aadb33SDmitri Tikhonov                lsquic_packet_out_avail(ref_out), 'A', 133, 0);
26250aadb33SDmitri Tikhonov        ref_out->po_data_sz += len;
26350aadb33SDmitri Tikhonov        /* STREAM D */
26450aadb33SDmitri Tikhonov        setup_stream_contents(123, "DDDDDDDDDD");
26550aadb33SDmitri Tikhonov        streams[0].id = 'D';
26650aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(ref_out->po_data + ref_out->po_data_sz,
26750aadb33SDmitri Tikhonov                lsquic_packet_out_avail(ref_out),
26850aadb33SDmitri Tikhonov                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
269bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[0]),
270bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[0]),
27150aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
27250aadb33SDmitri Tikhonov                &streams[0]);
27350aadb33SDmitri Tikhonov        d_off = ref_out->po_data_sz;
27450aadb33SDmitri Tikhonov        ref_out->po_data_sz += len;
27550aadb33SDmitri Tikhonov    }
27650aadb33SDmitri Tikhonov
27750aadb33SDmitri Tikhonov    /* Construct packet from which we will elide streams.  Here, we attach
27850aadb33SDmitri Tikhonov     * stream objects to the packet.
27950aadb33SDmitri Tikhonov     */
28050aadb33SDmitri Tikhonov    {
2815392f7a3SLiteSpeed Tech        packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
28250aadb33SDmitri Tikhonov        /* This is fake data for regeneration */
28350aadb33SDmitri Tikhonov        strcpy((char *) packet_out->po_data, "REGEN");
284b8fa6195SDmitri Tikhonov        lsquic_packet_out_add_frame(packet_out, &enpub.enp_mm, 0,
285b8fa6195SDmitri Tikhonov                                QUIC_FRAME_ACK, packet_out->po_data_sz, 5);
28650aadb33SDmitri Tikhonov        packet_out->po_data_sz = packet_out->po_regen_sz = 5;
28750aadb33SDmitri Tikhonov        /* STREAM A */
28850aadb33SDmitri Tikhonov        setup_stream_contents(123, "AAAAAAAAAA");
28950aadb33SDmitri Tikhonov        streams[0].id = 'A';
29050aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
29150aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
29250aadb33SDmitri Tikhonov                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
293bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[0]),
294bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[0]),
29550aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
29650aadb33SDmitri Tikhonov                &streams[0]);
29750aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
298c51ce338SDmitri Tikhonov                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
29950aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
30050aadb33SDmitri Tikhonov        /* STREAM B */
30150aadb33SDmitri Tikhonov        setup_stream_contents(123, "BBBBBBBBBB");
30250aadb33SDmitri Tikhonov        streams[1].id = 'B';
30350aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
30450aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
30550aadb33SDmitri Tikhonov                streams[1].id, lsquic_stream_tosend_offset(&streams[1]),
306bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[1]),
307bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[1]),
30850aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
30950aadb33SDmitri Tikhonov                &streams[1]);
31050aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[1],
311c51ce338SDmitri Tikhonov                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
31250aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
31350aadb33SDmitri Tikhonov        /* STREAM C */
31450aadb33SDmitri Tikhonov        setup_stream_contents(123, "CCCCCCCCCC");
31550aadb33SDmitri Tikhonov        streams[2].id = 'C';
31650aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
31750aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
31850aadb33SDmitri Tikhonov                streams[2].id, lsquic_stream_tosend_offset(&streams[2]),
319bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[2]),
320bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[2]),
32150aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
32250aadb33SDmitri Tikhonov                &streams[2]);
32350aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[2],
324c51ce338SDmitri Tikhonov                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
32550aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
32650aadb33SDmitri Tikhonov        /* Reset A */
32750aadb33SDmitri Tikhonov        len = pf->pf_gen_rst_frame(packet_out->po_data + packet_out->po_data_sz,
32850aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out), 'A', 133, 0);
32950aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
3304d83f5bdSDmitri Tikhonov                                     QUIC_FRAME_RST_STREAM, packet_out->po_data_sz, len);
33150aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
33250aadb33SDmitri Tikhonov        /* STREAM D */
33350aadb33SDmitri Tikhonov        setup_stream_contents(123, "DDDDDDDDDD");
33450aadb33SDmitri Tikhonov        streams[3].id = 'D';
33550aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
33650aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
33750aadb33SDmitri Tikhonov                streams[3].id, lsquic_stream_tosend_offset(&streams[3]),
338bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[3]),
339bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[3]),
34050aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
34150aadb33SDmitri Tikhonov                &streams[3]);
34250aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[3],
343c51ce338SDmitri Tikhonov                                QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
34450aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
34550aadb33SDmitri Tikhonov        /* STREAM E */
34650aadb33SDmitri Tikhonov        setup_stream_contents(123, "EEEEEEEEEE");
34750aadb33SDmitri Tikhonov        streams[4].id = 'E';
34850aadb33SDmitri Tikhonov        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
34950aadb33SDmitri Tikhonov                lsquic_packet_out_avail(packet_out),
35050aadb33SDmitri Tikhonov                streams[4].id, lsquic_stream_tosend_offset(&streams[4]),
351bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_fin(&streams[4]),
352bfc7bfd8SDmitri Tikhonov                lsquic_stream_tosend_sz(&streams[4]),
35350aadb33SDmitri Tikhonov                (gsf_read_f) lsquic_stream_tosend_read,
35450aadb33SDmitri Tikhonov                &streams[4]);
35550aadb33SDmitri Tikhonov        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[4],
356c51ce338SDmitri Tikhonov                                QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
35750aadb33SDmitri Tikhonov        packet_out->po_data_sz += len;
35850aadb33SDmitri Tikhonov        packet_out->po_frame_types = (1 << QUIC_FRAME_STREAM) | (1 << QUIC_FRAME_RST_STREAM);
35950aadb33SDmitri Tikhonov    }
36050aadb33SDmitri Tikhonov
36150aadb33SDmitri Tikhonov    /* Reset streams A, C, and E: */
36250aadb33SDmitri Tikhonov    streams[0].stream_flags |= STREAM_RST_SENT;
36350aadb33SDmitri Tikhonov    streams[2].stream_flags |= STREAM_RST_SENT;
36450aadb33SDmitri Tikhonov    streams[4].stream_flags |= STREAM_RST_SENT;
36550aadb33SDmitri Tikhonov
36650aadb33SDmitri Tikhonov    if (chop_regen)
36750aadb33SDmitri Tikhonov        lsquic_packet_out_chop_regen(packet_out);
368292abba1SDmitri Tikhonov    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
36950aadb33SDmitri Tikhonov
37050aadb33SDmitri Tikhonov    assert(ref_out->po_data_sz == packet_out->po_data_sz + (chop_regen ? 5 : 0));
37150aadb33SDmitri Tikhonov    assert(ref_out->po_regen_sz == packet_out->po_regen_sz + (chop_regen ? 5 : 0));
37250aadb33SDmitri Tikhonov    if (chop_regen)
37350aadb33SDmitri Tikhonov        assert(0 == memcmp(ref_out->po_data + 5, packet_out->po_data, packet_out->po_data_sz));
37450aadb33SDmitri Tikhonov    else
37550aadb33SDmitri Tikhonov        assert(0 == memcmp(ref_out->po_data, packet_out->po_data, packet_out->po_data_sz));
37650aadb33SDmitri Tikhonov
37750aadb33SDmitri Tikhonov    assert(1 == streams[0].n_unacked);  /* Still has RST outstanding */
37850aadb33SDmitri Tikhonov    assert(1 == streams[1].n_unacked);
37950aadb33SDmitri Tikhonov    assert(0 == streams[2].n_unacked);
38050aadb33SDmitri Tikhonov    assert(1 == streams[3].n_unacked);
38150aadb33SDmitri Tikhonov    assert(0 == streams[4].n_unacked);
38250aadb33SDmitri Tikhonov
38350aadb33SDmitri Tikhonov    assert(packet_out->po_frame_types == ((1 << QUIC_FRAME_STREAM) | (1 << QUIC_FRAME_RST_STREAM)));
38450aadb33SDmitri Tikhonov
385b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_first(&pofi, packet_out);
386b8fa6195SDmitri Tikhonov    if (!chop_regen)
387b8fa6195SDmitri Tikhonov        frec = lsquic_pofi_next(&pofi);
388b8fa6195SDmitri Tikhonov    assert(frec->fe_stream == &streams[1]);
389b8fa6195SDmitri Tikhonov    assert(frec->fe_frame_type == QUIC_FRAME_STREAM);
390b8fa6195SDmitri Tikhonov    assert(frec->fe_off == b_off - (chop_regen ? 5 : 0));
39150aadb33SDmitri Tikhonov
392b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_next(&pofi);
393b8fa6195SDmitri Tikhonov    assert(frec->fe_stream == &streams[0]);
394b8fa6195SDmitri Tikhonov    assert(frec->fe_frame_type == QUIC_FRAME_RST_STREAM);
3954d83f5bdSDmitri Tikhonov
396b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_next(&pofi);
397b8fa6195SDmitri Tikhonov    assert(frec->fe_stream == &streams[3]);
398b8fa6195SDmitri Tikhonov    assert(frec->fe_frame_type == QUIC_FRAME_STREAM);
399b8fa6195SDmitri Tikhonov    assert(frec->fe_off == d_off - (chop_regen ? 5 : 0));
40050aadb33SDmitri Tikhonov
401b8fa6195SDmitri Tikhonov    frec = lsquic_pofi_next(&pofi);
402b8fa6195SDmitri Tikhonov    assert(!frec);
40350aadb33SDmitri Tikhonov
4041e75f938SDmitri Tikhonov    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
4051e75f938SDmitri Tikhonov    lsquic_packet_out_destroy(ref_out, &enpub, NULL);
40650aadb33SDmitri Tikhonov    lsquic_mm_cleanup(&enpub.enp_mm);
40750aadb33SDmitri Tikhonov}
40850aadb33SDmitri Tikhonov
40950aadb33SDmitri Tikhonov
41050aadb33SDmitri Tikhonovint
41150aadb33SDmitri Tikhonovmain (void)
41250aadb33SDmitri Tikhonov{
41350aadb33SDmitri Tikhonov    /* TODO-ENDIAN: test with every PF */
41450aadb33SDmitri Tikhonov    elide_single_stream_frame();
4154d83f5bdSDmitri Tikhonov    shrink_packet_post_elision();
41650aadb33SDmitri Tikhonov    elide_three_stream_frames(0);
41750aadb33SDmitri Tikhonov    elide_three_stream_frames(1);
41850aadb33SDmitri Tikhonov
41950aadb33SDmitri Tikhonov    return 0;
42050aadb33SDmitri Tikhonov}
421