lsquic_packet_out.c revision a5fa05f9
1/* Copyright (c) 2017 - 2020 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 46static struct stream_rec * 47srec_one_posi_next (struct packet_out_srec_iter *posi) 48{ 49 return NULL; 50} 51 52 53static struct 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 * 99lsquic_posi_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 * 108lsquic_posi_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 { 245 if (lconn->cn_version == LSQVER_050) 246 { 247 if (lconn->cn_flags & (LSCONN_SERVER|LSCONN_HANDSHAKE_DONE)) 248 packet_out->po_header_type = HETY_0RTT; 249 else 250 packet_out->po_header_type = HETY_INITIAL; 251 } 252 else 253 packet_out->po_header_type = HETY_HANDSHAKE; 254 } 255 packet_out->po_path = path; 256 257 return packet_out; 258} 259 260 261void 262lsquic_packet_out_destroy (lsquic_packet_out_t *packet_out, 263 struct lsquic_engine_public *enpub, void *peer_ctx) 264{ 265 if (packet_out->po_flags & PO_SREC_ARR) 266 { 267 struct stream_rec_arr *srec_arr, *next; 268 for (srec_arr = TAILQ_FIRST(&packet_out->po_srecs.arr); 269 srec_arr; srec_arr = next) 270 { 271 next = TAILQ_NEXT(srec_arr, next_stream_rec_arr); 272 lsquic_malo_put(srec_arr); 273 } 274 } 275 if (packet_out->po_flags & PO_ENCRYPTED) 276 enpub->enp_pmi->pmi_release(enpub->enp_pmi_ctx, peer_ctx, 277 packet_out->po_enc_data, lsquic_packet_out_ipv6(packet_out)); 278 if (packet_out->po_nonce) 279 free(packet_out->po_nonce); 280 if (packet_out->po_bwp_state) 281 lsquic_malo_put(packet_out->po_bwp_state); 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 lsquic_stream_id_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 = lsquic_posi_first(&posi, packet_out); srec; 300 srec = lsquic_posi_next(&posi)) 301 { 302 if (srec->sr_frame_type == QUIC_FRAME_STREAM) 303 { 304 ++n_stream_frames; 305 306 /* Offsets of all STREAM frames should be adjusted */ 307 srec->sr_off -= adj; 308 309 if (stream_id) 310 { 311 victim = srec->sr_stream->id == stream_id; 312 if (victim) 313 { 314 assert(lsquic_stream_is_reset(srec->sr_stream)); 315 } 316 } 317 else 318 victim = lsquic_stream_is_reset(srec->sr_stream); 319 320 if (victim) 321 { 322 ++n_elided; 323 324 /* Move the data and adjust sizes */ 325 adj += srec->sr_len; 326 memmove(packet_out->po_data + srec->sr_off, 327 packet_out->po_data + srec->sr_off + srec->sr_len, 328 packet_out->po_data_sz - srec->sr_off - srec->sr_len); 329 packet_out->po_data_sz -= srec->sr_len; 330 331 lsquic_stream_acked(srec->sr_stream, srec->sr_frame_type); 332 srec->sr_frame_type = 0; 333 } 334 } 335 } 336 337 assert(n_stream_frames); 338 if (n_elided == n_stream_frames) 339 { 340 packet_out->po_frame_types &= ~(1 << QUIC_FRAME_STREAM); 341 packet_out->po_flags &= ~PO_STREAM_END; 342 } 343 344 return adj; 345} 346 347 348void 349lsquic_packet_out_chop_regen (lsquic_packet_out_t *packet_out) 350{ 351 struct packet_out_srec_iter posi; 352 struct stream_rec *srec; 353 unsigned delta; 354 355 delta = packet_out->po_regen_sz; 356 packet_out->po_data_sz -= delta; 357 memmove(packet_out->po_data, packet_out->po_data + delta, 358 packet_out->po_data_sz); 359 packet_out->po_regen_sz = 0; 360 361 for (srec = lsquic_posi_first(&posi, packet_out); srec; 362 srec = lsquic_posi_next(&posi)) 363 if (srec->sr_frame_type == QUIC_FRAME_STREAM) 364 srec->sr_off -= delta; 365} 366 367 368void 369lsquic_packet_out_ack_streams (lsquic_packet_out_t *packet_out) 370{ 371 struct packet_out_srec_iter posi; 372 struct stream_rec *srec; 373 for (srec = lsquic_posi_first(&posi, packet_out); srec; 374 srec = lsquic_posi_next(&posi)) 375 lsquic_stream_acked(srec->sr_stream, srec->sr_frame_type); 376} 377 378 379static int 380split_off_last_frames (struct lsquic_mm *mm, lsquic_packet_out_t *packet_out, 381 lsquic_packet_out_t *new_packet_out, struct stream_rec **srecs, 382 unsigned n_srecs, enum quic_frame_type frame_type) 383{ 384 unsigned n; 385 386 for (n = 0; n < n_srecs; ++n) 387 { 388 struct stream_rec *const srec = srecs[n]; 389 memcpy(new_packet_out->po_data + new_packet_out->po_data_sz, 390 packet_out->po_data + srec->sr_off, srec->sr_len); 391 if (0 != lsquic_packet_out_add_stream(new_packet_out, mm, 392 srec->sr_stream, frame_type, 393 new_packet_out->po_data_sz, srec->sr_len)) 394 return -1; 395 srec->sr_frame_type = 0; 396 assert(srec->sr_stream->n_unacked > 1); 397 --srec->sr_stream->n_unacked; 398 new_packet_out->po_data_sz += srec->sr_len; 399 } 400 401 packet_out->po_data_sz = srecs[0]->sr_off; 402 403 return 0; 404} 405 406 407static int 408move_largest_frame (struct lsquic_mm *mm, lsquic_packet_out_t *packet_out, 409 lsquic_packet_out_t *new_packet_out, struct stream_rec **srecs, 410 unsigned n_srecs, unsigned max_idx, enum quic_frame_type frame_type) 411{ 412 unsigned n; 413 struct stream_rec *const max_srec = srecs[max_idx]; 414 415 memcpy(new_packet_out->po_data + new_packet_out->po_data_sz, 416 packet_out->po_data + max_srec->sr_off, max_srec->sr_len); 417 memmove(packet_out->po_data + max_srec->sr_off, 418 packet_out->po_data + max_srec->sr_off + max_srec->sr_len, 419 packet_out->po_data_sz - max_srec->sr_off - max_srec->sr_len); 420 if (0 != lsquic_packet_out_add_stream(new_packet_out, mm, 421 max_srec->sr_stream, frame_type, 422 new_packet_out->po_data_sz, max_srec->sr_len)) 423 return -1; 424 425 max_srec->sr_frame_type = 0; 426 assert(max_srec->sr_stream->n_unacked > 1); 427 --max_srec->sr_stream->n_unacked; 428 new_packet_out->po_data_sz += max_srec->sr_len; 429 packet_out->po_data_sz -= max_srec->sr_len; 430 431 for (n = max_idx + 1; n < n_srecs; ++n) 432 srecs[n]->sr_off -= max_srec->sr_len; 433 434 return 0; 435} 436 437 438struct split_reader_ctx 439{ 440 unsigned off; 441 unsigned len; 442 signed char fin; 443 unsigned char buf[GQUIC_MAX_PAYLOAD_SZ / 2 + 1]; 444}; 445 446 447static int 448split_reader_fin (void *ctx) 449{ 450 struct split_reader_ctx *const reader_ctx = ctx; 451 return reader_ctx->off == reader_ctx->len && reader_ctx->fin; 452} 453 454 455static size_t 456split_reader_size (void *ctx) 457{ 458 struct split_reader_ctx *const reader_ctx = ctx; 459 return reader_ctx->len - reader_ctx->off; 460} 461 462 463static size_t 464split_stream_reader_read (void *ctx, void *buf, size_t len, int *fin) 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 *fin = split_reader_fin(reader_ctx); 472 return len; 473} 474 475 476static size_t 477split_crypto_reader_read (void *ctx, void *buf, size_t len) 478{ 479 struct split_reader_ctx *const reader_ctx = ctx; 480 if (len > reader_ctx->len - reader_ctx->off) 481 len = reader_ctx->len - reader_ctx->off; 482 memcpy(buf, reader_ctx->buf, len); 483 reader_ctx->off += len; 484 return len; 485} 486 487 488static int 489split_largest_frame (struct lsquic_mm *mm, lsquic_packet_out_t *packet_out, 490 lsquic_packet_out_t *new_packet_out, const struct parse_funcs *pf, 491 struct stream_rec **srecs, unsigned n_srecs, unsigned max_idx, 492 enum quic_frame_type frame_type) 493{ 494 struct stream_rec *const max_srec = srecs[max_idx]; 495 struct stream_frame frame; 496 int len; 497 unsigned n; 498 struct split_reader_ctx reader_ctx; 499 500 if (frame_type == QUIC_FRAME_STREAM) 501 len = pf->pf_parse_stream_frame(packet_out->po_data + max_srec->sr_off, 502 max_srec->sr_len, &frame); 503 else 504 len = pf->pf_parse_crypto_frame(packet_out->po_data + max_srec->sr_off, 505 max_srec->sr_len, &frame); 506 if (len < 0) 507 { 508 LSQ_ERROR("could not parse own frame"); 509 return -1; 510 } 511 512 assert(frame.data_frame.df_size / 2 <= sizeof(reader_ctx.buf)); 513 if (frame.data_frame.df_size / 2 > sizeof(reader_ctx.buf)) 514 return -1; 515 516 memcpy(reader_ctx.buf, 517 frame.data_frame.df_data + frame.data_frame.df_size / 2, 518 frame.data_frame.df_size - frame.data_frame.df_size / 2); 519 reader_ctx.off = 0; 520 reader_ctx.len = frame.data_frame.df_size - frame.data_frame.df_size / 2; 521 reader_ctx.fin = frame.data_frame.df_fin; 522 523 if (frame_type == QUIC_FRAME_STREAM) 524 len = pf->pf_gen_stream_frame( 525 new_packet_out->po_data + new_packet_out->po_data_sz, 526 lsquic_packet_out_avail(new_packet_out), frame.stream_id, 527 frame.data_frame.df_offset + frame.data_frame.df_size / 2, 528 split_reader_fin(&reader_ctx), split_reader_size(&reader_ctx), 529 split_stream_reader_read, &reader_ctx); 530 else 531 len = pf->pf_gen_crypto_frame( 532 new_packet_out->po_data + new_packet_out->po_data_sz, 533 lsquic_packet_out_avail(new_packet_out), 534 frame.data_frame.df_offset + frame.data_frame.df_size / 2, 535 split_reader_size(&reader_ctx), 536 split_crypto_reader_read, &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, max_srec->sr_frame_type, 544 new_packet_out->po_data_sz, len)) 545 return -1; 546 new_packet_out->po_data_sz += len; 547 if (0 == lsquic_packet_out_avail(new_packet_out)) 548 { 549 assert(0); /* We really should not fill here, but JIC */ 550 new_packet_out->po_flags |= PO_STREAM_END; 551 } 552 553 memcpy(reader_ctx.buf, frame.data_frame.df_data, 554 frame.data_frame.df_size / 2); 555 reader_ctx.off = 0; 556 reader_ctx.len = frame.data_frame.df_size / 2; 557 reader_ctx.fin = 0; 558 if (frame_type == QUIC_FRAME_STREAM) 559 len = pf->pf_gen_stream_frame( 560 packet_out->po_data + max_srec->sr_off, max_srec->sr_len, 561 frame.stream_id, frame.data_frame.df_offset, 562 split_reader_fin(&reader_ctx), split_reader_size(&reader_ctx), 563 split_stream_reader_read, &reader_ctx); 564 else 565 len = pf->pf_gen_crypto_frame( 566 packet_out->po_data + max_srec->sr_off, max_srec->sr_len, 567 frame.data_frame.df_offset, 568 split_reader_size(&reader_ctx), 569 split_crypto_reader_read, &reader_ctx); 570 if (len < 0) 571 { 572 LSQ_ERROR("could not generate new frame 2"); 573 return -1; 574 } 575 576 const unsigned short adj = max_srec->sr_len - (unsigned short) len; 577 max_srec->sr_len = len; 578 for (n = max_idx + 1; n < n_srecs; ++n) 579 srecs[n]->sr_off -= adj; 580 packet_out->po_data_sz -= adj; 581 582 return 0; 583} 584 585 586#ifndef NDEBUG 587static void 588verify_srecs (lsquic_packet_out_t *packet_out, enum quic_frame_type frame_type) 589{ 590 struct packet_out_srec_iter posi; 591 const struct stream_rec *srec; 592 unsigned off; 593 594 srec = lsquic_posi_first(&posi, packet_out); 595 assert(srec); 596 597 off = 0; 598 for ( ; srec; srec = lsquic_posi_next(&posi)) 599 { 600 assert(srec->sr_off == off); 601 assert(srec->sr_frame_type == frame_type); 602 off += srec->sr_len; 603 } 604 605 assert(packet_out->po_data_sz == off); 606} 607#endif 608 609 610int 611lsquic_packet_out_split_in_two (struct lsquic_mm *mm, 612 lsquic_packet_out_t *packet_out, lsquic_packet_out_t *new_packet_out, 613 const struct parse_funcs *pf, unsigned excess_bytes) 614{ 615 struct packet_out_srec_iter posi; 616 struct stream_rec *local_arr[4]; 617 struct stream_rec **new_srecs, **srecs = local_arr; 618 struct stream_rec *srec; 619 unsigned n_srecs_alloced = sizeof(local_arr) / sizeof(local_arr[0]); 620 unsigned n_srecs, max_idx, n, nbytes; 621 enum quic_frame_type frame_type; 622#ifndef NDEBUG 623 unsigned short frame_sum = 0; 624#endif 625 int rv; 626 627 /* We only split buffered packets or initial packets with CRYPTO frames. 628 * Either contain just one frame type: STREAM or CRYPTO. 629 */ 630 assert(packet_out->po_frame_types == (1 << QUIC_FRAME_STREAM) 631 || packet_out->po_frame_types == (1 << QUIC_FRAME_CRYPTO)); 632 if (packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM)) 633 frame_type = QUIC_FRAME_STREAM; 634 else 635 frame_type = QUIC_FRAME_CRYPTO; 636 637 n_srecs = 0; 638#ifdef WIN32 639 max_idx = 0; 640#endif 641 for (srec = lsquic_posi_first(&posi, packet_out); srec; 642 srec = lsquic_posi_next(&posi)) 643 { 644 assert(srec->sr_frame_type == QUIC_FRAME_STREAM 645 || srec->sr_frame_type == QUIC_FRAME_CRYPTO); 646 if (n_srecs >= n_srecs_alloced) 647 { 648 n_srecs_alloced *= 2; 649 if (srecs == local_arr) 650 { 651 srecs = malloc(sizeof(srecs[0]) * n_srecs_alloced); 652 if (!srecs) 653 goto err; 654 memcpy(srecs, local_arr, sizeof(local_arr)); 655 } 656 else 657 { 658 new_srecs = realloc(srecs, sizeof(srecs[0]) * n_srecs_alloced); 659 if (!new_srecs) 660 goto err; 661 srecs = new_srecs; 662 } 663 } 664 665#ifndef NDEBUG 666 frame_sum += srec->sr_len; 667#endif 668 if (n_srecs == 0 || srecs[max_idx]->sr_len < srec->sr_len) 669 max_idx = n_srecs; 670 671 srecs[n_srecs++] = srec; 672 } 673 674 assert(frame_sum == packet_out->po_data_sz); 675 676 if (n_srecs == 1) 677 goto common_case; 678 679 if (n_srecs < 1) 680 goto err; 681 682 /* Case 1: see if we can remove one or more trailing frames to make 683 * packet smaller. 684 */ 685 nbytes = 0; 686 for (n = n_srecs - 1; n > max_idx && nbytes < excess_bytes; --n) 687 nbytes += srecs[n]->sr_len; 688 if (nbytes >= excess_bytes) 689 { 690 rv = split_off_last_frames(mm, packet_out, new_packet_out, 691 srecs + n + 1, n_srecs - n - 1, frame_type); 692 goto end; 693 } 694 695 /* Case 2: see if we can move the largest frame to new packet. */ 696 nbytes = 0; 697 for (n = 0; n < n_srecs; ++n) 698 if (n != max_idx) 699 nbytes += srecs[n]->sr_len; 700 if (nbytes >= excess_bytes) 701 { 702 rv = move_largest_frame(mm, packet_out, new_packet_out, srecs, 703 n_srecs, max_idx, frame_type); 704 goto end; 705 } 706 707 common_case: 708 /* Case 3: we have to split the largest frame (which could be the 709 * the only frame) in two. 710 */ 711 rv = split_largest_frame(mm, packet_out, new_packet_out, pf, srecs, 712 n_srecs, max_idx, frame_type); 713 714 end: 715 if (srecs != local_arr) 716 free(srecs); 717 if (0 == rv) 718 { 719 new_packet_out->po_frame_types |= 1 << frame_type; 720#ifndef NDEBUG 721 verify_srecs(packet_out, frame_type); 722 verify_srecs(new_packet_out, frame_type); 723#endif 724 } 725 return rv; 726 727 err: 728 rv = -1; 729 goto end; 730} 731 732 733void 734lsquic_packet_out_zero_pad (lsquic_packet_out_t *packet_out) 735{ 736 if (packet_out->po_n_alloc > packet_out->po_data_sz) 737 { 738 memset(packet_out->po_data + packet_out->po_data_sz, 0, 739 packet_out->po_n_alloc - packet_out->po_data_sz); 740 packet_out->po_data_sz = packet_out->po_n_alloc; 741 packet_out->po_frame_types |= 1 << QUIC_FRAME_PADDING; 742 } 743} 744 745 746size_t 747lsquic_packet_out_mem_used (const struct lsquic_packet_out *packet_out) 748{ 749 const struct stream_rec_arr *srec_arr; 750 size_t size; 751 752 size = 0; /* The struct is allocated using malo */ 753 if (packet_out->po_enc_data) 754 size += packet_out->po_enc_data_sz; 755 if (packet_out->po_data) 756 size += packet_out->po_n_alloc; 757 if (packet_out->po_nonce) 758 size += 32; 759 760 if (packet_out->po_flags & PO_SREC_ARR) 761 TAILQ_FOREACH(srec_arr, &packet_out->po_srecs.arr, next_stream_rec_arr) 762 size += sizeof(*srec_arr); 763 764 return size; 765} 766 767 768int 769lsquic_packet_out_turn_on_fin (struct lsquic_packet_out *packet_out, 770 const struct parse_funcs *pf, 771 const struct lsquic_stream *stream) 772{ 773 struct packet_out_srec_iter posi; 774 const struct stream_rec *srec; 775 struct stream_frame stream_frame; 776 uint64_t last_offset; 777 int len; 778 779 for (srec = lsquic_posi_first(&posi, packet_out); srec; 780 srec = lsquic_posi_next(&posi)) 781 if (srec->sr_frame_type == QUIC_FRAME_STREAM 782 && srec->sr_stream == stream) 783 { 784 len = pf->pf_parse_stream_frame(packet_out->po_data + srec->sr_off, 785 srec->sr_len, &stream_frame); 786 assert(len >= 0); 787 if (len < 0) 788 return -1; 789 last_offset = stream_frame.data_frame.df_offset 790 + stream_frame.data_frame.df_size; 791 if (last_offset == stream->tosend_off) 792 { 793 pf->pf_turn_on_fin(packet_out->po_data + srec->sr_off); 794 EV_LOG_UPDATED_STREAM_FRAME( 795 lsquic_conn_log_cid(lsquic_stream_conn(stream)), 796 pf, packet_out->po_data + srec->sr_off, srec->sr_len); 797 return 0; 798 } 799 } 800 801 return -1; 802} 803