]> git.kaiwu.me - nginx.git/commitdiff
split ngx_http_block() further
authorIgor Sysoev <igor@sysoev.ru>
Thu, 22 May 2008 11:07:08 +0000 (11:07 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Thu, 22 May 2008 11:07:08 +0000 (11:07 +0000)
src/http/ngx_http.c

index 3d8a583cd0e0c412358cfd3b5c16cef6e8c03852..6be66715e56f454038874ee4210a6c968265d7d0 100644 (file)
@@ -17,18 +17,28 @@ static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
     ngx_http_core_main_conf_t *cmcf);
 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
     ngx_http_core_main_conf_t *cmcf);
+
+static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf,
+    ngx_array_t *servers, ngx_array_t *in_ports);
 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
-    ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *lscf,
-    ngx_http_core_srv_conf_t *cscf);
+    ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_port_t *in_port,
+    ngx_http_listen_t *listen);
 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
-    ngx_http_conf_in_addr_t *in_addr, ngx_http_core_srv_conf_t *cscf);
+    ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_addr_t *in_addr);
+
 static char *ngx_http_merge_locations(ngx_conf_t *cf,
     ngx_array_t *locations, void **loc_conf, ngx_http_module_t *module,
     ngx_uint_t ctx_index);
+
+static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
+    ngx_http_core_main_conf_t *cmcf, ngx_array_t *in_ports);
 static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two);
 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
     const void *two);
 
+static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
+    ngx_http_conf_in_port_t *in_port);
+
 ngx_uint_t   ngx_http_max_module;
 
 ngx_uint_t   ngx_http_total_requests;
@@ -79,28 +89,13 @@ static char *
 ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char                        *rv;
-    ngx_int_t                    rc;
-    ngx_uint_t                   mi, m, s, l, p, a, i;
-    ngx_uint_t                   last, bind_all, done;
+    ngx_uint_t                   mi, m, s;
     ngx_conf_t                   pcf;
     ngx_array_t                  in_ports;
-    ngx_hash_init_t              hash;
-    ngx_listening_t             *ls;
-    ngx_http_listen_t           *lscf;
     ngx_http_module_t           *module;
-    ngx_http_in_port_t          *hip;
     ngx_http_conf_ctx_t         *ctx;
-    ngx_http_conf_in_port_t     *in_port;
-    ngx_http_conf_in_addr_t     *in_addr;
-    ngx_hash_keys_arrays_t       ha;
-    ngx_http_server_name_t      *name;
-    ngx_http_virtual_names_t    *vn;
-    ngx_http_core_srv_conf_t   **cscfp, *cscf;
-    ngx_http_core_loc_conf_t    *clcf;
+    ngx_http_core_srv_conf_t   **cscfp;
     ngx_http_core_main_conf_t   *cmcf;
-#if (NGX_PCRE)
-    ngx_uint_t                   regex;
-#endif
 
     /* the main http context */
 
@@ -328,32 +323,265 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
     /*
      * create the lists of ports, addresses and server names
-     * to quickly find the server core module configuration at run-time
+     * to find quickly the server core module configuration at run-time
      */
 
-    if (ngx_array_init(&in_ports, cf->temp_pool, 2,
+    /* AF_INET only */
+
+    if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+
+    /* optimize the lists of ports, addresses and server names */
+
+    /* AF_INET only */
+
+    if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
+{
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
+                       cf->pool, 1, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
+                       cf->pool, 1, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
+                       cf->pool, 1, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
+                       cf->pool, 1, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
+                       cf->pool, 2, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
+                       cf->pool, 4, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
+                       cf->pool, 1, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
+{
+    ngx_array_t         headers_in;
+    ngx_hash_key_t     *hk;
+    ngx_hash_init_t     hash;
+    ngx_http_header_t  *header;
+
+    if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    for (header = ngx_http_headers_in; header->name.len; header++) {
+        hk = ngx_array_push(&headers_in);
+        if (hk == NULL) {
+            return NGX_ERROR;
+        }
+
+        hk->key = header->name;
+        hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
+        hk->value = header;
+    }
+
+    hash.hash = &cmcf->headers_in_hash;
+    hash.key = ngx_hash_key_lc;
+    hash.max_size = 512;
+    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
+    hash.name = "headers_in_hash";
+    hash.pool = cf->pool;
+    hash.temp_pool = NULL;
+
+    if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
+{
+    ngx_int_t                   j;
+    ngx_uint_t                  i, n;
+    ngx_uint_t                  find_config_index, use_rewrite, use_access;
+    ngx_http_handler_pt        *h;
+    ngx_http_phase_handler_t   *ph;
+    ngx_http_phase_handler_pt   checker;
+
+    cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
+    cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
+    find_config_index = 0;
+    use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
+    use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
+
+    n = use_rewrite + use_access + 1; /* find config phase */
+
+    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
+        n += cmcf->phases[i].handlers.nelts;
+    }
+
+    ph = ngx_pcalloc(cf->pool,
+                     n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
+    if (ph == NULL) {
+        return NGX_ERROR;
+    }
+
+    cmcf->phase_engine.handlers = ph;
+    n = 0;
+
+    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
+        h = cmcf->phases[i].handlers.elts;
+
+        switch (i) {
+
+        case NGX_HTTP_SERVER_REWRITE_PHASE:
+            if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
+                cmcf->phase_engine.server_rewrite_index = n;
+            }
+            checker = ngx_http_core_generic_phase;
+
+            break;
+
+        case NGX_HTTP_FIND_CONFIG_PHASE:
+            find_config_index = n;
+
+            ph->checker = ngx_http_core_find_config_phase;
+            n++;
+            ph++;
+
+            continue;
+
+        case NGX_HTTP_REWRITE_PHASE:
+            if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
+                cmcf->phase_engine.location_rewrite_index = n;
+            }
+            checker = ngx_http_core_generic_phase;
+
+            break;
+
+        case NGX_HTTP_POST_REWRITE_PHASE:
+            if (use_rewrite) {
+                ph->checker = ngx_http_core_post_rewrite_phase;
+                ph->next = find_config_index;
+                n++;
+                ph++;
+            }
+
+            continue;
+
+        case NGX_HTTP_ACCESS_PHASE:
+            checker = ngx_http_core_access_phase;
+            n++;
+            break;
+
+        case NGX_HTTP_POST_ACCESS_PHASE:
+            if (use_access) {
+                ph->checker = ngx_http_core_post_access_phase;
+                ph->next = n;
+                ph++;
+            }
+
+            continue;
+
+        case NGX_HTTP_CONTENT_PHASE:
+            checker = ngx_http_core_content_phase;
+            break;
+
+        default:
+            checker = ngx_http_core_generic_phase;
+        }
+
+        n += cmcf->phases[i].handlers.nelts;
+
+        for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
+            ph->checker = checker;
+            ph->handler = h[j];
+            ph->next = n;
+            ph++;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
+    ngx_array_t *in_ports)
+{
+    ngx_uint_t                  s, l, p, a;
+    ngx_http_listen_t          *listen;
+    ngx_http_conf_in_port_t    *in_port;
+    ngx_http_conf_in_addr_t    *in_addr;
+    ngx_http_core_srv_conf_t  **cscfp;
+
+    if (ngx_array_init(in_ports, cf->temp_pool, 2,
                        sizeof(ngx_http_conf_in_port_t))
         != NGX_OK)
     {
-        return NGX_CONF_ERROR;
+        return NGX_ERROR;
     }
 
     /* "server" directives */
 
-    cscfp = cmcf->servers.elts;
-    for (s = 0; s < cmcf->servers.nelts; s++) {
+    cscfp = servers->elts;
+    for (s = 0; s < servers->nelts; s++) {
 
         /* "listen" directives */
 
-        lscf = cscfp[s]->listen.elts;
+        listen = cscfp[s]->listen.elts;
         for (l = 0; l < cscfp[s]->listen.nelts; l++) {
 
             /* AF_INET only */
 
-            in_port = in_ports.elts;
-            for (p = 0; p < in_ports.nelts; p++) {
+            in_port = in_ports->elts;
+            for (p = 0; p < in_ports->nelts; p++) {
 
-                if (lscf[l].port != in_port[p].port) {
+                if (listen[l].port != in_port[p].port) {
                     continue;
                 }
 
@@ -362,15 +590,15 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                 in_addr = in_port[p].addrs.elts;
                 for (a = 0; a < in_port[p].addrs.nelts; a++) {
 
-                    if (lscf[l].addr != in_addr[a].addr) {
+                    if (listen[l].addr != in_addr[a].addr) {
                         continue;
                     }
 
                     /* the address is already in the address list */
 
-                    if (ngx_http_add_names(cf, &in_addr[a], cscfp[s]) != NGX_OK)
+                    if (ngx_http_add_names(cf, cscfp[s], &in_addr[a]) != NGX_OK)
                     {
-                        return NGX_CONF_ERROR;
+                        return NGX_ERROR;
                     }
 
                     /*
@@ -378,14 +606,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                      * for this address:port
                      */
 
-                    if (lscf[l].conf.default_server) {
+                    if (listen[l].conf.default_server) {
 
                         if (in_addr[a].default_server) {
                             ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                                       "the duplicate default server in %s:%ui",
-                                       lscf[l].file_name, lscf[l].line);
+                                       listen[l].file_name, listen[l].line);
 
-                            return NGX_CONF_ERROR;
+                            return NGX_ERROR;
                         }
 
                         in_addr[a].core_srv_conf = cscfp[s];
@@ -400,10 +628,10 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                  * bound to this port
                  */
 
-                if (ngx_http_add_address(cf, &in_port[p], &lscf[l], cscfp[s])
+                if (ngx_http_add_address(cf, cscfp[s], &in_port[p], &listen[l])
                     != NGX_OK)
                 {
-                    return NGX_CONF_ERROR;
+                    return NGX_ERROR;
                 }
 
                 goto found;
@@ -411,17 +639,18 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
             /* add the port to the in_port list */
 
-            in_port = ngx_array_push(&in_ports);
+            in_port = ngx_array_push(in_ports);
             if (in_port == NULL) {
-                return NGX_CONF_ERROR;
+                return NGX_ERROR;
             }
 
-            in_port->port = lscf[l].port;
+            in_port->port = listen[l].port;
             in_port->addrs.elts = NULL;
 
-            if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s]) != NGX_OK)
+            if (ngx_http_add_address(cf, cscfp[s], in_port, &listen[l])
+                != NGX_OK)
             {
-                return NGX_CONF_ERROR;
+                return NGX_ERROR;
             }
 
         found:
@@ -430,16 +659,160 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
         }
     }
 
+    return NGX_OK;
+}
 
-    /* optimize the lists of ports, addresses and server names */
 
-    /* AF_INET only */
+/*
+ * add the server address, the server names and the server core module
+ * configurations to the port (in_port)
+ */
 
-    in_port = in_ports.elts;
-    for (p = 0; p < in_ports.nelts; p++) {
+static ngx_int_t
+ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
+     ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *listen)
+{
+    ngx_http_conf_in_addr_t  *in_addr;
 
-        ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
-                 sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs);
+    if (in_port->addrs.elts == NULL) {
+        if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4,
+                           sizeof(ngx_http_conf_in_addr_t))
+            != NGX_OK)
+        {
+            return NGX_ERROR;
+        }
+    }
+
+    in_addr = ngx_array_push(&in_port->addrs);
+    if (in_addr == NULL) {
+        return NGX_ERROR;
+    }
+
+    in_addr->addr = listen->addr;
+    in_addr->hash.buckets = NULL;
+    in_addr->hash.size = 0;
+    in_addr->wc_head = NULL;
+    in_addr->wc_tail = NULL;
+    in_addr->names.elts = NULL;
+#if (NGX_PCRE)
+    in_addr->nregex = 0;
+    in_addr->regex = NULL;
+#endif
+    in_addr->core_srv_conf = cscf;
+    in_addr->default_server = listen->conf.default_server;
+    in_addr->bind = listen->conf.bind;
+    in_addr->listen_conf = &listen->conf;
+
+#if (NGX_DEBUG)
+    {
+    u_char text[20];
+    ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20);
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d",
+                   text, in_port->port);
+    }
+#endif
+
+    return ngx_http_add_names(cf, cscf, in_addr);
+}
+
+
+/*
+ * add the server names and the server core module
+ * configurations to the address:port (in_addr)
+ */
+
+static ngx_int_t
+ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
+    ngx_http_conf_in_addr_t *in_addr)
+{
+    ngx_uint_t               i, n;
+    ngx_http_server_name_t  *server_names, *name;
+
+    if (in_addr->names.elts == NULL) {
+        if (ngx_array_init(&in_addr->names, cf->temp_pool, 4,
+                           sizeof(ngx_http_server_name_t))
+            != NGX_OK)
+        {
+            return NGX_ERROR;
+        }
+    }
+
+    server_names = cscf->server_names.elts;
+
+    for (i = 0; i < cscf->server_names.nelts; i++) {
+
+        for (n = 0; n < server_names[i].name.len; n++) {
+            server_names[i].name.data[n] =
+                                     ngx_tolower(server_names[i].name.data[n]);
+        }
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+                       "name: %V", &server_names[i].name);
+
+        name = ngx_array_push(&in_addr->names);
+        if (name == NULL) {
+            return NGX_ERROR;
+        }
+
+        *name = server_names[i];
+    }
+
+    return NGX_OK;
+}
+
+
+static char *
+ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations,
+    void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
+{
+    char                       *rv;
+    ngx_uint_t                  i;
+    ngx_http_core_loc_conf_t  **clcfp;
+
+    clcfp = locations->elts;
+
+    for (i = 0; i < locations->nelts; i++) {
+        rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
+                                    clcfp[i]->loc_conf[ctx_index]);
+        if (rv != NGX_CONF_OK) {
+            return rv;
+        }
+
+        if (clcfp[i]->locations == NULL) {
+            continue;
+        }
+
+        rv = ngx_http_merge_locations(cf, clcfp[i]->locations,
+                                      clcfp[i]->loc_conf, module, ctx_index);
+        if (rv != NGX_CONF_OK) {
+            return rv;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
+    ngx_array_t *in_ports)
+{
+    ngx_int_t                  rc;
+    ngx_uint_t                 s, p, a, i;
+    ngx_hash_init_t            hash;
+    ngx_http_server_name_t    *name;
+    ngx_hash_keys_arrays_t     ha;
+    ngx_http_conf_in_port_t   *in_port;
+    ngx_http_conf_in_addr_t   *in_addr;
+#if (NGX_PCRE)
+    ngx_uint_t                 regex;
+#endif
+
+    in_port = in_ports->elts;
+    for (p = 0; p < in_ports->nelts; p++) {
+
+        ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
+                 sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs);
 
         /*
          * check whether all name-based servers have the same configuraiton
@@ -477,14 +850,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
             ha.temp_pool = ngx_create_pool(16384, cf->log);
             if (ha.temp_pool == NULL) {
-                return NGX_CONF_ERROR;
+                return NGX_ERROR;
             }
 
             ha.pool = cf->pool;
 
             if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
-                ngx_destroy_pool(ha.temp_pool);
-                return NGX_CONF_ERROR;
+                goto failed;
             }
 
 #if (NGX_PCRE)
@@ -506,14 +878,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                                       NGX_HASH_WILDCARD_KEY);
 
                 if (rc == NGX_ERROR) {
-                    return NGX_CONF_ERROR;
+                    return NGX_ERROR;
                 }
 
                 if (rc == NGX_DECLINED) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                                 "invalid server name or wildcard \"%V\" on %s",
                                 &name[s].name, in_addr[a].listen_conf->addr);
-                    return NGX_CONF_ERROR;
+                    return NGX_ERROR;
                 }
 
                 if (rc == NGX_BUSY) {
@@ -535,8 +907,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
                 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK)
                 {
-                    ngx_destroy_pool(ha.temp_pool);
-                    return NGX_CONF_ERROR;
+                    goto failed;
                 }
             }
 
@@ -554,8 +925,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                                            ha.dns_wc_head.nelts)
                     != NGX_OK)
                 {
-                    ngx_destroy_pool(ha.temp_pool);
-                    return NGX_CONF_ERROR;
+                    goto failed;
                 }
 
                 in_addr[a].wc_head = (ngx_hash_wildcard_t *) hash.hash;
@@ -575,8 +945,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                                            ha.dns_wc_tail.nelts)
                     != NGX_OK)
                 {
-                    ngx_destroy_pool(ha.temp_pool);
-                    return NGX_CONF_ERROR;
+                    goto failed;
                 }
 
                 in_addr[a].wc_tail = (ngx_hash_wildcard_t *) hash.hash;
@@ -595,7 +964,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                                        regex * sizeof(ngx_http_server_name_t));
 
             if (in_addr[a].regex == NULL) {
-                return NGX_CONF_ERROR;
+                return NGX_ERROR;
             }
 
             for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) {
@@ -606,534 +975,219 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 #endif
         }
 
-        in_addr = in_port[p].addrs.elts;
-        last = in_port[p].addrs.nelts;
-
-        /*
-         * if there is the binding to the "*:port" then we need to bind()
-         * to the "*:port" only and ignore the other bindings
-         */
+        if (ngx_http_init_listening(cf, &in_port[p]) != NGX_OK) {
+            return NGX_ERROR;
+        }
+    }
 
-        if (in_addr[last - 1].addr == INADDR_ANY) {
-            in_addr[last - 1].bind = 1;
-            bind_all = 0;
+    return NGX_OK;
 
-        } else {
-            bind_all = 1;
-        }
+failed:
 
-        for (a = 0; a < last; /* void */ ) {
+    ngx_destroy_pool(ha.temp_pool);
 
-            if (!bind_all && !in_addr[a].bind) {
-                a++;
-                continue;
-            }
+    return NGX_ERROR;
+}
 
-            ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
-                                                  in_port[p].port);
-            if (ls == NULL) {
-                return NGX_CONF_ERROR;
-            }
 
-            ls->addr_ntop = 1;
+static ngx_int_t
+ngx_http_cmp_conf_in_addrs(const void *one, const void *two)
+{
+    ngx_http_conf_in_addr_t  *first, *second;
 
-            ls->handler = ngx_http_init_connection;
+    first = (ngx_http_conf_in_addr_t *) one;
+    second = (ngx_http_conf_in_addr_t *) two;
 
-            cscf = in_addr[a].core_srv_conf;
-            ls->pool_size = cscf->connection_pool_size;
-            ls->post_accept_timeout = cscf->client_header_timeout;
+    if (first->addr == INADDR_ANY) {
+        /* the INADDR_ANY must be the last resort, shift it to the end */
+        return 1;
+    }
 
-            clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
+    if (first->bind && !second->bind) {
+        /* shift explicit bind()ed addresses to the start */
+        return -1;
+    }
 
-            ls->log = *clcf->err_log;
-            ls->log.data = &ls->addr_text;
-            ls->log.handler = ngx_accept_log_error;
+    if (!first->bind && second->bind) {
+        /* shift explicit bind()ed addresses to the start */
+        return 1;
+    }
 
-#if (NGX_WIN32)
-            {
-            ngx_iocp_conf_t  *iocpcf;
+    /* do not sort by default */
 
-            iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
-            if (iocpcf->acceptex_read) {
-                ls->post_accept_buffer_size = cscf->client_header_buffer_size;
-            }
-            }
-#endif
+    return 0;
+}
 
-            ls->backlog = in_addr[a].listen_conf->backlog;
-            ls->rcvbuf = in_addr[a].listen_conf->rcvbuf;
-            ls->sndbuf = in_addr[a].listen_conf->sndbuf;
 
-#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
-            ls->accept_filter = in_addr[a].listen_conf->accept_filter;
-#endif
+static int ngx_libc_cdecl
+ngx_http_cmp_dns_wildcards(const void *one, const void *two)
+{
+    ngx_hash_key_t  *first, *second;
 
-#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
-            ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
-#endif
+    first = (ngx_hash_key_t *) one;
+    second = (ngx_hash_key_t *) two;
 
-            hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
-            if (hip == NULL) {
-                return NGX_CONF_ERROR;
-            }
+    return ngx_strcmp(first->key.data, second->key.data);
+}
 
-            hip->port = in_port[p].port;
 
-            hip->port_text.data = ngx_palloc(cf->pool, 7);
-            if (hip->port_text.data == NULL) {
-                return NGX_CONF_ERROR;
-            }
+static ngx_int_t
+ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port)
+{
+    ngx_uint_t                 i, a, last, bind_all, done;
+    ngx_listening_t           *ls;
+    ngx_http_in_port_t        *hip;
+    ngx_http_conf_in_addr_t   *in_addr;
+    ngx_http_virtual_names_t  *vn;
+    ngx_http_core_loc_conf_t  *clcf;
+    ngx_http_core_srv_conf_t  *cscf;
 
-            ls->servers = hip;
+    in_addr = in_port->addrs.elts;
+    last = in_port->addrs.nelts;
 
-            hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d",
-                                             hip->port)
-                                 - hip->port_text.data;
+    /*
+     * if there is a binding to a "*:port" then we need to bind()
+     * to the "*:port" only and ignore other bindings
+     */
 
-            in_addr = in_port[p].addrs.elts;
+    if (in_addr[last - 1].addr == INADDR_ANY) {
+        in_addr[last - 1].bind = 1;
+        bind_all = 0;
 
-            if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
-                hip->naddrs = 1;
-                done = 0;
+    } else {
+        bind_all = 1;
+    }
 
-            } else if (in_port[p].addrs.nelts > 1
-                       && in_addr[last - 1].addr == INADDR_ANY)
-            {
-                hip->naddrs = last;
-                done = 1;
+    a = 0;
 
-            } else {
-                hip->naddrs = 1;
-                done = 0;
-            }
+    while (a < last) {
 
-#if 0
-            ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
-                          "%ui: %V %d %ui %ui",
-                          a, &ls->addr_text, in_addr[a].bind,
-                          hip->naddrs, last);
-#endif
+        if (!bind_all && !in_addr[a].bind) {
+            a++;
+            continue;
+        }
 
-            hip->addrs = ngx_pcalloc(cf->pool,
-                                     hip->naddrs * sizeof(ngx_http_in_addr_t));
-            if (hip->addrs == NULL) {
-                return NGX_CONF_ERROR;
-            }
+        ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
+                                              in_port->port);
+        if (ls == NULL) {
+            return NGX_ERROR;
+        }
 
-            for (i = 0; i < hip->naddrs; i++) {
-                hip->addrs[i].addr = in_addr[i].addr;
-                hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf;
+        ls->addr_ntop = 1;
 
-                if (in_addr[i].hash.buckets == NULL
-                    && (in_addr[i].wc_head == NULL
-                        || in_addr[i].wc_head->hash.buckets == NULL)
-                    && (in_addr[i].wc_head == NULL
-                        || in_addr[i].wc_head->hash.buckets == NULL))
-                {
-                    continue;
-                }
+        ls->handler = ngx_http_init_connection;
 
-                vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
-                if (vn == NULL) {
-                    return NGX_CONF_ERROR;
-                }
-                hip->addrs[i].virtual_names = vn;
+        cscf = in_addr[a].core_srv_conf;
+        ls->pool_size = cscf->connection_pool_size;
+        ls->post_accept_timeout = cscf->client_header_timeout;
 
-                vn->names.hash = in_addr[i].hash;
-                vn->names.wc_head = in_addr[i].wc_head;
-                vn->names.wc_tail = in_addr[i].wc_tail;
-#if (NGX_PCRE)
-                vn->nregex = in_addr[i].nregex;
-                vn->regex = in_addr[i].regex;
-#endif
-            }
+        clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
 
-            if (done) {
-                break;
-            }
+        ls->log = *clcf->err_log;
+        ls->log.data = &ls->addr_text;
+        ls->log.handler = ngx_accept_log_error;
 
-            in_addr++;
-            in_port[p].addrs.elts = in_addr;
-            last--;
+#if (NGX_WIN32)
+        {
+        ngx_iocp_conf_t  *iocpcf;
 
-            a = 0;
+        iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
+        if (iocpcf->acceptex_read) {
+            ls->post_accept_buffer_size = cscf->client_header_buffer_size;
         }
-    }
+        }
+#endif
 
-    return NGX_CONF_OK;
-}
+        ls->backlog = in_addr[a].listen_conf->backlog;
+        ls->rcvbuf = in_addr[a].listen_conf->rcvbuf;
+        ls->sndbuf = in_addr[a].listen_conf->sndbuf;
 
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+        ls->accept_filter = in_addr[a].listen_conf->accept_filter;
+#endif
 
-static ngx_int_t
-ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
-{
-    if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
-                       cf->pool, 1, sizeof(ngx_http_handler_pt))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+        ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
+#endif
 
-    if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
-                       cf->pool, 1, sizeof(ngx_http_handler_pt))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+        hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
+        if (hip == NULL) {
+            return NGX_ERROR;
+        }
 
-    if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
-                       cf->pool, 1, sizeof(ngx_http_handler_pt))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+        hip->port = in_port->port;
 
-    if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
-                       cf->pool, 1, sizeof(ngx_http_handler_pt))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+        hip->port_text.data = ngx_palloc(cf->pool, 7);
+        if (hip->port_text.data == NULL) {
+            return NGX_ERROR;
+        }
 
-    if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
-                       cf->pool, 2, sizeof(ngx_http_handler_pt))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+        ls->servers = hip;
 
-    if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
-                       cf->pool, 4, sizeof(ngx_http_handler_pt))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+        hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d", hip->port)
+                             - hip->port_text.data;
 
-    if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
-                       cf->pool, 1, sizeof(ngx_http_handler_pt))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+        in_addr = in_port->addrs.elts;
 
-    return NGX_OK;
-}
+        if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
+            hip->naddrs = 1;
+            done = 0;
 
+        } else if (in_port->addrs.nelts > 1
+                   && in_addr[last - 1].addr == INADDR_ANY)
+        {
+            hip->naddrs = last;
+            done = 1;
 
-static ngx_int_t
-ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
-{
-    ngx_array_t         headers_in;
-    ngx_hash_key_t     *hk;
-    ngx_hash_init_t     hash;
-    ngx_http_header_t  *header;
-
-    if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+        } else {
+            hip->naddrs = 1;
+            done = 0;
+        }
 
-    for (header = ngx_http_headers_in; header->name.len; header++) {
-        hk = ngx_array_push(&headers_in);
-        if (hk == NULL) {
+        hip->addrs = ngx_pcalloc(cf->pool,
+                                 hip->naddrs * sizeof(ngx_http_in_addr_t));
+        if (hip->addrs == NULL) {
             return NGX_ERROR;
         }
 
-        hk->key = header->name;
-        hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
-        hk->value = header;
-    }
-
-    hash.hash = &cmcf->headers_in_hash;
-    hash.key = ngx_hash_key_lc;
-    hash.max_size = 512;
-    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
-    hash.name = "headers_in_hash";
-    hash.pool = cf->pool;
-    hash.temp_pool = NULL;
-
-    if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
-        return NGX_ERROR;
-    }
-
-    return NGX_OK;
-}
-
+        for (i = 0; i < hip->naddrs; i++) {
+            hip->addrs[i].addr = in_addr[i].addr;
+            hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf;
 
-static ngx_int_t
-ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
-{
-    ngx_int_t                   j;
-    ngx_uint_t                  i, n;
-    ngx_uint_t                  find_config_index, use_rewrite, use_access;
-    ngx_http_handler_pt        *h;
-    ngx_http_phase_handler_t   *ph;
-    ngx_http_phase_handler_pt   checker;
-
-    cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
-    cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
-    find_config_index = 0;
-    use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
-    use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
-
-    n = use_rewrite + use_access + 1; /* find config phase */
-
-    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
-        n += cmcf->phases[i].handlers.nelts;
-    }
-
-    ph = ngx_pcalloc(cf->pool,
-                     n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
-    if (ph == NULL) {
-        return NGX_ERROR;
-    }
-
-    cmcf->phase_engine.handlers = ph;
-    n = 0;
-
-    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
-        h = cmcf->phases[i].handlers.elts;
-
-        switch (i) {
-
-        case NGX_HTTP_SERVER_REWRITE_PHASE:
-            if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
-                cmcf->phase_engine.server_rewrite_index = n;
-            }
-            checker = ngx_http_core_generic_phase;
-
-            break;
-
-        case NGX_HTTP_FIND_CONFIG_PHASE:
-            find_config_index = n;
-
-            ph->checker = ngx_http_core_find_config_phase;
-            n++;
-            ph++;
-
-            continue;
-
-        case NGX_HTTP_REWRITE_PHASE:
-            if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
-                cmcf->phase_engine.location_rewrite_index = n;
+            if (in_addr[i].hash.buckets == NULL
+                && (in_addr[i].wc_head == NULL
+                    || in_addr[i].wc_head->hash.buckets == NULL)
+                && (in_addr[i].wc_head == NULL
+                    || in_addr[i].wc_head->hash.buckets == NULL))
+            {
+                continue;
             }
-            checker = ngx_http_core_generic_phase;
 
-            break;
-
-        case NGX_HTTP_POST_REWRITE_PHASE:
-            if (use_rewrite) {
-                ph->checker = ngx_http_core_post_rewrite_phase;
-                ph->next = find_config_index;
-                n++;
-                ph++;
+            vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
+            if (vn == NULL) {
+                return NGX_ERROR;
             }
+            hip->addrs[i].virtual_names = vn;
 
-            continue;
-
-        case NGX_HTTP_ACCESS_PHASE:
-            checker = ngx_http_core_access_phase;
-            n++;
-            break;
-
-        case NGX_HTTP_POST_ACCESS_PHASE:
-            if (use_access) {
-                ph->checker = ngx_http_core_post_access_phase;
-                ph->next = n;
-                ph++;
-            }
-
-            continue;
-
-        case NGX_HTTP_CONTENT_PHASE:
-            checker = ngx_http_core_content_phase;
-            break;
-
-        default:
-            checker = ngx_http_core_generic_phase;
-        }
-
-        n += cmcf->phases[i].handlers.nelts;
-
-        for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
-            ph->checker = checker;
-            ph->handler = h[j];
-            ph->next = n;
-            ph++;
-        }
-    }
-
-    return NGX_OK;
-}
-
-
-/*
- * add the server address, the server names and the server core module
- * configurations to the port (in_port)
- */
-
-static ngx_int_t
-ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port,
-    ngx_http_listen_t *lscf, ngx_http_core_srv_conf_t *cscf)
-{
-    ngx_http_conf_in_addr_t  *in_addr;
-
-    if (in_port->addrs.elts == NULL) {
-        if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4,
-                           sizeof(ngx_http_conf_in_addr_t))
-            != NGX_OK)
-        {
-            return NGX_ERROR;
-        }
-    }
-
-    in_addr = ngx_array_push(&in_port->addrs);
-    if (in_addr == NULL) {
-        return NGX_ERROR;
-    }
-
-    in_addr->addr = lscf->addr;
-    in_addr->hash.buckets = NULL;
-    in_addr->hash.size = 0;
-    in_addr->wc_head = NULL;
-    in_addr->wc_tail = NULL;
-    in_addr->names.elts = NULL;
+            vn->names.hash = in_addr[i].hash;
+            vn->names.wc_head = in_addr[i].wc_head;
+            vn->names.wc_tail = in_addr[i].wc_tail;
 #if (NGX_PCRE)
-    in_addr->nregex = 0;
-    in_addr->regex = NULL;
-#endif
-    in_addr->core_srv_conf = cscf;
-    in_addr->default_server = lscf->conf.default_server;
-    in_addr->bind = lscf->conf.bind;
-    in_addr->listen_conf = &lscf->conf;
-
-#if (NGX_DEBUG)
-    {
-    u_char text[20];
-    ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20);
-    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d",
-                   text, in_port->port);
-    }
+            vn->nregex = in_addr[i].nregex;
+            vn->regex = in_addr[i].regex;
 #endif
-
-    return ngx_http_add_names(cf, in_addr, cscf);
-}
-
-
-/*
- * add the server names and the server core module
- * configurations to the address:port (in_addr)
- */
-
-static ngx_int_t
-ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr,
-    ngx_http_core_srv_conf_t *cscf)
-{
-    ngx_uint_t               i, n;
-    ngx_http_server_name_t  *server_names, *name;
-
-    if (in_addr->names.elts == NULL) {
-        if (ngx_array_init(&in_addr->names, cf->temp_pool, 4,
-                           sizeof(ngx_http_server_name_t))
-            != NGX_OK)
-        {
-            return NGX_ERROR;
         }
-    }
-
-    server_names = cscf->server_names.elts;
 
-    for (i = 0; i < cscf->server_names.nelts; i++) {
-
-        for (n = 0; n < server_names[i].name.len; n++) {
-            server_names[i].name.data[n] =
-                                     ngx_tolower(server_names[i].name.data[n]);
+        if (done) {
+            return NGX_OK;
         }
 
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
-                       "name: %V", &server_names[i].name);
+        in_addr++;
+        in_port->addrs.elts = in_addr;
+        last--;
 
-        name = ngx_array_push(&in_addr->names);
-        if (name == NULL) {
-            return NGX_ERROR;
-        }
-
-        *name = server_names[i];
+        a = 0;
     }
 
     return NGX_OK;
 }
-
-
-static char *
-ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations,
-    void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
-{
-    char                       *rv;
-    ngx_uint_t                  i;
-    ngx_http_core_loc_conf_t  **clcfp;
-
-    clcfp = locations->elts;
-
-    for (i = 0; i < locations->nelts; i++) {
-        rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
-                                    clcfp[i]->loc_conf[ctx_index]);
-        if (rv != NGX_CONF_OK) {
-            return rv;
-        }
-
-        if (clcfp[i]->locations == NULL) {
-            continue;
-        }
-
-        rv = ngx_http_merge_locations(cf, clcfp[i]->locations,
-                                      clcfp[i]->loc_conf, module, ctx_index);
-        if (rv != NGX_CONF_OK) {
-            return rv;
-        }
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_cmp_conf_in_addrs(const void *one, const void *two)
-{
-    ngx_http_conf_in_addr_t  *first, *second;
-
-    first = (ngx_http_conf_in_addr_t *) one;
-    second = (ngx_http_conf_in_addr_t *) two;
-
-    if (first->addr == INADDR_ANY) {
-        /* the INADDR_ANY must be the last resort, shift it to the end */
-        return 1;
-    }
-
-    if (first->bind && !second->bind) {
-        /* shift explicit bind()ed addresses to the start */
-        return -1;
-    }
-
-    if (!first->bind && second->bind) {
-        /* shift explicit bind()ed addresses to the start */
-        return 1;
-    }
-
-    /* do not sort by default */
-
-    return 0;
-}
-
-
-static int ngx_libc_cdecl
-ngx_http_cmp_dns_wildcards(const void *one, const void *two)
-{
-    ngx_hash_key_t  *first, *second;
-
-    first = (ngx_hash_key_t *) one;
-    second = (ngx_hash_key_t *) two;
-
-    return ngx_strcmp(first->key.data, second->key.data);
-}