src/http/ngx_http.c - nginx-1.31.3 nginx/ @ 42f8df65b

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;
  516.     ngx_queue_t                 *q, *locations, *named, 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.     for (q = ngx_queue_head(locations);
  536.          q != ngx_queue_sentinel(locations);
  537.          q = ngx_queue_next(q))
  538.     {
  539.         lq = (ngx_http_location_queue_t *) q;

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

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

  544. #if (NGX_PCRE)

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

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

  550.             continue;
  551.         }

  552. #endif

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

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

  558.             continue;
  559.         }

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

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

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

  573.         cscf->named_locations = clcfp;

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

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

  581.         *clcfp = NULL;

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

  584. #if (NGX_PCRE)

  585.     if (regex) {

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

  591.         pclcf->regex_locations = clcfp;

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

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

  599.         *clcfp = NULL;

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

  602. #endif

  603.     return NGX_OK;
  604. }


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

  612.     locations = pclcf->locations;

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

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

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

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

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

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

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

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

  637.     return NGX_OK;
  638. }


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

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

  650.         ngx_queue_init(*locations);
  651.     }

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

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

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

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

  671.     ngx_queue_init(&lq->list);

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

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

  676.     return NGX_OK;
  677. }


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

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

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

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

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

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

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

  698.     return NGX_OK;
  699. }


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

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

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

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

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

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

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

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

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

  733. #if (NGX_PCRE)

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

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

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

  746. #endif

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

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

  753.     return rc;
  754. }


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

  760.     q = ngx_queue_head(locations);

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

  762.         x = ngx_queue_next(q);

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

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

  773.                 return NGX_ERROR;
  774.             }

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

  776.             ngx_queue_remove(x);

  777.             continue;
  778.         }

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

  781.     return NGX_OK;
  782. }


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

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

  793.     lq = (ngx_http_location_queue_t *) q;

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

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

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

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

  811.     q = ngx_queue_next(q);

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

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

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

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

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

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


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

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

  839.     q = ngx_queue_middle(locations);

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

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

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

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

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

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

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

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

  868.     ngx_queue_remove(q);

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

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

  876. inclusive:

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

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

  884.     return node;
  885. }


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

  895.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

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

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

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

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

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

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

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

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

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

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


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

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

  947.     addr = port->addrs.elts;

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

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

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

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

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

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

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

  978.         if (lsopt->set) {

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

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

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

  988.         if (lsopt->default_server) {

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

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

  998.         /* check for conflicting protocol options */

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

  1000.             /* options added */

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

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

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

  1013.             /* options removed */

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

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

  1024.         } else {

  1025.             /* the same options */

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

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

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

  1047.         return NGX_OK;
  1048.     }

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

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


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

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

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

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

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

  1077. #endif

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

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

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


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

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

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

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

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

  1127.     *server = cscf;

  1128.     return NGX_OK;
  1129. }


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

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

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

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

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

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

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

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

  1165.     return NGX_OK;
  1166. }


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

  1179.     regex = 0;
  1180. #endif

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

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

  1186.     ha.pool = cf->pool;

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

  1190.     cscfp = addr->servers.elts;

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

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

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

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

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

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

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

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

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

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

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

  1230.     if (ha.dns_wc_head.nelts) {

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

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

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

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

  1243.     if (ha.dns_wc_tail.nelts) {

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

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

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

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

  1256.     ngx_destroy_pool(ha.temp_pool);

  1257. #if (NGX_PCRE)

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

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

  1266.     i = 0;

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

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

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

  1275. #endif

  1276.     return NGX_OK;

  1277. failed:

  1278.     ngx_destroy_pool(ha.temp_pool);

  1279.     return NGX_ERROR;
  1280. }


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

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

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

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

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

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

  1303.     /* do not sort by default */

  1304.     return 0;
  1305. }


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

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

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


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

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

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

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

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

  1335.     i = 0;

  1336.     while (i < last) {

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

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

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

  1349.         ls->servers = hport;

  1350.         hport->naddrs = i + 1;

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

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

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

  1368.     return NGX_OK;
  1369. }


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

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

  1380.     ls->addr_ntop = 1;

  1381.     ls->handler = ngx_http_init_connection;

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

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

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

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

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

  1399.     ls->type = addr->opt.type;
  1400.     ls->protocol = addr->opt.protocol;
  1401.     ls->backlog = addr->opt.backlog;
  1402.     ls->rcvbuf = addr->opt.rcvbuf;
  1403.     ls->sndbuf = addr->opt.sndbuf;

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

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

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

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

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

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

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

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

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

  1432.     return ls;
  1433. }


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

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

  1447.     addrs = hport->addrs;

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

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

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

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

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

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

  1487.     return NGX_OK;
  1488. }


  1489. #if (NGX_HAVE_INET6)

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

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

  1503.     addrs6 = hport->addrs;

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

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

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

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

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

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

  1543.     return NGX_OK;
  1544. }

  1545. #endif


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

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

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

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

  1558.     default_type = cmd->post;

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

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

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

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

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

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

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

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

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

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

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

  1598.     next:

  1599.         continue;
  1600.     }

  1601.     return NGX_CONF_OK;
  1602. }


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

  1609.     if (*keys) {

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

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

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

  1623.         return NGX_CONF_OK;
  1624.     }

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

  1626.         if (*prev_keys == NULL) {

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

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

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

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

  1649.     *types_hash = *prev_types_hash;

  1650.     return NGX_CONF_OK;

  1651. }


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

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

  1661.     while (default_type->len) {

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

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

  1670.         default_type++;
  1671.     }

  1672.     return NGX_OK;
  1673. }