comparison src/http/v3/ngx_http_v3_module.c @ 8481:0d2b2664b41c quic

QUIC: added "quic" listen parameter. The parameter allows processing HTTP/0.9-2 over QUIC. Also, introduced ngx_http_quic_module and moved QUIC settings there
author Roman Arutyunyan <arut@nginx.com>
date Tue, 21 Jul 2020 23:09:22 +0300
parents c9538aef3211
children 65c1fc5fae15
comparison
equal deleted inserted replaced
8480:f537f99b86ee 8481:0d2b2664b41c
8 #include <ngx_config.h> 8 #include <ngx_config.h>
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 #include <ngx_http.h> 10 #include <ngx_http.h>
11 11
12 12
13 static char *ngx_http_v3_max_ack_delay(ngx_conf_t *cf, void *post, void *data);
14 static char *ngx_http_v3_max_udp_payload_size(ngx_conf_t *cf, void *post,
15 void *data);
16
17
18 static ngx_conf_post_t ngx_http_v3_max_ack_delay_post =
19 { ngx_http_v3_max_ack_delay };
20 static ngx_conf_post_t ngx_http_v3_max_udp_payload_size_post =
21 { ngx_http_v3_max_udp_payload_size };
22 static ngx_conf_num_bounds_t ngx_http_v3_ack_delay_exponent_bounds =
23 { ngx_conf_check_num_bounds, 0, 20 };
24 static ngx_conf_num_bounds_t ngx_http_v3_active_connection_id_limit_bounds =
25 { ngx_conf_check_num_bounds, 2, -1 };
26
27
28 static ngx_command_t ngx_http_v3_commands[] = { 13 static ngx_command_t ngx_http_v3_commands[] = {
29
30 { ngx_string("quic_max_idle_timeout"),
31 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
32 ngx_conf_set_msec_slot,
33 NGX_HTTP_SRV_CONF_OFFSET,
34 offsetof(ngx_http_v3_srv_conf_t, quic.max_idle_timeout),
35 NULL },
36
37 { ngx_string("quic_max_ack_delay"),
38 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
39 ngx_conf_set_msec_slot,
40 NGX_HTTP_SRV_CONF_OFFSET,
41 offsetof(ngx_http_v3_srv_conf_t, quic.max_ack_delay),
42 &ngx_http_v3_max_ack_delay_post },
43
44 { ngx_string("quic_max_udp_payload_size"),
45 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
46 ngx_conf_set_size_slot,
47 NGX_HTTP_SRV_CONF_OFFSET,
48 offsetof(ngx_http_v3_srv_conf_t, quic.max_udp_payload_size),
49 &ngx_http_v3_max_udp_payload_size_post },
50
51 { ngx_string("quic_initial_max_data"),
52 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
53 ngx_conf_set_size_slot,
54 NGX_HTTP_SRV_CONF_OFFSET,
55 offsetof(ngx_http_v3_srv_conf_t, quic.initial_max_data),
56 NULL },
57
58 { ngx_string("quic_initial_max_stream_data_bidi_local"),
59 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
60 ngx_conf_set_size_slot,
61 NGX_HTTP_SRV_CONF_OFFSET,
62 offsetof(ngx_http_v3_srv_conf_t, quic.initial_max_stream_data_bidi_local),
63 NULL },
64
65 { ngx_string("quic_initial_max_stream_data_bidi_remote"),
66 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
67 ngx_conf_set_size_slot,
68 NGX_HTTP_SRV_CONF_OFFSET,
69 offsetof(ngx_http_v3_srv_conf_t, quic.initial_max_stream_data_bidi_remote),
70 NULL },
71
72 { ngx_string("quic_initial_max_stream_data_uni"),
73 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
74 ngx_conf_set_size_slot,
75 NGX_HTTP_SRV_CONF_OFFSET,
76 offsetof(ngx_http_v3_srv_conf_t, quic.initial_max_stream_data_uni),
77 NULL },
78
79 { ngx_string("quic_initial_max_streams_bidi"),
80 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
81 ngx_conf_set_num_slot,
82 NGX_HTTP_SRV_CONF_OFFSET,
83 offsetof(ngx_http_v3_srv_conf_t, quic.initial_max_streams_bidi),
84 NULL },
85
86 { ngx_string("quic_initial_max_streams_uni"),
87 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
88 ngx_conf_set_num_slot,
89 NGX_HTTP_SRV_CONF_OFFSET,
90 offsetof(ngx_http_v3_srv_conf_t, quic.initial_max_streams_uni),
91 NULL },
92
93 { ngx_string("quic_ack_delay_exponent"),
94 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
95 ngx_conf_set_num_slot,
96 NGX_HTTP_SRV_CONF_OFFSET,
97 offsetof(ngx_http_v3_srv_conf_t, quic.ack_delay_exponent),
98 &ngx_http_v3_ack_delay_exponent_bounds },
99
100 { ngx_string("quic_active_migration"),
101 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
102 ngx_conf_set_num_slot,
103 NGX_HTTP_SRV_CONF_OFFSET,
104 offsetof(ngx_http_v3_srv_conf_t, quic.disable_active_migration),
105 NULL },
106
107 { ngx_string("quic_active_connection_id_limit"),
108 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
109 ngx_conf_set_num_slot,
110 NGX_HTTP_SRV_CONF_OFFSET,
111 offsetof(ngx_http_v3_srv_conf_t, quic.active_connection_id_limit),
112 &ngx_http_v3_active_connection_id_limit_bounds },
113
114 { ngx_string("quic_retry"),
115 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
116 ngx_conf_set_flag_slot,
117 NGX_HTTP_SRV_CONF_OFFSET,
118 offsetof(ngx_http_v3_srv_conf_t, quic.retry),
119 NULL },
120 14
121 { ngx_string("http3_max_field_size"), 15 { ngx_string("http3_max_field_size"),
122 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, 16 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
123 ngx_conf_set_size_slot, 17 ngx_conf_set_size_slot,
124 NGX_HTTP_SRV_CONF_OFFSET, 18 NGX_HTTP_SRV_CONF_OFFSET,
141 35
142 ngx_null_command 36 ngx_null_command
143 }; 37 };
144 38
145 39
146 static ngx_int_t ngx_http_variable_quic(ngx_http_request_t *r,
147 ngx_http_variable_value_t *v, uintptr_t data);
148 static ngx_int_t ngx_http_variable_http3(ngx_http_request_t *r, 40 static ngx_int_t ngx_http_variable_http3(ngx_http_request_t *r,
149 ngx_http_variable_value_t *v, uintptr_t data); 41 ngx_http_variable_value_t *v, uintptr_t data);
150 static ngx_int_t ngx_http_v3_add_variables(ngx_conf_t *cf); 42 static ngx_int_t ngx_http_v3_add_variables(ngx_conf_t *cf);
151 static void *ngx_http_v3_create_srv_conf(ngx_conf_t *cf); 43 static void *ngx_http_v3_create_srv_conf(ngx_conf_t *cf);
152 static char *ngx_http_v3_merge_srv_conf(ngx_conf_t *cf, 44 static char *ngx_http_v3_merge_srv_conf(ngx_conf_t *cf,
183 NGX_MODULE_V1_PADDING 75 NGX_MODULE_V1_PADDING
184 }; 76 };
185 77
186 78
187 static ngx_http_variable_t ngx_http_v3_vars[] = { 79 static ngx_http_variable_t ngx_http_v3_vars[] = {
188 { ngx_string("quic"), NULL, ngx_http_variable_quic,
189 0, 0, 0 },
190 80
191 { ngx_string("http3"), NULL, ngx_http_variable_http3, 81 { ngx_string("http3"), NULL, ngx_http_variable_http3,
192 0, 0, 0 }, 82 0, 0, 0 },
193 83
194 ngx_http_null_variable 84 ngx_http_null_variable
195 }; 85 };
196
197
198 static ngx_int_t
199 ngx_http_variable_quic(ngx_http_request_t *r,
200 ngx_http_variable_value_t *v, uintptr_t data)
201 {
202 if (r->connection->qs) {
203
204 v->len = 4;
205 v->valid = 1;
206 v->no_cacheable = 1;
207 v->not_found = 0;
208 v->data = (u_char *) "quic";
209 return NGX_OK;
210 }
211
212 v->not_found = 1;
213
214 return NGX_OK;
215 }
216 86
217 87
218 static ngx_int_t 88 static ngx_int_t
219 ngx_http_variable_http3(ngx_http_request_t *r, 89 ngx_http_variable_http3(ngx_http_request_t *r,
220 ngx_http_variable_value_t *v, uintptr_t data) 90 ngx_http_variable_value_t *v, uintptr_t data)
262 v3cf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v3_srv_conf_t)); 132 v3cf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v3_srv_conf_t));
263 if (v3cf == NULL) { 133 if (v3cf == NULL) {
264 return NULL; 134 return NULL;
265 } 135 }
266 136
267 /*
268 * set by ngx_pcalloc():
269 * v3cf->quic.original_dcid = { 0, NULL };
270 * v3cf->quic.initial_scid = { 0, NULL };
271 * v3cf->quic.retry_scid = { 0, NULL };
272 * v3cf->quic.stateless_reset_token = { 0 }
273 * conf->quic.preferred_address = NULL
274 */
275
276 v3cf->quic.max_idle_timeout = NGX_CONF_UNSET_MSEC;
277 v3cf->quic.max_ack_delay = NGX_CONF_UNSET_MSEC;
278
279 v3cf->quic.max_udp_payload_size = NGX_CONF_UNSET_SIZE;
280 v3cf->quic.initial_max_data = NGX_CONF_UNSET_SIZE;
281 v3cf->quic.initial_max_stream_data_bidi_local = NGX_CONF_UNSET_SIZE;
282 v3cf->quic.initial_max_stream_data_bidi_remote = NGX_CONF_UNSET_SIZE;
283 v3cf->quic.initial_max_stream_data_uni = NGX_CONF_UNSET_SIZE;
284 v3cf->quic.initial_max_streams_bidi = NGX_CONF_UNSET_UINT;
285 v3cf->quic.initial_max_streams_uni = NGX_CONF_UNSET_UINT;
286 v3cf->quic.ack_delay_exponent = NGX_CONF_UNSET_UINT;
287 v3cf->quic.disable_active_migration = NGX_CONF_UNSET_UINT;
288 v3cf->quic.active_connection_id_limit = NGX_CONF_UNSET_UINT;
289
290 v3cf->quic.retry = NGX_CONF_UNSET;
291
292 v3cf->max_field_size = NGX_CONF_UNSET_SIZE; 137 v3cf->max_field_size = NGX_CONF_UNSET_SIZE;
293 v3cf->max_table_capacity = NGX_CONF_UNSET_SIZE; 138 v3cf->max_table_capacity = NGX_CONF_UNSET_SIZE;
294 v3cf->max_blocked_streams = NGX_CONF_UNSET_UINT; 139 v3cf->max_blocked_streams = NGX_CONF_UNSET_UINT;
295 140
296 return v3cf; 141 return v3cf;
300 static char * 145 static char *
301 ngx_http_v3_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) 146 ngx_http_v3_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
302 { 147 {
303 ngx_http_v3_srv_conf_t *prev = parent; 148 ngx_http_v3_srv_conf_t *prev = parent;
304 ngx_http_v3_srv_conf_t *conf = child; 149 ngx_http_v3_srv_conf_t *conf = child;
305
306 ngx_conf_merge_msec_value(conf->quic.max_idle_timeout,
307 prev->quic.max_idle_timeout, 60000);
308
309 ngx_conf_merge_msec_value(conf->quic.max_ack_delay,
310 prev->quic.max_ack_delay,
311 NGX_QUIC_DEFAULT_MAX_ACK_DELAY);
312
313 ngx_conf_merge_size_value(conf->quic.max_udp_payload_size,
314 prev->quic.max_udp_payload_size,
315 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE);
316
317 ngx_conf_merge_size_value(conf->quic.initial_max_data,
318 prev->quic.initial_max_data,
319 16 * NGX_QUIC_STREAM_BUFSIZE);
320
321 ngx_conf_merge_size_value(conf->quic.initial_max_stream_data_bidi_local,
322 prev->quic.initial_max_stream_data_bidi_local,
323 NGX_QUIC_STREAM_BUFSIZE);
324
325 ngx_conf_merge_size_value(conf->quic.initial_max_stream_data_bidi_remote,
326 prev->quic.initial_max_stream_data_bidi_remote,
327 NGX_QUIC_STREAM_BUFSIZE);
328
329 ngx_conf_merge_size_value(conf->quic.initial_max_stream_data_uni,
330 prev->quic.initial_max_stream_data_uni,
331 NGX_QUIC_STREAM_BUFSIZE);
332
333 ngx_conf_merge_uint_value(conf->quic.initial_max_streams_bidi,
334 prev->quic.initial_max_streams_bidi, 16);
335
336 ngx_conf_merge_uint_value(conf->quic.initial_max_streams_uni,
337 prev->quic.initial_max_streams_uni, 16);
338
339 ngx_conf_merge_uint_value(conf->quic.ack_delay_exponent,
340 prev->quic.ack_delay_exponent,
341 NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT);
342
343 ngx_conf_merge_uint_value(conf->quic.disable_active_migration,
344 prev->quic.disable_active_migration, 1);
345
346 ngx_conf_merge_uint_value(conf->quic.active_connection_id_limit,
347 prev->quic.active_connection_id_limit, 2);
348
349 ngx_conf_merge_value(conf->quic.retry, prev->quic.retry, 0);
350
351 if (conf->quic.retry) {
352 if (RAND_bytes(conf->quic.token_key, sizeof(conf->quic.token_key)) <= 0) {
353 return NGX_CONF_ERROR;
354 }
355 }
356 150
357 ngx_conf_merge_size_value(conf->max_field_size, 151 ngx_conf_merge_size_value(conf->max_field_size,
358 prev->max_field_size, 152 prev->max_field_size,
359 NGX_HTTP_V3_DEFAULT_MAX_FIELD_SIZE); 153 NGX_HTTP_V3_DEFAULT_MAX_FIELD_SIZE);
360 154
366 prev->max_blocked_streams, 160 prev->max_blocked_streams,
367 NGX_HTTP_V3_DEFAULT_MAX_BLOCKED_STREAMS); 161 NGX_HTTP_V3_DEFAULT_MAX_BLOCKED_STREAMS);
368 162
369 return NGX_CONF_OK; 163 return NGX_CONF_OK;
370 } 164 }
371
372
373 static char *
374 ngx_http_v3_max_ack_delay(ngx_conf_t *cf, void *post, void *data)
375 {
376 ngx_msec_t *sp = data;
377
378 if (*sp > 16384) {
379 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
380 "\"quic_max_ack_delay\" must be less than 16384");
381
382 return NGX_CONF_ERROR;
383 }
384
385 return NGX_CONF_OK;
386 }
387
388
389 static char *
390 ngx_http_v3_max_udp_payload_size(ngx_conf_t *cf, void *post, void *data)
391 {
392 size_t *sp = data;
393
394 if (*sp < NGX_QUIC_MIN_INITIAL_SIZE
395 || *sp > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE)
396 {
397 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
398 "\"quic_max_udp_payload_size\" must be between "
399 "%d and %d",
400 NGX_QUIC_MIN_INITIAL_SIZE,
401 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE);
402
403 return NGX_CONF_ERROR;
404 }
405
406 return NGX_CONF_OK;
407 }