3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
13 static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
14 ngx_http_core_main_conf_t *cmcf);
15 static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
16 ngx_http_core_main_conf_t *cmcf);
17 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
18 ngx_http_core_main_conf_t *cmcf);
20 static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf,
21 ngx_array_t *servers, ngx_array_t *in_ports);
22 static ngx_int_t ngx_http_add_ports(ngx_conf_t *cf,
23 ngx_http_core_srv_conf_t *cscf, ngx_array_t *ports,
24 ngx_http_listen_t *listen);
25 static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
26 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
27 ngx_http_listen_t *listen);
28 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
29 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
30 ngx_http_listen_t *listen);
31 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
32 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
34 static char *ngx_http_merge_locations(ngx_conf_t *cf,
35 ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
36 ngx_uint_t ctx_index);
37 static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
38 ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
39 static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
40 ngx_http_core_loc_conf_t *pclcf);
41 static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
42 const ngx_queue_t *two);
43 static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
44 ngx_queue_t *locations);
45 static void ngx_http_create_locations_list(ngx_queue_t *locations,
47 static ngx_http_location_tree_node_t *
48 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
51 static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
52 ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
53 static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
54 ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
55 static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
56 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
59 static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
60 ngx_http_conf_port_t *port);
61 static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
62 ngx_http_conf_addr_t *addr);
63 static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
64 ngx_http_conf_addr_t *addr);
66 static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
67 ngx_http_conf_addr_t *addr);
70 ngx_uint_t ngx_http_max_module;
73 ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
74 ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
77 ngx_str_t ngx_http_html_default_types[] = {
78 ngx_string("text/html"),
83 static ngx_command_t ngx_http_commands[] = {
86 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
96 static ngx_core_module_t ngx_http_module_ctx = {
103 ngx_module_t ngx_http_module = {
105 &ngx_http_module_ctx, /* module context */
106 ngx_http_commands, /* module directives */
107 NGX_CORE_MODULE, /* module type */
108 NULL, /* init master */
109 NULL, /* init module */
110 NULL, /* init process */
111 NULL, /* init thread */
112 NULL, /* exit thread */
113 NULL, /* exit process */
114 NULL, /* exit master */
115 NGX_MODULE_V1_PADDING
120 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
125 ngx_array_t in_ports;
126 ngx_http_module_t *module;
127 ngx_http_conf_ctx_t *ctx;
128 ngx_http_core_loc_conf_t *clcf;
129 ngx_http_core_srv_conf_t **cscfp;
130 ngx_http_core_main_conf_t *cmcf;
132 /* the main http context */
134 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
136 return NGX_CONF_ERROR;
139 *(ngx_http_conf_ctx_t **) conf = ctx;
142 /* count the number of the http modules and set up their indices */
144 ngx_http_max_module = 0;
145 for (m = 0; ngx_modules[m]; m++) {
146 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
150 ngx_modules[m]->ctx_index = ngx_http_max_module++;
154 /* the http main_conf context, it is the same in the all http contexts */
156 ctx->main_conf = ngx_pcalloc(cf->pool,
157 sizeof(void *) * ngx_http_max_module);
158 if (ctx->main_conf == NULL) {
159 return NGX_CONF_ERROR;
164 * the http null srv_conf context, it is used to merge
165 * the server{}s' srv_conf's
168 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
169 if (ctx->srv_conf == NULL) {
170 return NGX_CONF_ERROR;
175 * the http null loc_conf context, it is used to merge
176 * the server{}s' loc_conf's
179 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
180 if (ctx->loc_conf == NULL) {
181 return NGX_CONF_ERROR;
186 * create the main_conf's, the null srv_conf's, and the null loc_conf's
187 * of the all http modules
190 for (m = 0; ngx_modules[m]; m++) {
191 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
195 module = ngx_modules[m]->ctx;
196 mi = ngx_modules[m]->ctx_index;
198 if (module->create_main_conf) {
199 ctx->main_conf[mi] = module->create_main_conf(cf);
200 if (ctx->main_conf[mi] == NULL) {
201 return NGX_CONF_ERROR;
205 if (module->create_srv_conf) {
206 ctx->srv_conf[mi] = module->create_srv_conf(cf);
207 if (ctx->srv_conf[mi] == NULL) {
208 return NGX_CONF_ERROR;
212 if (module->create_loc_conf) {
213 ctx->loc_conf[mi] = module->create_loc_conf(cf);
214 if (ctx->loc_conf[mi] == NULL) {
215 return NGX_CONF_ERROR;
223 for (m = 0; ngx_modules[m]; m++) {
224 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
228 module = ngx_modules[m]->ctx;
230 if (module->preconfiguration) {
231 if (module->preconfiguration(cf) != NGX_OK) {
232 return NGX_CONF_ERROR;
237 /* parse inside the http{} block */
239 cf->module_type = NGX_HTTP_MODULE;
240 cf->cmd_type = NGX_HTTP_MAIN_CONF;
241 rv = ngx_conf_parse(cf, NULL);
243 if (rv != NGX_CONF_OK) {
248 * init http{} main_conf's, merge the server{}s' srv_conf's
249 * and its location{}s' loc_conf's
252 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
253 cscfp = cmcf->servers.elts;
255 for (m = 0; ngx_modules[m]; m++) {
256 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
260 module = ngx_modules[m]->ctx;
261 mi = ngx_modules[m]->ctx_index;
263 /* init http{} main_conf's */
265 if (module->init_main_conf) {
266 rv = module->init_main_conf(cf, ctx->main_conf[mi]);
267 if (rv != NGX_CONF_OK) {
272 for (s = 0; s < cmcf->servers.nelts; s++) {
274 /* merge the server{}s' srv_conf's */
276 if (module->merge_srv_conf) {
277 rv = module->merge_srv_conf(cf, ctx->srv_conf[mi],
278 cscfp[s]->ctx->srv_conf[mi]);
279 if (rv != NGX_CONF_OK) {
284 if (module->merge_loc_conf) {
286 /* merge the server{}'s loc_conf */
288 rv = module->merge_loc_conf(cf, ctx->loc_conf[mi],
289 cscfp[s]->ctx->loc_conf[mi]);
290 if (rv != NGX_CONF_OK) {
294 /* merge the locations{}' loc_conf's */
296 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
298 rv = ngx_http_merge_locations(cf, clcf->locations,
299 cscfp[s]->ctx->loc_conf,
301 if (rv != NGX_CONF_OK) {
309 /* create location trees */
311 for (s = 0; s < cmcf->servers.nelts; s++) {
313 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
315 if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
316 return NGX_CONF_ERROR;
319 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
320 return NGX_CONF_ERROR;
325 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
326 return NGX_CONF_ERROR;
329 if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
330 return NGX_CONF_ERROR;
334 for (m = 0; ngx_modules[m]; m++) {
335 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
339 module = ngx_modules[m]->ctx;
341 if (module->postconfiguration) {
342 if (module->postconfiguration(cf) != NGX_OK) {
343 return NGX_CONF_ERROR;
348 if (ngx_http_variables_init_vars(cf) != NGX_OK) {
349 return NGX_CONF_ERROR;
353 * http{}'s cf->ctx was needed while the configuration merging
354 * and in postconfiguration process
360 if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
361 return NGX_CONF_ERROR;
366 * create the lists of ports, addresses and server names
367 * to find quickly the server core module configuration at run-time
370 if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) {
371 return NGX_CONF_ERROR;
375 /* optimize the lists of ports, addresses and server names */
377 if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) {
378 return NGX_CONF_ERROR;
392 ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
394 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
395 cf->pool, 1, sizeof(ngx_http_handler_pt))
401 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
402 cf->pool, 1, sizeof(ngx_http_handler_pt))
408 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
409 cf->pool, 1, sizeof(ngx_http_handler_pt))
415 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
416 cf->pool, 1, sizeof(ngx_http_handler_pt))
422 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
423 cf->pool, 2, sizeof(ngx_http_handler_pt))
429 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
430 cf->pool, 4, sizeof(ngx_http_handler_pt))
436 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
437 cf->pool, 1, sizeof(ngx_http_handler_pt))
448 ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
450 ngx_array_t headers_in;
452 ngx_hash_init_t hash;
453 ngx_http_header_t *header;
455 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
461 for (header = ngx_http_headers_in; header->name.len; header++) {
462 hk = ngx_array_push(&headers_in);
467 hk->key = header->name;
468 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
472 hash.hash = &cmcf->headers_in_hash;
473 hash.key = ngx_hash_key_lc;
475 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
476 hash.name = "headers_in_hash";
477 hash.pool = cf->pool;
478 hash.temp_pool = NULL;
480 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
489 ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
493 ngx_uint_t find_config_index, use_rewrite, use_access;
494 ngx_http_handler_pt *h;
495 ngx_http_phase_handler_t *ph;
496 ngx_http_phase_handler_pt checker;
498 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
499 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
500 find_config_index = 0;
501 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
502 use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
504 n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;
506 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
507 n += cmcf->phases[i].handlers.nelts;
510 ph = ngx_pcalloc(cf->pool,
511 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
516 cmcf->phase_engine.handlers = ph;
519 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
520 h = cmcf->phases[i].handlers.elts;
524 case NGX_HTTP_SERVER_REWRITE_PHASE:
525 if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
526 cmcf->phase_engine.server_rewrite_index = n;
528 checker = ngx_http_core_generic_phase;
532 case NGX_HTTP_FIND_CONFIG_PHASE:
533 find_config_index = n;
535 ph->checker = ngx_http_core_find_config_phase;
541 case NGX_HTTP_REWRITE_PHASE:
542 if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
543 cmcf->phase_engine.location_rewrite_index = n;
545 checker = ngx_http_core_generic_phase;
549 case NGX_HTTP_POST_REWRITE_PHASE:
551 ph->checker = ngx_http_core_post_rewrite_phase;
552 ph->next = find_config_index;
559 case NGX_HTTP_ACCESS_PHASE:
560 checker = ngx_http_core_access_phase;
564 case NGX_HTTP_POST_ACCESS_PHASE:
566 ph->checker = ngx_http_core_post_access_phase;
573 case NGX_HTTP_TRY_FILES_PHASE:
574 if (cmcf->try_files) {
575 ph->checker = ngx_http_core_try_files_phase;
582 case NGX_HTTP_CONTENT_PHASE:
583 checker = ngx_http_core_content_phase;
587 checker = ngx_http_core_generic_phase;
590 n += cmcf->phases[i].handlers.nelts;
592 for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
593 ph->checker = checker;
605 ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
606 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
610 ngx_http_core_loc_conf_t *clcf;
611 ngx_http_location_queue_t *lq;
613 if (locations == NULL) {
617 for (q = ngx_queue_head(locations);
618 q != ngx_queue_sentinel(locations);
619 q = ngx_queue_next(q))
621 lq = (ngx_http_location_queue_t *) q;
623 clcf = lq->exact ? lq->exact : lq->inclusive;
625 rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
626 clcf->loc_conf[ctx_index]);
627 if (rv != NGX_CONF_OK) {
631 rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
633 if (rv != NGX_CONF_OK) {
643 ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
644 ngx_http_core_loc_conf_t *pclcf)
647 ngx_queue_t *q, *locations, *named, tail;
648 ngx_http_core_loc_conf_t *clcf;
649 ngx_http_location_queue_t *lq;
650 ngx_http_core_loc_conf_t **clcfp;
656 locations = pclcf->locations;
658 if (locations == NULL) {
662 ngx_queue_sort(locations, ngx_http_cmp_locations);
671 for (q = ngx_queue_head(locations);
672 q != ngx_queue_sentinel(locations);
673 q = ngx_queue_next(q))
675 lq = (ngx_http_location_queue_t *) q;
677 clcf = lq->exact ? lq->exact : lq->inclusive;
679 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
712 if (q != ngx_queue_sentinel(locations)) {
713 ngx_queue_split(locations, q, &tail);
717 clcfp = ngx_palloc(cf->pool,
718 (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
723 cscf->named_locations = clcfp;
726 q != ngx_queue_sentinel(locations);
727 q = ngx_queue_next(q))
729 lq = (ngx_http_location_queue_t *) q;
731 *(clcfp++) = lq->exact;
736 ngx_queue_split(locations, named, &tail);
743 clcfp = ngx_palloc(cf->pool,
744 (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
749 pclcf->regex_locations = clcfp;
752 q != ngx_queue_sentinel(locations);
753 q = ngx_queue_next(q))
755 lq = (ngx_http_location_queue_t *) q;
757 *(clcfp++) = lq->exact;
762 ngx_queue_split(locations, regex, &tail);
772 ngx_http_init_static_location_trees(ngx_conf_t *cf,
773 ngx_http_core_loc_conf_t *pclcf)
775 ngx_queue_t *q, *locations;
776 ngx_http_core_loc_conf_t *clcf;
777 ngx_http_location_queue_t *lq;
779 locations = pclcf->locations;
781 if (locations == NULL) {
785 if (ngx_queue_empty(locations)) {
789 for (q = ngx_queue_head(locations);
790 q != ngx_queue_sentinel(locations);
791 q = ngx_queue_next(q))
793 lq = (ngx_http_location_queue_t *) q;
795 clcf = lq->exact ? lq->exact : lq->inclusive;
797 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
802 if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
806 ngx_http_create_locations_list(locations, ngx_queue_head(locations));
808 pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
809 if (pclcf->static_locations == NULL) {
818 ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
819 ngx_http_core_loc_conf_t *clcf)
821 ngx_http_location_queue_t *lq;
823 if (*locations == NULL) {
824 *locations = ngx_palloc(cf->temp_pool,
825 sizeof(ngx_http_location_queue_t));
826 if (*locations == NULL) {
830 ngx_queue_init(*locations);
833 lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
838 if (clcf->exact_match
842 || clcf->named || clcf->noname)
845 lq->inclusive = NULL;
849 lq->inclusive = clcf;
852 lq->name = &clcf->name;
853 lq->file_name = cf->conf_file->file.name.data;
854 lq->line = cf->conf_file->line;
856 ngx_queue_init(&lq->list);
858 ngx_queue_insert_tail(*locations, &lq->queue);
865 ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
868 ngx_http_core_loc_conf_t *first, *second;
869 ngx_http_location_queue_t *lq1, *lq2;
871 lq1 = (ngx_http_location_queue_t *) one;
872 lq2 = (ngx_http_location_queue_t *) two;
874 first = lq1->exact ? lq1->exact : lq1->inclusive;
875 second = lq2->exact ? lq2->exact : lq2->inclusive;
877 if (first->noname && !second->noname) {
878 /* shift no named locations to the end */
882 if (!first->noname && second->noname) {
883 /* shift no named locations to the end */
887 if (first->noname || second->noname) {
888 /* do not sort no named locations */
892 if (first->named && !second->named) {
893 /* shift named locations to the end */
897 if (!first->named && second->named) {
898 /* shift named locations to the end */
902 if (first->named && second->named) {
903 return ngx_strcmp(first->name.data, second->name.data);
908 if (first->regex && !second->regex) {
909 /* shift the regex matches to the end */
913 if (!first->regex && second->regex) {
914 /* shift the regex matches to the end */
918 if (first->regex || second->regex) {
919 /* do not sort the regex matches */
925 rc = ngx_strcmp(first->name.data, second->name.data);
927 if (rc == 0 && !first->exact_match && second->exact_match) {
928 /* an exact match must be before the same inclusive one */
937 ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
940 ngx_http_location_queue_t *lq, *lx;
942 q = ngx_queue_head(locations);
944 while (q != ngx_queue_last(locations)) {
946 x = ngx_queue_next(q);
948 lq = (ngx_http_location_queue_t *) q;
949 lx = (ngx_http_location_queue_t *) x;
951 if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
953 if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
954 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
955 "duplicate location \"%V\" in %s:%ui",
956 lx->name, lx->file_name, lx->line);
961 lq->inclusive = lx->inclusive;
968 q = ngx_queue_next(q);
976 ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
980 ngx_queue_t *x, tail;
981 ngx_http_location_queue_t *lq, *lx;
983 if (q == ngx_queue_last(locations)) {
987 lq = (ngx_http_location_queue_t *) q;
989 if (lq->inclusive == NULL) {
990 ngx_http_create_locations_list(locations, ngx_queue_next(q));
995 name = lq->name->data;
997 for (x = ngx_queue_next(q);
998 x != ngx_queue_sentinel(locations);
999 x = ngx_queue_next(x))
1001 lx = (ngx_http_location_queue_t *) x;
1003 if (len > lx->name->len
1004 || (ngx_strncmp(name, lx->name->data, len) != 0))
1010 q = ngx_queue_next(q);
1013 ngx_http_create_locations_list(locations, x);
1017 ngx_queue_split(locations, q, &tail);
1018 ngx_queue_add(&lq->list, &tail);
1020 if (x == ngx_queue_sentinel(locations)) {
1021 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1025 ngx_queue_split(&lq->list, x, &tail);
1026 ngx_queue_add(locations, &tail);
1028 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1030 ngx_http_create_locations_list(locations, x);
1035 * to keep cache locality for left leaf nodes, allocate nodes in following
1036 * order: node, left subtree, right subtree, inclusive subtree
1039 static ngx_http_location_tree_node_t *
1040 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
1044 ngx_queue_t *q, tail;
1045 ngx_http_location_queue_t *lq;
1046 ngx_http_location_tree_node_t *node;
1048 q = ngx_queue_middle(locations);
1050 lq = (ngx_http_location_queue_t *) q;
1051 len = lq->name->len - prefix;
1053 node = ngx_palloc(cf->pool,
1054 offsetof(ngx_http_location_tree_node_t, name) + len);
1062 node->exact = lq->exact;
1063 node->inclusive = lq->inclusive;
1065 node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
1066 || (lq->inclusive && lq->inclusive->auto_redirect));
1068 node->len = (u_char) len;
1069 ngx_memcpy(node->name, &lq->name->data[prefix], len);
1071 ngx_queue_split(locations, q, &tail);
1073 if (ngx_queue_empty(locations)) {
1075 * ngx_queue_split() insures that if left part is empty,
1076 * then right one is empty too
1081 node->left = ngx_http_create_locations_tree(cf, locations, prefix);
1082 if (node->left == NULL) {
1086 ngx_queue_remove(q);
1088 if (ngx_queue_empty(&tail)) {
1092 node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
1093 if (node->right == NULL) {
1099 if (ngx_queue_empty(&lq->list)) {
1103 node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
1104 if (node->tree == NULL) {
1113 ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
1117 ngx_http_listen_t *listen;
1118 ngx_http_core_srv_conf_t **cscfp;
1120 if (ngx_array_init(ports, cf->temp_pool, 2, sizeof(ngx_http_conf_port_t))
1126 /* "server" directives */
1128 cscfp = servers->elts;
1129 for (s = 0; s < servers->nelts; s++) {
1131 /* "listen" directives */
1133 listen = cscfp[s]->listen.elts;
1134 for (i = 0; i < cscfp[s]->listen.nelts; i++) {
1136 if (ngx_http_add_ports(cf, cscfp[s], ports, &listen[i]) != NGX_OK) {
1147 ngx_http_add_ports(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1148 ngx_array_t *ports, ngx_http_listen_t *listen)
1152 struct sockaddr *sa;
1153 struct sockaddr_in *sin;
1154 ngx_http_conf_port_t *port;
1155 #if (NGX_HAVE_INET6)
1156 struct sockaddr_in6 *sin6;
1159 sa = (struct sockaddr *) &listen->sockaddr;
1161 switch (sa->sa_family) {
1163 #if (NGX_HAVE_INET6)
1165 sin6 = (struct sockaddr_in6 *) sa;
1166 p = sin6->sin6_port;
1170 default: /* AF_INET */
1171 sin = (struct sockaddr_in *) sa;
1177 for (i = 0; i < ports->nelts; i++) {
1179 if (p != port[i].port || sa->sa_family != port[i].family) {
1183 /* a port is already in the in_port list */
1185 return ngx_http_add_addresses(cf, cscf, &port[i], listen);
1188 /* add a port to the in_port list */
1190 port = ngx_array_push(ports);
1195 port->family = sa->sa_family;
1197 port->addrs.elts = NULL;
1199 return ngx_http_add_address(cf, cscf, port, listen);
1204 ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1205 ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
1210 struct sockaddr *sa;
1211 ngx_http_conf_addr_t *addr;
1214 * we can not compare whole sockaddr struct's as kernel
1215 * may fill some fields in inherited sockaddr struct's
1218 sa = (struct sockaddr *) &listen->sockaddr;
1220 switch (sa->sa_family) {
1222 #if (NGX_HAVE_INET6)
1224 off = offsetof(struct sockaddr_in6, sin6_addr);
1229 default: /* AF_INET */
1230 off = offsetof(struct sockaddr_in, sin_addr);
1235 p = listen->sockaddr + off;
1237 addr = port->addrs.elts;
1239 for (i = 0; i < port->addrs.nelts; i++) {
1241 if (ngx_memcmp(p, (u_char *) addr[i].sockaddr + off, len) != 0) {
1245 /* the address is already in the address list */
1247 if (ngx_http_add_names(cf, cscf, &addr[i]) != NGX_OK) {
1251 /* check the duplicate "default" server for this address:port */
1253 if (listen->conf.default_server) {
1255 if (addr[i].default_server) {
1256 ngx_log_error(NGX_LOG_ERR, cf->log, 0,
1257 "the duplicate default server in %s:%ui",
1258 listen->file_name, listen->line);
1263 addr[i].core_srv_conf = cscf;
1264 addr[i].default_server = 1;
1266 addr[i].ssl = listen->conf.ssl;
1268 addr[i].listen_conf = &listen->conf;
1274 /* add the address to the addresses list that bound to this port */
1276 return ngx_http_add_address(cf, cscf, port, listen);
1281 * add the server address, the server names and the server core module
1282 * configurations to the port (in_port)
1286 ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1287 ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
1289 ngx_http_conf_addr_t *addr;
1291 if (port->addrs.elts == NULL) {
1292 if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
1293 sizeof(ngx_http_conf_addr_t))
1300 addr = ngx_array_push(&port->addrs);
1305 addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
1306 addr->socklen = listen->socklen;
1307 addr->hash.buckets = NULL;
1308 addr->hash.size = 0;
1309 addr->wc_head = NULL;
1310 addr->wc_tail = NULL;
1311 addr->names.elts = NULL;
1316 addr->core_srv_conf = cscf;
1317 addr->default_server = listen->conf.default_server;
1318 addr->bind = listen->conf.bind;
1319 addr->wildcard = listen->conf.wildcard;
1321 addr->ssl = listen->conf.ssl;
1323 addr->listen_conf = &listen->conf;
1325 return ngx_http_add_names(cf, cscf, addr);
1330 * add the server names and the server core module
1331 * configurations to the address:port
1335 ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1336 ngx_http_conf_addr_t *addr)
1339 ngx_http_server_name_t *server_names, *name;
1341 if (addr->names.elts == NULL) {
1342 if (ngx_array_init(&addr->names, cf->temp_pool, 4,
1343 sizeof(ngx_http_server_name_t))
1350 server_names = cscf->server_names.elts;
1352 for (i = 0; i < cscf->server_names.nelts; i++) {
1354 ngx_strlow(server_names[i].name.data, server_names[i].name.data,
1355 server_names[i].name.len);
1357 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
1358 "name: %V", &server_names[i].name);
1360 name = ngx_array_push(&addr->names);
1365 *name = server_names[i];
1373 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1377 ngx_http_conf_port_t *port;
1378 ngx_http_conf_addr_t *addr;
1379 ngx_http_server_name_t *name;
1382 for (p = 0; p < ports->nelts; p++) {
1384 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
1385 sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
1388 * check whether all name-based servers have the same
1389 * configuraiton as a default server for given address:port
1392 addr = port[p].addrs.elts;
1393 for (a = 0; a < port[p].addrs.nelts; a++) {
1395 name = addr[a].names.elts;
1396 for (s = 0; s < addr[a].names.nelts; s++) {
1398 if (addr[a].core_srv_conf == name[s].core_srv_conf) {
1402 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
1410 if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
1420 ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1421 ngx_http_conf_addr_t *addr)
1425 ngx_hash_init_t hash;
1426 ngx_http_server_name_t *name;
1427 ngx_hash_keys_arrays_t ha;
1429 ngx_uint_t regex, i;
1434 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1436 ha.temp_pool = ngx_create_pool(16384, cf->log);
1437 if (ha.temp_pool == NULL) {
1443 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
1447 name = addr->names.elts;
1449 for (s = 0; s < addr->names.nelts; s++) {
1452 if (name[s].regex) {
1458 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
1459 NGX_HASH_WILDCARD_KEY);
1461 if (rc == NGX_ERROR) {
1465 if (rc == NGX_DECLINED) {
1466 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1467 "invalid server name or wildcard \"%V\" on %s",
1468 &name[s].name, addr->listen_conf->addr);
1472 if (rc == NGX_BUSY) {
1473 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
1474 "conflicting server name \"%V\" on %s, ignored",
1475 &name[s].name, addr->listen_conf->addr);
1479 hash.key = ngx_hash_key_lc;
1480 hash.max_size = cmcf->server_names_hash_max_size;
1481 hash.bucket_size = cmcf->server_names_hash_bucket_size;
1482 hash.name = "server_names_hash";
1483 hash.pool = cf->pool;
1485 if (ha.keys.nelts) {
1486 hash.hash = &addr->hash;
1487 hash.temp_pool = NULL;
1489 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
1494 if (ha.dns_wc_head.nelts) {
1496 ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
1497 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1500 hash.temp_pool = ha.temp_pool;
1502 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1503 ha.dns_wc_head.nelts)
1509 addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
1512 if (ha.dns_wc_tail.nelts) {
1514 ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
1515 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1518 hash.temp_pool = ha.temp_pool;
1520 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1521 ha.dns_wc_tail.nelts)
1527 addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
1530 ngx_destroy_pool(ha.temp_pool);
1538 addr->nregex = regex;
1539 addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
1540 if (addr->regex == NULL) {
1544 for (i = 0, s = 0; s < addr->names.nelts; s++) {
1545 if (name[s].regex) {
1546 addr->regex[i++] = name[s];
1556 ngx_destroy_pool(ha.temp_pool);
1563 ngx_http_cmp_conf_addrs(const void *one, const void *two)
1565 ngx_http_conf_addr_t *first, *second;
1567 first = (ngx_http_conf_addr_t *) one;
1568 second = (ngx_http_conf_addr_t *) two;
1570 if (first->wildcard) {
1571 /* a wildcard address must be the last resort, shift it to the end */
1575 if (first->bind && !second->bind) {
1576 /* shift explicit bind()ed addresses to the start */
1580 if (!first->bind && second->bind) {
1581 /* shift explicit bind()ed addresses to the start */
1585 /* do not sort by default */
1591 static int ngx_libc_cdecl
1592 ngx_http_cmp_dns_wildcards(const void *one, const void *two)
1594 ngx_hash_key_t *first, *second;
1596 first = (ngx_hash_key_t *) one;
1597 second = (ngx_hash_key_t *) two;
1599 return ngx_strcmp(first->key.data, second->key.data);
1604 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
1606 ngx_uint_t i, last, bind_wildcard;
1607 ngx_listening_t *ls;
1608 ngx_http_port_t *hport;
1609 ngx_http_conf_addr_t *addr;
1611 addr = port->addrs.elts;
1612 last = port->addrs.nelts;
1615 * If there is a binding to an "*:port" then we need to bind() to
1616 * the "*:port" only and ignore other implicit bindings. The bindings
1617 * have been already sorted: explicit bindings are on the start, then
1618 * implicit bindings go, and wildcard binding is in the end.
1621 if (addr[last - 1].wildcard) {
1622 addr[last - 1].bind = 1;
1633 if (bind_wildcard && !addr[i].bind) {
1638 ls = ngx_http_add_listening(cf, &addr[i]);
1643 hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
1644 if (hport == NULL) {
1648 ls->servers = hport;
1650 if (i == last - 1) {
1651 hport->naddrs = last;
1658 switch (ls->sockaddr->sa_family) {
1660 #if (NGX_HAVE_INET6)
1662 if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
1667 default: /* AF_INET */
1668 if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
1682 static ngx_listening_t *
1683 ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
1685 ngx_listening_t *ls;
1686 struct sockaddr *sa;
1687 ngx_http_core_loc_conf_t *clcf;
1688 ngx_http_core_srv_conf_t *cscf;
1689 u_char text[NGX_SOCKADDR_STRLEN];
1691 ls = ngx_array_push(&cf->cycle->listening);
1696 ngx_memzero(ls, sizeof(ngx_listening_t));
1698 sa = ngx_palloc(cf->pool, addr->socklen);
1703 ngx_memcpy(sa, addr->sockaddr, addr->socklen);
1706 ls->socklen = addr->socklen;
1708 ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
1710 ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len);
1711 if (ls->addr_text.data == NULL) {
1715 ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len);
1717 ls->fd = (ngx_socket_t) -1;
1718 ls->type = SOCK_STREAM;
1720 switch (ls->sockaddr->sa_family) {
1721 #if (NGX_HAVE_INET6)
1723 ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
1727 ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
1730 ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
1736 ls->handler = ngx_http_init_connection;
1738 cscf = addr->core_srv_conf;
1739 ls->pool_size = cscf->connection_pool_size;
1740 ls->post_accept_timeout = cscf->client_header_timeout;
1742 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1744 ls->log = *clcf->err_log;
1745 ls->log.data = &ls->addr_text;
1746 ls->log.handler = ngx_accept_log_error;
1750 ngx_iocp_conf_t *iocpcf;
1752 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1753 if (iocpcf->acceptex_read) {
1754 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
1759 ls->backlog = addr->listen_conf->backlog;
1760 ls->rcvbuf = addr->listen_conf->rcvbuf;
1761 ls->sndbuf = addr->listen_conf->sndbuf;
1763 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
1764 ls->accept_filter = addr->listen_conf->accept_filter;
1767 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
1768 ls->deferred_accept = addr->listen_conf->deferred_accept;
1776 ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
1777 ngx_http_conf_addr_t *addr)
1780 ngx_http_in_addr_t *addrs;
1781 struct sockaddr_in *sin;
1782 ngx_http_virtual_names_t *vn;
1784 hport->addrs = ngx_pcalloc(cf->pool,
1785 hport->naddrs * sizeof(ngx_http_in_addr_t));
1786 if (hport->addrs == NULL) {
1790 addrs = hport->addrs;
1792 for (i = 0; i < hport->naddrs; i++) {
1794 sin = (struct sockaddr_in *) addr[i].sockaddr;
1795 addrs[i].addr = sin->sin_addr.s_addr;
1796 addrs[i].conf.core_srv_conf = addr[i].core_srv_conf;
1798 addrs[i].conf.ssl = addr[i].ssl;
1801 if (addr[i].hash.buckets == NULL
1802 && (addr[i].wc_head == NULL
1803 || addr[i].wc_head->hash.buckets == NULL)
1804 && (addr[i].wc_head == NULL
1805 || addr[i].wc_head->hash.buckets == NULL))
1810 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1815 addrs[i].conf.core_srv_conf->virtual_names = vn;
1817 vn->names.hash = addr[i].hash;
1818 vn->names.wc_head = addr[i].wc_head;
1819 vn->names.wc_tail = addr[i].wc_tail;
1821 vn->nregex = addr[i].nregex;
1822 vn->regex = addr[i].regex;
1830 #if (NGX_HAVE_INET6)
1833 ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
1834 ngx_http_conf_addr_t *addr)
1837 ngx_http_in6_addr_t *addrs6;
1838 struct sockaddr_in6 *sin6;
1839 ngx_http_virtual_names_t *vn;
1841 hport->addrs = ngx_pcalloc(cf->pool,
1842 hport->naddrs * sizeof(ngx_http_in6_addr_t));
1843 if (hport->addrs == NULL) {
1847 addrs6 = hport->addrs;
1849 for (i = 0; i < hport->naddrs; i++) {
1851 sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
1852 addrs6[i].addr6 = sin6->sin6_addr;
1853 addrs6[i].conf.core_srv_conf = addr[i].core_srv_conf;
1855 addrs6[i].conf.ssl = addr[i].ssl;
1858 if (addr[i].hash.buckets == NULL
1859 && (addr[i].wc_head == NULL
1860 || addr[i].wc_head->hash.buckets == NULL)
1861 && (addr[i].wc_head == NULL
1862 || addr[i].wc_head->hash.buckets == NULL))
1867 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1872 addrs6[i].conf.core_srv_conf->virtual_names = vn;
1874 vn->names.hash = addr[i].hash;
1875 vn->names.wc_head = addr[i].wc_head;
1876 vn->names.wc_tail = addr[i].wc_tail;
1878 vn->nregex = addr[i].nregex;
1879 vn->regex = addr[i].regex;
1890 ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1894 ngx_array_t **types;
1895 ngx_str_t *value, *default_type;
1896 ngx_uint_t i, n, hash;
1897 ngx_hash_key_t *type;
1899 types = (ngx_array_t **) (p + cmd->offset);
1901 default_type = cmd->post;
1903 if (*types == NULL) {
1904 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
1905 if (*types == NULL) {
1906 return NGX_CONF_ERROR;
1910 type = ngx_array_push(*types);
1912 return NGX_CONF_ERROR;
1915 type->key = *default_type;
1916 type->key_hash = ngx_hash_key(default_type->data,
1918 type->value = (void *) 4;
1922 value = cf->args->elts;
1924 for (i = 1; i < cf->args->nelts; i++) {
1926 hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
1927 value[i].data[value[i].len] = '\0';
1929 type = (*types)->elts;
1930 for (n = 0; n < (*types)->nelts; n++) {
1932 if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
1933 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1934 "duplicate MIME type \"%V\"", &value[i]);
1939 type = ngx_array_push(*types);
1941 return NGX_CONF_ERROR;
1944 type->key = value[i];
1945 type->key_hash = hash;
1946 type->value = (void *) 4;
1954 ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys, ngx_hash_t *types_hash,
1955 ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
1956 ngx_str_t *default_types)
1958 ngx_hash_init_t hash;
1962 hash.hash = types_hash;
1964 hash.max_size = 2048;
1965 hash.bucket_size = 64;
1966 hash.name = "test_types_hash";
1967 hash.pool = cf->pool;
1968 hash.temp_pool = NULL;
1970 if (ngx_hash_init(&hash, keys->elts, keys->nelts) != NGX_OK) {
1971 return NGX_CONF_ERROR;
1977 if (prev_types_hash->buckets == NULL) {
1979 if (prev_keys == NULL) {
1981 if (ngx_http_set_default_types(cf, &prev_keys, default_types)
1984 return NGX_CONF_ERROR;
1988 hash.hash = prev_types_hash;
1990 hash.max_size = 2048;
1991 hash.bucket_size = 64;
1992 hash.name = "test_types_hash";
1993 hash.pool = cf->pool;
1994 hash.temp_pool = NULL;
1996 if (ngx_hash_init(&hash, prev_keys->elts, prev_keys->nelts) != NGX_OK) {
1997 return NGX_CONF_ERROR;
2001 *types_hash = *prev_types_hash;
2009 ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
2010 ngx_str_t *default_type)
2012 ngx_hash_key_t *type;
2014 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
2015 if (*types == NULL) {
2019 while (default_type->len) {
2021 type = ngx_array_push(*types);
2026 type->key = *default_type;
2027 type->key_hash = ngx_hash_key(default_type->data,
2029 type->value = (void *) 4;