lsquic_packet_out.c revision c7d81ce1
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_packet_out.c 4 */ 5 6#include <assert.h> 7#include <errno.h> 8#include <stdlib.h> 9#include <string.h> 10#include <sys/queue.h> 11 12#include "lsquic.h" 13#include "lsquic_int_types.h" 14#include "lsquic_malo.h" 15#include "lsquic_mm.h" 16#include "lsquic_engine_public.h" 17#include "lsquic_packet_common.h" 18#include "lsquic_packet_in.h" 19#include "lsquic_packet_out.h" 20#include "lsquic_parse.h" 21#include "lsquic_sfcw.h" 22#include "lsquic_stream.h" 23#include "lsquic_logger.h" 24#include "lsquic_ev_log.h" 25#include "lsquic_conn.h" 26 27typedef char _stream_rec_arr_is_at_most_64bytes[ 28 (sizeof(struct stream_rec_arr) <= 64)? 1: - 1]; 29 30static struct stream_rec * 31srec_one_posi_first (struct packet_out_srec_iter *posi, 32 struct lsquic_packet_out *packet_out) 33{ 34 if (packet_out->po_srecs.one.sr_frame_type) 35 return &packet_out->po_srecs.one; 36 else 37 return NULL; 38} 39 40 41struct stream_rec * 42srec_one_posi_next (struct packet_out_srec_iter *posi) 43{ 44 return NULL; 45} 46 47 48struct stream_rec * 49srec_arr_posi_next (struct packet_out_srec_iter *posi) 50{ 51 while (posi->cur_srec_arr) 52 { 53 for (; posi->srec_idx < sizeof(posi->cur_srec_arr->srecs) / sizeof(posi->cur_srec_arr->srecs[0]); 54 ++posi->srec_idx) 55 { 56 if (posi->cur_srec_arr->srecs[ posi->srec_idx ].sr_frame_type) 57 return &posi->cur_srec_arr->srecs[ posi->srec_idx++ ]; 58 } 59 posi->cur_srec_arr = TAILQ_NEXT(posi->cur_srec_arr, next_stream_rec_arr); 60 posi->srec_idx = 0; 61 } 62 return NULL; 63} 64 65 66static struct stream_rec * 67srec_arr_posi_first (struct packet_out_srec_iter *posi, 68 struct lsquic_packet_out *packet_out) 69{ 70 posi->packet_out = packet_out; 71 posi->cur_srec_arr = TAILQ_FIRST(&packet_out->po_srecs.arr); 72 posi->srec_idx = 0; 73 return srec_arr_posi_next(posi); 74} 75 76 77static struct stream_rec * (* const posi_firsts[]) 78 (struct packet_out_srec_iter *, struct lsquic_packet_out *) = 79{ 80 srec_one_posi_first, 81 srec_arr_posi_first, 82}; 83 84 85static struct stream_rec * (* const posi_nexts[]) 86 (struct packet_out_srec_iter *posi) = 87{ 88 srec_one_posi_next, 89 srec_arr_posi_next, 90}; 91 92 93struct stream_rec * 94posi_first (struct packet_out_srec_iter *posi, 95 lsquic_packet_out_t *packet_out) 96{ 97 posi->impl_idx = !!(packet_out->po_flags & PO_SREC_ARR); 98 return posi_firsts[posi->impl_idx](posi, packet_out); 99} 100 101 102struct stream_rec * 103posi_next (struct packet_out_srec_iter *posi) 104{ 105 return posi_nexts[posi->impl_idx](posi); 106} 107 108 109/* 110 * Assumption: frames are added to the packet_out in order of their placement 111 * in packet_out->po_data. There is no assertion to guard for for this. 112 */ 113int 114lsquic_packet_out_add_stream (lsquic_packet_out_t *packet_out, 115 struct lsquic_mm *mm, 116 struct lsquic_stream *new_stream, 117 enum quic_frame_type frame_type, 118 unsigned short off, unsigned short len) 119{ 120 struct stream_rec_arr *srec_arr; 121 int last_taken; 122 unsigned i; 123 124 assert(!(new_stream->stream_flags & STREAM_FINISHED)); 125 126 if (!(packet_out->po_flags & PO_SREC_ARR)) 127 { 128 if (!srec_taken(&packet_out->po_srecs.one)) 129 { 130 packet_out->po_srecs.one.sr_frame_type = frame_type; 131 packet_out->po_srecs.one.sr_stream = new_stream; 132 packet_out->po_srecs.one.sr_off = off; 133 packet_out->po_srecs.one.sr_len = len; 134 ++new_stream->n_unacked; 135 return 0; /* Insert in first slot */ 136 } 137 srec_arr = lsquic_malo_get(mm->malo.stream_rec_arr); 138 if (!srec_arr) 139 return -1; 140 memset(srec_arr, 0, sizeof(*srec_arr)); 141 srec_arr->srecs[0] = packet_out->po_srecs.one; 142 TAILQ_INIT(&packet_out->po_srecs.arr); 143 TAILQ_INSERT_TAIL(&packet_out->po_srecs.arr, srec_arr, 144 next_stream_rec_arr); 145 packet_out->po_flags |= PO_SREC_ARR; 146 i = 1; 147 goto set_elem; 148 } 149 150 /* New records go at the very end: */ 151 srec_arr = TAILQ_LAST(&packet_out->po_srecs.arr, stream_rec_arr_tailq); 152 last_taken = -1; 153 for (i = 0; i < sizeof(srec_arr->srecs) / sizeof(srec_arr->srecs[0]); ++i) 154 if (srec_taken(&srec_arr->srecs[i])) 155 last_taken = i; 156 157 i = last_taken + 1; 158 if (i < sizeof(srec_arr->srecs) / sizeof(srec_arr->srecs[0])) 159 { 160 set_elem: 161 srec_arr->srecs[i].sr_frame_type = frame_type; 162 srec_arr->srecs[i].sr_stream = new_stream; 163 srec_arr->srecs[i].sr_off = off; 164 srec_arr->srecs[i].sr_len = len; 165 ++new_stream->n_unacked; 166 return 0; /* Insert in existing srec */ 167 } 168 169 srec_arr = lsquic_malo_get(mm->malo.stream_rec_arr); 170 if (!srec_arr) 171 return -1; 172 173 memset(srec_arr, 0, sizeof(*srec_arr)); 174 srec_arr->srecs[0].sr_frame_type = frame_type; 175 srec_arr->srecs[0].sr_stream = new_stream; 176 srec_arr->srecs[0].sr_off = off; 177 srec_arr->srecs[0].sr_len = len; 178 TAILQ_INSERT_TAIL(&packet_out->po_srecs.arr, srec_arr, next_stream_rec_arr); 179 ++new_stream->n_unacked; 180 return 0; /* Insert in new srec */ 181} 182 183 184lsquic_packet_out_t * 185lsquic_packet_out_new (struct lsquic_mm *mm, struct malo *malo, int use_cid, 186 const struct lsquic_conn *lconn, enum packno_bits bits, 187 const lsquic_ver_tag_t *ver_tag, const unsigned char *nonce) 188{ 189 lsquic_packet_out_t *packet_out; 190 enum packet_out_flags flags; 191 unsigned short header_size, max_size; 192 193 flags = bits << POBIT_SHIFT; 194 if (ver_tag) 195 flags |= PO_VERSION; 196 if (nonce) 197 flags |= PO_NONCE; 198 if (use_cid) 199 flags |= PO_CONN_ID; 200 if ((1 << lconn->cn_version) & LSQUIC_GQUIC_HEADER_VERSIONS) 201 flags |= PO_GQUIC; 202 if ( 203 0 == (lconn->cn_flags & LSCONN_HANDSHAKE_DONE) 204 ) 205 { 206 flags |= PO_LONGHEAD; 207 if (lconn->cn_version == LSQVER_044) 208 { 209 flags &= ~(3 << POBIT_SHIFT); 210 flags |= GQUIC_PACKNO_LEN_4 << POBIT_SHIFT; 211 } 212 } 213 214 header_size = lsquic_po_header_length(lconn, flags); 215 max_size = lconn->cn_pack_size; 216 if (header_size + QUIC_PACKET_HASH_SZ >= max_size) 217 { 218 errno = EINVAL; 219 return NULL; 220 } 221 222 packet_out = lsquic_mm_get_packet_out(mm, malo, max_size - header_size 223 - QUIC_PACKET_HASH_SZ); 224 if (!packet_out) 225 return NULL; 226 227 packet_out->po_flags = flags; 228 if (ver_tag) 229 packet_out->po_ver_tag = *ver_tag; 230 if (nonce) 231 { 232 /* Nonces are allocated for a very small number of packets. This 233 * memory is too expensive to carry in every packet. 234 */ 235 packet_out->po_nonce = malloc(32); 236 if (!packet_out->po_nonce) 237 { 238 lsquic_mm_put_packet_out(mm, packet_out); 239 return NULL; 240 } 241 memcpy(packet_out->po_nonce, nonce, 32); 242 } 243 if (flags & PO_LONGHEAD) 244 packet_out->po_header_type = HETY_HANDSHAKE; 245 246 return packet_out; 247} 248 249 250void 251lsquic_packet_out_destroy (lsquic_packet_out_t *packet_out, 252 struct lsquic_engine_public *enpub, void *peer_ctx) 253{ 254 if (packet_out->po_flags & PO_SREC_ARR) 255 { 256 struct stream_rec_arr *srec_arr, *next; 257 for (srec_arr = TAILQ_FIRST(&packet_out->po_srecs.arr); 258 srec_arr; srec_arr = next) 259 { 260 next = TAILQ_NEXT(srec_arr, next_stream_rec_arr); 261 lsquic_malo_put(srec_arr); 262 } 263 } 264 if (packet_out->po_flags & PO_ENCRYPTED) 265 enpub->enp_pmi->pmi_release(enpub->enp_pmi_ctx, peer_ctx, 266 packet_out->po_enc_data, lsquic_packet_out_ipv6(packet_out)); 267 if (packet_out->po_nonce) 268 free(packet_out->po_nonce); 269 lsquic_mm_put_packet_out(&enpub->enp_mm, packet_out); 270} 271 272 273/* If `stream_id' is zero, stream frames from all reset streams are elided. 274 * Otherwise, elision is limited to the specified stream. 275 */ 276unsigned 277lsquic_packet_out_elide_reset_stream_frames (lsquic_packet_out_t *packet_out, 278 uint32_t stream_id) 279{ 280 struct packet_out_srec_iter posi; 281 struct stream_rec *srec; 282 unsigned short adj = 0; 283 int n_stream_frames = 0, n_elided = 0; 284 int victim; 285 286 for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi)) 287 { 288 if (srec->sr_frame_type == QUIC_FRAME_STREAM) 289 { 290 ++n_stream_frames; 291 292 /* Offsets of all STREAM frames should be adjusted */ 293 srec->sr_off -= adj; 294 295 if (stream_id) 296 { 297 victim = srec->sr_stream->id == stream_id; 298 if (victim) 299 { 300 assert(lsquic_stream_is_reset(srec->sr_stream)); 301 } 302 } 303 else 304 victim = lsquic_stream_is_reset(srec->sr_stream); 305 306 if (victim) 307 { 308 ++n_elided; 309 310 /* Move the data and adjust sizes */ 311 adj += srec->sr_len; 312 memmove(packet_out->po_data + srec->sr_off, 313 packet_out->po_data + srec->sr_off + srec->sr_len, 314 packet_out->po_data_sz - srec->sr_off - srec->sr_len); 315 packet_out->po_data_sz -= srec->sr_len; 316 317 /* See what we can do with the stream */ 318 srec->sr_frame_type = 0; 319 lsquic_stream_acked(srec->sr_stream); 320 } 321 } 322 } 323 324 assert(n_stream_frames); 325 if (n_elided == n_stream_frames) 326 { 327 packet_out->po_frame_types &= ~(1 << QUIC_FRAME_STREAM); 328 packet_out->po_flags &= ~PO_STREAM_END; 329 } 330 331 return adj; 332} 333 334 335void 336lsquic_packet_out_chop_regen (lsquic_packet_out_t *packet_out) 337{ 338 struct packet_out_srec_iter posi; 339 struct stream_rec *srec; 340 unsigned delta; 341 342 delta = packet_out->po_regen_sz; 343 packet_out->po_data_sz -= delta; 344 memmove(packet_out->po_data, packet_out->po_data + delta, 345 packet_out->po_data_sz); 346 packet_out->po_regen_sz = 0; 347 348 for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi)) 349 if (srec->sr_frame_type == QUIC_FRAME_STREAM) 350 srec->sr_off -= delta; 351} 352 353 354void 355lsquic_packet_out_ack_streams (lsquic_packet_out_t *packet_out) 356{ 357 struct packet_out_srec_iter posi; 358 struct stream_rec *srec; 359 for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi)) 360 lsquic_stream_acked(srec->sr_stream); 361} 362 363 364static int 365split_off_last_frames (struct lsquic_mm *mm, lsquic_packet_out_t *packet_out, 366 lsquic_packet_out_t *new_packet_out, struct stream_rec **srecs, 367 unsigned n_srecs) 368{ 369 unsigned n; 370 371 for (n = 0; n < n_srecs; ++n) 372 { 373 struct stream_rec *const srec = srecs[n]; 374 memcpy(new_packet_out->po_data + new_packet_out->po_data_sz, 375 packet_out->po_data + srec->sr_off, srec->sr_len); 376 if (0 != lsquic_packet_out_add_stream(new_packet_out, mm, 377 srec->sr_stream, QUIC_FRAME_STREAM, 378 new_packet_out->po_data_sz, srec->sr_len)) 379 return -1; 380 srec->sr_frame_type = 0; 381 assert(srec->sr_stream->n_unacked > 1); 382 --srec->sr_stream->n_unacked; 383 new_packet_out->po_data_sz += srec->sr_len; 384 } 385 386 packet_out->po_data_sz = srecs[0]->sr_off; 387 388 return 0; 389} 390 391 392static int 393move_largest_frame (struct lsquic_mm *mm, lsquic_packet_out_t *packet_out, 394 lsquic_packet_out_t *new_packet_out, struct stream_rec **srecs, 395 unsigned n_srecs, unsigned max_idx) 396{ 397 unsigned n; 398 struct stream_rec *const max_srec = srecs[max_idx]; 399 400 memcpy(new_packet_out->po_data + new_packet_out->po_data_sz, 401 packet_out->po_data + max_srec->sr_off, max_srec->sr_len); 402 memmove(packet_out->po_data + max_srec->sr_off, 403 packet_out->po_data + max_srec->sr_off + max_srec->sr_len, 404 packet_out->po_data_sz - max_srec->sr_off - max_srec->sr_len); 405 if (0 != lsquic_packet_out_add_stream(new_packet_out, mm, 406 max_srec->sr_stream, QUIC_FRAME_STREAM, 407 new_packet_out->po_data_sz, max_srec->sr_len)) 408 return -1; 409 410 max_srec->sr_frame_type = 0; 411 assert(max_srec->sr_stream->n_unacked > 1); 412 --max_srec->sr_stream->n_unacked; 413 new_packet_out->po_data_sz += max_srec->sr_len; 414 packet_out->po_data_sz -= max_srec->sr_len; 415 416 for (n = max_idx + 1; n < n_srecs; ++n) 417 srecs[n]->sr_off -= max_srec->sr_len; 418 419 return 0; 420} 421 422 423struct split_reader_ctx 424{ 425 unsigned off; 426 unsigned len; 427 signed char fin; 428 unsigned char buf[QUIC_MAX_PAYLOAD_SZ / 2 + 1]; 429}; 430 431 432static int 433split_reader_fin (void *ctx) 434{ 435 struct split_reader_ctx *const reader_ctx = ctx; 436 return reader_ctx->off == reader_ctx->len && reader_ctx->fin; 437} 438 439 440static size_t 441split_reader_size (void *ctx) 442{ 443 struct split_reader_ctx *const reader_ctx = ctx; 444 return reader_ctx->len - reader_ctx->off; 445} 446 447 448static size_t 449split_reader_read (void *ctx, void *buf, size_t len, int *fin) 450{ 451 struct split_reader_ctx *const reader_ctx = ctx; 452 if (len > reader_ctx->len - reader_ctx->off) 453 len = reader_ctx->len - reader_ctx->off; 454 memcpy(buf, reader_ctx->buf, len); 455 reader_ctx->off += len; 456 *fin = split_reader_fin(reader_ctx); 457 return len; 458} 459 460 461static int 462split_largest_frame (struct lsquic_mm *mm, lsquic_packet_out_t *packet_out, 463 lsquic_packet_out_t *new_packet_out, const struct parse_funcs *pf, 464 struct stream_rec **srecs, unsigned n_srecs, unsigned max_idx) 465{ 466 struct stream_rec *const max_srec = srecs[max_idx]; 467 struct stream_frame frame; 468 int len; 469 unsigned n; 470 struct split_reader_ctx reader_ctx; 471 472 len = pf->pf_parse_stream_frame(packet_out->po_data + max_srec->sr_off, 473 max_srec->sr_len, &frame); 474 if (len < 0) 475 { 476 LSQ_ERROR("could not parse own frame"); 477 return -1; 478 } 479 480 assert(frame.data_frame.df_size / 2 <= sizeof(reader_ctx.buf)); 481 if (frame.data_frame.df_size / 2 > sizeof(reader_ctx.buf)) 482 return -1; 483 484 memcpy(reader_ctx.buf, 485 frame.data_frame.df_data + frame.data_frame.df_size / 2, 486 frame.data_frame.df_size - frame.data_frame.df_size / 2); 487 reader_ctx.off = 0; 488 reader_ctx.len = frame.data_frame.df_size - frame.data_frame.df_size / 2; 489 reader_ctx.fin = frame.data_frame.df_fin; 490 491 len = pf->pf_gen_stream_frame( 492 new_packet_out->po_data + new_packet_out->po_data_sz, 493 lsquic_packet_out_avail(new_packet_out), frame.stream_id, 494 frame.data_frame.df_offset + frame.data_frame.df_size / 2, 495 split_reader_fin(&reader_ctx), split_reader_size(&reader_ctx), 496 split_reader_read, &reader_ctx); 497 if (len < 0) 498 { 499 LSQ_ERROR("could not generate new frame 1"); 500 return -1; 501 } 502 if (0 != lsquic_packet_out_add_stream(new_packet_out, mm, 503 max_srec->sr_stream, QUIC_FRAME_STREAM, 504 new_packet_out->po_data_sz, len)) 505 return -1; 506 new_packet_out->po_data_sz += len; 507 if (0 == lsquic_packet_out_avail(new_packet_out)) 508 { 509 assert(0); /* We really should not fill here, but JIC */ 510 new_packet_out->po_flags |= PO_STREAM_END; 511 } 512 513 memcpy(reader_ctx.buf, frame.data_frame.df_data, 514 frame.data_frame.df_size / 2); 515 reader_ctx.off = 0; 516 reader_ctx.len = frame.data_frame.df_size / 2; 517 reader_ctx.fin = 0; 518 len = pf->pf_gen_stream_frame( 519 packet_out->po_data + max_srec->sr_off, max_srec->sr_len, 520 frame.stream_id, frame.data_frame.df_offset, 521 split_reader_fin(&reader_ctx), split_reader_size(&reader_ctx), 522 split_reader_read, &reader_ctx); 523 if (len < 0) 524 { 525 LSQ_ERROR("could not generate new frame 2"); 526 return -1; 527 } 528 529 const unsigned short adj = max_srec->sr_len - (unsigned short) len; 530 max_srec->sr_len = len; 531 for (n = max_idx + 1; n < n_srecs; ++n) 532 srecs[n]->sr_off -= adj; 533 packet_out->po_data_sz -= adj; 534 535 return 0; 536} 537 538 539#ifndef NDEBUG 540static void 541verify_srecs (lsquic_packet_out_t *packet_out) 542{ 543 struct packet_out_srec_iter posi; 544 const struct stream_rec *srec; 545 unsigned off; 546 547 srec = posi_first(&posi, packet_out); 548 assert(srec); 549 550 off = 0; 551 for ( ; srec; srec = posi_next(&posi)) 552 { 553 assert(srec->sr_off == off); 554 assert(srec->sr_frame_type == QUIC_FRAME_STREAM); 555 off += srec->sr_len; 556 } 557 558 assert(packet_out->po_data_sz == off); 559} 560 561 562#endif 563 564 565int 566lsquic_packet_out_split_in_two (struct lsquic_mm *mm, 567 lsquic_packet_out_t *packet_out, lsquic_packet_out_t *new_packet_out, 568 const struct parse_funcs *pf, unsigned excess_bytes) 569{ 570 struct packet_out_srec_iter posi; 571 struct stream_rec *local_arr[4]; 572 struct stream_rec **new_srecs, **srecs = local_arr; 573 struct stream_rec *srec; 574 unsigned n_srecs_alloced = sizeof(local_arr) / sizeof(local_arr[0]); 575 unsigned n_srecs, max_idx, n, nbytes; 576#ifndef NDEBUG 577 unsigned short frame_sum = 0; 578#endif 579 int rv; 580 581 /* We only split buffered packets; buffered packets contain only STREAM 582 * frames: 583 */ 584 assert(packet_out->po_frame_types == (1 << QUIC_FRAME_STREAM)); 585 586 n_srecs = 0; 587#ifdef WIN32 588 max_idx = 0; 589#endif 590 for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi)) 591 { 592 /* We only expect references to STREAM frames (buffered packets): */ 593 assert(srec->sr_frame_type == QUIC_FRAME_STREAM); 594 if (n_srecs >= n_srecs_alloced) 595 { 596 n_srecs_alloced *= 2; 597 if (srecs == local_arr) 598 { 599 srecs = malloc(sizeof(srecs[0]) * n_srecs_alloced); 600 if (!srecs) 601 goto err; 602 memcpy(srecs, local_arr, sizeof(local_arr)); 603 } 604 else 605 { 606 new_srecs = realloc(srecs, sizeof(srecs[0]) * n_srecs_alloced); 607 if (!new_srecs) 608 goto err; 609 srecs = new_srecs; 610 } 611 } 612 613#ifndef NDEBUG 614 frame_sum += srec->sr_len; 615#endif 616 if (n_srecs == 0 || srecs[max_idx]->sr_len < srec->sr_len) 617 max_idx = n_srecs; 618 619 srecs[n_srecs++] = srec; 620 } 621 622 assert(frame_sum == packet_out->po_data_sz); 623 624 if (n_srecs == 1) 625 goto common_case; 626 627 if (n_srecs < 1) 628 goto err; 629 630 /* Case 1: see if we can remove one or more trailing frames to make 631 * packet smaller. 632 */ 633 nbytes = 0; 634 for (n = n_srecs - 1; n > max_idx && nbytes < excess_bytes; --n) 635 nbytes += srecs[n]->sr_len; 636 if (nbytes >= excess_bytes) 637 { 638 rv = split_off_last_frames(mm, packet_out, new_packet_out, 639 srecs + n + 1, n_srecs - n - 1); 640 goto end; 641 } 642 643 /* Case 2: see if we can move the largest frame to new packet. */ 644 nbytes = 0; 645 for (n = 0; n < n_srecs; ++n) 646 if (n != max_idx) 647 nbytes += srecs[n]->sr_len; 648 if (nbytes >= excess_bytes) 649 { 650 rv = move_largest_frame(mm, packet_out, new_packet_out, srecs, 651 n_srecs, max_idx); 652 goto end; 653 } 654 655 common_case: 656 /* Case 3: we have to split the largest frame (which could be the 657 * the only frame) in two. 658 */ 659 rv = split_largest_frame(mm, packet_out, new_packet_out, pf, srecs, 660 n_srecs, max_idx); 661 662 end: 663 if (srecs != local_arr) 664 free(srecs); 665 if (0 == rv) 666 { 667 new_packet_out->po_frame_types |= 1 << QUIC_FRAME_STREAM; 668#ifndef NDEBUG 669 verify_srecs(packet_out); 670 verify_srecs(new_packet_out); 671#endif 672 } 673 return rv; 674 675 err: 676 rv = -1; 677 goto end; 678} 679 680 681void 682lsquic_packet_out_zero_pad (lsquic_packet_out_t *packet_out) 683{ 684 if (packet_out->po_n_alloc > packet_out->po_data_sz) 685 { 686 memset(packet_out->po_data + packet_out->po_data_sz, 0, 687 packet_out->po_n_alloc - packet_out->po_data_sz); 688 packet_out->po_data_sz = packet_out->po_n_alloc; 689 packet_out->po_frame_types |= 1 << QUIC_FRAME_PADDING; 690 } 691} 692 693 694size_t 695lsquic_packet_out_mem_used (const struct lsquic_packet_out *packet_out) 696{ 697 const struct stream_rec_arr *srec_arr; 698 size_t size; 699 700 size = 0; /* The struct is allocated using malo */ 701 if (packet_out->po_enc_data) 702 size += packet_out->po_enc_data_sz; 703 if (packet_out->po_data) 704 size += packet_out->po_n_alloc; 705 if (packet_out->po_nonce) 706 size += 32; 707 708 if (packet_out->po_flags & PO_SREC_ARR) 709 TAILQ_FOREACH(srec_arr, &packet_out->po_srecs.arr, next_stream_rec_arr) 710 size += sizeof(*srec_arr); 711 712 return size; 713} 714 715 716int 717lsquic_packet_out_turn_on_fin (struct lsquic_packet_out *packet_out, 718 const struct parse_funcs *pf, 719 const struct lsquic_stream *stream) 720{ 721 struct packet_out_srec_iter posi; 722 const struct stream_rec *srec; 723 struct stream_frame stream_frame; 724 uint64_t last_offset; 725 int len; 726 727 for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi)) 728 if (srec->sr_frame_type == QUIC_FRAME_STREAM 729 && srec->sr_stream == stream) 730 { 731 len = pf->pf_parse_stream_frame(packet_out->po_data + srec->sr_off, 732 srec->sr_len, &stream_frame); 733 assert(len >= 0); 734 if (len < 0) 735 return -1; 736 last_offset = stream_frame.data_frame.df_offset 737 + stream_frame.data_frame.df_size; 738 if (last_offset == stream->tosend_off) 739 { 740 pf->pf_turn_on_fin(packet_out->po_data + srec->sr_off); 741 EV_LOG_UPDATED_STREAM_FRAME(lsquic_stream_cid(stream), 742 pf, packet_out->po_data + srec->sr_off, srec->sr_len); 743 return 0; 744 } 745 } 746 747 return -1; 748} 749