Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.h @ 6246:257b51c37c5a
The HTTP/2 implementation (RFC 7240, 7241).
The SPDY support is removed, as it's incompatible with the new module.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Fri, 11 Sep 2015 20:13:06 +0300 |
parents | |
children | 081a073e5164 |
comparison
equal
deleted
inserted
replaced
6245:3cf25d33886a | 6246:257b51c37c5a |
---|---|
1 /* | |
2 * Copyright (C) Nginx, Inc. | |
3 * Copyright (C) Valentin V. Bartenev | |
4 */ | |
5 | |
6 | |
7 #ifndef _NGX_HTTP_V2_H_INCLUDED_ | |
8 #define _NGX_HTTP_V2_H_INCLUDED_ | |
9 | |
10 | |
11 #include <ngx_config.h> | |
12 #include <ngx_core.h> | |
13 #include <ngx_http.h> | |
14 | |
15 | |
16 #define NGX_HTTP_V2_ALPN_ADVERTISE "\x02h2" | |
17 #define NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_V2_ALPN_ADVERTISE | |
18 | |
19 #define NGX_HTTP_V2_STATE_BUFFER_SIZE 16 | |
20 | |
21 #define NGX_HTTP_V2_MAX_FRAME_SIZE ((1 << 24) - 1) | |
22 | |
23 #define NGX_HTTP_V2_INT_OCTETS 4 | |
24 #define NGX_HTTP_V2_MAX_FIELD ((1 << NGX_HTTP_V2_INT_OCTETS * 7) - 1) | |
25 | |
26 #define NGX_HTTP_V2_DATA_DISCARD 1 | |
27 #define NGX_HTTP_V2_DATA_ERROR 2 | |
28 #define NGX_HTTP_V2_DATA_INTERNAL_ERROR 3 | |
29 | |
30 #define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 | |
31 | |
32 /* frame types */ | |
33 #define NGX_HTTP_V2_DATA_FRAME 0x0 | |
34 #define NGX_HTTP_V2_HEADERS_FRAME 0x1 | |
35 #define NGX_HTTP_V2_PRIORITY_FRAME 0x2 | |
36 #define NGX_HTTP_V2_RST_STREAM_FRAME 0x3 | |
37 #define NGX_HTTP_V2_SETTINGS_FRAME 0x4 | |
38 #define NGX_HTTP_V2_PUSH_PROMISE_FRAME 0x5 | |
39 #define NGX_HTTP_V2_PING_FRAME 0x6 | |
40 #define NGX_HTTP_V2_GOAWAY_FRAME 0x7 | |
41 #define NGX_HTTP_V2_WINDOW_UPDATE_FRAME 0x8 | |
42 #define NGX_HTTP_V2_CONTINUATION_FRAME 0x9 | |
43 | |
44 /* frame flags */ | |
45 #define NGX_HTTP_V2_NO_FLAG 0x00 | |
46 #define NGX_HTTP_V2_ACK_FLAG 0x01 | |
47 #define NGX_HTTP_V2_END_STREAM_FLAG 0x01 | |
48 #define NGX_HTTP_V2_END_HEADERS_FLAG 0x04 | |
49 #define NGX_HTTP_V2_PADDED_FLAG 0x08 | |
50 #define NGX_HTTP_V2_PRIORITY_FLAG 0x20 | |
51 | |
52 | |
53 typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t; | |
54 typedef struct ngx_http_v2_node_s ngx_http_v2_node_t; | |
55 typedef struct ngx_http_v2_out_frame_s ngx_http_v2_out_frame_t; | |
56 | |
57 | |
58 typedef u_char *(*ngx_http_v2_handler_pt) (ngx_http_v2_connection_t *h2c, | |
59 u_char *pos, u_char *end); | |
60 | |
61 | |
62 typedef struct { | |
63 ngx_str_t name; | |
64 ngx_str_t value; | |
65 } ngx_http_v2_header_t; | |
66 | |
67 | |
68 typedef struct { | |
69 ngx_uint_t sid; | |
70 size_t length; | |
71 size_t padding; | |
72 unsigned flags:8; | |
73 | |
74 unsigned incomplete:1; | |
75 | |
76 /* HPACK */ | |
77 unsigned parse_name:1; | |
78 unsigned parse_value:1; | |
79 unsigned index:1; | |
80 ngx_http_v2_header_t header; | |
81 size_t header_limit; | |
82 size_t field_limit; | |
83 u_char field_state; | |
84 u_char *field_start; | |
85 u_char *field_end; | |
86 size_t field_rest; | |
87 ngx_pool_t *pool; | |
88 | |
89 ngx_http_v2_stream_t *stream; | |
90 | |
91 u_char buffer[NGX_HTTP_V2_STATE_BUFFER_SIZE]; | |
92 size_t buffer_used; | |
93 ngx_http_v2_handler_pt handler; | |
94 } ngx_http_v2_state_t; | |
95 | |
96 | |
97 | |
98 typedef struct { | |
99 ngx_http_v2_header_t **entries; | |
100 | |
101 ngx_uint_t added; | |
102 ngx_uint_t deleted; | |
103 ngx_uint_t reused; | |
104 ngx_uint_t allocated; | |
105 | |
106 size_t size; | |
107 size_t free; | |
108 u_char *storage; | |
109 u_char *pos; | |
110 } ngx_http_v2_hpack_t; | |
111 | |
112 | |
113 struct ngx_http_v2_connection_s { | |
114 ngx_connection_t *connection; | |
115 ngx_http_connection_t *http_connection; | |
116 | |
117 ngx_uint_t processing; | |
118 | |
119 size_t send_window; | |
120 size_t recv_window; | |
121 size_t init_window; | |
122 | |
123 size_t frame_size; | |
124 | |
125 ngx_queue_t waiting; | |
126 | |
127 ngx_http_v2_state_t state; | |
128 | |
129 ngx_http_v2_hpack_t hpack; | |
130 | |
131 ngx_pool_t *pool; | |
132 | |
133 ngx_http_v2_out_frame_t *free_frames; | |
134 ngx_connection_t *free_fake_connections; | |
135 | |
136 ngx_http_v2_node_t **streams_index; | |
137 | |
138 ngx_http_v2_out_frame_t *last_out; | |
139 | |
140 ngx_queue_t posted; | |
141 ngx_queue_t dependencies; | |
142 ngx_queue_t closed; | |
143 | |
144 ngx_uint_t last_sid; | |
145 | |
146 unsigned closed_nodes:8; | |
147 unsigned blocked:1; | |
148 }; | |
149 | |
150 | |
151 struct ngx_http_v2_node_s { | |
152 ngx_uint_t id; | |
153 ngx_http_v2_node_t *index; | |
154 ngx_http_v2_node_t *parent; | |
155 ngx_queue_t queue; | |
156 ngx_queue_t children; | |
157 ngx_queue_t reuse; | |
158 ngx_uint_t rank; | |
159 ngx_uint_t weight; | |
160 double rel_weight; | |
161 ngx_http_v2_stream_t *stream; | |
162 }; | |
163 | |
164 | |
165 struct ngx_http_v2_stream_s { | |
166 ngx_http_request_t *request; | |
167 ngx_http_v2_connection_t *connection; | |
168 ngx_http_v2_node_t *node; | |
169 | |
170 ngx_uint_t header_buffers; | |
171 ngx_uint_t queued; | |
172 | |
173 /* | |
174 * A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the | |
175 * send_window to become negative, hence it's signed. | |
176 */ | |
177 ssize_t send_window; | |
178 size_t recv_window; | |
179 | |
180 ngx_http_v2_out_frame_t *free_frames; | |
181 ngx_chain_t *free_data_headers; | |
182 ngx_chain_t *free_bufs; | |
183 | |
184 ngx_queue_t queue; | |
185 | |
186 ngx_array_t *cookies; | |
187 | |
188 size_t header_limit; | |
189 | |
190 unsigned handled:1; | |
191 unsigned blocked:1; | |
192 unsigned exhausted:1; | |
193 unsigned end_headers:1; | |
194 unsigned in_closed:1; | |
195 unsigned out_closed:1; | |
196 unsigned skip_data:2; | |
197 }; | |
198 | |
199 | |
200 struct ngx_http_v2_out_frame_s { | |
201 ngx_http_v2_out_frame_t *next; | |
202 ngx_chain_t *first; | |
203 ngx_chain_t *last; | |
204 ngx_int_t (*handler)(ngx_http_v2_connection_t *h2c, | |
205 ngx_http_v2_out_frame_t *frame); | |
206 | |
207 ngx_http_v2_stream_t *stream; | |
208 size_t length; | |
209 | |
210 unsigned blocked:1; | |
211 unsigned fin:1; | |
212 }; | |
213 | |
214 | |
215 static ngx_inline void | |
216 ngx_http_v2_queue_frame(ngx_http_v2_connection_t *h2c, | |
217 ngx_http_v2_out_frame_t *frame) | |
218 { | |
219 ngx_http_v2_out_frame_t **out; | |
220 | |
221 for (out = &h2c->last_out; *out; out = &(*out)->next) { | |
222 | |
223 if ((*out)->blocked || (*out)->stream == NULL) { | |
224 break; | |
225 } | |
226 | |
227 if ((*out)->stream->node->rank < frame->stream->node->rank | |
228 || ((*out)->stream->node->rank == frame->stream->node->rank | |
229 && (*out)->stream->node->rel_weight | |
230 >= frame->stream->node->rel_weight)) | |
231 { | |
232 break; | |
233 } | |
234 } | |
235 | |
236 frame->next = *out; | |
237 *out = frame; | |
238 } | |
239 | |
240 | |
241 static ngx_inline void | |
242 ngx_http_v2_queue_blocked_frame(ngx_http_v2_connection_t *h2c, | |
243 ngx_http_v2_out_frame_t *frame) | |
244 { | |
245 ngx_http_v2_out_frame_t **out; | |
246 | |
247 for (out = &h2c->last_out; *out; out = &(*out)->next) | |
248 { | |
249 if ((*out)->blocked || (*out)->stream == NULL) { | |
250 break; | |
251 } | |
252 } | |
253 | |
254 frame->next = *out; | |
255 *out = frame; | |
256 } | |
257 | |
258 | |
259 void ngx_http_v2_init(ngx_event_t *rev); | |
260 void ngx_http_v2_request_headers_init(void); | |
261 | |
262 ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r, | |
263 ngx_http_client_body_handler_pt post_handler); | |
264 | |
265 void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc); | |
266 | |
267 ngx_int_t ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c); | |
268 | |
269 | |
270 ngx_int_t ngx_http_v2_get_indexed_header(ngx_http_v2_connection_t *h2c, | |
271 ngx_uint_t index, ngx_uint_t name_only); | |
272 ngx_int_t ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c, | |
273 ngx_http_v2_header_t *header); | |
274 ngx_int_t ngx_http_v2_table_size(ngx_http_v2_connection_t *h2c, size_t size); | |
275 | |
276 | |
277 ngx_int_t ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, | |
278 u_char **dst, ngx_uint_t last, ngx_log_t *log); | |
279 | |
280 | |
281 #define ngx_http_v2_prefix(bits) ((1 << (bits)) - 1) | |
282 | |
283 | |
284 #if (NGX_HAVE_NONALIGNED) | |
285 | |
286 #define ngx_http_v2_parse_uint16(p) ntohs(*(uint16_t *) (p)) | |
287 #define ngx_http_v2_parse_uint32(p) ntohl(*(uint32_t *) (p)) | |
288 | |
289 #else | |
290 | |
291 #define ngx_http_v2_parse_uint16(p) ((p)[0] << 8 | (p)[1]) | |
292 #define ngx_http_v2_parse_uint32(p) \ | |
293 ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]) | |
294 | |
295 #endif | |
296 | |
297 #define ngx_http_v2_parse_length(p) ((p) >> 8) | |
298 #define ngx_http_v2_parse_type(p) ((p) & 0xff) | |
299 #define ngx_http_v2_parse_sid(p) (ngx_http_v2_parse_uint32(p) & 0x7fffffff) | |
300 #define ngx_http_v2_parse_window(p) (ngx_http_v2_parse_uint32(p) & 0x7fffffff) | |
301 | |
302 | |
303 #define ngx_http_v2_write_uint16_aligned(p, s) \ | |
304 (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t)) | |
305 #define ngx_http_v2_write_uint32_aligned(p, s) \ | |
306 (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) | |
307 | |
308 #if (NGX_HAVE_NONALIGNED) | |
309 | |
310 #define ngx_http_v2_write_uint16 ngx_http_v2_write_uint16_aligned | |
311 #define ngx_http_v2_write_uint32 ngx_http_v2_write_uint32_aligned | |
312 | |
313 #else | |
314 | |
315 #define ngx_http_v2_write_uint16(p, s) \ | |
316 ((p)[0] = (u_char) ((s) >> 8), \ | |
317 (p)[1] = (u_char) (s), \ | |
318 (p) + sizeof(uint16_t)) | |
319 | |
320 #define ngx_http_v2_write_uint32(p, s) \ | |
321 ((p)[0] = (u_char) ((s) >> 24), \ | |
322 (p)[1] = (u_char) ((s) >> 16), \ | |
323 (p)[2] = (u_char) ((s) >> 8), \ | |
324 (p)[3] = (u_char) (s), \ | |
325 (p) + sizeof(uint32_t)) | |
326 | |
327 #endif | |
328 | |
329 #define ngx_http_v2_write_len_and_type(p, l, t) \ | |
330 ngx_http_v2_write_uint32_aligned(p, (l) << 8 | (t)) | |
331 | |
332 #define ngx_http_v2_write_sid ngx_http_v2_write_uint32 | |
333 | |
334 #endif /* _NGX_HTTP_V2_H_INCLUDED_ */ |