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