lsquic_stream.h revision c51ce338
1/* Copyright (c) 2017 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