Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
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,
16 static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
18 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
20 
21 static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
23  ngx_http_listen_opt_t *lsopt);
24 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
26  ngx_http_listen_opt_t *lsopt);
27 static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
29 
30 static char *ngx_http_merge_servers(ngx_conf_t *cf,
32  ngx_uint_t ctx_index);
33 static char *ngx_http_merge_locations(ngx_conf_t *cf,
34  ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
35  ngx_uint_t ctx_index);
36 static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
38 static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
40 static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
41  const ngx_queue_t *two);
42 static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
43  ngx_queue_t *locations);
44 static void ngx_http_create_locations_list(ngx_queue_t *locations,
45  ngx_queue_t *q);
47  ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
48  size_t prefix);
49 
50 static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
52 static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
54 static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
55 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
56  const void *two);
57 
58 static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
59  ngx_http_conf_port_t *port);
60 static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
61  ngx_http_conf_addr_t *addr);
62 static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
63  ngx_http_conf_addr_t *addr);
64 #if (NGX_HAVE_INET6)
65 static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
66  ngx_http_conf_addr_t *addr);
67 #endif
68 
70 
71 
74 
75 
77  ngx_string("text/html"),
79 };
80 
81 
82 static ngx_command_t ngx_http_commands[] = {
83 
84  { ngx_string("http"),
86  ngx_http_block,
87  0,
88  0,
89  NULL },
90 
92 };
93 
94 
95 static ngx_core_module_t ngx_http_module_ctx = {
96  ngx_string("http"),
97  NULL,
98  NULL
99 };
100 
101 
104  &ngx_http_module_ctx, /* module context */
105  ngx_http_commands, /* module directives */
106  NGX_CORE_MODULE, /* module type */
107  NULL, /* init master */
108  NULL, /* init module */
109  NULL, /* init process */
110  NULL, /* init thread */
111  NULL, /* exit thread */
112  NULL, /* exit process */
113  NULL, /* exit master */
115 };
116 
117 
118 static char *
119 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
120 {
121  char *rv;
122  ngx_uint_t mi, m, s;
123  ngx_conf_t pcf;
124  ngx_http_module_t *module;
127  ngx_http_core_srv_conf_t **cscfp;
129 
130  /* the main http context */
131 
132  ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
133  if (ctx == NULL) {
134  return NGX_CONF_ERROR;
135  }
136 
137  *(ngx_http_conf_ctx_t **) conf = ctx;
138 
139 
140  /* count the number of the http modules and set up their indices */
141 
143  for (m = 0; ngx_modules[m]; m++) {
144  if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
145  continue;
146  }
147 
149  }
150 
151 
152  /* the http main_conf context, it is the same in the all http contexts */
153 
154  ctx->main_conf = ngx_pcalloc(cf->pool,
155  sizeof(void *) * ngx_http_max_module);
156  if (ctx->main_conf == NULL) {
157  return NGX_CONF_ERROR;
158  }
159 
160 
161  /*
162  * the http null srv_conf context, it is used to merge
163  * the server{}s' srv_conf's
164  */
165 
166  ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
167  if (ctx->srv_conf == NULL) {
168  return NGX_CONF_ERROR;
169  }
170 
171 
172  /*
173  * the http null loc_conf context, it is used to merge
174  * the server{}s' loc_conf's
175  */
176 
177  ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
178  if (ctx->loc_conf == NULL) {
179  return NGX_CONF_ERROR;
180  }
181 
182 
183  /*
184  * create the main_conf's, the null srv_conf's, and the null loc_conf's
185  * of the all http modules
186  */
187 
188  for (m = 0; ngx_modules[m]; m++) {
189  if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
190  continue;
191  }
192 
193  module = ngx_modules[m]->ctx;
194  mi = ngx_modules[m]->ctx_index;
195 
196  if (module->create_main_conf) {
197  ctx->main_conf[mi] = module->create_main_conf(cf);
198  if (ctx->main_conf[mi] == NULL) {
199  return NGX_CONF_ERROR;
200  }
201  }
202 
203  if (module->create_srv_conf) {
204  ctx->srv_conf[mi] = module->create_srv_conf(cf);
205  if (ctx->srv_conf[mi] == NULL) {
206  return NGX_CONF_ERROR;
207  }
208  }
209 
210  if (module->create_loc_conf) {
211  ctx->loc_conf[mi] = module->create_loc_conf(cf);
212  if (ctx->loc_conf[mi] == NULL) {
213  return NGX_CONF_ERROR;
214  }
215  }
216  }
217 
218  pcf = *cf;
219  cf->ctx = ctx;
220 
221  for (m = 0; ngx_modules[m]; m++) {
222  if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
223  continue;
224  }
225 
226  module = ngx_modules[m]->ctx;
227 
228  if (module->preconfiguration) {
229  if (module->preconfiguration(cf) != NGX_OK) {
230  return NGX_CONF_ERROR;
231  }
232  }
233  }
234 
235  /* parse inside the http{} block */
236 
239  rv = ngx_conf_parse(cf, NULL);
240 
241  if (rv != NGX_CONF_OK) {
242  goto failed;
243  }
244 
245  /*
246  * init http{} main_conf's, merge the server{}s' srv_conf's
247  * and its location{}s' loc_conf's
248  */
249 
251  cscfp = cmcf->servers.elts;
252 
253  for (m = 0; ngx_modules[m]; m++) {
254  if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
255  continue;
256  }
257 
258  module = ngx_modules[m]->ctx;
259  mi = ngx_modules[m]->ctx_index;
260 
261  /* init http{} main_conf's */
262 
263  if (module->init_main_conf) {
264  rv = module->init_main_conf(cf, ctx->main_conf[mi]);
265  if (rv != NGX_CONF_OK) {
266  goto failed;
267  }
268  }
269 
270  rv = ngx_http_merge_servers(cf, cmcf, module, mi);
271  if (rv != NGX_CONF_OK) {
272  goto failed;
273  }
274  }
275 
276 
277  /* create location trees */
278 
279  for (s = 0; s < cmcf->servers.nelts; s++) {
280 
281  clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
282 
283  if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
284  return NGX_CONF_ERROR;
285  }
286 
287  if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
288  return NGX_CONF_ERROR;
289  }
290  }
291 
292 
293  if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
294  return NGX_CONF_ERROR;
295  }
296 
297  if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
298  return NGX_CONF_ERROR;
299  }
300 
301 
302  for (m = 0; ngx_modules[m]; m++) {
303  if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
304  continue;
305  }
306 
307  module = ngx_modules[m]->ctx;
308 
309  if (module->postconfiguration) {
310  if (module->postconfiguration(cf) != NGX_OK) {
311  return NGX_CONF_ERROR;
312  }
313  }
314  }
315 
317  return NGX_CONF_ERROR;
318  }
319 
320  /*
321  * http{}'s cf->ctx was needed while the configuration merging
322  * and in postconfiguration process
323  */
324 
325  *cf = pcf;
326 
327 
328  if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
329  return NGX_CONF_ERROR;
330  }
331 
332 
333  /* optimize the lists of ports, addresses and server names */
334 
335  if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
336  return NGX_CONF_ERROR;
337  }
338 
339  return NGX_CONF_OK;
340 
341 failed:
342 
343  *cf = pcf;
344 
345  return rv;
346 }
347 
348 
349 static ngx_int_t
350 ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
351 {
352  if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
353  cf->pool, 1, sizeof(ngx_http_handler_pt))
354  != NGX_OK)
355  {
356  return NGX_ERROR;
357  }
358 
359  if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
360  cf->pool, 1, sizeof(ngx_http_handler_pt))
361  != NGX_OK)
362  {
363  return NGX_ERROR;
364  }
365 
366  if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
367  cf->pool, 1, sizeof(ngx_http_handler_pt))
368  != NGX_OK)
369  {
370  return NGX_ERROR;
371  }
372 
373  if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
374  cf->pool, 1, sizeof(ngx_http_handler_pt))
375  != NGX_OK)
376  {
377  return NGX_ERROR;
378  }
379 
380  if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
381  cf->pool, 2, sizeof(ngx_http_handler_pt))
382  != NGX_OK)
383  {
384  return NGX_ERROR;
385  }
386 
387  if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
388  cf->pool, 4, sizeof(ngx_http_handler_pt))
389  != NGX_OK)
390  {
391  return NGX_ERROR;
392  }
393 
394  if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
395  cf->pool, 1, sizeof(ngx_http_handler_pt))
396  != NGX_OK)
397  {
398  return NGX_ERROR;
399  }
400 
401  return NGX_OK;
402 }
403 
404 
405 static ngx_int_t
406 ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
407 {
408  ngx_array_t headers_in;
409  ngx_hash_key_t *hk;
410  ngx_hash_init_t hash;
411  ngx_http_header_t *header;
412 
413  if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
414  != NGX_OK)
415  {
416  return NGX_ERROR;
417  }
418 
419  for (header = ngx_http_headers_in; header->name.len; header++) {
420  hk = ngx_array_push(&headers_in);
421  if (hk == NULL) {
422  return NGX_ERROR;
423  }
424 
425  hk->key = header->name;
426  hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
427  hk->value = header;
428  }
429 
430  hash.hash = &cmcf->headers_in_hash;
431  hash.key = ngx_hash_key_lc;
432  hash.max_size = 512;
434  hash.name = "headers_in_hash";
435  hash.pool = cf->pool;
436  hash.temp_pool = NULL;
437 
438  if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
439  return NGX_ERROR;
440  }
441 
442  return NGX_OK;
443 }
444 
445 
446 static ngx_int_t
447 ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
448 {
449  ngx_int_t j;
450  ngx_uint_t i, n;
451  ngx_uint_t find_config_index, use_rewrite, use_access;
455 
458  find_config_index = 0;
459  use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
460  use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
461 
462  n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;
463 
464  for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
465  n += cmcf->phases[i].handlers.nelts;
466  }
467 
468  ph = ngx_pcalloc(cf->pool,
469  n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
470  if (ph == NULL) {
471  return NGX_ERROR;
472  }
473 
474  cmcf->phase_engine.handlers = ph;
475  n = 0;
476 
477  for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
478  h = cmcf->phases[i].handlers.elts;
479 
480  switch (i) {
481 
483  if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
485  }
486  checker = ngx_http_core_rewrite_phase;
487 
488  break;
489 
491  find_config_index = n;
492 
494  n++;
495  ph++;
496 
497  continue;
498 
500  if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
502  }
503  checker = ngx_http_core_rewrite_phase;
504 
505  break;
506 
508  if (use_rewrite) {
510  ph->next = find_config_index;
511  n++;
512  ph++;
513  }
514 
515  continue;
516 
518  checker = ngx_http_core_access_phase;
519  n++;
520  break;
521 
523  if (use_access) {
525  ph->next = n;
526  ph++;
527  }
528 
529  continue;
530 
532  if (cmcf->try_files) {
534  n++;
535  ph++;
536  }
537 
538  continue;
539 
541  checker = ngx_http_core_content_phase;
542  break;
543 
544  default:
545  checker = ngx_http_core_generic_phase;
546  }
547 
548  n += cmcf->phases[i].handlers.nelts;
549 
550  for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
551  ph->checker = checker;
552  ph->handler = h[j];
553  ph->next = n;
554  ph++;
555  }
556  }
557 
558  return NGX_OK;
559 }
560 
561 
562 static char *
563 ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
564  ngx_http_module_t *module, ngx_uint_t ctx_index)
565 {
566  char *rv;
567  ngx_uint_t s;
568  ngx_http_conf_ctx_t *ctx, saved;
570  ngx_http_core_srv_conf_t **cscfp;
571 
572  cscfp = cmcf->servers.elts;
573  ctx = (ngx_http_conf_ctx_t *) cf->ctx;
574  saved = *ctx;
575  rv = NGX_CONF_OK;
576 
577  for (s = 0; s < cmcf->servers.nelts; s++) {
578 
579  /* merge the server{}s' srv_conf's */
580 
581  ctx->srv_conf = cscfp[s]->ctx->srv_conf;
582 
583  if (module->merge_srv_conf) {
584  rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
585  cscfp[s]->ctx->srv_conf[ctx_index]);
586  if (rv != NGX_CONF_OK) {
587  goto failed;
588  }
589  }
590 
591  if (module->merge_loc_conf) {
592 
593  /* merge the server{}'s loc_conf */
594 
595  ctx->loc_conf = cscfp[s]->ctx->loc_conf;
596 
597  rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
598  cscfp[s]->ctx->loc_conf[ctx_index]);
599  if (rv != NGX_CONF_OK) {
600  goto failed;
601  }
602 
603  /* merge the locations{}' loc_conf's */
604 
605  clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
606 
607  rv = ngx_http_merge_locations(cf, clcf->locations,
608  cscfp[s]->ctx->loc_conf,
609  module, ctx_index);
610  if (rv != NGX_CONF_OK) {
611  goto failed;
612  }
613  }
614  }
615 
616 failed:
617 
618  *ctx = saved;
619 
620  return rv;
621 }
622 
623 
624 static char *
625 ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
626  void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
627 {
628  char *rv;
629  ngx_queue_t *q;
630  ngx_http_conf_ctx_t *ctx, saved;
633 
634  if (locations == NULL) {
635  return NGX_CONF_OK;
636  }
637 
638  ctx = (ngx_http_conf_ctx_t *) cf->ctx;
639  saved = *ctx;
640 
641  for (q = ngx_queue_head(locations);
642  q != ngx_queue_sentinel(locations);
643  q = ngx_queue_next(q))
644  {
645  lq = (ngx_http_location_queue_t *) q;
646 
647  clcf = lq->exact ? lq->exact : lq->inclusive;
648  ctx->loc_conf = clcf->loc_conf;
649 
650  rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
651  clcf->loc_conf[ctx_index]);
652  if (rv != NGX_CONF_OK) {
653  return rv;
654  }
655 
656  rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
657  module, ctx_index);
658  if (rv != NGX_CONF_OK) {
659  return rv;
660  }
661  }
662 
663  *ctx = saved;
664 
665  return NGX_CONF_OK;
666 }
667 
668 
669 static ngx_int_t
670 ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
672 {
673  ngx_uint_t n;
674  ngx_queue_t *q, *locations, *named, tail;
677  ngx_http_core_loc_conf_t **clcfp;
678 #if (NGX_PCRE)
679  ngx_uint_t r;
680  ngx_queue_t *regex;
681 #endif
682 
683  locations = pclcf->locations;
684 
685  if (locations == NULL) {
686  return NGX_OK;
687  }
688 
689  ngx_queue_sort(locations, ngx_http_cmp_locations);
690 
691  named = NULL;
692  n = 0;
693 #if (NGX_PCRE)
694  regex = NULL;
695  r = 0;
696 #endif
697 
698  for (q = ngx_queue_head(locations);
699  q != ngx_queue_sentinel(locations);
700  q = ngx_queue_next(q))
701  {
702  lq = (ngx_http_location_queue_t *) q;
703 
704  clcf = lq->exact ? lq->exact : lq->inclusive;
705 
706  if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
707  return NGX_ERROR;
708  }
709 
710 #if (NGX_PCRE)
711 
712  if (clcf->regex) {
713  r++;
714 
715  if (regex == NULL) {
716  regex = q;
717  }
718 
719  continue;
720  }
721 
722 #endif
723 
724  if (clcf->named) {
725  n++;
726 
727  if (named == NULL) {
728  named = q;
729  }
730 
731  continue;
732  }
733 
734  if (clcf->noname) {
735  break;
736  }
737  }
738 
739  if (q != ngx_queue_sentinel(locations)) {
740  ngx_queue_split(locations, q, &tail);
741  }
742 
743  if (named) {
744  clcfp = ngx_palloc(cf->pool,
745  (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
746  if (clcfp == NULL) {
747  return NGX_ERROR;
748  }
749 
750  cscf->named_locations = clcfp;
751 
752  for (q = named;
753  q != ngx_queue_sentinel(locations);
754  q = ngx_queue_next(q))
755  {
756  lq = (ngx_http_location_queue_t *) q;
757 
758  *(clcfp++) = lq->exact;
759  }
760 
761  *clcfp = NULL;
762 
763  ngx_queue_split(locations, named, &tail);
764  }
765 
766 #if (NGX_PCRE)
767 
768  if (regex) {
769 
770  clcfp = ngx_palloc(cf->pool,
771  (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
772  if (clcfp == NULL) {
773  return NGX_ERROR;
774  }
775 
776  pclcf->regex_locations = clcfp;
777 
778  for (q = regex;
779  q != ngx_queue_sentinel(locations);
780  q = ngx_queue_next(q))
781  {
782  lq = (ngx_http_location_queue_t *) q;
783 
784  *(clcfp++) = lq->exact;
785  }
786 
787  *clcfp = NULL;
788 
789  ngx_queue_split(locations, regex, &tail);
790  }
791 
792 #endif
793 
794  return NGX_OK;
795 }
796 
797 
798 static ngx_int_t
799 ngx_http_init_static_location_trees(ngx_conf_t *cf,
801 {
802  ngx_queue_t *q, *locations;
805 
806  locations = pclcf->locations;
807 
808  if (locations == NULL) {
809  return NGX_OK;
810  }
811 
812  if (ngx_queue_empty(locations)) {
813  return NGX_OK;
814  }
815 
816  for (q = ngx_queue_head(locations);
817  q != ngx_queue_sentinel(locations);
818  q = ngx_queue_next(q))
819  {
820  lq = (ngx_http_location_queue_t *) q;
821 
822  clcf = lq->exact ? lq->exact : lq->inclusive;
823 
824  if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
825  return NGX_ERROR;
826  }
827  }
828 
829  if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
830  return NGX_ERROR;
831  }
832 
833  ngx_http_create_locations_list(locations, ngx_queue_head(locations));
834 
835  pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
836  if (pclcf->static_locations == NULL) {
837  return NGX_ERROR;
838  }
839 
840  return NGX_OK;
841 }
842 
843 
844 ngx_int_t
847 {
849 
850  if (*locations == NULL) {
851  *locations = ngx_palloc(cf->temp_pool,
852  sizeof(ngx_http_location_queue_t));
853  if (*locations == NULL) {
854  return NGX_ERROR;
855  }
856 
857  ngx_queue_init(*locations);
858  }
859 
861  if (lq == NULL) {
862  return NGX_ERROR;
863  }
864 
865  if (clcf->exact_match
866 #if (NGX_PCRE)
867  || clcf->regex
868 #endif
869  || clcf->named || clcf->noname)
870  {
871  lq->exact = clcf;
872  lq->inclusive = NULL;
873 
874  } else {
875  lq->exact = NULL;
876  lq->inclusive = clcf;
877  }
878 
879  lq->name = &clcf->name;
880  lq->file_name = cf->conf_file->file.name.data;
881  lq->line = cf->conf_file->line;
882 
883  ngx_queue_init(&lq->list);
884 
885  ngx_queue_insert_tail(*locations, &lq->queue);
886 
887  return NGX_OK;
888 }
889 
890 
891 static ngx_int_t
892 ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
893 {
894  ngx_int_t rc;
895  ngx_http_core_loc_conf_t *first, *second;
896  ngx_http_location_queue_t *lq1, *lq2;
897 
898  lq1 = (ngx_http_location_queue_t *) one;
899  lq2 = (ngx_http_location_queue_t *) two;
900 
901  first = lq1->exact ? lq1->exact : lq1->inclusive;
902  second = lq2->exact ? lq2->exact : lq2->inclusive;
903 
904  if (first->noname && !second->noname) {
905  /* shift no named locations to the end */
906  return 1;
907  }
908 
909  if (!first->noname && second->noname) {
910  /* shift no named locations to the end */
911  return -1;
912  }
913 
914  if (first->noname || second->noname) {
915  /* do not sort no named locations */
916  return 0;
917  }
918 
919  if (first->named && !second->named) {
920  /* shift named locations to the end */
921  return 1;
922  }
923 
924  if (!first->named && second->named) {
925  /* shift named locations to the end */
926  return -1;
927  }
928 
929  if (first->named && second->named) {
930  return ngx_strcmp(first->name.data, second->name.data);
931  }
932 
933 #if (NGX_PCRE)
934 
935  if (first->regex && !second->regex) {
936  /* shift the regex matches to the end */
937  return 1;
938  }
939 
940  if (!first->regex && second->regex) {
941  /* shift the regex matches to the end */
942  return -1;
943  }
944 
945  if (first->regex || second->regex) {
946  /* do not sort the regex matches */
947  return 0;
948  }
949 
950 #endif
951 
952  rc = ngx_strcmp(first->name.data, second->name.data);
953 
954  if (rc == 0 && !first->exact_match && second->exact_match) {
955  /* an exact match must be before the same inclusive one */
956  return 1;
957  }
958 
959  return rc;
960 }
961 
962 
963 static ngx_int_t
964 ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
965 {
966  ngx_queue_t *q, *x;
967  ngx_http_location_queue_t *lq, *lx;
968 
969  q = ngx_queue_head(locations);
970 
971  while (q != ngx_queue_last(locations)) {
972 
973  x = ngx_queue_next(q);
974 
975  lq = (ngx_http_location_queue_t *) q;
976  lx = (ngx_http_location_queue_t *) x;
977 
978  if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
979 
980  if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
982  "duplicate location \"%V\" in %s:%ui",
983  lx->name, lx->file_name, lx->line);
984 
985  return NGX_ERROR;
986  }
987 
988  lq->inclusive = lx->inclusive;
989 
990  ngx_queue_remove(x);
991 
992  continue;
993  }
994 
995  q = ngx_queue_next(q);
996  }
997 
998  return NGX_OK;
999 }
1000 
1001 
1002 static void
1003 ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
1004 {
1005  u_char *name;
1006  size_t len;
1007  ngx_queue_t *x, tail;
1008  ngx_http_location_queue_t *lq, *lx;
1009 
1010  if (q == ngx_queue_last(locations)) {
1011  return;
1012  }
1013 
1014  lq = (ngx_http_location_queue_t *) q;
1015 
1016  if (lq->inclusive == NULL) {
1017  ngx_http_create_locations_list(locations, ngx_queue_next(q));
1018  return;
1019  }
1020 
1021  len = lq->name->len;
1022  name = lq->name->data;
1023 
1024  for (x = ngx_queue_next(q);
1025  x != ngx_queue_sentinel(locations);
1026  x = ngx_queue_next(x))
1027  {
1028  lx = (ngx_http_location_queue_t *) x;
1029 
1030  if (len > lx->name->len
1031  || (ngx_strncmp(name, lx->name->data, len) != 0))
1032  {
1033  break;
1034  }
1035  }
1036 
1037  q = ngx_queue_next(q);
1038 
1039  if (q == x) {
1040  ngx_http_create_locations_list(locations, x);
1041  return;
1042  }
1043 
1044  ngx_queue_split(locations, q, &tail);
1045  ngx_queue_add(&lq->list, &tail);
1046 
1047  if (x == ngx_queue_sentinel(locations)) {
1048  ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1049  return;
1050  }
1051 
1052  ngx_queue_split(&lq->list, x, &tail);
1053  ngx_queue_add(locations, &tail);
1054 
1055  ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1056 
1057  ngx_http_create_locations_list(locations, x);
1058 }
1059 
1060 
1061 /*
1062  * to keep cache locality for left leaf nodes, allocate nodes in following
1063  * order: node, left subtree, right subtree, inclusive subtree
1064  */
1065 
1067 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
1068  size_t prefix)
1069 {
1070  size_t len;
1071  ngx_queue_t *q, tail;
1074 
1075  q = ngx_queue_middle(locations);
1076 
1077  lq = (ngx_http_location_queue_t *) q;
1078  len = lq->name->len - prefix;
1079 
1080  node = ngx_palloc(cf->pool,
1081  offsetof(ngx_http_location_tree_node_t, name) + len);
1082  if (node == NULL) {
1083  return NULL;
1084  }
1085 
1086  node->left = NULL;
1087  node->right = NULL;
1088  node->tree = NULL;
1089  node->exact = lq->exact;
1090  node->inclusive = lq->inclusive;
1091 
1092  node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
1093  || (lq->inclusive && lq->inclusive->auto_redirect));
1094 
1095  node->len = (u_char) len;
1096  ngx_memcpy(node->name, &lq->name->data[prefix], len);
1097 
1098  ngx_queue_split(locations, q, &tail);
1099 
1100  if (ngx_queue_empty(locations)) {
1101  /*
1102  * ngx_queue_split() insures that if left part is empty,
1103  * then right one is empty too
1104  */
1105  goto inclusive;
1106  }
1107 
1108  node->left = ngx_http_create_locations_tree(cf, locations, prefix);
1109  if (node->left == NULL) {
1110  return NULL;
1111  }
1112 
1113  ngx_queue_remove(q);
1114 
1115  if (ngx_queue_empty(&tail)) {
1116  goto inclusive;
1117  }
1118 
1119  node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
1120  if (node->right == NULL) {
1121  return NULL;
1122  }
1123 
1124 inclusive:
1125 
1126  if (ngx_queue_empty(&lq->list)) {
1127  return node;
1128  }
1129 
1130  node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
1131  if (node->tree == NULL) {
1132  return NULL;
1133  }
1134 
1135  return node;
1136 }
1137 
1138 
1139 ngx_int_t
1141  ngx_http_listen_opt_t *lsopt)
1142 {
1143  in_port_t p;
1144  ngx_uint_t i;
1145  struct sockaddr *sa;
1146  struct sockaddr_in *sin;
1147  ngx_http_conf_port_t *port;
1149 #if (NGX_HAVE_INET6)
1150  struct sockaddr_in6 *sin6;
1151 #endif
1152 
1154 
1155  if (cmcf->ports == NULL) {
1156  cmcf->ports = ngx_array_create(cf->temp_pool, 2,
1157  sizeof(ngx_http_conf_port_t));
1158  if (cmcf->ports == NULL) {
1159  return NGX_ERROR;
1160  }
1161  }
1162 
1163  sa = &lsopt->u.sockaddr;
1164 
1165  switch (sa->sa_family) {
1166 
1167 #if (NGX_HAVE_INET6)
1168  case AF_INET6:
1169  sin6 = &lsopt->u.sockaddr_in6;
1170  p = sin6->sin6_port;
1171  break;
1172 #endif
1173 
1174 #if (NGX_HAVE_UNIX_DOMAIN)
1175  case AF_UNIX:
1176  p = 0;
1177  break;
1178 #endif
1179 
1180  default: /* AF_INET */
1181  sin = &lsopt->u.sockaddr_in;
1182  p = sin->sin_port;
1183  break;
1184  }
1185 
1186  port = cmcf->ports->elts;
1187  for (i = 0; i < cmcf->ports->nelts; i++) {
1188 
1189  if (p != port[i].port || sa->sa_family != port[i].family) {
1190  continue;
1191  }
1192 
1193  /* a port is already in the port list */
1194 
1195  return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
1196  }
1197 
1198  /* add a port to the port list */
1199 
1200  port = ngx_array_push(cmcf->ports);
1201  if (port == NULL) {
1202  return NGX_ERROR;
1203  }
1204 
1205  port->family = sa->sa_family;
1206  port->port = p;
1207  port->addrs.elts = NULL;
1208 
1209  return ngx_http_add_address(cf, cscf, port, lsopt);
1210 }
1211 
1212 
1213 static ngx_int_t
1214 ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1216 {
1217  u_char *p;
1218  size_t len, off;
1219  ngx_uint_t i, default_server;
1220  struct sockaddr *sa;
1221  ngx_http_conf_addr_t *addr;
1222 #if (NGX_HAVE_UNIX_DOMAIN)
1223  struct sockaddr_un *saun;
1224 #endif
1225 #if (NGX_HTTP_SSL)
1226  ngx_uint_t ssl;
1227 #endif
1228 #if (NGX_HTTP_SPDY)
1229  ngx_uint_t spdy;
1230 #endif
1231 
1232  /*
1233  * we cannot compare whole sockaddr struct's as kernel
1234  * may fill some fields in inherited sockaddr struct's
1235  */
1236 
1237  sa = &lsopt->u.sockaddr;
1238 
1239  switch (sa->sa_family) {
1240 
1241 #if (NGX_HAVE_INET6)
1242  case AF_INET6:
1243  off = offsetof(struct sockaddr_in6, sin6_addr);
1244  len = 16;
1245  break;
1246 #endif
1247 
1248 #if (NGX_HAVE_UNIX_DOMAIN)
1249  case AF_UNIX:
1250  off = offsetof(struct sockaddr_un, sun_path);
1251  len = sizeof(saun->sun_path);
1252  break;
1253 #endif
1254 
1255  default: /* AF_INET */
1256  off = offsetof(struct sockaddr_in, sin_addr);
1257  len = 4;
1258  break;
1259  }
1260 
1261  p = lsopt->u.sockaddr_data + off;
1262 
1263  addr = port->addrs.elts;
1264 
1265  for (i = 0; i < port->addrs.nelts; i++) {
1266 
1267  if (ngx_memcmp(p, addr[i].opt.u.sockaddr_data + off, len) != 0) {
1268  continue;
1269  }
1270 
1271  /* the address is already in the address list */
1272 
1273  if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
1274  return NGX_ERROR;
1275  }
1276 
1277  /* preserve default_server bit during listen options overwriting */
1278  default_server = addr[i].opt.default_server;
1279 
1280 #if (NGX_HTTP_SSL)
1281  ssl = lsopt->ssl || addr[i].opt.ssl;
1282 #endif
1283 #if (NGX_HTTP_SPDY)
1284  spdy = lsopt->spdy || addr[i].opt.spdy;
1285 #endif
1286 
1287  if (lsopt->set) {
1288 
1289  if (addr[i].opt.set) {
1291  "duplicate listen options for %s", addr[i].opt.addr);
1292  return NGX_ERROR;
1293  }
1294 
1295  addr[i].opt = *lsopt;
1296  }
1297 
1298  /* check the duplicate "default" server for this address:port */
1299 
1300  if (lsopt->default_server) {
1301 
1302  if (default_server) {
1304  "a duplicate default server for %s", addr[i].opt.addr);
1305  return NGX_ERROR;
1306  }
1307 
1308  default_server = 1;
1309  addr[i].default_server = cscf;
1310  }
1311 
1312  addr[i].opt.default_server = default_server;
1313 #if (NGX_HTTP_SSL)
1314  addr[i].opt.ssl = ssl;
1315 #endif
1316 #if (NGX_HTTP_SPDY)
1317  addr[i].opt.spdy = spdy;
1318 #endif
1319 
1320  return NGX_OK;
1321  }
1322 
1323  /* add the address to the addresses list that bound to this port */
1324 
1325  return ngx_http_add_address(cf, cscf, port, lsopt);
1326 }
1327 
1328 
1329 /*
1330  * add the server address, the server names and the server core module
1331  * configurations to the port list
1332  */
1333 
1334 static ngx_int_t
1335 ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1337 {
1338  ngx_http_conf_addr_t *addr;
1339 
1340  if (port->addrs.elts == NULL) {
1341  if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
1342  sizeof(ngx_http_conf_addr_t))
1343  != NGX_OK)
1344  {
1345  return NGX_ERROR;
1346  }
1347  }
1348 
1349 #if (NGX_HTTP_SPDY && NGX_HTTP_SSL && !defined TLSEXT_TYPE_next_proto_neg)
1350  if (lsopt->spdy && lsopt->ssl) {
1352  "nginx was built without OpenSSL NPN support, "
1353  "SPDY is not enabled for %s", lsopt->addr);
1354  }
1355 #endif
1356 
1357  addr = ngx_array_push(&port->addrs);
1358  if (addr == NULL) {
1359  return NGX_ERROR;
1360  }
1361 
1362  addr->opt = *lsopt;
1363  addr->hash.buckets = NULL;
1364  addr->hash.size = 0;
1365  addr->wc_head = NULL;
1366  addr->wc_tail = NULL;
1367 #if (NGX_PCRE)
1368  addr->nregex = 0;
1369  addr->regex = NULL;
1370 #endif
1371  addr->default_server = cscf;
1372  addr->servers.elts = NULL;
1373 
1374  return ngx_http_add_server(cf, cscf, addr);
1375 }
1376 
1377 
1378 /* add the server core module configuration to the address:port */
1379 
1380 static ngx_int_t
1381 ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1382  ngx_http_conf_addr_t *addr)
1383 {
1384  ngx_uint_t i;
1385  ngx_http_core_srv_conf_t **server;
1386 
1387  if (addr->servers.elts == NULL) {
1388  if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
1389  sizeof(ngx_http_core_srv_conf_t *))
1390  != NGX_OK)
1391  {
1392  return NGX_ERROR;
1393  }
1394 
1395  } else {
1396  server = addr->servers.elts;
1397  for (i = 0; i < addr->servers.nelts; i++) {
1398  if (server[i] == cscf) {
1400  "a duplicate listen %s", addr->opt.addr);
1401  return NGX_ERROR;
1402  }
1403  }
1404  }
1405 
1406  server = ngx_array_push(&addr->servers);
1407  if (server == NULL) {
1408  return NGX_ERROR;
1409  }
1410 
1411  *server = cscf;
1412 
1413  return NGX_OK;
1414 }
1415 
1416 
1417 static ngx_int_t
1418 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1419  ngx_array_t *ports)
1420 {
1421  ngx_uint_t p, a;
1422  ngx_http_conf_port_t *port;
1423  ngx_http_conf_addr_t *addr;
1424 
1425  if (ports == NULL) {
1426  return NGX_OK;
1427  }
1428 
1429  port = ports->elts;
1430  for (p = 0; p < ports->nelts; p++) {
1431 
1432  ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
1433  sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
1434 
1435  /*
1436  * check whether all name-based servers have the same
1437  * configuration as a default server for given address:port
1438  */
1439 
1440  addr = port[p].addrs.elts;
1441  for (a = 0; a < port[p].addrs.nelts; a++) {
1442 
1443  if (addr[a].servers.nelts > 1
1444 #if (NGX_PCRE)
1445  || addr[a].default_server->captures
1446 #endif
1447  )
1448  {
1449  if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
1450  return NGX_ERROR;
1451  }
1452  }
1453  }
1454 
1455  if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
1456  return NGX_ERROR;
1457  }
1458  }
1459 
1460  return NGX_OK;
1461 }
1462 
1463 
1464 static ngx_int_t
1465 ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1466  ngx_http_conf_addr_t *addr)
1467 {
1468  ngx_int_t rc;
1469  ngx_uint_t n, s;
1470  ngx_hash_init_t hash;
1472  ngx_http_server_name_t *name;
1473  ngx_http_core_srv_conf_t **cscfp;
1474 #if (NGX_PCRE)
1475  ngx_uint_t regex, i;
1476 
1477  regex = 0;
1478 #endif
1479 
1480  ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1481 
1483  if (ha.temp_pool == NULL) {
1484  return NGX_ERROR;
1485  }
1486 
1487  ha.pool = cf->pool;
1488 
1490  goto failed;
1491  }
1492 
1493  cscfp = addr->servers.elts;
1494 
1495  for (s = 0; s < addr->servers.nelts; s++) {
1496 
1497  name = cscfp[s]->server_names.elts;
1498 
1499  for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
1500 
1501 #if (NGX_PCRE)
1502  if (name[n].regex) {
1503  regex++;
1504  continue;
1505  }
1506 #endif
1507 
1508  rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
1510 
1511  if (rc == NGX_ERROR) {
1512  return NGX_ERROR;
1513  }
1514 
1515  if (rc == NGX_DECLINED) {
1517  "invalid server name or wildcard \"%V\" on %s",
1518  &name[n].name, addr->opt.addr);
1519  return NGX_ERROR;
1520  }
1521 
1522  if (rc == NGX_BUSY) {
1523  ngx_log_error(NGX_LOG_WARN, cf->log, 0,
1524  "conflicting server name \"%V\" on %s, ignored",
1525  &name[n].name, addr->opt.addr);
1526  }
1527  }
1528  }
1529 
1530  hash.key = ngx_hash_key_lc;
1531  hash.max_size = cmcf->server_names_hash_max_size;
1533  hash.name = "server_names_hash";
1534  hash.pool = cf->pool;
1535 
1536  if (ha.keys.nelts) {
1537  hash.hash = &addr->hash;
1538  hash.temp_pool = NULL;
1539 
1540  if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
1541  goto failed;
1542  }
1543  }
1544 
1545  if (ha.dns_wc_head.nelts) {
1546 
1547  ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
1548  sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1549 
1550  hash.hash = NULL;
1551  hash.temp_pool = ha.temp_pool;
1552 
1553  if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1554  ha.dns_wc_head.nelts)
1555  != NGX_OK)
1556  {
1557  goto failed;
1558  }
1559 
1560  addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
1561  }
1562 
1563  if (ha.dns_wc_tail.nelts) {
1564 
1565  ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
1566  sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1567 
1568  hash.hash = NULL;
1569  hash.temp_pool = ha.temp_pool;
1570 
1571  if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1572  ha.dns_wc_tail.nelts)
1573  != NGX_OK)
1574  {
1575  goto failed;
1576  }
1577 
1578  addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
1579  }
1580 
1582 
1583 #if (NGX_PCRE)
1584 
1585  if (regex == 0) {
1586  return NGX_OK;
1587  }
1588 
1589  addr->nregex = regex;
1590  addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
1591  if (addr->regex == NULL) {
1592  return NGX_ERROR;
1593  }
1594 
1595  i = 0;
1596 
1597  for (s = 0; s < addr->servers.nelts; s++) {
1598 
1599  name = cscfp[s]->server_names.elts;
1600 
1601  for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
1602  if (name[n].regex) {
1603  addr->regex[i++] = name[n];
1604  }
1605  }
1606  }
1607 
1608 #endif
1609 
1610  return NGX_OK;
1611 
1612 failed:
1613 
1615 
1616  return NGX_ERROR;
1617 }
1618 
1619 
1620 static ngx_int_t
1621 ngx_http_cmp_conf_addrs(const void *one, const void *two)
1622 {
1623  ngx_http_conf_addr_t *first, *second;
1624 
1625  first = (ngx_http_conf_addr_t *) one;
1626  second = (ngx_http_conf_addr_t *) two;
1627 
1628  if (first->opt.wildcard) {
1629  /* a wildcard address must be the last resort, shift it to the end */
1630  return 1;
1631  }
1632 
1633  if (second->opt.wildcard) {
1634  /* a wildcard address must be the last resort, shift it to the end */
1635  return -1;
1636  }
1637 
1638  if (first->opt.bind && !second->opt.bind) {
1639  /* shift explicit bind()ed addresses to the start */
1640  return -1;
1641  }
1642 
1643  if (!first->opt.bind && second->opt.bind) {
1644  /* shift explicit bind()ed addresses to the start */
1645  return 1;
1646  }
1647 
1648  /* do not sort by default */
1649 
1650  return 0;
1651 }
1652 
1653 
1654 static int ngx_libc_cdecl
1655 ngx_http_cmp_dns_wildcards(const void *one, const void *two)
1656 {
1657  ngx_hash_key_t *first, *second;
1658 
1659  first = (ngx_hash_key_t *) one;
1660  second = (ngx_hash_key_t *) two;
1661 
1662  return ngx_dns_strcmp(first->key.data, second->key.data);
1663 }
1664 
1665 
1666 static ngx_int_t
1667 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
1668 {
1669  ngx_uint_t i, last, bind_wildcard;
1670  ngx_listening_t *ls;
1671  ngx_http_port_t *hport;
1672  ngx_http_conf_addr_t *addr;
1673 
1674  addr = port->addrs.elts;
1675  last = port->addrs.nelts;
1676 
1677  /*
1678  * If there is a binding to an "*:port" then we need to bind() to
1679  * the "*:port" only and ignore other implicit bindings. The bindings
1680  * have been already sorted: explicit bindings are on the start, then
1681  * implicit bindings go, and wildcard binding is in the end.
1682  */
1683 
1684  if (addr[last - 1].opt.wildcard) {
1685  addr[last - 1].opt.bind = 1;
1686  bind_wildcard = 1;
1687 
1688  } else {
1689  bind_wildcard = 0;
1690  }
1691 
1692  i = 0;
1693 
1694  while (i < last) {
1695 
1696  if (bind_wildcard && !addr[i].opt.bind) {
1697  i++;
1698  continue;
1699  }
1700 
1701  ls = ngx_http_add_listening(cf, &addr[i]);
1702  if (ls == NULL) {
1703  return NGX_ERROR;
1704  }
1705 
1706  hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
1707  if (hport == NULL) {
1708  return NGX_ERROR;
1709  }
1710 
1711  ls->servers = hport;
1712 
1713  if (i == last - 1) {
1714  hport->naddrs = last;
1715 
1716  } else {
1717  hport->naddrs = 1;
1718  i = 0;
1719  }
1720 
1721  switch (ls->sockaddr->sa_family) {
1722 
1723 #if (NGX_HAVE_INET6)
1724  case AF_INET6:
1725  if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
1726  return NGX_ERROR;
1727  }
1728  break;
1729 #endif
1730  default: /* AF_INET */
1731  if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
1732  return NGX_ERROR;
1733  }
1734  break;
1735  }
1736 
1737  addr++;
1738  last--;
1739  }
1740 
1741  return NGX_OK;
1742 }
1743 
1744 
1745 static ngx_listening_t *
1746 ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
1747 {
1748  ngx_listening_t *ls;
1751 
1752  ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen);
1753  if (ls == NULL) {
1754  return NULL;
1755  }
1756 
1757  ls->addr_ntop = 1;
1758 
1760 
1761  cscf = addr->default_server;
1762  ls->pool_size = cscf->connection_pool_size;
1764 
1765  clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1766 
1767  ls->logp = clcf->error_log;
1768  ls->log.data = &ls->addr_text;
1770 
1771 #if (NGX_WIN32)
1772  {
1773  ngx_iocp_conf_t *iocpcf = NULL;
1774 
1776  iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1777  }
1778  if (iocpcf && iocpcf->acceptex_read) {
1780  }
1781  }
1782 #endif
1783 
1784  ls->backlog = addr->opt.backlog;
1785  ls->rcvbuf = addr->opt.rcvbuf;
1786  ls->sndbuf = addr->opt.sndbuf;
1787 
1788  ls->keepalive = addr->opt.so_keepalive;
1789 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
1790  ls->keepidle = addr->opt.tcp_keepidle;
1791  ls->keepintvl = addr->opt.tcp_keepintvl;
1792  ls->keepcnt = addr->opt.tcp_keepcnt;
1793 #endif
1794 
1795 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
1796  ls->accept_filter = addr->opt.accept_filter;
1797 #endif
1798 
1799 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
1800  ls->deferred_accept = addr->opt.deferred_accept;
1801 #endif
1802 
1803 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
1804  ls->ipv6only = addr->opt.ipv6only;
1805 #endif
1806 
1807 #if (NGX_HAVE_SETFIB)
1808  ls->setfib = addr->opt.setfib;
1809 #endif
1810 
1811  return ls;
1812 }
1813 
1814 
1815 static ngx_int_t
1816 ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
1817  ngx_http_conf_addr_t *addr)
1818 {
1819  ngx_uint_t i;
1820  ngx_http_in_addr_t *addrs;
1821  struct sockaddr_in *sin;
1823 
1824  hport->addrs = ngx_pcalloc(cf->pool,
1825  hport->naddrs * sizeof(ngx_http_in_addr_t));
1826  if (hport->addrs == NULL) {
1827  return NGX_ERROR;
1828  }
1829 
1830  addrs = hport->addrs;
1831 
1832  for (i = 0; i < hport->naddrs; i++) {
1833 
1834  sin = &addr[i].opt.u.sockaddr_in;
1835  addrs[i].addr = sin->sin_addr.s_addr;
1836  addrs[i].conf.default_server = addr[i].default_server;
1837 #if (NGX_HTTP_SSL)
1838  addrs[i].conf.ssl = addr[i].opt.ssl;
1839 #endif
1840 #if (NGX_HTTP_SPDY)
1841  addrs[i].conf.spdy = addr[i].opt.spdy;
1842 #endif
1843 
1844  if (addr[i].hash.buckets == NULL
1845  && (addr[i].wc_head == NULL
1846  || addr[i].wc_head->hash.buckets == NULL)
1847  && (addr[i].wc_tail == NULL
1848  || addr[i].wc_tail->hash.buckets == NULL)
1849 #if (NGX_PCRE)
1850  && addr[i].nregex == 0
1851 #endif
1852  )
1853  {
1854  continue;
1855  }
1856 
1857  vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1858  if (vn == NULL) {
1859  return NGX_ERROR;
1860  }
1861 
1862  addrs[i].conf.virtual_names = vn;
1863 
1864  vn->names.hash = addr[i].hash;
1865  vn->names.wc_head = addr[i].wc_head;
1866  vn->names.wc_tail = addr[i].wc_tail;
1867 #if (NGX_PCRE)
1868  vn->nregex = addr[i].nregex;
1869  vn->regex = addr[i].regex;
1870 #endif
1871  }
1872 
1873  return NGX_OK;
1874 }
1875 
1876 
1877 #if (NGX_HAVE_INET6)
1878 
1879 static ngx_int_t
1880 ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
1881  ngx_http_conf_addr_t *addr)
1882 {
1883  ngx_uint_t i;
1884  ngx_http_in6_addr_t *addrs6;
1885  struct sockaddr_in6 *sin6;
1887 
1888  hport->addrs = ngx_pcalloc(cf->pool,
1889  hport->naddrs * sizeof(ngx_http_in6_addr_t));
1890  if (hport->addrs == NULL) {
1891  return NGX_ERROR;
1892  }
1893 
1894  addrs6 = hport->addrs;
1895 
1896  for (i = 0; i < hport->naddrs; i++) {
1897 
1898  sin6 = &addr[i].opt.u.sockaddr_in6;
1899  addrs6[i].addr6 = sin6->sin6_addr;
1900  addrs6[i].conf.default_server = addr[i].default_server;
1901 #if (NGX_HTTP_SSL)
1902  addrs6[i].conf.ssl = addr[i].opt.ssl;
1903 #endif
1904 #if (NGX_HTTP_SPDY)
1905  addrs6[i].conf.spdy = addr[i].opt.spdy;
1906 #endif
1907 
1908  if (addr[i].hash.buckets == NULL
1909  && (addr[i].wc_head == NULL
1910  || addr[i].wc_head->hash.buckets == NULL)
1911  && (addr[i].wc_tail == NULL
1912  || addr[i].wc_tail->hash.buckets == NULL)
1913 #if (NGX_PCRE)
1914  && addr[i].nregex == 0
1915 #endif
1916  )
1917  {
1918  continue;
1919  }
1920 
1921  vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1922  if (vn == NULL) {
1923  return NGX_ERROR;
1924  }
1925 
1926  addrs6[i].conf.virtual_names = vn;
1927 
1928  vn->names.hash = addr[i].hash;
1929  vn->names.wc_head = addr[i].wc_head;
1930  vn->names.wc_tail = addr[i].wc_tail;
1931 #if (NGX_PCRE)
1932  vn->nregex = addr[i].nregex;
1933  vn->regex = addr[i].regex;
1934 #endif
1935  }
1936 
1937  return NGX_OK;
1938 }
1939 
1940 #endif
1941 
1942 
1943 char *
1945 {
1946  char *p = conf;
1947 
1948  ngx_array_t **types;
1949  ngx_str_t *value, *default_type;
1950  ngx_uint_t i, n, hash;
1952 
1953  types = (ngx_array_t **) (p + cmd->offset);
1954 
1955  if (*types == (void *) -1) {
1956  return NGX_CONF_OK;
1957  }
1958 
1959  default_type = cmd->post;
1960 
1961  if (*types == NULL) {
1962  *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
1963  if (*types == NULL) {
1964  return NGX_CONF_ERROR;
1965  }
1966 
1967  if (default_type) {
1968  type = ngx_array_push(*types);
1969  if (type == NULL) {
1970  return NGX_CONF_ERROR;
1971  }
1972 
1973  type->key = *default_type;
1974  type->key_hash = ngx_hash_key(default_type->data,
1975  default_type->len);
1976  type->value = (void *) 4;
1977  }
1978  }
1979 
1980  value = cf->args->elts;
1981 
1982  for (i = 1; i < cf->args->nelts; i++) {
1983 
1984  if (value[i].len == 1 && value[i].data[0] == '*') {
1985  *types = (void *) -1;
1986  return NGX_CONF_OK;
1987  }
1988 
1989  hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
1990  value[i].data[value[i].len] = '\0';
1991 
1992  type = (*types)->elts;
1993  for (n = 0; n < (*types)->nelts; n++) {
1994 
1995  if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
1997  "duplicate MIME type \"%V\"", &value[i]);
1998  continue;
1999  }
2000  }
2001 
2002  type = ngx_array_push(*types);
2003  if (type == NULL) {
2004  return NGX_CONF_ERROR;
2005  }
2006 
2007  type->key = value[i];
2008  type->key_hash = hash;
2009  type->value = (void *) 4;
2010  }
2011 
2012  return NGX_CONF_OK;
2013 }
2014 
2015 
2016 char *
2018  ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
2019  ngx_str_t *default_types)
2020 {
2021  ngx_hash_init_t hash;
2022 
2023  if (*keys) {
2024 
2025  if (*keys == (void *) -1) {
2026  return NGX_CONF_OK;
2027  }
2028 
2029  hash.hash = types_hash;
2030  hash.key = NULL;
2031  hash.max_size = 2048;
2032  hash.bucket_size = 64;
2033  hash.name = "test_types_hash";
2034  hash.pool = cf->pool;
2035  hash.temp_pool = NULL;
2036 
2037  if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
2038  return NGX_CONF_ERROR;
2039  }
2040 
2041  return NGX_CONF_OK;
2042  }
2043 
2044  if (prev_types_hash->buckets == NULL) {
2045 
2046  if (*prev_keys == NULL) {
2047 
2048  if (ngx_http_set_default_types(cf, prev_keys, default_types)
2049  != NGX_OK)
2050  {
2051  return NGX_CONF_ERROR;
2052  }
2053 
2054  } else if (*prev_keys == (void *) -1) {
2055  *keys = *prev_keys;
2056  return NGX_CONF_OK;
2057  }
2058 
2059  hash.hash = prev_types_hash;
2060  hash.key = NULL;
2061  hash.max_size = 2048;
2062  hash.bucket_size = 64;
2063  hash.name = "test_types_hash";
2064  hash.pool = cf->pool;
2065  hash.temp_pool = NULL;
2066 
2067  if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
2068  != NGX_OK)
2069  {
2070  return NGX_CONF_ERROR;
2071  }
2072  }
2073 
2074  *types_hash = *prev_types_hash;
2075 
2076  return NGX_CONF_OK;
2077 
2078 }
2079 
2080 
2081 ngx_int_t
2083  ngx_str_t *default_type)
2084 {
2086 
2087  *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
2088  if (*types == NULL) {
2089  return NGX_ERROR;
2090  }
2091 
2092  while (default_type->len) {
2093 
2094  type = ngx_array_push(*types);
2095  if (type == NULL) {
2096  return NGX_ERROR;
2097  }
2098 
2099  type->key = *default_type;
2100  type->key_hash = ngx_hash_key(default_type->data,
2101  default_type->len);
2102  type->value = (void *) 4;
2103 
2104  default_type++;
2105  }
2106 
2107  return NGX_OK;
2108 }