test_elision.c revision a74702c6
1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <errno.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <sys/queue.h>
8
9#include "lsquic.h"
10
11#include "lsquic_int_types.h"
12#include "lsquic_packet_common.h"
13#include "lsquic_packet_gquic.h"
14#include "lsquic_packet_out.h"
15#include "lsquic_parse.h"
16#include "lsquic_conn_flow.h"
17#include "lsquic_sfcw.h"
18#include "lsquic_varint.h"
19#include "lsquic_hq.h"
20#include "lsquic_hash.h"
21#include "lsquic_stream.h"
22#include "lsquic_types.h"
23#include "lsquic_malo.h"
24#include "lsquic_mm.h"
25#include "lsquic_engine_public.h"
26#include "lsquic_logger.h"
27
28
29//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043); // will not work on MSVC
30#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_043))
31
32static struct {
33    unsigned char   buf[0x1000];
34    size_t      bufsz;
35    uint64_t    off;
36} stream_contents;
37
38
39void
40setup_stream_contents (uint64_t off, const char *str)
41{
42    stream_contents.bufsz = strlen(str);
43    stream_contents.off   = off;
44    memcpy(stream_contents.buf, str, stream_contents.bufsz);
45}
46
47
48void
49setup_stream_contents_n (uint64_t off, const unsigned char *buf, size_t size)
50{
51    stream_contents.bufsz = size;
52    stream_contents.off   = off;
53    memcpy(stream_contents.buf, buf, size);
54}
55
56
57int
58lsquic_stream_tosend_fin (const lsquic_stream_t *stream)
59{
60    return 0;
61}
62
63
64uint64_t
65lsquic_stream_tosend_offset (const lsquic_stream_t *stream)
66{
67    return stream_contents.off;
68}
69
70
71size_t
72lsquic_stream_tosend_read (lsquic_stream_t *stream, void *buf, size_t len,
73                           int *reached_fin)
74{
75    if (stream_contents.bufsz < len)
76        len = stream_contents.bufsz;
77    memcpy(buf, stream_contents.buf, len);
78    *reached_fin = lsquic_stream_tosend_fin(stream);
79    return len;
80}
81
82
83size_t
84lsquic_stream_tosend_sz (const lsquic_stream_t *stream)
85{
86    return stream_contents.bufsz;
87}
88
89
90void
91lsquic_stream_acked (lsquic_stream_t *stream, enum quic_frame_type frame_type)
92{
93    --stream->n_unacked;
94}
95
96
97static void
98elide_single_stream_frame (void)
99{
100    struct packet_out_frec_iter pofi;
101    struct lsquic_engine_public enpub;
102    lsquic_stream_t streams[1];
103    lsquic_packet_out_t *packet_out;
104    int len, off = 0;
105
106    memset(streams, 0, sizeof(streams));
107    memset(&enpub, 0, sizeof(enpub));
108    lsquic_mm_init(&enpub.enp_mm);
109    packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
110
111    setup_stream_contents(123, "Dude, where is my car?");
112    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
113            lsquic_packet_out_avail(packet_out),
114            streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
115            lsquic_stream_tosend_fin(&streams[0]),
116            lsquic_stream_tosend_sz(&streams[0]),
117            (gsf_read_f) lsquic_stream_tosend_read,
118            &streams[0]);
119    packet_out->po_data_sz += len;
120    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
121    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
122                                                QUIC_FRAME_STREAM, off, len);
123    assert(1 == streams[0].n_unacked);
124    assert(lsquic_pofi_first(&pofi, packet_out));
125
126    streams[0].stream_flags |= STREAM_RST_SENT;
127
128    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
129    assert(0 == streams[0].n_unacked);
130    assert(0 == packet_out->po_frame_types);
131    assert(!lsquic_pofi_first(&pofi, packet_out));
132
133    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
134    lsquic_mm_cleanup(&enpub.enp_mm);
135}
136
137
138/* In this test, we check that if the last STREAM frame is moved due to
139 * elision and PO_STREAM_END is set, the packet size is adjusted.  This
140 * is needed to prevent data corruption for STREAM frames that have
141 * implicit length.
142 */
143static void
144shrink_packet_post_elision (void)
145{
146    struct packet_out_frec_iter pofi;
147    struct lsquic_engine_public enpub;
148    lsquic_stream_t streams[2];
149    lsquic_packet_out_t *packet_out;
150    const struct frame_rec *frec;
151    int len, off = 0;
152    unsigned char stream2_data[0x1000];
153
154    memset(stream2_data, '2', sizeof(stream2_data));
155    memset(streams, 0, sizeof(streams));
156    memset(&enpub, 0, sizeof(enpub));
157    lsquic_mm_init(&enpub.enp_mm);
158    packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
159
160    setup_stream_contents(123, "Dude, where is my car?");
161    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
162            lsquic_packet_out_avail(packet_out),
163            streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
164            lsquic_stream_tosend_fin(&streams[0]),
165            lsquic_stream_tosend_sz(&streams[0]),
166            (gsf_read_f) lsquic_stream_tosend_read,
167            &streams[0]);
168    packet_out->po_data_sz += len;
169    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
170    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
171                                                QUIC_FRAME_STREAM, off, len);
172
173    /* We want to fill the packet just right so that PO_STREAM_END gets set */
174    const int exp = lsquic_packet_out_avail(packet_out);
175    setup_stream_contents_n(0, stream2_data, exp - 2);
176    len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
177            lsquic_packet_out_avail(packet_out),
178            streams[1].id, lsquic_stream_tosend_offset(&streams[1]),
179            lsquic_stream_tosend_fin(&streams[1]),
180            lsquic_stream_tosend_sz(&streams[1]),
181            (gsf_read_f) lsquic_stream_tosend_read,
182            &streams[1]);
183    assert(len == exp);
184    packet_out->po_data_sz += len;
185    packet_out->po_frame_types |= (1 << QUIC_FRAME_STREAM);
186    lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[1],
187                                                QUIC_FRAME_STREAM, off, len);
188    assert(0 == lsquic_packet_out_avail(packet_out));   /* Same as len == exp check really */
189    packet_out->po_flags |= PO_STREAM_END;
190
191    assert(1 == streams[0].n_unacked);
192    assert(1 == streams[1].n_unacked);
193    assert(lsquic_pofi_first(&pofi, packet_out));
194
195    streams[0].stream_flags |= STREAM_RST_SENT;
196
197    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
198    assert(0 == streams[0].n_unacked);
199
200    assert(QUIC_FTBIT_STREAM == packet_out->po_frame_types);
201    frec = lsquic_pofi_first(&pofi, packet_out);
202    assert(frec->fe_stream == &streams[1]);
203    assert(packet_out->po_data_sz == exp);
204
205    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
206    lsquic_mm_cleanup(&enpub.enp_mm);
207}
208
209
210/* This test is more involved.  We will construct the following packet:
211 *
212 *      | ACK | STREAM A | STREAM B | STREAM C | RST A | STREAM D | STREAM E
213 *
214 * and elide STREAM A, STREAM C, and STREAM E to get
215 *
216 *      | ACK | STREAM B | RST A | STREAM D |
217 *
218 * If `chop_regen' is set, ACK is dropped (this tests what happens when
219 * packet is resent).
220 *
221 * This should test most of the corner cases.
222 */
223static void
224elide_three_stream_frames (int chop_regen)
225{
226    struct packet_out_frec_iter pofi;
227    struct lsquic_engine_public enpub;
228    lsquic_stream_t streams[5];
229    lsquic_packet_out_t *packet_out, *ref_out;
230    struct frame_rec *frec;
231    unsigned short b_off, d_off;
232    int len;
233
234    memset(streams, 0, sizeof(streams));
235    memset(&enpub, 0, sizeof(enpub));
236    lsquic_mm_init(&enpub.enp_mm);
237
238    /* First, we construct the reference packet.  We will only use it to
239     * compare payload and sizes:
240     */
241    {
242        ref_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
243        /* This is fake data for regeneration */
244        strcpy((char *) ref_out->po_data, "REGEN");
245        lsquic_packet_out_add_frame(ref_out, &enpub.enp_mm, 0,
246                                QUIC_FRAME_ACK, ref_out->po_data_sz, 5);
247        ref_out->po_data_sz = ref_out->po_regen_sz = 5;
248        /* STREAM B */
249        setup_stream_contents(123, "BBBBBBBBBB");
250        streams[0].id = 'B';
251        len = pf->pf_gen_stream_frame(ref_out->po_data + ref_out->po_data_sz,
252                lsquic_packet_out_avail(ref_out),
253                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
254                lsquic_stream_tosend_fin(&streams[0]),
255                lsquic_stream_tosend_sz(&streams[0]),
256                (gsf_read_f) lsquic_stream_tosend_read,
257                &streams[0]);
258        b_off = ref_out->po_data_sz;
259        ref_out->po_data_sz += len;
260        len = pf->pf_gen_rst_frame(ref_out->po_data + ref_out->po_data_sz,
261                lsquic_packet_out_avail(ref_out), 'A', 133, 0);
262        ref_out->po_data_sz += len;
263        /* STREAM D */
264        setup_stream_contents(123, "DDDDDDDDDD");
265        streams[0].id = 'D';
266        len = pf->pf_gen_stream_frame(ref_out->po_data + ref_out->po_data_sz,
267                lsquic_packet_out_avail(ref_out),
268                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
269                lsquic_stream_tosend_fin(&streams[0]),
270                lsquic_stream_tosend_sz(&streams[0]),
271                (gsf_read_f) lsquic_stream_tosend_read,
272                &streams[0]);
273        d_off = ref_out->po_data_sz;
274        ref_out->po_data_sz += len;
275    }
276
277    /* Construct packet from which we will elide streams.  Here, we attach
278     * stream objects to the packet.
279     */
280    {
281        packet_out = lsquic_mm_get_packet_out(&enpub.enp_mm, NULL, GQUIC_MAX_PAYLOAD_SZ);
282        /* This is fake data for regeneration */
283        strcpy((char *) packet_out->po_data, "REGEN");
284        lsquic_packet_out_add_frame(packet_out, &enpub.enp_mm, 0,
285                                QUIC_FRAME_ACK, packet_out->po_data_sz, 5);
286        packet_out->po_data_sz = packet_out->po_regen_sz = 5;
287        /* STREAM A */
288        setup_stream_contents(123, "AAAAAAAAAA");
289        streams[0].id = 'A';
290        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
291                lsquic_packet_out_avail(packet_out),
292                streams[0].id, lsquic_stream_tosend_offset(&streams[0]),
293                lsquic_stream_tosend_fin(&streams[0]),
294                lsquic_stream_tosend_sz(&streams[0]),
295                (gsf_read_f) lsquic_stream_tosend_read,
296                &streams[0]);
297        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
298                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
299        packet_out->po_data_sz += len;
300        /* STREAM B */
301        setup_stream_contents(123, "BBBBBBBBBB");
302        streams[1].id = 'B';
303        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
304                lsquic_packet_out_avail(packet_out),
305                streams[1].id, lsquic_stream_tosend_offset(&streams[1]),
306                lsquic_stream_tosend_fin(&streams[1]),
307                lsquic_stream_tosend_sz(&streams[1]),
308                (gsf_read_f) lsquic_stream_tosend_read,
309                &streams[1]);
310        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[1],
311                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
312        packet_out->po_data_sz += len;
313        /* STREAM C */
314        setup_stream_contents(123, "CCCCCCCCCC");
315        streams[2].id = 'C';
316        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
317                lsquic_packet_out_avail(packet_out),
318                streams[2].id, lsquic_stream_tosend_offset(&streams[2]),
319                lsquic_stream_tosend_fin(&streams[2]),
320                lsquic_stream_tosend_sz(&streams[2]),
321                (gsf_read_f) lsquic_stream_tosend_read,
322                &streams[2]);
323        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[2],
324                                    QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
325        packet_out->po_data_sz += len;
326        /* Reset A */
327        len = pf->pf_gen_rst_frame(packet_out->po_data + packet_out->po_data_sz,
328                lsquic_packet_out_avail(packet_out), 'A', 133, 0);
329        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[0],
330                                     QUIC_FRAME_RST_STREAM, packet_out->po_data_sz, len);
331        packet_out->po_data_sz += len;
332        /* STREAM D */
333        setup_stream_contents(123, "DDDDDDDDDD");
334        streams[3].id = 'D';
335        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
336                lsquic_packet_out_avail(packet_out),
337                streams[3].id, lsquic_stream_tosend_offset(&streams[3]),
338                lsquic_stream_tosend_fin(&streams[3]),
339                lsquic_stream_tosend_sz(&streams[3]),
340                (gsf_read_f) lsquic_stream_tosend_read,
341                &streams[3]);
342        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[3],
343                                QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
344        packet_out->po_data_sz += len;
345        /* STREAM E */
346        setup_stream_contents(123, "EEEEEEEEEE");
347        streams[4].id = 'E';
348        len = pf->pf_gen_stream_frame(packet_out->po_data + packet_out->po_data_sz,
349                lsquic_packet_out_avail(packet_out),
350                streams[4].id, lsquic_stream_tosend_offset(&streams[4]),
351                lsquic_stream_tosend_fin(&streams[4]),
352                lsquic_stream_tosend_sz(&streams[4]),
353                (gsf_read_f) lsquic_stream_tosend_read,
354                &streams[4]);
355        lsquic_packet_out_add_stream(packet_out, &enpub.enp_mm, &streams[4],
356                                QUIC_FRAME_STREAM, packet_out->po_data_sz, len);
357        packet_out->po_data_sz += len;
358        packet_out->po_frame_types = (1 << QUIC_FRAME_STREAM) | (1 << QUIC_FRAME_RST_STREAM);
359    }
360
361    /* Reset streams A, C, and E: */
362    streams[0].stream_flags |= STREAM_RST_SENT;
363    streams[2].stream_flags |= STREAM_RST_SENT;
364    streams[4].stream_flags |= STREAM_RST_SENT;
365
366    if (chop_regen)
367        lsquic_packet_out_chop_regen(packet_out);
368    lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
369
370    assert(ref_out->po_data_sz == packet_out->po_data_sz + (chop_regen ? 5 : 0));
371    assert(ref_out->po_regen_sz == packet_out->po_regen_sz + (chop_regen ? 5 : 0));
372    if (chop_regen)
373        assert(0 == memcmp(ref_out->po_data + 5, packet_out->po_data, packet_out->po_data_sz));
374    else
375        assert(0 == memcmp(ref_out->po_data, packet_out->po_data, packet_out->po_data_sz));
376
377    assert(1 == streams[0].n_unacked);  /* Still has RST outstanding */
378    assert(1 == streams[1].n_unacked);
379    assert(0 == streams[2].n_unacked);
380    assert(1 == streams[3].n_unacked);
381    assert(0 == streams[4].n_unacked);
382
383    assert(packet_out->po_frame_types == ((1 << QUIC_FRAME_STREAM) | (1 << QUIC_FRAME_RST_STREAM)));
384
385    frec = lsquic_pofi_first(&pofi, packet_out);
386    if (!chop_regen)
387        frec = lsquic_pofi_next(&pofi);
388    assert(frec->fe_stream == &streams[1]);
389    assert(frec->fe_frame_type == QUIC_FRAME_STREAM);
390    assert(frec->fe_off == b_off - (chop_regen ? 5 : 0));
391
392    frec = lsquic_pofi_next(&pofi);
393    assert(frec->fe_stream == &streams[0]);
394    assert(frec->fe_frame_type == QUIC_FRAME_RST_STREAM);
395
396    frec = lsquic_pofi_next(&pofi);
397    assert(frec->fe_stream == &streams[3]);
398    assert(frec->fe_frame_type == QUIC_FRAME_STREAM);
399    assert(frec->fe_off == d_off - (chop_regen ? 5 : 0));
400
401    frec = lsquic_pofi_next(&pofi);
402    assert(!frec);
403
404    lsquic_packet_out_destroy(packet_out, &enpub, NULL);
405    lsquic_packet_out_destroy(ref_out, &enpub, NULL);
406    lsquic_mm_cleanup(&enpub.enp_mm);
407}
408
409
410int
411main (void)
412{
413    /* TODO-ENDIAN: test with every PF */
414    elide_single_stream_frame();
415    shrink_packet_post_elision();
416    elide_three_stream_frames(0);
417    elide_three_stream_frames(1);
418
419    return 0;
420}
421