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