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