src/http/ngx_http.c - nginx source code

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_body_filter_pt    ngx_http_top_body_filter;
  64. ngx_http_request_body_filter_pt   ngx_http_top_request_body_filter;


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


  69. static ngx_command_t  ngx_http_commands[] = {

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

  76.       ngx_null_command
  77. };


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


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


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

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

  111.     /* the main http context */

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

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


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

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


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

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


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

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


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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


  214.     /* create location trees */

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

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

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

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


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

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


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

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

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

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

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

  248.     *cf = pcf;


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


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

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

  256.     return NGX_CONF_OK;

  257. failed:

  258.     *cf = pcf;

  259.     return rv;
  260. }


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

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

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

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

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

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

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

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

  312.     return NGX_OK;
  313. }


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

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

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

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

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

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

  345.     return NGX_OK;
  346. }


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

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

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

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

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

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

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

  376.         switch (i) {

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

  382.             break;

  383.         case NGX_HTTP_FIND_CONFIG_PHASE:
  384.             find_config_index = n;

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

  388.             continue;

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

  394.             break;

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

  402.             continue;

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

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

  413.             continue;

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

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

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

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

  428.     return NGX_OK;
  429. }


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

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

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

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

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

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

  453.         if (module->merge_loc_conf) {

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

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

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

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

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

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

  471. failed:

  472.     *ctx = saved;

  473.     return rv;
  474. }


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

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

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

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

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

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

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

  507.     *ctx = saved;

  508.     return NGX_CONF_OK;
  509. }


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

  523.     locations = pclcf->locations;

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

  527.     ngx_queue_sort(locations, ngx_http_cmp_locations);

  528.     named = NULL;
  529.     n = 0;
  530. #if (NGX_PCRE)
  531.     regex = NULL;
  532.     r = 0;
  533. #endif

  534.     for (q = ngx_queue_head(locations);
  535.          q != ngx_queue_sentinel(locations);
  536.          q = ngx_queue_next(q))
  537.     {
  538.         lq = (ngx_http_location_queue_t *) q;

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

  540.         if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
  541.             return NGX_ERROR;
  542.         }

  543. #if (NGX_PCRE)

  544.         if (clcf->regex) {
  545.             r++;

  546.             if (regex == NULL) {
  547.                 regex = q;
  548.             }

  549.             continue;
  550.         }

  551. #endif

  552.         if (clcf->named) {
  553.             n++;

  554.             if (named == NULL) {
  555.                 named = q;
  556.             }

  557.             continue;
  558.         }

  559.         if (clcf->noname) {
  560.             break;
  561.         }
  562.     }

  563.     if (q != ngx_queue_sentinel(locations)) {
  564.         ngx_queue_split(locations, q, &tail);
  565.     }

  566.     if (named) {
  567.         clcfp = ngx_palloc(cf->pool,
  568.                            (n + 1) * sizeof(ngx_http_core_loc_conf_t *));
  569.         if (clcfp == NULL) {
  570.             return NGX_ERROR;
  571.         }

  572.         cscf->named_locations = clcfp;

  573.         for (q = named;
  574.              q != ngx_queue_sentinel(locations);
  575.              q = ngx_queue_next(q))
  576.         {
  577.             lq = (ngx_http_location_queue_t *) q;

  578.             *(clcfp++) = lq->exact;
  579.         }

  580.         *clcfp = NULL;

  581.         ngx_queue_split(locations, named, &tail);
  582.     }

  583. #if (NGX_PCRE)

  584.     if (regex) {

  585.         clcfp = ngx_palloc(cf->pool,
  586.                            (r + 1) * sizeof(ngx_http_core_loc_conf_t *));
  587.         if (clcfp == NULL) {
  588.             return NGX_ERROR;
  589.         }

  590.         pclcf->regex_locations = clcfp;

  591.         for (q = regex;
  592.              q != ngx_queue_sentinel(locations);
  593.              q = ngx_queue_next(q))
  594.         {
  595.             lq = (ngx_http_location_queue_t *) q;

  596.             *(clcfp++) = lq->exact;
  597.         }

  598.         *clcfp = NULL;

  599.         ngx_queue_split(locations, regex, &tail);
  600.     }

  601. #endif

  602.     return NGX_OK;
  603. }


  604. static ngx_int_t
  605. ngx_http_init_static_location_trees(ngx_conf_t *cf,
  606.     ngx_http_core_loc_conf_t *pclcf)
  607. {
  608.     ngx_queue_t                *q, *locations;
  609.     ngx_http_core_loc_conf_t   *clcf;
  610.     ngx_http_location_queue_t  *lq;

  611.     locations = pclcf->locations;

  612.     if (locations == NULL) {
  613.         return NGX_OK;
  614.     }

  615.     if (ngx_queue_empty(locations)) {
  616.         return NGX_OK;
  617.     }

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

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

  624.         if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
  625.             return NGX_ERROR;
  626.         }
  627.     }

  628.     if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
  629.         return NGX_ERROR;
  630.     }

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

  632.     pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
  633.     if (pclcf->static_locations == NULL) {
  634.         return NGX_ERROR;
  635.     }

  636.     return NGX_OK;
  637. }


  638. ngx_int_t
  639. ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
  640.     ngx_http_core_loc_conf_t *clcf)
  641. {
  642.     ngx_http_location_queue_t  *lq;

  643.     if (*locations == NULL) {
  644.         *locations = ngx_palloc(cf->temp_pool,
  645.                                 sizeof(ngx_http_location_queue_t));
  646.         if (*locations == NULL) {
  647.             return NGX_ERROR;
  648.         }

  649.         ngx_queue_init(*locations);
  650.     }

  651.     lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
  652.     if (lq == NULL) {
  653.         return NGX_ERROR;
  654.     }

  655.     if (clcf->exact_match
  656. #if (NGX_PCRE)
  657.         || clcf->regex
  658. #endif
  659.         || clcf->named || clcf->noname)
  660.     {
  661.         lq->exact = clcf;
  662.         lq->inclusive = NULL;

  663.     } else {
  664.         lq->exact = NULL;
  665.         lq->inclusive = clcf;
  666.     }

  667.     lq->name = &clcf->name;
  668.     lq->file_name = cf->conf_file->file.name.data;
  669.     lq->line = cf->conf_file->line;

  670.     ngx_queue_init(&lq->list);

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

  672.     if (ngx_http_escape_location_name(cf, clcf) != NGX_OK) {
  673.         return NGX_ERROR;
  674.     }

  675.     return NGX_OK;
  676. }


  677. static ngx_int_t
  678. ngx_http_escape_location_name(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf)
  679. {
  680.     u_char     *p;
  681.     size_t      len;
  682.     uintptr_t   escape;

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

  685.     if (escape) {
  686.         len = clcf->name.len + escape;

  687.         p = ngx_pnalloc(cf->pool, len);
  688.         if (p == NULL) {
  689.             return NGX_ERROR;
  690.         }

  691.         clcf->escaped_name.len = len;
  692.         clcf->escaped_name.data = p;

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

  694.     } else {
  695.         clcf->escaped_name = clcf->name;
  696.     }

  697.     return NGX_OK;
  698. }


  699. static ngx_int_t
  700. ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
  701. {
  702.     ngx_int_t                   rc;
  703.     ngx_http_core_loc_conf_t   *first, *second;
  704.     ngx_http_location_queue_t  *lq1, *lq2;

  705.     lq1 = (ngx_http_location_queue_t *) one;
  706.     lq2 = (ngx_http_location_queue_t *) two;

  707.     first = lq1->exact ? lq1->exact : lq1->inclusive;
  708.     second = lq2->exact ? lq2->exact : lq2->inclusive;

  709.     if (first->noname && !second->noname) {
  710.         /* shift no named locations to the end */
  711.         return 1;
  712.     }

  713.     if (!first->noname && second->noname) {
  714.         /* shift no named locations to the end */
  715.         return -1;
  716.     }

  717.     if (first->noname || second->noname) {
  718.         /* do not sort no named locations */
  719.         return 0;
  720.     }

  721.     if (first->named && !second->named) {
  722.         /* shift named locations to the end */
  723.         return 1;
  724.     }

  725.     if (!first->named && second->named) {
  726.         /* shift named locations to the end */
  727.         return -1;
  728.     }

  729.     if (first->named && second->named) {
  730.         return ngx_strcmp(first->name.data, second->name.data);
  731.     }

  732. #if (NGX_PCRE)

  733.     if (first->regex && !second->regex) {
  734.         /* shift the regex matches to the end */
  735.         return 1;
  736.     }

  737.     if (!first->regex && second->regex) {
  738.         /* shift the regex matches to the end */
  739.         return -1;
  740.     }

  741.     if (first->regex || second->regex) {
  742.         /* do not sort the regex matches */
  743.         return 0;
  744.     }

  745. #endif

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

  748.     if (rc == 0 && !first->exact_match && second->exact_match) {
  749.         /* an exact match must be before the same inclusive one */
  750.         return 1;
  751.     }

  752.     return rc;
  753. }


  754. static ngx_int_t
  755. ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
  756. {
  757.     ngx_queue_t                *q, *x;
  758.     ngx_http_location_queue_t  *lq, *lx;

  759.     q = ngx_queue_head(locations);

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

  761.         x = ngx_queue_next(q);

  762.         lq = (ngx_http_location_queue_t *) q;
  763.         lx = (ngx_http_location_queue_t *) x;

  764.         if (lq->name->len == lx->name->len
  765.             && ngx_filename_cmp(lq->name->data, lx->name->data, lx->name->len)
  766.                == 0)
  767.         {
  768.             if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
  769.                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  770.                               "duplicate location \"%V\" in %s:%ui",
  771.                               lx->name, lx->file_name, lx->line);

  772.                 return NGX_ERROR;
  773.             }

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

  775.             ngx_queue_remove(x);

  776.             continue;
  777.         }

  778.         q = ngx_queue_next(q);
  779.     }

  780.     return NGX_OK;
  781. }


  782. static void
  783. ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
  784. {
  785.     u_char                     *name;
  786.     size_t                      len;
  787.     ngx_queue_t                *x, tail;
  788.     ngx_http_location_queue_t  *lq, *lx;

  789.     if (q == ngx_queue_last(locations)) {
  790.         return;
  791.     }

  792.     lq = (ngx_http_location_queue_t *) q;

  793.     if (lq->inclusive == NULL) {
  794.         ngx_http_create_locations_list(locations, ngx_queue_next(q));
  795.         return;
  796.     }

  797.     len = lq->name->len;
  798.     name = lq->name->data;

  799.     for (x = ngx_queue_next(q);
  800.          x != ngx_queue_sentinel(locations);
  801.          x = ngx_queue_next(x))
  802.     {
  803.         lx = (ngx_http_location_queue_t *) x;

  804.         if (len > lx->name->len
  805.             || ngx_filename_cmp(name, lx->name->data, len) != 0)
  806.         {
  807.             break;
  808.         }
  809.     }

  810.     q = ngx_queue_next(q);

  811.     if (q == x) {
  812.         ngx_http_create_locations_list(locations, x);
  813.         return;
  814.     }

  815.     ngx_queue_split(locations, q, &tail);
  816.     ngx_queue_add(&lq->list, &tail);

  817.     if (x == ngx_queue_sentinel(locations)) {
  818.         ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
  819.         return;
  820.     }

  821.     ngx_queue_split(&lq->list, x, &tail);
  822.     ngx_queue_add(locations, &tail);

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

  824.     ngx_http_create_locations_list(locations, x);
  825. }


  826. /*
  827. * to keep cache locality for left leaf nodes, allocate nodes in following
  828. * order: node, left subtree, right subtree, inclusive subtree
  829. */

  830. static ngx_http_location_tree_node_t *
  831. ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
  832.     size_t prefix)
  833. {
  834.     size_t                          len;
  835.     ngx_queue_t                    *q, tail;
  836.     ngx_http_location_queue_t      *lq;
  837.     ngx_http_location_tree_node_t  *node;

  838.     q = ngx_queue_middle(locations);

  839.     lq = (ngx_http_location_queue_t *) q;
  840.     len = lq->name->len - prefix;

  841.     node = ngx_palloc(cf->pool,
  842.                       offsetof(ngx_http_location_tree_node_t, name) + len);
  843.     if (node == NULL) {
  844.         return NULL;
  845.     }

  846.     node->left = NULL;
  847.     node->right = NULL;
  848.     node->tree = NULL;
  849.     node->exact = lq->exact;
  850.     node->inclusive = lq->inclusive;

  851.     node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
  852.                            || (lq->inclusive && lq->inclusive->auto_redirect));

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

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

  856.     if (ngx_queue_empty(locations)) {
  857.         /*
  858.          * ngx_queue_split() insures that if left part is empty,
  859.          * then right one is empty too
  860.          */
  861.         goto inclusive;
  862.     }

  863.     node->left = ngx_http_create_locations_tree(cf, locations, prefix);
  864.     if (node->left == NULL) {
  865.         return NULL;
  866.     }

  867.     ngx_queue_remove(q);

  868.     if (ngx_queue_empty(&tail)) {
  869.         goto inclusive;
  870.     }

  871.     node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
  872.     if (node->right == NULL) {
  873.         return NULL;
  874.     }

  875. inclusive:

  876.     if (ngx_queue_empty(&lq->list)) {
  877.         return node;
  878.     }

  879.     node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
  880.     if (node->tree == NULL) {
  881.         return NULL;
  882.     }

  883.     return node;
  884. }


  885. ngx_int_t
  886. ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  887.     ngx_http_listen_opt_t *lsopt)
  888. {
  889.     in_port_t                   p;
  890.     ngx_uint_t                  i;
  891.     struct sockaddr            *sa;
  892.     ngx_http_conf_port_t       *port;
  893.     ngx_http_core_main_conf_t  *cmcf;

  894.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  895.     if (cmcf->ports == NULL) {
  896.         cmcf->ports = ngx_array_create(cf->temp_pool, 2,
  897.                                        sizeof(ngx_http_conf_port_t));
  898.         if (cmcf->ports == NULL) {
  899.             return NGX_ERROR;
  900.         }
  901.     }

  902.     sa = lsopt->sockaddr;
  903.     p = ngx_inet_get_port(sa);

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

  906.         if (p != port[i].port
  907.             || lsopt->type != port[i].type
  908.             || sa->sa_family != port[i].family)
  909.         {
  910.             continue;
  911.         }

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

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

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

  916.     port = ngx_array_push(cmcf->ports);
  917.     if (port == NULL) {
  918.         return NGX_ERROR;
  919.     }

  920.     port->family = sa->sa_family;
  921.     port->type = lsopt->type;
  922.     port->port = p;
  923.     port->addrs.elts = NULL;

  924.     return ngx_http_add_address(cf, cscf, port, lsopt);
  925. }


  926. static ngx_int_t
  927. ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  928.     ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
  929. {
  930.     ngx_uint_t             i, default_server, proxy_protocol,
  931.                            protocols, protocols_prev;
  932.     ngx_http_conf_addr_t  *addr;
  933. #if (NGX_HTTP_SSL)
  934.     ngx_uint_t             ssl;
  935. #endif
  936. #if (NGX_HTTP_V2)
  937.     ngx_uint_t             http2;
  938. #endif
  939. #if (NGX_HTTP_V3)
  940.     ngx_uint_t             quic;
  941. #endif

  942.     /*
  943.      * we cannot compare whole sockaddr struct's as kernel
  944.      * may fill some fields in inherited sockaddr struct's
  945.      */

  946.     addr = port->addrs.elts;

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

  948.         if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen,
  949.                              addr[i].opt.sockaddr,
  950.                              addr[i].opt.socklen, 0)
  951.             != NGX_OK)
  952.         {
  953.             continue;
  954.         }

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

  956.         if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
  957.             return NGX_ERROR;
  958.         }

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

  961.         proxy_protocol = lsopt->proxy_protocol || addr[i].opt.proxy_protocol;
  962.         protocols = lsopt->proxy_protocol;
  963.         protocols_prev = addr[i].opt.proxy_protocol;

  964. #if (NGX_HTTP_SSL)
  965.         ssl = lsopt->ssl || addr[i].opt.ssl;
  966.         protocols |= lsopt->ssl << 1;
  967.         protocols_prev |= addr[i].opt.ssl << 1;
  968. #endif
  969. #if (NGX_HTTP_V2)
  970.         http2 = lsopt->http2 || addr[i].opt.http2;
  971.         protocols |= lsopt->http2 << 2;
  972.         protocols_prev |= addr[i].opt.http2 << 2;
  973. #endif
  974. #if (NGX_HTTP_V3)
  975.         quic = lsopt->quic || addr[i].opt.quic;
  976. #endif

  977.         if (lsopt->set) {

  978.             if (addr[i].opt.set) {
  979.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  980.                                    "duplicate listen options for %V",
  981.                                    &addr[i].opt.addr_text);
  982.                 return NGX_ERROR;
  983.             }

  984.             addr[i].opt = *lsopt;
  985.         }

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

  987.         if (lsopt->default_server) {

  988.             if (default_server) {
  989.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  990.                                    "a duplicate default server for %V",
  991.                                    &addr[i].opt.addr_text);
  992.                 return NGX_ERROR;
  993.             }

  994.             default_server = 1;
  995.             addr[i].default_server = cscf;
  996.         }

  997.         /* check for conflicting protocol options */

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

  999.             /* options added */

  1000.             if ((addr[i].opt.set && !lsopt->set)
  1001.                 || addr[i].protocols_changed
  1002.                 || (protocols | protocols_prev) != protocols)
  1003.             {
  1004.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1005.                                    "protocol options redefined for %V",
  1006.                                    &addr[i].opt.addr_text);
  1007.             }

  1008.             addr[i].protocols = protocols_prev;
  1009.             addr[i].protocols_set = 1;
  1010.             addr[i].protocols_changed = 1;

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

  1012.             /* options removed */

  1013.             if (lsopt->set
  1014.                 || (addr[i].protocols_set && protocols != addr[i].protocols))
  1015.             {
  1016.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1017.                                    "protocol options redefined for %V",
  1018.                                    &addr[i].opt.addr_text);
  1019.             }

  1020.             addr[i].protocols = protocols;
  1021.             addr[i].protocols_set = 1;
  1022.             addr[i].protocols_changed = 1;

  1023.         } else {

  1024.             /* the same options */

  1025.             if ((lsopt->set && addr[i].protocols_changed)
  1026.                 || (addr[i].protocols_set && protocols != addr[i].protocols))
  1027.             {
  1028.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1029.                                    "protocol options redefined for %V",
  1030.                                    &addr[i].opt.addr_text);
  1031.             }

  1032.             addr[i].protocols = protocols;
  1033.             addr[i].protocols_set = 1;
  1034.         }

  1035.         addr[i].opt.default_server = default_server;
  1036.         addr[i].opt.proxy_protocol = proxy_protocol;
  1037. #if (NGX_HTTP_SSL)
  1038.         addr[i].opt.ssl = ssl;
  1039. #endif
  1040. #if (NGX_HTTP_V2)
  1041.         addr[i].opt.http2 = http2;
  1042. #endif
  1043. #if (NGX_HTTP_V3)
  1044.         addr[i].opt.quic = quic;
  1045. #endif

  1046.         return NGX_OK;
  1047.     }

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

  1049.     return ngx_http_add_address(cf, cscf, port, lsopt);
  1050. }


  1051. /*
  1052. * add the server address, the server names and the server core module
  1053. * configurations to the port list
  1054. */

  1055. static ngx_int_t
  1056. ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  1057.     ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
  1058. {
  1059.     ngx_http_conf_addr_t  *addr;

  1060.     if (port->addrs.elts == NULL) {
  1061.         if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
  1062.                            sizeof(ngx_http_conf_addr_t))
  1063.             != NGX_OK)
  1064.         {
  1065.             return NGX_ERROR;
  1066.         }
  1067.     }

  1068. #if (NGX_HTTP_V2 && NGX_HTTP_SSL                                              \
  1069.      && !defined TLSEXT_TYPE_application_layer_protocol_negotiation)

  1070.     if (lsopt->http2 && lsopt->ssl) {
  1071.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1072.                            "nginx was built with OpenSSL that lacks ALPN "
  1073.                            "support, HTTP/2 is not enabled for %V",
  1074.                            &lsopt->addr_text);
  1075.     }

  1076. #endif

  1077.     addr = ngx_array_push(&port->addrs);
  1078.     if (addr == NULL) {
  1079.         return NGX_ERROR;
  1080.     }

  1081.     addr->opt = *lsopt;
  1082.     addr->protocols = 0;
  1083.     addr->protocols_set = 0;
  1084.     addr->protocols_changed = 0;
  1085.     addr->hash.buckets = NULL;
  1086.     addr->hash.size = 0;
  1087.     addr->wc_head = NULL;
  1088.     addr->wc_tail = NULL;
  1089. #if (NGX_PCRE)
  1090.     addr->nregex = 0;
  1091.     addr->regex = NULL;
  1092. #endif
  1093.     addr->default_server = cscf;
  1094.     addr->servers.elts = NULL;

  1095.     return ngx_http_add_server(cf, cscf, addr);
  1096. }


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

  1098. static ngx_int_t
  1099. ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
  1100.     ngx_http_conf_addr_t *addr)
  1101. {
  1102.     ngx_uint_t                  i;
  1103.     ngx_http_core_srv_conf_t  **server;

  1104.     if (addr->servers.elts == NULL) {
  1105.         if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
  1106.                            sizeof(ngx_http_core_srv_conf_t *))
  1107.             != NGX_OK)
  1108.         {
  1109.             return NGX_ERROR;
  1110.         }

  1111.     } else {
  1112.         server = addr->servers.elts;
  1113.         for (i = 0; i < addr->servers.nelts; i++) {
  1114.             if (server[i] == cscf) {
  1115.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1116.                                    "a duplicate listen %V",
  1117.                                    &addr->opt.addr_text);
  1118.                 return NGX_ERROR;
  1119.             }
  1120.         }
  1121.     }

  1122.     server = ngx_array_push(&addr->servers);
  1123.     if (server == NULL) {
  1124.         return NGX_ERROR;
  1125.     }

  1126.     *server = cscf;

  1127.     return NGX_OK;
  1128. }


  1129. static ngx_int_t
  1130. ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
  1131.     ngx_array_t *ports)
  1132. {
  1133.     ngx_uint_t             p, a;
  1134.     ngx_http_conf_port_t  *port;
  1135.     ngx_http_conf_addr_t  *addr;

  1136.     if (ports == NULL) {
  1137.         return NGX_OK;
  1138.     }

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

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

  1143.         /*
  1144.          * check whether all name-based servers have the same
  1145.          * configuration as a default server for given address:port
  1146.          */

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

  1149.             if (addr[a].servers.nelts > 1
  1150. #if (NGX_PCRE)
  1151.                 || addr[a].default_server->captures
  1152. #endif
  1153.                )
  1154.             {
  1155.                 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
  1156.                     return NGX_ERROR;
  1157.                 }
  1158.             }
  1159.         }

  1160.         if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
  1161.             return NGX_ERROR;
  1162.         }
  1163.     }

  1164.     return NGX_OK;
  1165. }


  1166. static ngx_int_t
  1167. ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
  1168.     ngx_http_conf_addr_t *addr)
  1169. {
  1170.     ngx_int_t                   rc;
  1171.     ngx_uint_t                  n, s;
  1172.     ngx_hash_init_t             hash;
  1173.     ngx_hash_keys_arrays_t      ha;
  1174.     ngx_http_server_name_t     *name;
  1175.     ngx_http_core_srv_conf_t  **cscfp;
  1176. #if (NGX_PCRE)
  1177.     ngx_uint_t                  regex, i;

  1178.     regex = 0;
  1179. #endif

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

  1181.     ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
  1182.     if (ha.temp_pool == NULL) {
  1183.         return NGX_ERROR;
  1184.     }

  1185.     ha.pool = cf->pool;

  1186.     if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
  1187.         goto failed;
  1188.     }

  1189.     cscfp = addr->servers.elts;

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

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

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

  1193. #if (NGX_PCRE)
  1194.             if (name[n].regex) {
  1195.                 regex++;
  1196.                 continue;
  1197.             }
  1198. #endif

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

  1201.             if (rc == NGX_ERROR) {
  1202.                 goto failed;
  1203.             }

  1204.             if (rc == NGX_DECLINED) {
  1205.                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  1206.                               "invalid server name or wildcard \"%V\" on %V",
  1207.                               &name[n].name, &addr->opt.addr_text);
  1208.                 goto failed;
  1209.             }

  1210.             if (rc == NGX_BUSY) {
  1211.                 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
  1212.                               "conflicting server name \"%V\" on %V, ignored",
  1213.                               &name[n].name, &addr->opt.addr_text);
  1214.             }
  1215.         }
  1216.     }

  1217.     hash.key = ngx_hash_key_lc;
  1218.     hash.max_size = cmcf->server_names_hash_max_size;
  1219.     hash.bucket_size = cmcf->server_names_hash_bucket_size;
  1220.     hash.name = "server_names_hash";
  1221.     hash.pool = cf->pool;

  1222.     if (ha.keys.nelts) {
  1223.         hash.hash = &addr->hash;
  1224.         hash.temp_pool = NULL;

  1225.         if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
  1226.             goto failed;
  1227.         }
  1228.     }

  1229.     if (ha.dns_wc_head.nelts) {

  1230.         ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
  1231.                   sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);

  1232.         hash.hash = NULL;
  1233.         hash.temp_pool = ha.temp_pool;

  1234.         if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
  1235.                                    ha.dns_wc_head.nelts)
  1236.             != NGX_OK)
  1237.         {
  1238.             goto failed;
  1239.         }

  1240.         addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
  1241.     }

  1242.     if (ha.dns_wc_tail.nelts) {

  1243.         ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
  1244.                   sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);

  1245.         hash.hash = NULL;
  1246.         hash.temp_pool = ha.temp_pool;

  1247.         if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
  1248.                                    ha.dns_wc_tail.nelts)
  1249.             != NGX_OK)
  1250.         {
  1251.             goto failed;
  1252.         }

  1253.         addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
  1254.     }

  1255.     ngx_destroy_pool(ha.temp_pool);

  1256. #if (NGX_PCRE)

  1257.     if (regex == 0) {
  1258.         return NGX_OK;
  1259.     }

  1260.     addr->nregex = regex;
  1261.     addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
  1262.     if (addr->regex == NULL) {
  1263.         return NGX_ERROR;
  1264.     }

  1265.     i = 0;

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

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

  1268.         for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
  1269.             if (name[n].regex) {
  1270.                 addr->regex[i++] = name[n];
  1271.             }
  1272.         }
  1273.     }

  1274. #endif

  1275.     return NGX_OK;

  1276. failed:

  1277.     ngx_destroy_pool(ha.temp_pool);

  1278.     return NGX_ERROR;
  1279. }


  1280. static ngx_int_t
  1281. ngx_http_cmp_conf_addrs(const void *one, const void *two)
  1282. {
  1283.     ngx_http_conf_addr_t  *first, *second;

  1284.     first = (ngx_http_conf_addr_t *) one;
  1285.     second = (ngx_http_conf_addr_t *) two;

  1286.     if (first->opt.wildcard) {
  1287.         /* a wildcard address must be the last resort, shift it to the end */
  1288.         return 1;
  1289.     }

  1290.     if (second->opt.wildcard) {
  1291.         /* a wildcard address must be the last resort, shift it to the end */
  1292.         return -1;
  1293.     }

  1294.     if (first->opt.bind && !second->opt.bind) {
  1295.         /* shift explicit bind()ed addresses to the start */
  1296.         return -1;
  1297.     }

  1298.     if (!first->opt.bind && second->opt.bind) {
  1299.         /* shift explicit bind()ed addresses to the start */
  1300.         return 1;
  1301.     }

  1302.     /* do not sort by default */

  1303.     return 0;
  1304. }


  1305. static int ngx_libc_cdecl
  1306. ngx_http_cmp_dns_wildcards(const void *one, const void *two)
  1307. {
  1308.     ngx_hash_key_t  *first, *second;

  1309.     first = (ngx_hash_key_t *) one;
  1310.     second = (ngx_hash_key_t *) two;

  1311.     return ngx_dns_strcmp(first->key.data, second->key.data);
  1312. }


  1313. static ngx_int_t
  1314. ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
  1315. {
  1316.     ngx_uint_t                 i, last, bind_wildcard;
  1317.     ngx_listening_t           *ls;
  1318.     ngx_http_port_t           *hport;
  1319.     ngx_http_conf_addr_t      *addr;

  1320.     addr = port->addrs.elts;
  1321.     last = port->addrs.nelts;

  1322.     /*
  1323.      * If there is a binding to an "*:port" then we need to bind() to
  1324.      * the "*:port" only and ignore other implicit bindings.  The bindings
  1325.      * have been already sorted: explicit bindings are on the start, then
  1326.      * implicit bindings go, and wildcard binding is in the end.
  1327.      */

  1328.     if (addr[last - 1].opt.wildcard) {
  1329.         addr[last - 1].opt.bind = 1;
  1330.         bind_wildcard = 1;

  1331.     } else {
  1332.         bind_wildcard = 0;
  1333.     }

  1334.     i = 0;

  1335.     while (i < last) {

  1336.         if (bind_wildcard && !addr[i].opt.bind) {
  1337.             i++;
  1338.             continue;
  1339.         }

  1340.         ls = ngx_http_add_listening(cf, &addr[i]);
  1341.         if (ls == NULL) {
  1342.             return NGX_ERROR;
  1343.         }

  1344.         hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
  1345.         if (hport == NULL) {
  1346.             return NGX_ERROR;
  1347.         }

  1348.         ls->servers = hport;

  1349.         hport->naddrs = i + 1;

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

  1351. #if (NGX_HAVE_INET6)
  1352.         case AF_INET6:
  1353.             if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
  1354.                 return NGX_ERROR;
  1355.             }
  1356.             break;
  1357. #endif
  1358.         default: /* AF_INET */
  1359.             if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
  1360.                 return NGX_ERROR;
  1361.             }
  1362.             break;
  1363.         }

  1364.         addr++;
  1365.         last--;
  1366.     }

  1367.     return NGX_OK;
  1368. }


  1369. static ngx_listening_t *
  1370. ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
  1371. {
  1372.     ngx_listening_t           *ls;
  1373.     ngx_http_core_loc_conf_t  *clcf;
  1374.     ngx_http_core_srv_conf_t  *cscf;

  1375.     ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen);
  1376.     if (ls == NULL) {
  1377.         return NULL;
  1378.     }

  1379.     ls->addr_ntop = 1;

  1380.     ls->handler = ngx_http_init_connection;

  1381.     cscf = addr->default_server;
  1382.     ls->pool_size = cscf->connection_pool_size;

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

  1384.     ls->logp = clcf->error_log;
  1385.     ls->log.data = &ls->addr_text;
  1386.     ls->log.handler = ngx_accept_log_error;

  1387. #if (NGX_WIN32)
  1388.     {
  1389.     ngx_iocp_conf_t  *iocpcf = NULL;

  1390.     if (ngx_get_conf(cf->cycle->conf_ctx, ngx_events_module)) {
  1391.         iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
  1392.     }
  1393.     if (iocpcf && iocpcf->acceptex_read) {
  1394.         ls->post_accept_buffer_size = cscf->client_header_buffer_size;
  1395.     }
  1396.     }
  1397. #endif

  1398.     ls->type = addr->opt.type;
  1399.     ls->backlog = addr->opt.backlog;
  1400.     ls->rcvbuf = addr->opt.rcvbuf;
  1401.     ls->sndbuf = addr->opt.sndbuf;

  1402.     ls->keepalive = addr->opt.so_keepalive;
  1403. #if (NGX_HAVE_KEEPALIVE_TUNABLE)
  1404.     ls->keepidle = addr->opt.tcp_keepidle;
  1405.     ls->keepintvl = addr->opt.tcp_keepintvl;
  1406.     ls->keepcnt = addr->opt.tcp_keepcnt;
  1407. #endif

  1408. #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
  1409.     ls->accept_filter = addr->opt.accept_filter;
  1410. #endif

  1411. #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
  1412.     ls->deferred_accept = addr->opt.deferred_accept;
  1413. #endif

  1414. #if (NGX_HAVE_INET6)
  1415.     ls->ipv6only = addr->opt.ipv6only;
  1416. #endif

  1417. #if (NGX_HAVE_SETFIB)
  1418.     ls->setfib = addr->opt.setfib;
  1419. #endif

  1420. #if (NGX_HAVE_TCP_FASTOPEN)
  1421.     ls->fastopen = addr->opt.fastopen;
  1422. #endif

  1423. #if (NGX_HAVE_REUSEPORT)
  1424.     ls->reuseport = addr->opt.reuseport;
  1425. #endif

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

  1427. #if (NGX_HTTP_V3)
  1428.     ls->quic = addr->opt.quic;
  1429. #endif

  1430.     return ls;
  1431. }


  1432. static ngx_int_t
  1433. ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
  1434.     ngx_http_conf_addr_t *addr)
  1435. {
  1436.     ngx_uint_t                 i;
  1437.     ngx_http_in_addr_t        *addrs;
  1438.     struct sockaddr_in        *sin;
  1439.     ngx_http_virtual_names_t  *vn;

  1440.     hport->addrs = ngx_pcalloc(cf->pool,
  1441.                                hport->naddrs * sizeof(ngx_http_in_addr_t));
  1442.     if (hport->addrs == NULL) {
  1443.         return NGX_ERROR;
  1444.     }

  1445.     addrs = hport->addrs;

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

  1447.         sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
  1448.         addrs[i].addr = sin->sin_addr.s_addr;
  1449.         addrs[i].conf.default_server = addr[i].default_server;
  1450. #if (NGX_HTTP_SSL)
  1451.         addrs[i].conf.ssl = addr[i].opt.ssl;
  1452. #endif
  1453. #if (NGX_HTTP_V2)
  1454.         addrs[i].conf.http2 = addr[i].opt.http2;
  1455. #endif
  1456. #if (NGX_HTTP_V3)
  1457.         addrs[i].conf.quic = addr[i].opt.quic;
  1458. #endif
  1459.         addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;

  1460.         if (addr[i].hash.buckets == NULL
  1461.             && (addr[i].wc_head == NULL
  1462.                 || addr[i].wc_head->hash.buckets == NULL)
  1463.             && (addr[i].wc_tail == NULL
  1464.                 || addr[i].wc_tail->hash.buckets == NULL)
  1465. #if (NGX_PCRE)
  1466.             && addr[i].nregex == 0
  1467. #endif
  1468.             )
  1469.         {
  1470.             continue;
  1471.         }

  1472.         vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
  1473.         if (vn == NULL) {
  1474.             return NGX_ERROR;
  1475.         }

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

  1477.         vn->names.hash = addr[i].hash;
  1478.         vn->names.wc_head = addr[i].wc_head;
  1479.         vn->names.wc_tail = addr[i].wc_tail;
  1480. #if (NGX_PCRE)
  1481.         vn->nregex = addr[i].nregex;
  1482.         vn->regex = addr[i].regex;
  1483. #endif
  1484.     }

  1485.     return NGX_OK;
  1486. }


  1487. #if (NGX_HAVE_INET6)

  1488. static ngx_int_t
  1489. ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
  1490.     ngx_http_conf_addr_t *addr)
  1491. {
  1492.     ngx_uint_t                 i;
  1493.     ngx_http_in6_addr_t       *addrs6;
  1494.     struct sockaddr_in6       *sin6;
  1495.     ngx_http_virtual_names_t  *vn;

  1496.     hport->addrs = ngx_pcalloc(cf->pool,
  1497.                                hport->naddrs * sizeof(ngx_http_in6_addr_t));
  1498.     if (hport->addrs == NULL) {
  1499.         return NGX_ERROR;
  1500.     }

  1501.     addrs6 = hport->addrs;

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

  1503.         sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
  1504.         addrs6[i].addr6 = sin6->sin6_addr;
  1505.         addrs6[i].conf.default_server = addr[i].default_server;
  1506. #if (NGX_HTTP_SSL)
  1507.         addrs6[i].conf.ssl = addr[i].opt.ssl;
  1508. #endif
  1509. #if (NGX_HTTP_V2)
  1510.         addrs6[i].conf.http2 = addr[i].opt.http2;
  1511. #endif
  1512. #if (NGX_HTTP_V3)
  1513.         addrs6[i].conf.quic = addr[i].opt.quic;
  1514. #endif
  1515.         addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;

  1516.         if (addr[i].hash.buckets == NULL
  1517.             && (addr[i].wc_head == NULL
  1518.                 || addr[i].wc_head->hash.buckets == NULL)
  1519.             && (addr[i].wc_tail == NULL
  1520.                 || addr[i].wc_tail->hash.buckets == NULL)
  1521. #if (NGX_PCRE)
  1522.             && addr[i].nregex == 0
  1523. #endif
  1524.             )
  1525.         {
  1526.             continue;
  1527.         }

  1528.         vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
  1529.         if (vn == NULL) {
  1530.             return NGX_ERROR;
  1531.         }

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

  1533.         vn->names.hash = addr[i].hash;
  1534.         vn->names.wc_head = addr[i].wc_head;
  1535.         vn->names.wc_tail = addr[i].wc_tail;
  1536. #if (NGX_PCRE)
  1537.         vn->nregex = addr[i].nregex;
  1538.         vn->regex = addr[i].regex;
  1539. #endif
  1540.     }

  1541.     return NGX_OK;
  1542. }

  1543. #endif


  1544. char *
  1545. ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1546. {
  1547.     char  *p = conf;

  1548.     ngx_array_t     **types;
  1549.     ngx_str_t        *value, *default_type;
  1550.     ngx_uint_t        i, n, hash;
  1551.     ngx_hash_key_t   *type;

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

  1553.     if (*types == (void *) -1) {
  1554.         return NGX_CONF_OK;
  1555.     }

  1556.     default_type = cmd->post;

  1557.     if (*types == NULL) {
  1558.         *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
  1559.         if (*types == NULL) {
  1560.             return NGX_CONF_ERROR;
  1561.         }

  1562.         if (default_type) {
  1563.             type = ngx_array_push(*types);
  1564.             if (type == NULL) {
  1565.                 return NGX_CONF_ERROR;
  1566.             }

  1567.             type->key = *default_type;
  1568.             type->key_hash = ngx_hash_key(default_type->data,
  1569.                                           default_type->len);
  1570.             type->value = (void *) 4;
  1571.         }
  1572.     }

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

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

  1575.         if (value[i].len == 1 && value[i].data[0] == '*') {
  1576.             *types = (void *) -1;
  1577.             return NGX_CONF_OK;
  1578.         }

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

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

  1583.             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
  1584.                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1585.                                    "duplicate MIME type \"%V\"", &value[i]);
  1586.                 goto next;
  1587.             }
  1588.         }

  1589.         type = ngx_array_push(*types);
  1590.         if (type == NULL) {
  1591.             return NGX_CONF_ERROR;
  1592.         }

  1593.         type->key = value[i];
  1594.         type->key_hash = hash;
  1595.         type->value = (void *) 4;

  1596.     next:

  1597.         continue;
  1598.     }

  1599.     return NGX_CONF_OK;
  1600. }


  1601. char *
  1602. ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash,
  1603.     ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
  1604.     ngx_str_t *default_types)
  1605. {
  1606.     ngx_hash_init_t  hash;

  1607.     if (*keys) {

  1608.         if (*keys == (void *) -1) {
  1609.             return NGX_CONF_OK;
  1610.         }

  1611.         hash.hash = types_hash;
  1612.         hash.key = NULL;
  1613.         hash.max_size = 2048;
  1614.         hash.bucket_size = 64;
  1615.         hash.name = "test_types_hash";
  1616.         hash.pool = cf->pool;
  1617.         hash.temp_pool = NULL;

  1618.         if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
  1619.             return NGX_CONF_ERROR;
  1620.         }

  1621.         return NGX_CONF_OK;
  1622.     }

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

  1624.         if (*prev_keys == NULL) {

  1625.             if (ngx_http_set_default_types(cf, prev_keys, default_types)
  1626.                 != NGX_OK)
  1627.             {
  1628.                 return NGX_CONF_ERROR;
  1629.             }

  1630.         } else if (*prev_keys == (void *) -1) {
  1631.             *keys = *prev_keys;
  1632.             return NGX_CONF_OK;
  1633.         }

  1634.         hash.hash = prev_types_hash;
  1635.         hash.key = NULL;
  1636.         hash.max_size = 2048;
  1637.         hash.bucket_size = 64;
  1638.         hash.name = "test_types_hash";
  1639.         hash.pool = cf->pool;
  1640.         hash.temp_pool = NULL;

  1641.         if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
  1642.             != NGX_OK)
  1643.         {
  1644.             return NGX_CONF_ERROR;
  1645.         }
  1646.     }

  1647.     *types_hash = *prev_types_hash;

  1648.     return NGX_CONF_OK;

  1649. }


  1650. ngx_int_t
  1651. ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
  1652.     ngx_str_t *default_type)
  1653. {
  1654.     ngx_hash_key_t  *type;

  1655.     *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
  1656.     if (*types == NULL) {
  1657.         return NGX_ERROR;
  1658.     }

  1659.     while (default_type->len) {

  1660.         type = ngx_array_push(*types);
  1661.         if (type == NULL) {
  1662.             return NGX_ERROR;
  1663.         }

  1664.         type->key = *default_type;
  1665.         type->key_hash = ngx_hash_key(default_type->data,
  1666.                                       default_type->len);
  1667.         type->value = (void *) 4;

  1668.         default_type++;
  1669.     }

  1670.     return NGX_OK;
  1671. }