test_stream.c revision 71eb4000
1/* Copyright (c) 2017 - 2020 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#include <sys/types.h> 9#include <fcntl.h> 10#include <limits.h> 11#ifndef WIN32 12#include <unistd.h> 13#else 14#include <getopt.h> 15#endif 16 17#include "lsquic.h" 18 19#include "lsquic_packet_common.h" 20#include "lsquic_alarmset.h" 21#include "lsquic_packet_in.h" 22#include "lsquic_conn_flow.h" 23#include "lsquic_rtt.h" 24#include "lsquic_sfcw.h" 25#include "lsquic_varint.h" 26#include "lsquic_hq.h" 27#include "lsquic_hash.h" 28#include "lsquic_stream.h" 29#include "lsquic_types.h" 30#include "lsquic_malo.h" 31#include "lsquic_mm.h" 32#include "lsquic_conn_public.h" 33#include "lsquic_logger.h" 34#include "lsquic_parse.h" 35#include "lsquic_conn.h" 36#include "lsquic_engine_public.h" 37#include "lsquic_cubic.h" 38#include "lsquic_pacer.h" 39#include "lsquic_senhist.h" 40#include "lsquic_bw_sampler.h" 41#include "lsquic_minmax.h" 42#include "lsquic_bbr.h" 43#include "lsquic_adaptive_cc.h" 44#include "lsquic_send_ctl.h" 45#include "lsquic_ver_neg.h" 46#include "lsquic_packet_out.h" 47#include "lsquic_enc_sess.h" 48#include "lsqpack.h" 49#include "lsquic_frab_list.h" 50#include "lsquic_qenc_hdl.h" 51#include "lsquic_varint.h" 52#include "lsquic_hq.h" 53#include "lsquic_data_in_if.h" 54 55static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_043); 56 57static int g_use_crypto_ctor; 58 59struct test_ctl_settings 60{ 61 int tcs_schedule_stream_packets_immediately; 62 int tcs_have_delayed_packets; 63 int tcs_can_send; 64 int tcs_write_ack; 65 enum buf_packet_type 66 tcs_bp_type; 67 enum packno_bits 68 tcs_guess_packno_bits, 69 tcs_calc_packno_bits; 70}; 71 72 73static struct test_ctl_settings g_ctl_settings; 74 75 76static void 77init_buf (void *buf, size_t sz); 78 79 80/* Set values to default */ 81static void 82init_test_ctl_settings (struct test_ctl_settings *settings) 83{ 84 settings->tcs_schedule_stream_packets_immediately = 1; 85 settings->tcs_have_delayed_packets = 0; 86 settings->tcs_can_send = 1; 87 settings->tcs_write_ack = 0; 88 settings->tcs_bp_type = BPT_HIGHEST_PRIO; 89 settings->tcs_guess_packno_bits = GQUIC_PACKNO_LEN_2; 90 settings->tcs_calc_packno_bits = GQUIC_PACKNO_LEN_2; 91} 92 93 94#if __GNUC__ 95__attribute__((unused)) 96#endif 97static void 98apply_test_ctl_settings (const struct test_ctl_settings *settings) 99{ 100 g_ctl_settings = *settings; 101} 102 103 104enum packno_bits 105lsquic_send_ctl_calc_packno_bits (struct lsquic_send_ctl *ctl) 106{ 107 return g_ctl_settings.tcs_calc_packno_bits; 108} 109 110 111int 112lsquic_send_ctl_schedule_stream_packets_immediately (struct lsquic_send_ctl *ctl) 113{ 114 return g_ctl_settings.tcs_schedule_stream_packets_immediately; 115} 116 117 118int 119lsquic_send_ctl_have_delayed_packets (const struct lsquic_send_ctl *ctl) 120{ 121 return g_ctl_settings.tcs_have_delayed_packets; 122} 123 124 125int 126lsquic_send_ctl_can_send (struct lsquic_send_ctl *ctl) 127{ 128 return g_ctl_settings.tcs_can_send; 129} 130 131 132enum packno_bits 133lsquic_send_ctl_guess_packno_bits (struct lsquic_send_ctl *ctl) 134{ 135 return g_ctl_settings.tcs_guess_packno_bits; 136} 137 138 139enum buf_packet_type 140lsquic_send_ctl_determine_bpt (struct lsquic_send_ctl *ctl, 141 const struct lsquic_stream *stream) 142{ 143 return g_ctl_settings.tcs_bp_type; 144} 145 146 147/* This function is only here to avoid crash in the test: */ 148void 149lsquic_engine_add_conn_to_tickable (struct lsquic_engine_public *enpub, 150 lsquic_conn_t *conn) 151{ 152} 153 154 155static unsigned n_closed; 156static enum stream_ctor_flags stream_ctor_flags = 157 SCF_CALL_ON_NEW|SCF_DI_AUTOSWITCH; 158 159struct test_ctx { 160 lsquic_stream_t *stream; 161}; 162 163 164static lsquic_stream_ctx_t * 165on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream) 166{ 167 struct test_ctx *test_ctx = stream_if_ctx; 168 test_ctx->stream = stream; 169 return NULL; 170} 171 172 173static void 174on_close (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h) 175{ 176 ++n_closed; 177} 178 179 180static struct reset_call_ctx { 181 struct lsquic_stream *stream; 182 int how; 183} s_onreset_called = { NULL, -1, }; 184 185 186static void 187on_reset (lsquic_stream_t *stream, lsquic_stream_ctx_t *h, int how) 188{ 189 s_onreset_called = (struct reset_call_ctx) { stream, how, }; 190} 191 192 193const struct lsquic_stream_if stream_if = { 194 .on_new_stream = on_new_stream, 195 .on_close = on_close, 196 .on_reset = on_reset, 197}; 198 199 200/* This does not do anything beyond just acking the packet: we do not attempt 201 * to update the send controller to have the correct state. 202 */ 203static void 204ack_packet (lsquic_send_ctl_t *send_ctl, lsquic_packno_t packno) 205{ 206 struct lsquic_packet_out *packet_out; 207 TAILQ_FOREACH(packet_out, &send_ctl->sc_unacked_packets[PNS_APP], po_next) 208 if (packet_out->po_packno == packno) 209 { 210 lsquic_packet_out_ack_streams(packet_out); 211 return; 212 } 213 assert(0); 214} 215 216 217static size_t 218read_from_scheduled_packets (lsquic_send_ctl_t *send_ctl, lsquic_stream_id_t stream_id, 219 unsigned char *const begin, size_t bufsz, uint64_t first_offset, int *p_fin, 220 int fullcheck) 221{ 222 const struct parse_funcs *const pf_local = send_ctl->sc_conn_pub->lconn->cn_pf; 223 unsigned char *p = begin; 224 unsigned char *const end = p + bufsz; 225 const struct frame_rec *frec; 226 struct packet_out_frec_iter pofi; 227 struct lsquic_packet_out *packet_out; 228 struct stream_frame frame; 229 enum quic_frame_type expected_type; 230 int len, fin = 0; 231 232 if (g_use_crypto_ctor) 233 expected_type = QUIC_FRAME_CRYPTO; 234 else 235 expected_type = QUIC_FRAME_STREAM; 236 237 TAILQ_FOREACH(packet_out, &send_ctl->sc_scheduled_packets, po_next) 238 for (frec = lsquic_pofi_first(&pofi, packet_out); frec; 239 frec = lsquic_pofi_next(&pofi)) 240 { 241 if (fullcheck) 242 { 243 assert(frec->fe_frame_type == expected_type); 244 if (packet_out->po_packno != 1) 245 { 246 /* First packet may contain two stream frames, do not 247 * check it. 248 */ 249 assert(!lsquic_pofi_next(&pofi)); 250 if (TAILQ_NEXT(packet_out, po_next)) 251 { 252 assert(packet_out->po_data_sz == packet_out->po_n_alloc); 253 assert(frec->fe_len == packet_out->po_data_sz); 254 } 255 } 256 } 257 if (frec->fe_frame_type == expected_type && 258 frec->fe_stream->id == stream_id) 259 { 260 assert(!fin); 261 if (QUIC_FRAME_STREAM == expected_type) 262 len = pf_local->pf_parse_stream_frame(packet_out->po_data + frec->fe_off, 263 packet_out->po_data_sz - frec->fe_off, &frame); 264 else 265 len = pf_local->pf_parse_crypto_frame(packet_out->po_data + frec->fe_off, 266 packet_out->po_data_sz - frec->fe_off, &frame); 267 assert(len > 0); 268 if (QUIC_FRAME_STREAM == expected_type) 269 assert(frame.stream_id == frec->fe_stream->id); 270 else 271 assert(frame.stream_id == ~0ULL); 272 /* Otherwise not enough to copy to: */ 273 assert(end - p >= frame.data_frame.df_size); 274 /* Checks offset ordering: */ 275 assert(frame.data_frame.df_offset == 276 first_offset + (uintptr_t) (p - begin)); 277 if (frame.data_frame.df_fin) 278 { 279 assert(!fin); 280 fin = 1; 281 } 282 memcpy(p, packet_out->po_data + frec->fe_off + len - 283 frame.data_frame.df_size, frame.data_frame.df_size); 284 p += frame.data_frame.df_size; 285 } 286 } 287 288 if (p_fin) 289 *p_fin = fin; 290 return p + bufsz - end; 291} 292 293 294static struct test_ctx test_ctx; 295 296 297struct test_objs { 298 struct lsquic_conn lconn; 299 struct lsquic_engine_public eng_pub; 300 struct lsquic_conn_public conn_pub; 301 struct lsquic_send_ctl send_ctl; 302 struct lsquic_alarmset alset; 303 void *stream_if_ctx; 304 struct ver_neg ver_neg; 305 const struct lsquic_stream_if * 306 stream_if; 307 unsigned initial_stream_window; 308 enum stream_ctor_flags ctor_flags; 309 struct qpack_enc_hdl qeh; 310}; 311 312 313static struct network_path network_path; 314 315static struct network_path * 316get_network_path (struct lsquic_conn *lconn, const struct sockaddr *sa) 317{ 318 return &network_path; 319} 320 321 322static int 323can_write_ack (struct lsquic_conn *lconn) 324{ 325 return g_ctl_settings.tcs_write_ack; 326} 327 328 329static void 330write_ack (struct lsquic_conn *lconn, struct lsquic_packet_out *packet_out) 331{ 332 struct test_objs *const tobjs = (void *) lconn; 333 const size_t ack_size = 9; /* Arbitrary */ 334 int s; 335 336 packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK; 337 s = lsquic_packet_out_add_frame(packet_out, &tobjs->eng_pub.enp_mm, 0, 338 QUIC_FRAME_ACK, packet_out->po_data_sz, ack_size); 339 assert(s == 0); 340 memcpy(packet_out->po_data + packet_out->po_data_sz, "ACKACKACK", 9); 341 lsquic_send_ctl_incr_pack_sz(&tobjs->send_ctl, packet_out, ack_size); 342 packet_out->po_regen_sz += ack_size; 343} 344 345 346static const struct conn_iface our_conn_if = 347{ 348 .ci_can_write_ack = can_write_ack, 349 .ci_get_path = get_network_path, 350 .ci_write_ack = write_ack, 351}; 352 353static struct conn_stats s_conn_stats; 354 355static void 356init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window, 357 unsigned initial_stream_window, const struct parse_funcs *pf) 358{ 359 int s; 360 memset(tobjs, 0, sizeof(*tobjs)); 361 LSCONN_INITIALIZE(&tobjs->lconn); 362 tobjs->lconn.cn_pf = pf ? pf : g_pf; 363 tobjs->lconn.cn_version = tobjs->lconn.cn_pf == &lsquic_parse_funcs_ietf_v1 ? 364 LSQVER_ID27 : LSQVER_043; 365 tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_gquic_1; 366 network_path.np_pack_size = 1370; 367 tobjs->lconn.cn_if = &our_conn_if; 368 lsquic_mm_init(&tobjs->eng_pub.enp_mm); 369 TAILQ_INIT(&tobjs->conn_pub.sending_streams); 370 TAILQ_INIT(&tobjs->conn_pub.read_streams); 371 TAILQ_INIT(&tobjs->conn_pub.write_streams); 372 TAILQ_INIT(&tobjs->conn_pub.service_streams); 373 lsquic_cfcw_init(&tobjs->conn_pub.cfcw, &tobjs->conn_pub, 374 initial_conn_window); 375 lsquic_conn_cap_init(&tobjs->conn_pub.conn_cap, initial_conn_window); 376 lsquic_alarmset_init(&tobjs->alset, 0); 377 tobjs->conn_pub.mm = &tobjs->eng_pub.enp_mm; 378 tobjs->conn_pub.lconn = &tobjs->lconn; 379 tobjs->conn_pub.enpub = &tobjs->eng_pub; 380 tobjs->conn_pub.send_ctl = &tobjs->send_ctl; 381 tobjs->conn_pub.packet_out_malo = 382 lsquic_malo_create(sizeof(struct lsquic_packet_out)); 383 tobjs->conn_pub.path = &network_path; 384 tobjs->conn_pub.conn_stats = &s_conn_stats; 385 tobjs->initial_stream_window = initial_stream_window; 386 lsquic_send_ctl_init(&tobjs->send_ctl, &tobjs->alset, &tobjs->eng_pub, 387 &tobjs->ver_neg, &tobjs->conn_pub, 0); 388 tobjs->stream_if = &stream_if; 389 tobjs->stream_if_ctx = &test_ctx; 390 tobjs->ctor_flags = stream_ctor_flags; 391 if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS) 392 { 393 lsquic_qeh_init(&tobjs->qeh, &tobjs->lconn); 394 s = lsquic_qeh_settings(&tobjs->qeh, 0, 0, 0, 0); 395 assert(0 == s); 396 tobjs->conn_pub.u.ietf.qeh = &tobjs->qeh; 397 } 398} 399 400 401static void 402deinit_test_objs (struct test_objs *tobjs) 403{ 404 assert(!lsquic_malo_first(tobjs->eng_pub.enp_mm.malo.stream_frame)); 405 lsquic_send_ctl_cleanup(&tobjs->send_ctl); 406 lsquic_malo_destroy(tobjs->conn_pub.packet_out_malo); 407 lsquic_mm_cleanup(&tobjs->eng_pub.enp_mm); 408 if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS) 409 { 410 lsquic_qeh_cleanup(&tobjs->qeh); 411 } 412} 413 414 415/* Create a new stream frame. Each stream frame has a real packet_in to 416 * back it up, just like in real code. The contents of the packet do 417 * not matter. 418 */ 419static stream_frame_t * 420new_frame_in_ext (struct test_objs *tobjs, size_t off, size_t sz, int fin, 421 const void *data) 422{ 423 lsquic_packet_in_t *packet_in; 424 stream_frame_t *frame; 425 426 assert(sz <= 1370); 427 428 packet_in = lsquic_mm_get_packet_in(&tobjs->eng_pub.enp_mm); 429 if (data) 430 packet_in->pi_data = (void *) data; 431 else 432 { 433 packet_in->pi_data = lsquic_mm_get_packet_in_buf(&tobjs->eng_pub.enp_mm, 1370); 434 packet_in->pi_flags |= PI_OWN_DATA; 435 memset(packet_in->pi_data, 'A', sz); 436 } 437 /* This is not how stream frame looks in the packet: we have no 438 * header. In our test case it does not matter, as we only care 439 * about stream frame. 440 */ 441 packet_in->pi_data_sz = sz; 442 packet_in->pi_refcnt = 1; 443 444 frame = lsquic_malo_get(tobjs->eng_pub.enp_mm.malo.stream_frame); 445 memset(frame, 0, sizeof(*frame)); 446 frame->packet_in = packet_in; 447 frame->data_frame.df_offset = off; 448 frame->data_frame.df_size = sz; 449 frame->data_frame.df_data = &packet_in->pi_data[0]; 450 frame->data_frame.df_fin = fin; 451 452 return frame; 453} 454 455 456static stream_frame_t * 457new_frame_in (struct test_objs *tobjs, size_t off, size_t sz, int fin) 458{ 459 return new_frame_in_ext(tobjs, off, sz, fin, NULL); 460} 461 462 463static lsquic_stream_t * 464new_stream_ext (struct test_objs *tobjs, unsigned stream_id, uint64_t send_off) 465{ 466 enum stream_ctor_flags ctor_flags; 467 468 if (g_use_crypto_ctor) 469 return lsquic_stream_new_crypto(stream_id, &tobjs->conn_pub, 470 tobjs->stream_if, tobjs->stream_if_ctx, 471 tobjs->ctor_flags | SCF_CRITICAL); 472 else 473 { 474 /* For the purposes of the unit test, consider streams 1 and 3 critical */ 475 if (stream_id == 3 || stream_id == 1) 476 ctor_flags = SCF_CRITICAL; 477 else 478 ctor_flags = 0; 479 if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS) 480 ctor_flags |= SCF_IETF; 481 return lsquic_stream_new(stream_id, &tobjs->conn_pub, tobjs->stream_if, 482 tobjs->stream_if_ctx, tobjs->initial_stream_window, send_off, 483 tobjs->ctor_flags | ctor_flags); 484 } 485} 486 487 488static lsquic_stream_t * 489new_stream (struct test_objs *tobjs, unsigned stream_id) 490{ 491 return new_stream_ext(tobjs, stream_id, 16 * 1024); 492} 493 494 495static void 496run_frame_ordering_test (uint64_t run_id /* This is used to make it easier to set breakpoints */, 497 int *idx, size_t idx_sz, int read_asap) 498{ 499 int s; 500 size_t nw = 0, i; 501 char buf[0x1000]; 502 503 struct test_objs tobjs; 504 505 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 506 507 lsquic_stream_t *stream = new_stream(&tobjs, 123); 508 struct lsquic_mm *const mm = &tobjs.eng_pub.enp_mm; 509 struct malo *const frame_malo = mm->malo.stream_frame; 510 511 lsquic_packet_in_t *packet_in = lsquic_mm_get_packet_in(mm); 512 packet_in->pi_data = lsquic_mm_get_packet_in_buf(mm, 1370); 513 packet_in->pi_flags |= PI_OWN_DATA; 514 assert(idx_sz <= 10); 515 memcpy(packet_in->pi_data, "0123456789", 10); 516 packet_in->pi_data_sz = 10; 517 packet_in->pi_refcnt = idx_sz; 518 519 printf("inserting "); 520 for (i = 0; i < idx_sz; ++i) 521 { 522 stream_frame_t *frame; 523 frame = lsquic_malo_get(frame_malo); 524 memset(frame, 0, sizeof(*frame)); 525 frame->packet_in = packet_in; 526 frame->data_frame.df_offset = idx[i]; 527 if (idx[i] + 1 == (int) idx_sz) 528 { 529 printf("<FIN>"); 530 frame->data_frame.df_size = 0; 531 frame->data_frame.df_fin = 1; 532 } 533 else 534 { 535 printf("%c", packet_in->pi_data[idx[i]]); 536 frame->data_frame.df_size = 1; 537 frame->data_frame.df_data = &packet_in->pi_data[idx[i]]; 538 } 539 if (frame->data_frame.df_fin && read_asap && i + 1 == idx_sz) 540 { /* Last frame is the FIN frame. Read before inserting zero-sized 541 * FIN frame. 542 */ 543 nw = lsquic_stream_read(stream, buf, 10); 544 assert(("Read idx_sz bytes", nw == idx_sz - 1)); 545 assert(("Have not reached fin yet (frame has not come in)", 546 -1 == lsquic_stream_read(stream, buf, 1) && errno == EWOULDBLOCK)); 547 } 548 s = lsquic_stream_frame_in(stream, frame); 549 assert(("Inserted frame", 0 == s)); 550 } 551 printf("\n"); 552 553 if (read_asap && nw == idx_sz - 1) 554 { 555 assert(("Reached fin", 0 == lsquic_stream_read(stream, buf, 1))); 556 } 557 else 558 { 559 nw = lsquic_stream_read(stream, buf, 10); 560 assert(("Read idx_sz bytes", nw == idx_sz - 1)); 561 assert(("Reached fin", 0 == lsquic_stream_read(stream, buf, 1))); 562 } 563 564 lsquic_stream_destroy(stream); 565 566 assert(("all frames have been released", !lsquic_malo_first(frame_malo))); 567 deinit_test_objs(&tobjs); 568} 569 570 571static void 572permute_and_run (uint64_t run_id, 573 int mask, int level, int *idx, size_t idx_sz) 574{ 575 size_t i; 576 for (i = 0; i < idx_sz; ++i) 577 { 578 if (!(mask & (1 << i))) 579 { 580 idx[level] = i; 581 if (level + 1 == (int) idx_sz) 582 { 583 run_frame_ordering_test(run_id, idx, idx_sz, 0); 584 run_frame_ordering_test(run_id, idx, idx_sz, 1); 585 } 586 else 587 permute_and_run(run_id | (i << (8 * level)), 588 mask | (1 << i), level + 1, idx, idx_sz); 589 } 590 } 591} 592 593 594/* Client: we send some data and FIN, and remote end sends some data and 595 * FIN. 596 */ 597static void 598test_loc_FIN_rem_FIN (struct test_objs *tobjs) 599{ 600 lsquic_stream_t *stream; 601 lsquic_packet_out_t *packet_out; 602 char buf_out[0x100]; 603 unsigned char buf[0x100]; 604 ssize_t n; 605 int s, fin; 606 enum stream_state_sending sss; 607 608 init_buf(buf_out, sizeof(buf_out)); 609 610 stream = new_stream(tobjs, 345); 611 n = lsquic_stream_write(stream, buf_out, 100); 612 assert(n == 100); 613 assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 614 615 s = lsquic_stream_flush(stream); 616 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 617 618 n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf, 619 sizeof(buf), 0, &fin, 0); 620 assert(100 == n); 621 assert(0 == memcmp(buf_out, buf, 100)); 622 assert(!fin); 623 624 /* Pretend we sent out a packet: */ 625 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 626 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 627 628 s = lsquic_stream_shutdown(stream, 1); 629 assert(s == 0); 630 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */ 631 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); /* No need to close stream yet */ 632 633 n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf, 634 sizeof(buf), 100, &fin, 0); 635 assert(0 == n); 636 assert(fin); 637 sss = lsquic_stream_sending_state(stream); 638 assert(SSS_DATA_SENT == sss); 639 640 /* Pretend we sent out this packet as well: */ 641 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 642 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 643 644 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); /* No need to close stream yet */ 645 646 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0)); 647 assert(0 == s); 648 649 n = lsquic_stream_read(stream, buf, 60); 650 assert(60 == n); 651 n = lsquic_stream_read(stream, buf, 60); 652 assert(40 == n); 653 654 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 100, 0, 1)); 655 assert(0 == s); 656 n = lsquic_stream_read(stream, buf, 60); 657 assert(0 == n); 658 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 659 660 s = lsquic_stream_shutdown(stream, 0); 661 assert(0 == s); 662 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 663 assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE)); 664 ack_packet(&tobjs->send_ctl, 1); 665 ack_packet(&tobjs->send_ctl, 2); 666 assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE|SMQF_FREE_STREAM)); 667 sss = lsquic_stream_sending_state(stream); 668 assert(SSS_DATA_RECVD == sss); 669 670 lsquic_stream_destroy(stream); 671 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 672 673 assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off); 674 assert(100 == tobjs->conn_pub.cfcw.cf_read_off); 675} 676 677 678/* Server: we read data and FIN, and then send data and FIN. 679 */ 680static void 681test_rem_FIN_loc_FIN (struct test_objs *tobjs) 682{ 683 lsquic_stream_t *stream; 684 char buf_out[0x100]; 685 unsigned char buf[0x100]; 686 size_t n; 687 int s, fin; 688 lsquic_packet_out_t *packet_out; 689 690 stream = new_stream(tobjs, 345); 691 692 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0)); 693 assert(0 == s); 694 695 n = lsquic_stream_read(stream, buf, 60); 696 assert(60 == n); 697 n = lsquic_stream_read(stream, buf, 60); 698 assert(40 == n); 699 700 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 100, 0, 1)); 701 assert(0 == s); 702 n = lsquic_stream_read(stream, buf, 60); 703 assert(0 == n); 704 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 705 706 s = lsquic_stream_shutdown(stream, 0); 707 assert(0 == s); 708 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 709 710 init_buf(buf_out, sizeof(buf_out)); 711 n = lsquic_stream_write(stream, buf_out, 100); 712 assert(n == 100); 713 assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 714 715 s = lsquic_stream_flush(stream); 716 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 717 718 n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf, 719 sizeof(buf), 0, &fin, 0); 720 assert(100 == n); 721 assert(0 == memcmp(buf_out, buf, 100)); 722 assert(!fin); 723 724 /* Pretend we sent out a packet: */ 725 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 726 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 727 728 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); /* No need to close stream yet */ 729 730 s = lsquic_stream_shutdown(stream, 1); 731 assert(s == 0); 732 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */ 733 734 /* Now we can call on_close: */ 735 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 736 assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == SMQF_CALL_ONCLOSE); 737 738 n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf, 739 sizeof(buf), 100, &fin, 0); 740 assert(0 == n); 741 assert(fin); 742 743 /* Pretend we sent out this packet as well: */ 744 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 745 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 746 747 /* Cannot free stream yet: packets have not been acked */ 748 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 749 assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == SMQF_CALL_ONCLOSE); 750 751 ack_packet(&tobjs->send_ctl, 1); 752 ack_packet(&tobjs->send_ctl, 2); 753 754 /* Now we can free the stream: */ 755 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 756 assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE|SMQF_FREE_STREAM)); 757 758 lsquic_stream_destroy(stream); 759 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 760 761 assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off); 762 assert(100 == tobjs->conn_pub.cfcw.cf_read_off); 763} 764 765 766/* Server: we read data and close the read side before reading FIN, which 767 * results in stream being reset. 768 */ 769static void 770test_rem_data_loc_close_and_rst_in (struct test_objs *tobjs) 771{ 772 lsquic_stream_t *stream; 773 char buf[0x100]; 774 ssize_t n; 775 int s; 776 777 stream = new_stream(tobjs, 345); 778 779 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0)); 780 assert(0 == s); 781 782 n = lsquic_stream_read(stream, buf, 60); 783 assert(60 == n); 784 785 s = lsquic_stream_shutdown(stream, 0); 786 assert(0 == s); 787 /* Early read shutdown results in different frames on different QUIC 788 * transports: 789 */ 790 if (stream->sm_bflags & SMBF_IETF) 791 assert(stream->sm_qflags & SMQF_SEND_STOP_SENDING); 792 else 793 assert(stream->sm_qflags & SMQF_SEND_RST); 794 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 795 assert(!((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == SMQF_CALL_ONCLOSE)); 796 797 n = lsquic_stream_read(stream, buf, 60); 798 assert(n == -1); /* Cannot read from closed stream */ 799 800 /* Close write side */ 801 s = lsquic_stream_shutdown(stream, 1); 802 assert(0 == s); 803 804 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */ 805 assert(stream->n_unacked == 1); 806 807 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 808 assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == SMQF_CALL_ONCLOSE); 809 810 s_onreset_called = (struct reset_call_ctx) { NULL, -1, }; 811 s = lsquic_stream_rst_in(stream, 100, 1); 812 assert(0 == s); 813 assert(s_onreset_called.stream == stream); 814 if (stream->sm_bflags & SMBF_IETF) 815 assert(s_onreset_called.how == 0); 816 else 817 assert(s_onreset_called.how == 2); 818 819 assert(!(stream->sm_qflags & SMQF_FREE_STREAM)); /* Not yet */ 820 assert(stream->sm_qflags & SMQF_CALL_ONCLOSE); 821 822 lsquic_stream_rst_frame_sent(stream); 823 stream->n_unacked++; /* RESET frame take a reference */ 824 assert(!(stream->sm_qflags & SMQF_FREE_STREAM)); /* Not yet, 825 because: */ assert(stream->n_unacked == 2); 826 827 lsquic_stream_acked(stream, QUIC_FRAME_STREAM); 828 lsquic_stream_acked(stream, QUIC_FRAME_RST_STREAM); 829 assert(stream->sm_qflags & SMQF_FREE_STREAM); /* OK, now */ 830 831 lsquic_stream_destroy(stream); 832 /* This simply checks that the stream got removed from the queue: */ 833 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 834 835 assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off); 836 assert(100 == tobjs->conn_pub.cfcw.cf_read_off); 837} 838 839 840/* Server: we read data and close the read side before reading FIN. No 841 * FIN or RST arrive from peer. This should schedule RST_STREAM to be 842 * sent (this is gQUIC) and add "wait for known FIN" flag. 843 */ 844static void 845test_rem_data_loc_close (struct test_objs *tobjs) 846{ 847 lsquic_stream_t *stream; 848 char buf[0x100]; 849 ssize_t n; 850 int s; 851 852 stream = new_stream(tobjs, 345); 853 854 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0)); 855 assert(0 == s); 856 857 n = lsquic_stream_read(stream, buf, 60); 858 assert(60 == n); 859 860 s = lsquic_stream_shutdown(stream, 0); 861 assert(0 == s); 862 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 863 assert(!(stream->sm_qflags & SMQF_CALL_ONCLOSE)); 864 865 n = lsquic_stream_read(stream, buf, 60); 866 assert(n == -1); /* Cannot read from closed stream */ 867 868 /* Close write side */ 869 s = lsquic_stream_shutdown(stream, 1); 870 assert(0 == s); 871 872 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */ 873 874 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 875 assert(stream->sm_qflags & SMQF_CALL_ONCLOSE); 876 877 assert(!(stream->sm_qflags & SMQF_FREE_STREAM)); 878 lsquic_stream_acked(stream, QUIC_FRAME_STREAM); 879 880 lsquic_stream_rst_frame_sent(stream); 881 stream->n_unacked++; /* RESET frame take a reference */ 882 assert(!(stream->sm_qflags & SMQF_FREE_STREAM)); /* No */ 883 884 lsquic_stream_acked(stream, QUIC_FRAME_RST_STREAM); 885 assert(!(stream->sm_qflags & SMQF_FREE_STREAM)); /* Still no */ 886 887 /* Stream will linger until we have the offset: */ 888 assert(stream->sm_qflags & SMQF_WAIT_FIN_OFF); 889 890 lsquic_stream_destroy(stream); 891 /* This simply checks that the stream got removed from the queue: */ 892 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 893 894 assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off); 895 assert(100 == tobjs->conn_pub.cfcw.cf_read_off); 896} 897 898 899/* Client: we send some data and FIN, but remote end sends some data and 900 * then resets the stream. The client gets an error when it reads from 901 * stream, after which it closes and destroys the stream. 902 */ 903static void 904test_loc_FIN_rem_RST (struct test_objs *tobjs) 905{ 906 lsquic_packet_out_t *packet_out; 907 lsquic_stream_t *stream; 908 char buf_out[0x100]; 909 unsigned char buf[0x100]; 910 ssize_t n; 911 int s, fin; 912 913 init_buf(buf_out, sizeof(buf_out)); 914 915 stream = new_stream(tobjs, 345); 916 n = lsquic_stream_write(stream, buf_out, 100); 917 assert(n == 100); 918 assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 919 920 s = lsquic_stream_flush(stream); 921 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 922 923 n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf, 924 sizeof(buf), 0, &fin, 0); 925 assert(100 == n); 926 assert(0 == memcmp(buf_out, buf, 100)); 927 assert(!fin); 928 929 /* Pretend we sent out a packet: */ 930 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 931 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 932 933 s = lsquic_stream_shutdown(stream, 1); 934 assert(s == 0); 935 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */ 936 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); /* No need to close stream yet */ 937 938 n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf, 939 sizeof(buf), 100, &fin, 0); 940 assert(0 == n); 941 assert(fin); 942 943 /* Pretend we sent out this packet as well: */ 944 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 945 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 946 947 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); /* No need to close stream yet */ 948 949 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0)); 950 assert(0 == s); 951 s_onreset_called = (struct reset_call_ctx) { NULL, -1, }; 952 s = lsquic_stream_rst_in(stream, 100, 0); 953 assert(0 == s); 954 assert(s_onreset_called.stream == stream); 955 if (stream->sm_bflags & SMBF_IETF) 956 assert(s_onreset_called.how == 0); 957 else 958 assert(s_onreset_called.how == 2); 959 960 /* No RST to send, we already sent FIN */ 961 assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 962 963 /* The stream is not yet done: the user code has not closed it yet */ 964 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 965 assert(0 == (stream->sm_qflags & (SMQF_SERVICE_FLAGS))); 966 assert(0 == (stream->stream_flags & STREAM_U_READ_DONE)); 967 968 s = lsquic_stream_read(stream, buf, sizeof(buf)); 969 assert(-1 == s); /* Error collected */ 970 s = lsquic_stream_close(stream); 971 assert(0 == s); /* Stream closed successfully */ 972 973 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 974 assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE)); 975 976 ack_packet(&tobjs->send_ctl, 1); 977 ack_packet(&tobjs->send_ctl, 2); 978 979#if 0 980 /* OK, here we pretend that we sent a RESET and it was acked */ 981 assert(stream->sm_qflags & SMQF_SEND_RST); 982 stream->sm_qflags |= SMQF_SEND_RST; 983 stream->stream_flags 984#endif 985 986 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 987 assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE|SMQF_FREE_STREAM)); 988 989 lsquic_stream_destroy(stream); 990 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 991 992 assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off); 993 assert(100 == tobjs->conn_pub.cfcw.cf_read_off); 994} 995 996 997/* Client: we send some data (no FIN), and remote end sends some data and 998 * then resets the stream. 999 */ 1000static void 1001test_loc_data_rem_RST (struct test_objs *tobjs) 1002{ 1003 lsquic_packet_out_t *packet_out; 1004 lsquic_stream_t *stream; 1005 char buf_out[0x100]; 1006 unsigned char buf[0x100]; 1007 ssize_t n; 1008 int s, fin; 1009 1010 init_buf(buf_out, sizeof(buf_out)); 1011 1012 stream = new_stream(tobjs, 345); 1013 n = lsquic_stream_write(stream, buf_out, 100); 1014 assert(n == 100); 1015 assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1016 1017 s = lsquic_stream_flush(stream); 1018 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1019 1020 n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf, 1021 sizeof(buf), 0, &fin, 0); 1022 assert(100 == n); 1023 assert(0 == memcmp(buf_out, buf, 100)); 1024 assert(!fin); 1025 1026 /* Pretend we sent out a packet: */ 1027 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 1028 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 1029 1030 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0)); 1031 assert(0 == s); 1032 s_onreset_called = (struct reset_call_ctx) { NULL, -1, }; 1033 if (stream->sm_bflags & SMBF_IETF) 1034 lsquic_stream_stop_sending_in(stream, 12345); 1035 else 1036 { 1037 s = lsquic_stream_rst_in(stream, 200, 0); 1038 assert(0 == s); 1039 } 1040 assert(s_onreset_called.stream == stream); 1041 if (stream->sm_bflags & SMBF_IETF) 1042 assert(s_onreset_called.how == 1); 1043 else 1044 assert(s_onreset_called.how == 2); 1045 1046 ack_packet(&tobjs->send_ctl, 1); 1047 1048 if (!(stream->sm_bflags & SMBF_IETF)) 1049 { 1050 assert(!TAILQ_EMPTY(&tobjs->conn_pub.sending_streams)); 1051 assert((stream->sm_qflags & SMQF_SENDING_FLAGS) == SMQF_SEND_RST); 1052 } 1053 1054 /* Not yet closed: error needs to be collected */ 1055 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 1056 assert(0 == (stream->sm_qflags & SMQF_SERVICE_FLAGS)); 1057 1058 n = lsquic_stream_write(stream, buf, 100); 1059 assert(-1 == n); /* Error collected */ 1060 s = lsquic_stream_close(stream); 1061 assert(0 == s); /* Stream successfully closed */ 1062 1063 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 1064 assert((stream->sm_qflags & SMQF_SERVICE_FLAGS) == SMQF_CALL_ONCLOSE); 1065 1066 if (stream->sm_bflags & SMBF_IETF) 1067 lsquic_stream_ss_frame_sent(stream); 1068 lsquic_stream_rst_frame_sent(stream); 1069 lsquic_stream_call_on_close(stream); 1070 1071 assert(TAILQ_EMPTY(&tobjs->conn_pub.sending_streams)); 1072 if (stream->sm_bflags & SMBF_IETF) 1073 assert(stream->sm_qflags & SMQF_WAIT_FIN_OFF); 1074 else 1075 { 1076 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 1077 assert((stream->sm_qflags & SMQF_SERVICE_FLAGS) == SMQF_FREE_STREAM); 1078 } 1079 1080 const unsigned expected_nread = stream->sm_bflags & SMBF_IETF ? 100 : 200; 1081 lsquic_stream_destroy(stream); 1082 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 1083 1084 assert(expected_nread == tobjs->conn_pub.cfcw.cf_max_recv_off); 1085 assert(expected_nread == tobjs->conn_pub.cfcw.cf_read_off); 1086} 1087 1088 1089/* We send some data and RST, receive data and FIN 1090 */ 1091static void 1092test_loc_RST_rem_FIN (struct test_objs *tobjs) 1093{ 1094 lsquic_packet_out_t *packet_out; 1095 lsquic_stream_t *stream; 1096 char buf_out[0x100]; 1097 unsigned char buf[0x100]; 1098 size_t n; 1099 int s, fin; 1100 enum stream_state_sending sss; 1101 1102 init_buf(buf_out, sizeof(buf_out)); 1103 1104 stream = new_stream(tobjs, 345); 1105 1106 n = lsquic_stream_write(stream, buf_out, 100); 1107 assert(n == 100); 1108 assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1109 1110 s = lsquic_stream_flush(stream); 1111 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1112 1113 n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf, 1114 sizeof(buf), 0, &fin, 0); 1115 assert(100 == n); 1116 assert(0 == memcmp(buf_out, buf, 100)); 1117 assert(!fin); 1118 1119 /* Pretend we sent out a packet: */ 1120 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 1121 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 1122 1123 assert(1 == stream->n_unacked); 1124 ack_packet(&tobjs->send_ctl, 1); 1125 assert(0 == stream->n_unacked); 1126 sss = lsquic_stream_sending_state(stream); 1127 assert(SSS_SEND == sss); 1128 1129 lsquic_stream_reset(stream, 0); 1130 ++stream->n_unacked; /* Fake sending of packet with RST_STREAM */ 1131 assert(!TAILQ_EMPTY(&tobjs->conn_pub.sending_streams)); 1132 assert((stream->sm_qflags & SMQF_SENDING_FLAGS) == SMQF_SEND_RST); 1133 sss = lsquic_stream_sending_state(stream); 1134 assert(SSS_DATA_SENT == sss); /* FIN was packetized */ 1135 1136 s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 90, 1)); 1137 assert(s == 0); 1138 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 1139 assert((stream->sm_qflags & SMQF_SERVICE_FLAGS) == SMQF_CALL_ONCLOSE); 1140 1141 lsquic_stream_rst_frame_sent(stream); 1142 sss = lsquic_stream_sending_state(stream); 1143 assert(SSS_RESET_SENT == sss); 1144 1145 sss = lsquic_stream_sending_state(stream); 1146 assert(SSS_RESET_SENT == sss); 1147 lsquic_stream_acked(stream, QUIC_FRAME_RST_STREAM); /* Fake ack of RST_STREAM packet */ 1148 sss = lsquic_stream_sending_state(stream); 1149 assert(SSS_RESET_RECVD == sss); 1150 1151 assert(TAILQ_EMPTY(&tobjs->conn_pub.sending_streams)); 1152 1153 lsquic_stream_call_on_close(stream); 1154 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); /* Not acked yet */ 1155 lsquic_stream_acked(stream, QUIC_FRAME_STREAM); 1156 1157 assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 1158 assert((stream->sm_qflags & SMQF_SERVICE_FLAGS) == SMQF_FREE_STREAM); 1159 1160 lsquic_stream_destroy(stream); 1161 assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams)); 1162 1163 assert(90 == tobjs->conn_pub.cfcw.cf_max_recv_off); 1164 assert(90 == tobjs->conn_pub.cfcw.cf_read_off); 1165} 1166 1167 1168/* Test that when stream frame is elided and the packet is dropped, 1169 * the send controller produces a gapless sequence. 1170 * 1171 * Case "middle": 3 packets with STREAM frames for streams A, B, and A. 1172 * Stream B is reset. We should get a gapless sequence 1173 * of packets 1, 2. 1174 */ 1175static void 1176test_gapless_elision_middle (struct test_objs *tobjs) 1177{ 1178 lsquic_stream_t *streamA, *streamB; 1179 unsigned char buf[0x1000], buf_out[0x1000]; 1180 size_t n, thresh, written_to_A = 0; 1181 int s, fin; 1182 lsquic_packet_out_t *packet_out; 1183 1184 streamA = new_stream(tobjs, 345); 1185 streamB = new_stream(tobjs, 347); 1186 1187 init_buf(buf_out, sizeof(buf_out)); 1188 thresh = lsquic_stream_flush_threshold(streamA, 0); 1189 n = lsquic_stream_write(streamA, buf_out, thresh); 1190 assert(n == thresh); 1191 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1192 written_to_A += n; 1193 1194 thresh = lsquic_stream_flush_threshold(streamB, 0); 1195 n = lsquic_stream_write(streamB, buf_out, thresh); 1196 assert(n == thresh); 1197 assert(2 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1198 1199 thresh = lsquic_stream_flush_threshold(streamA, 0); 1200 n = lsquic_stream_write(streamA, buf_out + written_to_A, thresh); 1201 assert(n == thresh); 1202 assert(3 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1203 written_to_A += n; 1204 1205 /* Verify contents of A: */ 1206 n = read_from_scheduled_packets(&tobjs->send_ctl, streamA->id, buf, 1207 sizeof(buf), 0, &fin, 0); 1208 assert(n == written_to_A); 1209 assert(0 == memcmp(buf, buf_out, written_to_A)); 1210 1211 /* Now reset stream B: */ 1212 s_onreset_called = (struct reset_call_ctx) { NULL, -1, }; 1213 if (streamB->sm_bflags & SMBF_IETF) 1214 lsquic_stream_stop_sending_in(streamB, 12345); 1215 else 1216 { 1217 s = lsquic_stream_rst_in(streamB, 0, 0); 1218 assert(s == 0); 1219 } 1220 assert(s_onreset_called.stream == streamB); 1221 if (streamB->sm_bflags & SMBF_IETF) 1222 assert(s_onreset_called.how == 1); 1223 else 1224 assert(s_onreset_called.how == 2); 1225 assert(2 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1226 /* Verify A again: */ 1227 n = read_from_scheduled_packets(&tobjs->send_ctl, streamA->id, buf, 1228 sizeof(buf), 0, &fin, 0); 1229 assert(n == written_to_A); 1230 assert(0 == memcmp(buf, buf_out, written_to_A)); 1231 1232 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 1233 assert(packet_out->po_packno == 1); 1234 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 1235 1236 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 1237 assert(packet_out->po_packno == 2); 1238 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 1239 1240 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 1241 assert(!packet_out); 1242 1243 /* Now we can call on_close: */ 1244 lsquic_stream_destroy(streamA); 1245 lsquic_stream_destroy(streamB); 1246} 1247 1248 1249/* Test that when stream frame is elided and the packet is dropped, 1250 * the send controller produces a gapless sequence. 1251 * 1252 * Case "beginnig": 3 packets with STREAM frames for streams B, A, and A. 1253 * Stream B is reset. We should get a gapless sequence 1254 * of packets 1, 2. 1255 */ 1256static void 1257test_gapless_elision_beginning (struct test_objs *tobjs) 1258{ 1259 lsquic_stream_t *streamA, *streamB; 1260 unsigned char buf[0x1000], buf_out[0x1000]; 1261 size_t n, thresh, written_to_A = 0; 1262 int s, fin; 1263 lsquic_packet_out_t *packet_out; 1264 1265 streamA = new_stream(tobjs, 345); 1266 streamB = new_stream(tobjs, 347); 1267 1268 init_buf(buf_out, sizeof(buf_out)); 1269 1270 thresh = lsquic_stream_flush_threshold(streamB, 0); 1271 n = lsquic_stream_write(streamB, buf_out, thresh); 1272 assert(n == thresh); 1273 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1274 1275 thresh = lsquic_stream_flush_threshold(streamA, 0); 1276 n = lsquic_stream_write(streamA, buf_out, thresh); 1277 assert(n == thresh); 1278 assert(2 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1279 written_to_A += n; 1280 1281 thresh = lsquic_stream_flush_threshold(streamA, 0); 1282 n = lsquic_stream_write(streamA, buf_out + written_to_A, thresh); 1283 assert(n == thresh); 1284 assert(3 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1285 written_to_A += n; 1286 1287 /* Verify contents of A: */ 1288 n = read_from_scheduled_packets(&tobjs->send_ctl, streamA->id, buf, 1289 sizeof(buf), 0, &fin, 0); 1290 assert(n == written_to_A); 1291 assert(0 == memcmp(buf, buf_out, written_to_A)); 1292 1293 /* Now reset stream B: */ 1294 assert(!(streamB->stream_flags & STREAM_FRAMES_ELIDED)); 1295 if (streamB->sm_bflags & SMBF_IETF) 1296 lsquic_stream_stop_sending_in(streamB, 12345); 1297 else 1298 { 1299 s = lsquic_stream_rst_in(streamB, 0, 0); 1300 assert(s == 0); 1301 } 1302 assert(streamB->stream_flags & STREAM_FRAMES_ELIDED); 1303 assert(2 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1304 /* Verify A again: */ 1305 n = read_from_scheduled_packets(&tobjs->send_ctl, streamA->id, buf, 1306 sizeof(buf), 0, &fin, 0); 1307 assert(n == written_to_A); 1308 assert(0 == memcmp(buf, buf_out, written_to_A)); 1309 1310 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 1311 assert(packet_out->po_packno == 1); 1312 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 1313 1314 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 1315 assert(packet_out->po_packno == 2); 1316 lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out); 1317 1318 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0); 1319 assert(!packet_out); 1320 1321 /* Test on_reset() behavior. This is unrelated to the gapless elision 1322 * test, but convenient to do here. 1323 */ 1324 if (streamA->sm_bflags & SMBF_IETF) 1325 { 1326 s_onreset_called = (struct reset_call_ctx) { NULL, -1, }; 1327 lsquic_stream_stop_sending_in(streamA, 12345); 1328 assert(s_onreset_called.stream == streamA); 1329 assert(s_onreset_called.how == 1); 1330 } 1331 1332 /* Now we can call on_close: */ 1333 lsquic_stream_destroy(streamA); 1334 lsquic_stream_destroy(streamB); 1335} 1336 1337 1338 1339/* Write data to the stream, but do not flush: connection cap take a hit. 1340 * After stream is destroyed, connection cap should go back up. 1341 */ 1342static void 1343test_reset_stream_with_unflushed_data (struct test_objs *tobjs) 1344{ 1345 lsquic_stream_t *stream; 1346 char buf[0x100]; 1347 size_t n; 1348 const struct lsquic_conn_cap *const cap = &tobjs->conn_pub.conn_cap; 1349 1350 assert(0x4000 == lsquic_conn_cap_avail(cap)); /* Self-check */ 1351 stream = new_stream(tobjs, 345); 1352 n = lsquic_stream_write(stream, buf, 100); 1353 assert(n == 100); 1354 1355 /* Unflushed data counts towards connection cap for connection-limited 1356 * stream: 1357 */ 1358 assert(0x4000 - 100 == lsquic_conn_cap_avail(cap)); 1359 1360 lsquic_stream_destroy(stream); 1361 assert(0x4000 == lsquic_conn_cap_avail(cap)); /* Goes back up */ 1362} 1363 1364 1365/* Write a little data to the stream, flush and then reset it: connection 1366 * cap should NOT go back up. 1367 */ 1368static void 1369test_reset_stream_with_flushed_data (struct test_objs *tobjs) 1370{ 1371 char buf[0x100]; 1372 size_t n; 1373 lsquic_stream_t *stream; 1374 const struct lsquic_conn_cap *const cap = &tobjs->conn_pub.conn_cap; 1375 1376 assert(0x4000 == lsquic_conn_cap_avail(cap)); /* Self-check */ 1377 stream = new_stream(tobjs, 345); 1378 n = lsquic_stream_write(stream, buf, 100); 1379 assert(n == 100); 1380 1381 /* Unflushed data counts towards connection cap for 1382 * connection-limited stream: 1383 */ 1384 assert(0x4000 - 100 == lsquic_conn_cap_avail(cap)); 1385 1386 /* Flush the stream: */ 1387 lsquic_stream_flush(stream); 1388 assert(0x4000 - 100 == lsquic_conn_cap_avail(cap)); 1389 1390 lsquic_stream_destroy(stream); 1391 assert(0x4000 - 100 == lsquic_conn_cap_avail(cap)); /* Still unchanged */ 1392} 1393 1394 1395/* Write data to the handshake stream and flush: this should not affect 1396 * connection cap. 1397 */ 1398static void 1399test_unlimited_stream_flush_data (struct test_objs *tobjs) 1400{ 1401 char buf[0x100]; 1402 size_t n; 1403 lsquic_stream_t *stream; 1404 const struct lsquic_conn_cap *const cap = &tobjs->conn_pub.conn_cap; 1405 1406 assert(0x4000 == lsquic_conn_cap_avail(cap)); /* Self-check */ 1407 stream = new_stream(tobjs, 1); 1408 n = lsquic_stream_write(stream, buf, 100); 1409 assert(n == 100); 1410 1411 /* We DO NOT take connection cap hit after stream is flushed: */ 1412 lsquic_stream_flush(stream); 1413 assert(0x4000 == lsquic_conn_cap_avail(cap)); 1414 1415 lsquic_stream_reset(stream, 0xF00DF00D); 1416 assert(0x4000 == lsquic_conn_cap_avail(cap)); /* Still unchanged */ 1417 1418 lsquic_stream_destroy(stream); 1419 assert(0x4000 == lsquic_conn_cap_avail(cap)); /* Still unchanged */ 1420} 1421 1422 1423/* Test that data gets flushed when stream is closed. */ 1424static void 1425test_data_flush_on_close (struct test_objs *tobjs) 1426{ 1427 lsquic_stream_t *stream; 1428 const struct lsquic_conn_cap *const cap = &tobjs->conn_pub.conn_cap; 1429 char buf[0x100]; 1430 size_t n; 1431 1432 assert(0x4000 == lsquic_conn_cap_avail(cap)); /* Self-check */ 1433 stream = new_stream(tobjs, 345); 1434 n = lsquic_stream_write(stream, buf, 100); 1435 assert(n == 100); 1436 assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1437 1438 lsquic_stream_close(stream); 1439 /* Nothing is scheduled because STREAM frames are elided */ 1440 assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); 1441 1442 assert(stream->sm_qflags & SMQF_SEND_RST); 1443 assert(!(stream->sm_qflags & SMQF_FREE_STREAM)); 1444 assert(stream->sm_qflags & SMQF_WAIT_FIN_OFF); 1445 1446 /* We take connection cap hit after stream is flushed: */ 1447 assert(0x4000 - 100 == lsquic_conn_cap_avail(cap)); /* Conn cap hit */ 1448 1449 lsquic_stream_destroy(stream); 1450} 1451 1452 1453/* In this function, we test stream termination conditions. In particular, 1454 * we are interested in when the stream becomes finished (this is when 1455 * connection closes it and starts ignoring frames that come after this): 1456 * we need to test the following scenarios, both normal and abnormal 1457 * termination, initiated both locally and remotely. 1458 * 1459 * We avoid formalities like calling wantread() and wantwrite() and 1460 * dispatching read and write callbacks. 1461 */ 1462static void 1463test_termination (void) 1464{ 1465 struct test_objs tobjs; 1466 const struct { 1467 int gquic; 1468 int ietf; 1469 void (*func)(struct test_objs *); 1470 } test_funcs[] = { 1471 { 1, 1, test_loc_FIN_rem_FIN, }, 1472 { 1, 1, test_rem_FIN_loc_FIN, }, 1473 { 1, 0, test_rem_data_loc_close_and_rst_in, }, 1474 { 1, 0, test_rem_data_loc_close, }, 1475 { 1, 1, test_loc_FIN_rem_RST, }, 1476 { 1, 1, test_loc_data_rem_RST, }, 1477 { 1, 0, test_loc_RST_rem_FIN, }, 1478 { 1, 1, test_gapless_elision_beginning, }, 1479 { 1, 1, test_gapless_elision_middle, }, 1480 }, *tf; 1481 1482 for (tf = test_funcs; tf < test_funcs + sizeof(test_funcs) / sizeof(test_funcs[0]); ++tf) 1483 { 1484 if (tf->gquic) 1485 { 1486 init_test_ctl_settings(&g_ctl_settings); 1487 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 1488 init_test_objs(&tobjs, 0x4000, 0x4000, select_pf_by_ver(LSQVER_043)); 1489 tf->func(&tobjs); 1490 deinit_test_objs(&tobjs); 1491 } 1492 if (tf->ietf) 1493 { 1494 init_test_ctl_settings(&g_ctl_settings); 1495 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 1496 init_test_objs(&tobjs, 0x4000, 0x4000, select_pf_by_ver(LSQVER_ID27)); 1497 tf->func(&tobjs); 1498 deinit_test_objs(&tobjs); 1499 } 1500 } 1501} 1502 1503 1504/* Test flush-related corner cases */ 1505static void 1506test_flushing (void) 1507{ 1508 struct test_objs tobjs; 1509 unsigned i; 1510 void (*const test_funcs[])(struct test_objs *) = { 1511 test_reset_stream_with_unflushed_data, 1512 test_reset_stream_with_flushed_data, 1513 test_unlimited_stream_flush_data, 1514 test_data_flush_on_close, 1515 }; 1516 1517 for (i = 0; i < sizeof(test_funcs) / sizeof(test_funcs[0]); ++i) 1518 { 1519 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 1520 test_funcs[i](&tobjs); 1521 deinit_test_objs(&tobjs); 1522 } 1523} 1524 1525 1526static void 1527test_writev (void) 1528{ 1529 unsigned i; 1530 struct test_objs tobjs; 1531 lsquic_stream_t *stream; 1532 ssize_t n; 1533 unsigned char buf_in[0x4000]; 1534 unsigned char buf_out[0x4000]; 1535 int fin; 1536 1537 struct { 1538 struct iovec iov[0x20]; 1539 int count; 1540 } tests[] = { 1541 { .iov = { 1542 { .iov_base = buf_in, .iov_len = 0x4000, }, 1543 }, 1544 .count = 1, 1545 }, 1546 { .iov = { 1547 { .iov_base = buf_in , .iov_len = 0x1000, }, 1548 { .iov_base = buf_in + 0x1000, .iov_len = 0x3000, }, 1549 }, 1550 .count = 2, 1551 }, 1552 { .iov = { 1553 { .iov_base = buf_in , .iov_len = 0x1000, }, 1554 { .iov_base = buf_in + 0x1000, .iov_len = 0x1000, }, 1555 { .iov_base = buf_in + 0x2000, .iov_len = 0x1000, }, 1556 { .iov_base = buf_in + 0x3000, .iov_len = 0x1000, }, 1557 }, 1558 .count = 4, 1559 }, 1560 { .iov = { 1561 { .iov_base = buf_in , .iov_len = 0x1000, }, 1562 { .iov_base = buf_in + 0x1000, .iov_len = 0x1000, }, 1563 { .iov_base = buf_in + 0x2000, .iov_len = 0x1000, }, 1564 { .iov_base = buf_in + 0x3000, .iov_len = 0xFF0, }, 1565 { .iov_base = buf_in + 0x3FF0, .iov_len = 1, }, 1566 { .iov_base = buf_in + 0x3FF1, .iov_len = 0, }, 1567 { .iov_base = buf_in + 0x3FF1, .iov_len = 0, }, 1568 { .iov_base = buf_in + 0x3FF1, .iov_len = 1, }, 1569 { .iov_base = buf_in + 0x3FF2, .iov_len = 1, }, 1570 { .iov_base = buf_in + 0x3FF3, .iov_len = 1, }, 1571 { .iov_base = buf_in + 0x3FF4, .iov_len = 1, }, 1572 { .iov_base = buf_in + 0x3FF5, .iov_len = 1, }, 1573 { .iov_base = buf_in + 0x3FF6, .iov_len = 1, }, 1574 { .iov_base = buf_in + 0x3FF7, .iov_len = 1, }, 1575 { .iov_base = buf_in + 0x3FF8, .iov_len = 1, }, 1576 { .iov_base = buf_in + 0x3FF9, .iov_len = 1, }, 1577 { .iov_base = buf_in + 0x3FFA, .iov_len = 1, }, 1578 { .iov_base = buf_in + 0x3FFB, .iov_len = 1, }, 1579 { .iov_base = buf_in + 0x3FFC, .iov_len = 1, }, 1580 { .iov_base = buf_in + 0x3FFD, .iov_len = 1, }, 1581 { .iov_base = buf_in + 0x3FFE, .iov_len = 1, }, 1582 { .iov_base = buf_in + 0x3FFF, .iov_len = 1, }, 1583 }, 1584 .count = 22, 1585 }, 1586 }; 1587 1588 memset(buf_in, 'A', 0x1000); 1589 memset(buf_in + 0x1000, 'B', 0x1000); 1590 memset(buf_in + 0x2000, 'C', 0x1000); 1591 memset(buf_in + 0x3000, 'D', 0x1000); 1592 1593 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) 1594 { 1595 init_test_objs(&tobjs, UINT_MAX, UINT_MAX, NULL); 1596 stream = new_stream(&tobjs, 12345); 1597 n = lsquic_stream_writev(stream, tests[i].iov, tests[i].count); 1598 assert(0x4000 == n); 1599 lsquic_stream_flush(stream); 1600 n = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf_out, 1601 sizeof(buf_out), 0, &fin, 0); 1602 assert(0x4000 == n); 1603 assert(0 == memcmp(buf_out, buf_in, 0x1000)); 1604 assert(!fin); 1605 lsquic_stream_destroy(stream); 1606 deinit_test_objs(&tobjs); 1607 } 1608} 1609 1610 1611static void 1612test_prio_conversion (void) 1613{ 1614 struct test_objs tobjs; 1615 lsquic_stream_t *stream; 1616 unsigned prio; 1617 int s; 1618 1619 init_test_objs(&tobjs, UINT_MAX, UINT_MAX, NULL); 1620 stream = new_stream(&tobjs, 123); 1621 1622 s = lsquic_stream_set_priority(stream, -2); 1623 assert(-1 == s); 1624 s = lsquic_stream_set_priority(stream, 0); 1625 assert(-1 == s); 1626 s = lsquic_stream_set_priority(stream, 257); 1627 assert(-1 == s); 1628 1629 for (prio = 1; prio <= 256; ++prio) 1630 { 1631 s = lsquic_stream_set_priority(stream, prio); 1632 assert(0 == s); 1633 assert(prio == lsquic_stream_priority(stream)); 1634 } 1635 1636 lsquic_stream_destroy(stream); 1637 deinit_test_objs(&tobjs); 1638} 1639 1640 1641static void 1642test_read_in_middle (void) 1643{ 1644 int s; 1645 size_t nw = 0; 1646 char buf[0x1000]; 1647 const char data[] = "AAABBBCCC"; 1648 struct test_objs tobjs; 1649 stream_frame_t *frame; 1650 uint64_t n_readable; 1651 1652 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 1653 1654 lsquic_stream_t *stream = new_stream(&tobjs, 123); 1655 1656 frame = new_frame_in_ext(&tobjs, 0, 3, 0, &data[0]); 1657 s = lsquic_stream_frame_in(stream, frame); 1658 assert(0 == s); 1659 n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 0); 1660 assert(3 == n_readable); 1661 1662 /* Hole */ 1663 1664 frame = new_frame_in_ext(&tobjs, 6, 3, 0, &data[6]); 1665 s = lsquic_stream_frame_in(stream, frame); 1666 assert(0 == s); 1667 n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 0); 1668 assert(3 == n_readable); 1669 1670 /* Read up to hole */ 1671 1672 nw = lsquic_stream_read(stream, buf, sizeof(buf)); 1673 assert(3 == nw); 1674 assert(0 == memcmp(buf, "AAA", 3)); 1675 n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 3); 1676 assert(0 == n_readable); 1677 1678 frame = new_frame_in_ext(&tobjs, 3, 3, 0, &data[3]); 1679 s = lsquic_stream_frame_in(stream, frame); 1680 assert(0 == s); 1681 n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 3); 1682 assert(6 == n_readable); 1683 1684 nw = lsquic_stream_read(stream, buf, sizeof(buf)); 1685 assert(6 == nw); 1686 assert(0 == memcmp(buf, "BBBCCC", 6)); 1687 n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 9); 1688 assert(0 == n_readable); 1689 1690 lsquic_stream_destroy(stream); 1691 deinit_test_objs(&tobjs); 1692} 1693 1694 1695/* Test that connection flow control does not go past the max when both 1696 * connection limited and unlimited streams are used. 1697 */ 1698static void 1699test_conn_unlimited (void) 1700{ 1701 size_t nw; 1702 struct test_objs tobjs; 1703 lsquic_stream_t *header_stream, *data_stream; 1704 1705 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 1706 1707 unsigned char *const data = calloc(1, 0x4000); 1708 1709 /* Test 1: first write headers, then data stream */ 1710 header_stream = new_stream(&tobjs, 1); 1711 data_stream = new_stream(&tobjs, 123); 1712 nw = lsquic_stream_write(header_stream, data, 98); 1713 assert(98 == nw); 1714 lsquic_stream_flush(header_stream); 1715 nw = lsquic_stream_write(data_stream, data, 0x4000); 1716 assert(0x4000 == nw); 1717 assert(tobjs.conn_pub.conn_cap.cc_sent <= tobjs.conn_pub.conn_cap.cc_max); 1718 lsquic_stream_destroy(header_stream); 1719 lsquic_stream_destroy(data_stream); 1720 1721 /* Test 2: first write data, then headers stream */ 1722 header_stream = new_stream(&tobjs, 1); 1723 data_stream = new_stream(&tobjs, 123); 1724 lsquic_conn_cap_init(&tobjs.conn_pub.conn_cap, 0x4000); 1725 nw = lsquic_stream_write(data_stream, data, 0x4000); 1726 assert(0x4000 == nw); 1727 nw = lsquic_stream_write(header_stream, data, 98); 1728 assert(98 == nw); 1729 lsquic_stream_flush(header_stream); 1730 assert(tobjs.conn_pub.conn_cap.cc_sent <= tobjs.conn_pub.conn_cap.cc_max); 1731 1732 lsquic_stream_destroy(header_stream); 1733 lsquic_stream_destroy(data_stream); 1734 1735 deinit_test_objs(&tobjs); 1736 free(data); 1737} 1738 1739 1740static void 1741test_reading_from_stream2 (void) 1742{ 1743 struct test_objs tobjs; 1744 char buf[0x1000]; 1745 struct iovec iov[2]; 1746 lsquic_packet_in_t *packet_in; 1747 lsquic_stream_t *stream; 1748 stream_frame_t *frame; 1749 ssize_t nw; 1750 int s; 1751 enum stream_state_receiving ssr; 1752 const char data[] = "1234567890"; 1753 1754 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 1755 stream = new_stream(&tobjs, 123); 1756 ssr = lsquic_stream_receiving_state(stream); 1757 assert(SSR_RECV == ssr); 1758 1759 frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]); 1760 s = lsquic_stream_frame_in(stream, frame); 1761 assert(("Inserted frame #1", 0 == s)); 1762 1763 frame = new_frame_in_ext(&tobjs, 6, 4, 0, &data[6]); 1764 s = lsquic_stream_frame_in(stream, frame); 1765 assert(("Inserted frame #2", 0 == s)); 1766 1767 /* Invalid frame: FIN in the middle */ 1768 frame = new_frame_in(&tobjs, 6, 0, 1); 1769 s = lsquic_stream_frame_in(stream, frame); 1770 assert(("Invalid frame: FIN in the middle", -1 == s)); 1771 1772 /* Test for overlaps and DUPs: */ 1773 if (!(stream_ctor_flags & SCF_USE_DI_HASH)) 1774 { 1775 int dup; 1776 unsigned offset, length; 1777 for (offset = 0; offset < 7; ++offset) 1778 { 1779 for (length = 1; length <= sizeof(data) - 1 - offset; ++length) 1780 { 1781 dup = (offset == 0 && length == 6) 1782 || (offset == 6 && length == 4); 1783 frame = new_frame_in_ext(&tobjs, offset, length, 0, data + offset); 1784 s = lsquic_stream_frame_in(stream, frame); 1785 if (dup) 1786 assert(("Dup OK", 0 == s)); 1787 else 1788 assert(("Overlap OK", 0 == s)); 1789 } 1790 } 1791 } 1792 1793 { 1794 uint64_t n_readable; 1795 1796 n_readable = stream->data_in->di_if 1797 ->di_readable_bytes(stream->data_in, 0); 1798 assert(10 == n_readable); 1799 } 1800 1801 nw = lsquic_stream_read(stream, buf, 8); 1802 assert(("Read 8 bytes", nw == 8)); 1803 assert(("Expected 8 bytes", 0 == memcmp(buf, "12345678", nw))); 1804 1805 /* Insert invalid frame: its offset + length is before the already-read 1806 * offset. 1807 */ 1808 frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]); 1809 packet_in = lsquic_packet_in_get(frame->packet_in); /* incref to check for dups below */ 1810 assert(2 == packet_in->pi_refcnt); /* Self-check */ 1811 s = lsquic_stream_frame_in(stream, frame); 1812 assert(("Insert frame before already-read offset succeeds (duplicate)", 1813 s == 0)); 1814 assert(("Duplicate frame has been thrown out", 1815 packet_in->pi_refcnt == 1)); 1816 lsquic_packet_in_put(&tobjs.eng_pub.enp_mm, packet_in); 1817 packet_in = NULL; 1818 1819 iov[0].iov_base = buf; 1820 iov[0].iov_len = 1; 1821 iov[1].iov_base = buf + 1; 1822 iov[1].iov_len = sizeof(buf) - 1; 1823 nw = lsquic_stream_readv(stream, iov, 2); 1824 assert(("Read 2 bytes", nw == 2)); 1825 assert(("Expected 2 bytes", 0 == memcmp(buf, "90", nw))); 1826 nw = lsquic_stream_read(stream, buf, 8); 1827 assert(("Read -1 bytes (EWOULDBLOCK)", -1 == nw && errno == EWOULDBLOCK)); 1828 nw = lsquic_stream_read(stream, buf, 8); 1829 assert(("Read -1 bytes again (EWOULDBLOCK)", -1 == nw && errno == EWOULDBLOCK)); 1830 1831 /* Insert invalid frame: its offset + length is before the already-read 1832 * offset. This test is different from before: now there is buffered 1833 * incoming data. 1834 */ 1835 frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]); 1836 packet_in = lsquic_packet_in_get(frame->packet_in); /* incref to check for dups below */ 1837 assert(2 == packet_in->pi_refcnt); /* Self-check */ 1838 s = lsquic_stream_frame_in(stream, frame); 1839 assert(("Insert frame before already-read offset succeeds (duplicate)", 1840 s == 0)); 1841 assert(("Duplicate frame has been thrown out", 1842 packet_in->pi_refcnt == 1)); 1843 lsquic_packet_in_put(&tobjs.eng_pub.enp_mm, packet_in); 1844 packet_in = NULL; 1845 1846 /* Last frame has no data but has a FIN flag set */ 1847 frame = new_frame_in_ext(&tobjs, 10, 0, 1, 1848 (void *) 1234 /* Intentionally invalid: this pointer 1849 * should not be used 1850 */); 1851 s = lsquic_stream_frame_in(stream, frame); 1852 assert(("Inserted frame #3", 0 == s)); 1853 ssr = lsquic_stream_receiving_state(stream); 1854 assert(SSR_DATA_RECVD == ssr); 1855 1856 /* Invalid frame: writing after FIN */ 1857 frame = new_frame_in(&tobjs, 10, 2, 0); 1858 s = lsquic_stream_frame_in(stream, frame); 1859 assert(("Invalid frame caught", -1 == s)); 1860 1861 /* Duplicate FIN frame */ 1862 frame = new_frame_in_ext(&tobjs, 10, 0, 1, 1863 (void *) 1234 /* Intentionally invalid: this pointer 1864 * should not be used 1865 */); 1866 s = lsquic_stream_frame_in(stream, frame); 1867 assert(("Duplicate FIN frame", 0 == s)); 1868 1869 nw = lsquic_stream_read(stream, buf, 1); 1870 assert(("Read 0 bytes (at EOR)", 0 == nw)); 1871 ssr = lsquic_stream_receiving_state(stream); 1872 assert(SSR_DATA_READ == ssr); 1873 1874 lsquic_stream_destroy(stream); 1875 deinit_test_objs(&tobjs); 1876} 1877 1878 1879/* This tests stream overlap support */ 1880static void 1881test_overlaps (void) 1882{ 1883 struct test_objs tobjs; 1884 char buf[0x1000]; 1885 lsquic_stream_t *stream; 1886 stream_frame_t *frame; 1887 int s; 1888 const char data[] = "1234567890"; 1889 1890 struct frame_spec 1891 { 1892 unsigned off; 1893 unsigned len; 1894 signed char fin; 1895 }; 1896 1897 struct frame_step 1898 { 1899 struct frame_spec frame_spec; 1900 int insert_res; /* Expected result */ 1901 }; 1902 1903 struct overlap_test 1904 { 1905 int line; /* Test identifier */ 1906 struct frame_step steps[10]; /* Sequence of steps */ 1907 unsigned n_steps; 1908 const unsigned char buf[20]; /* Expected result of read */ 1909 ssize_t sz; /* Expected size of first read */ 1910 ssize_t second_read; /* Expected size of second read: 1911 * 0 means EOS (FIN). 1912 */ 1913 }; 1914 1915 static const struct overlap_test tests[] = 1916 { 1917 1918 { 1919 .line = __LINE__, 1920 .steps = 1921 { 1922 { 1923 .frame_spec = { .off = 0, .len = 10, .fin = 0, }, 1924 .insert_res = 0, 1925 }, 1926 }, 1927 .n_steps = 1, 1928 .buf = "0123456789", 1929 .sz = 10, 1930 .second_read = -1, 1931 }, 1932 1933 { 1934 .line = __LINE__, 1935 .steps = 1936 { 1937 { 1938 .frame_spec = { .off = 0, .len = 5, .fin = 0, }, 1939 .insert_res = 0, 1940 }, 1941 { 1942 .frame_spec = { .off = 0, .len = 10, .fin = 0, }, 1943 .insert_res = 0, 1944 }, 1945 }, 1946 .n_steps = 2, 1947 .buf = "0123456789", 1948 .sz = 10, 1949 .second_read = -1, 1950 }, 1951 1952 { 1953 .line = __LINE__, 1954 .steps = 1955 { 1956 { 1957 .frame_spec = { .off = 1, .len = 9, .fin = 0, }, 1958 .insert_res = 0, 1959 }, 1960 { 1961 .frame_spec = { .off = 1, .len = 9, .fin = 1, }, 1962 .insert_res = 0, 1963 }, 1964 { 1965 .frame_spec = { .off = 0, .len = 2, .fin = 0, }, 1966 .insert_res = 0, 1967 }, 1968 { 1969 .frame_spec = { .off = 2, .len = 6, .fin = 0, }, 1970 .insert_res = 0, 1971 }, 1972 }, 1973 .n_steps = 4, 1974 .buf = "0123456789", 1975 .sz = 10, 1976 .second_read = 0, 1977 }, 1978 1979 { 1980 .line = __LINE__, 1981 .steps = 1982 { 1983 { 1984 .frame_spec = { .off = 1, .len = 9, .fin = 1, }, 1985 .insert_res = 0, 1986 }, 1987 { 1988 .frame_spec = { .off = 0, .len = 2, .fin = 0, }, 1989 .insert_res = 0, 1990 }, 1991 }, 1992 .n_steps = 2, 1993 .buf = "0123456789", 1994 .sz = 10, 1995 .second_read = 0, 1996 }, 1997 1998 { 1999 .line = __LINE__, 2000 .steps = 2001 { 2002 { .frame_spec = { .off = 1, .len = 6, .fin = 0, }, .insert_res = 0, }, 2003 { .frame_spec = { .off = 2, .len = 1, .fin = 0, }, .insert_res = 0, }, 2004 { .frame_spec = { .off = 8, .len = 2, .fin = 1, }, .insert_res = 0, }, 2005 { .frame_spec = { .off = 3, .len = 2, .fin = 0, }, .insert_res = 0, }, 2006 { .frame_spec = { .off = 4, .len = 1, .fin = 0, }, .insert_res = 0, }, 2007 { .frame_spec = { .off = 5, .len = 2, .fin = 0, }, .insert_res = 0, }, 2008 { .frame_spec = { .off = 6, .len = 1, .fin = 0, }, .insert_res = 0, }, 2009 { .frame_spec = { .off = 7, .len = 3, .fin = 0, }, .insert_res = 0, }, 2010 { .frame_spec = { .off = 9, .len = 1, .fin = 1, }, .insert_res = 0, }, 2011 { .frame_spec = { .off = 0, .len = 2, .fin = 0, }, .insert_res = 0, }, 2012 }, 2013 .n_steps = 10, 2014 .buf = "0123456789", 2015 .sz = 10, 2016 .second_read = 0, 2017 }, 2018 2019 }; 2020 2021 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2022 2023 const struct overlap_test *test; 2024 for (test = tests; test < tests + sizeof(tests) / sizeof(tests[0]); ++test) 2025 { 2026 LSQ_NOTICE("executing stream overlap test, line %d", test->line); 2027 stream = new_stream(&tobjs, test->line); 2028 2029 const struct frame_step *step; 2030 for (step = test->steps; step < test->steps + test->n_steps; ++step) 2031 { 2032 frame = new_frame_in_ext(&tobjs, step->frame_spec.off, 2033 step->frame_spec.len, step->frame_spec.fin, 2034 &data[step->frame_spec.off]); 2035 s = lsquic_stream_frame_in(stream, frame); 2036 assert(s == step->insert_res); 2037 } 2038 2039 ssize_t nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2040 assert(nread == test->sz); 2041 assert(0 == memcmp(data, buf, test->sz)); 2042 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2043 assert(nread == test->second_read); 2044 if (nread < 0) 2045 assert(EWOULDBLOCK == errno); 2046 2047 lsquic_stream_destroy(stream); 2048 } 2049 2050 { 2051 LSQ_NOTICE("Special test on line %d", __LINE__); 2052 stream = new_stream(&tobjs, __LINE__); 2053 frame = new_frame_in_ext(&tobjs, 0, 5, 0, &data[0]); 2054 s = lsquic_stream_frame_in(stream, frame); 2055 assert(0 == s); 2056 ssize_t nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2057 assert(nread == 5); 2058 assert(0 == memcmp(data, buf, 5)); 2059 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2060 assert(nread < 0); 2061 assert(EWOULDBLOCK == errno); 2062 /* Test that a frame with FIN that ends before the read offset 2063 * results in an error. 2064 */ 2065 frame = new_frame_in_ext(&tobjs, 0, 3, 1, &data[0]); 2066 s = lsquic_stream_frame_in(stream, frame); 2067 assert(s < 0); 2068 /* This frame should be a DUP: the next read should still return -1. 2069 */ 2070 frame = new_frame_in_ext(&tobjs, 3, 2, 0, &data[3]); 2071 s = lsquic_stream_frame_in(stream, frame); 2072 assert(s == 0); 2073 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2074 assert(nread < 0); 2075 assert(EWOULDBLOCK == errno); 2076 /* This frame should be an overlap: FIN should register and 2077 * the next read should return 0. 2078 */ 2079 frame = new_frame_in_ext(&tobjs, 0, 5, 1, &data[0]); 2080 s = lsquic_stream_frame_in(stream, frame); 2081 assert(s == 0); 2082 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2083 assert(nread == 0); 2084 lsquic_stream_destroy(stream); 2085 } 2086 2087 { 2088 LSQ_NOTICE("Special test for bug 106 on line %d", __LINE__); 2089 char *const data = malloc(5862); 2090 init_buf(data, 5862); 2091 assert(data); 2092 stream = new_stream(&tobjs, __LINE__); 2093 /* Insert four frames: */ 2094 frame = new_frame_in_ext(&tobjs, 0, 1173, 0, data); 2095 s = lsquic_stream_frame_in(stream, frame); 2096 assert(0 == s); 2097 frame = new_frame_in_ext(&tobjs, 1173, 1173, 0, data + 1173); 2098 s = lsquic_stream_frame_in(stream, frame); 2099 assert(0 == s); 2100 frame = new_frame_in_ext(&tobjs, 2346, 1172, 0, data + 2346); 2101 s = lsquic_stream_frame_in(stream, frame); 2102 assert(0 == s); 2103 frame = new_frame_in_ext(&tobjs, 3518, 578, 0, data + 3518); 2104 s = lsquic_stream_frame_in(stream, frame); 2105 assert(0 == s); 2106 /* Read all data: */ 2107 ssize_t nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2108 assert(nread == 4096); 2109 assert(0 == memcmp(data, buf, 4096)); 2110 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2111 assert(nread < 0); 2112 assert(EWOULDBLOCK == errno); 2113 /* Insert overlapped frame and one more: */ 2114 frame = new_frame_in_ext(&tobjs, 3518, 1172, 0, data + 3518); 2115 s = lsquic_stream_frame_in(stream, frame); 2116 assert(0 == s); 2117 frame = new_frame_in_ext(&tobjs, 4690, 1172, 0, data + 4690); 2118 s = lsquic_stream_frame_in(stream, frame); 2119 assert(0 == s); 2120 /* Verify that continued read from offset 4096 succeeds and 2121 * contains expected data: 2122 */ 2123 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2124 assert(nread == 5862 - 4096); 2125 assert(0 == memcmp(data + 4096, buf, 5862 - 4096)); 2126 lsquic_stream_destroy(stream); 2127 free(data); 2128 } 2129 2130 deinit_test_objs(&tobjs); 2131} 2132 2133 2134static void 2135test_insert_edge_cases (void) 2136{ 2137 struct test_objs tobjs; 2138 lsquic_stream_t *stream; 2139 stream_frame_t *frame; 2140 int s; 2141 ssize_t nread; 2142 const char data[] = "1234567890"; 2143 enum stream_state_receiving ssr; 2144 unsigned buf[0x1000]; 2145 2146 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2147 2148 { 2149 stream = new_stream(&tobjs, 123); 2150 frame = new_frame_in_ext(&tobjs, 0, 6, 1, &data[0]); 2151 s = lsquic_stream_frame_in(stream, frame); 2152 assert(("Inserted frame #1", 0 == s)); 2153 ssr = lsquic_stream_receiving_state(stream); 2154 assert(SSR_DATA_RECVD == ssr); 2155 /* Invalid frame: different FIN location */ 2156 frame = new_frame_in_ext(&tobjs, 3, 2, 1, &data[3]); 2157 s = lsquic_stream_frame_in(stream, frame); 2158 assert(("Invalid frame: different FIN location", -1 == s)); 2159 lsquic_stream_destroy(stream); 2160 } 2161 2162 { 2163 stream = new_stream(&tobjs, 123); 2164 frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]); 2165 s = lsquic_stream_frame_in(stream, frame); 2166 assert(("Inserted frame #1", 0 == s)); 2167 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2168 assert(6 == nread); 2169 frame = new_frame_in_ext(&tobjs, 6, 0, 0, &data[6]); 2170 s = lsquic_stream_frame_in(stream, frame); 2171 assert(("Duplicate frame", 0 == s)); 2172 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2173 assert(nread == -1 && errno == EWOULDBLOCK); 2174 frame = new_frame_in_ext(&tobjs, 6, 0, 1, &data[6]); 2175 s = lsquic_stream_frame_in(stream, frame); 2176 assert(("Frame OK", 0 == s)); 2177 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2178 assert(nread == 0); /* Hit EOF */ 2179 frame = new_frame_in_ext(&tobjs, 6, 0, 1, &data[6]); 2180 s = lsquic_stream_frame_in(stream, frame); 2181 assert(("Duplicate FIN frame", 0 == s)); 2182 lsquic_stream_destroy(stream); 2183 } 2184 2185 { 2186 stream = new_stream(&tobjs, 123); 2187 frame = new_frame_in_ext(&tobjs, 6, 0, 1, &data[6]); 2188 s = lsquic_stream_frame_in(stream, frame); 2189 assert(("Frame OK", 0 == s)); 2190 ssr = lsquic_stream_receiving_state(stream); 2191 assert(SSR_SIZE_KNOWN == ssr); 2192 frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]); 2193 s = lsquic_stream_frame_in(stream, frame); 2194 assert(("Inserted frame #1", 0 == s)); 2195 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2196 assert(6 == nread); 2197 frame = new_frame_in_ext(&tobjs, 6, 0, 0, &data[6]); 2198 s = lsquic_stream_frame_in(stream, frame); 2199 assert(("Duplicate frame", 0 == s)); 2200 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2201 assert(nread == 0); /* Hit EOF */ 2202 frame = new_frame_in_ext(&tobjs, 6, 0, 1, &data[6]); 2203 s = lsquic_stream_frame_in(stream, frame); 2204 assert(("Duplicate FIN frame", 0 == s)); 2205 lsquic_stream_destroy(stream); 2206 } 2207 2208 { 2209 stream = new_stream(&tobjs, 123); 2210 frame = new_frame_in_ext(&tobjs, 0, 6, 1, &data[0]); 2211 s = lsquic_stream_frame_in(stream, frame); 2212 assert(("Inserted frame #1", 0 == s)); 2213 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2214 assert(6 == nread); 2215 nread = lsquic_stream_read(stream, buf, sizeof(buf)); 2216 assert(0 == nread); /* Hit EOF */ 2217 frame = new_frame_in_ext(&tobjs, 0, 6, 1, &data[0]); 2218 s = lsquic_stream_frame_in(stream, frame); 2219 assert(("Inserted duplicate frame", 0 == s)); 2220 lsquic_stream_destroy(stream); 2221 } 2222 2223 deinit_test_objs(&tobjs); 2224} 2225 2226 2227/* When HTTP stream is closed unexpectedly, send a reset instead of creating 2228 * an empty STREAM frame with a FIN bit set. 2229 */ 2230static void 2231test_unexpected_http_close (void) 2232{ 2233 struct test_objs tobjs; 2234 lsquic_stream_t *stream; 2235 int s; 2236 2237 stream_ctor_flags |= SCF_HTTP; 2238 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2239 2240 stream = new_stream(&tobjs, 123); 2241 assert(stream->sm_bflags & SMBF_USE_HEADERS); /* Self-check */ 2242 s = lsquic_stream_close(stream); 2243 assert(s == 0); 2244 assert(stream->sm_qflags & SMQF_SEND_RST); 2245 assert(stream->sm_qflags & SMQF_CALL_ONCLOSE); 2246 assert(!lsquic_send_ctl_has_buffered(&tobjs.send_ctl)); 2247 2248 lsquic_stream_destroy(stream); 2249 deinit_test_objs(&tobjs); 2250 stream_ctor_flags &= ~SCF_HTTP; 2251} 2252 2253 2254static void 2255test_writing_to_stream_schedule_stream_packets_immediately (void) 2256{ 2257 ssize_t nw; 2258 struct test_objs tobjs; 2259 struct lsquic_conn *const lconn = &tobjs.lconn; 2260 struct lsquic_stream *stream; 2261 int s; 2262 unsigned char buf[0x1000]; 2263 struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap; 2264 2265 init_test_ctl_settings(&g_ctl_settings); 2266 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 2267 2268 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2269 n_closed = 0; 2270 stream = new_stream(&tobjs, 123); 2271 assert(("Stream initialized", stream)); 2272 const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx; 2273 assert(("on_new_stream called correctly", stream == test_ctx_local->stream)); 2274 assert(LSQUIC_STREAM_DEFAULT_PRIO == lsquic_stream_priority(stream)); 2275 2276 assert(lconn == lsquic_stream_conn(stream)); 2277 2278 nw = lsquic_stream_write(stream, "Dude, where is", 14); 2279 assert(("14 bytes written correctly", nw == 14)); 2280 2281 assert(("not packetized", 2282 0 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl))); 2283 /* Cap hit is taken immediately, even for flushed data */ 2284 assert(("connection cap is reduced by 14 bytes", 2285 lsquic_conn_cap_avail(conn_cap) == 0x4000 - 14)); 2286 s = lsquic_stream_flush(stream); 2287 assert(0 == s); 2288 assert(("packetized -- 1 packet", 2289 1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl))); 2290 2291 nw = lsquic_stream_write(stream, " my car?!", 9); 2292 assert(("9 bytes written correctly", nw == 9)); 2293 s = lsquic_stream_flush(stream); 2294 assert(0 == s); 2295 assert(("packetized -- still 1 packet", 2296 1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl))); 2297 2298 assert(("connection cap is reduced by 23 bytes", 2299 lsquic_conn_cap_avail(conn_cap) == 0x4000 - 23)); 2300 2301 nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf, 2302 sizeof(buf), 0, NULL, 0); 2303 assert(23 == nw); 2304 assert(0 == memcmp(buf, "Dude, where is my car?!", 23)); 2305 assert(("cannot reduce max_send below what's been sent already", 2306 -1 == lsquic_stream_set_max_send_off(stream, 15))); 2307 assert(("cannot reduce max_send below what's been sent already #2", 2308 -1 == lsquic_stream_set_max_send_off(stream, 22))); 2309 assert(("can set to the same value...", 2310 0 == lsquic_stream_set_max_send_off(stream, 23))); 2311 assert(("...or larger", 2312 0 == lsquic_stream_set_max_send_off(stream, 23000))); 2313 lsquic_stream_destroy(stream); 2314 assert(("on_close called", 1 == n_closed)); 2315 deinit_test_objs(&tobjs); 2316} 2317 2318 2319static void 2320test_writing_to_stream_outside_callback (void) 2321{ 2322 ssize_t nw; 2323 struct test_objs tobjs; 2324 struct lsquic_conn *const lconn = &tobjs.lconn; 2325 struct lsquic_stream *stream; 2326 int s; 2327 unsigned char buf[0x1000]; 2328 struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap; 2329 2330 init_test_ctl_settings(&g_ctl_settings); 2331 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 2332 g_ctl_settings.tcs_bp_type = BPT_OTHER_PRIO; 2333 const struct buf_packet_q *const bpq = 2334 &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type]; 2335 2336 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2337 n_closed = 0; 2338 stream = new_stream(&tobjs, 123); 2339 assert(("Stream initialized", stream)); 2340 const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx; 2341 assert(("on_new_stream called correctly", stream == test_ctx_local->stream)); 2342 assert(LSQUIC_STREAM_DEFAULT_PRIO == lsquic_stream_priority(stream)); 2343 2344 assert(lconn == lsquic_stream_conn(stream)); 2345 2346 nw = lsquic_stream_write(stream, "Dude, where is", 14); 2347 assert(("14 bytes written correctly", nw == 14)); 2348 2349 assert(("not packetized", 0 == bpq->bpq_count)); 2350 s = lsquic_stream_flush(stream); 2351 assert(0 == s); 2352 assert(("packetized -- 1 packet", 1 == bpq->bpq_count)); 2353 2354 nw = lsquic_stream_write(stream, " my car?!", 9); 2355 assert(("9 bytes written correctly", nw == 9)); 2356 s = lsquic_stream_flush(stream); 2357 assert(0 == s); 2358 assert(("packetized -- still 1 packet", 1 == bpq->bpq_count)); 2359 2360 assert(("connection cap is reduced by 23 bytes", 2361 lsquic_conn_cap_avail(conn_cap) == 0x4000 - 23)); 2362 2363 /* Now we are magically inside the callback: */ 2364 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 2365 lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, 2366 g_ctl_settings.tcs_bp_type); 2367 assert(("packetized -- 1 packet", 2368 1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl))); 2369 2370 nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf, 2371 sizeof(buf), 0, NULL, 0); 2372 assert(23 == nw); 2373 assert(0 == memcmp(buf, "Dude, where is my car?!", 23)); 2374 assert(("cannot reduce max_send below what's been sent already", 2375 -1 == lsquic_stream_set_max_send_off(stream, 15))); 2376 assert(("cannot reduce max_send below what's been sent already #2", 2377 -1 == lsquic_stream_set_max_send_off(stream, 22))); 2378 assert(("can set to the same value...", 2379 0 == lsquic_stream_set_max_send_off(stream, 23))); 2380 assert(("...or larger", 2381 0 == lsquic_stream_set_max_send_off(stream, 23000))); 2382 lsquic_stream_destroy(stream); 2383 assert(("on_close called", 1 == n_closed)); 2384 deinit_test_objs(&tobjs); 2385} 2386 2387 2388static void 2389verify_ack (struct lsquic_packet_out *packet_out) 2390{ 2391 struct packet_out_frec_iter pofi; 2392 const struct frame_rec *frec; 2393 unsigned short regen_sz; 2394 enum quic_ft_bit frame_types; 2395 2396 assert(packet_out->po_regen_sz > 0); 2397 assert(packet_out->po_frame_types & (1 << QUIC_FRAME_ACK)); 2398 2399 regen_sz = 0; 2400 frame_types = 0; 2401 for (frec = lsquic_pofi_first(&pofi, packet_out); frec; 2402 frec = lsquic_pofi_next(&pofi)) 2403 { 2404 frame_types |= 1 << frec->fe_frame_type; 2405 if (frec->fe_frame_type == QUIC_FRAME_ACK) 2406 { 2407 assert(frec->fe_len == 9); 2408 assert(0 == memcmp(packet_out->po_data + frec->fe_off, "ACKACKACK", 9)); 2409 assert(regen_sz == frec->fe_off); 2410 regen_sz += frec->fe_len; 2411 } 2412 } 2413 2414 assert(frame_types & (1 << QUIC_FRAME_ACK)); 2415 assert(regen_sz == packet_out->po_regen_sz); 2416} 2417 2418 2419/* Write to buffered streams: first to low-priority, then high-priority. This 2420 * should trigger ACK generation and move. 2421 */ 2422static void 2423test_stealing_ack (void) 2424{ 2425 ssize_t nw; 2426 struct test_objs tobjs; 2427 struct lsquic_conn *const lconn = &tobjs.lconn; 2428 struct lsquic_stream *lo_stream, *hi_stream;; 2429 int s; 2430 const struct buf_packet_q *bpq; 2431 2432 init_test_ctl_settings(&g_ctl_settings); 2433 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 2434 g_ctl_settings.tcs_write_ack = 1; 2435 g_ctl_settings.tcs_bp_type = BPT_OTHER_PRIO; 2436 2437 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2438 2439 lo_stream = new_stream(&tobjs, 123); 2440 assert(("Stream initialized", lo_stream)); 2441 assert(LSQUIC_STREAM_DEFAULT_PRIO == lsquic_stream_priority(lo_stream)); 2442 assert(lconn == lsquic_stream_conn(lo_stream)); 2443 nw = lsquic_stream_write(lo_stream, "Dude, where is", 14); 2444 assert(("14 bytes written correctly", nw == 14)); 2445 s = lsquic_stream_flush(lo_stream); 2446 assert(0 == s); 2447 2448 bpq = &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type]; 2449 verify_ack(TAILQ_FIRST(&bpq->bpq_packets)); 2450 2451 g_ctl_settings.tcs_bp_type = BPT_HIGHEST_PRIO; 2452 2453 hi_stream = new_stream(&tobjs, 1); 2454 assert(("Stream initialized", hi_stream)); 2455 assert(lconn == lsquic_stream_conn(hi_stream)); 2456 nw = lsquic_stream_write(hi_stream, "DATA", 4); 2457 assert(("4 bytes written correctly", nw == 4)); 2458 s = lsquic_stream_flush(hi_stream); 2459 assert(0 == s); 2460 2461 /* ACK is moved (stolen) from low-priority stream to high-priority stream */ 2462 /* Check old packet */ 2463 assert(!(TAILQ_FIRST(&bpq->bpq_packets)->po_frame_types & (1 << QUIC_FRAME_ACK))); 2464 /* Check new packet */ 2465 bpq = &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type]; 2466 verify_ack(TAILQ_FIRST(&bpq->bpq_packets)); 2467 2468 /* And now chop regen, see if we hit any asserts there */ 2469 lsquic_packet_out_chop_regen(TAILQ_FIRST(&bpq->bpq_packets)); 2470 /* And now verify that ACK is gone */ 2471 assert(!(TAILQ_FIRST(&bpq->bpq_packets)->po_frame_types & (1 << QUIC_FRAME_ACK))); 2472 2473 lsquic_stream_destroy(lo_stream); 2474 lsquic_stream_destroy(hi_stream); 2475 deinit_test_objs(&tobjs); 2476} 2477 2478 2479static void 2480test_changing_pack_size (void) 2481{ 2482 ssize_t nw; 2483 struct test_objs tobjs; 2484 struct lsquic_conn *lconn = &tobjs.lconn; 2485 struct lsquic_stream *stream; 2486 int s, i; 2487 unsigned char buf[0x2000]; 2488 size_t len; 2489 2490 init_buf(buf, sizeof(buf)); 2491 2492 enum lsquic_version versions_to_test[3] = 2493 { 2494 LSQVER_046, 2495 LSQVER_ID27, 2496 }; 2497 2498 for (i = 0; i < 3; i++) 2499 { 2500 g_pf = select_pf_by_ver(versions_to_test[i]); 2501 2502 init_test_ctl_settings(&g_ctl_settings); 2503 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 2504 g_ctl_settings.tcs_bp_type = BPT_OTHER_PRIO; 2505 const struct buf_packet_q *const bpq = 2506 &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type]; 2507 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2508 n_closed = 0; 2509 if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) 2510 { 2511 tobjs.ctor_flags |= SCF_IETF; 2512 lconn->cn_flags |= LSCONN_IETF; 2513 network_path.np_pack_size = 4096; 2514 } 2515 stream = new_stream(&tobjs, 5); 2516 assert(("Stream initialized", stream)); 2517 const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx; 2518 assert(("on_new_stream called correctly", stream == test_ctx_local->stream)); 2519 2520 len = ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) ? 2048 : 1024; 2521 nw = lsquic_stream_write(stream, buf, len); 2522 assert(("n bytes written correctly", (size_t)nw == len)); 2523 2524 assert(("not packetized", 0 == bpq->bpq_count)); 2525 2526 /* IETF: shrink packet size before a flush */ 2527 if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) 2528 network_path.np_pack_size = 1370; 2529 2530 s = lsquic_stream_flush(stream); 2531 assert(0 == s); 2532 2533 if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) 2534 assert(("packetized -- 2 packets", 2 == bpq->bpq_count)); 2535 else 2536 assert(("packetized -- 1 packets", 1 == bpq->bpq_count)); 2537 2538 /* IETF: expand packet size before a write */ 2539 if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) 2540 network_path.np_pack_size = 4096; 2541 2542 len = ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) ? 2048 : 1024; 2543 nw = lsquic_stream_write(stream, buf, len); 2544 assert(("n bytes written correctly", (size_t)nw == len)); 2545 if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) 2546 assert(("packetized -- 3 packets", 3 == bpq->bpq_count)); 2547 else 2548 assert(("packetized -- 1 packets", 1 == bpq->bpq_count)); 2549 2550 s = lsquic_stream_flush(stream); 2551 assert(0 == s); 2552 if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) 2553 assert(("packetized -- 3 packets", 3 == bpq->bpq_count)); 2554 else 2555 assert(("packetized -- 2 packets", 2 == bpq->bpq_count)); 2556 2557 lsquic_stream_destroy(stream); 2558 assert(("on_close called", 1 == n_closed)); 2559 deinit_test_objs(&tobjs); 2560 } 2561 g_pf = select_pf_by_ver(LSQVER_043); 2562} 2563 2564 2565/* This tests what happens when a stream data is buffered using one packet 2566 * size, but then packet size get smaller (which is what happens when an RTO 2567 * occurs), and then more data is written. 2568 * 2569 * In particular, the write sizes in this tests are structured to make 2570 * maybe_resize_threshold() change the threshold. 2571 */ 2572static void 2573test_reducing_pack_size (void) 2574{ 2575 ssize_t nw; 2576 struct test_objs tobjs; 2577 struct lsquic_conn *lconn = &tobjs.lconn; 2578 struct lsquic_stream *stream; 2579 int s; 2580 unsigned i; 2581 unsigned char buf[0x4000]; 2582 2583 init_buf(buf, sizeof(buf)); 2584 2585 enum lsquic_version versions_to_test[] = 2586 { 2587 LSQVER_050, 2588 LSQVER_ID29, 2589 }; 2590 2591 /* Particular versions should not matter as this is tests the logic in 2592 * stream only, but we do it for completeness. 2593 */ 2594 for (i = 0; i < sizeof(versions_to_test) / sizeof(versions_to_test[0]); i++) 2595 { 2596 g_pf = select_pf_by_ver(versions_to_test[i]); 2597 2598 init_test_ctl_settings(&g_ctl_settings); 2599 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 2600 g_ctl_settings.tcs_bp_type = BPT_OTHER_PRIO; 2601 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2602 n_closed = 0; 2603 if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) 2604 { 2605 tobjs.ctor_flags |= SCF_IETF; 2606 lconn->cn_flags |= LSCONN_IETF; 2607 } 2608 network_path.np_pack_size = 2000; 2609 stream = new_stream(&tobjs, 5); 2610 assert(("Stream initialized", stream)); 2611 const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx; 2612 assert(("on_new_stream called correctly", stream == test_ctx_local->stream)); 2613 2614 nw = lsquic_stream_write(stream, buf, 1400); 2615 assert(stream->sm_n_allocated <= 2000); 2616 assert(stream->sm_n_buffered > 0); 2617 assert(("n bytes written correctly", (size_t)nw == 1400)); 2618 2619 /* Shrink packet size */ 2620 network_path.np_pack_size = 1300; 2621 2622 nw = lsquic_stream_write(stream, buf, 3000); 2623 assert(stream->sm_n_allocated <= 1300); 2624 assert(stream->sm_n_buffered > 0); 2625 assert(("n bytes written correctly", (size_t)nw == 3000)); 2626 2627 s = lsquic_stream_flush(stream); 2628 assert(stream->sm_n_buffered == 0); 2629 assert(0 == s); 2630 2631 lsquic_stream_destroy(stream); 2632 assert(("on_close called", 1 == n_closed)); 2633 deinit_test_objs(&tobjs); 2634 } 2635 g_pf = select_pf_by_ver(LSQVER_043); 2636} 2637 2638 2639/* Test window update logic, connection-limited */ 2640static void 2641test_window_update1 (void) 2642{ 2643 ssize_t nw; 2644 struct test_objs tobjs; 2645 struct lsquic_stream *stream; 2646 unsigned char buf[0x1000]; 2647 lsquic_packet_out_t *packet_out; 2648 struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap; 2649 int s; 2650 2651 init_test_ctl_settings(&g_ctl_settings); 2652 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 2653 2654 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 2655 n_closed = 0; 2656 stream = new_stream_ext(&tobjs, 123, 3); 2657 nw = lsquic_stream_write(stream, "1234567890", 10); 2658 assert(("lsquic_stream_write is limited by the send window", 3 == nw)); 2659 assert(("cc_tosend is updated immediately", 2660 3 == conn_cap->cc_sent)); 2661 s = lsquic_stream_flush(stream); 2662 assert(0 == s); 2663 assert(("cc_tosend is updated when limited by connection", 2664 3 == conn_cap->cc_sent)); 2665 nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf, 2666 sizeof(buf), 0, NULL, 0); 2667 assert(nw == 3); 2668 assert(0 == memcmp(buf, "123", 3)); 2669 2670 /* Pretend we sent out a packet: */ 2671 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0); 2672 lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out); 2673 2674 lsquic_stream_window_update(stream, 20); 2675 nw = lsquic_stream_write(stream, "4567890", 7); 2676 assert(("lsquic_stream_write: wrote remainig 7 bytes", 7 == nw)); 2677 s = lsquic_stream_flush(stream); 2678 assert(0 == s); 2679 2680 /* Verify written data: */ 2681 nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf, 2682 sizeof(buf), 3, NULL, 0); 2683 assert(nw == 7); 2684 assert(0 == memcmp(buf, "4567890", 7)); 2685 2686 lsquic_stream_destroy(stream); 2687 assert(("on_close called", 1 == n_closed)); 2688 deinit_test_objs(&tobjs); 2689} 2690 2691 2692/* Test two: large frame in the middle */ 2693static void 2694test_bad_packbits_guess_2 (void) 2695{ 2696 lsquic_packet_out_t *packet_out; 2697 ssize_t nw; 2698 struct test_objs tobjs; 2699 struct lsquic_stream *streams[3]; 2700 char buf[0x1000]; 2701 unsigned char buf_out[0x1000]; 2702 int s, fin; 2703 2704 init_buf(buf, sizeof(buf)); 2705 2706 init_test_ctl_settings(&g_ctl_settings); 2707 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 2708 g_ctl_settings.tcs_guess_packno_bits = GQUIC_PACKNO_LEN_1; 2709 2710 init_test_objs(&tobjs, 0x1000, 0x1000, NULL); 2711 streams[0] = new_stream(&tobjs, 5); 2712 streams[1] = new_stream(&tobjs, 7); 2713 streams[2] = new_stream(&tobjs, 9); 2714 2715 /* Perfrom writes on the three streams. This is tuned to fill a single 2716 * packet completely -- we check this later in this function. 2717 */ 2718 s = lsquic_stream_shutdown(streams[0], 1); 2719 assert(s == 0); 2720 nw = lsquic_stream_write(streams[1], buf, 1337); 2721 assert(nw == 1337); 2722 s = lsquic_stream_flush(streams[1]); 2723 assert(0 == s); 2724 nw = lsquic_stream_write(streams[2], buf + 1337, 1); 2725 assert(nw == 1); 2726 s = lsquic_stream_shutdown(streams[2], 1); 2727 assert(s == 0); 2728 2729 /* Verify that we got one packet filled to the top: */ 2730 const struct buf_packet_q *const bpq = 2731 &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type]; 2732 assert(("packetized -- 1 packet", 1 == bpq->bpq_count)); 2733 packet_out = TAILQ_FIRST(&bpq->bpq_packets); 2734 assert(0 == lsquic_packet_out_avail(packet_out)); 2735 2736 assert(1 == streams[0]->n_unacked); 2737 assert(1 == streams[1]->n_unacked); 2738 assert(1 == streams[2]->n_unacked); 2739 2740 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 2741 g_ctl_settings.tcs_calc_packno_bits = GQUIC_PACKNO_LEN_6; 2742 s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, 2743 g_ctl_settings.tcs_bp_type); 2744 assert(2 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)); 2745 2746 /* Verify written data: */ 2747 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out, 2748 sizeof(buf_out), 0, &fin, 0); 2749 assert(nw == 0); 2750 assert(fin); 2751 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[1]->id, buf_out, 2752 sizeof(buf_out), 0, &fin, 0); 2753 assert(nw == 1337); 2754 assert(!fin); 2755 assert(0 == memcmp(buf, buf_out, 1337)); 2756 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[2]->id, buf_out, 2757 sizeof(buf_out), 0, &fin, 0); 2758 assert(nw == 1); 2759 assert(fin); 2760 assert(0 == memcmp(buf + 1337, buf_out, 1)); 2761 2762 /* Verify packets */ 2763 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0); 2764 assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6); 2765 assert(1 == packet_out->po_packno); 2766 assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM)); 2767 lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out); 2768 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0); 2769 assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6); 2770 assert(2 == packet_out->po_packno); 2771 assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM)); 2772 lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out); 2773 2774 assert(1 == streams[0]->n_unacked); 2775 assert(1 == streams[1]->n_unacked); 2776 assert(1 == streams[2]->n_unacked); 2777 ack_packet(&tobjs.send_ctl, 1); 2778 assert(0 == streams[0]->n_unacked); 2779 assert(0 == streams[1]->n_unacked); 2780 assert(1 == streams[2]->n_unacked); 2781 ack_packet(&tobjs.send_ctl, 2); 2782 assert(0 == streams[0]->n_unacked); 2783 assert(0 == streams[1]->n_unacked); 2784 assert(0 == streams[2]->n_unacked); 2785 2786 lsquic_stream_destroy(streams[0]); 2787 lsquic_stream_destroy(streams[1]); 2788 lsquic_stream_destroy(streams[2]); 2789 deinit_test_objs(&tobjs); 2790} 2791 2792 2793/* Test three: split large STREAM frame into two halves. The second half 2794 * goes into new packet. 2795 */ 2796static void 2797test_bad_packbits_guess_3 (void) 2798{ 2799 lsquic_packet_out_t *packet_out; 2800 ssize_t nw; 2801 struct test_objs tobjs; 2802 struct lsquic_stream *streams[1]; 2803 char buf[0x1000]; 2804 unsigned char buf_out[0x1000]; 2805 int s, fin; 2806 2807 init_buf(buf, sizeof(buf)); 2808 2809 init_test_ctl_settings(&g_ctl_settings); 2810 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 2811 g_ctl_settings.tcs_guess_packno_bits = GQUIC_PACKNO_LEN_1; 2812 2813 init_test_objs(&tobjs, 0x1000, 0x1000, NULL); 2814 streams[0] = new_stream(&tobjs, 5); 2815 2816 nw = lsquic_stream_write(streams[0], buf, 2817 /* Use odd number to test halving logic: */ 1343); 2818 assert(nw == 1343); 2819 s = lsquic_stream_shutdown(streams[0], 1); 2820 assert(s == 0); 2821 2822 /* Verify that we got one packet filled to the top (minus one byte) */ 2823 const struct buf_packet_q *const bpq = 2824 &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type]; 2825 assert(("packetized -- 1 packet", 1 == bpq->bpq_count)); 2826 packet_out = TAILQ_FIRST(&bpq->bpq_packets); 2827 assert(1 == lsquic_packet_out_avail(packet_out)); 2828 2829 assert(1 == streams[0]->n_unacked); 2830 2831 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 2832 g_ctl_settings.tcs_calc_packno_bits = GQUIC_PACKNO_LEN_6; 2833 s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, 2834 g_ctl_settings.tcs_bp_type); 2835 assert(2 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)); 2836 2837 /* Verify written data: */ 2838 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out, 2839 sizeof(buf_out), 0, &fin, 0); 2840 assert(nw == 1343); 2841 assert(fin); 2842 assert(0 == memcmp(buf, buf_out, 1343)); 2843 2844 /* Verify packets */ 2845 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0); 2846 assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6); 2847 assert(1 == packet_out->po_packno); 2848 assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM)); 2849 lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out); 2850 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0); 2851 assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6); 2852 assert(2 == packet_out->po_packno); 2853 assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM)); 2854 lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out); 2855 2856 assert(2 == streams[0]->n_unacked); 2857 ack_packet(&tobjs.send_ctl, 1); 2858 assert(1 == streams[0]->n_unacked); 2859 ack_packet(&tobjs.send_ctl, 2); 2860 assert(0 == streams[0]->n_unacked); 2861 2862 lsquic_stream_destroy(streams[0]); 2863 deinit_test_objs(&tobjs); 2864} 2865 2866 2867/* Test resizing of buffered packets: 2868 * 1. Write data to buffered packets 2869 * 2. Reduce packet size 2870 * 3. Resize buffered packets 2871 * 4. Schedule them 2872 * 5. Check contents 2873 */ 2874static void 2875test_resize_buffered (void) 2876{ 2877 ssize_t nw; 2878 struct test_objs tobjs; 2879 struct lsquic_stream *streams[1]; 2880 const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27); 2881 char buf[0x10000]; 2882 unsigned char buf_out[0x10000]; 2883 int s, fin; 2884 unsigned packet_counts[2]; 2885 2886 init_buf(buf, sizeof(buf)); 2887 2888 lsquic_send_ctl_set_max_bpq_count(UINT_MAX); 2889 init_test_ctl_settings(&g_ctl_settings); 2890 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 2891 2892 init_test_objs(&tobjs, 0x100000, 0x100000, pf); 2893 tobjs.send_ctl.sc_flags |= SC_IETF; /* work around asserts lsquic_send_ctl_resize() */ 2894 network_path.np_pack_size = 4096; 2895 streams[0] = new_stream_ext(&tobjs, 8, 0x100000); 2896 2897 nw = lsquic_stream_write(streams[0], buf, sizeof(buf)); 2898 assert(nw == sizeof(buf)); 2899 s = lsquic_stream_shutdown(streams[0], 1); 2900 assert(s == 0); 2901 packet_counts[0] = tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type].bpq_count; 2902 2903 assert(streams[0]->n_unacked > 0); 2904 2905 network_path.np_pack_size = 1234; 2906 lsquic_send_ctl_resize(&tobjs.send_ctl); 2907 packet_counts[1] = tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type].bpq_count; 2908 assert(packet_counts[1] > packet_counts[0]); 2909 2910 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 2911 s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, 2912 g_ctl_settings.tcs_bp_type); 2913 assert(lsquic_send_ctl_n_scheduled(&tobjs.send_ctl) > 0); 2914 2915 /* Verify written data: */ 2916 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out, 2917 sizeof(buf_out), 0, &fin, 0); 2918 assert(nw == sizeof(buf)); 2919 assert(fin); 2920 assert(0 == memcmp(buf, buf_out, nw)); 2921 2922 lsquic_stream_destroy(streams[0]); 2923 deinit_test_objs(&tobjs); 2924 lsquic_send_ctl_set_max_bpq_count(10); 2925} 2926 2927 2928/* Test resizing of buffered packets: 2929 * 1. Write data to buffered packets 2930 * 2. Schedule them 2931 * 3. Reduce packet size 2932 * 4. Resize packets 2933 * 5. Check contents 2934 */ 2935static void 2936test_resize_scheduled (void) 2937{ 2938 ssize_t nw; 2939 struct test_objs tobjs; 2940 struct lsquic_stream *streams[1]; 2941 const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27); 2942 char buf[0x10000]; 2943 unsigned char buf_out[0x10000]; 2944 int s, fin; 2945 unsigned packet_counts[2]; 2946 2947 init_buf(buf, sizeof(buf)); 2948 2949 lsquic_send_ctl_set_max_bpq_count(UINT_MAX); 2950 init_test_ctl_settings(&g_ctl_settings); 2951 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 2952 2953 init_test_objs(&tobjs, 0x100000, 0x100000, pf); 2954 tobjs.send_ctl.sc_flags |= SC_IETF; /* work around asserts lsquic_send_ctl_resize() */ 2955 network_path.np_pack_size = 4096; 2956 streams[0] = new_stream_ext(&tobjs, 8, 0x100000); 2957 2958 nw = lsquic_stream_write(streams[0], buf, sizeof(buf)); 2959 assert(nw == sizeof(buf)); 2960 s = lsquic_stream_shutdown(streams[0], 1); 2961 assert(s == 0); 2962 2963 assert(streams[0]->n_unacked > 0); 2964 2965 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 2966 s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, 2967 g_ctl_settings.tcs_bp_type); 2968 packet_counts[0] = lsquic_send_ctl_n_scheduled(&tobjs.send_ctl); 2969 assert(packet_counts[0] > 0); 2970 2971 network_path.np_pack_size = 1234; 2972 lsquic_send_ctl_resize(&tobjs.send_ctl); 2973 packet_counts[1] = lsquic_send_ctl_n_scheduled(&tobjs.send_ctl); 2974 assert(packet_counts[1] > packet_counts[0]); 2975 2976 /* Verify written data: */ 2977 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out, 2978 sizeof(buf_out), 0, &fin, 0); 2979 assert(nw == sizeof(buf)); 2980 assert(fin); 2981 assert(0 == memcmp(buf, buf_out, nw)); 2982 2983 lsquic_stream_destroy(streams[0]); 2984 deinit_test_objs(&tobjs); 2985 lsquic_send_ctl_set_max_bpq_count(10); 2986} 2987 2988 2989struct packetization_test_stream_ctx 2990{ 2991 const unsigned char *buf; 2992 unsigned len, off, write_size; 2993}; 2994 2995 2996static lsquic_stream_ctx_t * 2997packetization_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream) 2998{ 2999 lsquic_stream_wantwrite(stream, 1); 3000 return stream_if_ctx; 3001} 3002 3003 3004static void 3005packetization_on_close (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h) 3006{ 3007} 3008 3009 3010#define RANDOM_WRITE_SIZE ~0U 3011 3012static unsigned 3013calc_n_to_write (unsigned write_size) 3014{ 3015 if (write_size == RANDOM_WRITE_SIZE) 3016 return rand() % 1000 + 1; 3017 else 3018 return write_size; 3019} 3020 3021 3022static void 3023packetization_write_as_much_as_you_can (lsquic_stream_t *stream, 3024 lsquic_stream_ctx_t *ctx) 3025{ 3026 struct packetization_test_stream_ctx *const pack_ctx = (void *) ctx; 3027 unsigned n_to_write; 3028 ssize_t n_written; 3029 int s; 3030 3031 while (pack_ctx->off < pack_ctx->len) 3032 { 3033 n_to_write = calc_n_to_write(pack_ctx->write_size); 3034 if (n_to_write > pack_ctx->len - pack_ctx->off) 3035 n_to_write = pack_ctx->len - pack_ctx->off; 3036 n_written = lsquic_stream_write(stream, pack_ctx->buf + pack_ctx->off, 3037 n_to_write); 3038 assert(n_written >= 0); 3039 if (n_written == 0) 3040 break; 3041 pack_ctx->off += n_written; 3042 } 3043 3044 s = lsquic_stream_flush(stream); 3045 assert(s == 0); 3046 lsquic_stream_wantwrite(stream, 0); 3047} 3048 3049 3050static void 3051packetization_perform_one_write (lsquic_stream_t *stream, 3052 lsquic_stream_ctx_t *ctx) 3053{ 3054 struct packetization_test_stream_ctx *const pack_ctx = (void *) ctx; 3055 unsigned n_to_write; 3056 ssize_t n_written; 3057 3058 n_to_write = calc_n_to_write(pack_ctx->write_size); 3059 if (n_to_write > pack_ctx->len - pack_ctx->off) 3060 n_to_write = pack_ctx->len - pack_ctx->off; 3061 n_written = lsquic_stream_write(stream, pack_ctx->buf + pack_ctx->off, 3062 n_to_write); 3063 assert(n_written >= 0); 3064 pack_ctx->off += n_written; 3065 if (n_written == 0) 3066 lsquic_stream_wantwrite(stream, 0); 3067} 3068 3069 3070static const struct lsquic_stream_if packetization_inside_once_stream_if = { 3071 .on_new_stream = packetization_on_new_stream, 3072 .on_close = packetization_on_close, 3073 .on_write = packetization_write_as_much_as_you_can, 3074}; 3075 3076 3077static const struct lsquic_stream_if packetization_inside_many_stream_if = { 3078 .on_new_stream = packetization_on_new_stream, 3079 .on_close = packetization_on_close, 3080 .on_write = packetization_perform_one_write, 3081}; 3082 3083 3084static void 3085test_packetization (int schedule_stream_packets_immediately, int dispatch_once, 3086 unsigned write_size, unsigned first_stream_sz) 3087{ 3088 struct test_objs tobjs; 3089 struct lsquic_stream *streams[2]; 3090 size_t nw; 3091 int fin; 3092 unsigned stream_ids[2]; 3093 unsigned char buf[0x8000]; 3094 unsigned char buf_out[0x8000]; 3095 3096 struct packetization_test_stream_ctx packet_stream_ctx = 3097 { 3098 .buf = buf, 3099 .off = 0, 3100 .len = sizeof(buf), 3101 .write_size = write_size, 3102 }; 3103 3104 init_buf(buf, sizeof(buf)); 3105 3106 init_test_ctl_settings(&g_ctl_settings); 3107 g_ctl_settings.tcs_schedule_stream_packets_immediately = schedule_stream_packets_immediately; 3108 3109 init_test_objs(&tobjs, 3110 /* Test limits a bit while we are at it: */ 3111 sizeof(buf) - 1, sizeof(buf) - 1, NULL); 3112 tobjs.stream_if_ctx = &packet_stream_ctx; 3113 3114 if (schedule_stream_packets_immediately) 3115 { 3116 if (dispatch_once) 3117 { 3118 tobjs.stream_if = &packetization_inside_once_stream_if; 3119 tobjs.ctor_flags |= SCF_DISP_RW_ONCE; 3120 } 3121 else 3122 tobjs.stream_if = &packetization_inside_many_stream_if; 3123 } 3124 else 3125 /* Need this for on_new_stream() callback not to mess with 3126 * the context, otherwise this is not used. 3127 */ 3128 tobjs.stream_if = &packetization_inside_many_stream_if; 3129 3130 if (g_use_crypto_ctor) 3131 { 3132 stream_ids[0] = ENC_LEV_CLEAR; 3133 stream_ids[1] = ENC_LEV_INIT; 3134 } 3135 else 3136 { 3137 stream_ids[0] = 7; 3138 stream_ids[1] = 5; 3139 } 3140 3141 streams[0] = new_stream(&tobjs, stream_ids[0]); 3142 streams[1] = new_stream_ext(&tobjs, stream_ids[1], sizeof(buf) - 1); 3143 3144 if (first_stream_sz) 3145 { 3146 lsquic_stream_write(streams[0], buf, first_stream_sz); 3147 lsquic_stream_flush(streams[0]); 3148 } 3149 3150 if (schedule_stream_packets_immediately) 3151 { 3152 lsquic_stream_dispatch_write_events(streams[1]); 3153 lsquic_stream_flush(streams[1]); 3154 } 3155 else 3156 { 3157 packetization_write_as_much_as_you_can(streams[1], 3158 (void *) &packet_stream_ctx); 3159 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 3160 lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, BPT_HIGHEST_PRIO); 3161 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 3162 } 3163 3164 if (!g_use_crypto_ctor) 3165 assert(packet_stream_ctx.off == packet_stream_ctx.len - first_stream_sz - 1); 3166 3167 /* Verify written data: */ 3168 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[1]->id, buf_out, 3169 sizeof(buf_out), 0, &fin, 1); 3170 if (!g_use_crypto_ctor) 3171 { 3172 assert(nw == sizeof(buf) - first_stream_sz - 1); 3173 assert(!fin); 3174 assert(0 == memcmp(buf, buf_out, sizeof(buf) - first_stream_sz - 1)); 3175 } 3176 else 3177 { 3178 assert(sizeof(buf) == nw); 3179 assert(0 == memcmp(buf, buf_out, nw)); 3180 } 3181 3182 lsquic_stream_destroy(streams[0]); 3183 lsquic_stream_destroy(streams[1]); 3184 deinit_test_objs(&tobjs); 3185} 3186 3187 3188/* Test condition when the room necessary to write a STREAM frame to a packet 3189 * is miscalculated and a brand-new packet has to be allocated. 3190 * 3191 * This does not affect IETF QUIC because the STREAM frame uses varint data 3192 * length representation and thus uses just a single byte to represent the 3193 * length of a 1-byte stream data chunk. 3194 */ 3195static void 3196test_cant_fit_frame (const struct parse_funcs *pf) 3197{ 3198 struct test_objs tobjs; 3199 struct lsquic_stream *streams[2]; 3200 struct lsquic_packet_out *packet_out; 3201 size_t pad_len, rem, nr; 3202 int fin, s; 3203 const char dude[] = "Dude, where is my car?!"; 3204 unsigned char buf_out[100]; 3205 3206 init_test_ctl_settings(&g_ctl_settings); 3207 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 3208 3209 init_test_objs(&tobjs, 0x8000, 0x8000, pf); 3210 3211 streams[0] = new_stream(&tobjs, 5); 3212 streams[1] = new_stream(&tobjs, 7); 3213 3214 /* Allocate a packet and pad it so just a few bytes remain to trigger 3215 * the condition we're after. 3216 */ 3217 lsquic_stream_write(streams[0], dude, sizeof(dude) - 1); 3218 lsquic_stream_flush(streams[0]); 3219 3220 rem = pf->pf_calc_stream_frame_header_sz(streams[1]->id, 0, 1) 3221 + 1 /* We'll write one byte */ 3222 + 1 /* This triggers the refit condition */ 3223 ; 3224 3225 packet_out = TAILQ_FIRST(&tobjs.send_ctl.sc_buffered_packets[0].bpq_packets); 3226 assert(NULL == TAILQ_NEXT(packet_out, po_next)); 3227 pad_len = packet_out->po_n_alloc - packet_out->po_data_sz - rem; 3228 memset(packet_out->po_data + packet_out->po_data_sz, 0, pad_len); 3229 packet_out->po_data_sz += pad_len; 3230 3231 lsquic_stream_write(streams[1], "A", 1); 3232 s = lsquic_stream_flush(streams[1]); 3233 assert(0 == s); 3234 /* Allocated another packet */ 3235 assert(TAILQ_NEXT(packet_out, po_next)); 3236 3237 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 3238 lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, BPT_HIGHEST_PRIO); 3239 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 3240 3241 /* Verify written data: */ 3242 nr = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out, 3243 sizeof(buf_out), 0, &fin, 1); 3244 assert(nr == sizeof(dude) - 1); 3245 assert(!fin); 3246 assert(0 == memcmp(dude, buf_out, sizeof(dude) - 1)); 3247 nr = read_from_scheduled_packets(&tobjs.send_ctl, streams[1]->id, buf_out, 3248 sizeof(buf_out), 0, &fin, 1); 3249 assert(nr == 1); 3250 assert(!fin); 3251 assert(buf_out[0] == 'A'); 3252 3253 lsquic_stream_destroy(streams[0]); 3254 lsquic_stream_destroy(streams[1]); 3255 deinit_test_objs(&tobjs); 3256} 3257 3258 3259/* Test window update logic, not connection limited */ 3260static void 3261test_window_update2 (void) 3262{ 3263 ssize_t nw; 3264 int s; 3265 struct test_objs tobjs; 3266 struct lsquic_stream *stream; 3267 lsquic_packet_out_t *packet_out; 3268 struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap; 3269 unsigned char buf[0x1000]; 3270 3271 init_test_objs(&tobjs, 0x4000, 0x4000, NULL); 3272 n_closed = 0; 3273 stream = new_stream_ext(&tobjs, 1, 3); 3274 nw = lsquic_stream_write(stream, "1234567890", 10); 3275 lsquic_stream_flush(stream); 3276 assert(("lsquic_stream_write is limited by the send window", 3 == nw)); 3277 s = lsquic_stream_flush(stream); 3278 assert(0 == s); 3279 assert(("cc_tosend is not updated when not limited by connection", 3280 0 == conn_cap->cc_sent)); 3281 assert(stream->sm_qflags & SMQF_SEND_BLOCKED); 3282 nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf, 3283 sizeof(buf), 0, NULL, 0); 3284 assert(nw == 3); 3285 assert(0 == memcmp(buf, "123", 3)); 3286 3287 /* Pretend we sent out a packet: */ 3288 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0); 3289 lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out); 3290 3291 lsquic_stream_window_update(stream, 20); 3292 nw = lsquic_stream_write(stream, "4567890", 7); 3293 assert(("lsquic_stream_write: wrote remainig 7 bytes", 7 == nw)); 3294 s = lsquic_stream_flush(stream); 3295 assert(0 == s); 3296 3297 /* Verify written data: */ 3298 nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf, 3299 sizeof(buf), 3, NULL, 0); 3300 assert(nw == 7); 3301 assert(0 == memcmp(buf, "4567890", 7)); 3302 3303 lsquic_stream_destroy(stream); 3304 assert(("on_close called", 1 == n_closed)); 3305 3306 deinit_test_objs(&tobjs); 3307} 3308 3309 3310/* Test that stream is marked as both stream- and connection-blocked */ 3311static void 3312test_blocked_flags (void) 3313{ 3314 ssize_t nw; 3315 struct test_objs tobjs; 3316 struct lsquic_stream *stream; 3317 struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap; 3318 int s; 3319 3320 init_test_ctl_settings(&g_ctl_settings); 3321 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 3322 3323 init_test_objs(&tobjs, 3, 3, NULL); 3324 stream = new_stream_ext(&tobjs, 123, 3); 3325 nw = lsquic_stream_write(stream, "1234567890", 10); 3326 assert(("lsquic_stream_write is limited by the send window", 3 == nw)); 3327 assert(("cc_tosend is updated immediately", 3328 3 == conn_cap->cc_sent)); 3329 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)); /* Flush occurred already */ 3330 s = lsquic_stream_flush(stream); 3331 assert(0 == s); 3332 assert(("cc_tosend is updated when limited by connection", 3333 3 == conn_cap->cc_sent)); 3334 assert(stream->sm_qflags & SMQF_SEND_BLOCKED); 3335 assert(3 == stream->blocked_off); 3336 assert(tobjs.lconn.cn_flags & LSCONN_SEND_BLOCKED); 3337 assert(3 == conn_cap->cc_blocked); 3338 3339 lsquic_stream_destroy(stream); 3340 deinit_test_objs(&tobjs); 3341} 3342 3343 3344static void 3345test_forced_flush_when_conn_blocked (void) 3346{ 3347 ssize_t nw; 3348 struct test_objs tobjs; 3349 struct lsquic_stream *stream; 3350 struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap; 3351 enum stream_state_sending sss; 3352 3353 init_test_ctl_settings(&g_ctl_settings); 3354 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 3355 3356 init_test_objs(&tobjs, 3, 0x1000, NULL); 3357 stream = new_stream(&tobjs, 123); 3358 sss = lsquic_stream_sending_state(stream); 3359 assert(SSS_READY == sss); 3360 nw = lsquic_stream_write(stream, "1234567890", 10); 3361 assert(("lsquic_stream_write is limited by the send window", 3 == nw)); 3362 assert(("cc_tosend is updated immediately", 3363 3 == conn_cap->cc_sent)); 3364 assert(1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)); /* Flush occurred */ 3365 sss = lsquic_stream_sending_state(stream); 3366 assert(SSS_SEND == sss); 3367 assert(tobjs.lconn.cn_flags & LSCONN_SEND_BLOCKED); 3368 assert(3 == conn_cap->cc_blocked); 3369 3370 lsquic_stream_destroy(stream); 3371 deinit_test_objs(&tobjs); 3372} 3373 3374 3375static int 3376my_gen_stream_frame_err (unsigned char *buf, size_t bufsz, 3377 lsquic_stream_id_t stream_id, uint64_t offset, 3378 int fin, size_t size, gsf_read_f read, 3379 void *stream) 3380{ 3381 return -1; 3382} 3383 3384 3385static void 3386test_conn_abort (void) 3387{ 3388 ssize_t nw; 3389 struct test_objs tobjs; 3390 struct lsquic_stream *stream; 3391 struct parse_funcs my_pf; 3392 int s; 3393 3394 init_test_ctl_settings(&g_ctl_settings); 3395 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 3396 3397 init_test_objs(&tobjs, 0x1000, 0x1000, NULL); 3398 my_pf = *tobjs.lconn.cn_pf; 3399 my_pf.pf_gen_stream_frame = my_gen_stream_frame_err; 3400 tobjs.lconn.cn_pf = &my_pf; 3401 3402 stream = new_stream(&tobjs, 123); 3403 nw = lsquic_stream_write(stream, "1234567890", 10); 3404 assert(10 == nw); /* No error yet */ 3405 s = lsquic_stream_flush(stream); 3406 assert(s < 0); 3407 assert(stream->sm_qflags & SMQF_ABORT_CONN); 3408 assert(!TAILQ_EMPTY(&tobjs.conn_pub.service_streams)); 3409 3410 lsquic_stream_destroy(stream); 3411 deinit_test_objs(&tobjs); 3412} 3413 3414 3415/* Test one: large frame first, followed by small frames to finish off 3416 * the packet. 3417 */ 3418static void 3419test_bad_packbits_guess_1 (void) 3420{ 3421 lsquic_packet_out_t *packet_out; 3422 ssize_t nw; 3423 struct test_objs tobjs; 3424 struct lsquic_stream *streams[3]; 3425 char buf[0x1000]; 3426 unsigned char buf_out[0x1000]; 3427 int s, fin; 3428 3429 init_buf(buf, sizeof(buf)); 3430 3431 init_test_ctl_settings(&g_ctl_settings); 3432 g_ctl_settings.tcs_schedule_stream_packets_immediately = 0; 3433 g_ctl_settings.tcs_guess_packno_bits = GQUIC_PACKNO_LEN_1; 3434 3435 init_test_objs(&tobjs, 0x1000, 0x1000, NULL); 3436 streams[0] = new_stream(&tobjs, 5); 3437 streams[1] = new_stream(&tobjs, 7); 3438 streams[2] = new_stream(&tobjs, 9); 3439 3440 /* Perfrom writes on the three streams. This is tuned to fill a single 3441 * packet completely -- we check this later in this function. 3442 */ 3443 nw = lsquic_stream_write(streams[0], buf, 1337); 3444 assert(nw == 1337); 3445 s = lsquic_stream_flush(streams[0]); 3446 assert(0 == s); 3447 s = lsquic_stream_shutdown(streams[1], 1); 3448 assert(s == 0); 3449 nw = lsquic_stream_write(streams[2], buf + 1337, 1); 3450 assert(nw == 1); 3451 s = lsquic_stream_shutdown(streams[2], 1); 3452 assert(s == 0); 3453 3454 /* Verify that we got one packet filled to the top: */ 3455 const struct buf_packet_q *const bpq = 3456 &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type]; 3457 assert(("packetized -- 1 packet", 1 == bpq->bpq_count)); 3458 packet_out = TAILQ_FIRST(&bpq->bpq_packets); 3459 assert(0 == lsquic_packet_out_avail(packet_out)); 3460 3461 assert(1 == streams[0]->n_unacked); 3462 assert(1 == streams[1]->n_unacked); 3463 assert(1 == streams[2]->n_unacked); 3464 3465 g_ctl_settings.tcs_schedule_stream_packets_immediately = 1; 3466 g_ctl_settings.tcs_calc_packno_bits = GQUIC_PACKNO_LEN_6; 3467 s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, 3468 g_ctl_settings.tcs_bp_type); 3469 assert(2 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)); 3470 3471 /* Verify written data: */ 3472 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out, 3473 sizeof(buf_out), 0, &fin, 0); 3474 assert(nw == 1337); 3475 assert(!fin); 3476 assert(0 == memcmp(buf, buf_out, 1337)); 3477 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[1]->id, buf_out, 3478 sizeof(buf_out), 0, &fin, 0); 3479 assert(nw == 0); 3480 assert(fin); 3481 nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[2]->id, buf_out, 3482 sizeof(buf_out), 0, &fin, 0); 3483 assert(nw == 1); 3484 assert(fin); 3485 assert(0 == memcmp(buf + 1337, buf_out, 1)); 3486 3487 /* Verify packets */ 3488 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0); 3489 assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6); 3490 assert(1 == packet_out->po_packno); 3491 assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM)); 3492 lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out); 3493 packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0); 3494 assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6); 3495 assert(2 == packet_out->po_packno); 3496 assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM)); 3497 lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out); 3498 3499 assert(1 == streams[0]->n_unacked); 3500 assert(1 == streams[1]->n_unacked); 3501 assert(1 == streams[2]->n_unacked); 3502 ack_packet(&tobjs.send_ctl, 1); 3503 assert(0 == streams[0]->n_unacked); 3504 assert(1 == streams[1]->n_unacked); 3505 assert(1 == streams[2]->n_unacked); 3506 ack_packet(&tobjs.send_ctl, 2); 3507 assert(0 == streams[0]->n_unacked); 3508 assert(0 == streams[1]->n_unacked); 3509 assert(0 == streams[2]->n_unacked); 3510 3511 lsquic_stream_destroy(streams[0]); 3512 lsquic_stream_destroy(streams[1]); 3513 lsquic_stream_destroy(streams[2]); 3514 deinit_test_objs(&tobjs); 3515} 3516 3517 3518static void 3519main_test_packetization (void) 3520{ 3521 const unsigned fp_sizes[] = { 0, 10, 100, 501, 1290, }; 3522 unsigned i; 3523 for (i = 0; i < sizeof(fp_sizes) / sizeof(fp_sizes[0]); ++i) 3524 { 3525 int once; 3526 unsigned write_size; 3527 if (!g_use_crypto_ctor) /* No buffered packets for CRYPTO frames */ 3528 { 3529 for (write_size = 1; write_size < GQUIC_MAX_PACKET_SZ; ++write_size) 3530 test_packetization(0, 0, write_size, fp_sizes[i]); 3531 srand(7891); 3532 for (write_size = 1; write_size < GQUIC_MAX_PACKET_SZ * 10; ++write_size) 3533 test_packetization(0, 0, RANDOM_WRITE_SIZE, fp_sizes[i]); 3534 } 3535 for (once = 0; once < 2; ++once) 3536 { 3537 for (write_size = 1; write_size < GQUIC_MAX_PACKET_SZ; ++write_size) 3538 test_packetization(1, once, write_size, fp_sizes[i]); 3539 srand(7891); 3540 for (write_size = 1; write_size < GQUIC_MAX_PACKET_SZ * 10; ++write_size) 3541 test_packetization(1, once, RANDOM_WRITE_SIZE, fp_sizes[i]); 3542 } 3543 } 3544} 3545 3546 3547int 3548main (int argc, char **argv) 3549{ 3550 int opt; 3551 3552 lsquic_global_init(LSQUIC_GLOBAL_SERVER); 3553 3554 while (-1 != (opt = getopt(argc, argv, "Ahl:"))) 3555 { 3556 switch (opt) 3557 { 3558 case 'A': 3559 stream_ctor_flags &= ~SCF_DI_AUTOSWITCH; 3560 break; 3561 case 'h': 3562 stream_ctor_flags |= SCF_USE_DI_HASH; 3563 break; 3564 case 'l': 3565 lsquic_log_to_fstream(stderr, 0); 3566 lsquic_logger_lopt(optarg); 3567 break; 3568 default: 3569 exit(1); 3570 } 3571 } 3572 3573 init_test_ctl_settings(&g_ctl_settings); 3574 3575 test_writing_to_stream_schedule_stream_packets_immediately(); 3576 test_writing_to_stream_outside_callback(); 3577 test_stealing_ack(); 3578 test_changing_pack_size(); 3579 test_reducing_pack_size(); 3580 test_window_update1(); 3581 test_window_update2(); 3582 test_forced_flush_when_conn_blocked(); 3583 test_blocked_flags(); 3584 test_reading_from_stream2(); 3585 test_overlaps(); 3586 test_insert_edge_cases(); 3587 test_unexpected_http_close(); 3588 3589 { 3590 int idx[6]; 3591 permute_and_run(0, 0, 0, idx, sizeof(idx) / sizeof(idx[0])); 3592 } 3593 3594 test_termination(); 3595 3596 test_writev(); 3597 3598 test_prio_conversion(); 3599 3600 test_read_in_middle(); 3601 3602 test_conn_unlimited(); 3603 3604 test_flushing(); 3605 3606 test_conn_abort(); 3607 3608 test_bad_packbits_guess_1(); 3609 test_bad_packbits_guess_2(); 3610 test_bad_packbits_guess_3(); 3611 3612 test_resize_buffered(); 3613 test_resize_scheduled(); 3614 3615 main_test_packetization(); 3616 3617 enum lsquic_version ver; 3618 for (ver = 0; ver < N_LSQVER; ++ver) 3619 if (!((1 << ver) & LSQUIC_IETF_VERSIONS)) 3620 test_cant_fit_frame(select_pf_by_ver(ver)); 3621 3622 /* Redo some tests using crypto streams and frames */ 3623 g_use_crypto_ctor = 1; 3624 g_pf = select_pf_by_ver(LSQVER_ID27); 3625 main_test_packetization(); 3626 3627 return 0; 3628} 3629 3630static const char on_being_idle[] = 3631"ON BEING IDLE." 3632"" 3633"Now, this is a subject on which I flatter myself I really am _au fait_." 3634"The gentleman who, when I was young, bathed me at wisdom's font for nine" 3635"guineas a term--no extras--used to say he never knew a boy who could" 3636"do less work in more time; and I remember my poor grandmother once" 3637"incidentally observing, in the course of an instruction upon the use" 3638"of the Prayer-book, that it was highly improbable that I should ever do" 3639"much that I ought not to do, but that she felt convinced beyond a doubt" 3640"that I should leave undone pretty well everything that I ought to do." 3641"" 3642"I am afraid I have somewhat belied half the dear old lady's prophecy." 3643"Heaven help me! I have done a good many things that I ought not to have" 3644"done, in spite of my laziness. But I have fully confirmed the accuracy" 3645"of her judgment so far as neglecting much that I ought not to have" 3646"neglected is concerned. Idling always has been my strong point. I take" 3647"no credit to myself in the matter--it is a gift. Few possess it. There" 3648"are plenty of lazy people and plenty of slow-coaches, but a genuine" 3649"idler is a rarity. He is not a man who slouches about with his hands in" 3650"his pockets. On the contrary, his most startling characteristic is that" 3651"he is always intensely busy." 3652"" 3653"It is impossible to enjoy idling thoroughly unless one has plenty of" 3654"work to do. There is no fun in doing nothing when you have nothing to" 3655"do. Wasting time is merely an occupation then, and a most exhausting" 3656"one. Idleness, like kisses, to be sweet must be stolen." 3657"" 3658"Many years ago, when I was a young man, I was taken very ill--I never" 3659"could see myself that much was the matter with me, except that I had" 3660"a beastly cold. But I suppose it was something very serious, for the" 3661"doctor said that I ought to have come to him a month before, and that" 3662"if it (whatever it was) had gone on for another week he would not have" 3663"answered for the consequences. It is an extraordinary thing, but I" 3664"never knew a doctor called into any case yet but what it transpired" 3665"that another day's delay would have rendered cure hopeless. Our medical" 3666"guide, philosopher, and friend is like the hero in a melodrama--he" 3667"always comes upon the scene just, and only just, in the nick of time. It" 3668"is Providence, that is what it is." 3669"" 3670"Well, as I was saying, I was very ill and was ordered to Buxton for a" 3671"month, with strict injunctions to do nothing whatever all the while" 3672"that I was there. \"Rest is what you require,\" said the doctor, \"perfect" 3673"rest.\"" 3674"" 3675"It seemed a delightful prospect. \"This man evidently understands my" 3676"complaint,\" said I, and I pictured to myself a glorious time--a four" 3677"weeks' _dolce far niente_ with a dash of illness in it. Not too much" 3678"illness, but just illness enough--just sufficient to give it the flavor" 3679"of suffering and make it poetical. I should get up late, sip chocolate," 3680"and have my breakfast in slippers and a dressing-gown. I should lie out" 3681"in the garden in a hammock and read sentimental novels with a melancholy" 3682"ending, until the books should fall from my listless hand, and I should" 3683"recline there, dreamily gazing into the deep blue of the firmament," 3684"watching the fleecy clouds floating like white-sailed ships across" 3685"its depths, and listening to the joyous song of the birds and the low" 3686"rustling of the trees. Or, on becoming too weak to go out of doors," 3687"I should sit propped up with pillows at the open window of the" 3688"ground-floor front, and look wasted and interesting, so that all the" 3689"pretty girls would sigh as they passed by." 3690"" 3691"And twice a day I should go down in a Bath chair to the Colonnade to" 3692"drink the waters. Oh, those waters! I knew nothing about them then," 3693"and was rather taken with the idea. \"Drinking the waters\" sounded" 3694"fashionable and Queen Anne-fied, and I thought I should like them. But," 3695"ugh! after the first three or four mornings! Sam Weller's description of" 3696"them as \"having a taste of warm flat-irons\" conveys only a faint idea of" 3697"their hideous nauseousness. If anything could make a sick man get well" 3698"quickly, it would be the knowledge that he must drink a glassful of them" 3699"every day until he was recovered. I drank them neat for six consecutive" 3700"days, and they nearly killed me; but after then I adopted the plan of" 3701"taking a stiff glass of brandy-and-water immediately on the top of them," 3702"and found much relief thereby. I have been informed since, by various" 3703"eminent medical gentlemen, that the alcohol must have entirely" 3704"counteracted the effects of the chalybeate properties contained in the" 3705"water. I am glad I was lucky enough to hit upon the right thing." 3706; 3707 3708static void 3709init_buf (void *buf, size_t sz) 3710{ 3711 unsigned char *p = buf; 3712 unsigned char *const end = (unsigned char*)buf + sz; 3713 size_t n; 3714 3715 while (p < end) 3716 { 3717 n = end - p; 3718 if (sizeof(on_being_idle) - 1 < n) 3719 n = sizeof(on_being_idle) - 1; 3720 memcpy(p, on_being_idle, n); 3721 p +=n; 3722 } 3723 3724 assert(p == end); 3725} 3726