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