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