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 }