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