comparison src/stream/ngx_stream_quic_module.c @ 8000:893b3313f53c quic

QUIC: added "quic" listen parameter in Stream. Also, introduced ngx_stream_quic_module.
author Roman Arutyunyan <arut@nginx.com>
date Tue, 21 Jul 2020 23:08:39 +0300
parents
children bed310672f39
comparison
equal deleted inserted replaced
7999:0d2b2664b41c 8000:893b3313f53c
1
2 /*
3 * Copyright (C) Nginx, Inc.
4 * Copyright (C) Roman Arutyunyan
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_stream.h>
11
12
13 static ngx_int_t ngx_stream_variable_quic(ngx_stream_session_t *s,
14 ngx_stream_variable_value_t *v, uintptr_t data);
15 static ngx_int_t ngx_stream_quic_add_variables(ngx_conf_t *cf);
16 static void *ngx_stream_quic_create_srv_conf(ngx_conf_t *cf);
17 static char *ngx_stream_quic_merge_srv_conf(ngx_conf_t *cf, void *parent,
18 void *child);
19 static char *ngx_stream_quic_max_ack_delay(ngx_conf_t *cf, void *post,
20 void *data);
21 static char *ngx_stream_quic_max_udp_payload_size(ngx_conf_t *cf, void *post,
22 void *data);
23
24
25 static ngx_conf_post_t ngx_stream_quic_max_ack_delay_post =
26 { ngx_stream_quic_max_ack_delay };
27 static ngx_conf_post_t ngx_stream_quic_max_udp_payload_size_post =
28 { ngx_stream_quic_max_udp_payload_size };
29 static ngx_conf_num_bounds_t ngx_stream_quic_ack_delay_exponent_bounds =
30 { ngx_conf_check_num_bounds, 0, 20 };
31 static ngx_conf_num_bounds_t
32 ngx_stream_quic_active_connection_id_limit_bounds =
33 { ngx_conf_check_num_bounds, 2, -1 };
34
35
36 static ngx_command_t ngx_stream_quic_commands[] = {
37
38 { ngx_string("quic_max_idle_timeout"),
39 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
40 ngx_conf_set_msec_slot,
41 NGX_STREAM_SRV_CONF_OFFSET,
42 offsetof(ngx_quic_conf_t, tp.max_idle_timeout),
43 NULL },
44
45 { ngx_string("quic_max_ack_delay"),
46 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
47 ngx_conf_set_msec_slot,
48 NGX_STREAM_SRV_CONF_OFFSET,
49 offsetof(ngx_quic_conf_t, tp.max_ack_delay),
50 &ngx_stream_quic_max_ack_delay_post },
51
52 { ngx_string("quic_max_udp_payload_size"),
53 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
54 ngx_conf_set_size_slot,
55 NGX_STREAM_SRV_CONF_OFFSET,
56 offsetof(ngx_quic_conf_t, tp.max_udp_payload_size),
57 &ngx_stream_quic_max_udp_payload_size_post },
58
59 { ngx_string("quic_initial_max_data"),
60 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
61 ngx_conf_set_size_slot,
62 NGX_STREAM_SRV_CONF_OFFSET,
63 offsetof(ngx_quic_conf_t, tp.initial_max_data),
64 NULL },
65
66 { ngx_string("quic_initial_max_stream_data_bidi_local"),
67 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
68 ngx_conf_set_size_slot,
69 NGX_STREAM_SRV_CONF_OFFSET,
70 offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_bidi_local),
71 NULL },
72
73 { ngx_string("quic_initial_max_stream_data_bidi_remote"),
74 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
75 ngx_conf_set_size_slot,
76 NGX_STREAM_SRV_CONF_OFFSET,
77 offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_bidi_remote),
78 NULL },
79
80 { ngx_string("quic_initial_max_stream_data_uni"),
81 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
82 ngx_conf_set_size_slot,
83 NGX_STREAM_SRV_CONF_OFFSET,
84 offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_uni),
85 NULL },
86
87 { ngx_string("quic_initial_max_streams_bidi"),
88 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
89 ngx_conf_set_num_slot,
90 NGX_STREAM_SRV_CONF_OFFSET,
91 offsetof(ngx_quic_conf_t, tp.initial_max_streams_bidi),
92 NULL },
93
94 { ngx_string("quic_initial_max_streams_uni"),
95 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
96 ngx_conf_set_num_slot,
97 NGX_STREAM_SRV_CONF_OFFSET,
98 offsetof(ngx_quic_conf_t, tp.initial_max_streams_uni),
99 NULL },
100
101 { ngx_string("quic_ack_delay_exponent"),
102 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
103 ngx_conf_set_num_slot,
104 NGX_STREAM_SRV_CONF_OFFSET,
105 offsetof(ngx_quic_conf_t, tp.ack_delay_exponent),
106 &ngx_stream_quic_ack_delay_exponent_bounds },
107
108 { ngx_string("quic_active_migration"),
109 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
110 ngx_conf_set_num_slot,
111 NGX_STREAM_SRV_CONF_OFFSET,
112 offsetof(ngx_quic_conf_t, tp.disable_active_migration),
113 NULL },
114
115 { ngx_string("quic_active_connection_id_limit"),
116 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
117 ngx_conf_set_num_slot,
118 NGX_STREAM_SRV_CONF_OFFSET,
119 offsetof(ngx_quic_conf_t, tp.active_connection_id_limit),
120 &ngx_stream_quic_active_connection_id_limit_bounds },
121
122 { ngx_string("quic_retry"),
123 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
124 ngx_conf_set_flag_slot,
125 NGX_STREAM_SRV_CONF_OFFSET,
126 offsetof(ngx_quic_conf_t, retry),
127 NULL },
128
129 ngx_null_command
130 };
131
132
133 static ngx_stream_module_t ngx_stream_quic_module_ctx = {
134 ngx_stream_quic_add_variables, /* preconfiguration */
135 NULL, /* postconfiguration */
136
137 NULL, /* create main configuration */
138 NULL, /* init main configuration */
139
140 ngx_stream_quic_create_srv_conf, /* create server configuration */
141 ngx_stream_quic_merge_srv_conf, /* merge server configuration */
142 };
143
144
145 ngx_module_t ngx_stream_quic_module = {
146 NGX_MODULE_V1,
147 &ngx_stream_quic_module_ctx, /* module context */
148 ngx_stream_quic_commands, /* module directives */
149 NGX_STREAM_MODULE, /* module type */
150 NULL, /* init master */
151 NULL, /* init module */
152 NULL, /* init process */
153 NULL, /* init thread */
154 NULL, /* exit thread */
155 NULL, /* exit process */
156 NULL, /* exit master */
157 NGX_MODULE_V1_PADDING
158 };
159
160
161 static ngx_stream_variable_t ngx_stream_quic_vars[] = {
162
163 { ngx_string("quic"), NULL, ngx_stream_variable_quic, 0, 0, 0 },
164
165 ngx_stream_null_variable
166 };
167
168
169 static ngx_int_t
170 ngx_stream_variable_quic(ngx_stream_session_t *s,
171 ngx_stream_variable_value_t *v, uintptr_t data)
172 {
173 if (s->connection->qs) {
174
175 v->len = 4;
176 v->valid = 1;
177 v->no_cacheable = 1;
178 v->not_found = 0;
179 v->data = (u_char *) "quic";
180 return NGX_OK;
181 }
182
183 v->not_found = 1;
184
185 return NGX_OK;
186 }
187
188
189 static ngx_int_t
190 ngx_stream_quic_add_variables(ngx_conf_t *cf)
191 {
192 ngx_stream_variable_t *var, *v;
193
194 for (v = ngx_stream_quic_vars; v->name.len; v++) {
195 var = ngx_stream_add_variable(cf, &v->name, v->flags);
196 if (var == NULL) {
197 return NGX_ERROR;
198 }
199
200 var->get_handler = v->get_handler;
201 var->data = v->data;
202 }
203
204 return NGX_OK;
205 }
206
207
208 static void *
209 ngx_stream_quic_create_srv_conf(ngx_conf_t *cf)
210 {
211 ngx_quic_conf_t *conf;
212
213 conf = ngx_pcalloc(cf->pool, sizeof(ngx_quic_conf_t));
214 if (conf == NULL) {
215 return NULL;
216 }
217
218 /*
219 * set by ngx_pcalloc():
220 *
221 * conf->tp.original_dcid = { 0, NULL };
222 * conf->tp.initial_scid = { 0, NULL };
223 * conf->tp.retry_scid = { 0, NULL };
224 * conf->tp.stateless_reset_token = { 0 }
225 * conf->tp.preferred_address = NULL
226 * conf->require_alpn = 0;
227 */
228
229 conf->tp.max_idle_timeout = NGX_CONF_UNSET_MSEC;
230 conf->tp.max_ack_delay = NGX_CONF_UNSET_MSEC;
231 conf->tp.max_udp_payload_size = NGX_CONF_UNSET_SIZE;
232 conf->tp.initial_max_data = NGX_CONF_UNSET_SIZE;
233 conf->tp.initial_max_stream_data_bidi_local = NGX_CONF_UNSET_SIZE;
234 conf->tp.initial_max_stream_data_bidi_remote = NGX_CONF_UNSET_SIZE;
235 conf->tp.initial_max_stream_data_uni = NGX_CONF_UNSET_SIZE;
236 conf->tp.initial_max_streams_bidi = NGX_CONF_UNSET_UINT;
237 conf->tp.initial_max_streams_uni = NGX_CONF_UNSET_UINT;
238 conf->tp.ack_delay_exponent = NGX_CONF_UNSET_UINT;
239 conf->tp.disable_active_migration = NGX_CONF_UNSET_UINT;
240 conf->tp.active_connection_id_limit = NGX_CONF_UNSET_UINT;
241
242 conf->retry = NGX_CONF_UNSET;
243
244 return conf;
245 }
246
247
248 static char *
249 ngx_stream_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
250 {
251 ngx_quic_conf_t *prev = parent;
252 ngx_quic_conf_t *conf = child;
253
254 ngx_conf_merge_msec_value(conf->tp.max_idle_timeout,
255 prev->tp.max_idle_timeout, 60000);
256
257 ngx_conf_merge_msec_value(conf->tp.max_ack_delay,
258 prev->tp.max_ack_delay,
259 NGX_QUIC_DEFAULT_MAX_ACK_DELAY);
260
261 ngx_conf_merge_size_value(conf->tp.max_udp_payload_size,
262 prev->tp.max_udp_payload_size,
263 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE);
264
265 ngx_conf_merge_size_value(conf->tp.initial_max_data,
266 prev->tp.initial_max_data,
267 16 * NGX_QUIC_STREAM_BUFSIZE);
268
269 ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_bidi_local,
270 prev->tp.initial_max_stream_data_bidi_local,
271 NGX_QUIC_STREAM_BUFSIZE);
272
273 ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_bidi_remote,
274 prev->tp.initial_max_stream_data_bidi_remote,
275 NGX_QUIC_STREAM_BUFSIZE);
276
277 ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_uni,
278 prev->tp.initial_max_stream_data_uni,
279 NGX_QUIC_STREAM_BUFSIZE);
280
281 ngx_conf_merge_uint_value(conf->tp.initial_max_streams_bidi,
282 prev->tp.initial_max_streams_bidi, 16);
283
284 ngx_conf_merge_uint_value(conf->tp.initial_max_streams_uni,
285 prev->tp.initial_max_streams_uni, 16);
286
287 ngx_conf_merge_uint_value(conf->tp.ack_delay_exponent,
288 prev->tp.ack_delay_exponent,
289 NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT);
290
291 ngx_conf_merge_uint_value(conf->tp.disable_active_migration,
292 prev->tp.disable_active_migration, 1);
293
294 ngx_conf_merge_uint_value(conf->tp.active_connection_id_limit,
295 prev->tp.active_connection_id_limit, 2);
296
297 ngx_conf_merge_value(conf->retry, prev->retry, 0);
298
299 if (conf->retry) {
300 if (RAND_bytes(conf->token_key, sizeof(conf->token_key)) <= 0) {
301 return NGX_CONF_ERROR;
302 }
303 }
304
305 return NGX_CONF_OK;
306 }
307
308
309 static char *
310 ngx_stream_quic_max_ack_delay(ngx_conf_t *cf, void *post, void *data)
311 {
312 ngx_msec_t *sp = data;
313
314 if (*sp > 16384) {
315 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
316 "\"quic_max_ack_delay\" must be less than 16384");
317
318 return NGX_CONF_ERROR;
319 }
320
321 return NGX_CONF_OK;
322 }
323
324
325 static char *
326 ngx_stream_quic_max_udp_payload_size(ngx_conf_t *cf, void *post, void *data)
327 {
328 size_t *sp = data;
329
330 if (*sp < NGX_QUIC_MIN_INITIAL_SIZE
331 || *sp > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE)
332 {
333 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
334 "\"quic_max_udp_payload_size\" must be between "
335 "%d and %d",
336 NGX_QUIC_MIN_INITIAL_SIZE,
337 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE);
338
339 return NGX_CONF_ERROR;
340 }
341
342 return NGX_CONF_OK;
343 }