ngx_http.c revision e18a033b
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
13static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
14static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
15    ngx_http_core_main_conf_t *cmcf);
16static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
17    ngx_http_core_main_conf_t *cmcf);
18static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
19    ngx_http_core_main_conf_t *cmcf);
20
21static 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);
24static 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);
27static 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
30static 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);
33static 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);
36static 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);
38static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
39    ngx_http_core_loc_conf_t *pclcf);
40static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
41    const ngx_queue_t *two);
42static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
43    ngx_queue_t *locations);
44static void ngx_http_create_locations_list(ngx_queue_t *locations,
45    ngx_queue_t *q);
46static 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
50static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
51    ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
52static 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);
54static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
55static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
56    const void *two);
57
58static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
59    ngx_http_conf_port_t *port);
60static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
61    ngx_http_conf_addr_t *addr);
62static 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)
65static 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
69ngx_uint_t   ngx_http_max_module;
70
71
72ngx_http_output_header_filter_pt  ngx_http_top_header_filter;
73ngx_http_output_body_filter_pt    ngx_http_top_body_filter;
74ngx_http_request_body_filter_pt   ngx_http_top_request_body_filter;
75
76
77ngx_str_t  ngx_http_html_default_types[] = {
78    ngx_string("text/html"),
79    ngx_null_string
80};
81
82
83static 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
96static ngx_core_module_t  ngx_http_module_ctx = {
97    ngx_string("http"),
98    NULL,
99    NULL
100};
101
102
103ngx_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
119static char *
120ngx_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
339failed:
340
341    *cf = pcf;
342
343    return rv;
344}
345
346
347static ngx_int_t
348ngx_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
403static ngx_int_t
404ngx_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
444static ngx_int_t
445ngx_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
563static char *
564ngx_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
617failed:
618
619    *ctx = saved;
620
621    return rv;
622}
623
624
625static char *
626ngx_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
670static ngx_int_t
671ngx_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
799static ngx_int_t
800ngx_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
845ngx_int_t
846ngx_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
892static ngx_int_t
893ngx_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
965static ngx_int_t
966ngx_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
1006static void
1007ngx_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
1070static ngx_http_location_tree_node_t *
1071ngx_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
1128inclusive:
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
1143ngx_int_t
1144ngx_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
1193static ngx_int_t
1194ngx_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
1289static ngx_int_t
1290ngx_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
1340static ngx_int_t
1341ngx_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
1377static ngx_int_t
1378ngx_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
1424static ngx_int_t
1425ngx_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
1572failed:
1573
1574    ngx_destroy_pool(ha.temp_pool);
1575
1576    return NGX_ERROR;
1577}
1578
1579
1580static ngx_int_t
1581ngx_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
1614static int ngx_libc_cdecl
1615ngx_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
1626static ngx_int_t
1627ngx_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
1703static ngx_listening_t *
1704ngx_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
1782static ngx_int_t
1783ngx_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
1847static ngx_int_t
1848ngx_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
1912char *
1913ngx_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
1989char *
1990ngx_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
2054ngx_int_t
2055ngx_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}
2082