• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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