comparison src/http/ngx_http.c @ 593:425af804d968 release-0.3.18

nginx-0.3.18-RELEASE import *) Feature: the "server_names" directive supports the ".domain.tld" names. *) Feature: the "server_names" directive uses the hash for the "*.domain.tld" names and more effective hash for usual names. *) Change: the "server_names_hash_max_size" and "server_names_hash_bucket_size" directives. *) Change: the "server_names_hash" and "server_names_hash_threshold" directives were canceled. *) Feature: the "valid_referers" directive uses the hash site names. *) Change: now the "valid_referers" directive checks the site names only without the URI part. *) Bugfix: some ".domain.tld" names incorrectly processed by the ngx_http_map_module. *) Bugfix: segmentation fault was occurred if configuration file did not exist; the bug had appeared in 0.3.12. *) Bugfix: on 64-bit platforms segmentation fault may occurred on start; the bug had appeared in 0.3.16.
author Igor Sysoev <igor@sysoev.ru>
date Mon, 26 Dec 2005 17:07:48 +0000
parents d4e858a5751a
children ebc68d8ca496
comparison
equal deleted inserted replaced
592:8b2e7f727cd0 593:425af804d968
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 int ngx_libc_cdecl ngx_cmp_server_names(const void *one, 14 static int ngx_libc_cdecl ngx_cmp_server_names(const void *one,
15 const void *two); 15 const void *two);
16 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, 16 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
17 ngx_http_in_port_t *in_port, ngx_http_listen_t *lscf, 17 ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *lscf,
18 ngx_http_core_srv_conf_t *cscf); 18 ngx_http_core_srv_conf_t *cscf);
19 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf, 19 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
20 ngx_http_in_addr_t *in_addr, ngx_http_core_srv_conf_t *cscf); 20 ngx_http_conf_in_addr_t *in_addr, ngx_http_core_srv_conf_t *cscf);
21 static char *ngx_http_merge_locations(ngx_conf_t *cf, 21 static char *ngx_http_merge_locations(ngx_conf_t *cf,
22 ngx_array_t *locations, void **loc_conf, ngx_http_module_t *module, 22 ngx_array_t *locations, void **loc_conf, ngx_http_module_t *module,
23 ngx_uint_t ctx_index); 23 ngx_uint_t ctx_index);
24 24 static int ngx_libc_cdecl ngx_http_cmp_conf_in_addrs(const void *one,
25 ngx_uint_t ngx_http_max_module; 25 const void *two);
26 26 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
27 ngx_uint_t ngx_http_total_requests; 27 const void *two);
28 uint64_t ngx_http_total_sent; 28
29 ngx_uint_t ngx_http_max_module;
30
31 ngx_uint_t ngx_http_total_requests;
32 uint64_t ngx_http_total_sent;
29 33
30 34
31 ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r); 35 ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
32 ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch); 36 ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
33 37
70 74
71 static char * 75 static char *
72 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 76 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
73 { 77 {
74 char *rv; 78 char *rv;
75 ngx_uint_t mi, m, s, l, p, a, n, key; 79 u_char ch;
76 ngx_uint_t port_found, addr_found; 80 ngx_int_t rc;
77 ngx_uint_t virtual_names, separate_binding; 81 ngx_uint_t mi, m, s, l, p, a, n, i;
82 ngx_uint_t last, bind_all, done;
78 ngx_conf_t pcf; 83 ngx_conf_t pcf;
79 ngx_array_t in_ports; 84 ngx_array_t in_ports;
85 ngx_hash_init_t hash;
80 ngx_listening_t *ls; 86 ngx_listening_t *ls;
81 ngx_http_listen_t *lscf; 87 ngx_http_listen_t *lscf;
82 ngx_http_module_t *module; 88 ngx_http_module_t *module;
89 ngx_http_in_port_t *hip;
83 ngx_http_handler_pt *h; 90 ngx_http_handler_pt *h;
84 ngx_http_conf_ctx_t *ctx; 91 ngx_http_conf_ctx_t *ctx;
85 ngx_http_in_port_t *in_port, *inport; 92 ngx_http_conf_in_port_t *in_port;
86 ngx_http_in_addr_t *in_addr, *inaddr; 93 ngx_http_conf_in_addr_t *in_addr;
87 ngx_http_server_name_t *s_name, *name; 94 ngx_hash_keys_arrays_t ha;
95 ngx_http_server_name_t *name;
96 ngx_http_virtual_names_t *vn;
88 ngx_http_core_srv_conf_t **cscfp, *cscf; 97 ngx_http_core_srv_conf_t **cscfp, *cscf;
89 ngx_http_core_loc_conf_t *clcf; 98 ngx_http_core_loc_conf_t *clcf;
90 ngx_http_core_main_conf_t *cmcf; 99 ngx_http_core_main_conf_t *cmcf;
91 #if (NGX_WIN32) 100 #if (NGX_WIN32)
92 ngx_iocp_conf_t *iocpcf; 101 ngx_iocp_conf_t *iocpcf;
412 /* 421 /*
413 * create the lists of ports, addresses and server names 422 * create the lists of ports, addresses and server names
414 * to quickly find the server core module configuration at run-time 423 * to quickly find the server core module configuration at run-time
415 */ 424 */
416 425
417 if (ngx_array_init(&in_ports, cf->pool, 2, sizeof(ngx_http_in_port_t)) 426 if (ngx_array_init(&in_ports, cf->temp_pool, 2,
427 sizeof(ngx_http_conf_in_port_t))
418 != NGX_OK) 428 != NGX_OK)
419 { 429 {
420 return NGX_CONF_ERROR; 430 return NGX_CONF_ERROR;
421 } 431 }
422 432
428 /* "listen" directives */ 438 /* "listen" directives */
429 439
430 lscf = cscfp[s]->listen.elts; 440 lscf = cscfp[s]->listen.elts;
431 for (l = 0; l < cscfp[s]->listen.nelts; l++) { 441 for (l = 0; l < cscfp[s]->listen.nelts; l++) {
432 442
433 port_found = 0;
434
435 /* AF_INET only */ 443 /* AF_INET only */
436 444
437 in_port = in_ports.elts; 445 in_port = in_ports.elts;
438 for (p = 0; p < in_ports.nelts; p++) { 446 for (p = 0; p < in_ports.nelts; p++) {
439 447
440 if (lscf[l].port == in_port[p].port) { 448 if (lscf[l].port != in_port[p].port) {
441 449 continue;
442 /* the port is already in the port list */ 450 }
443 451
444 port_found = 1; 452 /* the port is already in the port list */
445 addr_found = 0; 453
446 454 in_addr = in_port[p].addrs.elts;
447 in_addr = in_port[p].addrs.elts; 455 for (a = 0; a < in_port[p].addrs.nelts; a++) {
448 for (a = 0; a < in_port[p].addrs.nelts; a++) { 456
449 457 if (lscf[l].addr != in_addr[a].addr) {
450 if (lscf[l].addr == in_addr[a].addr) { 458 continue;
451 459 }
452 /* the address is already in the address list */ 460
453 461 /* the address is already in the address list */
454 if (ngx_http_add_names(cf, &in_addr[a], cscfp[s]) 462
455 != NGX_OK) 463 if (ngx_http_add_names(cf, &in_addr[a], cscfp[s]) != NGX_OK)
456 { 464 {
457 return NGX_CONF_ERROR; 465 return NGX_CONF_ERROR;
458 } 466 }
459 467
460 /* 468 /*
461 * check the duplicate "default" server 469 * check the duplicate "default" server
462 * for this address:port 470 * for this address:port
463 */ 471 */
464 472
465 if (lscf[l].conf.default_server) { 473 if (lscf[l].conf.default_server) {
466 474
467 if (in_addr[a].conf.default_server) { 475 if (in_addr[a].default_server) {
468 ngx_log_error(NGX_LOG_ERR, cf->log, 0, 476 ngx_log_error(NGX_LOG_ERR, cf->log, 0,
469 "the duplicate default server in %V:%d", 477 "the duplicate default server in %V:%d",
470 &lscf[l].file_name, lscf[l].line); 478 &lscf[l].file_name, lscf[l].line);
471 479
472 return NGX_CONF_ERROR;
473 }
474
475 in_addr[a].core_srv_conf = cscfp[s];
476 in_addr[a].conf.default_server = 1;
477 }
478
479 addr_found = 1;
480
481 break;
482
483 } else if (in_addr[a].addr == INADDR_ANY) {
484
485 /* the INADDR_ANY is always the last address */
486
487 inaddr = ngx_array_push(&in_port[p].addrs);
488 if (inaddr == NULL) {
489 return NGX_CONF_ERROR;
490 }
491 in_addr = in_port[p].addrs.elts;
492
493 /*
494 * the INADDR_ANY must be the last resort
495 * so we move it to the end of the address list
496 * and put the new address in its place
497 */
498
499 ngx_memcpy(inaddr, &in_addr[a],
500 sizeof(ngx_http_in_addr_t));
501
502 in_addr[a].addr = lscf[l].addr;
503 in_addr[a].names.elts = NULL;
504 in_addr[a].hash = NULL;
505 in_addr[a].wildcards.elts = NULL;
506 in_addr[a].core_srv_conf = cscfp[s];
507 in_addr[a].conf = lscf[l].conf;
508
509 if (ngx_http_add_names(cf, &in_addr[a], cscfp[s])
510 != NGX_OK)
511 {
512 return NGX_CONF_ERROR;
513 }
514
515 addr_found = 1;
516
517 break;
518 }
519 }
520
521 if (!addr_found) {
522
523 /*
524 * add the address to the addresses list that
525 * bound to this port
526 */
527
528 if (ngx_http_add_address(cf, &in_port[p], &lscf[l],
529 cscfp[s]) != NGX_OK)
530 {
531 return NGX_CONF_ERROR; 480 return NGX_CONF_ERROR;
532 } 481 }
482
483 in_addr[a].core_srv_conf = cscfp[s];
484 in_addr[a].default_server = 1;
533 } 485 }
534 } 486
535 } 487 goto found;
536 488 }
537 if (!port_found) { 489
538 490 /*
539 /* add the port to the in_port list */ 491 * add the address to the addresses list that
540 492 * bound to this port
541 in_port = ngx_array_push(&in_ports); 493 */
542 if (in_port == NULL) { 494
543 return NGX_CONF_ERROR; 495 if (ngx_http_add_address(cf, &in_port[p], &lscf[l], cscfp[s])
544 }
545
546 in_port->port = lscf[l].port;
547 in_port->addrs.elts = NULL;
548
549 in_port->port_text.data = ngx_palloc(cf->pool, 7);
550 if (in_port->port_text.data == NULL) {
551 return NGX_CONF_ERROR;
552 }
553
554 in_port->port_text.len = ngx_sprintf(in_port->port_text.data,
555 ":%d", in_port->port)
556 - in_port->port_text.data;
557
558 if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s])
559 != NGX_OK) 496 != NGX_OK)
560 { 497 {
561 return NGX_CONF_ERROR; 498 return NGX_CONF_ERROR;
562 } 499 }
563 } 500
501 goto found;
502 }
503
504 /* add the port to the in_port list */
505
506 in_port = ngx_array_push(&in_ports);
507 if (in_port == NULL) {
508 return NGX_CONF_ERROR;
509 }
510
511 in_port->port = lscf[l].port;
512 in_port->addrs.elts = NULL;
513
514 if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s]) != NGX_OK)
515 {
516 return NGX_CONF_ERROR;
517 }
518
519 found:
520
521 continue;
564 } 522 }
565 } 523 }
566 524
567 525
568 /* optimize the lists of ports, addresses and server names */ 526 /* optimize the lists of ports, addresses and server names */
570 /* AF_INET only */ 528 /* AF_INET only */
571 529
572 in_port = in_ports.elts; 530 in_port = in_ports.elts;
573 for (p = 0; p < in_ports.nelts; p++) { 531 for (p = 0; p < in_ports.nelts; p++) {
574 532
575 separate_binding = 0; 533 ngx_qsort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
534 sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs);
576 535
577 /* 536 /*
578 * check whether all name-based servers have the same configuraiton 537 * check whether all name-based servers have the same configuraiton
579 * as the default server, or some servers restrict the host names 538 * as the default server, or some servers restrict the host names
580 */ 539 */
581 540
582 in_addr = in_port[p].addrs.elts; 541 in_addr = in_port[p].addrs.elts;
583 for (a = 0; a < in_port[p].addrs.nelts; a++) { 542 for (a = 0; a < in_port[p].addrs.nelts; a++) {
584
585 if (in_addr[a].conf.bind) {
586 separate_binding = 1;
587 }
588
589 virtual_names = 0;
590 543
591 name = in_addr[a].names.elts; 544 name = in_addr[a].names.elts;
592 for (n = 0; n < in_addr[a].names.nelts; n++) { 545 for (n = 0; n < in_addr[a].names.nelts; n++) {
593 if (in_addr[a].core_srv_conf != name[n].core_srv_conf 546 if (in_addr[a].core_srv_conf != name[n].core_srv_conf
594 || name[n].core_srv_conf->restrict_host_names 547 || name[n].core_srv_conf->restrict_host_names
595 != NGX_HTTP_RESTRICT_HOST_OFF) 548 != NGX_HTTP_RESTRICT_HOST_OFF)
596 { 549 {
597 virtual_names = 1; 550 goto virtual_names;
598 break;
599 }
600 }
601
602 if (!virtual_names) {
603 name = in_addr[a].wildcards.elts;
604 for (n = 0; n < in_addr[a].wildcards.nelts; n++) {
605 if (in_addr[a].core_srv_conf != name[n].core_srv_conf
606 || name[n].core_srv_conf->restrict_host_names
607 != NGX_HTTP_RESTRICT_HOST_OFF)
608 {
609 virtual_names = 1;
610 break;
611 }
612 } 551 }
613 } 552 }
614 553
615 /* 554 /*
616 * if all name-based servers have the same configuration 555 * if all name-based servers have the same configuration
617 * as the default server, and no servers restrict the host names 556 * as the default server, and no servers restrict the host names
618 * then we do not need to check them at run-time at all 557 * then we do not need to check them at run-time at all
619 */ 558 */
620 559
621 if (!virtual_names) { 560 in_addr[a].names.nelts = 0;
622 in_addr[a].names.nelts = 0; 561
623 continue; 562 continue;
624 } 563
625 564 virtual_names:
626 565
627 ngx_qsort(in_addr[a].names.elts, in_addr[a].names.nelts, 566 ha.temp_pool = ngx_create_pool(16384, cf->log);
628 sizeof(ngx_http_server_name_t), ngx_cmp_server_names); 567 if (ha.temp_pool == NULL) {
629 568 return NGX_CONF_ERROR;
630 569 }
631 /* create a hash for many names */ 570
632 571 ha.pool = cf->pool;
633 if (in_addr[a].names.nelts > cmcf->server_names_hash_threshold) { 572
634 in_addr[a].hash = ngx_palloc(cf->pool, 573 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
635 cmcf->server_names_hash 574 ngx_destroy_pool(ha.temp_pool);
636 * sizeof(ngx_array_t)); 575 return NGX_CONF_ERROR;
637 if (in_addr[a].hash == NULL) { 576 }
577
578 name = in_addr[a].names.elts;
579 for (s = 0; s < in_addr[a].names.nelts; s++) {
580
581 ch = name[s].name.data[0];
582
583 if (ch == '*' || ch == '.') {
584 continue;
585 }
586
587 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
588 0);
589
590 if (rc == NGX_ERROR) {
638 return NGX_CONF_ERROR; 591 return NGX_CONF_ERROR;
639 } 592 }
640 593
641 for (n = 0; n < cmcf->server_names_hash; n++) { 594 if (rc == NGX_BUSY) {
642 if (ngx_array_init(&in_addr[a].hash[n], cf->pool, 4, 595 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
643 sizeof(ngx_http_server_name_t)) != NGX_OK) 596 "conflicting server name \"%V\", ignored",
644 { 597 &name[s].name);
645 return NGX_CONF_ERROR; 598 }
646 } 599 }
647 } 600
648 601 for (s = 0; s < in_addr[a].names.nelts; s++) {
649 name = in_addr[a].names.elts; 602
650 for (s = 0; s < in_addr[a].names.nelts; s++) { 603 ch = name[s].name.data[0];
651 ngx_http_server_names_hash_key(key, name[s].name.data, 604
652 name[s].name.len, 605 if (ch != '*' && ch != '.') {
653 cmcf->server_names_hash); 606 continue;
654 607 }
655 s_name = ngx_array_push(&in_addr[a].hash[key]); 608
656 if (s_name == NULL) { 609 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
657 return NGX_CONF_ERROR; 610 NGX_HASH_WILDCARD_KEY);
658 } 611
659 name = in_addr[a].names.elts; 612 if (rc == NGX_ERROR) {
660 613 return NGX_CONF_ERROR;
661 *s_name = name[s]; 614 }
662 } 615
663 } 616 if (rc == NGX_BUSY) {
664 } 617 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
618 "conflicting server name \"%V\", ignored",
619 &name[s].name);
620 }
621 }
622
623 hash.key = ngx_hash_key_lc;
624 hash.max_size = cmcf->server_names_hash_max_size;
625 hash.bucket_size = cmcf->server_names_hash_bucket_size;
626 hash.name = "server_names_hash";
627 hash.pool = cf->pool;
628
629 if (ha.keys.nelts) {
630 hash.hash = &in_addr[a].hash;
631 hash.temp_pool = NULL;
632
633 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK)
634 {
635 ngx_destroy_pool(ha.temp_pool);
636 return NGX_CONF_ERROR;
637 }
638 }
639
640 if (ha.dns_wildcards.nelts) {
641
642 ngx_qsort(ha.dns_wildcards.elts,
643 (size_t) ha.dns_wildcards.nelts,
644 sizeof(ngx_hash_key_t),
645 ngx_http_cmp_dns_wildcards);
646
647 hash.hash = NULL;
648 hash.temp_pool = ha.temp_pool;
649
650 if (ngx_hash_wildcard_init(&hash, ha.dns_wildcards.elts,
651 ha.dns_wildcards.nelts)
652 != NGX_OK)
653 {
654 ngx_destroy_pool(ha.temp_pool);
655 return NGX_CONF_ERROR;
656 }
657
658 in_addr[a].dns_wildcards = (ngx_hash_wildcard_t *) hash.hash;
659 }
660
661 ngx_destroy_pool(ha.temp_pool);
662 }
663
664 in_addr = in_port[p].addrs.elts;
665 last = in_port[p].addrs.nelts;
665 666
666 /* 667 /*
667 * if there is the binding to the "*:port" then we need to bind() 668 * if there is the binding to the "*:port" then we need to bind()
668 * to the "*:port" only and ignore the other bindings 669 * to the "*:port" only and ignore the other bindings
669 */ 670 */
670 671
671 if (in_addr[a - 1].addr == INADDR_ANY && !separate_binding) { 672 if (in_addr[last - 1].addr == INADDR_ANY) {
672 a--; 673 in_addr[last - 1].bind = 1;
674 bind_all = 0;
673 675
674 } else { 676 } else {
675 a = 0; 677 bind_all = 1;
676 } 678 }
677 679
678 in_addr = in_port[p].addrs.elts; 680 for (a = 0; a < last; /* void */ ) {
679 while (a < in_port[p].addrs.nelts) { 681
682 if (!bind_all && !in_addr[a].bind) {
683 a++;
684 continue;
685 }
680 686
681 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr, 687 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
682 in_port[p].port); 688 in_port[p].port);
683 if (ls == NULL) { 689 if (ls == NULL) {
684 return NGX_CONF_ERROR; 690 return NGX_CONF_ERROR;
703 if (iocpcf->acceptex_read) { 709 if (iocpcf->acceptex_read) {
704 ls->post_accept_buffer_size = cscf->client_header_buffer_size; 710 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
705 } 711 }
706 #endif 712 #endif
707 713
708 ls->backlog = in_addr[a].conf.backlog; 714 ls->backlog = in_addr[a].listen_conf->backlog;
709 ls->rcvbuf = in_addr[a].conf.rcvbuf; 715 ls->rcvbuf = in_addr[a].listen_conf->rcvbuf;
710 ls->sndbuf = in_addr[a].conf.sndbuf; 716 ls->sndbuf = in_addr[a].listen_conf->sndbuf;
711 717
712 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) 718 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
713 ls->accept_filter = in_addr[a].conf.accept_filter; 719 ls->accept_filter = in_addr[a].listen_conf->accept_filter;
714 #endif 720 #endif
715 721
716 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) 722 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
717 ls->deferred_accept = in_addr[a].conf.deferred_accept; 723 ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
718 #endif 724 #endif
719 725
720 ls->ctx = ctx; 726 ls->ctx = ctx;
721 727
722 if (in_port[p].addrs.nelts > 1) { 728 hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
723 729 if (hip == NULL) {
724 in_addr = in_port[p].addrs.elts; 730 return NGX_CONF_ERROR;
725 if (in_addr[in_port[p].addrs.nelts - 1].addr != INADDR_ANY) { 731 }
726 732
727 /* 733 hip->port = in_port[p].port;
728 * if this port has not the "*:port" binding then create 734
729 * the separate ngx_http_in_port_t for the all bindings 735 hip->port_text.data = ngx_palloc(cf->pool, 7);
730 */ 736 if (hip->port_text.data == NULL) {
731 737 return NGX_CONF_ERROR;
732 inport = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t)); 738 }
733 if (inport == NULL) { 739
734 return NGX_CONF_ERROR; 740 ls->servers = hip;
735 } 741
736 742 hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d",
737 inport->port = in_port[p].port; 743 hip->port)
738 inport->port_text = in_port[p].port_text; 744 - hip->port_text.data;
739 745
740 /* init list of the addresses ... */ 746 in_addr = in_port[p].addrs.elts;
741 747
742 if (ngx_array_init(&inport->addrs, cf->pool, 1, 748 if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
743 sizeof(ngx_http_in_addr_t)) != NGX_OK) 749 hip->naddrs = 1;
744 { 750 done = 0;
745 return NGX_CONF_ERROR; 751
746 } 752 } else if (in_port[p].addrs.nelts > 1
747 753 && in_addr[last - 1].addr == INADDR_ANY)
748 /* ... and set up it with the first address */ 754 {
749 755 hip->naddrs = last;
750 inport->addrs.nelts = 1; 756 done = 1;
751 inport->addrs.elts = in_port[p].addrs.elts; 757
752 758 } else {
753 ls->servers = inport; 759 hip->naddrs = 1;
754 760 done = 0;
755 /* prepare for the next cycle */ 761 }
756 762
757 in_port[p].addrs.elts = (char *) in_port[p].addrs.elts 763 #if 0
758 + in_port[p].addrs.size; 764 ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
759 in_port[p].addrs.nelts--; 765 "%ui: %V %d %ui %ui",
760 766 a, &ls->addr_text, in_addr[a].bind,
761 in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts; 767 hip->naddrs, last);
762 a = 0; 768 #endif
763 769
770 hip->addrs = ngx_pcalloc(cf->pool,
771 hip->naddrs * sizeof(ngx_http_in_addr_t));
772 if (hip->addrs == NULL) {
773 return NGX_CONF_ERROR;
774 }
775
776 for (i = 0; i < hip->naddrs; i++) {
777 hip->addrs[i].addr = in_addr[i].addr;
778 hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf;
779
780 if (in_addr[i].hash.buckets == NULL
781 && (in_addr[i].dns_wildcards == NULL
782 || in_addr[i].dns_wildcards->hash.buckets == NULL))
783 {
764 continue; 784 continue;
765 } 785 }
766 } 786
767 787 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
768 ls->servers = &in_port[p]; 788 if (vn == NULL) {
769 a++; 789 return NGX_CONF_ERROR;
790 }
791 hip->addrs[i].virtual_names = vn;
792
793 vn->hash = in_addr[i].hash;
794 vn->dns_wildcards = in_addr[i].dns_wildcards;
795 }
796
797 if (done) {
798 break;
799 }
800
801 in_addr++;
802 in_port[p].addrs.elts = in_addr;
803 last--;
804
805 a = 0;
770 } 806 }
771 } 807 }
772 808
773 #if 0 809 #if 0
774 { 810 {
783 for (a = 0; a < in_port[p].addrs.nelts; a++) { 819 for (a = 0; a < in_port[p].addrs.nelts; a++) {
784 ngx_inet_ntop(AF_INET, &in_addr[a].addr, address, 20); 820 ngx_inet_ntop(AF_INET, &in_addr[a].addr, address, 20);
785 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0, 821 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0,
786 "%s:%d %p", 822 "%s:%d %p",
787 address, in_port[p].port, in_addr[a].core_srv_conf); 823 address, in_port[p].port, in_addr[a].core_srv_conf);
788 s_name = in_addr[a].names.elts; 824 name = in_addr[a].names.elts;
789 for (n = 0; n < in_addr[a].names.nelts; n++) { 825 for (n = 0; n < in_addr[a].names.nelts; n++) {
790 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, cf->log, 0, 826 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, cf->log, 0,
791 "%s:%d %V %p", 827 "%s:%d %V %p",
792 address, in_port[p].port, &s_name[n].name, 828 address, in_port[p].port, &name[n].name,
793 s_name[n].core_srv_conf); 829 name[n].core_srv_conf);
794 } 830 }
795 } 831 }
796 } 832 }
797 } 833 }
798 #endif 834 #endif
799 835
800 return NGX_CONF_OK; 836 return NGX_CONF_OK;
801 }
802
803
804 static int ngx_libc_cdecl
805 ngx_cmp_server_names(const void *one, const void *two)
806 {
807 ngx_http_server_name_t *first = (ngx_http_server_name_t *) one;
808 ngx_http_server_name_t *second = (ngx_http_server_name_t *) two;
809
810 return ngx_strcmp(first->name.data, second->name.data);
811 } 837 }
812 838
813 839
814 /* 840 /*
815 * add the server address, the server names and the server core module 841 * add the server address, the server names and the server core module
816 * configurations to the port (in_port) 842 * configurations to the port (in_port)
817 */ 843 */
818 844
819 static ngx_int_t 845 static ngx_int_t
820 ngx_http_add_address(ngx_conf_t *cf, ngx_http_in_port_t *in_port, 846 ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port,
821 ngx_http_listen_t *lscf, ngx_http_core_srv_conf_t *cscf) 847 ngx_http_listen_t *lscf, ngx_http_core_srv_conf_t *cscf)
822 { 848 {
823 ngx_http_in_addr_t *in_addr; 849 ngx_http_conf_in_addr_t *in_addr;
824 850
825 if (in_port->addrs.elts == NULL) { 851 if (in_port->addrs.elts == NULL) {
826 if (ngx_array_init(&in_port->addrs, cf->pool, 4, 852 if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4,
827 sizeof(ngx_http_in_addr_t)) != NGX_OK) 853 sizeof(ngx_http_conf_in_addr_t)) != NGX_OK)
828 { 854 {
829 return NGX_ERROR; 855 return NGX_ERROR;
830 } 856 }
831 } 857 }
832 858
834 if (in_addr == NULL) { 860 if (in_addr == NULL) {
835 return NGX_ERROR; 861 return NGX_ERROR;
836 } 862 }
837 863
838 in_addr->addr = lscf->addr; 864 in_addr->addr = lscf->addr;
865 in_addr->hash.buckets = NULL;
866 in_addr->hash.size = 0;
867 in_addr->dns_wildcards = NULL;
839 in_addr->names.elts = NULL; 868 in_addr->names.elts = NULL;
840 in_addr->hash = NULL;
841 in_addr->wildcards.elts = NULL;
842 in_addr->core_srv_conf = cscf; 869 in_addr->core_srv_conf = cscf;
843 in_addr->conf = lscf->conf; 870 in_addr->default_server = lscf->conf.default_server;
871 in_addr->bind = lscf->conf.bind;
872 in_addr->listen_conf = &lscf->conf;
844 873
845 #if (NGX_DEBUG) 874 #if (NGX_DEBUG)
846 { 875 {
847 u_char text[20]; 876 u_char text[20];
848 ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20); 877 ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20);
859 * add the server names and the server core module 888 * add the server names and the server core module
860 * configurations to the address:port (in_addr) 889 * configurations to the address:port (in_addr)
861 */ 890 */
862 891
863 static ngx_int_t 892 static ngx_int_t
864 ngx_http_add_names(ngx_conf_t *cf, ngx_http_in_addr_t *in_addr, 893 ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr,
865 ngx_http_core_srv_conf_t *cscf) 894 ngx_http_core_srv_conf_t *cscf)
866 { 895 {
867 ngx_uint_t i, n; 896 ngx_uint_t i, n;
868 ngx_array_t *array;
869 ngx_http_server_name_t *server_names, *name; 897 ngx_http_server_name_t *server_names, *name;
870 898
871 if (in_addr->names.elts == NULL) { 899 if (in_addr->names.elts == NULL) {
872 if (ngx_array_init(&in_addr->names, cf->pool, 4, 900 if (ngx_array_init(&in_addr->names, cf->temp_pool, 4,
873 sizeof(ngx_http_server_name_t)) != NGX_OK) 901 sizeof(ngx_http_server_name_t)) != NGX_OK)
874 { 902 {
875 return NGX_ERROR; 903 return NGX_ERROR;
876 } 904 }
877 } 905 }
878 906
879 if (in_addr->wildcards.elts == NULL) {
880 if (ngx_array_init(&in_addr->wildcards, cf->pool, 1,
881 sizeof(ngx_http_server_name_t)) != NGX_OK)
882 {
883 return NGX_ERROR;
884 }
885 }
886
887 server_names = cscf->server_names.elts; 907 server_names = cscf->server_names.elts;
888 for (i = 0; i < cscf->server_names.nelts; i++) { 908 for (i = 0; i < cscf->server_names.nelts; i++) {
889 909
890 for (n = 0; n < server_names[i].name.len; n++) { 910 for (n = 0; n < server_names[i].name.len; n++) {
891 server_names[i].name.data[n] = 911 server_names[i].name.data[n] =
893 } 913 }
894 914
895 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, 915 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
896 "name: %V", &server_names[i].name); 916 "name: %V", &server_names[i].name);
897 917
898 /* TODO: duplicate names can be checked here */ 918
899 919 name = ngx_array_push(&in_addr->names);
900
901 if (server_names[i].wildcard) {
902 array = &in_addr->wildcards;
903
904 } else {
905 array = &in_addr->names;
906 }
907
908 name = ngx_array_push(array);
909 if (name == NULL) { 920 if (name == NULL) {
910 return NGX_ERROR; 921 return NGX_ERROR;
911 } 922 }
912 server_names = cscf->server_names.elts; 923 server_names = cscf->server_names.elts;
913 924
924 { 935 {
925 char *rv; 936 char *rv;
926 ngx_uint_t i; 937 ngx_uint_t i;
927 ngx_http_core_loc_conf_t **clcfp; 938 ngx_http_core_loc_conf_t **clcfp;
928 939
929 clcfp = /* (ngx_http_core_loc_conf_t **) */ locations->elts; 940 clcfp = locations->elts;
930 941
931 for (i = 0; i < locations->nelts; i++) { 942 for (i = 0; i < locations->nelts; i++) {
932 rv = module->merge_loc_conf(cf, loc_conf[ctx_index], 943 rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
933 clcfp[i]->loc_conf[ctx_index]); 944 clcfp[i]->loc_conf[ctx_index]);
934 if (rv != NGX_CONF_OK) { 945 if (rv != NGX_CONF_OK) {
942 } 953 }
943 } 954 }
944 955
945 return NGX_CONF_OK; 956 return NGX_CONF_OK;
946 } 957 }
958
959
960 static int ngx_libc_cdecl
961 ngx_http_cmp_conf_in_addrs(const void *one, const void *two)
962 {
963 ngx_http_conf_in_addr_t *first, *second;
964
965 first = (ngx_http_conf_in_addr_t *) one;
966 second = (ngx_http_conf_in_addr_t *) two;
967
968 if (first->addr == INADDR_ANY) {
969 /* the INADDR_ANY must be the last resort, shift it to the end */
970 return 1;
971 }
972
973 if (first->bind && !second->bind) {
974 /* shift explicit bind()ed addresses to the start */
975 return -1;
976 }
977
978 if (!first->bind && second->bind) {
979 /* shift explicit bind()ed addresses to the start */
980 return 1;
981 }
982
983 /* do not sort by default */
984
985 return 0;
986 }
987
988
989 static int ngx_libc_cdecl
990 ngx_http_cmp_dns_wildcards(const void *one, const void *two)
991 {
992 ngx_hash_key_t *first, *second;
993
994 first = (ngx_hash_key_t *) one;
995 second = (ngx_hash_key_t *) two;
996
997 return ngx_strcmp(first->key.data, second->key.data);
998 }