lsquic_stream.h revision 2f2f4363
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:8;
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#define N_SMBF_FLAGS 10
189};
190
191
192enum stream_flags {
193    STREAM_FIN_RECVD    = 1 << 0,   /* Received STREAM frame with FIN bit set */
194    STREAM_RST_RECVD    = 1 << 1,   /* Received RST frame */
195    STREAM_LAST_WRITE_OK= 1 << 2,   /* Used to break out of write event dispatch loop */
196    STREAM_U_READ_DONE  = 1 << 3,   /* User is done reading (shutdown was called) */
197    STREAM_U_WRITE_DONE = 1 << 4,   /* User is done writing (shutdown was called) */
198    STREAM_FIN_SENT     = 1 << 5,   /* FIN was written to network */
199    STREAM_RST_SENT     = 1 << 6,   /* RST_STREAM was written to network */
200    STREAM_FIN_REACHED  = 1 << 7,   /* User read data up to FIN */
201    STREAM_FINISHED     = 1 << 8,   /* Stream is finished */
202    STREAM_ONCLOSE_DONE = 1 << 9,   /* on_close has been called */
203    STREAM_CACHED_FRAME = 1 << 10,  /* If set, sm_has_frame can be used */
204    STREAM_HEADERS_SENT = 1 << 11,
205    STREAM_HAVE_UH      = 1 << 12,  /* Have uncompressed headers */
206    STREAM_ENCODER_DEP  = 1 << 13,  /* Encoder dependency: flush (IETF only) */
207    STREAM_HEAD_IN_FIN  = 1 << 14,  /* Incoming headers has FIN bit set */
208    STREAM_FRAMES_ELIDED= 1 << 15,
209    STREAM_FORCE_FINISH = 1 << 16,  /* Replaces FIN sent and received */
210    STREAM_ONNEW_DONE   = 1 << 17,  /* on_new_stream has been called */
211    STREAM_PUSHING      = 1 << 18,
212    STREAM_NOPUSH       = 1 << 19,  /* Disallow further push promises */
213    STREAM_GOAWAY_IN    = 1 << 20,  /* Incoming GOAWAY has been processed */
214    STREAM_SS_SENT      = 1 << 21,  /* STOP_SENDING sent */
215    STREAM_RST_ACKED    = 1 << 22,  /* Packet containing RST has been acked */
216    STREAM_BLOCKED_SENT = 1 << 23,  /* Stays set once a STREAM_BLOCKED frame is sent */
217    STREAM_RST_READ     = 1 << 24,  /* User code collected the error */
218    STREAM_DATA_RECVD   = 1 << 25,  /* Cache stream state calculation */
219    STREAM_UNUSED26     = 1 << 26,  /* Unused */
220    STREAM_HDRS_FLUSHED = 1 << 27,  /* Only used in buffered packets mode */
221    STREAM_SS_RECVD     = 1 << 28,  /* Received STOP_SENDING frame */
222    STREAM_DELAYED_SW   = 1 << 29,  /* Delayed shutdown_write call */
223};
224
225
226/* By keeping this number low, we make sure that the code to allocate HQ
227 * frames dynamically gets exercised whenever push promises are sent.
228 */
229#define NUM_ALLOCED_HQ_FRAMES 2
230
231
232struct lsquic_stream
233{
234    struct lsquic_hash_elem         sm_hash_el;
235    lsquic_stream_id_t              id;
236    enum stream_flags               stream_flags;
237    enum stream_b_flags             sm_bflags;
238    enum stream_q_flags             sm_qflags;
239    unsigned                        n_unacked;
240
241    const struct lsquic_stream_if  *stream_if;
242    struct lsquic_stream_ctx       *st_ctx;
243    struct lsquic_conn_public      *conn_pub;
244    TAILQ_ENTRY(lsquic_stream)      next_send_stream, next_read_stream,
245                                        next_write_stream, next_service_stream,
246                                        next_prio_stream;
247
248    uint64_t                        tosend_off;
249    uint64_t                        sm_payload;     /* Not counting HQ frames */
250    uint64_t                        max_send_off;
251    uint64_t                        sm_last_recv_off;
252    uint64_t                        error_code;
253
254    /* From the network, we get frames, which we keep on a list ordered
255     * by offset.
256     */
257    struct data_in                 *data_in;
258    uint64_t                        read_offset;
259    lsquic_sfcw_t                   fc;
260
261    /* List of active HQ frames */
262    STAILQ_HEAD(, stream_hq_frame)  sm_hq_frames;
263
264    /* For efficiency, several frames are allocated as part of the stream
265     * itself.  If more frames are needed, they are allocated.
266     */
267    struct stream_hq_frame          sm_hq_frame_arr[NUM_ALLOCED_HQ_FRAMES];
268
269    struct hq_filter                sm_hq_filter;
270
271    /* Optional tap for pwritev undo */
272    struct hq_arr                  *sm_hq_arr;
273
274    /* We can safely use sm_hq_filter */
275#define sm_uni_type_state sm_hq_filter.hqfi_vint2_state.vr2s_varint_state
276
277    /** If @ref SMQF_WANT_FLUSH is set, flush until this offset. */
278    uint64_t                        sm_flush_to;
279
280    /**
281     * If @ref SMQF_WANT_FLUSH is set, this indicates payload offset
282     * to flush to.  Used to adjust @ref sm_flush_to when H3 frame
283     * size grows.
284     */
285    uint64_t                        sm_flush_to_payload;
286
287    /* Last offset sent in BLOCKED frame */
288    uint64_t                        blocked_off;
289
290    struct uncompressed_headers    *uh,
291                                   *push_req;
292    union hblock_ctx               *sm_hblock_ctx;
293
294    unsigned char                  *sm_buf;
295    void                           *sm_onnew_arg;
296
297    unsigned char                  *sm_header_block;
298    uint64_t                        sm_hb_compl;
299
300    /* Valid if STREAM_FIN_RECVD is set: */
301    uint64_t                        sm_fin_off;
302
303    /* A stream may be generating STREAM or CRYPTO frames */
304    size_t                        (*sm_frame_header_sz)(
305                                        const struct lsquic_stream *, unsigned);
306    enum swtp_status              (*sm_write_to_packet)(struct frame_gen_ctx *,
307                                                const size_t);
308    size_t                        (*sm_write_avail)(struct lsquic_stream *);
309    int                           (*sm_readable)(struct lsquic_stream *);
310
311    /* This element is optional */
312    const struct stream_filter_if  *sm_sfi;
313
314    /* sm_promise and sm_promises are never used at the same time and can
315     * be combined into a union should space in this struct become tight.
316     */
317    /* Push promise that engendered this push stream */
318    struct push_promise            *sm_promise;
319
320    /* Push promises sent on this stream */
321    SLIST_HEAD(, push_promise)      sm_promises;
322
323    uint64_t                        sm_last_frame_off;
324
325#ifndef NDEBUG
326    /* Last time stream made progress */
327    lsquic_time_t                   sm_last_prog;
328#endif
329
330    /* Content length specified in incoming `content-length' header field.
331     * Used to verify size of DATA frames.
332     */
333    unsigned long long              sm_cont_len;
334    /* Sum of bytes in all incoming DATA frames.  Used for verification. */
335    unsigned long long              sm_data_in;
336
337    /* How much data there is in sm_header_block and how much of it has been
338     * sent:
339     */
340    unsigned                        sm_hblock_sz,
341                                    sm_hblock_off;
342
343    unsigned short                  sm_n_buffered;  /* Amount of data in sm_buf */
344    unsigned short                  sm_n_allocated;  /* Size of sm_buf */
345
346    unsigned char                   sm_priority;  /* 0: high; 255: low */
347    unsigned char                   sm_enc_level;
348    enum {
349        SSHS_BEGIN,         /* Nothing has happened yet */
350        SSHS_ENC_SENDING,   /* Sending encoder stream data */
351        SSHS_HBLOCK_SENDING,/* Sending header block data */
352    }                               sm_send_headers_state:8;
353    signed char                     sm_saved_want_write;
354    signed char                     sm_has_frame;
355
356#if LSQUIC_KEEP_STREAM_HISTORY
357    sm_hist_idx_t                   sm_hist_idx;
358#endif
359
360#if LSQUIC_KEEP_STREAM_HISTORY
361    /* Stream history: see enum stream_history_event */
362    unsigned char                   sm_hist_buf[ 1 << SM_HIST_BITS ];
363#endif
364};
365
366
367enum stream_ctor_flags
368{
369    SCF_CALL_ON_NEW   = (1 << (N_SMBF_FLAGS + 0)), /* Call on_new_stream() immediately */
370    SCF_USE_DI_HASH   = (1 << (N_SMBF_FLAGS + 1)), /* Use hash-based data input.  If not set,
371                                   * the nocopy data input is used.
372                                   */
373    SCF_CRYPTO_FRAMES = (1 << (N_SMBF_FLAGS + 2)), /* Write CRYPTO frames */
374    SCF_DI_AUTOSWITCH = SMBF_AUTOSWITCH, /* Automatically switch between nocopy
375                                   * and hash-based to data input for optimal
376                                   * performance.
377                                   */
378    SCF_DISP_RW_ONCE  = SMBF_RW_ONCE,
379    SCF_CRITICAL      = SMBF_CRITICAL, /* This is a critical stream */
380    SCF_IETF          = SMBF_IETF,
381    SCF_HTTP          = SMBF_USE_HEADERS,
382    SCF_CRYPTO        = SMBF_CRYPTO,
383    SCF_HEADERS       = SMBF_HEADERS,
384};
385
386
387lsquic_stream_t *
388lsquic_stream_new (lsquic_stream_id_t id, struct lsquic_conn_public *,
389                   const struct lsquic_stream_if *, void *stream_if_ctx,
390                   unsigned initial_sfrw, uint64_t initial_send_off,
391                   enum stream_ctor_flags);
392
393struct lsquic_stream *
394lsquic_stream_new_crypto (enum enc_level,
395        struct lsquic_conn_public *conn_pub,
396        const struct lsquic_stream_if *stream_if, void *stream_if_ctx,
397        enum stream_ctor_flags ctor_flags);
398
399void
400lsquic_stream_call_on_new (lsquic_stream_t *);
401
402void
403lsquic_stream_destroy (lsquic_stream_t *);
404
405/* Any of these flags will cause user-facing read and write and
406 * shutdown calls to return an error.  They also make the stream
407 * both readable and writeable, as we want the user to collect
408 * the error.
409 */
410#define lsquic_stream_is_reset(stream) \
411    (((stream)->stream_flags & \
412                    (STREAM_RST_RECVD|STREAM_RST_SENT|STREAM_SS_RECVD)) \
413        || ((stream)->sm_qflags & SMQF_SEND_RST))
414
415/* Data that from the network gets inserted into the stream using
416 * lsquic_stream_frame_in() function.  Returns 0 on success, -1 on
417 * failure.  The latter may be caused by flow control violation or
418 * invalid stream frame data, e.g. overlapping segments.
419 *
420 * Note that the caller gives up control of `frame' no matter
421 * what this function returns.
422 *
423 * This data is read by the user using lsquic_stream_read() function.
424 */
425int
426lsquic_stream_frame_in (lsquic_stream_t *, struct stream_frame *frame);
427
428/* Only one (at least for now) uncompressed header structure is allowed to be
429 * passed in, and only in HTTP mode.
430 */
431int
432lsquic_stream_uh_in (lsquic_stream_t *, struct uncompressed_headers *);
433
434void
435lsquic_stream_push_req (lsquic_stream_t *,
436                        struct uncompressed_headers *push_req);
437
438int
439lsquic_stream_rst_in (lsquic_stream_t *, uint64_t offset, uint64_t error_code);
440
441void
442lsquic_stream_stop_sending_in (struct lsquic_stream *, uint64_t error_code);
443
444uint64_t
445lsquic_stream_read_offset (const lsquic_stream_t *stream);
446
447/* Return true if we sent all available data to the network and write
448 * end of the stream was closed.
449 */
450int
451lsquic_stream_tosend_fin (const lsquic_stream_t *stream);
452
453void
454lsquic_stream_window_update (lsquic_stream_t *stream, uint64_t offset);
455
456int
457lsquic_stream_set_max_send_off (lsquic_stream_t *stream, uint64_t offset);
458
459/* The caller should only call this function if SMQF_SEND_WUF is set and
460 * it must generate a window update frame using this value.
461 */
462uint64_t
463lsquic_stream_fc_recv_off (lsquic_stream_t *stream);
464
465void
466lsquic_stream_peer_blocked (struct lsquic_stream *, uint64_t);
467
468void
469lsquic_stream_peer_blocked_gquic (struct lsquic_stream *);
470
471void
472lsquic_stream_dispatch_read_events (lsquic_stream_t *);
473
474void
475lsquic_stream_dispatch_write_events (lsquic_stream_t *);
476
477void
478lsquic_stream_blocked_frame_sent (lsquic_stream_t *);
479
480void
481lsquic_stream_rst_frame_sent (lsquic_stream_t *);
482
483void
484lsquic_stream_stream_frame_sent (lsquic_stream_t *);
485
486void
487lsquic_stream_reset (lsquic_stream_t *, uint64_t error_code);
488
489void
490lsquic_stream_reset_ext (lsquic_stream_t *, uint64_t error_code, int close);
491
492void
493lsquic_stream_call_on_close (lsquic_stream_t *);
494
495void
496lsquic_stream_shutdown_internal (lsquic_stream_t *);
497
498void
499lsquic_stream_received_goaway (lsquic_stream_t *);
500
501void
502lsquic_stream_acked (struct lsquic_stream *, enum quic_frame_type);
503
504#define lsquic_stream_is_closed(s)                                          \
505    (((s)->stream_flags & (STREAM_U_READ_DONE|STREAM_U_WRITE_DONE))         \
506                            == (STREAM_U_READ_DONE|STREAM_U_WRITE_DONE))
507int
508lsquic_stream_update_sfcw (lsquic_stream_t *, uint64_t max_off);
509
510int
511lsquic_stream_set_priority_internal (lsquic_stream_t *, unsigned priority);
512
513#define lsquic_stream_is_critical(s) ((s)->sm_bflags & SMBF_CRITICAL)
514
515#define lsquic_stream_is_crypto(s) ((s)->sm_bflags & SMBF_CRYPTO)
516
517size_t
518lsquic_stream_mem_used (const struct lsquic_stream *);
519
520const lsquic_cid_t *
521lsquic_stream_cid (const struct lsquic_stream *);
522
523#define lsquic_stream_has_data_to_flush(stream) ((stream)->sm_n_buffered > 0)
524
525int
526lsquic_stream_readable (struct lsquic_stream *);
527
528size_t
529lsquic_stream_write_avail (struct lsquic_stream *);
530
531void
532lsquic_stream_dump_state (const struct lsquic_stream *);
533
534#ifndef NDEBUG
535size_t
536lsquic_stream_flush_threshold (const struct lsquic_stream *, unsigned);
537#endif
538
539#define crypto_level(stream) (~0ULL - (stream)->id)
540
541void
542lsquic_stream_set_stream_if (struct lsquic_stream *,
543                   const struct lsquic_stream_if *, void *stream_if_ctx);
544
545uint64_t
546lsquic_stream_combined_send_off (const struct lsquic_stream *);
547
548/* [draft-ietf-quic-transport-16] Section 3.1 */
549enum stream_state_sending
550{
551    SSS_READY,
552    SSS_SEND,
553    SSS_DATA_SENT,
554    SSS_RESET_SENT,
555    SSS_DATA_RECVD,
556    SSS_RESET_RECVD,
557};
558
559extern const char *const lsquic_sss2str[];
560
561enum stream_state_sending
562lsquic_stream_sending_state (const struct lsquic_stream *);
563
564/* [draft-ietf-quic-transport-16] Section 3.2 */
565enum stream_state_receiving
566{
567    SSR_RECV,
568    SSR_SIZE_KNOWN,
569    SSR_DATA_RECVD,
570    SSR_RESET_RECVD,
571    SSR_DATA_READ,
572    SSR_RESET_READ,
573};
574
575extern const char *const lsquic_ssr2str[];
576
577enum stream_state_receiving
578lsquic_stream_receiving_state (struct lsquic_stream *);
579
580uint64_t
581lsquic_stream_fc_recv_off_const (const struct lsquic_stream *);
582
583void
584lsquic_stream_max_stream_data_sent (struct lsquic_stream *);
585
586void
587lsquic_stream_qdec_unblocked (struct lsquic_stream *);
588
589int
590lsquic_stream_can_push (const struct lsquic_stream *);
591
592int
593lsquic_stream_push_promise (struct lsquic_stream *, struct push_promise *);
594
595void
596lsquic_stream_force_finish (struct lsquic_stream *);
597
598int
599lsquic_stream_header_is_pp (const struct lsquic_stream *);
600
601int
602lsquic_stream_header_is_trailer (const struct lsquic_stream *);
603
604int
605lsquic_stream_verify_len (struct lsquic_stream *, unsigned long long);
606
607#define lsquic_stream_is_blocked(stream_) ((stream_)->blocked_off && \
608                        (stream_)->blocked_off == (stream_)->max_send_off)
609
610void
611lsquic_stream_ss_frame_sent (struct lsquic_stream *);
612
613#ifndef NDEBUG
614void
615lsquic_stream_set_pwritev_params (unsigned iovecs, unsigned frames);
616#endif
617
618#endif
619