lsquic_stream.h revision 10c492f0
1/* Copyright (c) 2017 - 2018 LiteSpeed Technologies Inc.  See LICENSE. */
2#ifndef LSQUIC_STREAM_H
3#define LSQUIC_STREAM_H
4
5#define LSQUIC_STREAM_HANDSHAKE 1
6#define LSQUIC_STREAM_HEADERS   3
7
8#define LSQUIC_STREAM_DEFAULT_PRIO 16   /* RFC 7540, Section 5.3.5 */
9
10
11struct lsquic_stream_if;
12struct lsquic_stream_ctx;
13struct lsquic_conn_public;
14struct stream_frame;
15struct uncompressed_headers;
16
17TAILQ_HEAD(lsquic_streams_tailq, lsquic_stream);
18
19
20#ifndef LSQUIC_KEEP_STREAM_HISTORY
21#   ifdef NDEBUG
22#       define LSQUIC_KEEP_STREAM_HISTORY 0
23#   else
24#       define LSQUIC_KEEP_STREAM_HISTORY 1
25#   endif
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
36struct lsquic_stream
37{
38    uint32_t                        id;
39    enum stream_flags {
40        STREAM_WANT_READ    = (1 << 0),
41        STREAM_WANT_WRITE   = (1 << 1),
42        STREAM_FIN_RECVD    = (1 << 2),     /* Received STREAM frame with FIN bit set */
43        STREAM_RST_RECVD    = (1 << 3),     /* Received RST frame */
44        STREAM_SEND_WUF     = (1 << 4),     /* WUF: Window Update Frame */
45        STREAM_LAST_WRITE_OK= (1 << 5),     /* Used to break out of write event dispatch loop */
46        STREAM_SEND_BLOCKED = (1 << 6),
47        STREAM_SEND_RST     = (1 << 7),     /* Error: want to send RST_STREAM */
48        STREAM_U_READ_DONE  = (1 << 8),     /* User is done reading (shutdown was called) */
49        STREAM_U_WRITE_DONE = (1 << 9),     /* User is done writing (shutdown was called) */
50        STREAM_FIN_SENT     = (1 <<10),     /* FIN was written to network */
51        STREAM_RST_SENT     = (1 <<11),     /* RST_STREAM was written to network */
52        STREAM_WANT_FLUSH   = (1 <<12),     /* Flush until sm_flush_to is hit */
53        STREAM_FIN_REACHED  = (1 <<13),     /* User read data up to FIN */
54        STREAM_FINISHED     = (1 <<14),     /* Stream is finished */
55        STREAM_ONCLOSE_DONE = (1 <<15),     /* on_close has been called */
56        STREAM_CALL_ONCLOSE = (1 <<16),
57        STREAM_FREE_STREAM  = (1 <<17),
58        STREAM_USE_HEADERS  = (1 <<18),
59        STREAM_HEADERS_SENT = (1 <<19),
60        STREAM_HAVE_UH      = (1 <<20),     /* Have uncompressed headers */
61        STREAM_CONN_LIMITED = (1 <<21),
62        STREAM_HEAD_IN_FIN  = (1 <<22),     /* Incoming headers has FIN bit set */
63        STREAM_ABORT_CONN   = (1 <<23),     /* Unrecoverable error occurred */
64        STREAM_FRAMES_ELIDED= (1 <<24),
65        STREAM_FORCE_FINISH = (1 <<25),     /* Replaces FIN sent and received */
66        STREAM_ONNEW_DONE   = (1 <<26),     /* on_new_stream has been called */
67        STREAM_AUTOSWITCH   = (1 <<27),
68        STREAM_RW_ONCE      = (1 <<28),     /* When set, read/write events are dispatched once per call */
69    }                               stream_flags;
70
71    /* There are more than one reason that a stream may be put onto
72     * connections's sending_streams queue.  Note that writing STREAM
73     * frames is done separately.
74     */
75    #define STREAM_SENDING_FLAGS (STREAM_SEND_WUF| \
76                                          STREAM_SEND_RST|STREAM_SEND_BLOCKED)
77
78    #define STREAM_WRITE_Q_FLAGS (STREAM_WANT_FLUSH|STREAM_WANT_WRITE)
79
80    /* Any of these flags will cause user-facing read and write and
81     * shutdown calls to return an error.  They also make the stream
82     * both readable and writeable, as we want the user to collect
83     * the error.
84     */
85    #define STREAM_RST_FLAGS (STREAM_RST_RECVD|STREAM_RST_SENT|\
86                                                        STREAM_SEND_RST)
87
88    #define STREAM_SERVICE_FLAGS (STREAM_CALL_ONCLOSE|STREAM_FREE_STREAM|\
89                                                            STREAM_ABORT_CONN)
90
91    const struct lsquic_stream_if  *stream_if;
92    struct lsquic_stream_ctx       *st_ctx;
93    struct lsquic_conn_public      *conn_pub;
94    TAILQ_ENTRY(lsquic_stream)      next_send_stream, next_read_stream,
95                                        next_write_stream, next_service_stream,
96                                        next_prio_stream;
97
98    uint32_t                        error_code;
99    uint64_t                        tosend_off;
100    uint64_t                        max_send_off;
101
102    /* From the network, we get frames, which we keep on a list ordered
103     * by offset.
104     */
105    struct data_in                 *data_in;
106    uint64_t                        read_offset;
107    lsquic_sfcw_t                   fc;
108
109    /** If @ref STREAM_WANT_FLUSH is set, flush until this offset. */
110    uint64_t                        sm_flush_to;
111
112    /* Last offset sent in BLOCKED frame */
113    uint64_t                        blocked_off;
114
115    struct uncompressed_headers    *uh,
116                                   *push_req;
117
118    unsigned char                  *sm_buf;
119    void                           *sm_onnew_arg;
120
121    unsigned                        n_unacked;
122    unsigned short                  sm_n_buffered;  /* Amount of data in sm_buf */
123
124    unsigned char                   sm_priority;  /* 0: high; 255: low */
125#if LSQUIC_KEEP_STREAM_HISTORY
126    sm_hist_idx_t                   sm_hist_idx;
127#endif
128
129#if LSQUIC_KEEP_STREAM_HISTORY
130    /* Stream history: see enum stream_history_event */
131    unsigned char                   sm_hist_buf[ 1 << SM_HIST_BITS ];
132#endif
133};
134
135
136enum stream_ctor_flags
137{
138    SCF_CALL_ON_NEW   = (1 << 0), /* Call on_new_stream() immediately */
139    SCF_USE_DI_HASH   = (1 << 1), /* Use hash-based data input.  If not set,
140                                   * the nocopy data input is used.
141                                   */
142    SCF_DI_AUTOSWITCH = (1 << 2), /* Automatically switch between nocopy
143                                   * and hash-based to data input for optimal
144                                   * performance.
145                                   */
146    SCF_DISP_RW_ONCE  = (1 << 3),
147};
148
149
150lsquic_stream_t *
151lsquic_stream_new_ext (uint32_t id, struct lsquic_conn_public *conn_pub,
152                       const struct lsquic_stream_if *, void *stream_if_ctx,
153                       unsigned initial_sfrw, unsigned initial_send_off,
154                       enum stream_ctor_flags);
155
156#define lsquic_stream_new(id, pub, sm_if, sm_if_ctx, cfcw, send_off)        \
157        lsquic_stream_new_ext(id, pub, sm_if, sm_if_ctx, cfcw, send_off,    \
158                              (SCF_CALL_ON_NEW|SCF_DI_AUTOSWITCH))
159
160void
161lsquic_stream_call_on_new (lsquic_stream_t *);
162
163void
164lsquic_stream_destroy (lsquic_stream_t *);
165
166#define lsquic_stream_is_reset(stream) \
167    (!!((stream)->stream_flags & STREAM_RST_FLAGS))
168
169/* Data that from the network gets inserted into the stream using
170 * lsquic_stream_frame_in() function.  Returns 0 on success, -1 on
171 * failure.  The latter may be caused by flow control violation or
172 * invalid stream frame data, e.g. overlapping segments.
173 *
174 * Note that the caller does gives up control of `frame' no matter
175 * what this function returns.
176 *
177 * This data is read by the user using lsquic_stream_read() function.
178 */
179int
180lsquic_stream_frame_in (lsquic_stream_t *, struct stream_frame *frame);
181
182/* Only one (at least for now) uncompressed header structure is allowed to be
183 * passed in, and only in HTTP mode.
184 */
185int
186lsquic_stream_uh_in (lsquic_stream_t *, struct uncompressed_headers *);
187
188void
189lsquic_stream_push_req (lsquic_stream_t *,
190                        struct uncompressed_headers *push_req);
191
192int
193lsquic_stream_rst_in (lsquic_stream_t *, uint64_t offset, uint32_t error_code);
194
195ssize_t
196lsquic_stream_read (lsquic_stream_t *stream, void *buf, size_t len);
197
198uint64_t
199lsquic_stream_read_offset (const lsquic_stream_t *stream);
200
201/* Return true if we sent all available data to the network and write
202 * end of the stream was closed.
203 */
204int
205lsquic_stream_tosend_fin (const lsquic_stream_t *stream);
206
207/* Data to be sent out to the network is written using lsquic_stream_write().
208 */
209ssize_t
210lsquic_stream_write (lsquic_stream_t *stream, const void *buf, size_t len);
211
212void
213lsquic_stream_window_update (lsquic_stream_t *stream, uint64_t offset);
214
215int
216lsquic_stream_set_max_send_off (lsquic_stream_t *stream, unsigned offset);
217
218/* The caller should only call this function if STREAM_SEND_WUF is set and
219 * it must generate a window update frame using this value.
220 */
221uint64_t
222lsquic_stream_fc_recv_off (lsquic_stream_t *stream);
223
224void
225lsquic_stream_dispatch_read_events (lsquic_stream_t *);
226
227void
228lsquic_stream_dispatch_write_events (lsquic_stream_t *);
229
230void
231lsquic_stream_blocked_frame_sent (lsquic_stream_t *);
232
233void
234lsquic_stream_rst_frame_sent (lsquic_stream_t *);
235
236void
237lsquic_stream_stream_frame_sent (lsquic_stream_t *);
238
239void
240lsquic_stream_reset (lsquic_stream_t *, uint32_t error_code);
241
242void
243lsquic_stream_reset_ext (lsquic_stream_t *, uint32_t error_code, int close);
244
245void
246lsquic_stream_call_on_close (lsquic_stream_t *);
247
248void
249lsquic_stream_shutdown_internal (lsquic_stream_t *);
250
251void
252lsquic_stream_received_goaway (lsquic_stream_t *);
253
254void
255lsquic_stream_acked (lsquic_stream_t *);
256
257#define lsquic_stream_is_closed(s)                                          \
258    (((s)->stream_flags & (STREAM_U_READ_DONE|STREAM_U_WRITE_DONE))         \
259                            == (STREAM_U_READ_DONE|STREAM_U_WRITE_DONE))
260int
261lsquic_stream_update_sfcw (lsquic_stream_t *, uint64_t max_off);
262
263int
264lsquic_stream_set_priority_internal (lsquic_stream_t *, unsigned priority);
265
266/* The following flags are checked to see whether progress was made: */
267#define STREAM_RW_PROG_FLAGS (                                              \
268    STREAM_U_READ_DONE  /* User closed read side of the stream */           \
269   |STREAM_FIN_REACHED  /* User reached FIN.  We check this because it */   \
270                        /*   may have been a result of zero-byte read. */   \
271)
272
273/* Stream progress status is used to judge whether a connection made progress
274 * during Pending RW Queue processing.  We only check for stream read progress,
275 * as the write progress is defined as any new data packetized for sending.
276 */
277struct stream_read_prog_status
278{
279    uint64_t                srps_read_offset;
280    enum stream_flags       srps_flags;
281};
282
283#define lsquic_stream_get_read_prog_status(stream, stats) do {              \
284    (stats)->srps_read_offset = (stream)->read_offset;                      \
285    (stats)->srps_flags       =                                             \
286                        (stream)->stream_flags & STREAM_RW_PROG_FLAGS;      \
287} while (0)
288
289#define lsquic_stream_progress_was_made(stream, stats) (                    \
290    (stats)->srps_read_offset != (stream)->read_offset                      \
291 || (stats)->srps_flags       !=                                            \
292                        ((stream)->stream_flags & STREAM_RW_PROG_FLAGS)     \
293)
294
295#define lsquic_stream_is_critical(stream) (                                 \
296    (stream)->id == LSQUIC_STREAM_HANDSHAKE ||                              \
297    ((stream)->id == LSQUIC_STREAM_HEADERS &&                               \
298        (stream)->stream_flags & STREAM_USE_HEADERS))
299
300size_t
301lsquic_stream_mem_used (const struct lsquic_stream *);
302
303lsquic_cid_t
304lsquic_stream_cid (const struct lsquic_stream *);
305
306#define lsquic_stream_has_data_to_flush(stream) ((stream)->sm_n_buffered > 0)
307
308#endif
309