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