Mercurial > hg > nginx-ranges
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 } |