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