lsquic_stream.h revision fbc6cc04
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 2#ifndef LSQUIC_STREAM_H 3#define LSQUIC_STREAM_H 4 5#define LSQUIC_STREAM_DEFAULT_PRIO 16 /* RFC 7540, Section 5.3.5 */ 6 7 8struct lsquic_stream_if; 9struct lsquic_stream_ctx; 10struct lsquic_conn_public; 11struct stream_frame; 12struct uncompressed_headers; 13enum enc_level; 14enum swtp_status; 15struct frame_gen_ctx; 16struct data_frame; 17enum quic_frame_type; 18struct push_promise; 19union hblock_ctx; 20 21TAILQ_HEAD(lsquic_streams_tailq, lsquic_stream); 22 23 24#ifndef LSQUIC_KEEP_STREAM_HISTORY 25# define LSQUIC_KEEP_STREAM_HISTORY 1 26#endif 27 28 29#if LSQUIC_KEEP_STREAM_HISTORY 30#define SM_HIST_BITS 6 31#define SM_HIST_IDX_MASK ((1 << SM_HIST_BITS) - 1) 32typedef unsigned char sm_hist_idx_t; 33#endif 34 35 36/* 37 * +----------+----------------------------------+ 38 * | Low Bits | Stream Type | 39 * +----------+----------------------------------+ 40 * | 0x0 | Client-Initiated, Bidirectional | 41 * | | | 42 * | 0x1 | Server-Initiated, Bidirectional | 43 * | | | 44 * | 0x2 | Client-Initiated, Unidirectional | 45 * | | | 46 * | 0x3 | Server-Initiated, Unidirectional | 47 * +----------+----------------------------------+ 48 */ 49 50enum stream_id_type 51{ 52 SIT_BIDI_CLIENT, 53 SIT_BIDI_SERVER, 54 SIT_UNI_CLIENT, 55 SIT_UNI_SERVER, 56 N_SITS 57}; 58 59#define SIT_MASK (N_SITS - 1) 60 61#define SIT_SHIFT 2 62#define SD_SHIFT 1 63 64enum stream_dir { SD_BIDI, SD_UNI, N_SDS }; 65 66 67struct stream_hq_frame 68{ 69 STAILQ_ENTRY(stream_hq_frame) 70 shf_next; 71 /* At which point in the stream (sm_payload) to insert the HQ frame. */ 72 uint64_t shf_off; 73 union { 74 /* Points to the frame if SHF_FIXED_SIZE is not set */ 75 unsigned char *frame_ptr; 76 /* If SHF_FIXED_SIZE is set, the size of the frame to follow. 77 * Non-fixed frame size gets calculated using sm_payload when they 78 * are closed. 79 */ 80 size_t frame_size; 81 } shf_u; 82#define shf_frame_ptr shf_u.frame_ptr 83#define shf_frame_size shf_u.frame_size 84 enum hq_frame_type shf_frame_type; 85 enum shf_flags { 86 SHF_TWO_BYTES = 1 << 0, /* Use two byte to encode frame length */ 87 SHF_FIXED_SIZE = 1 << 1, /* Payload size guaranteed */ 88 SHF_ACTIVE = 1 << 2, /* On sm_hq_frames list */ 89 SHF_WRITTEN = 1 << 3, /* Framing bytes have been packetized */ 90 SHF_CC_PAID = 1 << 4, /* Paid connection cap */ 91 SHF_PHANTOM = 1 << 5, /* Phantom frame headers are not written */ 92 } shf_flags:8; 93}; 94 95 96struct hq_filter 97{ 98 struct varint_read2_state hqfi_vint2_state; 99 /* No need to copy the values: use it directly */ 100#define hqfi_left hqfi_vint2_state.vr2s_two 101#define hqfi_type hqfi_vint2_state.vr2s_one 102 struct varint_read_state hqfi_vint1_state; 103#define hqfi_push_id hqfi_vint1_state.value 104 enum { 105 HQFI_FLAG_UNUSED_0 = 1 << 0, 106 HQFI_FLAG_ERROR = 1 << 1, 107 HQFI_FLAG_BEGIN = 1 << 2, 108 HQFI_FLAG_BLOCKED = 1 << 3, 109 } hqfi_flags:8; 110 enum { 111 HQFI_STATE_FRAME_HEADER_BEGIN, 112 HQFI_STATE_FRAME_HEADER_CONTINUE, 113 HQFI_STATE_READING_PAYLOAD, 114 HQFI_STATE_PUSH_ID_BEGIN, 115 HQFI_STATE_PUSH_ID_CONTINUE, 116 } hqfi_state:8; 117 unsigned char hqfi_hist_idx; 118#define MAX_HQFI_ENTRIES (sizeof(unsigned) * 8 / 3) 119 unsigned hqfi_hist_buf; 120}; 121 122 123struct stream_filter_if 124{ 125 int (*sfi_readable)(struct lsquic_stream *); 126 size_t (*sfi_filter_df)(struct lsquic_stream *, struct data_frame *); 127 void (*sfi_decr_left)(struct lsquic_stream *, size_t); 128}; 129 130 131/* These flags indicate which queues -- or other entities -- currently 132 * reference the stream. 133 */ 134enum stream_q_flags 135{ 136 /* read_streams: */ 137 SMQF_WANT_READ = 1 << 0, 138 139 /* write_streams: */ 140#define SMQF_WRITE_Q_FLAGS (SMQF_WANT_FLUSH|SMQF_WANT_WRITE) 141 SMQF_WANT_WRITE = 1 << 1, 142 SMQF_WANT_FLUSH = 1 << 2, /* Flush until sm_flush_to is hit */ 143 144 /* There are more than one reason that a stream may be put onto 145 * connections's sending_streams queue. Note that writing STREAM 146 * frames is done separately. 147 */ 148#define SMQF_SENDING_FLAGS (SMQF_SEND_WUF|SMQF_SEND_RST|SMQF_SEND_BLOCKED\ 149 |SMQF_SEND_STOP_SENDING) 150 /* sending_streams: */ 151 SMQF_SEND_WUF = 1 << 3, /* WUF: Window Update Frame */ 152 SMQF_SEND_BLOCKED = 1 << 4, 153 SMQF_SEND_RST = 1 << 5, /* Error: want to send RST_STREAM */ 154 SMQF_SEND_STOP_SENDING = 1 << 10, 155 156 /* The equivalent of WINDOW_UPDATE frame for streams in IETF QUIC is 157 * the MAX_STREAM_DATA frame. Define an alias for use in the IETF 158 * QUIC code: 159 */ 160#define SMQF_SEND_MAX_STREAM_DATA SMQF_SEND_WUF 161 162#define SMQF_SERVICE_FLAGS (SMQF_CALL_ONCLOSE|SMQF_FREE_STREAM|SMQF_ABORT_CONN) 163 SMQF_CALL_ONCLOSE = 1 << 6, 164 SMQF_FREE_STREAM = 1 << 7, 165 SMQF_ABORT_CONN = 1 << 8, /* Unrecoverable error occurred */ 166 167 SMQF_QPACK_DEC = 1 << 9, /* QPACK decoder handler is holding a reference to this stream */ 168 169 /* The stream can reference itself, preventing its own destruction: */ 170#define SMQF_SELF_FLAGS SMQF_WAIT_FIN_OFF 171 SMQF_WAIT_FIN_OFF = 1 << 11, /* Waiting for final offset: FIN or RST */ 172}; 173 174 175/* Stream behavior flags */ 176enum stream_b_flags 177{ 178 SMBF_SERVER = 1 << 0, 179 SMBF_IETF = 1 << 1, 180 SMBF_USE_HEADERS = 1 << 2, 181 SMBF_CRYPTO = 1 << 3, /* Crypto stream: applies to both gQUIC and IETF QUIC */ 182 SMBF_CRITICAL = 1 << 4, /* This is a critical stream */ 183 SMBF_AUTOSWITCH = 1 << 5, 184 SMBF_RW_ONCE = 1 << 6, /* When set, read/write events are dispatched once per call */ 185 SMBF_CONN_LIMITED = 1 << 7, 186 SMBF_HEADERS = 1 << 8, /* Headers stream */ 187 SMBF_VERIFY_CL = 1 << 9, /* Verify content-length (stored in sm_cont_len) */ 188 SMBF_HTTP_PRIO = 1 <<10, /* Extensible HTTP Priorities are used */ 189 SMBF_INCREMENTAL = 1 <<11, /* Value of the "incremental" HTTP Priority parameter */ 190 SMBF_HPRIO_SET = 1 <<12, /* Extensible HTTP Priorities have been set once */ 191#define N_SMBF_FLAGS 13 192}; 193 194 195enum stream_flags { 196 STREAM_FIN_RECVD = 1 << 0, /* Received STREAM frame with FIN bit set */ 197 STREAM_RST_RECVD = 1 << 1, /* Received RST frame */ 198 STREAM_LAST_WRITE_OK= 1 << 2, /* Used to break out of write event dispatch loop */ 199 STREAM_U_READ_DONE = 1 << 3, /* User is done reading (shutdown was called) */ 200 STREAM_U_WRITE_DONE = 1 << 4, /* User is done writing (shutdown was called) */ 201 STREAM_FIN_SENT = 1 << 5, /* FIN was written to network */ 202 STREAM_RST_SENT = 1 << 6, /* RST_STREAM was written to network */ 203 STREAM_FIN_REACHED = 1 << 7, /* User read data up to FIN */ 204 STREAM_FINISHED = 1 << 8, /* Stream is finished */ 205 STREAM_ONCLOSE_DONE = 1 << 9, /* on_close has been called */ 206 STREAM_CACHED_FRAME = 1 << 10, /* If set, sm_has_frame can be used */ 207 STREAM_HEADERS_SENT = 1 << 11, 208 STREAM_HAVE_UH = 1 << 12, /* Have uncompressed headers */ 209 STREAM_ENCODER_DEP = 1 << 13, /* Encoder dependency: flush (IETF only) */ 210 STREAM_HEAD_IN_FIN = 1 << 14, /* Incoming headers has FIN bit set */ 211 STREAM_FRAMES_ELIDED= 1 << 15, 212 STREAM_FORCE_FINISH = 1 << 16, /* Replaces FIN sent and received */ 213 STREAM_ONNEW_DONE = 1 << 17, /* on_new_stream has been called */ 214 STREAM_PUSHING = 1 << 18, 215 STREAM_NOPUSH = 1 << 19, /* Disallow further push promises */ 216 STREAM_GOAWAY_IN = 1 << 20, /* Incoming GOAWAY has been processed */ 217 STREAM_SS_SENT = 1 << 21, /* STOP_SENDING sent */ 218 STREAM_RST_ACKED = 1 << 22, /* Packet containing RST has been acked */ 219 STREAM_BLOCKED_SENT = 1 << 23, /* Stays set once a STREAM_BLOCKED frame is sent */ 220 STREAM_RST_READ = 1 << 24, /* User code collected the error */ 221 STREAM_DATA_RECVD = 1 << 25, /* Cache stream state calculation */ 222 STREAM_UNUSED26 = 1 << 26, /* Unused */ 223 STREAM_HDRS_FLUSHED = 1 << 27, /* Only used in buffered packets mode */ 224 STREAM_SS_RECVD = 1 << 28, /* Received STOP_SENDING frame */ 225 STREAM_DELAYED_SW = 1 << 29, /* Delayed shutdown_write call */ 226}; 227 228 229/* By keeping this number low, we make sure that the code to allocate HQ 230 * frames dynamically gets exercised whenever push promises are sent. 231 */ 232#define NUM_ALLOCED_HQ_FRAMES 2 233 234 235struct lsquic_stream 236{ 237 struct lsquic_hash_elem sm_hash_el; 238 lsquic_stream_id_t id; 239 enum stream_flags stream_flags; 240 enum stream_b_flags sm_bflags; 241 enum stream_q_flags sm_qflags; 242 unsigned n_unacked; 243 244 const struct lsquic_stream_if *stream_if; 245 struct lsquic_stream_ctx *st_ctx; 246 struct lsquic_conn_public *conn_pub; 247 TAILQ_ENTRY(lsquic_stream) next_send_stream, next_read_stream, 248 next_write_stream, next_service_stream, 249 next_prio_stream; 250 251 uint64_t tosend_off; 252 uint64_t sm_payload; /* Not counting HQ frames */ 253 uint64_t max_send_off; 254 uint64_t sm_last_recv_off; 255 uint64_t error_code; 256 257 /* From the network, we get frames, which we keep on a list ordered 258 * by offset. 259 */ 260 struct data_in *data_in; 261 uint64_t read_offset; 262 lsquic_sfcw_t fc; 263 264 /* List of active HQ frames */ 265 STAILQ_HEAD(, stream_hq_frame) sm_hq_frames; 266 267 /* For efficiency, several frames are allocated as part of the stream 268 * itself. If more frames are needed, they are allocated. 269 */ 270 struct stream_hq_frame sm_hq_frame_arr[NUM_ALLOCED_HQ_FRAMES]; 271 272 struct hq_filter sm_hq_filter; 273 274 /* Optional tap for pwritev undo */ 275 struct hq_arr *sm_hq_arr; 276 277 /* We can safely use sm_hq_filter */ 278#define sm_uni_type_state sm_hq_filter.hqfi_vint2_state.vr2s_varint_state 279 280 /** If @ref SMQF_WANT_FLUSH is set, flush until this offset. */ 281 uint64_t sm_flush_to; 282 283 /** 284 * If @ref SMQF_WANT_FLUSH is set, this indicates payload offset 285 * to flush to. Used to adjust @ref sm_flush_to when H3 frame 286 * size grows. 287 */ 288 uint64_t sm_flush_to_payload; 289 290 /* Last offset sent in BLOCKED frame */ 291 uint64_t blocked_off; 292 293 struct uncompressed_headers *uh, 294 *push_req; 295 union hblock_ctx *sm_hblock_ctx; 296 297 unsigned char *sm_buf; 298 void *sm_onnew_arg; 299 300 unsigned char *sm_header_block; 301 uint64_t sm_hb_compl; 302 303 /* Valid if STREAM_FIN_RECVD is set: */ 304 uint64_t sm_fin_off; 305 306 /* A stream may be generating STREAM or CRYPTO frames */ 307 size_t (*sm_frame_header_sz)( 308 const struct lsquic_stream *, unsigned); 309 enum swtp_status (*sm_write_to_packet)(struct frame_gen_ctx *, 310 const size_t); 311 size_t (*sm_write_avail)(struct lsquic_stream *); 312 int (*sm_readable)(struct lsquic_stream *); 313 314 /* This element is optional */ 315 const struct stream_filter_if *sm_sfi; 316 317 /* sm_promise and sm_promises are never used at the same time and can 318 * be combined into a union should space in this struct become tight. 319 */ 320 /* Push promise that engendered this push stream */ 321 struct push_promise *sm_promise; 322 323 /* Push promises sent on this stream */ 324 SLIST_HEAD(, push_promise) sm_promises; 325 326 uint64_t sm_last_frame_off; 327 328#ifndef NDEBUG 329 /* Last time stream made progress */ 330 lsquic_time_t sm_last_prog; 331#endif 332 333 /* Content length specified in incoming `content-length' header field. 334 * Used to verify size of DATA frames. 335 */ 336 unsigned long long sm_cont_len; 337 /* Sum of bytes in all incoming DATA frames. Used for verification. */ 338 unsigned long long sm_data_in; 339 340 /* How much data there is in sm_header_block and how much of it has been 341 * sent: 342 */ 343 unsigned sm_hblock_sz, 344 sm_hblock_off; 345 346 unsigned short sm_n_buffered; /* Amount of data in sm_buf */ 347 unsigned short sm_n_allocated; /* Size of sm_buf */ 348 349 /* If SMBF_HTTP_PRIO is set, the priority is used to represent the 350 * Extensible Priority urgency, which is in the range [0, 7]. 351 */ 352 unsigned char sm_priority; /* 0: high; 255: low */ 353 unsigned char sm_enc_level; 354 enum { 355 SSHS_BEGIN, /* Nothing has happened yet */ 356 SSHS_ENC_SENDING, /* Sending encoder stream data */ 357 SSHS_HBLOCK_SENDING,/* Sending header block data */ 358 } sm_send_headers_state:8; 359 signed char sm_saved_want_write; 360 signed char sm_has_frame; 361 362#if LSQUIC_KEEP_STREAM_HISTORY 363 sm_hist_idx_t sm_hist_idx; 364#endif 365 366#if LSQUIC_KEEP_STREAM_HISTORY 367 /* Stream history: see enum stream_history_event */ 368 unsigned char sm_hist_buf[ 1 << SM_HIST_BITS ]; 369#endif 370}; 371 372 373enum stream_ctor_flags 374{ 375 SCF_CALL_ON_NEW = (1 << (N_SMBF_FLAGS + 0)), /* Call on_new_stream() immediately */ 376 SCF_USE_DI_HASH = (1 << (N_SMBF_FLAGS + 1)), /* Use hash-based data input. If not set, 377 * the nocopy data input is used. 378 */ 379 SCF_CRYPTO_FRAMES = (1 << (N_SMBF_FLAGS + 2)), /* Write CRYPTO frames */ 380 SCF_DI_AUTOSWITCH = SMBF_AUTOSWITCH, /* Automatically switch between nocopy 381 * and hash-based to data input for optimal 382 * performance. 383 */ 384 SCF_DISP_RW_ONCE = SMBF_RW_ONCE, 385 SCF_CRITICAL = SMBF_CRITICAL, /* This is a critical stream */ 386 SCF_IETF = SMBF_IETF, 387 SCF_HTTP = SMBF_USE_HEADERS, 388 SCF_CRYPTO = SMBF_CRYPTO, 389 SCF_HEADERS = SMBF_HEADERS, 390 SCF_HTTP_PRIO = SMBF_HTTP_PRIO, 391}; 392 393 394lsquic_stream_t * 395lsquic_stream_new (lsquic_stream_id_t id, struct lsquic_conn_public *, 396 const struct lsquic_stream_if *, void *stream_if_ctx, 397 unsigned initial_sfrw, uint64_t initial_send_off, 398 enum stream_ctor_flags); 399 400struct lsquic_stream * 401lsquic_stream_new_crypto (enum enc_level, 402 struct lsquic_conn_public *conn_pub, 403 const struct lsquic_stream_if *stream_if, void *stream_if_ctx, 404 enum stream_ctor_flags ctor_flags); 405 406void 407lsquic_stream_call_on_new (lsquic_stream_t *); 408 409void 410lsquic_stream_destroy (lsquic_stream_t *); 411 412/* Any of these flags will cause user-facing read and write and 413 * shutdown calls to return an error. They also make the stream 414 * both readable and writeable, as we want the user to collect 415 * the error. 416 */ 417#define lsquic_stream_is_reset(stream) \ 418 (((stream)->stream_flags & \ 419 (STREAM_RST_RECVD|STREAM_RST_SENT|STREAM_SS_RECVD)) \ 420 || ((stream)->sm_qflags & SMQF_SEND_RST)) 421 422/* Data that from the network gets inserted into the stream using 423 * lsquic_stream_frame_in() function. Returns 0 on success, -1 on 424 * failure. The latter may be caused by flow control violation or 425 * invalid stream frame data, e.g. overlapping segments. 426 * 427 * Note that the caller gives up control of `frame' no matter 428 * what this function returns. 429 * 430 * This data is read by the user using lsquic_stream_read() function. 431 */ 432int 433lsquic_stream_frame_in (lsquic_stream_t *, struct stream_frame *frame); 434 435/* Only one (at least for now) uncompressed header structure is allowed to be 436 * passed in, and only in HTTP mode. 437 */ 438int 439lsquic_stream_uh_in (lsquic_stream_t *, struct uncompressed_headers *); 440 441void 442lsquic_stream_push_req (lsquic_stream_t *, 443 struct uncompressed_headers *push_req); 444 445int 446lsquic_stream_rst_in (lsquic_stream_t *, uint64_t offset, uint64_t error_code); 447 448void 449lsquic_stream_stop_sending_in (struct lsquic_stream *, uint64_t error_code); 450 451uint64_t 452lsquic_stream_read_offset (const lsquic_stream_t *stream); 453 454/* Return true if we sent all available data to the network and write 455 * end of the stream was closed. 456 */ 457int 458lsquic_stream_tosend_fin (const lsquic_stream_t *stream); 459 460void 461lsquic_stream_window_update (lsquic_stream_t *stream, uint64_t offset); 462 463int 464lsquic_stream_set_max_send_off (lsquic_stream_t *stream, uint64_t offset); 465 466/* The caller should only call this function if SMQF_SEND_WUF is set and 467 * it must generate a window update frame using this value. 468 */ 469uint64_t 470lsquic_stream_fc_recv_off (lsquic_stream_t *stream); 471 472void 473lsquic_stream_peer_blocked (struct lsquic_stream *, uint64_t); 474 475void 476lsquic_stream_peer_blocked_gquic (struct lsquic_stream *); 477 478void 479lsquic_stream_dispatch_read_events (lsquic_stream_t *); 480 481void 482lsquic_stream_dispatch_write_events (lsquic_stream_t *); 483 484void 485lsquic_stream_blocked_frame_sent (lsquic_stream_t *); 486 487void 488lsquic_stream_rst_frame_sent (lsquic_stream_t *); 489 490void 491lsquic_stream_stream_frame_sent (lsquic_stream_t *); 492 493void 494lsquic_stream_reset (lsquic_stream_t *, uint64_t error_code); 495 496void 497lsquic_stream_reset_ext (lsquic_stream_t *, uint64_t error_code, int close); 498 499void 500lsquic_stream_call_on_close (lsquic_stream_t *); 501 502void 503lsquic_stream_shutdown_internal (lsquic_stream_t *); 504 505void 506lsquic_stream_received_goaway (lsquic_stream_t *); 507 508void 509lsquic_stream_acked (struct lsquic_stream *, enum quic_frame_type); 510 511#define lsquic_stream_is_closed(s) \ 512 (((s)->stream_flags & (STREAM_U_READ_DONE|STREAM_U_WRITE_DONE)) \ 513 == (STREAM_U_READ_DONE|STREAM_U_WRITE_DONE)) 514int 515lsquic_stream_update_sfcw (lsquic_stream_t *, uint64_t max_off); 516 517int 518lsquic_stream_set_priority_internal (lsquic_stream_t *, unsigned priority); 519 520#define lsquic_stream_is_critical(s) ((s)->sm_bflags & SMBF_CRITICAL) 521 522#define lsquic_stream_is_crypto(s) ((s)->sm_bflags & SMBF_CRYPTO) 523 524size_t 525lsquic_stream_mem_used (const struct lsquic_stream *); 526 527const lsquic_cid_t * 528lsquic_stream_cid (const struct lsquic_stream *); 529 530#define lsquic_stream_has_data_to_flush(stream) ((stream)->sm_n_buffered > 0) 531 532int 533lsquic_stream_readable (struct lsquic_stream *); 534 535size_t 536lsquic_stream_write_avail (struct lsquic_stream *); 537 538void 539lsquic_stream_dump_state (const struct lsquic_stream *); 540 541#ifndef NDEBUG 542size_t 543lsquic_stream_flush_threshold (const struct lsquic_stream *, unsigned); 544#endif 545 546#define crypto_level(stream) (UINT64_MAX - (stream)->id) 547 548void 549lsquic_stream_set_stream_if (struct lsquic_stream *, 550 const struct lsquic_stream_if *, void *stream_if_ctx); 551 552uint64_t 553lsquic_stream_combined_send_off (const struct lsquic_stream *); 554 555/* [draft-ietf-quic-transport-16] Section 3.1 */ 556enum stream_state_sending 557{ 558 SSS_READY, 559 SSS_SEND, 560 SSS_DATA_SENT, 561 SSS_RESET_SENT, 562 SSS_DATA_RECVD, 563 SSS_RESET_RECVD, 564}; 565 566extern const char *const lsquic_sss2str[]; 567 568enum stream_state_sending 569lsquic_stream_sending_state (const struct lsquic_stream *); 570 571/* [draft-ietf-quic-transport-16] Section 3.2 */ 572enum stream_state_receiving 573{ 574 SSR_RECV, 575 SSR_SIZE_KNOWN, 576 SSR_DATA_RECVD, 577 SSR_RESET_RECVD, 578 SSR_DATA_READ, 579 SSR_RESET_READ, 580}; 581 582extern const char *const lsquic_ssr2str[]; 583 584enum stream_state_receiving 585lsquic_stream_receiving_state (struct lsquic_stream *); 586 587uint64_t 588lsquic_stream_fc_recv_off_const (const struct lsquic_stream *); 589 590void 591lsquic_stream_max_stream_data_sent (struct lsquic_stream *); 592 593void 594lsquic_stream_qdec_unblocked (struct lsquic_stream *); 595 596int 597lsquic_stream_can_push (const struct lsquic_stream *); 598 599int 600lsquic_stream_push_promise (struct lsquic_stream *, struct push_promise *); 601 602void 603lsquic_stream_force_finish (struct lsquic_stream *); 604 605int 606lsquic_stream_header_is_pp (const struct lsquic_stream *); 607 608int 609lsquic_stream_header_is_trailer (const struct lsquic_stream *); 610 611int 612lsquic_stream_verify_len (struct lsquic_stream *, unsigned long long); 613 614#define lsquic_stream_is_blocked(stream_) ((stream_)->blocked_off && \ 615 (stream_)->blocked_off == (stream_)->max_send_off) 616 617void 618lsquic_stream_ss_frame_sent (struct lsquic_stream *); 619 620#ifndef NDEBUG 621void 622lsquic_stream_set_pwritev_params (unsigned iovecs, unsigned frames); 623#endif 624 625#endif 626