comparison src/http/ngx_http.c @ 378:820f6378fc00 NGINX_0_7_1

nginx 0.7.1 *) Change: now locations are searched in a tree. *) Change: the "optimize_server_names" directive was canceled due to the "server_name_in_redirect" directive introduction. *) Change: some long deprecated directives are not supported anymore. *) Change: the "none" parameter in the "ssl_session_cache" directive; now this is default parameter. Thanks to Rob Mueller. *) Bugfix: worker processes might not catch reconfiguration and log rotation signals. *) Bugfix: nginx could not be built on latest Fedora 9 Linux. Thanks to Roxis.
author Igor Sysoev <http://sysoev.ru>
date Mon, 26 May 2008 00:00:00 +0400
parents 6639b93e81b2
children bc21d9cd9c54
comparison
equal deleted inserted replaced
377:5d98007adb5f 378:820f6378fc00
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <ngx_http.h> 10 #include <ngx_http.h>
11 11
12 12
13 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 13 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
14 static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
15 ngx_http_core_main_conf_t *cmcf);
16 static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
17 ngx_http_core_main_conf_t *cmcf);
18 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
19 ngx_http_core_main_conf_t *cmcf);
20
21 static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf,
22 ngx_array_t *servers, ngx_array_t *in_ports);
14 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, 23 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
15 ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *lscf, 24 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_port_t *in_port,
16 ngx_http_core_srv_conf_t *cscf); 25 ngx_http_listen_t *listen);
17 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf, 26 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
18 ngx_http_conf_in_addr_t *in_addr, ngx_http_core_srv_conf_t *cscf); 27 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_addr_t *in_addr);
28
19 static char *ngx_http_merge_locations(ngx_conf_t *cf, 29 static char *ngx_http_merge_locations(ngx_conf_t *cf,
20 ngx_array_t *locations, void **loc_conf, ngx_http_module_t *module, 30 ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
21 ngx_uint_t ctx_index); 31 ngx_uint_t ctx_index);
32 static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
33 ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
34 static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
35 ngx_http_core_loc_conf_t *pclcf);
36 static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
37 const ngx_queue_t *two);
38 static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
39 ngx_queue_t *locations);
40 static void ngx_http_create_locations_list(ngx_queue_t *locations,
41 ngx_queue_t *q);
42 static ngx_http_location_tree_node_t *
43 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
44 size_t prefix);
45
46 static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
47 ngx_http_core_main_conf_t *cmcf, ngx_array_t *in_ports);
22 static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two); 48 static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two);
23 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one, 49 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
24 const void *two); 50 const void *two);
25 51
52 static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
53 ngx_http_conf_in_port_t *in_port);
54
26 ngx_uint_t ngx_http_max_module; 55 ngx_uint_t ngx_http_max_module;
27
28 ngx_uint_t ngx_http_total_requests;
29 uint64_t ngx_http_total_sent;
30 56
31 57
32 ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r); 58 ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
33 ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch); 59 ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
34 60
71 97
72 static char * 98 static char *
73 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 99 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
74 { 100 {
75 char *rv; 101 char *rv;
76 ngx_int_t rc, j; 102 ngx_uint_t mi, m, s;
77 ngx_uint_t mi, m, s, l, p, a, i, n;
78 ngx_uint_t find_config_index, use_rewrite, use_access;
79 ngx_uint_t last, bind_all, done;
80 ngx_conf_t pcf; 103 ngx_conf_t pcf;
81 ngx_array_t headers_in, in_ports; 104 ngx_array_t in_ports;
82 ngx_hash_key_t *hk;
83 ngx_hash_init_t hash;
84 ngx_listening_t *ls;
85 ngx_http_listen_t *lscf;
86 ngx_http_module_t *module; 105 ngx_http_module_t *module;
87 ngx_http_header_t *header;
88 ngx_http_in_port_t *hip;
89 ngx_http_handler_pt *h;
90 ngx_http_conf_ctx_t *ctx; 106 ngx_http_conf_ctx_t *ctx;
91 ngx_http_conf_in_port_t *in_port;
92 ngx_http_conf_in_addr_t *in_addr;
93 ngx_hash_keys_arrays_t ha;
94 ngx_http_server_name_t *name;
95 ngx_http_phase_handler_t *ph;
96 ngx_http_virtual_names_t *vn;
97 ngx_http_core_srv_conf_t **cscfp, *cscf;
98 ngx_http_core_loc_conf_t *clcf; 107 ngx_http_core_loc_conf_t *clcf;
99 ngx_http_phase_handler_pt checker; 108 ngx_http_core_srv_conf_t **cscfp;
100 ngx_http_core_main_conf_t *cmcf; 109 ngx_http_core_main_conf_t *cmcf;
101 #if (NGX_PCRE)
102 ngx_uint_t regex;
103 #endif
104 110
105 /* the main http context */ 111 /* the main http context */
106 112
107 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); 113 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
108 if (ctx == NULL) { 114 if (ctx == NULL) {
197 if (ngx_modules[m]->type != NGX_HTTP_MODULE) { 203 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
198 continue; 204 continue;
199 } 205 }
200 206
201 module = ngx_modules[m]->ctx; 207 module = ngx_modules[m]->ctx;
202 mi = ngx_modules[m]->ctx_index;
203 208
204 if (module->preconfiguration) { 209 if (module->preconfiguration) {
205 if (module->preconfiguration(cf) != NGX_OK) { 210 if (module->preconfiguration(cf) != NGX_OK) {
206 return NGX_CONF_ERROR; 211 return NGX_CONF_ERROR;
207 } 212 }
213 cf->module_type = NGX_HTTP_MODULE; 218 cf->module_type = NGX_HTTP_MODULE;
214 cf->cmd_type = NGX_HTTP_MAIN_CONF; 219 cf->cmd_type = NGX_HTTP_MAIN_CONF;
215 rv = ngx_conf_parse(cf, NULL); 220 rv = ngx_conf_parse(cf, NULL);
216 221
217 if (rv != NGX_CONF_OK) { 222 if (rv != NGX_CONF_OK) {
218 *cf = pcf; 223 goto failed;
219 return rv;
220 } 224 }
221 225
222 /* 226 /*
223 * init http{} main_conf's, merge the server{}s' srv_conf's 227 * init http{} main_conf's, merge the server{}s' srv_conf's
224 * and its location{}s' loc_conf's 228 * and its location{}s' loc_conf's
238 /* init http{} main_conf's */ 242 /* init http{} main_conf's */
239 243
240 if (module->init_main_conf) { 244 if (module->init_main_conf) {
241 rv = module->init_main_conf(cf, ctx->main_conf[mi]); 245 rv = module->init_main_conf(cf, ctx->main_conf[mi]);
242 if (rv != NGX_CONF_OK) { 246 if (rv != NGX_CONF_OK) {
243 *cf = pcf; 247 goto failed;
244 return rv;
245 } 248 }
246 } 249 }
247 250
248 for (s = 0; s < cmcf->servers.nelts; s++) { 251 for (s = 0; s < cmcf->servers.nelts; s++) {
249 252
250 /* merge the server{}s' srv_conf's */ 253 /* merge the server{}s' srv_conf's */
251 254
252 if (module->merge_srv_conf) { 255 if (module->merge_srv_conf) {
253 rv = module->merge_srv_conf(cf, 256 rv = module->merge_srv_conf(cf, ctx->srv_conf[mi],
254 ctx->srv_conf[mi],
255 cscfp[s]->ctx->srv_conf[mi]); 257 cscfp[s]->ctx->srv_conf[mi]);
256 if (rv != NGX_CONF_OK) { 258 if (rv != NGX_CONF_OK) {
257 *cf = pcf; 259 goto failed;
258 return rv;
259 } 260 }
260 } 261 }
261 262
262 if (module->merge_loc_conf) { 263 if (module->merge_loc_conf) {
263 264
264 /* merge the server{}'s loc_conf */ 265 /* merge the server{}'s loc_conf */
265 266
266 rv = module->merge_loc_conf(cf, 267 rv = module->merge_loc_conf(cf, ctx->loc_conf[mi],
267 ctx->loc_conf[mi],
268 cscfp[s]->ctx->loc_conf[mi]); 268 cscfp[s]->ctx->loc_conf[mi]);
269 if (rv != NGX_CONF_OK) { 269 if (rv != NGX_CONF_OK) {
270 *cf = pcf; 270 goto failed;
271 return rv;
272 } 271 }
273 272
274 /* merge the locations{}' loc_conf's */ 273 /* merge the locations{}' loc_conf's */
275 274
276 rv = ngx_http_merge_locations(cf, &cscfp[s]->locations, 275 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
276
277 rv = ngx_http_merge_locations(cf, clcf->locations,
277 cscfp[s]->ctx->loc_conf, 278 cscfp[s]->ctx->loc_conf,
278 module, mi); 279 module, mi);
279 if (rv != NGX_CONF_OK) { 280 if (rv != NGX_CONF_OK) {
280 *cf = pcf; 281 goto failed;
281 return rv;
282 } 282 }
283 } 283 }
284 } 284 }
285 } 285 }
286 286
287 287
288 /* init lists of the handlers */ 288 /* create location trees */
289 289
290 for (s = 0; s < cmcf->servers.nelts; s++) {
291
292 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
293
294 if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
295 return NGX_CONF_ERROR;
296 }
297
298 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
299 return NGX_CONF_ERROR;
300 }
301 }
302
303
304 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
305 return NGX_CONF_ERROR;
306 }
307
308 if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
309 return NGX_CONF_ERROR;
310 }
311
312
313 for (m = 0; ngx_modules[m]; m++) {
314 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
315 continue;
316 }
317
318 module = ngx_modules[m]->ctx;
319
320 if (module->postconfiguration) {
321 if (module->postconfiguration(cf) != NGX_OK) {
322 return NGX_CONF_ERROR;
323 }
324 }
325 }
326
327 if (ngx_http_variables_init_vars(cf) != NGX_OK) {
328 return NGX_CONF_ERROR;
329 }
330
331 /*
332 * http{}'s cf->ctx was needed while the configuration merging
333 * and in postconfiguration process
334 */
335
336 *cf = pcf;
337
338
339 if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
340 return NGX_CONF_ERROR;
341 }
342
343
344 /*
345 * create the lists of ports, addresses and server names
346 * to find quickly the server core module configuration at run-time
347 */
348
349 /* AF_INET only */
350
351 if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) {
352 return NGX_CONF_ERROR;
353 }
354
355
356 /* optimize the lists of ports, addresses and server names */
357
358 /* AF_INET only */
359
360 if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) {
361 return NGX_CONF_ERROR;
362 }
363
364 return NGX_CONF_OK;
365
366 failed:
367
368 *cf = pcf;
369
370 return rv;
371 }
372
373
374 static ngx_int_t
375 ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
376 {
290 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers, 377 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
291 cf->pool, 1, sizeof(ngx_http_handler_pt)) 378 cf->pool, 1, sizeof(ngx_http_handler_pt))
292 != NGX_OK) 379 != NGX_OK)
293 { 380 {
294 return NGX_CONF_ERROR; 381 return NGX_ERROR;
295 } 382 }
296
297 383
298 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers, 384 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
299 cf->pool, 1, sizeof(ngx_http_handler_pt)) 385 cf->pool, 1, sizeof(ngx_http_handler_pt))
300 != NGX_OK) 386 != NGX_OK)
301 { 387 {
302 return NGX_CONF_ERROR; 388 return NGX_ERROR;
303 } 389 }
304
305 390
306 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, 391 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
307 cf->pool, 1, sizeof(ngx_http_handler_pt)) 392 cf->pool, 1, sizeof(ngx_http_handler_pt))
308 != NGX_OK) 393 != NGX_OK)
309 { 394 {
310 return NGX_CONF_ERROR; 395 return NGX_ERROR;
311 } 396 }
312
313 397
314 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers, 398 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
315 cf->pool, 1, sizeof(ngx_http_handler_pt)) 399 cf->pool, 1, sizeof(ngx_http_handler_pt))
316 != NGX_OK) 400 != NGX_OK)
317 { 401 {
318 return NGX_CONF_ERROR; 402 return NGX_ERROR;
319 } 403 }
320
321 404
322 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, 405 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
323 cf->pool, 2, sizeof(ngx_http_handler_pt)) 406 cf->pool, 2, sizeof(ngx_http_handler_pt))
324 != NGX_OK) 407 != NGX_OK)
325 { 408 {
326 return NGX_CONF_ERROR; 409 return NGX_ERROR;
327 } 410 }
328
329 411
330 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, 412 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
331 cf->pool, 4, sizeof(ngx_http_handler_pt)) 413 cf->pool, 4, sizeof(ngx_http_handler_pt))
332 != NGX_OK) 414 != NGX_OK)
333 { 415 {
334 return NGX_CONF_ERROR; 416 return NGX_ERROR;
335 } 417 }
336
337 418
338 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers, 419 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
339 cf->pool, 1, sizeof(ngx_http_handler_pt)) 420 cf->pool, 1, sizeof(ngx_http_handler_pt))
340 != NGX_OK) 421 != NGX_OK)
341 { 422 {
342 return NGX_CONF_ERROR; 423 return NGX_ERROR;
343 } 424 }
344 425
426 return NGX_OK;
427 }
428
429
430 static ngx_int_t
431 ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
432 {
433 ngx_array_t headers_in;
434 ngx_hash_key_t *hk;
435 ngx_hash_init_t hash;
436 ngx_http_header_t *header;
345 437
346 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) 438 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
347 != NGX_OK) 439 != NGX_OK)
348 { 440 {
349 return NGX_CONF_ERROR; 441 return NGX_ERROR;
350 } 442 }
351 443
352 for (header = ngx_http_headers_in; header->name.len; header++) { 444 for (header = ngx_http_headers_in; header->name.len; header++) {
353 hk = ngx_array_push(&headers_in); 445 hk = ngx_array_push(&headers_in);
354 if (hk == NULL) { 446 if (hk == NULL) {
355 return NGX_CONF_ERROR; 447 return NGX_ERROR;
356 } 448 }
357 449
358 hk->key = header->name; 450 hk->key = header->name;
359 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); 451 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
360 hk->value = header; 452 hk->value = header;
367 hash.name = "headers_in_hash"; 459 hash.name = "headers_in_hash";
368 hash.pool = cf->pool; 460 hash.pool = cf->pool;
369 hash.temp_pool = NULL; 461 hash.temp_pool = NULL;
370 462
371 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) { 463 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
372 return NGX_CONF_ERROR; 464 return NGX_ERROR;
373 } 465 }
374 466
375 467 return NGX_OK;
376 for (m = 0; ngx_modules[m]; m++) { 468 }
377 if (ngx_modules[m]->type != NGX_HTTP_MODULE) { 469
378 continue; 470
379 } 471 static ngx_int_t
380 472 ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
381 module = ngx_modules[m]->ctx; 473 {
382 mi = ngx_modules[m]->ctx_index; 474 ngx_int_t j;
383 475 ngx_uint_t i, n;
384 if (module->postconfiguration) { 476 ngx_uint_t find_config_index, use_rewrite, use_access;
385 if (module->postconfiguration(cf) != NGX_OK) { 477 ngx_http_handler_pt *h;
386 return NGX_CONF_ERROR; 478 ngx_http_phase_handler_t *ph;
387 } 479 ngx_http_phase_handler_pt checker;
388 }
389 }
390
391 if (ngx_http_variables_init_vars(cf) != NGX_OK) {
392 return NGX_CONF_ERROR;
393 }
394
395 /*
396 * http{}'s cf->ctx was needed while the configuration merging
397 * and in postconfiguration process
398 */
399
400 *cf = pcf;
401
402 480
403 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1; 481 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
404 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1; 482 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
405 find_config_index = 0; 483 find_config_index = 0;
406 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0; 484 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
413 } 491 }
414 492
415 ph = ngx_pcalloc(cf->pool, 493 ph = ngx_pcalloc(cf->pool,
416 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *)); 494 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
417 if (ph == NULL) { 495 if (ph == NULL) {
418 return NGX_CONF_ERROR; 496 return NGX_ERROR;
419 } 497 }
420 498
421 cmcf->phase_engine.handlers = ph; 499 cmcf->phase_engine.handlers = ph;
422 n = 0; 500 n = 0;
423 501
491 ph->next = n; 569 ph->next = n;
492 ph++; 570 ph++;
493 } 571 }
494 } 572 }
495 573
496 574 return NGX_OK;
497 /* 575 }
498 * create the lists of ports, addresses and server names 576
499 * to quickly find the server core module configuration at run-time 577
500 */ 578 static char *
501 579 ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
502 if (ngx_array_init(&in_ports, cf->temp_pool, 2, 580 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
581 {
582 char *rv;
583 ngx_queue_t *q;
584 ngx_http_core_loc_conf_t *clcf;
585 ngx_http_location_queue_t *lq;
586
587 if (locations == NULL) {
588 return NGX_CONF_OK;
589 }
590
591 for (q = ngx_queue_head(locations);
592 q != ngx_queue_sentinel(locations);
593 q = ngx_queue_next(q))
594 {
595 lq = (ngx_http_location_queue_t *) q;
596
597 clcf = lq->exact ? lq->exact : lq->inclusive;
598
599 rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
600 clcf->loc_conf[ctx_index]);
601 if (rv != NGX_CONF_OK) {
602 return rv;
603 }
604
605 rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
606 module, ctx_index);
607 if (rv != NGX_CONF_OK) {
608 return rv;
609 }
610 }
611
612 return NGX_CONF_OK;
613 }
614
615
616 static ngx_int_t
617 ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
618 ngx_http_core_loc_conf_t *pclcf)
619 {
620 ngx_uint_t n;
621 ngx_queue_t *q, *locations, *named, tail;
622 ngx_http_core_loc_conf_t *clcf;
623 ngx_http_location_queue_t *lq;
624 ngx_http_core_loc_conf_t **clcfp;
625 #if (NGX_PCRE)
626 ngx_uint_t r;
627 ngx_queue_t *regex;
628 #endif
629
630 locations = pclcf->locations;
631
632 if (locations == NULL) {
633 return NGX_OK;
634 }
635
636 ngx_queue_sort(locations, ngx_http_cmp_locations);
637
638 named = NULL;
639 n = 0;
640 #if (NGX_PCRE)
641 regex = NULL;
642 r = 0;
643 #endif
644
645 for (q = ngx_queue_head(locations);
646 q != ngx_queue_sentinel(locations);
647 q = ngx_queue_next(q))
648 {
649 lq = (ngx_http_location_queue_t *) q;
650
651 clcf = lq->exact ? lq->exact : lq->inclusive;
652
653 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
654 return NGX_ERROR;
655 }
656
657 #if (NGX_PCRE)
658
659 if (clcf->regex) {
660 r++;
661
662 if (regex == NULL) {
663 regex = q;
664 }
665
666 continue;
667 }
668
669 #endif
670
671 if (clcf->named) {
672 n++;
673
674 if (named == NULL) {
675 named = q;
676 }
677
678 continue;
679 }
680
681 if (clcf->noname) {
682 break;
683 }
684 }
685
686 if (q != ngx_queue_sentinel(locations)) {
687 ngx_queue_split(locations, q, &tail);
688 }
689
690 if (named) {
691 clcfp = ngx_palloc(cf->pool,
692 (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
693 if (clcfp == NULL) {
694 return NGX_ERROR;
695 }
696
697 cscf->named_locations = clcfp;
698
699 for (q = named;
700 q != ngx_queue_sentinel(locations);
701 q = ngx_queue_next(q))
702 {
703 lq = (ngx_http_location_queue_t *) q;
704
705 *(clcfp++) = lq->exact;
706 }
707
708 *clcfp = NULL;
709
710 ngx_queue_split(locations, named, &tail);
711 }
712
713 #if (NGX_PCRE)
714
715 if (regex) {
716
717 clcfp = ngx_palloc(cf->pool,
718 (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
719 if (clcfp == NULL) {
720 return NGX_ERROR;
721 }
722
723 pclcf->regex_locations = clcfp;
724
725 for (q = regex;
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, regex, &tail);
737 }
738
739 #endif
740
741 return NGX_OK;
742 }
743
744
745 static ngx_int_t
746 ngx_http_init_static_location_trees(ngx_conf_t *cf,
747 ngx_http_core_loc_conf_t *pclcf)
748 {
749 ngx_queue_t *q, *locations;
750 ngx_http_core_loc_conf_t *clcf;
751 ngx_http_location_queue_t *lq;
752
753 locations = pclcf->locations;
754
755 if (locations == NULL) {
756 return NGX_OK;
757 }
758
759 if (ngx_queue_empty(locations)) {
760 return NGX_OK;
761 }
762
763 for (q = ngx_queue_head(locations);
764 q != ngx_queue_sentinel(locations);
765 q = ngx_queue_next(q))
766 {
767 lq = (ngx_http_location_queue_t *) q;
768
769 clcf = lq->exact ? lq->exact : lq->inclusive;
770
771 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
772 return NGX_ERROR;
773 }
774 }
775
776 if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
777 return NGX_ERROR;
778 }
779
780 ngx_http_create_locations_list(locations, ngx_queue_head(locations));
781
782 pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
783 if (pclcf->static_locations == NULL) {
784 return NGX_ERROR;
785 }
786
787 return NGX_OK;
788 }
789
790
791 ngx_int_t
792 ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
793 ngx_http_core_loc_conf_t *clcf)
794 {
795 ngx_http_location_queue_t *lq;
796
797 if (*locations == NULL) {
798 *locations = ngx_palloc(cf->temp_pool,
799 sizeof(ngx_http_location_queue_t));
800 if (*locations == NULL) {
801 return NGX_ERROR;
802 }
803
804 ngx_queue_init(*locations);
805 }
806
807 lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
808 if (lq == NULL) {
809 return NGX_ERROR;
810 }
811
812 if (clcf->exact_match
813 #if (NGX_PCRE)
814 || clcf->regex
815 #endif
816 || clcf->named || clcf->noname)
817 {
818 lq->exact = clcf;
819 lq->inclusive = NULL;
820
821 } else {
822 lq->exact = NULL;
823 lq->inclusive = clcf;
824 }
825
826 lq->name = &clcf->name;
827 lq->file_name = cf->conf_file->file.name.data;
828 lq->line = cf->conf_file->line;
829
830 ngx_queue_init(&lq->list);
831
832 ngx_queue_insert_tail(*locations, &lq->queue);
833
834 return NGX_OK;
835 }
836
837
838 static ngx_int_t
839 ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
840 {
841 ngx_int_t rc;
842 ngx_http_core_loc_conf_t *first, *second;
843 ngx_http_location_queue_t *lq1, *lq2;
844
845 lq1 = (ngx_http_location_queue_t *) one;
846 lq2 = (ngx_http_location_queue_t *) two;
847
848 first = lq1->exact ? lq1->exact : lq1->inclusive;
849 second = lq2->exact ? lq2->exact : lq2->inclusive;
850
851 if (first->noname && !second->noname) {
852 /* shift no named locations to the end */
853 return 1;
854 }
855
856 if (!first->noname && second->noname) {
857 /* shift no named locations to the end */
858 return -1;
859 }
860
861 if (first->noname || second->noname) {
862 /* do not sort no named locations */
863 return 0;
864 }
865
866 if (first->named && !second->named) {
867 /* shift named locations to the end */
868 return 1;
869 }
870
871 if (!first->named && second->named) {
872 /* shift named locations to the end */
873 return -1;
874 }
875
876 if (first->named && second->named) {
877 return ngx_strcmp(first->name.data, second->name.data);
878 }
879
880 #if (NGX_PCRE)
881
882 if (first->regex && !second->regex) {
883 /* shift the regex matches to the end */
884 return 1;
885 }
886
887 if (!first->regex && second->regex) {
888 /* shift the regex matches to the end */
889 return -1;
890 }
891
892 if (first->regex || second->regex) {
893 /* do not sort the regex matches */
894 return 0;
895 }
896
897 #endif
898
899 rc = ngx_strcmp(first->name.data, second->name.data);
900
901 if (rc == 0 && !first->exact_match && second->exact_match) {
902 /* an exact match must be before the same inclusive one */
903 return 1;
904 }
905
906 return rc;
907 }
908
909
910 static ngx_int_t
911 ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
912 {
913 ngx_queue_t *q, *x;
914 ngx_http_location_queue_t *lq, *lx;
915
916 q = ngx_queue_head(locations);
917
918 while (q != ngx_queue_last(locations)) {
919
920 x = ngx_queue_next(q);
921
922 lq = (ngx_http_location_queue_t *) q;
923 lx = (ngx_http_location_queue_t *) x;
924
925 if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
926
927 if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
928 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
929 "duplicate location \"%V\" in %s:%ui",
930 lx->name, lx->file_name, lx->line);
931
932 return NGX_ERROR;
933 }
934
935 lq->inclusive = lx->inclusive;
936
937 ngx_queue_remove(x);
938
939 continue;
940 }
941
942 q = ngx_queue_next(q);
943 }
944
945 return NGX_OK;
946 }
947
948
949 static void
950 ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
951 {
952 u_char *name;
953 size_t len;
954 ngx_queue_t *x, tail;
955 ngx_http_location_queue_t *lq, *lx;
956
957 if (q == ngx_queue_last(locations)) {
958 return;
959 }
960
961 lq = (ngx_http_location_queue_t *) q;
962
963 if (lq->inclusive == NULL) {
964 ngx_http_create_locations_list(locations, ngx_queue_next(q));
965 return;
966 }
967
968 len = lq->name->len;
969 name = lq->name->data;
970
971 for (x = ngx_queue_next(q);
972 x != ngx_queue_sentinel(locations);
973 x = ngx_queue_next(x))
974 {
975 lx = (ngx_http_location_queue_t *) x;
976
977 if (len > lx->name->len
978 || (ngx_strncmp(name, lx->name->data, len) != 0))
979 {
980 break;
981 }
982 }
983
984 q = ngx_queue_next(q);
985
986 if (q == x) {
987 ngx_http_create_locations_list(locations, x);
988 return;
989 }
990
991 ngx_queue_split(locations, q, &tail);
992 ngx_queue_add(&lq->list, &tail);
993
994 if (x == ngx_queue_sentinel(locations)) {
995 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
996 return;
997 }
998
999 ngx_queue_split(&lq->list, x, &tail);
1000 ngx_queue_add(locations, &tail);
1001
1002 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1003
1004 ngx_http_create_locations_list(locations, x);
1005 }
1006
1007
1008 /*
1009 * to keep cache locality for left leaf nodes, allocate nodes in following
1010 * order: node, left subtree, right subtree, inclusive subtree
1011 */
1012
1013 static ngx_http_location_tree_node_t *
1014 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
1015 size_t prefix)
1016 {
1017 size_t len;
1018 ngx_queue_t *q, tail;
1019 ngx_http_location_queue_t *lq;
1020 ngx_http_location_tree_node_t *node;
1021
1022 q = ngx_queue_middle(locations);
1023
1024 lq = (ngx_http_location_queue_t *) q;
1025 len = lq->name->len - prefix;
1026
1027 node = ngx_pcalloc(cf->pool,
1028 offsetof(ngx_http_location_tree_node_t, name) + len);
1029 if (node == NULL) {
1030 return NULL;
1031 }
1032
1033 node->exact = lq->exact;
1034 node->inclusive = lq->inclusive;
1035
1036 node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
1037 || (lq->inclusive && lq->inclusive->auto_redirect));
1038
1039 node->len = (u_char) len;
1040 ngx_memcpy(node->name, &lq->name->data[prefix], len);
1041
1042 ngx_queue_split(locations, q, &tail);
1043
1044 if (ngx_queue_empty(locations)) {
1045 /*
1046 * ngx_queue_split() insures that if left part is empty,
1047 * then right one is empty too
1048 */
1049 goto inclusive;
1050 }
1051
1052 node->left = ngx_http_create_locations_tree(cf, locations, prefix);
1053 if (node->left == NULL) {
1054 return NULL;
1055 }
1056
1057 ngx_queue_remove(q);
1058
1059 if (ngx_queue_empty(&tail)) {
1060 goto inclusive;
1061 }
1062
1063 node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
1064 if (node->right == NULL) {
1065 return NULL;
1066 }
1067
1068 inclusive:
1069
1070 if (ngx_queue_empty(&lq->list)) {
1071 return node;
1072 }
1073
1074 node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
1075 if (node->tree == NULL) {
1076 return NULL;
1077 }
1078
1079 return node;
1080 }
1081
1082
1083 static ngx_int_t
1084 ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
1085 ngx_array_t *in_ports)
1086 {
1087 ngx_uint_t s, l, p, a;
1088 ngx_http_listen_t *listen;
1089 ngx_http_conf_in_port_t *in_port;
1090 ngx_http_conf_in_addr_t *in_addr;
1091 ngx_http_core_srv_conf_t **cscfp;
1092
1093 if (ngx_array_init(in_ports, cf->temp_pool, 2,
503 sizeof(ngx_http_conf_in_port_t)) 1094 sizeof(ngx_http_conf_in_port_t))
504 != NGX_OK) 1095 != NGX_OK)
505 { 1096 {
506 return NGX_CONF_ERROR; 1097 return NGX_ERROR;
507 } 1098 }
508 1099
509 /* "server" directives */ 1100 /* "server" directives */
510 1101
511 cscfp = cmcf->servers.elts; 1102 cscfp = servers->elts;
512 for (s = 0; s < cmcf->servers.nelts; s++) { 1103 for (s = 0; s < servers->nelts; s++) {
513 1104
514 /* "listen" directives */ 1105 /* "listen" directives */
515 1106
516 lscf = cscfp[s]->listen.elts; 1107 listen = cscfp[s]->listen.elts;
517 for (l = 0; l < cscfp[s]->listen.nelts; l++) { 1108 for (l = 0; l < cscfp[s]->listen.nelts; l++) {
518 1109
519 /* AF_INET only */ 1110 /* AF_INET only */
520 1111
521 in_port = in_ports.elts; 1112 in_port = in_ports->elts;
522 for (p = 0; p < in_ports.nelts; p++) { 1113 for (p = 0; p < in_ports->nelts; p++) {
523 1114
524 if (lscf[l].port != in_port[p].port) { 1115 if (listen[l].port != in_port[p].port) {
525 continue; 1116 continue;
526 } 1117 }
527 1118
528 /* the port is already in the port list */ 1119 /* the port is already in the port list */
529 1120
530 in_addr = in_port[p].addrs.elts; 1121 in_addr = in_port[p].addrs.elts;
531 for (a = 0; a < in_port[p].addrs.nelts; a++) { 1122 for (a = 0; a < in_port[p].addrs.nelts; a++) {
532 1123
533 if (lscf[l].addr != in_addr[a].addr) { 1124 if (listen[l].addr != in_addr[a].addr) {
534 continue; 1125 continue;
535 } 1126 }
536 1127
537 /* the address is already in the address list */ 1128 /* the address is already in the address list */
538 1129
539 if (ngx_http_add_names(cf, &in_addr[a], cscfp[s]) != NGX_OK) 1130 if (ngx_http_add_names(cf, cscfp[s], &in_addr[a]) != NGX_OK)
540 { 1131 {
541 return NGX_CONF_ERROR; 1132 return NGX_ERROR;
542 } 1133 }
543 1134
544 /* 1135 /*
545 * check the duplicate "default" server 1136 * check the duplicate "default" server
546 * for this address:port 1137 * for this address:port
547 */ 1138 */
548 1139
549 if (lscf[l].conf.default_server) { 1140 if (listen[l].conf.default_server) {
550 1141
551 if (in_addr[a].default_server) { 1142 if (in_addr[a].default_server) {
552 ngx_log_error(NGX_LOG_ERR, cf->log, 0, 1143 ngx_log_error(NGX_LOG_ERR, cf->log, 0,
553 "the duplicate default server in %s:%ui", 1144 "the duplicate default server in %s:%ui",
554 lscf[l].file_name, lscf[l].line); 1145 listen[l].file_name, listen[l].line);
555 1146
556 return NGX_CONF_ERROR; 1147 return NGX_ERROR;
557 } 1148 }
558 1149
559 in_addr[a].core_srv_conf = cscfp[s]; 1150 in_addr[a].core_srv_conf = cscfp[s];
560 in_addr[a].default_server = 1; 1151 in_addr[a].default_server = 1;
561 } 1152 }
566 /* 1157 /*
567 * add the address to the addresses list that 1158 * add the address to the addresses list that
568 * bound to this port 1159 * bound to this port
569 */ 1160 */
570 1161
571 if (ngx_http_add_address(cf, &in_port[p], &lscf[l], cscfp[s]) 1162 if (ngx_http_add_address(cf, cscfp[s], &in_port[p], &listen[l])
572 != NGX_OK) 1163 != NGX_OK)
573 { 1164 {
574 return NGX_CONF_ERROR; 1165 return NGX_ERROR;
575 } 1166 }
576 1167
577 goto found; 1168 goto found;
578 } 1169 }
579 1170
580 /* add the port to the in_port list */ 1171 /* add the port to the in_port list */
581 1172
582 in_port = ngx_array_push(&in_ports); 1173 in_port = ngx_array_push(in_ports);
583 if (in_port == NULL) { 1174 if (in_port == NULL) {
584 return NGX_CONF_ERROR; 1175 return NGX_ERROR;
585 } 1176 }
586 1177
587 in_port->port = lscf[l].port; 1178 in_port->port = listen[l].port;
588 in_port->addrs.elts = NULL; 1179 in_port->addrs.elts = NULL;
589 1180
590 if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s]) != NGX_OK) 1181 if (ngx_http_add_address(cf, cscfp[s], in_port, &listen[l])
1182 != NGX_OK)
591 { 1183 {
592 return NGX_CONF_ERROR; 1184 return NGX_ERROR;
593 } 1185 }
594 1186
595 found: 1187 found:
596 1188
597 continue; 1189 continue;
598 } 1190 }
599 } 1191 }
600 1192
601 1193 return NGX_OK;
602 /* optimize the lists of ports, addresses and server names */
603
604 /* AF_INET only */
605
606 in_port = in_ports.elts;
607 for (p = 0; p < in_ports.nelts; p++) {
608
609 ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
610 sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs);
611
612 /*
613 * check whether all name-based servers have the same configuraiton
614 * as the default server,
615 * or some servers disable optimizing the server names
616 */
617
618 in_addr = in_port[p].addrs.elts;
619 for (a = 0; a < in_port[p].addrs.nelts; a++) {
620
621 name = in_addr[a].names.elts;
622 for (s = 0; s < in_addr[a].names.nelts; s++) {
623
624 if (in_addr[a].core_srv_conf != name[s].core_srv_conf
625 || name[s].core_srv_conf->optimize_server_names == 0)
626 {
627 goto virtual_names;
628 }
629 }
630
631 /*
632 * if all name-based servers have the same configuration
633 * as the default server,
634 * and no servers disable optimizing the server names
635 * then we do not need to check them at run-time at all
636 */
637
638 in_addr[a].names.nelts = 0;
639
640 continue;
641
642 virtual_names:
643
644 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
645
646 ha.temp_pool = ngx_create_pool(16384, cf->log);
647 if (ha.temp_pool == NULL) {
648 return NGX_CONF_ERROR;
649 }
650
651 ha.pool = cf->pool;
652
653 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
654 ngx_destroy_pool(ha.temp_pool);
655 return NGX_CONF_ERROR;
656 }
657
658 #if (NGX_PCRE)
659 regex = 0;
660 #endif
661
662 name = in_addr[a].names.elts;
663
664 for (s = 0; s < in_addr[a].names.nelts; s++) {
665
666 #if (NGX_PCRE)
667 if (name[s].regex) {
668 regex++;
669 continue;
670 }
671 #endif
672
673 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
674 NGX_HASH_WILDCARD_KEY);
675
676 if (rc == NGX_ERROR) {
677 return NGX_CONF_ERROR;
678 }
679
680 if (rc == NGX_DECLINED) {
681 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
682 "invalid server name or wildcard \"%V\" on %s",
683 &name[s].name, in_addr[a].listen_conf->addr);
684 return NGX_CONF_ERROR;
685 }
686
687 if (rc == NGX_BUSY) {
688 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
689 "conflicting server name \"%V\" on %s, ignored",
690 &name[s].name, in_addr[a].listen_conf->addr);
691 }
692 }
693
694 hash.key = ngx_hash_key_lc;
695 hash.max_size = cmcf->server_names_hash_max_size;
696 hash.bucket_size = cmcf->server_names_hash_bucket_size;
697 hash.name = "server_names_hash";
698 hash.pool = cf->pool;
699
700 if (ha.keys.nelts) {
701 hash.hash = &in_addr[a].hash;
702 hash.temp_pool = NULL;
703
704 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK)
705 {
706 ngx_destroy_pool(ha.temp_pool);
707 return NGX_CONF_ERROR;
708 }
709 }
710
711 if (ha.dns_wc_head.nelts) {
712
713 ngx_qsort(ha.dns_wc_head.elts,
714 (size_t) ha.dns_wc_head.nelts,
715 sizeof(ngx_hash_key_t),
716 ngx_http_cmp_dns_wildcards);
717
718 hash.hash = NULL;
719 hash.temp_pool = ha.temp_pool;
720
721 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
722 ha.dns_wc_head.nelts)
723 != NGX_OK)
724 {
725 ngx_destroy_pool(ha.temp_pool);
726 return NGX_CONF_ERROR;
727 }
728
729 in_addr[a].wc_head = (ngx_hash_wildcard_t *) hash.hash;
730 }
731
732 if (ha.dns_wc_tail.nelts) {
733
734 ngx_qsort(ha.dns_wc_tail.elts,
735 (size_t) ha.dns_wc_tail.nelts,
736 sizeof(ngx_hash_key_t),
737 ngx_http_cmp_dns_wildcards);
738
739 hash.hash = NULL;
740 hash.temp_pool = ha.temp_pool;
741
742 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
743 ha.dns_wc_tail.nelts)
744 != NGX_OK)
745 {
746 ngx_destroy_pool(ha.temp_pool);
747 return NGX_CONF_ERROR;
748 }
749
750 in_addr[a].wc_tail = (ngx_hash_wildcard_t *) hash.hash;
751 }
752
753 ngx_destroy_pool(ha.temp_pool);
754
755 #if (NGX_PCRE)
756
757 if (regex == 0) {
758 continue;
759 }
760
761 in_addr[a].nregex = regex;
762 in_addr[a].regex = ngx_palloc(cf->pool,
763 regex * sizeof(ngx_http_server_name_t));
764
765 if (in_addr[a].regex == NULL) {
766 return NGX_CONF_ERROR;
767 }
768
769 for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) {
770 if (name[s].regex) {
771 in_addr[a].regex[i++] = name[s];
772 }
773 }
774 #endif
775 }
776
777 in_addr = in_port[p].addrs.elts;
778 last = in_port[p].addrs.nelts;
779
780 /*
781 * if there is the binding to the "*:port" then we need to bind()
782 * to the "*:port" only and ignore the other bindings
783 */
784
785 if (in_addr[last - 1].addr == INADDR_ANY) {
786 in_addr[last - 1].bind = 1;
787 bind_all = 0;
788
789 } else {
790 bind_all = 1;
791 }
792
793 for (a = 0; a < last; /* void */ ) {
794
795 if (!bind_all && !in_addr[a].bind) {
796 a++;
797 continue;
798 }
799
800 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
801 in_port[p].port);
802 if (ls == NULL) {
803 return NGX_CONF_ERROR;
804 }
805
806 ls->addr_ntop = 1;
807
808 ls->handler = ngx_http_init_connection;
809
810 cscf = in_addr[a].core_srv_conf;
811 ls->pool_size = cscf->connection_pool_size;
812 ls->post_accept_timeout = cscf->client_header_timeout;
813
814 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
815
816 ls->log = *clcf->err_log;
817 ls->log.data = &ls->addr_text;
818 ls->log.handler = ngx_accept_log_error;
819
820 #if (NGX_WIN32)
821 {
822 ngx_iocp_conf_t *iocpcf;
823
824 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
825 if (iocpcf->acceptex_read) {
826 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
827 }
828 }
829 #endif
830
831 ls->backlog = in_addr[a].listen_conf->backlog;
832 ls->rcvbuf = in_addr[a].listen_conf->rcvbuf;
833 ls->sndbuf = in_addr[a].listen_conf->sndbuf;
834
835 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
836 ls->accept_filter = in_addr[a].listen_conf->accept_filter;
837 #endif
838
839 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
840 ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
841 #endif
842
843 hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
844 if (hip == NULL) {
845 return NGX_CONF_ERROR;
846 }
847
848 hip->port = in_port[p].port;
849
850 hip->port_text.data = ngx_palloc(cf->pool, 7);
851 if (hip->port_text.data == NULL) {
852 return NGX_CONF_ERROR;
853 }
854
855 ls->servers = hip;
856
857 hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d",
858 hip->port)
859 - hip->port_text.data;
860
861 in_addr = in_port[p].addrs.elts;
862
863 if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
864 hip->naddrs = 1;
865 done = 0;
866
867 } else if (in_port[p].addrs.nelts > 1
868 && in_addr[last - 1].addr == INADDR_ANY)
869 {
870 hip->naddrs = last;
871 done = 1;
872
873 } else {
874 hip->naddrs = 1;
875 done = 0;
876 }
877
878 #if 0
879 ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
880 "%ui: %V %d %ui %ui",
881 a, &ls->addr_text, in_addr[a].bind,
882 hip->naddrs, last);
883 #endif
884
885 hip->addrs = ngx_pcalloc(cf->pool,
886 hip->naddrs * sizeof(ngx_http_in_addr_t));
887 if (hip->addrs == NULL) {
888 return NGX_CONF_ERROR;
889 }
890
891 for (i = 0; i < hip->naddrs; i++) {
892 hip->addrs[i].addr = in_addr[i].addr;
893 hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf;
894
895 if (in_addr[i].hash.buckets == NULL
896 && (in_addr[i].wc_head == NULL
897 || in_addr[i].wc_head->hash.buckets == NULL)
898 && (in_addr[i].wc_head == NULL
899 || in_addr[i].wc_head->hash.buckets == NULL))
900 {
901 continue;
902 }
903
904 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
905 if (vn == NULL) {
906 return NGX_CONF_ERROR;
907 }
908 hip->addrs[i].virtual_names = vn;
909
910 vn->names.hash = in_addr[i].hash;
911 vn->names.wc_head = in_addr[i].wc_head;
912 vn->names.wc_tail = in_addr[i].wc_tail;
913 #if (NGX_PCRE)
914 vn->nregex = in_addr[i].nregex;
915 vn->regex = in_addr[i].regex;
916 #endif
917 }
918
919 if (done) {
920 break;
921 }
922
923 in_addr++;
924 in_port[p].addrs.elts = in_addr;
925 last--;
926
927 a = 0;
928 }
929 }
930
931 #if 0
932 {
933 u_char address[20];
934 ngx_uint_t p, a;
935
936 in_port = in_ports.elts;
937 for (p = 0; p < in_ports.nelts; p++) {
938 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
939 "port: %d %p", in_port[p].port, &in_port[p]);
940 in_addr = in_port[p].addrs.elts;
941 for (a = 0; a < in_port[p].addrs.nelts; a++) {
942 ngx_inet_ntop(AF_INET, &in_addr[a].addr, address, 20);
943 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0,
944 "%s:%d %p",
945 address, in_port[p].port, in_addr[a].core_srv_conf);
946 name = in_addr[a].names.elts;
947 for (n = 0; n < in_addr[a].names.nelts; n++) {
948 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, cf->log, 0,
949 "%s:%d %V %p",
950 address, in_port[p].port, &name[n].name,
951 name[n].core_srv_conf);
952 }
953 }
954 }
955 }
956 #endif
957
958 return NGX_CONF_OK;
959 } 1194 }
960 1195
961 1196
962 /* 1197 /*
963 * add the server address, the server names and the server core module 1198 * add the server address, the server names and the server core module
964 * configurations to the port (in_port) 1199 * configurations to the port (in_port)
965 */ 1200 */
966 1201
967 static ngx_int_t 1202 static ngx_int_t
968 ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port, 1203 ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
969 ngx_http_listen_t *lscf, ngx_http_core_srv_conf_t *cscf) 1204 ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *listen)
970 { 1205 {
971 ngx_http_conf_in_addr_t *in_addr; 1206 ngx_http_conf_in_addr_t *in_addr;
972 1207
973 if (in_port->addrs.elts == NULL) { 1208 if (in_port->addrs.elts == NULL) {
974 if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4, 1209 if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4,
982 in_addr = ngx_array_push(&in_port->addrs); 1217 in_addr = ngx_array_push(&in_port->addrs);
983 if (in_addr == NULL) { 1218 if (in_addr == NULL) {
984 return NGX_ERROR; 1219 return NGX_ERROR;
985 } 1220 }
986 1221
987 in_addr->addr = lscf->addr; 1222 in_addr->addr = listen->addr;
988 in_addr->hash.buckets = NULL; 1223 in_addr->hash.buckets = NULL;
989 in_addr->hash.size = 0; 1224 in_addr->hash.size = 0;
990 in_addr->wc_head = NULL; 1225 in_addr->wc_head = NULL;
991 in_addr->wc_tail = NULL; 1226 in_addr->wc_tail = NULL;
992 in_addr->names.elts = NULL; 1227 in_addr->names.elts = NULL;
993 #if (NGX_PCRE) 1228 #if (NGX_PCRE)
994 in_addr->nregex = 0; 1229 in_addr->nregex = 0;
995 in_addr->regex = NULL; 1230 in_addr->regex = NULL;
996 #endif 1231 #endif
997 in_addr->core_srv_conf = cscf; 1232 in_addr->core_srv_conf = cscf;
998 in_addr->default_server = lscf->conf.default_server; 1233 in_addr->default_server = listen->conf.default_server;
999 in_addr->bind = lscf->conf.bind; 1234 in_addr->bind = listen->conf.bind;
1000 in_addr->listen_conf = &lscf->conf; 1235 in_addr->listen_conf = &listen->conf;
1001 1236
1002 #if (NGX_DEBUG) 1237 #if (NGX_DEBUG)
1003 { 1238 {
1004 u_char text[20]; 1239 u_char text[20];
1005 ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20); 1240 ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20);
1006 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d", 1241 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d",
1007 text, in_port->port); 1242 text, in_port->port);
1008 } 1243 }
1009 #endif 1244 #endif
1010 1245
1011 return ngx_http_add_names(cf, in_addr, cscf); 1246 return ngx_http_add_names(cf, cscf, in_addr);
1012 } 1247 }
1013 1248
1014 1249
1015 /* 1250 /*
1016 * add the server names and the server core module 1251 * add the server names and the server core module
1017 * configurations to the address:port (in_addr) 1252 * configurations to the address:port (in_addr)
1018 */ 1253 */
1019 1254
1020 static ngx_int_t 1255 static ngx_int_t
1021 ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr, 1256 ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1022 ngx_http_core_srv_conf_t *cscf) 1257 ngx_http_conf_in_addr_t *in_addr)
1023 { 1258 {
1024 ngx_uint_t i, n; 1259 ngx_uint_t i, n;
1025 ngx_http_server_name_t *server_names, *name; 1260 ngx_http_server_name_t *server_names, *name;
1026 1261
1027 if (in_addr->names.elts == NULL) { 1262 if (in_addr->names.elts == NULL) {
1055 1290
1056 return NGX_OK; 1291 return NGX_OK;
1057 } 1292 }
1058 1293
1059 1294
1060 static char * 1295 static ngx_int_t
1061 ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations, 1296 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1062 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index) 1297 ngx_array_t *in_ports)
1063 { 1298 {
1064 char *rv; 1299 ngx_int_t rc;
1065 ngx_uint_t i; 1300 ngx_uint_t s, p, a, i;
1066 ngx_http_core_loc_conf_t **clcfp; 1301 ngx_hash_init_t hash;
1067 1302 ngx_http_server_name_t *name;
1068 clcfp = locations->elts; 1303 ngx_hash_keys_arrays_t ha;
1069 1304 ngx_http_conf_in_port_t *in_port;
1070 for (i = 0; i < locations->nelts; i++) { 1305 ngx_http_conf_in_addr_t *in_addr;
1071 rv = module->merge_loc_conf(cf, loc_conf[ctx_index], 1306 #if (NGX_PCRE)
1072 clcfp[i]->loc_conf[ctx_index]); 1307 ngx_uint_t regex;
1073 if (rv != NGX_CONF_OK) { 1308 #endif
1074 return rv; 1309
1075 } 1310 in_port = in_ports->elts;
1076 1311 for (p = 0; p < in_ports->nelts; p++) {
1077 if (clcfp[i]->locations == NULL) { 1312
1313 ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
1314 sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs);
1315
1316 /*
1317 * check whether all name-based servers have
1318 * the same configuraiton as the default server
1319 */
1320
1321 in_addr = in_port[p].addrs.elts;
1322 for (a = 0; a < in_port[p].addrs.nelts; a++) {
1323
1324 name = in_addr[a].names.elts;
1325 for (s = 0; s < in_addr[a].names.nelts; s++) {
1326
1327 if (in_addr[a].core_srv_conf != name[s].core_srv_conf) {
1328 goto virtual_names;
1329 }
1330 }
1331
1332 /*
1333 * if all name-based servers have the same configuration
1334 * as the default server, then we do not need to check
1335 * them at run-time at all
1336 */
1337
1338 in_addr[a].names.nelts = 0;
1339
1078 continue; 1340 continue;
1079 } 1341
1080 1342 virtual_names:
1081 rv = ngx_http_merge_locations(cf, clcfp[i]->locations, 1343
1082 clcfp[i]->loc_conf, module, ctx_index); 1344 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1083 if (rv != NGX_CONF_OK) { 1345
1084 return rv; 1346 ha.temp_pool = ngx_create_pool(16384, cf->log);
1085 } 1347 if (ha.temp_pool == NULL) {
1086 } 1348 return NGX_ERROR;
1087 1349 }
1088 return NGX_CONF_OK; 1350
1351 ha.pool = cf->pool;
1352
1353 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
1354 goto failed;
1355 }
1356
1357 #if (NGX_PCRE)
1358 regex = 0;
1359 #endif
1360
1361 name = in_addr[a].names.elts;
1362
1363 for (s = 0; s < in_addr[a].names.nelts; s++) {
1364
1365 #if (NGX_PCRE)
1366 if (name[s].regex) {
1367 regex++;
1368 continue;
1369 }
1370 #endif
1371
1372 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
1373 NGX_HASH_WILDCARD_KEY);
1374
1375 if (rc == NGX_ERROR) {
1376 return NGX_ERROR;
1377 }
1378
1379 if (rc == NGX_DECLINED) {
1380 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1381 "invalid server name or wildcard \"%V\" on %s",
1382 &name[s].name, in_addr[a].listen_conf->addr);
1383 return NGX_ERROR;
1384 }
1385
1386 if (rc == NGX_BUSY) {
1387 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
1388 "conflicting server name \"%V\" on %s, ignored",
1389 &name[s].name, in_addr[a].listen_conf->addr);
1390 }
1391 }
1392
1393 hash.key = ngx_hash_key_lc;
1394 hash.max_size = cmcf->server_names_hash_max_size;
1395 hash.bucket_size = cmcf->server_names_hash_bucket_size;
1396 hash.name = "server_names_hash";
1397 hash.pool = cf->pool;
1398
1399 if (ha.keys.nelts) {
1400 hash.hash = &in_addr[a].hash;
1401 hash.temp_pool = NULL;
1402
1403 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK)
1404 {
1405 goto failed;
1406 }
1407 }
1408
1409 if (ha.dns_wc_head.nelts) {
1410
1411 ngx_qsort(ha.dns_wc_head.elts,
1412 (size_t) ha.dns_wc_head.nelts,
1413 sizeof(ngx_hash_key_t),
1414 ngx_http_cmp_dns_wildcards);
1415
1416 hash.hash = NULL;
1417 hash.temp_pool = ha.temp_pool;
1418
1419 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1420 ha.dns_wc_head.nelts)
1421 != NGX_OK)
1422 {
1423 goto failed;
1424 }
1425
1426 in_addr[a].wc_head = (ngx_hash_wildcard_t *) hash.hash;
1427 }
1428
1429 if (ha.dns_wc_tail.nelts) {
1430
1431 ngx_qsort(ha.dns_wc_tail.elts,
1432 (size_t) ha.dns_wc_tail.nelts,
1433 sizeof(ngx_hash_key_t),
1434 ngx_http_cmp_dns_wildcards);
1435
1436 hash.hash = NULL;
1437 hash.temp_pool = ha.temp_pool;
1438
1439 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1440 ha.dns_wc_tail.nelts)
1441 != NGX_OK)
1442 {
1443 goto failed;
1444 }
1445
1446 in_addr[a].wc_tail = (ngx_hash_wildcard_t *) hash.hash;
1447 }
1448
1449 ngx_destroy_pool(ha.temp_pool);
1450
1451 #if (NGX_PCRE)
1452
1453 if (regex == 0) {
1454 continue;
1455 }
1456
1457 in_addr[a].nregex = regex;
1458 in_addr[a].regex = ngx_palloc(cf->pool,
1459 regex * sizeof(ngx_http_server_name_t));
1460
1461 if (in_addr[a].regex == NULL) {
1462 return NGX_ERROR;
1463 }
1464
1465 for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) {
1466 if (name[s].regex) {
1467 in_addr[a].regex[i++] = name[s];
1468 }
1469 }
1470 #endif
1471 }
1472
1473 if (ngx_http_init_listening(cf, &in_port[p]) != NGX_OK) {
1474 return NGX_ERROR;
1475 }
1476 }
1477
1478 return NGX_OK;
1479
1480 failed:
1481
1482 ngx_destroy_pool(ha.temp_pool);
1483
1484 return NGX_ERROR;
1089 } 1485 }
1090 1486
1091 1487
1092 static ngx_int_t 1488 static ngx_int_t
1093 ngx_http_cmp_conf_in_addrs(const void *one, const void *two) 1489 ngx_http_cmp_conf_in_addrs(const void *one, const void *two)
1126 first = (ngx_hash_key_t *) one; 1522 first = (ngx_hash_key_t *) one;
1127 second = (ngx_hash_key_t *) two; 1523 second = (ngx_hash_key_t *) two;
1128 1524
1129 return ngx_strcmp(first->key.data, second->key.data); 1525 return ngx_strcmp(first->key.data, second->key.data);
1130 } 1526 }
1527
1528
1529 static ngx_int_t
1530 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port)
1531 {
1532 ngx_uint_t i, a, last, bind_all, done;
1533 ngx_listening_t *ls;
1534 ngx_http_in_port_t *hip;
1535 ngx_http_conf_in_addr_t *in_addr;
1536 ngx_http_virtual_names_t *vn;
1537 ngx_http_core_loc_conf_t *clcf;
1538 ngx_http_core_srv_conf_t *cscf;
1539
1540 in_addr = in_port->addrs.elts;
1541 last = in_port->addrs.nelts;
1542
1543 /*
1544 * if there is a binding to a "*:port" then we need to bind()
1545 * to the "*:port" only and ignore other bindings
1546 */
1547
1548 if (in_addr[last - 1].addr == INADDR_ANY) {
1549 in_addr[last - 1].bind = 1;
1550 bind_all = 0;
1551
1552 } else {
1553 bind_all = 1;
1554 }
1555
1556 a = 0;
1557
1558 while (a < last) {
1559
1560 if (!bind_all && !in_addr[a].bind) {
1561 a++;
1562 continue;
1563 }
1564
1565 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
1566 in_port->port);
1567 if (ls == NULL) {
1568 return NGX_ERROR;
1569 }
1570
1571 ls->addr_ntop = 1;
1572
1573 ls->handler = ngx_http_init_connection;
1574
1575 cscf = in_addr[a].core_srv_conf;
1576 ls->pool_size = cscf->connection_pool_size;
1577 ls->post_accept_timeout = cscf->client_header_timeout;
1578
1579 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1580
1581 ls->log = *clcf->err_log;
1582 ls->log.data = &ls->addr_text;
1583 ls->log.handler = ngx_accept_log_error;
1584
1585 #if (NGX_WIN32)
1586 {
1587 ngx_iocp_conf_t *iocpcf;
1588
1589 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1590 if (iocpcf->acceptex_read) {
1591 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
1592 }
1593 }
1594 #endif
1595
1596 ls->backlog = in_addr[a].listen_conf->backlog;
1597 ls->rcvbuf = in_addr[a].listen_conf->rcvbuf;
1598 ls->sndbuf = in_addr[a].listen_conf->sndbuf;
1599
1600 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
1601 ls->accept_filter = in_addr[a].listen_conf->accept_filter;
1602 #endif
1603
1604 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
1605 ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
1606 #endif
1607
1608 hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
1609 if (hip == NULL) {
1610 return NGX_ERROR;
1611 }
1612
1613 hip->port = in_port->port;
1614
1615 hip->port_text.data = ngx_palloc(cf->pool, 7);
1616 if (hip->port_text.data == NULL) {
1617 return NGX_ERROR;
1618 }
1619
1620 ls->servers = hip;
1621
1622 hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d", hip->port)
1623 - hip->port_text.data;
1624
1625 in_addr = in_port->addrs.elts;
1626
1627 if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
1628 hip->naddrs = 1;
1629 done = 0;
1630
1631 } else if (in_port->addrs.nelts > 1
1632 && in_addr[last - 1].addr == INADDR_ANY)
1633 {
1634 hip->naddrs = last;
1635 done = 1;
1636
1637 } else {
1638 hip->naddrs = 1;
1639 done = 0;
1640 }
1641
1642 hip->addrs = ngx_pcalloc(cf->pool,
1643 hip->naddrs * sizeof(ngx_http_in_addr_t));
1644 if (hip->addrs == NULL) {
1645 return NGX_ERROR;
1646 }
1647
1648 for (i = 0; i < hip->naddrs; i++) {
1649 hip->addrs[i].addr = in_addr[i].addr;
1650 hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf;
1651
1652 if (in_addr[i].hash.buckets == NULL
1653 && (in_addr[i].wc_head == NULL
1654 || in_addr[i].wc_head->hash.buckets == NULL)
1655 && (in_addr[i].wc_head == NULL
1656 || in_addr[i].wc_head->hash.buckets == NULL))
1657 {
1658 continue;
1659 }
1660
1661 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1662 if (vn == NULL) {
1663 return NGX_ERROR;
1664 }
1665 hip->addrs[i].virtual_names = vn;
1666
1667 vn->names.hash = in_addr[i].hash;
1668 vn->names.wc_head = in_addr[i].wc_head;
1669 vn->names.wc_tail = in_addr[i].wc_tail;
1670 #if (NGX_PCRE)
1671 vn->nregex = in_addr[i].nregex;
1672 vn->regex = in_addr[i].regex;
1673 #endif
1674 }
1675
1676 if (done) {
1677 return NGX_OK;
1678 }
1679
1680 in_addr++;
1681 in_port->addrs.elts = in_addr;
1682 last--;
1683
1684 a = 0;
1685 }
1686
1687 return NGX_OK;
1688 }