src/http/ngx_http.c - nginx-1.31.7 nginx/ @ 939334eff

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>


  8. static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  9. static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
  10.     ngx_http_core_main_conf_t *cmcf);
  11. static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
  12.     ngx_http_core_main_conf_t *cmcf);
  13. static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
  14.     ngx_http_core_main_conf_t *cmcf);

  15. static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
  16.     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
  17.     ngx_http_listen_opt_t *lsopt);
  18. static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
  19.     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
  20.     ngx_http_listen_opt_t *lsopt);
  21. static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
  22.     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);

  23. static char *ngx_http_merge_servers(ngx_conf_t *cf,
  24.     ngx_http_core_main_conf_t *cmcf, ngx_http_module_t *module,
  25.     ngx_uint_t ctx_index);
  26. static char *ngx_http_merge_locations(ngx_conf_t *cf,
  27.     ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
  28.     ngx_uint_t ctx_index);
  29. static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
  30.     ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
  31. static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
  32.     ngx_http_core_loc_conf_t *pclcf);
  33. static ngx_int_t ngx_http_escape_location_name(ngx_conf_t *cf,
  34.     ngx_http_core_loc_conf_t *clcf);
  35. static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
  36.     const ngx_queue_t *two);
  37. static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
  38.     ngx_queue_t *locations);
  39. static void ngx_http_create_locations_list(ngx_queue_t *locations,
  40.     ngx_queue_t *q);
  41. static ngx_http_location_tree_node_t *
  42.     ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
  43.     size_t prefix);

  44. static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
  45.     ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
  46. static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
  47.     ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
  48. static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
  49. static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
  50.     const void *two);

  51. static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
  52.     ngx_http_conf_port_t *port);
  53. static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
  54.     ngx_http_conf_addr_t *addr);
  55. static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
  56.     ngx_http_conf_addr_t *addr);
  57. #if (NGX_HAVE_INET6)
  58. static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
  59.     ngx_http_conf_addr_t *addr);
  60. #endif

  61. ‌ngx_uint_t   ngx_http_max_module;


  62. ‌ngx_http_output_header_filter_pt  ngx_http_top_header_filter;
  63. ‌ngx_http_output_header_filter_pt  ngx_http_top_early_hints_filter;
  64. ‌ngx_http_output_body_filter_pt    ngx_http_top_body_filter;
  65. ‌ngx_http_request_body_filter_pt   ngx_http_top_request_body_filter;


  66. ‌ngx_str_t  ngx_http_html_default_types[] = {
  67.     ngx_string("text/html"),
  68.     ngx_null_string
  69. };


  70. ‌static ngx_command_t  ngx_http_commands[] = {

  71.     { ngx_string("http"),
  72.       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
  73.       ngx_http_block,
  74.       0,
  75.       0,
  76.       NULL },

  77.       ngx_null_command
  78. };


  79. ‌static ngx_core_module_t  ngx_http_module_ctx = {
  80.     ngx_string("http"),
  81.     NULL,
  82.     NULL
  83. };


  84. ‌ngx_module_t  ngx_http_module = {
  85.     NGX_MODULE_V1,
  86.     &ngx_http_module_ctx,                  /* module context */
  87.     ngx_http_commands,                     /* module directives */
  88.     NGX_CORE_MODULE,                       /* module type */
  89.     NULL,                                  /* init master */
  90.     NULL,                                  /* init module */
  91.     NULL,                                  /* init process */
  92.     NULL,                                  /* init thread */
  93.     NULL,                                  /* exit thread */
  94.     NULL,                                  /* exit process */
  95.     NULL,                                  /* exit master */
  96.     NGX_MODULE_V1_PADDING
  97. };


  98. static char *
  99. ‌ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  100. {
  101.     char                        *rv;
  102.     ngx_uint_t                   mi, m, s;
  103.     ngx_conf_t                   pcf;
  104.     ngx_http_module_t           *module;
  105.     ngx_http_conf_ctx_t         *ctx;
  106.     ngx_http_core_loc_conf_t    *clcf;
  107.     ngx_http_core_srv_conf_t   **cscfp;
  108.     ngx_http_core_main_conf_t   *cmcf;

  109.     if (*(ngx_http_conf_ctx_t **) conf) {
  110.         return "is duplicate";
  111.     }

  112.     /* the main http context */

  113.     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
  114.     if (ctx == NULL) {
  115.         return NGX_CONF_ERROR;
  116.     }

  117.     *(ngx_http_conf_ctx_t **) conf = ctx;


  118.     /* count the number of the http modules and set up their indices */

  119.     ngx_http_max_module = ngx_count_modules(cf->cycle, NGX_HTTP_MODULE);


  120.     /* the http main_conf context, it is the same in the all http contexts */

  121.     ctx->main_conf = ngx_pcalloc(cf->pool,
  122.                                  sizeof(void *) * ngx_http_max_module);
  123.     if (ctx->main_conf == NULL) {
  124.         return NGX_CONF_ERROR;
  125.     }


  126.     /*
  127.      * the http null srv_conf context, it is used to merge
  128.      * the server{}s' srv_conf's
  129.      */

  130.     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
  131.     if (ctx->srv_conf == NULL) {
  132.         return NGX_CONF_ERROR;
  133.     }


  134.     /*
  135.      * the http null loc_conf context, it is used to merge
  136.      * the server{}s' loc_conf's
  137.      */

  138.     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
  139.     if (ctx->loc_conf == NULL) {
  140.         return NGX_CONF_ERROR;
  141.     }


  142.     /*
  143.      * create the main_conf's, the null srv_conf's, and the null loc_conf's
  144.      * of the all http modules
  145.      */

  146.     for (m = 0; cf->cycle->modules[m]; m++) {
  147.         if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
  148.             continue;
  149.         }

  150.         module = cf->cycle->modules[m]->ctx;
  151.         mi = cf->cycle->modules[m]->ctx_index;

  152.         if (module->create_main_conf) {
  153.             ctx->main_conf[mi] = module->create_main_conf(cf);
  154.             if (ctx->main_conf[mi] == NULL) {
  155.                 return NGX_CONF_ERROR;
  156.             }
  157.         }

  158.         if (module->create_srv_conf) {
  159.             ctx->srv_conf[mi] = module->create_srv_conf(cf);
  160.             if (ctx->srv_conf[mi] == NULL) {
  161.                 return NGX_CONF_ERROR;
  162.             }
  163.         }

  164.         if (module->create_loc_conf) {
  165.             ctx->loc_conf[mi] = module->create_loc_conf(cf);
  166.             if (ctx->loc_conf[mi] == NULL) {
  167.                 return NGX_CONF_ERROR;
  168.             }
  169.         }
  170.     }

  171.     pcf = *cf;
  172.     cf->ctx = ctx;

  173.     for (m = 0; cf->cycle->modules[m]; m++) {
  174.         if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
  175.             continue;
  176.         }

  177.         module = cf->cycle->modules[m]->ctx;

  178.         if (module->preconfiguration) {
  179.             if (module->preconfiguration(cf) != NGX_OK) {
  180.                 return NGX_CONF_ERROR;
  181.             }
  182.         }
  183.     }

  184.     /* parse inside the http{} block */

  185.     cf->module_type = NGX_HTTP_MODULE;
  186.     cf->cmd_type = NGX_HTTP_MAIN_CONF;
  187.     rv = ngx_conf_parse(cf, NULL);

  188.     if (rv != NGX_CONF_OK) {
  189.         goto failed;
  190.     }

  191.     /*
  192.      * init http{} main_conf's, merge the server{}s' srv_conf's
  193.      * and its location{}s' loc_conf's
  194.      */

  195.     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
  196.     cscfp = cmcf->servers.elts;

  197.     for (m = 0; cf->cycle->modules[m]; m++) {
  198.         if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
  199.             continue;
  200.         }

  201.         module = cf->cycle->modules[m]->ctx;
  202.         mi = cf->cycle->modules[m]->ctx_index;

  203.         /* init http{} main_conf's */

  204.         if (module->init_main_conf) {
  205.             rv = module->init_main_conf(cf, ctx->main_conf[mi]);
  206.             if (rv != NGX_CONF_OK) {
  207.                 goto failed;
  208.             }
  209.         }

  210.         rv = ngx_http_merge_servers(cf, cmcf, module, mi);
  211.         if (rv != NGX_CONF_OK) {
  212.             goto failed;
  213.         }
  214.     }


  215.     /* create location trees */

  216.     for (s = 0; s < cmcf->servers.nelts; s++) {

  217.         clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

  218.         if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
  219.             return NGX_CONF_ERROR;
  220.         }

  221.         if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
  222.             return NGX_CONF_ERROR;
  223.         }
  224.     }


  225.     if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
  226.         return NGX_CONF_ERROR;
  227.     }

  228.     if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
  229.         return NGX_CONF_ERROR;
  230.     }


  231.     for (m = 0; cf->cycle->modules[m]; m++) {
  232.         if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
  233.             continue;
  234.         }

  235.         module = cf->cycle->modules[m]->ctx;

  236.         if (module->postconfiguration) {
  237.             if (module->postconfiguration(cf) != NGX_OK) {
  238.                 return NGX_CONF_ERROR;
  239.             }
  240.         }
  241.     }

  242.     if (ngx_http_variables_init_vars(cf) != NGX_OK) {
  243.         return NGX_CONF_ERROR;
  244.     }

  245.     /*
  246.      * http{}'s cf->ctx was needed while the configuration merging
  247.      * and in postconfiguration process
  248.      */

  249.     *cf = pcf;


  250.     if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
  251.         return NGX_CONF_ERROR;
  252.     }


  253.     /* optimize the lists of ports, addresses and server names */

  254.     if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
  255.         return NGX_CONF_ERROR;
  256.     }

  257.     return NGX_CONF_OK;

  258. failed:

  259.     *cf = pcf;

  260.     return rv;
  261. }


  262. static ngx_int_t
  263. ‌ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
  264. {
  265.     if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
  266.                        cf->pool, 1, sizeof(ngx_http_handler_pt))
  267.         != NGX_OK)
  268.     {
  269.         return NGX_ERROR;
  270.     }

  271.     if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
  272.                        cf->pool, 1, sizeof(ngx_http_handler_pt))
  273.         != NGX_OK)
  274.     {
  275.         return NGX_ERROR;
  276.     }

  277.     if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
  278.                        cf->pool, 1, sizeof(ngx_http_handler_pt))
  279.         != NGX_OK)
  280.     {
  281.         return NGX_ERROR;
  282.     }

  283.     if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
  284.                        cf->pool, 1, sizeof(ngx_http_handler_pt))
  285.         != NGX_OK)
  286.     {
  287.         return NGX_ERROR;
  288.     }

  289.     if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
  290.                        cf->pool, 2, sizeof(ngx_http_handler_pt))
  291.         != NGX_OK)
  292.     {
  293.         return NGX_ERROR;
  294.     }

  295.     if (ngx_array_init(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers,
  296.                        cf->pool, 2, sizeof(ngx_http_handler_pt))
  297.         != NGX_OK)
  298.     {
  299.         return NGX_ERROR;
  300.     }

  301.     if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
  302.                        cf->pool, 4, sizeof(ngx_http_handler_pt))
  303.         != NGX_OK)
  304.     {
  305.         return NGX_ERROR;
  306.     }

  307.     if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
  308.                        cf->pool, 1, sizeof(ngx_http_handler_pt))
  309.         != NGX_OK)
  310.     {
  311.         return NGX_ERROR;
  312.     }

  313.     return NGX_OK;
  314. }


  315. static ngx_int_t
  316. ‌ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
  317. {
  318.     ngx_array_t         headers_in;
  319.     ngx_hash_key_t     *hk;
  320.     ngx_hash_init_t     hash;
  321.     ngx_http_header_t  *header;

  322.     if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
  323.         != NGX_OK)
  324.     {
  325.         return NGX_ERROR;
  326.     }

  327.     for (header = ngx_http_headers_in; header->name.len; header++) {
  328.         hk = ngx_array_push(&headers_in);
  329.         if (hk == NULL) {
  330.             return NGX_ERROR;
  331.         }

  332.         hk->key = header->name;
  333.         hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
  334.         hk->value = header;
  335.     }

  336.     hash.hash = &cmcf->headers_in_hash;
  337.     hash.key = ngx_hash_key_lc;
  338.     hash.max_size = 512;
  339.     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
  340.     hash.name = "headers_in_hash";
  341.     hash.pool = cf->pool;
  342.     hash.temp_pool = NULL;

  343.     if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
  344.         return NGX_ERROR;
  345.     }

  346.     return NGX_OK;
  347. }


  348. static ngx_int_t
  349. ‌ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
  350. {
  351.     ngx_int_t                   j;
  352.     ngx_uint_t                  i, n;
  353.     ngx_uint_t                  find_config_index, use_rewrite, use_access;
  354.     ngx_http_handler_pt        *h;
  355.     ngx_http_phase_handler_t   *ph;
  356.     ngx_http_phase_handler_pt   checker;

  357.     cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
  358.     cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
  359.     find_config_index = 0;
  360.     use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
  361.     use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;

  362.     n = 1                  /* find config phase */
  363.         + use_rewrite      /* post rewrite phase */
  364.         + use_access;      /* post access phase */

  365.     for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
  366.         n += cmcf->phases[i].handlers.nelts;
  367.     }

  368.     ph = ngx_pcalloc(cf->pool,
  369.                      n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
  370.     if (ph == NULL) {
  371.         return NGX_ERROR;
  372.     }

  373.     cmcf->phase_engine.handlers = ph;
  374.     n = 0;

  375.     for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
  376.         h = cmcf->phases[i].handlers.elts;

  377.         switch (i) {

  378.         case NGX_HTTP_SERVER_REWRITE_PHASE:
  379.             if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
  380.                 cmcf->phase_engine.server_rewrite_index = n;
  381.             }
  382.             checker = ngx_http_core_rewrite_phase;

  383.             break;

  384.         case NGX_HTTP_FIND_CONFIG_PHASE:
  385.             find_config_index = n;

  386.             ph->checker = ngx_http_core_find_config_phase;
  387.             n++;
  388.             ph++;

  389.             continue;

  390.         case NGX_HTTP_REWRITE_PHASE:
  391.             if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
  392.                 cmcf->phase_engine.location_rewrite_index = n;
  393.             }
  394.             checker = ngx_http_core_rewrite_phase;

  395.             break;

  396.         case NGX_HTTP_POST_REWRITE_PHASE:
  397.             if (use_rewrite) {
  398.                 ph->checker = ngx_http_core_post_rewrite_phase;
  399.                 ph->next = find_config_index;
  400.                 n++;
  401.                 ph++;
  402.             }

  403.             continue;

  404.         case NGX_HTTP_ACCESS_PHASE:
  405.             checker = ngx_http_core_access_phase;
  406.             n++;
  407.             break;

  408.         case NGX_HTTP_POST_ACCESS_PHASE:
  409.             if (use_access) {
  410.                 ph->checker = ngx_http_core_post_access_phase;
  411.                 ph->next = n;
  412.                 ph++;
  413.             }

  414.             continue;

  415.         case NGX_HTTP_CONTENT_PHASE:
  416.             checker = ngx_http_core_content_phase;
  417.             break;

  418.         default:
  419.             checker = ngx_http_core_generic_phase;
  420.         }

  421.         n += cmcf->phases[i].handlers.nelts;

  422.         for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) {
  423.             ph->checker = checker;
  424.             ph->handler = h[j];
  425.             ph->next = n;
  426.             ph++;
  427.         }
  428.     }

  429.     return NGX_OK;
  430. }


  431. static char *
  432. ‌ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
  433.     ngx_http_module_t *module, ngx_uint_t ctx_index)
  434. {
  435.     char                        *rv;
  436.     ngx_uint_t                   s;
  437.     ngx_http_conf_ctx_t         *ctx, saved;
  438.     ngx_http_core_loc_conf_t    *clcf;
  439.     ngx_http_core_srv_conf_t   **cscfp;

  440.     cscfp = cmcf->servers.elts;
  441.     ctx = (ngx_http_conf_ctx_t *) cf->ctx;
  442.     saved = *ctx;
  443.     rv = NGX_CONF_OK;

  444.     for (s = 0; s < cmcf->servers.nelts; s++) {

  445.         /* merge the server{}s' srv_conf's */

  446.         ctx->srv_conf = cscfp[s]->ctx->srv_conf;

  447.         if (module->merge_srv_conf) {
  448.             rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
  449.                                         cscfp[s]->ctx->srv_conf[ctx_index]);
  450.             if (rv != NGX_CONF_OK) {
  451.                 goto failed;
  452.             }
  453.         }

  454.         if (module->merge_loc_conf) {

  455.             /* merge the server{}'s loc_conf */

  456.             ctx->loc_conf = cscfp[s]->ctx->loc_conf;

  457.             rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
  458.                                         cscfp[s]->ctx->loc_conf[ctx_index]);
  459.             if (rv != NGX_CONF_OK) {
  460.                 goto failed;
  461.             }

  462.             /* merge the locations{}' loc_conf's */

  463.             clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

  464.             rv = ngx_http_merge_locations(cf, clcf->locations,
  465.                                           cscfp[s]->ctx->loc_conf,
  466.                                           module, ctx_index);
  467.             if (rv != NGX_CONF_OK) {
  468.                 goto failed;
  469.             }
  470.         }
  471.     }

  472. failed:

  473.     *ctx = saved;

  474.     return rv;
  475. }


  476. static char *
  477. ‌ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
  478.     void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
  479. {
  480.     char                       *rv;
  481.     ngx_queue_t                *q;
  482.     ngx_http_conf_ctx_t        *ctx, saved;
  483.     ngx_http_core_loc_conf_t   *clcf;
  484.     ngx_http_location_queue_t  *lq;

  485.     if (locations == NULL) {
  486.         return NGX_CONF_OK;
  487.     }

  488.     ctx = (ngx_http_conf_ctx_t *) cf->ctx;
  489.     saved = *ctx;

  490.     for (q = ngx_queue_head(locations);
  491.          q != ngx_queue_sentinel(locations);
  492.          q = ngx_queue_next(q))
  493.     {
  494.         lq = (ngx_http_location_queue_t *) q;

  495.         clcf = lq->exact ? lq->exact : lq->inclusive;
  496.         ctx->loc_conf = clcf->loc_conf;

  497.         rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
  498.                                     clcf->loc_conf[ctx_index]);
  499.         if (rv != NGX_CONF_OK) {
  500.             return rv;
  501.         }

  502.         rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
  503.                                       module, ctx_index);
  504.         if (rv != NGX_CONF_OK) {
  505.             return rv;
  506.         }
  507.     }

  508.     *ctx = saved;

  509.     return NGX_CONF_OK;
  510. }


  511. static ngx_int_t
  512. ‌ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  513.     ngx_http_core_loc_conf_t *pclcf)
  514. {
  515.     ngx_uint_t                   n, p;
  516.     ngx_queue_t                 *q, *locations, *named, *predicate, tail;
  517.     ngx_http_core_loc_conf_t    *clcf;
  518.     ngx_http_location_queue_t   *lq;
  519.     ngx_http_core_loc_conf_t   **clcfp;
  520. #if (NGX_PCRE)
  521.     ngx_uint_t                   r;
  522.     ngx_queue_t                 *regex;
  523. #endif

  524.     locations = pclcf->locations;

  525.     if (locations == NULL) {
  526.         return NGX_OK;
  527.     }

  528.     ngx_queue_sort(locations, ngx_http_cmp_locations);

  529.     named = NULL;
  530.     n = 0;
  531. #if (NGX_PCRE)
  532.     regex = NULL;
  533.     r = 0;
  534. #endif
  535.     predicate = NULL;
  536.     p = 0;

  537.     for (q = ngx_queue_head(locations);
  538.          q != ngx_queue_sentinel(locations);
  539.          q = ngx_queue_next(q))
  540.     {
  541.         lq = (ngx_http_location_queue_t *) q;

  542.         clcf = lq->exact ? lq->exact : lq->inclusive;

  543.         if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
  544.             return NGX_ERROR;
  545.         }

  546. #if (NGX_PCRE)

  547.         if (clcf->regex) {
  548.             r++;

  549.             if (regex == NULL) {
  550.                 regex = q;
  551.             }

  552.             continue;
  553.         }

  554. #endif

  555.         if (clcf->predicate) {
  556.             p++;

  557.             if (predicate == NULL) {
  558.                 predicate = q;
  559.             }

  560.             continue;
  561.         }

  562.         if (clcf->named) {
  563.             n++;

  564.             if (named == NULL) {
  565.                 named = q;
  566.             }

  567.             continue;
  568.         }

  569.         if (clcf->noname) {
  570.             break;
  571.         }
  572.     }

  573.     if (q != ngx_queue_sentinel(locations)) {
  574.         ngx_queue_split(locations, q, &tail);
  575.     }

  576.     if (named) {
  577.         clcfp = ngx_palloc(cf->pool,
  578.                            (n + 1) * sizeof(ngx_http_core_loc_conf_t *));
  579.         if (clcfp == NULL) {
  580.             return NGX_ERROR;
  581.         }

  582.         cscf->named_locations = clcfp;

  583.         for (q = named;
  584.              q != ngx_queue_sentinel(locations);
  585.              q = ngx_queue_next(q))
  586.         {
  587.             lq = (ngx_http_location_queue_t *) q;

  588.             *(clcfp++) = lq->exact;
  589.         }

  590.         *clcfp = NULL;

  591.         ngx_queue_split(locations, named, &tail);
  592.     }

  593.     if (predicate) {
  594.         clcfp = ngx_palloc(cf->pool,
  595.                            (p + 1) * sizeof(ngx_http_core_loc_conf_t *));
  596.         if (clcfp == NULL) {
  597.             return NGX_ERROR;
  598.         }

  599.         pclcf->predicate_locations = clcfp;

  600.         for (q = predicate;
  601.              q != ngx_queue_sentinel(locations);
  602.              q = ngx_queue_next(q))
  603.         {
  604.             lq = (ngx_http_location_queue_t *) q;

  605.             *(clcfp++) = lq->exact;
  606.         }

  607.         *clcfp = NULL;

  608.         ngx_queue_split(locations, predicate, &tail);
  609.     }

  610. #if (NGX_PCRE)

  611.     if (regex) {

  612.         clcfp = ngx_palloc(cf->pool,
  613.                            (r + 1) * sizeof(ngx_http_core_loc_conf_t *));
  614.         if (clcfp == NULL) {
  615.             return NGX_ERROR;
  616.         }

  617.         pclcf->regex_locations = clcfp;

  618.         for (q = regex;
  619.              q != ngx_queue_sentinel(locations);
  620.              q = ngx_queue_next(q))
  621.         {
  622.             lq = (ngx_http_location_queue_t *) q;

  623.             *(clcfp++) = lq->exact;
  624.         }

  625.         *clcfp = NULL;

  626.         ngx_queue_split(locations, regex, &tail);
  627.     }

  628. #endif

  629.     return NGX_OK;
  630. }


  631. static ngx_int_t
  632. ‌ngx_http_init_static_location_trees(ngx_conf_t *cf,
  633.     ngx_http_core_loc_conf_t *pclcf)
  634. {
  635.     ngx_queue_t                *q, *locations;
  636.     ngx_http_core_loc_conf_t   *clcf, **clcfp;
  637.     ngx_http_location_queue_t  *lq;

  638.     if (pclcf->predicate_locations) {
  639.         for (clcfp = pclcf->predicate_locations; *clcfp; clcfp++) {
  640.             if (ngx_http_init_static_location_trees(cf, *clcfp) != NGX_OK) {
  641.                 return NGX_ERROR;
  642.             }
  643.         }
  644.     }

  645.     locations = pclcf->locations;

  646.     if (locations == NULL) {
  647.         return NGX_OK;
  648.     }

  649.     if (ngx_queue_empty(locations)) {
  650.         return NGX_OK;
  651.     }

  652.     for (q = ngx_queue_head(locations);
  653.          q != ngx_queue_sentinel(locations);
  654.          q = ngx_queue_next(q))
  655.     {
  656.         lq = (ngx_http_location_queue_t *) q;

  657.         clcf = lq->exact ? lq->exact : lq->inclusive;

  658.         if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
  659.             return NGX_ERROR;
  660.         }
  661.     }

  662.     if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
  663.         return NGX_ERROR;
  664.     }

  665.     ngx_http_create_locations_list(locations, ngx_queue_head(locations));

  666.     pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
  667.     if (pclcf->static_locations == NULL) {
  668.         return NGX_ERROR;
  669.     }

  670.     return NGX_OK;
  671. }


  672. ngx_int_t
  673. ‌ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
  674.     ngx_http_core_loc_conf_t *clcf)
  675. {
  676.     ngx_http_location_queue_t  *lq;

  677.     if (*locations == NULL) {
  678.         *locations = ngx_palloc(cf->temp_pool,
  679.                                 sizeof(ngx_http_location_queue_t));
  680.         if (*locations == NULL) {
  681.             return NGX_ERROR;
  682.         }

  683.         ngx_queue_init(*locations);
  684.     }

  685.     lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
  686.     if (lq == NULL) {
  687.         return NGX_ERROR;
  688.     }

  689.     if (clcf->exact_match
  690. #if (NGX_PCRE)
  691.         || clcf->regex
  692. #endif
  693.         || clcf->predicate || clcf->named || clcf->noname)
  694.     {
  695.         lq->exact = clcf;
  696.         lq->inclusive = NULL;

  697.     } else {
  698.         lq->exact = NULL;
  699.         lq->inclusive = clcf;
  700.     }

  701.     lq->name = &clcf->name;
  702.     lq->file_name = cf->conf_file->file.name.data;
  703.     lq->line = cf->conf_file->line;

  704.     ngx_queue_init(&lq->list);

  705.     ngx_queue_insert_tail(*locations, &lq->queue);

  706.     if (ngx_http_escape_location_name(cf, clcf) != NGX_OK) {
  707.         return NGX_ERROR;
  708.     }

  709.     return NGX_OK;
  710. }


  711. static ngx_int_t
  712. ‌ngx_http_escape_location_name(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf)
  713. {
  714.     u_char     *p;
  715.     size_t      len;
  716.     uintptr_t   escape;

  717.     escape = 2 * ngx_escape_uri(NULL, clcf->name.data, clcf->name.len,
  718.                                 NGX_ESCAPE_URI);

  719.     if (escape) {
  720.         len = clcf->name.len + escape;

  721.         p = ngx_pnalloc(cf->pool, len);
  722.         if (p == NULL) {
  723.             return NGX_ERROR;
  724.         }

  725.         clcf->escaped_name.len = len;
  726.         clcf->escaped_name.data = p;

  727.         ngx_escape_uri(p, clcf->name.data, clcf->name.len, NGX_ESCAPE_URI);

  728.     } else {
  729.         clcf->escaped_name = clcf->name;
  730.     }

  731.     return NGX_OK;
  732. }


  733. static ngx_int_t
  734. ‌ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
  735. {
  736.     ngx_int_t                   rc;
  737.     ngx_http_core_loc_conf_t   *first, *second;
  738.     ngx_http_location_queue_t  *lq1, *lq2;

  739.     lq1 = (ngx_http_location_queue_t *) one;
  740.     lq2 = (ngx_http_location_queue_t *) two;

  741.     first = lq1->exact ? lq1->exact : lq1->inclusive;
  742.     second = lq2->exact ? lq2->exact : lq2->inclusive;

  743.     if (first->noname && !second->noname) {
  744.         /* shift no named locations to the end */
  745.         return 1;
  746.     }

  747.     if (!first->noname && second->noname) {
  748.         /* shift no named locations to the end */
  749.         return -1;
  750.     }

  751.     if (first->noname || second->noname) {
  752.         /* do not sort no named locations */
  753.         return 0;
  754.     }

  755.     if (first->named && !second->named) {
  756.         /* shift named locations to the end */
  757.         return 1;
  758.     }

  759.     if (!first->named && second->named) {
  760.         /* shift named locations to the end */
  761.         return -1;
  762.     }

  763.     if (first->named && second->named) {
  764.         return ngx_strcmp(first->name.data, second->name.data);
  765.     }

  766.     if (first->predicate && !second->predicate) {
  767.         /* shift predicate locations to the end */
  768.         return 1;
  769.     }

  770.     if (!first->predicate && second->predicate) {
  771.         /* shift predicate locations to the end */
  772.         return -1;
  773.     }

  774.     if (first->predicate || second->predicate) {
  775.         /* do not sort the predicate locations */
  776.         return 0;
  777.     }

  778. #if (NGX_PCRE)

  779.     if (first->regex && !second->regex) {
  780.         /* shift the regex matches to the end */
  781.         return 1;
  782.     }

  783.     if (!first->regex && second->regex) {
  784.         /* shift the regex matches to the end */
  785.         return -1;
  786.     }

  787.     if (first->regex || second->regex) {
  788.         /* do not sort the regex matches */
  789.         return 0;
  790.     }

  791. #endif

  792.     rc = ngx_filename_cmp(first->name.data, second->name.data,
  793.                           ngx_min(first->name.len, second->name.len) + 1);

  794.     if (rc == 0 && !first->exact_match && second->exact_match) {
  795.         /* an exact match must be before the same inclusive one */
  796.         return 1;
  797.     }

  798.     return rc;
  799. }


  800. static ngx_int_t
  801. ‌ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
  802. {
  803.     ngx_queue_t                *q, *x;
  804.     ngx_http_location_queue_t  *lq, *lx;

  805.     q = ngx_queue_head(locations);

  806.     while (q != ngx_queue_last(locations)) {

  807.         x = ngx_queue_next(q);

  808.         lq = (ngx_http_location_queue_t *) q;
  809.         lx = (ngx_http_location_queue_t *) x;

  810.         if (lq->name->len == lx->name->len
  811.             && ngx_filename_cmp(lq->name->data, lx->name->data, lx->name->len)
  812.                == 0)
  813.         {
  814.             if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
  815.                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  816.                               "duplicate location \"%V\" in %s:%ui",
  817.                               lx->name, lx->file_name, lx->line);

  818.                 return NGX_ERROR;
  819.             }

  820.             lq->inclusive = lx->inclusive;

  821.             ngx_queue_remove(x);

  822.             continue;
  823.         }

  824.         q = ngx_queue_next(q);
  825.     }

  826.     return NGX_OK;
  827. }


  828. static void
  829. ‌ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
  830. {
  831.     u_char                     *name;
  832.     size_t                      len;
  833.     ngx_queue_t                *x, tail;
  834.     ngx_http_location_queue_t  *lq, *lx;

  835.     if (q == ngx_queue_last(locations)) {
  836.         return;
  837.     }

  838.     lq = (ngx_http_location_queue_t *) q;

  839.     if (lq->inclusive == NULL) {
  840.         ngx_http_create_locations_list(locations, ngx_queue_next(q));
  841.         return;
  842.     }

  843.     len = lq->name->len;
  844.     name = lq->name->data;

  845.     for (x = ngx_queue_next(q);
  846.          x != ngx_queue_sentinel(locations);
  847.          x = ngx_queue_next(x))
  848.     {
  849.         lx = (ngx_http_location_queue_t *) x;

  850.         if (len > lx->name->len
  851.             || ngx_filename_cmp(name, lx->name->data, len) != 0)
  852.         {
  853.             break;
  854.         }
  855.     }

  856.     q = ngx_queue_next(q);

  857.     if (q == x) {
  858.         ngx_http_create_locations_list(locations, x);
  859.         return;
  860.     }

  861.     ngx_queue_split(locations, q, &tail);
  862.     ngx_queue_add(&lq->list, &tail);

  863.     if (x == ngx_queue_sentinel(locations)) {
  864.         ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
  865.         return;
  866.     }

  867.     ngx_queue_split(&lq->list, x, &tail);
  868.     ngx_queue_add(locations, &tail);

  869.     ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));

  870.     ngx_http_create_locations_list(locations, x);
  871. }


  872. /*
  873. * to keep cache locality for left leaf nodes, allocate nodes in following
  874. * order: node, left subtree, right subtree, inclusive subtree
  875. */

  876. static ngx_http_location_tree_node_t *
  877. ‌ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
  878.     size_t prefix)
  879. {
  880.     size_t                          len;
  881.     ngx_queue_t                    *q, tail;
  882.     ngx_http_location_queue_t      *lq;
  883.     ngx_http_location_tree_node_t  *node;

  884.     q = ngx_queue_middle(locations);

  885.     lq = (ngx_http_location_queue_t *) q;
  886.     len = lq->name->len - prefix;

  887.     node = ngx_palloc(cf->pool,
  888.                       offsetof(ngx_http_location_tree_node_t, name) + len);
  889.     if (node == NULL) {
  890.         return NULL;
  891.     }

  892.     node->left = NULL;
  893.     node->right = NULL;
  894.     node->tree = NULL;
  895.     node->exact = lq->exact;
  896.     node->inclusive = lq->inclusive;

  897.     node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
  898.                            || (lq->inclusive && lq->inclusive->auto_redirect));

  899.     node->len = (u_short) len;
  900.     ngx_memcpy(node->name, &lq->name->data[prefix], len);

  901.     ngx_queue_split(locations, q, &tail);

  902.     if (ngx_queue_empty(locations)) {
  903.         /*
  904.          * ngx_queue_split() insures that if left part is empty,
  905.          * then right one is empty too
  906.          */
  907.         goto inclusive;
  908.     }

  909.     node->left = ngx_http_create_locations_tree(cf, locations, prefix);
  910.     if (node->left == NULL) {
  911.         return NULL;
  912.     }

  913.     ngx_queue_remove(q);

  914.     if (ngx_queue_empty(&tail)) {
  915.         goto inclusive;
  916.     }

  917.     node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
  918.     if (node->right == NULL) {
  919.         return NULL;
  920.     }

  921. inclusive:

  922.     if (ngx_queue_empty(&lq->list)) {
  923.         return node;
  924.     }

  925.     node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
  926.     if (node->tree == NULL) {
  927.         return NULL;
  928.     }

  929.     return node;
  930. }


  931. ngx_int_t
  932. ‌ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  933.     ngx_http_listen_opt_t *lsopt)
  934. {
  935.     in_port_t                   p;
  936.     ngx_uint_t                  i;
  937.     struct sockaddr            *sa;
  938.     ngx_http_conf_port_t       *port;
  939.     ngx_http_core_main_conf_t  *cmcf;

  940.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  941.     if (cmcf->ports == NULL) {
  942.         cmcf->ports = ngx_array_create(cf->temp_pool, 2,
  943.                                        sizeof(ngx_http_conf_port_t));
  944.         if (cmcf->ports == NULL) {
  945.             return NGX_ERROR;
  946.         }
  947.     }

  948.     sa = lsopt->sockaddr;
  949.     p = ngx_inet_get_port(sa);

  950.     port = cmcf->ports->elts;
  951.     for (i = 0; i < cmcf->ports->nelts; i++) {

  952.         if (p != port[i].port
  953.             || lsopt->type != port[i].type
  954.             || sa->sa_family != port[i].family)
  955.         {
  956.             continue;
  957.         }

  958.         /* a port is already in the port list */

  959.         return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
  960.     }

  961.     /* add a port to the port list */

  962.     port = ngx_array_push(cmcf->ports);
  963.     if (port == NULL) {
  964.         return NGX_ERROR;
  965.     }

  966.     port->family = sa->sa_family;
  967.     port->type = lsopt->type;
  968.     port->port = p;
  969.     port->addrs.elts = NULL;

  970.     return ngx_http_add_address(cf, cscf, port, lsopt);
  971. }


  972. static ngx_int_t
  973. ‌ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  974.     ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
  975. {
  976.     ngx_uint_t             i, default_server, proxy_protocol,
  977.                            protocols, protocols_prev;
  978.     ngx_http_conf_addr_t  *addr;
  979. #if (NGX_HTTP_SSL)
  980.     ngx_uint_t             ssl;
  981. #endif
  982. #if (NGX_HTTP_V2)
  983.     ngx_uint_t             http2;
  984. #endif
  985. #if (NGX_HTTP_V3)
  986.     ngx_uint_t             quic;
  987. #endif

  988.     /*
  989.      * we cannot compare whole sockaddr struct's as kernel
  990.      * may fill some fields in inherited sockaddr struct's
  991.      */

  992.     addr = port->addrs.elts;

  993.     for (i = 0; i < port->addrs.nelts; i++) {

  994.         if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen,
  995.                              addr[i].opt.sockaddr,
  996.                              addr[i].opt.socklen, 0)
  997.             != NGX_OK)
  998.         {
  999.             continue;
  1000.         }

  1001.         /* the address is already in the address list */

  1002.         if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
  1003.             return NGX_ERROR;
  1004.         }

  1005.         /* preserve default_server bit during listen options overwriting */
  1006.         default_server = addr[i].opt.default_server;

  1007.         proxy_protocol = lsopt->proxy_protocol || addr[i].opt.proxy_protocol;
  1008.         protocols = lsopt->proxy_protocol;
  1009.         protocols_prev = addr[i].opt.proxy_protocol;

  1010. #if (NGX_HTTP_SSL)
  1011.         ssl = lsopt->ssl || addr[i].opt.ssl;
  1012.         protocols |= lsopt->ssl << 1;
  1013.         protocols_prev |= addr[i].opt.ssl << 1;
  1014. #endif
  1015. #if (NGX_HTTP_V2)
  1016.         http2 = lsopt->http2 || addr[i].opt.http2;
  1017.         protocols |= lsopt->http2 << 2;
  1018.         protocols_prev |= addr[i].opt.http2 << 2;
  1019. #endif
  1020. #if (NGX_HTTP_V3)
  1021.         quic = lsopt->quic || addr[i].opt.quic;
  1022. #endif

  1023.         if (lsopt->set) {

  1024.             if (addr[i].opt.set) {
  1025.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1026.                                    "duplicate listen options for %V",
  1027.                                    &addr[i].opt.addr_text);
  1028.                 return NGX_ERROR;
  1029.             }

  1030.             addr[i].opt = *lsopt;
  1031.         }

  1032.         /* check the duplicate "default" server for this address:port */

  1033.         if (lsopt->default_server) {

  1034.             if (default_server) {
  1035.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1036.                                    "a duplicate default server for %V",
  1037.                                    &addr[i].opt.addr_text);
  1038.                 return NGX_ERROR;
  1039.             }

  1040.             default_server = 1;
  1041.             addr[i].default_server = cscf;
  1042.         }

  1043.         /* check for conflicting protocol options */

  1044.         if ((protocols | protocols_prev) != protocols_prev) {

  1045.             /* options added */

  1046.             if ((addr[i].opt.set && !lsopt->set)
  1047.                 || addr[i].protocols_changed
  1048.                 || (protocols | protocols_prev) != protocols)
  1049.             {
  1050.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1051.                                    "protocol options redefined for %V",
  1052.                                    &addr[i].opt.addr_text);
  1053.             }

  1054.             addr[i].protocols = protocols_prev;
  1055.             addr[i].protocols_set = 1;
  1056.             addr[i].protocols_changed = 1;

  1057.         } else if ((protocols_prev | protocols) != protocols) {

  1058.             /* options removed */

  1059.             if (lsopt->set
  1060.                 || (addr[i].protocols_set && protocols != addr[i].protocols))
  1061.             {
  1062.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1063.                                    "protocol options redefined for %V",
  1064.                                    &addr[i].opt.addr_text);
  1065.             }

  1066.             addr[i].protocols = protocols;
  1067.             addr[i].protocols_set = 1;
  1068.             addr[i].protocols_changed = 1;

  1069.         } else {

  1070.             /* the same options */

  1071.             if ((lsopt->set && addr[i].protocols_changed)
  1072.                 || (addr[i].protocols_set && protocols != addr[i].protocols))
  1073.             {
  1074.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1075.                                    "protocol options redefined for %V",
  1076.                                    &addr[i].opt.addr_text);
  1077.             }

  1078.             addr[i].protocols = protocols;
  1079.             addr[i].protocols_set = 1;
  1080.         }

  1081.         addr[i].opt.default_server = default_server;
  1082.         addr[i].opt.proxy_protocol = proxy_protocol;
  1083. #if (NGX_HTTP_SSL)
  1084.         addr[i].opt.ssl = ssl;
  1085. #endif
  1086. #if (NGX_HTTP_V2)
  1087.         addr[i].opt.http2 = http2;
  1088. #endif
  1089. #if (NGX_HTTP_V3)
  1090.         addr[i].opt.quic = quic;
  1091. #endif

  1092.         return NGX_OK;
  1093.     }

  1094.     /* add the address to the addresses list that bound to this port */

  1095.     return ngx_http_add_address(cf, cscf, port, lsopt);
  1096. }


  1097. /*
  1098. * add the server address, the server names and the server core module
  1099. * configurations to the port list
  1100. */

  1101. static ngx_int_t
  1102. ‌ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  1103.     ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
  1104. {
  1105.     ngx_http_conf_addr_t  *addr;

  1106.     if (port->addrs.elts == NULL) {
  1107.         if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
  1108.                            sizeof(ngx_http_conf_addr_t))
  1109.             != NGX_OK)
  1110.         {
  1111.             return NGX_ERROR;
  1112.         }
  1113.     }

  1114. #if (NGX_HTTP_V2 && NGX_HTTP_SSL                                              \
  1115.      && !defined TLSEXT_TYPE_application_layer_protocol_negotiation)

  1116.     if (lsopt->http2 && lsopt->ssl) {
  1117.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1118.                            "nginx was built with OpenSSL that lacks ALPN "
  1119.                            "support, HTTP/2 is not enabled for %V",
  1120.                            &lsopt->addr_text);
  1121.     }

  1122. #endif

  1123.     addr = ngx_array_push(&port->addrs);
  1124.     if (addr == NULL) {
  1125.         return NGX_ERROR;
  1126.     }

  1127.     addr->opt = *lsopt;
  1128.     addr->protocols = 0;
  1129.     addr->protocols_set = 0;
  1130.     addr->protocols_changed = 0;
  1131.     addr->hash.buckets = NULL;
  1132.     addr->hash.size = 0;
  1133.     addr->wc_head = NULL;
  1134.     addr->wc_tail = NULL;
  1135. #if (NGX_PCRE)
  1136.     addr->nregex = 0;
  1137.     addr->regex = NULL;
  1138. #endif
  1139.     addr->default_server = cscf;
  1140.     addr->servers.elts = NULL;

  1141.     return ngx_http_add_server(cf, cscf, addr);
  1142. }


  1143. /* add the server core module configuration to the address:port */

  1144. static ngx_int_t
  1145. ‌ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  1146.     ngx_http_conf_addr_t *addr)
  1147. {
  1148.     ngx_uint_t                  i;
  1149.     ngx_http_core_srv_conf_t  **server;

  1150.     if (addr->servers.elts == NULL) {
  1151.         if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
  1152.                            sizeof(ngx_http_core_srv_conf_t *))
  1153.             != NGX_OK)
  1154.         {
  1155.             return NGX_ERROR;
  1156.         }

  1157.     } else {
  1158.         server = addr->servers.elts;
  1159.         for (i = 0; i < addr->servers.nelts; i++) {
  1160.             if (server[i] == cscf) {
  1161.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1162.                                    "a duplicate listen %V",
  1163.                                    &addr->opt.addr_text);
  1164.                 return NGX_ERROR;
  1165.             }
  1166.         }
  1167.     }

  1168.     server = ngx_array_push(&addr->servers);
  1169.     if (server == NULL) {
  1170.         return NGX_ERROR;
  1171.     }

  1172.     *server = cscf;

  1173.     return NGX_OK;
  1174. }


  1175. static ngx_int_t
  1176. ‌ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
  1177.     ngx_array_t *ports)
  1178. {
  1179.     ngx_uint_t             p, a;
  1180.     ngx_http_conf_port_t  *port;
  1181.     ngx_http_conf_addr_t  *addr;

  1182.     if (ports == NULL) {
  1183.         return NGX_OK;
  1184.     }

  1185.     port = ports->elts;
  1186.     for (p = 0; p < ports->nelts; p++) {

  1187.         ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
  1188.                  sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);

  1189.         /*
  1190.          * check whether all name-based servers have the same
  1191.          * configuration as a default server for given address:port
  1192.          */

  1193.         addr = port[p].addrs.elts;
  1194.         for (a = 0; a < port[p].addrs.nelts; a++) {

  1195.             if (addr[a].servers.nelts > 1
  1196. #if (NGX_PCRE)
  1197.                 || addr[a].default_server->captures
  1198. #endif
  1199.                )
  1200.             {
  1201.                 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
  1202.                     return NGX_ERROR;
  1203.                 }
  1204.             }
  1205.         }

  1206.         if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
  1207.             return NGX_ERROR;
  1208.         }
  1209.     }

  1210.     return NGX_OK;
  1211. }


  1212. static ngx_int_t
  1213. ‌ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
  1214.     ngx_http_conf_addr_t *addr)
  1215. {
  1216.     ngx_int_t                   rc;
  1217.     ngx_uint_t                  n, s;
  1218.     ngx_hash_init_t             hash;
  1219.     ngx_hash_keys_arrays_t      ha;
  1220.     ngx_http_server_name_t     *name;
  1221.     ngx_http_core_srv_conf_t  **cscfp;
  1222. #if (NGX_PCRE)
  1223.     ngx_uint_t                  regex, i;

  1224.     regex = 0;
  1225. #endif

  1226.     ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));

  1227.     ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
  1228.     if (ha.temp_pool == NULL) {
  1229.         return NGX_ERROR;
  1230.     }

  1231.     ha.pool = cf->pool;

  1232.     if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
  1233.         goto failed;
  1234.     }

  1235.     cscfp = addr->servers.elts;

  1236.     for (s = 0; s < addr->servers.nelts; s++) {

  1237.         name = cscfp[s]->server_names.elts;

  1238.         for (n = 0; n < cscfp[s]->server_names.nelts; n++) {

  1239. #if (NGX_PCRE)
  1240.             if (name[n].regex) {
  1241.                 regex++;
  1242.                 continue;
  1243.             }
  1244. #endif

  1245.             rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
  1246.                                   NGX_HASH_WILDCARD_KEY);

  1247.             if (rc == NGX_ERROR) {
  1248.                 goto failed;
  1249.             }

  1250.             if (rc == NGX_DECLINED) {
  1251.                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  1252.                               "invalid server name or wildcard \"%V\" on %V",
  1253.                               &name[n].name, &addr->opt.addr_text);
  1254.                 goto failed;
  1255.             }

  1256.             if (rc == NGX_BUSY) {
  1257.                 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
  1258.                               "conflicting server name \"%V\" on %V, ignored",
  1259.                               &name[n].name, &addr->opt.addr_text);
  1260.             }
  1261.         }
  1262.     }

  1263.     hash.key = ngx_hash_key_lc;
  1264.     hash.max_size = cmcf->server_names_hash_max_size;
  1265.     hash.bucket_size = cmcf->server_names_hash_bucket_size;
  1266.     hash.name = "server_names_hash";
  1267.     hash.pool = cf->pool;

  1268.     if (ha.keys.nelts) {
  1269.         hash.hash = &addr->hash;
  1270.         hash.temp_pool = NULL;

  1271.         if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
  1272.             goto failed;
  1273.         }
  1274.     }

  1275.     if (ha.dns_wc_head.nelts) {

  1276.         ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
  1277.                   sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);

  1278.         hash.hash = NULL;
  1279.         hash.temp_pool = ha.temp_pool;

  1280.         if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
  1281.                                    ha.dns_wc_head.nelts)
  1282.             != NGX_OK)
  1283.         {
  1284.             goto failed;
  1285.         }

  1286.         addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
  1287.     }

  1288.     if (ha.dns_wc_tail.nelts) {

  1289.         ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
  1290.                   sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);

  1291.         hash.hash = NULL;
  1292.         hash.temp_pool = ha.temp_pool;

  1293.         if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
  1294.                                    ha.dns_wc_tail.nelts)
  1295.             != NGX_OK)
  1296.         {
  1297.             goto failed;
  1298.         }

  1299.         addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
  1300.     }

  1301.     ngx_destroy_pool(ha.temp_pool);

  1302. #if (NGX_PCRE)

  1303.     if (regex == 0) {
  1304.         return NGX_OK;
  1305.     }

  1306.     addr->nregex = regex;
  1307.     addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
  1308.     if (addr->regex == NULL) {
  1309.         return NGX_ERROR;
  1310.     }

  1311.     i = 0;

  1312.     for (s = 0; s < addr->servers.nelts; s++) {

  1313.         name = cscfp[s]->server_names.elts;

  1314.         for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
  1315.             if (name[n].regex) {
  1316.                 addr->regex[i++] = name[n];
  1317.             }
  1318.         }
  1319.     }

  1320. #endif

  1321.     return NGX_OK;

  1322. failed:

  1323.     ngx_destroy_pool(ha.temp_pool);

  1324.     return NGX_ERROR;
  1325. }


  1326. static ngx_int_t
  1327. ‌ngx_http_cmp_conf_addrs(const void *one, const void *two)
  1328. {
  1329.     ngx_http_conf_addr_t  *first, *second;

  1330.     first = (ngx_http_conf_addr_t *) one;
  1331.     second = (ngx_http_conf_addr_t *) two;

  1332.     if (first->opt.wildcard) {
  1333.         /* a wildcard address must be the last resort, shift it to the end */
  1334.         return 1;
  1335.     }

  1336.     if (second->opt.wildcard) {
  1337.         /* a wildcard address must be the last resort, shift it to the end */
  1338.         return -1;
  1339.     }

  1340.     if (first->opt.bind && !second->opt.bind) {
  1341.         /* shift explicit bind()ed addresses to the start */
  1342.         return -1;
  1343.     }

  1344.     if (!first->opt.bind && second->opt.bind) {
  1345.         /* shift explicit bind()ed addresses to the start */
  1346.         return 1;
  1347.     }

  1348.     /* do not sort by default */

  1349.     return 0;
  1350. }


  1351. static int ngx_libc_cdecl
  1352. ‌ngx_http_cmp_dns_wildcards(const void *one, const void *two)
  1353. {
  1354.     ngx_hash_key_t  *first, *second;

  1355.     first = (ngx_hash_key_t *) one;
  1356.     second = (ngx_hash_key_t *) two;

  1357.     return ngx_dns_strcmp(first->key.data, second->key.data);
  1358. }


  1359. static ngx_int_t
  1360. ‌ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
  1361. {
  1362.     ngx_uint_t                 i, last, bind_wildcard;
  1363.     ngx_listening_t           *ls;
  1364.     ngx_http_port_t           *hport;
  1365.     ngx_http_conf_addr_t      *addr;

  1366.     addr = port->addrs.elts;
  1367.     last = port->addrs.nelts;

  1368.     /*
  1369.      * If there is a binding to an "*:port" then we need to bind() to
  1370.      * the "*:port" only and ignore other implicit bindings.  The bindings
  1371.      * have been already sorted: explicit bindings are on the start, then
  1372.      * implicit bindings go, and wildcard binding is in the end.
  1373.      */

  1374.     if (addr[last - 1].opt.wildcard) {
  1375.         addr[last - 1].opt.bind = 1;
  1376.         bind_wildcard = 1;

  1377.     } else {
  1378.         bind_wildcard = 0;
  1379.     }

  1380.     i = 0;

  1381.     while (i < last) {

  1382.         if (bind_wildcard && !addr[i].opt.bind) {
  1383.             i++;
  1384.             continue;
  1385.         }

  1386.         ls = ngx_http_add_listening(cf, &addr[i]);
  1387.         if (ls == NULL) {
  1388.             return NGX_ERROR;
  1389.         }

  1390.         hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
  1391.         if (hport == NULL) {
  1392.             return NGX_ERROR;
  1393.         }

  1394.         ls->servers = hport;

  1395.         hport->naddrs = i + 1;

  1396.         switch (ls->sockaddr->sa_family) {

  1397. #if (NGX_HAVE_INET6)
  1398.         case AF_INET6:
  1399.             if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
  1400.                 return NGX_ERROR;
  1401.             }
  1402.             break;
  1403. #endif
  1404.         default: /* AF_INET */
  1405.             if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
  1406.                 return NGX_ERROR;
  1407.             }
  1408.             break;
  1409.         }

  1410.         addr++;
  1411.         last--;
  1412.     }

  1413.     return NGX_OK;
  1414. }


  1415. static ngx_listening_t *
  1416. ‌ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
  1417. {
  1418.     ngx_listening_t           *ls;
  1419.     ngx_http_core_loc_conf_t  *clcf;
  1420.     ngx_http_core_srv_conf_t  *cscf;

  1421.     ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen);
  1422.     if (ls == NULL) {
  1423.         return NULL;
  1424.     }

  1425.     ls->addr_ntop = 1;

  1426.     ls->handler = ngx_http_init_connection;

  1427.     cscf = addr->default_server;
  1428.     ls->pool_size = cscf->connection_pool_size;

  1429.     clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];

  1430.     ls->logp = clcf->error_log;
  1431.     ls->log.data = &ls->addr_text;
  1432.     ls->log.handler = ngx_accept_log_error;

  1433. #if (NGX_WIN32)
  1434.     {
  1435.     ngx_iocp_conf_t  *iocpcf = NULL;

  1436.     if (ngx_get_conf(cf->cycle->conf_ctx, ngx_events_module)) {
  1437.         iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
  1438.     }
  1439.     if (iocpcf && iocpcf->acceptex_read) {
  1440.         ls->post_accept_buffer_size = cscf->client_header_buffer_size;
  1441.     }
  1442.     }
  1443. #endif

  1444.     ls->type = addr->opt.type;
  1445.     ls->protocol = addr->opt.protocol;
  1446.     ls->backlog = addr->opt.backlog;
  1447.     ls->rcvbuf = addr->opt.rcvbuf;
  1448.     ls->sndbuf = addr->opt.sndbuf;

  1449.     ls->keepalive = addr->opt.so_keepalive;
  1450. #if (NGX_HAVE_KEEPALIVE_TUNABLE)
  1451.     ls->keepidle = addr->opt.tcp_keepidle;
  1452.     ls->keepintvl = addr->opt.tcp_keepintvl;
  1453.     ls->keepcnt = addr->opt.tcp_keepcnt;
  1454. #endif

  1455. #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
  1456.     ls->accept_filter = addr->opt.accept_filter;
  1457. #endif

  1458. #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
  1459.     ls->deferred_accept = addr->opt.deferred_accept;
  1460. #endif

  1461. #if (NGX_HAVE_INET6)
  1462.     ls->ipv6only = addr->opt.ipv6only;
  1463. #endif

  1464. #if (NGX_HAVE_SETFIB)
  1465.     ls->setfib = addr->opt.setfib;
  1466. #endif

  1467. #if (NGX_HAVE_TCP_FASTOPEN)
  1468.     ls->fastopen = addr->opt.fastopen;
  1469. #endif

  1470. #if (NGX_HAVE_REUSEPORT)
  1471.     ls->reuseport = addr->opt.reuseport;
  1472. #endif

  1473.     ls->wildcard = addr->opt.wildcard;

  1474. #if (NGX_HTTP_V3)
  1475.     ls->quic = addr->opt.quic;
  1476. #endif

  1477.     return ls;
  1478. }


  1479. static ngx_int_t
  1480. ‌ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
  1481.     ngx_http_conf_addr_t *addr)
  1482. {
  1483.     ngx_uint_t                 i;
  1484.     ngx_http_in_addr_t        *addrs;
  1485.     struct sockaddr_in        *sin;
  1486.     ngx_http_virtual_names_t  *vn;

  1487.     hport->addrs = ngx_pcalloc(cf->pool,
  1488.                                hport->naddrs * sizeof(ngx_http_in_addr_t));
  1489.     if (hport->addrs == NULL) {
  1490.         return NGX_ERROR;
  1491.     }

  1492.     addrs = hport->addrs;

  1493.     for (i = 0; i < hport->naddrs; i++) {

  1494.         sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
  1495.         addrs[i].addr = sin->sin_addr.s_addr;
  1496.         addrs[i].conf.default_server = addr[i].default_server;
  1497. #if (NGX_HTTP_SSL)
  1498.         addrs[i].conf.ssl = addr[i].opt.ssl;
  1499. #endif
  1500. #if (NGX_HTTP_V2)
  1501.         addrs[i].conf.http2 = addr[i].opt.http2;
  1502. #endif
  1503. #if (NGX_HTTP_V3)
  1504.         addrs[i].conf.quic = addr[i].opt.quic;
  1505. #endif
  1506.         addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;

  1507.         if (addr[i].hash.buckets == NULL
  1508.             && (addr[i].wc_head == NULL
  1509.                 || addr[i].wc_head->hash.buckets == NULL)
  1510.             && (addr[i].wc_tail == NULL
  1511.                 || addr[i].wc_tail->hash.buckets == NULL)
  1512. #if (NGX_PCRE)
  1513.             && addr[i].nregex == 0
  1514. #endif
  1515.             )
  1516.         {
  1517.             continue;
  1518.         }

  1519.         vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
  1520.         if (vn == NULL) {
  1521.             return NGX_ERROR;
  1522.         }

  1523.         addrs[i].conf.virtual_names = vn;

  1524.         vn->names.hash = addr[i].hash;
  1525.         vn->names.wc_head = addr[i].wc_head;
  1526.         vn->names.wc_tail = addr[i].wc_tail;
  1527. #if (NGX_PCRE)
  1528.         vn->nregex = addr[i].nregex;
  1529.         vn->regex = addr[i].regex;
  1530. #endif
  1531.     }

  1532.     return NGX_OK;
  1533. }


  1534. #if (NGX_HAVE_INET6)

  1535. static ngx_int_t
  1536. ‌ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
  1537.     ngx_http_conf_addr_t *addr)
  1538. {
  1539.     ngx_uint_t                 i;
  1540.     ngx_http_in6_addr_t       *addrs6;
  1541.     struct sockaddr_in6       *sin6;
  1542.     ngx_http_virtual_names_t  *vn;

  1543.     hport->addrs = ngx_pcalloc(cf->pool,
  1544.                                hport->naddrs * sizeof(ngx_http_in6_addr_t));
  1545.     if (hport->addrs == NULL) {
  1546.         return NGX_ERROR;
  1547.     }

  1548.     addrs6 = hport->addrs;

  1549.     for (i = 0; i < hport->naddrs; i++) {

  1550.         sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
  1551.         addrs6[i].addr6 = sin6->sin6_addr;
  1552.         addrs6[i].conf.default_server = addr[i].default_server;
  1553. #if (NGX_HTTP_SSL)
  1554.         addrs6[i].conf.ssl = addr[i].opt.ssl;
  1555. #endif
  1556. #if (NGX_HTTP_V2)
  1557.         addrs6[i].conf.http2 = addr[i].opt.http2;
  1558. #endif
  1559. #if (NGX_HTTP_V3)
  1560.         addrs6[i].conf.quic = addr[i].opt.quic;
  1561. #endif
  1562.         addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;

  1563.         if (addr[i].hash.buckets == NULL
  1564.             && (addr[i].wc_head == NULL
  1565.                 || addr[i].wc_head->hash.buckets == NULL)
  1566.             && (addr[i].wc_tail == NULL
  1567.                 || addr[i].wc_tail->hash.buckets == NULL)
  1568. #if (NGX_PCRE)
  1569.             && addr[i].nregex == 0
  1570. #endif
  1571.             )
  1572.         {
  1573.             continue;
  1574.         }

  1575.         vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
  1576.         if (vn == NULL) {
  1577.             return NGX_ERROR;
  1578.         }

  1579.         addrs6[i].conf.virtual_names = vn;

  1580.         vn->names.hash = addr[i].hash;
  1581.         vn->names.wc_head = addr[i].wc_head;
  1582.         vn->names.wc_tail = addr[i].wc_tail;
  1583. #if (NGX_PCRE)
  1584.         vn->nregex = addr[i].nregex;
  1585.         vn->regex = addr[i].regex;
  1586. #endif
  1587.     }

  1588.     return NGX_OK;
  1589. }

  1590. #endif


  1591. char *
  1592. ‌ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1593. {
  1594.     char  *p = conf;

  1595.     ngx_array_t     **types;
  1596.     ngx_str_t        *value, *default_type;
  1597.     ngx_uint_t        i, n, hash;
  1598.     ngx_hash_key_t   *type;

  1599.     types = (ngx_array_t **) (p + cmd->offset);

  1600.     if (*types == (void *) -1) {
  1601.         return NGX_CONF_OK;
  1602.     }

  1603.     default_type = cmd->post;

  1604.     if (*types == NULL) {
  1605.         *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
  1606.         if (*types == NULL) {
  1607.             return NGX_CONF_ERROR;
  1608.         }

  1609.         if (default_type) {
  1610.             type = ngx_array_push(*types);
  1611.             if (type == NULL) {
  1612.                 return NGX_CONF_ERROR;
  1613.             }

  1614.             type->key = *default_type;
  1615.             type->key_hash = ngx_hash_key(default_type->data,
  1616.                                           default_type->len);
  1617.             type->value = (void *) 4;
  1618.         }
  1619.     }

  1620.     value = cf->args->elts;

  1621.     for (i = 1; i < cf->args->nelts; i++) {

  1622.         if (value[i].len == 1 && value[i].data[0] == '*') {
  1623.             *types = (void *) -1;
  1624.             return NGX_CONF_OK;
  1625.         }

  1626.         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
  1627.         value[i].data[value[i].len] = '\0';

  1628.         type = (*types)->elts;
  1629.         for (n = 0; n < (*types)->nelts; n++) {

  1630.             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
  1631.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1632.                                    "duplicate MIME type \"%V\"", &value[i]);
  1633.                 goto next;
  1634.             }
  1635.         }

  1636.         type = ngx_array_push(*types);
  1637.         if (type == NULL) {
  1638.             return NGX_CONF_ERROR;
  1639.         }

  1640.         type->key = value[i];
  1641.         type->key_hash = hash;
  1642.         type->value = (void *) 4;

  1643.     next:

  1644.         continue;
  1645.     }

  1646.     return NGX_CONF_OK;
  1647. }


  1648. char *
  1649. ‌ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash,
  1650.     ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
  1651.     ngx_str_t *default_types)
  1652. {
  1653.     ngx_hash_init_t  hash;

  1654.     if (*keys) {

  1655.         if (*keys == (void *) -1) {
  1656.             return NGX_CONF_OK;
  1657.         }

  1658.         hash.hash = types_hash;
  1659.         hash.key = NULL;
  1660.         hash.max_size = 2048;
  1661.         hash.bucket_size = 64;
  1662.         hash.name = "test_types_hash";
  1663.         hash.pool = cf->pool;
  1664.         hash.temp_pool = NULL;

  1665.         if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
  1666.             return NGX_CONF_ERROR;
  1667.         }

  1668.         return NGX_CONF_OK;
  1669.     }

  1670.     if (prev_types_hash->buckets == NULL) {

  1671.         if (*prev_keys == NULL) {

  1672.             if (ngx_http_set_default_types(cf, prev_keys, default_types)
  1673.                 != NGX_OK)
  1674.             {
  1675.                 return NGX_CONF_ERROR;
  1676.             }

  1677.         } else if (*prev_keys == (void *) -1) {
  1678.             *keys = *prev_keys;
  1679.             return NGX_CONF_OK;
  1680.         }

  1681.         hash.hash = prev_types_hash;
  1682.         hash.key = NULL;
  1683.         hash.max_size = 2048;
  1684.         hash.bucket_size = 64;
  1685.         hash.name = "test_types_hash";
  1686.         hash.pool = cf->pool;
  1687.         hash.temp_pool = NULL;

  1688.         if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
  1689.             != NGX_OK)
  1690.         {
  1691.             return NGX_CONF_ERROR;
  1692.         }
  1693.     }

  1694.     *types_hash = *prev_types_hash;

  1695.     return NGX_CONF_OK;

  1696. }


  1697. ngx_int_t
  1698. ‌ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
  1699.     ngx_str_t *default_type)
  1700. {
  1701.     ngx_hash_key_t  *type;

  1702.     *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
  1703.     if (*types == NULL) {
  1704.         return NGX_ERROR;
  1705.     }

  1706.     while (default_type->len) {

  1707.         type = ngx_array_push(*types);
  1708.         if (type == NULL) {
  1709.             return NGX_ERROR;
  1710.         }

  1711.         type->key = *default_type;
  1712.         type->key_hash = ngx_hash_key(default_type->data,
  1713.                                       default_type->len);
  1714.         type->value = (void *) 4;

  1715.         default_type++;
  1716.     }

  1717.     return NGX_OK;
  1718. }