Mercurial > hg > nginx
comparison src/http/ngx_http.c @ 2022:35b35b84f5ef
split ngx_http_block() further
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 22 May 2008 11:07:08 +0000 |
parents | 2022e71d26d2 |
children | 7d58e319285e |
comparison
equal
deleted
inserted
replaced
2021:2022e71d26d2 | 2022:35b35b84f5ef |
---|---|
15 ngx_http_core_main_conf_t *cmcf); | 15 ngx_http_core_main_conf_t *cmcf); |
16 static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf, | 16 static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf, |
17 ngx_http_core_main_conf_t *cmcf); | 17 ngx_http_core_main_conf_t *cmcf); |
18 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf, | 18 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf, |
19 ngx_http_core_main_conf_t *cmcf); | 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); | |
20 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, |
21 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, |
22 ngx_http_core_srv_conf_t *cscf); | 25 ngx_http_listen_t *listen); |
23 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, |
24 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 | |
25 static char *ngx_http_merge_locations(ngx_conf_t *cf, | 29 static char *ngx_http_merge_locations(ngx_conf_t *cf, |
26 ngx_array_t *locations, void **loc_conf, ngx_http_module_t *module, | 30 ngx_array_t *locations, void **loc_conf, ngx_http_module_t *module, |
27 ngx_uint_t ctx_index); | 31 ngx_uint_t ctx_index); |
32 | |
33 static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, | |
34 ngx_http_core_main_conf_t *cmcf, ngx_array_t *in_ports); | |
28 static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two); | 35 static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two); |
29 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one, | 36 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one, |
30 const void *two); | 37 const void *two); |
38 | |
39 static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, | |
40 ngx_http_conf_in_port_t *in_port); | |
31 | 41 |
32 ngx_uint_t ngx_http_max_module; | 42 ngx_uint_t ngx_http_max_module; |
33 | 43 |
34 ngx_uint_t ngx_http_total_requests; | 44 ngx_uint_t ngx_http_total_requests; |
35 uint64_t ngx_http_total_sent; | 45 uint64_t ngx_http_total_sent; |
77 | 87 |
78 static char * | 88 static char * |
79 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 89 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
80 { | 90 { |
81 char *rv; | 91 char *rv; |
82 ngx_int_t rc; | 92 ngx_uint_t mi, m, s; |
83 ngx_uint_t mi, m, s, l, p, a, i; | |
84 ngx_uint_t last, bind_all, done; | |
85 ngx_conf_t pcf; | 93 ngx_conf_t pcf; |
86 ngx_array_t in_ports; | 94 ngx_array_t in_ports; |
87 ngx_hash_init_t hash; | |
88 ngx_listening_t *ls; | |
89 ngx_http_listen_t *lscf; | |
90 ngx_http_module_t *module; | 95 ngx_http_module_t *module; |
91 ngx_http_in_port_t *hip; | |
92 ngx_http_conf_ctx_t *ctx; | 96 ngx_http_conf_ctx_t *ctx; |
93 ngx_http_conf_in_port_t *in_port; | 97 ngx_http_core_srv_conf_t **cscfp; |
94 ngx_http_conf_in_addr_t *in_addr; | |
95 ngx_hash_keys_arrays_t ha; | |
96 ngx_http_server_name_t *name; | |
97 ngx_http_virtual_names_t *vn; | |
98 ngx_http_core_srv_conf_t **cscfp, *cscf; | |
99 ngx_http_core_loc_conf_t *clcf; | |
100 ngx_http_core_main_conf_t *cmcf; | 98 ngx_http_core_main_conf_t *cmcf; |
101 #if (NGX_PCRE) | |
102 ngx_uint_t regex; | |
103 #endif | |
104 | 99 |
105 /* the main http context */ | 100 /* the main http context */ |
106 | 101 |
107 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); | 102 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
108 if (ctx == NULL) { | 103 if (ctx == NULL) { |
326 } | 321 } |
327 | 322 |
328 | 323 |
329 /* | 324 /* |
330 * create the lists of ports, addresses and server names | 325 * create the lists of ports, addresses and server names |
331 * to quickly find the server core module configuration at run-time | 326 * to find quickly the server core module configuration at run-time |
332 */ | 327 */ |
333 | 328 |
334 if (ngx_array_init(&in_ports, cf->temp_pool, 2, | 329 /* AF_INET only */ |
335 sizeof(ngx_http_conf_in_port_t)) | 330 |
336 != NGX_OK) | 331 if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) { |
337 { | |
338 return NGX_CONF_ERROR; | 332 return NGX_CONF_ERROR; |
339 } | 333 } |
340 | 334 |
341 /* "server" directives */ | |
342 | |
343 cscfp = cmcf->servers.elts; | |
344 for (s = 0; s < cmcf->servers.nelts; s++) { | |
345 | |
346 /* "listen" directives */ | |
347 | |
348 lscf = cscfp[s]->listen.elts; | |
349 for (l = 0; l < cscfp[s]->listen.nelts; l++) { | |
350 | |
351 /* AF_INET only */ | |
352 | |
353 in_port = in_ports.elts; | |
354 for (p = 0; p < in_ports.nelts; p++) { | |
355 | |
356 if (lscf[l].port != in_port[p].port) { | |
357 continue; | |
358 } | |
359 | |
360 /* the port is already in the port list */ | |
361 | |
362 in_addr = in_port[p].addrs.elts; | |
363 for (a = 0; a < in_port[p].addrs.nelts; a++) { | |
364 | |
365 if (lscf[l].addr != in_addr[a].addr) { | |
366 continue; | |
367 } | |
368 | |
369 /* the address is already in the address list */ | |
370 | |
371 if (ngx_http_add_names(cf, &in_addr[a], cscfp[s]) != NGX_OK) | |
372 { | |
373 return NGX_CONF_ERROR; | |
374 } | |
375 | |
376 /* | |
377 * check the duplicate "default" server | |
378 * for this address:port | |
379 */ | |
380 | |
381 if (lscf[l].conf.default_server) { | |
382 | |
383 if (in_addr[a].default_server) { | |
384 ngx_log_error(NGX_LOG_ERR, cf->log, 0, | |
385 "the duplicate default server in %s:%ui", | |
386 lscf[l].file_name, lscf[l].line); | |
387 | |
388 return NGX_CONF_ERROR; | |
389 } | |
390 | |
391 in_addr[a].core_srv_conf = cscfp[s]; | |
392 in_addr[a].default_server = 1; | |
393 } | |
394 | |
395 goto found; | |
396 } | |
397 | |
398 /* | |
399 * add the address to the addresses list that | |
400 * bound to this port | |
401 */ | |
402 | |
403 if (ngx_http_add_address(cf, &in_port[p], &lscf[l], cscfp[s]) | |
404 != NGX_OK) | |
405 { | |
406 return NGX_CONF_ERROR; | |
407 } | |
408 | |
409 goto found; | |
410 } | |
411 | |
412 /* add the port to the in_port list */ | |
413 | |
414 in_port = ngx_array_push(&in_ports); | |
415 if (in_port == NULL) { | |
416 return NGX_CONF_ERROR; | |
417 } | |
418 | |
419 in_port->port = lscf[l].port; | |
420 in_port->addrs.elts = NULL; | |
421 | |
422 if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s]) != NGX_OK) | |
423 { | |
424 return NGX_CONF_ERROR; | |
425 } | |
426 | |
427 found: | |
428 | |
429 continue; | |
430 } | |
431 } | |
432 | |
433 | 335 |
434 /* optimize the lists of ports, addresses and server names */ | 336 /* optimize the lists of ports, addresses and server names */ |
435 | 337 |
436 /* AF_INET only */ | 338 /* AF_INET only */ |
437 | 339 |
438 in_port = in_ports.elts; | 340 if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) { |
439 for (p = 0; p < in_ports.nelts; p++) { | 341 return NGX_CONF_ERROR; |
440 | |
441 ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts, | |
442 sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs); | |
443 | |
444 /* | |
445 * check whether all name-based servers have the same configuraiton | |
446 * as the default server, | |
447 * or some servers disable optimizing the server names | |
448 */ | |
449 | |
450 in_addr = in_port[p].addrs.elts; | |
451 for (a = 0; a < in_port[p].addrs.nelts; a++) { | |
452 | |
453 name = in_addr[a].names.elts; | |
454 for (s = 0; s < in_addr[a].names.nelts; s++) { | |
455 | |
456 if (in_addr[a].core_srv_conf != name[s].core_srv_conf | |
457 || name[s].core_srv_conf->optimize_server_names == 0) | |
458 { | |
459 goto virtual_names; | |
460 } | |
461 } | |
462 | |
463 /* | |
464 * if all name-based servers have the same configuration | |
465 * as the default server, | |
466 * and no servers disable optimizing the server names | |
467 * then we do not need to check them at run-time at all | |
468 */ | |
469 | |
470 in_addr[a].names.nelts = 0; | |
471 | |
472 continue; | |
473 | |
474 virtual_names: | |
475 | |
476 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t)); | |
477 | |
478 ha.temp_pool = ngx_create_pool(16384, cf->log); | |
479 if (ha.temp_pool == NULL) { | |
480 return NGX_CONF_ERROR; | |
481 } | |
482 | |
483 ha.pool = cf->pool; | |
484 | |
485 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) { | |
486 ngx_destroy_pool(ha.temp_pool); | |
487 return NGX_CONF_ERROR; | |
488 } | |
489 | |
490 #if (NGX_PCRE) | |
491 regex = 0; | |
492 #endif | |
493 | |
494 name = in_addr[a].names.elts; | |
495 | |
496 for (s = 0; s < in_addr[a].names.nelts; s++) { | |
497 | |
498 #if (NGX_PCRE) | |
499 if (name[s].regex) { | |
500 regex++; | |
501 continue; | |
502 } | |
503 #endif | |
504 | |
505 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf, | |
506 NGX_HASH_WILDCARD_KEY); | |
507 | |
508 if (rc == NGX_ERROR) { | |
509 return NGX_CONF_ERROR; | |
510 } | |
511 | |
512 if (rc == NGX_DECLINED) { | |
513 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
514 "invalid server name or wildcard \"%V\" on %s", | |
515 &name[s].name, in_addr[a].listen_conf->addr); | |
516 return NGX_CONF_ERROR; | |
517 } | |
518 | |
519 if (rc == NGX_BUSY) { | |
520 ngx_log_error(NGX_LOG_WARN, cf->log, 0, | |
521 "conflicting server name \"%V\" on %s, ignored", | |
522 &name[s].name, in_addr[a].listen_conf->addr); | |
523 } | |
524 } | |
525 | |
526 hash.key = ngx_hash_key_lc; | |
527 hash.max_size = cmcf->server_names_hash_max_size; | |
528 hash.bucket_size = cmcf->server_names_hash_bucket_size; | |
529 hash.name = "server_names_hash"; | |
530 hash.pool = cf->pool; | |
531 | |
532 if (ha.keys.nelts) { | |
533 hash.hash = &in_addr[a].hash; | |
534 hash.temp_pool = NULL; | |
535 | |
536 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) | |
537 { | |
538 ngx_destroy_pool(ha.temp_pool); | |
539 return NGX_CONF_ERROR; | |
540 } | |
541 } | |
542 | |
543 if (ha.dns_wc_head.nelts) { | |
544 | |
545 ngx_qsort(ha.dns_wc_head.elts, | |
546 (size_t) ha.dns_wc_head.nelts, | |
547 sizeof(ngx_hash_key_t), | |
548 ngx_http_cmp_dns_wildcards); | |
549 | |
550 hash.hash = NULL; | |
551 hash.temp_pool = ha.temp_pool; | |
552 | |
553 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts, | |
554 ha.dns_wc_head.nelts) | |
555 != NGX_OK) | |
556 { | |
557 ngx_destroy_pool(ha.temp_pool); | |
558 return NGX_CONF_ERROR; | |
559 } | |
560 | |
561 in_addr[a].wc_head = (ngx_hash_wildcard_t *) hash.hash; | |
562 } | |
563 | |
564 if (ha.dns_wc_tail.nelts) { | |
565 | |
566 ngx_qsort(ha.dns_wc_tail.elts, | |
567 (size_t) ha.dns_wc_tail.nelts, | |
568 sizeof(ngx_hash_key_t), | |
569 ngx_http_cmp_dns_wildcards); | |
570 | |
571 hash.hash = NULL; | |
572 hash.temp_pool = ha.temp_pool; | |
573 | |
574 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts, | |
575 ha.dns_wc_tail.nelts) | |
576 != NGX_OK) | |
577 { | |
578 ngx_destroy_pool(ha.temp_pool); | |
579 return NGX_CONF_ERROR; | |
580 } | |
581 | |
582 in_addr[a].wc_tail = (ngx_hash_wildcard_t *) hash.hash; | |
583 } | |
584 | |
585 ngx_destroy_pool(ha.temp_pool); | |
586 | |
587 #if (NGX_PCRE) | |
588 | |
589 if (regex == 0) { | |
590 continue; | |
591 } | |
592 | |
593 in_addr[a].nregex = regex; | |
594 in_addr[a].regex = ngx_palloc(cf->pool, | |
595 regex * sizeof(ngx_http_server_name_t)); | |
596 | |
597 if (in_addr[a].regex == NULL) { | |
598 return NGX_CONF_ERROR; | |
599 } | |
600 | |
601 for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) { | |
602 if (name[s].regex) { | |
603 in_addr[a].regex[i++] = name[s]; | |
604 } | |
605 } | |
606 #endif | |
607 } | |
608 | |
609 in_addr = in_port[p].addrs.elts; | |
610 last = in_port[p].addrs.nelts; | |
611 | |
612 /* | |
613 * if there is the binding to the "*:port" then we need to bind() | |
614 * to the "*:port" only and ignore the other bindings | |
615 */ | |
616 | |
617 if (in_addr[last - 1].addr == INADDR_ANY) { | |
618 in_addr[last - 1].bind = 1; | |
619 bind_all = 0; | |
620 | |
621 } else { | |
622 bind_all = 1; | |
623 } | |
624 | |
625 for (a = 0; a < last; /* void */ ) { | |
626 | |
627 if (!bind_all && !in_addr[a].bind) { | |
628 a++; | |
629 continue; | |
630 } | |
631 | |
632 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr, | |
633 in_port[p].port); | |
634 if (ls == NULL) { | |
635 return NGX_CONF_ERROR; | |
636 } | |
637 | |
638 ls->addr_ntop = 1; | |
639 | |
640 ls->handler = ngx_http_init_connection; | |
641 | |
642 cscf = in_addr[a].core_srv_conf; | |
643 ls->pool_size = cscf->connection_pool_size; | |
644 ls->post_accept_timeout = cscf->client_header_timeout; | |
645 | |
646 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index]; | |
647 | |
648 ls->log = *clcf->err_log; | |
649 ls->log.data = &ls->addr_text; | |
650 ls->log.handler = ngx_accept_log_error; | |
651 | |
652 #if (NGX_WIN32) | |
653 { | |
654 ngx_iocp_conf_t *iocpcf; | |
655 | |
656 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module); | |
657 if (iocpcf->acceptex_read) { | |
658 ls->post_accept_buffer_size = cscf->client_header_buffer_size; | |
659 } | |
660 } | |
661 #endif | |
662 | |
663 ls->backlog = in_addr[a].listen_conf->backlog; | |
664 ls->rcvbuf = in_addr[a].listen_conf->rcvbuf; | |
665 ls->sndbuf = in_addr[a].listen_conf->sndbuf; | |
666 | |
667 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) | |
668 ls->accept_filter = in_addr[a].listen_conf->accept_filter; | |
669 #endif | |
670 | |
671 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) | |
672 ls->deferred_accept = in_addr[a].listen_conf->deferred_accept; | |
673 #endif | |
674 | |
675 hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t)); | |
676 if (hip == NULL) { | |
677 return NGX_CONF_ERROR; | |
678 } | |
679 | |
680 hip->port = in_port[p].port; | |
681 | |
682 hip->port_text.data = ngx_palloc(cf->pool, 7); | |
683 if (hip->port_text.data == NULL) { | |
684 return NGX_CONF_ERROR; | |
685 } | |
686 | |
687 ls->servers = hip; | |
688 | |
689 hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d", | |
690 hip->port) | |
691 - hip->port_text.data; | |
692 | |
693 in_addr = in_port[p].addrs.elts; | |
694 | |
695 if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) { | |
696 hip->naddrs = 1; | |
697 done = 0; | |
698 | |
699 } else if (in_port[p].addrs.nelts > 1 | |
700 && in_addr[last - 1].addr == INADDR_ANY) | |
701 { | |
702 hip->naddrs = last; | |
703 done = 1; | |
704 | |
705 } else { | |
706 hip->naddrs = 1; | |
707 done = 0; | |
708 } | |
709 | |
710 #if 0 | |
711 ngx_log_error(NGX_LOG_ALERT, cf->log, 0, | |
712 "%ui: %V %d %ui %ui", | |
713 a, &ls->addr_text, in_addr[a].bind, | |
714 hip->naddrs, last); | |
715 #endif | |
716 | |
717 hip->addrs = ngx_pcalloc(cf->pool, | |
718 hip->naddrs * sizeof(ngx_http_in_addr_t)); | |
719 if (hip->addrs == NULL) { | |
720 return NGX_CONF_ERROR; | |
721 } | |
722 | |
723 for (i = 0; i < hip->naddrs; i++) { | |
724 hip->addrs[i].addr = in_addr[i].addr; | |
725 hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf; | |
726 | |
727 if (in_addr[i].hash.buckets == NULL | |
728 && (in_addr[i].wc_head == NULL | |
729 || in_addr[i].wc_head->hash.buckets == NULL) | |
730 && (in_addr[i].wc_head == NULL | |
731 || in_addr[i].wc_head->hash.buckets == NULL)) | |
732 { | |
733 continue; | |
734 } | |
735 | |
736 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t)); | |
737 if (vn == NULL) { | |
738 return NGX_CONF_ERROR; | |
739 } | |
740 hip->addrs[i].virtual_names = vn; | |
741 | |
742 vn->names.hash = in_addr[i].hash; | |
743 vn->names.wc_head = in_addr[i].wc_head; | |
744 vn->names.wc_tail = in_addr[i].wc_tail; | |
745 #if (NGX_PCRE) | |
746 vn->nregex = in_addr[i].nregex; | |
747 vn->regex = in_addr[i].regex; | |
748 #endif | |
749 } | |
750 | |
751 if (done) { | |
752 break; | |
753 } | |
754 | |
755 in_addr++; | |
756 in_port[p].addrs.elts = in_addr; | |
757 last--; | |
758 | |
759 a = 0; | |
760 } | |
761 } | 342 } |
762 | 343 |
763 return NGX_CONF_OK; | 344 return NGX_CONF_OK; |
764 } | 345 } |
765 | 346 |
966 | 547 |
967 return NGX_OK; | 548 return NGX_OK; |
968 } | 549 } |
969 | 550 |
970 | 551 |
552 static ngx_int_t | |
553 ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers, | |
554 ngx_array_t *in_ports) | |
555 { | |
556 ngx_uint_t s, l, p, a; | |
557 ngx_http_listen_t *listen; | |
558 ngx_http_conf_in_port_t *in_port; | |
559 ngx_http_conf_in_addr_t *in_addr; | |
560 ngx_http_core_srv_conf_t **cscfp; | |
561 | |
562 if (ngx_array_init(in_ports, cf->temp_pool, 2, | |
563 sizeof(ngx_http_conf_in_port_t)) | |
564 != NGX_OK) | |
565 { | |
566 return NGX_ERROR; | |
567 } | |
568 | |
569 /* "server" directives */ | |
570 | |
571 cscfp = servers->elts; | |
572 for (s = 0; s < servers->nelts; s++) { | |
573 | |
574 /* "listen" directives */ | |
575 | |
576 listen = cscfp[s]->listen.elts; | |
577 for (l = 0; l < cscfp[s]->listen.nelts; l++) { | |
578 | |
579 /* AF_INET only */ | |
580 | |
581 in_port = in_ports->elts; | |
582 for (p = 0; p < in_ports->nelts; p++) { | |
583 | |
584 if (listen[l].port != in_port[p].port) { | |
585 continue; | |
586 } | |
587 | |
588 /* the port is already in the port list */ | |
589 | |
590 in_addr = in_port[p].addrs.elts; | |
591 for (a = 0; a < in_port[p].addrs.nelts; a++) { | |
592 | |
593 if (listen[l].addr != in_addr[a].addr) { | |
594 continue; | |
595 } | |
596 | |
597 /* the address is already in the address list */ | |
598 | |
599 if (ngx_http_add_names(cf, cscfp[s], &in_addr[a]) != NGX_OK) | |
600 { | |
601 return NGX_ERROR; | |
602 } | |
603 | |
604 /* | |
605 * check the duplicate "default" server | |
606 * for this address:port | |
607 */ | |
608 | |
609 if (listen[l].conf.default_server) { | |
610 | |
611 if (in_addr[a].default_server) { | |
612 ngx_log_error(NGX_LOG_ERR, cf->log, 0, | |
613 "the duplicate default server in %s:%ui", | |
614 listen[l].file_name, listen[l].line); | |
615 | |
616 return NGX_ERROR; | |
617 } | |
618 | |
619 in_addr[a].core_srv_conf = cscfp[s]; | |
620 in_addr[a].default_server = 1; | |
621 } | |
622 | |
623 goto found; | |
624 } | |
625 | |
626 /* | |
627 * add the address to the addresses list that | |
628 * bound to this port | |
629 */ | |
630 | |
631 if (ngx_http_add_address(cf, cscfp[s], &in_port[p], &listen[l]) | |
632 != NGX_OK) | |
633 { | |
634 return NGX_ERROR; | |
635 } | |
636 | |
637 goto found; | |
638 } | |
639 | |
640 /* add the port to the in_port list */ | |
641 | |
642 in_port = ngx_array_push(in_ports); | |
643 if (in_port == NULL) { | |
644 return NGX_ERROR; | |
645 } | |
646 | |
647 in_port->port = listen[l].port; | |
648 in_port->addrs.elts = NULL; | |
649 | |
650 if (ngx_http_add_address(cf, cscfp[s], in_port, &listen[l]) | |
651 != NGX_OK) | |
652 { | |
653 return NGX_ERROR; | |
654 } | |
655 | |
656 found: | |
657 | |
658 continue; | |
659 } | |
660 } | |
661 | |
662 return NGX_OK; | |
663 } | |
664 | |
665 | |
971 /* | 666 /* |
972 * add the server address, the server names and the server core module | 667 * add the server address, the server names and the server core module |
973 * configurations to the port (in_port) | 668 * configurations to the port (in_port) |
974 */ | 669 */ |
975 | 670 |
976 static ngx_int_t | 671 static ngx_int_t |
977 ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port, | 672 ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, |
978 ngx_http_listen_t *lscf, ngx_http_core_srv_conf_t *cscf) | 673 ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *listen) |
979 { | 674 { |
980 ngx_http_conf_in_addr_t *in_addr; | 675 ngx_http_conf_in_addr_t *in_addr; |
981 | 676 |
982 if (in_port->addrs.elts == NULL) { | 677 if (in_port->addrs.elts == NULL) { |
983 if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4, | 678 if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4, |
991 in_addr = ngx_array_push(&in_port->addrs); | 686 in_addr = ngx_array_push(&in_port->addrs); |
992 if (in_addr == NULL) { | 687 if (in_addr == NULL) { |
993 return NGX_ERROR; | 688 return NGX_ERROR; |
994 } | 689 } |
995 | 690 |
996 in_addr->addr = lscf->addr; | 691 in_addr->addr = listen->addr; |
997 in_addr->hash.buckets = NULL; | 692 in_addr->hash.buckets = NULL; |
998 in_addr->hash.size = 0; | 693 in_addr->hash.size = 0; |
999 in_addr->wc_head = NULL; | 694 in_addr->wc_head = NULL; |
1000 in_addr->wc_tail = NULL; | 695 in_addr->wc_tail = NULL; |
1001 in_addr->names.elts = NULL; | 696 in_addr->names.elts = NULL; |
1002 #if (NGX_PCRE) | 697 #if (NGX_PCRE) |
1003 in_addr->nregex = 0; | 698 in_addr->nregex = 0; |
1004 in_addr->regex = NULL; | 699 in_addr->regex = NULL; |
1005 #endif | 700 #endif |
1006 in_addr->core_srv_conf = cscf; | 701 in_addr->core_srv_conf = cscf; |
1007 in_addr->default_server = lscf->conf.default_server; | 702 in_addr->default_server = listen->conf.default_server; |
1008 in_addr->bind = lscf->conf.bind; | 703 in_addr->bind = listen->conf.bind; |
1009 in_addr->listen_conf = &lscf->conf; | 704 in_addr->listen_conf = &listen->conf; |
1010 | 705 |
1011 #if (NGX_DEBUG) | 706 #if (NGX_DEBUG) |
1012 { | 707 { |
1013 u_char text[20]; | 708 u_char text[20]; |
1014 ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20); | 709 ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20); |
1015 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d", | 710 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d", |
1016 text, in_port->port); | 711 text, in_port->port); |
1017 } | 712 } |
1018 #endif | 713 #endif |
1019 | 714 |
1020 return ngx_http_add_names(cf, in_addr, cscf); | 715 return ngx_http_add_names(cf, cscf, in_addr); |
1021 } | 716 } |
1022 | 717 |
1023 | 718 |
1024 /* | 719 /* |
1025 * add the server names and the server core module | 720 * add the server names and the server core module |
1026 * configurations to the address:port (in_addr) | 721 * configurations to the address:port (in_addr) |
1027 */ | 722 */ |
1028 | 723 |
1029 static ngx_int_t | 724 static ngx_int_t |
1030 ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr, | 725 ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, |
1031 ngx_http_core_srv_conf_t *cscf) | 726 ngx_http_conf_in_addr_t *in_addr) |
1032 { | 727 { |
1033 ngx_uint_t i, n; | 728 ngx_uint_t i, n; |
1034 ngx_http_server_name_t *server_names, *name; | 729 ngx_http_server_name_t *server_names, *name; |
1035 | 730 |
1036 if (in_addr->names.elts == NULL) { | 731 if (in_addr->names.elts == NULL) { |
1097 return NGX_CONF_OK; | 792 return NGX_CONF_OK; |
1098 } | 793 } |
1099 | 794 |
1100 | 795 |
1101 static ngx_int_t | 796 static ngx_int_t |
797 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, | |
798 ngx_array_t *in_ports) | |
799 { | |
800 ngx_int_t rc; | |
801 ngx_uint_t s, p, a, i; | |
802 ngx_hash_init_t hash; | |
803 ngx_http_server_name_t *name; | |
804 ngx_hash_keys_arrays_t ha; | |
805 ngx_http_conf_in_port_t *in_port; | |
806 ngx_http_conf_in_addr_t *in_addr; | |
807 #if (NGX_PCRE) | |
808 ngx_uint_t regex; | |
809 #endif | |
810 | |
811 in_port = in_ports->elts; | |
812 for (p = 0; p < in_ports->nelts; p++) { | |
813 | |
814 ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts, | |
815 sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs); | |
816 | |
817 /* | |
818 * check whether all name-based servers have the same configuraiton | |
819 * as the default server, | |
820 * or some servers disable optimizing the server names | |
821 */ | |
822 | |
823 in_addr = in_port[p].addrs.elts; | |
824 for (a = 0; a < in_port[p].addrs.nelts; a++) { | |
825 | |
826 name = in_addr[a].names.elts; | |
827 for (s = 0; s < in_addr[a].names.nelts; s++) { | |
828 | |
829 if (in_addr[a].core_srv_conf != name[s].core_srv_conf | |
830 || name[s].core_srv_conf->optimize_server_names == 0) | |
831 { | |
832 goto virtual_names; | |
833 } | |
834 } | |
835 | |
836 /* | |
837 * if all name-based servers have the same configuration | |
838 * as the default server, | |
839 * and no servers disable optimizing the server names | |
840 * then we do not need to check them at run-time at all | |
841 */ | |
842 | |
843 in_addr[a].names.nelts = 0; | |
844 | |
845 continue; | |
846 | |
847 virtual_names: | |
848 | |
849 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t)); | |
850 | |
851 ha.temp_pool = ngx_create_pool(16384, cf->log); | |
852 if (ha.temp_pool == NULL) { | |
853 return NGX_ERROR; | |
854 } | |
855 | |
856 ha.pool = cf->pool; | |
857 | |
858 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) { | |
859 goto failed; | |
860 } | |
861 | |
862 #if (NGX_PCRE) | |
863 regex = 0; | |
864 #endif | |
865 | |
866 name = in_addr[a].names.elts; | |
867 | |
868 for (s = 0; s < in_addr[a].names.nelts; s++) { | |
869 | |
870 #if (NGX_PCRE) | |
871 if (name[s].regex) { | |
872 regex++; | |
873 continue; | |
874 } | |
875 #endif | |
876 | |
877 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf, | |
878 NGX_HASH_WILDCARD_KEY); | |
879 | |
880 if (rc == NGX_ERROR) { | |
881 return NGX_ERROR; | |
882 } | |
883 | |
884 if (rc == NGX_DECLINED) { | |
885 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
886 "invalid server name or wildcard \"%V\" on %s", | |
887 &name[s].name, in_addr[a].listen_conf->addr); | |
888 return NGX_ERROR; | |
889 } | |
890 | |
891 if (rc == NGX_BUSY) { | |
892 ngx_log_error(NGX_LOG_WARN, cf->log, 0, | |
893 "conflicting server name \"%V\" on %s, ignored", | |
894 &name[s].name, in_addr[a].listen_conf->addr); | |
895 } | |
896 } | |
897 | |
898 hash.key = ngx_hash_key_lc; | |
899 hash.max_size = cmcf->server_names_hash_max_size; | |
900 hash.bucket_size = cmcf->server_names_hash_bucket_size; | |
901 hash.name = "server_names_hash"; | |
902 hash.pool = cf->pool; | |
903 | |
904 if (ha.keys.nelts) { | |
905 hash.hash = &in_addr[a].hash; | |
906 hash.temp_pool = NULL; | |
907 | |
908 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) | |
909 { | |
910 goto failed; | |
911 } | |
912 } | |
913 | |
914 if (ha.dns_wc_head.nelts) { | |
915 | |
916 ngx_qsort(ha.dns_wc_head.elts, | |
917 (size_t) ha.dns_wc_head.nelts, | |
918 sizeof(ngx_hash_key_t), | |
919 ngx_http_cmp_dns_wildcards); | |
920 | |
921 hash.hash = NULL; | |
922 hash.temp_pool = ha.temp_pool; | |
923 | |
924 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts, | |
925 ha.dns_wc_head.nelts) | |
926 != NGX_OK) | |
927 { | |
928 goto failed; | |
929 } | |
930 | |
931 in_addr[a].wc_head = (ngx_hash_wildcard_t *) hash.hash; | |
932 } | |
933 | |
934 if (ha.dns_wc_tail.nelts) { | |
935 | |
936 ngx_qsort(ha.dns_wc_tail.elts, | |
937 (size_t) ha.dns_wc_tail.nelts, | |
938 sizeof(ngx_hash_key_t), | |
939 ngx_http_cmp_dns_wildcards); | |
940 | |
941 hash.hash = NULL; | |
942 hash.temp_pool = ha.temp_pool; | |
943 | |
944 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts, | |
945 ha.dns_wc_tail.nelts) | |
946 != NGX_OK) | |
947 { | |
948 goto failed; | |
949 } | |
950 | |
951 in_addr[a].wc_tail = (ngx_hash_wildcard_t *) hash.hash; | |
952 } | |
953 | |
954 ngx_destroy_pool(ha.temp_pool); | |
955 | |
956 #if (NGX_PCRE) | |
957 | |
958 if (regex == 0) { | |
959 continue; | |
960 } | |
961 | |
962 in_addr[a].nregex = regex; | |
963 in_addr[a].regex = ngx_palloc(cf->pool, | |
964 regex * sizeof(ngx_http_server_name_t)); | |
965 | |
966 if (in_addr[a].regex == NULL) { | |
967 return NGX_ERROR; | |
968 } | |
969 | |
970 for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) { | |
971 if (name[s].regex) { | |
972 in_addr[a].regex[i++] = name[s]; | |
973 } | |
974 } | |
975 #endif | |
976 } | |
977 | |
978 if (ngx_http_init_listening(cf, &in_port[p]) != NGX_OK) { | |
979 return NGX_ERROR; | |
980 } | |
981 } | |
982 | |
983 return NGX_OK; | |
984 | |
985 failed: | |
986 | |
987 ngx_destroy_pool(ha.temp_pool); | |
988 | |
989 return NGX_ERROR; | |
990 } | |
991 | |
992 | |
993 static ngx_int_t | |
1102 ngx_http_cmp_conf_in_addrs(const void *one, const void *two) | 994 ngx_http_cmp_conf_in_addrs(const void *one, const void *two) |
1103 { | 995 { |
1104 ngx_http_conf_in_addr_t *first, *second; | 996 ngx_http_conf_in_addr_t *first, *second; |
1105 | 997 |
1106 first = (ngx_http_conf_in_addr_t *) one; | 998 first = (ngx_http_conf_in_addr_t *) one; |
1135 first = (ngx_hash_key_t *) one; | 1027 first = (ngx_hash_key_t *) one; |
1136 second = (ngx_hash_key_t *) two; | 1028 second = (ngx_hash_key_t *) two; |
1137 | 1029 |
1138 return ngx_strcmp(first->key.data, second->key.data); | 1030 return ngx_strcmp(first->key.data, second->key.data); |
1139 } | 1031 } |
1032 | |
1033 | |
1034 static ngx_int_t | |
1035 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port) | |
1036 { | |
1037 ngx_uint_t i, a, last, bind_all, done; | |
1038 ngx_listening_t *ls; | |
1039 ngx_http_in_port_t *hip; | |
1040 ngx_http_conf_in_addr_t *in_addr; | |
1041 ngx_http_virtual_names_t *vn; | |
1042 ngx_http_core_loc_conf_t *clcf; | |
1043 ngx_http_core_srv_conf_t *cscf; | |
1044 | |
1045 in_addr = in_port->addrs.elts; | |
1046 last = in_port->addrs.nelts; | |
1047 | |
1048 /* | |
1049 * if there is a binding to a "*:port" then we need to bind() | |
1050 * to the "*:port" only and ignore other bindings | |
1051 */ | |
1052 | |
1053 if (in_addr[last - 1].addr == INADDR_ANY) { | |
1054 in_addr[last - 1].bind = 1; | |
1055 bind_all = 0; | |
1056 | |
1057 } else { | |
1058 bind_all = 1; | |
1059 } | |
1060 | |
1061 a = 0; | |
1062 | |
1063 while (a < last) { | |
1064 | |
1065 if (!bind_all && !in_addr[a].bind) { | |
1066 a++; | |
1067 continue; | |
1068 } | |
1069 | |
1070 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr, | |
1071 in_port->port); | |
1072 if (ls == NULL) { | |
1073 return NGX_ERROR; | |
1074 } | |
1075 | |
1076 ls->addr_ntop = 1; | |
1077 | |
1078 ls->handler = ngx_http_init_connection; | |
1079 | |
1080 cscf = in_addr[a].core_srv_conf; | |
1081 ls->pool_size = cscf->connection_pool_size; | |
1082 ls->post_accept_timeout = cscf->client_header_timeout; | |
1083 | |
1084 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index]; | |
1085 | |
1086 ls->log = *clcf->err_log; | |
1087 ls->log.data = &ls->addr_text; | |
1088 ls->log.handler = ngx_accept_log_error; | |
1089 | |
1090 #if (NGX_WIN32) | |
1091 { | |
1092 ngx_iocp_conf_t *iocpcf; | |
1093 | |
1094 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module); | |
1095 if (iocpcf->acceptex_read) { | |
1096 ls->post_accept_buffer_size = cscf->client_header_buffer_size; | |
1097 } | |
1098 } | |
1099 #endif | |
1100 | |
1101 ls->backlog = in_addr[a].listen_conf->backlog; | |
1102 ls->rcvbuf = in_addr[a].listen_conf->rcvbuf; | |
1103 ls->sndbuf = in_addr[a].listen_conf->sndbuf; | |
1104 | |
1105 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) | |
1106 ls->accept_filter = in_addr[a].listen_conf->accept_filter; | |
1107 #endif | |
1108 | |
1109 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) | |
1110 ls->deferred_accept = in_addr[a].listen_conf->deferred_accept; | |
1111 #endif | |
1112 | |
1113 hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t)); | |
1114 if (hip == NULL) { | |
1115 return NGX_ERROR; | |
1116 } | |
1117 | |
1118 hip->port = in_port->port; | |
1119 | |
1120 hip->port_text.data = ngx_palloc(cf->pool, 7); | |
1121 if (hip->port_text.data == NULL) { | |
1122 return NGX_ERROR; | |
1123 } | |
1124 | |
1125 ls->servers = hip; | |
1126 | |
1127 hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d", hip->port) | |
1128 - hip->port_text.data; | |
1129 | |
1130 in_addr = in_port->addrs.elts; | |
1131 | |
1132 if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) { | |
1133 hip->naddrs = 1; | |
1134 done = 0; | |
1135 | |
1136 } else if (in_port->addrs.nelts > 1 | |
1137 && in_addr[last - 1].addr == INADDR_ANY) | |
1138 { | |
1139 hip->naddrs = last; | |
1140 done = 1; | |
1141 | |
1142 } else { | |
1143 hip->naddrs = 1; | |
1144 done = 0; | |
1145 } | |
1146 | |
1147 hip->addrs = ngx_pcalloc(cf->pool, | |
1148 hip->naddrs * sizeof(ngx_http_in_addr_t)); | |
1149 if (hip->addrs == NULL) { | |
1150 return NGX_ERROR; | |
1151 } | |
1152 | |
1153 for (i = 0; i < hip->naddrs; i++) { | |
1154 hip->addrs[i].addr = in_addr[i].addr; | |
1155 hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf; | |
1156 | |
1157 if (in_addr[i].hash.buckets == NULL | |
1158 && (in_addr[i].wc_head == NULL | |
1159 || in_addr[i].wc_head->hash.buckets == NULL) | |
1160 && (in_addr[i].wc_head == NULL | |
1161 || in_addr[i].wc_head->hash.buckets == NULL)) | |
1162 { | |
1163 continue; | |
1164 } | |
1165 | |
1166 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t)); | |
1167 if (vn == NULL) { | |
1168 return NGX_ERROR; | |
1169 } | |
1170 hip->addrs[i].virtual_names = vn; | |
1171 | |
1172 vn->names.hash = in_addr[i].hash; | |
1173 vn->names.wc_head = in_addr[i].wc_head; | |
1174 vn->names.wc_tail = in_addr[i].wc_tail; | |
1175 #if (NGX_PCRE) | |
1176 vn->nregex = in_addr[i].nregex; | |
1177 vn->regex = in_addr[i].regex; | |
1178 #endif | |
1179 } | |
1180 | |
1181 if (done) { | |
1182 return NGX_OK; | |
1183 } | |
1184 | |
1185 in_addr++; | |
1186 in_port->addrs.elts = in_addr; | |
1187 last--; | |
1188 | |
1189 a = 0; | |
1190 } | |
1191 | |
1192 return NGX_OK; | |
1193 } |