0
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
|
4 */
|
|
5
|
|
6
|
|
7 #include <ngx_config.h>
|
|
8 #include <ngx_core.h>
|
|
9 #include <ngx_http.h>
|
|
10
|
|
11
|
|
12 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
378
|
13 static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
|
|
14 ngx_http_core_main_conf_t *cmcf);
|
|
15 static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
|
|
16 ngx_http_core_main_conf_t *cmcf);
|
|
17 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
|
|
18 ngx_http_core_main_conf_t *cmcf);
|
|
19
|
|
20 static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf,
|
|
21 ngx_array_t *servers, ngx_array_t *in_ports);
|
448
|
22 static ngx_int_t ngx_http_add_ports(ngx_conf_t *cf,
|
|
23 ngx_http_core_srv_conf_t *cscf, ngx_array_t *ports,
|
|
24 ngx_http_listen_t *listen);
|
|
25 static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
|
|
26 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
|
|
27 ngx_http_listen_t *listen);
|
4
|
28 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
|
448
|
29 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
|
378
|
30 ngx_http_listen_t *listen);
|
4
|
31 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
|
448
|
32 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
|
378
|
33
|
0
|
34 static char *ngx_http_merge_locations(ngx_conf_t *cf,
|
378
|
35 ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
|
48
|
36 ngx_uint_t ctx_index);
|
378
|
37 static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
|
|
38 ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
|
|
39 static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
|
|
40 ngx_http_core_loc_conf_t *pclcf);
|
|
41 static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
|
|
42 const ngx_queue_t *two);
|
|
43 static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
|
|
44 ngx_queue_t *locations);
|
|
45 static void ngx_http_create_locations_list(ngx_queue_t *locations,
|
|
46 ngx_queue_t *q);
|
|
47 static ngx_http_location_tree_node_t *
|
|
48 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
|
|
49 size_t prefix);
|
|
50
|
|
51 static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
|
448
|
52 ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
|
|
53 static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
|
|
54 ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
|
|
55 static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
|
142
|
56 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
|
|
57 const void *two);
|
0
|
58
|
378
|
59 static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
|
448
|
60 ngx_http_conf_port_t *port);
|
|
61 static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
|
|
62 ngx_http_conf_addr_t *addr);
|
|
63 static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
|
|
64 ngx_http_conf_addr_t *addr);
|
|
65 #if (NGX_HAVE_INET6)
|
|
66 static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
|
|
67 ngx_http_conf_addr_t *addr);
|
|
68 #endif
|
142
|
69
|
378
|
70 ngx_uint_t ngx_http_max_module;
|
0
|
71
|
|
72
|
|
73 ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
|
|
74 ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
|
|
75
|
|
76
|
394
|
77 ngx_str_t ngx_http_html_default_types[] = {
|
|
78 ngx_string("text/html"),
|
|
79 ngx_null_string
|
|
80 };
|
|
81
|
|
82
|
0
|
83 static ngx_command_t ngx_http_commands[] = {
|
|
84
|
48
|
85 { ngx_string("http"),
|
|
86 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
|
|
87 ngx_http_block,
|
|
88 0,
|
|
89 0,
|
|
90 NULL },
|
0
|
91
|
48
|
92 ngx_null_command
|
0
|
93 };
|
|
94
|
126
|
95
|
0
|
96 static ngx_core_module_t ngx_http_module_ctx = {
|
|
97 ngx_string("http"),
|
|
98 NULL,
|
|
99 NULL
|
126
|
100 };
|
0
|
101
|
|
102
|
|
103 ngx_module_t ngx_http_module = {
|
58
|
104 NGX_MODULE_V1,
|
0
|
105 &ngx_http_module_ctx, /* module context */
|
|
106 ngx_http_commands, /* module directives */
|
|
107 NGX_CORE_MODULE, /* module type */
|
90
|
108 NULL, /* init master */
|
0
|
109 NULL, /* init module */
|
90
|
110 NULL, /* init process */
|
|
111 NULL, /* init thread */
|
|
112 NULL, /* exit thread */
|
|
113 NULL, /* exit process */
|
|
114 NULL, /* exit master */
|
|
115 NGX_MODULE_V1_PADDING
|
0
|
116 };
|
|
117
|
|
118
|
48
|
119 static char *
|
|
120 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
0
|
121 {
|
|
122 char *rv;
|
378
|
123 ngx_uint_t mi, m, s;
|
0
|
124 ngx_conf_t pcf;
|
378
|
125 ngx_array_t in_ports;
|
0
|
126 ngx_http_module_t *module;
|
|
127 ngx_http_conf_ctx_t *ctx;
|
|
128 ngx_http_core_loc_conf_t *clcf;
|
378
|
129 ngx_http_core_srv_conf_t **cscfp;
|
0
|
130 ngx_http_core_main_conf_t *cmcf;
|
|
131
|
|
132 /* the main http context */
|
26
|
133
|
50
|
134 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
|
|
135 if (ctx == NULL) {
|
34
|
136 return NGX_CONF_ERROR;
|
|
137 }
|
0
|
138
|
|
139 *(ngx_http_conf_ctx_t **) conf = ctx;
|
|
140
|
34
|
141
|
0
|
142 /* count the number of the http modules and set up their indices */
|
|
143
|
|
144 ngx_http_max_module = 0;
|
|
145 for (m = 0; ngx_modules[m]; m++) {
|
|
146 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
|
|
147 continue;
|
|
148 }
|
|
149
|
|
150 ngx_modules[m]->ctx_index = ngx_http_max_module++;
|
|
151 }
|
|
152
|
26
|
153
|
34
|
154 /* the http main_conf context, it is the same in the all http contexts */
|
0
|
155
|
34
|
156 ctx->main_conf = ngx_pcalloc(cf->pool,
|
|
157 sizeof(void *) * ngx_http_max_module);
|
|
158 if (ctx->main_conf == NULL) {
|
|
159 return NGX_CONF_ERROR;
|
|
160 }
|
0
|
161
|
|
162
|
34
|
163 /*
|
|
164 * the http null srv_conf context, it is used to merge
|
|
165 * the server{}s' srv_conf's
|
|
166 */
|
|
167
|
|
168 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
|
|
169 if (ctx->srv_conf == NULL) {
|
|
170 return NGX_CONF_ERROR;
|
|
171 }
|
|
172
|
|
173
|
|
174 /*
|
|
175 * the http null loc_conf context, it is used to merge
|
|
176 * the server{}s' loc_conf's
|
|
177 */
|
|
178
|
|
179 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
|
|
180 if (ctx->loc_conf == NULL) {
|
|
181 return NGX_CONF_ERROR;
|
|
182 }
|
|
183
|
|
184
|
|
185 /*
|
|
186 * create the main_conf's, the null srv_conf's, and the null loc_conf's
|
|
187 * of the all http modules
|
|
188 */
|
0
|
189
|
|
190 for (m = 0; ngx_modules[m]; m++) {
|
|
191 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
|
|
192 continue;
|
|
193 }
|
|
194
|
|
195 module = ngx_modules[m]->ctx;
|
|
196 mi = ngx_modules[m]->ctx_index;
|
|
197
|
|
198 if (module->create_main_conf) {
|
50
|
199 ctx->main_conf[mi] = module->create_main_conf(cf);
|
|
200 if (ctx->main_conf[mi] == NULL) {
|
34
|
201 return NGX_CONF_ERROR;
|
|
202 }
|
0
|
203 }
|
|
204
|
|
205 if (module->create_srv_conf) {
|
50
|
206 ctx->srv_conf[mi] = module->create_srv_conf(cf);
|
|
207 if (ctx->srv_conf[mi] == NULL) {
|
34
|
208 return NGX_CONF_ERROR;
|
|
209 }
|
0
|
210 }
|
|
211
|
|
212 if (module->create_loc_conf) {
|
50
|
213 ctx->loc_conf[mi] = module->create_loc_conf(cf);
|
|
214 if (ctx->loc_conf[mi] == NULL) {
|
34
|
215 return NGX_CONF_ERROR;
|
|
216 }
|
0
|
217 }
|
|
218 }
|
|
219
|
58
|
220 pcf = *cf;
|
|
221 cf->ctx = ctx;
|
|
222
|
|
223 for (m = 0; ngx_modules[m]; m++) {
|
|
224 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
|
|
225 continue;
|
|
226 }
|
|
227
|
|
228 module = ngx_modules[m]->ctx;
|
|
229
|
|
230 if (module->preconfiguration) {
|
|
231 if (module->preconfiguration(cf) != NGX_OK) {
|
|
232 return NGX_CONF_ERROR;
|
|
233 }
|
|
234 }
|
|
235 }
|
34
|
236
|
0
|
237 /* parse inside the http{} block */
|
|
238
|
|
239 cf->module_type = NGX_HTTP_MODULE;
|
|
240 cf->cmd_type = NGX_HTTP_MAIN_CONF;
|
|
241 rv = ngx_conf_parse(cf, NULL);
|
|
242
|
|
243 if (rv != NGX_CONF_OK) {
|
378
|
244 goto failed;
|
0
|
245 }
|
|
246
|
|
247 /*
|
|
248 * init http{} main_conf's, merge the server{}s' srv_conf's
|
|
249 * and its location{}s' loc_conf's
|
|
250 */
|
|
251
|
|
252 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
|
|
253 cscfp = cmcf->servers.elts;
|
|
254
|
|
255 for (m = 0; ngx_modules[m]; m++) {
|
|
256 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
|
|
257 continue;
|
|
258 }
|
|
259
|
|
260 module = ngx_modules[m]->ctx;
|
|
261 mi = ngx_modules[m]->ctx_index;
|
|
262
|
|
263 /* init http{} main_conf's */
|
|
264
|
|
265 if (module->init_main_conf) {
|
|
266 rv = module->init_main_conf(cf, ctx->main_conf[mi]);
|
|
267 if (rv != NGX_CONF_OK) {
|
378
|
268 goto failed;
|
0
|
269 }
|
|
270 }
|
|
271
|
|
272 for (s = 0; s < cmcf->servers.nelts; s++) {
|
|
273
|
|
274 /* merge the server{}s' srv_conf's */
|
|
275
|
|
276 if (module->merge_srv_conf) {
|
378
|
277 rv = module->merge_srv_conf(cf, ctx->srv_conf[mi],
|
0
|
278 cscfp[s]->ctx->srv_conf[mi]);
|
|
279 if (rv != NGX_CONF_OK) {
|
378
|
280 goto failed;
|
0
|
281 }
|
|
282 }
|
|
283
|
|
284 if (module->merge_loc_conf) {
|
|
285
|
|
286 /* merge the server{}'s loc_conf */
|
|
287
|
378
|
288 rv = module->merge_loc_conf(cf, ctx->loc_conf[mi],
|
0
|
289 cscfp[s]->ctx->loc_conf[mi]);
|
|
290 if (rv != NGX_CONF_OK) {
|
378
|
291 goto failed;
|
0
|
292 }
|
|
293
|
|
294 /* merge the locations{}' loc_conf's */
|
|
295
|
378
|
296 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
|
|
297
|
|
298 rv = ngx_http_merge_locations(cf, clcf->locations,
|
0
|
299 cscfp[s]->ctx->loc_conf,
|
|
300 module, mi);
|
|
301 if (rv != NGX_CONF_OK) {
|
378
|
302 goto failed;
|
0
|
303 }
|
|
304 }
|
|
305 }
|
|
306 }
|
|
307
|
34
|
308
|
378
|
309 /* create location trees */
|
34
|
310
|
378
|
311 for (s = 0; s < cmcf->servers.nelts; s++) {
|
122
|
312
|
378
|
313 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
|
0
|
314
|
378
|
315 if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
|
|
316 return NGX_CONF_ERROR;
|
|
317 }
|
122
|
318
|
378
|
319 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
|
|
320 return NGX_CONF_ERROR;
|
|
321 }
|
34
|
322 }
|
|
323
|
0
|
324
|
378
|
325 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
|
130
|
326 return NGX_CONF_ERROR;
|
|
327 }
|
|
328
|
378
|
329 if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
|
198
|
330 return NGX_CONF_ERROR;
|
|
331 }
|
|
332
|
58
|
333
|
|
334 for (m = 0; ngx_modules[m]; m++) {
|
|
335 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
|
|
336 continue;
|
|
337 }
|
|
338
|
|
339 module = ngx_modules[m]->ctx;
|
|
340
|
|
341 if (module->postconfiguration) {
|
|
342 if (module->postconfiguration(cf) != NGX_OK) {
|
|
343 return NGX_CONF_ERROR;
|
|
344 }
|
|
345 }
|
|
346 }
|
|
347
|
122
|
348 if (ngx_http_variables_init_vars(cf) != NGX_OK) {
|
|
349 return NGX_CONF_ERROR;
|
|
350 }
|
58
|
351
|
|
352 /*
|
|
353 * http{}'s cf->ctx was needed while the configuration merging
|
|
354 * and in postconfiguration process
|
|
355 */
|
|
356
|
|
357 *cf = pcf;
|
|
358
|
56
|
359
|
378
|
360 if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
|
|
361 return NGX_CONF_ERROR;
|
|
362 }
|
|
363
|
|
364
|
|
365 /*
|
|
366 * create the lists of ports, addresses and server names
|
|
367 * to find quickly the server core module configuration at run-time
|
|
368 */
|
|
369
|
|
370 if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) {
|
|
371 return NGX_CONF_ERROR;
|
|
372 }
|
|
373
|
|
374
|
|
375 /* optimize the lists of ports, addresses and server names */
|
|
376
|
|
377 if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) {
|
|
378 return NGX_CONF_ERROR;
|
|
379 }
|
|
380
|
|
381 return NGX_CONF_OK;
|
|
382
|
|
383 failed:
|
|
384
|
|
385 *cf = pcf;
|
|
386
|
|
387 return rv;
|
|
388 }
|
|
389
|
|
390
|
|
391 static ngx_int_t
|
|
392 ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
|
|
393 {
|
|
394 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
|
|
395 cf->pool, 1, sizeof(ngx_http_handler_pt))
|
|
396 != NGX_OK)
|
|
397 {
|
|
398 return NGX_ERROR;
|
|
399 }
|
|
400
|
|
401 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
|
|
402 cf->pool, 1, sizeof(ngx_http_handler_pt))
|
|
403 != NGX_OK)
|
|
404 {
|
|
405 return NGX_ERROR;
|
|
406 }
|
|
407
|
|
408 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
|
|
409 cf->pool, 1, sizeof(ngx_http_handler_pt))
|
|
410 != NGX_OK)
|
|
411 {
|
|
412 return NGX_ERROR;
|
|
413 }
|
|
414
|
|
415 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
|
|
416 cf->pool, 1, sizeof(ngx_http_handler_pt))
|
|
417 != NGX_OK)
|
|
418 {
|
|
419 return NGX_ERROR;
|
|
420 }
|
|
421
|
|
422 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
|
|
423 cf->pool, 2, sizeof(ngx_http_handler_pt))
|
|
424 != NGX_OK)
|
|
425 {
|
|
426 return NGX_ERROR;
|
|
427 }
|
|
428
|
|
429 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
|
|
430 cf->pool, 4, sizeof(ngx_http_handler_pt))
|
|
431 != NGX_OK)
|
|
432 {
|
|
433 return NGX_ERROR;
|
|
434 }
|
|
435
|
|
436 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
|
|
437 cf->pool, 1, sizeof(ngx_http_handler_pt))
|
|
438 != NGX_OK)
|
|
439 {
|
|
440 return NGX_ERROR;
|
|
441 }
|
|
442
|
|
443 return NGX_OK;
|
|
444 }
|
|
445
|
|
446
|
|
447 static ngx_int_t
|
|
448 ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
|
|
449 {
|
|
450 ngx_array_t headers_in;
|
|
451 ngx_hash_key_t *hk;
|
|
452 ngx_hash_init_t hash;
|
|
453 ngx_http_header_t *header;
|
|
454
|
|
455 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
|
|
456 != NGX_OK)
|
|
457 {
|
|
458 return NGX_ERROR;
|
|
459 }
|
|
460
|
|
461 for (header = ngx_http_headers_in; header->name.len; header++) {
|
|
462 hk = ngx_array_push(&headers_in);
|
|
463 if (hk == NULL) {
|
|
464 return NGX_ERROR;
|
|
465 }
|
|
466
|
|
467 hk->key = header->name;
|
|
468 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
|
|
469 hk->value = header;
|
|
470 }
|
|
471
|
|
472 hash.hash = &cmcf->headers_in_hash;
|
|
473 hash.key = ngx_hash_key_lc;
|
|
474 hash.max_size = 512;
|
|
475 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
|
|
476 hash.name = "headers_in_hash";
|
|
477 hash.pool = cf->pool;
|
|
478 hash.temp_pool = NULL;
|
|
479
|
|
480 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
|
|
481 return NGX_ERROR;
|
|
482 }
|
|
483
|
|
484 return NGX_OK;
|
|
485 }
|
|
486
|
|
487
|
|
488 static ngx_int_t
|
|
489 ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
|
|
490 {
|
|
491 ngx_int_t j;
|
|
492 ngx_uint_t i, n;
|
|
493 ngx_uint_t find_config_index, use_rewrite, use_access;
|
|
494 ngx_http_handler_pt *h;
|
|
495 ngx_http_phase_handler_t *ph;
|
|
496 ngx_http_phase_handler_pt checker;
|
|
497
|
230
|
498 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
|
324
|
499 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
|
230
|
500 find_config_index = 0;
|
|
501 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
|
|
502 use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
|
|
503
|
430
|
504 n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;
|
230
|
505
|
|
506 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
|
|
507 n += cmcf->phases[i].handlers.nelts;
|
|
508 }
|
|
509
|
|
510 ph = ngx_pcalloc(cf->pool,
|
|
511 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
|
|
512 if (ph == NULL) {
|
378
|
513 return NGX_ERROR;
|
230
|
514 }
|
|
515
|
|
516 cmcf->phase_engine.handlers = ph;
|
|
517 n = 0;
|
|
518
|
|
519 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
|
|
520 h = cmcf->phases[i].handlers.elts;
|
|
521
|
|
522 switch (i) {
|
|
523
|
|
524 case NGX_HTTP_SERVER_REWRITE_PHASE:
|
|
525 if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
|
|
526 cmcf->phase_engine.server_rewrite_index = n;
|
|
527 }
|
|
528 checker = ngx_http_core_generic_phase;
|
|
529
|
|
530 break;
|
|
531
|
|
532 case NGX_HTTP_FIND_CONFIG_PHASE:
|
|
533 find_config_index = n;
|
|
534
|
|
535 ph->checker = ngx_http_core_find_config_phase;
|
|
536 n++;
|
|
537 ph++;
|
|
538
|
|
539 continue;
|
|
540
|
324
|
541 case NGX_HTTP_REWRITE_PHASE:
|
|
542 if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
|
|
543 cmcf->phase_engine.location_rewrite_index = n;
|
|
544 }
|
|
545 checker = ngx_http_core_generic_phase;
|
|
546
|
|
547 break;
|
|
548
|
230
|
549 case NGX_HTTP_POST_REWRITE_PHASE:
|
|
550 if (use_rewrite) {
|
|
551 ph->checker = ngx_http_core_post_rewrite_phase;
|
|
552 ph->next = find_config_index;
|
|
553 n++;
|
|
554 ph++;
|
|
555 }
|
|
556
|
|
557 continue;
|
|
558
|
|
559 case NGX_HTTP_ACCESS_PHASE:
|
|
560 checker = ngx_http_core_access_phase;
|
|
561 n++;
|
|
562 break;
|
|
563
|
|
564 case NGX_HTTP_POST_ACCESS_PHASE:
|
|
565 if (use_access) {
|
|
566 ph->checker = ngx_http_core_post_access_phase;
|
|
567 ph->next = n;
|
|
568 ph++;
|
|
569 }
|
|
570
|
|
571 continue;
|
|
572
|
430
|
573 case NGX_HTTP_TRY_FILES_PHASE:
|
|
574 if (cmcf->try_files) {
|
|
575 ph->checker = ngx_http_core_try_files_phase;
|
|
576 n++;
|
|
577 ph++;
|
|
578 }
|
|
579
|
|
580 continue;
|
|
581
|
230
|
582 case NGX_HTTP_CONTENT_PHASE:
|
|
583 checker = ngx_http_core_content_phase;
|
|
584 break;
|
|
585
|
|
586 default:
|
|
587 checker = ngx_http_core_generic_phase;
|
|
588 }
|
|
589
|
|
590 n += cmcf->phases[i].handlers.nelts;
|
|
591
|
|
592 for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
|
|
593 ph->checker = checker;
|
|
594 ph->handler = h[j];
|
|
595 ph->next = n;
|
|
596 ph++;
|
|
597 }
|
|
598 }
|
|
599
|
378
|
600 return NGX_OK;
|
|
601 }
|
230
|
602
|
378
|
603
|
|
604 static char *
|
|
605 ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
|
|
606 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
|
|
607 {
|
|
608 char *rv;
|
|
609 ngx_queue_t *q;
|
|
610 ngx_http_core_loc_conf_t *clcf;
|
|
611 ngx_http_location_queue_t *lq;
|
|
612
|
|
613 if (locations == NULL) {
|
|
614 return NGX_CONF_OK;
|
|
615 }
|
|
616
|
|
617 for (q = ngx_queue_head(locations);
|
|
618 q != ngx_queue_sentinel(locations);
|
|
619 q = ngx_queue_next(q))
|
|
620 {
|
|
621 lq = (ngx_http_location_queue_t *) q;
|
|
622
|
|
623 clcf = lq->exact ? lq->exact : lq->inclusive;
|
|
624
|
|
625 rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
|
|
626 clcf->loc_conf[ctx_index]);
|
|
627 if (rv != NGX_CONF_OK) {
|
|
628 return rv;
|
|
629 }
|
|
630
|
|
631 rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
|
|
632 module, ctx_index);
|
|
633 if (rv != NGX_CONF_OK) {
|
|
634 return rv;
|
|
635 }
|
|
636 }
|
|
637
|
|
638 return NGX_CONF_OK;
|
|
639 }
|
|
640
|
|
641
|
|
642 static ngx_int_t
|
|
643 ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|
644 ngx_http_core_loc_conf_t *pclcf)
|
|
645 {
|
|
646 ngx_uint_t n;
|
|
647 ngx_queue_t *q, *locations, *named, tail;
|
|
648 ngx_http_core_loc_conf_t *clcf;
|
|
649 ngx_http_location_queue_t *lq;
|
|
650 ngx_http_core_loc_conf_t **clcfp;
|
|
651 #if (NGX_PCRE)
|
|
652 ngx_uint_t r;
|
|
653 ngx_queue_t *regex;
|
|
654 #endif
|
|
655
|
|
656 locations = pclcf->locations;
|
|
657
|
|
658 if (locations == NULL) {
|
|
659 return NGX_OK;
|
|
660 }
|
|
661
|
|
662 ngx_queue_sort(locations, ngx_http_cmp_locations);
|
|
663
|
|
664 named = NULL;
|
|
665 n = 0;
|
|
666 #if (NGX_PCRE)
|
|
667 regex = NULL;
|
|
668 r = 0;
|
|
669 #endif
|
|
670
|
|
671 for (q = ngx_queue_head(locations);
|
|
672 q != ngx_queue_sentinel(locations);
|
|
673 q = ngx_queue_next(q))
|
|
674 {
|
|
675 lq = (ngx_http_location_queue_t *) q;
|
|
676
|
|
677 clcf = lq->exact ? lq->exact : lq->inclusive;
|
|
678
|
|
679 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
|
|
680 return NGX_ERROR;
|
|
681 }
|
|
682
|
|
683 #if (NGX_PCRE)
|
|
684
|
|
685 if (clcf->regex) {
|
|
686 r++;
|
|
687
|
|
688 if (regex == NULL) {
|
|
689 regex = q;
|
|
690 }
|
|
691
|
|
692 continue;
|
|
693 }
|
|
694
|
|
695 #endif
|
|
696
|
|
697 if (clcf->named) {
|
|
698 n++;
|
|
699
|
|
700 if (named == NULL) {
|
|
701 named = q;
|
|
702 }
|
|
703
|
|
704 continue;
|
|
705 }
|
|
706
|
|
707 if (clcf->noname) {
|
|
708 break;
|
|
709 }
|
|
710 }
|
|
711
|
|
712 if (q != ngx_queue_sentinel(locations)) {
|
|
713 ngx_queue_split(locations, q, &tail);
|
|
714 }
|
|
715
|
|
716 if (named) {
|
|
717 clcfp = ngx_palloc(cf->pool,
|
|
718 (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
|
|
719 if (clcfp == NULL) {
|
|
720 return NGX_ERROR;
|
|
721 }
|
|
722
|
|
723 cscf->named_locations = clcfp;
|
|
724
|
|
725 for (q = named;
|
|
726 q != ngx_queue_sentinel(locations);
|
|
727 q = ngx_queue_next(q))
|
|
728 {
|
|
729 lq = (ngx_http_location_queue_t *) q;
|
|
730
|
|
731 *(clcfp++) = lq->exact;
|
|
732 }
|
|
733
|
|
734 *clcfp = NULL;
|
|
735
|
|
736 ngx_queue_split(locations, named, &tail);
|
|
737 }
|
|
738
|
|
739 #if (NGX_PCRE)
|
|
740
|
|
741 if (regex) {
|
|
742
|
|
743 clcfp = ngx_palloc(cf->pool,
|
|
744 (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
|
|
745 if (clcfp == NULL) {
|
|
746 return NGX_ERROR;
|
|
747 }
|
|
748
|
|
749 pclcf->regex_locations = clcfp;
|
|
750
|
|
751 for (q = regex;
|
|
752 q != ngx_queue_sentinel(locations);
|
|
753 q = ngx_queue_next(q))
|
|
754 {
|
|
755 lq = (ngx_http_location_queue_t *) q;
|
|
756
|
|
757 *(clcfp++) = lq->exact;
|
|
758 }
|
|
759
|
|
760 *clcfp = NULL;
|
|
761
|
|
762 ngx_queue_split(locations, regex, &tail);
|
|
763 }
|
|
764
|
|
765 #endif
|
|
766
|
|
767 return NGX_OK;
|
|
768 }
|
|
769
|
|
770
|
|
771 static ngx_int_t
|
|
772 ngx_http_init_static_location_trees(ngx_conf_t *cf,
|
|
773 ngx_http_core_loc_conf_t *pclcf)
|
|
774 {
|
|
775 ngx_queue_t *q, *locations;
|
|
776 ngx_http_core_loc_conf_t *clcf;
|
|
777 ngx_http_location_queue_t *lq;
|
|
778
|
|
779 locations = pclcf->locations;
|
|
780
|
|
781 if (locations == NULL) {
|
|
782 return NGX_OK;
|
|
783 }
|
|
784
|
|
785 if (ngx_queue_empty(locations)) {
|
|
786 return NGX_OK;
|
|
787 }
|
|
788
|
|
789 for (q = ngx_queue_head(locations);
|
|
790 q != ngx_queue_sentinel(locations);
|
|
791 q = ngx_queue_next(q))
|
|
792 {
|
|
793 lq = (ngx_http_location_queue_t *) q;
|
|
794
|
|
795 clcf = lq->exact ? lq->exact : lq->inclusive;
|
|
796
|
|
797 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
|
|
798 return NGX_ERROR;
|
|
799 }
|
|
800 }
|
|
801
|
|
802 if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
|
|
803 return NGX_ERROR;
|
|
804 }
|
|
805
|
|
806 ngx_http_create_locations_list(locations, ngx_queue_head(locations));
|
|
807
|
|
808 pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
|
|
809 if (pclcf->static_locations == NULL) {
|
|
810 return NGX_ERROR;
|
|
811 }
|
|
812
|
|
813 return NGX_OK;
|
|
814 }
|
|
815
|
|
816
|
|
817 ngx_int_t
|
|
818 ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
|
|
819 ngx_http_core_loc_conf_t *clcf)
|
|
820 {
|
|
821 ngx_http_location_queue_t *lq;
|
|
822
|
|
823 if (*locations == NULL) {
|
|
824 *locations = ngx_palloc(cf->temp_pool,
|
|
825 sizeof(ngx_http_location_queue_t));
|
|
826 if (*locations == NULL) {
|
|
827 return NGX_ERROR;
|
|
828 }
|
|
829
|
|
830 ngx_queue_init(*locations);
|
|
831 }
|
|
832
|
|
833 lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
|
|
834 if (lq == NULL) {
|
|
835 return NGX_ERROR;
|
|
836 }
|
|
837
|
|
838 if (clcf->exact_match
|
|
839 #if (NGX_PCRE)
|
|
840 || clcf->regex
|
|
841 #endif
|
|
842 || clcf->named || clcf->noname)
|
|
843 {
|
|
844 lq->exact = clcf;
|
|
845 lq->inclusive = NULL;
|
|
846
|
|
847 } else {
|
|
848 lq->exact = NULL;
|
|
849 lq->inclusive = clcf;
|
|
850 }
|
|
851
|
|
852 lq->name = &clcf->name;
|
|
853 lq->file_name = cf->conf_file->file.name.data;
|
|
854 lq->line = cf->conf_file->line;
|
|
855
|
|
856 ngx_queue_init(&lq->list);
|
|
857
|
|
858 ngx_queue_insert_tail(*locations, &lq->queue);
|
0
|
859
|
378
|
860 return NGX_OK;
|
|
861 }
|
|
862
|
|
863
|
|
864 static ngx_int_t
|
|
865 ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
|
|
866 {
|
|
867 ngx_int_t rc;
|
|
868 ngx_http_core_loc_conf_t *first, *second;
|
|
869 ngx_http_location_queue_t *lq1, *lq2;
|
|
870
|
|
871 lq1 = (ngx_http_location_queue_t *) one;
|
|
872 lq2 = (ngx_http_location_queue_t *) two;
|
|
873
|
|
874 first = lq1->exact ? lq1->exact : lq1->inclusive;
|
|
875 second = lq2->exact ? lq2->exact : lq2->inclusive;
|
|
876
|
|
877 if (first->noname && !second->noname) {
|
|
878 /* shift no named locations to the end */
|
|
879 return 1;
|
|
880 }
|
|
881
|
|
882 if (!first->noname && second->noname) {
|
|
883 /* shift no named locations to the end */
|
|
884 return -1;
|
|
885 }
|
|
886
|
|
887 if (first->noname || second->noname) {
|
|
888 /* do not sort no named locations */
|
|
889 return 0;
|
|
890 }
|
|
891
|
|
892 if (first->named && !second->named) {
|
|
893 /* shift named locations to the end */
|
|
894 return 1;
|
|
895 }
|
|
896
|
|
897 if (!first->named && second->named) {
|
|
898 /* shift named locations to the end */
|
|
899 return -1;
|
|
900 }
|
|
901
|
|
902 if (first->named && second->named) {
|
|
903 return ngx_strcmp(first->name.data, second->name.data);
|
|
904 }
|
|
905
|
|
906 #if (NGX_PCRE)
|
|
907
|
|
908 if (first->regex && !second->regex) {
|
|
909 /* shift the regex matches to the end */
|
|
910 return 1;
|
|
911 }
|
|
912
|
|
913 if (!first->regex && second->regex) {
|
|
914 /* shift the regex matches to the end */
|
|
915 return -1;
|
|
916 }
|
|
917
|
|
918 if (first->regex || second->regex) {
|
|
919 /* do not sort the regex matches */
|
|
920 return 0;
|
|
921 }
|
|
922
|
|
923 #endif
|
|
924
|
|
925 rc = ngx_strcmp(first->name.data, second->name.data);
|
|
926
|
|
927 if (rc == 0 && !first->exact_match && second->exact_match) {
|
|
928 /* an exact match must be before the same inclusive one */
|
|
929 return 1;
|
|
930 }
|
|
931
|
|
932 return rc;
|
|
933 }
|
|
934
|
|
935
|
|
936 static ngx_int_t
|
|
937 ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
|
|
938 {
|
|
939 ngx_queue_t *q, *x;
|
|
940 ngx_http_location_queue_t *lq, *lx;
|
|
941
|
|
942 q = ngx_queue_head(locations);
|
|
943
|
|
944 while (q != ngx_queue_last(locations)) {
|
|
945
|
|
946 x = ngx_queue_next(q);
|
|
947
|
|
948 lq = (ngx_http_location_queue_t *) q;
|
|
949 lx = (ngx_http_location_queue_t *) x;
|
|
950
|
|
951 if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
|
|
952
|
|
953 if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
|
|
954 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
|
955 "duplicate location \"%V\" in %s:%ui",
|
|
956 lx->name, lx->file_name, lx->line);
|
|
957
|
|
958 return NGX_ERROR;
|
|
959 }
|
|
960
|
|
961 lq->inclusive = lx->inclusive;
|
|
962
|
|
963 ngx_queue_remove(x);
|
|
964
|
|
965 continue;
|
|
966 }
|
|
967
|
|
968 q = ngx_queue_next(q);
|
|
969 }
|
|
970
|
|
971 return NGX_OK;
|
|
972 }
|
|
973
|
|
974
|
|
975 static void
|
|
976 ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
|
|
977 {
|
|
978 u_char *name;
|
|
979 size_t len;
|
|
980 ngx_queue_t *x, tail;
|
|
981 ngx_http_location_queue_t *lq, *lx;
|
|
982
|
|
983 if (q == ngx_queue_last(locations)) {
|
|
984 return;
|
|
985 }
|
|
986
|
|
987 lq = (ngx_http_location_queue_t *) q;
|
|
988
|
|
989 if (lq->inclusive == NULL) {
|
|
990 ngx_http_create_locations_list(locations, ngx_queue_next(q));
|
|
991 return;
|
|
992 }
|
|
993
|
|
994 len = lq->name->len;
|
|
995 name = lq->name->data;
|
|
996
|
|
997 for (x = ngx_queue_next(q);
|
|
998 x != ngx_queue_sentinel(locations);
|
|
999 x = ngx_queue_next(x))
|
|
1000 {
|
|
1001 lx = (ngx_http_location_queue_t *) x;
|
|
1002
|
|
1003 if (len > lx->name->len
|
|
1004 || (ngx_strncmp(name, lx->name->data, len) != 0))
|
|
1005 {
|
|
1006 break;
|
|
1007 }
|
|
1008 }
|
|
1009
|
|
1010 q = ngx_queue_next(q);
|
|
1011
|
|
1012 if (q == x) {
|
|
1013 ngx_http_create_locations_list(locations, x);
|
|
1014 return;
|
|
1015 }
|
|
1016
|
|
1017 ngx_queue_split(locations, q, &tail);
|
|
1018 ngx_queue_add(&lq->list, &tail);
|
|
1019
|
|
1020 if (x == ngx_queue_sentinel(locations)) {
|
|
1021 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
|
|
1022 return;
|
|
1023 }
|
|
1024
|
|
1025 ngx_queue_split(&lq->list, x, &tail);
|
|
1026 ngx_queue_add(locations, &tail);
|
|
1027
|
|
1028 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
|
|
1029
|
|
1030 ngx_http_create_locations_list(locations, x);
|
|
1031 }
|
|
1032
|
|
1033
|
|
1034 /*
|
|
1035 * to keep cache locality for left leaf nodes, allocate nodes in following
|
|
1036 * order: node, left subtree, right subtree, inclusive subtree
|
|
1037 */
|
|
1038
|
|
1039 static ngx_http_location_tree_node_t *
|
|
1040 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
|
|
1041 size_t prefix)
|
|
1042 {
|
|
1043 size_t len;
|
|
1044 ngx_queue_t *q, tail;
|
|
1045 ngx_http_location_queue_t *lq;
|
|
1046 ngx_http_location_tree_node_t *node;
|
|
1047
|
|
1048 q = ngx_queue_middle(locations);
|
|
1049
|
|
1050 lq = (ngx_http_location_queue_t *) q;
|
|
1051 len = lq->name->len - prefix;
|
|
1052
|
382
|
1053 node = ngx_palloc(cf->pool,
|
|
1054 offsetof(ngx_http_location_tree_node_t, name) + len);
|
378
|
1055 if (node == NULL) {
|
|
1056 return NULL;
|
|
1057 }
|
|
1058
|
380
|
1059 node->left = NULL;
|
|
1060 node->right = NULL;
|
|
1061 node->tree = NULL;
|
378
|
1062 node->exact = lq->exact;
|
|
1063 node->inclusive = lq->inclusive;
|
|
1064
|
|
1065 node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
|
|
1066 || (lq->inclusive && lq->inclusive->auto_redirect));
|
|
1067
|
|
1068 node->len = (u_char) len;
|
|
1069 ngx_memcpy(node->name, &lq->name->data[prefix], len);
|
|
1070
|
|
1071 ngx_queue_split(locations, q, &tail);
|
|
1072
|
|
1073 if (ngx_queue_empty(locations)) {
|
|
1074 /*
|
|
1075 * ngx_queue_split() insures that if left part is empty,
|
|
1076 * then right one is empty too
|
|
1077 */
|
|
1078 goto inclusive;
|
|
1079 }
|
|
1080
|
|
1081 node->left = ngx_http_create_locations_tree(cf, locations, prefix);
|
|
1082 if (node->left == NULL) {
|
|
1083 return NULL;
|
|
1084 }
|
|
1085
|
|
1086 ngx_queue_remove(q);
|
|
1087
|
|
1088 if (ngx_queue_empty(&tail)) {
|
|
1089 goto inclusive;
|
|
1090 }
|
|
1091
|
|
1092 node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
|
|
1093 if (node->right == NULL) {
|
|
1094 return NULL;
|
|
1095 }
|
|
1096
|
|
1097 inclusive:
|
|
1098
|
|
1099 if (ngx_queue_empty(&lq->list)) {
|
|
1100 return node;
|
|
1101 }
|
|
1102
|
|
1103 node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
|
|
1104 if (node->tree == NULL) {
|
|
1105 return NULL;
|
|
1106 }
|
|
1107
|
|
1108 return node;
|
|
1109 }
|
|
1110
|
|
1111
|
|
1112 static ngx_int_t
|
|
1113 ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
|
448
|
1114 ngx_array_t *ports)
|
378
|
1115 {
|
448
|
1116 ngx_uint_t s, i;
|
378
|
1117 ngx_http_listen_t *listen;
|
|
1118 ngx_http_core_srv_conf_t **cscfp;
|
|
1119
|
448
|
1120 if (ngx_array_init(ports, cf->temp_pool, 2, sizeof(ngx_http_conf_port_t))
|
50
|
1121 != NGX_OK)
|
4
|
1122 {
|
378
|
1123 return NGX_ERROR;
|
4
|
1124 }
|
0
|
1125
|
|
1126 /* "server" directives */
|
4
|
1127
|
378
|
1128 cscfp = servers->elts;
|
|
1129 for (s = 0; s < servers->nelts; s++) {
|
0
|
1130
|
|
1131 /* "listen" directives */
|
4
|
1132
|
378
|
1133 listen = cscfp[s]->listen.elts;
|
448
|
1134 for (i = 0; i < cscfp[s]->listen.nelts; i++) {
|
|
1135
|
|
1136 if (ngx_http_add_ports(cf, cscfp[s], ports, &listen[i]) != NGX_OK) {
|
378
|
1137 return NGX_ERROR;
|
142
|
1138 }
|
0
|
1139 }
|
|
1140 }
|
|
1141
|
378
|
1142 return NGX_OK;
|
0
|
1143 }
|
|
1144
|
|
1145
|
448
|
1146 static ngx_int_t
|
|
1147 ngx_http_add_ports(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|
1148 ngx_array_t *ports, ngx_http_listen_t *listen)
|
|
1149 {
|
|
1150 in_port_t p;
|
|
1151 ngx_uint_t i;
|
|
1152 struct sockaddr *sa;
|
|
1153 struct sockaddr_in *sin;
|
|
1154 ngx_http_conf_port_t *port;
|
|
1155 #if (NGX_HAVE_INET6)
|
|
1156 struct sockaddr_in6 *sin6;
|
|
1157 #endif
|
|
1158
|
|
1159 sa = (struct sockaddr *) &listen->sockaddr;
|
|
1160
|
|
1161 switch (sa->sa_family) {
|
|
1162
|
|
1163 #if (NGX_HAVE_INET6)
|
|
1164 case AF_INET6:
|
|
1165 sin6 = (struct sockaddr_in6 *) sa;
|
|
1166 p = sin6->sin6_port;
|
|
1167 break;
|
|
1168 #endif
|
|
1169
|
|
1170 default: /* AF_INET */
|
|
1171 sin = (struct sockaddr_in *) sa;
|
|
1172 p = sin->sin_port;
|
|
1173 break;
|
|
1174 }
|
|
1175
|
|
1176 port = ports->elts;
|
|
1177 for (i = 0; i < ports->nelts; i++) {
|
|
1178
|
|
1179 if (p != port[i].port || sa->sa_family != port[i].family) {
|
|
1180 continue;
|
|
1181 }
|
|
1182
|
|
1183 /* a port is already in the in_port list */
|
|
1184
|
|
1185 return ngx_http_add_addresses(cf, cscf, &port[i], listen);
|
|
1186 }
|
|
1187
|
|
1188 /* add a port to the in_port list */
|
|
1189
|
|
1190 port = ngx_array_push(ports);
|
|
1191 if (port == NULL) {
|
|
1192 return NGX_ERROR;
|
|
1193 }
|
|
1194
|
|
1195 port->family = sa->sa_family;
|
|
1196 port->port = p;
|
|
1197 port->addrs.elts = NULL;
|
|
1198
|
|
1199 return ngx_http_add_address(cf, cscf, port, listen);
|
|
1200 }
|
|
1201
|
|
1202
|
|
1203 static ngx_int_t
|
|
1204 ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|
1205 ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
|
|
1206 {
|
|
1207 u_char *p;
|
|
1208 size_t len, off;
|
|
1209 ngx_uint_t i;
|
|
1210 struct sockaddr *sa;
|
|
1211 ngx_http_conf_addr_t *addr;
|
|
1212
|
|
1213 /*
|
|
1214 * we can not compare whole sockaddr struct's as kernel
|
|
1215 * may fill some fields in inherited sockaddr struct's
|
|
1216 */
|
|
1217
|
|
1218 sa = (struct sockaddr *) &listen->sockaddr;
|
|
1219
|
|
1220 switch (sa->sa_family) {
|
|
1221
|
|
1222 #if (NGX_HAVE_INET6)
|
|
1223 case AF_INET6:
|
|
1224 off = offsetof(struct sockaddr_in6, sin6_addr);
|
|
1225 len = 16;
|
|
1226 break;
|
|
1227 #endif
|
|
1228
|
|
1229 default: /* AF_INET */
|
|
1230 off = offsetof(struct sockaddr_in, sin_addr);
|
|
1231 len = 4;
|
|
1232 break;
|
|
1233 }
|
|
1234
|
|
1235 p = listen->sockaddr + off;
|
|
1236
|
|
1237 addr = port->addrs.elts;
|
|
1238
|
|
1239 for (i = 0; i < port->addrs.nelts; i++) {
|
|
1240
|
|
1241 if (ngx_memcmp(p, (u_char *) addr[i].sockaddr + off, len) != 0) {
|
|
1242 continue;
|
|
1243 }
|
|
1244
|
|
1245 /* the address is already in the address list */
|
|
1246
|
|
1247 if (ngx_http_add_names(cf, cscf, &addr[i]) != NGX_OK) {
|
|
1248 return NGX_ERROR;
|
|
1249 }
|
|
1250
|
|
1251 /* check the duplicate "default" server for this address:port */
|
|
1252
|
|
1253 if (listen->conf.default_server) {
|
|
1254
|
|
1255 if (addr[i].default_server) {
|
|
1256 ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
|
1257 "the duplicate default server in %s:%ui",
|
|
1258 listen->file_name, listen->line);
|
|
1259
|
|
1260 return NGX_ERROR;
|
|
1261 }
|
|
1262
|
|
1263 addr[i].core_srv_conf = cscf;
|
|
1264 addr[i].default_server = 1;
|
|
1265 #if (NGX_HTTP_SSL)
|
|
1266 addr[i].ssl = listen->conf.ssl;
|
|
1267 #endif
|
|
1268 addr[i].listen_conf = &listen->conf;
|
|
1269 }
|
|
1270
|
|
1271 return NGX_OK;
|
|
1272 }
|
|
1273
|
|
1274 /* add the address to the addresses list that bound to this port */
|
|
1275
|
|
1276 return ngx_http_add_address(cf, cscf, port, listen);
|
|
1277 }
|
|
1278
|
|
1279
|
4
|
1280 /*
|
|
1281 * add the server address, the server names and the server core module
|
|
1282 * configurations to the port (in_port)
|
|
1283 */
|
|
1284
|
48
|
1285 static ngx_int_t
|
378
|
1286 ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
448
|
1287 ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
|
4
|
1288 {
|
448
|
1289 ngx_http_conf_addr_t *addr;
|
|
1290
|
|
1291 if (port->addrs.elts == NULL) {
|
|
1292 if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
|
|
1293 sizeof(ngx_http_conf_addr_t))
|
326
|
1294 != NGX_OK)
|
4
|
1295 {
|
|
1296 return NGX_ERROR;
|
|
1297 }
|
|
1298 }
|
|
1299
|
448
|
1300 addr = ngx_array_push(&port->addrs);
|
|
1301 if (addr == NULL) {
|
4
|
1302 return NGX_ERROR;
|
|
1303 }
|
|
1304
|
448
|
1305 addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
|
|
1306 addr->socklen = listen->socklen;
|
|
1307 addr->hash.buckets = NULL;
|
|
1308 addr->hash.size = 0;
|
|
1309 addr->wc_head = NULL;
|
|
1310 addr->wc_tail = NULL;
|
|
1311 addr->names.elts = NULL;
|
326
|
1312 #if (NGX_PCRE)
|
448
|
1313 addr->nregex = 0;
|
|
1314 addr->regex = NULL;
|
326
|
1315 #endif
|
448
|
1316 addr->core_srv_conf = cscf;
|
|
1317 addr->default_server = listen->conf.default_server;
|
|
1318 addr->bind = listen->conf.bind;
|
|
1319 addr->wildcard = listen->conf.wildcard;
|
404
|
1320 #if (NGX_HTTP_SSL)
|
448
|
1321 addr->ssl = listen->conf.ssl;
|
404
|
1322 #endif
|
448
|
1323 addr->listen_conf = &listen->conf;
|
|
1324
|
|
1325 return ngx_http_add_names(cf, cscf, addr);
|
4
|
1326 }
|
|
1327
|
|
1328
|
|
1329 /*
|
|
1330 * add the server names and the server core module
|
448
|
1331 * configurations to the address:port
|
4
|
1332 */
|
|
1333
|
48
|
1334 static ngx_int_t
|
378
|
1335 ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
448
|
1336 ngx_http_conf_addr_t *addr)
|
4
|
1337 {
|
392
|
1338 ngx_uint_t i;
|
4
|
1339 ngx_http_server_name_t *server_names, *name;
|
|
1340
|
448
|
1341 if (addr->names.elts == NULL) {
|
|
1342 if (ngx_array_init(&addr->names, cf->temp_pool, 4,
|
326
|
1343 sizeof(ngx_http_server_name_t))
|
|
1344 != NGX_OK)
|
26
|
1345 {
|
|
1346 return NGX_ERROR;
|
|
1347 }
|
|
1348 }
|
|
1349
|
4
|
1350 server_names = cscf->server_names.elts;
|
326
|
1351
|
4
|
1352 for (i = 0; i < cscf->server_names.nelts; i++) {
|
|
1353
|
392
|
1354 ngx_strlow(server_names[i].name.data, server_names[i].name.data,
|
|
1355 server_names[i].name.len);
|
26
|
1356
|
4
|
1357 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
|
10
|
1358 "name: %V", &server_names[i].name);
|
4
|
1359
|
448
|
1360 name = ngx_array_push(&addr->names);
|
50
|
1361 if (name == NULL) {
|
4
|
1362 return NGX_ERROR;
|
|
1363 }
|
|
1364
|
|
1365 *name = server_names[i];
|
|
1366 }
|
|
1367
|
|
1368 return NGX_OK;
|
|
1369 }
|
|
1370
|
|
1371
|
378
|
1372 static ngx_int_t
|
|
1373 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
|
448
|
1374 ngx_array_t *ports)
|
|
1375 {
|
|
1376 ngx_uint_t s, p, a;
|
|
1377 ngx_http_conf_port_t *port;
|
|
1378 ngx_http_conf_addr_t *addr;
|
|
1379 ngx_http_server_name_t *name;
|
|
1380
|
|
1381 port = ports->elts;
|
|
1382 for (p = 0; p < ports->nelts; p++) {
|
|
1383
|
|
1384 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
|
|
1385 sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
|
|
1386
|
|
1387 /*
|
|
1388 * check whether all name-based servers have the same
|
|
1389 * configuraiton as a default server for given address:port
|
|
1390 */
|
|
1391
|
|
1392 addr = port[p].addrs.elts;
|
|
1393 for (a = 0; a < port[p].addrs.nelts; a++) {
|
|
1394
|
|
1395 name = addr[a].names.elts;
|
|
1396 for (s = 0; s < addr[a].names.nelts; s++) {
|
|
1397
|
|
1398 if (addr[a].core_srv_conf == name[s].core_srv_conf) {
|
|
1399 continue;
|
|
1400 }
|
|
1401
|
|
1402 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
|
|
1403 return NGX_ERROR;
|
|
1404 }
|
|
1405
|
|
1406 break;
|
|
1407 }
|
|
1408 }
|
|
1409
|
|
1410 if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
|
|
1411 return NGX_ERROR;
|
|
1412 }
|
|
1413 }
|
|
1414
|
|
1415 return NGX_OK;
|
|
1416 }
|
|
1417
|
|
1418
|
|
1419 static ngx_int_t
|
|
1420 ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
|
|
1421 ngx_http_conf_addr_t *addr)
|
0
|
1422 {
|
378
|
1423 ngx_int_t rc;
|
448
|
1424 ngx_uint_t s;
|
378
|
1425 ngx_hash_init_t hash;
|
|
1426 ngx_http_server_name_t *name;
|
|
1427 ngx_hash_keys_arrays_t ha;
|
|
1428 #if (NGX_PCRE)
|
380
|
1429 ngx_uint_t regex, i;
|
448
|
1430
|
|
1431 regex = 0;
|
378
|
1432 #endif
|
|
1433
|
448
|
1434 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
|
|
1435
|
|
1436 ha.temp_pool = ngx_create_pool(16384, cf->log);
|
|
1437 if (ha.temp_pool == NULL) {
|
|
1438 return NGX_ERROR;
|
|
1439 }
|
|
1440
|
|
1441 ha.pool = cf->pool;
|
|
1442
|
|
1443 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
|
|
1444 goto failed;
|
|
1445 }
|
|
1446
|
|
1447 name = addr->names.elts;
|
|
1448
|
|
1449 for (s = 0; s < addr->names.nelts; s++) {
|
378
|
1450
|
|
1451 #if (NGX_PCRE)
|
448
|
1452 if (name[s].regex) {
|
|
1453 regex++;
|
|
1454 continue;
|
|
1455 }
|
378
|
1456 #endif
|
|
1457
|
448
|
1458 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
|
|
1459 NGX_HASH_WILDCARD_KEY);
|
|
1460
|
|
1461 if (rc == NGX_ERROR) {
|
|
1462 return NGX_ERROR;
|
|
1463 }
|
|
1464
|
|
1465 if (rc == NGX_DECLINED) {
|
|
1466 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
|
1467 "invalid server name or wildcard \"%V\" on %s",
|
|
1468 &name[s].name, addr->listen_conf->addr);
|
|
1469 return NGX_ERROR;
|
|
1470 }
|
|
1471
|
|
1472 if (rc == NGX_BUSY) {
|
|
1473 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
|
|
1474 "conflicting server name \"%V\" on %s, ignored",
|
|
1475 &name[s].name, addr->listen_conf->addr);
|
|
1476 }
|
|
1477 }
|
|
1478
|
|
1479 hash.key = ngx_hash_key_lc;
|
|
1480 hash.max_size = cmcf->server_names_hash_max_size;
|
|
1481 hash.bucket_size = cmcf->server_names_hash_bucket_size;
|
|
1482 hash.name = "server_names_hash";
|
|
1483 hash.pool = cf->pool;
|
|
1484
|
|
1485 if (ha.keys.nelts) {
|
|
1486 hash.hash = &addr->hash;
|
|
1487 hash.temp_pool = NULL;
|
|
1488
|
|
1489 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
|
|
1490 goto failed;
|
|
1491 }
|
|
1492 }
|
|
1493
|
|
1494 if (ha.dns_wc_head.nelts) {
|
|
1495
|
|
1496 ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
|
|
1497 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
|
|
1498
|
|
1499 hash.hash = NULL;
|
|
1500 hash.temp_pool = ha.temp_pool;
|
|
1501
|
|
1502 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
|
|
1503 ha.dns_wc_head.nelts)
|
|
1504 != NGX_OK)
|
|
1505 {
|
|
1506 goto failed;
|
|
1507 }
|
|
1508
|
|
1509 addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
|
|
1510 }
|
|
1511
|
|
1512 if (ha.dns_wc_tail.nelts) {
|
|
1513
|
|
1514 ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
|
|
1515 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
|
|
1516
|
|
1517 hash.hash = NULL;
|
|
1518 hash.temp_pool = ha.temp_pool;
|
|
1519
|
|
1520 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
|
|
1521 ha.dns_wc_tail.nelts)
|
|
1522 != NGX_OK)
|
|
1523 {
|
|
1524 goto failed;
|
|
1525 }
|
|
1526
|
|
1527 addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
|
|
1528 }
|
|
1529
|
|
1530 ngx_destroy_pool(ha.temp_pool);
|
378
|
1531
|
|
1532 #if (NGX_PCRE)
|
|
1533
|
448
|
1534 if (regex == 0) {
|
|
1535 return NGX_OK;
|
|
1536 }
|
|
1537
|
|
1538 addr->nregex = regex;
|
|
1539 addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
|
|
1540 if (addr->regex == NULL) {
|
|
1541 return NGX_ERROR;
|
|
1542 }
|
|
1543
|
|
1544 for (i = 0, s = 0; s < addr->names.nelts; s++) {
|
|
1545 if (name[s].regex) {
|
|
1546 addr->regex[i++] = name[s];
|
0
|
1547 }
|
|
1548 }
|
|
1549
|
448
|
1550 #endif
|
|
1551
|
378
|
1552 return NGX_OK;
|
|
1553
|
|
1554 failed:
|
|
1555
|
|
1556 ngx_destroy_pool(ha.temp_pool);
|
|
1557
|
|
1558 return NGX_ERROR;
|
0
|
1559 }
|
142
|
1560
|
|
1561
|
372
|
1562 static ngx_int_t
|
448
|
1563 ngx_http_cmp_conf_addrs(const void *one, const void *two)
|
142
|
1564 {
|
448
|
1565 ngx_http_conf_addr_t *first, *second;
|
|
1566
|
|
1567 first = (ngx_http_conf_addr_t *) one;
|
|
1568 second = (ngx_http_conf_addr_t *) two;
|
|
1569
|
|
1570 if (first->wildcard) {
|
|
1571 /* a wildcard address must be the last resort, shift it to the end */
|
142
|
1572 return 1;
|
|
1573 }
|
|
1574
|
|
1575 if (first->bind && !second->bind) {
|
|
1576 /* shift explicit bind()ed addresses to the start */
|
|
1577 return -1;
|
|
1578 }
|
|
1579
|
|
1580 if (!first->bind && second->bind) {
|
|
1581 /* shift explicit bind()ed addresses to the start */
|
|
1582 return 1;
|
|
1583 }
|
|
1584
|
|
1585 /* do not sort by default */
|
|
1586
|
|
1587 return 0;
|
|
1588 }
|
|
1589
|
|
1590
|
|
1591 static int ngx_libc_cdecl
|
|
1592 ngx_http_cmp_dns_wildcards(const void *one, const void *two)
|
|
1593 {
|
|
1594 ngx_hash_key_t *first, *second;
|
|
1595
|
|
1596 first = (ngx_hash_key_t *) one;
|
|
1597 second = (ngx_hash_key_t *) two;
|
|
1598
|
|
1599 return ngx_strcmp(first->key.data, second->key.data);
|
|
1600 }
|
378
|
1601
|
|
1602
|
|
1603 static ngx_int_t
|
448
|
1604 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
|
378
|
1605 {
|
448
|
1606 ngx_uint_t i, a, last, bind_wildcard;
|
378
|
1607 ngx_listening_t *ls;
|
448
|
1608 ngx_http_port_t *hport;
|
|
1609 ngx_http_conf_addr_t *addr;
|
|
1610
|
|
1611 addr = port->addrs.elts;
|
|
1612 last = port->addrs.nelts;
|
378
|
1613
|
|
1614 /*
|
448
|
1615 * If there is a binding to an "*:port" then we need to bind() to
|
|
1616 * the "*:port" only and ignore other implicit bindings. The bindings
|
|
1617 * have been already sorted: explicit bindings are on the start, then
|
|
1618 * implicit bindings go, and wildcard binding is in the end.
|
378
|
1619 */
|
|
1620
|
448
|
1621 if (addr[last - 1].wildcard) {
|
|
1622 addr[last - 1].bind = 1;
|
|
1623 bind_wildcard = 1;
|
378
|
1624
|
|
1625 } else {
|
448
|
1626 bind_wildcard = 0;
|
378
|
1627 }
|
|
1628
|
|
1629 a = 0;
|
|
1630
|
|
1631 while (a < last) {
|
|
1632
|
448
|
1633 if (bind_wildcard && !addr[a].bind) {
|
378
|
1634 a++;
|
|
1635 continue;
|
|
1636 }
|
|
1637
|
448
|
1638 ls = ngx_http_add_listening(cf, &addr[a]);
|
378
|
1639 if (ls == NULL) {
|
|
1640 return NGX_ERROR;
|
|
1641 }
|
|
1642
|
448
|
1643 hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
|
|
1644 if (hport == NULL) {
|
378
|
1645 return NGX_ERROR;
|
|
1646 }
|
|
1647
|
448
|
1648 ls->servers = hport;
|
|
1649
|
|
1650 hport->port = ntohs(port->port);
|
|
1651
|
|
1652 for (i = ls->addr_text.len - 1; i; i--) {
|
|
1653
|
|
1654 if (ls->addr_text.data[i] == ':') {
|
|
1655 hport->port_text.len = ls->addr_text.len - i;
|
|
1656 hport->port_text.data = &ls->addr_text.data[i];
|
|
1657 break;
|
|
1658 }
|
|
1659 }
|
|
1660
|
|
1661 if (a == last - 1) {
|
|
1662 hport->naddrs = last;
|
378
|
1663
|
|
1664 } else {
|
448
|
1665 hport->naddrs = 1;
|
|
1666 a = 0;
|
378
|
1667 }
|
|
1668
|
448
|
1669 switch (ls->sockaddr->sa_family) {
|
|
1670
|
|
1671 #if (NGX_HAVE_INET6)
|
|
1672 case AF_INET6:
|
|
1673 if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
|
378
|
1674 return NGX_ERROR;
|
|
1675 }
|
448
|
1676 break;
|
378
|
1677 #endif
|
448
|
1678 default: /* AF_INET */
|
|
1679 if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
|
|
1680 return NGX_ERROR;
|
|
1681 }
|
|
1682 break;
|
378
|
1683 }
|
|
1684
|
448
|
1685 addr++;
|
378
|
1686 last--;
|
|
1687 }
|
|
1688
|
|
1689 return NGX_OK;
|
|
1690 }
|
392
|
1691
|
|
1692
|
448
|
1693 static ngx_listening_t *
|
|
1694 ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
|
|
1695 {
|
|
1696 ngx_listening_t *ls;
|
|
1697 struct sockaddr *sa;
|
|
1698 ngx_http_core_loc_conf_t *clcf;
|
|
1699 ngx_http_core_srv_conf_t *cscf;
|
|
1700 u_char text[NGX_SOCKADDR_STRLEN];
|
|
1701
|
|
1702 ls = ngx_array_push(&cf->cycle->listening);
|
|
1703 if (ls == NULL) {
|
|
1704 return NULL;
|
|
1705 }
|
|
1706
|
|
1707 ngx_memzero(ls, sizeof(ngx_listening_t));
|
|
1708
|
|
1709 sa = ngx_palloc(cf->pool, addr->socklen);
|
|
1710 if (sa == NULL) {
|
|
1711 return NULL;
|
|
1712 }
|
|
1713
|
|
1714 ngx_memcpy(sa, addr->sockaddr, addr->socklen);
|
|
1715
|
|
1716 ls->sockaddr = sa;
|
|
1717 ls->socklen = addr->socklen;
|
|
1718
|
|
1719 ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
|
|
1720
|
|
1721 ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len);
|
|
1722 if (ls->addr_text.data == NULL) {
|
|
1723 return NULL;
|
|
1724 }
|
|
1725
|
|
1726 ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len);
|
|
1727
|
|
1728 ls->fd = (ngx_socket_t) -1;
|
|
1729 ls->type = SOCK_STREAM;
|
|
1730
|
|
1731 switch (ls->sockaddr->sa_family) {
|
|
1732 #if (NGX_HAVE_INET6)
|
|
1733 case AF_INET6:
|
|
1734 ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
|
|
1735 break;
|
|
1736 #endif
|
|
1737 case AF_INET:
|
|
1738 ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
|
|
1739 break;
|
|
1740 default:
|
|
1741 ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
|
|
1742 break;
|
|
1743 }
|
|
1744
|
|
1745 ls->addr_ntop = 1;
|
|
1746
|
|
1747 ls->handler = ngx_http_init_connection;
|
|
1748
|
|
1749 cscf = addr->core_srv_conf;
|
|
1750 ls->pool_size = cscf->connection_pool_size;
|
|
1751 ls->post_accept_timeout = cscf->client_header_timeout;
|
|
1752
|
|
1753 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
|
|
1754
|
|
1755 ls->log = *clcf->err_log;
|
|
1756 ls->log.data = &ls->addr_text;
|
|
1757 ls->log.handler = ngx_accept_log_error;
|
|
1758
|
|
1759 #if (NGX_WIN32)
|
|
1760 {
|
|
1761 ngx_iocp_conf_t *iocpcf;
|
|
1762
|
|
1763 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
|
|
1764 if (iocpcf->acceptex_read) {
|
|
1765 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
|
|
1766 }
|
|
1767 }
|
|
1768 #endif
|
|
1769
|
|
1770 ls->backlog = addr->listen_conf->backlog;
|
|
1771 ls->rcvbuf = addr->listen_conf->rcvbuf;
|
|
1772 ls->sndbuf = addr->listen_conf->sndbuf;
|
|
1773
|
|
1774 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
|
1775 ls->accept_filter = addr->listen_conf->accept_filter;
|
|
1776 #endif
|
|
1777
|
|
1778 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
|
|
1779 ls->deferred_accept = addr->listen_conf->deferred_accept;
|
|
1780 #endif
|
|
1781
|
|
1782 return ls;
|
|
1783 }
|
|
1784
|
|
1785
|
|
1786 static ngx_int_t
|
|
1787 ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
|
|
1788 ngx_http_conf_addr_t *addr)
|
|
1789 {
|
|
1790 ngx_uint_t i;
|
|
1791 ngx_http_in_addr_t *addrs;
|
|
1792 struct sockaddr_in *sin;
|
|
1793 ngx_http_virtual_names_t *vn;
|
|
1794
|
|
1795 hport->addrs = ngx_pcalloc(cf->pool,
|
|
1796 hport->naddrs * sizeof(ngx_http_in_addr_t));
|
|
1797 if (hport->addrs == NULL) {
|
|
1798 return NGX_ERROR;
|
|
1799 }
|
|
1800
|
|
1801 addrs = hport->addrs;
|
|
1802
|
|
1803 for (i = 0; i < hport->naddrs; i++) {
|
|
1804
|
|
1805 sin = (struct sockaddr_in *) addr[i].sockaddr;
|
|
1806 addrs[i].addr = sin->sin_addr.s_addr;
|
|
1807 addrs[i].conf.core_srv_conf = addr[i].core_srv_conf;
|
|
1808 #if (NGX_HTTP_SSL)
|
|
1809 addrs[i].conf.ssl = addr[i].ssl;
|
|
1810 #endif
|
|
1811
|
|
1812 if (addr[i].hash.buckets == NULL
|
|
1813 && (addr[i].wc_head == NULL
|
|
1814 || addr[i].wc_head->hash.buckets == NULL)
|
|
1815 && (addr[i].wc_head == NULL
|
|
1816 || addr[i].wc_head->hash.buckets == NULL))
|
|
1817 {
|
|
1818 continue;
|
|
1819 }
|
|
1820
|
|
1821 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
|
|
1822 if (vn == NULL) {
|
|
1823 return NGX_ERROR;
|
|
1824 }
|
|
1825
|
|
1826 addrs[i].conf.virtual_names = vn;
|
|
1827
|
|
1828 vn->names.hash = addr[i].hash;
|
|
1829 vn->names.wc_head = addr[i].wc_head;
|
|
1830 vn->names.wc_tail = addr[i].wc_tail;
|
|
1831 #if (NGX_PCRE)
|
|
1832 vn->nregex = addr[i].nregex;
|
|
1833 vn->regex = addr[i].regex;
|
|
1834 #endif
|
|
1835 }
|
|
1836
|
|
1837 return NGX_OK;
|
|
1838 }
|
|
1839
|
|
1840
|
|
1841 #if (NGX_HAVE_INET6)
|
|
1842
|
|
1843 static ngx_int_t
|
|
1844 ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
|
|
1845 ngx_http_conf_addr_t *addr)
|
|
1846 {
|
|
1847 ngx_uint_t i;
|
|
1848 ngx_http_in6_addr_t *addrs6;
|
|
1849 struct sockaddr_in6 *sin6;
|
|
1850 ngx_http_virtual_names_t *vn;
|
|
1851
|
|
1852 hport->addrs = ngx_pcalloc(cf->pool,
|
|
1853 hport->naddrs * sizeof(ngx_http_in6_addr_t));
|
|
1854 if (hport->addrs == NULL) {
|
|
1855 return NGX_ERROR;
|
|
1856 }
|
|
1857
|
|
1858 addrs6 = hport->addrs;
|
|
1859
|
|
1860 for (i = 0; i < hport->naddrs; i++) {
|
|
1861
|
|
1862 sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
|
|
1863 addrs6[i].addr6 = sin6->sin6_addr;
|
|
1864 addrs6[i].conf.core_srv_conf = addr[i].core_srv_conf;
|
|
1865 #if (NGX_HTTP_SSL)
|
|
1866 addrs6[i].conf.ssl = addr[i].ssl;
|
|
1867 #endif
|
|
1868
|
|
1869 if (addr[i].hash.buckets == NULL
|
|
1870 && (addr[i].wc_head == NULL
|
|
1871 || addr[i].wc_head->hash.buckets == NULL)
|
|
1872 && (addr[i].wc_head == NULL
|
|
1873 || addr[i].wc_head->hash.buckets == NULL))
|
|
1874 {
|
|
1875 continue;
|
|
1876 }
|
|
1877
|
|
1878 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
|
|
1879 if (vn == NULL) {
|
|
1880 return NGX_ERROR;
|
|
1881 }
|
|
1882
|
|
1883 addrs6[i].conf.virtual_names = vn;
|
|
1884
|
|
1885 vn->names.hash = addr[i].hash;
|
|
1886 vn->names.wc_head = addr[i].wc_head;
|
|
1887 vn->names.wc_tail = addr[i].wc_tail;
|
|
1888 #if (NGX_PCRE)
|
|
1889 vn->nregex = addr[i].nregex;
|
|
1890 vn->regex = addr[i].regex;
|
|
1891 #endif
|
|
1892 }
|
|
1893
|
|
1894 return NGX_OK;
|
|
1895 }
|
|
1896
|
|
1897 #endif
|
|
1898
|
|
1899
|
392
|
1900 char *
|
|
1901 ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|
1902 {
|
|
1903 char *p = conf;
|
|
1904
|
|
1905 ngx_array_t **types;
|
|
1906 ngx_str_t *value, *default_type;
|
|
1907 ngx_uint_t i, n, hash;
|
|
1908 ngx_hash_key_t *type;
|
|
1909
|
|
1910 types = (ngx_array_t **) (p + cmd->offset);
|
|
1911
|
|
1912 default_type = cmd->post;
|
|
1913
|
|
1914 if (*types == NULL) {
|
|
1915 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
|
|
1916 if (*types == NULL) {
|
|
1917 return NGX_CONF_ERROR;
|
|
1918 }
|
|
1919
|
|
1920 if (default_type) {
|
|
1921 type = ngx_array_push(*types);
|
|
1922 if (type == NULL) {
|
|
1923 return NGX_CONF_ERROR;
|
|
1924 }
|
|
1925
|
|
1926 type->key = *default_type;
|
|
1927 type->key_hash = ngx_hash_key(default_type->data,
|
|
1928 default_type->len);
|
|
1929 type->value = (void *) 4;
|
|
1930 }
|
|
1931 }
|
|
1932
|
|
1933 value = cf->args->elts;
|
|
1934
|
|
1935 for (i = 1; i < cf->args->nelts; i++) {
|
|
1936
|
|
1937 hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
|
|
1938 value[i].data[value[i].len] = '\0';
|
|
1939
|
|
1940 type = (*types)->elts;
|
|
1941 for (n = 0; n < (*types)->nelts; n++) {
|
|
1942
|
|
1943 if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
|
|
1944 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
|
1945 "duplicate MIME type \"%V\"", &value[i]);
|
|
1946 continue;
|
|
1947 }
|
|
1948 }
|
|
1949
|
|
1950 type = ngx_array_push(*types);
|
|
1951 if (type == NULL) {
|
|
1952 return NGX_CONF_ERROR;
|
|
1953 }
|
|
1954
|
|
1955 type->key = value[i];
|
|
1956 type->key_hash = hash;
|
|
1957 type->value = (void *) 4;
|
|
1958 }
|
|
1959
|
|
1960 return NGX_CONF_OK;
|
|
1961 }
|
|
1962
|
|
1963
|
|
1964 char *
|
|
1965 ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys, ngx_hash_t *types_hash,
|
396
|
1966 ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
|
392
|
1967 ngx_str_t *default_types)
|
|
1968 {
|
|
1969 ngx_hash_init_t hash;
|
|
1970
|
396
|
1971 if (keys) {
|
392
|
1972
|
396
|
1973 hash.hash = types_hash;
|
|
1974 hash.key = NULL;
|
|
1975 hash.max_size = 2048;
|
|
1976 hash.bucket_size = 64;
|
|
1977 hash.name = "test_types_hash";
|
|
1978 hash.pool = cf->pool;
|
|
1979 hash.temp_pool = NULL;
|
|
1980
|
|
1981 if (ngx_hash_init(&hash, keys->elts, keys->nelts) != NGX_OK) {
|
|
1982 return NGX_CONF_ERROR;
|
392
|
1983 }
|
|
1984
|
396
|
1985 return NGX_CONF_OK;
|
|
1986 }
|
|
1987
|
|
1988 if (prev_types_hash->buckets == NULL) {
|
|
1989
|
|
1990 if (prev_keys == NULL) {
|
|
1991
|
404
|
1992 if (ngx_http_set_default_types(cf, &prev_keys, default_types)
|
396
|
1993 != NGX_OK)
|
|
1994 {
|
404
|
1995 return NGX_CONF_ERROR;
|
|
1996 }
|
396
|
1997 }
|
|
1998
|
|
1999 hash.hash = prev_types_hash;
|
|
2000 hash.key = NULL;
|
|
2001 hash.max_size = 2048;
|
|
2002 hash.bucket_size = 64;
|
|
2003 hash.name = "test_types_hash";
|
|
2004 hash.pool = cf->pool;
|
|
2005 hash.temp_pool = NULL;
|
|
2006
|
|
2007 if (ngx_hash_init(&hash, prev_keys->elts, prev_keys->nelts) != NGX_OK) {
|
392
|
2008 return NGX_CONF_ERROR;
|
|
2009 }
|
|
2010 }
|
|
2011
|
396
|
2012 *types_hash = *prev_types_hash;
|
392
|
2013
|
|
2014 return NGX_CONF_OK;
|
|
2015
|
|
2016 }
|
|
2017
|
|
2018
|
396
|
2019 ngx_int_t
|
392
|
2020 ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
|
|
2021 ngx_str_t *default_type)
|
|
2022 {
|
|
2023 ngx_hash_key_t *type;
|
|
2024
|
|
2025 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
|
|
2026 if (*types == NULL) {
|
396
|
2027 return NGX_ERROR;
|
392
|
2028 }
|
|
2029
|
|
2030 while (default_type->len) {
|
|
2031
|
|
2032 type = ngx_array_push(*types);
|
|
2033 if (type == NULL) {
|
396
|
2034 return NGX_ERROR;
|
392
|
2035 }
|
|
2036
|
|
2037 type->key = *default_type;
|
|
2038 type->key_hash = ngx_hash_key(default_type->data,
|
|
2039 default_type->len);
|
|
2040 type->value = (void *) 4;
|
|
2041
|
|
2042 default_type++;
|
|
2043 }
|
|
2044
|
396
|
2045 return NGX_OK;
|
392
|
2046 }
|