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