tizen 2.4 release
[external/nghttp2.git] / lib / nghttp2_stream.h
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2012 Tatsuhiro Tsujikawa
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 NGHTTP2_STREAM_H
26 #define NGHTTP2_STREAM_H
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif /* HAVE_CONFIG_H */
31
32 #include <nghttp2/nghttp2.h>
33 #include "nghttp2_outbound_item.h"
34 #include "nghttp2_map.h"
35 #include "nghttp2_pq.h"
36 #include "nghttp2_int.h"
37
38 /*
39  * Maximum number of streams in one dependency tree.
40  */
41 #define NGHTTP2_MAX_DEP_TREE_LENGTH 100
42
43 /*
44  * If local peer is stream initiator:
45  * NGHTTP2_STREAM_OPENING : upon sending request HEADERS
46  * NGHTTP2_STREAM_OPENED : upon receiving response HEADERS
47  * NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM
48  *
49  * If remote peer is stream initiator:
50  * NGHTTP2_STREAM_OPENING : upon receiving request HEADERS
51  * NGHTTP2_STREAM_OPENED : upon sending response HEADERS
52  * NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM
53  */
54 typedef enum {
55   /* Initial state */
56   NGHTTP2_STREAM_INITIAL,
57   /* For stream initiator: request HEADERS has been sent, but response
58      HEADERS has not been received yet.  For receiver: request HEADERS
59      has been received, but it does not send response HEADERS yet. */
60   NGHTTP2_STREAM_OPENING,
61   /* For stream initiator: response HEADERS is received. For receiver:
62      response HEADERS is sent. */
63   NGHTTP2_STREAM_OPENED,
64   /* RST_STREAM is received, but somehow we need to keep stream in
65      memory. */
66   NGHTTP2_STREAM_CLOSING,
67   /* PUSH_PROMISE is received or sent */
68   NGHTTP2_STREAM_RESERVED,
69   /* Stream is created in this state if it is used as anchor in
70      dependency tree. */
71   NGHTTP2_STREAM_IDLE
72 } nghttp2_stream_state;
73
74 typedef enum {
75   NGHTTP2_SHUT_NONE = 0,
76   /* Indicates further receptions will be disallowed. */
77   NGHTTP2_SHUT_RD = 0x01,
78   /* Indicates further transmissions will be disallowed. */
79   NGHTTP2_SHUT_WR = 0x02,
80   /* Indicates both further receptions and transmissions will be
81      disallowed. */
82   NGHTTP2_SHUT_RDWR = NGHTTP2_SHUT_RD | NGHTTP2_SHUT_WR
83 } nghttp2_shut_flag;
84
85 typedef enum {
86   NGHTTP2_STREAM_FLAG_NONE = 0,
87   /* Indicates that this stream is pushed stream */
88   NGHTTP2_STREAM_FLAG_PUSH = 0x01,
89   /* Indicates that this stream was closed */
90   NGHTTP2_STREAM_FLAG_CLOSED = 0x02,
91   /* Indicates the item is deferred due to flow control. */
92   NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL = 0x04,
93   /* Indicates the item is deferred by user callback */
94   NGHTTP2_STREAM_FLAG_DEFERRED_USER = 0x08,
95   /* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and
96      NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
97   NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c
98
99 } nghttp2_stream_flag;
100
101 typedef enum {
102   NGHTTP2_STREAM_DPRI_NONE = 0,
103   NGHTTP2_STREAM_DPRI_NO_ITEM = 0x01,
104   NGHTTP2_STREAM_DPRI_TOP = 0x02,
105   NGHTTP2_STREAM_DPRI_REST = 0x04
106 } nghttp2_stream_dpri;
107
108 struct nghttp2_stream_roots;
109
110 typedef struct nghttp2_stream_roots nghttp2_stream_roots;
111
112 struct nghttp2_stream;
113
114 typedef struct nghttp2_stream nghttp2_stream;
115
116 struct nghttp2_stream {
117   /* Intrusive Map */
118   nghttp2_map_entry map_entry;
119   /* pointers to form dependency tree.  If multiple streams depend on
120      a stream, only one stream (left most) has non-NULL dep_prev which
121      points to the stream it depends on. The remaining streams are
122      linked using sib_prev and sib_next.  The stream which has
123      non-NULL dep_prev always NULL sib_prev.  The right most stream
124      has NULL sib_next.  If this stream is a root of dependency tree,
125      dep_prev and sib_prev are NULL. */
126   nghttp2_stream *dep_prev, *dep_next;
127   nghttp2_stream *sib_prev, *sib_next;
128   /* pointers to track dependency tree root streams.  This is
129      doubly-linked list and first element is pointed by
130      roots->head. */
131   nghttp2_stream *root_prev, *root_next;
132   /* When stream is kept after closure, it may be kept in doubly
133      linked list pointed by nghttp2_session closed_stream_head.
134      closed_next points to the next stream object if it is the element
135      of the list. */
136   nghttp2_stream *closed_prev, *closed_next;
137   /* pointer to roots, which tracks dependency tree roots */
138   nghttp2_stream_roots *roots;
139   /* The arbitrary data provided by user for this stream. */
140   void *stream_user_data;
141   /* Item to send */
142   nghttp2_outbound_item *item;
143   /* stream ID */
144   int32_t stream_id;
145   /* categorized priority of this stream.  Only stream bearing
146      NGHTTP2_STREAM_DPRI_TOP can send item. */
147   nghttp2_stream_dpri dpri;
148   /* the number of streams in subtree */
149   size_t num_substreams;
150   /* Current remote window size. This value is computed against the
151      current initial window size of remote endpoint. */
152   int32_t remote_window_size;
153   /* Keep track of the number of bytes received without
154      WINDOW_UPDATE. This could be negative after submitting negative
155      value to WINDOW_UPDATE */
156   int32_t recv_window_size;
157   /* The number of bytes consumed by the application and now is
158      subject to WINDOW_UPDATE.  This is only used when auto
159      WINDOW_UPDATE is turned off. */
160   int32_t consumed_size;
161   /* The amount of recv_window_size cut using submitting negative
162      value to WINDOW_UPDATE */
163   int32_t recv_reduction;
164   /* window size for local flow control. It is initially set to
165      NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by
166      submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */
167   int32_t local_window_size;
168   /* weight of this stream */
169   int32_t weight;
170   /* effective weight of this stream in belonging dependency tree */
171   int32_t effective_weight;
172   /* sum of weight (not effective_weight) of direct descendants */
173   int32_t sum_dep_weight;
174   /* sum of weight of direct descendants which have at least one
175      descendant with dpri == NGHTTP2_STREAM_DPRI_TOP.  We use this
176      value to calculate effective weight. */
177   int32_t sum_norest_weight;
178   /* sum of weight of direct descendants whose dpri value is
179      NGHTTP2_STREAM_DPRI_TOP */
180   int32_t sum_top_weight;
181   nghttp2_stream_state state;
182   /* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */
183   uint8_t flags;
184   /* Bitwise OR of zero or more nghttp2_shut_flag values */
185   uint8_t shut_flags;
186 };
187
188 void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
189                          uint8_t flags, nghttp2_stream_state initial_state,
190                          int32_t weight, nghttp2_stream_roots *roots,
191                          int32_t remote_initial_window_size,
192                          int32_t local_initial_window_size,
193                          void *stream_user_data);
194
195 void nghttp2_stream_free(nghttp2_stream *stream);
196
197 /*
198  * Disallow either further receptions or transmissions, or both.
199  * |flag| is bitwise OR of one or more of nghttp2_shut_flag.
200  */
201 void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag);
202
203 /*
204  * Defer |stream->item|.  We won't call this function in the situation
205  * where |stream->item| == NULL.  The |flags| is bitwise OR of zero or
206  * more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and
207  * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL.  The |flags| indicates
208  * the reason of this action.
209  *
210  * This function returns 0 if it succeeds, or one of the following
211  * negative error codes:
212  *
213  * NGHTTP2_ERR_NOMEM
214  *     Out of memory
215  */
216 int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags,
217                               nghttp2_session *session);
218
219 /*
220  * Put back deferred data in this stream to active state.  The |flags|
221  * are one or more of bitwise OR of the following values:
222  * NGHTTP2_STREAM_FLAG_DEFERRED_USER and
223  * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are
224  * cleared if they are set.  So even if this function is called, if
225  * one of flag is still set, data does not become active.
226  */
227 int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags,
228                                         nghttp2_session *session);
229
230 /*
231  * Returns nonzero if item is deferred by whatever reason.
232  */
233 int nghttp2_stream_check_deferred_item(nghttp2_stream *stream);
234
235 /*
236  * Returns nonzero if item is deferred by flow control.
237  */
238 int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream);
239
240 /*
241  * Updates the remote window size with the new value
242  * |new_initial_window_size|. The |old_initial_window_size| is used to
243  * calculate the current window size.
244  *
245  * This function returns 0 if it succeeds or -1. The failure is due to
246  * overflow.
247  */
248 int nghttp2_stream_update_remote_initial_window_size(
249     nghttp2_stream *stream, int32_t new_initial_window_size,
250     int32_t old_initial_window_size);
251
252 /*
253  * Updates the local window size with the new value
254  * |new_initial_window_size|. The |old_initial_window_size| is used to
255  * calculate the current window size.
256  *
257  * This function returns 0 if it succeeds or -1. The failure is due to
258  * overflow.
259  */
260 int nghttp2_stream_update_local_initial_window_size(
261     nghttp2_stream *stream, int32_t new_initial_window_size,
262     int32_t old_initial_window_size);
263
264 /*
265  * Call this function if promised stream |stream| is replied with
266  * HEADERS.  This function makes the state of the |stream| to
267  * NGHTTP2_STREAM_OPENED.
268  */
269 void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream);
270
271 /*
272  * Returns the stream positioned in root of the dependency tree the
273  * |stream| belongs to.
274  */
275 nghttp2_stream *nghttp2_stream_get_dep_root(nghttp2_stream *stream);
276
277 /*
278  * Returns nonzero if |target| is found in subtree of |stream|.
279  */
280 int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream,
281                                     nghttp2_stream *target);
282
283 /*
284  * Computes distributed weight of a stream of the |weight| under the
285  * |stream| if |stream| is removed from a dependency tree.  The result
286  * is computed using stream->weight rather than
287  * stream->effective_weight.
288  */
289 int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
290                                               int32_t weight);
291
292 /*
293  * Computes effective weight of a stream of the |weight| under the
294  * |stream|.  The result is computed using stream->effective_weight
295  * rather than stream->weight.  This function is used to determine
296  * weight in dependency tree.
297  */
298 int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream,
299                                                         int32_t weight);
300
301 /*
302  * Makes the |stream| depend on the |dep_stream|.  This dependency is
303  * exclusive.  All existing direct descendants of |dep_stream| become
304  * the descendants of the |stream|.  This function assumes
305  * |stream->data| is NULL and no dpri members are changed in this
306  * dependency tree.
307  */
308 void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
309                                nghttp2_stream *stream);
310
311 /*
312  * Makes the |stream| depend on the |dep_stream|.  This dependency is
313  * not exclusive.  This function assumes |stream->data| is NULL and no
314  * dpri members are changed in this dependency tree.
315  */
316 void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream);
317
318 /*
319  * Removes the |stream| from the current dependency tree.  This
320  * function assumes |stream->data| is NULL.
321  */
322 void nghttp2_stream_dep_remove(nghttp2_stream *stream);
323
324 /*
325  * Attaches |item| to |stream|.  Updates dpri members in this
326  * dependency tree.
327  *
328  * This function returns 0 if it succeeds, or one of the following
329  * negative error codes:
330  *
331  * NGHTTP2_ERR_NOMEM
332  *     Out of memory
333  */
334 int nghttp2_stream_attach_item(nghttp2_stream *stream,
335                                nghttp2_outbound_item *item,
336                                nghttp2_session *session);
337
338 /*
339  * Detaches |stream->item|.  Updates dpri members in this dependency
340  * tree.  This function does not free |stream->item|.  The caller must
341  * free it.
342  *
343  * This function returns 0 if it succeeds, or one of the following
344  * negative error codes:
345  *
346  * NGHTTP2_ERR_NOMEM
347  *     Out of memory
348  */
349 int nghttp2_stream_detach_item(nghttp2_stream *stream,
350                                nghttp2_session *session);
351
352 /*
353  * Makes the |stream| depend on the |dep_stream|.  This dependency is
354  * exclusive.  Updates dpri members in this dependency tree.
355  *
356  * This function returns 0 if it succeeds, or one of the following
357  * negative error codes:
358  *
359  * NGHTTP2_ERR_NOMEM
360  *     Out of memory
361  */
362 int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
363                                       nghttp2_stream *stream,
364                                       nghttp2_session *session);
365
366 /*
367  * Makes the |stream| depend on the |dep_stream|.  This dependency is
368  * not exclusive.  Updates dpri members in this dependency tree.
369  *
370  * This function returns 0 if it succeeds, or one of the following
371  * negative error codes:
372  *
373  * NGHTTP2_ERR_NOMEM
374  *     Out of memory
375  */
376 int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
377                                    nghttp2_stream *stream,
378                                    nghttp2_session *session);
379
380 /*
381  * Removes subtree whose root stream is |stream|.  Removing subtree
382  * does not change dpri values.  The effective_weight of streams in
383  * removed subtree is not updated.
384  *
385  * This function returns 0 if it succeeds, or one of the following
386  * negative error codes:
387  *
388  * NGHTTP2_ERR_NOMEM
389  *     Out of memory
390  */
391 void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
392
393 /*
394  * Makes the |stream| as root.  Updates dpri members in this
395  * dependency tree.
396  *
397  * This function returns 0 if it succeeds, or one of the following
398  * negative error codes:
399  *
400  * NGHTTP2_ERR_NOMEM
401  *     Out of memory
402  */
403 int nghttp2_stream_dep_make_root(nghttp2_stream *stream,
404                                  nghttp2_session *session);
405
406 /*
407  * Makes the |stream| as root and all existing root streams become
408  * direct children of |stream|.
409  *
410  * This function returns 0 if it succeeds, or one of the following
411  * negative error codes:
412  *
413  * NGHTTP2_ERR_NOMEM
414  *     Out of memory
415  */
416 int
417 nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream,
418                                                     nghttp2_session *session);
419
420 /*
421  * Returns nonzero if |stream| is in any dependency tree.
422  */
423 int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);
424
425 struct nghttp2_stream_roots {
426   nghttp2_stream *head;
427
428   int32_t num_streams;
429 };
430
431 void nghttp2_stream_roots_init(nghttp2_stream_roots *roots);
432
433 void nghttp2_stream_roots_free(nghttp2_stream_roots *roots);
434
435 void nghttp2_stream_roots_add(nghttp2_stream_roots *roots,
436                               nghttp2_stream *stream);
437
438 void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots,
439                                  nghttp2_stream *stream);
440
441 void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots);
442
443 #endif /* NGHTTP2_STREAM */