1 /* 2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 #include "internal/packet.h" 10 #include "internal/quic_stream.h" 11 #include "testutil.h" 12 13 static int compare_iov(const unsigned char *ref, size_t ref_len, 14 const OSSL_QTX_IOVEC *iov, size_t iov_len) 15 { 16 size_t i, total_len = 0; 17 const unsigned char *cur = ref; 18 19 for (i = 0; i < iov_len; ++i) 20 total_len += iov[i].buf_len; 21 22 if (ref_len != total_len) 23 return 0; 24 25 for (i = 0; i < iov_len; ++i) { 26 if (memcmp(cur, iov[i].buf, iov[i].buf_len)) 27 return 0; 28 29 cur += iov[i].buf_len; 30 } 31 32 return 1; 33 } 34 35 static const unsigned char data_1[] = { 36 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 37 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f 38 }; 39 40 static int test_sstream_simple(void) 41 { 42 int testresult = 0; 43 QUIC_SSTREAM *sstream = NULL; 44 OSSL_QUIC_FRAME_STREAM hdr; 45 OSSL_QTX_IOVEC iov[2]; 46 size_t num_iov = 0, wr = 0, i, init_size = 8192; 47 48 if (!TEST_ptr(sstream = ossl_quic_sstream_new(init_size))) 49 goto err; 50 51 /* A stream with nothing yet appended is totally acked */ 52 if (!TEST_true(ossl_quic_sstream_is_totally_acked(sstream))) 53 goto err; 54 55 /* Should not have any data yet */ 56 num_iov = OSSL_NELEM(iov); 57 if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 58 &num_iov))) 59 goto err; 60 61 /* Append data */ 62 if (!TEST_true(ossl_quic_sstream_append(sstream, data_1, sizeof(data_1), 63 &wr)) 64 || !TEST_size_t_eq(wr, sizeof(data_1))) 65 goto err; 66 67 /* No longer totally acked */ 68 if (!TEST_false(ossl_quic_sstream_is_totally_acked(sstream))) 69 goto err; 70 71 /* Read data */ 72 num_iov = OSSL_NELEM(iov); 73 if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 74 &num_iov)) 75 || !TEST_size_t_gt(num_iov, 0) 76 || !TEST_uint64_t_eq(hdr.offset, 0) 77 || !TEST_uint64_t_eq(hdr.len, sizeof(data_1)) 78 || !TEST_false(hdr.is_fin)) 79 goto err; 80 81 if (!TEST_true(compare_iov(data_1, sizeof(data_1), iov, num_iov))) 82 goto err; 83 84 /* Mark data as half transmitted */ 85 if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 0, 7))) 86 goto err; 87 88 /* Read data */ 89 num_iov = OSSL_NELEM(iov); 90 if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 91 &num_iov)) 92 || !TEST_size_t_gt(num_iov, 0) 93 || !TEST_uint64_t_eq(hdr.offset, 8) 94 || !TEST_uint64_t_eq(hdr.len, sizeof(data_1) - 8) 95 || !TEST_false(hdr.is_fin)) 96 goto err; 97 98 if (!TEST_true(compare_iov(data_1 + 8, sizeof(data_1) - 8, iov, num_iov))) 99 goto err; 100 101 if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 8, 15))) 102 goto err; 103 104 /* Read more data; should not be any more */ 105 num_iov = OSSL_NELEM(iov); 106 if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 107 &num_iov))) 108 goto err; 109 110 /* Now we have lost bytes 4-6 */ 111 if (!TEST_true(ossl_quic_sstream_mark_lost(sstream, 4, 6))) 112 goto err; 113 114 /* Should be able to read them */ 115 num_iov = OSSL_NELEM(iov); 116 if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 117 &num_iov)) 118 || !TEST_size_t_gt(num_iov, 0) 119 || !TEST_uint64_t_eq(hdr.offset, 4) 120 || !TEST_uint64_t_eq(hdr.len, 3) 121 || !TEST_false(hdr.is_fin)) 122 goto err; 123 124 if (!TEST_true(compare_iov(data_1 + 4, 3, iov, num_iov))) 125 goto err; 126 127 /* Retransmit */ 128 if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 4, 6))) 129 goto err; 130 131 /* Read more data; should not be any more */ 132 num_iov = OSSL_NELEM(iov); 133 if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 134 &num_iov))) 135 goto err; 136 137 if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 16)) 138 goto err; 139 140 /* Data has been acknowledged, space should be not be freed yet */ 141 if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 1, 7)) 142 || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 16)) 143 goto err; 144 145 /* Now data should be freed */ 146 if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 0)) 147 || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 8)) 148 goto err; 149 150 if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 15)) 151 || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 0)) 152 goto err; 153 154 /* Now FIN */ 155 ossl_quic_sstream_fin(sstream); 156 157 /* Get FIN frame */ 158 for (i = 0; i < 2; ++i) { 159 num_iov = OSSL_NELEM(iov); 160 if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 161 &num_iov)) 162 || !TEST_uint64_t_eq(hdr.offset, 16) 163 || !TEST_uint64_t_eq(hdr.len, 0) 164 || !TEST_true(hdr.is_fin) 165 || !TEST_size_t_eq(num_iov, 0)) 166 goto err; 167 } 168 169 if (!TEST_true(ossl_quic_sstream_mark_transmitted_fin(sstream, 16))) 170 goto err; 171 172 /* Read more data; FIN should not be returned any more */ 173 num_iov = OSSL_NELEM(iov); 174 if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 175 &num_iov))) 176 goto err; 177 178 /* Lose FIN frame */ 179 if (!TEST_true(ossl_quic_sstream_mark_lost_fin(sstream))) 180 goto err; 181 182 /* Get FIN frame */ 183 for (i = 0; i < 2; ++i) { 184 num_iov = OSSL_NELEM(iov); 185 if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 186 &num_iov)) 187 || !TEST_uint64_t_eq(hdr.offset, 16) 188 || !TEST_uint64_t_eq(hdr.len, 0) 189 || !TEST_true(hdr.is_fin) 190 || !TEST_size_t_eq(num_iov, 0)) 191 goto err; 192 } 193 194 if (!TEST_true(ossl_quic_sstream_mark_transmitted_fin(sstream, 16))) 195 goto err; 196 197 /* Read more data; FIN should not be returned any more */ 198 num_iov = OSSL_NELEM(iov); 199 if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, 200 &num_iov))) 201 goto err; 202 203 /* Acknowledge fin. */ 204 if (!TEST_true(ossl_quic_sstream_mark_acked_fin(sstream))) 205 goto err; 206 207 if (!TEST_true(ossl_quic_sstream_is_totally_acked(sstream))) 208 goto err; 209 210 testresult = 1; 211 err: 212 ossl_quic_sstream_free(sstream); 213 return testresult; 214 } 215 216 static int test_sstream_bulk(int idx) 217 { 218 int testresult = 0; 219 QUIC_SSTREAM *sstream = NULL; 220 OSSL_QUIC_FRAME_STREAM hdr; 221 OSSL_QTX_IOVEC iov[2]; 222 size_t i, j, num_iov = 0, init_size = 8192, l; 223 size_t consumed = 0, total_written = 0, rd, cur_rd, expected = 0, start_at; 224 unsigned char *src_buf = NULL, *dst_buf = NULL; 225 unsigned char *ref_src_buf = NULL, *ref_dst_buf = NULL; 226 unsigned char *ref_dst_cur, *ref_src_cur, *dst_cur; 227 228 if (!TEST_ptr(sstream = ossl_quic_sstream_new(init_size))) 229 goto err; 230 231 if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_size(sstream), init_size)) 232 goto err; 233 234 if (!TEST_ptr(src_buf = OPENSSL_zalloc(init_size))) 235 goto err; 236 237 if (!TEST_ptr(dst_buf = OPENSSL_malloc(init_size))) 238 goto err; 239 240 if (!TEST_ptr(ref_src_buf = OPENSSL_malloc(init_size))) 241 goto err; 242 243 if (!TEST_ptr(ref_dst_buf = OPENSSL_malloc(init_size))) 244 goto err; 245 246 /* 247 * Append a preliminary buffer to allow later code to exercise wraparound. 248 */ 249 if (!TEST_true(ossl_quic_sstream_append(sstream, src_buf, init_size / 2, 250 &consumed)) 251 || !TEST_size_t_eq(consumed, init_size / 2) 252 || !TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 0, 253 init_size / 2 - 1)) 254 || !TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 255 init_size / 2 - 1))) 256 goto err; 257 258 start_at = init_size / 2; 259 260 /* Generate a random buffer. */ 261 for (i = 0; i < init_size; ++i) 262 src_buf[i] = (unsigned char)(test_random() & 0xFF); 263 264 /* Append bytes into the buffer in chunks of random length. */ 265 ref_src_cur = ref_src_buf; 266 do { 267 l = (test_random() % init_size) + 1; 268 if (!TEST_true(ossl_quic_sstream_append(sstream, src_buf, l, &consumed))) 269 goto err; 270 271 memcpy(ref_src_cur, src_buf, consumed); 272 ref_src_cur += consumed; 273 total_written += consumed; 274 } while (consumed > 0); 275 276 if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), init_size) 277 || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_avail(sstream), 0)) 278 goto err; 279 280 /* 281 * Randomly select bytes out of the buffer by marking them as transmitted. 282 * Record the remaining bytes, which should be the sequence of bytes 283 * returned. 284 */ 285 ref_src_cur = ref_src_buf; 286 ref_dst_cur = ref_dst_buf; 287 for (i = 0; i < total_written; ++i) { 288 if ((test_random() & 1) != 0) { 289 *ref_dst_cur++ = *ref_src_cur; 290 ++expected; 291 } else if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 292 start_at + i, 293 start_at + i))) 294 goto err; 295 296 ++ref_src_cur; 297 } 298 299 /* Exercise resize. */ 300 if (!TEST_true(ossl_quic_sstream_set_buffer_size(sstream, init_size * 2)) 301 || !TEST_true(ossl_quic_sstream_set_buffer_size(sstream, init_size))) 302 goto err; 303 304 /* Readout and verification. */ 305 dst_cur = dst_buf; 306 for (i = 0, rd = 0; rd < expected; ++i) { 307 num_iov = OSSL_NELEM(iov); 308 if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, i, &hdr, iov, 309 &num_iov))) 310 goto err; 311 312 cur_rd = 0; 313 for (j = 0; j < num_iov; ++j) { 314 if (!TEST_size_t_le(iov[j].buf_len + rd, expected)) 315 goto err; 316 317 memcpy(dst_cur, iov[j].buf, iov[j].buf_len); 318 dst_cur += iov[j].buf_len; 319 cur_rd += iov[j].buf_len; 320 } 321 322 if (!TEST_uint64_t_eq(cur_rd, hdr.len)) 323 goto err; 324 325 rd += cur_rd; 326 } 327 328 if (!TEST_mem_eq(dst_buf, rd, ref_dst_buf, expected)) 329 goto err; 330 331 testresult = 1; 332 err: 333 OPENSSL_free(src_buf); 334 OPENSSL_free(dst_buf); 335 OPENSSL_free(ref_src_buf); 336 OPENSSL_free(ref_dst_buf); 337 ossl_quic_sstream_free(sstream); 338 return testresult; 339 } 340 341 static int test_single_copy_read(QUIC_RSTREAM *qrs, 342 unsigned char *buf, size_t size, 343 size_t *readbytes, int *fin) 344 { 345 const unsigned char *record; 346 size_t rec_len; 347 348 *readbytes = 0; 349 350 for (;;) { 351 if (!ossl_quic_rstream_get_record(qrs, &record, &rec_len, fin)) 352 return 0; 353 if (rec_len == 0) 354 break; 355 if (rec_len > size) { 356 rec_len = size; 357 *fin = 0; 358 } 359 memcpy(buf, record, rec_len); 360 size -= rec_len; 361 *readbytes += rec_len; 362 buf += rec_len; 363 364 if (!ossl_quic_rstream_release_record(qrs, rec_len)) 365 return 0; 366 if (*fin || size == 0) 367 break; 368 } 369 370 return 1; 371 } 372 373 static const unsigned char simple_data[] = 374 "Hello world! And thank you for all the fish!"; 375 376 static int test_rstream_simple(int idx) 377 { 378 QUIC_RSTREAM *rstream = NULL; 379 int ret = 0; 380 unsigned char buf[sizeof(simple_data)]; 381 size_t readbytes = 0, avail = 0; 382 int fin = 0; 383 int use_rbuf = idx > 1; 384 int use_sc = idx % 2; 385 int (* read_fn)(QUIC_RSTREAM *, unsigned char *, size_t, size_t *, 386 int *) = use_sc ? test_single_copy_read 387 : ossl_quic_rstream_read; 388 389 if (!TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, 0))) 390 goto err; 391 392 if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 5, 393 simple_data + 5, 10, 0)) 394 || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 395 sizeof(simple_data) - 1, 396 simple_data + sizeof(simple_data) - 1, 397 1, 1)) 398 || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf), 399 &readbytes, &fin)) 400 || !TEST_false(fin) 401 || !TEST_size_t_eq(readbytes, 0) 402 || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 403 sizeof(simple_data) - 10, 404 simple_data + sizeof(simple_data) - 10, 405 10, 1)) 406 || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 0, 407 simple_data, 1, 0)) 408 || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf), 409 &readbytes, &fin)) 410 || !TEST_false(fin) 411 || !TEST_size_t_eq(readbytes, 1) 412 || !TEST_mem_eq(buf, 1, simple_data, 1) 413 || (use_rbuf && !TEST_false(ossl_quic_rstream_move_to_rbuf(rstream))) 414 || (use_rbuf 415 && !TEST_true(ossl_quic_rstream_resize_rbuf(rstream, 416 sizeof(simple_data)))) 417 || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream))) 418 || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 419 0, simple_data, 420 10, 0)) 421 || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 422 sizeof(simple_data), 423 NULL, 424 0, 1)) 425 || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf), 426 &readbytes, &fin)) 427 || !TEST_false(fin) 428 || !TEST_size_t_eq(readbytes, 15) 429 || !TEST_mem_eq(buf, 15, simple_data, 15) 430 || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 431 15, 432 simple_data + 15, 433 sizeof(simple_data) - 15, 1)) 434 || !TEST_true(ossl_quic_rstream_available(rstream, &avail, &fin)) 435 || !TEST_true(fin) 436 || !TEST_size_t_eq(avail, sizeof(simple_data)) 437 || !TEST_true(read_fn(rstream, buf, 2, &readbytes, &fin)) 438 || !TEST_false(fin) 439 || !TEST_size_t_eq(readbytes, 2) 440 || !TEST_mem_eq(buf, 2, simple_data, 2) 441 || !TEST_true(read_fn(rstream, buf + 2, 12, &readbytes, &fin)) 442 || !TEST_false(fin) 443 || !TEST_size_t_eq(readbytes, 12) 444 || !TEST_mem_eq(buf + 2, 12, simple_data + 2, 12) 445 || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 446 sizeof(simple_data), 447 NULL, 448 0, 1)) 449 || (use_rbuf 450 && !TEST_true(ossl_quic_rstream_resize_rbuf(rstream, 451 2 * sizeof(simple_data)))) 452 || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream))) 453 || !TEST_true(read_fn(rstream, buf + 14, 5, &readbytes, &fin)) 454 || !TEST_false(fin) 455 || !TEST_size_t_eq(readbytes, 5) 456 || !TEST_mem_eq(buf, 14 + 5, simple_data, 14 + 5) 457 || !TEST_true(read_fn(rstream, buf + 14 + 5, sizeof(buf) - 14 - 5, 458 &readbytes, &fin)) 459 || !TEST_true(fin) 460 || !TEST_size_t_eq(readbytes, sizeof(buf) - 14 - 5) 461 || !TEST_mem_eq(buf, sizeof(buf), simple_data, sizeof(simple_data)) 462 || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream))) 463 || !TEST_true(read_fn(rstream, buf, sizeof(buf), &readbytes, &fin)) 464 || !TEST_true(fin) 465 || !TEST_size_t_eq(readbytes, 0)) 466 goto err; 467 468 ret = 1; 469 470 err: 471 ossl_quic_rstream_free(rstream); 472 return ret; 473 } 474 475 static int test_rstream_random(int idx) 476 { 477 unsigned char *bulk_data = NULL; 478 unsigned char *read_buf = NULL; 479 QUIC_RSTREAM *rstream = NULL; 480 size_t i, read_off, queued_min, queued_max; 481 const size_t data_size = 10000; 482 int r, s, fin = 0, fin_set = 0; 483 int ret = 0; 484 size_t readbytes = 0; 485 486 if (!TEST_ptr(bulk_data = OPENSSL_malloc(data_size)) 487 || !TEST_ptr(read_buf = OPENSSL_malloc(data_size)) 488 || !TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, 0))) 489 goto err; 490 491 if (idx % 3 == 0) 492 ossl_quic_rstream_set_cleanse(rstream, 1); 493 494 for (i = 0; i < data_size; ++i) 495 bulk_data[i] = (unsigned char)(test_random() & 0xFF); 496 497 read_off = queued_min = queued_max = 0; 498 for (r = 0; r < 100; ++r) { 499 for (s = 0; s < 10; ++s) { 500 size_t off = (r * 10 + s) * 10, size = 10; 501 502 if (test_random() % 10 == 0) 503 /* drop packet */ 504 continue; 505 506 if (off <= queued_min && off + size > queued_min) 507 queued_min = off + size; 508 509 if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, off, 510 bulk_data + off, 511 size, 0))) 512 goto err; 513 if (queued_max < off + size) 514 queued_max = off + size; 515 516 if (test_random() % 5 != 0) 517 continue; 518 519 /* random overlapping retransmit */ 520 off = read_off + test_random() % 50; 521 if (off > 50) 522 off -= 50; 523 size = test_random() % 100 + 1; 524 if (off + size > data_size) 525 off = data_size - size; 526 if (off <= queued_min && off + size > queued_min) 527 queued_min = off + size; 528 529 if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, off, 530 bulk_data + off, 531 size, 0))) 532 goto err; 533 if (queued_max < off + size) 534 queued_max = off + size; 535 } 536 if (idx % 2 == 0) { 537 if (!TEST_true(test_single_copy_read(rstream, read_buf, data_size, 538 &readbytes, &fin))) 539 goto err; 540 } else if (!TEST_true(ossl_quic_rstream_read(rstream, read_buf, 541 data_size, 542 &readbytes, &fin))) { 543 goto err; 544 } 545 if (!TEST_size_t_ge(readbytes, queued_min - read_off) 546 || !TEST_size_t_le(readbytes + read_off, data_size) 547 || (idx % 3 != 0 548 && !TEST_mem_eq(read_buf, readbytes, bulk_data + read_off, 549 readbytes))) 550 goto err; 551 read_off += readbytes; 552 queued_min = read_off; 553 if (test_random() % 50 == 0) 554 if (!TEST_true(ossl_quic_rstream_resize_rbuf(rstream, 555 queued_max - read_off + 1)) 556 || !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream))) 557 goto err; 558 if (!fin_set && queued_max >= data_size - test_random() % 200) { 559 fin_set = 1; 560 /* Queue empty fin frame */ 561 if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, data_size, 562 NULL, 0, 1))) 563 goto err; 564 } 565 } 566 567 TEST_info("Total read bytes: %zu Fin rcvd: %d", read_off, fin); 568 569 if (idx % 3 == 0) 570 for (i = 0; i < read_off; i++) 571 if (!TEST_uchar_eq(bulk_data[i], 0)) 572 goto err; 573 574 if (read_off == data_size && fin_set && !fin) { 575 /* We might still receive the final empty frame */ 576 if (idx % 2 == 0) { 577 if (!TEST_true(test_single_copy_read(rstream, read_buf, data_size, 578 &readbytes, &fin))) 579 goto err; 580 } else if (!TEST_true(ossl_quic_rstream_read(rstream, read_buf, 581 data_size, 582 &readbytes, &fin))) { 583 goto err; 584 } 585 if (!TEST_size_t_eq(readbytes, 0) || !TEST_true(fin)) 586 goto err; 587 } 588 589 ret = 1; 590 591 err: 592 ossl_quic_rstream_free(rstream); 593 OPENSSL_free(bulk_data); 594 OPENSSL_free(read_buf); 595 return ret; 596 } 597 598 int setup_tests(void) 599 { 600 ADD_TEST(test_sstream_simple); 601 ADD_ALL_TESTS(test_sstream_bulk, 100); 602 ADD_ALL_TESTS(test_rstream_simple, 4); 603 ADD_ALL_TESTS(test_rstream_random, 100); 604 return 1; 605 } 606