test_elision.c revision 292abba1
17d09751dSDmitri Tikhonov/* Copyright (c) 2017 - 2020 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