comparison src/http/v2/ngx_http_v2_module.c @ 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 2cd019520210
comparison
equal deleted inserted replaced
6245:3cf25d33886a 6246:257b51c37c5a
1
2 /*
3 * Copyright (C) Nginx, Inc.
4 * Copyright (C) Valentin V. Bartenev
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 #include <ngx_http_v2_module.h>
12
13
14 static ngx_int_t ngx_http_v2_add_variables(ngx_conf_t *cf);
15
16 static ngx_int_t ngx_http_v2_variable(ngx_http_request_t *r,
17 ngx_http_variable_value_t *v, uintptr_t data);
18
19 static ngx_int_t ngx_http_v2_module_init(ngx_cycle_t *cycle);
20
21 static void *ngx_http_v2_create_main_conf(ngx_conf_t *cf);
22 static char *ngx_http_v2_init_main_conf(ngx_conf_t *cf, void *conf);
23 static void *ngx_http_v2_create_srv_conf(ngx_conf_t *cf);
24 static char *ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent,
25 void *child);
26 static void *ngx_http_v2_create_loc_conf(ngx_conf_t *cf);
27 static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent,
28 void *child);
29
30 static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post,
31 void *data);
32 static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data);
33 static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post,
34 void *data);
35 static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data);
36 static char *ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd,
37 void *conf);
38
39
40 static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post =
41 { ngx_http_v2_recv_buffer_size };
42 static ngx_conf_post_t ngx_http_v2_pool_size_post =
43 { ngx_http_v2_pool_size };
44 static ngx_conf_post_t ngx_http_v2_streams_index_mask_post =
45 { ngx_http_v2_streams_index_mask };
46 static ngx_conf_post_t ngx_http_v2_chunk_size_post =
47 { ngx_http_v2_chunk_size };
48
49
50 static ngx_command_t ngx_http_v2_commands[] = {
51
52 { ngx_string("http2_recv_buffer_size"),
53 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
54 ngx_conf_set_size_slot,
55 NGX_HTTP_MAIN_CONF_OFFSET,
56 offsetof(ngx_http_v2_main_conf_t, recv_buffer_size),
57 &ngx_http_v2_recv_buffer_size_post },
58
59 { ngx_string("http2_pool_size"),
60 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
61 ngx_conf_set_size_slot,
62 NGX_HTTP_SRV_CONF_OFFSET,
63 offsetof(ngx_http_v2_srv_conf_t, pool_size),
64 &ngx_http_v2_pool_size_post },
65
66 { ngx_string("http2_max_concurrent_streams"),
67 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
68 ngx_conf_set_num_slot,
69 NGX_HTTP_SRV_CONF_OFFSET,
70 offsetof(ngx_http_v2_srv_conf_t, concurrent_streams),
71 NULL },
72
73 { ngx_string("http2_max_field_size"),
74 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
75 ngx_conf_set_size_slot,
76 NGX_HTTP_SRV_CONF_OFFSET,
77 offsetof(ngx_http_v2_srv_conf_t, max_field_size),
78 NULL },
79
80 { ngx_string("http2_max_header_size"),
81 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
82 ngx_conf_set_size_slot,
83 NGX_HTTP_SRV_CONF_OFFSET,
84 offsetof(ngx_http_v2_srv_conf_t, max_header_size),
85 NULL },
86
87 { ngx_string("http2_streams_index_size"),
88 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
89 ngx_conf_set_num_slot,
90 NGX_HTTP_SRV_CONF_OFFSET,
91 offsetof(ngx_http_v2_srv_conf_t, streams_index_mask),
92 &ngx_http_v2_streams_index_mask_post },
93
94 { ngx_string("http2_recv_timeout"),
95 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
96 ngx_conf_set_msec_slot,
97 NGX_HTTP_SRV_CONF_OFFSET,
98 offsetof(ngx_http_v2_srv_conf_t, recv_timeout),
99 NULL },
100
101 { ngx_string("http2_idle_timeout"),
102 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
103 ngx_conf_set_msec_slot,
104 NGX_HTTP_SRV_CONF_OFFSET,
105 offsetof(ngx_http_v2_srv_conf_t, idle_timeout),
106 NULL },
107
108 { ngx_string("http2_chunk_size"),
109 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
110 ngx_conf_set_size_slot,
111 NGX_HTTP_LOC_CONF_OFFSET,
112 offsetof(ngx_http_v2_loc_conf_t, chunk_size),
113 &ngx_http_v2_chunk_size_post },
114
115 { ngx_string("spdy_recv_buffer_size"),
116 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
117 ngx_http_v2_spdy_deprecated,
118 NGX_HTTP_MAIN_CONF_OFFSET,
119 0,
120 NULL },
121
122 { ngx_string("spdy_pool_size"),
123 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
124 ngx_http_v2_spdy_deprecated,
125 NGX_HTTP_SRV_CONF_OFFSET,
126 0,
127 NULL },
128
129 { ngx_string("spdy_max_concurrent_streams"),
130 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
131 ngx_http_v2_spdy_deprecated,
132 NGX_HTTP_SRV_CONF_OFFSET,
133 0,
134 NULL },
135
136 { ngx_string("spdy_streams_index_size"),
137 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
138 ngx_http_v2_spdy_deprecated,
139 NGX_HTTP_SRV_CONF_OFFSET,
140 0,
141 NULL },
142
143 { ngx_string("spdy_recv_timeout"),
144 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
145 ngx_http_v2_spdy_deprecated,
146 NGX_HTTP_SRV_CONF_OFFSET,
147 0,
148 NULL },
149
150 { ngx_string("spdy_keepalive_timeout"),
151 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
152 ngx_http_v2_spdy_deprecated,
153 NGX_HTTP_SRV_CONF_OFFSET,
154 0,
155 NULL },
156
157 { ngx_string("spdy_headers_comp"),
158 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
159 ngx_http_v2_spdy_deprecated,
160 NGX_HTTP_SRV_CONF_OFFSET,
161 0,
162 NULL },
163
164 { ngx_string("spdy_chunk_size"),
165 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
166 ngx_http_v2_spdy_deprecated,
167 NGX_HTTP_LOC_CONF_OFFSET,
168 0,
169 NULL },
170
171 ngx_null_command
172 };
173
174
175 static ngx_http_module_t ngx_http_v2_module_ctx = {
176 ngx_http_v2_add_variables, /* preconfiguration */
177 NULL, /* postconfiguration */
178
179 ngx_http_v2_create_main_conf, /* create main configuration */
180 ngx_http_v2_init_main_conf, /* init main configuration */
181
182 ngx_http_v2_create_srv_conf, /* create server configuration */
183 ngx_http_v2_merge_srv_conf, /* merge server configuration */
184
185 ngx_http_v2_create_loc_conf, /* create location configuration */
186 ngx_http_v2_merge_loc_conf /* merge location configuration */
187 };
188
189
190 ngx_module_t ngx_http_v2_module = {
191 NGX_MODULE_V1,
192 &ngx_http_v2_module_ctx, /* module context */
193 ngx_http_v2_commands, /* module directives */
194 NGX_HTTP_MODULE, /* module type */
195 NULL, /* init master */
196 ngx_http_v2_module_init, /* init module */
197 NULL, /* init process */
198 NULL, /* init thread */
199 NULL, /* exit thread */
200 NULL, /* exit process */
201 NULL, /* exit master */
202 NGX_MODULE_V1_PADDING
203 };
204
205
206 static ngx_http_variable_t ngx_http_v2_vars[] = {
207
208 { ngx_string("http2"), NULL,
209 ngx_http_v2_variable, 0, 0, 0 },
210
211 { ngx_null_string, NULL, NULL, 0, 0, 0 }
212 };
213
214
215 static ngx_int_t
216 ngx_http_v2_add_variables(ngx_conf_t *cf)
217 {
218 ngx_http_variable_t *var, *v;
219
220 for (v = ngx_http_v2_vars; v->name.len; v++) {
221 var = ngx_http_add_variable(cf, &v->name, v->flags);
222 if (var == NULL) {
223 return NGX_ERROR;
224 }
225
226 var->get_handler = v->get_handler;
227 var->data = v->data;
228 }
229
230 return NGX_OK;
231 }
232
233
234 static ngx_int_t
235 ngx_http_v2_variable(ngx_http_request_t *r,
236 ngx_http_variable_value_t *v, uintptr_t data)
237 {
238
239 if (r->stream) {
240 #if (NGX_HTTP_SSL)
241
242 if (r->connection->ssl) {
243 v->len = sizeof("h2") - 1;
244 v->valid = 1;
245 v->no_cacheable = 0;
246 v->not_found = 0;
247 v->data = (u_char *) "h2";
248
249 return NGX_OK;
250 }
251
252 #endif
253 v->len = sizeof("h2c") - 1;
254 v->valid = 1;
255 v->no_cacheable = 0;
256 v->not_found = 0;
257 v->data = (u_char *) "h2c";
258
259 return NGX_OK;
260 }
261
262 *v = ngx_http_variable_null_value;
263
264 return NGX_OK;
265 }
266
267
268 static ngx_int_t
269 ngx_http_v2_module_init(ngx_cycle_t *cycle)
270 {
271 return NGX_OK;
272 }
273
274
275 static void *
276 ngx_http_v2_create_main_conf(ngx_conf_t *cf)
277 {
278 ngx_http_v2_main_conf_t *h2mcf;
279
280 h2mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_main_conf_t));
281 if (h2mcf == NULL) {
282 return NULL;
283 }
284
285 h2mcf->recv_buffer_size = NGX_CONF_UNSET_SIZE;
286
287 return h2mcf;
288 }
289
290
291 static char *
292 ngx_http_v2_init_main_conf(ngx_conf_t *cf, void *conf)
293 {
294 ngx_http_v2_main_conf_t *h2mcf = conf;
295
296 ngx_conf_init_size_value(h2mcf->recv_buffer_size, 256 * 1024);
297
298 return NGX_CONF_OK;
299 }
300
301
302 static void *
303 ngx_http_v2_create_srv_conf(ngx_conf_t *cf)
304 {
305 ngx_http_v2_srv_conf_t *h2scf;
306
307 h2scf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_srv_conf_t));
308 if (h2scf == NULL) {
309 return NULL;
310 }
311
312 h2scf->pool_size = NGX_CONF_UNSET_SIZE;
313
314 h2scf->concurrent_streams = NGX_CONF_UNSET_UINT;
315
316 h2scf->max_field_size = NGX_CONF_UNSET_SIZE;
317 h2scf->max_header_size = NGX_CONF_UNSET_SIZE;
318
319 h2scf->streams_index_mask = NGX_CONF_UNSET_UINT;
320
321 h2scf->recv_timeout = NGX_CONF_UNSET_MSEC;
322 h2scf->idle_timeout = NGX_CONF_UNSET_MSEC;
323
324 return h2scf;
325 }
326
327
328 static char *
329 ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
330 {
331 ngx_http_v2_srv_conf_t *prev = parent;
332 ngx_http_v2_srv_conf_t *conf = child;
333
334 ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096);
335
336 ngx_conf_merge_uint_value(conf->concurrent_streams,
337 prev->concurrent_streams, 128);
338
339 ngx_conf_merge_size_value(conf->max_field_size, prev->max_field_size,
340 4096);
341 ngx_conf_merge_size_value(conf->max_header_size, prev->max_header_size,
342 16384);
343
344 ngx_conf_merge_uint_value(conf->streams_index_mask,
345 prev->streams_index_mask, 32 - 1);
346
347 ngx_conf_merge_msec_value(conf->recv_timeout,
348 prev->recv_timeout, 30000);
349 ngx_conf_merge_msec_value(conf->idle_timeout,
350 prev->idle_timeout, 180000);
351
352 return NGX_CONF_OK;
353 }
354
355
356 static void *
357 ngx_http_v2_create_loc_conf(ngx_conf_t *cf)
358 {
359 ngx_http_v2_loc_conf_t *h2lcf;
360
361 h2lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_loc_conf_t));
362 if (h2lcf == NULL) {
363 return NULL;
364 }
365
366 h2lcf->chunk_size = NGX_CONF_UNSET_SIZE;
367
368 return h2lcf;
369 }
370
371
372 static char *
373 ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
374 {
375 ngx_http_v2_loc_conf_t *prev = parent;
376 ngx_http_v2_loc_conf_t *conf = child;
377
378 ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024);
379
380 return NGX_CONF_OK;
381 }
382
383
384 static char *
385 ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, void *data)
386 {
387 size_t *sp = data;
388
389 if (*sp <= 2 * NGX_HTTP_V2_STATE_BUFFER_SIZE) {
390 return "value is too small";
391 }
392
393 return NGX_CONF_OK;
394 }
395
396
397 static char *
398 ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data)
399 {
400 size_t *sp = data;
401
402 if (*sp < NGX_MIN_POOL_SIZE) {
403 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
404 "the pool size must be no less than %uz",
405 NGX_MIN_POOL_SIZE);
406
407 return NGX_CONF_ERROR;
408 }
409
410 if (*sp % NGX_POOL_ALIGNMENT) {
411 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
412 "the pool size must be a multiple of %uz",
413 NGX_POOL_ALIGNMENT);
414
415 return NGX_CONF_ERROR;
416 }
417
418 return NGX_CONF_OK;
419 }
420
421
422 static char *
423 ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data)
424 {
425 ngx_uint_t *np = data;
426
427 ngx_uint_t mask;
428
429 mask = *np - 1;
430
431 if (*np == 0 || (*np & mask)) {
432 return "must be a power of two";
433 }
434
435 *np = mask;
436
437 return NGX_CONF_OK;
438 }
439
440
441 static char *
442 ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data)
443 {
444 size_t *sp = data;
445
446 if (*sp == 0) {
447 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
448 "the http2 chunk size cannot be zero");
449
450 return NGX_CONF_ERROR;
451 }
452
453 if (*sp > NGX_HTTP_V2_MAX_FRAME_SIZE) {
454 *sp = NGX_HTTP_V2_MAX_FRAME_SIZE;
455 }
456
457 return NGX_CONF_OK;
458 }
459
460
461 static char *
462 ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
463 {
464 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
465 "invalid directive \"%V\": ngx_http_spdy_module "
466 "was superseded by ngx_http_v2_module", &cmd->name);
467
468 return NGX_CONF_OK;
469 }