Mercurial > hg > nginx
comparison src/http/ngx_http.c @ 2021:2022e71d26d2
split ngx_http_block()
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 22 May 2008 09:57:47 +0000 |
parents | 248a376403b0 |
children | 35b35b84f5ef |
comparison
equal
deleted
inserted
replaced
2020:248a376403b0 | 2021:2022e71d26d2 |
---|---|
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); | |
14 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, | 20 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, | 21 ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *lscf, |
16 ngx_http_core_srv_conf_t *cscf); | 22 ngx_http_core_srv_conf_t *cscf); |
17 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf, | 23 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); | 24 ngx_http_conf_in_addr_t *in_addr, ngx_http_core_srv_conf_t *cscf); |
71 | 77 |
72 static char * | 78 static char * |
73 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 79 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
74 { | 80 { |
75 char *rv; | 81 char *rv; |
76 ngx_int_t rc, j; | 82 ngx_int_t rc; |
77 ngx_uint_t mi, m, s, l, p, a, i, n; | 83 ngx_uint_t mi, m, s, l, p, a, i; |
78 ngx_uint_t find_config_index, use_rewrite, use_access; | |
79 ngx_uint_t last, bind_all, done; | 84 ngx_uint_t last, bind_all, done; |
80 ngx_conf_t pcf; | 85 ngx_conf_t pcf; |
81 ngx_array_t headers_in, in_ports; | 86 ngx_array_t in_ports; |
82 ngx_hash_key_t *hk; | |
83 ngx_hash_init_t hash; | 87 ngx_hash_init_t hash; |
84 ngx_listening_t *ls; | 88 ngx_listening_t *ls; |
85 ngx_http_listen_t *lscf; | 89 ngx_http_listen_t *lscf; |
86 ngx_http_module_t *module; | 90 ngx_http_module_t *module; |
87 ngx_http_header_t *header; | |
88 ngx_http_in_port_t *hip; | 91 ngx_http_in_port_t *hip; |
89 ngx_http_handler_pt *h; | |
90 ngx_http_conf_ctx_t *ctx; | 92 ngx_http_conf_ctx_t *ctx; |
91 ngx_http_conf_in_port_t *in_port; | 93 ngx_http_conf_in_port_t *in_port; |
92 ngx_http_conf_in_addr_t *in_addr; | 94 ngx_http_conf_in_addr_t *in_addr; |
93 ngx_hash_keys_arrays_t ha; | 95 ngx_hash_keys_arrays_t ha; |
94 ngx_http_server_name_t *name; | 96 ngx_http_server_name_t *name; |
95 ngx_http_phase_handler_t *ph; | |
96 ngx_http_virtual_names_t *vn; | 97 ngx_http_virtual_names_t *vn; |
97 ngx_http_core_srv_conf_t **cscfp, *cscf; | 98 ngx_http_core_srv_conf_t **cscfp, *cscf; |
98 ngx_http_core_loc_conf_t *clcf; | 99 ngx_http_core_loc_conf_t *clcf; |
99 ngx_http_phase_handler_pt checker; | |
100 ngx_http_core_main_conf_t *cmcf; | 100 ngx_http_core_main_conf_t *cmcf; |
101 #if (NGX_PCRE) | 101 #if (NGX_PCRE) |
102 ngx_uint_t regex; | 102 ngx_uint_t regex; |
103 #endif | 103 #endif |
104 | 104 |
283 } | 283 } |
284 } | 284 } |
285 } | 285 } |
286 | 286 |
287 | 287 |
288 /* init lists of the handlers */ | 288 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) { |
289 | 289 return NGX_CONF_ERROR; |
290 } | |
291 | |
292 if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) { | |
293 return NGX_CONF_ERROR; | |
294 } | |
295 | |
296 | |
297 for (m = 0; ngx_modules[m]; m++) { | |
298 if (ngx_modules[m]->type != NGX_HTTP_MODULE) { | |
299 continue; | |
300 } | |
301 | |
302 module = ngx_modules[m]->ctx; | |
303 mi = ngx_modules[m]->ctx_index; | |
304 | |
305 if (module->postconfiguration) { | |
306 if (module->postconfiguration(cf) != NGX_OK) { | |
307 return NGX_CONF_ERROR; | |
308 } | |
309 } | |
310 } | |
311 | |
312 if (ngx_http_variables_init_vars(cf) != NGX_OK) { | |
313 return NGX_CONF_ERROR; | |
314 } | |
315 | |
316 /* | |
317 * http{}'s cf->ctx was needed while the configuration merging | |
318 * and in postconfiguration process | |
319 */ | |
320 | |
321 *cf = pcf; | |
322 | |
323 | |
324 if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) { | |
325 return NGX_CONF_ERROR; | |
326 } | |
327 | |
328 | |
329 /* | |
330 * create the lists of ports, addresses and server names | |
331 * to quickly find the server core module configuration at run-time | |
332 */ | |
333 | |
334 if (ngx_array_init(&in_ports, cf->temp_pool, 2, | |
335 sizeof(ngx_http_conf_in_port_t)) | |
336 != NGX_OK) | |
337 { | |
338 return NGX_CONF_ERROR; | |
339 } | |
340 | |
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 | |
434 /* optimize the lists of ports, addresses and server names */ | |
435 | |
436 /* AF_INET only */ | |
437 | |
438 in_port = in_ports.elts; | |
439 for (p = 0; p < in_ports.nelts; p++) { | |
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 } | |
762 | |
763 return NGX_CONF_OK; | |
764 } | |
765 | |
766 | |
767 static ngx_int_t | |
768 ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) | |
769 { | |
290 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers, | 770 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers, |
291 cf->pool, 1, sizeof(ngx_http_handler_pt)) | 771 cf->pool, 1, sizeof(ngx_http_handler_pt)) |
292 != NGX_OK) | 772 != NGX_OK) |
293 { | 773 { |
294 return NGX_CONF_ERROR; | 774 return NGX_ERROR; |
295 } | 775 } |
296 | |
297 | 776 |
298 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers, | 777 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers, |
299 cf->pool, 1, sizeof(ngx_http_handler_pt)) | 778 cf->pool, 1, sizeof(ngx_http_handler_pt)) |
300 != NGX_OK) | 779 != NGX_OK) |
301 { | 780 { |
302 return NGX_CONF_ERROR; | 781 return NGX_ERROR; |
303 } | 782 } |
304 | |
305 | 783 |
306 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, | 784 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, |
307 cf->pool, 1, sizeof(ngx_http_handler_pt)) | 785 cf->pool, 1, sizeof(ngx_http_handler_pt)) |
308 != NGX_OK) | 786 != NGX_OK) |
309 { | 787 { |
310 return NGX_CONF_ERROR; | 788 return NGX_ERROR; |
311 } | 789 } |
312 | |
313 | 790 |
314 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers, | 791 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers, |
315 cf->pool, 1, sizeof(ngx_http_handler_pt)) | 792 cf->pool, 1, sizeof(ngx_http_handler_pt)) |
316 != NGX_OK) | 793 != NGX_OK) |
317 { | 794 { |
318 return NGX_CONF_ERROR; | 795 return NGX_ERROR; |
319 } | 796 } |
320 | |
321 | 797 |
322 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, | 798 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, |
323 cf->pool, 2, sizeof(ngx_http_handler_pt)) | 799 cf->pool, 2, sizeof(ngx_http_handler_pt)) |
324 != NGX_OK) | 800 != NGX_OK) |
325 { | 801 { |
326 return NGX_CONF_ERROR; | 802 return NGX_ERROR; |
327 } | 803 } |
328 | |
329 | 804 |
330 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, | 805 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, |
331 cf->pool, 4, sizeof(ngx_http_handler_pt)) | 806 cf->pool, 4, sizeof(ngx_http_handler_pt)) |
332 != NGX_OK) | 807 != NGX_OK) |
333 { | 808 { |
334 return NGX_CONF_ERROR; | 809 return NGX_ERROR; |
335 } | 810 } |
336 | |
337 | 811 |
338 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers, | 812 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers, |
339 cf->pool, 1, sizeof(ngx_http_handler_pt)) | 813 cf->pool, 1, sizeof(ngx_http_handler_pt)) |
340 != NGX_OK) | 814 != NGX_OK) |
341 { | 815 { |
342 return NGX_CONF_ERROR; | 816 return NGX_ERROR; |
343 } | 817 } |
344 | 818 |
819 return NGX_OK; | |
820 } | |
821 | |
822 | |
823 static ngx_int_t | |
824 ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) | |
825 { | |
826 ngx_array_t headers_in; | |
827 ngx_hash_key_t *hk; | |
828 ngx_hash_init_t hash; | |
829 ngx_http_header_t *header; | |
345 | 830 |
346 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) | 831 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) |
347 != NGX_OK) | 832 != NGX_OK) |
348 { | 833 { |
349 return NGX_CONF_ERROR; | 834 return NGX_ERROR; |
350 } | 835 } |
351 | 836 |
352 for (header = ngx_http_headers_in; header->name.len; header++) { | 837 for (header = ngx_http_headers_in; header->name.len; header++) { |
353 hk = ngx_array_push(&headers_in); | 838 hk = ngx_array_push(&headers_in); |
354 if (hk == NULL) { | 839 if (hk == NULL) { |
355 return NGX_CONF_ERROR; | 840 return NGX_ERROR; |
356 } | 841 } |
357 | 842 |
358 hk->key = header->name; | 843 hk->key = header->name; |
359 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); | 844 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); |
360 hk->value = header; | 845 hk->value = header; |
367 hash.name = "headers_in_hash"; | 852 hash.name = "headers_in_hash"; |
368 hash.pool = cf->pool; | 853 hash.pool = cf->pool; |
369 hash.temp_pool = NULL; | 854 hash.temp_pool = NULL; |
370 | 855 |
371 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) { | 856 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) { |
372 return NGX_CONF_ERROR; | 857 return NGX_ERROR; |
373 } | 858 } |
374 | 859 |
375 | 860 return NGX_OK; |
376 for (m = 0; ngx_modules[m]; m++) { | 861 } |
377 if (ngx_modules[m]->type != NGX_HTTP_MODULE) { | 862 |
378 continue; | 863 |
379 } | 864 static ngx_int_t |
380 | 865 ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) |
381 module = ngx_modules[m]->ctx; | 866 { |
382 mi = ngx_modules[m]->ctx_index; | 867 ngx_int_t j; |
383 | 868 ngx_uint_t i, n; |
384 if (module->postconfiguration) { | 869 ngx_uint_t find_config_index, use_rewrite, use_access; |
385 if (module->postconfiguration(cf) != NGX_OK) { | 870 ngx_http_handler_pt *h; |
386 return NGX_CONF_ERROR; | 871 ngx_http_phase_handler_t *ph; |
387 } | 872 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 | 873 |
403 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1; | 874 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1; |
404 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1; | 875 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1; |
405 find_config_index = 0; | 876 find_config_index = 0; |
406 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0; | 877 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0; |
413 } | 884 } |
414 | 885 |
415 ph = ngx_pcalloc(cf->pool, | 886 ph = ngx_pcalloc(cf->pool, |
416 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *)); | 887 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *)); |
417 if (ph == NULL) { | 888 if (ph == NULL) { |
418 return NGX_CONF_ERROR; | 889 return NGX_ERROR; |
419 } | 890 } |
420 | 891 |
421 cmcf->phase_engine.handlers = ph; | 892 cmcf->phase_engine.handlers = ph; |
422 n = 0; | 893 n = 0; |
423 | 894 |
491 ph->next = n; | 962 ph->next = n; |
492 ph++; | 963 ph++; |
493 } | 964 } |
494 } | 965 } |
495 | 966 |
496 | 967 return NGX_OK; |
497 /* | |
498 * create the lists of ports, addresses and server names | |
499 * to quickly find the server core module configuration at run-time | |
500 */ | |
501 | |
502 if (ngx_array_init(&in_ports, cf->temp_pool, 2, | |
503 sizeof(ngx_http_conf_in_port_t)) | |
504 != NGX_OK) | |
505 { | |
506 return NGX_CONF_ERROR; | |
507 } | |
508 | |
509 /* "server" directives */ | |
510 | |
511 cscfp = cmcf->servers.elts; | |
512 for (s = 0; s < cmcf->servers.nelts; s++) { | |
513 | |
514 /* "listen" directives */ | |
515 | |
516 lscf = cscfp[s]->listen.elts; | |
517 for (l = 0; l < cscfp[s]->listen.nelts; l++) { | |
518 | |
519 /* AF_INET only */ | |
520 | |
521 in_port = in_ports.elts; | |
522 for (p = 0; p < in_ports.nelts; p++) { | |
523 | |
524 if (lscf[l].port != in_port[p].port) { | |
525 continue; | |
526 } | |
527 | |
528 /* the port is already in the port list */ | |
529 | |
530 in_addr = in_port[p].addrs.elts; | |
531 for (a = 0; a < in_port[p].addrs.nelts; a++) { | |
532 | |
533 if (lscf[l].addr != in_addr[a].addr) { | |
534 continue; | |
535 } | |
536 | |
537 /* the address is already in the address list */ | |
538 | |
539 if (ngx_http_add_names(cf, &in_addr[a], cscfp[s]) != NGX_OK) | |
540 { | |
541 return NGX_CONF_ERROR; | |
542 } | |
543 | |
544 /* | |
545 * check the duplicate "default" server | |
546 * for this address:port | |
547 */ | |
548 | |
549 if (lscf[l].conf.default_server) { | |
550 | |
551 if (in_addr[a].default_server) { | |
552 ngx_log_error(NGX_LOG_ERR, cf->log, 0, | |
553 "the duplicate default server in %s:%ui", | |
554 lscf[l].file_name, lscf[l].line); | |
555 | |
556 return NGX_CONF_ERROR; | |
557 } | |
558 | |
559 in_addr[a].core_srv_conf = cscfp[s]; | |
560 in_addr[a].default_server = 1; | |
561 } | |
562 | |
563 goto found; | |
564 } | |
565 | |
566 /* | |
567 * add the address to the addresses list that | |
568 * bound to this port | |
569 */ | |
570 | |
571 if (ngx_http_add_address(cf, &in_port[p], &lscf[l], cscfp[s]) | |
572 != NGX_OK) | |
573 { | |
574 return NGX_CONF_ERROR; | |
575 } | |
576 | |
577 goto found; | |
578 } | |
579 | |
580 /* add the port to the in_port list */ | |
581 | |
582 in_port = ngx_array_push(&in_ports); | |
583 if (in_port == NULL) { | |
584 return NGX_CONF_ERROR; | |
585 } | |
586 | |
587 in_port->port = lscf[l].port; | |
588 in_port->addrs.elts = NULL; | |
589 | |
590 if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s]) != NGX_OK) | |
591 { | |
592 return NGX_CONF_ERROR; | |
593 } | |
594 | |
595 found: | |
596 | |
597 continue; | |
598 } | |
599 } | |
600 | |
601 | |
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 return NGX_CONF_OK; | |
932 } | 968 } |
933 | 969 |
934 | 970 |
935 /* | 971 /* |
936 * add the server address, the server names and the server core module | 972 * add the server address, the server names and the server core module |