2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2012 Tatsuhiro Tsujikawa
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:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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.
25 #ifndef NGHTTP2_STREAM_H
26 #define NGHTTP2_STREAM_H
30 #endif /* HAVE_CONFIG_H */
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"
39 * If local peer is stream initiator:
40 * NGHTTP2_STREAM_OPENING : upon sending request HEADERS
41 * NGHTTP2_STREAM_OPENED : upon receiving response HEADERS
42 * NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM
44 * If remote peer is stream initiator:
45 * NGHTTP2_STREAM_OPENING : upon receiving request HEADERS
46 * NGHTTP2_STREAM_OPENED : upon sending response HEADERS
47 * NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM
51 NGHTTP2_STREAM_INITIAL,
52 /* For stream initiator: request HEADERS has been sent, but response
53 HEADERS has not been received yet. For receiver: request HEADERS
54 has been received, but it does not send response HEADERS yet. */
55 NGHTTP2_STREAM_OPENING,
56 /* For stream initiator: response HEADERS is received. For receiver:
57 response HEADERS is sent. */
58 NGHTTP2_STREAM_OPENED,
59 /* RST_STREAM is received, but somehow we need to keep stream in
61 NGHTTP2_STREAM_CLOSING,
62 /* PUSH_PROMISE is received or sent */
63 NGHTTP2_STREAM_RESERVED,
64 /* Stream is created in this state if it is used as anchor in
67 } nghttp2_stream_state;
70 NGHTTP2_SHUT_NONE = 0,
71 /* Indicates further receptions will be disallowed. */
72 NGHTTP2_SHUT_RD = 0x01,
73 /* Indicates further transmissions will be disallowed. */
74 NGHTTP2_SHUT_WR = 0x02,
75 /* Indicates both further receptions and transmissions will be
77 NGHTTP2_SHUT_RDWR = NGHTTP2_SHUT_RD | NGHTTP2_SHUT_WR
81 NGHTTP2_STREAM_FLAG_NONE = 0,
82 /* Indicates that this stream is pushed stream and not opened
84 NGHTTP2_STREAM_FLAG_PUSH = 0x01,
85 /* Indicates that this stream was closed */
86 NGHTTP2_STREAM_FLAG_CLOSED = 0x02,
87 /* Indicates the item is deferred due to flow control. */
88 NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL = 0x04,
89 /* Indicates the item is deferred by user callback */
90 NGHTTP2_STREAM_FLAG_DEFERRED_USER = 0x08,
91 /* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and
92 NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
93 NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c
95 } nghttp2_stream_flag;
97 /* HTTP related flags to enforce HTTP semantics */
99 NGHTTP2_HTTP_FLAG_NONE = 0,
100 /* header field seen so far */
101 NGHTTP2_HTTP_FLAG__AUTHORITY = 1,
102 NGHTTP2_HTTP_FLAG__PATH = 1 << 1,
103 NGHTTP2_HTTP_FLAG__METHOD = 1 << 2,
104 NGHTTP2_HTTP_FLAG__SCHEME = 1 << 3,
105 /* host is not pseudo header, but we require either host or
107 NGHTTP2_HTTP_FLAG_HOST = 1 << 4,
108 NGHTTP2_HTTP_FLAG__STATUS = 1 << 5,
109 /* required header fields for HTTP request except for CONNECT
111 NGHTTP2_HTTP_FLAG_REQ_HEADERS = NGHTTP2_HTTP_FLAG__METHOD |
112 NGHTTP2_HTTP_FLAG__PATH |
113 NGHTTP2_HTTP_FLAG__SCHEME,
114 NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED = 1 << 6,
115 /* HTTP method flags */
116 NGHTTP2_HTTP_FLAG_METH_CONNECT = 1 << 7,
117 NGHTTP2_HTTP_FLAG_METH_HEAD = 1 << 8,
118 NGHTTP2_HTTP_FLAG_METH_OPTIONS = 1 << 9,
119 NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND = 1 << 10,
120 NGHTTP2_HTTP_FLAG_METH_ALL = NGHTTP2_HTTP_FLAG_METH_CONNECT |
121 NGHTTP2_HTTP_FLAG_METH_HEAD |
122 NGHTTP2_HTTP_FLAG_METH_OPTIONS |
123 NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND,
125 /* path starts with "/" */
126 NGHTTP2_HTTP_FLAG_PATH_REGULAR = 1 << 11,
128 NGHTTP2_HTTP_FLAG_PATH_ASTERISK = 1 << 12,
130 /* "http" or "https" scheme */
131 NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13,
132 /* set if final response is expected */
133 NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14,
134 NGHTTP2_HTTP_FLAG__PROTOCOL = 1 << 15,
137 struct nghttp2_stream {
138 /* Entry for dep_prev->obq */
139 nghttp2_pq_entry pq_entry;
140 /* Priority Queue storing direct descendant (nghttp2_stream). Only
141 streams which itself has some data to send, or has a descendant
142 which has some data to sent. */
144 /* Content-Length of request/response body. -1 if unknown. */
145 int64_t content_length;
146 /* Received body so far */
147 int64_t recv_content_length;
148 /* Base last_cycle for direct descendent streams. */
149 uint64_t descendant_last_cycle;
150 /* Next scheduled time to sent item */
152 /* Next seq used for direct descendant streams */
153 uint64_t descendant_next_seq;
154 /* Secondary key for prioritization to break a tie for cycle. This
155 value is monotonically increased for single parent stream. */
157 /* pointers to form dependency tree. If multiple streams depend on
158 a stream, only one stream (left most) has non-NULL dep_prev which
159 points to the stream it depends on. The remaining streams are
160 linked using sib_prev and sib_next. The stream which has
161 non-NULL dep_prev always NULL sib_prev. The right most stream
162 has NULL sib_next. If this stream is a root of dependency tree,
163 dep_prev and sib_prev are NULL. */
164 nghttp2_stream *dep_prev, *dep_next;
165 nghttp2_stream *sib_prev, *sib_next;
166 /* When stream is kept after closure, it may be kept in doubly
167 linked list pointed by nghttp2_session closed_stream_head.
168 closed_next points to the next stream object if it is the element
170 nghttp2_stream *closed_prev, *closed_next;
171 /* The arbitrary data provided by user for this stream. */
172 void *stream_user_data;
174 nghttp2_outbound_item *item;
175 /* Last written length of frame payload */
176 size_t last_writelen;
179 /* Current remote window size. This value is computed against the
180 current initial window size of remote endpoint. */
181 int32_t remote_window_size;
182 /* Keep track of the number of bytes received without
183 WINDOW_UPDATE. This could be negative after submitting negative
184 value to WINDOW_UPDATE */
185 int32_t recv_window_size;
186 /* The number of bytes consumed by the application and now is
187 subject to WINDOW_UPDATE. This is only used when auto
188 WINDOW_UPDATE is turned off. */
189 int32_t consumed_size;
190 /* The amount of recv_window_size cut using submitting negative
191 value to WINDOW_UPDATE */
192 int32_t recv_reduction;
193 /* window size for local flow control. It is initially set to
194 NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by
195 submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */
196 int32_t local_window_size;
197 /* weight of this stream */
199 /* This is unpaid penalty (offset) when calculating cycle. */
200 uint32_t pending_penalty;
201 /* sum of weight of direct descendants */
202 int32_t sum_dep_weight;
203 nghttp2_stream_state state;
204 /* status code from remote server */
206 /* Bitwise OR of zero or more nghttp2_http_flag values */
208 /* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */
210 /* Bitwise OR of zero or more nghttp2_shut_flag values */
212 /* Nonzero if this stream has been queued to stream pointed by
213 dep_prev. We maintain the invariant that if a stream is queued,
214 then its ancestors, except for root, are also queued. This
215 invariant may break in fatal error condition. */
217 /* This flag is used to reduce excessive queuing of WINDOW_UPDATE to
218 this stream. The nonzero does not necessarily mean WINDOW_UPDATE
220 uint8_t window_update_queued;
223 void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
224 uint8_t flags, nghttp2_stream_state initial_state,
225 int32_t weight, int32_t remote_initial_window_size,
226 int32_t local_initial_window_size,
227 void *stream_user_data, nghttp2_mem *mem);
229 void nghttp2_stream_free(nghttp2_stream *stream);
232 * Disallow either further receptions or transmissions, or both.
233 * |flag| is bitwise OR of one or more of nghttp2_shut_flag.
235 void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag);
238 * Defer |stream->item|. We won't call this function in the situation
239 * where |stream->item| == NULL. The |flags| is bitwise OR of zero or
240 * more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and
241 * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL. The |flags| indicates
242 * the reason of this action.
244 * This function returns 0 if it succeeds, or one of the following
245 * negative error codes:
250 int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);
253 * Put back deferred data in this stream to active state. The |flags|
254 * are one or more of bitwise OR of the following values:
255 * NGHTTP2_STREAM_FLAG_DEFERRED_USER and
256 * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are
257 * cleared if they are set. So even if this function is called, if
258 * one of flag is still set, data does not become active.
260 * This function returns 0 if it succeeds, or one of the following
261 * negative error codes:
266 int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags);
269 * Returns nonzero if item is deferred by whatever reason.
271 int nghttp2_stream_check_deferred_item(nghttp2_stream *stream);
274 * Returns nonzero if item is deferred by flow control.
276 int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream);
279 * Updates the remote window size with the new value
280 * |new_initial_window_size|. The |old_initial_window_size| is used to
281 * calculate the current window size.
283 * This function returns 0 if it succeeds or -1. The failure is due to
286 int nghttp2_stream_update_remote_initial_window_size(
287 nghttp2_stream *stream, int32_t new_initial_window_size,
288 int32_t old_initial_window_size);
291 * Updates the local window size with the new value
292 * |new_initial_window_size|. The |old_initial_window_size| is used to
293 * calculate the current window size.
295 * This function returns 0 if it succeeds or -1. The failure is due to
298 int nghttp2_stream_update_local_initial_window_size(
299 nghttp2_stream *stream, int32_t new_initial_window_size,
300 int32_t old_initial_window_size);
303 * Call this function if promised stream |stream| is replied with
304 * HEADERS. This function makes the state of the |stream| to
305 * NGHTTP2_STREAM_OPENED.
307 void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream);
310 * Returns nonzero if |target| is an ancestor of |stream|.
312 int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
313 nghttp2_stream *target);
316 * Computes distributed weight of a stream of the |weight| under the
317 * |stream| if |stream| is removed from a dependency tree.
319 int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
323 * Makes the |stream| depend on the |dep_stream|. This dependency is
324 * exclusive. All existing direct descendants of |dep_stream| become
325 * the descendants of the |stream|. This function assumes
326 * |stream->item| is NULL.
328 * This function returns 0 if it succeeds, or one of the following
329 * negative error codes:
334 int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
335 nghttp2_stream *stream);
338 * Makes the |stream| depend on the |dep_stream|. This dependency is
339 * not exclusive. This function assumes |stream->item| is NULL.
341 void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream);
344 * Removes the |stream| from the current dependency tree. This
345 * function assumes |stream->item| is NULL.
347 int nghttp2_stream_dep_remove(nghttp2_stream *stream);
350 * Attaches |item| to |stream|.
352 * This function returns 0 if it succeeds, or one of the following
353 * negative error codes:
358 int nghttp2_stream_attach_item(nghttp2_stream *stream,
359 nghttp2_outbound_item *item);
362 * Detaches |stream->item|. This function does not free
363 * |stream->item|. The caller must free it.
365 * This function returns 0 if it succeeds, or one of the following
366 * negative error codes:
371 int nghttp2_stream_detach_item(nghttp2_stream *stream);
374 * Makes the |stream| depend on the |dep_stream|. This dependency is
377 * This function returns 0 if it succeeds, or one of the following
378 * negative error codes:
383 int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
384 nghttp2_stream *stream);
387 * Makes the |stream| depend on the |dep_stream|. This dependency is
390 * This function returns 0 if it succeeds, or one of the following
391 * negative error codes:
396 int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
397 nghttp2_stream *stream);
400 * Removes subtree whose root stream is |stream|. The
401 * effective_weight of streams in removed subtree is not updated.
403 * This function returns 0 if it succeeds, or one of the following
404 * negative error codes:
409 void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
412 * Returns nonzero if |stream| is in any dependency tree.
414 int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);
417 * Schedules transmission of |stream|'s item, assuming stream->item is
418 * attached, and stream->last_writelen was updated.
420 void nghttp2_stream_reschedule(nghttp2_stream *stream);
423 * Changes |stream|'s weight to |weight|. If |stream| is queued, it
424 * will be rescheduled based on new weight.
426 void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight);
429 * Returns a stream which has highest priority, updating
430 * descendant_last_cycle of selected stream's ancestors.
432 nghttp2_outbound_item *
433 nghttp2_stream_next_outbound_item(nghttp2_stream *stream);
435 #endif /* NGHTTP2_STREAM */