1 /* 2 * nghttp3 3 * 4 * Copyright (c) 2019 nghttp3 contributors 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #ifndef NGHTTP3_STREAM_H 26 #define NGHTTP3_STREAM_H 27 28 #ifdef HAVE_CONFIG_H 29 # include <config.h> 30 #endif /* HAVE_CONFIG_H */ 31 32 #include <nghttp3/nghttp3.h> 33 34 #include "nghttp3_map.h" 35 #include "nghttp3_tnode.h" 36 #include "nghttp3_ringbuf.h" 37 #include "nghttp3_buf.h" 38 #include "nghttp3_frame.h" 39 #include "nghttp3_qpack.h" 40 #include "nghttp3_objalloc.h" 41 42 #define NGHTTP3_STREAM_MIN_CHUNK_SIZE 256 43 44 /* NGHTTP3_MIN_UNSENT_BYTES is the minimum unsent bytes which is large 45 enough to fill outgoing single QUIC packet. */ 46 #define NGHTTP3_MIN_UNSENT_BYTES 4096 47 48 /* NGHTTP3_STREAM_MIN_WRITELEN is the minimum length of write to cause 49 the stream to reschedule. */ 50 #define NGHTTP3_STREAM_MIN_WRITELEN 800 51 52 /* nghttp3_stream_type is unidirectional stream type. */ 53 typedef enum nghttp3_stream_type { 54 NGHTTP3_STREAM_TYPE_CONTROL = 0x00, 55 NGHTTP3_STREAM_TYPE_PUSH = 0x01, 56 NGHTTP3_STREAM_TYPE_QPACK_ENCODER = 0x02, 57 NGHTTP3_STREAM_TYPE_QPACK_DECODER = 0x03, 58 NGHTTP3_STREAM_TYPE_UNKNOWN = UINT64_MAX, 59 } nghttp3_stream_type; 60 61 typedef enum nghttp3_ctrl_stream_state { 62 NGHTTP3_CTRL_STREAM_STATE_FRAME_TYPE, 63 NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH, 64 NGHTTP3_CTRL_STREAM_STATE_SETTINGS, 65 NGHTTP3_CTRL_STREAM_STATE_GOAWAY, 66 NGHTTP3_CTRL_STREAM_STATE_MAX_PUSH_ID, 67 NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME, 68 NGHTTP3_CTRL_STREAM_STATE_SETTINGS_ID, 69 NGHTTP3_CTRL_STREAM_STATE_SETTINGS_VALUE, 70 NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE_PRI_ELEM_ID, 71 NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE, 72 } nghttp3_ctrl_stream_state; 73 74 typedef enum nghttp3_req_stream_state { 75 NGHTTP3_REQ_STREAM_STATE_FRAME_TYPE, 76 NGHTTP3_REQ_STREAM_STATE_FRAME_LENGTH, 77 NGHTTP3_REQ_STREAM_STATE_DATA, 78 NGHTTP3_REQ_STREAM_STATE_HEADERS, 79 NGHTTP3_REQ_STREAM_STATE_IGN_FRAME, 80 NGHTTP3_REQ_STREAM_STATE_IGN_REST, 81 } nghttp3_req_stream_state; 82 83 typedef struct nghttp3_varint_read_state { 84 int64_t acc; 85 size_t left; 86 } nghttp3_varint_read_state; 87 88 typedef struct nghttp3_stream_read_state { 89 nghttp3_varint_read_state rvint; 90 nghttp3_frame fr; 91 int state; 92 int64_t left; 93 } nghttp3_stream_read_state; 94 95 /* NGHTTP3_STREAM_FLAG_NONE indicates that no flag is set. */ 96 #define NGHTTP3_STREAM_FLAG_NONE 0x0000u 97 /* NGHTTP3_STREAM_FLAG_TYPE_IDENTIFIED is set when a unidirectional 98 stream type is identified. */ 99 #define NGHTTP3_STREAM_FLAG_TYPE_IDENTIFIED 0x0001u 100 /* NGHTTP3_STREAM_FLAG_FC_BLOCKED indicates that stream is blocked by 101 QUIC flow control. */ 102 #define NGHTTP3_STREAM_FLAG_FC_BLOCKED 0x0002u 103 /* NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED indicates that application is 104 temporarily unable to provide data. */ 105 #define NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED 0x0004u 106 /* NGHTTP3_STREAM_FLAG_WRITE_END_STREAM indicates that application 107 finished to feed outgoing data. */ 108 #define NGHTTP3_STREAM_FLAG_WRITE_END_STREAM 0x0008u 109 /* NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED indicates that stream is 110 blocked due to QPACK decoding. */ 111 #define NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED 0x0010u 112 /* NGHTTP3_STREAM_FLAG_READ_EOF indicates that remote endpoint sent 113 fin. */ 114 #define NGHTTP3_STREAM_FLAG_READ_EOF 0x0020u 115 /* NGHTTP3_STREAM_FLAG_CLOSED indicates that QUIC stream was closed. 116 nghttp3_stream object can still alive because it might be blocked 117 by QPACK decoder. */ 118 #define NGHTTP3_STREAM_FLAG_CLOSED 0x0040u 119 /* NGHTTP3_STREAM_FLAG_SHUT_WR indicates that any further write 120 operation to a stream is prohibited. */ 121 #define NGHTTP3_STREAM_FLAG_SHUT_WR 0x0100u 122 /* NGHTTP3_STREAM_FLAG_SHUT_RD indicates that a read-side stream is 123 closed abruptly and any incoming and pending stream data is just 124 discarded for a stream. */ 125 #define NGHTTP3_STREAM_FLAG_SHUT_RD 0x0200u 126 /* NGHTTP3_STREAM_FLAG_SERVER_PRIORITY_SET indicates that server 127 overrides stream priority. */ 128 #define NGHTTP3_STREAM_FLAG_SERVER_PRIORITY_SET 0x0400u 129 /* NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED indicates that server 130 received PRIORITY_UPDATE frame for this stream. */ 131 #define NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED 0x0800u 132 /* NGHTTP3_STREAM_FLAG_HTTP_ERROR indicates that 133 NGHTTP3_ERR_MALFORMED_HTTP_HEADER error is encountered while 134 processing incoming HTTP fields. */ 135 #define NGHTTP3_STREAM_FLAG_HTTP_ERROR 0x1000u 136 137 typedef enum nghttp3_stream_http_state { 138 NGHTTP3_HTTP_STATE_NONE, 139 NGHTTP3_HTTP_STATE_REQ_INITIAL, 140 NGHTTP3_HTTP_STATE_REQ_BEGIN, 141 NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN, 142 NGHTTP3_HTTP_STATE_REQ_HEADERS_END, 143 NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN, 144 NGHTTP3_HTTP_STATE_REQ_DATA_END, 145 NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN, 146 NGHTTP3_HTTP_STATE_REQ_TRAILERS_END, 147 NGHTTP3_HTTP_STATE_REQ_END, 148 NGHTTP3_HTTP_STATE_RESP_INITIAL, 149 NGHTTP3_HTTP_STATE_RESP_BEGIN, 150 NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN, 151 NGHTTP3_HTTP_STATE_RESP_HEADERS_END, 152 NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN, 153 NGHTTP3_HTTP_STATE_RESP_DATA_END, 154 NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN, 155 NGHTTP3_HTTP_STATE_RESP_TRAILERS_END, 156 NGHTTP3_HTTP_STATE_RESP_END, 157 } nghttp3_stream_http_state; 158 159 typedef enum nghttp3_stream_http_event { 160 NGHTTP3_HTTP_EVENT_DATA_BEGIN, 161 NGHTTP3_HTTP_EVENT_DATA_END, 162 NGHTTP3_HTTP_EVENT_HEADERS_BEGIN, 163 NGHTTP3_HTTP_EVENT_HEADERS_END, 164 NGHTTP3_HTTP_EVENT_MSG_END, 165 } nghttp3_stream_http_event; 166 167 typedef struct nghttp3_stream nghttp3_stream; 168 169 /* 170 * nghttp3_stream_acked_data is a callback function which is invoked 171 * when data sent on stream denoted by |stream_id| supplied from 172 * application is acknowledged by remote endpoint. The number of 173 * bytes acknowledged is given in |datalen|. 174 * 175 * The implementation of this callback must return 0 if it succeeds. 176 * Returning NGHTTP3_ERR_CALLBACK_FAILURE will return to the caller 177 * immediately. Any values other than 0 is treated as 178 * NGHTTP3_ERR_CALLBACK_FAILURE. 179 */ 180 typedef int (*nghttp3_stream_acked_data)(nghttp3_stream *stream, 181 int64_t stream_id, uint64_t datalen, 182 void *user_data); 183 184 typedef struct nghttp3_stream_callbacks { 185 nghttp3_stream_acked_data acked_data; 186 } nghttp3_stream_callbacks; 187 188 typedef struct nghttp3_http_state { 189 /* status_code is HTTP status code received. This field is used 190 if connection is initialized as client. */ 191 int32_t status_code; 192 /* content_length is the value of received content-length header 193 field. */ 194 int64_t content_length; 195 /* recv_content_length is the number of body bytes received so 196 far. */ 197 int64_t recv_content_length; 198 uint32_t flags; 199 /* pri is a stream priority produced by nghttp3_pri_to_uint8. */ 200 uint8_t pri; 201 } nghttp3_http_state; 202 203 struct nghttp3_stream { 204 union { 205 struct { 206 const nghttp3_mem *mem; 207 nghttp3_objalloc *out_chunk_objalloc; 208 nghttp3_objalloc *stream_objalloc; 209 nghttp3_tnode node; 210 nghttp3_pq_entry qpack_blocked_pe; 211 nghttp3_stream_callbacks callbacks; 212 nghttp3_ringbuf frq; 213 nghttp3_ringbuf chunks; 214 nghttp3_ringbuf outq; 215 /* inq stores the stream raw data which cannot be read because 216 stream is blocked by QPACK decoder. */ 217 nghttp3_ringbuf inq; 218 nghttp3_qpack_stream_context qpack_sctx; 219 /* conn is a reference to underlying connection. It could be NULL 220 if stream is not a request stream. */ 221 nghttp3_conn *conn; 222 void *user_data; 223 /* unsent_bytes is the number of bytes in outq not written yet */ 224 uint64_t unsent_bytes; 225 /* outq_idx is an index into outq where next write is made. */ 226 size_t outq_idx; 227 /* outq_offset is write offset relative to the element at outq_idx 228 in outq. */ 229 uint64_t outq_offset; 230 /* ack_offset is offset acknowledged by peer relative to the first 231 element in outq. */ 232 uint64_t ack_offset; 233 /* ack_done is the number of bytes notified to an application that 234 they are acknowledged inside the first outq element if it is of 235 type NGHTTP3_BUF_TYPE_ALIEN. */ 236 uint64_t ack_done; 237 uint64_t unscheduled_nwrite; 238 nghttp3_stream_type type; 239 nghttp3_stream_read_state rstate; 240 /* error_code indicates the reason of closure of this stream. */ 241 uint64_t error_code; 242 243 struct { 244 uint64_t offset; 245 nghttp3_stream_http_state hstate; 246 } tx; 247 248 struct { 249 nghttp3_stream_http_state hstate; 250 nghttp3_http_state http; 251 } rx; 252 253 uint16_t flags; 254 }; 255 256 nghttp3_opl_entry oplent; 257 }; 258 }; 259 260 nghttp3_objalloc_def(stream, nghttp3_stream, oplent); 261 262 typedef struct nghttp3_frame_entry { 263 nghttp3_frame fr; 264 union { 265 struct { 266 nghttp3_settings *local_settings; 267 } settings; 268 struct { 269 nghttp3_data_reader dr; 270 } data; 271 } aux; 272 } nghttp3_frame_entry; 273 274 int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id, 275 uint64_t seq, const nghttp3_stream_callbacks *callbacks, 276 nghttp3_objalloc *out_chunk_objalloc, 277 nghttp3_objalloc *stream_objalloc, 278 const nghttp3_mem *mem); 279 280 void nghttp3_stream_del(nghttp3_stream *stream); 281 282 void nghttp3_varint_read_state_reset(nghttp3_varint_read_state *rvint); 283 284 void nghttp3_stream_read_state_reset(nghttp3_stream_read_state *rstate); 285 286 nghttp3_ssize nghttp3_read_varint(nghttp3_varint_read_state *rvint, 287 const uint8_t *src, size_t srclen, int fin); 288 289 int nghttp3_stream_frq_add(nghttp3_stream *stream, 290 const nghttp3_frame_entry *frent); 291 292 int nghttp3_stream_fill_outq(nghttp3_stream *stream); 293 294 int nghttp3_stream_write_stream_type(nghttp3_stream *stream); 295 296 nghttp3_ssize nghttp3_stream_writev(nghttp3_stream *stream, int *pfin, 297 nghttp3_vec *vec, size_t veccnt); 298 299 int nghttp3_stream_write_qpack_decoder_stream(nghttp3_stream *stream); 300 301 int nghttp3_stream_outq_is_full(nghttp3_stream *stream); 302 303 int nghttp3_stream_outq_add(nghttp3_stream *stream, 304 const nghttp3_typed_buf *tbuf); 305 306 int nghttp3_stream_write_headers(nghttp3_stream *stream, 307 nghttp3_frame_entry *frent); 308 309 int nghttp3_stream_write_header_block(nghttp3_stream *stream, 310 nghttp3_qpack_encoder *qenc, 311 nghttp3_stream *qenc_stream, 312 nghttp3_buf *rbuf, nghttp3_buf *ebuf, 313 int64_t frame_type, const nghttp3_nv *nva, 314 size_t nvlen); 315 316 int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof, 317 nghttp3_frame_entry *frent); 318 319 int nghttp3_stream_write_settings(nghttp3_stream *stream, 320 nghttp3_frame_entry *frent); 321 322 int nghttp3_stream_write_goaway(nghttp3_stream *stream, 323 nghttp3_frame_entry *frent); 324 325 int nghttp3_stream_write_priority_update(nghttp3_stream *stream, 326 nghttp3_frame_entry *frent); 327 328 int nghttp3_stream_ensure_chunk(nghttp3_stream *stream, size_t need); 329 330 nghttp3_buf *nghttp3_stream_get_chunk(nghttp3_stream *stream); 331 332 int nghttp3_stream_is_blocked(nghttp3_stream *stream); 333 334 int nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n); 335 336 /* 337 * nghttp3_stream_outq_write_done returns nonzero if all contents in 338 * outq have been written. 339 */ 340 int nghttp3_stream_outq_write_done(nghttp3_stream *stream); 341 342 int nghttp3_stream_add_ack_offset(nghttp3_stream *stream, uint64_t n); 343 344 /* 345 * nghttp3_stream_is_active returns nonzero if |stream| is active. In 346 * other words, it has something to send. This function does not take 347 * into account its descendants. 348 */ 349 int nghttp3_stream_is_active(nghttp3_stream *stream); 350 351 /* 352 * nghttp3_stream_require_schedule returns nonzero if |stream| should 353 * be scheduled. In other words, |stream| or its descendants have 354 * something to send. 355 */ 356 int nghttp3_stream_require_schedule(nghttp3_stream *stream); 357 358 int nghttp3_stream_buffer_data(nghttp3_stream *stream, const uint8_t *src, 359 size_t srclen); 360 361 size_t nghttp3_stream_get_buffered_datalen(nghttp3_stream *stream); 362 363 int nghttp3_stream_ensure_qpack_stream_context(nghttp3_stream *stream); 364 365 void nghttp3_stream_delete_qpack_stream_context(nghttp3_stream *stream); 366 367 int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream, 368 nghttp3_stream_http_event event); 369 370 int nghttp3_stream_empty_headers_allowed(nghttp3_stream *stream); 371 372 /* 373 * nghttp3_stream_uni returns nonzero if stream identified by 374 * |stream_id| is unidirectional. 375 */ 376 int nghttp3_stream_uni(int64_t stream_id); 377 378 /* 379 * nghttp3_client_stream_bidi returns nonzero if stream identified by 380 * |stream_id| is client initiated bidirectional stream. 381 */ 382 int nghttp3_client_stream_bidi(int64_t stream_id); 383 384 /* 385 * nghttp3_client_stream_uni returns nonzero if stream identified by 386 * |stream_id| is client initiated unidirectional stream. 387 */ 388 int nghttp3_client_stream_uni(int64_t stream_id); 389 390 /* 391 * nghttp3_server_stream_uni returns nonzero if stream identified by 392 * |stream_id| is server initiated unidirectional stream. 393 */ 394 int nghttp3_server_stream_uni(int64_t stream_id); 395 396 #endif /* NGHTTP3_STREAM_H */ 397